1 /*
2  * Motif
3  *
4  * Copyright (c) 1987-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22 */
23 #ifdef REV_INFO
24 #ifndef lint
25 static char rcsid[] = "$TOG: ScrollBar.c /main/20 1997/03/10 14:52:28 dbl $"
26 #endif
27 #endif
28 
29 #ifdef HAVE_CONFIG_H
30 #include <config.h>
31 #endif
32 
33 
34 #ifndef X_NOT_STDC_ENV
35 #include <stdlib.h>
36 #endif
37 
38 #include <Xm/DisplayP.h>        /* for enableThinThickness */
39 #include <Xm/DrawP.h>
40 #include <Xm/DropSMgr.h>	/* for XmDropSiteStartUpdate/EndUPdate */
41 #include <Xm/ManagerP.h>
42 #include <Xm/NavigatorT.h>
43 #include <Xm/ScrollBarP.h>
44 #include <Xm/TraitP.h>
45 #include <Xm/TransltnsP.h>
46 #include <Xm/VaSimpleP.h>
47 #include "ColorI.h"
48 #include "MessagesI.h"
49 #include "RepTypeI.h"
50 #include "ScreenI.h"
51 #include "XmI.h"
52 
53 /* see comments in ScrollBarP.h */
54 #define slider_visual	etched_slider
55 #define flat_slider_GC	unhighlight_GC
56 
57 #define MESSAGE1	_XmMMsgScrollBar_0000
58 #define MESSAGE2	_XmMMsgScrollBar_0001
59 #define MESSAGE3	_XmMMsgScrollBar_0002
60 #define MESSAGE4	_XmMMsgScrollBar_0003
61 #define MESSAGE6	_XmMMsgScaleScrBar_0004
62 #define MESSAGE7	_XmMMsgScrollBar_0004
63 #define MESSAGE8	_XmMMsgScrollBar_0005
64 #define MESSAGE9	_XmMMsgScrollBar_0006
65 #define MESSAGE10	_XmMMsgScrollBar_0007
66 #define MESSAGE13	_XmMMsgScrollBar_0008
67 #define MESSAGE14	_XmMMsgMotif_0001
68 
69 #define MAXDIMENSION	65535
70 
71 #define DRAWARROW(sbw, t_gc, b_gc, x, y, dir)\
72     XmeDrawArrow(XtDisplay ((Widget) sbw),\
73 		XtWindow ((Widget) sbw),\
74 		t_gc, b_gc,\
75 		sbw->scrollBar.foreground_GC,\
76 		x-1, y-1,\
77 		sbw->scrollBar.arrow_width+2,\
78 		sbw->scrollBar.arrow_height+2,\
79 		sbw->primitive.shadow_thickness,\
80 		dir);
81 
82 #define PROCESS_DIR_INVERSED(sbw) \
83     ((sbw->scrollBar.processing_direction == XmMAX_ON_LEFT) || \
84      (sbw->scrollBar.processing_direction == XmMAX_ON_TOP))
85 
86 #define INVERSED_VALUE(sbw) \
87     (sbw->scrollBar.maximum + sbw->scrollBar.minimum - \
88 	sbw->scrollBar.value - sbw->scrollBar.slider_size)
89 
90 /********    Static Function Declarations    ********/
91 
92 static void ClassPartInitialize(
93                         WidgetClass wc) ;
94 static void ProcessingDirectionDefault(
95                         XmScrollBarWidget widget,
96                         int offset,
97                         XrmValue *value) ;
98 static void BackgroundPixelDefault(
99                         XmScrollBarWidget widget,
100                         int offset,
101                         XrmValue *value) ;
102 static void TraversalDefault(
103                         XmScrollBarWidget widget,
104                         int offset,
105                         XrmValue *value) ;
106 static void HighlightDefault(
107                         XmScrollBarWidget widget,
108                         int offset,
109                         XrmValue *value) ;
110 static void SliderVisualDefault(
111                         XmScrollBarWidget widget,
112                         int offset,
113                         XrmValue *value) ;
114 static void SliderMarkDefault(
115                         XmScrollBarWidget widget,
116                         int offset,
117                         XrmValue *value) ;
118 static void EditableDefault(
119                         XmScrollBarWidget widget,
120                         int offset,
121                         XrmValue *value) ;
122 static void Initialize(
123                         Widget rw,
124                         Widget nw,
125                         ArgList args,
126                         Cardinal *num_args) ;
127 static void GetForegroundGC(
128                         XmScrollBarWidget sbw) ;
129 static void GetUnavailableGC(
130                         XmScrollBarWidget sbw) ;
131 static void GetFlatSliderGC(
132                         XmScrollBarWidget sbw) ;
133 static void GetSliderPixmap(
134                         XmScrollBarWidget sbw) ;
135 static void CalcSliderRect(
136                         XmScrollBarWidget sbw,
137                         short *slider_x,
138                         short *slider_y,
139                         short *slider_width,
140                         short *slider_height) ;
141 static void DrawSliderPixmap(
142                         XmScrollBarWidget sbw) ;
143 static void Redisplay(
144                         Widget wid,
145                         XEvent *event,
146                         Region region) ;
147 static void Resize(
148                         Widget wid) ;
149 static void Realize(
150                         Widget sbw,
151                         XtValueMask *window_mask,
152                         XSetWindowAttributes *window_attributes) ;
153 static void Destroy(
154                         Widget wid) ;
155 static Boolean ValidateInputs(
156                         XmScrollBarWidget current,
157                         XmScrollBarWidget request,
158                         XmScrollBarWidget new_w) ;
159 static Boolean SetValues(
160                         Widget cw,
161                         Widget rw,
162                         Widget nw,
163                         ArgList args,
164                         Cardinal *num_args) ;
165 static int CalcSliderVal(
166                         XmScrollBarWidget sbw,
167                         int x,
168                         int y) ;
169 static void Select(
170                         Widget wid,
171                         XEvent *event,
172                         String *params,
173                         Cardinal *num_params) ;
174 static void Release(
175                         Widget wid,
176                         XEvent *event,
177                         String *params,
178                         Cardinal *num_params) ;
179 static void Moved(
180                         Widget wid,
181                         XEvent *event,
182                         String *params,
183                         Cardinal *num_params) ;
184 static void TopOrBottom(
185                         Widget wid,
186                         XEvent *event,
187                         String *params,
188                         Cardinal *num_params) ;
189 static void IncrementUpOrLeft(
190                         Widget wid,
191                         XEvent *event,
192                         String *params,
193                         Cardinal *num_params) ;
194 static void IncrementDownOrRight(
195                         Widget wid,
196                         XEvent *event,
197                         String *params,
198                         Cardinal *num_params) ;
199 static void PageUpOrLeft(
200                         Widget wid,
201                         XEvent *event,
202                         String *params,
203                         Cardinal *num_params) ;
204 static void PageDownOrRight(
205                         Widget wid,
206                         XEvent *event,
207                         String *params,
208                         Cardinal *num_params) ;
209 static void CancelDrag(
210                         Widget wid,
211                         XEvent *event,
212                         String *params,
213                         Cardinal *num_params) ;
214 static void MoveSlider(
215                         XmScrollBarWidget sbw,
216                         int currentX,
217                         int currentY) ;
218 static void RedrawSliderWindow(
219                         XmScrollBarWidget sbw) ;
220 static Boolean ChangeScrollBarValue(
221                         XmScrollBarWidget sbw) ;
222 static void TimerEvent(
223                         XtPointer closure,
224                         XtIntervalId *id) ;
225 static void ScrollCallback(
226                         XmScrollBarWidget sbw,
227                         int reason,
228                         int value,
229                         int xpixel,
230                         int ypixel,
231                         XEvent *event) ;
232 static void ExportScrollBarValue(
233                         Widget wid,
234                         int offset,
235                         XtArgVal *value) ;
236 static XmImportOperator ImportScrollBarValue(
237                         Widget wid,
238                         int offset,
239                         XtArgVal *value) ;
240 
241 
242 static void NavigChangeMoveCB(Widget nav,
243 			      XtCallbackProc moveProc,
244 			      XtPointer closure,
245 			      Boolean setunset) ;
246 static void NavigSetValue(Widget nav,
247 			  XmNavigatorData nav_data,
248 			  Boolean notify) ;
249 static void NavigGetValue(Widget nav,
250 			  XmNavigatorData nav_data) ;
251 
252 /********    End Static Function Declarations    ********/
253 
254 /*  Default translation table and action list  */
255 
256 #define defaultTranslations	_XmScrollBar_defaultTranslations
257 
258 static XtActionsRec actions[] =
259 {
260 	{ "Select",                 Select },
261 	{ "Release",                Release },
262 	{ "Moved",                  Moved },
263 	{ "TopOrBottom",            TopOrBottom },
264 	{ "IncrementUpOrLeft",      IncrementUpOrLeft },
265 	{ "IncrementDownOrRight",   IncrementDownOrRight },
266 	{ "PageUpOrLeft",           PageUpOrLeft },
267 	{ "PageDownOrRight",        PageDownOrRight },
268 	{ "CancelDrag",             CancelDrag },
269 };
270 
271 
272 /*  Resource list for ScrollBar  */
273 
274 static XtResource resources[] =
275 {
276 	{ XmNnavigationType, XmCNavigationType, XmRNavigationType,
277 	  sizeof(unsigned char),
278 	  XtOffsetOf(XmScrollBarRec, primitive.navigation_type),
279 	  XmRImmediate, (XtPointer) XmSTICKY_TAB_GROUP
280 	},
281 	{ XmNbackground, XmCBackground, XmRPixel, sizeof(Pixel),
282 	  XtOffsetOf(XmScrollBarRec, core.background_pixel),
283 	  XmRCallProc, (XtPointer) BackgroundPixelDefault
284 	},
285 	{ XmNtroughColor, XmCTroughColor, XmRPixel, sizeof(Pixel),
286 	  XtOffsetOf(XmScrollBarRec, scrollBar.trough_color),
287 	  XmRCallProc, (XtPointer) _XmSelectColorDefault
288 	},
289 	{ XmNvalue, XmCValue, XmRInt, sizeof (int),
290 	  XtOffsetOf(XmScrollBarRec, scrollBar.value),
291 	  XmRImmediate, (XtPointer) XmINVALID_DIMENSION
292 	},
293 	{ XmNminimum, XmCMinimum, XmRInt, sizeof (int),
294 	  XtOffsetOf(XmScrollBarRec, scrollBar.minimum),
295 	  XmRImmediate, (XtPointer) 0
296 	},
297 	{ XmNmaximum, XmCMaximum, XmRInt, sizeof (int),
298 	  XtOffsetOf(XmScrollBarRec, scrollBar.maximum),
299 	  XmRImmediate, (XtPointer) 100
300 	},
301 	{ XmNsliderSize, XmCSliderSize, XmRInt, sizeof (int),
302 	  XtOffsetOf(XmScrollBarRec, scrollBar.slider_size),
303 	  XmRImmediate, (XtPointer) XmINVALID_DIMENSION
304 	},
305 	{ XmNshowArrows, XmCShowArrows, XmRShowArrows, sizeof (XtEnum),
306 	  XtOffsetOf(XmScrollBarRec, scrollBar.show_arrows),
307 	  XmRImmediate, (XtPointer) XmEACH_SIDE
308 	},
309 	{ XmNorientation, XmCOrientation,
310 	  XmROrientation, sizeof (unsigned char),
311 	  XtOffsetOf(XmScrollBarRec, scrollBar.orientation),
312 	  XmRImmediate, (XtPointer) XmVERTICAL
313 	},
314 	{ XmNprocessingDirection, XmCProcessingDirection,
315 	  XmRProcessingDirection, sizeof (unsigned char),
316 	  XtOffsetOf(XmScrollBarRec, scrollBar.processing_direction),
317 	  XmRCallProc, (XtPointer) ProcessingDirectionDefault
318 	},
319 	{ XmNincrement, XmCIncrement, XmRInt, sizeof (int),
320 	  XtOffsetOf(XmScrollBarRec, scrollBar.increment),
321 	  XmRImmediate, (XtPointer) 1
322 	},
323 	{ XmNpageIncrement, XmCPageIncrement, XmRInt, sizeof (int),
324 	  XtOffsetOf(XmScrollBarRec, scrollBar.page_increment),
325 	  XmRImmediate, (XtPointer) 10
326 	},
327 	{ XmNinitialDelay, XmCInitialDelay, XmRInt, sizeof (int),
328 	  XtOffsetOf(XmScrollBarRec, scrollBar.initial_delay),
329 	  XmRImmediate, (XtPointer) 250
330 	},
331 	{ XmNrepeatDelay, XmCRepeatDelay, XmRInt, sizeof (int),
332 	  XtOffsetOf(XmScrollBarRec, scrollBar.repeat_delay),
333 	  XmRImmediate, (XtPointer) 50
334 	},
335 	{ XmNvalueChangedCallback, XmCCallback,
336 	  XmRCallback, sizeof(XtCallbackList),
337 	  XtOffsetOf(XmScrollBarRec, scrollBar.value_changed_callback),
338 	  XmRPointer, (XtPointer) NULL
339 	},
340 	{ XmNincrementCallback, XmCCallback,
341 	  XmRCallback, sizeof(XtCallbackList),
342 	  XtOffsetOf(XmScrollBarRec, scrollBar.increment_callback),
343 	  XmRPointer, (XtPointer) NULL
344 	},
345 	{ XmNdecrementCallback, XmCCallback,
346 	  XmRCallback, sizeof(XtCallbackList),
347 	  XtOffsetOf(XmScrollBarRec, scrollBar.decrement_callback),
348 	  XmRPointer, (XtPointer) NULL
349 	},
350 	{ XmNpageIncrementCallback, XmCCallback,
351 	  XmRCallback, sizeof(XtCallbackList),
352 	  XtOffsetOf(XmScrollBarRec, scrollBar.page_increment_callback),
353 	  XmRPointer, (XtPointer) NULL
354 	},
355 	{ XmNpageDecrementCallback, XmCCallback,
356 	  XmRCallback, sizeof (XtCallbackList),
357 	  XtOffsetOf(XmScrollBarRec, scrollBar.page_decrement_callback),
358 	  XmRPointer, (XtPointer) NULL
359 	},
360 	{ XmNtoTopCallback, XmCCallback,
361 	  XmRCallback, sizeof(XtCallbackList),
362 	  XtOffsetOf(XmScrollBarRec, scrollBar.to_top_callback),
363 	  XmRPointer, (XtPointer) NULL
364 	},
365 	{ XmNtoBottomCallback, XmCCallback,
366 	  XmRCallback, sizeof(XtCallbackList),
367 	  XtOffsetOf(XmScrollBarRec, scrollBar.to_bottom_callback),
368 	  XmRPointer, (XtPointer) NULL
369 	},
370 	{ XmNdragCallback, XmCCallback,
371 	  XmRCallback, sizeof(XtCallbackList),
372 	  XtOffsetOf(XmScrollBarRec, scrollBar.drag_callback),
373 	  XmRPointer, (XtPointer) NULL
374 	},
375         {
376           XmNtraversalOn, XmCTraversalOn, XmRBoolean, sizeof (Boolean),
377           XtOffsetOf(XmPrimitiveRec, primitive.traversal_on),
378           XmRCallProc, (XtPointer) TraversalDefault
379         },
380         {
381           XmNhighlightThickness, XmCHighlightThickness,
382 	  XmRHorizontalDimension, sizeof (Dimension),
383           XtOffsetOf(XmPrimitiveRec, primitive.highlight_thickness),
384           XmRCallProc, (XtPointer) HighlightDefault
385         },
386         {
387 	  XmNsnapBackMultiple, XmCSnapBackMultiple, XmRShort,
388           sizeof (unsigned short),
389           XtOffsetOf(XmScrollBarRec, scrollBar.snap_back_multiple),
390           XmRImmediate, (XtPointer) MAXDIMENSION
391         },
392         {
393           XmNslidingMode, XmCSlidingMode, XmRSlidingMode,
394 	  sizeof(XtEnum), XtOffsetOf(XmScrollBarRec, scrollBar.sliding_mode),
395 	  XmRImmediate, (XtPointer) XmSLIDER
396         },
397 	{
398           XmNeditable, XmCEditable, XmRBoolean,
399           sizeof(XtEnum), XtOffsetOf(XmScrollBarRec,scrollBar.editable),
400           XmRCallProc, (XtPointer) EditableDefault
401         },
402         {
403 	  XmNsliderVisual, XmCSliderVisual, XmRSliderVisual,
404           sizeof (XtEnum),
405           XtOffsetOf(XmScrollBarRec, scrollBar.slider_visual),
406           XmRCallProc, (XtPointer) SliderVisualDefault
407         },
408         {
409 	  XmNsliderMark, XmCSliderMark, XmRSliderMark,
410           sizeof (XtEnum),
411           XtOffsetOf(XmScrollBarRec, scrollBar.slider_mark),
412           XmRCallProc, (XtPointer) SliderMarkDefault
413         },
414    };
415 
416 
417 /*  Definition for resources that need special processing in get values  */
418 
419 static XmSyntheticResource syn_resources[] =
420 {
421 	{ XmNvalue,
422 	  sizeof (int),
423 	  XtOffsetOf(XmScrollBarRec, scrollBar.value),
424 	  ExportScrollBarValue,
425 	  ImportScrollBarValue
426 	},
427 };
428 
429 
430 externaldef(xmscrollbarclassrec) XmScrollBarClassRec xmScrollBarClassRec =
431 {
432    {
433       (WidgetClass) &xmPrimitiveClassRec, /* superclass	         */
434       "XmScrollBar",                    /* class_name	         */
435       sizeof(XmScrollBarRec),           /* widget_size	         */
436       NULL,                             /* class_initialize      */
437       ClassPartInitialize,              /* class_part_initialize */
438       FALSE,                            /* class_inited          */
439       Initialize,                       /* initialize	         */
440       (XtArgsProc)NULL,                 /* initialize_hook       */
441       Realize,                          /* realize	         */
442       actions,                          /* actions               */
443       XtNumber(actions),                /* num_actions	         */
444       resources,                        /* resources	         */
445       XtNumber(resources),              /* num_resources         */
446       NULLQUARK,                        /* xrm_class	         */
447       TRUE,                             /* compress_motion       */
448       XtExposeCompressMaximal,          /* compress_exposure     */
449       TRUE,                             /* compress_enterleave   */
450       FALSE,                            /* visible_interest      */
451       Destroy,                          /* destroy               */
452       Resize,                           /* resize                */
453       Redisplay,                        /* expose                */
454       SetValues,                        /* set_values    	 */
455       (XtArgsFunc)NULL,                 /* set_values_hook       */
456       XtInheritSetValuesAlmost,         /* set_values_almost     */
457       (XtArgsProc)NULL,			/* get_values_hook       */
458       (XtAcceptFocusProc)NULL,          /* accept_focus	         */
459       XtVersion,                        /* version               */
460       NULL,                             /* callback private      */
461       defaultTranslations,              /* tm_table              */
462       (XtGeometryHandler)NULL,          /* query_geometry        */
463       (XtStringProc)NULL,               /* display_accelerator   */
464       (XtPointer) NULL,                 /* extension             */
465    },
466 
467    {
468       XmInheritWidgetProc,		/* border_highlight   */
469       XmInheritWidgetProc,		/* border_unhighlight */
470       NULL,				/* translations       */
471       (XtActionProc)NULL,		/* arm_and_activate   */
472       syn_resources,   			/* syn_resources      */
473       XtNumber(syn_resources),		/* num syn_resources  */
474       NULL,				/* extension          */
475    },
476 
477    {
478       (XtPointer) NULL,			/* extension          */
479    },
480 };
481 
482 externaldef(xmscrollbarwidgetclass) WidgetClass xmScrollBarWidgetClass =
483      (WidgetClass) &xmScrollBarClassRec;
484 
485 
486 /* Trait record for ScrollBar */
487 
488 static XmConst XmNavigatorTraitRec scrollBarNT = {
489   0,		/* version */
490   NavigChangeMoveCB,
491   NavigSetValue,
492   NavigGetValue,
493 };
494 
495 /*********************************************************************
496  *
497  *  ExportScrollBarValue
498  *	Convert the scrollbar value from the normal processing direction
499  *	to reverse processing if needed.
500  *
501  *********************************************************************/
502 /*ARGSUSED*/
503 static void
ExportScrollBarValue(Widget wid,int offset,XtArgVal * value)504 ExportScrollBarValue(
505         Widget wid,
506         int offset,		/* unused */
507         XtArgVal *value )
508 {
509         XmScrollBarWidget sbw = (XmScrollBarWidget) wid ;
510 	if (PROCESS_DIR_INVERSED(sbw))
511 		*value = (XtArgVal) INVERSED_VALUE(sbw);
512 	else
513 		*value = (XtArgVal) sbw->scrollBar.value;
514 }
515 
516 /*********************************************************************
517  *
518  *  ImportScrollBarValue
519  *  Indicate that the value did indeed change.
520  *
521  *********************************************************************/
522 /*ARGSUSED*/
523 static XmImportOperator
ImportScrollBarValue(Widget wid,int offset,XtArgVal * value)524 ImportScrollBarValue(
525         Widget wid,
526         int offset,		/* unused */
527         XtArgVal *value )
528 {
529         XmScrollBarWidget sbw = (XmScrollBarWidget) wid ;
530 
531 	sbw->scrollBar.flags |= VALUE_SET_FLAG;
532 	*value = (XtArgVal)sbw->scrollBar.value;
533 	return(XmSYNTHETIC_LOAD);
534 }
535 
536 
537 /*********************************************************************
538  *
539  * ProcessingDirectionDefault
540  *    This procedure provides the dynamic default behavior for
541  *    the processing direction resource dependent on the orientation.
542  *
543  *********************************************************************/
544 /*ARGSUSED*/
545 static void
ProcessingDirectionDefault(XmScrollBarWidget widget,int offset,XrmValue * value)546 ProcessingDirectionDefault(
547         XmScrollBarWidget widget,
548         int offset,		/* unused */
549         XrmValue *value )
550 {
551 	static unsigned char direction;
552 
553 	value->addr = (XPointer) &direction;
554 
555 	if (widget->scrollBar.orientation == XmHORIZONTAL)
556         {
557            if (LayoutIsRtoLP(widget))
558 	     direction = XmMAX_ON_LEFT;
559            else
560 	     direction = XmMAX_ON_RIGHT;
561         }
562 	else /* XmVERTICAL  -- range checking done during widget
563 		initialization */
564 	  direction = XmMAX_ON_BOTTOM;
565 }
566 
567 
568 /*********************************************************************
569  *
570  * BackgroundPixelDefault
571  *    This procedure provides the dynamic default behavior for
572  *    the background color. It looks to see if the parent is a
573  *    ScrolledWindow, and if so, it uses the parent background.
574  *    This is mostly for compatibility with 1.1 where the scrolledwindow
575  *    was forcing its scrollbar color to its own background.
576  *    Note that it works for both automatic and non automatic SW,
577  *    which is a new feature for non automatic.
578  *
579  *********************************************************************/
580 static void
BackgroundPixelDefault(XmScrollBarWidget widget,int offset,XrmValue * value)581 BackgroundPixelDefault(
582         XmScrollBarWidget widget,
583         int offset,
584         XrmValue *value )
585 {
586 	static Pixel background;
587 	Widget parent = XtParent(widget) ;
588 
589 	if (XmIsScrolledWindow(parent)) {
590 	    value->addr = (XPointer) &background;
591 	    background = parent->core.background_pixel;
592 	    return ;
593 	}
594 
595 	/* else use the primitive defaulting mechanism */
596 
597 	_XmBackgroundColorDefault((Widget )widget, offset, value);
598 }
599 
600 /*********************************************************************
601  *
602  * TraversalDefault
603  *    This procedure provides the dynamic default behavior for
604  *    the traversal. It looks to see if the parent is a
605  *    ScrolledWindow, and if so, it sets it to On.
606  *    This is mostly for compatibility with 1.1 where the scrolledwindow
607  *    was forcing its scrollbar traversal to On
608  *    Note that it works only for automatic.
609  *
610  *********************************************************************/
611 /*ARGSUSED*/
612 static void
TraversalDefault(XmScrollBarWidget widget,int offset,XrmValue * value)613 TraversalDefault(
614         XmScrollBarWidget widget,
615         int offset,		/* unused */
616         XrmValue *value )
617 {
618       static Boolean traversal ;
619       Widget parent = XtParent(widget) ;
620       Arg al[1] ;
621       unsigned char sp ;
622 
623       traversal = False ;
624       value->addr = (XPointer) &traversal;
625 
626       if (XmIsScrolledWindow(parent)) {
627           XtSetArg(al[0], XmNscrollingPolicy, &sp);
628           XtGetValues(parent, al, 1);
629           if (sp == XmAUTOMATIC) {
630               traversal = True ;
631               return ;
632           }
633       }
634 }
635 
636 
637 
638 /*********************************************************************
639  *
640  * SliderVisualDefault
641  *
642  *
643  *********************************************************************/
644 /*ARGSUSED*/
645 static void
SliderVisualDefault(XmScrollBarWidget widget,int offset,XrmValue * value)646 SliderVisualDefault(
647         XmScrollBarWidget widget,
648         int offset,		/* unused */
649         XrmValue *value )
650 {
651       static XtEnum slider_visual ;
652 
653       value->addr = (XPointer) &slider_visual;
654 
655       if (widget->scrollBar.sliding_mode == XmTHERMOMETER) {
656           slider_visual = XmTROUGH_COLOR ;
657       } else {
658 	  slider_visual = XmSHADOWED_BACKGROUND ;
659       }
660 
661 }
662 
663 
664 
665 /*********************************************************************
666  *
667  * SliderMarkDefault
668  *
669  *
670  *********************************************************************/
671 /*ARGSUSED*/
672 static void
SliderMarkDefault(XmScrollBarWidget widget,int offset,XrmValue * value)673 SliderMarkDefault(
674         XmScrollBarWidget widget,
675         int offset,		/* unused */
676         XrmValue *value )
677 {
678       static XtEnum slider_mark ;
679 
680       value->addr = (XPointer) &slider_mark;
681 
682       if ((widget->scrollBar.sliding_mode == XmTHERMOMETER) &&
683 	  (widget->scrollBar.editable))
684 	  slider_mark = XmROUND_MARK ;
685       else
686 	  slider_mark = XmNONE ;
687 }
688 
689 
690 
691 /*********************************************************************
692  *
693  * EditableDefault
694  *
695  *
696  *********************************************************************/
697 /*ARGSUSED*/
698 static void
EditableDefault(XmScrollBarWidget widget,int offset,XrmValue * value)699 EditableDefault(
700         XmScrollBarWidget widget,
701         int offset,		/* unused */
702         XrmValue *value )
703 {
704       static XtEnum editable ;
705 
706       value->addr = (XPointer) &editable;
707 
708       if (widget->scrollBar.sliding_mode == XmTHERMOMETER) {
709           editable = False ;
710       } else {
711 	  editable = True ;
712       }
713 
714 }
715 
716 /*********************************************************************
717  *
718  * HighlightDefault
719  *    This procedure provides the dynamic default behavior for
720  *    the highlight. It looks to see if the parent is a
721  *    ScrolledWindow, and if so, it sets it to 2 or 1 depending on
722  *    the enableThinThickness resource, otherwise, 0.
723  *    Note that it works only for automatic.
724  *
725  *********************************************************************/
726 /*ARGSUSED*/
727 static void
HighlightDefault(XmScrollBarWidget widget,int offset,XrmValue * value)728 HighlightDefault(
729         XmScrollBarWidget widget,
730         int offset,		/* unused */
731         XrmValue *value )
732 {
733     static Dimension highlight ;
734     Widget parent = XtParent(widget) ;
735     Arg al[1] ;
736     unsigned char sp ;
737     Boolean thinthickness = False;
738 
739     highlight = 0 ;
740     value->addr = (XPointer) &highlight;
741 
742     if (XmIsScrolledWindow(parent)) {
743 	XtSetArg(al[0], XmNscrollingPolicy, &sp);
744 	XtGetValues(parent, al, 1);
745 	if (sp == XmAUTOMATIC) {
746 	    XmDisplay dpy = (XmDisplay) XmGetXmDisplay(XtDisplay(widget));
747 	    thinthickness = dpy->display.enable_thin_thickness;
748 
749 	    if (thinthickness) {
750 		highlight = 1;
751 	    }
752 	    else {
753 		highlight = 2 ;
754 	    }
755 	    return ;
756 	}
757     }
758 }
759 
760 
761 
762 
763 /*********************************************************************
764  *
765  *  ClassPartInitialize
766  *     Initialize the fast subclassing.
767  *
768  *********************************************************************/
769 static void
ClassPartInitialize(WidgetClass wc)770 ClassPartInitialize(
771         WidgetClass wc )
772 {
773     _XmFastSubclassInit (wc, XmSCROLL_BAR_BIT);
774 
775     /* Install the navigator trait for all subclasses */
776     XmeTraitSet((XtPointer)wc, XmQTnavigator, (XtPointer) &scrollBarNT);
777 }
778 
779 
780 
781 
782 
783 
784 /*********************************************************************
785  *
786  *  Initialize
787  *     The main widget instance initialization routine.
788  *
789  *********************************************************************/
790 /*ARGSUSED*/
791 static void
Initialize(Widget rw,Widget nw,ArgList args,Cardinal * num_args)792 Initialize(
793         Widget rw,
794         Widget nw,
795         ArgList args,		/* unused */
796         Cardinal *num_args )	/* unused */
797 {
798     XmScrollBarWidget request = (XmScrollBarWidget) rw ;
799     XmScrollBarWidget new_w = (XmScrollBarWidget) nw ;
800 
801     Boolean default_value = FALSE;
802 
803     if(!XmRepTypeValidValue( XmRID_SHOW_ARROWS,
804 			    new_w->scrollBar.show_arrows, (Widget) new_w) )
805 	{
806 	    new_w->scrollBar.show_arrows = XmEACH_SIDE;
807 	}
808 
809     if(!XmRepTypeValidValue( XmRID_SLIDER_VISUAL,
810 			    new_w->scrollBar.slider_visual, (Widget) new_w) )
811 	{
812 	    new_w->scrollBar.slider_visual = XmSHADOWED_BACKGROUND;
813 	}
814 
815     if(!XmRepTypeValidValue( XmRID_SLIDER_MARK,
816 			    new_w->scrollBar.slider_mark, (Widget) new_w) )
817 	{
818 	    new_w->scrollBar.slider_mark = XmNONE;
819 	}
820 
821     if(!XmRepTypeValidValue( XmRID_SLIDING_MODE,
822 			    new_w->scrollBar.sliding_mode, (Widget) new_w) )
823 	{
824 	    new_w->scrollBar.sliding_mode = XmSLIDER;
825 	}
826 
827      if (new_w->scrollBar.value == XmINVALID_DIMENSION)
828 	{
829 	    new_w->scrollBar.value = 0;
830 	    default_value = True;
831 	}
832 
833     /* Validate the incoming data  */
834 
835     if (new_w->scrollBar.minimum >= new_w->scrollBar.maximum)
836 	{
837 	    new_w->scrollBar.minimum = 0;
838 	    new_w->scrollBar.maximum = 100;
839 	    XmeWarning( (Widget) new_w, MESSAGE1);
840 	}
841 
842     if (new_w->scrollBar.slider_size == XmINVALID_DIMENSION)
843 	{
844 	    new_w->scrollBar.slider_size = (new_w->scrollBar.maximum
845 					    - new_w->scrollBar.minimum) / 10;
846 	    if (new_w->scrollBar.slider_size < 1)
847 		new_w->scrollBar.slider_size = 1;
848 	}
849 
850     if (new_w->scrollBar.slider_size < 1)
851 	{
852 	    new_w->scrollBar.slider_size = 1;
853 	    XmeWarning( (Widget) new_w, MESSAGE2);
854 	}
855 
856     if (new_w->scrollBar.slider_size >
857 	(new_w->scrollBar.maximum - new_w->scrollBar.minimum))
858 	{
859 	    new_w->scrollBar.slider_size = new_w->scrollBar.maximum
860 		- new_w->scrollBar.minimum;
861 	    XmeWarning( (Widget) new_w, MESSAGE13);
862 	}
863 
864     /* in thermo, slider_size is forced to be 0 */
865     if (new_w->scrollBar.sliding_mode == XmTHERMOMETER)
866 	new_w->scrollBar.slider_size = 0 ;
867 
868     if (new_w->scrollBar.value < new_w->scrollBar.minimum)
869 	{
870 	    new_w->scrollBar.value = new_w->scrollBar.minimum;
871 	    if (!default_value) XmeWarning( (Widget) new_w, MESSAGE3);
872 	}
873 
874     if (new_w->scrollBar.value >
875 	new_w->scrollBar.maximum - new_w->scrollBar.slider_size)
876 	{
877 	    new_w->scrollBar.value = new_w->scrollBar.minimum;
878 	    if (!default_value) XmeWarning( (Widget) new_w, MESSAGE4);
879 	}
880 
881     if(    !XmRepTypeValidValue(XmRID_ORIENTATION,
882 				new_w->scrollBar.orientation, (Widget) new_w))
883 	{
884 	    new_w->scrollBar.orientation = XmVERTICAL;
885 	}
886 
887     if (new_w->scrollBar.orientation == XmHORIZONTAL)
888 	{
889 	    if ((new_w->scrollBar.processing_direction != XmMAX_ON_RIGHT) &&
890 		(new_w->scrollBar.processing_direction != XmMAX_ON_LEFT))
891 
892 		{
893 		    new_w->scrollBar.processing_direction = XmMAX_ON_RIGHT;
894 		    XmeWarning( (Widget) new_w, MESSAGE6);
895 		}
896 	}
897     else
898 	{
899 	    if ((new_w->scrollBar.processing_direction != XmMAX_ON_TOP) &&
900 		(new_w->scrollBar.processing_direction != XmMAX_ON_BOTTOM))
901 		{
902 		    new_w->scrollBar.processing_direction = XmMAX_ON_BOTTOM;
903 		    XmeWarning( (Widget) new_w, MESSAGE6);
904 		}
905 	}
906 
907     if (new_w->scrollBar.increment <= 0)
908 	{
909 	    new_w->scrollBar.increment = 1;
910 	    XmeWarning( (Widget) new_w, MESSAGE7);
911 	}
912 
913     if (new_w->scrollBar.page_increment <= 0)
914 	{
915 	    new_w->scrollBar.page_increment = 10;
916 	    XmeWarning( (Widget) new_w, MESSAGE8);
917 	}
918 
919     if (new_w->scrollBar.initial_delay <= 0)
920 	{
921 	    new_w->scrollBar.initial_delay = 250;
922 	    XmeWarning( (Widget) new_w, MESSAGE9);
923 	}
924 
925     if (new_w->scrollBar.repeat_delay <= 0)
926 	{
927 	    new_w->scrollBar.repeat_delay = 75;
928 	    XmeWarning( (Widget) new_w, MESSAGE10);
929 	}
930 
931     /*  Set up a geometry for the widget if it is currently 0.  */
932 
933     if (request->core.width == 0)
934 	{
935 	    if (new_w->scrollBar.orientation == XmHORIZONTAL)
936 		new_w->core.width += 100;
937 	    else
938 		new_w->core.width += 11;
939 	}
940     if (request->core.height == 0)
941 	{
942 	    if (new_w->scrollBar.orientation == XmHORIZONTAL)
943 		new_w->core.height += 11;
944 	    else
945 		new_w->core.height += 100;
946 	}
947 
948     /*  Reverse the value for reverse processing.  */
949 
950     if (PROCESS_DIR_INVERSED(new_w))
951 	new_w->scrollBar.value = INVERSED_VALUE(new_w);
952 
953     /*  Set the internally used variables.  */
954 
955     new_w->scrollBar.flags = 0;
956     if (new_w->scrollBar.slider_size < (new_w->scrollBar.maximum
957 					- new_w->scrollBar.minimum))
958 	{
959 	    new_w->scrollBar.flags |= SLIDER_AVAILABLE;
960 
961 	    if (new_w->scrollBar.value > new_w->scrollBar.minimum)
962 		new_w->scrollBar.flags |= ARROW1_AVAILABLE;
963 	    if (new_w->scrollBar.value < (new_w->scrollBar.maximum
964 					  - new_w->scrollBar.slider_size))
965 		new_w->scrollBar.flags |= ARROW2_AVAILABLE;
966 	}
967     else
968 	{
969 	    /*
970 	     * For correct setvalues processing, when the slider is
971 	     * unavailable, the arrows should be available.
972 	     */
973 	    new_w->scrollBar.flags |= ARROW1_AVAILABLE;
974 	    new_w->scrollBar.flags |= ARROW2_AVAILABLE;
975 	}
976 
977     new_w->scrollBar.pixmap = 0;
978     new_w->scrollBar.sliding_on = FALSE;
979     new_w->scrollBar.timer = 0;
980     new_w->scrollBar.add_flags = 0 ;
981 
982     new_w->scrollBar.arrow_width = 0;
983     new_w->scrollBar.arrow_height = 0;
984 
985     new_w->scrollBar.arrow1_x = 0;
986     new_w->scrollBar.arrow1_y = 0;
987     new_w->scrollBar.arrow1_selected = FALSE;
988 
989     new_w->scrollBar.arrow2_x = 0;
990     new_w->scrollBar.arrow2_y = 0;
991     new_w->scrollBar.arrow2_selected = FALSE;
992 
993     new_w->scrollBar.saved_value = new_w->scrollBar.value;
994 
995     if (LayoutIsRtoLP(new_w))
996 	new_w->scrollBar.flags &= ~VALUE_SET_FLAG;
997 
998     /*  Get the drawing graphics contexts.  */
999 
1000     GetForegroundGC(new_w);
1001     GetUnavailableGC(new_w);
1002     GetFlatSliderGC(new_w);
1003 
1004     /* call the resize method to get an initial size */
1005 
1006     {
1007 	XtWidgetProc resize;
1008 	_XmProcessLock();
1009 	resize = new_w->core.widget_class->core_class.resize;
1010 	_XmProcessUnlock();
1011 
1012 	(* (resize)) ((Widget) new_w);
1013     }
1014 
1015 }
1016 
1017 
1018 
1019 
1020 /************************************************************************
1021  *
1022  *  GetForegroundGC
1023  *     Get the graphics context used for drawing the slider and arrows.
1024  *
1025  ************************************************************************/
1026 static void
GetForegroundGC(XmScrollBarWidget sbw)1027 GetForegroundGC(
1028         XmScrollBarWidget sbw )
1029 {
1030     XGCValues values;
1031     XtGCMask  valueMask;
1032 
1033     valueMask = GCForeground | GCBackground | GCGraphicsExposures;
1034     values.foreground = sbw->core.background_pixel;
1035     values.background = sbw->primitive.foreground;
1036     values.graphics_exposures = False;
1037 
1038     sbw->scrollBar.foreground_GC = XtAllocateGC ((Widget) sbw, 0, valueMask,
1039 						 &values, 0, GCFont);
1040 }
1041 
1042 /************************************************************************
1043  *
1044  *  GetFlatSliderGC
1045  *     Get the graphics context used for drawing the flat slider
1046  *
1047  ************************************************************************/
1048 static void
GetFlatSliderGC(XmScrollBarWidget sbw)1049 GetFlatSliderGC(
1050         XmScrollBarWidget sbw )
1051 {
1052     XGCValues values;
1053     XtGCMask  valueMask, unusedMask;
1054 
1055     valueMask = GCForeground | GCBackground | GCGraphicsExposures;
1056     unusedMask = GCFont | GCClipXOrigin | GCClipYOrigin;
1057     if (sbw->scrollBar.slider_visual == XmTROUGH_COLOR)
1058 	values.foreground = sbw->scrollBar.trough_color;
1059     else
1060 	values.foreground = sbw->primitive.foreground;
1061     values.background = sbw->core.background_pixel;
1062     values.graphics_exposures = False;
1063 
1064     sbw->scrollBar.flat_slider_GC = XtAllocateGC ((Widget) sbw, 0, valueMask,
1065 						  &values, GCClipMask,
1066 						  unusedMask);
1067 }
1068 
1069 
1070 
1071 /************************************************************************
1072  *
1073  *  GetUnavailableGC
1074  *     Get the graphics context used for drawing the slider and arrows
1075  *     as being unavailable.
1076  *
1077  ************************************************************************/
1078 static void
GetUnavailableGC(XmScrollBarWidget sbw)1079 GetUnavailableGC(
1080         XmScrollBarWidget sbw )
1081 {
1082     XGCValues values;
1083     XtGCMask  valueMask, unusedMask;
1084 
1085     valueMask = GCForeground | GCBackground | GCGraphicsExposures |
1086 	        GCFillStyle | GCStipple;
1087     unusedMask = GCClipXOrigin | GCClipYOrigin | GCFont;
1088     values.graphics_exposures = False;
1089     values.fill_style = FillStippled;
1090     values.background = sbw->core.background_pixel;
1091     values.foreground = sbw->primitive.foreground;
1092 
1093     values.stipple = _XmGetInsensitiveStippleBitmap((Widget) sbw);
1094 
1095     sbw->scrollBar.unavailable_GC = XtAllocateGC((Widget) sbw, 0, valueMask,
1096 						 &values, GCClipMask,
1097 						 unusedMask);
1098 }
1099 
1100 
1101 
1102 
1103 /************************************************************************
1104  *
1105  *  Logic of the scrollbar pixmap management:
1106  *  ----------------------------------------
1107  *     A pixmap the size of the trough area is created each time the
1108  *     scrollbar changes size.
1109  *     This pixmap receives the drawing of the slider which is then
1110  *     copied on the scrollbar window whenever exposure is needed.
1111  *     GetSliderPixmap:
1112  *         creates the pixmap and possibly free the current one if present.
1113  *         the pixmap is free upon destruction of the widget.
1114  *         the field pixmap == 0 means there is no pixmap to freed.
1115  *         Is called from Resize method.
1116  *     DrawSliderPixmap:
1117  *         draws the slider graphics (sized shadowed rectangle) in the pixmap.
1118  *         the fields slider_width and height must have been calculated.
1119  *         Is called from Resize, after the pixmap has been created,
1120  *           and from SetValues, if something has changed in the visual
1121  *           of the slider.
1122  *     RedrawSliderWindow:
1123  *         clears the current scrollbar slider area, computes the
1124  *         new position and call CopySliderInWindow.
1125  *         Is called from SetValues method, from increment actions, and
1126  *         from ChangeScrollBarValue (from Select, Timer).
1127  *    CopySliderInWindow:
1128  *         color slider case and then dump the slider pixmap using
1129  *         XCopyArea. Called from Redisplay and from Move, where
1130  *         the more expensive RedrawSliderWindow is not needed.
1131  *
1132  ************************************************************************/
1133 
1134 
1135 /************************************************************************
1136  *
1137  *  GetSliderPixmap
1138  *     Create the new pixmap for the slider.
1139  *     This pixmap is the size of the widget minus the arrows.
1140  *
1141  ************************************************************************/
1142 static void
GetSliderPixmap(XmScrollBarWidget sbw)1143 GetSliderPixmap(
1144         XmScrollBarWidget sbw )
1145 {
1146 
1147    if (sbw->scrollBar.pixmap)
1148       XFreePixmap (XtDisplay (sbw), sbw->scrollBar.pixmap);
1149 
1150    sbw->scrollBar.pixmap =
1151       XCreatePixmap (XtDisplay(sbw), RootWindowOfScreen(XtScreen(sbw)),
1152                      sbw->scrollBar.slider_area_width,
1153 		     sbw->scrollBar.slider_area_height,
1154 		     sbw->core.depth);
1155 }
1156 
1157 
1158 
1159 
1160 
1161 /************************************************************************
1162  *
1163  *  DrawSliderPixmap
1164  *     Draw the slider graphic into the pixmap.
1165  *     Draw the rectangle with a shadow or not and a mark in
1166  *     the middle or the side.
1167  *
1168  ************************************************************************/
1169 static void
DrawSliderPixmap(XmScrollBarWidget sbw)1170 DrawSliderPixmap(
1171         XmScrollBarWidget sbw )
1172 {
1173    register int slider_width = sbw->scrollBar.slider_width;
1174    register int slider_height = sbw->scrollBar.slider_height;
1175    register Drawable slider = sbw->scrollBar.pixmap;
1176 
1177    if ((sbw->scrollBar.slider_visual ==  XmFOREGROUND_COLOR) ||
1178        (sbw->scrollBar.slider_visual ==  XmTROUGH_COLOR)) {
1179 	   /* we use the same GC, previously filled with either the
1180 	      foreground or the trough_color pixel */
1181 	   /* The trough area itself has been set, as the window background,
1182 	      to either the trough color (not in that case) or the background
1183 	      pixel */
1184 	   XSetClipMask(XtDisplay((Widget) sbw),
1185 			sbw->scrollBar.flat_slider_GC,
1186 			None);
1187 	   XFillRectangle (XtDisplay ((Widget) sbw), slider,
1188 			   sbw->scrollBar.flat_slider_GC,
1189 			   0, 0, slider_width, slider_height);
1190    } else
1191    if ((sbw->scrollBar.slider_visual == XmBACKGROUND_COLOR) ||
1192        (sbw->scrollBar.slider_visual == XmSHADOWED_BACKGROUND)) {
1193 
1194        /* in all other case, draw the shadow */
1195        XFillRectangle (XtDisplay ((Widget) sbw), slider,
1196 		       sbw->scrollBar.foreground_GC,
1197 		       0, 0, slider_width, slider_height);
1198 
1199        if (sbw->scrollBar.slider_visual == XmSHADOWED_BACKGROUND)
1200 	   XmeDrawShadows (XtDisplay (sbw), slider,
1201 			   sbw->primitive.top_shadow_GC,
1202 			   sbw->primitive.bottom_shadow_GC,
1203 			   0, 0, slider_width, slider_height,
1204 			   sbw->primitive.shadow_thickness,
1205 			   XmSHADOW_OUT);
1206    }
1207 
1208 
1209    if (sbw->scrollBar.sliding_mode == XmTHERMOMETER) {
1210        /* in thermo mode, the mark must go on the side
1211 	  of the slider, not in the middle.
1212 	  We do that by modifying slider_width or _height
1213 	  up front and share the same code thereafter */
1214        if (sbw->scrollBar.orientation == XmHORIZONTAL) {
1215 	   if (PROCESS_DIR_INVERSED(sbw)) {
1216 	       slider_width = THERMO_MARK_OFFSET ;
1217 	   } else {
1218 	       slider_width = 2 * slider_width - THERMO_MARK_OFFSET ;
1219 	   }
1220        } else {
1221 	   if (PROCESS_DIR_INVERSED(sbw)) {
1222 	       slider_height = THERMO_MARK_OFFSET;
1223 	   } else {
1224 	       slider_height = 2 * slider_height - THERMO_MARK_OFFSET;
1225 	   }
1226        }
1227    }
1228 
1229    if (sbw->scrollBar.slider_mark == XmETCHED_LINE) {
1230 
1231       if (sbw->scrollBar.orientation == XmHORIZONTAL) {
1232          XDrawLine (XtDisplay (sbw), slider,
1233                     sbw->primitive.bottom_shadow_GC,
1234                     slider_width / 2 - 1, 1,
1235                     slider_width / 2 - 1, slider_height - 2);
1236          XDrawLine (XtDisplay (sbw), slider,
1237                     sbw->primitive.top_shadow_GC,
1238                     slider_width / 2, 1,
1239                     slider_width / 2, slider_height - 2);
1240       } else {
1241          XDrawLine (XtDisplay (sbw), slider,
1242                     sbw->primitive.bottom_shadow_GC,
1243                     1, slider_height / 2 - 1,
1244                     slider_width - 2, slider_height / 2 - 1);
1245          XDrawLine (XtDisplay (sbw), slider,
1246                     sbw->primitive.top_shadow_GC,
1247                     1, slider_height / 2,
1248                     slider_width - 2, slider_height / 2);
1249       }
1250    } else
1251 
1252    if (sbw->scrollBar.slider_mark == XmTHUMB_MARK) {
1253        Dimension thumb_spacing = 4, margin = 2 ;
1254 
1255        if (sbw->scrollBar.orientation == XmHORIZONTAL) {
1256          XmeDrawSeparator (XtDisplay (sbw), slider,
1257 			   sbw->primitive.top_shadow_GC,
1258 			   sbw->primitive.bottom_shadow_GC, NULL,
1259 			   slider_width / 2, 0,
1260 			   2, slider_height, 2, margin,
1261 			   XmVERTICAL, XmSHADOW_ETCHED_OUT);
1262          XmeDrawSeparator (XtDisplay (sbw), slider,
1263 			   sbw->primitive.top_shadow_GC,
1264 			   sbw->primitive.bottom_shadow_GC, NULL,
1265 			   slider_width / 2 - thumb_spacing, 0,
1266 			   2, slider_height, 2, margin,
1267 			   XmVERTICAL, XmSHADOW_ETCHED_OUT);
1268          XmeDrawSeparator (XtDisplay (sbw), slider,
1269 			   sbw->primitive.top_shadow_GC,
1270 			   sbw->primitive.bottom_shadow_GC, NULL,
1271 			   slider_width / 2 + thumb_spacing, 0,
1272 			   2, slider_height, 2, margin,
1273 			   XmVERTICAL, XmSHADOW_ETCHED_OUT);
1274       }
1275       else
1276       {
1277          XmeDrawSeparator (XtDisplay (sbw), slider,
1278 			   sbw->primitive.top_shadow_GC,
1279 			   sbw->primitive.bottom_shadow_GC, NULL,
1280 			   0, slider_height / 2,
1281 			   slider_width, 2, 2, margin,
1282 			   XmHORIZONTAL, XmSHADOW_ETCHED_OUT);
1283          XmeDrawSeparator (XtDisplay (sbw), slider,
1284 			   sbw->primitive.top_shadow_GC,
1285 			   sbw->primitive.bottom_shadow_GC, NULL,
1286 			   0, slider_height / 2 - thumb_spacing,
1287 			   slider_width, 2, 2, margin,
1288 			   XmHORIZONTAL, XmSHADOW_ETCHED_OUT);
1289          XmeDrawSeparator (XtDisplay (sbw), slider,
1290 			   sbw->primitive.top_shadow_GC,
1291 			   sbw->primitive.bottom_shadow_GC, NULL,
1292 			   0, slider_height / 2 + thumb_spacing,
1293 			   slider_width, 2, 2, margin,
1294 			   XmHORIZONTAL, XmSHADOW_ETCHED_OUT);
1295 
1296       }
1297    }
1298 
1299    if (sbw->scrollBar.slider_mark == XmROUND_MARK) {
1300        Dimension radius = DEFAULT_ROUND_MARK_RADIUS ;
1301 
1302        XmeDrawCircle(XtDisplay (sbw), slider,
1303 		     sbw->primitive.top_shadow_GC,
1304 		     sbw->primitive.bottom_shadow_GC,
1305 		     NULL,
1306 		     slider_width / 2 - radius,
1307 		     slider_height / 2 - radius,
1308 		     2*radius, 2*radius,
1309 		     sbw->primitive.shadow_thickness, 0);
1310    }
1311 
1312 }
1313 
1314 /************************************************************************
1315  *
1316  *  CopySliderInWindow
1317  *	Dump the slider pixmap into the window using CopyArea.
1318  *
1319  ************************************************************************/
1320 static void
CopySliderInWindow(XmScrollBarWidget sbw)1321 CopySliderInWindow(
1322         XmScrollBarWidget sbw )
1323 {
1324     /* use the pixmap that contains the slider graphics */
1325     if (XtIsRealized((Widget)sbw) && sbw->scrollBar.pixmap) {
1326 	XCopyArea (XtDisplay ((Widget) sbw),
1327 		   sbw->scrollBar.pixmap, XtWindow ((Widget) sbw),
1328 		   sbw->scrollBar.foreground_GC,
1329 		   0, 0,
1330 		   sbw->scrollBar.slider_width, sbw->scrollBar.slider_height,
1331 		   sbw->scrollBar.slider_x, sbw->scrollBar.slider_y);
1332     }
1333 }
1334 
1335 /************************************************************************
1336  *
1337  *  RedrawSliderWindow
1338  *	Clear the trough area at the current slider position,
1339  *      recompute the slider coordinates and redraw the slider the window by
1340  *      copying from the pixmap graphics.
1341  *
1342  ************************************************************************/
1343 static void
RedrawSliderWindow(XmScrollBarWidget sbw)1344 RedrawSliderWindow(
1345         XmScrollBarWidget sbw )
1346 {
1347     short old_slider_width = sbw->scrollBar.slider_width ;
1348     short old_slider_height = sbw->scrollBar.slider_height ;
1349 
1350     if (XtIsRealized((Widget)sbw))
1351 	XClearArea(XtDisplay ((Widget) sbw), XtWindow ((Widget) sbw),
1352 		   (int) sbw->scrollBar.slider_area_x,
1353 		   (int) sbw->scrollBar.slider_area_y,
1354 		   (unsigned int) sbw->scrollBar.slider_area_width,
1355 		   (unsigned int) sbw->scrollBar.slider_area_height,
1356 		   (Bool) FALSE);
1357 
1358     CalcSliderRect(sbw,
1359 		   &(sbw->scrollBar.slider_x),
1360 		   &(sbw->scrollBar.slider_y),
1361 		   &(sbw->scrollBar.slider_width),
1362 		   &(sbw->scrollBar.slider_height));
1363 
1364     if ((old_slider_width != sbw->scrollBar.slider_width) ||
1365 	(old_slider_height != sbw->scrollBar.slider_height))
1366 	DrawSliderPixmap(sbw);
1367 
1368     CopySliderInWindow(sbw);
1369 }
1370 
1371 
1372 
1373 
1374 /************************************************************************
1375  *
1376  *  CalcSliderRect
1377  *     Calculate the slider location and size in pixels so that
1378  *     it can be drawn.  Note that number and location of pixels
1379  *     is always positive, so no special case rounding is needed.
1380  *     DD: better be a CalcSliderPosition and CalcSliderSize, since
1381  *         this routine is often use for one _or_ the other case.
1382  *
1383  ************************************************************************/
1384 static void
CalcSliderRect(XmScrollBarWidget sbw,short * slider_x,short * slider_y,short * slider_width,short * slider_height)1385 CalcSliderRect(
1386         XmScrollBarWidget sbw,
1387         short *slider_x,
1388         short *slider_y,
1389         short *slider_width,
1390         short *slider_height )
1391 {
1392 	float range;
1393 	float trueSize;
1394 	float factor;
1395 	float slideSize;
1396 	int minSliderWidth;
1397 	int minSliderHeight;
1398 	int hitTheWall = 0;
1399 	int value ;
1400 
1401 	/* Set up */
1402 	if (sbw->scrollBar.orientation == XmHORIZONTAL)
1403 	{
1404 		trueSize =  sbw->scrollBar.slider_area_width;
1405 		minSliderWidth = MIN_SLIDER_LENGTH;
1406 		if (sbw->scrollBar.sliding_mode == XmTHERMOMETER)
1407 		    minSliderWidth = 1;
1408 		minSliderHeight = MIN_SLIDER_THICKNESS;
1409 
1410 	}
1411 	else /* orientation == XmVERTICAL */
1412 	{
1413 		trueSize = sbw->scrollBar.slider_area_height;
1414 		minSliderWidth = MIN_SLIDER_THICKNESS;
1415 		minSliderHeight = MIN_SLIDER_LENGTH;
1416 		if (sbw->scrollBar.sliding_mode == XmTHERMOMETER)
1417 		    minSliderHeight = 1;
1418 	}
1419 
1420 	/* Total number of user units displayed */
1421 	range = sbw->scrollBar.maximum - sbw->scrollBar.minimum;
1422 
1423 	/* A naive notion of pixels per user unit */
1424 	factor = trueSize / range;
1425 
1426 	if (PROCESS_DIR_INVERSED(sbw))
1427 	    value = INVERSED_VALUE(sbw);
1428 	else
1429 	    value = sbw->scrollBar.value ;
1430 
1431 	/* A naive notion of the size of the slider in pixels */
1432 	/* in thermo, slider_size is 0 ans is ignored */
1433 	if (sbw->scrollBar.sliding_mode == XmTHERMOMETER)
1434 	    slideSize = (float) value * factor;
1435 	else
1436 	    slideSize = (float) (sbw->scrollBar.slider_size) * factor;
1437 
1438 
1439 
1440 	/* NOTE SIDE EFFECT */
1441 #define MAX_SCROLLBAR_DIMENSION(val, min)\
1442 	((val) > (min)) ? (val) : (hitTheWall = min)
1443 
1444 
1445 	/* Don't let the slider get too small */
1446 	if (sbw->scrollBar.orientation == XmHORIZONTAL)
1447 	{
1448 		*slider_width = MAX_SCROLLBAR_DIMENSION(
1449 			(int) (slideSize + 0.5), minSliderWidth);
1450 		*slider_height = MAX(sbw->scrollBar.slider_area_height,
1451 			minSliderHeight);
1452 	}
1453 	else /* orientation == XmVERTICAL */
1454 	{
1455 		*slider_width = MAX(sbw->scrollBar.slider_area_width,
1456 			minSliderWidth);
1457 		*slider_height = MAX_SCROLLBAR_DIMENSION((int)
1458 			(slideSize + 0.5), minSliderHeight);
1459 	}
1460 
1461 	if (hitTheWall)
1462 	{
1463 		/*
1464 		 * The slider has not been allowed to take on its true
1465 		 * proportionate size (it would have been too small).  This
1466 		 * breaks proportionality of the slider and the conversion
1467 		 * between pixels and user units.
1468 		 *
1469 		 * The factor needs to be tweaked in this case.
1470 		 */
1471 
1472 		trueSize -= hitTheWall; /* actual pixels available */
1473 		range -= sbw->scrollBar.slider_size; /* actual range */
1474 	        if (range == 0) range = 1;
1475 		factor = trueSize / range;
1476 
1477 	}
1478 
1479 	if (sbw->scrollBar.orientation == XmHORIZONTAL)
1480 	{
1481 		/* Many parentheses to explicitly control type conversion. */
1482 		if (sbw->scrollBar.sliding_mode == XmTHERMOMETER) {
1483 		    if (PROCESS_DIR_INVERSED(sbw)) {
1484 			*slider_x = sbw->scrollBar.slider_area_x +
1485 			    sbw->scrollBar.slider_area_width - *slider_width;
1486 		    } else {
1487 			*slider_x = sbw->scrollBar.slider_area_x;
1488 		    }
1489 		} else
1490 		    *slider_x = ((int) (((((float) sbw->scrollBar.value)
1491 			- ((float) sbw->scrollBar.minimum)) * factor) + 0.5))
1492 			+ sbw->scrollBar.slider_area_x;
1493 		*slider_y = sbw->scrollBar.slider_area_y ;
1494 	}
1495 	else
1496 	{
1497 		*slider_x = sbw->scrollBar.slider_area_x;
1498 		if (sbw->scrollBar.sliding_mode == XmTHERMOMETER) {
1499 		    if (PROCESS_DIR_INVERSED(sbw)) {
1500 			*slider_y = sbw->scrollBar.slider_area_y +
1501 			    sbw->scrollBar.slider_area_height - *slider_height;
1502 		    } else {
1503 			*slider_y = sbw->scrollBar.slider_area_y ;
1504 		    }
1505 		} else
1506 		    *slider_y = ((int) (((((float) sbw->scrollBar.value)
1507 			- ((float) sbw->scrollBar.minimum)) * factor) + 0.5))
1508 			+ sbw->scrollBar.slider_area_y;
1509 	}
1510 
1511 	/* One final adjustment (of questionable value--preserved
1512 	   for visual backward compatibility) */
1513 
1514 	if ((sbw->scrollBar.orientation == XmHORIZONTAL)
1515 		&&
1516 		((*slider_x + *slider_width) > (sbw->scrollBar.slider_area_x
1517 			+ sbw->scrollBar.slider_area_width)))
1518 	{
1519 		*slider_x = sbw->scrollBar.slider_area_x
1520 			+ sbw->scrollBar.slider_area_width - *slider_width;
1521 	}
1522 
1523 	if ((sbw->scrollBar.orientation == XmVERTICAL)
1524 		&&
1525 		((*slider_y + *slider_height) > (sbw->scrollBar.slider_area_y
1526 			+ sbw->scrollBar.slider_area_height)))
1527 	{
1528 		*slider_y = sbw->scrollBar.slider_area_y
1529 			+ sbw->scrollBar.slider_area_height - *slider_height;
1530 	}
1531 }
1532 
1533 
1534 
1535 
1536 /************************************************************************
1537  *
1538  *  Redisplay
1539  *     General redisplay function called on exposure events.
1540  *
1541  ************************************************************************/
1542 static void
Redisplay(Widget wid,XEvent * event,Region region)1543 Redisplay(
1544         Widget wid,
1545         XEvent *event,
1546         Region region )
1547 {
1548     XmScrollBarWidget sbw = (XmScrollBarWidget) wid ;
1549 
1550 
1551     if (sbw->primitive.shadow_thickness > 0)
1552 	XmeDrawShadows (XtDisplay (sbw), XtWindow (sbw),
1553 		      sbw->primitive.bottom_shadow_GC,
1554 		      sbw->primitive.top_shadow_GC,
1555 		      sbw->primitive.highlight_thickness,
1556 		      sbw->primitive.highlight_thickness,
1557 		      sbw->core.width-2 *
1558 		        sbw->primitive.highlight_thickness,
1559 		      sbw->core.height-2 *
1560 		        sbw->primitive.highlight_thickness,
1561 		      sbw->primitive.shadow_thickness,
1562 		      XmSHADOW_OUT);
1563 
1564     /* dump the pixmap that contains the slider graphics */
1565     CopySliderInWindow(sbw);
1566 
1567     if (sbw -> scrollBar.show_arrows) {
1568 
1569 	DRAWARROW(sbw, ((sbw->scrollBar.arrow1_selected)?
1570 		 sbw -> primitive.bottom_shadow_GC:
1571 		 sbw -> primitive.top_shadow_GC),
1572 		((sbw->scrollBar.arrow1_selected)?
1573 		 sbw -> primitive.top_shadow_GC :
1574 		 sbw -> primitive.bottom_shadow_GC),
1575 		sbw->scrollBar.arrow1_x,
1576 		sbw->scrollBar.arrow1_y,
1577 		sbw->scrollBar.arrow1_orientation);
1578 	DRAWARROW(sbw, ((sbw->scrollBar.arrow2_selected)?
1579 		 sbw -> primitive.bottom_shadow_GC:
1580 		 sbw -> primitive.top_shadow_GC),
1581 		((sbw->scrollBar.arrow2_selected)?
1582 		 sbw -> primitive.top_shadow_GC :
1583 		 sbw -> primitive.bottom_shadow_GC),
1584 		sbw->scrollBar.arrow2_x,
1585 		sbw->scrollBar.arrow2_y,
1586 		sbw->scrollBar.arrow2_orientation);
1587   }
1588 
1589     if (!(XtIsSensitive(wid))) {
1590         XSetClipMask(XtDisplay(sbw), sbw->scrollBar.unavailable_GC, None);
1591 	XFillRectangle(XtDisplay(sbw), XtWindow(sbw),
1592 		       sbw->scrollBar.unavailable_GC,
1593 		       sbw->primitive.highlight_thickness
1594 		       + sbw->primitive.shadow_thickness,
1595 		       sbw->primitive.highlight_thickness
1596 		       + sbw->primitive.shadow_thickness,
1597 		       XtWidth(sbw) - (2 * (sbw->primitive.highlight_thickness
1598 				+ sbw->primitive.shadow_thickness)),
1599 		       XtHeight(sbw) - (2 * (sbw->primitive.highlight_thickness
1600 				+ sbw->primitive.shadow_thickness)));
1601     }
1602 #ifdef FUNKY_INSENSITIVE_VISUAL
1603     else if (sbw->scrollBar.show_arrows)
1604     {
1605         XSetClipMask(XtDisplay(sbw), sbw->scrollBar.unavailable_GC, None);
1606         if (!(sbw->scrollBar.flags & ARROW1_AVAILABLE))
1607         {
1608 			XFillRectangle(XtDisplay(sbw), XtWindow(sbw),
1609 				sbw->scrollBar.unavailable_GC,
1610 				sbw->scrollBar.arrow1_x,
1611 				sbw->scrollBar.arrow1_y,
1612 				sbw->scrollBar.arrow_width,
1613 				sbw->scrollBar.arrow_height);
1614         }
1615         if (!(sbw->scrollBar.flags & ARROW2_AVAILABLE))
1616         {
1617 			XFillRectangle(XtDisplay(sbw), XtWindow(sbw),
1618 				sbw->scrollBar.unavailable_GC,
1619 				sbw->scrollBar.arrow2_x,
1620 				sbw->scrollBar.arrow2_y,
1621 				sbw->scrollBar.arrow_width,
1622 				sbw->scrollBar.arrow_height);
1623         }
1624     }
1625 #endif
1626 
1627 
1628     /* envelop primitive expose method for highlight */
1629     {
1630 	XtExposeProc expose;
1631 
1632 	_XmProcessLock();
1633 	expose = xmPrimitiveClassRec.core_class.expose;
1634 	_XmProcessUnlock();
1635 
1636 	(*(expose))(wid, event, region) ;
1637     }
1638 
1639 }
1640 
1641 
1642 
1643 
1644 
1645 /************************************************************************
1646  *
1647  *  Resize
1648  *     Process resizes on the widget by destroying and recreating the
1649  *     slider pixmap.
1650  *     Also draw the correct sized slider onto this pixmap.
1651  *
1652  ************************************************************************/
1653 static void
Resize(Widget wid)1654 Resize(
1655         Widget wid )
1656 {
1657     XmScrollBarWidget sbw = (XmScrollBarWidget) wid ;
1658     register int ht = sbw->primitive.highlight_thickness;
1659     register int st = sbw->primitive.shadow_thickness;
1660 
1661 #define CHECK(x) if (x <= 0) x = 1
1662 
1663 #define BOTH_ARROWS_NEAR_SIDE(sbw) \
1664 	    (((sbw->scrollBar.show_arrows == XmMIN_SIDE) &&\
1665 	      !PROCESS_DIR_INVERSED(sbw)) ||\
1666 	     ((sbw->scrollBar.show_arrows == XmMAX_SIDE) &&\
1667 	      PROCESS_DIR_INVERSED(sbw)))
1668 
1669 #define BOTH_ARROWS_FAR_SIDE(sbw) \
1670 	  (((sbw->scrollBar.show_arrows == XmMIN_SIDE) &&\
1671 	    PROCESS_DIR_INVERSED(sbw)) ||\
1672 	   ((sbw->scrollBar.show_arrows == XmMAX_SIDE) &&\
1673 	    !PROCESS_DIR_INVERSED(sbw)))
1674 
1675 #define ARROW1_NEAR_SIDE(sbw) \
1676 	  ( (sbw->scrollBar.show_arrows == XmEACH_SIDE) ||\
1677 	   BOTH_ARROWS_NEAR_SIDE (sbw) )
1678 
1679 #define ARROW2_FAR_SIDE(sbw) \
1680 	 ((sbw->scrollBar.show_arrows == XmEACH_SIDE) ||\
1681 	  BOTH_ARROWS_FAR_SIDE (sbw) )
1682 
1683     /*  Calculate all of the internal data for slider */
1684 
1685     if (sbw->scrollBar.show_arrows) {
1686 
1687 	if (sbw->scrollBar.orientation == XmHORIZONTAL) {
1688 
1689 	    sbw->scrollBar.arrow1_orientation = XmARROW_LEFT;
1690 	    sbw->scrollBar.arrow2_orientation = XmARROW_RIGHT;
1691 
1692 	    /*  left arrow position and size  */
1693 
1694 	    sbw->scrollBar.arrow1_y = ht + st;
1695 
1696 	    sbw->scrollBar.arrow_width =
1697 		sbw->scrollBar.arrow_height = sbw->core.height
1698 		    - 2 * (ht + st);
1699 
1700 	    if (ARROW1_NEAR_SIDE (sbw)) {
1701 		 sbw->scrollBar.arrow1_x = ht + st;
1702 	     } else {
1703 		 sbw->scrollBar.arrow1_x = sbw->core.width -ht -st
1704 		     - 2 * sbw->scrollBar.arrow_width;
1705 	     }
1706 
1707 	    if (sbw->core.width <
1708 		2 * (sbw->scrollBar.arrow_width + ht + st)
1709 		+ MIN_SLIDER_LENGTH + 2)
1710 		sbw->scrollBar.arrow_width = (sbw->core.width
1711 			 - (MIN_SLIDER_LENGTH + 2 + 2 * (ht + st))) / 2;
1712 
1713 	    /*  slide area position and size  */
1714 
1715 	    if (sbw->scrollBar.show_arrows == XmEACH_SIDE) {
1716 		sbw->scrollBar.slider_area_x =
1717 		    ht + st + sbw->scrollBar.arrow_width + 1;
1718 	    } else
1719 	    if (BOTH_ARROWS_NEAR_SIDE (sbw)) {
1720 		sbw->scrollBar.slider_area_x =
1721 		    ht + st + 2 * sbw->scrollBar.arrow_width + 2;
1722 	    } else {
1723 		sbw->scrollBar.slider_area_x = ht + st ;
1724 	    }
1725 
1726 	    sbw->scrollBar.slider_area_width =
1727 		sbw->core.width
1728 		    - 2 * (ht + st + sbw->scrollBar.arrow_width + 1);
1729 
1730 	    if ((2*(ht+st)) > XtHeight(sbw))
1731 		sbw->scrollBar.slider_area_y = XtHeight(sbw) / 2;
1732 	    else
1733 		sbw->scrollBar.slider_area_y = ht + st;
1734 
1735 	    sbw->scrollBar.slider_area_height =
1736 		sbw->core.height - 2 * (ht + st);
1737 
1738 
1739 	    /*  right arrow position  */
1740 
1741 	    if (ARROW2_FAR_SIDE(sbw)) {
1742 		sbw->scrollBar.arrow2_x = ht + st
1743 		    + sbw->scrollBar.arrow_width + 1 +
1744 			sbw->scrollBar.slider_area_width + 1;
1745 	    } else {
1746 		sbw->scrollBar.arrow2_x = ht + st
1747 		    + sbw->scrollBar.arrow_width ;
1748 	    }
1749 
1750 	    sbw->scrollBar.arrow2_y = ht + st;
1751 
1752 	} else { /* VERTICAL */
1753 
1754 	    sbw->scrollBar.arrow1_orientation = XmARROW_UP;
1755 	    sbw->scrollBar.arrow2_orientation = XmARROW_DOWN;
1756 
1757 	    /*  top arrow position and size  */
1758 
1759 	    sbw->scrollBar.arrow1_x = ht + st;
1760 
1761 	    sbw->scrollBar.arrow_width = sbw->scrollBar.arrow_height =
1762 		sbw->core.width - 2 * (ht + st);
1763 
1764 	    if (ARROW1_NEAR_SIDE(sbw)) {
1765 		sbw->scrollBar.arrow1_y = ht + st;
1766 	    } else {
1767 		sbw->scrollBar.arrow1_y = sbw->core.height -ht -st
1768 		    - 2 * sbw->scrollBar.arrow_height;
1769 	    }
1770 
1771 	    if (sbw->core.height <
1772 		2 * (sbw->scrollBar.arrow_height + ht + st)
1773 		+ MIN_SLIDER_LENGTH +2)
1774 		sbw->scrollBar.arrow_height = (sbw->core.height
1775 			- (MIN_SLIDER_LENGTH + 2 + 2 * (ht + st))) / 2;
1776 
1777 	    /*  slide area position and size  */
1778 
1779 	    if (sbw->scrollBar.show_arrows == XmEACH_SIDE) {
1780 		sbw->scrollBar.slider_area_y =
1781 		    ht + st + sbw->scrollBar.arrow_height + 1;
1782 	    } else
1783 	    if (BOTH_ARROWS_NEAR_SIDE (sbw)) {
1784 		sbw->scrollBar.slider_area_y =
1785 		    ht + st + 2 * sbw->scrollBar.arrow_height + 2 ;
1786 	    } else {
1787 		sbw->scrollBar.slider_area_y = ht + st ;
1788 	    }
1789 
1790 	    sbw->scrollBar.slider_area_height = sbw->core.height
1791 		- 2 * (ht + st + sbw->scrollBar.arrow_height +1);
1792 
1793 	    if ((2*(st+ht)) > XtWidth(sbw))
1794 		sbw->scrollBar.slider_area_x = XtWidth(sbw) / 2;
1795 	    else
1796 		sbw->scrollBar.slider_area_x = ht + st;
1797 
1798 	    sbw->scrollBar.slider_area_width = sbw->core.width
1799 		- 2 * (ht + st);
1800 
1801 
1802 	    /*  down arrow position  */
1803 	    if (ARROW2_FAR_SIDE(sbw)) {
1804 		sbw->scrollBar.arrow2_y = ht + st
1805 		    + sbw->scrollBar.arrow_height + 1 +
1806 			sbw->scrollBar.slider_area_height + 1;
1807 	    } else {
1808 		sbw->scrollBar.arrow2_y = ht + st
1809 		    + sbw->scrollBar.arrow_height ;
1810 	    }
1811 
1812 	    sbw->scrollBar.arrow2_x = ht + st;
1813 	}
1814 
1815 	CHECK(sbw->scrollBar.arrow_height);
1816 	CHECK(sbw->scrollBar.arrow_width);
1817     } else {
1818 	sbw->scrollBar.arrow_width = 0;
1819 	sbw->scrollBar.arrow_height = 0;
1820 
1821 	if (sbw->scrollBar.orientation == XmHORIZONTAL) {
1822 	    /*  slide area position and size  */
1823 
1824 	    sbw->scrollBar.slider_area_x = ht + st;
1825 	    sbw->scrollBar.slider_area_width = sbw->core.width
1826 		- 2 * (ht + st);
1827 
1828 	    if ((2*(ht+st)) > XtHeight(sbw))
1829 		sbw->scrollBar.slider_area_y = XtHeight(sbw) / 2;
1830 	    else
1831 		sbw->scrollBar.slider_area_y = ht + st;
1832 	    sbw->scrollBar.slider_area_height = sbw->core.height
1833 		- 2 * (ht + st);
1834 	} else {
1835 	    /*  slide area position and size  */
1836 
1837 	    sbw->scrollBar.slider_area_y = ht + st;
1838 	    sbw->scrollBar.slider_area_height = sbw->core.height
1839 		- 2 * (ht + st);
1840 
1841 	    if ((2*(st+ht)) > XtWidth(sbw))
1842 		sbw->scrollBar.slider_area_x = XtWidth(sbw) / 2;
1843 	    else
1844 		sbw->scrollBar.slider_area_x = ht + st;
1845 	    sbw->scrollBar.slider_area_width = sbw->core.width
1846 		- 2 * (ht + st);
1847 	}
1848     }
1849 
1850     CHECK(sbw->scrollBar.slider_area_height);
1851     CHECK(sbw->scrollBar.slider_area_width);
1852 
1853     GetSliderPixmap (sbw); /* the size of the scrollbar window - arrows */
1854 
1855     CalcSliderRect(sbw,
1856 		   &(sbw->scrollBar.slider_x),
1857 		   &(sbw->scrollBar.slider_y),
1858 		   &(sbw->scrollBar.slider_width),
1859 		   &(sbw->scrollBar.slider_height));
1860 
1861     DrawSliderPixmap (sbw);
1862 }
1863 
1864 
1865 
1866 
1867 /*********************************************************************
1868  *
1869  * Realize
1870  *
1871  ********************************************************************/
1872 static void
Realize(Widget wid,XtValueMask * window_mask,XSetWindowAttributes * window_attributes)1873 Realize(
1874         Widget wid,
1875         XtValueMask *window_mask,
1876         XSetWindowAttributes *window_attributes )
1877 {
1878     XmScrollBarWidget sbw = (XmScrollBarWidget) wid ;
1879 
1880     *window_mask |= CWBitGravity;
1881     window_attributes->bit_gravity = ForgetGravity;
1882 
1883     /* if we are in the slider color = trough color case, we need to
1884        get the regular background as the trough (= window) color,
1885        otherwise, we need to get the trough color */
1886     if (sbw->scrollBar.slider_visual != XmTROUGH_COLOR) {
1887 	*window_mask |= CWBackPixel ;
1888 	window_attributes->background_pixel = sbw->scrollBar.trough_color;
1889     }
1890 
1891     XtCreateWindow (wid, InputOutput, CopyFromParent, *window_mask,
1892 		    window_attributes);
1893 }
1894 
1895 
1896 
1897 
1898 /************************************************************************
1899  *
1900  *  Destroy
1901  *	Clean up allocated resources when the widget is destroyed.
1902  *
1903  ************************************************************************/
1904 static void
Destroy(Widget wid)1905 Destroy(
1906         Widget wid )
1907 {
1908     XmScrollBarWidget sbw = (XmScrollBarWidget) wid ;
1909 
1910     XtReleaseGC ((Widget) sbw, sbw->scrollBar.foreground_GC);
1911     XtReleaseGC ((Widget) sbw, sbw->scrollBar.unavailable_GC);
1912     XtReleaseGC ((Widget) sbw, sbw->scrollBar.flat_slider_GC);
1913 
1914     if (sbw->scrollBar.pixmap != 0)
1915 	XFreePixmap (XtDisplay (sbw), sbw->scrollBar.pixmap);
1916 
1917     if (sbw->scrollBar.timer != 0)
1918      {
1919        XtRemoveTimeOut (sbw->scrollBar.timer);
1920        sbw->scrollBar.timer = 0;
1921      }
1922 }
1923 
1924 
1925 
1926 
1927 /************************************************************************
1928  *
1929  *  ValidateInputs
1930  *
1931  ************************************************************************/
1932 /*ARGSUSED*/
1933 static Boolean
ValidateInputs(XmScrollBarWidget current,XmScrollBarWidget request,XmScrollBarWidget new_w)1934 ValidateInputs(
1935 	       XmScrollBarWidget current,
1936 	       XmScrollBarWidget request, /* unused */
1937 	       XmScrollBarWidget new_w )
1938 {
1939     Boolean returnFlag = TRUE;
1940     int value ;
1941 
1942     /* Validate the incoming data  */
1943 
1944     if (new_w->scrollBar.minimum >= new_w->scrollBar.maximum)
1945 	{
1946 	    new_w->scrollBar.minimum = current->scrollBar.minimum;
1947 	    new_w->scrollBar.maximum = current->scrollBar.maximum;
1948 	    XmeWarning( (Widget) new_w, MESSAGE1);
1949 	    returnFlag = FALSE;
1950 	}
1951 
1952     if (new_w->scrollBar.sliding_mode != current->scrollBar.sliding_mode) {
1953 	if (new_w->scrollBar.sliding_mode != XmTHERMOMETER) {
1954 	    new_w->scrollBar.slider_size = (new_w->scrollBar.maximum
1955 					    - new_w->scrollBar.minimum) / 10;
1956 	    if (new_w->scrollBar.slider_size < 1)
1957 		new_w->scrollBar.slider_size = 1;
1958 	} else
1959 	    new_w->scrollBar.slider_size = 0 ;
1960     }
1961 
1962     if (new_w->scrollBar.sliding_mode != XmTHERMOMETER) {
1963 
1964 	if (new_w->scrollBar.slider_size < 1) {
1965 	    if ((new_w->scrollBar.maximum - new_w->scrollBar.minimum) <
1966 		current->scrollBar.slider_size)
1967 		new_w->scrollBar.slider_size = new_w->scrollBar.maximum
1968 		    - new_w->scrollBar.minimum;
1969 	    else
1970 		new_w->scrollBar.slider_size = current->scrollBar.slider_size;
1971 	    XmeWarning( (Widget) new_w, MESSAGE2);
1972 	    returnFlag = FALSE;
1973 	}
1974 
1975 	if ((new_w->scrollBar.slider_size >
1976 	     new_w->scrollBar.maximum - new_w->scrollBar.minimum)) {
1977 	    if ((new_w->scrollBar.maximum - new_w->scrollBar.minimum) <
1978 		current->scrollBar.slider_size)
1979 		new_w->scrollBar.slider_size = new_w->scrollBar.maximum
1980 		    - new_w->scrollBar.minimum;
1981 	    else
1982 		new_w->scrollBar.slider_size = current->scrollBar.slider_size;
1983 	    XmeWarning( (Widget) new_w, MESSAGE13);
1984 	    returnFlag = FALSE;
1985 	}
1986     } else
1987 	new_w->scrollBar.slider_size = 0 ;
1988 
1989     if (new_w->scrollBar.value < new_w->scrollBar.minimum)
1990 	{
1991 	    new_w->scrollBar.value = new_w->scrollBar.minimum;
1992 	    XmeWarning( (Widget) new_w, MESSAGE3);
1993 	    returnFlag = FALSE;
1994 	}
1995 
1996     /* do the checking on the real user value */
1997     if (new_w->scrollBar.value == current->scrollBar.value) {
1998 	if (PROCESS_DIR_INVERSED(new_w))
1999 	    /* use new for value since that's the one getting changed below */
2000 #ifdef FIX_1396
2001 	    value = INVERSED_VALUE(new_w);
2002 #else
2003 	    value = INVERSED_VALUE(current);
2004 #endif
2005 	else
2006 	    value = new_w->scrollBar.value ;
2007     } else
2008 	value = new_w->scrollBar.value ;
2009 
2010     if (value > new_w->scrollBar.maximum - new_w->scrollBar.slider_size)
2011 	{
2012 	    new_w->scrollBar.value =
2013 		new_w->scrollBar.maximum - new_w->scrollBar.slider_size;
2014 	    new_w->scrollBar.flags |= VALUE_SET_FLAG;
2015 	    XmeWarning( (Widget) new_w, MESSAGE4);
2016 	}
2017 
2018     if(  !XmRepTypeValidValue( XmRID_ORIENTATION,
2019 			      new_w->scrollBar.orientation, (Widget) new_w))
2020 	{
2021 	    new_w->scrollBar.orientation = current->scrollBar.orientation;
2022 	    returnFlag = FALSE;
2023 	}
2024 
2025     if (new_w->scrollBar.orientation == XmHORIZONTAL)
2026 	{
2027 	    if ((new_w->scrollBar.processing_direction != XmMAX_ON_LEFT) &&
2028 		(new_w->scrollBar.processing_direction != XmMAX_ON_RIGHT))
2029 		{
2030 		    new_w->scrollBar.processing_direction =
2031 			current->scrollBar.processing_direction;
2032 		    XmeWarning( (Widget) new_w, MESSAGE6);
2033 		    returnFlag = FALSE;
2034 		}
2035 	}
2036     else /* new_w->scrollBar.orientation == XmVERTICAL */
2037 	{
2038 	    if ((new_w->scrollBar.processing_direction != XmMAX_ON_TOP) &&
2039 		(new_w->scrollBar.processing_direction != XmMAX_ON_BOTTOM))
2040 		{
2041 		    new_w->scrollBar.processing_direction =
2042 			current->scrollBar.processing_direction;
2043 		    XmeWarning( (Widget) new_w, MESSAGE6);
2044 		    returnFlag = FALSE;
2045 		}
2046 	}
2047 
2048     if (new_w->scrollBar.increment <= 0)
2049 	{
2050 	    new_w->scrollBar.increment = current->scrollBar.increment;
2051 	    XmeWarning( (Widget) new_w, MESSAGE7);
2052 	    returnFlag = FALSE;
2053 	}
2054 
2055     if (new_w->scrollBar.page_increment <= 0)
2056 	{
2057 	    new_w->scrollBar.page_increment =
2058 		current->scrollBar.page_increment;
2059 	    XmeWarning( (Widget) new_w,  MESSAGE8);
2060 	    returnFlag = FALSE;
2061 	}
2062 
2063     if (new_w->scrollBar.initial_delay <= 0)
2064 	{
2065 	    new_w->scrollBar.initial_delay = current->scrollBar.initial_delay;
2066 	    XmeWarning( (Widget) new_w, MESSAGE9);
2067 	    returnFlag = FALSE;
2068 	}
2069 
2070     if (new_w->scrollBar.repeat_delay <= 0)
2071 	{
2072 	    new_w->scrollBar.repeat_delay = current->scrollBar.repeat_delay;
2073 	    XmeWarning( (Widget) new_w, MESSAGE10);
2074 	    returnFlag = FALSE;
2075 	}
2076 
2077     if (new_w->core.width == 0)
2078 	{
2079 	    if (new_w->scrollBar.orientation == XmHORIZONTAL)
2080 		new_w->core.width += 100;
2081 	    else
2082 		new_w->core.width += 11;
2083 	}
2084 
2085     if (new_w->core.height == 0)
2086 	{
2087 	    if (new_w->scrollBar.orientation == XmHORIZONTAL)
2088 		new_w->core.height += 11;
2089 	    else
2090 		new_w->core.height += 100;
2091 	}
2092 
2093     return(returnFlag);
2094 }
2095 
2096 /************************************************************************
2097  *
2098  *  SetValues
2099  *
2100  ************************************************************************/
2101 /*ARGSUSED*/
2102 static Boolean
SetValues(Widget cw,Widget rw,Widget nw,ArgList args,Cardinal * num_args)2103 SetValues(
2104         Widget cw,
2105         Widget rw,
2106         Widget nw,
2107         ArgList args,		/* unused */
2108         Cardinal *num_args )	/* unused */
2109 {
2110     XmScrollBarWidget current = (XmScrollBarWidget) cw ;
2111     XmScrollBarWidget request = (XmScrollBarWidget) rw ;
2112     XmScrollBarWidget new_w = (XmScrollBarWidget) nw ;
2113     Boolean returnFlag = FALSE;
2114     Boolean current_backwards = PROCESS_DIR_INVERSED(current);
2115     Boolean new_backwards = PROCESS_DIR_INVERSED(new_w);
2116 
2117 
2118 
2119     if(!XmRepTypeValidValue( XmRID_SHOW_ARROWS,
2120 			    new_w->scrollBar.show_arrows, (Widget) new_w) )
2121 	{
2122 	    new_w->scrollBar.show_arrows = current->scrollBar.sliding_mode;
2123 	}
2124 
2125     if(!XmRepTypeValidValue( XmRID_SLIDING_MODE,
2126 			    new_w->scrollBar.sliding_mode, (Widget) new_w) )
2127 	{
2128 	    new_w->scrollBar.sliding_mode = current->scrollBar.sliding_mode;
2129 	}
2130 
2131     if(!XmRepTypeValidValue( XmRID_SLIDER_VISUAL,
2132 			    new_w->scrollBar.slider_visual, (Widget) new_w) )
2133 	{
2134 	    new_w->scrollBar.slider_visual = current->scrollBar.slider_visual;
2135 	}
2136 
2137     if(!XmRepTypeValidValue( XmRID_SLIDER_MARK,
2138 			    new_w->scrollBar.slider_mark, (Widget) new_w) )
2139 	{
2140 	    new_w->scrollBar.slider_mark = current->scrollBar.slider_mark;
2141 	}
2142 
2143     if (new_w->scrollBar.orientation == XmHORIZONTAL)
2144       {
2145 	if (new_w->scrollBar.processing_direction == XmMAX_ON_LEFT &&
2146 	    !(new_w->scrollBar.flags & VALUE_SET_FLAG) &&
2147 	    ((new_w->scrollBar.slider_size != current->scrollBar.slider_size) ||
2148 	     (new_w->scrollBar.maximum != current->scrollBar.maximum) ||
2149 	     (new_w->scrollBar.minimum != current->scrollBar.minimum) ))
2150 
2151 	  {
2152 	    new_w->scrollBar.value = (new_w->scrollBar.maximum
2153 				      + new_w->scrollBar.minimum
2154 				      - new_w->scrollBar.slider_size) -
2155 					  INVERSED_VALUE(current);
2156 	    new_backwards = FALSE;
2157 	    current_backwards = FALSE;
2158 	  }
2159       }
2160 
2161 
2162     /* Make sure that processing direction tracks orientation */
2163 
2164     if ((new_w->scrollBar.orientation != current->scrollBar.orientation)
2165 	&&
2166 	(new_w->scrollBar.processing_direction ==
2167 	 current->scrollBar.processing_direction))
2168 	{
2169 	    if ((new_w->scrollBar.orientation == XmHORIZONTAL) &&
2170 		(current->scrollBar.processing_direction == XmMAX_ON_TOP))
2171 		new_w->scrollBar.processing_direction = XmMAX_ON_LEFT;
2172 	    else if ((new_w->scrollBar.orientation == XmHORIZONTAL) &&
2173 		     (current->scrollBar.processing_direction ==
2174 		      XmMAX_ON_BOTTOM))
2175 		new_w->scrollBar.processing_direction = XmMAX_ON_RIGHT;
2176 	    else if ((new_w->scrollBar.orientation == XmVERTICAL) &&
2177 		     (current->scrollBar.processing_direction == XmMAX_ON_LEFT))
2178 		new_w->scrollBar.processing_direction = XmMAX_ON_TOP;
2179 	    else if ((new_w->scrollBar.orientation == XmVERTICAL) &&
2180 		     (current->scrollBar.processing_direction == XmMAX_ON_RIGHT))
2181 		new_w->scrollBar.processing_direction = XmMAX_ON_BOTTOM;
2182 	}
2183 
2184     while (!ValidateInputs(current, request, new_w)) /*EMPTY*/;
2185 
2186     /*
2187      * Because someone somewhere originally thought that it was clever
2188      * for the scrollbar widget to do all of its internal processing in
2189      * just one direction, all of the interface procedures have to go
2190      * through extreme gymnastics to support reversal.
2191      */
2192     if ((new_backwards && !current_backwards) ||
2193 	(!new_backwards && current_backwards))
2194 	{
2195 	    if (new_w->scrollBar.flags & VALUE_SET_FLAG)
2196 		{
2197 		    if (new_backwards)
2198 			new_w->scrollBar.value = INVERSED_VALUE(new_w);
2199 		}
2200 	    else
2201 		{
2202 		    new_w->scrollBar.value = INVERSED_VALUE(new_w);
2203 		}
2204 	}
2205     else
2206 	{
2207 	    if ((new_w->scrollBar.flags & VALUE_SET_FLAG) &&
2208 		(new_backwards))
2209 		new_w->scrollBar.value = INVERSED_VALUE(new_w);
2210 	}
2211 
2212     if (new_w->scrollBar.flags & VALUE_SET_FLAG)
2213 	new_w->scrollBar.flags &= ~VALUE_SET_FLAG;
2214 
2215     /*  See if the GC needs to be regenerated  */
2216 
2217     if (new_w->core.background_pixel != current->core.background_pixel)
2218 	{
2219 	    XtReleaseGC((Widget) new_w, new_w->scrollBar.foreground_GC);
2220 	    GetForegroundGC(new_w);
2221 	}
2222 
2223     if (((new_w->scrollBar.slider_visual == XmTROUGH_COLOR) &&
2224 	(new_w->scrollBar.trough_color != current->scrollBar.trough_color)) ||
2225 	((new_w->scrollBar.slider_visual == XmFOREGROUND_COLOR) &&
2226 	 (new_w->primitive.foreground != current->primitive.foreground)))
2227 	{
2228 	    XtReleaseGC((Widget) new_w, new_w->scrollBar.flat_slider_GC);
2229 	    GetFlatSliderGC(new_w);
2230 	}
2231 
2232     /*
2233      * See if the trough (a.k.a the window background) needs to be
2234      * changed to use a different pixel.
2235      */
2236     if (XtIsRealized(nw)) {
2237 	Pixel change_to = XmUNSPECIFIED_PIXEL ;
2238 	/* slider_visual == XmTROUGH_COLOR is the case where the
2239 	   window background is the real core.background_pixel, all the
2240 	   other use the trough_color as the window background */
2241 
2242 	if ((new_w->scrollBar.slider_visual == XmTROUGH_COLOR) &&
2243 	    (current->scrollBar.slider_visual != XmTROUGH_COLOR)) {
2244 	    /* no need to care for background change since Core did it */
2245 	    change_to = new_w->core.background_pixel;
2246 	}
2247 	if ((new_w->scrollBar.slider_visual != XmTROUGH_COLOR) &&
2248 	    ((current->scrollBar.slider_visual == XmTROUGH_COLOR) ||
2249 	     (new_w->scrollBar.trough_color != current->scrollBar.trough_color) ||
2250 	     /* if the background had changed, Core has certainly reset the
2251 		window background already, so we need to undo that */
2252 	     (new_w->core.background_pixel != current->core.background_pixel))) {
2253 	    change_to = new_w->scrollBar.trough_color ;
2254 	}
2255 	if (change_to != XmUNSPECIFIED_PIXEL) {
2256 	    returnFlag = TRUE;
2257 	    XtReleaseGC((Widget) new_w, new_w->scrollBar.flat_slider_GC);
2258 	    GetFlatSliderGC(new_w);
2259 	    XSetWindowBackground(XtDisplay((Widget)new_w),
2260 				 XtWindow((Widget)new_w), change_to);
2261 	}
2262     }
2263 
2264     /*
2265      * See if the widget needs to be redrawn.  Minimize the amount
2266      * of redraw by having specific checks.
2267      */
2268 
2269     if ((new_w->scrollBar.orientation !=
2270 	 current->scrollBar.orientation)         ||
2271 	(new_w->primitive.shadow_thickness !=
2272 	 current->primitive.shadow_thickness)    ||
2273 	(new_w->primitive.highlight_thickness !=
2274 	 current->primitive.highlight_thickness) ||
2275 	(new_w->scrollBar.show_arrows !=
2276 	 current->scrollBar.show_arrows))
2277 	{
2278 	    /* call Resize method, that will have the effect of
2279 	       recomputing all the internal variables (arrow size,
2280 	       trough are) and recreating the slider pixmap. */
2281 	    XtWidgetProc resize;
2282 	    _XmProcessLock();
2283 	    resize = new_w->core.widget_class->core_class.resize;
2284 	    _XmProcessUnlock();
2285 
2286 	    (* (resize)) ((Widget) new_w);
2287 	    returnFlag = TRUE;
2288 	}
2289 
2290     if ((new_w->primitive.foreground !=
2291 	 current->primitive.foreground)
2292 	||
2293 	(new_w->core.background_pixel != current->core.background_pixel)
2294 	||
2295 	(new_w->primitive.top_shadow_color !=
2296 	 current->primitive.top_shadow_color)
2297 	||
2298 	(new_w->scrollBar.slider_visual !=
2299 	 current->scrollBar.slider_visual)
2300 	||
2301 	(new_w->scrollBar.slider_mark !=
2302 	 current->scrollBar.slider_mark)
2303 	||
2304 	(new_w->scrollBar.trough_color !=
2305 	 current->scrollBar.trough_color)
2306 	||
2307 	(new_w->primitive.bottom_shadow_color !=
2308 	 current->primitive.bottom_shadow_color))
2309 	{
2310 	    returnFlag = TRUE;
2311 	    /* only draw the slider graphics, no need to change the
2312 	       pixmap (call to GetSliderPixmap) nor the slider size
2313 	       (call to CalcSliderRect). */
2314 	    DrawSliderPixmap(new_w);
2315 
2316 	}
2317 
2318     if ((new_w->scrollBar.slider_size !=
2319 	 current->scrollBar.slider_size)                    ||
2320 	(new_w->scrollBar.minimum != current->scrollBar.minimum) ||
2321 	(new_w->scrollBar.maximum != current->scrollBar.maximum) ||
2322 	(new_w->scrollBar.processing_direction !=
2323 	 current->scrollBar.processing_direction)) {
2324 
2325 	/* have to clear the current slider before setting the
2326 	   new slider position and size */
2327 	if (XtIsRealized(nw))
2328 	    XClearArea(XtDisplay((Widget)new_w),
2329 		       XtWindow((Widget)new_w),
2330 		       new_w->scrollBar.slider_x,
2331 		       new_w->scrollBar.slider_y,
2332 		       new_w->scrollBar.slider_width,
2333 		       new_w->scrollBar.slider_height, False);
2334 
2335 	/* recompute the slider size and draw in the pixmap */
2336 	CalcSliderRect(new_w,
2337 		       &(new_w->scrollBar.slider_x),
2338 		       &(new_w->scrollBar.slider_y),
2339 		       &(new_w->scrollBar.slider_width),
2340 		       &(new_w->scrollBar.slider_height));
2341 
2342 	/* redraw the slider in the pixmap */
2343 	DrawSliderPixmap (new_w);
2344 
2345 	if (new_w->scrollBar.slider_size >= (new_w->scrollBar.maximum
2346 					     - new_w->scrollBar.minimum))
2347 	    {
2348 		new_w->scrollBar.flags &= ~SLIDER_AVAILABLE;
2349 		/*
2350 		 * Disabling the slider enables the arrows.  This
2351 		 * leaves the scrollbar in a state amenable to reenabling
2352 		 * the slider.
2353 		 */
2354 		new_w->scrollBar.flags |= ARROW1_AVAILABLE;
2355 		new_w->scrollBar.flags |= ARROW2_AVAILABLE;
2356 		returnFlag = TRUE;
2357 	    }
2358 	else
2359 	    {
2360 		if (! (new_w->scrollBar.flags & SLIDER_AVAILABLE)) {
2361 		    returnFlag = TRUE;
2362 		    new_w->scrollBar.flags |= SLIDER_AVAILABLE;
2363 		} else {
2364 		    /* directly use the pixmap that contains the slider
2365 		       graphics, no need to call RedrawSliderWindow since the
2366 		       cleararea and the calcrect have already been made */
2367 		    CopySliderInWindow(new_w);
2368 		}
2369 	    }
2370     }
2371 
2372 
2373     if (new_w->scrollBar.value != current->scrollBar.value) {
2374 	/* the value has changed, the slider needs to move. */
2375 	RedrawSliderWindow (new_w);
2376 
2377 	if (XtIsRealized(nw))
2378 	{
2379 	/* Following lines taken from Redisplay code; the XmNvalue can change
2380         ** even when the widget is insensitive. Other paths through the code
2381 	** involve user interaction and so sensitivity doesn't need to be
2382 	** considered.
2383 	** NOTE! doesn't deal with FUNKY_INSENSITIVE_VISUAL
2384 	*/
2385 	    if (!(XtIsSensitive((Widget)new_w))) {
2386 		XmScrollBarWidget sbw = (XmScrollBarWidget) new_w;
2387 		XSetClipMask(XtDisplay(sbw), sbw->scrollBar.unavailable_GC, None);
2388 		XFillRectangle(XtDisplay(sbw), XtWindow(sbw),
2389 			       sbw->scrollBar.unavailable_GC,
2390 			       sbw->primitive.highlight_thickness
2391 			       + sbw->primitive.shadow_thickness,
2392 			       sbw->primitive.highlight_thickness
2393 			       + sbw->primitive.shadow_thickness,
2394 			       XtWidth(sbw) - (2 * (sbw->primitive.highlight_thickness
2395 					+ sbw->primitive.shadow_thickness)),
2396 			       XtHeight(sbw) - (2 * (sbw->primitive.highlight_thickness
2397 					+ sbw->primitive.shadow_thickness)));
2398 	    }
2399 	}
2400     }
2401 
2402     if (XtIsSensitive(nw) != XtIsSensitive(cw))
2403 	returnFlag = TRUE;
2404 
2405     return(returnFlag);
2406 }
2407 
2408 
2409 
2410 
2411 /************************************************************************
2412  *
2413  *  CalcSliderVal
2414  *     Calculate the slider val in application coordinates given
2415  *     the input x and y.
2416  *
2417  ************************************************************************/
2418 static int
CalcSliderVal(XmScrollBarWidget sbw,int x,int y)2419 CalcSliderVal(
2420         XmScrollBarWidget sbw,
2421         int x,
2422         int y )
2423 {
2424 	float range;
2425 	float trueSize;       /* size of slider area in pixels */
2426 	float referencePoint; /* origin of slider */
2427 	float proportion;
2428 	int int_proportion;
2429 	int slider_area_origin;
2430 
2431 
2432 	if (sbw->scrollBar.orientation == XmHORIZONTAL)
2433 	{
2434 	    referencePoint = (float) x - sbw->scrollBar.separation_x;
2435 	    trueSize = sbw->scrollBar.slider_area_width;
2436 	    if (sbw->scrollBar.sliding_mode != XmTHERMOMETER)
2437 		trueSize -= sbw->scrollBar.slider_width;
2438 	    slider_area_origin = sbw->scrollBar.slider_area_x;
2439 	}
2440 	else
2441 	{
2442 	    referencePoint = (float) y - sbw->scrollBar.separation_y;
2443 	    trueSize = sbw->scrollBar.slider_area_height;
2444 	    if (sbw->scrollBar.sliding_mode != XmTHERMOMETER)
2445 		trueSize -= sbw->scrollBar.slider_height;
2446 	    slider_area_origin = sbw->scrollBar.slider_area_y;
2447 	}
2448 
2449 	if (trueSize > 0)
2450 
2451 	    /* figure the proportion of slider area between the origin
2452 	       of the slider area and the origin of the slider. */
2453 	    proportion = (referencePoint - slider_area_origin
2454 		 + (((sbw->scrollBar.show_arrows == XmEACH_SIDE) &&
2455 		    (sbw->scrollBar.sliding_mode != XmTHERMOMETER))?1:0)) /
2456 			      trueSize;
2457 	else
2458 		/*
2459 		 * We've got an interesting problem here.  There isn't any
2460 		 * slider area available to slide in.  What should the value
2461 		 * of the scrollbar be when the user tries to drag the slider?
2462 		 *
2463 		 * Setting proportion to 1 snaps to maximum.  Setting
2464 		 * proportion to the reciprocal of "range" will cause the
2465 		 * slider to snap to the minimum.
2466 		 *
2467 		 */
2468 		proportion = 1;
2469 
2470 	/* Actual range displayed */
2471 	range = sbw->scrollBar.maximum - sbw->scrollBar.minimum
2472 		- sbw->scrollBar.slider_size;
2473 
2474 	/* Now scale the proportion in pixels to user units */
2475 	proportion = (proportion * range)
2476 		+ ((float) sbw->scrollBar.minimum);
2477 
2478 	/* Round off appropriately */
2479 	if (proportion > 0)
2480 		proportion += 0.5;
2481 	else if (proportion < 0)
2482 		proportion -= 0.5;
2483 
2484 	int_proportion = (int) proportion;
2485 
2486 	if (int_proportion < sbw->scrollBar.minimum)
2487 		int_proportion = sbw->scrollBar.minimum;
2488 	else if (int_proportion > (sbw->scrollBar.maximum
2489 			- sbw->scrollBar.slider_size))
2490 		int_proportion = sbw->scrollBar.maximum
2491 			- sbw->scrollBar.slider_size;
2492 
2493 	return (int_proportion);
2494 }
2495 
2496 
2497 
2498 
2499 /************************************************************************
2500  *
2501  *  Select
2502  *     This function processes selections occuring on the scrollBar.
2503  *
2504  ************************************************************************/
2505 static void
Select(Widget wid,XEvent * event,String * params,Cardinal * num_params)2506 Select(
2507         Widget wid,
2508         XEvent *event,
2509         String *params,
2510         Cardinal *num_params )
2511 {
2512     XmScrollBarWidget sbw = (XmScrollBarWidget) wid ;
2513     XButtonPressedEvent *buttonEvent = (XButtonPressedEvent *) event ;
2514     int slider_x = sbw->scrollBar.slider_x;
2515     int slider_y = sbw->scrollBar.slider_y;
2516     int slider_width = sbw->scrollBar.slider_width;
2517     int slider_height = sbw->scrollBar.slider_height;
2518     Boolean slider_moved;
2519 
2520     if (!sbw->scrollBar.editable) return ;
2521 
2522 
2523     /* add a start update when the button is pressed
2524        so that scrollbar moves generating widget
2525        configurations be bracketed for dropsite update.
2526        The endupdate is done in Release */
2527 
2528     XmDropSiteStartUpdate(wid);
2529 
2530     sbw->scrollBar.flags &=  ~OPERATION_CANCELLED ;
2531 
2532 #ifndef DEBUG_NO_SB_GRAB
2533     if (XtGrabKeyboard(wid, False, GrabModeAsync,
2534 		       GrabModeAsync, buttonEvent->time) == GrabSuccess)
2535 	sbw->scrollBar.flags |= KEYBOARD_GRABBED;
2536 #endif
2537 
2538     XAllowEvents(XtDisplay(wid), AsyncPointer, CurrentTime);
2539     XAllowEvents(XtDisplay(wid), AsyncKeyboard, CurrentTime);
2540 
2541     if (!(sbw->scrollBar.flags & SLIDER_AVAILABLE))
2542 	return;
2543     if ((buttonEvent->button == Button1) &&
2544 	(!XmIsScrolledWindow(XtParent(wid))))
2545 	(void) XmProcessTraversal( (Widget) sbw, XmTRAVERSE_CURRENT);
2546 
2547     sbw->scrollBar.separation_x = 0;
2548     sbw->scrollBar.separation_y = 0;
2549 
2550 
2551     if ((sbw->scrollBar.orientation == XmHORIZONTAL) &&
2552 	(buttonEvent->y >= slider_y)                      &&
2553 	(buttonEvent->y <= slider_y + slider_height)  &&
2554 	(buttonEvent->button == Button1) &&
2555 	(sbw->scrollBar.sliding_mode == XmTHERMOMETER) &&
2556 	(((PROCESS_DIR_INVERSED(sbw)) &&
2557 	  (buttonEvent->x >= slider_x) &&
2558 	  (buttonEvent->x <= slider_x + THERMO_MARK_OFFSET)) ||
2559 	 (!PROCESS_DIR_INVERSED(sbw) &&
2560 	  (buttonEvent->x <= slider_x + slider_width)   &&
2561 	  (buttonEvent->x >= slider_x + slider_width - THERMO_MARK_OFFSET))))
2562 	/* hack */
2563 	buttonEvent->button = Button2 ;
2564 
2565     if ((sbw->scrollBar.orientation == XmVERTICAL) &&
2566 	(buttonEvent->x >= slider_x) &&
2567 	(buttonEvent->x <= slider_x + slider_width)   &&
2568 	(buttonEvent->button == Button1) &&
2569 	(sbw->scrollBar.sliding_mode == XmTHERMOMETER) &&
2570 	(((PROCESS_DIR_INVERSED(sbw)) &&
2571 	  (buttonEvent->y >= slider_y) &&
2572 	  (buttonEvent->y <= slider_y + THERMO_MARK_OFFSET)) ||
2573 	 (!PROCESS_DIR_INVERSED(sbw) &&
2574 	  (buttonEvent->y >= slider_y + slider_height - THERMO_MARK_OFFSET) &&
2575 	  (buttonEvent->y <= slider_y + slider_height))))
2576 	/* hack */
2577 	buttonEvent->button = Button2 ;
2578 
2579     /*  Calculate whether the selection point is in the slider  */
2580     if ((buttonEvent->x >= slider_x)                 &&
2581 	(buttonEvent->x <= slider_x + slider_width)   &&
2582 	(buttonEvent->y >= slider_y)                      &&
2583 	(buttonEvent->y <= slider_y + slider_height) &&
2584 	((buttonEvent->button != Button1) ||
2585 	 (sbw->scrollBar.sliding_mode != XmTHERMOMETER)))
2586 	{
2587 	    sbw->scrollBar.initial_x = slider_x;
2588 	    sbw->scrollBar.initial_y = slider_y;
2589 	    sbw->scrollBar.sliding_on = True;
2590 	    sbw->scrollBar.saved_value = sbw->scrollBar.value;
2591 	    sbw->scrollBar.arrow1_selected = FALSE;
2592 	    sbw->scrollBar.arrow2_selected = FALSE;
2593 
2594 	    if ((buttonEvent->button == Button1) &&
2595 		(sbw->scrollBar.sliding_mode != XmTHERMOMETER))
2596 		{
2597 		    sbw->scrollBar.separation_x = buttonEvent->x - slider_x;
2598 		    sbw->scrollBar.separation_y = buttonEvent->y - slider_y;
2599 		}
2600 	    else  if (buttonEvent->button == Button2)
2601 		{
2602 		    /* Warp the slider to the cursor, and then drag */
2603 		    if  (sbw->scrollBar.sliding_mode != XmTHERMOMETER) {
2604 			if (sbw->scrollBar.orientation == XmHORIZONTAL)
2605 			    sbw->scrollBar.separation_x =
2606 				sbw->scrollBar.slider_width / 2;
2607 			else
2608 			    sbw->scrollBar.separation_y =
2609 				sbw->scrollBar.slider_height / 2;
2610 		    } else {
2611 			sbw->scrollBar.separation_x = 0 ;
2612 			sbw->scrollBar.separation_y = 0 ;
2613 		    }
2614 		    Moved ((Widget) sbw, (XEvent *) buttonEvent,
2615 			   params, num_params);
2616 		}
2617 
2618 	    return;
2619 	}
2620 
2621     /* ... in the trough (i.e. slider area)... */
2622     else if ((buttonEvent->x >= sbw->scrollBar.slider_area_x)   &&
2623 	     (buttonEvent->y >= sbw->scrollBar.slider_area_y)        &&
2624 	     (buttonEvent->x <= sbw->scrollBar.slider_area_x
2625 	      + sbw->scrollBar.slider_area_width)                 &&
2626 	     (buttonEvent->y <= sbw->scrollBar.slider_area_y
2627 	      + sbw->scrollBar.slider_area_height)) {
2628 
2629 	sbw->scrollBar.arrow1_selected = FALSE;
2630 	sbw->scrollBar.arrow2_selected = FALSE;
2631 	sbw->scrollBar.saved_value = sbw->scrollBar.value;
2632 
2633 	if (buttonEvent->button == Button1) {
2634 	    Position limit_x, limit_y ;
2635 
2636 	    /* Page the slider up or down */
2637 	    /* what is up or down depends on the processing direction... */
2638 
2639 	    limit_x = sbw->scrollBar.slider_x ;
2640 	    limit_y = sbw->scrollBar.slider_y ;
2641 	    if  (sbw->scrollBar.sliding_mode == XmTHERMOMETER) {
2642 		if (PROCESS_DIR_INVERSED(sbw)) {
2643 		    limit_x = sbw->scrollBar.slider_area_width -
2644 			sbw->scrollBar.slider_width ;
2645 		    limit_y = sbw->scrollBar.slider_area_height -
2646 			sbw->scrollBar.slider_height ;
2647 		} else {
2648 		    limit_x = sbw->scrollBar.slider_width ;
2649 		    limit_y = sbw->scrollBar.slider_height ;
2650 		}
2651 	    }
2652 
2653 	    if (sbw->scrollBar.orientation == XmHORIZONTAL) {
2654 		if (buttonEvent->x < limit_x)
2655 		    sbw->scrollBar.change_type = XmCR_PAGE_DECREMENT;
2656 		else
2657 		    sbw->scrollBar.change_type = XmCR_PAGE_INCREMENT;
2658 	    }
2659 	    else
2660 		{
2661 		    if (buttonEvent->y < limit_y)
2662 			sbw->scrollBar.change_type = XmCR_PAGE_DECREMENT;
2663 		    else
2664 			sbw->scrollBar.change_type = XmCR_PAGE_INCREMENT;
2665 		}
2666 	    slider_moved = ChangeScrollBarValue(sbw);
2667 	}
2668 	else  /* Button2 */ {
2669 		/* Warp the slider to the cursor, and then drag */
2670 
2671 		 if  (sbw->scrollBar.sliding_mode != XmTHERMOMETER) {
2672 			if (sbw->scrollBar.orientation == XmHORIZONTAL)
2673 			    sbw->scrollBar.separation_x =
2674 				sbw->scrollBar.slider_width / 2;
2675 			else
2676 			    sbw->scrollBar.separation_y =
2677 				sbw->scrollBar.slider_height / 2;
2678 		    } else {
2679 			sbw->scrollBar.separation_x = 0 ;
2680 			sbw->scrollBar.separation_y = 0 ;
2681 		    }
2682 
2683 		sbw->scrollBar.initial_x = slider_x;
2684 		sbw->scrollBar.initial_y = slider_y;
2685 		sbw->scrollBar.sliding_on = True;
2686 
2687 		Moved ((Widget) sbw, (XEvent *) buttonEvent,
2688 		       params, num_params);
2689 		return;
2690 	    }
2691     }
2692 
2693     /* ... in arrow 1 */
2694     else if ((buttonEvent->x >= sbw->scrollBar.arrow1_x)  &&
2695 	     (buttonEvent->y >= sbw->scrollBar.arrow1_y)       &&
2696 	     (buttonEvent->x <= sbw->scrollBar.arrow1_x
2697 	      + sbw->scrollBar.arrow_width)                 &&
2698 	     (buttonEvent->y <= sbw->scrollBar.arrow1_y
2699 	      + sbw->scrollBar.arrow_height))
2700 	{
2701 	    sbw->scrollBar.change_type = XmCR_DECREMENT;
2702 	    sbw->scrollBar.saved_value = sbw->scrollBar.value;
2703 	    sbw->scrollBar.arrow1_selected = True;
2704 
2705 	    slider_moved = ChangeScrollBarValue(sbw) ;
2706 	    DRAWARROW(sbw, sbw->primitive.bottom_shadow_GC,
2707 		      sbw -> primitive.top_shadow_GC,
2708 		      sbw->scrollBar.arrow1_x,
2709 		      sbw->scrollBar.arrow1_y,
2710 		      sbw->scrollBar.arrow1_orientation);
2711 	}
2712 
2713     /* ... in arrow 2 */
2714     else if ((buttonEvent->x >= sbw->scrollBar.arrow2_x)      &&
2715 	     (buttonEvent->y >= sbw->scrollBar.arrow2_y)           &&
2716 	     (buttonEvent->x <= sbw->scrollBar.arrow2_x
2717 	      + sbw->scrollBar.arrow_width)                     &&
2718 	     (buttonEvent->y <= sbw->scrollBar.arrow2_y
2719 	      + sbw->scrollBar.arrow_height))
2720 	{
2721 	    sbw->scrollBar.change_type = XmCR_INCREMENT;
2722 	    sbw->scrollBar.saved_value = sbw->scrollBar.value;
2723 	    sbw->scrollBar.arrow2_selected = True;
2724 
2725 	    slider_moved = ChangeScrollBarValue(sbw) ;
2726 	    DRAWARROW(sbw, sbw->primitive.bottom_shadow_GC,
2727 		      sbw -> primitive.top_shadow_GC,
2728 		      sbw->scrollBar.arrow2_x,
2729 		      sbw->scrollBar.arrow2_y,
2730 		      sbw->scrollBar.arrow2_orientation);
2731 	}
2732     else
2733 	/* ... in the highlight area.  */
2734 	return;
2735 
2736     if (slider_moved) {
2737 
2738 	ScrollCallback (sbw, sbw->scrollBar.change_type,
2739 			sbw->scrollBar.value, 0, 0, (XEvent *) buttonEvent);
2740 
2741 	XSync (XtDisplay((Widget)sbw), False);
2742 
2743 	sbw->scrollBar.flags |= FIRST_SCROLL_FLAG ;
2744 	sbw->scrollBar.flags &= ~END_TIMER;
2745 
2746 
2747 	if (!sbw->scrollBar.timer)
2748 	    sbw->scrollBar.timer = XtAppAddTimeOut
2749 		(XtWidgetToApplicationContext((Widget) sbw),
2750 		 (unsigned long) sbw->scrollBar.initial_delay,
2751 		 TimerEvent, (XtPointer) sbw);
2752     }
2753 }
2754 
2755 
2756 
2757 
2758 /************************************************************************
2759  *
2760  *  Release
2761  *     This function processes releases occuring on the scrollBar.
2762  *
2763  ************************************************************************/
2764 /*ARGSUSED*/
2765 static void
Release(Widget wid,XEvent * event,String * params,Cardinal * num_params)2766 Release(
2767         Widget wid,
2768         XEvent *event,
2769         String *params,		/* unused */
2770         Cardinal *num_params )	/* unused */
2771 {
2772     XmScrollBarWidget sbw = (XmScrollBarWidget) wid ;
2773 
2774     if (!sbw->scrollBar.editable) return ;
2775 
2776 
2777     /* add an end update when the button is released.
2778        see comment in Select for the start update */
2779 
2780     XmDropSiteEndUpdate(wid);
2781 
2782     sbw->scrollBar.flags &=  ~OPERATION_CANCELLED ;
2783 
2784     if (sbw->scrollBar.flags & KEYBOARD_GRABBED)
2785 	{
2786 	    XtUngrabKeyboard(wid, ((XButtonPressedEvent *)event)->time);
2787 	    sbw->scrollBar.flags &= ~KEYBOARD_GRABBED;
2788 	}
2789 
2790 #ifdef FUNKY_INSENSITIVE_VISUAL
2791     if ( (!(sbw->scrollBar.flags & ARROW1_AVAILABLE)) &&
2792 	(sbw->scrollBar.value > sbw->scrollBar.minimum))
2793 	{
2794 	    XClearArea(XtDisplay(sbw), XtWindow(sbw),
2795 		       sbw->scrollBar.arrow1_x,
2796 		       sbw->scrollBar.arrow1_y,
2797 		       sbw->scrollBar.arrow_width,
2798 		       sbw->scrollBar.arrow_height,
2799 		       FALSE);
2800 
2801 	    DRAWARROW (sbw, sbw -> primitive.top_shadow_GC,
2802 		       sbw->primitive.bottom_shadow_GC,
2803 		       sbw->scrollBar.arrow1_x,
2804 		       sbw->scrollBar.arrow1_y,
2805 		       sbw->scrollBar.arrow1_orientation);
2806 
2807 	    sbw->scrollBar.flags |= ARROW1_AVAILABLE;
2808 	}
2809     else if (sbw->scrollBar.value == sbw->scrollBar.minimum)
2810 	sbw->scrollBar.flags &= ~ARROW1_AVAILABLE;
2811 
2812     if ( (!(sbw->scrollBar.flags & ARROW2_AVAILABLE)) &&
2813 	(sbw->scrollBar.value < (sbw->scrollBar.maximum
2814 				 - sbw->scrollBar.slider_size)))
2815 	{
2816 	    XClearArea(XtDisplay(sbw), XtWindow(sbw),
2817 		       sbw->scrollBar.arrow2_x,
2818 		       sbw->scrollBar.arrow2_y,
2819 		       sbw->scrollBar.arrow_width,
2820 		       sbw->scrollBar.arrow_height,
2821 		       FALSE);
2822 
2823 	    DRAWARROW (sbw, sbw->primitive.top_shadow_GC,
2824 		       sbw -> primitive.bottom_shadow_GC,
2825 		       sbw->scrollBar.arrow2_x,
2826 		       sbw->scrollBar.arrow2_y,
2827 		       sbw->scrollBar.arrow2_orientation);
2828 
2829 	    sbw->scrollBar.flags |= ARROW2_AVAILABLE;
2830 	}
2831     else if (sbw->scrollBar.value == (sbw->scrollBar.maximum
2832 				      - sbw->scrollBar.slider_size))
2833 	sbw->scrollBar.flags &= ~ARROW2_AVAILABLE;
2834 #endif
2835     if (sbw->scrollBar.arrow1_selected)
2836 	{
2837 	    sbw->scrollBar.arrow1_selected = False;
2838 
2839 	    DRAWARROW (sbw, sbw -> primitive.top_shadow_GC,
2840 		       sbw->primitive.bottom_shadow_GC,
2841 		       sbw->scrollBar.arrow1_x,
2842 		       sbw->scrollBar.arrow1_y,
2843 		       sbw->scrollBar.arrow1_orientation);
2844 	}
2845 
2846     if (sbw->scrollBar.arrow2_selected)
2847 	{
2848 	    sbw->scrollBar.arrow2_selected = False;
2849 
2850 	    DRAWARROW (sbw, sbw->primitive.top_shadow_GC,
2851 		       sbw -> primitive.bottom_shadow_GC,
2852 		       sbw->scrollBar.arrow2_x,
2853 		       sbw->scrollBar.arrow2_y,
2854 		       sbw->scrollBar.arrow2_orientation);
2855 	}
2856 
2857     if (! (sbw->scrollBar.flags & SLIDER_AVAILABLE))
2858         return;
2859 
2860     if (sbw->scrollBar.timer != 0)
2861 	{
2862 	    sbw->scrollBar.flags |= END_TIMER;
2863 	}
2864 
2865     if (sbw->scrollBar.sliding_on == True)
2866 	{
2867 	    sbw->scrollBar.sliding_on = False;
2868 	    ScrollCallback (sbw, XmCR_VALUE_CHANGED, sbw->scrollBar.value,
2869 			    event->xbutton.x, event->xbutton.y, event);
2870 	}
2871 
2872 #ifdef FUNKY_INSENSITIVE_VISUAL
2873     XSetClipMask(XtDisplay(sbw), sbw->scrollBar.unavailable_GC, None);
2874     if (! (sbw->scrollBar.flags & ARROW1_AVAILABLE))
2875 	{
2876 	    XFillRectangle(XtDisplay(sbw), XtWindow(sbw),
2877 			   sbw->scrollBar.unavailable_GC,
2878 			   sbw->scrollBar.arrow1_x,
2879 			   sbw->scrollBar.arrow1_y,
2880 			   sbw->scrollBar.arrow_width,
2881 			   sbw->scrollBar.arrow_height);
2882 	}
2883     else if (! (sbw->scrollBar.flags & ARROW2_AVAILABLE))
2884 	{
2885 	    XFillRectangle(XtDisplay(sbw), XtWindow(sbw),
2886 			   sbw->scrollBar.unavailable_GC,
2887 			   sbw->scrollBar.arrow2_x,
2888 			   sbw->scrollBar.arrow2_y,
2889 			   sbw->scrollBar.arrow_width,
2890 			   sbw->scrollBar.arrow_height);
2891 	}
2892 #endif
2893 }
2894 
2895 
2896 
2897 
2898 /************************************************************************
2899  *
2900  *  Moved
2901  *     This function processes mouse moved events during interactive
2902  *     slider moves.
2903  *
2904  ************************************************************************/
2905 /*ARGSUSED*/
2906 static void
Moved(Widget wid,XEvent * event,String * params,Cardinal * num_params)2907 Moved(
2908         Widget wid,
2909         XEvent *event,
2910         String *params,		/* unused */
2911         Cardinal *num_params )	/* unused */
2912 {
2913     XmScrollBarWidget sbw = (XmScrollBarWidget) wid ;
2914     XButtonPressedEvent * buttonEvent = (XButtonPressedEvent *) event;
2915     int newX, newY;
2916     int realX, realY;
2917     int slideVal;
2918     int button_x;
2919     int button_y;
2920     int real_width_limit =
2921 	(sbw->scrollBar.snap_back_multiple +
2922 	 (buttonEvent->x > 0)) * XtWidth(wid);
2923     int real_height_limit =
2924 	(sbw->scrollBar.snap_back_multiple +
2925 	 (buttonEvent->y > 0)) * XtHeight(wid) ;
2926 
2927     if (!sbw->scrollBar.editable) return ;
2928 
2929     if (! (sbw->scrollBar.flags & SLIDER_AVAILABLE)) return;
2930 
2931     /* operation was cancelled, so don't restart the move
2932        as it could happen with the snapBack stuff */
2933     if (sbw->scrollBar.flags & OPERATION_CANCELLED) return;
2934 
2935     if (!sbw->scrollBar.sliding_on) return;
2936 
2937     /* Only deal with snap_back if operation was started by a
2938        click in the slider. */
2939     if (((sbw->scrollBar.orientation == XmVERTICAL) &&
2940 	 ((buttonEvent->x > real_width_limit) ||
2941 	  (-buttonEvent->x > real_width_limit))) ||
2942 	((sbw->scrollBar.orientation == XmHORIZONTAL) &&
2943 	 ((buttonEvent->y > real_height_limit) ||
2944 	  (-buttonEvent->y > real_height_limit)))) {
2945 	/* going out of the snap back area */
2946 
2947 	if (!(sbw->scrollBar.add_flags & SNAPPED_OUT)) {
2948 	    short savedX, savedY, j1, j2;
2949 
2950 	    /* get the saved value, also used by the Cancel action */
2951 	    sbw->scrollBar.value = sbw->scrollBar.saved_value;
2952 	    CalcSliderRect(sbw, &savedX, &savedY, &j1, &j2);
2953 	    MoveSlider(sbw, savedX, savedY);
2954 	    if (sbw->scrollBar.sliding_mode == XmTHERMOMETER)
2955 		    RedrawSliderWindow (sbw);
2956 	    ScrollCallback (sbw, XmCR_VALUE_CHANGED,
2957 			    sbw->scrollBar.value, savedX, savedY,
2958 			    (XEvent *) buttonEvent);
2959 
2960 	    sbw->scrollBar.add_flags |= SNAPPED_OUT ;
2961 	}
2962 	return ;
2963     } else {
2964 	/* moving in the snap back area */
2965 	sbw->scrollBar.add_flags &= ~SNAPPED_OUT ; ;
2966     }
2967 
2968     button_x = buttonEvent->x;
2969     button_y = buttonEvent->y;
2970 
2971     /*
2972      * Force button_x and button_y to be within the slider_area.
2973      */
2974     if (button_x < sbw->scrollBar.slider_area_x)
2975 	button_x = sbw->scrollBar.slider_area_x;
2976 
2977     if (button_x >
2978 	sbw->scrollBar.slider_area_x + sbw->scrollBar.slider_area_width)
2979 	button_x = sbw->scrollBar.slider_area_x
2980 	    + sbw->scrollBar.slider_area_width;
2981 
2982     if (button_y < sbw->scrollBar.slider_area_y)
2983 	button_y = sbw->scrollBar.slider_area_y;
2984 
2985     if (button_y >
2986 	sbw->scrollBar.slider_area_y
2987 	+ sbw->scrollBar.slider_area_height)
2988 	button_y = sbw->scrollBar.slider_area_y
2989 	    + sbw->scrollBar.slider_area_height;
2990 
2991 
2992     /*
2993      * Calculate the new origin of the slider.
2994      * Bound the values with the slider area.
2995      */
2996     if (sbw->scrollBar.orientation == XmHORIZONTAL)
2997 	{
2998 	    newX = realX = button_x - sbw->scrollBar.separation_x;
2999 	    newY = realY = sbw->scrollBar.slider_y;
3000 
3001 	    if (newX < sbw->scrollBar.slider_area_x)
3002 		newX = sbw->scrollBar.slider_area_x;
3003 
3004 	    if ((newX + sbw->scrollBar.slider_width >
3005 		sbw->scrollBar.slider_area_x
3006 		+ sbw->scrollBar.slider_area_width) &&
3007 		    (sbw->scrollBar.sliding_mode != XmTHERMOMETER))
3008 		newX = sbw->scrollBar.slider_area_x
3009 		    + sbw->scrollBar.slider_area_width
3010 			- sbw->scrollBar.slider_width;
3011 	}
3012     else
3013 	{
3014 	    newX = realX = sbw->scrollBar.slider_x;
3015 	    newY = realY = button_y - sbw->scrollBar.separation_y;
3016 
3017 
3018 	    if (newY < sbw->scrollBar.slider_area_y)
3019 		newY = sbw->scrollBar.slider_area_y;
3020 
3021 	    if ((newY + sbw->scrollBar.slider_height >
3022 		sbw->scrollBar.slider_area_y
3023 		+ sbw->scrollBar.slider_area_height) &&
3024 		    (sbw->scrollBar.sliding_mode != XmTHERMOMETER))
3025 		newY = sbw->scrollBar.slider_area_y
3026 		    + sbw->scrollBar.slider_area_height
3027 			- sbw->scrollBar.slider_height;
3028 	}
3029 
3030 
3031     if (((sbw->scrollBar.orientation == XmHORIZONTAL) &&
3032 	 (realX != sbw->scrollBar.initial_x))
3033 	||
3034 	((sbw->scrollBar.orientation == XmVERTICAL)   &&
3035 	 (realY != sbw->scrollBar.initial_y)))
3036 	{
3037 	    slideVal = CalcSliderVal (sbw, button_x, button_y);
3038 
3039 	    if ((newX != sbw->scrollBar.initial_x) ||
3040 		(newY != sbw->scrollBar.initial_y))
3041 		{
3042 		    MoveSlider (sbw, newX, newY);
3043 		    sbw->scrollBar.initial_x = newX;
3044 		    sbw->scrollBar.initial_y = newY;
3045 		}
3046 
3047 	    if (slideVal != sbw->scrollBar.value)
3048 		{
3049 		    sbw->scrollBar.value = slideVal;
3050 
3051 		    if (slideVal >= (sbw->scrollBar.maximum
3052 				     - sbw->scrollBar.slider_size))
3053 			slideVal = sbw->scrollBar.maximum
3054 			    - sbw->scrollBar.slider_size;
3055 
3056 		    if (slideVal <= sbw->scrollBar.minimum)
3057 			slideVal = sbw->scrollBar.minimum;
3058 		    if (sbw->scrollBar.sliding_mode == XmTHERMOMETER)
3059 			RedrawSliderWindow (sbw);
3060 		    ScrollCallback(sbw, XmCR_DRAG,
3061 				   sbw->scrollBar.value = slideVal,
3062 				   buttonEvent->x, buttonEvent->y,
3063 				   (XEvent *) buttonEvent);
3064 		}
3065 	}
3066 }
3067 
3068 
3069 
3070 
3071 /*********************************************************************
3072  *
3073  *  TopOrBottom
3074  *	Issue the to top or bottom callbacks.
3075  *
3076  *********************************************************************/
3077 /*ARGSUSED*/
3078 static void
TopOrBottom(Widget wid,XEvent * event,String * params,Cardinal * num_params)3079 TopOrBottom(
3080         Widget wid,
3081         XEvent *event,
3082         String *params,		/* unused */
3083         Cardinal *num_params )	/* unused */
3084 {
3085     XmScrollBarWidget sbw = (XmScrollBarWidget) wid ;
3086     XmScrollBarPart *sbp = (XmScrollBarPart *) &(sbw->scrollBar);
3087 
3088     if (!sbw->scrollBar.editable) return ;
3089 
3090     sbw->scrollBar.flags &=  ~OPERATION_CANCELLED ;
3091 
3092     if (! (sbw->scrollBar.flags & SLIDER_AVAILABLE))
3093 	return;
3094 
3095     if (event->type == KeyPress) {
3096 	Modifiers junk;
3097 	KeySym key_sym;
3098 	XKeyPressedEvent *keyEvent = (XKeyPressedEvent *) event;
3099 
3100 	key_sym = XtGetActionKeysym(event, &junk);
3101 
3102 	if (key_sym == osfXK_BeginLine) {
3103 	    if (sbp->orientation == XmVERTICAL) {
3104 		if (sbp->processing_direction == XmMAX_ON_BOTTOM)
3105 		    MoveSlider(sbw, sbp->slider_x, sbp->slider_area_y);
3106 		else
3107 		    MoveSlider(sbw,
3108 			       sbp->slider_x,
3109 			       sbp->slider_area_y + sbp->slider_area_height
3110 			       - sbp->slider_height);
3111 	    } else {
3112 		if (sbp->processing_direction == XmMAX_ON_RIGHT)
3113 		    MoveSlider(sbw, sbp->slider_area_x, sbp->slider_y);
3114 		else
3115 		    MoveSlider(sbw,
3116 			       sbp->slider_area_x + sbp->slider_area_width
3117 			       - sbp->slider_width,
3118 			       sbp->slider_y);
3119 	    }
3120 	    /*
3121 	     * The following grevious bogosity is due to the fact
3122 	     * that the key behavior was implemented long after
3123 	     * the rest of this code, and so we have to work around
3124 	     * currently operating nonsense.
3125 	     *
3126 	     * Specifically, since the dawn of time, ScrollBar
3127 	     * processes in just one direction, and does any necessary
3128 	     * reversal just before calling the callback.
3129 	     *
3130 	     * We now proceed to trick that code into doing the right
3131 	     * thing anyway
3132 	     */
3133 	    if (!PROCESS_DIR_INVERSED(sbw)) {
3134 		sbp->value = sbp->minimum;
3135 		if (sbp->sliding_mode == XmTHERMOMETER)
3136 		    RedrawSliderWindow (sbw);
3137 		ScrollCallback(sbw, XmCR_TO_TOP, sbp->value,
3138 			       keyEvent->x, keyEvent->y,
3139 			       (XEvent *) keyEvent);
3140 	    } else {
3141 		sbp->value = sbp->maximum - sbp->slider_size;
3142 		if (sbp->sliding_mode == XmTHERMOMETER)
3143 		    RedrawSliderWindow (sbw);
3144 		ScrollCallback(sbw, XmCR_TO_BOTTOM, sbp->value,
3145 			       keyEvent->x, keyEvent->y,
3146 			       (XEvent *) keyEvent);
3147 	    }
3148 	}
3149 	else /* key_sym == osfXK_EndLine */ {
3150 	    if (sbp->orientation == XmVERTICAL) {
3151 		if (sbp->processing_direction == XmMAX_ON_BOTTOM)
3152 		    MoveSlider(sbw,
3153 			       sbp->slider_x,
3154 			       sbp->slider_area_y + sbp->slider_area_height
3155 			       - sbp->slider_height);
3156 		else
3157 		    MoveSlider(sbw, sbp->slider_x, sbp->slider_area_y);
3158 	    } else {
3159 		if (sbp->processing_direction == XmMAX_ON_RIGHT)
3160 		    MoveSlider(sbw,
3161 			       sbp->slider_area_x + sbp->slider_area_width
3162 			       - sbp->slider_width,
3163 			       sbp->slider_y);
3164 		else
3165 		    MoveSlider(sbw, sbp->slider_area_x, sbp->slider_y);
3166 	    }
3167 
3168 	    /* See above for explanation of this nonsense */
3169 	    if (!PROCESS_DIR_INVERSED(sbw)) {
3170 		sbp->value = sbp->maximum - sbp->slider_size;
3171 		if (sbp->sliding_mode == XmTHERMOMETER)
3172 		    RedrawSliderWindow (sbw);
3173 		ScrollCallback(sbw, XmCR_TO_BOTTOM, sbp->value,
3174 			       keyEvent->x, keyEvent->y,
3175 			       (XEvent *) keyEvent);
3176 	    } else {
3177 		sbp->value = sbp->minimum;
3178 		if (sbp->sliding_mode == XmTHERMOMETER)
3179 		    RedrawSliderWindow (sbw);
3180 		ScrollCallback (sbw, XmCR_TO_TOP, sbp->value,
3181 				keyEvent->x, keyEvent->y,
3182 				(XEvent *) keyEvent);
3183 	    }
3184 	}
3185     } else  /* event->type == ButtonPress */ {
3186 	XButtonPressedEvent *buttonEvent =
3187 	    (XButtonPressedEvent *) event;
3188 
3189 	XmDropSiteStartUpdate(wid);
3190 
3191 	if /* In arrow1... */
3192 	    ((buttonEvent->x >= sbp->arrow1_x)                   &&
3193 	     (buttonEvent->y >= sbp->arrow1_y)                    &&
3194 	     (buttonEvent->x <= sbp->arrow1_x + sbp->arrow_width) &&
3195 	     (buttonEvent->y <= sbp->arrow1_y + sbp->arrow_height)) {
3196 		sbp->change_type = XmCR_DECREMENT;
3197 		sbp->arrow1_selected = True;
3198 
3199 		DRAWARROW(sbw, sbw->primitive.bottom_shadow_GC,
3200 			  sbw -> primitive.top_shadow_GC,
3201 			  sbw->scrollBar.arrow1_x,
3202 			  sbw->scrollBar.arrow1_y,
3203 			  sbw->scrollBar.arrow1_orientation);
3204 
3205 		if (sbp->orientation == XmVERTICAL)
3206 		    MoveSlider(sbw, sbp->slider_x, sbp->slider_area_y);
3207 		else
3208 		    MoveSlider(sbw, sbp->slider_area_x, sbp->slider_y);
3209 
3210 		sbp->value = sbp->minimum;
3211 		if (sbp->sliding_mode == XmTHERMOMETER)
3212 		    RedrawSliderWindow (sbw);
3213 		ScrollCallback (sbw, XmCR_TO_TOP, sbp->value,
3214 				buttonEvent->x, buttonEvent->y,
3215 				(XEvent *) buttonEvent);
3216 	    }
3217 
3218 	else if /* In arrow2... */
3219 	    ((buttonEvent->x >= sbp->arrow2_x)  &&
3220 	     (buttonEvent->y >= sbp->arrow2_y)   &&
3221 	     (buttonEvent->x <= sbp->arrow2_x
3222 	      + sbp->arrow_width)             &&
3223 	     (buttonEvent->y <= sbp->arrow2_y
3224 	      + sbp->arrow_height))
3225 		{
3226 		    sbp->change_type = XmCR_INCREMENT;
3227 		    sbp->arrow2_selected = True;
3228 
3229 		    DRAWARROW (sbw, sbw->primitive.bottom_shadow_GC,
3230 			       sbw -> primitive.top_shadow_GC,
3231 			       sbw->scrollBar.arrow2_x,
3232 			       sbw->scrollBar.arrow2_y,
3233 			       sbw->scrollBar.arrow2_orientation);
3234 		    if (sbp->orientation == XmVERTICAL)
3235 			MoveSlider(sbw,
3236 				   sbp->slider_x,
3237 				   sbp->slider_area_y + sbp->slider_area_height
3238 				   - sbp->slider_height);
3239 		    else
3240 			MoveSlider(sbw,
3241 				   sbp->slider_area_x + sbp->slider_area_width
3242 				   - sbp->slider_width,
3243 				   sbp->slider_y);
3244 		    sbp->value = sbp->maximum - sbp->slider_size;
3245 		    if (sbp->sliding_mode == XmTHERMOMETER)
3246 			RedrawSliderWindow (sbw);
3247 		    ScrollCallback (sbw, XmCR_TO_BOTTOM,
3248 				    sbp->value, buttonEvent->x, buttonEvent->y,
3249 				    (XEvent *) buttonEvent);
3250 		}
3251 	else if /* in the trough between arrow2 and the slider... */
3252 	    (((sbp->sliding_mode != XmTHERMOMETER) &&
3253 	      (((sbp->orientation == XmHORIZONTAL)       &&
3254 	      (buttonEvent->x >= sbp->slider_area_x) &&
3255 	      (buttonEvent->x < sbp->slider_x)       &&
3256 	      (buttonEvent->y >= sbp->slider_area_y) &&
3257 	      (buttonEvent->y <= sbp->slider_area_y
3258 	       + sbp->slider_area_height))
3259 	     ||
3260 	     ((sbp->orientation == XmVERTICAL) &&
3261 	      (buttonEvent->y >= sbp->slider_area_y)  &&
3262 	      (buttonEvent->y < sbp->slider_y)        &&
3263 	      (buttonEvent->x >= sbp->slider_area_x)  &&
3264 	      (buttonEvent->x < sbp->slider_area_x
3265 	       + sbp->slider_area_width)))) ||
3266 	     /* only partial treatment, processing direction
3267 		has to be handled here */
3268 	     ((sbp->sliding_mode == XmTHERMOMETER) &&
3269 	      (((sbp->orientation == XmHORIZONTAL)       &&
3270 	      (buttonEvent->x >= sbp->slider_area_x) &&
3271 	      (buttonEvent->x < sbp->slider_width)       &&
3272 	      (buttonEvent->y >= sbp->slider_area_y) &&
3273 	      (buttonEvent->y <= sbp->slider_area_y
3274 	       + sbp->slider_area_height))
3275 	     ||
3276 	     ((sbp->orientation == XmVERTICAL) &&
3277 	      (buttonEvent->y < sbp->slider_area_height
3278 	       - sbp->slider_height) &&
3279 	      (buttonEvent->x >= sbp->slider_area_x)  &&
3280 	      (buttonEvent->x < sbp->slider_area_x
3281 	       + sbp->slider_area_width)))))
3282 		{
3283 		    if (sbp->orientation == XmVERTICAL)
3284 			MoveSlider(sbw, sbp->slider_x, sbp->slider_area_y);
3285 		    else
3286 			MoveSlider(sbw, sbp->slider_area_x, sbp->slider_y);
3287 		    sbp->value = sbp->minimum;
3288 		    if (sbp->sliding_mode == XmTHERMOMETER)
3289 			RedrawSliderWindow (sbw);
3290 		    ScrollCallback (sbw, XmCR_TO_TOP, sbp->value,
3291 				    buttonEvent->x, buttonEvent->y,
3292 				    (XEvent *) buttonEvent);
3293 		}
3294 	else if
3295 		/* in the trough between arrow1 and the slider... */
3296 	    (((sbp->orientation == XmHORIZONTAL)                     &&
3297 	      (buttonEvent->x > sbp->slider_x + sbp->slider_width) &&
3298 	      (buttonEvent->x <= sbp->slider_area_x
3299 	       + sbp->slider_area_width)                        &&
3300 	      (buttonEvent->y >= sbp->slider_area_y)               &&
3301 	      (buttonEvent->y <= sbp->slider_area_y
3302 	       + sbp->slider_area_height))
3303 	     ||
3304 	     ((sbp->orientation == XmVERTICAL)           &&
3305 	      (buttonEvent->y > sbp->slider_y
3306 	       + sbp->slider_height)               &&
3307 	      (buttonEvent->y <= sbp->slider_area_y
3308 	       + sbp->slider_area_height)          &&
3309 	      (buttonEvent->x >= sbp->slider_area_x)  &&
3310 	      (buttonEvent->x <= sbp->slider_area_x
3311 	       + sbp->slider_area_width))
3312 	     || (sbp->sliding_mode == XmTHERMOMETER)) {
3313 		if (sbp->orientation == XmVERTICAL)
3314 		    MoveSlider(sbw,
3315 			       sbp->slider_x,
3316 			       sbp->slider_area_y + sbp->slider_area_height
3317 			       - sbp->slider_height);
3318 		else
3319 		    MoveSlider(sbw,
3320 			       sbp->slider_area_x + sbp->slider_area_width
3321 			       - sbp->slider_width,
3322 			       sbp->slider_y);
3323 		sbp->value = sbp->maximum - sbp->slider_size;
3324 		if (sbp->sliding_mode == XmTHERMOMETER)
3325 			RedrawSliderWindow (sbw);
3326 		ScrollCallback (sbw, XmCR_TO_BOTTOM,
3327 				sbp->value, buttonEvent->x, buttonEvent->y,
3328 				(XEvent *) buttonEvent);
3329 	    }
3330 
3331     }
3332 #ifdef FUNKY_INSENSITIVE_VISUAL
3333     XSetClipMask(XtDisplay(sbw), sbw->scrollBar.unavailable_GC, None);
3334     if (sbp->value == sbp->minimum) {
3335 	XFillRectangle(XtDisplay(sbw), XtWindow(sbw),
3336 		       sbw->scrollBar.unavailable_GC,
3337 		       sbw->scrollBar.arrow1_x,
3338 		       sbw->scrollBar.arrow1_y,
3339 		       sbw->scrollBar.arrow_width,
3340 		       sbw->scrollBar.arrow_height);
3341 
3342 	sbw->scrollBar.flags &= ~ARROW1_AVAILABLE;
3343 
3344 	if (! (sbw->scrollBar.flags & ARROW2_AVAILABLE)) {
3345 	    XClearArea(XtDisplay(sbw), XtWindow(sbw),
3346 		       sbw->scrollBar.arrow2_x,
3347 		       sbw->scrollBar.arrow2_y,
3348 		       sbw->scrollBar.arrow_width,
3349 		       sbw->scrollBar.arrow_height,
3350 		       FALSE);
3351 
3352 	    DRAWARROW (sbw, sbw -> primitive.top_shadow_GC,
3353 		       sbw->primitive.bottom_shadow_GC,
3354 		       sbw->scrollBar.arrow2_x,
3355 		       sbw->scrollBar.arrow2_y,
3356 		       sbw->scrollBar.arrow2_orientation);
3357 
3358 	    sbw->scrollBar.flags |= ARROW2_AVAILABLE;
3359 	}
3360     }
3361     else /* sbp->value == (sbp->maximum - sbp->slider_size) */
3362 	{
3363 	    /*		XFillRectangle(XtDisplay(sbw), XtWindow(sbw),
3364 			sbw->scrollBar.unavailable_GC,
3365 			sbw->scrollBar.arrow2_x,
3366 			sbw->scrollBar.arrow2_y,
3367 			sbw->scrollBar.arrow_width,
3368 			sbw->scrollBar.arrow_height);
3369 			*/
3370 	    sbw->scrollBar.flags &= ~ARROW2_AVAILABLE;
3371 
3372 	    if (! (sbw->scrollBar.flags & ARROW1_AVAILABLE)) {
3373 		XClearArea(XtDisplay(sbw), XtWindow(sbw),
3374 			   sbw->scrollBar.arrow1_x,
3375 			   sbw->scrollBar.arrow1_y,
3376 			   sbw->scrollBar.arrow_width,
3377 			   sbw->scrollBar.arrow_height,
3378 			   FALSE);
3379 
3380 		DRAWARROW (sbw, sbw -> primitive.top_shadow_GC,
3381 			   sbw->primitive.bottom_shadow_GC,
3382 			   sbw->scrollBar.arrow1_x,
3383 			   sbw->scrollBar.arrow1_y,
3384 			   sbw->scrollBar.arrow1_orientation);
3385 
3386 		sbw->scrollBar.flags |= ARROW1_AVAILABLE;
3387 	    }
3388 	}
3389 #endif
3390 }
3391 
3392 
3393 
3394 
3395 /*********************************************************************
3396  *
3397  *  IncrementUpOrLeft
3398  *	The up or left key was pressed, decrease the value by
3399  *	one increment.
3400  *
3401  *********************************************************************/
3402 /*ARGSUSED*/
3403 static void
IncrementUpOrLeft(Widget wid,XEvent * event,String * params,Cardinal * num_params)3404 IncrementUpOrLeft(
3405         Widget wid,
3406         XEvent *event,
3407         String *params,
3408         Cardinal *num_params )
3409 {
3410         XmScrollBarWidget sbw = (XmScrollBarWidget) wid ;
3411 
3412 	int new_value;
3413 	int key_pressed;
3414 
3415 	if (!num_params || (*num_params != 1) || !params)
3416 	{
3417 	    XmeWarning(wid, MESSAGE14);
3418 	    return;
3419 	}
3420 
3421 	if (!sbw->scrollBar.editable) return ;
3422 
3423 
3424 	sbw->scrollBar.flags &=  ~OPERATION_CANCELLED ;
3425 
3426 	if (! (sbw->scrollBar.flags & SLIDER_AVAILABLE))
3427 		return;
3428 
3429 	/*
3430  	 * arg value passed in will either be "up" for the up key or
3431 	 * "left" for the left arrow key (or for compatibility 0 -> up
3432 	 * key or 1 -> left key. The key needs to be compared with the
3433 	 * scrollbar orientation to ensure only the proper directional key
3434 	 * presses work.
3435 	 */
3436 
3437 	if (_XmConvertActionParamToRepTypeId((Widget) sbw,
3438 		     XmRID_SCROLL_BAR_INCREMENT_UP_OR_LEFT_ACTION_PARAMS,
3439 		     params[0], True, &key_pressed) == False)
3440 	{
3441 	    /* We couldn't convert the value. Just assume a value of 0. */
3442 	    key_pressed = 0;
3443 	}
3444 
3445 	if (((key_pressed == 0) &&
3446 		(sbw->scrollBar.orientation == XmHORIZONTAL))
3447 		||
3448 		((key_pressed == 1) &&
3449 		(sbw->scrollBar.orientation == XmVERTICAL)))
3450 		return;
3451 
3452 	new_value = sbw->scrollBar.value - sbw->scrollBar.increment;
3453 
3454 	if (new_value < sbw->scrollBar.minimum)
3455 		new_value = sbw->scrollBar.minimum;
3456 
3457 	if (new_value != sbw->scrollBar.value)
3458 	{
3459 		sbw->scrollBar.value = new_value;
3460 #ifdef FUNKY_INSENSITIVE_VISUAL
3461 		if ((sbw->scrollBar.value = new_value)
3462 			== sbw->scrollBar.minimum)
3463 		{
3464 		        XSetClipMask(XtDisplay(sbw),
3465 				     sbw->scrollBar.unavailable_GC, None);
3466 			XFillRectangle(XtDisplay(sbw), XtWindow(sbw),
3467 				sbw->scrollBar.unavailable_GC,
3468 				sbw->scrollBar.arrow1_x,
3469 				sbw->scrollBar.arrow1_y,
3470 				sbw->scrollBar.arrow_width,
3471 				sbw->scrollBar.arrow_height);
3472 
3473             sbw->scrollBar.flags &= ~ARROW1_AVAILABLE;
3474 		}
3475 #endif
3476 		if ((sbw->scrollBar.show_arrows) &&
3477 		    (! (sbw->scrollBar.flags & ARROW2_AVAILABLE)))
3478 		{
3479 			XClearArea(XtDisplay(sbw), XtWindow(sbw),
3480 				sbw->scrollBar.arrow2_x,
3481 				sbw->scrollBar.arrow2_y,
3482 				sbw->scrollBar.arrow_width,
3483 				sbw->scrollBar.arrow_height,
3484 				FALSE);
3485 
3486 			DRAWARROW (sbw, sbw -> primitive.top_shadow_GC,
3487 				sbw->primitive.bottom_shadow_GC,
3488 				sbw->scrollBar.arrow2_x,
3489 				sbw->scrollBar.arrow2_y,
3490 				sbw->scrollBar.arrow2_orientation);
3491 
3492 			sbw->scrollBar.flags |= ARROW2_AVAILABLE;
3493 		}
3494 
3495 		RedrawSliderWindow (sbw);
3496 
3497 		ScrollCallback (sbw, XmCR_DECREMENT, sbw->scrollBar.value,
3498                         event->xbutton.x, event->xbutton.y, event);
3499 	}
3500 }
3501 
3502 
3503 
3504 
3505 /*********************************************************************
3506  *
3507  *  IncrementDownOrRight
3508  *	The down or right key was pressed, increase the value by
3509  *	one increment.
3510  *
3511  *********************************************************************/
3512 /*ARGSUSED*/
3513 static void
IncrementDownOrRight(Widget wid,XEvent * event,String * params,Cardinal * num_params)3514 IncrementDownOrRight(
3515         Widget wid,
3516         XEvent *event,
3517         String *params,
3518         Cardinal *num_params )
3519 {
3520         XmScrollBarWidget sbw = (XmScrollBarWidget) wid ;
3521 	int new_value;
3522 	int key_pressed;
3523 
3524 	if (!num_params || (*num_params != 1) || !params)
3525 	{
3526 	    XmeWarning(wid, MESSAGE14);
3527 	    return;
3528 	}
3529 
3530 	if (!sbw->scrollBar.editable) return ;
3531 
3532 	sbw->scrollBar.flags &=  ~OPERATION_CANCELLED ;
3533 
3534 	if (! (sbw->scrollBar.flags & SLIDER_AVAILABLE))
3535 		return;
3536 
3537 	/*
3538  	 * arg value passed in will either be "down" for the down key or
3539 	 * "right" for the right arrow key (or for compatibility 0 -> down
3540 	 * key or 1 -> right key. The key needs to be compared with the
3541 	 * scrollbar orientation to ensure only the proper directional key
3542 	 * presses work.
3543 	 */
3544 
3545 	if (_XmConvertActionParamToRepTypeId((Widget) sbw,
3546 		     XmRID_SCROLL_BAR_INCREMENT_DOWN_OR_RIGHT_ACTION_PARAMS,
3547 		     params[0], True, &key_pressed) == False)
3548 	{
3549 	    /* We couldn't convert the value. Just assume a value of 0. */
3550 	    key_pressed = 0;
3551 	}
3552 
3553 	if (((key_pressed == 0) &&
3554 		(sbw->scrollBar.orientation == XmHORIZONTAL))
3555 		||
3556 		((key_pressed == 1) &&
3557 		(sbw->scrollBar.orientation == XmVERTICAL)))
3558 		return;
3559 
3560 	new_value = sbw->scrollBar.value + sbw->scrollBar.increment;
3561 
3562 	if (new_value > sbw->scrollBar.maximum - sbw->scrollBar.slider_size)
3563 		new_value = sbw->scrollBar.maximum - sbw->scrollBar.slider_size;
3564 
3565 	if (new_value != sbw->scrollBar.value)
3566 	{
3567 		sbw->scrollBar.value = new_value;
3568 #ifdef FUNKY_INSENSITIVE_VISUAL
3569 		if ((sbw->scrollBar.value = new_value)
3570 			== (sbw->scrollBar.maximum - sbw->scrollBar.slider_size))
3571 		{
3572 		        XSetClipMask(XtDisplay(sbw),
3573 				     sbw->scrollBar.unavailable_GC, None);
3574 			XFillRectangle(XtDisplay(sbw), XtWindow(sbw),
3575 				sbw->scrollBar.unavailable_GC,
3576 				sbw->scrollBar.arrow2_x,
3577 				sbw->scrollBar.arrow2_y,
3578 				sbw->scrollBar.arrow_width,
3579 				sbw->scrollBar.arrow_height);
3580 
3581             sbw->scrollBar.flags &= ~ARROW2_AVAILABLE;
3582 		}
3583 #endif
3584 		if ((sbw->scrollBar.show_arrows) &&
3585 		    (! (sbw->scrollBar.flags & ARROW1_AVAILABLE)))
3586 
3587 		{
3588 			XClearArea(XtDisplay(sbw), XtWindow(sbw),
3589 				sbw->scrollBar.arrow1_x,
3590 				sbw->scrollBar.arrow1_y,
3591 				sbw->scrollBar.arrow_width,
3592 				sbw->scrollBar.arrow_height,
3593 				FALSE);
3594 
3595 			DRAWARROW (sbw, sbw -> primitive.top_shadow_GC,
3596 				sbw->primitive.bottom_shadow_GC,
3597 				sbw->scrollBar.arrow1_x,
3598 				sbw->scrollBar.arrow1_y,
3599 				sbw->scrollBar.arrow1_orientation);
3600 
3601 			sbw->scrollBar.flags |= ARROW1_AVAILABLE;
3602 		}
3603 
3604 		RedrawSliderWindow (sbw);
3605 
3606 		ScrollCallback (sbw, XmCR_INCREMENT, sbw->scrollBar.value,
3607                                     event->xbutton.x, event->xbutton.y, event);
3608 	}
3609 }
3610 
3611 
3612 
3613 
3614 /*********************************************************************
3615  *
3616  *  PageUpOrLeft
3617  *	The up or left key was pressed, decrease the value by
3618  *	one increment.
3619  *
3620  *********************************************************************/
3621 /*ARGSUSED*/
3622 static void
PageUpOrLeft(Widget wid,XEvent * event,String * params,Cardinal * num_params)3623 PageUpOrLeft(
3624         Widget wid,
3625         XEvent *event,
3626         String *params,
3627         Cardinal *num_params )
3628 {
3629         XmScrollBarWidget sbw = (XmScrollBarWidget) wid ;
3630 	int new_value;
3631 	int key_pressed;
3632 
3633 	if (!num_params || (*num_params != 1) || !params)
3634 	{
3635 	    XmeWarning(wid, MESSAGE14);
3636 	    return;
3637 	}
3638 
3639 	if (!sbw->scrollBar.editable) return ;
3640 
3641 	sbw->scrollBar.flags &=  ~OPERATION_CANCELLED ;
3642 
3643 	if (! (sbw->scrollBar.flags & SLIDER_AVAILABLE))
3644 		return;
3645 	/*
3646  	 * arg value passed in will either be "up" for the up key or
3647 	 * "left" for the left arrow key (or for compatibility 0 -> up
3648 	 * key or 1 -> left key. The key needs to be compared with the
3649 	 * scrollbar orientation to ensure only the proper directional key
3650 	 * presses work.
3651 	 */
3652 
3653 	if (_XmConvertActionParamToRepTypeId((Widget) sbw,
3654 		     XmRID_SCROLL_BAR_PAGE_UP_OR_LEFT_ACTION_PARAMS,
3655 		     params[0], True, &key_pressed) == False)
3656 	{
3657 	    /* We couldn't convert the value. Just assume a value of 0. */
3658 	    key_pressed = 0;
3659 	}
3660 
3661 	if (((key_pressed == 0) &&
3662 		(sbw->scrollBar.orientation == XmHORIZONTAL))
3663 		||
3664 		((key_pressed == 1) &&
3665 		(sbw->scrollBar.orientation == XmVERTICAL)))
3666 		return;
3667 
3668 	new_value = sbw->scrollBar.value - sbw->scrollBar.page_increment;
3669 
3670 	if (new_value < sbw->scrollBar.minimum)
3671 		new_value = sbw->scrollBar.minimum;
3672 
3673 	if (new_value != sbw->scrollBar.value)
3674 	{
3675 		sbw->scrollBar.value = new_value;
3676 #ifdef FUNKY_INSENSITIVE_VISUAL
3677 		if ((sbw->scrollBar.value = new_value)
3678 			== sbw->scrollBar.minimum)
3679 		{
3680 		        XSetClipMask(XtDisplay(sbw),
3681 				     sbw->scrollBar.unavailable_GC, None);
3682 			XFillRectangle(XtDisplay(sbw), XtWindow(sbw),
3683 				sbw->scrollBar.unavailable_GC,
3684 				sbw->scrollBar.arrow1_x,
3685 				sbw->scrollBar.arrow1_y,
3686 				sbw->scrollBar.arrow_width,
3687 				sbw->scrollBar.arrow_height);
3688 
3689             sbw->scrollBar.flags &= ~ARROW1_AVAILABLE;
3690 		}
3691 #endif
3692                if ((sbw->scrollBar.show_arrows) &&
3693                    (! (sbw->scrollBar.flags & ARROW2_AVAILABLE)))
3694 		{
3695 			XClearArea(XtDisplay(sbw), XtWindow(sbw),
3696 				sbw->scrollBar.arrow2_x,
3697 				sbw->scrollBar.arrow2_y,
3698 				sbw->scrollBar.arrow_width,
3699 				sbw->scrollBar.arrow_height,
3700 				FALSE);
3701 
3702 			DRAWARROW (sbw, sbw -> primitive.top_shadow_GC,
3703 				sbw->primitive.bottom_shadow_GC,
3704 				sbw->scrollBar.arrow2_x,
3705 				sbw->scrollBar.arrow2_y,
3706 				sbw->scrollBar.arrow2_orientation);
3707 
3708 			sbw->scrollBar.flags |= ARROW2_AVAILABLE;
3709 		}
3710 
3711 		RedrawSliderWindow (sbw);
3712 
3713 		ScrollCallback (sbw, XmCR_PAGE_DECREMENT,
3714 				sbw->scrollBar.value,
3715 				event->xbutton.x, event->xbutton.y, event);
3716 	}
3717 }
3718 
3719 
3720 
3721 
3722 /*********************************************************************
3723  *
3724  *  PageDownOrRight
3725  *	The down or right key was pressed, increase the value by
3726  *	one increment.
3727  *
3728  *********************************************************************/
3729 /*ARGSUSED*/
3730 static void
PageDownOrRight(Widget wid,XEvent * event,String * params,Cardinal * num_params)3731 PageDownOrRight(
3732         Widget wid,
3733         XEvent *event,
3734         String *params,
3735         Cardinal *num_params )
3736 {
3737         XmScrollBarWidget sbw = (XmScrollBarWidget) wid ;
3738 	int new_value;
3739 	int key_pressed;
3740 
3741 	if (!num_params || (*num_params != 1) || !params)
3742 	{
3743 	    XmeWarning(wid, MESSAGE14);
3744 	    return;
3745 	}
3746 
3747 	if (!sbw->scrollBar.editable) return ;
3748 
3749 	sbw->scrollBar.flags &=  ~OPERATION_CANCELLED ;
3750 
3751 	if (! (sbw->scrollBar.flags & SLIDER_AVAILABLE))
3752 		return;
3753 
3754 	/*
3755  	 * arg value passed in will either be "down" for the down key or
3756 	 * "right" for the right arrow key (or for compatibility 0 -> down
3757 	 * key or 1 -> right key. The key needs to be compared with the
3758 	 * scrollbar orientation to ensure only the proper directional key
3759 	 * presses work.
3760 	 */
3761 
3762 	if (_XmConvertActionParamToRepTypeId((Widget) sbw,
3763 		     XmRID_SCROLL_BAR_PAGE_DOWN_OR_RIGHT_ACTION_PARAMS,
3764 		     params[0], True, &key_pressed) == False)
3765 	{
3766 	    /* We couldn't convert the value. Just assume a value of 0. */
3767 	    key_pressed = 0;
3768 	}
3769 
3770 	if (((key_pressed == 0) &&
3771 		(sbw->scrollBar.orientation == XmHORIZONTAL))
3772 		||
3773 		((key_pressed == 1) &&
3774 		(sbw->scrollBar.orientation == XmVERTICAL)))
3775 		return;
3776 
3777 	new_value = sbw->scrollBar.value + sbw->scrollBar.page_increment;
3778 
3779 	if (new_value > sbw->scrollBar.maximum - sbw->scrollBar.slider_size)
3780 		new_value = sbw->scrollBar.maximum - sbw->scrollBar.slider_size;
3781 
3782 	if (new_value != sbw->scrollBar.value)
3783 	{
3784 		sbw->scrollBar.value = new_value;
3785 #ifdef FUNKY_INSENSITIVE_VISUAL
3786 		if ((sbw->scrollBar.value = new_value)
3787 			== (sbw->scrollBar.maximum - sbw->scrollBar.slider_size))
3788 		{
3789 		        XSetClipMask(XtDisplay(sbw),
3790 				     sbw->scrollBar.unavailable_GC, None);
3791 			XFillRectangle(XtDisplay(sbw), XtWindow(sbw),
3792 				sbw->scrollBar.unavailable_GC,
3793 				sbw->scrollBar.arrow2_x,
3794 				sbw->scrollBar.arrow2_y,
3795 				sbw->scrollBar.arrow_width,
3796 				sbw->scrollBar.arrow_height);
3797 
3798             sbw->scrollBar.flags &= ~ARROW2_AVAILABLE;
3799 		}
3800 #endif
3801                if ((sbw->scrollBar.show_arrows) &&
3802                    (! (sbw->scrollBar.flags & ARROW1_AVAILABLE)))
3803 		{
3804 			XClearArea(XtDisplay(sbw), XtWindow(sbw),
3805 				sbw->scrollBar.arrow1_x,
3806 				sbw->scrollBar.arrow1_y,
3807 				sbw->scrollBar.arrow_width,
3808 				sbw->scrollBar.arrow_height,
3809 				FALSE);
3810 
3811 			DRAWARROW (sbw, sbw -> primitive.top_shadow_GC,
3812 				sbw->primitive.bottom_shadow_GC,
3813 				sbw->scrollBar.arrow1_x,
3814 				sbw->scrollBar.arrow1_y,
3815 				sbw->scrollBar.arrow1_orientation);
3816 
3817 			sbw->scrollBar.flags |= ARROW1_AVAILABLE;
3818 		}
3819 
3820 		RedrawSliderWindow (sbw);
3821 
3822 		ScrollCallback (sbw, XmCR_PAGE_INCREMENT, sbw->scrollBar.value,
3823                                     event->xbutton.x, event->xbutton.y, event);
3824 	}
3825 }
3826 
3827 /*ARGSUSED*/
3828 static void
CancelDrag(Widget wid,XEvent * event,String * params,Cardinal * num_params)3829 CancelDrag(
3830         Widget wid,
3831         XEvent *event,
3832         String *params,
3833         Cardinal *num_params)
3834 {
3835 	XmScrollBarWidget sbw = (XmScrollBarWidget) wid;
3836 
3837 	if (!sbw->scrollBar.editable) return ;
3838 
3839 	if (sbw->scrollBar.flags & KEYBOARD_GRABBED)
3840 	{
3841 		short savedX, savedY, j1, j2;
3842 
3843 		XtUngrabKeyboard(wid, ((XButtonPressedEvent *)event)->time);
3844 		sbw->scrollBar.flags &= ~KEYBOARD_GRABBED;
3845 
3846 		sbw->scrollBar.flags |= OPERATION_CANCELLED;
3847 
3848 		sbw->scrollBar.sliding_on = False;
3849 		sbw->scrollBar.value = sbw->scrollBar.saved_value;
3850 		CalcSliderRect(sbw, &savedX, &savedY, &j1, &j2);
3851 		MoveSlider(sbw, savedX, savedY);
3852 		if (sbw->scrollBar.sliding_mode == XmTHERMOMETER)
3853 		    RedrawSliderWindow (sbw);
3854 		ScrollCallback (sbw, XmCR_VALUE_CHANGED,
3855 		                sbw->scrollBar.value, savedX, savedY,
3856 				(XEvent *) event);
3857 
3858 		if (sbw->scrollBar.timer != 0)
3859 		{
3860 			sbw->scrollBar.flags |= END_TIMER;
3861 		}
3862 
3863 	}
3864 	else
3865 	{
3866 		XmParentInputActionRec pp_data ;
3867 
3868 		pp_data.process_type = XmINPUT_ACTION ;
3869 		pp_data.action = XmPARENT_CANCEL ;
3870 		pp_data.event = event ;
3871 		pp_data.params = params ;
3872 		pp_data.num_params = num_params ;
3873 
3874 		_XmParentProcess( XtParent( wid), (XmParentProcessData) &pp_data) ;
3875 	}
3876 }
3877 
3878 
3879 /*********************************************************************
3880  *
3881  *  MoveSlider
3882  *	Given x and y positions, move the slider and clear the area
3883  *	moved out of.
3884  *
3885  *********************************************************************/
3886 static void
MoveSlider(XmScrollBarWidget sbw,int currentX,int currentY)3887 MoveSlider(
3888         XmScrollBarWidget sbw,
3889         int currentX,
3890         int currentY )
3891 {
3892     int oldX = sbw->scrollBar.slider_x;
3893     int oldY = sbw->scrollBar.slider_y;
3894     int width = sbw->scrollBar.slider_width;
3895     int height = sbw->scrollBar.slider_height;
3896 
3897     XSegment seg[2];
3898 
3899     if ((currentX == oldX) && (currentY == oldY))
3900 	return;
3901 
3902     if (sbw->scrollBar.sliding_mode == XmTHERMOMETER) {
3903 	if (sbw->scrollBar.orientation == XmHORIZONTAL)
3904 	    sbw->scrollBar.slider_x = currentX;
3905 	else
3906 	    sbw->scrollBar.slider_y = currentY;
3907 	return ;
3908     }
3909 
3910     if (sbw->scrollBar.orientation == XmHORIZONTAL)
3911 	{
3912 	    sbw->scrollBar.slider_x = currentX;
3913 
3914 	    seg[0].y1 = seg[0].y2 = oldY + 2;
3915 	    seg[1].y1 = seg[1].y2 = oldY + height - 3;
3916 
3917 	    if (oldX < currentX)
3918 		{
3919 		    seg[0].x1 = seg[1].x1 = oldX;
3920 		    seg[0].x2 = seg[1].x2 = oldX + currentX - oldX - 1;
3921 		}
3922 	    else
3923 		{
3924 		    seg[0].x1 = seg[1].x1 = currentX + width;
3925 		    seg[0].x2 = seg[1].x2 = seg[0].x1 + oldX - currentX - 1;
3926 		}
3927 
3928 
3929 	    if (sbw->scrollBar.pixmap != 0)
3930 		{
3931 		    CopySliderInWindow(sbw);
3932 		    XClearArea (XtDisplay((Widget)sbw),
3933 				XtWindow((Widget)sbw),
3934 				seg[0].x1, oldY,
3935 				seg[0].x2 - seg[0].x1 + 1,
3936 				height, False);
3937 		}
3938 	}
3939     else /* sbw->scrollBar.orientation == XmVERTICAL */
3940 	{
3941 	    sbw->scrollBar.slider_y = currentY;
3942 
3943 	    seg[0].x1 = seg[0].x2 = oldX + 2;
3944 	    seg[1].x1 = seg[1].x2 = oldX + width - 3;
3945 
3946 	    if (oldY < currentY)
3947 		{
3948 		    seg[0].y1 = seg[1].y1 = oldY;
3949 		    seg[0].y2 = seg[1].y2 = oldY + currentY - oldY - 1;
3950 		}
3951 	    else
3952 		{
3953 		    seg[0].y1 = seg[1].y1 = currentY + height;
3954 		    seg[0].y2 = seg[1].y2 = seg[0].y1 + oldY - currentY - 1;
3955 		}
3956 
3957 	    if (sbw->scrollBar.pixmap != 0)
3958 		{
3959 		    CopySliderInWindow(sbw);
3960 		    XClearArea (XtDisplay((Widget)sbw),
3961 				XtWindow((Widget)sbw),
3962 				oldX, seg[0].y1, width,
3963 				seg[0].y2 - seg[0].y1 + 1, False);
3964 		}
3965 	}
3966 }
3967 
3968 
3969 
3970 
3971 /************************************************************************
3972  *
3973  *  ChangeScrollBarValue
3974  *	Change the scrollbar value by the indicated change type.  Return
3975  *	True if the value changes, False otherwise.
3976  *
3977  ************************************************************************/
3978 static Boolean
ChangeScrollBarValue(XmScrollBarWidget sbw)3979 ChangeScrollBarValue(
3980         XmScrollBarWidget sbw )
3981 {
3982     register unsigned char change_type = sbw->scrollBar.change_type;
3983     register int change_amount = 0;
3984     register Boolean returnFlag = TRUE;
3985     register int old_value = sbw->scrollBar.value;
3986 
3987     if (! (sbw->scrollBar.flags & SLIDER_AVAILABLE))
3988 	return(FALSE);
3989     /*  Get the amount to change the scroll bar value based on  */
3990     /*  the type of change occuring.                            */
3991 
3992     if (change_type == XmCR_INCREMENT)
3993 	change_amount = sbw->scrollBar.increment;
3994     else if (change_type == XmCR_PAGE_INCREMENT)
3995 	change_amount = sbw->scrollBar.page_increment;
3996     else if (change_type == XmCR_DECREMENT)
3997 	change_amount = -sbw->scrollBar.increment;
3998     else if (change_type == XmCR_PAGE_DECREMENT)
3999 	change_amount = -sbw->scrollBar.page_increment;
4000 
4001     /* Change the value */
4002     sbw->scrollBar.value += change_amount;
4003 
4004     /* Truncate and set flags as appropriate */
4005     if (sbw->scrollBar.value >= (sbw->scrollBar.maximum
4006 				 - sbw->scrollBar.slider_size))
4007 	sbw->scrollBar.value = sbw->scrollBar.maximum
4008 	    - sbw->scrollBar.slider_size;
4009 
4010     if (sbw->scrollBar.value <= sbw->scrollBar.minimum)
4011 	sbw->scrollBar.value = sbw->scrollBar.minimum;
4012 
4013     if ((returnFlag = (sbw->scrollBar.value != old_value)) != False) {
4014 	RedrawSliderWindow (sbw);
4015     }
4016 
4017 
4018     return (returnFlag);
4019 }
4020 
4021 
4022 
4023 
4024 /*********************************************************************
4025  *
4026  *  TimerEvent
4027  *	This is an event processing function which handles timer
4028  *	event evoked because of arrow selection.
4029  *
4030  *********************************************************************/
4031 /*ARGSUSED*/
4032 static void
TimerEvent(XtPointer closure,XtIntervalId * id)4033 TimerEvent(
4034         XtPointer closure,
4035         XtIntervalId *id )	/* unused */
4036 {
4037         XmScrollBarWidget sbw = (XmScrollBarWidget) closure ;
4038 	Boolean flag;
4039 
4040 	sbw->scrollBar.timer = 0;
4041 
4042 	if (sbw->scrollBar.flags & END_TIMER)
4043 	{
4044 		sbw->scrollBar.flags &= ~END_TIMER;
4045 		return;
4046 	}
4047 
4048 	if (sbw->scrollBar.flags & FIRST_SCROLL_FLAG)
4049 	{
4050 		XSync (XtDisplay (sbw), False);
4051 
4052 		sbw->scrollBar.flags &= ~FIRST_SCROLL_FLAG;
4053 
4054 		sbw->scrollBar.timer =
4055 		XtAppAddTimeOut (XtWidgetToApplicationContext((Widget) sbw),
4056                                    (unsigned long) sbw->scrollBar.repeat_delay,
4057                                                   TimerEvent, (XtPointer) sbw);
4058 		return;
4059 	}
4060 
4061 
4062 	/*  Change the scrollbar slider value  */
4063 
4064 	flag = ChangeScrollBarValue (sbw);
4065 
4066 	/*  If the orgin was changed invoke the application supplied  */
4067 	/*  slider moved callbacks                                    */
4068 
4069 	if (flag)
4070 		ScrollCallback (sbw, sbw->scrollBar.change_type,
4071 			sbw->scrollBar.value, 0, 0, NULL);
4072 
4073 	/*
4074 	 * If the callback does alot of processing, and XSync is needed
4075 	 * to flush the output and input buffers.  If this is not done,
4076 	 * the entry back to MainLoop will cause the flush.  The server
4077 	 * will then perform it work which may take longer than the timer
4078 	 * interval which will cause the scrollbar to be stuck in a loop.
4079 	 */
4080 
4081 	XSync (XtDisplay (sbw), False);
4082 
4083 	/*  Add the repeat timer and check that the scrollbar hasn't been set
4084 	    insensitive by some callbacks */
4085 
4086 	if (flag)
4087 	{
4088 		sbw->scrollBar.timer =
4089 		    XtAppAddTimeOut (XtWidgetToApplicationContext((Widget) sbw),
4090 				     (unsigned long) sbw->scrollBar.repeat_delay,
4091 				     TimerEvent, (XtPointer) sbw);
4092 	}
4093 }
4094 
4095 
4096 
4097 
4098 /************************************************************************
4099  *
4100  *  ScrollCallback
4101  *	This routine services the widget's callbacks.  It calls the
4102  *	specific callback if it is not empty.  If it is empty then the
4103  *	main callback is called.
4104  *
4105  ************************************************************************/
4106 static void
ScrollCallback(XmScrollBarWidget sbw,int reason,int value,int xpixel,int ypixel,XEvent * event)4107 ScrollCallback(
4108         XmScrollBarWidget sbw,
4109         int reason,
4110         int value,
4111         int xpixel,
4112         int ypixel,
4113         XEvent *event )
4114 {
4115    XmScrollBarCallbackStruct call_value;
4116 
4117    call_value.reason = reason;
4118    call_value.event  = event;
4119 
4120    if (PROCESS_DIR_INVERSED(sbw)) {
4121        switch (reason) {
4122        case XmCR_INCREMENT:
4123 	   call_value.reason = reason = XmCR_DECREMENT;
4124 	   break;
4125        case XmCR_DECREMENT:
4126 	   call_value.reason = reason = XmCR_INCREMENT;
4127 	   break;
4128        case XmCR_PAGE_INCREMENT:
4129 	   call_value.reason = reason = XmCR_PAGE_DECREMENT;
4130 	   break;
4131        case XmCR_PAGE_DECREMENT:
4132 	   call_value.reason = reason = XmCR_PAGE_INCREMENT;
4133 	   break;
4134        case XmCR_TO_TOP:
4135 	   call_value.reason = reason = XmCR_TO_BOTTOM;
4136 	   break;
4137        case XmCR_TO_BOTTOM:
4138 	   call_value.reason = reason = XmCR_TO_TOP;
4139 	   break;
4140        }
4141        call_value.value = sbw->scrollBar.maximum
4142 	   + sbw->scrollBar.minimum - value - sbw->scrollBar.slider_size;
4143    }
4144    else
4145        call_value.value = value;
4146 
4147 
4148    if (sbw->scrollBar.orientation == XmHORIZONTAL)
4149       call_value.pixel = xpixel;
4150    else
4151       call_value.pixel = ypixel;
4152 
4153    switch (reason) {
4154 
4155    case XmCR_VALUE_CHANGED:
4156        XtCallCallbackList ((Widget) sbw, sbw->scrollBar.value_changed_callback,
4157 			   &call_value);
4158        break;
4159 
4160    case XmCR_INCREMENT:
4161        if  (sbw->scrollBar.increment_callback)
4162 	   XtCallCallbackList ((Widget) sbw,
4163 			       sbw->scrollBar.increment_callback, &call_value);
4164        else
4165 	   {
4166 	       call_value.reason = XmCR_VALUE_CHANGED;
4167 	       XtCallCallbackList ((Widget) sbw,
4168 				 sbw->scrollBar.value_changed_callback, &call_value);
4169 	   }
4170        break;
4171 
4172    case XmCR_DECREMENT:
4173        if  (sbw->scrollBar.decrement_callback)
4174 	   XtCallCallbackList ((Widget) sbw,
4175 			       sbw->scrollBar.decrement_callback, &call_value);
4176        else
4177 	   {
4178 	       call_value.reason = XmCR_VALUE_CHANGED;
4179 	       XtCallCallbackList ((Widget) sbw,
4180 				sbw->scrollBar.value_changed_callback, &call_value);
4181 	   }
4182        break;
4183 
4184    case XmCR_PAGE_INCREMENT:
4185        if  (sbw->scrollBar.page_increment_callback)
4186 	   XtCallCallbackList ((Widget) sbw,
4187 			       sbw->scrollBar.page_increment_callback, &call_value);
4188        else
4189 	   {
4190 	       call_value.reason = XmCR_VALUE_CHANGED;
4191 	       XtCallCallbackList ((Widget) sbw,
4192 				sbw->scrollBar.value_changed_callback, &call_value);
4193 	   }
4194        break;
4195 
4196    case XmCR_PAGE_DECREMENT:
4197        if  (sbw->scrollBar.page_decrement_callback)
4198 	   XtCallCallbackList ((Widget) sbw,
4199 			       sbw->scrollBar.page_decrement_callback, &call_value);
4200        else
4201 	   {
4202 	       call_value.reason = XmCR_VALUE_CHANGED;
4203 	       XtCallCallbackList ((Widget) sbw,
4204 				 sbw->scrollBar.value_changed_callback, &call_value);
4205 	   }
4206        break;
4207 
4208    case XmCR_TO_TOP:
4209        if (sbw->scrollBar.to_top_callback)
4210 	   XtCallCallbackList ((Widget) sbw,
4211 			       sbw->scrollBar.to_top_callback, &call_value);
4212        else
4213 	   {
4214 	       call_value.reason = XmCR_VALUE_CHANGED;
4215 	       XtCallCallbackList ((Widget) sbw,
4216 				sbw->scrollBar.value_changed_callback, &call_value);
4217 	   }
4218        break;
4219 
4220    case XmCR_TO_BOTTOM:
4221        if (sbw->scrollBar.to_bottom_callback)
4222 	   XtCallCallbackList ((Widget) sbw,
4223 			       sbw->scrollBar.to_bottom_callback, &call_value);
4224        else
4225 	   {
4226 	       call_value.reason = XmCR_VALUE_CHANGED;
4227 	       XtCallCallbackList ((Widget) sbw,
4228 				 sbw->scrollBar.value_changed_callback, &call_value);
4229 	   }
4230        break;
4231 
4232    case XmCR_DRAG:
4233        if (sbw->scrollBar.drag_callback)
4234 	   XtCallCallbackList ((Widget) sbw,
4235 			       sbw->scrollBar.drag_callback, &call_value);
4236        break;
4237    }
4238 }
4239 
4240 
4241 
4242 
4243 /************************************************************************
4244  *
4245  *  NavigChangeMoveCB
4246  *	add or remove the callback list to be called on any move.
4247  *      Since valueChangedCallback is not called on increment (& co)
4248  *      if an increment callback is present, we have to set them all.
4249  *
4250  ************************************************************************/
4251 static void
NavigChangeMoveCB(Widget nav,XtCallbackProc moveCB,XtPointer closure,Boolean setunset)4252 NavigChangeMoveCB(
4253            Widget nav,
4254 	   XtCallbackProc moveCB,
4255            XtPointer closure,
4256            Boolean setunset)
4257 {
4258     if (setunset) {
4259 	XtAddCallback (nav, XmNvalueChangedCallback, moveCB, closure);
4260 	XtAddCallback (nav, XmNincrementCallback, moveCB, closure);
4261 	XtAddCallback (nav, XmNdecrementCallback, moveCB, closure);
4262 	XtAddCallback (nav, XmNpageIncrementCallback, moveCB, closure);
4263 	XtAddCallback (nav, XmNpageDecrementCallback, moveCB, closure);
4264 	XtAddCallback (nav, XmNtoTopCallback, moveCB, closure);
4265 	XtAddCallback (nav, XmNtoBottomCallback, moveCB, closure);
4266 	XtAddCallback (nav, XmNdragCallback, moveCB, closure);
4267     } else {
4268 	XtRemoveCallback (nav, XmNvalueChangedCallback, moveCB, closure);
4269 	XtRemoveCallback (nav, XmNincrementCallback, moveCB, closure);
4270 	XtRemoveCallback (nav, XmNdecrementCallback, moveCB, closure);
4271 	XtRemoveCallback (nav, XmNpageIncrementCallback, moveCB, closure);
4272 	XtRemoveCallback (nav, XmNpageDecrementCallback, moveCB, closure);
4273 	XtRemoveCallback (nav, XmNtoTopCallback, moveCB, closure);
4274 	XtRemoveCallback (nav, XmNtoBottomCallback, moveCB, closure);
4275 	XtRemoveCallback (nav, XmNdragCallback, moveCB, closure);
4276     }
4277 }
4278 
4279 
4280 
4281 
4282 
4283 /************************************************************************
4284  *
4285  *  NavigSetValue
4286  *	change the value and possibly call the callbacks
4287  *
4288  ************************************************************************/
4289 static void
NavigSetValue(Widget nav,XmNavigatorData nav_data,Boolean notify)4290 NavigSetValue(
4291            Widget nav,
4292 	   XmNavigatorData nav_data,
4293            Boolean notify)
4294 {
4295     XmScrollBarWidget sbw = (XmScrollBarWidget) nav;
4296     int save_value;
4297     Arg arglist[6];
4298     Cardinal n;
4299 
4300     /* register which dimension this scrollbar is to operate */
4301     if (nav_data->valueMask & NavDimMask) {
4302 	sbw->scrollBar.dimMask = nav_data->dimMask ;
4303     }
4304 
4305     /* scrollbar is a one dimensional navigator, it expects
4306        only one dimension to be set, the one that has been registered
4307        for using the NavDimMask (as treated above) */
4308 
4309     if (!(sbw->scrollBar.dimMask & nav_data->dimMask)) return ;
4310 
4311     /* we need to fetch either the x or y values out of the
4312        passed nav_data record, depending on the dimmask.
4313        scrollbar is only interested in one value */
4314 
4315 
4316     save_value = sbw->scrollBar.value;
4317 
4318     n = 0;
4319     if (nav_data->valueMask & NavValue) {
4320       if ((PROCESS_DIR_INVERSED(sbw) ?
4321 	   INVERSED_VALUE(sbw) : sbw->scrollBar.value) !=
4322 	  ACCESS_DIM(sbw->scrollBar.dimMask, nav_data->value)) {
4323 	XtSetArg (arglist[n], XmNvalue,
4324 		  ACCESS_DIM(sbw->scrollBar.dimMask, nav_data->value));n++;
4325       }
4326     }
4327 
4328 
4329     if ((nav_data->valueMask & NavMinimum) &&
4330 	(sbw->scrollBar.minimum !=
4331 	 ACCESS_DIM(sbw->scrollBar.dimMask, nav_data->minimum))) {
4332 	XtSetArg (arglist[n], XmNminimum,
4333 		  ACCESS_DIM(sbw->scrollBar.dimMask, nav_data->minimum));n++;
4334     }
4335 
4336     if ((nav_data->valueMask & NavMaximum) &&
4337 	(sbw->scrollBar.maximum !=
4338 	 ACCESS_DIM(sbw->scrollBar.dimMask, nav_data->maximum))) {
4339 	XtSetArg (arglist[n], XmNmaximum,
4340 		  ACCESS_DIM(sbw->scrollBar.dimMask, nav_data->maximum));n++;
4341     }
4342 
4343     if (sbw->scrollBar.sliding_mode != XmTHERMOMETER) {
4344 	if ((nav_data->valueMask & NavSliderSize) &&
4345 	    (sbw->scrollBar.slider_size !=
4346 	     ACCESS_DIM(sbw->scrollBar.dimMask, nav_data->slider_size)) &&
4347 	    (ACCESS_DIM(sbw->scrollBar.dimMask, nav_data->slider_size) != 0)) {
4348 	    XtSetArg (arglist[n], XmNsliderSize,
4349 		      ACCESS_DIM(sbw->scrollBar.dimMask, nav_data->slider_size));
4350 	    n++;
4351 	}
4352     }
4353 
4354     if ((nav_data->valueMask & NavIncrement) &&
4355 	(sbw->scrollBar.increment !=
4356 	 ACCESS_DIM(sbw->scrollBar.dimMask, nav_data->increment)) &&
4357 	(ACCESS_DIM(sbw->scrollBar.dimMask, nav_data->increment) != 0)) {
4358 	XtSetArg (arglist[n], XmNincrement,
4359 		  ACCESS_DIM(sbw->scrollBar.dimMask, nav_data->increment)); n++;
4360     }
4361 
4362     if ((nav_data->valueMask & NavPageIncrement) &&
4363 	(sbw->scrollBar.page_increment !=
4364 	 ACCESS_DIM(sbw->scrollBar.dimMask, nav_data->page_increment)) &&
4365 	(ACCESS_DIM(sbw->scrollBar.dimMask, nav_data->page_increment) != 0)) {
4366 	XtSetArg (arglist[n], XmNpageIncrement,
4367 		  ACCESS_DIM(sbw->scrollBar.dimMask, nav_data->page_increment));
4368 	n++;
4369     }
4370 
4371     if (n) XtSetValues (nav, arglist, n);
4372 
4373     if (notify && sbw->scrollBar.value != save_value)
4374 	ScrollCallback (sbw, XmCR_VALUE_CHANGED,
4375 			sbw->scrollBar.value, 0, 0, NULL);
4376 
4377 }
4378 
4379 
4380 /************************************************************************
4381  *
4382  *  NavigGetValue
4383  *	reports the all the data for this navigator scrollbar
4384  *      nav_data allocated by the caller
4385  ************************************************************************/
4386 static void
NavigGetValue(Widget nav,XmNavigatorData nav_data)4387 NavigGetValue(
4388            Widget nav,
4389            XmNavigatorData nav_data)
4390 {
4391     XmScrollBarWidget sbw = (XmScrollBarWidget) nav;
4392 
4393     nav_data->dimMask =  sbw->scrollBar.dimMask;
4394 
4395     if (nav_data->valueMask & NavValue) {
4396 	int value ;
4397 
4398 	if (PROCESS_DIR_INVERSED(sbw)) {
4399 	    value = INVERSED_VALUE(sbw);
4400 	} else
4401 	    value = sbw->scrollBar.value;
4402 
4403 	ASSIGN_DIM(nav_data->dimMask, nav_data->value, value) ;
4404     }
4405 
4406     if (nav_data->valueMask & NavMinimum)
4407 	ASSIGN_DIM(nav_data->dimMask, nav_data->minimum,
4408 		   sbw->scrollBar.minimum) ;
4409 
4410 
4411     if (nav_data->valueMask & NavMaximum)
4412 	ASSIGN_DIM(nav_data->dimMask, nav_data->maximum,
4413 		   sbw->scrollBar.maximum) ;
4414 
4415 
4416     if (nav_data->valueMask & NavSliderSize)
4417 	ASSIGN_DIM(nav_data->dimMask, nav_data->slider_size,
4418 		   sbw->scrollBar.slider_size) ;
4419 
4420     if (nav_data->valueMask & NavIncrement)
4421 	ASSIGN_DIM(nav_data->dimMask, nav_data->increment,
4422 		   sbw->scrollBar.increment) ;
4423 
4424     if (nav_data->valueMask & NavPageIncrement)
4425 	ASSIGN_DIM(nav_data->dimMask, nav_data->page_increment,
4426 		   sbw->scrollBar.page_increment) ;
4427 
4428 }
4429 
4430 
4431 
4432 
4433 /************************************************************************
4434  *
4435  *		Application Accessible External Functions
4436  *
4437  ************************************************************************/
4438 
4439 
4440 /************************************************************************
4441  *
4442  *  XmCreateScrollBar
4443  *	Create an instance of a scrollbar and return the widget id.
4444  *
4445  ************************************************************************/
4446 Widget
XmCreateScrollBar(Widget parent,char * name,ArgList arglist,Cardinal argcount)4447 XmCreateScrollBar(
4448         Widget parent,
4449         char *name,
4450         ArgList arglist,
4451         Cardinal argcount )
4452 {
4453    return (XtCreateWidget (name, xmScrollBarWidgetClass,
4454                            parent, arglist, argcount));
4455 }
4456 
4457 Widget
XmVaCreateScrollBar(Widget parent,char * name,...)4458 XmVaCreateScrollBar(
4459         Widget parent,
4460         char *name,
4461         ...)
4462 {
4463     register Widget w;
4464     va_list var;
4465     int count;
4466 
4467     Va_start(var,name);
4468     count = XmeCountVaListSimple(var);
4469     va_end(var);
4470 
4471 
4472     Va_start(var, name);
4473     w = XmeVLCreateWidget(name,
4474                          xmScrollBarWidgetClass,
4475                          parent, False,
4476                          var, count);
4477     va_end(var);
4478     return w;
4479 }
4480 
4481 Widget
XmVaCreateManagedScrollBar(Widget parent,char * name,...)4482 XmVaCreateManagedScrollBar(
4483         Widget parent,
4484         char *name,
4485         ...)
4486 {
4487     Widget w = NULL;
4488     va_list var;
4489     int count;
4490 
4491     Va_start(var, name);
4492     count = XmeCountVaListSimple(var);
4493     va_end(var);
4494 
4495     Va_start(var, name);
4496     w = XmeVLCreateWidget(name,
4497                          xmScrollBarWidgetClass,
4498                          parent, True,
4499                          var, count);
4500     va_end(var);
4501     return w;
4502 }
4503 
4504 /************************************************************************
4505  *
4506  *  XmScrollBarGetValues
4507  *	Return some scrollbar values.
4508  *
4509  ************************************************************************/
4510 void
XmScrollBarGetValues(Widget w,int * value,int * slider_size,int * increment,int * page_increment)4511 XmScrollBarGetValues(
4512         Widget w,
4513         int *value,
4514         int *slider_size,
4515         int *increment,
4516         int *page_increment )
4517 {
4518    XmScrollBarWidget sbw = (XmScrollBarWidget) w;
4519    XtAppContext app = XtWidgetToApplicationContext(w);
4520 
4521    _XmAppLock(app);
4522 
4523    if (PROCESS_DIR_INVERSED(sbw)) {
4524       if (value) *value = INVERSED_VALUE(sbw);
4525    } else
4526       if (value) *value = sbw->scrollBar.value;
4527 
4528    if (slider_size) *slider_size = sbw->scrollBar.slider_size;
4529    if (increment) *increment = sbw->scrollBar.increment;
4530    if (page_increment) *page_increment = sbw->scrollBar.page_increment;
4531    _XmAppUnlock(app);
4532 }
4533 
4534 
4535 
4536 
4537 /************************************************************************
4538  *
4539  *  XmScrollBarSetValues
4540  *	Set some scrollbar values.
4541  *
4542  ************************************************************************/
4543 void
XmScrollBarSetValues(Widget w,int value,int slider_size,int increment,int page_increment,int notify)4544 XmScrollBarSetValues(
4545         Widget w,
4546         int value,
4547         int slider_size,
4548         int increment,
4549         int page_increment,
4550 #if NeedWidePrototypes
4551         int notify )
4552 #else
4553         Boolean notify )
4554 #endif /* NeedWidePrototypes */
4555 {
4556    XmScrollBarWidget sbw = (XmScrollBarWidget) w;
4557    int save_value;
4558    Arg arglist[4];
4559    Cardinal n;
4560    XtAppContext app = XtWidgetToApplicationContext(w);
4561 
4562    _XmAppLock(app);
4563 
4564 
4565    save_value = sbw->scrollBar.value;
4566 
4567    n = 0;
4568    XtSetArg (arglist[n], XmNvalue, value);			n++;
4569 
4570    if (sbw->scrollBar.sliding_mode != XmTHERMOMETER) {
4571        if (slider_size != 0) {
4572 	   XtSetArg (arglist[n], XmNsliderSize, slider_size);	n++;
4573        }
4574    }
4575 
4576    if (increment != 0) {
4577       XtSetArg (arglist[n], XmNincrement, increment);		n++;
4578    }
4579 
4580    if (page_increment != 0) {
4581       XtSetArg (arglist[n], XmNpageIncrement, page_increment);	n++;
4582    }
4583 
4584    XtSetValues ((Widget) sbw, arglist, n);
4585 
4586    if (notify && sbw->scrollBar.value != save_value)
4587       ScrollCallback (sbw, XmCR_VALUE_CHANGED,
4588                       sbw->scrollBar.value, 0, 0, NULL);
4589    _XmAppUnlock(app);
4590 }
4591 
4592