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