1 /***********************************************************************/
2 /* Open Visualization Data Explorer                                    */
3 /* (C) Copyright IBM Corp. 1989,1999                                   */
4 /* ALL RIGHTS RESERVED                                                 */
5 /* This code licensed under the                                        */
6 /*    "IBM PUBLIC LICENSE - Open Visualization Data Explorer"          */
7 /***********************************************************************/
8 
9 #include <dxconfig.h>
10 #include "../base/defines.h"
11 
12 #include <Xm/DialogS.h>
13 #include <Xm/DrawP.h>
14 
15 #ifdef OS2
16 #include <stdlib.h>
17 #include <types.h>
18 #endif
19 
20 #include "VCRControl.h"
21 #include "VCRControlP.h"
22 #include "backward.bm"
23 #include "forward.bm"
24 /* #include "frame.bm" */
25 #include "loop.bm"
26 #include "palim.bm"
27 #include "pause.bm"
28 #include "step.bm"
29 #include "stepb.bm"
30 #include "stepf.bm"
31 #include "stop.bm"
32 
33 #ifndef MIN
34 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
35 #endif
36 #ifndef MAX
37 #define MAX(a,b) (((a) > (b)) ? (a) : (b))
38 #endif
39 
40 
41 
42 extern void _XmForegroundColorDefault();
43 extern void _XmBackgroundColorDefault();
44 
45 static XtResource resources[] =
46     {
47         {
48             XmNactionCallback,XmCActionCallback, XmRCallback, sizeof(XtPointer),
49             XtOffset(XmVCRControlWidget, vcr_control.action_callback),
50             XmRCallback, NULL
51         },
52         {
53             XmNframeCallback, XmCFrameCallback, XmRCallback, sizeof(XtPointer),
54             XtOffset(XmVCRControlWidget, vcr_control.frame_callback),
55             XmRCallback, NULL
56         },
57         {
58             XmNstart, XmCStart, XmRShort, sizeof(short),
59             XtOffset(XmVCRControlWidget, vcr_control.start_value),
60             XmRImmediate, (XtPointer) 0
61         },
62         {
63             XmNnext, XmCNext, XmRShort, sizeof(short),
64             XtOffset(XmVCRControlWidget, vcr_control.next_value),
65             XmRImmediate, (XtPointer) 0
66         },
67         {
68             XmNcurrent, XmCCurrent, XmRShort, sizeof(short),
69             XtOffset(XmVCRControlWidget, vcr_control.current_value),
70             XmRImmediate, (XtPointer) 0
71         },
72         {
73             XmNcurrentVisible,XmCCurrentVisible,XmRBoolean, sizeof(Boolean),
74             XtOffset(XmVCRControlWidget, vcr_control.current_visible),
75             XmRImmediate, (XtPointer) True
76         },
77         {
78             XmNstop, XmCStop, XmRShort, sizeof(short),
79             XtOffset(XmVCRControlWidget, vcr_control.stop_value),
80             XmRImmediate, (XtPointer) 0
81         },
82         {
83             XmNminimum, XmCMinimum, XmRShort, sizeof(short),
84             XtOffset(XmVCRControlWidget, vcr_control.min_value),
85             XmRImmediate, (XtPointer) 1
86         },
87         {
88             XmNmaximum, XmCMaximum, XmRShort, sizeof(short),
89             XtOffset(XmVCRControlWidget, vcr_control.max_value),
90             XmRImmediate, (XtPointer) 10
91         },
92         {
93             XmNincrement, XmCIncrement, XmRShort, sizeof(short),
94             XtOffset(XmVCRControlWidget, vcr_control.frame_increment),
95             XmRImmediate, (XtPointer) 1
96         },
97         {
98             XmNforwardButtonState, XmCForwardButtonState, XmRBoolean, sizeof(Boolean),
99             XtOffset(XmVCRControlWidget, vcr_control.button_is_in[VCR_FORWARD]),
100             XmRImmediate, (XtPointer) 0
101         },
102         {
103             XmNbackwardButtonState,XmCBackwardButtonState,XmRBoolean, sizeof(Boolean),
104             XtOffset(XmVCRControlWidget, vcr_control.button_is_in[VCR_BACKWARD]),
105             XmRImmediate, (XtPointer) 0
106         },
107         {
108             XmNloopButtonState, XmCLoopButtonState, XmRBoolean, sizeof(Boolean),
109             XtOffset(XmVCRControlWidget, vcr_control.button_is_in[VCR_LOOP]),
110             XmRImmediate, (XtPointer) 0
111         },
112         {
113             XmNpalindromeButtonState, XmCPalindromeButtonState, XmRBoolean, sizeof(Boolean),
114             XtOffset(XmVCRControlWidget, vcr_control.button_is_in[VCR_PALINDROME]),
115             XmRImmediate, (XtPointer) 0
116         },
117         {
118             XmNstepButtonState, XmCStepButtonState, XmRBoolean, sizeof(Boolean),
119             XtOffset(XmVCRControlWidget, vcr_control.button_is_in[VCR_STEP]),
120             XmRImmediate, (XtPointer) 0
121         },
122         {
123             XmNcountButtonState, XmCCountButtonState, XmRBoolean, sizeof(Boolean),
124             XtOffset(XmVCRControlWidget, vcr_control.button_is_in[VCR_COUNT]),
125             XmRImmediate, (XtPointer) 0
126         },
127         {
128             XmNlimitColor, XmCLimitColor, XmRPixel, sizeof(Pixel),
129             XtOffset(XmVCRControlWidget, vcr_control.limit_color),
130             XmRCallProc, (XtPointer) _XmForegroundColorDefault
131         },
132         {
133             XmNnextColor, XmCNextColor, XmRPixel, sizeof(Pixel),
134             XtOffset(XmVCRControlWidget, vcr_control.next_color),
135             XmRCallProc, (XtPointer) _XmForegroundColorDefault
136         },
137         {
138             XmNcurrentColor, XmCCurrentColor, XmRPixel, sizeof(Pixel),
139             XtOffset(XmVCRControlWidget, vcr_control.current_color),
140             XmRCallProc, (XtPointer) _XmForegroundColorDefault
141         },
142         {
143             XmNframeSensitive, XmCFrameSensitive, XmRBoolean, sizeof(Boolean),
144             XtOffset(XmVCRControlWidget, vcr_control.frame_sensitive),
145             XmRImmediate, (XtPointer) TRUE
146         },
147         {
148             XmNminSensitive, XmCMinSensitive, XmRBoolean, sizeof(Boolean),
149             XtOffset(XmVCRControlWidget, vcr_control.min_sensitive),
150             XmRImmediate, (XtPointer) TRUE
151         },
152         {
153             XmNmaxSensitive, XmCMaxSensitive, XmRBoolean, sizeof(Boolean),
154             XtOffset(XmVCRControlWidget, vcr_control.max_sensitive),
155             XmRImmediate, (XtPointer) TRUE
156         },
157         {
158             XmNincSensitive, XmCIncSensitive, XmRBoolean, sizeof(Boolean),
159             XtOffset(XmVCRControlWidget, vcr_control.inc_sensitive),
160             XmRImmediate, (XtPointer) TRUE
161         },
162     };
163 
164 
165 /*  Maintain actions support for basic manager functioning  */
166 static char defaultTranslations[] =
167     "<EnterWindow>:  Enter() \n\
168     <FocusIn>:      FocusIn()";
169 
170 extern void _XmManagerEnter();
171 extern void _XmManagerFocusIn();
172 
173 static XtActionsRec actionsList[] =
174     {
175         { "Enter",    (XtActionProc) _XmManagerEnter },
176         { "FocusIn",  (XtActionProc) _XmManagerFocusIn },
177     };
178 
179 
180 /****************************************************************
181  *
182  * Full class record constant
183  *
184  ****************************************************************/
185 
186 static void Initialize(XmVCRControlWidget request, XmVCRControlWidget new);
187 static Boolean SetValues(XmVCRControlWidget current,
188                          XmVCRControlWidget request,
189                          XmVCRControlWidget new);
190 static void Destroy(XmVCRControlWidget w);
191 static void MyRealize(XmVCRControlWidget w, XtValueMask *valueMask,
192                       XSetWindowAttributes *attributes);
193 static void SimulateButtonPress(XmVCRControlWidget vcr, int button_num);
194 
195 XmVCRControlClassRec xmVCRControlClassRec =
196     {
197         {			/* core_class fields      */
198             (WidgetClass) &xmFormClassRec,		/* superclass         */
199             "XmVCRControl",				/* class_name         */
200             sizeof(XmVCRControlRec),			/* widget_size        */
201             NULL,					/* class_initialize   */
202             NULL,					/* class_part_init    */
203             FALSE,					/* class_inited       */
204             (XtInitProc) Initialize,			/* initialize         */
205             NULL,					/* initialize_hook    */
206             (XtRealizeProc)MyRealize,			/* realize            */
207             actionsList,				/* actions	      */
208             XtNumber(actionsList),			/* num_actions	      */
209             resources,				/* resources          */
210             XtNumber(resources),			/* num_resources      */
211             NULLQUARK,				/* xrm_class          */
212             TRUE,					/* compress_motion    */
213             TRUE,					/* compress_exposure  */
214             TRUE,					/* compress_enterlv   */
215             FALSE,					/* visible_interest   */
216             (XtWidgetProc) Destroy,			/* destroy            */
217             (XtWidgetProc) XtInheritResize,			/* resize             */
218             (XtExposeProc)_XtInherit,/*(XtExposeProc) Redisplay,*//* expose */
219             (XtSetValuesFunc) SetValues,		/* set_values         */
220             NULL,					/* set_values_hook    */
221             (XtAlmostProc)_XtInherit,			/* set_values_almost  */
222             NULL,					/* get_values_hook    */
223             NULL,					/* accept_focus       */
224             XtVersion,				/* version            */
225             NULL,					/* callback_private   */
226             defaultTranslations,			/* tm_table           */
227             XtInheritQueryGeometry,			/* query_geometry     */
228             NULL,             	                /* display_accelerator   */
229             NULL,		                        /* extension             */
230         },
231 
232         {		/* composite_class fields */
233             XtInheritGeometryManager,			/* geometry _manager  */
234             XtInheritChangeManaged,			/* change_managed     */
235             (XtWidgetProc)_XtInherit,			/* insert_child       */
236             XtInheritDeleteChild,			/* delete_child       */
237             NULL,                                     /* extension          */
238         },
239 
240         {		/* constraint_class fields */
241             NULL,					/* resource list        */
242             0,					/* num resources        */
243             sizeof(XmFormConstraintRec),		/* constraint size      */
244             NULL,					/* init proc            */
245             NULL,					/* destroy proc         */
246             NULL,					/* set values proc      */
247             NULL,                                     /* extension            */
248         },
249 
250         {		/* manager_class fields */
251 #if (XmVersion >= 1001)
252             XtInheritTranslations,     		/* translations           */
253 #else
254             (XtTranslations)_XtInherit,     		/* translations           */
255 #endif
256             NULL,					/* get resources      	  */
257             0,					/* num get_resources 	  */
258             NULL,					/* get_cont_resources     */
259             0,					/* num_get_cont_resources */
260             (XmParentProcessProc)NULL,                /* parent_process         */
261             NULL,					/* extension           */
262         },
263 
264         {            /* bulletin board widget class */
265             False,					/* install_accelarators */
266             NULL,					/* install_accelarators */
267             NULL,					/* install_accelarators */
268             NULL,					/* extension           */
269         },
270 
271         {            /* form widget class */
272             NULL,					/* extension           */
273         },
274 
275         {		/* vcr_control class - none */
276             NULL,						/* mumble */
277         }
278     };
279 
280 WidgetClass xmVCRControlWidgetClass = (WidgetClass) &xmVCRControlClassRec;
281 
282 /*  Define interval of showing momentary button as depressed  */
283 
284 #define SHORT_WAIT 150
285 #define LONG_WAIT 500
286 #define MAX_VAL(a,b) ((a)>(b)?(a):(b))
287 #define MIN_VAL(a,b) ((a)<(b)?(a):(b))
288 #define superclass (&widgetClassRec)
289 
290 static void SetLabel();
291 static void CreateVCRCounter();
292 static void VCRButtonResize();
293 static void _VCRButtonEvent();
294 static void VCRButtonEvent();
295 static void VCRButtonExpose();
296 static void VCRCounterExpose();
297 static void ReleaseVCRButton();
298 static void PushVCRButton();
299 static void ReleaseModeButtons();
300 static void ReplaceFrame();
301 void ChangeVCRStopValue( XmVCRControlWidget vcr, int value, Boolean to_vcr,
302                          Boolean to_frame_control, Boolean to_outside );
303 void ChangeVCRStartValue( XmVCRControlWidget vcr, int value, Boolean to_vcr,
304                           Boolean to_frame_control, Boolean to_outside );
305 void ChangeVCRNextValue( XmVCRControlWidget vcr, int value, Boolean to_vcr,
306                          Boolean to_frame_control, Boolean to_outside );
307 void ChangeVCRCurrentValue( XmVCRControlWidget vcr, int value, Boolean to_vcr,
308                             Boolean to_frame_control, Boolean to_outside );
309 void ChangeVCRIncrementValue( XmVCRControlWidget vcr, int increment,
310                               Boolean to_vcr, Boolean to_frame_control,
311                               Boolean to_outside );
312 static void PopdownCallback();
313 static void map_dialog();
314 static void FrameControlCallback();
315 
316 /*  Subroutine:	Initialize
317  *  Effect:	Create and initialize the component widgets
318  */
319 
Initialize(XmVCRControlWidget request,XmVCRControlWidget new)320 static void Initialize( XmVCRControlWidget request, XmVCRControlWidget new )
321 {
322     Arg wargs[20];
323 
324     if (request->core.width == 0)
325         new->core.width = 240;
326     if (request->core.height == 0)
327         new->core.height = 60;
328 
329     new->vcr_control.last_frame_control_press = -1;  /* Net pressed yet */
330 
331     new->vcr_control.parent = XtParent(new);
332 
333     new->vcr_control.button_timeout = (XtIntervalId)NULL;
334 
335     /*
336      * Check min and max relative to each other
337      */
338     if( request->vcr_control.max_value < request->vcr_control.min_value )
339         new->vcr_control.max_value = new->vcr_control.min_value;
340 
341     /*
342      * Check current and next relative to min.
343      */
344     if( request->vcr_control.next_value < request->vcr_control.min_value )
345         new->vcr_control.next_value = new->vcr_control.min_value;
346     if( request->vcr_control.current_value < request->vcr_control.min_value )
347         new->vcr_control.current_value = new->vcr_control.min_value;
348 
349     /*
350      * Check current and next relative to max.
351      */
352     if( request->vcr_control.next_value > request->vcr_control.max_value )
353         new->vcr_control.next_value = new->vcr_control.max_value;
354     if( request->vcr_control.current_value > request->vcr_control.max_value )
355         new->vcr_control.current_value = new->vcr_control.max_value;
356 
357     new->vcr_control.step_being_held = FALSE;
358     new->vcr_control.frame_control_is_up = FALSE;
359 
360     /* Init all non-resource buttons to the up state */
361     new->vcr_control.button_is_in[VCR_STOP] = FALSE;
362     new->vcr_control.button_is_in[VCR_PAUSE] = FALSE;
363     new->vcr_control.button_is_in[VCR_FORWARD_STEP] = FALSE;
364     new->vcr_control.button_is_in[VCR_BACKWARD_STEP] = FALSE;
365 
366 
367     /*  Loop  */
368     XtSetArg(wargs[0], XmNleftAttachment, XmATTACH_POSITION);
369     XtSetArg(wargs[1], XmNrightAttachment, XmATTACH_POSITION);
370     XtSetArg(wargs[2], XmNtopAttachment, XmATTACH_FORM);
371     XtSetArg(wargs[3], XmNbottomAttachment, XmATTACH_POSITION);
372     XtSetArg(wargs[4], XmNleftPosition, 0);
373     XtSetArg(wargs[5], XmNrightPosition, 25);
374     XtSetArg(wargs[6], XmNtopPosition, 0);
375     XtSetArg(wargs[7], XmNbottomPosition, 50);
376     XtSetArg(wargs[8], XmNshadowType, XmSHADOW_OUT);
377     new->vcr_control.frame[VCR_LOOP] =
378         (XmFrameWidget)XmCreateFrame((Widget)new, "loop", wargs, 9);
379     SetLabel(new, VCR_LOOP, loop_bits, loop_width, loop_height);
380 
381     /*  Palindrome  */
382     XtSetArg(wargs[4], XmNleftPosition, 25);
383     XtSetArg(wargs[5], XmNrightPosition, 50);
384     new->vcr_control.frame[VCR_PALINDROME] =
385         (XmFrameWidget)XmCreateFrame((Widget)new, "palindrome", wargs, 9);
386     SetLabel(new, VCR_PALINDROME, palim_bits, palim_width, palim_height);
387 
388     /*  Step  */
389     XtSetArg(wargs[4], XmNleftPosition, 50);
390     XtSetArg(wargs[5], XmNrightPosition, 75);
391     new->vcr_control.frame[VCR_STEP] =
392         (XmFrameWidget)XmCreateFrame((Widget)new, "step", wargs, 9);
393     SetLabel(new, VCR_STEP, step_bits, step_width, step_height);
394 
395     /*  Counter  */
396     XtSetArg(wargs[4], XmNleftPosition, 75);
397     XtSetArg(wargs[5], XmNrightPosition, 100);
398     new->vcr_control.frame[VCR_COUNT] =
399         (XmFrameWidget)XmCreateFrame((Widget)new, "frame", wargs, 9);
400     CreateVCRCounter(new);
401 
402     /*  Backward  */
403     XtSetArg(wargs[2], XmNtopAttachment, XmATTACH_POSITION);
404     XtSetArg(wargs[4], XmNleftPosition, 0);
405     XtSetArg(wargs[5], XmNrightPosition, 25);
406     XtSetArg(wargs[6], XmNtopPosition, 50);
407     XtSetArg(wargs[7], XmNbottomPosition, 100);
408     new->vcr_control.frame[VCR_BACKWARD] =
409         (XmFrameWidget)XmCreateFrame((Widget)new, "backward", wargs, 9);
410     SetLabel(new, VCR_BACKWARD, backward_bits, backward_width, backward_height);
411 
412     /*  Forward  */
413     XtSetArg(wargs[4], XmNleftPosition, 25);
414     XtSetArg(wargs[5], XmNrightPosition, 50);
415     new->vcr_control.frame[VCR_FORWARD] =
416         (XmFrameWidget)XmCreateFrame((Widget)new, "forward", wargs, 9);
417     SetLabel(new, VCR_FORWARD, forward_bits, forward_width, forward_height);
418 
419     /*  Stop  */
420     XtSetArg(wargs[4], XmNleftPosition, 50);
421     XtSetArg(wargs[5], XmNrightPosition, 62);
422     new->vcr_control.frame[VCR_STOP] =
423         (XmFrameWidget)XmCreateFrame((Widget)new, "stop", wargs, 9);
424     SetLabel(new, VCR_STOP, stop_bits, stop_width, stop_height);
425 
426     /*  Pause  */
427     XtSetArg(wargs[4], XmNleftPosition, 62);
428     XtSetArg(wargs[5], XmNrightPosition, 100);
429     new->vcr_control.frame[VCR_PAUSE] =
430         (XmFrameWidget) XmCreateFrame((Widget)new, "pause", wargs, 9);
431     SetLabel(new, VCR_PAUSE, pause_bits, pause_width, pause_height);
432     XtManageChildren((Widget*)new->vcr_control.frame, 8);
433 
434     /*  Forward Step  */
435     new->vcr_control.frame[VCR_FORWARD_STEP] =
436         (XmFrameWidget)XmCreateFrame((Widget)new, "stepf", wargs, 9);
437     SetLabel(new, VCR_FORWARD_STEP, stepf_bits, stepf_width, stepf_height);
438 
439     /*  Backward Step  */
440     new->vcr_control.frame[VCR_BACKWARD_STEP] =
441         (XmFrameWidget)XmCreateFrame((Widget)new, "stepb", wargs, 9);
442     SetLabel(new, VCR_BACKWARD_STEP, stepb_bits, stepb_width, stepb_height);
443 
444     XtSetArg(wargs[0], XmNwidth, 400);
445     XtSetArg(wargs[1], XmNheight, 180);
446     XtSetArg(wargs[2], XmNdeleteResponse, XmUNMAP);
447     XtSetArg(wargs[3], XmNallowShellResize, True);
448     XtSetArg(wargs[4], XmNminWidth, 380);
449     XtSetArg(wargs[5], XmNminHeight, 160);
450 
451     new->vcr_control.shell = XmCreateDialogShell((Widget)new, "Frame Control",
452                              wargs, 6);
453 
454     XtSetArg(wargs[2], XmNstart, new->vcr_control.start_value);
455     XtSetArg(wargs[3], XmNnext, new->vcr_control.next_value);
456     XtSetArg(wargs[4], XmNcurrent, new->vcr_control.current_value);
457     XtSetArg(wargs[5], XmNstop, new->vcr_control.stop_value);
458     XtSetArg(wargs[6], XmNminimum, new->vcr_control.min_value);
459     XtSetArg(wargs[7], XmNincrement, new->vcr_control.frame_increment);
460     XtSetArg(wargs[8], XmNmaximum, new->vcr_control.max_value);
461     XtSetArg(wargs[9], XmNnextColor, new->vcr_control.next_color);
462     XtSetArg(wargs[10], XmNcurrentColor, new->vcr_control.current_color);
463     XtSetArg(wargs[11], XmNlimitColor, new->vcr_control.limit_color);
464     XtSetArg(wargs[12], XmNcurrentVisible, new->vcr_control.current_visible);
465     XtSetArg(wargs[13], XmNdefaultPosition, False);
466     new->vcr_control.frame_control = (XmFrameControlWidget)XmCreateFrameControl(
467                                          (Widget)new->vcr_control.shell, "frame_control", wargs, 14);
468 
469 
470     XtAddCallback((Widget)new->vcr_control.frame_control, XmNvalueCallback,
471                   (XtCallbackProc)FrameControlCallback, new);
472     XtAddCallback((Widget)new->vcr_control.shell, XmNpopdownCallback,
473                   (XtCallbackProc)PopdownCallback, new);
474     XtAddCallback((Widget)new->vcr_control.frame_control, XmNmapCallback,
475                   (XtCallbackProc)map_dialog, new);
476 }
477 
478 #undef MIN_VAL
479 #undef MAX_VAL
MyRealize(XmVCRControlWidget w,XtValueMask * valueMask,XSetWindowAttributes * attributes)480 static void MyRealize(XmVCRControlWidget w, XtValueMask *valueMask,
481                       XSetWindowAttributes *attributes)
482 {
483 
484     /* Call the superclass Realize */
485     (*superclass->core_class.realize)((Widget)w, valueMask, attributes);
486     if (w->vcr_control.button_is_in[VCR_COUNT]) {
487         w->vcr_control.button_is_in[VCR_COUNT] = FALSE;
488         SimulateButtonPress(w, VCR_COUNT);
489     }
490     XtRealizeWidget((Widget)w->vcr_control.frame[VCR_BACKWARD]);
491     XtRealizeWidget((Widget)w->vcr_control.button[VCR_BACKWARD]);
492     if (w->vcr_control.button_is_in[VCR_BACKWARD]) {
493         w->vcr_control.button_is_in[VCR_BACKWARD] = FALSE;
494         SimulateButtonPress(w, VCR_BACKWARD);
495     }
496     XtRealizeWidget((Widget)w->vcr_control.frame[VCR_FORWARD]);
497     XtRealizeWidget((Widget)w->vcr_control.button[VCR_FORWARD]);
498     if (w->vcr_control.button_is_in[VCR_FORWARD]) {
499         w->vcr_control.button_is_in[VCR_FORWARD] = FALSE;
500         SimulateButtonPress(w, VCR_FORWARD);
501     }
502     XtRealizeWidget((Widget)w->vcr_control.frame[VCR_LOOP]);
503     XtRealizeWidget((Widget)w->vcr_control.button[VCR_LOOP]);
504     if (w->vcr_control.button_is_in[VCR_LOOP]) {
505         w->vcr_control.button_is_in[VCR_LOOP] = FALSE;
506         SimulateButtonPress(w, VCR_LOOP);
507     }
508     XtRealizeWidget((Widget)w->vcr_control.frame[VCR_STEP]);
509     XtRealizeWidget((Widget)w->vcr_control.button[VCR_STEP]);
510     if (w->vcr_control.button_is_in[VCR_STEP]) {
511         w->vcr_control.button_is_in[VCR_STEP] = FALSE;
512         SimulateButtonPress(w, VCR_STEP);
513     }
514     XtRealizeWidget((Widget)w->vcr_control.frame[VCR_PALINDROME]);
515     XtRealizeWidget((Widget)w->vcr_control.button[VCR_PALINDROME]);
516     if (w->vcr_control.button_is_in[VCR_PALINDROME]) {
517         w->vcr_control.button_is_in[VCR_PALINDROME] = FALSE;
518         SimulateButtonPress(w, VCR_PALINDROME);
519     }
520 }
SimulateButtonPress(XmVCRControlWidget vcr,int button_num)521 static void SimulateButtonPress(XmVCRControlWidget vcr, int button_num)
522 {
523     Widget widget;
524     XmDrawingAreaCallbackStruct call_data;
525 
526     call_data.event = (XEvent *)XtMalloc(sizeof(XEvent));
527 
528     call_data.event->type           = ButtonPress;
529     call_data.event->xbutton.button = Button1;
530 
531     /*
532      * Kludge to tell VCRButtonEvent not to callback application.
533      */
534     call_data.event->xbutton.x = -1;
535     widget = (Widget)vcr->vcr_control.button[button_num];
536     VCRButtonEvent(widget, vcr, &call_data);
537     XtFree((char*)call_data.event);
538 
539 }
540 
541 /*  Subroutine: SetValues
542  *  Effect:     Handles requests to change things from the application
543 */
544 
SetValues(XmVCRControlWidget current,XmVCRControlWidget request,XmVCRControlWidget new)545 static Boolean SetValues(XmVCRControlWidget current,
546                          XmVCRControlWidget request,
547                          XmVCRControlWidget new)
548 {
549     int i;
550     Arg wargs[12];
551 
552     if (new->vcr_control.min_value > new->vcr_control.max_value) {
553         new->vcr_control.min_value = new->vcr_control.max_value;
554     };
555 
556     if (new->vcr_control.max_value < new->vcr_control.min_value) {
557         new->vcr_control.max_value = new->vcr_control.min_value;
558     };
559 
560     if (new->vcr_control.start_value > new->vcr_control.stop_value) {
561         new->vcr_control.start_value = new->vcr_control.stop_value;
562     };
563 
564     if (new->vcr_control.stop_value < new->vcr_control.start_value) {
565         new->vcr_control.stop_value = new->vcr_control.start_value;
566     };
567 
568     if (new->vcr_control.next_value < new->vcr_control.start_value) {
569         new->vcr_control.next_value = new->vcr_control.start_value;
570     };
571 #ifdef OBSOLETE
572 
573     if (new->vcr_control.current_value < new->vcr_control.start_value) {
574         new->vcr_control.current_value = new->vcr_control.start_value;
575     };
576 #endif
577 
578     if (new->vcr_control.next_value > (new->vcr_control.stop_value)) {
579         new->vcr_control.next_value = new->vcr_control.stop_value;
580     };
581 #ifdef OBSOLETE
582 
583     if (new->vcr_control.current_value > (new->vcr_control.stop_value)) {
584         new->vcr_control.current_value = new->vcr_control.stop_value;
585     };
586 #endif
587 
588     if (new->vcr_control.frame_increment > (new->vcr_control.stop_value -
589                                             new->vcr_control.start_value)) {
590         new->vcr_control.frame_increment = new->vcr_control.stop_value -
591                                            new->vcr_control.start_value;
592     };
593 
594     for(i = 0; i < VCR_STOP; i++)	/* To first non-resource button */
595     {
596         if (current->vcr_control.button_is_in[i] !=
597                 request->vcr_control.button_is_in[i])
598         {
599             new->vcr_control.button_is_in[i] =
600                 current->vcr_control.button_is_in[i];
601             SimulateButtonPress(new, i);
602             XFlush(XtDisplay(new));
603         }
604     }
605     if (current->vcr_control.min_value !=
606             new->vcr_control.min_value) {
607         XtSetArg(wargs[0], XmNminimum, new->vcr_control.min_value);
608         XtSetValues((Widget)new->vcr_control.frame_control, wargs, 1);
609         if (new->vcr_control.min_value > new->vcr_control.next_value)
610             ChangeVCRNextValue(new, new->vcr_control.min_value,
611                                TRUE, FALSE, TRUE);
612     }
613     if (current->vcr_control.max_value !=
614             new->vcr_control.max_value) {
615         XtSetArg(wargs[0], XmNmaximum, new->vcr_control.max_value);
616         XtSetValues((Widget)new->vcr_control.frame_control, wargs, 1);
617         if (new->vcr_control.max_value < new->vcr_control.next_value)
618             ChangeVCRNextValue(new, new->vcr_control.max_value,
619                                TRUE, FALSE, TRUE);
620     }
621     if (current->vcr_control.start_value !=
622             request->vcr_control.start_value) {
623         ChangeVCRStartValue(new, request->vcr_control.start_value,
624                             TRUE, TRUE, FALSE);
625     }
626     if (current->vcr_control.stop_value !=
627             request->vcr_control.stop_value) {
628         ChangeVCRStopValue(new, request->vcr_control.stop_value,
629                            TRUE, TRUE, FALSE);
630     }
631     if (current->vcr_control.next_value !=
632             request->vcr_control.next_value) {
633         ChangeVCRNextValue(new, new->vcr_control.next_value,
634                            TRUE, TRUE, FALSE);
635     }
636     if (current->vcr_control.current_value !=
637             request->vcr_control.current_value) {
638         ChangeVCRCurrentValue(new, new->vcr_control.current_value,
639                               TRUE, TRUE, FALSE);
640     }
641     if (current->vcr_control.frame_increment !=
642             request->vcr_control.frame_increment) {
643         ChangeVCRIncrementValue(new, new->vcr_control.frame_increment,
644                                 TRUE, TRUE, FALSE);
645     }
646     if (current->vcr_control.next_color !=
647             new->vcr_control.next_color) {
648         XtSetArg(wargs[0],XmNnextColor, new->vcr_control.next_color);
649         XtSetValues((Widget)new->vcr_control.frame_control, wargs, 1);
650     }
651     if (current->vcr_control.current_color !=
652             new->vcr_control.current_color) {
653         XtSetArg(wargs[0],XmNcurrentColor, new->vcr_control.current_color);
654         XtSetValues((Widget)new->vcr_control.frame_control, wargs, 1);
655     }
656     if (current->vcr_control.limit_color !=
657             new->vcr_control.limit_color) {
658         XtSetArg(wargs[0], XmNlimitColor, new->vcr_control.limit_color);
659         XtSetValues((Widget)new->vcr_control.frame_control, wargs, 1);
660     }
661     if (current->vcr_control.frame_sensitive !=
662             new->vcr_control.frame_sensitive) {
663         XtSetSensitive((Widget)new->vcr_control.frame_control,
664                        new->vcr_control.frame_sensitive);
665     }
666     if (current->vcr_control.min_sensitive !=
667             new->vcr_control.min_sensitive) {
668         XtVaSetValues((Widget)new->vcr_control.frame_control,
669                       XmNminSensitive, new->vcr_control.min_sensitive, NULL);
670     }
671     if (current->vcr_control.max_sensitive !=
672             new->vcr_control.max_sensitive) {
673         XtVaSetValues((Widget)new->vcr_control.frame_control,
674                       XmNmaxSensitive, new->vcr_control.max_sensitive, NULL);
675     }
676     if (current->vcr_control.inc_sensitive !=
677             new->vcr_control.inc_sensitive) {
678         XtVaSetValues((Widget)new->vcr_control.frame_control,
679                       XmNincSensitive, new->vcr_control.inc_sensitive, NULL);
680     }
681     if (current->vcr_control.current_visible !=
682             new->vcr_control.current_visible) {
683         ChangeVCRCurrentValue(new, new->vcr_control.current_value,
684                               TRUE, TRUE, FALSE);
685     }
686 
687     return FALSE;
688 }
689 
690 /*  Subroutine: Destroy
691  *  Effect:     Frees resources before widget is destroyed
692 */
693 
Destroy(XmVCRControlWidget w)694 static void Destroy(XmVCRControlWidget w)
695 {
696     /* Free all the callbacks */
697 }
698 
699 /*  Subroutine:	SetLabel
700  *  Purpose:	Prepare the interactive part of a button and its iconic image
701  *  Note:	The interaction is through a DrawingArea while the 3d frame
702  *		is currently a Frame parent (only because the DrawingArea
703  *		doesn't want to draw its own shadow).  Since we are already
704  *		handling some of the Frame's shadow drawing, we may be able
705  *		to do the same for a DrawingArea without frame).
706  */
707 
SetLabel(XmVCRControlWidget vcr,int i,char * bits,int width,int height)708 static void SetLabel( XmVCRControlWidget vcr,
709                       int i, char* bits, int width, int height )
710 {
711     Arg wargs[2];
712     unsigned long fg, bg;
713     Display *display;
714 
715     vcr->vcr_control.button[i] =
716         (XmDrawingAreaWidget) XmCreateDrawingArea((Widget)vcr->vcr_control.frame[i],
717                 "label", wargs, 0);
718     display = XtDisplay(vcr->vcr_control.button[i]);
719     fg = vcr->vcr_control.button[i]->manager.foreground;
720     bg = vcr->vcr_control.button[i]->core.background_pixel;
721     vcr->vcr_control.button_image[i].width = width;
722     vcr->vcr_control.button_image[i].height = height;
723     vcr->vcr_control.button_image[i].gc = NULL;
724     vcr->vcr_control.button_image[i].pixid =
725         XCreatePixmapFromBitmapData(display,
726                                     XRootWindowOfScreen(XtScreen(vcr)), bits, width, height,
727                                     fg,bg,DefaultDepth(display,XScreenNumberOfScreen(XtScreen(vcr))));
728     vcr->vcr_control.button[i]->manager.user_data =
729         (void *)(&vcr->vcr_control.button_image[i]);
730 
731     XtAddCallback((Widget)vcr->vcr_control.button[i], XmNexposeCallback,
732                   VCRButtonExpose, vcr);
733     XtAddCallback((Widget)vcr->vcr_control.button[i], XmNresizeCallback,
734                   VCRButtonResize, vcr);
735     XtAddCallback((Widget)vcr->vcr_control.button[i], XmNinputCallback,
736                   VCRButtonEvent, vcr);
737     XtManageChild((Widget)vcr->vcr_control.button[i]);
738 }
739 
740 /*  Subroutine:	CreateVCRCounter
741  *  Purpose:	Prepare the frame number display and the button which brings
742  *		up the frame_control.  This button is different from the others.
743  */
CreateVCRCounter(XmVCRControlWidget vcr)744 static void CreateVCRCounter( XmVCRControlWidget vcr )
745 {
746     Arg                  wargs[16];
747     XmString             text;
748     char                 string[100];
749     Dimension            width;
750 
751     vcr->vcr_control.button[VCR_COUNT] = (XmDrawingAreaWidget)
752                                          XmCreateDrawingArea((Widget)vcr->vcr_control.frame[VCR_COUNT],
753                                                              "label", wargs, 0);
754     XtManageChild((Widget)vcr->vcr_control.button[VCR_COUNT]);
755     XtAddCallback((Widget)vcr->vcr_control.button[VCR_COUNT], XmNexposeCallback,
756                   VCRCounterExpose, vcr);
757     XtAddCallback((Widget)vcr->vcr_control.button[VCR_COUNT], XmNinputCallback,
758                   VCRButtonEvent, vcr);
759 
760     /* Create the label */
761     XtSetArg(wargs[0], XmNx, 10);
762     XtSetArg(wargs[1], XmNy, 15);
763     /* Leave room for 5 digits */
764     sprintf(string, "55555");
765     text = XmStringCreate(string, XmSTRING_DEFAULT_CHARSET);
766     XtSetArg(wargs[2], XmNlabelString, text);
767     XtSetArg(wargs[3], XmNrecomputeSize, False);
768     vcr->vcr_control.label = (XmLabelWidget)XmCreateLabel(
769                                  (Widget)vcr->vcr_control.button[VCR_COUNT],
770                                  "label", wargs, 4);
771     XtManageChild((Widget)vcr->vcr_control.label);
772     XmStringFree(text);
773 
774     /*
775      * Now give the label the real string to display
776      */
777     if (vcr->vcr_control.current_visible) {
778         sprintf(string, "%5d", vcr->vcr_control.current_value);
779     } else {
780         sprintf(string, "     ");
781     }
782     text = XmStringCreate(string, XmSTRING_DEFAULT_CHARSET);
783     XtSetArg(wargs[0], XmNlabelString, text);
784     XtSetValues((Widget)vcr->vcr_control.label, wargs, 1);
785     XmStringFree(text);
786 
787     XtSetArg(wargs[0], XmNwidth, &width);
788     XtGetValues((Widget)vcr->vcr_control.label, wargs, 1);
789 
790     text = XmStringCreate("...", XmSTRING_DEFAULT_CHARSET);
791     XtSetArg(wargs[0], XmNx, 20 + width);
792     XtSetArg(wargs[1], XmNy, 15);
793     XtSetArg(wargs[2], XmNlabelString, text);
794     vcr->vcr_control.dot_dot_dot =
795         (XmLabelWidget)XmCreateLabel((Widget)vcr->vcr_control.button[VCR_COUNT],
796                                      "label", wargs,3);
797     XmStringFree(text);
798     XtManageChild((Widget)vcr->vcr_control.dot_dot_dot);
799 
800     XtAddEventHandler((Widget)vcr->vcr_control.label, ButtonPressMask,
801                       False, _VCRButtonEvent, vcr);
802     XtAddEventHandler((Widget)vcr->vcr_control.dot_dot_dot, ButtonPressMask,
803                       False, _VCRButtonEvent, vcr);
804 }
805 
806 
807 /*  Subroutine:	VCRButtonResize
808  *  Purpose:	Clear the old image and treat the resize as a new exposure
809  */
VCRButtonResize(XmDrawingAreaWidget w,XmVCRControlWidget vcr,XmDrawingAreaCallbackStruct * cb)810 static void VCRButtonResize( XmDrawingAreaWidget w, XmVCRControlWidget vcr,
811                              XmDrawingAreaCallbackStruct* cb )
812 {
813     if( XtIsRealized((Widget)w) ) {
814         XClearWindow(XtDisplay(w), XtWindow(w));
815         VCRButtonExpose(w, vcr, cb);
816     }
817 }
818 
819 /*  Subroutine:	VCRButtonExpose
820  *  Purpose:	Draw the iconic image in the button (it is usually attached
821  *		as user_data, but there may be exceptions).
822  */
VCRButtonExpose(XmDrawingAreaWidget w,XmVCRControlWidget vcr,XmDrawingAreaCallbackStruct * cb)823 static void VCRButtonExpose( XmDrawingAreaWidget w, XmVCRControlWidget vcr,
824                              XmDrawingAreaCallbackStruct* cb )
825 {
826     int x, y;
827     ButtonImage *image_data = (ButtonImage *)(w->manager.user_data);
828     Display *display;
829     Window window;
830 
831     if(   (image_data->background != w->core.background_pixel)
832             && image_data->gc ) {
833         XtReleaseGC((Widget)w, image_data->gc);
834         image_data->gc = NULL;
835     }
836     if( image_data->gc == NULL ) {
837         XGCValues	values;
838         XtGCMask	valueMask;
839         valueMask = GCForeground | GCBackground | GCFunction;
840         values.foreground = w->manager.foreground;
841         values.background = w->core.background_pixel;
842         values.function = GXcopy;
843         image_data->gc = XtGetGC((Widget)w, valueMask, &values);
844         image_data->background = w->core.background_pixel;
845     }
846     x = (w->core.width - image_data->width) / 2;
847     y = (w->core.height - image_data->height) / 2;
848     display = XtDisplay(w);
849     if (XtIsRealized((Widget)w)) {
850         window = XtWindow(w);
851         XCopyArea(display, image_data->pixid, window, image_data->gc, 0, 0,
852                   image_data->width, image_data->height, x, y);
853     }
854 }
855 
856 
857 /*  Subroutine:	VCRCounterExpose
858  *  Purpose:	Center the contents of the counter button
859  */
VCRCounterExpose(XmDrawingAreaWidget w,XmVCRControlWidget vcr,XmDrawingAreaCallbackStruct * cb)860 static void VCRCounterExpose( XmDrawingAreaWidget w, XmVCRControlWidget vcr,
861                               XmDrawingAreaCallbackStruct* cb )
862 {
863     int x1, x2, y;
864     x1 = vcr->vcr_control.button[VCR_COUNT]->core.width
865          - (vcr->vcr_control.label->core.width * 2);
866     if( x1 > 16 )
867         x1 /= 4;
868     else if( x1 > 4 )
869         x1 = 4;
870     else
871         x1 = 0;
872     y = (vcr->vcr_control.button[VCR_COUNT]->core.height
873          - vcr->vcr_control.label->core.height) / 2;
874     if( (x1 != vcr->vcr_control.label->core.x) ||
875             (y != vcr->vcr_control.label->core.y) ) {
876         RectObj g = (RectObj) vcr->vcr_control.label;
877         XmDropSiteStartUpdate((Widget)vcr->vcr_control.label);
878         XtMoveWidget((Widget)g, x1, y);
879     }
880     x1 += vcr->vcr_control.label->core.width;
881     x2 = x1 + ((vcr->vcr_control.button[VCR_COUNT]->core.width -
882                 (x1 + vcr->vcr_control.dot_dot_dot->core.width)) / 2);
883     y = (vcr->vcr_control.button[VCR_COUNT]->core.height
884          - vcr->vcr_control.dot_dot_dot->core.height) / 2;
885     if(   (x2 != vcr->vcr_control.dot_dot_dot->core.x)
886             || (y != vcr->vcr_control.dot_dot_dot->core.y) ) {
887         /*  Move the Gadget (XtMoveWidget doesn't move Gadgets in R3)  */
888         RectObj g = (RectObj) vcr->vcr_control.dot_dot_dot;
889         XmDropSiteStartUpdate((Widget)vcr->vcr_control.dot_dot_dot);
890         XtMoveWidget((Widget)g, x2, y);
891     }
892 }
893 
894 /*  Subroutine:	_VCRButtonEvent
895  *  Purpose: In XtR4/Motif1.1, the button events did not get to the drawing
896  *           area widget, so we will dispatch them on our own...
897  */
_VCRButtonEvent(Widget w,XmVCRControlWidget vcr,XEvent * event,Boolean * continue_to_dispatch)898 static void _VCRButtonEvent( Widget w, XmVCRControlWidget vcr,
899                              XEvent *event, Boolean *continue_to_dispatch )
900 {
901     XmDrawingAreaCallbackStruct call_data;
902 
903     call_data.event = event;
904     VCRButtonEvent(vcr->vcr_control.button[VCR_COUNT], vcr, &call_data);
905 }
906 /*  Subroutine:	VCRButtonEvent
907  *  Purpose:	Field button events from the Drawing Areas to make them behave
908  *		like buttons (including all interactions among the buttons).
909  */
VCRButtonEvent(XmDrawingAreaWidget w,XmVCRControlWidget vcr,XmDrawingAreaCallbackStruct * call_data)910 static void VCRButtonEvent( XmDrawingAreaWidget w, XmVCRControlWidget vcr,
911                             XmDrawingAreaCallbackStruct* call_data )
912 {
913     VCRCallbackStruct data;
914 
915     if( call_data->event->type == ButtonPress &&
916             call_data->event->xbutton.button == Button1 )
917     {
918         if ( w != vcr->vcr_control.button[VCR_COUNT] )
919             vcr->vcr_control.last_frame_control_press = -1;
920 
921         if( w == vcr->vcr_control.button[VCR_FORWARD] ) {
922             if( !vcr->vcr_control.button_is_in[VCR_FORWARD] ) {
923                 ReleaseModeButtons(vcr);
924                 PushVCRButton(vcr, VCR_FORWARD);
925 
926                 if (call_data->event->xbutton.x != -1) {
927                     data.action = VCR_FORWARD;
928                     data.on     = TRUE;
929                     XtCallCallbacks((Widget)vcr, XmNactionCallback, &data);
930                 }
931                 if(   (vcr->vcr_control.button_is_in[VCR_LOOP] == FALSE)
932                         && (vcr->vcr_control.button_is_in[VCR_PALINDROME] == FALSE)
933                         && (  (vcr->vcr_control.next_value +
934                                vcr->vcr_control.frame_increment)
935                               > vcr->vcr_control.stop_value) ) {
936                     /*  Do not queue up additional step is step mode */
937                     if( vcr->vcr_control.button_is_in[VCR_STEP] )
938                         return;
939                 }
940             }
941             /*  If in, pressing releases (releases pause as well) exc. step  */
942             else if( vcr->vcr_control.button_is_in[VCR_STEP] == FALSE ) {
943                 ReleaseVCRButton(vcr, VCR_FORWARD);
944 
945 
946                 if (call_data->event->xbutton.x != -1) {
947                     data.action = VCR_PAUSE;
948                     data.on     = TRUE;
949                     XtCallCallbacks((Widget)vcr, XmNactionCallback, &data);
950                 }
951             }
952         } else if( w == vcr->vcr_control.button[VCR_BACKWARD] ) {
953             /*  If out, unset forward, stop, pause  */
954             if( !vcr->vcr_control.button_is_in[VCR_BACKWARD] ) {
955                 ReleaseModeButtons(vcr);
956                 PushVCRButton(vcr, VCR_BACKWARD);
957                 if (call_data->event->xbutton.x != -1) {
958                     data.action = VCR_BACKWARD;
959                     data.on     = TRUE;
960                     XtCallCallbacks((Widget)vcr, XmNactionCallback, &data);
961                 }
962                 if(   (vcr->vcr_control.button_is_in[VCR_LOOP] == FALSE)
963                         && (vcr->vcr_control.button_is_in[VCR_PALINDROME] == FALSE)
964                         && (  (vcr->vcr_control.next_value -
965                                vcr->vcr_control.frame_increment)
966                               < vcr->vcr_control.start_value) ) {
967                     /*  Do not queue up additional step is step mode */
968                     if( vcr->vcr_control.button_is_in[VCR_STEP] )
969                         return;
970                 }
971             }
972             /*  If in, pressing releases (releases pause as well) exc. step  */
973             else if( vcr->vcr_control.button_is_in[VCR_STEP] == FALSE ) {
974                 ReleaseVCRButton(vcr, VCR_BACKWARD);
975 
976                 if (call_data->event->xbutton.x != -1) {
977                     data.action = VCR_PAUSE;
978                     data.on     = TRUE;
979                     XtCallCallbacks((Widget)vcr, XmNactionCallback, &data);
980                 }
981             }
982         } else if( w == vcr->vcr_control.button[VCR_PALINDROME] ) {
983             if( vcr->vcr_control.button_is_in[VCR_PALINDROME] ) {
984                 ReleaseVCRButton(vcr, VCR_PALINDROME);
985             } else {
986                 PushVCRButton(vcr, VCR_PALINDROME);
987             }
988             if (call_data->event->xbutton.x != -1) {
989                 data.action = VCR_PALINDROME;
990                 data.on     = vcr->vcr_control.button_is_in[VCR_PALINDROME];
991                 XtCallCallbacks((Widget)vcr, XmNactionCallback, &data);
992             }
993         } else if( w == vcr->vcr_control.button[VCR_STEP] ) {
994             if( vcr->vcr_control.button_is_in[VCR_STEP] ) {
995                 /*  Call application first, then change the button state  */
996                 data.action = VCR_STEP;
997                 if (call_data->event->xbutton.x != -1) {
998                     data.on     = FALSE;
999                     XtCallCallbacks((Widget)vcr, XmNactionCallback, &data);
1000                 }
1001                 ReleaseVCRButton(vcr, VCR_STEP);
1002                 /*  Switch the button icons  */
1003                 vcr->vcr_control.button[VCR_FORWARD]->manager.user_data =
1004                     (void *)(&vcr->vcr_control.button_image[VCR_FORWARD]);
1005                 vcr->vcr_control.button[VCR_BACKWARD]->manager.user_data =
1006                     (void *)(&vcr->vcr_control.button_image[VCR_BACKWARD]);
1007                 /*  Clear old icons before drawing new ones  */
1008                 XClearWindow(XtDisplay(vcr),
1009                              XtWindow(vcr->vcr_control.button[VCR_FORWARD]));
1010                 XClearWindow(XtDisplay(vcr),
1011                              XtWindow(vcr->vcr_control.button[VCR_BACKWARD]));
1012             } else {
1013                 /*  Call application first, then change the button state  */
1014                 if (call_data->event->xbutton.x != -1) {
1015                     data.action = VCR_STEP;
1016                     data.on     = TRUE;
1017                     XtCallCallbacks((Widget)vcr, XmNactionCallback, &data);
1018                 }
1019                 PushVCRButton(vcr, VCR_STEP);
1020                 if(   vcr->vcr_control.button_is_in[VCR_FORWARD]
1021                         || vcr->vcr_control.button_is_in[VCR_BACKWARD] ) {
1022                     /*  Invoking step during playing pauses action  */
1023                     if( vcr->vcr_control.button_is_in[VCR_FORWARD] )
1024                         ReleaseVCRButton(vcr, VCR_FORWARD);
1025                     else
1026                         ReleaseVCRButton(vcr, VCR_BACKWARD);
1027                 }
1028                 /*  Switch the button icons  */
1029                 vcr->vcr_control.button[VCR_FORWARD]->manager.user_data =
1030                     (void *)(&vcr->vcr_control.button_image[VCR_FORWARD_STEP]);
1031                 vcr->vcr_control.button[VCR_BACKWARD]->manager.user_data =
1032                     (void *)(&vcr->vcr_control.button_image[VCR_BACKWARD_STEP]);
1033                 /*  No need to clear since the step icon is bigger  */
1034             }
1035             /*  Redraw the Button icon  */
1036             VCRButtonExpose(vcr->vcr_control.button[VCR_FORWARD], vcr, NULL);
1037             VCRButtonExpose(vcr->vcr_control.button[VCR_BACKWARD], vcr, NULL);
1038         } else if( w == vcr->vcr_control.button[VCR_LOOP] ) {
1039             if( vcr->vcr_control.button_is_in[VCR_LOOP] )
1040                 ReleaseVCRButton(vcr, VCR_LOOP);
1041             else
1042                 PushVCRButton(vcr, VCR_LOOP);
1043             if (call_data->event->xbutton.x != -1) {
1044                 data.action = VCR_LOOP;
1045                 data.on     = vcr->vcr_control.button_is_in[VCR_LOOP];
1046                 XtCallCallbacks((Widget)vcr, XmNactionCallback, &data);
1047             }
1048         } else if( w == vcr->vcr_control.button[VCR_STOP] ) {
1049             if( !vcr->vcr_control.button_is_in[VCR_STOP] ) {
1050                 ReleaseModeButtons(vcr);
1051                 if( vcr->vcr_control.button_is_in[VCR_PAUSE] )
1052                     ReleaseVCRButton(vcr, VCR_PAUSE);
1053                 PushVCRButton(vcr, VCR_STOP);
1054                 if (call_data->event->xbutton.x != -1) {
1055                     data.action = VCR_STOP;
1056                     data.on     = TRUE;
1057                     XtCallCallbacks((Widget)vcr, XmNactionCallback, &data);
1058                 }
1059             }
1060         } else if( w == vcr->vcr_control.button[VCR_PAUSE] ) {
1061             /*  This only happens if pause is a toggle  */
1062             if( vcr->vcr_control.button_is_in[VCR_PAUSE] )
1063                 ReleaseVCRButton(vcr, VCR_PAUSE);
1064             else {
1065                 ReleaseModeButtons(vcr);
1066                 PushVCRButton(vcr, VCR_PAUSE);
1067             }
1068             if (call_data->event->xbutton.x != -1) {
1069                 data.action = VCR_PAUSE;
1070                 data.on     = TRUE;
1071                 XtCallCallbacks((Widget)vcr, XmNactionCallback, &data);
1072             }
1073         } else if( w == vcr->vcr_control.button[VCR_COUNT] ) {
1074             /*
1075              * Ignore the second click of a double click on this button.
1076              */
1077             if((vcr->vcr_control.last_frame_control_press != -1) &&
1078                     (abs(vcr->vcr_control.last_frame_control_press -
1079                          call_data->event->xbutton.time) < 500)) {
1080                 return;
1081             }
1082 
1083             vcr->vcr_control.last_frame_control_press =
1084                 call_data->event->xbutton.time;
1085             if( vcr->vcr_control.button_is_in[VCR_COUNT] ) {
1086                 ReleaseVCRButton(vcr, VCR_COUNT);
1087                 if( vcr->vcr_control.frame_control_is_up ) {
1088                     XtUnmanageChild((Widget)vcr->vcr_control.frame_control);
1089                 }
1090                 vcr->vcr_control.frame_control_is_up = False;
1091             } else {
1092 
1093                 XtManageChild((Widget)vcr->vcr_control.frame_control);
1094 
1095                 PushVCRButton(vcr, VCR_COUNT);
1096                 vcr->vcr_control.frame_control_is_up = True;
1097                 ChangeVCRCurrentValue(vcr, vcr->vcr_control.current_value,
1098                                       TRUE, TRUE, FALSE);
1099                 ChangeVCRNextValue(vcr, vcr->vcr_control.next_value,
1100                                    TRUE, TRUE, FALSE);
1101             }
1102         }
1103     } else if( call_data->event->type == ButtonRelease ) {
1104         /*  Release buttons which are press-only (momentary)  */
1105         if( vcr->vcr_control.button_is_in[VCR_PAUSE] )
1106             ReleaseVCRButton(vcr, VCR_PAUSE);
1107         else if( vcr->vcr_control.button_is_in[VCR_STOP] )
1108             ReleaseVCRButton(vcr, VCR_STOP);
1109         else if(   vcr->vcr_control.button_is_in[VCR_STEP]
1110                    && (vcr->vcr_control.button_timeout == 0) ) {
1111             /*  If in step mode and time has expired, release play button  */
1112             if( vcr->vcr_control.button_is_in[VCR_FORWARD] )
1113                 ReleaseVCRButton(vcr, VCR_FORWARD);
1114             else if( vcr->vcr_control.button_is_in[VCR_BACKWARD] )
1115                 ReleaseVCRButton(vcr, VCR_BACKWARD);
1116         }
1117         vcr->vcr_control.step_being_held = FALSE;
1118     }
1119 }
1120 
1121 /*  Subroutine:	ReleaseVCRButton
1122  *  Purpose:	Simulate effect of releasing button which had been pushed in
1123  */
ReleaseVCRButton(XmVCRControlWidget vcr,int button)1124 static void ReleaseVCRButton( XmVCRControlWidget vcr, int button )
1125 {
1126     Arg wargs[2];
1127 
1128     XtSetArg(wargs[0], XmNshadowType, XmSHADOW_OUT);
1129     XtSetValues((Widget)vcr->vcr_control.frame[button], wargs, 1);
1130     vcr->vcr_control.button_is_in[button] = FALSE;
1131     /*  Since the Frame's SetValues doesn't ask to redraw, we must do it!  */
1132     ReplaceFrame(vcr->vcr_control.frame[button]);
1133 }
1134 
1135 /*  Subroutine:	PushVCRButton
1136  *  Purpose:	Simulate effect of pushing in a button
1137  */
PushVCRButton(XmVCRControlWidget vcr,int button)1138 static void PushVCRButton( XmVCRControlWidget vcr, int button )
1139 {
1140     Arg wargs[2];
1141 
1142     XtSetArg(wargs[0], XmNshadowType, XmSHADOW_IN);
1143     XtSetValues((Widget)vcr->vcr_control.frame[button], wargs, 1);
1144     vcr->vcr_control.button_is_in[button] = TRUE;
1145     /*  Since the Frame's SetValues doesn't ask to redraw, we must do it!  */
1146     if (XtIsRealized((Widget)vcr->vcr_control.frame[button])) {
1147         ReplaceFrame(vcr->vcr_control.frame[button]);
1148         /*  Send it right-away to maximize flicker, before it gets released  */
1149 
1150     }
1151 }
1152 
1153 
1154 /*  Subroutine:	ReleaseModeButtons
1155  *  Purpose:	Release any pushed button of the ganged radiobutton set
1156  */
ReleaseModeButtons(XmVCRControlWidget vcr)1157 static void ReleaseModeButtons( XmVCRControlWidget vcr )
1158 {
1159     if( vcr->vcr_control.button_is_in[VCR_FORWARD] )
1160         ReleaseVCRButton(vcr, VCR_FORWARD);
1161     else if( vcr->vcr_control.button_is_in[VCR_BACKWARD] )
1162         ReleaseVCRButton(vcr, VCR_BACKWARD);
1163     else if( vcr->vcr_control.button_is_in[VCR_STOP] )
1164         ReleaseVCRButton(vcr, VCR_STOP);
1165     else if( vcr->vcr_control.button_is_in[VCR_PAUSE] )
1166         ReleaseVCRButton(vcr, VCR_PAUSE);
1167 }
1168 
1169 /*  Subroutine:	ReplaceFrame
1170  *  Purpose:	Redraw widget shadow.  Calls internal Xm call when stupid
1171  *		widget doesn't but should (i.e. when shadow of Frame is
1172  *		changed by SetValues).
1173  *  Note: %%	This uses Xm internals in violation of object oriented
1174  *		practice.  It may need adjustment with rev changes in Xm.
1175  */
ReplaceFrame(XmFrameWidget frame)1176 static void ReplaceFrame( XmFrameWidget frame )
1177 {
1178 #if (OLD_LESSTIF != 1)
1179 
1180     short highlight_thickness = 0;
1181 
1182     if( XtIsRealized((Widget)frame) )
1183 #if    (XmVersion < 2000)
1184 
1185         _XmDrawShadowType((Widget)frame, frame->frame.shadow_type,
1186                           frame->core.width, frame->core.height,
1187                           frame->manager.shadow_thickness,
1188                           highlight_thickness, frame->manager.top_shadow_GC,
1189                           frame->manager.bottom_shadow_GC);
1190 #else    /* XmVersion >= 2000 */
1191 
1192         XmeDrawShadows(XtDisplay((Widget)frame), XtWindow((Widget)frame),
1193                        frame->manager.top_shadow_GC,
1194                        frame->manager.bottom_shadow_GC,
1195                        highlight_thickness, highlight_thickness,
1196                        frame->core.width, frame->core.height,
1197                        frame->manager.shadow_thickness,
1198                        frame->frame.shadow_type);
1199 #endif    /* XmVersion */
1200 #endif /* OLD_LESSTIF */
1201 }
1202 
1203 
1204 
1205 /*  Subroutine:	ChangeVCRNextValue
1206  *  Purpose:	Change the next frame value everywhere in the VCR control
1207  */
ChangeVCRNextValue(XmVCRControlWidget vcr,int value,Boolean to_vcr,Boolean to_frame_control,Boolean to_outside)1208 void ChangeVCRNextValue( XmVCRControlWidget vcr, int value, Boolean to_vcr,
1209                          Boolean to_frame_control, Boolean to_outside )
1210 {
1211     VCRCallbackStruct data;
1212     Arg wargs[2];
1213 
1214     vcr->vcr_control.next_value = value;
1215     /*  An idea to try, but may not be so great  */
1216     /*  Use the change of number to trigger the button release  */
1217     if( vcr->vcr_control.button_is_in[VCR_STEP] &&
1218             (vcr->vcr_control.step_being_held == FALSE) ) {
1219         if( vcr->vcr_control.button_timeout ) {
1220             XtRemoveTimeOut(vcr->vcr_control.button_timeout);
1221             vcr->vcr_control.button_timeout = 0;
1222         }
1223         if( vcr->vcr_control.button_is_in[VCR_FORWARD] )
1224             ReleaseVCRButton(vcr, VCR_FORWARD);
1225         if( vcr->vcr_control.button_is_in[VCR_BACKWARD] )
1226             ReleaseVCRButton(vcr, VCR_BACKWARD);
1227     }
1228 
1229     if( to_frame_control && vcr->vcr_control.frame_control_is_up) {
1230         XtSetArg(wargs[0], XmNnext, value);
1231         XtSetValues((Widget)vcr->vcr_control.frame_control, wargs, 1);
1232     }
1233 
1234     if( to_outside ) {
1235 
1236         data.detent = value;
1237         data.which  = XmCR_NEXT;
1238         XtCallCallbacks((Widget)vcr, XmNframeCallback, &data);
1239     }
1240 }
1241 
1242 
1243 /*  Subroutine:	ChangeVCRCurrentValue
1244  *  Purpose:	Change the current frame value everywhere in the VCR control
1245  */
ChangeVCRCurrentValue(XmVCRControlWidget vcr,int value,Boolean to_vcr,Boolean to_frame_control,Boolean to_outside)1246 void ChangeVCRCurrentValue( XmVCRControlWidget vcr, int value, Boolean to_vcr,
1247                             Boolean to_frame_control, Boolean to_outside )
1248 {
1249     VCRCallbackStruct data;
1250     Arg wargs[2];
1251     char string[100];
1252     XmString text;
1253 
1254     vcr->vcr_control.current_value = value;
1255 
1256     /*Update the display */
1257     if (vcr->vcr_control.current_visible) {
1258         sprintf(string, "%4d", vcr->vcr_control.current_value);
1259     } else {
1260         sprintf(string, " ");
1261     }
1262 
1263     text = XmStringCreate(string, XmSTRING_DEFAULT_CHARSET);
1264     XtSetArg(wargs[0], XmNlabelString, text);
1265     XtSetValues( (Widget)vcr->vcr_control.label, wargs, 1);
1266     XmStringFree(text);
1267 
1268     if( to_frame_control && vcr->vcr_control.frame_control_is_up) {
1269         XtSetArg(wargs[0], XmNcurrent, value);
1270         XtSetArg(wargs[1], XmNcurrentVisible, vcr->vcr_control.current_visible);
1271         XtSetValues((Widget)vcr->vcr_control.frame_control, wargs, 2);
1272     }
1273 
1274     if( to_outside ) {
1275 
1276         data.detent = value;
1277         data.which  = XmCR_CURRENT;
1278         XtCallCallbacks((Widget)vcr, XmNframeCallback, &data);
1279     }
1280 }
1281 
1282 /*  Function: FrameControlCallback
1283  *  Purpose:	Handle changes due to the frame_control
1284  */
FrameControlCallback(Widget w,XmVCRControlWidget vcr,FrameControlCallbackStruct * call_data)1285 static void FrameControlCallback( Widget w, XmVCRControlWidget vcr,
1286                                   FrameControlCallbackStruct *call_data )
1287 {
1288     VCRCallbackStruct data;
1289 
1290     if (call_data->reason == XmCR_START) {
1291         ChangeVCRStartValue(vcr, call_data->value, TRUE, FALSE, TRUE);
1292     }
1293     if (call_data->reason == XmCR_STOP) {
1294         ChangeVCRStopValue(vcr, call_data->value, TRUE, FALSE, TRUE);
1295     }
1296     if (call_data->reason == XmCR_NEXT) {
1297         ChangeVCRNextValue(vcr, call_data->value, TRUE, FALSE, TRUE);
1298     }
1299     if (call_data->reason == XmCR_INCREMENT) {
1300         ChangeVCRIncrementValue(vcr, call_data->value, TRUE, FALSE, TRUE);
1301     }
1302     if (call_data->reason == XmCR_MIN) {
1303         data.value = call_data->value;
1304         data.which  = XmCR_MIN;
1305         XtCallCallbacks((Widget)vcr, XmNframeCallback, &data);
1306     }
1307     if (call_data->reason == XmCR_MAX) {
1308         data.value = call_data->value;
1309         data.which  = XmCR_MAX;
1310         XtCallCallbacks((Widget)vcr, XmNframeCallback,
1311                         &data);
1312     }
1313 }
1314 
1315 /*  Function: PopdownCallback
1316  *  Purpose:	Assure appropriate state of interface if something else pops
1317  *		down the frame guide
1318  */
PopdownCallback(Widget w,XmVCRControlWidget vcr,XmAnyCallbackStruct * call_data)1319 static void PopdownCallback( Widget w, XmVCRControlWidget vcr,
1320                              XmAnyCallbackStruct* call_data )
1321 {
1322     if( vcr->vcr_control.button_is_in[VCR_COUNT] )
1323         ReleaseVCRButton(vcr, VCR_COUNT);
1324 }
1325 
1326 /*  Function: map_dialog
1327  *  Purpose:	Make sure the frame control doesn't map over the sequencer.
1328  */
map_dialog(Widget dialog,XmVCRControlWidget vcr,XmAnyCallbackStruct * call_data)1329 static void map_dialog (Widget dialog, XmVCRControlWidget vcr,
1330                         XmAnyCallbackStruct* call_data)
1331 {
1332     Arg wargs[12];
1333     Display *display;
1334     Dimension width, height;
1335     int dest_x, dest_y;
1336     int dispHeight = 0, dispWidth = 0, wmHeight = 0, borderWidth = 0;
1337     int screen = 0;
1338     Window child, rootW, parentW, *childrenW, vcrW;
1339     unsigned int numChildren;
1340     XWindowAttributes xwa;
1341 
1342     /*
1343        Get the location of the VCR control and then
1344        determine if the frame control should go above or
1345        below. Once determined, put it there.
1346      */
1347 
1348     display = XtDisplay(vcr);
1349     XtSetArg(wargs[0], XmNheight, &height);
1350 	XtSetArg(wargs[1], XmNwidth, &width);
1351     XtGetValues((Widget)vcr, wargs, 2);
1352     screen = XScreenNumberOfScreen(XtScreen(vcr));
1353     dispHeight = DisplayHeight(display, screen);
1354 	dispWidth = DisplayWidth(display, screen);
1355 
1356     vcrW = XtWindow(vcr);
1357 
1358     XTranslateCoordinates( display, vcrW,
1359                            XRootWindowOfScreen(XtScreen(vcr)),
1360                            0, 0, &dest_x, &dest_y, &child);
1361 
1362     /*
1363        Not very elegant, but it does the job. In order
1364        to get the window manager decorations sizes, it
1365        is required to get the window attributes of the
1366        parent's, parent's, parent of the shell.
1367     */
1368 
1369     XQueryTree(display, vcrW, &rootW, &parentW,
1370                &childrenW, &numChildren);
1371     if(childrenW)
1372         XFree((char *)childrenW);
1373 
1374     XQueryTree(display, parentW, &rootW, &parentW,
1375                &childrenW, &numChildren);
1376     if(childrenW)
1377         XFree((char *)childrenW);
1378 
1379     XQueryTree(display, parentW, &rootW, &parentW,
1380                &childrenW, &numChildren);
1381     if(childrenW)
1382         XFree((char *)childrenW);
1383 
1384     XGetWindowAttributes(display, parentW, &xwa);
1385     wmHeight = dest_y - xwa.y;
1386     borderWidth = dest_x - xwa.x;
1387 
1388     if(dest_y + height + 180 + wmHeight + 2  + borderWidth * 2 > dispHeight) {
1389         XtGetValues((Widget)vcr->vcr_control.frame_control, wargs, 1);
1390         dest_y = dest_y - 2 * wmHeight - borderWidth - height - 2;
1391     } else
1392         dest_y = dest_y + height + borderWidth + 2;
1393 
1394 	if(dest_x + 400 + borderWidth * 2 > dispWidth) {
1395 		dest_x = dispWidth - 2*borderWidth - 400 - 2;
1396 	} else
1397 	    dest_x -= borderWidth;
1398 
1399     XtVaSetValues(dialog,
1400                   XmNx, dest_x,
1401                   XmNy, dest_y,
1402                   NULL);
1403 
1404 }
1405 
1406 /*  Subroutine:	ChangeVCRStartValue
1407  *  Purpose:	Change the start frame value everywhere in the VCR control
1408  *  Note:	Values are in external format (min based or +min from internal)
1409  */
1410 
ChangeVCRStartValue(XmVCRControlWidget vcr,int value,Boolean to_vcr,Boolean to_frame_control,Boolean to_outside)1411 void ChangeVCRStartValue( XmVCRControlWidget vcr, int value, Boolean to_vcr,
1412                           Boolean to_frame_control, Boolean to_outside )
1413 {
1414     VCRCallbackStruct data;
1415     Arg wargs[2];
1416 
1417     vcr->vcr_control.start_value = value;
1418     if( to_frame_control) {
1419         XtSetArg(wargs[0], XmNstart, value);
1420         XtSetValues((Widget)vcr->vcr_control.frame_control, wargs, 1);
1421     }
1422     if( to_outside ) {
1423         data.detent = value;
1424         data.which  = XmCR_START;
1425         XtCallCallbacks((Widget)vcr, XmNframeCallback, &data);
1426     }
1427 }
1428 
1429 
1430 /*  Subroutine:	ChangeVCRStopValue
1431  *  Purpose:	Change the stop frame value everywhere in the VCR control
1432  *  Note:	Values are in external format (min based or +min from internal)
1433  */
ChangeVCRStopValue(XmVCRControlWidget vcr,int value,Boolean to_vcr,Boolean to_frame_control,Boolean to_outside)1434 void ChangeVCRStopValue( XmVCRControlWidget vcr, int value, Boolean to_vcr,
1435                          Boolean to_frame_control, Boolean to_outside )
1436 {
1437     VCRCallbackStruct data;
1438     Arg wargs[2];
1439 
1440     vcr->vcr_control.stop_value = value;
1441     if( to_frame_control) {
1442         XtSetArg(wargs[0], XmNstop, value);
1443         XtSetValues((Widget)vcr->vcr_control.frame_control, wargs, 1);
1444     }
1445     if( to_outside ) {
1446         data.detent = value;
1447         data.which  = XmCR_STOP;
1448         XtCallCallbacks((Widget)vcr, XmNframeCallback, &data);
1449     }
1450 }
1451 
1452 
1453 /*  Subroutine:	ChangeVCRIncrementValue
1454  *  Purpose:	Change the frame increment value for the sequence controller
1455  */
ChangeVCRIncrementValue(XmVCRControlWidget vcr,int increment,Boolean to_vcr,Boolean to_frame_control,Boolean to_outside)1456 void ChangeVCRIncrementValue( XmVCRControlWidget vcr, int increment,
1457                               Boolean to_vcr, Boolean to_frame_control,
1458                               Boolean to_outside )
1459 {
1460     VCRCallbackStruct data;
1461     Arg wargs[2];
1462 
1463     vcr->vcr_control.frame_increment = increment;
1464     if( to_frame_control) {
1465         XtSetArg(wargs[0], XmNincrement, increment);
1466         XtSetValues((Widget)vcr->vcr_control.frame_control, wargs, 1);
1467     }
1468     if( to_outside ) {/*&& vcr->vcr_control.value_callback )*/
1469         data.detent = increment;
1470         data.which  = XmCR_INCREMENT;
1471         XtCallCallbacks((Widget)vcr, XmNframeCallback, &data);
1472     }
1473 }
1474 
1475 /*   Subroutine: XmCreateVCRControl
1476  *   Purpose: This function creates and returns a VCRControl widget.
1477 */
1478 
XmCreateVCRControl(Widget parent,char * name,ArgList args,Cardinal num_args)1479 Widget XmCreateVCRControl( Widget parent, char *name, ArgList args,
1480                            Cardinal num_args)
1481 {
1482     return (XtCreateWidget(name, xmVCRControlWidgetClass, parent, args,
1483                            num_args));
1484 
1485 }
1486