1 char copyright[]=
2 "xbmbrowser Version 5.0 (c) Copyright Ashley Roll and Anthony Thyssen.";
3 /*
4 *****************************************************************************
5 ** FILE: xbmbrowser.c
6 **
7 ** xbmbrowser is Public Domain. However it, and all the code still belong to me.
8 ** I do, however grant permission for you to freely copy and distribute it on
9 ** the condition that this and all other copyright notices remain unchanged in
10 ** all distributions.
11 **
12 ** This software comes with NO warranty whatsoever. I therefore take no
13 ** responsibility for any damages, losses or problems that the program may
14 ** cause.
15 **                                     Anthony Thyssen and Ashley Roll
16 *****************************************************************************
17 */
18 
19 #define MAIN
20 #include "xbmbrowser.h"
21 #include "patchlevel.h"
22 
23 /* application icon */
24 #include "icon.xbm"
25 
26 /* Tick Box Symbols */
27 #include "tickbox_off.xbm"
28 #include "tickbox_on.xbm"
29 
30 /* File Type Symbols */
31 #include "filesyms/unknown.xbm"
32 #include "filesyms/dir.xbm"
33 #include "filesyms/dirup.xbm"
34 #include "filesyms/dirlink.xbm"
35 #include "filesyms/dirbad.xbm"
36 #include "filesyms/file.xbm"
37 #include "filesyms/text.xbm"
38 #include "filesyms/binary.xbm"
39 #include "filesyms/xbm.xbm"  /* Xbm and Xpm do not really need these symbols */
40 #include "filesyms/xpm.xbm"  /* but are included for completeness, who knows!*/
41 #include "filesyms/xpmbad.xbm"
42 
43 /* mask bitmaps for file symbols */
44 #include "filesyms/dirmask.xbm"
45 #include "filesyms/filemask.xbm"
46 
47 /* Define the width to give the main buttons.
48 ** This width is reduced by the form widget to fit the
49 ** applications real width, but sound be the same for all
50 ** the buttons defined in the button box. */
51 #define  BUTTON_WIDTH 100
52 
53 /* -------------------------- */
54 static Atom  wm_delete_window;      /* insure that delete window works */
55 
56 /* define command line options to change resource settings */
57 static XrmOptionDescRec cmdline_options[] = {
58   /* option      resource      option_type      value */
59   /* command line menu configuration file */
60   {"-config",      "*cmd_rc",       XrmoptionSepArg,  NULL },
61   {"-cf",          "*cmd_rc",       XrmoptionSepArg,  NULL },
62   /* symbol resources */
63   {"-iconsonly",   "*icons_only",   XrmoptionNoArg,  "True"},
64   {"-dir",         "*show_dir",     XrmoptionNoArg,  "True"},
65   {"-xpmbad",      "*show_xpmbad",  XrmoptionNoArg,  "True"},
66   {"-other",       "*show_other",   XrmoptionNoArg,  "True"},
67   /* symbol resources (inverted) */
68   {"-noiconsonly", "*icons_only",   XrmoptionNoArg,  "False"},
69   {"-nodir",       "*show_dir",     XrmoptionNoArg,  "False"},
70   {"-noxpmbad",    "*show_xpmbad",  XrmoptionNoArg,  "False"},
71   {"-noother",     "*show_other",   XrmoptionNoArg,  "False"},
72   /* special resources toggles */
73   {"-solid",       "*solid_bgnd",   XrmoptionNoArg,  "True"},
74   {"-stipple",     "*solid_bgnd",   XrmoptionNoArg,  "False"},
75   {"-label",       "*label_all",    XrmoptionNoArg,  "True"},
76   {"-nolabel",     "*label_all",    XrmoptionNoArg,  "False"},
77   /* recursive directory scan */
78   {"-R",           "*recursive",    XrmoptionNoArg,  "True"},
79   {"-recursive",   "*recursive",    XrmoptionNoArg,  "True"},
80 };
81 
82 /* Unknown is a boolean! value which means it was never set
83 ** by any user resource. Used to calculate a correct default
84 ** later in the main initialization section. */
85 #define Bool_Unset (Boolean)2
86 
87 /* define the applications own resources */
88 #define offset(field)  XtOffsetOf(AppData, field)
89 static XtResource resources[] = {
90   /* res_name  res_class  res_type  var_size
91    *   var_ptr   var_type   default_value   */
92 /* --- configuration resources --- */
93   { "cmd_rc",       "Config",   XtRString, sizeof(char *),
94        offset(cmd_rc), XtRString, (XtPointer) NULL },
95   { "user_rc",      "Config",   XtRString, sizeof(char *),
96        offset(user_rc), XtRString, (XtPointer) USERS_RC },
97   { "library_rc",   "Config",   XtRString, sizeof(char *),
98        offset(library_rc), XtRString, (XtPointer) LIBRARY_RC },
99 /* --- option menu resources --- */
100   /* display style resources */
101   { "solid_bgnd",   XtCBoolean,  XtRBoolean, sizeof(Boolean),
102        offset(solid_bgnd), XtRImmediate,  (XtPointer) Bool_Unset },
103   { "shape_syms",   XtCBoolean,  XtRBoolean, sizeof(Boolean),
104        offset(shape_syms), XtRImmediate,  (XtPointer) Bool_Unset },
105   { "label_all",   XtCBoolean,  XtRBoolean, sizeof(Boolean),
106        offset(label_all), XtRImmediate,   (XtPointer) False },
107   { "label_icons",   XtCBoolean,  XtRBoolean, sizeof(Boolean),
108        offset(label_icons), XtRImmediate, (XtPointer) False },
109   { "label_syms",   XtCBoolean,  XtRBoolean, sizeof(Boolean),
110        offset(label_syms), XtRImmediate,  (XtPointer) False },
111   { "label_dirs",   XtCBoolean,  XtRBoolean, sizeof(Boolean),
112        offset(label_dirs), XtRImmediate,  (XtPointer) False },
113   /* visibility resources */
114   { "icons_only",   "Show",     XtRBoolean, sizeof(Boolean),
115        offset(icons_only), XtRImmediate,  (XtPointer) False },
116   { "show_dir",     "Show",     XtRBoolean, sizeof(Boolean),
117        offset(show_dir), XtRImmediate,    (XtPointer) True },
118   { "show_xpmbad",  "Show",     XtRBoolean, sizeof(Boolean),
119        offset(show_xpmbad), XtRImmediate, (XtPointer) True },
120   { "show_other",   "Show",     XtRBoolean, sizeof(Boolean),
121        offset(show_other), XtRImmediate,  (XtPointer) False },
122   { "show_hidden",  "Show",     XtRBoolean, sizeof(Boolean),
123        offset(show_hidden), XtRImmediate, (XtPointer) False },
124   /* recursive scan resource */
125   { "recursive",   XtCBoolean,  XtRBoolean, sizeof(Boolean),
126        offset(recursive), XtRImmediate,   (XtPointer) False },
127 /* --- Colors --- */
128   /* symbols and bitmap icon colors */
129   { "sym_foreground",  XtCForeground,  XtRPixel, sizeof(Pixel),
130        offset(sym_fg), XtRString, (XtPointer) XtDefaultForeground },
131   { "sym_background",  XtCBackground,  XtRPixel, sizeof(Pixel),
132        offset(sym_bg), XtRString, (XtPointer) XtDefaultBackground },
133   { "icon_foreground",  XtCForeground,  XtRPixel, sizeof(Pixel),
134        offset(icon_fg), XtRString, (XtPointer) XtDefaultForeground },
135   { "icon_background",  XtCBackground,  XtRPixel, sizeof(Pixel),
136        offset(icon_bg), XtRString, (XtPointer) XtDefaultBackground },
137   /* background colors */
138   { "icon_transparent",  XtCBackground,  XtRPixel, sizeof(Pixel),
139        offset(icon_tr), XtRString, (XtPointer) XtDefaultBackground },
140   { "solid_background",  XtCBackground,  XtRPixel, sizeof(Pixel),
141        offset(solid_bg), XtRString, (XtPointer) XtDefaultBackground },
142   { "stipple_background",  XtCBackground,  XtRPixel, sizeof(Pixel),
143        offset(stipple_bg), XtRString, (XtPointer) XtDefaultBackground },
144 };
145 #undef offset
146 
147 /* declare action routines for translations */
148 static XtActionsRec  actions[] = {
149 /* action_name    routine */
150   { "Dir_Return", dir_return },      /* directory dialog return */
151   { "Set_Name",   set_name },        /* set info line for this file */
152   { "Set_Label",  set_label },       /* set general default information */
153   { "Pos_Dir",    pos_dir },         /* Set dir menu's location */
154   { "Pop_Menu",   popup_user_menu }, /* popup user menu (or cd to subdir) */
155   { "Quit",       quit_browser },    /* quit application */
156 };
157 
158 /* translation table (override) for menu (command) widget */
159 static char menu_trans[] =
160   "<EnterWindow>:  highlight() \n\
161    <LeaveWindow>:  reset() \n\
162    <BtnDown>:      Pop_Menu() \n\
163    <BtnDown>(2+): ";  /* this stops double clicks crashing the program */
164 
165 /* translation table for widget displaying the icon images */
166 char icon_trans[] =
167   "<EnterWindow>:  Set_Name() \n\
168    <LeaveWindow>:  Set_Label() \n\
169    <BtnDown>:      Pop_Menu() \n\
170    <BtnDown>(2+): ";  /* this stops double clicks crashing the program */
171 
172 /* translation table (override) for "global" popup anywhere in the iconbox */
173 static char box_trans[] =
174   "<BtnDown>:      Pop_Menu() \n\
175    <BtnDown>(2+): ";  /* this stops double clicks crashing the program */
176 
177 /* translation table (override) for the directory text widget */
178 static char text_trans[] =
179   "<Key>Return:  Dir_Return() \n\
180    Ctrl<Key>M:   Dir_Return() \n\
181    <Btn3Down>:   Pos_Dir() MenuPopup(dirmenu) ";
182 
183 /* translation table for the directory list popup menu */
184 static char list_trans[] =
185    "<Enter>:      Set() \n\
186     <Leave>:      Unset() \n\
187     <BtnMotion>:  Set() \n\
188     <BtnUp>:      MenuPopdown(dirmenu) Notify() Unset()";
189 
190 /* translation table for the transient shell containing the list
191 ** This translation makes the list popdown if the button is released
192 ** outside the window    -- Ashley Roll */
193 static char tshell_trans[] =
194        "<BtnUp>: MenuPopdown(dirmenu)";
195 
196 
197 /* fallback resources -- things required to function at all */
198 static char *fall_back[] = {
199    "XbmBrowser.width:    500",
200    "XbmBrowser.height:   600",
201    "*optmenu*leftMargin: 24",
202    NULL
203 };
204 
205 /* -------------------------- */
206 
usage()207 static void usage()
208 {
209   fprintf(stderr, "%s%s%s%s%s%s%s%s%s%s%s%s",
210     "Usage: xbmbrowser [options...] [directory]\n",
211     "    Where ``directory'' is an directory of icons to display.\n",
212     "    Options can be any standard X toolkit option or...\n",
213     "       -config file     Use the given config file instead\n",
214     "       -solid           Use a solid background and shaped windows\n",
215     "       -stipple         Stripple background and unshaped icons\n",
216     "       -(no)iconsonly   (Don't) Display only the icon images\n",
217     "       -(no)dir         (Don't) Display directories found\n",
218     "       -(no)xpmbad      (Don't) Display Bad X Pixmap Loads\n",
219     "       -(no)other       (Don't) Display other files\n",
220     "       -(no)label       (Don't) Label the displayed icon images\n",
221     "       -R | -recursive  Recursive Scan of all sub-directories\n"
222   );
223   exit(1);
224 }
225 
226 
main(argc,argv)227 main(argc, argv)
228   int argc;
229   char **argv;
230 {
231   XtAppContext appcon;    /* these item only really needed in here */
232   Widget       toplevel;  /* the application widget -- only needed in here */
233 
234   /* Setup the toplevel window */
235   { char title[80];
236 
237     (void) sprintf(title,"XbmBrowser Version %s",PATCHLEVEL);
238     toplevel = XtVaAppInitialize(
239               &appcon, "XbmBrowser",       /* app context, ClassName */
240               cmdline_options,             /* app command line options */
241               XtNumber(cmdline_options),
242               &argc, argv,                 /* command line */
243               fall_back,                   /* Fall back resources */
244               XtNtitle, (XtArgVal)title,
245               NULL);                       /* End Va resource list */
246 
247     XtVaGetApplicationResources(
248               toplevel, &app_data, resources, XtNumber(resources),
249               /* varargs of non-user-defined resources here */
250               NULL );
251 
252     XtAppAddActions( appcon, actions, XtNumber(actions) );
253   }
254 
255   /* collect some extra information */
256   display  = XtDisplay(toplevel);
257   screen   = XtScreen(toplevel);
258   colormap = DefaultColormapOfScreen(screen);
259   depth    = DefaultDepthOfScreen(screen);
260 
261 #if 0
262   /* Color Tests of the display -- Pixmap Debugging */
263   printf("icon: fore=%d, back=%d, trans=%d\n",
264      app_data.icon_fore, app_data.icon_back, app_data.icon_trans );
265 #endif
266 
267   /* If no icon is set by the user -- set a default one */
268   { Pixmap icon;
269 
270     XtVaGetValues(toplevel, XtNiconPixmap, &icon, NULL);
271     if ( icon == None ) {
272       icon = LOAD_BMAP(icon);
273       XtVaSetValues(toplevel, XtNiconPixmap, icon, NULL);
274     }
275   }
276 
277   /* locate the users home directory, and save this for future use */
278   /* required to find rc files where to find user's rc file */
279   { extern char *getenv();
280     (void) strcpy(home_dir, getenv("HOME"));
281     if( strcmp(home_dir,"/") != 0 )
282       (void) strncat(home_dir, "/", MAXNAMLEN);
283   }
284 
285   /* Initialize other substitution strings */
286   dir_name[0]  = '\0';
287   file_name[0] = '\0';
288   base_name[0] = '\0';
289   suffix[0]    = '\0';
290   input[0]     = '\0';
291 
292   /* process any other options leftover -- presumably a directory to cd to */
293   { Boolean opts_done = FALSE, errored = FALSE;
294 
295     while( argc >= 2 && argv[1][0] == '-' && !opts_done ) {
296       if( strcmp(argv[1], "--") == 0 )
297 	opts_done = TRUE;         /* "--" end of options */
298       else {
299 	fprintf(stderr, "Unknown Option: %s\n", argv[1]);
300 
301       }
302       argv++; argc--;
303     }
304     if( errored ) usage();
305     if( argc > 2 ) {
306       fprintf(stderr, "Too many arguments found.\n");
307       usage();
308     }
309     if(argc == 2) {      /* any other argument is a directory name */
310       strcpy(dir_name, argv[1]);  /* don't chdir() yet! */
311     }
312   }
313 
314   /* Initialize user menus from the appropiate RC file */
315   /* Do this before we chdir() into some other directory */
316   { FILE *rc;
317     char rcfile[MAXNAMLEN];
318 
319      menu_global = menu_bitmap = menu_pixmap =
320         menu_directory = menu_other = NULL;
321 
322     /* if a config file is on command line use it */
323     if( app_data.cmd_rc != NULL
324         && (rc = fopen(app_data.cmd_rc, "r")) != (FILE *)NULL  ) {
325       read_user_menus(toplevel, rc, app_data.cmd_rc);
326       fclose(rc);
327     }
328     else if( app_data.cmd_rc != NULL ) {
329       /* We failed to open a config file given on the command line! */
330       fprintf(stderr, "xbmbrowser: Cound not open -config \"%s\"\n",
331                     app_data.cmd_rc );
332       exit(-1);
333     }
334     /* try to find the config file in users home */
335     else if( app_data.user_rc != NULL &&
336              ( sprintf(rcfile, "%s%s", home_dir, app_data.user_rc),
337                (rc = fopen(rcfile, "r")) != (FILE *)NULL ) ) {
338       read_user_menus(toplevel, rc, rcfile);
339       fclose(rc);
340     }
341     /* try the library default config file */
342     else if( app_data.library_rc != NULL
343              && (rc = fopen(app_data.library_rc, "r")) != (FILE *)NULL  ) {
344       read_user_menus(toplevel, rc, app_data.library_rc);
345       fclose(rc);
346     }
347     else {  /* unable to find and load any config file! */
348       fprintf(stderr,"xbmbrowser: Can not find a menu configuration file\n");
349       exit(-1);
350     }
351   }
352 
353   /* CD and Initialize dir_name correctly
354   ** DO NOT call change_dir() now as this will reset the current
355   ** resursive resource setting given by the user on the command line.
356   */
357   if( dir_name[0] != '\0' && chdir(dir_name) != 0 ) {
358     fprintf(stderr,"xbmbrowser: couldn't chdir to '%s'\n",argv[1]);
359     exit(-1);
360   }
361   (void) getcwd(dir_name, MAXNAMLEN);
362   if( strcmp(dir_name,"/") != 0 )
363     (void) strncat(dir_name, "/", MAXNAMLEN);
364 
365   /* copy this as the initial startup directory */
366   strcpy(init_dir, dir_name);
367 
368   /* create the cursors */
369   normalCursor = XCreateFontCursor(display, XC_left_ptr);
370   waitCursor   = XCreateFontCursor(display, XC_watch);
371 
372   /* NOTE: LOAD_BMAP(file) is a marco to creat a X bitmap from bitmap data */
373 
374   /* create tickbox bitmaps for options menu */
375   tickoff = LOAD_BMAP(tickbox_off);
376   tickon  = LOAD_BMAP(tickbox_on);
377 
378   /* load masks first and save them */
379   sym_masks[Dir] = sym_masks[DirUp] = sym_masks[DirLink] =
380      sym_masks[DirBad] = LOAD_BMAP(dirmask);
381   sym_masks[File] = sym_masks[Text] = sym_masks[Binary] =
382      sym_masks[Xbm] = sym_masks[Xpm] = sym_masks[XpmBad] =
383      sym_masks[Unknown] = LOAD_BMAP(filemask);
384 
385   /* Load and save the rest of the file symbols */
386   sym_bmaps[Unknown] = LOAD_BMAP(unknown);
387   sym_bmaps[Dir]     = LOAD_BMAP(dir);
388   sym_bmaps[DirUp]   = LOAD_BMAP(dirup);
389   sym_bmaps[DirLink] = LOAD_BMAP(dirlink);
390   sym_bmaps[DirBad]  = LOAD_BMAP(dirbad);
391   sym_bmaps[File]    = LOAD_BMAP(file);
392   sym_bmaps[Text]    = LOAD_BMAP(text);
393   sym_bmaps[Binary]  = LOAD_BMAP(binary);
394   sym_bmaps[Xbm]     = LOAD_BMAP(xbm);
395   sym_bmaps[Xpm]     = LOAD_BMAP(xpm);
396   sym_bmaps[XpmBad]  = LOAD_BMAP(xpmbad);
397 
398 
399   /* create a paned widget to put everything into */
400   mainpw  = XtVaCreateManagedWidget(
401               "main", panedWidgetClass, toplevel,
402               XtNcursor,(XtArgVal)normalCursor,  /* the default cursour */
403               NULL);
404 
405   /* create buttons and options menu */
406   { Widget form, button, options, optmenu, optitem;
407 
408     /* create form to hold the buttons */
409     form = XtVaCreateManagedWidget(
410               "buttons", formWidgetClass, mainpw,
411               XtNshowGrip,   (XtArgVal)False,
412               XtNskipAdjust, (XtArgVal)True,NULL);
413 
414     /* create the Buttons */
415     mainmenu = XtVaCreateManagedWidget(
416               "mainmenu", commandWidgetClass, form,
417               XtNwidth,      (XtArgVal)BUTTON_WIDTH,
418               NULL);
419     XtOverrideTranslations(mainmenu, XtParseTranslationTable(menu_trans));
420     options = XtVaCreateManagedWidget(
421               "options", menuButtonWidgetClass, form,
422               XtNwidth,      (XtArgVal)BUTTON_WIDTH,
423               XtNfromHoriz,  (XtArgVal)mainmenu,
424               XtNmenuName,   (XtArgVal)"optmenu",
425               NULL);
426     button = XtVaCreateManagedWidget(
427               "rescan", commandWidgetClass, form,
428               XtNwidth,      (XtArgVal)BUTTON_WIDTH,
429               XtNfromHoriz,  (XtArgVal)options,
430               NULL);
431     XtAddCallback(button, XtNcallback, rescan, NULL);
432 
433     button = XtVaCreateManagedWidget(
434               "scan", commandWidgetClass, form,
435               XtNwidth,      (XtArgVal)BUTTON_WIDTH,
436               XtNfromHoriz,  (XtArgVal)button,
437               NULL);
438     XtAddCallback(button, XtNcallback, scan, NULL);
439 
440     /* initialize the solid_bgnd resource is still unset */
441     if ( app_data.solid_bgnd == Bool_Unset )
442       app_data.solid_bgnd = (depth > 1);   /* true if on color display */
443 
444     if ( app_data.shape_syms == Bool_Unset )
445       app_data.shape_syms = app_data.solid_bgnd;  /* true if on color display */
446 
447     /* create the options menu */
448     optmenu = XtVaCreatePopupShell(
449               "optmenu", simpleMenuWidgetClass, options,
450               NULL);
451     /* ----- display style options ----- */
452     optitem = XtVaCreateManagedWidget(
453               "solid_bgnd", smeBSBObjectClass, optmenu,
454               XtNleftBitmap, app_data.solid_bgnd ? tickon : tickoff, NULL);
455     XtAddCallback(optitem, XtNcallback, toggle_option, &app_data.solid_bgnd);
456     optitem = XtVaCreateManagedWidget(
457               "shape_syms", smeBSBObjectClass, optmenu,
458               XtNleftBitmap, app_data.shape_syms ? tickon : tickoff, NULL);
459     XtAddCallback(optitem, XtNcallback, toggle_option, &app_data.shape_syms);
460     optitem = XtVaCreateManagedWidget(
461               "label_all", smeBSBObjectClass, optmenu,
462               XtNleftBitmap, app_data.label_all ? tickon : tickoff, NULL);
463     XtAddCallback(optitem, XtNcallback, toggle_option, &app_data.label_all);
464     optitem = XtVaCreateManagedWidget(
465               "label_icons", smeBSBObjectClass, optmenu,
466               XtNleftBitmap, app_data.label_icons ? tickon : tickoff, NULL);
467     XtAddCallback(optitem, XtNcallback, toggle_option, &app_data.label_icons);
468     optitem = XtVaCreateManagedWidget(
469               "label_syms", smeBSBObjectClass, optmenu,
470               XtNleftBitmap, app_data.label_syms ? tickon : tickoff, NULL);
471     XtAddCallback(optitem, XtNcallback, toggle_option, &app_data.label_syms);
472     optitem = XtVaCreateManagedWidget(
473               "label_dirs", smeBSBObjectClass, optmenu,
474               XtNleftBitmap, app_data.label_dirs ? tickon : tickoff, NULL);
475     XtAddCallback(optitem, XtNcallback, toggle_option, &app_data.label_dirs);
476 
477     /* ----- what is visible options ----- */
478     XtVaCreateManagedWidget("line", smeLineObjectClass, optmenu, NULL);
479     optitem = XtVaCreateManagedWidget(
480               "icons_only", smeBSBObjectClass, optmenu,
481               XtNleftBitmap, app_data.icons_only ? tickon : tickoff, NULL);
482     XtAddCallback(optitem, XtNcallback, toggle_option, &app_data.icons_only);
483     optitem = XtVaCreateManagedWidget(
484               "show_dir", smeBSBObjectClass, optmenu,
485               XtNleftBitmap, app_data.show_dir ? tickon : tickoff, NULL);
486     XtAddCallback(optitem, XtNcallback, toggle_option, &app_data.show_dir);
487     optitem = XtVaCreateManagedWidget(
488               "show_xpmbad", smeBSBObjectClass, optmenu,
489               XtNleftBitmap, app_data.show_xpmbad ? tickon : tickoff, NULL);
490     XtAddCallback(optitem, XtNcallback, toggle_option, &app_data.show_xpmbad);
491     optitem = XtVaCreateManagedWidget(
492               "show_other", smeBSBObjectClass, optmenu,
493               XtNleftBitmap, app_data.show_other ? tickon : tickoff, NULL);
494     XtAddCallback(optitem, XtNcallback, toggle_option, &app_data.show_other);
495     optitem = XtVaCreateManagedWidget(
496               "show_hidden", smeBSBObjectClass, optmenu,
497               XtNleftBitmap, app_data.show_hidden ? tickon : tickoff, NULL);
498     XtAddCallback(optitem, XtNcallback, toggle_option, &app_data.show_hidden);
499 
500     /* ----- recursive scaning of directories ----- */
501     /* this is globally known so change_dir() can reset it */
502     XtVaCreateManagedWidget("line", smeLineObjectClass, optmenu, NULL);
503     recur_opt = XtVaCreateManagedWidget(
504               "recursive", smeBSBObjectClass, optmenu,
505               XtNleftBitmap, app_data.recursive ? tickon : tickoff, NULL);
506     XtAddCallback(recur_opt, XtNcallback, toggle_option, &app_data.recursive);
507   }
508 
509 
510   /* dialogWidget -- show and change the current directory
511   ** NOTE: the actual value for this widget set in change_dir()
512   */
513   dirwidget = XtVaCreateManagedWidget(
514               "directory", dialogWidgetClass, mainpw,
515               XtNlabel,      (XtArgVal)"Current Directory",
516               XtNvalue,      (XtArgVal)dir_name, /* current directory */
517               XtNshowGrip,   (XtArgVal)False,
518               XtNskipAdjust, (XtArgVal)True,
519               NULL);
520   XtOverrideTranslations(XtNameToWidget(dirwidget,"value"),
521               XtParseTranslationTable(text_trans));
522 
523   /* create the dirMenu list widget in a popup shell. */
524   dirmenu = XtVaCreatePopupShell(
525               "dirmenu", transientShellWidgetClass, dirwidget,
526               XtNoverrideRedirect, (XtArgVal)True,
527               XtNallowShellResize, (XtArgVal)True,
528               NULL);
529   XtOverrideTranslations(dirmenu, XtParseTranslationTable(tshell_trans));
530 
531   dirlist = XtVaCreateManagedWidget(
532               "dirlist",listWidgetClass,dirmenu,
533               XtNforceColumns,    True,   /* set the defaults */
534               XtNdefaultColumns,  1,      /* changed later */
535               NULL);
536   XtAddCallback(dirlist, XtNcallback, dir_menu, NULL);
537   XtOverrideTranslations(dirlist, XtParseTranslationTable(list_trans));
538 
539   /* label widget to hold information about the current bitmap */
540   strcpy( label_info, "Loading Bitmaps" );   /* initialize label_info */
541   label = XtVaCreateManagedWidget("label",labelWidgetClass,mainpw,
542               XtNlabel,      (XtArgVal)label_info,
543               XtNshowGrip,   (XtArgVal)False,
544               XtNskipAdjust, (XtArgVal)True,NULL);
545 
546 
547   /* setup the box to hold all the images */
548   { Widget  viewport;
549     int     width;
550 
551     XtVaGetValues(toplevel,XtNwidth,&width,NULL);
552 
553     /* create a viewport widget to stick the images in */
554     viewport = XtVaCreateManagedWidget(
555               "viewport",viewportWidgetClass,mainpw,
556               XtNwidth,(XtArgVal)width,
557               XtNallowHoriz,(XtArgVal)False,
558               XtNallowVert,(XtArgVal)True,
559               XtNshowGrip,(XtArgVal)False,
560               XtNskipAdjust,(XtArgVal)True,NULL);
561 
562     /* create the box widget to put all the icon images in */
563     iconbox = XtVaCreateManagedWidget(
564               "iconbox",      boxWidgetClass,  viewport,
565               XtNwidth,       width,
566               XtNorientation, (XtArgVal)XtorientVertical,
567               XtNfromVert,    (XtArgVal)label,
568               NULL);
569     /* This is currently NOT working -- It stops the file popups!
570     ** All I want is for the global menu to popup on mouse press anywhere
571     ** in the iconbox, but for the normal actions to continue to work
572     ** when mouse button is used on a displays icon or symbol.
573     ** This overrides everything inside the iconbox. Arrgghhh. */
574     XtOverrideTranslations(iconbox, XtParseTranslationTable(box_trans));
575   }
576 
577   /* initialize and set the stipple for the icon box */
578   init_stipple();
579 
580   /* WARNING :- Heavy Magic in progress, Xperts please note....
581   **   We need to Register the appropiate Grab Information for the
582   ** popup_user_menu action routine. This is only needed as we are
583   ** NOT using a MenuButton widget, or the builtin MenuPopup() action
584   ** routine to do the actual popup. It is done this way to allow the
585   ** application to pick the appropriate menu to popup or do a chdir(),
586   ** depending on the type of object the widget is currently
587   ** representing.
588   **                                 --- Anthony Thyssen   2 May 1994
589   */
590   XtRegisterGrabAction(popup_user_menu, True,
591               ButtonPressMask | ButtonReleaseMask,
592               GrabModeAsync, GrabModeAsync);
593 
594   /* scan for the images -- DON'T call change_dir() */
595   scan_images();
596 
597   XtRealizeWidget(toplevel);
598 
599   /* Set the window to call quit() action if `deleted' */
600   XtOverrideTranslations(toplevel,
601               XtParseTranslationTable("<Message>WM_PROTOCOLS:Quit()") );
602   wm_delete_window = XInternAtom(display, "WM_DELETE_WINDOW", False);
603   (void) XSetWMProtocols(display, XtWindow(toplevel), &wm_delete_window, 1);
604 
605   /* start the main event loop */
606   XtAppMainLoop(appcon);
607 }
608