1 /*****************************************************************************
2  ** File          : menus.c                                                 **
3  ** Purpose       : Create, and handle the pull down menus                  **
4  ** Author        : Edward Groenendaal                                      **
5  ** Date          : 18th Feb 1991                                           **
6  ** Documentation : Xdtm Design Folder                                      **
7  ** Related Files :                                                         **
8  ** Changes       : 18-04-92, Edward Groenendaal                            **
9  **                 Added #if NeedFunctionPrototypes stuff                  **
10  **                 June 20, 1992, Ramon Santiago                           **
11  **                 Changed all XtCreate calls to XtVaCreate calls.         **
12  **                 Changed all caddr_t to XtPointer.                       **
13  **                 Removed some lint.                                      **
14  *****************************************************************************/
15 
16 #include "xdtm.h"
17 #include "menus.h"
18 #include "parse.h"  /* Get type for process_list */
19 #include <stdio.h>
20 #include <unistd.h> /* for R_OK */
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <X11/Xaw/MenuButton.h>
24 #include <X11/Xaw/SimpleMenu.h>
25 #include <X11/Xaw/SmeBSB.h>
26 #include <X11/Xaw/SmeLine.h>
27 
28 #include "Xedw/XedwList.h"
29 #include "Xedw/XedwForm.h"
30 #include "bitmaps/Tick"
31 #include "bitmaps/EmptyTick"
32 
33 extern ProcessList *process_list;
34 
35 static MenuContents fileMenuStrings[] = {
36   { "about",     "About Xdtm...",  About,     noflag },
37   { "help",      "Help",           Help,      noflag },
38   {  LINE,        NULL,            0,         noflag },
39   { "info",	 "Info",           Getinfo,   noflag },
40   { "listprocs", "List Processes", Listprocs, noflag },
41   {  LINE,        NULL,            0,         noflag },
42   { "new",       "New File",       New,       noflag },
43   { "duplicate", "Duplicate File", Duplicate, noflag },
44   {  LINE,        NULL,            0,         noflag },
45   { "copy",      "Copy files",     Copy,      noflag },
46   { "move",      "Move files",     Move,      noflag },
47   { "trash",     "Delete files",   Trash,     noflag },
48   {  LINE,        NULL,            0,         noflag },
49   { "reload",    "Reload config file", Reload, noflag},
50   {  LINE,        NULL,            0,         noflag },
51   { "quit",      "Quit Program",   Quit,      noflag },
52 };
53 
54 static MenuContents optionMenuStrings[] = {
55   { "dirfirst",       "Directories first", Dirfirst,       flagged },
56 #ifndef TRUE_SYSV
57   { "followsymlinks", "Follow Sym Links",  FollowSymLinks, flagged },
58 #endif
59   { "usedotspec",     "Use . Spec",        Usedotspec,     flagged },
60   { "usedotdotspec",  "Use .. Spec",       Usedotdotspec,  flagged },
61   {  LINE,             NULL,               0,              flagged },
62   { "silentsel",      "Silent Selection",  Silentsel,      flagged },
63 };
64 
65 static MenuContents viewMenuStrings[] = {
66   { "icons",    "Show Icons",     Icons,   flagged },
67   { "short",    "No Icons",       Short,   flagged },
68   {  LINE,       NULL,            0,       flagged },
69   { "long",     "Long Listing",   Long,    flagged },
70   { "options",  "Options",        Options, flagged },
71 };
72 
73 static MenuContents selectionMenuStrings[] = {
74   { "map",      "Map Program over Files",     Map,    noflag },
75   { "select",   "Select Files by Template",   Select, noflag },
76 };
77 
78 Cardinal fileMenuSize   = sizeof(fileMenuStrings)   /
79                                 sizeof(fileMenuStrings[0]);
80 Cardinal optionMenuSize = sizeof(optionMenuStrings) /
81                                 sizeof(optionMenuStrings[0]);
82 Cardinal viewMenuSize   = sizeof(viewMenuStrings)   /
83                                 sizeof(viewMenuStrings[0]);
84 Cardinal selectionMenuSize   = sizeof(selectionMenuStrings)   /
85                                 sizeof(selectionMenuStrings[0]);
86 
87 public Pixmap tick, emptytick;
88 public Widget menuBar;
89 
90 public Icon_mode current_mode;
91 
92 /* external and forward functions definitions */
93 #if NeedFunctionPrototypes
94   extern void button_selected(Widget, Cardinal, XtPointer);
95   extern void changestate(Boolean);
96   public  void createMenu(Widget, MenuContents[], Cardinal, void (*)(Widget, Cardinal, XtPointer) );
97   extern Boolean directoryManagerNewDirectory(String);
98   extern void displayfile(String, String, String, XtGrabKind);
99   extern void doubleclick_dialog(String, String);
100   extern String getfilename(String);
101   extern void listoption_dialog(void);
102   extern void map_dialog(Boolean);
103   private void menuSelect(Widget, Cardinal, XtPointer);
104   extern void newfile_dialog(Boolean, String, Boolean);
105   extern void popup_process_list(void);
106   extern void loadConfig(void);
107   extern void quit_dialog(void);
108   extern void setCursor(Cursor);
109 #else
110   extern void button_selected();
111   extern void changestate();
112   public  void createMenu();
113   extern Boolean directoryManagerNewDirectory();
114   extern void displayfile();
115   extern void doubleclick_dialog();
116   extern String getfilename();
117   extern void listoption_dialog();
118   extern void map_dialog();
119   private void menuSelect();
120   extern void newfile_dialog();
121   extern void popup_process_list();
122   extern void loadConfig();
123   extern void quit_dialog();
124   extern void setCursor();
125 #endif
126 
127 /*****************************************************************************
128  *                        createMenuWidgets                                  *
129  *****************************************************************************/
createMenuWidgets(w)130 public void createMenuWidgets(w)
131 Widget w;
132 {
133   /* This procedure creates the widgets for the menu bar.
134    * It's 4:41 in the morning, I'm tired, but the work must go on..
135    * so it's time to smile :-) Always look on the bright side of life...
136    */
137 
138   Widget fileMenuButton, optionMenuButton, viewMenuButton, selectionMenuButton;
139   Widget fileMenu, optionMenu, viewMenu, selectionMenu;
140 
141   menuBar =
142     XtVaCreateManagedWidget(
143         "menuBar",
144 	xedwFormWidgetClass,
145 	w,
146 	    XtNrubberWidth,  False,
147 	    XtNrubberHeight, False,
148 	    XtNborderWidth,      0,
149 	    XtNtop,     XtChainTop,
150 	    XtNbottom,  XtChainBottom,
151 	    XtNleft,    XtChainLeft,
152 	    XtNright,   XtChainRight,
153 	    NULL ) ;
154 
155   fileMenuButton =
156     XtVaCreateManagedWidget(
157         "fileMenuButton",
158         menuButtonWidgetClass,
159 	menuBar,
160 	    XtNhighlightThickness, 0,
161 	    XtNborderWidth,        0,
162 	    XtNmenuName,  "fileMenu",
163 	    XtNlabel,         "File",
164 	    XtNvertDistance,       0,
165 	    NULL ) ;
166 
167   optionMenuButton =
168     XtVaCreateManagedWidget(
169         "optionMenuButton",
170 	menuButtonWidgetClass,
171 	menuBar,
172 	    XtNhighlightThickness, 0,
173 	    XtNborderWidth,        0,
174 	    XtNmenuName,         "optionMenu",
175 	    XtNlabel,               "Options",
176 	    XtNfromHoriz,      fileMenuButton,
177 	    XtNvertDistance,                0,
178 	    NULL ) ;
179 
180   viewMenuButton =
181     XtVaCreateManagedWidget(
182         "viewMenuButton",
183 	menuButtonWidgetClass,
184 	menuBar,
185 	    XtNhighlightThickness, 0,
186 	    XtNborderWidth,        0,
187 	    XtNmenuName,        "viewMenu",
188 	    XtNlabel,               "View",
189 	    XtNfromHoriz, optionMenuButton,
190 	    XtNvertDistance,       0,
191 	    NULL ) ;
192 
193   selectionMenuButton =
194     XtVaCreateManagedWidget(
195         "selectionMenuButton",
196 	menuButtonWidgetClass,
197 	menuBar,
198 	    XtNhighlightThickness, 0,
199 	    XtNborderWidth,        0,
200 	    XtNmenuName,        "selectionMenu",
201 	    XtNlabel,               "Selection",
202 	    XtNfromHoriz, viewMenuButton,
203 	    XtNvertDistance,       0,
204 	    NULL ) ;
205 
206   fileMenu =
207     XtVaCreatePopupShell(
208         "fileMenu",
209 	simpleMenuWidgetClass,
210 	fileMenuButton,
211 	    NULL ) ;
212 
213   optionMenu =
214     XtVaCreatePopupShell(
215         "optionMenu",
216 	simpleMenuWidgetClass,
217 	optionMenuButton,
218 	    NULL ) ;
219 
220   viewMenu =
221     XtVaCreatePopupShell(
222         "viewMenu",
223 	simpleMenuWidgetClass,
224 	viewMenuButton,
225 	    NULL ) ;
226 
227   selectionMenu =
228     XtVaCreatePopupShell(
229         "selectionMenu",
230 	simpleMenuWidgetClass,
231 	selectionMenuButton,
232 	    NULL ) ;
233 
234   tick =
235     XCreateBitmapFromData(
236         XtDisplay(w),
237 	RootWindowOfScreen(XtScreen(w)),
238 	tick_bits, tick_width, tick_height);
239 
240   emptytick =
241     XCreateBitmapFromData(
242         XtDisplay(w),
243 	RootWindowOfScreen(XtScreen(w)),
244 	EmptyTick_bits, EmptyTick_width, EmptyTick_height);
245 
246   /* Default long listing options */
247 
248   current_mode.options = (char)app_data.options;
249 
250   /* create the menu panes from the arrays defined at the top of this file. */
251 
252   createMenu(fileMenu, fileMenuStrings, fileMenuSize, menuSelect);
253 
254   createMenu(optionMenu, optionMenuStrings, optionMenuSize, menuSelect);
255 
256   createMenu(viewMenu, viewMenuStrings, viewMenuSize, menuSelect);
257 
258   createMenu(selectionMenu, selectionMenuStrings, selectionMenuSize,
259 	     menuSelect);
260 
261 }
262 
263 
264 /*****************************************************************************
265  *                                createMenu                                 *
266  *****************************************************************************/
createMenu(menu,menuStrings,menuSize,function)267 public void createMenu(menu, menuStrings, menuSize, function)
268 Widget menu;
269 MenuContents menuStrings[];
270 Cardinal menuSize;
271 void (*function)();
272 {
273   /* Given a MenuContents stucture, the number of entries and a function
274    * that should be called when that pane is pressed, this procedure
275    * creates the menu panes for the menu widget 'menu'
276    */
277 
278   Widget menuEntry;
279   Cardinal i, n;
280   Arg arglist[3];
281 
282   for ( n = 0 ; n < menuSize ; n++ )
283     {
284       MenuContents entry ;
285       String widgetname ;
286       entry = menuStrings[n] ;
287       widgetname = entry.paneName ;
288 
289       if (!strcmp(LINE, widgetname))
290 	{
291 	  menuEntry =
292 	    XtVaCreateManagedWidget(
293 	        widgetname,
294 		smeLineObjectClass,
295 		menu,
296 		    NULL ) ;
297 	}
298       else
299 	{
300 	  i = 0;
301 	  XtSetArg(arglist[i], XtNlabel, entry.paneLabel); i++;
302 	  if (entry.set == flagged)
303 	    {
304 	      XtSetArg(arglist[i], XtNleftMargin, (tick_width*1.5)); i++;
305 	      if ((entry.paneNumber == current_mode.mode) ||
306 		  ((entry.paneNumber == Dirfirst) && app_data.dirfirst) ||
307 #ifndef TRUE_SYSV
308 		  ((entry.paneNumber == FollowSymLinks) && app_data.followsymlinks) ||
309 #endif
310 		  ((entry.paneNumber == Usedotspec) && app_data.usedotspec) ||
311 		  ((entry.paneNumber == Usedotdotspec) && app_data.usedotdotspec) ||
312 		  ((entry.paneNumber == Silentsel) && app_data.silentsel))
313 		{
314 		  XtSetArg(arglist[i], XtNleftBitmap, tick); i++;
315 		}
316 	      else
317 		{
318 		  XtSetArg(arglist[i], XtNleftBitmap, None); i++;
319 		}
320 	    }
321 
322 	  menuEntry =
323 	    XtCreateManagedWidget(
324 	        widgetname,
325 		smeBSBObjectClass,
326 		menu,
327 	        arglist,
328 		i ) ;
329 #if 0
330 	  menuEntry =
331 	    XtVaCreateManagedWidget(
332 	        widgetname,
333 		smeBSBObjectClass,
334 		menu,
335 		    XtNlabel, entry.paneLabel,
336 		    XtNleftMargin, ((entry.set == flagged) ? (tick_width*1.5) : 4),
337 		    XtNleftBitmap, ((entry.set == flagged) &&
338 				    (entry.paneNumber == current_mode.mode) ? tick : None),
339 		    NULL ) ;
340 #endif
341 	  if (entry.paneNumber == current_mode.mode && entry.set == flagged)
342 	    current_mode.w = menuEntry;
343 
344 	  XtAddCallback(menuEntry, XtNcallback, function,
345 			(XtPointer)entry.paneNumber);
346 	}
347     }
348 }
349 
350 /*****************************************************************************
351  *                              menuSelect                                   *
352  *****************************************************************************/
menuSelect(w,paneNumber,rubbish)353 private void menuSelect(w, paneNumber, rubbish)
354 Widget w;
355 Cardinal paneNumber;
356 XtPointer rubbish;
357 {
358   /* This procedure is called when a pane is pressed in any of the main
359    * three pull down menus.
360    *
361    * - Takes the paneNumber of the pane selected. Rest is discarded.
362    */
363   extern String cwd;
364   extern Widget directoryManager;
365 
366   XedwListReturnStruct *highlighted;
367   String filename, fullname, level;
368   struct stat filestatus;
369 
370   switch( paneNumber )   /* Which pane was selected */
371     {
372       case About :       /* display about dialog */
373 	level = XtMalloc (sizeof(char) * 40);
374 	sprintf(level, "The X Desktop Manager Version %d.%d",
375 		RELEASE, PATCHLEVEL);
376 	alert_dialog(level, "bug-reports: rjs@pencom.com\n\
377 or         : Lionel.Mallet@sophia.inria.fr", NULL);
378       break ;
379 
380       case Help :        /* If help file is readable show it */
381 	if (access(help_file, R_OK) == 0)
382 	  displayfile(help_file, NULL, "X Desktop Manager Help", XtGrabNone);
383 	else
384 	  alert_dialog("Help file not found at", help_file, "Cancel");
385       break ;
386 
387       case New :         /* Create a newfile */
388 	newfile_dialog(False, NULL, False);
389       break ;
390 
391       case Duplicate :   /* Find out whether highlighted file is a regular file or a directory */
392 	highlighted = XedwListShowCurrent(directoryManager);
393 	if (highlighted->xedwList_index != XDTM_LIST_NONE)
394 	  {
395 	    if (highlighted->next != NULL)
396 	      alert_dialog("You can only duplicate", "one file at a time",
397 			   "Cancel");
398 	    else
399 	      {
400 		filename = getfilename(highlighted->string);
401 		fullname=(String) XtMalloc((strlen(filename)+strlen(cwd)+3) *
402 					   sizeof(char));
403 		strcpy(fullname, cwd);
404 		if (strcmp(cwd, "/") != 0)
405 		  strcat(fullname, "/");
406 		strcat(fullname, filename);
407 		if (stat(fullname, &filestatus) == -1)
408 		  {
409 		    fprintf(stderr,"xdtm: ARRRGGHHH stat error\n");
410 		  }
411 		else
412 		  {
413 		    if ((filestatus.st_mode & S_IFMT) == S_IFDIR)
414 		      /* Is a directory */
415 		      newfile_dialog(True, filename, True);
416 		    else if ((filestatus.st_mode & S_IFMT) == S_IFREG)
417 		      newfile_dialog(True, filename, False);
418 		    else
419 		      alert_dialog("Sorry, that file can not", "be duplicated",
420 				   "Cancel");
421 		  }
422 		XtFree((char *)fullname);
423 	      }
424 	  }
425 	else
426 	  fprintf(stderr, "Error: Duplicate selected when should have been disabled\n");
427 	XedwListFreeCurrent(highlighted);
428       break ;
429 
430       case Getinfo :
431 	highlighted = XedwListShowCurrent(directoryManager);
432 	if (highlighted->xedwList_index != XDTM_LIST_NONE)
433 	  {
434 	    if (highlighted->next != NULL)
435 	      alert_dialog("You can get info on only", "one file at a time",
436 			   "Cancel");
437 	    else
438 	      {
439 		filename = getfilename(highlighted->string);
440 		fullname=(String) XtMalloc((strlen(filename)+strlen(cwd)+3) *
441 					   sizeof(char));
442 		strcpy(fullname, cwd);
443 		if (strcmp(cwd, "/") != 0)
444 		  strcat(fullname, "/");
445 		strcat(fullname, filename);
446 		if (stat(fullname, &filestatus) == -1)
447 		  {
448 		    fprintf(stderr,"xdtm: ARRRGGHHH stat error\n");
449 		  }
450 		else
451 		  {
452 		    doubleclick_dialog(filename,cwd);
453 		  }
454 		XtFree((char *)fullname);
455 	      }
456 	  }
457 	else
458 	  fprintf(stderr,
459 		  "Error: Info selected when should have been disabled\n");
460 	XedwListFreeCurrent(highlighted);
461       break ;
462 
463       case Listprocs:
464 	popup_process_list();
465       break;
466 
467       case Copy:
468 	/* FALL THROUGH */
469 
470       case Move:
471 	/* FALL THROUGH */
472 
473       case Trash:	/* Call button press with it */
474 	button_selected(w, paneNumber, 0);
475       break;
476 
477     case Reload:  /* Reload config file */
478         loadConfig();
479 	directoryManagerNewDirectory(cwd);
480 	selectionChange(w, 0, NULL);
481 	break;
482 
483     case Quit:    /* Quit the program.. maybe */
484 	if (app_data.confirmaction || process_list)
485 	  quit_dialog();
486 	else
487 	  exit(0);
488 	break ;
489 
490     case Dirfirst: /* Change to dirsfirst display option */
491 	app_data.dirfirst = !app_data.dirfirst;
492 	XtVaSetValues(w, XtNleftBitmap, (app_data.dirfirst ? tick : None),
493 		      NULL);
494 	directoryManagerNewDirectory(cwd);
495 	changestate(False);  /* implicitly deslecting dirman selections */
496 	break;
497 
498 #ifndef TRUE_SYSV
499     case FollowSymLinks: /* Change to followsymlinks display option */
500 	app_data.followsymlinks = !app_data.followsymlinks;
501 	XtVaSetValues(w, XtNleftBitmap, (app_data.followsymlinks ? tick : None),
502 		      NULL);
503 	directoryManagerNewDirectory(cwd);
504 	changestate(False);  /* implicitly deslecting dirman selections */
505 	break;
506 #endif
507 
508     case Usedotspec: /* Change to usedotspec display option */
509 	app_data.usedotspec = !app_data.usedotspec;
510 	XtVaSetValues(w, XtNleftBitmap, (app_data.usedotspec ? tick : None),
511 		      NULL);
512 	directoryManagerNewDirectory(cwd);
513 	changestate(False);  /* implicitly deslecting dirman selections */
514 	break;
515 
516     case Usedotdotspec: /* Change to usedotdotspec display option */
517 	app_data.usedotdotspec = !app_data.usedotdotspec;
518 	XtVaSetValues(w, XtNleftBitmap, (app_data.usedotdotspec ? tick : None),
519 		      NULL);
520 	directoryManagerNewDirectory(cwd);
521 	changestate(False);  /* implicitly deslecting dirman selections */
522 	break;
523 
524     case Silentsel: /* Chnge to silentsel appman option */
525 	app_data.silentsel = !app_data.silentsel;
526 	XtVaSetValues(w, XtNleftBitmap, (app_data.silentsel ? tick : None),
527 		      NULL);
528 	break;
529 
530     case Icons:    /* Change to icon mode */
531 	if (current_mode.mode != Icons)
532 	{
533 	    XtVaSetValues( current_mode.w, XtNleftBitmap, None, NULL ) ;
534 	    XtVaSetValues( w, XtNleftBitmap, tick, NULL ) ;
535 	    current_mode.w = w;
536 	    current_mode.mode = Icons;
537 	    XtVaSetValues(
538 			  directoryManager,
539 			  XtNleftBitmap, tick,
540 			  XtNshowIcons,     True,
541 			  XtNrowSpacing,      10,
542 			  XtNforceColumns, False,
543 			  XtNdefaultColumns,   2,
544 			  NULL ) ;
545 	    directoryManagerNewDirectory(cwd);
546 	    changestate(False);  /* implicitly deslecting dirman selections */
547 	}
548 	break;
549 
550     case Short:    /* Change to short listing mode */
551 	if (current_mode.mode != Short)
552 	{
553 	    XtVaSetValues( current_mode.w, XtNleftBitmap, None, NULL ) ;
554 	    XtVaSetValues( w, XtNleftBitmap, tick, NULL ) ;
555 	    current_mode.w = w;
556 	    current_mode.mode = Short;
557 	    XtVaSetValues(
558 			  directoryManager,
559 			  XtNshowIcons,    False,
560 			  XtNrowSpacing,       5,
561 			  XtNforceColumns, False,
562 			  XtNdefaultColumns,   2,
563 			  NULL ) ;
564 	    directoryManagerNewDirectory(cwd);	/* To be consistent */
565 	    changestate(False);  /* This implicitly deselects the selection
566 				    in the dirman. */
567 	}
568 	break ;
569 
570     case Long:    /* change to long listing mode */
571 	if (current_mode.mode != Long)
572 	{
573 	    XtVaSetValues( current_mode.w, XtNleftBitmap, None, NULL ) ;
574 	    XtVaSetValues( w, XtNleftBitmap, tick, NULL ) ;
575 	    current_mode.w = w;
576 	    current_mode.mode = Long;
577 	    XtVaSetValues(
578 			  directoryManager,
579 			  XtNshowIcons,   False,
580 			  XtNrowSpacing,      5,
581 			  XtNforceColumns, True,
582 			  XtNdefaultColumns,  1,
583 			  NULL ) ;
584 	    directoryManagerNewDirectory(cwd);	   /* To be consistent */
585 	    changestate(False);  /* This was where the error was in leaving
586 				    things in 'selected mode' in the menus
587 				    and trash/copy/move. */
588 	}
589 	break ;
590 
591     case Options:	/* allow changes to long listing format. */
592 	listoption_dialog();
593 	break;
594 
595     case Map:    /* Map program over files */
596 	map_dialog(True);
597 	break;
598 
599     case Select: /* Select files via RE template, uses same dilaog as map,
600 		     except with different resources. */
601 	map_dialog(False);
602 	break;
603 
604       default:
605 	fprintf(stderr, "Menu option number %d not supported\n", paneNumber);
606       break;
607     }
608 }
609 
610