1 /**
2 *
3 * $Header: /cvsroot/lesstif/lesstif/lib/Xm-2.1/Scale.c,v 1.2 2004/10/27 20:57:58 dannybackx Exp $
4 *
5 * Copyright (C) 1995 Free Software Foundation, Inc.
6 * Copyright � 1995-2002, 2004 LessTif Development Team
7 *
8 * This file is part of the GNU LessTif Library.
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Library General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Library General Public License for more details.
19 *
20 * You should have received a copy of the GNU Library General Public
21 * License along with this library; if not, write to the Free
22 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 **/
25
26 static const char rcsid[] = "$Id: Scale.c,v 1.2 2004/10/27 20:57:58 dannybackx Exp $";
27
28 #include <LTconfig.h>
29
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <limits.h>
33 #include <math.h>
34
35 #include <XmI/XmI.h>
36 #include <Xm/XmP.h>
37 #include <Xm/ScaleP.h>
38 #include <Xm/LabelGP.h>
39 #include <Xm/ScrollBarP.h>
40 #include <Xm/BulletinBP.h>
41 #include <Xm/MenuShellP.h>
42 #include <Xm/VendorSP.h>
43 #include <Xm/VendorSEP.h>
44
45 #include <XmI/DebugUtil.h>
46
47
48 #define USE_LAYOUT 1
49
50 #define CHILD_LAB 0
51 #define CHILD_SB 1
52
53 /* FIX ME/BUGS
54 * - highlight
55 */
56
57 /*
58 * these values come from behavior observation of M*tif. Change at your own
59 * risk
60 *
61 * Hmm, I've observed HSLIDERSIZE to be 30 (M*tif 1.2.2) -- PvH
62 */
63 #define SCB_MAX 1000000000
64 #define SCB_MIN 0
65 #define HSLIDERSIZE /*40*/30
66 #define VSLIDERSIZE 12
67 #define MIN_SLIDE 4
68
69 #define SB_TRANSVERSAL_SIZE 15
70 #define SB_LONGITUDAL_SIZE 100
71
72 /* T. Straumann: special value to indicate that the value rectangle position
73 * is invalid and hence must not be erased.
74 */
75 #define SHOW_VALUE_X_INVALID -65536
76
77 #define Scale_ShadowThickness(x) MGR_ShadowThickness(x)
78
79 static void class_initialize(void);
80 static void class_part_initialize(WidgetClass w_class);
81 static void initialize(Widget request, Widget new_w,
82 ArgList args, Cardinal *num_args);
83 static void destroy(Widget w);
84 static void realize(Widget w, XtValueMask *value_mask,
85 XSetWindowAttributes *attributes);
86 static Boolean set_values(Widget current, Widget request, Widget new_w,
87 ArgList args, Cardinal *num_args);
88 static XtGeometryResult query_geometry(Widget w,
89 XtWidgetGeometry *request,
90 XtWidgetGeometry *reply);
91 static XtGeometryResult geometry_manager(Widget w,
92 XtWidgetGeometry *request,
93 XtWidgetGeometry *reply);
94 static void expose(Widget w, XEvent *event, Region region);
95 static void resize(Widget w);
96 static void change_managed(Widget w);
97
98 #if 0
99 static void insert_child(Widget w);
100 #endif
101
102 static XmKidGeometry _XmScalePreferredSize(Widget scale, Widget child,
103 XtWidgetGeometry *childgeom,
104 Dimension *w, Dimension *ht);
105 static XtGeometryResult _XmScaleGeomRequest(Widget scale,
106 Dimension *wd, Dimension *ht);
107 static void _XmScaleLayout(Widget scale, XmKidGeometry boxes,
108 Widget child, XtWidgetGeometry *childgeom,
109 Dimension curw, Dimension curh);
110 static void _XmScaleConfigureChildren(Widget scale,
111 Widget child,
112 XmKidGeometry boxes);
113 static int _XmScaleConvertWidthToSliderSize(Widget w);
114 static int _XmScaleConvertSCBValueToScaleValue(Widget w, int value);
115 static int _XmScaleConvertScaleValueToSCBValue(Widget w);
116 static void _XmScaleConvertScaleIncrementToSCBIncrements(Widget w,
117 int* inc,
118 int* page_inc);
119 static void _ScaleValueChanged(Widget sb, XtPointer cd, XtPointer data);
120 static void _ScaleDrag(Widget sb, XtPointer cd, XtPointer data);
121 static void computeValueSize(Widget w);
122 static void showValue(Widget w, int scb_value, int scale_value);
123
124 #if 0
125 static void GetFocus(Widget w, XEvent *event,
126 String *params, Cardinal *num_params);
127 static void LoseFocus(Widget w, XEvent *event,
128 String *params, Cardinal *num_params);
129 #endif
130
131 static void _XmScaleProcessingDirectionDefault(Widget w,
132 int offset,
133 XrmValue *val);
134
135 /*
136 * Resources for the scale class
137 */
138 #define Offset(field) XtOffsetOf(XmScaleRec, scale.field)
139 static XtResource resources[] =
140 {
141 {
142 XmNshadowThickness, XmCShadowThickness, XmRHorizontalDimension,
143 sizeof(Dimension), XtOffsetOf(XmScaleRec, manager.shadow_thickness),
144 XmRImmediate, (XtPointer)2
145 },
146 {
147 XmNvalue, XmCValue, XmRInt,
148 sizeof(int), Offset(value),
149 XmRImmediate, (XtPointer)INT_MAX
150 },
151 {
152 XmNmaximum, XmCMaximum, XmRInt,
153 sizeof(int), Offset(maximum),
154 XmRImmediate, (XtPointer)100
155 },
156 {
157 XmNminimum, XmCMinimum, XmRInt,
158 sizeof(int), Offset(minimum),
159 XmRImmediate, (XtPointer)0
160 },
161 {
162 XmNorientation, XmCOrientation, XmROrientation,
163 sizeof(unsigned char), Offset(orientation),
164 XmRImmediate, (XtPointer)XmVERTICAL
165 },
166 {
167 XmNprocessingDirection, XmCProcessingDirection, XmRProcessingDirection,
168 sizeof(unsigned char), Offset(processing_direction),
169 XmRCallProc, (XtPointer)_XmScaleProcessingDirectionDefault
170 },
171 {
172 XmNtitleString, XmCTitleString, XmRXmString,
173 sizeof(XmString), Offset(title),
174 XtRImmediate, (XtPointer)NULL
175 },
176 {
177 XmNfontList, XmCFontList, XmRFontList,
178 sizeof(XmFontList), Offset(font_list),
179 XtRImmediate, (XtPointer)NULL
180 },
181 {
182 XmNshowValue, XmCShowValue, XmRBoolean,
183 sizeof(Boolean), Offset(show_value),
184 XmRImmediate, (XtPointer)False
185 },
186 {
187 XmNdecimalPoints, XmCDecimalPoints, XmRShort,
188 sizeof(short), Offset(decimal_points),
189 XmRImmediate, (XtPointer)(short)0
190 },
191 {
192 XmNscaleWidth, XmCScaleWidth, XmRHorizontalDimension,
193 sizeof(Dimension), Offset(scale_width),
194 XmRImmediate, (XtPointer)0
195 },
196 {
197 XmNscaleHeight, XmCScaleHeight, XmRVerticalDimension,
198 sizeof(Dimension), Offset(scale_height),
199 XmRImmediate, (XtPointer)0
200 },
201 {
202 XmNhighlightThickness, XmCHighlightThickness, XmRHorizontalDimension,
203 sizeof(Dimension), Offset(highlight_thickness),
204 XmRImmediate, (XtPointer)2
205 },
206 {
207 XmNhighlightOnEnter, XmCHighlightOnEnter, XmRBoolean,
208 sizeof(Boolean), Offset(highlight_on_enter),
209 XmRImmediate, (XtPointer)False
210 },
211 {
212 XmNvalueChangedCallback, XmCCallback, XmRCallback,
213 sizeof(XtCallbackList), Offset(value_changed_callback),
214 XmRCallback, (XtPointer)NULL
215 },
216 {
217 XmNdragCallback, XmCCallback, XmRCallback,
218 sizeof(XtCallbackList), Offset(drag_callback),
219 XmRCallback, (XtPointer)NULL
220 },
221 #if XmVERSION > 1
222 {
223 XmNeditable, XmCEditable, XmRBoolean,
224 sizeof(Boolean), Offset(editable),
225 XmRImmediate, (XtPointer)True
226 },
227 #endif
228 {
229 XmNscaleMultiple, XmCScaleMultiple, XmRInt,
230 sizeof(int), Offset(scale_multiple),
231 XmRImmediate, (XtPointer)0
232 }
233 };
234
235 static XmSyntheticResource syn_resources[] =
236 {
237 {
238 XmNtitleString,
239 sizeof(XmString), Offset(title),
240 _XmExportXmString, NULL
241 },
242 {
243 XmNscaleWidth,
244 sizeof(Dimension), Offset(scale_width),
245 _XmFromHorizontalPixels, _XmToHorizontalPixels
246 },
247 {
248 XmNscaleHeight,
249 sizeof(Dimension), Offset(scale_height),
250 _XmFromVerticalPixels, _XmToVerticalPixels
251 },
252 };
253
254 #if 0
255 static char defaultTranslations[] =
256 "<FocusIn>: FocusIn() \n\
257 <FocusOut>: FocusOut()";
258
259 static XtActionsRec actions[] =
260 {
261 {"FocusIn", GetFocus},
262 {"FocusOut", LoseFocus}
263 };
264 #endif
265
266 static XmBaseClassExtRec _XmScaleCoreClassExtRec = {
267 /* next_extension */ NULL,
268 /* record_type */ NULLQUARK,
269 /* version */ XmBaseClassExtVersion,
270 /* size */ sizeof(XmBaseClassExtRec),
271 /* initialize_prehook */ NULL,
272 /* set_values_prehook */ NULL,
273 /* initialize_posthook */ NULL,
274 /* set_values_posthook */ NULL,
275 /* secondary_object_class */ NULL,
276 /* secondary_object_create */ NULL,
277 /* get_secondary_resources */ NULL,
278 /* fast_subclass */ { 0 },
279 /* get_values_prehook */ NULL,
280 /* get_values_posthook */ NULL,
281 /* class_part_init_prehook */ NULL,
282 /* class_part_init_posthook */ NULL,
283 /* ext_resources */ NULL,
284 /* compiled_ext_resources */ NULL,
285 /* num_ext_resources */ 0,
286 /* use_sub_resources */ False,
287 /* widget_navigable */ XmInheritWidgetNavigable, /* Motif has one */
288 /* focus_change */ XmInheritFocusChange, /* Motif has NULL */
289 /* wrapper_data */ NULL
290 };
291
292 #if 0
293 static XmManagerClassExtRec _XmScaleMClassExtRec = {
294 /* next_extension */ NULL,
295 /* record_type */ NULLQUARK,
296 /* version */ XmManagerClassExtVersion,
297 /* record_size */ sizeof(XmManagerClassExtRec),
298 /* traversal_children */ NULL /* FIX ME */
299 };
300 #endif
301
302 XmScaleClassRec xmScaleClassRec =
303 {
304 /* Core class part */
305 {
306 /* superclass */ (WidgetClass) & xmManagerClassRec,
307 /* class_name */ "XmScale",
308 /* widget_size */ sizeof(XmScaleRec),
309 /* class_initialize */ class_initialize,
310 /* class_part_initialize */ class_part_initialize,
311 /* class_inited */ False,
312 /* initialize */ initialize,
313 /* initialize_hook */ NULL,
314 /* realize */ realize,
315 /* actions */ NULL /*actions*/,
316 /* num_actions */ 0 /*XtNumber(actions)*/,
317 /* resources */ resources,
318 /* num_resources */ XtNumber(resources),
319 /* xrm_class */ NULLQUARK,
320 /* compress_motion */ True,
321 /* compress_exposure */ XtExposeCompressMaximal,
322 /* compress_enterleave */ True,
323 /* visible_interest */ False,
324 /* destroy */ destroy,
325 /* resize */ resize,
326 /* expose */ expose,
327 /* set_values */ set_values,
328 /* set_values_hook */ NULL,
329 /* set_values_almost */ XtInheritSetValuesAlmost,
330 /* get_values_hook */ NULL,
331 /* accept_focus */ NULL,
332 /* version */ XtVersion,
333 /* callback offsets */ NULL,
334 /* tm_table */ XtInheritTranslations /*defaultTranslations*/,
335 /* query_geometry */ query_geometry,
336 /* display_accelerator */ NULL /*XtInheritDisplayAccelerator*/,
337 /* extension */ (XtPointer)&_XmScaleCoreClassExtRec
338 },
339 /* Composite class part */
340 {
341 /* geometry manager */ geometry_manager,
342 /* change_managed */ change_managed,
343 /* insert_child */ XtInheritInsertChild /*insert_child*/,
344 /* delete_child */ XtInheritDeleteChild,
345 /* extension */ NULL,
346 },
347 /* Constraint class part */
348 {
349 /* subresources */ NULL,
350 /* subresource_count */ 0,
351 /* constraint_size */ 0,
352 /* initialize */ NULL,
353 /* destroy */ NULL,
354 /* set_values */ NULL,
355 /* extension */ NULL,
356 },
357 /* XmManager class part */
358 {
359 /* translations */ XtInheritTranslations,
360 /* syn_resources */ syn_resources,
361 /* num_syn_resources */ XtNumber(syn_resources),
362 /* syn_constraint_resources */ NULL,
363 /* num_syn_constraint_resources */ 0,
364 /* parent_process */ XmInheritParentProcess,
365 /* extension */ (XtPointer)NULL /*&_XmScaleMClassExtRec*/
366 },
367 /* XmScale part */
368 {
369 /* extension */ NULL,
370 },
371 };
372
373
374
375 WidgetClass xmScaleWidgetClass = (WidgetClass)&xmScaleClassRec;
376
377
378 static void
class_initialize(void)379 class_initialize(void)
380 {
381 _XmScaleCoreClassExtRec.record_type = XmQmotif;
382 }
383
384
385 static void
class_part_initialize(WidgetClass widget_class)386 class_part_initialize(WidgetClass widget_class)
387 {
388 XmScaleWidgetClass scclass = (XmScaleWidgetClass)widget_class;
389 CompositeClassExtension ext, *extptr;
390
391 extptr = (CompositeClassExtension *)_XmGetClassExtensionPtr(
392 (XmGenericClassExt *)&(scclass->composite_class.extension),
393 NULLQUARK);
394
395 if (extptr == NULL || *extptr == NULL)
396 {
397 ext = (CompositeClassExtension)XtNew(CompositeClassExtensionRec);
398 if (ext != NULL)
399 {
400 ext->next_extension = scclass->composite_class.extension;
401 ext->record_type = NULLQUARK;
402 ext->version = XtCompositeExtensionVersion;
403 ext->record_size = sizeof(CompositeClassExtensionRec);
404 ext->accepts_objects = True;
405 #if XtSpecificationRelease >= 6
406 ext->allows_change_managed_set = True;
407 #endif
408 scclass->composite_class.extension = (XtPointer)ext;
409 }
410 }
411
412 _XmFastSubclassInit(widget_class, XmSCALE_BIT);
413 }
414
415
416 static void
CreateForegroundGC(Widget w)417 CreateForegroundGC(Widget w)
418 {
419 XtGCMask mask;
420 XGCValues values;
421
422 mask = GCForeground | GCBackground | GCFillStyle | GCFunction | GCFont |
423 GCSubwindowMode | GCGraphicsExposures | GCPlaneMask;
424 values.function = GXcopy;
425 values.plane_mask = -1;
426 values.subwindow_mode = ClipByChildren;
427 values.graphics_exposures = False;
428 values.foreground = MGR_Foreground(w);
429 values.background = XtBackground(w);
430 values.fill_style = FillSolid;
431 values.font = Scale_FontStruct(w)->fid;
432
433 Scale_ForegroundGC(w) = XtGetGC(w, mask, &values);
434 }
435
436
437 static void
initialize(Widget request,Widget new_w,ArgList args,Cardinal * num_args)438 initialize(Widget request, Widget new_w,
439 ArgList args, Cardinal *num_args)
440 {
441 Widget title;
442 Widget sb;
443 Arg argl[15];
444 int argc;
445 /*
446 XmKidGeometry boxes;
447 Dimension wd, ht;
448 */
449
450 DEBUGOUT(_LtDebug(__FILE__, new_w,
451 "%s:initialize(%d) - %i args\n"
452 "\trequest X %5i Y %5i W %5i H %5i\n"
453 "\t new_w X %5i Y %5i W %5i H %5i\n",
454 __FILE__, __LINE__,
455 *num_args,
456 XtX(request), XtY(request),
457 XtWidth(request), XtHeight(request),
458 XtX(new_w), XtY(new_w),
459 XtWidth(new_w), XtHeight(new_w)));
460 DEBUGOUT(_LtDebugPrintArgList(__FILE__, new_w, args, *num_args, False));
461
462 if (Scale_ScaleWidth(new_w) == 0)
463 {
464 /* rws 22 Dec 1999
465 scale/test18 scale/test16
466 */
467 if (Scale_Orientation(new_w) == XmHORIZONTAL)
468 {
469 Scale_ScaleWidth(new_w) = XtWidth(request);
470 }
471 else
472 {
473 Scale_ScaleWidth(new_w) = XtHeight(request);
474 }
475 }
476 if (Scale_Value(new_w) == INT_MAX)
477 {
478 if (Scale_Minimum(new_w) >= 0)
479 {
480 Scale_Value(new_w) = Scale_Minimum(new_w);
481 }
482 else
483 {
484 Scale_Value(new_w) = 0;
485 }
486 }
487
488 if (Scale_ScaleMultiple(new_w) == 0)
489 {
490 Scale_ScaleMultiple(new_w) =
491 (Scale_Maximum(new_w) - Scale_Minimum(new_w)) / 10;
492 }
493
494 Scale_LastValue(new_w) = Scale_Value(new_w);
495
496 /* T. Straumann: there is no old value to be erased in showValue() */
497 Scale_ShowValueX(new_w) = SHOW_VALUE_X_INVALID;
498
499 if (Scale_FontList(new_w) == NULL)
500 {
501 Scale_FontList(new_w) = _XmGetDefaultFontList(new_w, XmLABEL_FONTLIST);
502 }
503 /* if user specified fontlist, COPY it */
504 else
505 {
506 Scale_FontList(new_w) = XmFontListCopy(Scale_FontList(new_w));
507 }
508
509 /* MLM FIX ME -- Should the titleString get the FontList from the scale? */
510 argc = 0;
511 if (Scale_Title(new_w) != NULL)
512 {
513 Scale_Title(new_w) = XmStringCopy(Scale_Title(new_w));
514 }
515 XtSetArg(argl[argc], XmNlabelString, Scale_Title(new_w)); argc++;
516 XtSetArg(argl[argc], XmNalignment, XmALIGNMENT_BEGINNING); argc++;
517
518 title = XmCreateLabelGadget(new_w, "Title", argl, argc);
519 if (Scale_Title(new_w) != NULL)
520 {
521 XtManageChild(title);
522 }
523
524 argc = 0;
525 XtSetArg(argl[argc], XmNshowArrows, False); argc++;
526 XtSetArg(argl[argc], XmNtraversalOn, True); argc++;
527 XtSetArg(argl[argc], XmNhighlightOnEnter, True); argc++;
528 XtSetArg(argl[argc], XmNmaximum, SCB_MAX); argc++;
529 XtSetArg(argl[argc], XmNminimum, SCB_MIN); argc++;
530 XtSetArg(argl[argc], XmNorientation, Scale_Orientation(new_w)); argc++;
531 XtSetArg(argl[argc], XmNprocessingDirection,
532 Scale_ProcessingDirection(new_w)); argc++;
533 XtSetArg(argl[argc], XmNwidth, Scale_ScaleWidth(new_w)); argc++;
534 XtSetArg(argl[argc], XmNheight, Scale_ScaleHeight(new_w)); argc++;
535 XtSetArg(argl[argc], XmNshadowThickness,
536 Scale_ShadowThickness(new_w)); argc++;
537 XtSetArg(argl[argc], XmNhighlightThickness,
538 Scale_HighlightThickness(new_w)); argc++;
539 XtSetArg(argl[argc], XmNhighlightOnEnter,
540 Scale_HighlightOnEnter(new_w)); argc++;
541 /* T. Straumann: M*TIF enforces 0 borderWidth for scrollBar */
542 XtSetArg(argl[argc], XmNborderWidth, 0); argc++;
543
544 sb = XmCreateScrollBar(new_w, "Scrollbar", argl, argc);
545
546 _XmSetEtchedSlider((XmScrollBarWidget)sb);
547
548 XtAddCallback(sb, XmNdragCallback, _ScaleDrag, NULL);
549
550 if (Scale_Value(new_w) == INT_MAX)
551 {
552 Scale_Value(new_w) = Scale_Minimum(new_w);
553 }
554
555 XtAddCallback(sb, XmNvalueChangedCallback, _ScaleValueChanged, NULL);
556 XtManageChild(sb);
557
558 _XmFontListGetDefaultFont(Scale_FontList(new_w), &Scale_FontStruct(new_w));
559
560 if (Scale_FontStruct(new_w) == NULL)
561 {
562 Scale_FontList(new_w) = _XmFontListCreateDefault(XtDisplay(new_w));
563
564 _XmFontListGetDefaultFont(Scale_FontList(new_w),
565 &Scale_FontStruct(new_w));
566 }
567
568 CreateForegroundGC(new_w);
569
570 #if 1
571 { Dimension ht, wd;
572 XmKidGeometry boxes;
573 wd = ht = 0;
574 boxes = _XmScalePreferredSize(new_w, NULL, NULL, &wd, &ht);
575 _XmScaleGeomRequest(new_w, &wd, &ht);
576 _XmScaleLayout(new_w, boxes, NULL, NULL, wd, ht);
577 _XmScaleConfigureChildren(new_w, NULL, boxes);
578 XtFree((char *)boxes);
579 }
580 #endif
581 }
582
583
584 static void
destroy(Widget w)585 destroy(Widget w)
586 {
587
588 if (Scale_Title(w))
589 {
590 XmStringFree(Scale_Title(w));
591 }
592 XmFontListFree(Scale_FontList(w));
593 XtDestroyGC(Scale_ForegroundGC(w));
594 }
595
596
597 /*
598 * called when the user changes a resource
599 */
600 /*
601 * FIX ME: changing sensitivity will move value.
602 */
603 static Boolean
set_values(Widget old,Widget request,Widget new_w,ArgList args,Cardinal * num_args)604 set_values(Widget old, Widget request, Widget new_w,
605 ArgList args, Cardinal *num_args)
606 {
607 Boolean refresh = False;
608 Arg argl[8];
609 int argc;
610 Widget sb, lab;
611 int resize = False;
612
613 DEBUGOUT(_LtDebug(__FILE__, new_w, "XmScale set_values()\n"));
614
615 sb = ((XmScaleWidget)new_w)->composite.children[CHILD_SB];
616 lab = ((XmScaleWidget)new_w)->composite.children[CHILD_LAB];
617
618 if (Scale_FontList(new_w) &&
619 Scale_FontList(new_w) != (XmFontList)XmUNSPECIFIED &&
620 Scale_FontList(new_w) != Scale_FontList(old))
621 {
622 XmFontListFree(Scale_FontList(old));
623 Scale_FontList(new_w) = XmFontListCopy(Scale_FontList(new_w));
624 }
625
626 if (MGR_Foreground(new_w) != MGR_Foreground(old) ||
627 XtBackground(new_w) != XtBackground(old) ||
628 Scale_FontList(new_w) != Scale_FontList(old))
629 {
630 _XmFontListGetDefaultFont(Scale_FontList(new_w),
631 &Scale_FontStruct(new_w));
632
633 if (Scale_FontStruct(new_w) == NULL)
634 {
635 Scale_FontList(new_w) = _XmFontListCreateDefault(XtDisplay(new_w));
636
637 _XmFontListGetDefaultFont(Scale_FontList(new_w),
638 &Scale_FontStruct(new_w));
639 }
640
641 XtReleaseGC(new_w, Scale_ForegroundGC(new_w));
642 CreateForegroundGC(new_w);
643
644 refresh = True;
645 }
646
647 if (Scale_Title(new_w) != Scale_Title(old))
648 {
649 if (Scale_Title(old))
650 {
651 XmStringFree(Scale_Title(old));
652 }
653
654 if (Scale_Title(new_w) != NULL)
655 {
656 Scale_Title(new_w) = XmStringCopy(Scale_Title(new_w));
657
658 argc = 0;
659
660 XtSetArg(argl[argc], XmNlabelString, Scale_Title(new_w)); argc++;
661 XtSetValues(lab, argl, argc);
662
663 if (!XtIsManaged(lab))
664 {
665 XtManageChild(lab);
666 }
667 }
668 }
669
670 if (Scale_Maximum(new_w) != Scale_Maximum(old) ||
671 Scale_Minimum(new_w) != Scale_Minimum(old) ||
672 Scale_ProcessingDirection(new_w) != Scale_ProcessingDirection(old) ||
673 Scale_ScaleMultiple(new_w) != Scale_ScaleMultiple(old) ||
674 Scale_HighlightOnEnter(new_w) != Scale_HighlightOnEnter(old) ||
675 Scale_HighlightThickness(new_w) != Scale_HighlightThickness(old) ||
676 Scale_Value(new_w) != Scale_Value(old))
677 {
678 int newval;
679 int inc, page_inc;
680
681
682 newval = _XmScaleConvertScaleValueToSCBValue(new_w);
683 _XmScaleConvertScaleIncrementToSCBIncrements(new_w, &inc, &page_inc);
684
685 argc = 0;
686 XtSetArg(argl[argc], XmNorientation, Scale_Orientation(new_w)); argc++;
687 XtSetArg(argl[argc], XmNprocessingDirection,
688 Scale_ProcessingDirection(new_w)); argc++;
689 XtSetArg(argl[argc], XmNvalue, newval); argc++;
690 XtSetArg(argl[argc], XmNincrement, inc); argc++;
691 XtSetArg(argl[argc], XmNpageIncrement, page_inc); argc++;
692 XtSetArg(argl[argc], XmNshadowThickness,
693 Scale_ShadowThickness(new_w)); argc++;
694 XtSetArg(argl[argc], XmNhighlightThickness,
695 Scale_HighlightThickness(new_w)); argc++;
696 XtSetArg(argl[argc], XmNhighlightOnEnter,
697 Scale_HighlightOnEnter(new_w)); argc++;
698 XtSetValues(sb, argl, argc);
699
700 refresh = True;
701 }
702
703 if (Scale_Orientation(new_w) != Scale_Orientation(old))
704
705 {
706 argc = 0;
707 XtSetArg(argl[argc], XmNorientation, Scale_Orientation(new_w)); argc++;
708
709 XtSetValues(sb, argl, argc);
710
711 /* Surprise, surprise, M*tif doesn't do a relayout here */
712 resize = False;
713 }
714
715 if (Scale_ScaleWidth(new_w) != Scale_ScaleWidth(old) ||
716 Scale_ScaleHeight(new_w) != Scale_ScaleHeight(old))
717 {
718 argc = 0;
719 if (Scale_ScaleWidth(new_w) != Scale_ScaleWidth(old) ) {
720 XtSetArg(argl[argc], XmNwidth, Scale_ScaleWidth(new_w)); argc++;
721 }
722 if ( Scale_ScaleHeight(new_w) != Scale_ScaleHeight(old) ) {
723 XtSetArg(argl[argc], XmNheight, Scale_ScaleHeight(new_w)); argc++;
724 }
725
726 XtSetValues(sb, argl, argc);
727
728 #if 0
729 resize = False;
730
731 /* FIX ME: adapt for new style _XmScaleLayout */
732 _XmScaleLayout(new_w, resize, NULL, False, NULL);
733 #endif
734
735 refresh = True;
736 }
737
738 /* T. Straumann: if Scale_ShowValue changed we have to
739 * do some more things
740 */
741 if (Scale_ShowValue(new_w) != Scale_ShowValue(old))
742 {
743 refresh = True;
744 if ( ! Scale_ShowValue(new_w) )
745 {
746 /* undraw the old value */
747 if (XtIsRealized(old) && SHOW_VALUE_X_INVALID != Scale_ShowValueX(old))
748 {
749 XFillRectangle(XtDisplay(old), XtWindow(old), MGR_BackgroundGC(old),
750 Scale_ShowValueX(old), Scale_ShowValueY(old),
751 Scale_ShowValueWidth(old), Scale_ShowValueHeight(old));
752 }
753 }
754 /* Mark Scale_ShowValueX as invalid */
755 Scale_ShowValueX(new_w) = SHOW_VALUE_X_INVALID;
756 }
757
758 if (Scale_Maximum(new_w) != Scale_Maximum(old) ||
759 Scale_Minimum(new_w) != Scale_Minimum(old) ||
760 Scale_DecimalPoints(new_w) != Scale_DecimalPoints(old) ||
761 Scale_FontList(new_w) != Scale_FontList(old))
762 {
763 refresh = True;
764
765 if (Scale_ShowValue(new_w))
766 {
767 computeValueSize(new_w);
768 if (XtIsRealized(old) && SHOW_VALUE_X_INVALID != Scale_ShowValueX(old))
769 {
770 XFillRectangle(XtDisplay(old), XtWindow(old), MGR_BackgroundGC(old),
771 Scale_ShowValueX(old), Scale_ShowValueY(old),
772 Scale_ShowValueWidth(old), Scale_ShowValueHeight(old));
773 }
774 Scale_ShowValueX(new_w) = SHOW_VALUE_X_INVALID;
775 }
776 #if 0
777 resize = False;
778
779 /* FIX ME: adapt for new style _XmScaleLayout */
780 _XmScaleLayout(new_w, resize, NULL, False, XtWidth(new_w),
781 XtHeight(new_w));
782 #endif
783 }
784
785 #if 0
786 /* dunno about this */
787 XmKidGeometry boxes;
788 Dimension wd, ht;
789
790 wd = XtWidth(new_w);
791 ht = XtHeight(new_w);
792 boxes = _XmScalePreferredSize(new_w, NULL, NULL, &wd, &ht);
793
794 _XmScaleGeomRequest(new_w, &wd, &ht);
795 _XmScaleLayout(new_w, boxes, NULL, NULL, wd, ht);
796 _XmScaleConfigureChildren(new_w, NULL, boxes);
797
798 XtFree((char *)boxes);
799 #endif
800
801 return refresh;
802 }
803
804
805 static void
expose(Widget w,XEvent * event,Region region)806 expose(Widget w,
807 XEvent *event,
808 Region region)
809 {
810 DEBUGOUT(_LtDebug(__FILE__, w, "XmScale expose()\n"));
811
812 _XmRedisplayGadgets(w, event, region);
813
814 if (Scale_ShowValue(w))
815 {
816 showValue(w,
817 _XmScaleConvertScaleValueToSCBValue(w),
818 Scale_Value(w));
819 }
820 }
821
822
823 /*
824 * called when our parent wants to find out how we would like to look. It
825 * doesn't have to honor our preference, though.
826 */
827 static XtGeometryResult
query_geometry(Widget w,XtWidgetGeometry * request,XtWidgetGeometry * reply)828 query_geometry(Widget w, XtWidgetGeometry *request, XtWidgetGeometry *reply)
829 {
830 #if 0
831 XtWidgetGeometry wants;
832 XmKidGeometry boxes;
833 Dimension wd, ht;
834
835 #define Wants(x) ((wants.request_mode & x) == x)
836
837 DEBUGOUT(_LtDebug(__FILE__, w, "XmScale %s QueryGeometry\n", XtName(w)));
838
839 wants = *request;
840 *reply = *request;
841 reply->request_mode = 0;
842
843 if (Wants(CWWidth))
844 {
845 reply->request_mode |= CWWidth;
846 reply->width = XtWidth(w);
847 }
848
849 if (Wants(CWHeight))
850 {
851 reply->request_mode |= CWHeight;
852 reply->height = XtHeight(w);
853 }
854
855 boxes = _XmScalePreferredSize(w, NULL, NULL, &wd, &ht);
856
857 reply->width = wd;
858 reply->height = ht;
859
860 if (Wants(CWHeight) && (wants.height < reply->height))
861 {
862 return XtGeometryNo;
863 }
864 else if (Wants(CWHeight) && (wants.height > reply->height))
865 {
866 return XtGeometryAlmost;
867 }
868
869 if (Wants(CWWidth) && (wants.width < reply->width))
870 {
871 return XtGeometryNo;
872 }
873 else if (Wants(CWWidth) && (wants.width > reply->width))
874 {
875 return XtGeometryAlmost;
876 }
877
878 return XtGeometryYes;
879
880 #undef Wants
881 #else
882 XtWidgetGeometry wants;
883 Dimension wd, ht;
884
885 DEBUGOUT(_LtDebug(__FILE__, w, "XmScale %s QueryGeometry\n", XtName(w)));
886
887 wants = *request;
888
889 _XmScalePreferredSize(w, NULL, NULL, &wd, &ht);
890
891 reply->width = wd;
892 reply->height = ht;
893
894 return _XmGMReplyToQueryGeometry(w, &wants, reply);
895 #endif
896 }
897
898
899 /*
900 * called when our parent is resizing us. We have no choice but to obey.
901 */
902 static void
resize(Widget w)903 resize(Widget w)
904 {
905 XmKidGeometry boxes;
906 Dimension wd, ht;
907
908 DEBUGOUT(_LtDebug(__FILE__, w, "Scale %s Resize: x %d y %d w %d h %d\n",
909 XtName(w), XtX(w), XtY(w), XtWidth(w), XtHeight(w)));
910
911 Scale_SliderSize(w) = _XmScaleConvertWidthToSliderSize(w);
912
913 wd = XtWidth(w);
914 ht = XtHeight(w);
915 boxes = _XmScalePreferredSize(w, NULL, NULL, &wd, &ht);
916
917 _XmScaleLayout(w, boxes, NULL, NULL, wd, ht);
918
919 _XmScaleConfigureChildren(w, NULL, boxes);
920
921 XtFree((char *)boxes);
922 }
923
924
925 /*
926 * called when one of our children wants to change. We control whether
927 * the child can, or not
928 * Note that the scrolbar can't change it's size.
929 */
930 #define Wants(x) (wants.request_mode & x)
931 static XtGeometryResult
geometry_manager(Widget w,XtWidgetGeometry * request,XtWidgetGeometry * reply)932 geometry_manager(Widget w, XtWidgetGeometry *request, XtWidgetGeometry *reply)
933 {
934 Dimension wd, ht;
935 XmKidGeometry boxes;
936 XtWidgetGeometry wants;
937
938 DEBUGOUT(_LtDebug(__FILE__, w, "XmScale geometry_manager()\n"));
939
940 wants = *request;
941
942 if ((Wants(CWX) /* FIX ME: && request->x != XtX(w) */ ) ||
943 (Wants(CWY) /* FIX ME: && request->y != XtY(w) */ ))
944 {
945 return XtGeometryNo;
946 }
947
948 /* FIX ME: Should XtCWQueryOnly be handled at all? */
949 if (Wants(XtCWQueryOnly))
950 {
951 _XmWarning(XtParent(w),
952 "FIX ME: XtCWQueryOnly not handled (child %s)\n",
953 XtName(w));
954 }
955
956 boxes = _XmScalePreferredSize(XtParent(w), w, request, &wd, &ht);
957
958 _XmScaleGeomRequest(XtParent(w), &wd, &ht);
959
960 *reply = *request;
961 reply->request_mode &= CWWidth|CWHeight;
962
963 if (Wants(CWWidth) && Wants(CWHeight) &&
964 wants.width == reply->width && wants.height == reply->height)
965 {
966 _XmScaleConfigureChildren(XtParent(w), w, boxes);
967
968 return XtGeometryYes;
969 }
970
971 if (Wants(CWWidth) && wants.width == reply->width)
972 {
973 _XmScaleConfigureChildren(XtParent(w), w, boxes);
974
975 return XtGeometryYes;
976 }
977
978 if (Wants(CWHeight) && wants.height == reply->height)
979 {
980 _XmScaleConfigureChildren(XtParent(w), w, boxes);
981
982 return XtGeometryYes;
983 }
984
985 if (Wants(CWWidth) && wants.width == reply->width)
986 {
987 reply->request_mode &= ~CWWidth;
988 }
989 if (Wants(CWHeight) && wants.height == reply->height)
990 {
991 reply->request_mode &= ~CWHeight;
992 }
993 return XtGeometryAlmost;
994 #undef Wants
995 }
996
997
998 /*
999 * called when our Window is allocated. We may want to change our layout,
1000 * and we can ask our parent to allow this
1001 */
1002 static void
realize(Widget w,XtValueMask * value_mask,XSetWindowAttributes * attributes)1003 realize(Widget w, XtValueMask *value_mask, XSetWindowAttributes *attributes)
1004 {
1005 /*
1006 Dimension wd, ht;
1007 Dimension pwd, pht;
1008 XmKidGeometry boxes;
1009 */
1010
1011 DEBUGOUT(_LtDebug(__FILE__, w, "XmScale realize()\n"));
1012
1013 #define superclass (&xmManagerClassRec)
1014 (*superclass->core_class.realize) (w, value_mask, attributes);
1015 #undef superclass
1016
1017 #if 0
1018 wd = ht = 0;
1019 boxes = _XmScalePreferredSize(w, NULL, NULL, &wd, &ht);
1020 pwd = wd;
1021 pht = ht;
1022
1023 _XmScaleGeomRequest(w, &wd, &ht);
1024 _XmScaleLayout(w, boxes, NULL, NULL, pwd, pht);
1025 _XmScaleConfigureChildren(w, NULL, boxes);
1026
1027 XtFree((char *)boxes);
1028 #endif
1029 }
1030
1031
1032 /*
1033 * one of our children has become managed or unmanaged. We need to relayout
1034 */
1035 static void
change_managed(Widget w)1036 change_managed(Widget w)
1037 {
1038 Dimension wd, ht;
1039 XmKidGeometry boxes;
1040
1041 DEBUGOUT(_LtDebug(__FILE__, w, "XmScale change_managed()\n"));
1042
1043 wd = ht = 0;
1044 boxes = _XmScalePreferredSize(w, NULL, NULL, &wd, &ht);
1045
1046 _XmScaleGeomRequest(w, &wd, &ht);
1047
1048 _XmScaleLayout(w, boxes, NULL, NULL, wd, ht);
1049
1050 _XmScaleConfigureChildren(w, NULL, boxes);
1051
1052 XtFree((char *)boxes);
1053
1054 _XmNavigChangeManaged(w);
1055 }
1056
1057
1058 #if 0
1059 /*
1060 * a child has been added
1061 */
1062 static void
1063 insert_child(Widget w)
1064 {
1065 #define superclass (&xmManagerClassRec)
1066 (*superclass->composite_class.insert_child) (w);
1067 #undef superclass
1068
1069 DEBUGOUT(_LtDebug(__FILE__, w,
1070 "Scale %s: insert child %s\n",
1071 XtName(XtParent(w)), XtName(w)));
1072 }
1073 #endif
1074
1075
1076 extern Widget
XmCreateScale(Widget parent,char * name,Arg * arglist,Cardinal argcount)1077 XmCreateScale(Widget parent,
1078 char *name,
1079 Arg *arglist,
1080 Cardinal argcount)
1081 {
1082 return XtCreateWidget(name,
1083 xmScaleWidgetClass,
1084 parent,
1085 arglist,
1086 argcount);
1087 }
1088
1089
1090 extern void
XmScaleGetValue(Widget widget,int * value_return)1091 XmScaleGetValue(Widget widget,
1092 int *value_return)
1093 {
1094 *value_return = Scale_Value(widget);
1095 }
1096
1097
1098 extern void
XmScaleSetValue(Widget widget,int value)1099 XmScaleSetValue(Widget widget,
1100 int value)
1101 {
1102 Widget sb;
1103 int newval;
1104
1105 sb = ((XmScaleWidget)widget)->composite.children[CHILD_SB];
1106
1107 if (value < Scale_Minimum(widget) || value > Scale_Maximum(widget))
1108 {
1109 return;
1110 }
1111
1112 Scale_Value(widget) = value;
1113 newval = _XmScaleConvertScaleValueToSCBValue(widget);
1114
1115 XtVaSetValues((Widget)sb,
1116 XmNvalue, newval,
1117 NULL);
1118
1119 if (Scale_ShowValue(widget))
1120 {
1121 showValue(widget, newval, Scale_Value(widget));
1122 }
1123 }
1124
1125
1126 static void
valueToString(Widget w,char * buf)1127 valueToString(Widget w, char *buf)
1128 {
1129 int base, i;
1130 char buf2[17]; /* anybody got larger than 64 bit ints? */
1131
1132 if (Scale_DecimalPoints(w) <= 0)
1133 {
1134 sprintf(buf, "%d", Scale_Value(w));
1135 }
1136 else
1137 {
1138 /* I'd like to use %d.%*d here, but not everyone has that */
1139 base = 10;
1140 for (i = 1; i < Scale_DecimalPoints(w); i++)
1141 {
1142 base *= 10;
1143 }
1144
1145 #if 0
1146 sprintf(buf, "%d.", Scale_Value(w) / base);
1147 #else
1148 sprintf(buf, "%s%d.", Scale_Value(w) >= 0 ? "" : "-",
1149 abs(Scale_Value(w) / base));
1150 #endif
1151 for (i = 1; i <= Scale_DecimalPoints(w); i++)
1152 {
1153 strcat(buf, "0");
1154 }
1155
1156 #if 0
1157 sprintf(buf2, "%d", Scale_Value(w) % base);
1158 #else
1159 sprintf(buf2, "%d", abs(Scale_Value(w) % base));
1160 #endif
1161 strcpy(&buf[strlen(buf) - strlen(buf2)], buf2);
1162 }
1163 }
1164
1165 /*
1166 * layout rules
1167 *
1168 * scrollbar stays at rightmost or bottommost position, when no label
1169 * ScaleWidth/ScaleHeight are hints. If it is set, pay attention to it;
1170 * otherwise, obey the parent.
1171 *
1172 * FIX ME - currently, we always allow a widget to resize.
1173 *
1174 * FIX ME: signs are some of the XtIsManaged tests will have to go.
1175 *
1176 * FIX ME: if scaleWidth/Height is specified scrollbar_width/height can
1177 * get arbitrary small. If width/height is specified slider_width/height
1178 * is bound to a minimum.
1179 *
1180 * FIX ME:
1181 * Srollbar should not go off the scale by wide tick marks.
1182 * Children's initial geometry not respected.
1183 *
1184 * FIX ME: tick mark x/y seems to have a minimum value of -4
1185 *
1186 * layout is normal processing as per the M*tif docs
1187 * (Hmm.. tick marks and title get laid out on opposite sides of SB -- PvH)
1188 * per me, this is as follows (FIX ME -- this is not complete):
1189 * if (orientation is HORIZONTAL) then
1190 * layout title (if managed), and other children (if present)
1191 * along the bottom edge. This initially defines our preferred
1192 * width, and the tallest child defines the slider's bottom edge.
1193 * if (TestMode) then
1194 * if the child widget argument is the same as the current child
1195 * and the geometry request is a match for the calculated
1196 * geometry, the return XtGeometryYes.
1197 * else
1198 * return XtGeometryNo
1199 * endif
1200 * endif
1201 * layout the slider above the tallest managed child other than the
1202 * scrollbar (if any).
1203 * if (ScaleHeight hint is set) then
1204 * we must use that as the slider height
1205 * else
1206 * use the default slider height
1207 * endif
1208 * if (ScaleWidth hint is set)
1209 * we must use it as the slider width
1210 * else
1211 * use our width as the slider width
1212 * endif
1213 * if (TestMode) then
1214 * if the child widget argument is the same as the current child
1215 * and the geometry request is a match for the calculated
1216 * geometry, the return XtGeometryYes.
1217 * else
1218 * return XtGeometryNo
1219 * endif
1220 * endif
1221 * layout the value (if ShowValue is true) to be from the top of the
1222 * slider. The value should not affect the width calculation.
1223 * else if (orientation is VERTICAL) then
1224 * layout title (if managed), and other children (if present)
1225 * along the right edge. This initially defines our preferred
1226 * height, and the tallest child defines the slider's right edge.
1227 * if (TestMode) then
1228 * if the child widget argument is the same as the current child
1229 * and the geometry request is a match for the calculated
1230 * geometry, the return XtGeometryYes.
1231 * else
1232 * return XtGeometryNo
1233 * endif
1234 * endif
1235 * layout the slider left of the tallest managed child other than the
1236 * scrollbar (if any).
1237 * if (ScaleWidth hint is set) then
1238 * we must use that as the slider width
1239 * else
1240 * use the default slider width
1241 * endif
1242 * if (ScaleHeight hint is set)
1243 * we must use it as the slider height
1244 * else
1245 * use our height as the slider height
1246 * endif
1247 * if (TestMode) then
1248 * if the child widget argument is the same as the current child
1249 * and the geometry request is a match for the calculated
1250 * geometry, the return XtGeometryYes.
1251 * else
1252 * return XtGeometryNo
1253 * endif
1254 * endif
1255 * layout the value (if ShowValue is true) to be from the right of the
1256 * slider. The value should not affect the height calculation.
1257 * endif
1258 *
1259 * we have now computed our preferred width and height, or returned.
1260 * if (ParentResizeMode) then
1261 * do
1262 * request size change
1263 * while (change not allowed, but close)
1264 * our width = new width
1265 * our height = new height
1266 * else
1267 * our width = XtWidth
1268 * our height = XtHeight
1269 * endif
1270 *
1271 * if (our width < preferred width) then
1272 * compute layouts that maximize the display of the scrollbar and
1273 * the value (if ShowValue is true)
1274 * else
1275 * compute proportional layouts
1276 * endif
1277 * if (our height < preferred height) then
1278 * compute layouts that maximize the display of the scrollbar and
1279 * the value (if ShowValue is true)
1280 * else
1281 * compute proportional layouts
1282 * endif
1283 *
1284 * for each widget
1285 * XmConfigureWidget
1286 * endfor
1287 *
1288 * end algorithm
1289 *
1290 * My additions:
1291 * never allow a child to request an XY change. (is this correct?)
1292 * the ScrollBar shall always be children[1]
1293 * the LabelGadget shall always be children[0]
1294 * This is per M*tif!
1295 */
1296 static XmKidGeometry
_XmScalePreferredSize(Widget scale,Widget child,XtWidgetGeometry * childgeom,Dimension * wd,Dimension * ht)1297 _XmScalePreferredSize(Widget scale, Widget child, XtWidgetGeometry *childgeom,
1298 Dimension *wd, Dimension *ht)
1299 {
1300 Position curx, cury;
1301 XmKidGeometry boxes;
1302 Dimension curw, curh;
1303 Dimension incw, inch;
1304 int maxw, maxh;
1305 Widget *children;
1306 int num_children;
1307 int i, cnt;
1308
1309 curx = cury = 0;
1310 curw = curh = 0;
1311 incw = inch = 0;
1312 maxw = maxh = 0;
1313
1314 num_children = MGR_NumChildren(scale);
1315 children = MGR_Children(scale);
1316
1317 boxes = (XmKidGeometry)XtCalloc(num_children + 1, sizeof(XmKidGeometryRec));
1318
1319 boxes[CHILD_SB].kid = children[CHILD_SB];
1320 if (children[CHILD_SB])
1321 {
1322 _XmGeoLoadValues(children[CHILD_SB], XmGET_PREFERRED_SIZE,
1323 child, childgeom, &boxes[CHILD_SB].box);
1324 }
1325
1326 boxes[CHILD_LAB].kid = children[CHILD_LAB];
1327 if (children[CHILD_LAB])
1328 {
1329 _XmGeoLoadValues(children[CHILD_LAB], XmGET_PREFERRED_SIZE,
1330 child, childgeom, &boxes[CHILD_LAB].box);
1331 }
1332
1333 for (i = 2, cnt = 2; i < num_children; i++)
1334 {
1335 if (XtIsManaged(children[i]))
1336 {
1337 boxes[cnt].kid = children[i];
1338
1339 _XmGeoLoadValues(children[i], XmGET_PREFERRED_SIZE,
1340 child, childgeom, &boxes[cnt].box);
1341
1342 if (maxw < boxes[cnt].box.width)
1343 {
1344 maxw = boxes[cnt].box.width;
1345 }
1346 if (maxh < boxes[cnt].box.height)
1347 {
1348 maxh = boxes[cnt].box.height;
1349 }
1350
1351 cnt++;
1352 }
1353 else
1354 {
1355 boxes[i].kid = NULL;
1356 }
1357 }
1358
1359 boxes[i].kid = NULL;
1360
1361 num_children = cnt;
1362
1363 /*
1364 * compute it.
1365 */
1366 if (Scale_Orientation(scale) == XmHORIZONTAL)
1367 {
1368
1369 curh = maxh;
1370 cury = maxh;
1371
1372 /*
1373 * do the value, if there is one
1374 */
1375 if (Scale_ShowValue(scale))
1376 {
1377
1378 computeValueSize(scale);
1379
1380 incw = Scale_ShowValueWidth(scale);
1381 inch = Scale_ShowValueHeight(scale);
1382
1383 if (incw > curw)
1384 {
1385 curw = incw;
1386 }
1387 curh += inch;
1388
1389 cury += inch;
1390 }
1391
1392 /*
1393 * then do the ScrollBar
1394 */
1395 if (XtIsManaged(boxes[CHILD_SB].kid))
1396 {
1397
1398 boxes[CHILD_SB].box.x = curx;
1399 boxes[CHILD_SB].box.y = cury;
1400
1401 inch = Scale_ScaleHeight(scale);
1402
1403 if (inch == 0)
1404 {
1405 inch = SB_TRANSVERSAL_SIZE +
1406 2 * Scale_HighlightThickness(scale);
1407 }
1408
1409 incw = Scale_ScaleWidth(scale);
1410
1411 if (incw == 0)
1412 {
1413 incw = XtWidth(scale);
1414 }
1415
1416 #if 0
1417 if (incw == 0 && num_children >= 3)
1418 #else
1419 if (Scale_ScaleWidth(scale) == 0 && num_children >= 3)
1420 #endif
1421 {
1422 if (num_children == 3)
1423 {
1424 incw = boxes[2].box.width;
1425 }
1426 else
1427 {
1428 incw = HSLIDERSIZE +
1429 2 * (Prim_HighlightThickness(boxes[CHILD_SB].kid) +
1430 Prim_ShadowThickness(boxes[CHILD_SB].kid)) +
1431 maxw * (num_children - 3);
1432 }
1433 }
1434
1435 if (incw == 0)
1436 {
1437 incw = SB_LONGITUDAL_SIZE + 2 * Scale_HighlightThickness(scale);
1438 }
1439
1440 boxes[CHILD_SB].box.width = incw;
1441 boxes[CHILD_SB].box.height = inch;
1442
1443 if (incw > curw)
1444 {
1445 curw = incw;
1446 }
1447
1448 curh += inch;
1449 cury += inch;
1450 }
1451
1452 /* lay out the tick marks */
1453 if (num_children > 2)
1454 {
1455 /* centres are nicely aligned */
1456
1457 if (num_children > 3)
1458 {
1459 int spacing;
1460
1461 if (curw == 0)
1462 {
1463 spacing = maxw * (num_children - 3);
1464 }
1465 else
1466 {
1467 spacing = (curw -
1468 (HSLIDERSIZE +
1469 2 * (Prim_HighlightThickness(boxes[CHILD_SB].kid) +
1470 Prim_ShadowThickness(boxes[CHILD_SB].kid))));
1471 }
1472
1473 for (i = 2; i < num_children; i++)
1474 {
1475 boxes[i].box.y = (maxh - boxes[i].box.height) / 2;
1476 boxes[i].box.x = (HSLIDERSIZE - boxes[i].box.width) / 2 +
1477 Prim_HighlightThickness(boxes[CHILD_SB].kid) +
1478 Prim_ShadowThickness(boxes[CHILD_SB].kid) +
1479 (i - 2) * spacing / (num_children - 3);
1480 }
1481 }
1482 else
1483 {
1484 boxes[2].box.y = 0;
1485 boxes[2].box.x = (curw - boxes[2].box.width) / 2;
1486 }
1487 }
1488
1489 /*
1490 * then the title, if there is one
1491 */
1492 if (Scale_Title(scale) && XtIsManaged(boxes[CHILD_LAB].kid))
1493 {
1494 boxes[CHILD_LAB].box.x = curx;
1495 boxes[CHILD_LAB].box.y = cury;
1496
1497 incw = boxes[CHILD_LAB].box.width;
1498 inch = boxes[CHILD_LAB].box.height;
1499
1500 if (incw > curw)
1501 {
1502 curw = incw;
1503 }
1504 curh += inch;
1505
1506 curx += incw;
1507 curh += 2 * MGR_ShadowThickness(scale);
1508 }
1509 }
1510 /* XmNorientation == XmVERTICAL */
1511 else
1512 {
1513
1514 curw = maxw;
1515 curx = maxw;
1516
1517 /*
1518 * do the value, if there is one
1519 */
1520 if (Scale_ShowValue(scale))
1521 {
1522
1523 computeValueSize(scale);
1524
1525 inch = Scale_ShowValueHeight(scale);
1526 incw = Scale_ShowValueWidth(scale);
1527
1528 if (inch > curh)
1529 {
1530 curh = inch;
1531 }
1532
1533 curw += incw;
1534
1535 curx += incw;
1536 }
1537
1538 /*
1539 * then do the ScrollBar
1540 */
1541 if (XtIsManaged(boxes[CHILD_SB].kid))
1542 {
1543 boxes[CHILD_SB].box.x = curx;
1544 boxes[CHILD_SB].box.y = cury;
1545
1546 incw = Scale_ScaleWidth(scale);
1547
1548 if (incw == 0)
1549 {
1550 incw = SB_TRANSVERSAL_SIZE +
1551 2 * Scale_HighlightThickness(scale);
1552 }
1553
1554 inch = Scale_ScaleHeight(scale);
1555
1556 if (inch == 0)
1557 {
1558 inch = XtHeight(scale);
1559 }
1560
1561 #if 0
1562 if (inch == 0 && num_children >= 3)
1563 #else
1564 if (Scale_ScaleHeight(scale) == 0 && num_children >= 3)
1565 #endif
1566 {
1567 if (num_children == 3)
1568 {
1569 inch = boxes[2].box.height;
1570 }
1571 else
1572 {
1573 /* FIX ME: SrollBar's or Scale's? */
1574 inch = HSLIDERSIZE +
1575 2 * (Prim_HighlightThickness(boxes[CHILD_SB].kid) +
1576 Prim_ShadowThickness(boxes[CHILD_SB].kid)) +
1577 maxh * (num_children - 3);
1578 }
1579 }
1580
1581 if (inch == 0)
1582 {
1583 inch = SB_LONGITUDAL_SIZE + 2 * Scale_HighlightThickness(scale);
1584 }
1585
1586 boxes[CHILD_SB].box.width = incw;
1587 boxes[CHILD_SB].box.height = inch;
1588
1589 if (inch > curh)
1590 {
1591 curh = inch;
1592 }
1593
1594 curw += incw;
1595 curx += incw;
1596 }
1597
1598 /* lay out the tick marks */
1599 if (num_children > 2)
1600 {
1601 /* centres are nicely aligned */
1602
1603 if (num_children > 3)
1604 {
1605 int spacing;
1606
1607 if (curh == 0)
1608 {
1609 spacing = maxh * (num_children - 3);
1610 }
1611 else
1612 {
1613 spacing = (curh - (HSLIDERSIZE +
1614 2 * (Prim_HighlightThickness(boxes[CHILD_SB].kid) +
1615 Prim_ShadowThickness(boxes[CHILD_SB].kid))));
1616 }
1617 printf("curh %i %i %i %i %i %i %i\n",
1618 spacing,
1619 curh,
1620 HSLIDERSIZE,
1621 maxh,
1622 num_children,
1623 Prim_HighlightThickness(boxes[CHILD_SB].kid),
1624 Prim_ShadowThickness(boxes[CHILD_SB].kid));
1625
1626 for (i = 2; i < num_children; i++)
1627 {
1628 boxes[i].box.x = (maxw - boxes[i].box.width) / 2;
1629 boxes[i].box.y = 1 + (HSLIDERSIZE - boxes[i].box.height) / 2 +
1630 Prim_HighlightThickness(boxes[CHILD_SB].kid) +
1631 Prim_ShadowThickness(boxes[CHILD_SB].kid) +
1632 (i - 2) * spacing / (num_children - 3);
1633 }
1634 #if 1
1635 /* scale/test13 ???? */
1636 curh++;
1637 boxes[CHILD_SB].box.height++;
1638 #endif
1639 }
1640 else
1641 {
1642 boxes[2].box.x = 0;
1643 boxes[2].box.y = (curh - boxes[2].box.height) / 2;
1644 }
1645 }
1646
1647 /*
1648 * then the title, if there is one
1649 */
1650 if (Scale_Title(scale) && XtIsManaged(boxes[CHILD_LAB].kid))
1651 {
1652
1653 boxes[CHILD_LAB].box.x = curx;
1654 boxes[CHILD_LAB].box.y = cury;
1655
1656
1657 incw = boxes[CHILD_LAB].box.width;
1658 inch = boxes[CHILD_LAB].box.height;
1659
1660 if (inch > curh)
1661 {
1662 curh = inch;
1663 }
1664
1665 curw += incw;
1666 cury += inch;
1667 curw += 2 * MGR_ShadowThickness(scale);
1668 /*
1669 printf("COMPUTED %d %d : %d %d\n", curw, cury, incw, inch);
1670 */
1671 }
1672 }
1673
1674 /*
1675 * if we're being queried for our geometry, return what we've got
1676 */
1677 *wd = curw;
1678 *ht = curh;
1679
1680 return boxes;
1681 }
1682
1683
1684 /*
1685 * if we can, change our size to match
1686 */
1687 static XtGeometryResult
_XmScaleGeomRequest(Widget scale,Dimension * wd,Dimension * ht)1688 _XmScaleGeomRequest(Widget scale, Dimension *wd, Dimension *ht)
1689 {
1690 XtWidgetGeometry request;
1691 XtGeometryResult result;
1692
1693 request.request_mode = (CWWidth | CWHeight);
1694 request.width = *wd;
1695 request.height = *ht;
1696
1697 DEBUGOUT(_LtDebug(__FILE__, scale, "_XmScaleGeomRequest(ing) (%d %d)\n",
1698 *wd, *ht));
1699
1700 result = _XmMakeGeometryRequest(scale, &request);
1701
1702 if (result == XtGeometryYes)
1703 {
1704 *wd = request.width;
1705 *ht = request.height;
1706 }
1707 else
1708 {
1709 *wd = XtWidth(scale);
1710 *ht = XtHeight(scale);
1711 }
1712
1713 DEBUGOUT(_LtDebug(__FILE__, scale, "_XmScaleLayout (%d %d) => %s\n",
1714 *wd, *ht, _LtDebugGeometryResult2String(result)));
1715
1716 return result;
1717 }
1718
1719
1720 static void
_XmScaleLayout(Widget scale,XmKidGeometry boxes,Widget child,XtWidgetGeometry * childgeom,Dimension curw,Dimension curh)1721 _XmScaleLayout(Widget scale, XmKidGeometry boxes,
1722 Widget child, XtWidgetGeometry *childgeom,
1723 Dimension curw, Dimension curh)
1724 {
1725 int i, delta;
1726
1727 int num_children = MGR_NumChildren(scale);
1728 /*
1729 * do the layout
1730 */
1731 if (Scale_Orientation(scale) == XmHORIZONTAL)
1732 {
1733 #if 0
1734 if (Scale_ScaleWidth(scale) == 0)
1735 boxes[CHILD_SB].box.width = XtWidth(scale);
1736
1737 if (boxes[CHILD_SB].box.width < (HSLIDERSIZE + MIN_SLIDE +
1738 2 * Prim_ShadowThickness(children[CHILD_SB]) +
1739 2 * Scale_HighlightThickness(scale)))
1740 {
1741 boxes[CHILD_SB].box.width = (HSLIDERSIZE + MIN_SLIDE +
1742 2 * Prim_ShadowThickness(children[CHILD_SB]) +
1743 2 * Scale_HighlightThickness(scale));
1744 boxes[CHILD_SB].box.x = (XtWidth(scale) -
1745 boxes[CHILD_SB].box.width) / 2;
1746 }
1747
1748 if (num_children == 2)
1749 {
1750 boxes[CHILD_LAB].box.width = boxes[CHILD_SB].box.width;
1751 boxes[CHILD_LAB].box.x = boxes[CHILD_SB].box.x;
1752 }
1753
1754 if (XtHeight(scale) < (boxes[CHILD_SB].box.y + VSLIDERSIZE +
1755 2 * Prim_ShadowThickness(children[CHILD_SB]) +
1756 2 * Scale_HighlightThickness(scale)))
1757 {
1758 boxes[CHILD_SB].box.y -= (boxes[CHILD_SB].box.y + VSLIDERSIZE +
1759 2 * Prim_ShadowThickness(children[CHILD_SB]) +
1760 2 * Scale_HighlightThickness(scale)) -
1761 XtHeight(scale) + 1;
1762 }
1763
1764 if (XtWidth(scale) > curw)
1765 {
1766 for (i = 2; i < num_children; i++)
1767 {
1768 boxes[i].box.width = (Dimension)((double)boxes[i].box.width /
1769 (double)curw *
1770 (double)XtWidth(scale));
1771 }
1772 }
1773 #endif /* 0 */
1774
1775 if ((delta = XtHeight(scale) - curh))
1776 {
1777 if (delta < 0 && XtIsManaged(boxes[CHILD_LAB].kid))
1778 {
1779 delta += boxes[CHILD_LAB].box.height +
1780 (MGR_ShadowThickness(scale) << 1);
1781 if (delta > 0)
1782 delta = 0;
1783 }
1784 for (i = 0; i < 2 && boxes[i].kid; i++)
1785 {
1786 boxes[i].box.y += delta;
1787 }
1788 }
1789
1790 /* T. Straumann: adjust width / tickmark positions if our geometry
1791 * is different from the one used in _XmScalePreferredSize().
1792 *
1793 * They do this only if Scale_ScaleWidth() == 0 or delta < 0
1794 * as can be confirmed by test14. Try also to resize
1795 *
1796 * test13 -xrm "*scaleHeight:200"
1797 *
1798 * using the WM
1799 */
1800 delta = XtWidth(scale) - curw;
1801 if ( delta < 0 || (delta > 0 && 0 == Scale_ScaleWidth(scale) ) )
1802 {
1803 /* different layout whether one or more tick marks are present */
1804 int denom = (num_children == 3 ? 2 : num_children -3);
1805 for (i = 0; boxes[i].kid; i++)
1806 {
1807 switch (i)
1808 {
1809 /* adjust the width of SB and LAB */
1810 case CHILD_LAB:
1811 case CHILD_SB:
1812 boxes[i].box.width = XtWidth(scale);
1813 break;
1814
1815 /* adjust the tick marks */
1816
1817 default:
1818 boxes[i].box.x += delta * (i - 2) / denom;
1819 break;
1820 }
1821 }
1822 }
1823
1824 }
1825 else if (Scale_Orientation(scale) == XmVERTICAL)
1826 {
1827 #if 0
1828 if (Scale_ScaleHeight(scale) == 0)
1829 boxes[CHILD_SB].box.height = XtHeight(scale);
1830
1831 if (boxes[CHILD_SB].box.height < (HSLIDERSIZE + MIN_SLIDE +
1832 2 * Prim_ShadowThickness(children[CHILD_SB]) +
1833 2 * Scale_HighlightThickness(scale)))
1834 {
1835 boxes[CHILD_SB].box.height = (HSLIDERSIZE + MIN_SLIDE +
1836 2 * Prim_ShadowThickness(children[CHILD_SB]) +
1837 2 * Scale_HighlightThickness(scale));
1838 boxes[CHILD_SB].box.y = (XtHeight(scale) -
1839 boxes[CHILD_SB].box.height) / 2;
1840 }
1841
1842 if (num_children == 2)
1843 {
1844 boxes[CHILD_LAB].box.height = boxes[CHILD_SB].box.height;
1845 boxes[CHILD_LAB].box.y = boxes[CHILD_SB].box.y;
1846 }
1847
1848 if (XtWidth(scale) < (boxes[CHILD_SB].box.width + VSLIDERSIZE +
1849 2 * Prim_ShadowThickness(children[CHILD_SB]) +
1850 2 * Scale_HighlightThickness(scale)))
1851 {
1852 boxes[CHILD_SB].box.x -= (boxes[CHILD_SB].box.x + VSLIDERSIZE +
1853 2 * Prim_ShadowThickness(children[CHILD_SB]) +
1854 2 * Scale_HighlightThickness(scale)) -
1855 XtWidth(scale) + 1;
1856 }
1857
1858 if (XtWidth(scale) > curw)
1859 {
1860 for (i = 2; i < num_children; i++)
1861 boxes[i].box.height = (Dimension)((double)boxes[i].box.height /
1862 (double)curw *
1863 (double)XtWidth(scale));
1864 }
1865 #endif /* 0 */
1866
1867 if ((delta = XtWidth(scale) - curw))
1868 {
1869 if (delta < 0 && XtIsManaged(boxes[CHILD_LAB].kid))
1870 {
1871 delta += boxes[CHILD_LAB].box.width +
1872 (MGR_ShadowThickness(scale) << 1);
1873 if (delta > 0)
1874 delta = 0;
1875 }
1876 for (i = 0; boxes[i].kid; i++)
1877 {
1878 boxes[i].box.x += delta;
1879 }
1880 }
1881
1882 /* T. Straumann: adjust height / tickmark positions if our geometry
1883 * is different from the one used in _XmScalePreferredSize()
1884 *
1885 * They do this only if Scale_ScaleWidth() == 0 or delta < 0
1886 * as can be confirmed by test14. Try also to resize
1887 *
1888 * test13 -xrm "*scaleHeight:200"
1889 *
1890 * using the WM
1891 */
1892 delta = XtHeight(scale) - curh;
1893 if ( delta < 0 || (delta > 0 && 0 == Scale_ScaleHeight(scale) ) )
1894 {
1895 /* different layout whether one or more tick marks are present */
1896 int denom = (num_children == 3 ? 2 : num_children -3);
1897 for (i = 0; boxes[i].kid; i++)
1898 {
1899 switch (i)
1900 {
1901 /* adjust the height of SB and LAB */
1902 case CHILD_LAB:
1903 case CHILD_SB:
1904 boxes[i].box.height = XtHeight(scale);
1905 break;
1906
1907 /* adjust the tick marks */
1908 default:
1909 boxes[i].box.y += delta * (i - 2) / denom;
1910 break;
1911 }
1912 }
1913 }
1914 }
1915 }
1916
1917
1918 /*
1919 * if we've gotten here, layout the children
1920 */
1921 static void
_XmScaleConfigureChildren(Widget scale,Widget child,XmKidGeometry boxes)1922 _XmScaleConfigureChildren(Widget scale, Widget child, XmKidGeometry boxes)
1923 {
1924 int inc;
1925 int p_inc;
1926
1927 _XmSetKidGeo(boxes, child);
1928
1929 Scale_SliderSize(scale) = _XmScaleConvertWidthToSliderSize(scale);
1930 _XmScaleConvertScaleIncrementToSCBIncrements(scale, &inc, &p_inc);
1931
1932 XmScrollBarSetValues(boxes[CHILD_SB].kid,
1933 _XmScaleConvertScaleValueToSCBValue(scale),
1934 Scale_SliderSize(scale),
1935 inc, p_inc, False);
1936 }
1937
1938
1939 static void
computeValueSize(Widget w)1940 computeValueSize(Widget w)
1941 {
1942 int maxlen, maxval;
1943
1944 #if 0
1945 maxval = ( Scale_Maximum(w) > -Scale_Minimum(w) ) ?
1946 Scale_Maximum(w) :
1947 Scale_Minimum(w);
1948
1949 maxlen = ( maxval < 0 ) ? 2 : 1;
1950 #else
1951 maxval = abs(Scale_Maximum(w)) > abs(Scale_Minimum(w)) ? abs(Scale_Maximum(w)) : abs(Scale_Minimum(w));
1952 if (Scale_Maximum(w) < 0 || Scale_Minimum(w) < 0)
1953 {
1954 maxlen = 2;
1955 }
1956 else
1957 {
1958 maxlen = 1;
1959 }
1960 #endif
1961
1962 for (maxval = abs(maxval); maxval >= 10; maxlen++)
1963 {
1964 maxval /= 10;
1965 }
1966
1967 if (Scale_DecimalPoints(w))
1968 {
1969 maxlen++;
1970 maxlen = maxlen < 3 ? 3 : maxlen;
1971 }
1972
1973 Scale_ShowValueWidth(w) = 2 + Scale_FontStruct(w)->max_bounds.width * maxlen;
1974 Scale_ShowValueHeight(w) = 3 + Scale_FontStruct(w)->max_bounds.ascent +
1975 Scale_FontStruct(w)->max_bounds.descent;
1976 }
1977
1978
1979 static void
showValue(Widget w,int scb_value,int scale_value)1980 showValue(Widget w, int scb_value, int scale_value)
1981 {
1982 char buf[256];
1983 Widget sb;
1984
1985 sb = ((XmScaleWidget)w)->composite.children[CHILD_SB];
1986 valueToString(w, buf);
1987
1988 #if 1
1989 /* Fix from John Richardson <jrichard@zko.dec.com> 1/7/1996 */
1990 /* T. Straumann: only erase if Scale_ShowValueX() is valid */
1991 if (XtIsRealized(w) && SHOW_VALUE_X_INVALID != Scale_ShowValueX(w))
1992 {
1993 XFillRectangle(XtDisplay(w), XtWindow(w), MGR_BackgroundGC(w),
1994 Scale_ShowValueX(w), Scale_ShowValueY(w),
1995 Scale_ShowValueWidth(w), Scale_ShowValueHeight(w));
1996 }
1997 #else
1998 if (XtIsRealized(w))
1999 {
2000 XFillRectangle(XtDisplay(w), XtWindow(w), MGR_BackgroundGC(w),
2001 Scale_ShowValueX(w), Scale_ShowValueY(w) - Scale_FontStruct(w)->descent,
2002 Scale_ShowValueWidth(w), Scale_ShowValueHeight(w));
2003 }
2004 #endif
2005
2006 if (Scale_Orientation(w) == XmHORIZONTAL)
2007 {
2008 Scale_ShowValueX(w) = SCB_SliderX(sb) + (SCB_SliderWidth(sb) >> 1) -
2009 (Scale_ShowValueWidth(w) / 2) + XtX(sb);
2010
2011 Scale_ShowValueY(w) = XtY(sb) - Scale_ShowValueHeight(w);
2012 }
2013 else if (Scale_Orientation(w) == XmVERTICAL)
2014 {
2015 Scale_ShowValueY(w) = SCB_SliderY(sb) + (SCB_SliderHeight(sb) >> 1) -
2016 (Scale_ShowValueHeight(w) / 2) + XtY(sb);
2017
2018 Scale_ShowValueX(w) = XtX(sb) - Scale_ShowValueWidth(w);
2019 }
2020 else
2021 {
2022 _XmError(w, "Scale Orientation wrong.");
2023 }
2024
2025 if (XtIsRealized(w))
2026 {
2027 int offset;
2028
2029 offset = (Scale_ShowValueWidth(w) -
2030 XTextWidth(Scale_FontStruct(w), buf, strlen(buf))) ;
2031 if (Scale_Orientation(w) == XmHORIZONTAL)
2032 {
2033 XDrawString(XtDisplay(w), XtWindow(w),
2034 Scale_ForegroundGC(w),
2035 Scale_ShowValueX(w) + offset / 2,
2036 Scale_ShowValueY(w) + Scale_FontStruct(w)->ascent,
2037 buf, strlen(buf));
2038 }
2039 else if (Scale_Orientation(w) == XmVERTICAL)
2040 {
2041 XDrawString(XtDisplay(w), XtWindow(w),
2042 Scale_ForegroundGC(w),
2043 Scale_ShowValueX(w) + offset,
2044 Scale_ShowValueY(w) + Scale_FontStruct(w)->ascent,
2045 buf, strlen(buf));
2046 }
2047 else
2048 _XmError(w, "Scale Orientation wrong");
2049 }
2050 }
2051
2052
2053 static void
_ScaleValueChanged(Widget sb,XtPointer cd,XtPointer data)2054 _ScaleValueChanged(Widget sb, XtPointer cd, XtPointer data)
2055 {
2056 XmScrollBarCallbackStruct *cbs = (XmScrollBarCallbackStruct *)data;
2057 XmScaleCallbackStruct scbs;
2058 int scale_value;
2059
2060 Scale_LastValue(XtParent(sb)) = Scale_Value(sb);
2061 scale_value = _XmScaleConvertSCBValueToScaleValue(XtParent(sb), cbs->value);
2062 Scale_Value(XtParent(sb)) = scale_value;
2063
2064 if (Scale_ShowValue(XtParent(sb)))
2065 {
2066 showValue(XtParent(sb), cbs->value, scale_value);
2067 }
2068
2069 scbs.reason = cbs->reason;
2070 scbs.event = cbs->event;
2071 scbs.value = scale_value;
2072
2073 if (Scale_ValueChangedCallback(XtParent(sb)))
2074 {
2075 XtCallCallbackList(XtParent(sb),
2076 Scale_ValueChangedCallback(XtParent(sb)), &scbs);
2077 }
2078 }
2079
2080
2081 static void
_ScaleDrag(Widget sb,XtPointer cd,XtPointer data)2082 _ScaleDrag(Widget sb, XtPointer cd, XtPointer data)
2083 {
2084 XmScrollBarCallbackStruct *cbs = (XmScrollBarCallbackStruct *)data;
2085 XmScaleCallbackStruct scbs;
2086 int scale_value;
2087
2088 #if XmVERSION > 1
2089 if (! Scale_Editable(XtParent(sb)))
2090 return;
2091 #endif
2092
2093 Scale_LastValue(XtParent(sb)) = Scale_Value(sb);
2094 scale_value = _XmScaleConvertSCBValueToScaleValue(XtParent(sb), cbs->value);
2095 Scale_Value(XtParent(sb)) = scale_value;
2096
2097 if (Scale_ShowValue(XtParent(sb)))
2098 {
2099 showValue(XtParent(sb), cbs->value, scale_value);
2100 }
2101
2102 scbs.reason = cbs->reason;
2103 scbs.event = cbs->event;
2104 scbs.value = scale_value;
2105 if (Scale_DragCallback(XtParent(sb)))
2106 {
2107 XtCallCallbackList(XtParent(sb),
2108 Scale_DragCallback(XtParent(sb)), &scbs);
2109 }
2110 }
2111
2112
2113 #if 0
2114 static void
2115 GetFocus(Widget w, XEvent *event, String *params, Cardinal *num_params)
2116 {
2117 XmScrollBarWidget sb;
2118
2119 DEBUGOUT(_LtDebug(__FILE__, w, "GetFocus\n"));
2120
2121 sb = (XmScrollBarWidget)(((XmScaleWidget)w)->composite.children[CHILD_SB]);
2122
2123 XtCallActionProc((Widget)sb, "PrimitiveFocusIn", event,
2124 params, *num_params);
2125 }
2126
2127
2128 static void
2129 LoseFocus(Widget w, XEvent *event, String *params, Cardinal *num_params)
2130 {
2131 XmScrollBarWidget sb;
2132
2133 DEBUGOUT(_LtDebug(__FILE__, w, "LoseFocus\n"));
2134
2135 sb = (XmScrollBarWidget)(((XmScaleWidget)w)->composite.children[CHILD_SB]);
2136
2137 XtCallActionProc((Widget)sb, "PrimitiveFocusOut", event,
2138 params, *num_params);
2139 }
2140 #endif /* 0 */
2141
2142
2143 static int
_XmScaleConvertWidthToSliderSize(Widget w)2144 _XmScaleConvertWidthToSliderSize(Widget w)
2145 {
2146 int ret, last_ret;
2147 XmScrollBarWidget sb;
2148 Dimension ht;
2149 Dimension st;
2150
2151 /* FIX ME: the next two statements are a kludge */
2152 sb = (XmScrollBarWidget)(((XmScaleWidget)w)->composite.children[CHILD_SB]);
2153
2154 /* FIX ME: Can't we use scale's values here? I.o.w. what shouls scale do
2155 * when these values are set explicitly and thus differ from scale's ?
2156 */
2157 XtVaGetValues((Widget)sb,
2158 XmNhighlightThickness, &ht,
2159 XmNshadowThickness, &st,
2160 NULL);
2161
2162 ret = Scale_SliderSize(w);
2163 do
2164 {
2165 /* FIX ME: rework the if's */
2166 last_ret = ret;
2167 if (Scale_Orientation(w) == XmHORIZONTAL)
2168 {
2169 if (XtWidth(sb) == 2 * (ht + st))
2170 {
2171 /* Note: M*tif 1.2.2 SIGFPE's on this -- PvH */
2172 ret = (int)((double)(SCB_MAX - SCB_MIN) /
2173 (double)(Scale_Maximum(w) - Scale_Minimum(w)) *
2174 (double)HSLIDERSIZE);
2175 }
2176 else if (XtWidth(sb) < HSLIDERSIZE)
2177 {
2178 ret = SCB_MAX - SCB_MIN;
2179 }
2180 else
2181 {
2182 /* Note: M*tif doesn't use float arithmetic here -- PvH */
2183 ret = (int)((SCB_MAX - SCB_MIN) /
2184 (XtWidth(sb) - 2 * (ht + st)) *
2185 HSLIDERSIZE);
2186 }
2187 }
2188 else
2189 {
2190 if (XtHeight(sb) == 2 * (ht + st))
2191 {
2192 ret = (int)((float)(SCB_MAX - SCB_MIN) /
2193 (float)(Scale_Maximum(w) - Scale_Minimum(w)) *
2194 (float)HSLIDERSIZE);
2195 }
2196 else if (XtHeight(sb) < HSLIDERSIZE)
2197 {
2198 ret = SCB_MAX - SCB_MIN;
2199 }
2200 else
2201 {
2202 /* Note: M*tif doesn't use float arithmetic here -- PvH */
2203 ret = (int)((SCB_MAX - SCB_MIN) /
2204 (XtHeight(sb) - 2 * (ht + st)) *
2205 HSLIDERSIZE);
2206 }
2207 }
2208 }
2209 while (last_ret != ret);
2210
2211 return ret;
2212 }
2213
2214
2215 static int
_XmScaleConvertSCBValueToScaleValue(Widget w,int value)2216 _XmScaleConvertSCBValueToScaleValue(Widget w, int value)
2217 {
2218 double roundarg;
2219 int result;
2220
2221 DEBUGOUT(_LtDebug(__FILE__, w, "_XmScaleConvertSCBValueToScaleValue(,%i)\n",
2222 value));
2223 if ((SCB_MAX - SCB_MIN - Scale_SliderSize(w)) == 0)
2224 {
2225 return Scale_Minimum(w);
2226 }
2227
2228 roundarg = (double)(Scale_Maximum(w) - Scale_Minimum(w))
2229 * (double)value
2230 / (double)(SCB_MAX - SCB_MIN - Scale_SliderSize(w))
2231 + (double)Scale_Minimum(w);
2232
2233 result = (int)(roundarg + 0.5);
2234
2235 return result;
2236 }
2237
2238
2239 static int
_XmScaleConvertScaleValueToSCBValue(Widget w)2240 _XmScaleConvertScaleValueToSCBValue(Widget w)
2241 {
2242
2243 double roundarg;
2244 int result;
2245
2246 DEBUGOUT(_LtDebug(__FILE__, w, "_XmScaleConvertScaleValueToSCBValue()\n"));
2247 roundarg = (double)(Scale_Value(w) - Scale_Minimum(w))
2248 * (double)(SCB_MAX - SCB_MIN - Scale_SliderSize(w))
2249 / (double)(Scale_Maximum(w) - Scale_Minimum(w));
2250 /* amai: is this the correct formula?
2251 looks like the old one in _XmScaleConvertSCBValueToScaleValue() */
2252 result = (int)(roundarg);
2253 return result;
2254 }
2255
2256
2257 static void
_XmScaleConvertScaleIncrementToSCBIncrements(Widget w,int * inc,int * page_inc)2258 _XmScaleConvertScaleIncrementToSCBIncrements(Widget w,
2259 int* inc,
2260 int* page_inc)
2261 {
2262 *inc = (int)((double)(SCB_MAX - SCB_MIN - Scale_SliderSize(w)) /
2263 (double)(Scale_Maximum(w) - Scale_Minimum(w)) +
2264 0.5);
2265 *inc = _XmMax(*inc, 1); /* FIX ME */
2266 *page_inc = *inc * Scale_ScaleMultiple(w);
2267 }
2268
2269
2270 static void
_XmScaleProcessingDirectionDefault(Widget w,int offset,XrmValue * val)2271 _XmScaleProcessingDirectionDefault(Widget w, int offset, XrmValue *val)
2272 {
2273 static unsigned char direction;
2274 XmScaleWidget sw = (XmScaleWidget)w;
2275
2276 if (sw->scale.orientation == XmVERTICAL)
2277 {
2278 direction = XmMAX_ON_TOP;
2279 }
2280 else
2281 {
2282 direction = XmMAX_ON_RIGHT; /* FIX ME */
2283 }
2284
2285 val->addr = (XPointer)&direction;
2286 }
2287