442
|
1 /* Gauge Widget for XEmacs.
|
424
|
2 Copyright (C) 1999 Edward A. Falk
|
|
3
|
|
4 This file is part of XEmacs.
|
|
5
|
|
6 XEmacs is free software; you can redistribute it and/or modify it
|
|
7 under the terms of the GNU General Public License as published by the
|
|
8 Free Software Foundation; either version 2, or (at your option) any
|
|
9 later version.
|
|
10
|
|
11 XEmacs is distributed in the hope that it will be useful, but WITHOUT
|
|
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
14 for more details.
|
|
15
|
|
16 You should have received a copy of the GNU General Public License
|
|
17 along with XEmacs; see the file COPYING. If not, write to
|
|
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
19 Boston, MA 02111-1307, USA. */
|
|
20
|
|
21 /* Synched up with: Gauge.c 1.2 */
|
|
22
|
|
23 /*
|
|
24 * Gauge.c - Gauge widget
|
|
25 *
|
|
26 * Author: Edward A. Falk
|
|
27 * falk@falconer.vip.best.com
|
442
|
28 *
|
424
|
29 * Date: July 9, 1997
|
|
30 *
|
|
31 * Note: for fun and demonstration purposes, I have added selection
|
|
32 * capabilities to this widget. If you select the widget, you create
|
|
33 * a primary selection containing the current value of the widget in
|
|
34 * both integer and string form. If you copy into the widget, the
|
|
35 * primary selection is converted to an integer value and the gauge is
|
|
36 * set to that value.
|
|
37 */
|
|
38
|
|
39 /* TODO: display time instead of value
|
|
40 */
|
|
41
|
|
42 #define DEF_LEN 50 /* default width (or height for vertical gauge) */
|
|
43 #define MIN_LEN 10 /* minimum reasonable width (height) */
|
|
44 #define TIC_LEN 6 /* length of tic marks */
|
|
45 #define GA_WID 3 /* width of gauge */
|
|
46 #define MS_PER_SEC 1000
|
|
47
|
|
48 #include <config.h>
|
|
49 #include <stdlib.h>
|
|
50 #include <stdio.h>
|
|
51 #include <ctype.h>
|
|
52 #include <X11/IntrinsicP.h>
|
|
53 #include <X11/Xatom.h>
|
|
54 #include <X11/StringDefs.h>
|
442
|
55 #include ATHENA_XawInit_h_
|
424
|
56 #include "xlwgaugeP.h"
|
|
57 #include "../src/xmu.h"
|
|
58 #ifdef HAVE_XMU
|
|
59 #include <X11/Xmu/Atoms.h>
|
|
60 #include <X11/Xmu/Drawing.h>
|
|
61 #include <X11/Xmu/StdSel.h>
|
|
62 #endif
|
|
63
|
|
64
|
|
65 /****************************************************************
|
|
66 *
|
|
67 * Gauge resources
|
|
68 *
|
|
69 ****************************************************************/
|
|
70
|
|
71
|
|
72 static char defaultTranslations[] =
|
|
73 "<Btn1Up>: select()\n\
|
|
74 <Key>F1: select(CLIPBOARD)\n\
|
|
75 <Btn2Up>: paste()\n\
|
|
76 <Key>F2: paste(CLIPBOARD)" ;
|
|
77
|
|
78
|
|
79
|
|
80 #define offset(field) XtOffsetOf(GaugeRec, field)
|
|
81 static XtResource resources[] = {
|
|
82 {XtNvalue, XtCValue, XtRInt, sizeof(int),
|
|
83 offset(gauge.value), XtRImmediate, (XtPointer)0},
|
|
84 {XtNminValue, XtCMinValue, XtRInt, sizeof(int),
|
|
85 offset(gauge.v0), XtRImmediate, (XtPointer)0},
|
|
86 {XtNmaxValue, XtCMaxValue, XtRInt, sizeof(int),
|
|
87 offset(gauge.v1), XtRImmediate, (XtPointer)100},
|
|
88 {XtNntics, XtCNTics, XtRInt, sizeof(int),
|
|
89 offset(gauge.ntics), XtRImmediate, (XtPointer) 0},
|
|
90 {XtNnlabels, XtCNLabels, XtRInt, sizeof(int),
|
|
91 offset(gauge.nlabels), XtRImmediate, (XtPointer) 0},
|
|
92 {XtNlabels, XtCLabels, XtRStringArray, sizeof(String *),
|
|
93 offset(gauge.labels), XtRStringArray, NULL},
|
|
94 {XtNautoScaleUp, XtCAutoScaleUp, XtRBoolean, sizeof(Boolean),
|
|
95 offset(gauge.autoScaleUp), XtRImmediate, FALSE},
|
|
96 {XtNautoScaleDown, XtCAutoScaleDown, XtRBoolean, sizeof(Boolean),
|
|
97 offset(gauge.autoScaleDown), XtRImmediate, FALSE},
|
|
98 {XtNorientation, XtCOrientation, XtROrientation, sizeof(XtOrientation),
|
|
99 offset(gauge.orientation), XtRImmediate, (XtPointer)XtorientHorizontal},
|
|
100 {XtNupdate, XtCInterval, XtRInt, sizeof(int),
|
|
101 offset(gauge.update), XtRImmediate, (XtPointer)0},
|
|
102 {XtNgetValue, XtCCallback, XtRCallback, sizeof(XtPointer),
|
|
103 offset(gauge.getValue), XtRImmediate, (XtPointer)NULL},
|
|
104 };
|
|
105 #undef offset
|
|
106
|
|
107
|
|
108
|
|
109 /* member functions */
|
|
110
|
|
111 static void GaugeClassInit (void);
|
|
112 static void GaugeInit (Widget, Widget, ArgList, Cardinal *);
|
|
113 static void GaugeDestroy (Widget);
|
|
114 static void GaugeResize (Widget);
|
|
115 static void GaugeExpose (Widget, XEvent *, Region);
|
|
116 static Boolean GaugeSetValues (Widget, Widget, Widget, ArgList, Cardinal *);
|
|
117 static XtGeometryResult GaugeQueryGeometry (Widget, XtWidgetGeometry *,
|
|
118 XtWidgetGeometry *);
|
|
119
|
|
120 /* action procs */
|
|
121
|
|
122 static void GaugeSelect (Widget, XEvent *, String *, Cardinal *);
|
|
123 static void GaugePaste (Widget, XEvent *, String *, Cardinal *);
|
|
124
|
|
125 /* internal privates */
|
|
126
|
|
127 static void GaugeSize (GaugeWidget, Dimension *, Dimension *, Dimension);
|
|
128 static void MaxLabel (GaugeWidget, Dimension *, Dimension *,
|
|
129 Dimension *, Dimension *);
|
|
130 static void AutoScale (GaugeWidget);
|
|
131 static void EnableUpdate (GaugeWidget);
|
|
132 static void DisableUpdate (GaugeWidget);
|
|
133
|
|
134 static void GaugeGetValue (XtPointer, XtIntervalId *);
|
|
135 static void GaugeMercury (Display *, Window, GC, GaugeWidget, Cardinal, Cardinal);
|
|
136
|
|
137 static Boolean GaugeConvert (Widget, Atom *, Atom *, Atom *,
|
458
|
138 XtPointer *, unsigned long *, int *);
|
424
|
139 static void GaugeLoseSel (Widget, Atom *);
|
|
140 static void GaugeDoneSel (Widget, Atom *, Atom *);
|
|
141 static void GaugeGetSelCB (Widget, XtPointer, Atom *, Atom *,
|
458
|
142 XtPointer, unsigned long *, int *);
|
424
|
143
|
|
144 static GC Get_GC (GaugeWidget, Pixel);
|
|
145
|
|
146
|
|
147 static XtActionsRec actionsList[] =
|
|
148 {
|
|
149 {"select", GaugeSelect},
|
|
150 {"paste", GaugePaste},
|
|
151 } ;
|
|
152
|
|
153
|
|
154
|
|
155 /****************************************************************
|
|
156 *
|
|
157 * Full class record constant
|
|
158 *
|
|
159 ****************************************************************/
|
|
160
|
|
161 GaugeClassRec gaugeClassRec = {
|
|
162 {
|
442
|
163 /* core_class fields */
|
424
|
164 /* superclass */ (WidgetClass) &labelClassRec,
|
|
165 /* class_name */ "Gauge",
|
|
166 /* widget_size */ sizeof(GaugeRec),
|
|
167 /* class_initialize */ GaugeClassInit,
|
|
168 /* class_part_initialize */ NULL,
|
|
169 /* class_inited */ FALSE,
|
|
170 /* initialize */ GaugeInit,
|
|
171 /* initialize_hook */ NULL,
|
|
172 /* realize */ XtInheritRealize, /* TODO? */
|
|
173 /* actions */ actionsList,
|
|
174 /* num_actions */ XtNumber(actionsList),
|
|
175 /* resources */ resources,
|
|
176 /* num_resources */ XtNumber(resources),
|
|
177 /* xrm_class */ NULLQUARK,
|
|
178 /* compress_motion */ TRUE,
|
|
179 /* compress_exposure */ TRUE,
|
|
180 /* compress_enterleave */ TRUE,
|
|
181 /* visible_interest */ FALSE,
|
|
182 /* destroy */ GaugeDestroy,
|
|
183 /* resize */ GaugeResize,
|
|
184 /* expose */ GaugeExpose,
|
|
185 /* set_values */ GaugeSetValues,
|
|
186 /* set_values_hook */ NULL,
|
|
187 /* set_values_almost */ XtInheritSetValuesAlmost,
|
|
188 /* get_values_hook */ NULL,
|
|
189 /* accept_focus */ NULL,
|
|
190 /* version */ XtVersion,
|
|
191 /* callback_private */ NULL,
|
|
192 /* tm_table */ defaultTranslations,
|
|
193 /* query_geometry */ GaugeQueryGeometry,
|
|
194 /* display_accelerator */ XtInheritDisplayAccelerator,
|
|
195 /* extension */ NULL
|
|
196 },
|
|
197 /* Simple class fields initialization */
|
|
198 {
|
|
199 /* change_sensitive */ XtInheritChangeSensitive
|
|
200 },
|
|
201 #ifdef _ThreeDP_h
|
|
202 /* ThreeD class fields initialization */
|
|
203 {
|
|
204 XtInheritXaw3dShadowDraw /* shadowdraw */
|
|
205 },
|
|
206 #endif
|
|
207 /* Label class fields initialization */
|
|
208 {
|
|
209 /* ignore */ 0
|
|
210 },
|
|
211 /* Gauge class fields initialization */
|
|
212 {
|
|
213 /* extension */ NULL
|
|
214 },
|
|
215 };
|
|
216
|
|
217 WidgetClass gaugeWidgetClass = (WidgetClass)&gaugeClassRec;
|
|
218
|
|
219
|
|
220
|
|
221
|
|
222 /****************************************************************
|
|
223 *
|
|
224 * Member Procedures
|
|
225 *
|
|
226 ****************************************************************/
|
|
227
|
|
228 static void
|
|
229 GaugeClassInit (void)
|
|
230 {
|
|
231 XawInitializeWidgetSet();
|
|
232 #ifdef HAVE_XMU
|
|
233 XtAddConverter(XtRString, XtROrientation, XmuCvtStringToOrientation,
|
|
234 NULL, 0) ;
|
|
235 #endif
|
|
236 }
|
|
237
|
|
238
|
|
239
|
|
240 /* ARGSUSED */
|
|
241 static void
|
|
242 GaugeInit (Widget request,
|
|
243 Widget new,
|
|
244 ArgList args,
|
|
245 Cardinal *num_args)
|
|
246 {
|
|
247 GaugeWidget gw = (GaugeWidget) new;
|
|
248
|
|
249 if( gw->gauge.v0 == 0 && gw->gauge.v1 == 0 ) {
|
|
250 gw->gauge.autoScaleUp = gw->gauge.autoScaleDown = TRUE ;
|
|
251 AutoScale(gw) ;
|
|
252 }
|
|
253
|
|
254 /* If size not explicitly set, set it to our preferred size now. */
|
|
255
|
|
256 if( request->core.width == 0 || request->core.height == 0 )
|
|
257 {
|
|
258 Dimension w,h ;
|
|
259 GaugeSize(gw, &w,&h, DEF_LEN) ;
|
|
260 if( request->core.width == 0 )
|
|
261 new->core.width = w ;
|
|
262 if( request->core.height == 0 )
|
|
263 new->core.height = h ;
|
|
264 gw->core.widget_class->core_class.resize(new) ;
|
|
265 }
|
|
266
|
|
267 gw->gauge.selected = None ;
|
|
268 gw->gauge.selstr = NULL ;
|
|
269
|
|
270 if( gw->gauge.update > 0 )
|
|
271 EnableUpdate(gw) ;
|
|
272
|
|
273 gw->gauge.inverse_GC = Get_GC(gw, gw->core.background_pixel) ;
|
|
274 }
|
|
275
|
|
276 static void
|
|
277 GaugeDestroy (Widget w)
|
|
278 {
|
|
279 GaugeWidget gw = (GaugeWidget)w;
|
|
280
|
|
281 if( gw->gauge.selstr != NULL )
|
|
282 XtFree(gw->gauge.selstr) ;
|
|
283
|
|
284 if( gw->gauge.selected != None )
|
|
285 XtDisownSelection(w, gw->gauge.selected, CurrentTime) ;
|
|
286
|
|
287 XtReleaseGC(w, gw->gauge.inverse_GC) ;
|
|
288
|
|
289 if( gw->gauge.update > 0 )
|
|
290 DisableUpdate(gw) ;
|
|
291 }
|
|
292
|
|
293
|
|
294 /* React to size change from manager. Label widget will compute some
|
|
295 * internal stuff, but we need to override.
|
|
296 */
|
|
297
|
|
298 static void
|
|
299 GaugeResize (Widget w)
|
|
300 {
|
|
301 GaugeWidget gw = (GaugeWidget)w;
|
|
302 int size ; /* height (width) of gauge */
|
|
303 int vmargin ; /* vertical (horizontal) margin */
|
|
304 int hmargin ; /* horizontal (vertical) margin */
|
|
305
|
|
306 vmargin = gw->gauge.orientation == XtorientHorizontal ?
|
|
307 gw->label.internal_height : gw->label.internal_width ;
|
|
308 hmargin = gw->gauge.orientation == XtorientHorizontal ?
|
|
309 gw->label.internal_width : gw->label.internal_height ;
|
|
310
|
|
311 /* TODO: need to call parent resize proc? I don't think so since
|
|
312 * we're recomputing everything from scratch anyway.
|
|
313 */
|
|
314
|
|
315 /* find total height (width) of contents */
|
|
316
|
|
317 size = GA_WID+2 ; /* gauge itself + edges */
|
|
318
|
|
319 if( gw->gauge.ntics > 1 ) /* tic marks */
|
|
320 size += vmargin + TIC_LEN ;
|
|
321
|
|
322 if( gw->gauge.nlabels > 1 )
|
|
323 {
|
|
324 Dimension lwm, lw0, lw1 ; /* width of max, left, right labels */
|
|
325 Dimension lh ;
|
|
326
|
|
327 MaxLabel(gw,&lwm,&lh, &lw0,&lw1) ;
|
|
328
|
|
329 if( gw->gauge.orientation == XtorientHorizontal )
|
|
330 {
|
|
331 gw->gauge.margin0 = lw0 / 2 ;
|
|
332 gw->gauge.margin1 = lw1 / 2 ;
|
|
333 size += lh + vmargin ;
|
|
334 }
|
|
335 else
|
|
336 {
|
442
|
337 gw->gauge.margin0 =
|
424
|
338 gw->gauge.margin1 = lh / 2 ;
|
|
339 size += lwm + vmargin ;
|
|
340 }
|
|
341 }
|
|
342 else
|
|
343 gw->gauge.margin0 = gw->gauge.margin1 = 0 ;
|
|
344
|
|
345 gw->gauge.margin0 += hmargin ;
|
|
346 gw->gauge.margin1 += hmargin ;
|
|
347
|
|
348 /* Now distribute height (width) over components */
|
|
349
|
|
350 if( gw->gauge.orientation == XtorientHorizontal )
|
|
351 gw->gauge.gmargin = (gw->core.height-size)/2 ;
|
|
352 else
|
|
353 gw->gauge.gmargin = (gw->core.width-size)/2 ;
|
|
354
|
|
355 gw->gauge.tmargin = gw->gauge.gmargin + GA_WID+2 + vmargin ;
|
|
356 if( gw->gauge.ntics > 1 )
|
|
357 gw->gauge.lmargin = gw->gauge.tmargin + TIC_LEN + vmargin ;
|
|
358 else
|
|
359 gw->gauge.lmargin = gw->gauge.tmargin ;
|
|
360 }
|
|
361
|
|
362 /*
|
|
363 * Repaint the widget window
|
|
364 */
|
|
365
|
|
366 /* ARGSUSED */
|
|
367 static void
|
|
368 GaugeExpose (Widget w,
|
|
369 XEvent *event,
|
|
370 Region region)
|
|
371 {
|
|
372 GaugeWidget gw = (GaugeWidget) w;
|
|
373 register Display *dpy = XtDisplay(w) ;
|
|
374 register Window win = XtWindow(w) ;
|
|
375 GC gc; /* foreground, background */
|
|
376 GC gctop, gcbot ; /* dark, light shadows */
|
|
377
|
|
378 int len ; /* length (width or height) of widget */
|
|
379 int hgt ; /* height (width) of widget */
|
|
380 int e0,e1 ; /* ends of the gauge */
|
|
381 int x ;
|
|
382 int y ; /* vertical (horizontal) position */
|
|
383 int i ;
|
|
384 int v0 = gw->gauge.v0 ;
|
|
385 int v1 = gw->gauge.v1 ;
|
|
386 int value = gw->gauge.value ;
|
|
387
|
|
388 gc = XtIsSensitive(w) ? gw->label.normal_GC : gw->label.gray_GC ;
|
|
389
|
|
390
|
|
391 #ifdef _ThreeDP_h
|
|
392 gctop = gw->threeD.bot_shadow_GC ;
|
|
393 gcbot = gw->threeD.top_shadow_GC ;
|
|
394 #else
|
|
395 gctop = gcbot = gc ;
|
|
396 #endif
|
|
397
|
|
398 if( gw->gauge.orientation == XtorientHorizontal ) {
|
|
399 len = gw->core.width ;
|
|
400 hgt = gw->core.height ;
|
|
401 } else {
|
|
402 len = gw->core.height ;
|
|
403 hgt = gw->core.width ;
|
|
404 }
|
|
405
|
|
406 /* if the gauge is selected, signify by drawing the background
|
442
|
407 * in a contrasting color.
|
424
|
408 */
|
|
409
|
|
410 if( gw->gauge.selected )
|
|
411 {
|
|
412 XFillRectangle(dpy,win, gc, 0,0, w->core.width,w->core.height) ;
|
|
413 gc = gw->gauge.inverse_GC ;
|
|
414 }
|
|
415
|
|
416 e0 = gw->gauge.margin0 ; /* left (top) end */
|
|
417 e1 = len - gw->gauge.margin1 -1 ; /* right (bottom) end */
|
|
418
|
|
419 /* Draw the Gauge itself */
|
|
420
|
|
421 y = gw->gauge.gmargin ;
|
|
422
|
|
423 if( gw->gauge.orientation == XtorientHorizontal ) /* horizontal */
|
|
424 {
|
|
425 XDrawLine(dpy,win,gctop, e0+1,y, e1-1,y) ;
|
|
426 XDrawLine(dpy,win,gctop, e0,y+1, e0,y+GA_WID) ;
|
|
427 XDrawLine(dpy,win,gcbot, e0+1, y+GA_WID+1, e1-1, y+GA_WID+1) ;
|
|
428 XDrawLine(dpy,win,gcbot, e1,y+1, e1,y+GA_WID) ;
|
|
429 }
|
|
430 else /* vertical */
|
|
431 {
|
|
432 XDrawLine(dpy,win,gctop, y,e0+1, y,e1-1) ;
|
|
433 XDrawLine(dpy,win,gctop, y+1,e0, y+GA_WID,e0) ;
|
|
434 XDrawLine(dpy,win,gcbot, y+GA_WID+1,e0+1, y+GA_WID+1, e1-1) ;
|
|
435 XDrawLine(dpy,win,gcbot, y+1,e1, y+GA_WID,e1) ;
|
|
436 }
|
|
437
|
|
438
|
|
439 /* draw the mercury */
|
|
440
|
|
441 GaugeMercury(dpy, win, gc, gw, 0,value) ;
|
|
442
|
|
443
|
|
444 if( gw->gauge.ntics > 1 )
|
|
445 {
|
|
446 y = gw->gauge.tmargin ;
|
|
447 for(i=0; i<gw->gauge.ntics; ++i)
|
|
448 {
|
|
449 x = e0 + i*(e1-e0-1)/(gw->gauge.ntics-1) ;
|
|
450 if( gw->gauge.orientation == XtorientHorizontal ) {
|
|
451 XDrawLine(dpy,win,gcbot, x,y+1, x,y+TIC_LEN-2) ;
|
|
452 XDrawLine(dpy,win,gcbot, x,y, x+1,y) ;
|
|
453 XDrawLine(dpy,win,gctop, x+1,y+1, x+1,y+TIC_LEN-2) ;
|
|
454 XDrawLine(dpy,win,gctop, x,y+TIC_LEN-1, x+1,y+TIC_LEN-1) ;
|
|
455 }
|
|
456 else {
|
|
457 XDrawLine(dpy,win,gcbot, y+1,x, y+TIC_LEN-2,x) ;
|
|
458 XDrawLine(dpy,win,gcbot, y,x, y,x+1) ;
|
|
459 XDrawLine(dpy,win,gctop, y+1,x+1, y+TIC_LEN-2,x+1) ;
|
|
460 XDrawLine(dpy,win,gctop, y+TIC_LEN-1,x, y+TIC_LEN-1,x+1) ;
|
|
461 }
|
|
462 }
|
|
463 }
|
|
464
|
|
465 /* draw labels */
|
|
466 if( gw->gauge.nlabels > 1 )
|
|
467 {
|
|
468 char label[20], *s = label ;
|
442
|
469 int xlen, wd,h =0 ;
|
424
|
470
|
|
471 if( gw->gauge.orientation == XtorientHorizontal )
|
|
472 y = gw->gauge.lmargin + gw->label.font->max_bounds.ascent - 1 ;
|
|
473 else {
|
|
474 y = gw->gauge.lmargin ;
|
|
475 h = gw->label.font->max_bounds.ascent / 2 ;
|
|
476 }
|
|
477
|
|
478 for(i=0; i<gw->gauge.nlabels; ++i)
|
|
479 {
|
|
480 if( gw->gauge.labels == NULL )
|
|
481 sprintf(label, "%d", v0+i*(v1 - v0)/(gw->gauge.nlabels - 1)) ;
|
|
482 else
|
|
483 s = gw->gauge.labels[i] ;
|
|
484 if( s != NULL ) {
|
|
485 x = e0 + i*(e1-e0-1)/(gw->gauge.nlabels-1) ;
|
442
|
486 xlen = strlen(s) ;
|
424
|
487 if( gw->gauge.orientation == XtorientHorizontal ) {
|
442
|
488 wd = XTextWidth(gw->label.font, s, xlen) ;
|
|
489 XDrawString(dpy,win,gc, x-wd/2,y, s,xlen) ;
|
424
|
490 }
|
|
491 else {
|
442
|
492 XDrawString(dpy,win,gc, y,x+h, s,xlen) ;
|
424
|
493 }
|
|
494 }
|
|
495 }
|
|
496 }
|
|
497 }
|
|
498
|
|
499
|
|
500 /*
|
|
501 * Set specified arguments into widget
|
|
502 */
|
|
503
|
|
504 static Boolean
|
|
505 GaugeSetValues (Widget old,
|
|
506 Widget request,
|
|
507 Widget new,
|
|
508 ArgList args,
|
|
509 Cardinal *num_args)
|
|
510 {
|
|
511 GaugeWidget oldgw = (GaugeWidget) old;
|
|
512 GaugeWidget gw = (GaugeWidget) new;
|
|
513 Boolean was_resized = False;
|
|
514
|
|
515 if( gw->gauge.selected != None ) {
|
|
516 XtDisownSelection(new, gw->gauge.selected, CurrentTime) ;
|
|
517 gw->gauge.selected = None ;
|
|
518 }
|
|
519
|
|
520 /* Changes to v0,v1,labels, ntics, nlabels require resize & redraw. */
|
|
521 /* Change to value requires redraw and possible resize if autoscale */
|
|
522
|
|
523 was_resized =
|
|
524 gw->gauge.v0 != oldgw->gauge.v0 ||
|
|
525 gw->gauge.v1 != oldgw->gauge.v1 ||
|
|
526 gw->gauge.ntics != oldgw->gauge.ntics ||
|
|
527 gw->gauge.nlabels != oldgw->gauge.nlabels ||
|
|
528 gw->gauge.labels != oldgw->gauge.labels ;
|
|
529
|
|
530 if( (gw->gauge.autoScaleUp && gw->gauge.value > gw->gauge.v1) ||
|
|
531 (gw->gauge.autoScaleDown && gw->gauge.value < gw->gauge.v1/3 ))
|
|
532 {
|
|
533 AutoScale(gw) ;
|
|
534 was_resized = TRUE ;
|
|
535 }
|
|
536
|
|
537 if( was_resized ) {
|
|
538 if( gw->label.resize )
|
|
539 GaugeSize(gw, &gw->core.width, &gw->core.height, DEF_LEN) ;
|
|
540 else
|
|
541 GaugeResize(new) ;
|
|
542 }
|
442
|
543
|
424
|
544 if( gw->gauge.update != oldgw->gauge.update )
|
|
545 {
|
|
546 if( gw->gauge.update > 0 )
|
|
547 EnableUpdate(gw) ;
|
|
548 else
|
|
549 DisableUpdate(gw) ;
|
|
550 }
|
|
551
|
|
552 if( gw->core.background_pixel != oldgw->core.background_pixel )
|
|
553 {
|
|
554 XtReleaseGC(new, gw->gauge.inverse_GC) ;
|
|
555 gw->gauge.inverse_GC = Get_GC(gw, gw->core.background_pixel) ;
|
|
556 }
|
|
557
|
|
558 return was_resized || gw->gauge.value != oldgw->gauge.value ||
|
|
559 XtIsSensitive(old) != XtIsSensitive(new);
|
|
560 }
|
|
561
|
|
562
|
|
563 static XtGeometryResult
|
|
564 GaugeQueryGeometry (Widget w,
|
|
565 XtWidgetGeometry *intended,
|
|
566 XtWidgetGeometry *preferred)
|
|
567 {
|
|
568 register GaugeWidget gw = (GaugeWidget)w;
|
|
569
|
|
570 if( intended->width == w->core.width &&
|
|
571 intended->height == w->core.height )
|
|
572 return XtGeometryNo ;
|
|
573
|
|
574 preferred->request_mode = CWWidth | CWHeight;
|
|
575 GaugeSize(gw, &preferred->width, &preferred->height, DEF_LEN) ;
|
|
576
|
|
577 if( (!(intended->request_mode & CWWidth) ||
|
|
578 intended->width >= preferred->width) &&
|
|
579 (!(intended->request_mode & CWHeight) ||
|
|
580 intended->height >= preferred->height) )
|
|
581 return XtGeometryYes;
|
|
582 else
|
|
583 return XtGeometryAlmost;
|
|
584 }
|
|
585
|
|
586
|
|
587
|
|
588
|
|
589 /****************************************************************
|
|
590 *
|
|
591 * Action Procedures
|
|
592 *
|
|
593 ****************************************************************/
|
|
594
|
|
595 static void
|
|
596 GaugeSelect (Widget w,
|
|
597 XEvent *event,
|
|
598 String *params,
|
|
599 Cardinal *num_params)
|
|
600 {
|
|
601 GaugeWidget gw = (GaugeWidget)w ;
|
|
602 Atom seln = XA_PRIMARY ;
|
|
603
|
|
604 if( gw->gauge.selected != None ) {
|
|
605 XtDisownSelection(w, gw->gauge.selected, CurrentTime) ;
|
|
606 gw->gauge.selected = None ;
|
|
607 }
|
|
608
|
|
609 if( *num_params > 0 ) {
|
|
610 seln = XInternAtom(XtDisplay(w), params[0], False) ;
|
|
611 printf("atom %s is %ld\n", params[0], seln) ;
|
|
612 }
|
|
613
|
|
614 if( ! XtOwnSelection(w, seln, event->xbutton.time, GaugeConvert,
|
|
615 GaugeLoseSel, GaugeDoneSel) )
|
|
616 {
|
|
617 /* in real code, this error message would be replaced by
|
|
618 * something more elegant, or at least deleted
|
|
619 */
|
|
620
|
|
621 fprintf(stderr, "Gauge failed to get selection, try again\n") ;
|
|
622 }
|
|
623 else
|
|
624 {
|
|
625 gw->gauge.selected = TRUE ;
|
|
626 gw->gauge.selstr = (String)XtMalloc(4*sizeof(int)) ;
|
|
627 sprintf(gw->gauge.selstr, "%d", gw->gauge.value) ;
|
|
628 GaugeExpose(w,0,0) ;
|
|
629 }
|
|
630 }
|
|
631
|
|
632
|
|
633 static Boolean
|
|
634 GaugeConvert (Widget w,
|
|
635 Atom *selection, /* usually XA_PRIMARY */
|
|
636 Atom *target, /* requested target */
|
|
637 Atom *type, /* returned type */
|
|
638 XtPointer *value, /* returned value */
|
458
|
639 unsigned long *length, /* returned length */
|
424
|
640 int *format) /* returned format */
|
|
641 {
|
|
642 GaugeWidget gw = (GaugeWidget)w ;
|
|
643 XSelectionRequestEvent *req ;
|
|
644
|
|
645 printf( "requesting selection %s:%s\n",
|
|
646 XGetAtomName(XtDisplay(w),*selection),
|
|
647 XGetAtomName(XtDisplay(w),*target));
|
|
648
|
|
649 #ifdef HAVE_XMU
|
|
650 if( *target == XA_TARGETS(XtDisplay(w)) )
|
|
651 {
|
|
652 Atom *rval, *stdTargets ;
|
458
|
653 unsigned long stdLength ;
|
424
|
654
|
|
655 /* XmuConvertStandardSelection can handle this. This function
|
|
656 * will return a list of standard targets. We prepend TEXT,
|
|
657 * STRING and INTEGER to the list and return it.
|
|
658 */
|
|
659
|
|
660 req = XtGetSelectionRequest(w, *selection, NULL) ;
|
|
661 XmuConvertStandardSelection(w, req->time, selection, target,
|
|
662 type, (XPointer*)&stdTargets, &stdLength, format) ;
|
|
663
|
|
664 *type = XA_ATOM ; /* TODO: needed? */
|
|
665 *length = stdLength + 3 ;
|
|
666 rval = (Atom *) XtMalloc(sizeof(Atom)*(stdLength+3)) ;
|
|
667 *value = (XtPointer) rval ;
|
|
668 *rval++ = XA_INTEGER ;
|
|
669 *rval++ = XA_STRING ;
|
|
670 *rval++ = XA_TEXT(XtDisplay(w)) ;
|
440
|
671 memcpy((char *)rval, (char *)stdTargets, stdLength*sizeof(Atom)) ;
|
424
|
672 XtFree((char*) stdTargets) ;
|
|
673 *format = 8*sizeof(Atom) ; /* TODO: needed? */
|
|
674 return True ;
|
|
675 }
|
|
676
|
442
|
677 else
|
424
|
678 #endif
|
|
679 if( *target == XA_INTEGER )
|
|
680 {
|
|
681 *type = XA_INTEGER ;
|
|
682 *length = 1 ;
|
|
683 *value = (XtPointer) &gw->gauge.value ;
|
|
684 *format = 8*sizeof(int) ;
|
|
685 return True ;
|
|
686 }
|
|
687
|
442
|
688 else if( *target == XA_STRING
|
424
|
689 #ifdef HAVE_XMU
|
442
|
690 ||
|
|
691 *target == XA_TEXT(XtDisplay(w))
|
424
|
692 #endif
|
|
693 )
|
|
694 {
|
|
695 *type = *target ;
|
|
696 *length = strlen(gw->gauge.selstr)*sizeof(char) ;
|
|
697 *value = (XtPointer) gw->gauge.selstr ;
|
|
698 *format = 8 ;
|
|
699 return True ;
|
|
700 }
|
|
701
|
|
702 else
|
|
703 {
|
|
704 /* anything else, we just give it to XmuConvertStandardSelection() */
|
|
705 #ifdef HAVE_XMU
|
|
706 req = XtGetSelectionRequest(w, *selection, NULL) ;
|
|
707 if( XmuConvertStandardSelection(w, req->time, selection, target,
|
|
708 type, (XPointer *) value, length, format) )
|
|
709 return True ;
|
442
|
710 else
|
424
|
711 #endif
|
|
712 {
|
|
713 printf(
|
|
714 "Gauge: requestor is requesting unsupported selection %s:%s\n",
|
|
715 XGetAtomName(XtDisplay(w),*selection),
|
|
716 XGetAtomName(XtDisplay(w),*target));
|
|
717 return False ;
|
|
718 }
|
|
719 }
|
|
720 }
|
|
721
|
|
722
|
|
723
|
|
724 static void
|
|
725 GaugeLoseSel (Widget w,
|
|
726 Atom *selection) /* usually XA_PRIMARY */
|
|
727 {
|
|
728 GaugeWidget gw = (GaugeWidget)w ;
|
|
729 Display *dpy = XtDisplay(w) ;
|
|
730 Window win = XtWindow(w) ;
|
|
731
|
|
732 if( gw->gauge.selstr != NULL ) {
|
|
733 XtFree(gw->gauge.selstr) ;
|
|
734 gw->gauge.selstr = NULL ;
|
|
735 }
|
|
736
|
|
737 gw->gauge.selected = False ;
|
|
738 XClearWindow(dpy,win) ;
|
|
739 GaugeExpose(w,0,0) ;
|
|
740 }
|
|
741
|
|
742
|
|
743 static void
|
|
744 GaugeDoneSel (Widget w,
|
|
745 Atom *selection, /* usually XA_PRIMARY */
|
|
746 Atom *target) /* requested target */
|
|
747 {
|
|
748 /* selection done, anything to do? */
|
|
749 }
|
|
750
|
|
751
|
|
752 static void
|
|
753 GaugePaste (Widget w,
|
|
754 XEvent *event,
|
|
755 String *params,
|
|
756 Cardinal *num_params)
|
|
757 {
|
|
758 Atom seln = XA_PRIMARY ;
|
|
759
|
|
760 if( *num_params > 0 ) {
|
|
761 seln = XInternAtom(XtDisplay(w), params[0], False) ;
|
|
762 printf("atom %s is %ld\n", params[0], seln) ;
|
|
763 }
|
|
764
|
|
765 /* try for integer value first */
|
|
766 XtGetSelectionValue(w, seln, XA_INTEGER,
|
|
767 GaugeGetSelCB, (XtPointer)XA_INTEGER,
|
|
768 event->xbutton.time) ;
|
|
769 }
|
|
770
|
|
771 static void
|
|
772 GaugeGetSelCB (Widget w,
|
|
773 XtPointer client,
|
|
774 Atom *selection,
|
|
775 Atom *type,
|
|
776 XtPointer value,
|
458
|
777 unsigned long *length,
|
424
|
778 int *format)
|
|
779 {
|
|
780 Display *dpy = XtDisplay(w) ;
|
|
781 Atom target = (Atom)client ;
|
|
782 int *iptr ;
|
|
783 char *cptr ;
|
|
784
|
|
785 if( *type == XA_INTEGER ) {
|
|
786 iptr = (int *)value ;
|
|
787 XawGaugeSetValue(w, *iptr) ;
|
|
788 }
|
|
789
|
442
|
790 else if( *type == XA_STRING
|
424
|
791 #ifdef HAVE_XMU
|
|
792 ||
|
442
|
793 *type == XA_TEXT(dpy)
|
424
|
794 #endif
|
442
|
795 )
|
424
|
796 {
|
|
797 cptr = (char *)value ;
|
|
798 XawGaugeSetValue(w, atoi(cptr)) ;
|
|
799 }
|
|
800
|
|
801 /* failed, try string */
|
|
802 else if( *type == None && target == XA_INTEGER )
|
|
803 XtGetSelectionValue(w, *selection, XA_STRING,
|
|
804 GaugeGetSelCB, (XtPointer)XA_STRING,
|
|
805 CurrentTime) ;
|
|
806 }
|
|
807
|
|
808
|
|
809
|
|
810 /****************************************************************
|
|
811 *
|
|
812 * Public Procedures
|
|
813 *
|
|
814 ****************************************************************/
|
|
815
|
|
816
|
|
817 /* Change gauge value. Only undraw or draw what needs to be
|
|
818 * changed.
|
|
819 */
|
|
820
|
|
821 void
|
|
822 XawGaugeSetValue (Widget w,
|
|
823 Cardinal value)
|
|
824 {
|
|
825 GaugeWidget gw = (GaugeWidget)w ;
|
|
826 int oldvalue ;
|
|
827 GC gc ;
|
|
828
|
|
829 if( gw->gauge.selected != None ) {
|
|
830 XtDisownSelection(w, gw->gauge.selected, CurrentTime) ;
|
|
831 gw->gauge.selected = None ;
|
|
832 }
|
|
833
|
|
834 if( !XtIsRealized(w) ) {
|
|
835 gw->gauge.value = value ;
|
|
836 return ;
|
|
837 }
|
|
838
|
|
839 /* need to rescale? */
|
|
840 if(( gw->gauge.autoScaleUp && value > gw->gauge.v1) ||
|
|
841 (gw->gauge.autoScaleDown && value < gw->gauge.v1/3 ))
|
|
842 {
|
|
843 XtVaSetValues(w, XtNvalue, value, 0) ;
|
|
844 return ;
|
|
845 }
|
|
846
|
|
847 oldvalue = gw->gauge.value ;
|
|
848 gw->gauge.value = value ;
|
|
849
|
|
850 gc = XtIsSensitive(w) ? gw->label.normal_GC : gw->label.gray_GC ;
|
|
851 GaugeMercury(XtDisplay(w), XtWindow(w), gc, gw, oldvalue,value) ;
|
|
852 }
|
|
853
|
|
854
|
|
855 Cardinal
|
|
856 XawGaugeGetValue (Widget w)
|
|
857 {
|
|
858 GaugeWidget gw = (GaugeWidget)w ;
|
|
859 return gw->gauge.value ;
|
|
860 }
|
|
861
|
|
862
|
|
863
|
|
864
|
|
865 /****************************************************************
|
|
866 *
|
|
867 * Private Procedures
|
|
868 *
|
|
869 ****************************************************************/
|
|
870
|
|
871 /* draw the mercury over a specific region */
|
|
872
|
|
873 static void
|
|
874 GaugeMercury (Display *dpy,
|
|
875 Window win,
|
|
876 GC gc,
|
|
877 GaugeWidget gw,
|
|
878 Cardinal val0,
|
|
879 Cardinal val1)
|
|
880 {
|
|
881 int v0 = gw->gauge.v0 ;
|
|
882 int v1 = gw->gauge.v1 ;
|
|
883 int vd = v1 - v0 ;
|
|
884 Dimension len ; /* length (width or height) of gauge */
|
|
885 Position e0, e1 ; /* gauge ends */
|
|
886 Position p0, p1 ; /* mercury ends */
|
|
887 int y ; /* vertical (horizontal) position */
|
|
888 Boolean undraw = FALSE ;
|
|
889
|
|
890 len = gw->gauge.orientation == XtorientHorizontal ?
|
|
891 gw->core.width : gw->core.height ;
|
|
892
|
|
893 e0 = gw->gauge.margin0 ; /* left (top) end */
|
|
894 e1 = len - gw->gauge.margin1 -1 ; /* right (bottom) end */
|
|
895
|
|
896 if( vd <= 0 ) vd = 1 ;
|
|
897
|
|
898 if( val0 < v0 ) val0 = v0 ;
|
|
899 else if( val0 > v1 ) val0 = v1 ;
|
|
900 if( val1 < v0 ) val1 = v0 ;
|
|
901 else if( val1 > v1 ) val1 = v1 ;
|
|
902
|
|
903 p0 = (val0-v0)*(e1-e0-1)/vd ;
|
|
904 p1 = (val1-v0)*(e1-e0-1)/vd ;
|
|
905
|
|
906 if( p1 == p0 )
|
|
907 return ;
|
|
908
|
|
909 y = gw->gauge.gmargin ;
|
|
910
|
|
911 if( p1 < p0 )
|
|
912 {
|
|
913 Position tmp = p0 ;
|
|
914 p0 = p1 ;
|
|
915 p1 = tmp ;
|
|
916 gc = gw->label.normal_GC ;
|
|
917 XSetForeground(dpy,gc, gw->core.background_pixel) ;
|
|
918 undraw = TRUE ;
|
|
919 }
|
|
920
|
|
921 if( gw->gauge.orientation == XtorientHorizontal )
|
|
922 XFillRectangle(dpy,win,gc, e0+p0+1,y+1, p1-p0,GA_WID) ;
|
|
923 else
|
|
924 XFillRectangle(dpy,win,gc, y+1,e1-p1, GA_WID,p1-p0) ;
|
|
925
|
|
926 if( undraw )
|
|
927 XSetForeground(dpy,gc, gw->label.foreground) ;
|
|
928 }
|
|
929
|
|
930
|
|
931
|
|
932 /* Search the labels, find the largest one. */
|
|
933 /* TODO: handle vertical fonts? */
|
|
934
|
|
935 static void
|
|
936 MaxLabel (GaugeWidget gw,
|
|
937 Dimension *wid, /* max label width */
|
|
938 Dimension *hgt, /* max label height */
|
|
939 Dimension *w0, /* width of first label */
|
|
940 Dimension *w1) /* width of last label */
|
|
941 {
|
|
942 char lstr[80], *lbl ;
|
|
943 int w ;
|
|
944 XFontStruct *font = gw->label.font ;
|
|
945 int i ;
|
|
946 int lw = 0;
|
|
947 int v0 = gw->gauge.v0 ;
|
|
948 int dv = gw->gauge.v1 - v0 ;
|
|
949 int n = gw->gauge.nlabels ;
|
|
950
|
|
951 if( n > 0 )
|
|
952 {
|
|
953 if( --n <= 0 ) {n = 1 ; v0 += dv/2 ;}
|
|
954
|
|
955 /* loop through all labels, figure out how much room they
|
|
956 * need.
|
|
957 */
|
|
958 w = 0 ;
|
|
959 for(i=0; i<gw->gauge.nlabels; ++i)
|
|
960 {
|
|
961 if( gw->gauge.labels == NULL ) /* numeric labels */
|
|
962 sprintf(lbl = lstr,"%d", v0 + i*dv/n) ;
|
|
963 else
|
|
964 lbl = gw->gauge.labels[i] ;
|
|
965
|
|
966 if( lbl != NULL ) {
|
|
967 lw = XTextWidth(font, lbl, strlen(lbl)) ;
|
|
968 w = Max( w, lw ) ;
|
|
969 }
|
|
970 else
|
|
971 lw = 0 ;
|
|
972
|
|
973 if( i == 0 && w0 != NULL ) *w0 = lw ;
|
|
974 }
|
|
975 if( w1 != NULL ) *w1 = lw ;
|
|
976
|
|
977 *wid = w ;
|
|
978 *hgt = font->max_bounds.ascent + font->max_bounds.descent ;
|
|
979 }
|
|
980 else
|
|
981 *wid = *hgt = 0 ;
|
|
982 }
|
|
983
|
|
984
|
|
985 /* Determine the preferred size for this widget. choose 100x100 for
|
|
986 * debugging.
|
|
987 */
|
|
988
|
|
989 static void
|
|
990 GaugeSize (GaugeWidget gw,
|
|
991 Dimension *wid,
|
|
992 Dimension *hgt,
|
|
993 Dimension min_len)
|
|
994 {
|
|
995 int w,h ; /* width, height of gauge */
|
|
996 int vmargin ; /* vertical margin */
|
|
997 int hmargin ; /* horizontal margin */
|
|
998
|
|
999 hmargin = gw->label.internal_width ;
|
|
1000 vmargin = gw->label.internal_height ;
|
|
1001
|
|
1002 /* find total height (width) of contents */
|
|
1003
|
|
1004
|
|
1005 /* find minimum size for undecorated gauge */
|
|
1006
|
|
1007 if( gw->gauge.orientation == XtorientHorizontal )
|
|
1008 {
|
|
1009 w = min_len ;
|
|
1010 h = GA_WID+2 ; /* gauge itself + edges */
|
|
1011 }
|
|
1012 else
|
|
1013 {
|
|
1014 w = GA_WID+2 ;
|
|
1015 h = min_len ;
|
|
1016 }
|
|
1017
|
|
1018 if( gw->gauge.ntics > 0 )
|
|
1019 {
|
|
1020 if( gw->gauge.orientation == XtorientHorizontal )
|
|
1021 {
|
|
1022 w = Max(w, gw->gauge.ntics*3) ;
|
|
1023 h += vmargin + TIC_LEN ;
|
|
1024 }
|
|
1025 else
|
|
1026 {
|
|
1027 w += hmargin + TIC_LEN ;
|
|
1028 h = Max(h, gw->gauge.ntics*3) ;
|
|
1029 }
|
|
1030 }
|
|
1031
|
|
1032
|
|
1033 /* If labels are requested, this gets a little interesting.
|
|
1034 * We want the end labels centered on the ends of the gauge and
|
|
1035 * the centers of the labels evenly spaced. The labels at the ends
|
|
1036 * will not be the same width, meaning that the gauge itself need
|
|
1037 * not be centered in the widget.
|
|
1038 *
|
|
1039 * First, determine the spacing. This is the width of the widest
|
|
1040 * label, plus the internal margin. Total length of the gauge is
|
|
1041 * spacing * (nlabels-1). To this, we add half the width of the
|
|
1042 * left-most label and half the width of the right-most label
|
|
1043 * to get the entire desired width of the widget.
|
|
1044 */
|
|
1045 if( gw->gauge.nlabels > 0 )
|
|
1046 {
|
|
1047 Dimension lwm, lw0, lw1 ; /* width of max, left, right labels */
|
|
1048 Dimension lh ;
|
|
1049
|
|
1050 MaxLabel(gw,&lwm,&lh, &lw0,&lw1) ;
|
|
1051
|
|
1052 if( gw->gauge.orientation == XtorientHorizontal )
|
|
1053 {
|
|
1054 lwm = (lwm+hmargin) * (gw->gauge.nlabels-1) + (lw0+lw1)/2 ;
|
|
1055 w = Max(w, lwm) ;
|
|
1056 h += lh + vmargin ;
|
|
1057 }
|
|
1058 else
|
|
1059 {
|
|
1060 lh = lh*gw->gauge.nlabels + (gw->gauge.nlabels - 1)*vmargin ;
|
|
1061 h = Max(h, lh) ;
|
|
1062 w += lwm + hmargin ;
|
|
1063 }
|
|
1064 }
|
|
1065
|
|
1066 w += hmargin*2 ;
|
|
1067 h += vmargin*2 ;
|
|
1068
|
|
1069 *wid = w ;
|
|
1070 *hgt = h ;
|
|
1071 }
|
|
1072
|
|
1073
|
|
1074
|
|
1075 static void
|
|
1076 AutoScale (GaugeWidget gw)
|
|
1077 {
|
|
1078 static int scales[3] = {1,2,5} ;
|
|
1079 int sptr = 0, smult=1 ;
|
|
1080
|
|
1081 if( gw->gauge.autoScaleDown )
|
|
1082 gw->gauge.v1 = 0 ;
|
|
1083 while( gw->gauge.value > gw->gauge.v1 )
|
|
1084 {
|
|
1085 if( ++sptr > 2 ) {
|
|
1086 sptr = 0 ;
|
|
1087 smult *= 10 ;
|
|
1088 }
|
|
1089 gw->gauge.v1 = scales[sptr] * smult ;
|
|
1090 }
|
|
1091 }
|
|
1092
|
|
1093 static void
|
|
1094 EnableUpdate (GaugeWidget gw)
|
|
1095 {
|
|
1096 gw->gauge.intervalId =
|
|
1097 XtAppAddTimeOut(XtWidgetToApplicationContext((Widget)gw),
|
|
1098 gw->gauge.update * MS_PER_SEC, GaugeGetValue,
|
|
1099 (XtPointer)gw) ;
|
|
1100 }
|
|
1101
|
|
1102 static void
|
|
1103 DisableUpdate (GaugeWidget gw)
|
|
1104 {
|
|
1105 XtRemoveTimeOut(gw->gauge.intervalId) ;
|
|
1106 }
|
|
1107
|
|
1108 static void
|
|
1109 GaugeGetValue (XtPointer clientData,
|
|
1110 XtIntervalId *intervalId)
|
|
1111 {
|
|
1112 GaugeWidget gw = (GaugeWidget)clientData ;
|
|
1113 Cardinal value ;
|
|
1114
|
|
1115 if( gw->gauge.update > 0 )
|
|
1116 EnableUpdate(gw) ;
|
|
1117
|
|
1118 if( gw->gauge.getValue != NULL )
|
|
1119 {
|
|
1120 XtCallCallbackList((Widget)gw, gw->gauge.getValue, (XtPointer)&value);
|
|
1121 XawGaugeSetValue((Widget)gw, value) ;
|
|
1122 }
|
|
1123 }
|
|
1124
|
|
1125
|
|
1126 static GC
|
|
1127 Get_GC (GaugeWidget gw,
|
|
1128 Pixel fg)
|
|
1129 {
|
|
1130 XGCValues values ;
|
|
1131 #define vmask GCForeground
|
|
1132 #define umask (GCBackground|GCSubwindowMode|GCGraphicsExposures|GCDashOffset\
|
|
1133 |GCFont|GCDashList|GCArcMode)
|
|
1134
|
|
1135 values.foreground = fg ;
|
|
1136
|
|
1137 return XtAllocateGC((Widget)gw, 0, vmask, &values, 0L, umask) ;
|
|
1138 }
|