~ubuntu-branches/debian/sid/acfax/sid

« back to all changes in this revision

Viewing changes to FChooser.c

  • Committer: Bazaar Package Importer
  • Author(s): Hamish Moffatt
  • Date: 2001-12-27 12:07:46 UTC
  • Revision ID: james.westby@ubuntu.com-20011227120746-iz2p5k757bcla8ov
Tags: upstream-981011
ImportĀ upstreamĀ versionĀ 981011

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * FChooser.c : A widget for choosing a file
 
3
 *
 
4
 * George Ferguson, ferguson@cs.rochester.edu, 21 Jan 1993.
 
5
 *
 
6
 * This code is derived from the FileSelector widget by Brian Totty,
 
7
 * hence the following copyright applies:
 
8
 *
 
9
 * Copyright 1990,1991,1992 Brian Totty
 
10
 * 
 
11
 * Permission to use, copy, modify, distribute, and sell this software
 
12
 * and its documentation for any purpose is hereby granted without fee,
 
13
 * provided that the above copyright notice appears in all copies and that
 
14
 * both that copyright notice and this permission notice appear in
 
15
 * supporting documentation, and that the name of Brian Totty or
 
16
 * University of Illinois not be used in advertising or publicity
 
17
 * pertaining to distribution of the software without specific, written
 
18
 * prior permission.  Brian Totty and University of Illinois make no
 
19
 * representations about the suitability of this software for any
 
20
 * purpose.  It is provided "as is" without express or implied warranty.
 
21
 *
 
22
 * Brian Totty and University of Illinois disclaim all warranties with
 
23
 * regard to this software, including all implied warranties of
 
24
 * merchantability and fitness, in no event shall Brian Totty or
 
25
 * University of Illinois be liable for any special, indirect or
 
26
 * consequential damages or any damages whatsoever resulting from loss of
 
27
 * use, data or profits, whether in an action of contract, negligence or
 
28
 * other tortious action, arising out of or in connection with the use or
 
29
 * performance of this software.
 
30
 *
 
31
 * Author:
 
32
 *      Brian Totty
 
33
 *      Department of Computer Science
 
34
 *      University Of Illinois at Urbana-Champaign
 
35
 *      1304 West Springfield Avenue
 
36
 *      Urbana, IL 61801
 
37
 * 
 
38
 *      totty@cs.uiuc.edu
 
39
 *      
 
40
 */ 
 
41
 
 
42
#include <X11/Xlib.h>
 
43
#include <X11/Xos.h>
 
44
#include <X11/IntrinsicP.h>
 
45
#include <X11/Intrinsic.h>
 
46
#include <X11/StringDefs.h>
 
47
#include <X11/cursorfont.h>
 
48
#include <X11/CompositeP.h>
 
49
#include <X11/Composite.h>
 
50
#ifdef USE_XAW3D
 
51
#include <X11/Xaw3d/MenuButton.h>
 
52
#include <X11/Xaw3d/SimpleMenu.h>
 
53
#include <X11/Xaw3d/SmeBSB.h>
 
54
#include <X11/Xaw3d/Viewport.h>
 
55
#include <X11/Xaw3d/List.h>
 
56
#else
 
57
#include <X11/Xaw/MenuButton.h>
 
58
#include <X11/Xaw/SimpleMenu.h>
 
59
#include <X11/Xaw/SmeBSB.h>
 
60
#include <X11/Xaw/Viewport.h>
 
61
#include <X11/Xaw/List.h>
 
62
#endif
 
63
 
 
64
#include "DirMgr.h"
 
65
#include "FChooserP.h"
 
66
#include "FChooser.h"
 
67
 
 
68
/*---------------------------------------------------------------------------*
 
69
 
 
70
                   I N T E R N A L    R O U T I N E S
 
71
 
 
72
 *---------------------------------------------------------------------------*/
 
73
 
 
74
#if (!NeedFunctionPrototypes)
 
75
 
 
76
static void             Initialize();
 
77
static void             Realize();
 
78
static void             Destroy();
 
79
static void             Resize();
 
80
static Boolean          SetValues();
 
81
static XtGeometryResult GeometryManager();
 
82
static void             ChildrenCreate();
 
83
static void             ChildrenRealize();
 
84
static void             ChildrenUpdate();
 
85
static void             DirectoryCallback();
 
86
static void             FileCallback();
 
87
static void             SelectFileByIndex();
 
88
static Boolean          SelectFileByName();
 
89
static void             UnselectAll();
 
90
static void             Notify();
 
91
static void             GotoDeepestLegalDirectory();
 
92
static void             UpdateLists();
 
93
static void             Chdir();
 
94
 
 
95
#else
 
96
 
 
97
static void             Initialize(Widget request, Widget new);
 
98
static void             Realize(Widget w, XtValueMask *valueMask,
 
99
                                XSetWindowAttributes *attrs);
 
100
static void             Destroy(XfwfFileChooserWidget fcw);
 
101
static void             Resize(Widget w);
 
102
static Boolean          SetValues(Widget current, Widget request, Widget new);
 
103
static XtGeometryResult GeometryManager(Widget w,
 
104
                                XtWidgetGeometry *request,
 
105
                                XtWidgetGeometry *reply);
 
106
static void             ChildrenCreate(XfwfFileChooserWidget fcw);
 
107
static void             ChildrenRealize(XfwfFileChooserWidget fcw);
 
108
static void             ChildrenUpdate(XfwfFileChooserWidget fcw);
 
109
static void             DirectoryCallback(Widget w, XtPointer client_data,
 
110
                                XtPointer call_data);
 
111
static void             FileCallback(Widget w, XtPointer client_data,
 
112
                                XtPointer call_data);
 
113
static void             SelectFileByIndex(XfwfFileChooserWidget fcw, int index);
 
114
static Boolean          SelectFileByName(XfwfFileChooserWidget fcw, char *name);
 
115
static void             UnselectAll(XfwfFileChooserWidget fcw);
 
116
static void             Notify(XfwfFileChooserWidget fcw);
 
117
static void             GotoDeepestLegalDirectory(XfwfFileChooserWidget fcw);
 
118
static void             UpdateLists(XfwfFileChooserWidget fcw);
 
119
static void             Chdir(XfwfFileChooserWidget fcw);
 
120
 
 
121
#endif
 
122
 
 
123
/*---------------------------------------------------------------------------*
 
124
 
 
125
              R E S O U R C E    I N I T I A L I Z A T I O N
 
126
 
 
127
 *---------------------------------------------------------------------------*/
 
128
 
 
129
#define FCFieldOffset(FIELD)    XtOffset(XfwfFileChooserWidget,fileChooser.FIELD)
 
130
#define CoreFieldOffset(FIELD)  XtOffset(Widget,core.FIELD)
 
131
 
 
132
static XtResource resources[] = {
 
133
    { XtNwidth, XtCWidth, XtRDimension, sizeof(Dimension),
 
134
         CoreFieldOffset(width), XtRString, "500" },
 
135
    { XtNheight, XtCHeight, XtRDimension, sizeof(Dimension),
 
136
         CoreFieldOffset(height), XtRString, "250" },
 
137
    { XtNbackground, XtCBackground, XtRPixel, sizeof(Pixel),
 
138
         CoreFieldOffset(background_pixel), XtRString, "white" },
 
139
    { XtNcurrentDirectory, XtCPathname, XtRString, sizeof(String),
 
140
         FCFieldOffset(current_dir), XtRString, NULL },
 
141
    { XtNcurrentFile, XtCFilename, XtRString, sizeof(String),
 
142
         FCFieldOffset(current_file), XtRString, NULL },
 
143
    { XtNcallback, XtCCallback, XtRCallback,
 
144
         sizeof(XtCallbackList), FCFieldOffset(callbacks), XtRCallback, NULL},
 
145
    {XtNsortMode, XtCValue, XtRInt, sizeof(int),
 
146
         FCFieldOffset(sort_mode), XtRString, "2"},
 
147
    {XtNpattern, XtCFile, XtRString, sizeof(String),
 
148
         FCFieldOffset(pattern), XtRString, NULL},
 
149
};
 
150
 
 
151
#undef FCFieldOffset
 
152
#undef CoreFieldOffset
 
153
 
 
154
/*---------------------------------------------------------------------------*
 
155
 
 
156
                    C L A S S    A L L O C A T I O N
 
157
 
 
158
 *---------------------------------------------------------------------------*/
 
159
 
 
160
XfwfFileChooserClassRec xfwfFileChooserClassRec = {
 
161
    {
 
162
        /* superclass           */      (WidgetClass)&compositeClassRec,
 
163
        /* class_name           */      "XfwfFileChooser",
 
164
        /* widget_size          */      sizeof(XfwfFileChooserRec),
 
165
        /* class_initialize     */      NULL,
 
166
        /* class_part_initialize*/      NULL,
 
167
        /* class_inited         */      FALSE,
 
168
        /* initialize           */      (XtInitProc)Initialize,
 
169
        /* initialize_hook      */      NULL,
 
170
        /* realize              */      (XtRealizeProc)Realize,
 
171
        /* actions              */      NULL,
 
172
        /* num_actions          */      0,
 
173
        /* resources            */      resources,
 
174
        /* resource_count       */      XtNumber(resources),
 
175
        /* xrm_class            */      NULLQUARK,
 
176
        /* compress_motion      */      TRUE,
 
177
        /* compress_exposure    */      TRUE,
 
178
        /* compress_enterleave  */      TRUE,
 
179
        /* visible_interest     */      FALSE,
 
180
        /* destroy              */      (XtWidgetProc)Destroy,
 
181
        /* resize               */      (XtWidgetProc)Resize,
 
182
        /* expose               */      XtInheritExpose,
 
183
        /* set_values           */      (XtSetValuesFunc)SetValues,
 
184
        /* set_values_hook      */      NULL,
 
185
        /* set_values_almost    */      XtInheritSetValuesAlmost,
 
186
        /* get_values_hook      */      NULL,
 
187
        /* accept_focus         */      NULL,
 
188
        /* version              */      XtVersion,
 
189
        /* callback_private     */      NULL,
 
190
        /* tm_table             */      NULL,
 
191
        /* query_geometry       */      XtInheritQueryGeometry,
 
192
        /* display_accelerator  */      XtInheritDisplayAccelerator,
 
193
        /* extension            */      NULL
 
194
    }, /* Core Part */
 
195
    {
 
196
        /* geometry_manager     */      GeometryManager,
 
197
        /* change_managed       */      XtInheritChangeManaged,
 
198
        /* insert_child         */      XtInheritInsertChild,
 
199
        /* delete_child         */      XtInheritDeleteChild,
 
200
        /* extension            */      NULL
 
201
    }, /* Composite Part */             
 
202
    {
 
203
        /* no extra class data  */      0
 
204
    }  /* FileSelector Part */
 
205
};
 
206
 
 
207
WidgetClass xfwfFileChooserWidgetClass =
 
208
        (WidgetClass)&xfwfFileChooserClassRec;
 
209
 
 
210
/*---------------------------------------------------------------------------*
 
211
 
 
212
                    E X P O R T E D    M E T H O D S
 
213
 
 
214
 *---------------------------------------------------------------------------*/
 
215
 
 
216
 
 
217
/*---------------------------------------------------------------------------*
 
218
 
 
219
        Initialize()
 
220
 
 
221
        This procedure is called by the X toolkit to initialize
 
222
        the FileChooser widget instance.  The hook to this routine is in the
 
223
        initialize part of the core part of the class.
 
224
 
 
225
 *---------------------------------------------------------------------------*/
 
226
 
 
227
/* ARGSUSED */
 
228
static void
 
229
Initialize(request,new)
 
230
Widget request,new;
 
231
{
 
232
    XfwfFileChooserWidget fcw = (XfwfFileChooserWidget)new;
 
233
    char *str,*initial_file,path[MAXPATHLEN + 2];
 
234
    static char *star = "*";
 
235
 
 
236
    FCBusyCursor(fcw) = XCreateFontCursor(XtDisplay(fcw),XC_watch);
 
237
    FCDirMenu(fcw) = NULL;
 
238
    FCDirMenuButton(fcw) = NULL;
 
239
    FCFileList(fcw) = NULL;
 
240
    FCDirMgr(fcw) = NULL;
 
241
    FCFileNames(fcw) = NULL;
 
242
    FCNumFileNames(fcw) = 0;
 
243
    FCDirNames(fcw) = NULL;
 
244
    FCNumDirNames(fcw) = 0;
 
245
 
 
246
    str = (char *)XtCalloc((MAXPATHLEN + 2),sizeof(char));
 
247
    if (FCCurrentDirectory(fcw) != NULL) {      /* User Specified Path */
 
248
        strcpy(str,FCCurrentDirectory(fcw));
 
249
    } else {
 
250
        getwd(path);
 
251
        strcpy(str,path);
 
252
    }
 
253
    FCCurrentDirectory(fcw) = str;
 
254
 
 
255
    str = (char *)XtCalloc((MAXPATHLEN + 2),sizeof(char));
 
256
    initial_file = FCCurrentFile(fcw);
 
257
    FCCurrentFile(fcw) = str;
 
258
 
 
259
    if (FCCorePart(request)->width <= 0)
 
260
        FCCorePart(new)->width = 500;
 
261
    if (FCCorePart(request)->height <= 0)
 
262
        FCCorePart(new)->height = 200;
 
263
 
 
264
    if (FCPattern(fcw) == NULL)
 
265
        FCPattern(fcw) = star;
 
266
    FCPattern(fcw) = XtNewString(FCPattern(fcw));
 
267
 
 
268
    ChildrenCreate(fcw);
 
269
    GotoDeepestLegalDirectory(fcw);
 
270
    if (initial_file)
 
271
        SelectFileByName(fcw,initial_file);
 
272
} /* End Initialize */
 
273
 
 
274
/*---------------------------------------------------------------------------*
 
275
 
 
276
        Realize()
 
277
 
 
278
        This function is called to realize a FileChooser widget.
 
279
 
 
280
 *---------------------------------------------------------------------------*/
 
281
 
 
282
static void Realize(w,valueMask,attrs)
 
283
Widget w;
 
284
XtValueMask *valueMask;
 
285
XSetWindowAttributes *attrs;
 
286
{
 
287
    XfwfFileChooserWidget fcw = (XfwfFileChooserWidget)w;
 
288
 
 
289
    XtCreateWindow(w,InputOutput,(Visual *)CopyFromParent,*valueMask,attrs);
 
290
    ChildrenRealize(fcw);
 
291
    ChildrenUpdate(fcw);
 
292
    Resize(w);
 
293
    Notify(fcw);
 
294
} /* End Realize */
 
295
 
 
296
/*---------------------------------------------------------------------------*
 
297
 
 
298
        Destroy()
 
299
 
 
300
        This function is called to destroy a FileChooser widget.
 
301
 
 
302
 *---------------------------------------------------------------------------*/
 
303
 
 
304
static void
 
305
Destroy(fcw)
 
306
XfwfFileChooserWidget fcw;
 
307
{
 
308
    int i;
 
309
 
 
310
    XtFree(FCCurrentDirectory(fcw));
 
311
    XtFree(FCCurrentFile(fcw));
 
312
    XtFree(FCPattern(fcw));
 
313
    if (FCFileNames(fcw) != NULL) {
 
314
        for (i=0; i < FCNumFileNames(fcw); i++)
 
315
            XtFree(FCFileNames(fcw)[i]);
 
316
        XtFree(FCFileNames(fcw));
 
317
    }
 
318
    if (FCDirNames(fcw) != NULL) {
 
319
        for (i=0; i < FCNumDirNames(fcw); i++)
 
320
            XtFree(FCDirNames(fcw)[i]);
 
321
        XtFree(FCDirNames(fcw));
 
322
    }
 
323
} /* End Destroy */
 
324
 
 
325
/*---------------------------------------------------------------------------*
 
326
 
 
327
        Resize()
 
328
 
 
329
        This function is called to resize a FileChooser widget.
 
330
 
 
331
 *---------------------------------------------------------------------------*/
 
332
 
 
333
static void
 
334
Resize(w) 
 
335
Widget w;
 
336
{
 
337
    XfwfFileChooserWidget fcw = (XfwfFileChooserWidget)w;
 
338
 
 
339
    ChildrenUpdate(fcw);
 
340
} /* End Resize */
 
341
 
 
342
/*---------------------------------------------------------------------------*
 
343
 
 
344
        SetValues()
 
345
 
 
346
        This function is the external interface for setting resources.
 
347
 
 
348
 *---------------------------------------------------------------------------*/
 
349
 
 
350
/* ARGSUSED */
 
351
static Boolean
 
352
SetValues(current,request,new)
 
353
Widget current,request,new;
 
354
{
 
355
    XfwfFileChooserWidget fcw_current = (XfwfFileChooserWidget)current;
 
356
    XfwfFileChooserWidget fcw_new = (XfwfFileChooserWidget)new;
 
357
    XfwfFileChooserWidget fcw_request = (XfwfFileChooserWidget)request;
 
358
 
 
359
    if (FCCurrentDirectory(fcw_current) != FCCurrentDirectory(fcw_new)){
 
360
/*      strcpy(FCCurrentDirectory(fcw_current),FCCurrentDirectory(fcw_new));
 
361
        FCCurrentDirectory(fcw_new) = FCCurrentDirectory(fcw_current); */
 
362
        /* didn't understand why to copy the new string into old space and
 
363
           use this for the new widget ?! - ACZ */
 
364
        Chdir(fcw_new);
 
365
    }
 
366
    if (FCCurrentFile(fcw_current) != FCCurrentFile(fcw_new)) {
 
367
        char *new_name;
 
368
 
 
369
        new_name = FCCurrentFile(fcw_new);
 
370
        FCCurrentFile(fcw_new) = FCCurrentFile(fcw_current);
 
371
        SelectFileByName(fcw_new,new_name);
 
372
    }
 
373
    if (FCPattern(fcw_current) != FCPattern(fcw_new)) {
 
374
/*      XtFree(FCPattern(fcw_current));
 
375
        FCPattern(fcw_new) = XtNewString(FCPattern(fcw_request)); */
 
376
                /* above was XtNewString(FCPattern(fcw_current)) - ACZ */
 
377
        Chdir(fcw_new);
 
378
    }
 
379
    if (FCSortMode(fcw_current) != FCSortMode(fcw_new)) {
 
380
        Chdir(fcw_new);
 
381
    }
 
382
    return(False);
 
383
} /* End SetValues() */
 
384
 
 
385
/*---------------------------------------------------------------------------*
 
386
 
 
387
        GeometryManager(w,request,reply)
 
388
 
 
389
        This routine acts as the geometry_manager method for the
 
390
        FileChooser widget.  It is called when a child wants to
 
391
        resize/reposition itself.
 
392
 
 
393
        Currently, we allow all requests.
 
394
 
 
395
 *---------------------------------------------------------------------------*/
 
396
 
 
397
/* ARGSUSED */
 
398
static XtGeometryResult
 
399
GeometryManager(w,request,reply)
 
400
Widget w;
 
401
XtWidgetGeometry *request;
 
402
XtWidgetGeometry *reply;
 
403
{
 
404
    return(XtGeometryYes);
 
405
} /* End GeometryManager */
 
406
 
 
407
/*---------------------------------------------------------------------------*
 
408
 
 
409
                     L O C A L    R O U T I N E S
 
410
 
 
411
 *---------------------------------------------------------------------------*/
 
412
 
 
413
/*---------------------------------------------------------------------------*
 
414
 
 
415
        ChildrenCreate(fcw)
 
416
 
 
417
        This routine creates the initial child widgets for the
 
418
        file selector widget and places them in the widget fcw.
 
419
        No placement or resizing is done.  That is done by
 
420
        ChildrenUpdate().
 
421
 
 
422
 *---------------------------------------------------------------------------*/
 
423
 
 
424
static void
 
425
ChildrenCreate(fcw)
 
426
XfwfFileChooserWidget fcw;
 
427
{
 
428
    static char *str = NULL;
 
429
 
 
430
    FCDirMenuButton(fcw) =
 
431
        XtVaCreateManagedWidget(FC_DIR_MENU_BUTTON_NAME,menuButtonWidgetClass,
 
432
                (Widget)fcw,
 
433
                XtNmenuName, FC_DIR_MENU_NAME,
 
434
                NULL);
 
435
 
 
436
    FCFileViewport(fcw) =
 
437
        XtVaCreateManagedWidget(FC_FILE_VIEWPORT_NAME,viewportWidgetClass,
 
438
                (Widget)fcw,
 
439
                XtNallowVert, True,
 
440
                XtNforceBars, True,
 
441
                XtNuseRight, True,
 
442
                NULL);
 
443
 
 
444
    FCFileList(fcw) = XtVaCreateManagedWidget(FC_FILE_LIST_NAME,listWidgetClass,
 
445
                FCFileViewport(fcw),
 
446
                XtNlist, &str,
 
447
                XtNdefaultColumns, 1,
 
448
                XtNforceColumns, True,
 
449
                XtNverticalList, True,
 
450
                /* XtNborderWidth, 0, */
 
451
                NULL);
 
452
 
 
453
    XtAddCallback(FCFileList(fcw),XtNcallback,
 
454
                  (XtCallbackProc)FileCallback,(XtPointer)fcw);
 
455
} /* End ChildrenCreate */
 
456
 
 
457
/*---------------------------------------------------------------------------*
 
458
 
 
459
        ChildrenRealize(fcw)
 
460
 
 
461
        This routine realizes the child widgets.  The widgets must
 
462
        already have been created and initialized.  Their coordinates
 
463
        should already have been set.
 
464
 
 
465
 *---------------------------------------------------------------------------*/
 
466
 
 
467
static void
 
468
ChildrenRealize(fcw)
 
469
XfwfFileChooserWidget fcw;
 
470
{
 
471
    XtRealizeWidget(FCDirMenuButton(fcw));
 
472
    XtRealizeWidget(FCFileViewport(fcw));
 
473
    XtRealizeWidget(FCFileList(fcw));
 
474
} /* End ChildrenRealize */
 
475
 
 
476
/*---------------------------------------------------------------------------*
 
477
 
 
478
        ChildrenUpdate(fcw)
 
479
 
 
480
        This routine takes a FileChooser widget fcw and updates
 
481
        the child widgets by recalculating their coordinates based
 
482
        on the current size of the FileChooser, and setting the
 
483
        appropriate resources.
 
484
 
 
485
        We go to some trouble to get something useful displayed in the
 
486
        FCDirMenuButton(fcw) if the current directory name is too long
 
487
        to fit in the button. It would be nice if the "justify" resource
 
488
        of the MenuButton widget did this, but...
 
489
 
 
490
 *---------------------------------------------------------------------------*/
 
491
 
 
492
static void
 
493
ChildrenUpdate(fcw)
 
494
XfwfFileChooserWidget fcw;
 
495
{
 
496
    Dimension w,h;
 
497
    int gap;
 
498
    Dimension menuButtonW,menuButtonH,fileListW,fileListH;
 
499
    Position menuButtonX,menuButtonY,fileListX,fileListY;
 
500
    XtWidgetGeometry parent_idea,child_idea;
 
501
    XFontStruct *fs;
 
502
    char *label;
 
503
    Dimension intw;
 
504
 
 
505
    if (!XtIsRealized((Widget)fcw)) {
 
506
        return;
 
507
    }
 
508
    w = CoreWidth(fcw);
 
509
    h = CoreHeight(fcw);
 
510
    gap = 3;
 
511
 
 
512
    intw = 8;
 
513
 
 
514
    XtVaGetValues(FCDirMenuButton(fcw), XtNfont, &fs, NULL);
 
515
    /* Get The Child Widgets Current Widths And Heights */
 
516
    /* (although we don't actually use the existing values... */
 
517
    menuButtonW = CoreWidth(FCDirMenuButton(fcw));
 
518
    menuButtonH = CoreHeight(FCDirMenuButton(fcw));
 
519
 
 
520
    /* Adjust Widths */
 
521
    menuButtonW = w;
 
522
    fileListW = w;
 
523
 
 
524
    /* Adjust menu button label if too small */
 
525
    /* It would be nice if the "justify" resource of MenuButton did this... */
 
526
    label = FCCurrentDirectory(fcw);
 
527
    if (XTextWidth(fs,label,strlen(label)) > menuButtonW-intw) {
 
528
        char newLabel[MAXPATHLEN];
 
529
        /* cut away chars from left side until it fits into the button */
 
530
        while (*label && XTextWidth(fs,label,strlen(label))>menuButtonW-intw) {
 
531
            label += 1;
 
532
        }
 
533
        if (*label)
 
534
            label += 1;
 
535
        strcpy(newLabel,""); /* was "<" - ACZ */
 
536
        strcat(newLabel,label);
 
537
        XtVaSetValues(FCDirMenuButton(fcw), XtNlabel, newLabel, NULL);
 
538
    } else {
 
539
        XtVaSetValues(FCDirMenuButton(fcw), XtNlabel, label, NULL);
 
540
    }
 
541
    /* Adjust Heights */
 
542
    fileListH = h - menuButtonH - gap;
 
543
    /* Listen To Child Height Request For List */
 
544
/*
 
545
    parent_idea.request_mode = CWWidth | CWHeight;
 
546
    parent_idea.width = fileListW;
 
547
    parent_idea.height = fileListH;
 
548
    XtQueryGeometry(FCFileList(fcw),&parent_idea,&child_idea);
 
549
    if ((child_idea.request_mode & CWHeight) &&
 
550
        (child_idea.height < parent_idea.height)) {
 
551
        fileListH = child_idea.height;
 
552
    }
 
553
*/
 
554
    /* Vertical Positions */
 
555
    menuButtonY = 0;
 
556
    fileListY = menuButtonH + gap;
 
557
    /* Horizontal Positions */
 
558
    menuButtonX = 0;
 
559
    fileListX = 0;
 
560
 
 
561
    /* Move them */
 
562
    XtMoveWidget(FCDirMenuButton(fcw),menuButtonX,menuButtonY);
 
563
    XtMoveWidget(FCFileViewport(fcw),fileListX,fileListY);
 
564
    /* Resize them */
 
565
    XtResizeWidget(FCDirMenuButton(fcw),menuButtonW,menuButtonH,
 
566
                   CoreBorderWidth(FCDirMenuButton(fcw)));
 
567
    XtResizeWidget(FCFileViewport(fcw),fileListW,fileListH,
 
568
                   CoreBorderWidth(FCFileViewport(fcw)));
 
569
} /* End ChildrenUpdate */
 
570
 
 
571
/*---------------------------------------------------------------------------*
 
572
 
 
573
                 I N T E R N A L    C A L L B A C K S
 
574
 
 
575
 *---------------------------------------------------------------------------*/
 
576
 
 
577
/*---------------------------------------------------------------------------*
 
578
 
 
579
        DirectoryCallback(w,client_data,call_data)
 
580
 
 
581
        This is called when the user selects an ancestor directory from
 
582
        the menu. The argument "w" is the selected object (hence the two
 
583
        calls to XtParent()) and "client_data" is it's index in the menu.
 
584
 
 
585
 *---------------------------------------------------------------------------*/
 
586
 
 
587
/*ARGSUSED*/
 
588
static void
 
589
DirectoryCallback(w,client_data,call_data)
 
590
Widget w;
 
591
XtPointer client_data;  /* index */
 
592
XtPointer call_data;    /* not used */
 
593
{
 
594
    int index = (int)client_data;
 
595
    XfwfFileChooserWidget fcw = (XfwfFileChooserWidget)XtParent(XtParent(w));
 
596
    int i;
 
597
 
 
598
    strcpy(FCCurrentDirectory(fcw),"/");
 
599
    for (i = 1; i <= index; i++) {
 
600
        strcat(FCCurrentDirectory(fcw),FCDirNames(fcw)[i]);
 
601
        strcat(FCCurrentDirectory(fcw),"/");
 
602
    }
 
603
    Chdir(fcw);
 
604
} /* End DirectoryCallback */
 
605
 
 
606
/*---------------------------------------------------------------------------*
 
607
 
 
608
        FileCallback(w,client_data,call_data)
 
609
 
 
610
        This is called when the user selects a file in the fileList.
 
611
        The argument "client_data" is the FileChooser widget, "call_data"
 
612
        is a pointer to the standard List widget callback information.
 
613
 
 
614
 *---------------------------------------------------------------------------*/
 
615
 
 
616
/*ARGSUSED*/
 
617
static void
 
618
FileCallback(w,client_data,call_data)
 
619
Widget w;
 
620
XtPointer client_data;  /* fcw */
 
621
XtPointer call_data;    /* return struct */
 
622
{
 
623
    XfwfFileChooserWidget fcw = (XfwfFileChooserWidget)client_data;
 
624
    XawListReturnStruct *ret = (XawListReturnStruct *)call_data;
 
625
 
 
626
    if (ret->list_index == -1) {
 
627
        UnselectAll(fcw);               /* Click On Blank Space */
 
628
        Notify(fcw);
 
629
    } else {
 
630
        SelectFileByIndex(fcw,ret->list_index);
 
631
    }
 
632
} /* End FileCallback */
 
633
 
 
634
/*---------------------------------------------------------------------------*
 
635
 
 
636
             I N T E R N A L    S U P P O R T    R O U T I N E S
 
637
 
 
638
 *---------------------------------------------------------------------------*/
 
639
 
 
640
static void
 
641
SelectFileByIndex(fcw,index)
 
642
XfwfFileChooserWidget fcw;
 
643
int index;
 
644
{
 
645
    DirEntry *dir_entry;
 
646
 
 
647
    DirectoryMgrGotoItem(FCDirMgr(fcw),index);
 
648
    if ((dir_entry=DirectoryMgrCurrentEntry(FCDirMgr(fcw))) == NULL) {
 
649
        fprintf(stderr,"SelectFileByIndex: Entry %d invalid\n",index);
 
650
        exit(-1);
 
651
    }
 
652
    if (DirEntryIsDir(dir_entry) || DirEntryIsDirectoryLink(dir_entry)) {
 
653
        strcat(FCCurrentDirectory(fcw),DirEntryFileName(dir_entry));
 
654
        Chdir(fcw);
 
655
    } else if (!DirEntryIsBrokenLink(dir_entry)) {      /* File */
 
656
        strcpy(FCCurrentFile(fcw),DirEntryFileName(dir_entry));
 
657
        XawListHighlight(FCFileList(fcw),index);
 
658
        Notify(fcw);
 
659
    } else {                                            /* Broken Link */
 
660
        XBell(XtDisplay(fcw),0);
 
661
        UnselectAll(fcw);
 
662
    }
 
663
} /* End SelectFileByIndex */
 
664
 
 
665
static Boolean
 
666
SelectFileByName(fcw,name)
 
667
XfwfFileChooserWidget fcw;
 
668
char *name;
 
669
{
 
670
    if (DirectoryMgrGotoNamedItem(FCDirMgr(fcw),name) == FALSE) {
 
671
        return(False);
 
672
    }
 
673
    SelectFileByIndex(fcw,DirectoryMgrCurrentIndex(FCDirMgr(fcw)));
 
674
    return(True);
 
675
} /* End SelectFileByName */
 
676
 
 
677
static void
 
678
UnselectAll(fcw)
 
679
XfwfFileChooserWidget fcw;
 
680
{
 
681
    Boolean selected = FCCurrentFile(fcw)[0] != '\0';
 
682
 
 
683
    FCCurrentFile(fcw)[0] = '\0';
 
684
    XawListUnhighlight(FCFileList(fcw));
 
685
    if (selected)
 
686
        Notify(fcw);
 
687
} /* End UnselectAll */
 
688
 
 
689
static void
 
690
Notify(fcw)
 
691
XfwfFileChooserWidget fcw;
 
692
{
 
693
    XfwfFileChooserReturnStruct ret;
 
694
 
 
695
    if (FCCurrentFile(fcw)[0] != '\0') {
 
696
        ret.directory = FCCurrentDirectory(fcw);
 
697
        ret.file = FCCurrentFile(fcw);
 
698
    } else {
 
699
        ret.directory = NULL;
 
700
        ret.file = NULL;
 
701
    }
 
702
    XtCallCallbacks((Widget)fcw,XtNcallback,(XtPointer)&ret);
 
703
} /* End Notify */
 
704
 
 
705
/*---------------------------------------------------------------------------*
 
706
 
 
707
        GotoDeepestLegalDirectory(fcw)
 
708
 
 
709
        This function takes a FileChooser widget <fcw> and modifies the
 
710
        directory string in FCCurrentDirectory(fcw) to be the deepest
 
711
        legal directory above the string.  Partial or incorrect directory
 
712
        names are stripped starting at the end.
 
713
 
 
714
        It then calls UpdateLists() to reset the information dislayed in
 
715
        the FileChooser.
 
716
 
 
717
 *---------------------------------------------------------------------------*/
 
718
 
 
719
static void
 
720
GotoDeepestLegalDirectory(fcw)
 
721
XfwfFileChooserWidget fcw;
 
722
{
 
723
    char *dir,*end;
 
724
    char temp[MAXPATHLEN + 2];
 
725
 
 
726
    dir = FCCurrentDirectory(fcw);
 
727
    for (end=dir; *end != '\0'; ++end)
 
728
        /*EMPTY*/;
 
729
    while (1) {
 
730
        if (DirectoryPathExpand(dir,temp) == NULL) {
 
731
            while (*end != '/' && end != dir) {
 
732
                end -= 1;
 
733
            }
 
734
            *end = '\0';
 
735
        } else {
 
736
            strcpy(FCCurrentDirectory(fcw),temp);
 
737
            break;
 
738
        }
 
739
    }
 
740
    UnselectAll(fcw);
 
741
    UpdateLists(fcw);
 
742
} /* End GotoDeepestLegalDirectory */
 
743
 
 
744
/*---------------------------------------------------------------------------*
 
745
 
 
746
        UpdateLists(fcw)
 
747
 
 
748
        This routine resets the information displayed in a FileChooser
 
749
        widget by doing the following:
 
750
        1. It changes the cursor to the value of the "busyCursor" resource.
 
751
        2. The old directory manager (FCDirMgr(fcw)) is closed and a
 
752
           new one opened based on the value of FCCurrentDirectory(fcw).
 
753
        3. Any old string arrays are freed, and any existing directory
 
754
           menu is destroyed.
 
755
        4. A new array of strings (FCFileNames(fcw)) is allocated and filled
 
756
           with the names of the files in the directory, then this array
 
757
           is used to set what is displayed in the FCFileList(fcw) widget.
 
758
        5. A new array of strings (FCDirNames(fcw)) is allocated and filled
 
759
           with the names of the ancestor directories. These are also used
 
760
           to create a new FCDirMenu(fcw), and the label FCDirMenuButton(fcw)
 
761
           is set to the name of the directory.
 
762
        6. Finally, the cursor is restored.
 
763
 
 
764
 *---------------------------------------------------------------------------*/
 
765
 
 
766
static void
 
767
UpdateLists(fcw)
 
768
XfwfFileChooserWidget fcw;
 
769
{
 
770
    int i,count;
 
771
    char *dir,*start;
 
772
    DirEntry *dir_entry;
 
773
    char temp[MAXPATHLEN + 2];
 
774
    Widget menuItem;
 
775
 
 
776
    if (XtIsRealized((Widget)fcw)) {
 
777
        /* This is puke-ola. */
 
778
        XDefineCursor(XtDisplay(fcw),XtWindow(fcw),FCBusyCursor(fcw));
 
779
        XDefineCursor(XtDisplay(fcw),XtWindow(FCFileList(fcw)),
 
780
                      FCBusyCursor(fcw));
 
781
        XDefineCursor(XtDisplay(fcw),XtWindow(FCDirMenuButton(fcw)),
 
782
                      FCBusyCursor(fcw));
 
783
        XFlush(XtDisplay(fcw));
 
784
    }
 
785
    if (FCDirMgr(fcw))
 
786
        DirectoryMgrClose(FCDirMgr(fcw));
 
787
    FCDirMgr(fcw) = DirectoryMgrSimpleOpen(FCCurrentDirectory(fcw),
 
788
                                           FCSortMode(fcw),FCPattern(fcw));
 
789
 
 
790
    /* Throw away old info */
 
791
    if (FCFileNames(fcw) != NULL) {
 
792
        for (i = 0; i < FCNumFileNames(fcw); i++)
 
793
            XtFree(FCFileNames(fcw)[i]);
 
794
        XtFree((char *)FCFileNames(fcw));
 
795
    }
 
796
    if (FCDirNames(fcw) != NULL) {
 
797
        for (i = 0; i < FCNumDirNames(fcw); i++)
 
798
            XtFree(FCDirNames(fcw)[i]);
 
799
        XtFree((char *)FCDirNames(fcw));
 
800
    }
 
801
    if (FCDirMenu(fcw) != NULL)
 
802
        XtDestroyWidget(FCDirMenu(fcw));
 
803
 
 
804
    /* Count how many files and dirs we have now */
 
805
    FCNumFileNames(fcw) = DirectoryMgrFilteredCount(FCDirMgr(fcw));
 
806
    FCNumDirNames(fcw) = 1;
 
807
    for (dir=FCCurrentDirectory(fcw)+1; *dir != '\0'; dir++) {
 
808
        if (*dir == '/') 
 
809
            FCNumDirNames(fcw) += 1;
 
810
    }
 
811
 
 
812
    /* Make the array of filenames and set the fileList widget */
 
813
    FCFileNames(fcw) = (char **)XtCalloc(FCNumFileNames(fcw)+1,sizeof(char *));
 
814
    for (i=0; i < FCNumFileNames(fcw); i++) {
 
815
        dir_entry = DirectoryMgrNextEntry(FCDirMgr(fcw));
 
816
        if (dir_entry == NULL)
 
817
            XtError("Inconsistent Directory");
 
818
        strcpy(temp,DirEntryFileName(dir_entry));
 
819
        if (DirEntryIsDir(dir_entry))
 
820
            strcat(temp,"/");
 
821
        else if (DirEntryIsBrokenLink(dir_entry))
 
822
            strcat(temp," X");
 
823
        else if (DirEntryIsDirectoryLink(dir_entry))
 
824
            strcat(temp,"/");
 
825
        else if (DirEntryIsSymLink(dir_entry))
 
826
            strcat(temp," @");
 
827
        FCFileNames(fcw)[i] = XtNewString(temp);
 
828
    }
 
829
    FCFileNames(fcw)[i] = NULL;
 
830
    XawListChange(FCFileList(fcw),FCFileNames(fcw),0,0,True);
 
831
 
 
832
    /* Make the array of dirnames and build a new dirMenu widget */
 
833
    FCDirNames(fcw) = (char **)XtCalloc(FCNumDirNames(fcw)+1,sizeof(char *));
 
834
    FCDirNames(fcw)[0] = XtNewString("/");
 
835
    FCDirMenu(fcw) = XtCreatePopupShell(FC_DIR_MENU_NAME,simpleMenuWidgetClass,
 
836
                                        (Widget)fcw,NULL,0);
 
837
    menuItem = XtCreateManagedWidget("/",smeBSBObjectClass,FCDirMenu(fcw),
 
838
                                     NULL,0);
 
839
    XtAddCallback(menuItem,XtNcallback,DirectoryCallback,(XtPointer)0);
 
840
    start = FCCurrentDirectory(fcw);
 
841
    for (i = 1; i < FCNumDirNames(fcw); i++) {
 
842
        while (*start != '\0' && *start == '/')
 
843
            start += 1;
 
844
        count = 0;
 
845
        while (*start != '\0' && *start != '/')
 
846
            temp[count++] = *start++;
 
847
        temp[count] = '\0';
 
848
        FCDirNames(fcw)[i] = XtNewString(temp);
 
849
        menuItem = XtVaCreateManagedWidget("dirMenuItem",smeBSBObjectClass,
 
850
                        FCDirMenu(fcw),
 
851
                        XtNlabel, temp,
 
852
                        NULL);
 
853
        XtAddCallback(menuItem,XtNcallback,DirectoryCallback,(XtPointer)i);
 
854
    }
 
855
    XtVaSetValues(FCDirMenuButton(fcw), XtNlabel,FCCurrentDirectory(fcw), NULL);
 
856
    if (XtIsRealized((Widget)fcw)) {
 
857
        XUndefineCursor(XtDisplay(fcw),XtWindow(fcw));
 
858
        XUndefineCursor(XtDisplay(fcw),XtWindow(FCFileList(fcw)));
 
859
        XUndefineCursor(XtDisplay(fcw),XtWindow(FCDirMenuButton(fcw)));
 
860
    }
 
861
} /* End UpdateLists */
 
862
 
 
863
 
 
864
static void Chdir(fcw)
 
865
XfwfFileChooserWidget fcw;
 
866
{
 
867
    GotoDeepestLegalDirectory(fcw);
 
868
    ChildrenUpdate(fcw);
 
869
} /* End Chdir */
 
870
 
 
871
/*---------------------------------------------------------------------------*
 
872
 
 
873
                    E X T E R N A L    R O U T I N E S
 
874
 
 
875
 *---------------------------------------------------------------------------*/
 
876
 
 
877
void
 
878
XfwfFileChooserChangeDirectory(fcw,dir)
 
879
XfwfFileChooserWidget fcw;
 
880
char *dir;
 
881
{
 
882
    strcpy(FCCurrentDirectory(fcw),dir);
 
883
    Chdir(fcw);
 
884
} /* End XfwfFileChooserChangeDirectory */
 
885
 
 
886
void
 
887
XfwfFileChooserRefresh(fcw)
 
888
XfwfFileChooserWidget fcw;
 
889
{
 
890
    XfwfFileChooserChangeDirectory(fcw,".");
 
891
} /* End XfwfFileChooserRefresh */
 
892
 
 
893
char *
 
894
XfwfFileChooserCurrentDirectory(fcw)
 
895
XfwfFileChooserWidget fcw;
 
896
{
 
897
    return(FCCurrentDirectory(fcw));
 
898
} /* End XfwfFileChooserCurrentDirectory */
 
899
 
 
900
char *
 
901
XfwfFileChooserCurrentFile(fcw)
 
902
XfwfFileChooserWidget fcw;
 
903
{
 
904
    return(FCCurrentFile(fcw));
 
905
} /* End XfwfFileChooserCurrentFile */
 
906