17a84e134Smrg/*
27a84e134Smrg *
37a84e134SmrgCopyright 1990, 1994, 1998  The Open Group
47a84e134Smrg
57a84e134SmrgPermission to use, copy, modify, distribute, and sell this software and its
67a84e134Smrgdocumentation for any purpose is hereby granted without fee, provided that
77a84e134Smrgthe above copyright notice appear in all copies and that both that
87a84e134Smrgcopyright notice and this permission notice appear in supporting
97a84e134Smrgdocumentation.
107a84e134Smrg
117a84e134SmrgThe above copyright notice and this permission notice shall be included in
127a84e134Smrgall copies or substantial portions of the Software.
137a84e134Smrg
147a84e134SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
157a84e134SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
167a84e134SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
177a84e134SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
187a84e134SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
197a84e134SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
207a84e134Smrg
217a84e134SmrgExcept as contained in this notice, the name of The Open Group shall not be
227a84e134Smrgused in advertising or otherwise to promote the sale, use or other dealings
237a84e134Smrgin this Software without prior written authorization from The Open Group.
247a84e134Smrg *
257a84e134Smrg * Author:  Jim Fulton, MIT X Consortium
26421c997bSmrg *
277a84e134Smrg * This widget is used for press-and-hold style buttons.
287a84e134Smrg */
297a84e134Smrg
307a84e134Smrg#ifdef HAVE_CONFIG_H
317a84e134Smrg#include <config.h>
327a84e134Smrg#endif
337a84e134Smrg#include <X11/IntrinsicP.h>
347a84e134Smrg#include <X11/StringDefs.h>
357a84e134Smrg#include <X11/Xaw/RepeaterP.h>
367a84e134Smrg#include <X11/Xaw/XawInit.h>
377a84e134Smrg
387a84e134Smrg#define DO_CALLBACK(rw) \
397a84e134SmrgXtCallCallbackList((Widget)rw, rw->command.callbacks, NULL)
407a84e134Smrg
417a84e134Smrg#define ADD_TIMEOUT(rw, delay)					\
427a84e134SmrgXtAppAddTimeOut(XtWidgetToApplicationContext((Widget)rw),	\
437a84e134Smrg		delay, tic, (XtPointer)rw)
447a84e134Smrg
457a84e134Smrg#define CLEAR_TIMEOUT(rw) \
467a84e134Smrgif ((rw)->repeater.timer) {			\
477a84e134Smrg    XtRemoveTimeOut((rw)->repeater.timer);	\
487a84e134Smrg    (rw)->repeater.timer = 0;			\
497a84e134Smrg}
507a84e134Smrg
517a84e134Smrg/*
527a84e134Smrg * Class Methods
537a84e134Smrg */
547a84e134Smrgstatic void XawRepeaterInitialize(Widget, Widget, ArgList, Cardinal*);
557a84e134Smrgstatic void XawRepeaterDestroy(Widget);
567a84e134Smrgstatic Boolean XawRepeaterSetValues(Widget, Widget, Widget,
577a84e134Smrg				    ArgList, Cardinal*);
587a84e134Smrg
597a84e134Smrg/*
607a84e134Smrg * Prototypes
617a84e134Smrg */
627a84e134Smrgstatic void tic(XtPointer, XtIntervalId*);
637a84e134Smrg
647a84e134Smrg/*
657a84e134Smrg * Actions
667a84e134Smrg */
677a84e134Smrgstatic void ActionStart(Widget, XEvent*, String*, Cardinal*);
687a84e134Smrgstatic void ActionStop(Widget, XEvent*, String*, Cardinal*);
697a84e134Smrg
707a84e134Smrg/*
717a84e134Smrg * Initialization
727a84e134Smrg */
737a84e134Smrgstatic char defaultTranslations[] =
747a84e134Smrg"<Enter>:"	"highlight()\n"
757a84e134Smrg"<Leave>:"	"unhighlight()\n"
767a84e134Smrg"<Btn1Down>:"	"set() start()\n"
777a84e134Smrg"<Btn1Up>:"	"stop() unset()\n"
787a84e134Smrg;
797a84e134Smrg
807a84e134Smrgstatic XtActionsRec actions[] = {
817a84e134Smrg  {"start",	ActionStart},
827a84e134Smrg  {"stop",	ActionStop},
837a84e134Smrg};
847a84e134Smrg
857a84e134Smrg#define offset(field)	XtOffsetOf(RepeaterRec, repeater.field)
867a84e134Smrgstatic XtResource resources[] = {
877a84e134Smrg  {
887a84e134Smrg    XtNdecay,
897a84e134Smrg    XtCDecay,
907a84e134Smrg    XtRInt,
917a84e134Smrg    sizeof(int),
927a84e134Smrg    offset(decay),
937a84e134Smrg    XtRImmediate,
947a84e134Smrg    (XtPointer)REP_DEF_DECAY
957a84e134Smrg  },
967a84e134Smrg  {
977a84e134Smrg    XtNinitialDelay,
987a84e134Smrg    XtCDelay,
997a84e134Smrg    XtRInt,
1007a84e134Smrg    sizeof(int),
1017a84e134Smrg    offset(initial_delay),
1027a84e134Smrg    XtRImmediate,
1037a84e134Smrg    (XtPointer)REP_DEF_INITIAL_DELAY
1047a84e134Smrg  },
1057a84e134Smrg  {
1067a84e134Smrg    XtNminimumDelay,
1077a84e134Smrg    XtCMinimumDelay,
1087a84e134Smrg    XtRInt,
1097a84e134Smrg    sizeof(int),
1107a84e134Smrg    offset(minimum_delay),
1117a84e134Smrg    XtRImmediate,
1127a84e134Smrg    (XtPointer)REP_DEF_MINIMUM_DELAY
1137a84e134Smrg  },
1147a84e134Smrg  {
1157a84e134Smrg    XtNrepeatDelay,
1167a84e134Smrg    XtCDelay,
1177a84e134Smrg    XtRInt,
1187a84e134Smrg    sizeof(int),
1197a84e134Smrg    offset(repeat_delay),
1207a84e134Smrg    XtRImmediate,
1217a84e134Smrg    (XtPointer)REP_DEF_REPEAT_DELAY
1227a84e134Smrg  },
1237a84e134Smrg  {
1247a84e134Smrg    XtNflash,
1257a84e134Smrg    XtCBoolean,
1267a84e134Smrg    XtRBoolean,
1277a84e134Smrg    sizeof(Boolean),
1287a84e134Smrg    offset(flash),
1297a84e134Smrg    XtRImmediate,
1307a84e134Smrg    (XtPointer)False
1317a84e134Smrg  },
1327a84e134Smrg  {
1337a84e134Smrg    XtNstartCallback,
1347a84e134Smrg    XtCStartCallback,
1357a84e134Smrg    XtRCallback,
1367a84e134Smrg    sizeof(XtPointer),
1377a84e134Smrg    offset(start_callbacks),
1387a84e134Smrg    XtRImmediate,
1397a84e134Smrg    NULL
1407a84e134Smrg  },
1417a84e134Smrg  {
1427a84e134Smrg    XtNstopCallback,
1437a84e134Smrg    XtCStopCallback,
1447a84e134Smrg    XtRCallback,
1457a84e134Smrg    sizeof(XtPointer),
1467a84e134Smrg    offset(stop_callbacks),
1477a84e134Smrg    XtRImmediate,
1487a84e134Smrg    NULL
1497a84e134Smrg  },
1507a84e134Smrg};
1517a84e134Smrg#undef offset
1527a84e134Smrg
1537a84e134Smrg#define Superclass	(&commandClassRec)
1547a84e134SmrgRepeaterClassRec repeaterClassRec = {
1557a84e134Smrg  /* core */
1567a84e134Smrg  {
1577a84e134Smrg    (WidgetClass)Superclass,		/* superclass */
1587a84e134Smrg    "Repeater",				/* class_name */
1597a84e134Smrg    sizeof(RepeaterRec),		/* widget_size */
1607a84e134Smrg    XawInitializeWidgetSet,		/* class_initialize */
1617a84e134Smrg    NULL,				/* class_part_initialize */
1627a84e134Smrg    False,				/* class_inited */
1637a84e134Smrg    XawRepeaterInitialize,		/* initialize */
1647a84e134Smrg    NULL,				/* initialize_hook */
1657a84e134Smrg    XtInheritRealize,			/* realize */
1667a84e134Smrg    actions,				/* actions */
1677a84e134Smrg    XtNumber(actions),			/* num_actions */
1687a84e134Smrg    resources,				/* resources */
1697a84e134Smrg    XtNumber(resources),		/* num_resources */
1707a84e134Smrg    NULLQUARK,				/* xrm_class */
1717a84e134Smrg    True,				/* compress_motion */
1727a84e134Smrg    True,				/* compress_exposure */
1737a84e134Smrg    True,				/* compress_enterleave */
1747a84e134Smrg    False,				/* visible_interest */
1757a84e134Smrg    XawRepeaterDestroy,			/* destroy */
1767a84e134Smrg    XtInheritResize,			/* resize */
1777a84e134Smrg    XtInheritExpose,			/* expose */
1787a84e134Smrg    XawRepeaterSetValues,		/* set_values */
1797a84e134Smrg    NULL,				/* set_values_hook */
1807a84e134Smrg    XtInheritSetValuesAlmost,		/* set_values_almost */
1817a84e134Smrg    NULL,				/* get_values_hook */
1827a84e134Smrg    NULL,				/* accept_focus */
1837a84e134Smrg    XtVersion,				/* version */
1847a84e134Smrg    NULL,				/* callback_private */
1857a84e134Smrg    defaultTranslations,		/* tm_table */
1867a84e134Smrg    XtInheritQueryGeometry,		/* query_geometry */
1877a84e134Smrg    XtInheritDisplayAccelerator,	/* display_accelerator */
1887a84e134Smrg    NULL,				/* extension */
1897a84e134Smrg  },
1907a84e134Smrg  /* simple */
1917a84e134Smrg  {
1927a84e134Smrg    XtInheritChangeSensitive,		/* change_sensitive */
193efbcb2bfSmrg#ifndef OLDXAW
194efbcb2bfSmrg    NULL,
195efbcb2bfSmrg#endif
1967a84e134Smrg  },
1977a84e134Smrg  /* label */
1987a84e134Smrg  {
1997a84e134Smrg    NULL,				/* extension */
2007a84e134Smrg  },
2017a84e134Smrg  /* command */
2027a84e134Smrg  {
2037a84e134Smrg    NULL,				/* extension */
2047a84e134Smrg  },
2057a84e134Smrg  /* repeater */
2067a84e134Smrg  {
2077a84e134Smrg    NULL,				/* extension */
2087a84e134Smrg  },
2097a84e134Smrg};
2107a84e134Smrg
2117a84e134SmrgWidgetClass repeaterWidgetClass = (WidgetClass) &repeaterClassRec;
2127a84e134Smrg
2137a84e134Smrg
2147a84e134Smrg/*
2157a84e134Smrg * Implementation
2167a84e134Smrg */
2177a84e134Smrg/*ARGSUSED*/
2187a84e134Smrgstatic void
2195ec34c4cSmrgtic(XtPointer client_data, XtIntervalId *id _X_UNUSED)
2207a84e134Smrg{
2217a84e134Smrg    RepeaterWidget rw = (RepeaterWidget)client_data;
2227a84e134Smrg
2237a84e134Smrg    rw->repeater.timer = 0;		/* timer is removed */
2247a84e134Smrg    if (rw->repeater.flash) {
2257a84e134Smrg	Widget w = (Widget)rw;
2267a84e134Smrg
2277a84e134Smrg	XClearWindow(XtDisplay(w), XtWindow(w));
2287a84e134Smrg	XtCallActionProc(w, "reset", NULL, NULL, 0);
2297a84e134Smrg	XClearWindow(XtDisplay(w), XtWindow(w));
2307a84e134Smrg	XtCallActionProc(w, "set", NULL, NULL, 0);
2317a84e134Smrg    }
2327a84e134Smrg    DO_CALLBACK(rw);
2337a84e134Smrg
2345ec34c4cSmrg    rw->repeater.timer = ADD_TIMEOUT(rw, (unsigned long)rw->repeater.next_delay);
2357a84e134Smrg
2367a84e134Smrg    if (rw->repeater.decay) {
2377a84e134Smrg	rw->repeater.next_delay -= rw->repeater.decay;
2387a84e134Smrg	if (rw->repeater.next_delay < rw->repeater.minimum_delay)
2397a84e134Smrg	    rw->repeater.next_delay = rw->repeater.minimum_delay;
2407a84e134Smrg    }
2417a84e134Smrg}
2427a84e134Smrg
2437a84e134Smrg/*ARGSUSED*/
2447a84e134Smrgstatic void
2455ec34c4cSmrgXawRepeaterInitialize(Widget greq _X_UNUSED, Widget gnew,
2465ec34c4cSmrg		      ArgList args _X_UNUSED, Cardinal *num_args _X_UNUSED)
2477a84e134Smrg{
2487a84e134Smrg    RepeaterWidget cnew = (RepeaterWidget)gnew;
2497a84e134Smrg
2507a84e134Smrg    if (cnew->repeater.minimum_delay < 0)
2517a84e134Smrg	cnew->repeater.minimum_delay = 0;
2527a84e134Smrg    cnew->repeater.timer = 0;
2537a84e134Smrg}
2547a84e134Smrg
2557a84e134Smrgstatic void
2567a84e134SmrgXawRepeaterDestroy(Widget gw)
2577a84e134Smrg{
2587a84e134Smrg    CLEAR_TIMEOUT((RepeaterWidget)gw);
2597a84e134Smrg}
2607a84e134Smrg
2617a84e134Smrg/*ARGSUSED*/
2627a84e134Smrgstatic Boolean
2635ec34c4cSmrgXawRepeaterSetValues(Widget gcur, Widget greq _X_UNUSED, Widget gnew,
2645ec34c4cSmrg		     ArgList args _X_UNUSED, Cardinal *num_args _X_UNUSED)
2657a84e134Smrg{
2667a84e134Smrg    RepeaterWidget cur = (RepeaterWidget)gcur;
2677a84e134Smrg    RepeaterWidget cnew = (RepeaterWidget)gnew;
2687a84e134Smrg
2697a84e134Smrg    if (cur->repeater.minimum_delay != cnew->repeater.minimum_delay) {
2707a84e134Smrg	if (cnew->repeater.next_delay < cnew->repeater.minimum_delay)
2717a84e134Smrg	    cnew->repeater.next_delay = cnew->repeater.minimum_delay;
2727a84e134Smrg    }
2737a84e134Smrg
2747a84e134Smrg    return (False);
2757a84e134Smrg}
2767a84e134Smrg
2777a84e134Smrg/*ARGSUSED*/
2787a84e134Smrgstatic void
2795ec34c4cSmrgActionStart(Widget gw, XEvent *event _X_UNUSED, String *params _X_UNUSED, Cardinal *num_params _X_UNUSED)
2807a84e134Smrg{
2817a84e134Smrg    RepeaterWidget rw = (RepeaterWidget)gw;
2827a84e134Smrg
2837a84e134Smrg    CLEAR_TIMEOUT(rw);
284421c997bSmrg    if (rw->repeater.start_callbacks)
2857a84e134Smrg	XtCallCallbackList(gw, rw->repeater.start_callbacks, NULL);
2867a84e134Smrg
2877a84e134Smrg    DO_CALLBACK(rw);
2885ec34c4cSmrg    rw->repeater.timer = ADD_TIMEOUT(rw, (unsigned long)rw->repeater.initial_delay);
2897a84e134Smrg    rw->repeater.next_delay = rw->repeater.repeat_delay;
2907a84e134Smrg}
2917a84e134Smrg
2927a84e134Smrg/*ARGSUSED*/
2937a84e134Smrgstatic void
2945ec34c4cSmrgActionStop(Widget gw, XEvent *event _X_UNUSED, String *params _X_UNUSED, Cardinal *num_params _X_UNUSED)
2957a84e134Smrg{
2967a84e134Smrg    RepeaterWidget rw = (RepeaterWidget)gw;
2977a84e134Smrg
2987a84e134Smrg    CLEAR_TIMEOUT((RepeaterWidget)gw);
299421c997bSmrg    if (rw->repeater.stop_callbacks)
3007a84e134Smrg	XtCallCallbackList(gw, rw->repeater.stop_callbacks, NULL);
3017a84e134Smrg}
302