1 /*
2 **
3 ** Vlist.c
4 **
5 ** Copyright (C) 1995, 1996, 1997 Johannes Plass
6 ** Copyright (C) 2004 Jose E. Marchesi
7 ** modified 2008 by Bernhard R. Link
8 **
9 ** This program is free software; you can redistribute it and/or modify
10 ** it under the terms of the GNU General Public License as published by
11 ** the Free Software Foundation; either version 3 of the License, or
12 ** (at your option) any later version.
13 **
14 ** This program is distributed in the hope that it will be useful,
15 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 ** GNU General Public License for more details.
18 **
19 ** You should have received a copy of the GNU General Public License
20 ** along with GNU gv; see the file COPYING. If not, write to
21 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 ** Boston, MA 02111-1307, USA.
23 **
24 ** Author: Johannes Plass (plass@thep.physik.uni-mainz.de)
25 ** Department of Physics
26 ** Johannes Gutenberg-University
27 ** Mainz, Germany
28 **
29 ** Jose E. Marchesi (jemarch@gnu.org)
30 ** GNU Project
31 **
32 */
33
34 #include "ac_config.h"
35
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <math.h>
39 /*
40 #define MESSAGES
41 */
42 #include "message.h"
43
44 #include "paths.h"
45 #include INC_X11(IntrinsicP.h)
46 #include INC_X11(StringDefs.h)
47 #include INC_XMU(Misc.h)
48 #include INC_XAW(XawInit.h)
49 #include "VlistP.h"
50 #include "Frame.h"
51 #include INC_XMU(Converters.h)
52
53 #define VLIST_MARK_LEFT_INDENT 4
54 #define VLIST_MARK_LABEL_INTERNAL_WIDTH 11
55 #define VLIST_MARK_LABEL_INDENT 4
56 #define VLIST_MARK_VERTICAL_INDENT 3
57 #define VLIST_MARK_WIDTH 5
58
59 /****************************************************************
60 *
61 * Full class record constant
62 *
63 ****************************************************************/
64
65 /* Private Data */
66
67 static char defaultTranslations[] = "";
68
69 #define offset(field) XtOffsetOf(VlistRec, field)
70 static XtResource resources[] = {
71 {XtNreportCallback, XtCReportCallback, XtRCallback, sizeof(XtPointer),
72 offset(vlist.report_callbacks), XtRCallback, (XtPointer) NULL },
73 {XtNselectedShadowWidth, XtCShadowWidth, XtRDimension, sizeof(Dimension),
74 offset(vlist.selected_shadow_width), XtRImmediate, (XtPointer) 1},
75 {XtNmarkShadowWidth, XtCShadowWidth, XtRDimension, sizeof(Dimension),
76 offset(vlist.mark_shadow_width), XtRImmediate, (XtPointer) 1},
77 {XtNhighlightedShadowWidth, XtCShadowWidth, XtRDimension, sizeof(Dimension),
78 offset(vlist.highlighted_shadow_width), XtRImmediate, (XtPointer) 1},
79 {XtNhighlightedGeometry, XtCHighlightedGeometry, XtRString, sizeof(String),
80 offset(vlist.highlighted_geometry), XtRImmediate, (XtPointer)"2 0 -2 1"},
81 {XtNselectedGeometry, XtCSelectedGeometry, XtRString, sizeof(String),
82 offset(vlist.selected_geometry), XtRImmediate, (XtPointer)"12 0 -2 1"},
83 {XtNvlist, XtCVlist, XtRString, sizeof(String),
84 offset(vlist.vlist), XtRString, NULL},
85 {XtNmarkBackground, XtCMarkBackground, XtRPixel, sizeof(Pixel),
86 offset(vlist.mark_background), XtRString, XtDefaultBackground},
87 {XtNselectedBackground, XtCSelectedBackground, XtRPixel, sizeof(Pixel),
88 offset(vlist.selected_background), XtRString, XtDefaultBackground},
89 {XtNhighlightedBackground, XtCHighlightedBackground, XtRPixel, sizeof(Pixel),
90 offset(vlist.highlighted_background), XtRString, XtDefaultBackground},
91 {XtNshadowWidth, XtCShadowWidth, XtRDimension, sizeof(Dimension),
92 offset(threeD.shadow_width), XtRImmediate, (XtPointer) 2},
93 {XtNallowMarks, XtCAllowMarks, XtRBoolean, sizeof(Boolean),
94 offset(vlist.allow_marks), XtRImmediate, (XtPointer)True},
95 {XtNinternalWidth, XtCWidth, XtRDimension, sizeof(Dimension),
96 offset(label.internal_width), XtRImmediate, (XtPointer)VLIST_MARK_LABEL_INTERNAL_WIDTH},
97 {XtNborderWidth, XtCBorderWidth, XtRDimension, sizeof(Dimension),
98 XtOffsetOf(RectObjRec,rectangle.border_width), XtRImmediate,
99 (XtPointer)0}
100 };
101 #undef offset
102
103 static Boolean SetValues(Widget,Widget,Widget,ArgList,Cardinal*);
104 static void Initialize(Widget,Widget,ArgList,Cardinal*);
105 static void Redisplay(Widget,XEvent*,Region);
106 static void Destroy(Widget);
107 static void PaintVlistWidget(Widget,XEvent*,Region);
108 static void ClassInitialize(void);
109 static void Resize(Widget);
110 static void PaintMarkOfEntry(Widget,Region,int,int,Boolean);
111 static void PaintMarkMarkOfEntry(Widget,Region,int,Boolean);
112
113
114 #define SuperClass ((LabelWidgetClass)&labelClassRec)
115
116 VlistClassRec vlistClassRec = {
117 {
118 (WidgetClass) SuperClass, /* superclass */
119 "Vlist", /* class_name */
120 sizeof(VlistRec), /* size */
121 ClassInitialize, /* class_initialize */
122 NULL, /* class_part_initialize */
123 FALSE, /* class_inited */
124 Initialize, /* initialize */
125 NULL, /* initialize_hook */
126 XtInheritRealize, /* realize */
127 NULL, /* actions */
128 0, /* num_actions */
129 resources, /* resources */
130 XtNumber(resources), /* resource_count */
131 NULLQUARK, /* xrm_class */
132 TRUE, /* compress_motion */
133 TRUE, /* compress_exposure */
134 TRUE, /* compress_enterleave */
135 FALSE, /* visible_interest */
136 Destroy, /* destroy */
137 Resize, /* resize */
138 Redisplay, /* expose */
139 SetValues, /* set_values */
140 NULL, /* set_values_hook */
141 XtInheritSetValuesAlmost, /* set_values_almost */
142 NULL, /* get_values_hook */
143 NULL, /* accept_focus */
144 XtVersion, /* version */
145 NULL, /* callback_private */
146 defaultTranslations, /* tm_table */
147 XtInheritQueryGeometry, /* query_geometry */
148 XtInheritDisplayAccelerator, /* display_accelerator */
149 NULL /* extension */
150 }, /* CoreClass fields initialization */
151 {
152 XtInheritChangeSensitive /* change_sensitive */
153 }, /* SimpleClass fields initialization */
154 {
155 XtInheritXaw3dShadowDraw, /* shadowdraw */
156 }, /* ThreeD Class fields initialization */
157 {
158 0, /* field not used */
159 }, /* LabelClass fields initialization */
160 {
161 0, /* field not used */
162 }, /* VlistClass fields initialization */
163 };
164
165 /* for public consumption */
166 WidgetClass vlistWidgetClass = (WidgetClass) &vlistClassRec;
167
168 /*---------------------------------------------------*/
169 /* ClassInitialize */
170 /*---------------------------------------------------*/
171
ClassInitialize(void)172 static void ClassInitialize(void)
173 {
174 BEGINMESSAGE(ClassInitialize)
175 XawInitializeWidgetSet();
176 ENDMESSAGE(ClassInitialize)
177 }
178
179 /*---------------------------------------------------*/
180 /* Initialize */
181 /*---------------------------------------------------*/
182
183 static void
Initialize(Widget request _GL_UNUSED,Widget new,ArgList args _GL_UNUSED,Cardinal * num_args _GL_UNUSED)184 Initialize(Widget request _GL_UNUSED, Widget new, ArgList args _GL_UNUSED, Cardinal *num_args _GL_UNUSED)
185 {
186 VlistWidget vw = (VlistWidget) new;
187 String s="";
188 char *c;
189 XGCValues values;
190
191 BEGINMESSAGE(Initialize)
192 if (vw->vlist.vlist) s = vw->vlist.vlist;
193 vw->vlist.vlist = XtNewString(s);
194 c = vw->vlist.vlist;
195 vw->vlist.firstVisible = 0;
196 vw->vlist.selected = -1;
197 vw->vlist.highlighted = -1;
198 vw->vlist.entries = (int)strlen(vw->vlist.vlist);
199 sscanf(vw->vlist.highlighted_geometry,"%d %d %d %d",
200 &(vw->vlist.hulx),&(vw->vlist.huly),&(vw->vlist.hlrx),&(vw->vlist.hlry));
201 sscanf(vw->vlist.selected_geometry,"%d %d %d %d",
202 &(vw->vlist.sulx),&(vw->vlist.suly),&(vw->vlist.slrx),&(vw->vlist.slry));
203 /* mark background GC */
204 values.foreground = vw->vlist.mark_background;
205 vw->vlist.mark_background_GC = XtGetGC((Widget)vw,(unsigned) GCForeground,&values);
206 /* selected background GC */
207 values.foreground = vw->vlist.selected_background;
208 vw->vlist.selected_background_GC = XtGetGC((Widget)vw,(unsigned) GCForeground,&values);
209 /* highlighted background GC */
210 values.foreground = vw->vlist.highlighted_background;
211 vw->vlist.highlighted_background_GC = XtGetGC((Widget)vw,(unsigned) GCForeground,&values);
212 /* background GC */
213 values.foreground = vw->core.background_pixel;
214 values.graphics_exposures = False;
215 vw->vlist.background_GC = XtGetGC((Widget)vw,(unsigned) GCForeground | GCGraphicsExposures,&values);
216
217 /* TODO: check if this works here in international mode, or if it has
218 * to be moved to Realize... */
219 #ifdef HAVE_XAW3D_INTERNATIONAL
220 if( vw->simple.international == True ) {
221 XFontSetExtents *ext = XExtentsOfFontSet(vw->label.fontset);
222 vw->vlist.yofs = (ext->max_ink_extent.y<0)?-ext->max_ink_extent.y:ext->max_ink_extent.y;
223 vw->vlist.ydelta = ext->max_ink_extent.height;
224 } else {
225 #endif
226 vw->vlist.yofs = vw->label.font->max_bounds.ascent;
227 vw->vlist.ydelta = vw->label.font->max_bounds.ascent + vw->label.font->max_bounds.descent;
228 #ifdef HAVE_XAW3D_INTERNATIONAL
229 }
230 #endif
231
232 ENDMESSAGE(Initialize)
233 }
234
235 /*---------------------------------------------------*/
236 /* Redisplay */
237 /*---------------------------------------------------*/
238
239 static void
Redisplay(Widget w,XEvent * event,Region region)240 Redisplay(Widget w, XEvent *event, Region region)
241 {
242 BEGINMESSAGE(Redisplay)
243 PaintVlistWidget(w, event, region);
244 ENDMESSAGE(Redisplay)
245 }
246
247 /*---------------------------------------------------*/
248 /* Resize */
249 /*---------------------------------------------------*/
250
shiftLabel(VlistWidget vw)251 static void shiftLabel(VlistWidget vw)
252 {
253 BEGINMESSAGE(shiftLabel)
254 if (vw->vlist.allow_marks) {
255 vw->label.label_x = vw->label.internal_width +
256 vw->threeD.shadow_width +
257 VLIST_MARK_LABEL_INDENT;
258 }
259 ENDMESSAGE(shiftLabel)
260 }
261
Resize(Widget w)262 static void Resize(Widget w)
263 {
264 VlistWidget vw = (VlistWidget) w;
265 BEGINMESSAGE(Resize)
266 (*vlistWidgetClass->core_class.superclass->core_class.resize)(w);
267 shiftLabel(vw);
268 ENDMESSAGE(Resize)
269 }
270
271 /*---------------------------------------------------*/
272 /* SetValues */
273 /*---------------------------------------------------*/
274
275 static Boolean
SetValues(Widget current,Widget request _GL_UNUSED,Widget new,ArgList args _GL_UNUSED,Cardinal * num_args _GL_UNUSED)276 SetValues (Widget current, Widget request _GL_UNUSED, Widget new, ArgList args _GL_UNUSED, Cardinal *num_args _GL_UNUSED)
277 {
278 VlistWidget cvw = (VlistWidget) current;
279 VlistWidget nvw = (VlistWidget) new;
280 Boolean changed = False;
281
282 BEGINMESSAGE(SetValues)
283 if (nvw->vlist.vlist == NULL) nvw->vlist.vlist = "";
284 if (cvw->vlist.vlist != nvw->vlist.vlist) {
285 XtFree((char *)cvw->vlist.vlist);
286 nvw->vlist.vlist = XtNewString(nvw->vlist.vlist);
287 nvw->vlist.entries = (int)strlen(nvw->vlist.vlist);
288 if (!nvw->vlist.entries) nvw->vlist.entries =- 1;
289 SMESSAGE(nvw->vlist.vlist)
290 IMESSAGE(nvw->vlist.entries)
291 changed = True;
292 }
293 ENDMESSAGE(SetValues)
294 return (changed);
295 }
296
297 /*---------------------------------------------------*/
298 /* Destroy */
299 /*---------------------------------------------------*/
300
301 static void
Destroy(Widget w)302 Destroy(Widget w)
303 {
304 VlistWidget vw = (VlistWidget)w;
305
306 BEGINMESSAGE(Destroy)
307 XtFree(vw->vlist.vlist);
308 XtReleaseGC(w,vw->vlist.background_GC);
309 XtReleaseGC(w,vw->vlist.mark_background_GC);
310 XtReleaseGC(w,vw->vlist.selected_background_GC);
311 XtReleaseGC(w,vw->vlist.highlighted_background_GC);
312 ENDMESSAGE(Destroy)
313 }
314
315 /*---------------------------------------------------*/
316 /* PaintEntryString */
317 /*---------------------------------------------------*/
318
319 static void
PaintEntryString(Widget w,int entry)320 PaintEntryString(Widget w, int entry)
321 {
322 VlistWidget vw = (VlistWidget)w;
323 char * s;
324 int i;
325 int yofs = vw->vlist.yofs, ydelta = vw->vlist.ydelta;
326
327 yofs -= ydelta * vw->vlist.firstVisible;
328
329 BEGINMESSAGE1(PaintEntryString)
330 s = vw->label.label;
331 i = entry;
332 if (s) while (i > 0 && (s = strchr(s,'\n'))) { s++; i--; }
333 if (s) {
334 char *nl = strchr(s,'\n');
335 int len;
336 if (nl)
337 len = nl - s;
338 else
339 len = strlen(s);
340 #ifdef HAVE_XAW3D_INTERNATIONAL
341 if( vw->simple.international == True )
342 XmbDrawString(XtDisplay(w), XtWindow(w), vw->label.fontset,
343 vw->label.normal_GC,
344 vw->label.label_x, vw->label.label_y + yofs + entry*ydelta,
345 s, len);
346 else
347 #endif
348 XDrawString(XtDisplay(w), XtWindow(w), vw->label.normal_GC,
349 vw->label.label_x, vw->label.label_y + yofs + entry*ydelta,
350 s, len);
351 }
352 ENDMESSAGE1(PaintEntryString)
353 }
354
355 /*---------------------------------------------------*/
356 /* PaintMarkOfEntry */
357 /*---------------------------------------------------*/
358
359 static int
PaintMark(Widget w,Region region,int entry,int style,Boolean erase)360 PaintMark(Widget w, Region region, int entry, int style, Boolean erase)
361 {
362 VlistWidget vw = (VlistWidget)w;
363 int ss,ulx,uly,lrx,lry,ret=0;
364 Position x,y;
365 Dimension width,height;
366 Dimension sw;
367 GC gc;
368
369 BEGINMESSAGE(PaintMark)
370 IIMESSAGE(entry,erase)
371 if (entry < 0 || entry >= vw->vlist.entries) {
372 INFMESSAGE(invalid entry)
373 ENDMESSAGE(PaintMark)
374 return(ret);
375 }
376 if (entry < vw->vlist.firstVisible) {
377 ENDMESSAGE(PaintMark)
378 return 0;
379 }
380 if (style<0) { /* highlighted */
381 INFMESSAGE(highlighted entry)
382 ulx = vw->vlist.hulx;
383 uly = vw->vlist.huly;
384 lrx = vw->vlist.hlrx;
385 lry = vw->vlist.hlry;
386 sw = vw->vlist.highlighted_shadow_width;
387 gc = vw->vlist.highlighted_background_GC;
388 } else { /* selected */
389 INFMESSAGE(selected entry)
390 ulx = vw->vlist.sulx;
391 uly = vw->vlist.suly;
392 lrx = vw->vlist.slrx;
393 lry = vw->vlist.slry;
394 sw = vw->vlist.selected_shadow_width;
395 gc = vw->vlist.selected_background_GC;
396 }
397 x = (Position) ulx;
398 y = (Position) (((int) vw->label.label_y) +
399 ((entry - vw->vlist.firstVisible)*vw->vlist.ydelta) +
400 uly);
401 width = (Dimension)((int) vw->core.width - ulx + lrx);
402 height= (Dimension)(vw->vlist.ydelta - uly + lry + .5);
403 ss = XawSUNKEN;
404 if (region == NULL || XRectInRegion(region,x,y,width,height) != RectangleOut) {
405 if (erase) {
406 INFMESSAGE(clearing entry)
407 XFillRectangle(XtDisplayOfObject(w), XtWindowOfObject(w),vw->vlist.background_GC,x,y,width,height);
408 } else {
409 INFMESSAGE(drawing entry)
410 XFillRectangle(XtDisplayOfObject(w), XtWindowOfObject(w),gc,x,y,width,height);
411 FrameDrawFrame(w,x,y,width,height,ss,sw,
412 vw->threeD.top_shadow_GC,
413 vw->threeD.bot_shadow_GC);
414 }
415 ret=1;
416 }
417 ENDMESSAGE(PaintMark)
418 return ret;
419 }
420
421 static void
PaintMarkOfEntry(Widget w,Region region,int entry,int style,Boolean erase)422 PaintMarkOfEntry(Widget w, Region region, int entry, int style, Boolean erase)
423 {
424 VlistWidget vw = (VlistWidget)w;
425 int pstyle,dstyle,d,p;
426 int drawn=0,pdrawn=0;
427 int order=0;
428
429 BEGINMESSAGE(PaintMarkOfEntry)
430 if (entry < 0 || entry >= vw->vlist.entries) {
431 INFMESSAGE(invalid entry)
432 ENDMESSAGE(PaintMarkOfEntry)
433 return;
434 }
435 d = entry; dstyle=style;
436 if (style<0) { p=vw->vlist.selected; pstyle=1; }
437 else { p=vw->vlist.highlighted; pstyle=-1; }
438 if (d+1 == p) order = 10;
439 else if (d-1 == p) { if (erase) order=10; else order=01; }
440 else if (d==p) { if (dstyle<0) order=10; else order=01; }
441 else order = 999;
442 IIMESSAGE(d,p)
443 IMESSAGE(order)
444 if (order==10 || order == 999) {
445 drawn = PaintMark(w, region, d, dstyle,erase);
446 if (order==10) pdrawn = PaintMark(w, region, p, pstyle,False);
447 } else if (order==01) {
448 pdrawn = PaintMark(w, region, p, pstyle,False);
449 drawn = PaintMark(w, region, d, dstyle,erase);
450 }
451 if (pdrawn) {
452 PaintEntryString(w,p);
453 PaintMarkMarkOfEntry(w,region,p,False);
454 }
455 if (drawn && p!=d) {
456 PaintEntryString(w,d);
457 PaintMarkMarkOfEntry(w,region,d,False);
458 }
459 ENDMESSAGE(PaintMarkOfEntry)
460 }
461
462 /*---------------------------------------------------*/
463 /* PaintMarkMarkOfEntry */
464 /*---------------------------------------------------*/
465
466 static void
PaintMarkMarkOfEntry(Widget w,Region region,int entry,Boolean erase)467 PaintMarkMarkOfEntry(Widget w, Region region, int entry, Boolean erase)
468 {
469 VlistWidget vw = (VlistWidget)w;
470
471 BEGINMESSAGE1(PaintMarkMarkOfEntry)
472 if (vw->vlist.allow_marks) {
473 int ss;
474 Position x,y;
475 Dimension width,height;
476 char *vlist = vw->vlist.vlist;
477 Boolean paint=False;
478
479 if (entry < vw->vlist.firstVisible)
480 return;
481
482 if (vlist[entry] == '*') paint = True;
483 if (paint || erase) {
484 x = (Position) (VLIST_MARK_LEFT_INDENT);
485 y = (Position) (((int) vw->label.label_y) +
486 VLIST_MARK_VERTICAL_INDENT +
487 ((entry-vw->vlist.firstVisible)*vw->vlist.ydelta));
488 width = (Dimension) (VLIST_MARK_WIDTH);
489 height= (Dimension)(vw->vlist.ydelta + 0.5 - 2*VLIST_MARK_VERTICAL_INDENT);
490 ss = XawSUNKEN;
491 if (region == NULL || XRectInRegion(region,x,y,width,height) != RectangleOut) {
492 if (paint) {
493 INFMESSAGE(drawing mark)
494 XFillRectangle(XtDisplayOfObject(w), XtWindowOfObject(w),vw->vlist.mark_background_GC,x,y,width,height);
495 FrameDrawFrame(w,x,y,width,height,ss,vw->vlist.mark_shadow_width,
496 vw->threeD.top_shadow_GC,
497 vw->threeD.bot_shadow_GC);
498 } else {
499 INFMESSAGE(clearing mark)
500 XFillRectangle(XtDisplayOfObject(w), XtWindowOfObject(w),
501 (entry == vw->vlist.highlighted) ? vw->vlist.highlighted_background_GC : vw->vlist.background_GC,
502 x,y,width,height);
503 }
504 }
505 }
506 }
507 ENDMESSAGE1(PaintMarkMarkOfEntry)
508 }
509
510 /*---------------------------------------------------*/
511 /* PaintMarksOfEntries */
512 /*---------------------------------------------------*/
513
514 static void
PaintMarksOfEntries(Widget w,XEvent * event _GL_UNUSED,Region region)515 PaintMarksOfEntries(Widget w, XEvent *event _GL_UNUSED, Region region)
516 {
517 VlistWidget vw = (VlistWidget)w;
518
519 BEGINMESSAGE(PaintMarksOfEntries)
520 PaintMarkOfEntry(w, region, vw->vlist.highlighted,-1, False);
521 if (vw->vlist.allow_marks) {
522 int i= vw->vlist.firstVisible;
523 while (i < vw->vlist.entries) {
524 if (i != vw->vlist.highlighted)
525 PaintMarkMarkOfEntry(w, region, i, False);
526 i++;
527 }
528 }
529 if (vw->vlist.selected != vw->vlist.highlighted && vw->vlist.entries >= 0)
530 PaintMarkOfEntry(w, region, vw->vlist.selected,1, False);
531 ENDMESSAGE(PaintMarksOfEntries)
532 }
533
534 /*---------------------------------------------------*/
535 /* PaintVlistWidget */
536 /*---------------------------------------------------*/
537
538 static void
PaintVlistWidget(Widget w,XEvent * event,Region region)539 PaintVlistWidget(Widget w, XEvent *event, Region region)
540 {
541 Dimension width;
542 char *s, *o;
543 int i, y;
544 VlistWidget vw = (VlistWidget)w;
545 XRectangle rectangle;
546
547 BEGINMESSAGE(PaintVlistWidget)
548 /* better not allow the widget to grow that large, but that needs fixing
549 * of the Clip widget */
550 shiftLabel(vw);
551 PaintMarksOfEntries(w, event, region);
552 width = vw->threeD.shadow_width;
553 o = vw->label.label;
554 s = vw->label.label;
555 i = vw->vlist.firstVisible;
556 if (s) while (i > 0 && (s = strchr(s,'\n'))) { s++; i--; }
557 /* This still fails when the list is too long and does not print anything.
558 * Though that is perhaps best fixed by making Clip to enforce a real window
559 * height...
560 vw->label.label = s;
561 vw->threeD.shadow_width = 0;
562 (*SuperClass->core_class.expose) (w, event, region);
563 vw->threeD.shadow_width = width;
564 vw->label.label = o;
565 until Clip is extended, just manually draw each line:
566 */
567 if (region)
568 XClipBox(region, &rectangle);
569 else {
570 rectangle.x = 0;
571 rectangle.y = 0;
572 rectangle.width = vw->core.width;
573 rectangle.height = vw->core.height;
574 if( rectangle.height >= 0x4000 )
575 rectangle.height = 0x3fff;
576 }
577 y = vw->label.label_y + vw->vlist.yofs;
578 i = 0;
579
580 while (s != NULL) {
581 char *nl = strchr(s, '\n');
582 int len;
583 if (nl)
584 len = nl - s;
585 else
586 len = strlen(s);
587 if (y - vw->vlist.yofs > rectangle.y + rectangle.height)
588 break;
589 if (y + (vw->vlist.ydelta - vw->vlist.yofs) >= rectangle.y) {
590 #ifdef HAVE_XAW3D_INTERNATIONAL
591 if( vw->simple.international == True )
592 XmbDrawString(XtDisplay(w), XtWindow(w), vw->label.fontset,
593 vw->label.normal_GC, vw->label.label_x, y, s, len);
594 else
595 #endif
596 XDrawString(XtDisplay(w), XtWindow(w), vw->label.normal_GC,
597 vw->label.label_x, y, s, len);
598 }
599 if (nl)
600 s = nl + 1;
601 else
602 s = NULL;
603 y += vw->vlist.ydelta;
604 }
605 ENDMESSAGE(PaintVlistWidget)
606 }
607
608 /*####################################################################*/
609 /*####################################################################*/
610 /* Public Routines */
611 /*####################################################################*/
612 /*####################################################################*/
613
614 /*###################################################*/
615 /* VlistSelected */
616 /*###################################################*/
617
618 int
VlistSelected(Widget w)619 VlistSelected(Widget w)
620 {
621 VlistWidget vw = (VlistWidget)w;
622
623 BEGINMESSAGE(VlistSelected)
624 ENDMESSAGE(VlistSelected)
625 return(vw->vlist.selected);
626 }
627
628 /*###################################################*/
629 /* VlistHighlighted */
630 /*###################################################*/
631
632 int
VlistHighlighted(Widget w)633 VlistHighlighted(Widget w)
634 {
635 VlistWidget vw = (VlistWidget)w;
636
637 BEGINMESSAGE(VlistHighlighted)
638 ENDMESSAGE(VlistHighlighted)
639 return(vw->vlist.highlighted);
640 }
641
642 /*###################################################*/
643 /* VlistEntries */
644 /*###################################################*/
645
646 int
VlistEntries(Widget w)647 VlistEntries(Widget w)
648 {
649 VlistWidget vw = (VlistWidget)w;
650
651 BEGINMESSAGE(VlistEntries)
652 ENDMESSAGE(VlistEntries)
653 return(vw->vlist.entries);
654 }
655
656 /*###################################################*/
657 /* VlistVlist */
658 /*###################################################*/
659
660 char*
VlistVlist(Widget w)661 VlistVlist(Widget w)
662 {
663 VlistWidget vw = (VlistWidget)w;
664
665 BEGINMESSAGE(VlistVlist)
666 ENDMESSAGE(VlistVlist)
667 return(vw->vlist.vlist);
668 }
669
670 /*###################################################*/
671 /* VlistEntryOfPosition */
672 /*###################################################*/
673
674 int
VlistEntryOfPosition(Widget w,int y)675 VlistEntryOfPosition(Widget w, int y)
676 {
677 VlistWidget vw = (VlistWidget)w;
678 int entry = -1;
679
680 BEGINMESSAGE(VlistEntryOfPosition)
681 y = y - (int) vw->label.label_y;
682 if (vw->vlist.ydelta > 0) {
683 if (y < 0) entry = -1;
684 else entry = y/vw->vlist.ydelta;
685 }
686 if (entry >= vw->vlist.entries)
687 entry = vw->vlist.entries-1;
688 if (entry >= 0)
689 entry += vw->vlist.firstVisible;
690 IMESSAGE(entry)
691 ENDMESSAGE(VlistEntryOfPosition)
692 return(entry);
693 }
694
695 /*###################################################*/
696 /* VlistPositionOfEntry */
697 /*###################################################*/
698
699 void
VlistPositionOfEntry(Widget w,int e,int * yuP,int * ylP)700 VlistPositionOfEntry(Widget w, int e, int *yuP, int *ylP)
701 {
702 VlistWidget vw = (VlistWidget)w;
703 float h;
704 BEGINMESSAGE(VlistPositionOfEntry)
705 *yuP = *ylP = (int) vw->label.label_y;
706 if (e >= vw->vlist.firstVisible && vw->vlist.entries > 0) {
707 e -= vw->vlist.firstVisible;
708 h = vw->vlist.ydelta;
709 *yuP += (int)((float)e*h);
710 *ylP += (int)((float)(e+1)*h);
711 }
712 ENDMESSAGE(VlistPositionOfEntry)
713 }
714
715 /*###################################################*/
716 /* VlistChangeMark */
717 /*###################################################*/
718
719 void
VlistChangeMark(Widget w,int entry,int change)720 VlistChangeMark(Widget w, int entry,int change)
721 {
722 VlistWidget vw = (VlistWidget)w;
723 char *vlist=vw->vlist.vlist;
724 Boolean paint;
725 int lb,ub,st;
726
727 BEGINMESSAGE(VlistChangeMark)
728 switch (entry) {
729 case XawVlistAll:
730 lb=0;
731 ub=vw->vlist.entries-1;
732 st=1;
733 break;
734 case XawVlistEven:
735 lb=1;
736 ub=vw->vlist.entries-1;
737 st=2;
738 break;
739 case XawVlistOdd:
740 lb=0;
741 ub=vw->vlist.entries-1;
742 st=2;
743 break;
744 case XawVlistCurrent:
745 lb=vw->vlist.selected;
746 ub=vw->vlist.selected;
747 st=1;
748 break;
749 default:
750 lb=entry;
751 ub=entry;
752 st=1;
753 break;
754 }
755
756 if (ub < 0 || ub >= vw->vlist.entries) {
757 INFMESSAGE(invalid setup)
758 ENDMESSAGE(VlistChangeMark)
759 return;
760 }
761
762 entry=lb;
763 while (entry <= ub) {
764 paint=False;
765 switch (change) {
766 case XawVlistToggle:
767 switch (vlist[entry]) {
768 case '*':
769 vlist[entry]=' ';
770 paint=True;
771 break;
772 default:
773 vlist[entry]='*';
774 paint=True;
775 break;
776 }
777 break;
778 case XawVlistSet:
779 vlist[entry]='*';
780 paint=True;
781 break;
782 case XawVlistUnset:
783 vlist[entry]=' ';
784 paint=True;
785 break;
786 default:
787 INFMESSAGE(invalid action)
788 break;
789 }
790 if (paint) PaintMarkMarkOfEntry(w,NULL,entry,True);
791 entry += st;
792 }
793 ENDMESSAGE(VlistChangeMark)
794 }
795
796 /*---------------------------------------------------*/
797 /* vlist_change_mark */
798 /*---------------------------------------------------*/
799
800 static void
vlist_change_mark(Widget w,int e,int change,int kind)801 vlist_change_mark(Widget w, int e, int change, int kind)
802 {
803 VlistWidget vw = (VlistWidget)w;
804 int *eP;
805
806 BEGINMESSAGE(vlist_change_mark)
807 if (kind < 0) eP = &(vw->vlist.highlighted);
808 else eP = &(vw->vlist.selected);
809 switch (change) {
810 case XawVlistSet:
811 if (*eP >= 0 && *eP < vw->vlist.entries) PaintMarkOfEntry(w,NULL,*eP,kind,True);
812 *eP = -1;
813 if (e >= 0 && e < vw->vlist.entries) {
814 PaintMarkOfEntry(w,NULL,e,kind,False);
815 *eP = e;
816 }
817 break;
818 case XawVlistUnset:
819 if (*eP >= 0 && *eP < vw->vlist.entries) PaintMarkOfEntry(w,NULL,*eP,kind,True);
820 *eP = -1;
821 break;
822 default:
823 INFMESSAGE(invalid action)
824 break;
825 }
826 ENDMESSAGE(vlist_change_mark)
827 }
828
829 /*###################################################*/
830 /* VlistChangeSelected */
831 /*###################################################*/
832
833 void
VlistChangeSelected(Widget w,int entry,int change)834 VlistChangeSelected(Widget w, int entry, int change)
835 {
836 BEGINMESSAGE(VlistChangeSelected)
837 vlist_change_mark(w,entry,change,1);
838 ENDMESSAGE(VlistChangeSelected)
839 }
840
841 /*###################################################*/
842 /* VlistChangeHighlighted */
843 /*###################################################*/
844
845 void
VlistChangeHighlighted(Widget w,int entry,int change)846 VlistChangeHighlighted(Widget w, int entry, int change)
847 {
848 BEGINMESSAGE(VlistChangeHighlighted)
849 vlist_change_mark(w,entry,change,-1);
850 ENDMESSAGE(VlistChangeHighlighted)
851 }
852
853 /*###################################################*/
854 /* VlistGetFirstVisible */
855 /*###################################################*/
856
VlistGetFirstVisible(Widget w)857 int VlistGetFirstVisible(Widget w)
858 {
859 VlistWidget vw = (VlistWidget)w;
860
861 return vw->vlist.firstVisible;
862 }
863
864 /*###################################################*/
865 /* VlistSetFirstVisible */
866 /*###################################################*/
867
VlistSetFirstVisible(Widget w,int newf)868 void VlistSetFirstVisible(Widget w, int newf)
869 {
870 VlistWidget vw = (VlistWidget)w;
871 unsigned int height;
872
873 BEGINMESSAGE(VlistSetFirstVisible)
874 IIMESSAGE(newf,vw->vlist.entries)
875 if (newf < 0)
876 newf = 0;
877 else if (newf >= vw->vlist.entries)
878 newf = vw->vlist.entries - 1;
879 if (newf == -1) {
880 ENDMESSAGE(VlistSetFirstVisible)
881 return;
882 }
883 IIMESSAGE(newf,vw->vlist.firstVisible)
884 if (newf != vw->vlist.firstVisible) {
885 vw->vlist.firstVisible = newf;
886 /* better not allow the widget to grow that large, but that needs fixing
887 * of the Clip widget */
888 height = vw->core.height;
889 if( height >= 0x8000 )
890 height = 0x3fff;
891 IIMESSAGE(vw->core.height,height)
892 XFillRectangle(XtDisplayOfObject(w), XtWindowOfObject(w), vw->vlist.background_GC,
893 vw->core.x, vw->core.y, vw->core.width, height);
894 Redisplay(w, NULL, NULL);
895 if (vw->vlist.report_callbacks)
896 XtCallCallbackList (w, vw->vlist.report_callbacks, (XtPointer)0);
897 }
898 ENDMESSAGE(VlistSetFirstVisible)
899 }
900 /*###################################################*/
901 /* VlistMoveFirstVisible */
902 /*###################################################*/
903
904 extern int debug_p;
905
VlistMoveFirstVisible(Widget w,int start,int ydiff)906 void VlistMoveFirstVisible(Widget w, int start, int ydiff)
907 {
908 VlistWidget vw = (VlistWidget)w;
909 int ly;
910 int newf;
911
912 BEGINMESSAGE(VlistMoveFirstVisible)
913 IIMESSAGE(start,ydiff)
914 ly = vw->vlist.ydelta;
915 if (debug_p) fprintf(stderr, "move: start=%d ydiff=%d ly=%d\n", start, ydiff, ly);
916
917 if (ydiff > 0 && ly > ydiff) ydiff=ly;
918 if (ydiff < 0 && ly > -ydiff) ydiff=-ly;
919
920 if (ydiff >= 0)
921 ydiff += ly/2;
922 else
923 ydiff -= ly/2;
924
925 newf = start + ydiff/ly;
926 VlistSetFirstVisible(w, newf);
927 ENDMESSAGE(VlistMoveFirstVisible)
928 }
929
930 /*###################################################*/
931 /* VlistScrollPosition */
932 /*###################################################*/
933
VlistScrollPosition(Widget w)934 float VlistScrollPosition(Widget w)
935 {
936 VlistWidget vw = (VlistWidget)w;
937 float position;
938
939 #if 0
940 printf("Scroll position %d/%d=%f\n",
941 vw->vlist.firstVisible,(int)(vw->vlist.entries),
942 vw->vlist.firstVisible/(float)(vw->vlist.entries));
943 #endif
944 position = vw->vlist.firstVisible/(float)vw->vlist.entries;
945 INFMESSAGE(VlistScrollPosition)
946 IIMESSAGE(vw->vlist.firstVisible,vw->vlist.entries)
947 FMESSAGE(position)
948 return position;
949 }
950
VlistVisibleLength(Widget w,unsigned int height)951 float VlistVisibleLength(Widget w, unsigned int height)
952 {
953 VlistWidget vw = (VlistWidget)w;
954 float percent;
955 int entriesvisible = -1;
956
957 if (vw->vlist.ydelta > 0) {
958 entriesvisible = height/vw->vlist.ydelta;
959 }
960 #if 0
961 printf("fitting %d entries of height %d in %d",
962 entriesvisible, (int)vw->vlist.ydelta, (int)height);
963 #endif
964 if (entriesvisible >= vw->vlist.entries)
965 entriesvisible = vw->vlist.entries;
966 #if 0
967 printf(", visible percents %d/%d=%f\n",
968 entriesvisible,(int)(vw->vlist.entries),
969 entriesvisible/(float)(vw->vlist.entries));
970 #endif
971 percent = entriesvisible/(float)(vw->vlist.entries);
972 INFMESSAGE(VlistVisibleLength)
973 IIMESSAGE(entriesvisible,vw->vlist.entries)
974 FMESSAGE(percent)
975 return percent;
976 }
977
VlistMaxEntriesVisible(Widget w,int height)978 int VlistMaxEntriesVisible(Widget w, int height)
979 {
980 VlistWidget vw = (VlistWidget)w;
981 int entriesvisible = -1;
982
983 if (vw->vlist.ydelta > 0) {
984 entriesvisible = (height - vw->label.label_y)/vw->vlist.ydelta;
985 }
986
987 INFIMESSAGE(VlistMaxEntriesVisible,entriesvisible)
988
989 return entriesvisible;
990 }
991