1
/*-----------------------------------------------------------------------------
2
* ListTree A list widget that displays a file manager style tree
4
* Copyright (c) 1996 Robert W. McMullen
6
* This library is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU Library General Public
8
* License as published by the Free Software Foundation; either
9
* version 2 of the License, or (at your option) any later version.
11
* This library is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
* Library General Public License for more details.
16
* You should have received a copy of the GNU Library General Public
17
* License along with this library; if not, write to the Free
18
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21
* Author: Rob McMullen <rwmcm@mail.ae.utexas.edu>
22
* http://www.ae.utexas.edu/~rwmcm
25
/* see ListTree.h !! */
26
/* #define _ListTree_ */
30
#include <X11/IntrinsicP.h>
31
#include <X11/StringDefs.h>
37
#include "ListTreeP.h"
43
#define __FUNCTION__ "-unknown-"
50
static void LT_DBG(int line, const char *fcn, const char *fmt, ...)
54
fprintf(stderr, "%s:%d %s() ",__FILE__,line,fcn);
56
vfprintf(stderr, fmt, ap);
59
#define DARG __LINE__,__FUNCTION__
60
#define LT_DBGW(a) fprintf(stderr,"%s:%d %s() %s\n",__FILE__,__LINE__,__FUNCTION__, a)
62
static void LT_DBG(int line, const char *fcn, const char *fmt, ...)
65
#define DARG __LINE__,__FUNCTION__
70
#define folder_width 16
71
#define folder_height 12
72
static unsigned char folder_bits[] =
74
0x00, 0x1f, 0x80, 0x20, 0x7c, 0x5f, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40,
75
0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0xfc, 0x3f,
78
#define folderopen_width 16
79
#define folderopen_height 12
80
static unsigned char folderopen_bits[] =
82
0x00, 0x3e, 0x00, 0x41, 0xf8, 0xd5, 0xac, 0xaa, 0x54, 0xd5, 0xfe, 0xaf,
83
0x01, 0xd0, 0x02, 0xa0, 0x02, 0xe0, 0x04, 0xc0, 0x04, 0xc0, 0xf8, 0x7f,
86
#define document_width 9
87
#define document_height 14
88
static unsigned char document_bits[] =
90
0x1f, 0x00, 0x31, 0x00, 0x51, 0x00, 0x91, 0x00, 0xf1, 0x01, 0x01, 0x01,
91
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
92
0x01, 0x01, 0xff, 0x01,};
94
#define offset(field) XtOffsetOf(ListTreeRec, list.field)
95
static XtResource resources[] =
97
{XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
98
offset(foreground_pixel), XtRString, XtDefaultForeground},
99
{XtNmargin, XtCMargin, XtRDimension, sizeof(Dimension),
100
offset(Margin), XtRImmediate, (XtPointer) 2},
101
{XtNindent, XtCMargin, XtRDimension, sizeof(Dimension),
102
offset(Indent), XtRImmediate, (XtPointer) 0},
103
{XtNhorizontalSpacing, XtCMargin, XtRDimension, sizeof(Dimension),
104
offset(HSpacing), XtRImmediate, (XtPointer) 2},
105
{XtNverticalSpacing, XtCMargin, XtRDimension, sizeof(Dimension),
106
offset(VSpacing), XtRImmediate, (XtPointer) 0},
107
{XtNlineWidth, XtCMargin, XtRDimension, sizeof(Dimension),
108
offset(LineWidth), XtRImmediate, (XtPointer) 0},
109
{XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *),
110
offset(font), XtRString, XtDefaultFont},
111
{XtNhighlightPath, XtCBoolean, XtRBoolean, sizeof(Boolean),
112
offset(HighlightPath), XtRImmediate, (XtPointer) False},
113
{XtNclickPixmapToOpen, XtCBoolean, XtRBoolean, sizeof(Boolean),
114
offset(ClickPixmapToOpen), XtRImmediate, (XtPointer) True},
115
{XtNdoIncrementalHighlightCallback, XtCBoolean, XtRBoolean, sizeof(Boolean),
116
offset(DoIncrementalHighlightCallback), XtRImmediate, (XtPointer) False},
117
{XtNbranchPixmap, XtCPixmap, XtRBitmap, sizeof(Pixmap),
118
offset(Closed.bitmap), XtRImmediate, (XtPointer) XtUnspecifiedPixmap},
119
{XtNbranchOpenPixmap, XtCPixmap, XtRBitmap, sizeof(Pixmap),
120
offset(Open.bitmap), XtRImmediate, (XtPointer) XtUnspecifiedPixmap},
121
{XtNleafPixmap, XtCPixmap, XtRBitmap, sizeof(Pixmap),
122
offset(Leaf.bitmap), XtRImmediate, (XtPointer) XtUnspecifiedPixmap},
123
{XtNleafOpenPixmap, XtCPixmap, XtRBitmap, sizeof(Pixmap),
124
offset(LeafOpen.bitmap), XtRImmediate, (XtPointer) XtUnspecifiedPixmap},
125
{XtNhighlightCallback, XtCCallback, XtRCallback, sizeof(XtPointer),
126
offset(HighlightCallback), XtRCallback, NULL},
127
{XtNactivateCallback, XtCCallback, XtRCallback, sizeof(XtPointer),
128
offset(ActivateCallback), XtRCallback, NULL},
129
{XtNmenuCallback, XtCCallback, XtRCallback, sizeof(XtPointer),
130
offset(MenuCallback), XtRCallback, NULL},
131
{XtNdestroyItemCallback, XtCCallback, XtRCallback, sizeof(XtPointer),
132
offset(DestroyItemCallback), XtRCallback, NULL},
133
{XtNcreateItemCallback, XtCCallback, XtRCallback, sizeof(XtPointer),
134
offset(CreateItemCallback), XtRCallback, NULL},
138
{XtNlistMode, XtCListMode, XtRBoolean, sizeof(Boolean),
139
offset(ListMode), XtRImmediate, (XtPointer)True }
147
static void Initialize P_((Widget req, Widget new,
148
ArgList args, Cardinal *num));
149
static void Destroy P_((Widget w));
150
static void Redisplay P_((Widget w, XEvent *event, Region region));
151
static void Resize P_((Widget w));
152
static Boolean SetValues P_((Widget old, Widget req, Widget new,
153
ArgList args, Cardinal *num));
154
static void Realize P_((Widget w, XtValueMask *mask,
155
XSetWindowAttributes *attr));
156
static XtGeometryResult QueryGeometry P_((Widget w, XtWidgetGeometry *request,
157
XtWidgetGeometry *reply));
159
/* Helper functions */
160
static void Draw P_((ListTreeWidget w, int yevent,int hevent));
161
static void DrawAll P_((ListTreeWidget w));
162
static void DrawChanged P_((ListTreeWidget w));
163
static void DrawItemHighlight P_((ListTreeWidget w, ListTreeItem *item));
164
static void DrawItemHighlightClear P_((ListTreeWidget w, ListTreeItem
166
static ListTreeItem *GetItem P_((ListTreeWidget w, int findy));
168
static void DeleteChildren P_((ListTreeWidget w, ListTreeItem *item));
169
static void DeleteItem P_((ListTreeWidget w, ListTreeItem *item));
170
static void CountAll P_((ListTreeWidget w));
171
static void GotoPosition P_((ListTreeWidget w));
172
static void VSBCallback P_((Widget w, XtPointer client_data, XtPointer
174
static void HSBCallback P_((Widget w, XtPointer client_data, XtPointer
178
static void focus_in P_((Widget aw, XEvent *event, String *params,
179
Cardinal *num_params));
180
static void focus_out P_((Widget aw, XEvent *event, String *params,
181
Cardinal *num_params));
182
static void notify P_((Widget aw, XEvent *event, String *params,
183
Cardinal *num_params));
184
static void unset P_((Widget aw, XEvent *event, String *params,
185
Cardinal *num_params));
186
static void menu P_((Widget aw, XEvent *event, String *params,
187
Cardinal *num_params));
188
static void select_start P_((Widget aw, XEvent *event, String *params,
189
Cardinal *num_params));
190
static void extend_select_start P_((Widget aw, XEvent *event, String *params,
191
Cardinal *num_params));
192
static void extend_select P_((Widget aw, XEvent *event, String *params,
193
Cardinal *num_params));
194
static void keypress P_((Widget aw, XEvent *event, String *params,
195
Cardinal *num_params));
198
#ifdef max /* just in case--we don't know, but these are commonly set */
199
#undef max /* by arbitrary unix systems. Also, we cast to int! */
201
/* redefine "max" and "min" macros to take into account "unsigned" values */
202
#define max(a,b) ((int)(a)>(int)(b)?(int)(a):(int)(b))
203
#define min(a,b) ((int)(a)<(int)(b)?(int)(a):(int)(b))
205
/* Font convenience macros */
206
#define FontHeight(f) (int)(f->max_bounds.ascent + f->max_bounds.descent)
207
#define FontDescent(f) (int)(f->max_bounds.descent)
208
#define FontAscent(f) (int)(f->max_bounds.ascent)
209
#define FontTextWidth(f,c) (int)XTextWidth(f, c, strlen(c))
212
static char defaultTranslations[] =
213
"<FocusIn>: focus-in()\n\
214
<FocusOut>: focus-out()\n\
215
<Btn3Down>: menu()\n\
216
<Btn2Down>: start-drag()\n\
217
Shift <Btn1Down>: extend-select-start()\n\
218
<Btn1Down>: select-start()\n\
219
<Btn1Up>: notify()\n\
220
Button1 <Btn1Motion>: extend-select()";
222
static char defaultTranslations[] =
223
"<FocusIn>: focus-in()\n\
224
<FocusOut>: focus-out()\n\
225
<Key>Return: keypress()\n\
226
<Key>osfUp: keypress()\n\
227
<Btn3Down>: menu()\n\
228
Shift <Btn1Down>: extend-select-start()\n\
229
<Btn1Down>: select-start()\n\
230
<Btn1Up>: notify()\n\
231
Button1 <Btn1Motion>: extend-select()";
234
static XtActionsRec actions[] =
236
{"focus-in", focus_in},
237
{"focus-out", focus_out},
239
{"select-start", select_start},
240
{"extend-select", extend_select},
241
{"extend-select-start", extend_select_start},
243
{"keypress", keypress},
245
{"start-drag", start_drag},
250
static XmBaseClassExtRec listtreeCoreClassExtRec =
252
/* next_extension */ NULL,
253
/* record_type */ NULLQUARK,
254
/* version */ XmBaseClassExtVersion,
255
/* size */ sizeof(XmBaseClassExtRec),
256
/* initialize_prehook */ NULL, /* FIXME */
257
/* set_values_prehook */ NULL, /* FIXME */
258
/* initialize_posthook */ NULL, /* FIXME */
259
/* set_values_posthook */ NULL, /* FIXME */
260
/* secondary_object_class */ NULL, /* FIXME */
261
/* secondary_object_create */ NULL, /* FIXME */
262
/* get_secondary_resources */ NULL, /* FIXME */
263
/* fast_subclass */ {0}, /* FIXME */
264
/* get_values_prehook */ NULL, /* FIXME */
265
/* get_values_posthook */ NULL, /* FIXME */
266
/* class_part_init_prehook */ NULL,
267
/* class_part_init_posthook */ NULL,
268
/* ext_resources */ NULL,
269
/* compiled_ext_resources */ NULL,
270
/* num_ext_resources */ 0,
271
/* use_sub_resources */ FALSE,
272
/* widget_navigable */ XmInheritWidgetNavigable,
273
/* focus_change */ XmInheritFocusChange,
274
/* wrapper_data */ NULL
277
XmPrimitiveClassExtRec listtreePrimClassExtRec =
279
/* next_extension */ NULL,
280
/* record_type */ NULLQUARK,
281
/* version */ XmPrimitiveClassExtVersion,
282
/* record_size */ sizeof(XmPrimitiveClassExtRec),
283
/* widget_baseline */ NULL,
284
/* widget_display_rect */ NULL,
285
/* widget_margins */ NULL
288
ListTreeClassRec listtreeClassRec =
291
/* core_class fields */
292
/* MOTIF superclass */ (WidgetClass) & xmPrimitiveClassRec,
293
/* class_name */ "ListTree",
294
/* widget_size */ sizeof(ListTreeRec),
295
/* class_initialize */ NULL,
296
/* class_part_initialize */ NULL,
297
/* class_inited */ False,
298
/* initialize */ Initialize,
299
/* initialize_hook */ NULL,
300
/* realize */ Realize,
301
/* actions */ actions,
302
/* num_actions */ XtNumber(actions),
303
/* resources */ resources,
304
/* num_resources */ XtNumber(resources),
305
/* xrm_class */ NULLQUARK,
306
/* compress_motion */ True,
307
/* compress_exposure */ XtExposeCompressMultiple,
308
/* compress_enterleave */ True,
309
/* visible_interest */ True,
310
/* destroy */ Destroy,
312
/* expose */ Redisplay,
313
/* set_values */ SetValues,
314
/* set_values_hook */ NULL,
315
/* set_values_almost */ XtInheritSetValuesAlmost,
316
/* get_values_hook */ NULL,
317
/* accept_focus */ NULL,
318
/* version */ XtVersion,
319
/* callback_private */ NULL,
320
/* tm_table */ defaultTranslations,
321
/* query_geometry */ QueryGeometry,
322
/* display_accelerator */ XtInheritDisplayAccelerator,
323
/* extension */ (XtPointer) & listtreeCoreClassExtRec
325
/* Primitive Class part */
327
/* border_highlight */ XmInheritBorderHighlight,
328
/* border_unhighlight */ XmInheritBorderUnhighlight,
329
/* translations */ NULL,
330
/* arm_and_activate_proc */ XmInheritArmAndActivate,
331
/* synthetic resources */ NULL,
333
/* extension */ (XtPointer) & listtreePrimClassExtRec,
336
/* some stupid compilers barf on empty structures */ 0
340
WidgetClass listtreeWidgetClass = (WidgetClass) & listtreeClassRec;
342
/*-------------------------------------------------------------------------*/
343
#if NeedFunctionPrototypes
344
static void MakePixmap(ListTreeWidget w, Pixinfo * pix)
346
static void MakePixmap(w, pix)
353
unsigned int width, height, bw, depth;
355
if (pix->bitmap && XGetGeometry(XtDisplay((Widget) w), pix->bitmap,
356
&root, &x, &y, &width, &height, &bw, &depth)) {
357
pix->width = (int) width;
358
pix->height = (int) height;
359
if (pix->height>w->list.maxPixHeight)
360
w->list.maxPixHeight=pix->height;
362
/* Xmu dependency removed by Alan Marcinkowski */
367
gcv.background = w->core.background_pixel;
368
gcv.foreground = w->list.foreground_pixel;
369
gc = XCreateGC(XtDisplay((Widget) w),
370
RootWindowOfScreen(XtScreen((Widget) w)),
371
GCForeground | GCBackground, &gcv);
372
pix->pix = XCreatePixmap(XtDisplay((Widget) w),
373
RootWindowOfScreen(XtScreen((Widget) w)),
374
width, height, w->core.depth);
375
XCopyPlane (XtDisplay((Widget) w), pix->bitmap, pix->pix, gc, 0, 0,
376
width, height, 0, 0, 1);
377
XFreeGC (XtDisplay((Widget) w), gc);
380
pix->pix = pix->bitmap;
383
pix->width = pix->height = 0;
384
pix->pix = (Pixmap) NULL;
388
/*-------------------------------------------------------------------------*/
389
#if NeedFunctionPrototypes
390
static void FreePixmap(ListTreeWidget w, Pixinfo * pix)
392
static void FreePixmap(w, pix)
398
XFreePixmap(XtDisplay((Widget) w), pix->pix);
402
/*-------------------------------------------------------------------------*/
403
#if NeedFunctionPrototypes
404
static void InitializePixmaps(ListTreeWidget w)
406
static void InitializePixmaps(w)
410
w->list.maxPixHeight=0;
412
if (w->list.Closed.bitmap == XtUnspecifiedPixmap)
413
w->list.Closed.bitmap = XCreateBitmapFromData(XtDisplay((Widget) w),
414
RootWindowOfScreen(XtScreen((Widget) w)),
415
(char *) folder_bits, folder_width, folder_height);
416
MakePixmap(w, &w->list.Closed);
418
if (w->list.Open.bitmap == XtUnspecifiedPixmap)
419
w->list.Open.bitmap = XCreateBitmapFromData(XtDisplay((Widget) w),
420
RootWindowOfScreen(XtScreen((Widget) w)),
421
(char *)folderopen_bits, folderopen_width,
423
MakePixmap(w, &w->list.Open);
425
if (w->list.Leaf.bitmap == XtUnspecifiedPixmap)
426
w->list.Leaf.bitmap = XCreateBitmapFromData(XtDisplay((Widget) w),
427
RootWindowOfScreen(XtScreen((Widget) w)),
428
(char *)document_bits, document_width, document_height);
429
MakePixmap(w, &w->list.Leaf);
431
if (w->list.LeafOpen.bitmap == XtUnspecifiedPixmap)
432
w->list.LeafOpen.bitmap = XCreateBitmapFromData(XtDisplay((Widget) w),
433
RootWindowOfScreen(XtScreen((Widget) w)),
434
(char *)document_bits, document_width,
436
MakePixmap(w, &w->list.LeafOpen);
438
w->list.pixWidth = w->list.Closed.width;
439
if (w->list.Open.width > w->list.pixWidth)
440
w->list.pixWidth = w->list.Open.width;
441
if (w->list.Leaf.width > w->list.pixWidth)
442
w->list.pixWidth = w->list.Leaf.width;
443
if (w->list.LeafOpen.width > w->list.pixWidth)
444
w->list.pixWidth = w->list.LeafOpen.width;
446
w->list.Closed.xoff = (w->list.pixWidth - w->list.Closed.width) / 2;
447
w->list.Open.xoff = (w->list.pixWidth - w->list.Open.width) / 2;
448
w->list.Leaf.xoff = (w->list.pixWidth - w->list.Leaf.width) / 2;
449
w->list.LeafOpen.xoff = (w->list.pixWidth - w->list.LeafOpen.width) / 2;
453
/*-------------------------------------------------------------------------*/
454
#if NeedFunctionPrototypes
455
static void InitializeGC(ListTreeWidget w)
457
static void InitializeGC(w)
464
values.line_style = LineSolid;
465
values.line_width = w->list.LineWidth;
466
values.fill_style = FillSolid;
467
values.font = w->list.font->fid;
468
values.background = w->core.background_pixel;
469
values.foreground = w->list.foreground_pixel;
471
mask = GCLineStyle | GCLineWidth | GCFillStyle | GCForeground |
472
GCBackground | GCFont;
473
w->list.drawGC = XtGetGC((Widget) w, mask, &values);
475
values.function = GXinvert;
476
mask = GCLineStyle | GCLineWidth | GCFillStyle | GCForeground |
477
GCBackground | GCFont | GCFunction;
478
w->list.eorGC = XtGetGC((Widget) w, mask, &values);
480
values.background = w->list.foreground_pixel;
481
values.foreground = w->core.background_pixel;
482
mask = GCLineStyle | GCLineWidth | GCFillStyle | GCForeground |
483
GCBackground | GCFont;
484
w->list.highlightGC = XtGetGC((Widget) w, mask, &values);
487
/*-------------------------------------------------------------------------*/
488
#if NeedFunctionPrototypes
489
static void InitializeScrollBars(ListTreeWidget w)
491
static void InitializeScrollBars(w)
495
if (XmIsScrolledWindow(XtParent(w)))
496
w->list.mom = XtParent(w);
501
char *name = XtMalloc(strlen(XtName((Widget)w))+4);
503
strcpy(name,XtName((Widget)w));
505
w->list.hsb = XtVaCreateManagedWidget(name,
506
xmScrollBarWidgetClass,w->list.mom,
507
XmNorientation, XmHORIZONTAL,
509
XtAddCallback(w->list.hsb, XmNdecrementCallback,
510
HSBCallback, (XtPointer)w);
511
XtAddCallback(w->list.hsb, XmNdragCallback,
512
HSBCallback, (XtPointer)w);
513
XtAddCallback(w->list.hsb, XmNincrementCallback,
514
HSBCallback, (XtPointer)w);
515
XtAddCallback(w->list.hsb, XmNpageDecrementCallback,
516
HSBCallback, (XtPointer)w);
517
XtAddCallback(w->list.hsb, XmNpageIncrementCallback,
518
HSBCallback, (XtPointer)w);
519
XtAddCallback(w->list.hsb, XmNtoBottomCallback,
520
HSBCallback, (XtPointer)w);
521
XtAddCallback(w->list.hsb, XmNtoTopCallback,
522
HSBCallback, (XtPointer)w);
523
XtAddCallback(w->list.hsb, XmNvalueChangedCallback,
524
HSBCallback, (XtPointer)w);
526
strcpy(name,XtName((Widget)w));
528
w->list.vsb = XtVaCreateManagedWidget(name,
529
xmScrollBarWidgetClass,XtParent(w),
531
XtAddCallback(w->list.vsb, XmNdecrementCallback,
532
VSBCallback, (XtPointer)w);
533
XtAddCallback(w->list.vsb, XmNdragCallback,
534
VSBCallback, (XtPointer)w);
535
XtAddCallback(w->list.vsb, XmNincrementCallback,
536
VSBCallback, (XtPointer)w);
537
XtAddCallback(w->list.vsb, XmNpageDecrementCallback,
538
VSBCallback, (XtPointer)w);
539
XtAddCallback(w->list.vsb, XmNpageIncrementCallback,
540
VSBCallback, (XtPointer)w);
541
XtAddCallback(w->list.vsb, XmNtoBottomCallback,
542
VSBCallback, (XtPointer)w);
543
XtAddCallback(w->list.vsb, XmNtoTopCallback,
544
VSBCallback, (XtPointer)w);
545
XtAddCallback(w->list.vsb, XmNvalueChangedCallback,
546
VSBCallback, (XtPointer)w);
548
XtVaSetValues(w->list.mom,
549
XmNscrollBarDisplayPolicy, XmSTATIC,
550
XmNscrollingPolicy, XmAPPLICATION_DEFINED,
551
XmNvisualPolicy, XmVARIABLE,
552
/* Instead of call to XmScrolledWindowSetAreas() */
554
XmNhorizontalScrollBar, w->list.hsb,
555
XmNverticalScrollBar, w->list.vsb,
561
/*-------------------------------------------------------------------------*/
562
#if NeedFunctionPrototypes
563
static void InitializeGeometry(ListTreeWidget w)
565
static void InitializeGeometry(w)
571
if (XtHeight(w) < 10) {
574
working = FontHeight(w->list.font);
575
if (w->list.maxPixHeight>working) working=w->list.maxPixHeight;
576
working+=w->list.VSpacing;
578
if (w->list.visibleCount==0)
579
w->list.visibleCount=1;
581
w->list.preferredHeight=working*w->list.visibleCount;
582
w->list.preferredWidth=200;
583
XtWidth(w)=w->list.preferredWidth + 2*Prim_ShadowThickness(w)
584
+ 2*Prim_HighlightThickness(w);
585
XtHeight(w)=w->list.preferredHeight + 2*Prim_ShadowThickness(w)
586
+ 2*Prim_HighlightThickness(w);
589
w->list.preferredWidth = XtWidth(w) - 2*Prim_ShadowThickness(w)
590
- 2*Prim_HighlightThickness(w);
591
w->list.preferredHeight = XtHeight(w) - 2*Prim_ShadowThickness(w)
592
- 2*Prim_HighlightThickness(w);
594
LT_DBG(DARG,"prefWidth=%d prefHeight=%d\n",
595
w->list.preferredWidth,w->list.preferredHeight);
599
/*-------------------------------------------------------------------------*/
600
#if NeedFunctionPrototypes
601
static void Initialize(Widget request, Widget tnew, ArgList args,
604
static void Initialize(request, tnew, args, num)
611
ListTreeWidget w = (ListTreeWidget) tnew;
613
w->list.ret_item_list = NULL;
614
w->list.ret_item_alloc = 0;
615
w->list.first = w->list.highlighted = w->list.topItem = NULL;
616
w->list.topItemPos = w->list.lastItemPos = w->list.bottomItemPos =
617
w->list.itemCount = w->list.visibleCount = 0;
619
w->list.Refresh = True;
620
w->list.HasFocus=False;
622
w->list.timer_id = (XtIntervalId) 0;
623
w->list.multi_click_time = XtGetMultiClickTime(XtDisplay((Widget) w));
625
w->list.hsb = w->list.vsb=NULL;
631
InitializeScrollBars(w);
635
InitializePixmaps(w);
637
w->list.visibleCount=10;
638
InitializeGeometry(w);
642
** drop site registration
644
InitializeDropSite((Widget)w);
649
/*-------------------------------------------------------------------------*/
650
#if NeedFunctionPrototypes
651
static void Destroy(Widget aw)
653
static void Destroy(aw)
657
ListTreeWidget w = (ListTreeWidget)aw;
660
XtReleaseGC((Widget) w, w->list.drawGC);
661
XtReleaseGC((Widget) w, w->list.highlightGC);
662
item = w->list.first;
663
DeleteChildren(w, item);
665
FreePixmap(w, &w->list.Closed);
666
FreePixmap(w, &w->list.Open);
667
FreePixmap(w, &w->list.Leaf);
668
FreePixmap(w, &w->list.LeafOpen);
671
/*-------------------------------------------------------------------------*/
672
#if NeedFunctionPrototypes
673
static void Redisplay(Widget aw, XEvent *xevent, Region region)
675
static void Redisplay(aw, event, region)
681
ListTreeWidget w = (ListTreeWidget) aw;
682
XExposeEvent *event = (XExposeEvent*)xevent;
684
if (!XtIsRealized(aw))
688
Draw(w, (int) event->y, (int) event->height);
690
else { /* event==NULL ==> repaint the entire list */
694
_XmDrawShadows(XtDisplay((Widget)w),
697
Prim_BottomShadowGC(w),
698
Prim_HighlightThickness(w),
699
Prim_HighlightThickness(w),
700
XtWidth(w) - 2 * Prim_HighlightThickness(w),
701
XtHeight(w) - 2 * Prim_HighlightThickness(w),
702
Prim_ShadowThickness(w),
706
/*-------------------------------------------------------------------------*/
707
#if NeedFunctionPrototypes
708
static Boolean SetValues(Widget current, Widget request, Widget reply,
709
ArgList args, Cardinal * nargs)
711
static Boolean SetValues(current, request, reply, args, nargs)
719
if (!XtIsRealized(current))
725
/*-------------------------------------------------------------------------*/
726
#if NeedFunctionPrototypes
727
static void ResizeStuff(ListTreeWidget w)
729
static void ResizeStuff(w)
735
w->list.viewWidth = w->core.width - 2*Prim_ShadowThickness(w)
736
- 2*Prim_HighlightThickness(w);
737
w->list.viewHeight = w->core.height - 2*Prim_ShadowThickness(w)
738
- 2*Prim_HighlightThickness(w);
740
w->list.viewX=Prim_ShadowThickness(w)+Prim_HighlightThickness(w);
741
w->list.viewY=Prim_ShadowThickness(w)+Prim_HighlightThickness(w);
743
clip.x = w->list.viewX;
744
clip.y = w->list.viewY;
745
clip.width = w->list.viewWidth;
746
clip.height = w->list.viewHeight;
747
XSetClipRectangles(XtDisplay((Widget) w), w->list.drawGC,
748
0, 0, &clip, 1, Unsorted);
749
XSetClipRectangles(XtDisplay((Widget) w), w->list.eorGC,
750
0, 0, &clip, 1, Unsorted);
751
XSetClipRectangles(XtDisplay((Widget) w), w->list.highlightGC,
752
0, 0, &clip, 1, Unsorted);
756
w->list.visibleCount = 1;
757
if (w->list.itemHeight>0) {
758
w->list.visibleCount=w->list.viewHeight/(w->list.itemHeight +
763
/*-------------------------------------------------------------------------*/
764
#define HSB2X(w) w->list.XOffset=-((int) w->list.Margin - w->list.Indent + \
765
(w->list.Indent + w->list.pixWidth)*w->list.hsbPos);
767
/*-------------------------------------------------------------------------*/
768
#if NeedFunctionPrototypes
769
static void SetScrollbars(ListTreeWidget w)
771
static void SetScrollbars(w)
776
if (w->list.itemCount==0) {
777
XtVaSetValues( w->list.vsb,
787
LT_DBG(DARG, "topItemPos = %d, botItemPos = %d, visibleCount = %d, itemCount= %d\n", w->list.topItemPos, w->list.bottomItemPos,
788
w->list.visibleCount, w->list.itemCount);
790
top = w->list.topItemPos;
791
bot=w->list.itemCount;
792
size=w->list.visibleCount;
793
LT_DBG(DARG,"BEFORE: top=%d bot=%d size=%d ",top,bot,size);
794
if (top+size>bot) bot=top+size;
795
LT_DBG(DARG," AFTER: bot=%d\n",bot);
797
XtVaSetValues( w->list.vsb,
798
XmNvalue, w->list.topItemPos,
800
XmNpageIncrement, w->list.visibleCount,
804
XmScrollBarSetValues(w->list.vsb,top,size,1,size,False);
811
divisor=w->list.Indent + w->list.pixWidth;
812
view=(w->list.viewWidth+divisor-1)/divisor;
813
w->list.hsbMax=(w->list.preferredWidth+divisor-1)/divisor;
814
if (w->list.hsbPos>0 && w->list.hsbPos+view>w->list.hsbMax) {
815
int save=w->list.hsbPos;
817
w->list.hsbPos=w->list.hsbMax-view;
818
if (w->list.hsbPos<0)
820
if (save!=w->list.hsbPos) {
825
if (w->list.itemCount == 0 || w->list.preferredWidth==0) {
826
XtVaSetValues( w->list.hsb,
834
XtVaSetValues( w->list.hsb,
835
XmNvalue, w->list.hsbPos,
836
XmNsliderSize, min(w->list.hsbMax,view),
837
XmNpageIncrement, view,
838
XmNmaximum, w->list.hsbMax,
843
LT_DBG(DARG,"item=%d visible=%d\n", w->list.itemCount, w->list.visibleCount);
846
/*-------------------------------------------------------------------------*/
847
#if NeedFunctionPrototypes
848
static void VSBCallback(Widget scrollbar, XtPointer client_data,
851
static void VSBCallback(scrollbar, client_data, call_data)
853
XtPointer client_data;
857
ListTreeWidget w = (ListTreeWidget) client_data;
858
XmScrollBarCallbackStruct *cbs = (XmScrollBarCallbackStruct *)call_data;
860
w->list.topItemPos=cbs->value;
862
LT_DBG(DARG,"topItemPos=%d\n",w->list.topItemPos);
865
LT_DBG(DARG,"VSBCallback: cbs->reason=%d ",cbs->reason);
866
if (cbs->reason==XmCR_INCREMENT) {
867
LT_DBG(DARG,"increment\n");
869
else if (cbs->reason==XmCR_DECREMENT) {
870
LT_DBG(DARG,"decrement\n");
872
else if (cbs->reason==XmCR_VALUE_CHANGED) {
873
LT_DBG(DARG,"value_changed\n");
877
if (w->list.topItemPos!=w->list.lastItemPos) {
886
/*-------------------------------------------------------------------------*/
887
#if NeedFunctionPrototypes
888
static void HSBCallback(Widget scrollbar, XtPointer client_data,
891
static void HSBCallback(scrollbar, client_data, call_data)
893
XtPointer client_data;
897
ListTreeWidget w = (ListTreeWidget) client_data;
898
XmScrollBarCallbackStruct *cbs = (XmScrollBarCallbackStruct *)call_data;
900
w->list.hsbPos=cbs->value;
903
LT_DBG(DARG,"XOffset=%d prefWidth=%d viewWidth=%d\n",
904
w->list.XOffset,w->list.preferredWidth,w->list.viewWidth);
905
if (w->list.XOffset!=w->list.lastXOffset) {
910
/*-------------------------------------------------------------------------*/
911
#if NeedFunctionPrototypes
912
static void Resize(Widget aw)
914
static void Resize(aw)
918
ListTreeWidget w = (ListTreeWidget)aw;
920
if (!XtIsRealized(aw))
927
/*-------------------------------------------------------------------------*/
928
#if NeedFunctionPrototypes
929
static XtGeometryResult QueryGeometry(Widget aw,
930
XtWidgetGeometry *proposed, XtWidgetGeometry *answer)
932
static XtGeometryResult QueryGeometry(aw, proposed, answer)
934
XtWidgetGeometry *proposed;
935
XtWidgetGeometry *answer;
938
ListTreeWidget w = (ListTreeWidget)aw;
940
answer->request_mode = CWWidth | CWHeight;
941
answer->width = w->list.preferredWidth + 2*Prim_ShadowThickness(w)
942
+ 2*Prim_HighlightThickness(w);
943
answer->height = w->list.preferredHeight + 2*Prim_ShadowThickness(w)
944
+ 2*Prim_HighlightThickness(w);
946
LT_DBG(DARG,"w=%d h=%d\n", answer->width, answer->height);
948
if (proposed->width>=answer->width && proposed->height>=answer->height)
949
return XtGeometryYes;
950
else if (answer->width == XtWidth(w) && answer->height == XtHeight(w)) {
951
answer->request_mode = 0;
955
return XtGeometryAlmost;
958
/*-------------------------------------------------------------------------*/
959
#if NeedFunctionPrototypes
960
static void Realize(Widget aw, XtValueMask * value_mask,
961
XSetWindowAttributes * attributes)
963
static void Realize(aw, value_mask, attributes)
965
XtValueMask * value_mask;
966
XSetWindowAttributes * attributes;
969
#define superclass (&xmPrimitiveClassRec)
970
(*superclass->core_class.realize) (aw, value_mask, attributes);
978
/*-------------------- DEBUGGING FUNCTIONS ---------------------------*/
980
#if NeedFunctionPrototypes
981
static void ItemCheck(ListTreeWidget w, ListTreeItem * item)
983
static void ItemCheck(w, item)
992
/* if (p->parent) fprintf(stderr,"%x %x \t",p,p->parent); */
993
/* else fprintf(stderr,"%x 00000000 \t",p); */
994
/* while (p) { fprintf(stderr," "); p=p->parent; } */
997
/* fprintf(stderr,"%s/",p->text); */
1000
/* fprintf(stderr,"\n"); */
1002
if (strcmp(item->text, "pixmaps") == 0) {
1003
fprintf(stderr, "parent: %x\n", item->parent);
1004
fprintf(stderr, "firstchild: %x\n", item->firstchild);
1005
fprintf(stderr, "prevsibling: %x\n", item->prevsibling);
1006
fprintf(stderr, "nextsibling: %x\n", item->nextsibling);
1010
#if NeedFunctionPrototypes
1011
static void ChildrenCheck(ListTreeWidget w, ListTreeItem * item)
1013
static void ChildrenCheck(w, item)
1015
ListTreeItem * item;
1020
if (item->firstchild)
1021
ChildrenCheck(w, item->firstchild);
1022
item = item->nextsibling;
1026
#if NeedFunctionPrototypes
1027
static void TreeCheck(ListTreeWidget w, char *txt)
1029
static void TreeCheck(w, txt)
1036
fprintf(stderr, "\n\n%s\n", txt);
1037
item = w->list.first;
1040
if (item->firstchild)
1041
ChildrenCheck(w, item->firstchild);
1042
item = item->nextsibling;
1046
#define TreeCheck(a,b)
1051
/*------------------- Highlighting Utilities ------------------------------*/
1052
#if NeedFunctionPrototypes
1053
static void HighlightItem(ListTreeWidget w, ListTreeItem * item,
1054
Boolean state, Boolean draw)
1056
static void HighlightItem(w, item, state, draw)
1058
ListTreeItem * item;
1064
if (item == w->list.highlighted && !state) {
1065
w->list.highlighted = NULL;
1066
if (draw && item->count>=w->list.topItemPos)
1067
DrawItemHighlightClear(w, item);
1069
else if (state != item->highlighted) {
1071
printf("Highlighting '%s' state=%d x=%d y=%d\n",
1072
item->text, draw, item->x, item->ytext);
1074
item->highlighted = state;
1075
if (draw && item->count>=w->list.topItemPos &&
1076
item->count<=w->list.bottomItemPos)
1077
DrawItemHighlightClear(w, item);
1083
/*-------------------------------------------------------------------------*/
1084
#if NeedFunctionPrototypes
1085
static void HighlightChildren(ListTreeWidget w, ListTreeItem * item,
1086
Boolean state, Boolean draw)
1088
static void HighlightChildren(w, item, state, draw)
1090
ListTreeItem * item;
1096
HighlightItem(w, item, state, draw);
1097
if (item->firstchild) {
1104
HighlightChildren(w, item->firstchild, state, drawkids);
1106
item = item->nextsibling;
1110
/*-------------------------------------------------------------------------*/
1111
#if NeedFunctionPrototypes
1112
static void HighlightAll(ListTreeWidget w, Boolean state, Boolean draw)
1114
static void HighlightAll(w, state, draw)
1120
HighlightChildren(w,w->list.first,state,draw);
1123
/*-------------------------------------------------------------------------*/
1124
#if NeedFunctionPrototypes
1125
static void HighlightVisibleChildren(ListTreeWidget w, ListTreeItem * item,
1126
Boolean state, Boolean draw)
1128
static void HighlightVisibleChildren(w, item, state, draw)
1130
ListTreeItem * item;
1136
HighlightItem(w, item, state, draw);
1137
if (item->firstchild && item->open) {
1138
HighlightVisibleChildren(w, item->firstchild, state, draw);
1140
item = item->nextsibling;
1144
/*-------------------------------------------------------------------------*/
1145
#if NeedFunctionPrototypes
1146
static void HighlightAllVisible(ListTreeWidget w, Boolean state, Boolean draw)
1148
static void HighlightAllVisible(w, state, draw)
1156
item = w->list.first;
1158
HighlightItem(w, item, state, draw);
1159
if (item->firstchild && item->open) {
1160
HighlightVisibleChildren(w, item->firstchild, state, draw);
1162
item = item->nextsibling;
1166
/*-------------------------------------------------------------------------*/
1167
#if NeedFunctionPrototypes
1168
static void AddItemToReturnList(ListTreeWidget w, ListTreeItem * item,
1171
static void AddItemToReturnList(w, item, loc)
1173
ListTreeItem * item;
1177
if (loc >= w->list.ret_item_alloc) {
1178
w->list.ret_item_alloc += ListTreeRET_ALLOC;
1179
w->list.ret_item_list = (ListTreeItem **) XtRealloc((char *) w->list.ret_item_list, w->list.ret_item_alloc * sizeof(ListTreeItem *));
1181
w->list.ret_item_list[loc] = item;
1184
/*-------------------------------------------------------------------------*/
1185
#if NeedFunctionPrototypes
1186
static void MultiAddToReturn(ListTreeWidget w, ListTreeItem * item,
1187
ListTreeMultiReturnStruct * ret)
1189
static void MultiAddToReturn(w, item, ret)
1191
ListTreeItem * item;
1192
ListTreeMultiReturnStruct * ret;
1195
AddItemToReturnList(w, item, ret->count);
1196
ret->items = w->list.ret_item_list;
1200
/*-------------------------------------------------------------------------*/
1201
#if NeedFunctionPrototypes
1202
static void HighlightCount(ListTreeWidget w, ListTreeItem * item,
1203
ListTreeMultiReturnStruct * ret)
1205
static void HighlightCount(w, item, ret)
1207
ListTreeItem * item;
1208
ListTreeMultiReturnStruct * ret;
1212
if (item->highlighted)
1213
MultiAddToReturn(w, item, ret);
1214
if (item->firstchild && item->open)
1215
HighlightCount(w, item->firstchild, ret);
1216
item = item->nextsibling;
1220
/*-------------------------------------------------------------------------*/
1221
#if NeedFunctionPrototypes
1222
static void MakeMultiCallbackStruct(ListTreeWidget w,
1223
ListTreeMultiReturnStruct * ret)
1225
static void MakeMultiCallbackStruct(w, ret)
1227
ListTreeMultiReturnStruct * ret;
1234
item = w->list.first;
1236
if (item->highlighted)
1237
MultiAddToReturn(w, item, ret);
1238
if (item->firstchild && item->open)
1239
HighlightCount(w, item->firstchild, ret);
1240
item = item->nextsibling;
1244
/*-------------------------------------------------------------------------*/
1245
#if NeedFunctionPrototypes
1246
static void HighlightDoCallback(ListTreeWidget w)
1248
static void HighlightDoCallback(w)
1252
ListTreeMultiReturnStruct ret;
1254
if (w->list.HighlightCallback) {
1255
MakeMultiCallbackStruct(w, &ret);
1256
XtCallCallbacks((Widget) w, XtNhighlightCallback, &ret);
1260
/*-------------------------- Events ---------------------------------------*/
1261
#if NeedFunctionPrototypes
1262
static void MakeActivateCallbackStruct(ListTreeWidget w, ListTreeItem * item,
1263
ListTreeActivateStruct * ret)
1265
static void MakeActivateCallbackStruct(w, item, ret)
1267
ListTreeItem * item;
1268
ListTreeActivateStruct * ret;
1272
ListTreeItem *parent;
1276
while (parent->parent) {
1277
parent = parent->parent;
1283
ret->open = item->open;
1284
if (item->firstchild)
1285
ret->reason = XtBRANCH;
1287
ret->reason = XtLEAF;
1290
AddItemToReturnList(w, item, count);
1291
item = item->parent;
1293
ret->path = w->list.ret_item_list;
1296
/*-------------------------------------------------------------------------*/
1297
#if NeedFunctionPrototypes
1298
static void SelectDouble(ListTreeWidget w)
1300
static void SelectDouble(w)
1304
ListTreeActivateStruct ret;
1306
TreeCheck(w, "in SelectDouble");
1307
if (w->list.timer_item) {
1308
w->list.timer_type = TIMER_DOUBLE;
1309
w->list.timer_item->open = !w->list.timer_item->open;
1310
w->list.highlighted = w->list.timer_item;
1312
HighlightAll(w, False, True);
1314
MakeActivateCallbackStruct(w, w->list.timer_item, &ret);
1317
/* Highlight the path if we need to */
1318
if (w->list.HighlightPath) {
1321
save=w->list.Refresh;
1322
w->list.Refresh=False;
1323
ListTreeSetHighlighted((Widget)w,ret.path,ret.count,True);
1324
w->list.Refresh=save;
1325
/* ListTreeGetHighlighted((Widget)w,&ret2); */
1326
/* ListTreeSetHighlighted((Widget)w,ret2.items,ret2.count,True); */
1330
if (w->list.ActivateCallback) {
1331
XtCallCallbacks((Widget) w, XtNactivateCallback, (XtPointer) & ret);
1334
w->list.timer_item->highlighted = True;
1335
w->list.recount = True;
1338
TreeCheck(w, "exiting SelectDouble");
1341
/*-------------------------------------------------------------------------*/
1342
#if NeedFunctionPrototypes
1343
static void SelectSingle(XtPointer client_data, XtIntervalId * idp)
1345
static void SelectSingle(client_data, idp)
1346
XtPointer client_data;
1350
ListTreeWidget w = (ListTreeWidget) client_data;
1352
w->list.timer_id = (XtIntervalId) 0;
1353
if (w->list.timer_item) {
1354
if (w->list.ClickPixmapToOpen && w->list.timer_x <
1355
w->list.timer_item->x) {
1359
HighlightAll(w, False, True);
1360
HighlightItem(w, w->list.timer_item, True, True);
1361
if (w->list.timer_type != TIMER_CLEAR &&
1362
w->list.DoIncrementalHighlightCallback)
1363
HighlightDoCallback(w);
1364
w->list.timer_type = TIMER_SINGLE;
1369
/*-------------------------------------------------------------------------*/
1370
#if NeedFunctionPrototypes
1371
static void select_start(Widget aw, XEvent *event, String *params,
1372
Cardinal *num_params)
1374
static void select_start(aw, event, params, num_params)
1378
Cardinal *num_params;
1381
ListTreeWidget w = (ListTreeWidget) aw;
1384
w->list.timer_item=NULL;
1385
w->list.timer_x = event->xbutton.x - w->list.XOffset;
1386
w->list.timer_y = event->xbutton.y;
1387
w->list.timer_type = TIMER_WAITING;
1388
w->list.timer_item = GetItem(w, event->xbutton.y);
1390
if (!w->list.timer_item) {
1391
if (w->list.timer_id) {
1392
XtRemoveTimeOut(w->list.timer_id);
1393
w->list.timer_id = (XtIntervalId) 0;
1397
if (w->list.timer_id) {
1398
XtRemoveTimeOut(w->list.timer_id);
1399
w->list.timer_id = (XtIntervalId) 0;
1403
w->list.timer_id = XtAppAddTimeOut(
1404
XtWidgetToApplicationContext((Widget) w),
1405
(unsigned long) w->list.multi_click_time,
1406
SelectSingle, (XtPointer) w);
1412
/*-------------------------------------------------------------------------*/
1413
#if NeedFunctionPrototypes
1414
static void extend_select_start(Widget aw, XEvent *event, String *params,
1415
Cardinal *num_params)
1417
static void extend_select_start(aw, event, params, num_params)
1421
Cardinal *num_params;
1424
ListTreeWidget w = (ListTreeWidget) aw;
1426
w->list.timer_item=NULL;
1427
w->list.timer_x = event->xbutton.x;
1428
w->list.timer_y = event->xbutton.y;
1429
w->list.timer_type = TIMER_WAITING;
1430
w->list.timer_item = GetItem(w, event->xbutton.y);
1431
w->list.timer_id = (XtIntervalId) 0;
1432
HighlightItem(w, w->list.timer_item, True, True);
1433
if (w->list.timer_type != TIMER_CLEAR &&
1434
w->list.DoIncrementalHighlightCallback)
1435
HighlightDoCallback(w);
1438
/*-------------------------------------------------------------------------*/
1439
#if NeedFunctionPrototypes
1440
static void extend_select(Widget aw, XEvent *event, String *params,
1441
Cardinal *num_params)
1443
static void extend_select(aw, event, params, num_params)
1447
Cardinal *num_params;
1451
ListTreeWidget w = (ListTreeWidget) aw;
1454
/* If we are waiting for a double click, return before doing anything */
1455
if (w->list.timer_id)
1458
/* We need the timer_item to be pointing to the first selection in this */
1459
/* group. If we got here without it being set, something is very wrong. */
1460
if (w->list.timer_item) {
1461
y = w->list.timer_y;
1462
yend = event->xbutton.y;
1463
item = GetItem(w, y);
1465
while (item && y < yend && y < w->list.viewY+w->list.viewHeight) {
1467
LT_DBG(DARG,"Highlighting y=%d item=%s\n",y,item->text);
1468
HighlightItem(w, item, True, True);
1469
y += item->height + w->list.VSpacing;
1471
item = GetItem(w, y);
1475
while (item && y > yend && y > 0) {
1477
LT_DBG(DARG,"Highlighting y=%d item=%s\n",y,item->text);
1478
HighlightItem(w, item, True, True);
1479
y -= item->height + w->list.VSpacing;
1481
item = GetItem(w, y);
1484
if (w->list.timer_type != TIMER_CLEAR &&
1485
w->list.DoIncrementalHighlightCallback)
1486
HighlightDoCallback(w);
1490
/*-------------------------------------------------------------------------*/
1491
#if NeedFunctionPrototypes
1492
static void unset(Widget aw, XEvent *event, String *params,
1493
Cardinal *num_params)
1495
static void unset(aw, event, params, num_params)
1499
Cardinal *num_params;
1503
ListTreeWidget w = (ListTreeWidget) aw;
1505
item = GetItem(w, event->xbutton.y);
1507
/* item->open=False; */
1508
/* lw->list.highlighted=item; */
1510
/* ListTreeDelete(lw,item); */
1514
/*-------------------------------------------------------------------------*/
1515
#if NeedFunctionPrototypes
1516
static void notify(Widget aw, XEvent *event, String *params,
1517
Cardinal *num_params)
1519
static void notify(aw, event, params, num_params)
1523
Cardinal *num_params;
1526
ListTreeWidget w = (ListTreeWidget) aw;
1528
if (w->list.timer_id) {
1529
/* don't call highlightCallback if we are waiting for a double click */
1531
else if (w->list.timer_type != TIMER_CLEAR &&
1532
!w->list.DoIncrementalHighlightCallback) {
1533
HighlightDoCallback(w);
1534
w->list.timer_type = TIMER_CLEAR;
1538
/*-------------------------------------------------------------------------*/
1539
#if NeedFunctionPrototypes
1540
static void focus_in(Widget aw, XEvent *event, String *params,
1541
Cardinal *num_params)
1543
static void focus_in(aw, event, params, num_params)
1547
Cardinal *num_params;
1550
ListTreeWidget w = (ListTreeWidget) aw;
1552
LT_DBGW("focus_in");
1554
if (!w->list.HasFocus) {
1555
XtCallActionProc(aw, "PrimitiveFocusIn", event, params, *num_params);
1557
w->list.HasFocus=True;
1561
/*-------------------------------------------------------------------------*/
1562
#if NeedFunctionPrototypes
1563
static void focus_out(Widget aw, XEvent *event, String *params,
1564
Cardinal *num_params)
1566
static void focus_out(aw, event, params, num_params)
1570
Cardinal *num_params;
1573
ListTreeWidget w = (ListTreeWidget) aw;
1575
LT_DBGW("focus_out");
1577
if (w->list.HasFocus) {
1578
XtCallActionProc(aw, "PrimitiveFocusOut", event, params, *num_params);
1580
w->list.HasFocus=False;
1584
/*-------------------------------------------------------------------------*/
1585
#if NeedFunctionPrototypes
1586
static void menu(Widget aw, XEvent *event, String *params,
1587
Cardinal *num_params)
1589
static void menu(aw, event, params, num_params)
1593
Cardinal *num_params;
1596
ListTreeWidget w = (ListTreeWidget) aw;
1598
ListTreeItemReturnStruct ret;
1600
if (w->list.MenuCallback) {
1602
/* See if there is an item at the position of the click */
1603
item=GetItem (w, event->xbutton.y);
1606
ret.reason = XtMENU;
1609
XtCallCallbacks((Widget) w, XtNmenuCallback, &ret);
1614
/*-------------------------------------------------------------------------*/
1615
#if NeedFunctionPrototypes
1616
static void keypress(Widget aw, XEvent *event, String *params,
1617
Cardinal *num_params)
1619
static void keypress(aw, event, params, num_params)
1623
Cardinal *num_params;
1627
LT_DBG(DARG,"keypress\n");
1631
/*------------- ListTree private drawing functions ------------------------*/
1632
/*-------------------------------------------------------------------------*/
1633
/* Select the pixmap to use, if any */
1634
/*-------------------------------------------------------------------------*/
1635
#if NeedFunctionPrototypes
1636
static Pixinfo * GetItemPix(ListTreeWidget w, ListTreeItem *item)
1638
static Pixinfo * GetItemPix(w, item)
1647
/* Another enhancement from Alan Marcinkowski */
1648
if (item->openPixmap || item->closedPixmap) {
1649
/* Guess that it is closed. */
1650
Pixmap pixmap = item->closedPixmap;
1654
unsigned int pixwidth, pixheight, pixbw, pixdepth;
1656
/* If it is not closed and there is a pixmap for it, then use that one
1659
if (item->open && item->openPixmap) {
1660
pixmap = item->openPixmap;
1663
/* Make sure we got one. */
1665
/* Get the geometry of the pixmap. */
1666
XGetGeometry(XtDisplay((Widget) w), pixmap, &root, &pixx, &pixy,
1667
&pixwidth, &pixheight, &pixbw, &pixdepth);
1669
/* Setup the temporary one that will be used and point to it. */
1670
w->list.ItemPix.width = (int) pixwidth;
1671
w->list.ItemPix.height = (int) pixheight;
1672
w->list.ItemPix.xoff = 0;
1673
w->list.ItemPix.pix = pixmap;
1674
pix = &w->list.ItemPix;
1678
/* If we don't have a pixmap yet... */
1680
if (item->firstchild || item->type == ItemBranchType) {
1682
pix = &w->list.Open;
1684
pix = &w->list.Closed;
1688
pix = &w->list.LeafOpen;
1690
pix = &w->list.Leaf;
1697
/*-------------------------------------------------------------------------*/
1698
#if NeedFunctionPrototypes
1699
static void DrawItemHighlight(ListTreeWidget w, ListTreeItem *item)
1701
static void DrawItemHighlight(w, item)
1708
if (item->highlighted || item == w->list.highlighted) {
1709
width = w->core.width - item->x - w->list.XOffset;
1710
XFillRectangle(XtDisplay(w), XtWindow(w),
1712
item->x + w->list.XOffset, item->ytext,
1713
width, FontHeight(w->list.font));
1714
XDrawString(XtDisplay(w), XtWindow(w), w->list.highlightGC,
1715
item->x + w->list.XOffset, item->ytext + FontAscent(w->list.font),
1716
item->text, item->length);
1719
XDrawString(XtDisplay(w), XtWindow(w), w->list.drawGC,
1720
item->x + w->list.XOffset,
1721
item->ytext + FontAscent(w->list.font),
1722
item->text, item->length);
1726
/*-------------------------------------------------------------------------*/
1727
#if NeedFunctionPrototypes
1728
static void DrawItemHighlightClear(ListTreeWidget w, ListTreeItem *item)
1730
static void DrawItemHighlightClear(w, item)
1737
width = w->core.width - item->x - w->list.XOffset;
1738
if (item->highlighted || item == w->list.highlighted) {
1739
XFillRectangle(XtDisplay(w), XtWindow(w),
1741
item->x + w->list.XOffset, item->ytext,
1742
width, FontHeight(w->list.font));
1743
XDrawString(XtDisplay(w), XtWindow(w), w->list.highlightGC,
1744
item->x + w->list.XOffset,
1745
item->ytext + FontAscent(w->list.font),
1746
item->text, item->length);
1749
XFillRectangle(XtDisplay(w), XtWindow(w),
1750
w->list.highlightGC,
1751
item->x + w->list.XOffset, item->ytext,
1752
width, FontHeight(w->list.font));
1753
XDrawString(XtDisplay(w), XtWindow(w), w->list.drawGC,
1754
item->x + w->list.XOffset,
1755
item->ytext + FontAscent(w->list.font),
1756
item->text, item->length);
1760
/*-------------------------------------------------------------------------*/
1761
#if NeedFunctionPrototypes
1762
static void DrawItem(ListTreeWidget w, ListTreeItem *item,
1763
int y, int *xroot, int *yroot,
1764
int *retwidth, int *retheight)
1766
static void DrawItem(w, item, y, xroot, yroot, retwidth, retheight)
1776
int height, xpix, ypix, xbranch, ybranch, xtext, ytext, yline;
1779
if (item->count<w->list.topItemPos) {
1780
*xroot = item->x - (int) w->list.HSpacing - w->list.pixWidth/2;
1782
*retwidth = *retheight = 0;
1786
pix=GetItemPix(w,item);
1788
/* Compute the height of this line */
1789
height = FontHeight(w->list.font);
1791
xpix = xtext - (int) w->list.HSpacing - w->list.pixWidth + pix->xoff;
1794
if (pix->height > height) {
1795
ytext = y + ((pix->height - height) / 2);
1796
height = pix->height;
1801
ypix = y + ((height - pix->height) / 2);
1803
ybranch = ypix + pix->height;
1804
yline = ypix + (pix->height / 2);
1808
yline = ybranch = ypix + (height / 2);
1809
yline = ypix + (height / 2);
1811
xbranch=item->x - (int) w->list.HSpacing - w->list.pixWidth/2;
1813
/* Save the basic graphics info for use by other functions */
1815
item->ytext = ytext;
1816
item->height = (Dimension)height;
1818
if ((*xroot >= 0) &&
1819
((*yroot >= w->list.exposeTop && *yroot <= w->list.exposeBot) ||
1820
(yline >= w->list.exposeTop && yline <= w->list.exposeBot) ||
1821
(*yroot < w->list.exposeTop && yline > w->list.exposeBot)))
1822
XDrawLine(XtDisplay(w), XtWindow(w), w->list.drawGC,
1823
*xroot + w->list.XOffset, *yroot,
1824
*xroot + w->list.XOffset, yline);
1825
if (y >= w->list.exposeTop && y <= w->list.exposeBot) {
1827
XDrawLine(XtDisplay(w), XtWindow(w), w->list.drawGC,
1828
*xroot + w->list.XOffset, yline,
1829
xbranch + w->list.XOffset, yline);
1830
if (pix && pix->pix)
1831
XCopyArea(XtDisplay(w), pix->pix, XtWindow(w),
1833
0, 0, pix->width, pix->height,
1834
xpix + w->list.XOffset, ypix);
1835
DrawItemHighlight(w, item);
1839
*retwidth = FontTextWidth(w->list.font, item->text);
1840
*retheight = height;
1843
/*-------------------------------------------------------------------------*/
1844
#if NeedFunctionPrototypes
1845
static int DrawChildren(ListTreeWidget w, ListTreeItem *item,
1846
ListTreeItem **last, int y, int xroot, int yroot)
1848
static int DrawChildren(w, item, last, y, xroot, yroot)
1851
ListTreeItem **last;
1858
int xbranch, ybranch;
1860
while (item && y<w->list.exposeBot) {
1863
DrawItem(w, item, y, &xbranch, &ybranch, &width, &height);
1865
width += item->x + (int) w->list.Margin;
1867
if (width > w->list.preferredWidth)
1868
w->list.preferredWidth = width;
1871
y += height + (int) w->list.VSpacing;
1876
if ((item->firstchild) && (item->open))
1877
y = DrawChildren(w, item->firstchild, last, y, xbranch, ybranch);
1879
item = item->nextsibling;
1884
/*-------------------------------------------------------------------------*/
1885
/* Draws vertical lines connecting items to their siblings below the last */
1887
/*-------------------------------------------------------------------------*/
1888
#if NeedFunctionPrototypes
1889
static void DrawVertical(ListTreeWidget w, ListTreeItem *item)
1891
static void DrawVertical(w, item)
1896
int xroot,yroot, pos;
1899
while (item->parent) {
1900
/* If this parent has another child, that means that a line extends off
1901
* the screen to the bottom. */
1902
if (item->nextsibling) {
1903
xroot = item->parent->x - (int) w->list.HSpacing -
1905
if (item->parent->count<w->list.topItemPos)
1908
yroot=item->parent->y + item->parent->height;
1910
LT_DBG(DARG,"parent=%s drawing x=%d y=%d\n",
1911
item->parent->text,xroot,yroot);
1912
XDrawLine(XtDisplay(w), XtWindow(w), w->list.drawGC,
1913
xroot + w->list.XOffset, yroot,
1914
xroot + w->list.XOffset, w->list.exposeBot);
1917
LT_DBG(DARG,"parent=%s NOT DRAWING\n",item->parent->text);
1924
/*-------------------------------------------------------------------------*/
1925
/* Draws items starting from topItemPos */
1926
/*-------------------------------------------------------------------------*/
1927
#if NeedFunctionPrototypes
1928
static void Draw(ListTreeWidget w, int yevent,int hevent)
1930
static void Draw(w, yevent, hevent)
1936
int y, xbranch, ybranch;
1937
ListTreeItem *item,*lastdrawn;
1939
TreeCheck(w, "Draw");
1941
if (w->list.recount)
1944
/* Overestimate the expose region to be sure to draw an item that gets */
1945
/* cut by the region */
1946
w->list.exposeTop = yevent - FontHeight(w->list.font);
1947
w->list.exposeBot = yevent + hevent + FontHeight(w->list.font);
1948
w->list.preferredWidth = 0;
1950
item = w->list.topItem;
1951
/* skip if this is an empty list */
1955
while (item->parent)
1957
y = (int)w->list.viewY + (int) w->list.Margin;
1961
DrawChildren(w, item, &lastdrawn, y, xbranch, ybranch);
1963
LT_DBG(DARG,"lastdrawn=%s\n",lastdrawn->text);
1964
w->list.bottomItemPos=lastdrawn->count;
1966
DrawVertical(w,lastdrawn);
1968
/* SetScrollbars(w); */
1970
w->list.lastItemPos=w->list.topItemPos;
1971
w->list.lastXOffset=w->list.XOffset;
1974
/*-------------------------------------------------------------------------*/
1975
#if NeedFunctionPrototypes
1976
static void DrawAll(ListTreeWidget w)
1978
static void DrawAll(w)
1982
XClearArea(XtDisplay((Widget) w), XtWindow((Widget) w),
1983
w->list.viewX,w->list.viewY,
1984
w->list.viewWidth,w->list.viewHeight,False);
1985
if (w->list.recount)
1987
Draw(w, w->list.viewY, w->list.viewY+w->list.viewHeight);
1990
/*-------------------------------------------------------------------------*/
1991
#if NeedFunctionPrototypes
1992
static void DrawChanged(ListTreeWidget w)
1994
static void DrawChanged(w)
1998
w->list.recount = True;
2003
/*-------------------------------------------------------------------------*/
2004
/* Counting functions */
2005
/*-------------------------------------------------------------------------*/
2006
#if NeedFunctionPrototypes
2007
static int GotoPositionChildren(ListTreeWidget w, ListTreeItem *item, int i)
2009
static int GotoPositionChildren(w, item, i)
2015
while (item && i < w->list.topItemPos) {
2017
w->list.topItem=item;
2019
if (item->firstchild && item->open && i<w->list.topItemPos)
2020
i=GotoPositionChildren(w,item->firstchild,i);
2022
item=item->nextsibling;
2027
/*-------------------------------------------------------------------------*/
2028
#if NeedFunctionPrototypes
2029
static void GotoPosition(ListTreeWidget w)
2031
static void GotoPosition(w)
2035
w->list.topItem=w->list.first;
2036
GotoPositionChildren(w,w->list.topItem,-1);
2039
/*-------------------------------------------------------------------------*/
2040
#if NeedFunctionPrototypes
2041
static int CountItem(ListTreeWidget w, ListTreeItem *item, int x, int y)
2043
static int CountItem(w, item, x, y)
2050
int height, xpix, xtext;
2053
item->count=w->list.itemCount;
2054
w->list.itemCount++;
2056
/* Select the pixmap to use, if any */
2057
pix=GetItemPix(w,item);
2059
/* Compute the height of this line */
2060
height = FontHeight(w->list.font);
2061
xpix = x - w->list.pixWidth + pix->xoff;
2062
xtext = x + (int) w->list.HSpacing;
2063
if (pix && pix->height > height) {
2064
height = pix->height;
2067
/* Save the basic graphics info for use by other functions */
2069
item->y = item->ytext = -1;
2070
item->height = (Dimension)height;
2072
if (item->height > w->list.itemHeight)
2073
w->list.itemHeight=item->height;
2078
/*-------------------------------------------------------------------------*/
2079
#if NeedFunctionPrototypes
2080
static int CountChildren(ListTreeWidget w, ListTreeItem *item, int x, int y)
2082
static int CountChildren(w, item, x, y)
2091
x += (int) w->list.Indent + w->list.pixWidth;
2093
height = CountItem(w, item, x, y);
2095
y += height + (int) w->list.VSpacing;
2096
if ((item->firstchild) && (item->open))
2097
y = CountChildren(w, item->firstchild, x, y);
2099
item = item->nextsibling;
2104
/*-------------------------------------------------------------------------*/
2105
#if NeedFunctionPrototypes
2106
static void CountAll(ListTreeWidget w)
2108
static void CountAll(w)
2114
w->list.itemCount = 0;
2115
w->list.itemHeight = 0;
2116
w->list.recount = False;
2119
* the first x must be w->list.Margin + w->list.pixWidth, so set it up
2120
* so CountChildren gets it right for the root items
2122
x = (int)w->list.viewX + (int) w->list.Margin - w->list.Indent;
2123
y = (int)w->list.viewY + (int) w->list.Margin;
2124
CountChildren(w,w->list.first,x,y);
2128
/*------------------ Private Functions ------------------------------------*/
2129
/* This function removes the specified item from the linked list. It does */
2130
/* not do anything with the data contained in the item, though. */
2131
/*-------------------------------------------------------------------------*/
2132
#if NeedFunctionPrototypes
2133
static void RemoveReference(ListTreeWidget w, ListTreeItem *item)
2135
static void RemoveReference(w, item)
2144
** If there exists a previous sibling, just skip over item to be
2147
if (item->prevsibling) {
2148
item->prevsibling->nextsibling = item->nextsibling;
2149
if (item->nextsibling)
2150
item->nextsibling->prevsibling = item->prevsibling;
2152
/* If not, then the deleted item is the first item in some branch. */
2155
item->parent->firstchild = item->nextsibling;
2157
w->list.first = item->nextsibling;
2158
if (item->nextsibling)
2159
item->nextsibling->prevsibling = NULL;
2163
** reset parent to NULL it has been unchained
2165
item->parent = NULL;
2168
** Don't forget to update topItem
2169
** (Paul Newton <pkn@Cs.Nott.AC.UK> caught this )
2171
if (item == w->list.topItem)
2172
w->list.topItem = item->nextsibling;
2175
/*-------------------------------------------------------------------------*/
2176
#if NeedFunctionPrototypes
2177
static void DeleteChildren(ListTreeWidget w, ListTreeItem *item)
2179
static void DeleteChildren(w, item)
2184
ListTreeItem *sibling;
2185
ListTreeItem *current;
2187
if (!item || !item->firstchild)
2191
** all children of item are deleted
2193
current = item->firstchild;
2195
DeleteChildren(w, current);
2196
sibling = current->nextsibling;
2197
DeleteItem(w, current);
2200
item->firstchild = NULL;
2204
/*-------------------------------------------------------------------------*/
2205
#if NeedFunctionPrototypes
2206
static void DeleteItem(ListTreeWidget w, ListTreeItem *item)
2208
static void DeleteItem(w, item)
2213
ListTreeItemReturnStruct ret;
2215
if (w->list.DestroyItemCallback) {
2216
ret.reason = XtDESTROY;
2219
XtCallCallbacks((Widget) w, XtNdestroyItemCallback, &ret);
2222
XtFree((char *) item->text);
2223
XtFree((char *) item);
2226
/*-------------------------------------------------------------------------*/
2227
#if NeedFunctionPrototypes
2228
static void InsertChild(ListTreeWidget w, ListTreeItem *parent,
2231
static void InsertChild(w, parent, item)
2233
ListTreeItem *parent;
2239
item->parent = parent;
2240
item->nextsibling = item->prevsibling = NULL;
2242
if (parent->firstchild) {
2243
i = parent->firstchild;
2244
while (i->nextsibling) {
2247
i->nextsibling = item;
2248
item->prevsibling = i;
2251
parent->firstchild = item;
2254
else { /* if parent==NULL, this is a top level entry */
2255
if (w->list.first) {
2257
while (i->nextsibling) {
2260
i->nextsibling = item;
2261
item->prevsibling = i;
2264
w->list.first = w->list.topItem = item;
2267
w->list.recount = True;
2270
/*-------------------------------------------------------------------------*/
2271
/* Insert a list of ALREADY LINKED children into another list */
2272
/*-------------------------------------------------------------------------*/
2273
#if NeedFunctionPrototypes
2274
static void InsertChildren(ListTreeWidget w, ListTreeItem *parent,
2277
static void InsertChildren(w, parent, item)
2279
ListTreeItem *parent;
2283
ListTreeItem *next, *newnext;
2285
/* while (item) { */
2286
/* next=item->nextsibling; */
2287
/* InsertChild(w,parent,item); */
2293
/* Save the reference for the next item in the new list */
2294
next = item->nextsibling;
2296
/* Insert the first item in the new list into the existing list */
2297
InsertChild(w, parent, item);
2299
/* The first item is inserted, with its prev and next siblings updated */
2300
/* to fit into the existing list. So, save the existing list reference */
2301
newnext = item->nextsibling;
2303
/* Now, mark the first item's next sibling to point back to the new list */
2304
item->nextsibling = next;
2306
/* Mark the parents of the new list to the new parent. The order of the */
2307
/* rest of the new list should be OK, and the second item should still */
2308
/* point to the first, even though the first was reparented. */
2309
while (item->nextsibling) {
2310
item->parent = parent;
2311
item = item->nextsibling;
2314
/* Fit the end of the new list back into the existing list */
2315
item->nextsibling = newnext;
2317
newnext->prevsibling = item;
2321
/*-------------------------------------------------------------------------*/
2322
#if NeedFunctionPrototypes
2323
static int SearchChildren(ListTreeWidget w, ListTreeItem *item,
2324
ListTreeItem **last, int y, int findy,
2325
ListTreeItem **finditem)
2327
static int SearchChildren(w, item, last, y, findy, finditem)
2330
ListTreeItem **last;
2333
ListTreeItem **finditem;
2337
LT_DBG(DARG,"searching y=%d item=%s\n",y,item->text);
2338
if (findy >= y && findy <= y + item->height + w->list.VSpacing) {
2342
y += item->height + (int) w->list.VSpacing;
2343
if ((item->firstchild) && (item->open)) {
2344
y = SearchChildren(w, item->firstchild, NULL,
2345
y, findy, finditem);
2349
if (last) *last=item;
2350
item = item->nextsibling;
2355
/*-------------------------------------------------------------------------*/
2356
#if NeedFunctionPrototypes
2357
static ListTreeItem * GetItem(ListTreeWidget w, int findy)
2359
static ListTreeItem * GetItem(w, findy)
2365
ListTreeItem *item, *finditem, *lastdrawn;
2367
TreeCheck(w, "in GetItem");
2368
y = (int)w->list.viewY + (int) w->list.Margin;
2369
item = w->list.topItem;
2372
while (!finditem && lastdrawn && y<w->core.height) {
2373
y = SearchChildren(w, item, &lastdrawn, y, findy, &finditem);
2376
* If there are still more items to draw, but the previous group of
2377
* siblings ran out, start checking up through the parents for more
2380
if (lastdrawn->parent && y<w->core.height) {
2381
ListTreeItem *parent;
2383
/* continue with the item after the parent of the previous group */
2386
parent=parent->parent;
2388
item=parent->nextsibling;
2391
} while (parent && !item);
2398
TreeCheck(w, "exiting GetItem");
2402
/*-------------------------------------------------------------------------*/
2403
#if NeedFunctionPrototypes
2404
static int SearchPosition(ListTreeWidget w, ListTreeItem *item, int y,
2405
int *counter, ListTreeItem *finditem, Boolean *found)
2407
static int SearchPosition(w, item, y, counter, finditem, found)
2412
ListTreeItem *finditem;
2420
LT_DBG(DARG,"Checking y=%d item=%s\n",y,item->text);
2421
if (item == finditem) {
2426
pix=GetItemPix(w,item);
2428
/* Compute the height of this line */
2429
height = FontHeight(w->list.font);
2430
if (pix && pix->height > height)
2431
height = pix->height;
2433
y += height + (int) w->list.VSpacing;
2434
if ((item->firstchild) && (item->open)) {
2436
y = SearchPosition(w, item->firstchild, y, counter, finditem, found);
2440
item = item->nextsibling;
2446
/*-------------------------------------------------------------------------*/
2447
#if NeedFunctionPrototypes
2448
static Position GetPosition(ListTreeWidget w, ListTreeItem *finditem, int *counter)
2450
static Position GetPosition(w, finditem, counter)
2452
ListTreeItem *finditem;
2456
int y = 0, height = 0;
2459
Boolean found = False;
2461
TreeCheck(w, "in GetPosition");
2462
y = (int)w->list.viewY + (int) w->list.Margin;
2463
item = w->list.first;
2464
while (item && item != finditem) {
2465
pix=GetItemPix(w,item);
2467
/* Compute the height of this line */
2468
height = FontHeight(w->list.font);
2469
if (pix && pix->height > height)
2470
height = pix->height;
2472
y += height + (int) w->list.VSpacing;
2473
if ((item->firstchild) && (item->open)) {
2474
y = SearchPosition(w, item->firstchild, y, counter, finditem, &found);
2475
LT_DBG(DARG,"y=%d counter=%d\n", y, counter);
2477
return (Position) y;
2479
item = item->nextsibling;
2482
TreeCheck(w, "exiting GetPosition");
2483
if (item != finditem)
2486
LT_DBG(DARG,"y=%d counter=%d\n", y, counter);
2488
return (Position) y;
2492
/*-------------------------------------------------------------------------*/
2493
/*------------------------ Public Functions -------------------------------*/
2494
/*-------------------------------------------------------------------------*/
2495
#if NeedFunctionPrototypes
2496
void ListTreeRefresh(Widget w)
2498
void ListTreeRefresh(w)
2502
ListTreeWidget lw = (ListTreeWidget)w;
2504
if (XtIsRealized(w) && lw->list.Refresh)
2508
/*-------------------------------------------------------------------------*/
2509
#if NeedFunctionPrototypes
2510
void ListTreeRefreshOff(Widget w)
2512
void ListTreeRefreshOff(w)
2516
ListTreeWidget lw = (ListTreeWidget)w;
2518
lw->list.Refresh = False;
2521
/*-------------------------------------------------------------------------*/
2522
#if NeedFunctionPrototypes
2523
void ListTreeRefreshOn(Widget w)
2525
void ListTreeRefreshOn(w)
2529
ListTreeWidget lw = (ListTreeWidget)w;
2531
lw->list.Refresh = True;
2535
/*-------------------------------------------------------------------------*/
2536
#if NeedFunctionPrototypes
2537
static ListTreeItem * AddItem(Widget w, ListTreeItem * parent,
2538
char *string, ListTreeItemType type)
2540
static ListTreeItem * AddItem(w, parent, string, type)
2542
ListTreeItem * parent;
2544
ListTreeItemType type;
2547
ListTreeWidget lw = (ListTreeWidget) w;
2548
ListTreeItemReturnStruct ret;
2553
TreeCheck((ListTreeWidget)w, "in ListTreeAdd");
2554
len = strlen(string);
2555
item = (ListTreeItem *) XtMalloc(sizeof(ListTreeItem));
2556
copy = (char *) XtMalloc(len + 1);
2557
strcpy(copy, string);
2561
item->parent = parent;
2563
item->highlighted = False;
2564
item->openPixmap = item->closedPixmap = (Pixmap)NULL;
2565
item->firstchild = item->prevsibling = item->nextsibling = NULL;
2566
item->user_data = NULL;
2568
if (lw->list.CreateItemCallback) {
2569
ret.reason = XtCREATE;
2572
XtCallCallbacks((Widget) lw, XtNcreateItemCallback, &ret);
2575
InsertChild((ListTreeWidget)w, parent, item);
2582
/*-------------------------------------------------------------------------*/
2583
#if NeedFunctionPrototypes
2584
ListTreeItem * ListTreeAdd(Widget w, ListTreeItem *parent,
2587
ListTreeItem * ListTreeAdd(w, parent, string)
2589
ListTreeItem *parent;
2593
return (AddItem(w,parent,string,ItemDetermineType));
2596
/*-------------------------------------------------------------------------*/
2597
#if NeedFunctionPrototypes
2598
ListTreeItem * ListTreeAddType(Widget w, ListTreeItem *parent,
2599
char *string, ListTreeItemType type)
2601
ListTreeItem * ListTreeAddType(w, parent, string, type)
2603
ListTreeItem *parent;
2605
ListTreeItemType type;
2608
return (AddItem(w,parent,string,type));
2611
/*-------------------------------------------------------------------------*/
2612
#if NeedFunctionPrototypes
2613
ListTreeItem * ListTreeAddBranch(Widget w, ListTreeItem *parent,
2616
ListTreeItem * ListTreeAddBranch(w, parent, string)
2618
ListTreeItem *parent;
2622
return (AddItem(w,parent,string,ItemBranchType));
2625
/*-------------------------------------------------------------------------*/
2626
#if NeedFunctionPrototypes
2627
ListTreeItem * ListTreeAddLeaf(Widget w, ListTreeItem *parent,
2630
ListTreeItem * ListTreeAddLeaf(w, parent, string)
2632
ListTreeItem *parent;
2636
return (AddItem(w,parent,string,ItemLeafType));
2639
/*-------------------------------------------------------------------------*/
2640
#if NeedFunctionPrototypes
2641
void ListTreeSetItemPixmaps(Widget w, ListTreeItem *item,
2642
Pixmap openPixmap, Pixmap closedPixmap)
2644
void ListTreeSetItemPixmaps(w, item, openPixmap, closedPixmap)
2648
Pixmap closedPixmap;
2651
item->openPixmap = openPixmap;
2652
item->closedPixmap = closedPixmap;
2655
/*-------------------------------------------------------------------------*/
2656
#if NeedFunctionPrototypes
2657
void ListTreeRenameItem(Widget w, ListTreeItem * item, char *string)
2659
void ListTreeRenameItem(w, item, string)
2661
ListTreeItem * item;
2668
TreeCheck((ListTreeWidget)w, "in ListTreeRename");
2670
len = strlen(string);
2671
copy = (char *) XtMalloc(len + 1);
2672
strcpy(copy, string);
2679
/*-------------------------------------------------------------------------*/
2680
#if NeedFunctionPrototypes
2681
ListTreeItem* ListTreeDelete(Widget w, ListTreeItem * item)
2683
ListTreeItem* ListTreeDelete(w, item)
2685
ListTreeItem * item;
2688
ListTreeWidget lw = (ListTreeWidget)w;
2691
if (item->parent || item == ListTreeFirstItem(w))
2692
RemoveReference(lw, item);
2693
DeleteChildren(lw, item);
2694
DeleteItem(lw, item);
2702
/*-------------------------------------------------------------------------*/
2703
#if NeedFunctionPrototypes
2704
int ListTreeDeleteChildren(Widget w, ListTreeItem * item)
2706
int ListTreeDeleteChildren(w, item)
2708
ListTreeItem * item;
2711
ListTreeWidget lw = (ListTreeWidget)w;
2713
DeleteChildren(lw, item);
2719
/*-------------------------------------------------------------------------*/
2720
#if NeedFunctionPrototypes
2721
void ListTreeUnchainItem(Widget w, ListTreeItem * item)
2723
void ListTreeUnchainItem(w, item)
2725
ListTreeItem * item;
2728
ListTreeWidget lw = (ListTreeWidget)w;
2730
/* Remove the item from its old location. */
2731
RemoveReference(lw, item);
2736
/*-------------------------------------------------------------------------*/
2737
#if NeedFunctionPrototypes
2738
int ListTreeReparent(Widget w, ListTreeItem * item, ListTreeItem * newparent)
2740
int ListTreeReparent(w, item, newparent)
2742
ListTreeItem * item;
2743
ListTreeItem * newparent;
2746
ListTreeWidget lw = (ListTreeWidget)w;
2748
if (item == newparent)
2751
TreeCheck(lw, "in ListTreeReparent");
2752
/* Remove the item from its old location. */
2753
RemoveReference(lw, item);
2755
/* The item is now unattached. Reparent it. */
2756
InsertChild(lw, newparent, item);
2763
/*-------------------------------------------------------------------------*/
2764
#if NeedFunctionPrototypes
2765
int ListTreeReparentChildren(Widget w, ListTreeItem * item,
2766
ListTreeItem * newparent)
2768
int ListTreeReparentChildren(w, item, newparent)
2771
ListTreeItem * newparent;
2774
ListTreeWidget lw = (ListTreeWidget)w;
2775
ListTreeItem *first;
2777
TreeCheck(lw, "in ListTreeReparentChildren");
2778
if (item->firstchild) {
2779
first = item->firstchild;
2780
item->firstchild = NULL;
2782
InsertChildren(lw, newparent, first);
2790
/*-------------------------------------------------------------------------*/
2791
#if NeedFunctionPrototypes
2792
int AlphabetizeItems(_Xconst void *item1, _Xconst void *item2)
2794
int AlphabetizeItems(item1, item2)
2795
_Xconst void *item1;
2796
_Xconst void *item2;
2799
char *text1 = (*((ListTreeItem **) item1))->text;
2800
char *text2 = (*((ListTreeItem **) item2))->text;
2802
return strcmp(text1, text2);
2805
/*-------------------------------------------------------------------------*/
2806
#if NeedFunctionPrototypes
2807
int ListTreeUserOrderSiblings(Widget w, ListTreeItem * item,
2808
int (*func) (_Xconst void*, _Xconst void*))
2810
int ListTreeUserOrderSiblings(w, item, func)
2812
ListTreeItem * item;
2816
ListTreeWidget lw = (ListTreeWidget)w;
2817
ListTreeItem *first, *parent, **list;
2818
size_t i, count, size;
2820
TreeCheck(lw, "in ListTreeUserOrderSiblings");
2821
/* Get first child in list; */
2822
while (item->prevsibling)
2823
item = item->prevsibling;
2825
parent = first->parent;
2827
/* Count the children */
2829
while (item->nextsibling)
2830
item = item->nextsibling, count++;
2834
size = sizeof(ListTreeItem *);
2835
list = (ListTreeItem **) XtMalloc(size * count);
2838
while (first->nextsibling) {
2839
list[count] = first->nextsibling;
2841
first = first->nextsibling;
2844
qsort(list, count, size, func);
2846
list[0]->prevsibling = NULL;
2847
for (i = 0; i < count; i++) {
2849
list[i]->nextsibling = list[i + 1];
2851
list[i]->prevsibling = list[i - 1];
2853
list[count - 1]->nextsibling = NULL;
2855
parent->firstchild = list[0];
2857
lw->list.first = list[0];
2858
XtFree((char *) list);
2861
TreeCheck((ListTreeWidget)w, "exiting ListTreeOrderSiblings");
2866
/*-------------------------------------------------------------------------*/
2867
#if NeedFunctionPrototypes
2868
int ListTreeUserOrderChildren(Widget w, ListTreeItem * item,
2869
int (*func) (_Xconst void*, _Xconst void*))
2871
int ListTreeUserOrderChildren(w, item, func)
2873
ListTreeItem * item;
2877
TreeCheck(lw, "in ListTreeUserOrderChildren");
2880
ListTreeUserOrderSiblings(w, item, func);
2881
while (item->prevsibling)
2882
item = item->prevsibling;
2884
ListTreeUserOrderChildren(w, item->firstchild, func);
2885
item = item->nextsibling;
2889
TreeCheck(lw, "exiting ListTreeUserOrderChildren");
2894
/*-------------------------------------------------------------------------*/
2895
#if NeedFunctionPrototypes
2896
int ListTreeOrderChildren(Widget w, ListTreeItem * item)
2898
int ListTreeOrderChildren(w, item)
2900
ListTreeItem * item;
2903
return ListTreeUserOrderChildren(w, item, AlphabetizeItems);
2907
/*-------------------------------------------------------------------------*/
2908
#if NeedFunctionPrototypes
2909
ListTreeItem* ListTreeFindSiblingName(Widget w, ListTreeItem * item,
2912
ListTreeItem* ListTreeFindSiblingName(w, item, name)
2914
ListTreeItem * item;
2918
ListTreeItem *first;
2920
TreeCheck((ListTreeWidget)w, "in ListTreeFindSiblingName");
2921
/* Get first child in list; */
2923
while (item->prevsibling)
2924
item = item->prevsibling;
2928
if (strncmp(item->text, name, strlen(name)) == 0)
2930
item = item->nextsibling;
2937
/*-------------------------------------------------------------------------*/
2938
#if NeedFunctionPrototypes
2939
ListTreeItem* ListTreeFindPath(Widget w, ListTreeItem * item,
2940
char *name, char *path, char delim)
2942
ListTreeItem* ListTreeFindPath(w, item, name, path, delim)
2944
ListTreeItem * item;
2950
ListTreeItem *ret = NULL, *child;
2951
char *buf=NULL, *bufp;
2953
TreeCheck(lw, "in ListTreeFindPath");
2958
if (name == NULL || !strcmp(name, "*") || !strncmp(name, item->text, strlen(name))) {
2965
/* get next component from path */
2967
bufp = buf = (char *)malloc(strlen(path)+1);
2968
if (*path == '.' || *path == '/')
2970
while (*path && *path != '.' && *path != '/')
2974
} else if (delim == '/')
2977
for (child=item->firstchild; child && !ret; child=child->nextsibling)
2978
ret = ListTreeFindPath(w, child, name, path, delim);
2985
/*-------------------------------------------------------------------------*/
2986
#if NeedFunctionPrototypes
2987
ListTreeItem* ListTreeFindChildName(Widget w, ListTreeItem * item,
2990
ListTreeItem* ListTreeFindChildName(w, item, name)
2992
ListTreeItem * item;
2997
ListTreeItem *ret = NULL;
2999
TreeCheck(lw, "in ListTreeFindChildName");
3001
/* Get first child in list; */
3003
ret = ListTreeFindChildName(w, item->firstchild, name);
3006
if (!strcmp(item->text, name)) {
3010
item = item->nextsibling;
3018
return ListTreeFindPath(w, item, NULL, name, 0);
3023
/*-------------------------------------------------------------------------*/
3024
#if NeedFunctionPrototypes
3025
ListTreeMultiReturnStruct* ListTreeBuildSearchList(Widget w, ListTreeItem *start, char *name, int reset)
3027
ListTreeMultiReturnStruct* ListTreeBuildSearchList(w, start, name, reset)
3029
ListTreeItem *start;
3034
static ListTreeMultiReturnStruct itemlist = {NULL, 0};
3035
static int count = 0;
3038
TreeCheck(lw, "in ListTreeBuildSearchList");
3040
** free the allocated items
3043
if (itemlist.count > 0) {
3044
free(itemlist.items);
3045
itemlist.items = NULL;
3052
** Build a list of all items matching the search string
3055
for (item = start->firstchild; item; item = item->nextsibling) {
3056
if (item->type == ItemBranchType)
3057
ListTreeBuildSearchList(w, item, name, 0);
3058
if (!strncmp(item->text, name, strlen(name))) {
3059
if (itemlist.count >= count) {
3061
itemlist.items = (ListTreeItem**) XtRealloc((char*)itemlist.items, sizeof(ListTreeItem *) * count);
3063
itemlist.items[itemlist.count++] = item;
3072
/*-------------------------------------------------------------------------*/
3073
#if NeedFunctionPrototypes
3074
void ListTreeOpenLikeTree(Widget w, ListTreeItem *new, ListTreeItem *old)
3076
void ListTreeOpenLikeTree(w, new, old)
3082
ListTreeItem *new_to_set;
3084
TreeCheck(lw, "in ListTreeOpenLikeTree");
3087
new_to_set = ListTreeFindSiblingName(w, new, old->text);
3089
new_to_set->open = old->open;
3090
if (old->firstchild && new_to_set->firstchild)
3091
ListTreeOpenLikeTree(w, new_to_set->firstchild, old->firstchild);
3094
old = old->nextsibling;
3098
/*-------------------------------------------------------------------------*/
3099
#if NeedFunctionPrototypes
3100
void ListTreeHighlightItem(Widget w, ListTreeItem * item, Boolean notify)
3102
void ListTreeHighlightItem(w, item, notify)
3104
ListTreeItem * item;
3108
ListTreeWidget lw = (ListTreeWidget)w;
3110
/* printf("ListTreeHighlightItem: start\n"); */
3116
lw->list.timer_x = item->x;
3117
lw->list.timer_y = item->y;
3118
lw->list.timer_type = TIMER_SINGLE;
3119
lw->list.timer_item = item;
3120
lw->list.timer_id = (XtIntervalId) 0;
3122
HighlightAll(lw, False, False);
3123
HighlightItem(lw, item, True, False);
3125
/* printf("ListTreeHighlightItem: before HighlightDoCallback()\n"); */
3126
if (notify && lw->list.timer_type != TIMER_CLEAR &&
3127
lw->list.HighlightCallback) {
3128
/* printf("ListTreeHighlightItem: HighlightDoCallback()\n"); */
3129
HighlightDoCallback(lw);
3130
lw->list.timer_type = TIMER_CLEAR;
3137
/*-------------------------------------------------------------------------*/
3138
#if NeedFunctionPrototypes
3139
void ListTreeHighlightAll(Widget w)
3141
void ListTreeHighlightAll(w)
3145
ListTreeWidget lw = (ListTreeWidget)w;
3147
HighlightAllVisible(lw, True, False);
3151
/*-------------------------------------------------------------------------*/
3152
#if NeedFunctionPrototypes
3153
void ListTreeClearHighlighted(Widget w)
3155
void ListTreeClearHighlighted(w)
3159
ListTreeWidget lw = (ListTreeWidget)w;
3161
HighlightAll(lw, False, False);
3165
/*-------------------------------------------------------------------------*/
3166
#if NeedFunctionPrototypes
3167
void ListTreeGetHighlighted(Widget w, ListTreeMultiReturnStruct * ret)
3169
void ListTreeGetHighlighted(w, ret)
3171
ListTreeMultiReturnStruct * ret;
3174
ListTreeWidget lw = (ListTreeWidget)w;
3176
MakeMultiCallbackStruct(lw, ret);
3179
/*-------------------------------------------------------------------------*/
3180
#if NeedFunctionPrototypes
3181
void ListTreeSetHighlighted(Widget w, ListTreeItem ** items,
3182
int count, Boolean clear)
3184
void ListTreeSetHighlighted(w, items, count, clear)
3186
ListTreeItem ** items;
3191
ListTreeWidget lw = (ListTreeWidget)w;
3194
HighlightAll(lw, False, False);
3197
HighlightItem(lw, *items, True, False);
3204
for (i = 0; i < count; i++) {
3205
HighlightItem(lw, items[i], True, False);
3211
/*-------------------------------------------------------------------------*/
3212
#if NeedFunctionPrototypes
3213
ListTreeItem * ListTreeFirstItem(Widget w)
3215
ListTreeItem * ListTreeFirstItem(w)
3219
ListTreeWidget lw = (ListTreeWidget)w;
3220
ListTreeItem *first;
3222
/* Get first child in widget */
3223
first = lw->list.first;
3227
/*-------------------------------------------------------------------------*/
3228
#if NeedFunctionPrototypes
3229
ListTreeItem* ListTreeFirstChild(ListTreeItem *item)
3231
ListTreeItem* ListTreeFirstChild(item)
3238
/* Get first child of item */
3239
return item->firstchild;
3242
/*-------------------------------------------------------------------------*/
3243
#if NeedFunctionPrototypes
3244
ListTreeItem* ListTreeNextSibling(ListTreeItem *item)
3246
ListTreeItem* ListTreeNextSibling(item)
3253
/* Get first child of item */
3254
return item->nextsibling;
3257
/*-------------------------------------------------------------------------*/
3258
#if NeedFunctionPrototypes
3259
ListTreeItem* ListTreePrevSibling(ListTreeItem *item)
3261
ListTreeItem* ListTreePrevSibling(item)
3268
/* Get first child of item */
3269
return item->prevsibling;
3272
/*-------------------------------------------------------------------------*/
3273
#if NeedFunctionPrototypes
3274
ListTreeItem* ListTreeParent(ListTreeItem *item)
3276
ListTreeItem* ListTreeParent(item)
3283
/* Get first child of item */
3284
return item->parent;
3288
/*-------------------------------------------------------------------------*/
3289
#if NeedFunctionPrototypes
3290
void ListTreeOpenToLevel(Widget w, ListTreeItem *item, int level)
3292
void ListTreeOpenToLevel(w, item, level)
3298
Boolean refresh = False;
3301
item = ListTreeFirstItem(w);
3305
item = ListTreeFirstChild(item);
3307
while (item && (level > 0)) {
3308
ListTreeOpenToLevel(w, item, level-1);
3310
item = ListTreeNextSibling(item);
3319
/*-------------------------------------------------------------------------*/
3320
#if NeedFunctionPrototypes
3321
void ListTreeCloseToLevel(Widget w, ListTreeItem *item, int level)
3323
void ListTreeCloseToLevel(w, item, level)
3329
Boolean refresh = False;
3332
item = ListTreeFirstItem(w);
3336
item = ListTreeFirstChild(item);
3339
ListTreeOpenToLevel(w, item, level-1);
3342
item = ListTreeNextSibling(item);
3349
/*-------------------------------------------------------------------------*/
3350
#if NeedFunctionPrototypes
3351
void ListTreeOpenNode(Widget w, ListTreeItem *item)
3353
void ListTreeOpenNode(w, item)
3363
while (item->parent) {
3364
item = item->parent;
3370
/*-------------------------------------------------------------------------*/
3371
#if NeedFunctionPrototypes
3372
void ListTreeCloseNode(Widget w, ListTreeItem *item)
3374
void ListTreeCloseNode(w, item)
3387
/*-------------------------------------------------------------------------*/
3388
#if NeedFunctionPrototypes
3389
Position ListTreeGetItemPosition(Widget w, ListTreeItem *item)
3391
Position ListTreeGetItemPosition(w, item)
3396
ListTreeWidget lw = (ListTreeWidget)w;
3399
return GetPosition(lw, item, &counter);
3402
/*-------------------------------------------------------------------------*/
3403
#if NeedFunctionPrototypes
3404
void ListTreeMakeItemVisible(Widget w, ListTreeItem *item)
3406
void ListTreeMakeItemVisible(w, item)
3411
ListTreeWidget lw = (ListTreeWidget)w;
3415
GetPosition(lw, item, &counter);
3418
LT_DBG(DARG, ".. topItemPos = %d, botItemPos = %d, visibleCount = %d, item_pos = %d, itemCount= %d\n", lw->list.topItemPos, lw->list.bottomItemPos,
3419
lw->list.visibleCount, item_pos, lw->list.itemCount);
3421
if (item_pos > (lw->list.topItemPos + lw->list.visibleCount) ||
3422
(item_pos < lw->list.topItemPos)) {
3423
lw->list.topItemPos = item_pos;
3424
lw->list.bottomItemPos = item_pos + lw->list.visibleCount - 1;
3429
LT_DBG(DARG, ".. topItemPos = %d, botItemPos = %d, visibleCount = %d, item_pos = %d, itemCount= %d\n", lw->list.topItemPos, lw->list.bottomItemPos,
3430
lw->list.visibleCount, item_pos, lw->list.itemCount);
3434
/*-------------------------------------------------------------------------*/
3435
#if NeedFunctionPrototypes
3436
void ListTreeGetPathname(ListTreeReturnStruct * ret, char *dir)
3438
void ListTreeGetPathname(ret, dir)
3439
ListTreeReturnStruct * ret;
3445
if (*ret->path[0]->text != '/')
3449
strcat(dir, ret->path[0]->text);
3451
while (count < ret->count) {
3453
strcat(dir, ret->path[count]->text);
3458
/*-------------------------------------------------------------------------*/
3459
#if NeedFunctionPrototypes
3460
void ListTreeGetPathnameFromItem(ListTreeItem * item, char *dir)
3462
void ListTreeGetPathnameFromItem(item. dir)
3463
ListTreeItem * item;
3471
sprintf(tmppath, "/%s%s", item->text, dir);
3472
strcpy(dir, tmppath);
3473
item = item->parent;
3477
/*-------------------------------------------------------------------------*/
3478
#if NeedFunctionPrototypes
3479
Widget XmCreateScrolledListTree(Widget parent, char *name, Arg *args,
3482
Widget XmCreateScrolledListTree(parent, name, args, count)
3494
sname = XtMalloc(strlen(name)+3);
3495
strcpy(sname, name);
3496
strcat(sname, "SW");
3498
al = (Arg *)XtCalloc(count + 4, sizeof(Arg));
3499
for (i=0; i<count; i++) {
3500
al[i].name = args[i].name;
3501
al[i].value = args[i].value;
3504
XtSetArg(al[i], XmNscrollingPolicy, XmAPPLICATION_DEFINED); i++;
3505
XtSetArg(al[i], XmNvisualPolicy, XmVARIABLE); i++;
3506
XtSetArg(al[i], XmNscrollBarDisplayPolicy, XmSTATIC); i++;
3507
XtSetArg(al[i], XmNshadowThickness, 0); i++;
3509
sw = XtCreateManagedWidget(sname,
3510
xmScrolledWindowWidgetClass,
3513
XtFree((XtPointer)al);
3515
return XtCreateWidget(name, listtreeWidgetClass, sw, args, count);