various bug fixes
[wmaker-crm.git] / WPrefs.app / Menu.c
blob2f68f665f3fb502cf2d658f003c1c87efa97ea23
1 /* Menu.c- menu definition
2 *
3 * WPrefs - Window Maker Preferences Program
4 *
5 * Copyright (c) 1998 Alfredo K. Kojima
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
20 * USA.
24 #include "WPrefs.h"
25 #include <assert.h>
26 #include <ctype.h>
28 #include <X11/keysym.h>
30 typedef struct _Panel {
31 WMFrame *frame;
32 char *sectionName;
34 CallbackRec callbacks;
35 WMWindow *win;
37 WMPopUpButton *cmd1P;
38 WMPopUpButton *cmd2P;
40 WMTextField *tit1T;
41 WMTextField *tit2T;
43 WMBrowser *browser;
45 WMFrame *labF;
46 WMTextField *labT;
48 WMFrame *cmdF;
49 WMPopUpButton *cmdP;
51 WMButton *noconfirmB;
53 WMFrame *proF;
54 WMTextField *proT;
55 WMLabel *infoL;
57 WMFrame *pathF;
58 WMTextField *pathT;
59 WMLabel *pathL;
61 WMFrame *shoF;
62 WMTextField *shoT;
63 WMButton *shoB;
65 WMButton *guruB;
67 /**/
68 proplist_t menu;
69 proplist_t editedItem;
71 proplist_t itemClipboard; /* for copy/paste */
73 char capturing; /* shortcut capture */
74 char unsaved; /* if there are unsaved changes */
75 char dontSave;
76 } _Panel;
80 #define ICON_FILE "menus"
84 extern char *OpenMenuGuru(WMWindow *mainWindow);
86 extern Bool AskMenuCopy(WMWindow *wwin);
89 /* must match the indexes of the commands popup */
90 enum {
91 CAddCommand = 0,
92 CAddSubmenu = 1,
93 CAddExternal = 2,
94 CAddWorkspace = 3,
95 CRemove = 4,
96 CCut = 5,
97 CCopy = 6,
98 CPaste = 7
102 enum {
103 CpExec = 0,
104 CpArrange = 1,
105 CpHide = 2,
106 CpShow = 3,
107 CpExit = 4,
108 CpShutdown = 5,
109 CpRestart = 6,
110 CpRestartWM = 7,
111 CpSaveSession = 8,
112 CpClearSession = 9,
113 CpRefresh = 10,
114 CpInfo = 11,
115 CpLegal = 12
118 enum {
119 TNothing,
120 TExec,
121 TSimpleCommand,
122 TRestart,
123 TRestartWM,
124 TExit,
125 TExternalMenu,
126 TWSMenu
131 static void showData(_Panel *panel);
135 static Bool
136 isMenu(proplist_t item)
138 if (PLGetNumberOfElements(item)==1)
139 return True;
141 return PLIsArray(PLGetArrayElement(item, 1));
145 static void
146 splitOpenMenuParameter(char *str, char **dirs, char **prog)
148 char *p;
150 if (!(p = strstr(str, " WITH "))) {
151 *dirs = wstrdup(str);
152 *prog = NULL;
153 } else {
154 int i, j;
156 i = strlen(str);
157 j = strlen(p);
158 *dirs = wmalloc(i-j+1);
159 strncpy(*dirs, str, i-j+1);
160 (*dirs)[i-j] = 0;
162 p += 6;
163 while (isspace(*p)) p++;
164 if (*p!=0) {
165 *prog = wmalloc(j);
166 strcpy(*prog, p);
167 } else {
168 *prog = NULL;
174 static void
175 changeItemTitle(proplist_t item, char *title)
177 proplist_t tmp;
179 tmp = PLGetArrayElement(item, 0);
180 PLRelease(tmp);
181 PLRemoveArrayElement(item, 0);
182 PLInsertArrayElement(item, title?PLMakeString(title):PLMakeString(""), 0);
186 static void
187 removeParameter(proplist_t item)
189 proplist_t tmp;
190 int index;
192 if (strcmp(PLGetString(PLGetArrayElement(item, 1)), "SHORTCUT")==0) {
193 index = 4;
194 } else {
195 index = 2;
197 tmp = PLGetArrayElement(item, index);
198 PLRemoveArrayElement(item, index);
199 if (tmp)
200 PLRelease(tmp);
204 static void
205 changeItemParameter(proplist_t item, char *param)
207 proplist_t tmp;
208 int index;
210 if (strcmp(PLGetString(PLGetArrayElement(item, 1)), "SHORTCUT")==0) {
211 index = 4;
212 } else {
213 index = 2;
215 tmp = PLGetArrayElement(item, index);
216 PLRemoveArrayElement(item, index);
217 PLRelease(tmp);
218 tmp = param?PLMakeString(param):PLMakeString("");
219 PLInsertArrayElement(item, tmp, index);
223 static void
224 changeItemShortcut(proplist_t item, char *shortcut)
226 proplist_t tmp;
228 if (strcmp(PLGetString(PLGetArrayElement(item, 1)), "SHORTCUT")==0) {
229 if (shortcut) {
230 tmp = PLGetArrayElement(item, 2);
231 PLRemoveArrayElement(item, 2);
232 PLRelease(tmp);
233 PLInsertArrayElement(item, PLMakeString(shortcut), 2);
234 } else {
235 /* remove SHORTCUT keyword */
236 tmp = PLGetArrayElement(item, 1);
237 PLRemoveArrayElement(item, 1);
238 PLRelease(tmp);
239 /* remove the shortcut */
240 tmp = PLGetArrayElement(item, 1);
241 PLRemoveArrayElement(item, 1);
242 PLRelease(tmp);
244 } else {
245 if (shortcut) {
246 PLInsertArrayElement(item, PLMakeString("SHORTCUT"), 1);
247 PLInsertArrayElement(item, PLMakeString(shortcut), 2);
248 } else {
249 /* do nothing */
255 static void
256 changeItemCommand(proplist_t item, char *command)
258 proplist_t tmp;
260 tmp = PLGetArrayElement(item, 1);
261 if (strcmp(PLGetString(tmp), "SHORTCUT")==0) {
262 PLRelease(tmp);
263 PLRemoveArrayElement(item, 3);
264 PLInsertArrayElement(item, PLMakeString(command), 3);
265 } else {
266 PLRelease(tmp);
267 PLRemoveArrayElement(item, 1);
268 PLInsertArrayElement(item, PLMakeString(command), 1);
273 static char*
274 getItemTitle(proplist_t item)
276 return PLGetString(PLGetArrayElement(item, 0));
280 static char*
281 getItemParameter(proplist_t item)
283 proplist_t tmp;
285 tmp = PLGetArrayElement(item, 1);
286 if (strcmp(PLGetString(tmp), "SHORTCUT")==0) {
287 tmp = PLGetArrayElement(item, 4);
288 return tmp ? PLGetString(tmp) : NULL;
289 } else {
290 tmp = PLGetArrayElement(item, 2);
291 return tmp ? PLGetString(tmp) : NULL;
297 static char*
298 getItemShortcut(proplist_t item)
300 proplist_t tmp;
302 tmp = PLGetArrayElement(item, 1);
303 if (strcmp(PLGetString(tmp), "SHORTCUT")==0) {
304 return PLGetString(PLGetArrayElement(item, 2));
305 } else {
306 return NULL;
312 static char*
313 getItemCommand(proplist_t item)
315 proplist_t tmp;
316 char *str;
318 tmp = PLGetArrayElement(item, 1);
319 if (!tmp)
320 return "";
321 if (strcmp(PLGetString(tmp), "SHORTCUT")==0) {
322 str = PLGetString(PLGetArrayElement(item,3));
323 } else {
324 str = PLGetString(tmp);
326 return str;
331 static proplist_t
332 getSubmenuInColumn(_Panel *panel, int column)
334 proplist_t parent;
335 proplist_t submenu;
336 WMList *list;
337 int r;
339 if (column == 0) {
340 return panel->menu;
342 if (column >= WMGetBrowserNumberOfColumns(panel->browser))
343 return NULL;
345 list = WMGetBrowserListInColumn(panel->browser, column - 1);
346 assert(list != NULL);
348 r = WMGetListSelectedItemRow(list);
350 parent = getSubmenuInColumn(panel, column - 1);
352 assert(parent != NULL);
354 submenu = PLGetArrayElement(parent, r + 1);
356 return submenu;
360 static void
361 updateForItemType(_Panel *panel, int type)
363 if (type==TNothing) {
364 WMUnmapWidget(panel->labF);
365 } else {
366 WMMapWidget(panel->labF);
368 if (type==TExternalMenu || type==TNothing) {
369 WMUnmapWidget(panel->cmdF);
370 } else {
371 WMMapWidget(panel->cmdF);
373 if (type==TNothing || type==TWSMenu || type==TExternalMenu) {
374 WMUnmapWidget(panel->shoF);
375 } else {
376 WMMapWidget(panel->shoF);
378 if (type==TExec || type==TRestart || type==TExternalMenu) {
379 WMMapWidget(panel->proF);
380 } else {
381 WMUnmapWidget(panel->proF);
383 if (type==TExternalMenu) {
384 WMMapWidget(panel->pathF);
385 } else {
386 WMUnmapWidget(panel->pathF);
388 if (type==TExit) {
389 WMMapWidget(panel->noconfirmB);
390 } else {
391 WMUnmapWidget(panel->noconfirmB);
393 if (type==TWSMenu) {
394 WMMapWidget(panel->infoL);
395 } else {
396 WMUnmapWidget(panel->infoL);
398 if (type==TExternalMenu) {
399 WMMapWidget(panel->guruB);
400 } else {
401 WMUnmapWidget(panel->guruB);
403 if (type == TRestart) {
404 WMSetFrameTitle(panel->proF, _("Window Manager"));
405 } else if (type == TExternalMenu) {
406 WMSetFrameTitle(panel->proF, _("Program to open files"));
407 } else {
408 WMSetFrameTitle(panel->proF, _("Program to Run"));
413 proplist_t
414 getItemOfSelectedEntry(WMBrowser *bPtr)
416 proplist_t item;
417 proplist_t menu;
418 int i;
420 i = WMGetBrowserSelectedColumn(bPtr);
421 menu = getSubmenuInColumn((_Panel*)WMGetHangedData(bPtr), i);
423 i = WMGetBrowserSelectedRowInColumn(bPtr, i);
424 item = PLGetArrayElement(menu, i+1);
426 return item;
430 static void
431 performCommand(WMWidget *w, void *data)
433 _Panel *panel = (_Panel*)data;
434 WMPopUpButton *pop = (WMPopUpButton*)w;
435 proplist_t menuItem = NULL;
436 proplist_t menu;
437 int column;
438 int row;
439 static int cmdIndex=0;
440 char *title = NULL;
441 Bool removed = False;
443 column = WMGetBrowserFirstVisibleColumn(panel->browser);
444 if (pop == panel->cmd2P) {
445 column++;
448 if (column >= WMGetBrowserNumberOfColumns(panel->browser))
449 return;
451 menu = getSubmenuInColumn(panel, column);
453 row = WMGetBrowserSelectedRowInColumn(panel->browser, column);
455 switch (WMGetPopUpButtonSelectedItem(pop)) {
456 case CAddCommand:
457 title = wmalloc(strlen(_("New Command %i"))+6);
458 sprintf(title, _("New Command %i"), cmdIndex++);
459 menuItem = PLMakeArrayFromElements(PLMakeString(title),
460 PLMakeString("EXEC"),
461 PLMakeString(""),
462 NULL);
463 break;
464 case CAddSubmenu:
465 title = wstrdup(_("New Submenu"));
466 menuItem = PLMakeArrayFromElements(PLMakeString(title),
467 NULL);
468 break;
469 case CAddExternal:
470 title = wstrdup(_("External Menu"));
471 menuItem = PLMakeArrayFromElements(PLMakeString(title),
472 PLMakeString("OPEN_MENU"),
473 PLMakeString(""),
474 NULL);
475 break;
476 case CAddWorkspace:
477 title = wstrdup(_("Workspaces"));
478 menuItem = PLMakeArrayFromElements(PLMakeString(title),
479 PLMakeString("WORKSPACE_MENU"),
480 NULL);
481 WMSetPopUpButtonItemEnabled(panel->cmd1P, CAddWorkspace, False);
482 WMSetPopUpButtonItemEnabled(panel->cmd2P, CAddWorkspace, False);
483 break;
484 case CRemove:
485 if (row < 0)
486 return;
487 WMRemoveBrowserItem(panel->browser, column, row);
488 menuItem = PLGetArrayElement(menu, row+1);
489 if (strcmp(getItemCommand(menuItem), "WORKSPACE_MENU")==0) {
490 WMSetPopUpButtonItemEnabled(panel->cmd1P, CAddWorkspace, True);
491 WMSetPopUpButtonItemEnabled(panel->cmd2P, CAddWorkspace, True);
493 PLRemoveArrayElement(menu, row+1);
494 PLRelease(menuItem);
495 updateForItemType(panel, TNothing);
496 panel->editedItem = NULL;
497 panel->unsaved = 1;
498 if (pop == panel->cmd1P) {
499 WMSetTextFieldText(panel->tit2T, NULL);
501 removed = True;
502 return;
503 case CCut:
504 if (row < 0)
505 return;
506 if (panel->itemClipboard
507 && strcmp(getItemCommand(panel->itemClipboard), "WORKSPACE_MENU")==0){
508 WMSetPopUpButtonItemEnabled(panel->cmd1P, CAddWorkspace, True);
509 WMSetPopUpButtonItemEnabled(panel->cmd2P, CAddWorkspace, True);
511 if (panel->itemClipboard)
512 PLRelease(panel->itemClipboard);
513 WMRemoveBrowserItem(panel->browser, column, row);
514 menuItem = PLGetArrayElement(menu, row+1);
515 PLRemoveArrayElement(menu, row+1);
516 updateForItemType(panel, TNothing);
518 panel->itemClipboard = menuItem;
520 WMSetPopUpButtonItemEnabled(panel->cmd1P, CPaste, True);
521 WMSetPopUpButtonItemEnabled(panel->cmd2P, CPaste, True);
522 panel->unsaved = 1;
523 removed = True;
524 return;
525 case CCopy:
526 if (row < 0)
527 return;
528 if (panel->itemClipboard
529 && strcmp(getItemCommand(panel->itemClipboard), "WORKSPACE_MENU")==0){
530 WMSetPopUpButtonItemEnabled(panel->cmd1P, CAddWorkspace, True);
531 WMSetPopUpButtonItemEnabled(panel->cmd2P, CAddWorkspace, True);
533 if (panel->itemClipboard)
534 PLRelease(panel->itemClipboard);
535 panel->itemClipboard = NULL;
536 menuItem = PLGetArrayElement(menu, row+1);
537 if (strcmp(getItemCommand(menuItem), "WORKSPACE_MENU")==0)
538 return;
539 panel->itemClipboard = PLDeepCopy(menuItem);
541 WMSetPopUpButtonItemEnabled(panel->cmd1P, CPaste, True);
542 WMSetPopUpButtonItemEnabled(panel->cmd2P, CPaste, True);
543 return;
544 case CPaste:
545 menuItem = panel->itemClipboard;
546 title = wstrdup(getItemTitle(menuItem));
547 panel->itemClipboard = NULL;
548 WMSetPopUpButtonItemEnabled(panel->cmd1P, CPaste, False);
549 WMSetPopUpButtonItemEnabled(panel->cmd2P, CPaste, False);
550 break;
553 if (row>=0) row++;
554 WMInsertBrowserItem(panel->browser, column, row, title, isMenu(menuItem));
555 if (row<0)
556 PLAppendArrayElement(menu, menuItem);
557 else
558 PLInsertArrayElement(menu, menuItem, row+1);
559 free(title);
560 panel->unsaved = 1;
562 if (removed) {
563 if (pop == panel->cmd1P) {
564 WMSetTextFieldText(panel->tit2T, NULL);
570 static void
571 browserClick(WMWidget *w, void *data)
573 _Panel *panel = (_Panel*)data;
574 proplist_t item;
575 char *command;
577 /* stop shortcut capture */
578 panel->capturing = 0;
580 item = getItemOfSelectedEntry(panel->browser);
582 panel->editedItem = item;
584 /* set title */
585 WMSetTextFieldText(panel->labT, getItemTitle(item));
587 if (isMenu(item)) {
588 updateForItemType(panel, TNothing);
590 WMSetPopUpButtonEnabled(panel->cmd2P, True);
591 return;
592 } else {
593 int column = WMGetBrowserSelectedColumn(panel->browser);
595 if (column == WMGetBrowserNumberOfColumns(panel->browser)-1
596 && column > 0)
597 WMSetPopUpButtonEnabled(panel->cmd2P, True);
598 else
599 WMSetPopUpButtonEnabled(panel->cmd2P, False);
601 if (column==WMGetBrowserFirstVisibleColumn(panel->browser)) {
602 /* second column is empty, because selected item is not a submenu */
603 WMSetTextFieldText(panel->tit2T, NULL);
607 command = getItemCommand(item);
609 WMSetTextFieldText(panel->shoT, getItemShortcut(item));
611 if (strcmp(command, "OPEN_MENU")==0) {
612 char *p, *c;
614 splitOpenMenuParameter(getItemParameter(item), &p, &c);
615 WMSetTextFieldText(panel->pathT, p);
616 WMSetTextFieldText(panel->proT, c);
617 if (p)
618 free(p);
619 if (c)
620 free(c);
621 updateForItemType(panel, TExternalMenu);
622 } else if (strcmp(command, "EXEC")==0) {
623 WMSetTextFieldText(panel->proT, getItemParameter(item));
624 WMSetPopUpButtonSelectedItem(panel->cmdP, CpExec);
625 updateForItemType(panel, TExec);
626 } else if (strcmp(command, "WORKSPACE_MENU")==0) {
627 updateForItemType(panel, TWSMenu);
628 } else if (strcmp(command, "EXIT")==0) {
629 WMSetPopUpButtonSelectedItem(panel->cmdP, CpExit);
630 updateForItemType(panel, TExit);
631 } else if (strcmp(command, "SHUTDOWN")==0) {
632 WMSetPopUpButtonSelectedItem(panel->cmdP, CpShutdown);
633 updateForItemType(panel, TExit);
634 } else if (strcmp(command, "RESTARTW")==0) {
635 WMSetPopUpButtonSelectedItem(panel->cmdP, CpRestartWM);
636 updateForItemType(panel, TRestartWM);
637 } else if (strcmp(command, "RESTART")==0) {
638 WMSetPopUpButtonSelectedItem(panel->cmdP, CpRestart);
639 WMSetTextFieldText(panel->proT, getItemParameter(item));
640 updateForItemType(panel, TRestart);
641 } else {
642 /* simple commands */
643 if (strcmp(command, "ARRANGE_ICONS")==0)
644 WMSetPopUpButtonSelectedItem(panel->cmdP, CpArrange);
645 else if (strcmp(command, "HIDE_OTHERS")==0)
646 WMSetPopUpButtonSelectedItem(panel->cmdP, CpHide);
647 else if (strcmp(command, "SHOW_ALL")==0)
648 WMSetPopUpButtonSelectedItem(panel->cmdP, CpShow);
649 else if (strcmp(command, "SAVE_SESSION")==0)
650 WMSetPopUpButtonSelectedItem(panel->cmdP, CpSaveSession);
651 else if (strcmp(command, "CLEAR_SESSION")==0)
652 WMSetPopUpButtonSelectedItem(panel->cmdP, CpClearSession);
653 else if (strcmp(command, "REFRESH")==0)
654 WMSetPopUpButtonSelectedItem(panel->cmdP, CpRefresh);
655 else if (strcmp(command, "INFO_PANEL")==0)
656 WMSetPopUpButtonSelectedItem(panel->cmdP, CpInfo);
657 else if (strcmp(command, "LEGAL_PANEL")==0)
658 WMSetPopUpButtonSelectedItem(panel->cmdP, CpLegal);
659 updateForItemType(panel, TSimpleCommand);
665 static void
666 fillBrowserColumn(WMBrowser *bPtr, int column)
668 _Panel *panel = (_Panel*)WMGetHangedData(bPtr);
669 proplist_t menuItem;
670 proplist_t menuList = NULL;
671 int i;
674 menuList = getSubmenuInColumn(panel, column);
675 assert(menuList != NULL);
677 if (column > WMGetBrowserFirstVisibleColumn(bPtr)) {
678 WMSetTextFieldText(panel->tit2T, getItemTitle(menuList));
679 } else {
680 WMSetTextFieldText(panel->tit1T, getItemTitle(menuList));
683 for (i=1; i<PLGetNumberOfElements(menuList); i++) {
684 menuItem = PLGetArrayElement(menuList, i);
685 WMInsertBrowserItem(bPtr, column, -1, getItemTitle(menuItem),
686 isMenu(menuItem));
693 static void
694 changedItem(void *observerData, WMNotification *notification)
696 _Panel *panel = (_Panel*)observerData;
697 WMTextField *t = (WMTextField*)WMGetNotificationObject(notification);
698 proplist_t item = panel->editedItem;
699 WMList *list;
700 WMListItem *litem;
701 char *command;
702 char *str;
705 if (!item)
706 return;
708 panel->unsaved = 1;
709 if (!isMenu(item)) {
710 command = getItemCommand(item);
712 if (t == panel->shoT) {
713 str = WMGetTextFieldText(t);
714 if (strlen(str)==0) {
715 free(str);
716 str = NULL;
718 changeItemShortcut(item, str);
719 if (str)
720 free(str);
721 } else if (t == panel->labT) {
722 int column;
724 str = WMGetTextFieldText(t);
725 if (!str)
726 str = wstrdup("");
727 changeItemTitle(item, str);
728 column = WMGetBrowserSelectedColumn(panel->browser);
729 list = WMGetBrowserListInColumn(panel->browser, column);
730 litem = WMGetListSelectedItem(list);
732 free(litem->text);
733 litem->text = str;
735 WMRedisplayWidget(list);
736 } else if (strcmp(command, "EXEC")==0
737 || strcmp(command, "RESTART")==0) {
738 if (t == panel->proT) {
739 str = WMGetTextFieldText(t);
741 changeItemParameter(item, str);
743 free(str);
745 } else if (strcmp(command, "OPEN_MENU")==0) {
746 char *text;
747 char *str2;
749 str = WMGetTextFieldText(panel->pathT);
750 str2 = WMGetTextFieldText(panel->proT);
751 text = wmalloc(strlen(str)+strlen(str2)+16);
752 strcpy(text, str);
753 free(str);
754 if (strlen(str2)>0) {
755 strcat(text, " WITH ");
756 strcat(text, str2);
758 free(str2);
759 changeItemParameter(item, text);
760 free(text);
766 static void
767 changedTitle(void *observerData, WMNotification *notification)
769 _Panel *panel = (_Panel*)observerData;
770 WMTextField *t = (WMTextField*)WMGetNotificationObject(notification);
771 proplist_t menu;
772 WMList *list;
773 int column;
774 char *txt;
776 column = WMGetBrowserFirstVisibleColumn(panel->browser);
777 if (panel->tit2T == t)
778 column++;
780 menu = getSubmenuInColumn(panel, column);
781 if (!menu)
782 return;
784 txt = WMGetTextFieldText(t);
785 changeItemTitle(menu, txt);
787 if (column > 0) {
788 WMListItem *litem;
790 list = WMGetBrowserListInColumn(panel->browser, column-1);
791 litem = WMGetListSelectedItem(list);
793 free(litem->text);
794 litem->text = txt;
796 WMRedisplayWidget(list);
797 } else {
798 free(txt);
800 panel->unsaved = 1;
804 static void
805 changedCommand(WMWidget *w, void *data)
807 _Panel *panel = (_Panel*)data;
808 int i;
809 char *tmp;
811 panel->unsaved = 1;
812 i = WMGetPopUpButtonSelectedItem(panel->cmdP);
813 changeItemParameter(panel->editedItem, "");
814 switch (i) {
815 case CpExec:
816 if (strcmp(getItemCommand(panel->editedItem), "EXEC")!=0) {
817 changeItemCommand(panel->editedItem, "EXEC");
818 tmp = WMGetTextFieldText(panel->proT);
819 changeItemParameter(panel->editedItem, tmp);
820 free(tmp);
821 updateForItemType(panel, TExec);
823 break;
824 case CpArrange:
825 if (strcmp(getItemCommand(panel->editedItem), "ARRANGE_ICONS")!=0) {
826 changeItemCommand(panel->editedItem, "ARRANGE_ICONS");
827 updateForItemType(panel, TSimpleCommand);
829 break;
830 case CpHide:
831 if (strcmp(getItemCommand(panel->editedItem), "HIDE_OTHERS")!=0) {
832 changeItemCommand(panel->editedItem, "HIDE_OTHERS");
833 updateForItemType(panel, TSimpleCommand);
835 break;
836 case CpShow:
837 if (strcmp(getItemCommand(panel->editedItem), "SHOW_ALL")!=0) {
838 changeItemCommand(panel->editedItem, "SHOW_ALL");
839 updateForItemType(panel, TSimpleCommand);
841 break;
842 case CpExit:
843 if (strcmp(getItemCommand(panel->editedItem), "EXIT")!=0) {
844 changeItemCommand(panel->editedItem, "EXIT");
845 updateForItemType(panel, TExit);
847 if (WMGetButtonSelected(panel->noconfirmB))
848 changeItemParameter(panel->editedItem, "QUICK");
849 else
850 changeItemParameter(panel->editedItem, "");
851 break;
852 case CpShutdown:
853 if (strcmp(getItemCommand(panel->editedItem), "SHUTDOWN")!=0) {
854 changeItemCommand(panel->editedItem, "SHUTDOWN");
855 updateForItemType(panel, TExit);
857 if (WMGetButtonSelected(panel->noconfirmB))
858 changeItemParameter(panel->editedItem, "QUICK");
859 else
860 changeItemParameter(panel->editedItem, "");
861 break;
862 case CpRestartWM:
863 changeItemCommand(panel->editedItem, "RESTARTW");
864 updateForItemType(panel, TRestartWM);
865 break;
866 case CpRestart:
867 changeItemCommand(panel->editedItem, "RESTART");
868 updateForItemType(panel, TRestart);
869 tmp = WMGetTextFieldText(panel->proT);
870 changeItemParameter(panel->editedItem, tmp);
871 free(tmp);
872 break;
873 case CpSaveSession:
874 if (strcmp(getItemCommand(panel->editedItem), "SAVE_SESSION")!=0) {
875 changeItemCommand(panel->editedItem, "SAVE_SESSION");
876 updateForItemType(panel, TSimpleCommand);
878 break;
879 case CpClearSession:
880 if (strcmp(getItemCommand(panel->editedItem), "CLEAR_SESSION")!=0) {
881 changeItemCommand(panel->editedItem, "CLEAR_SESSION");
882 updateForItemType(panel, TSimpleCommand);
884 break;
885 case CpRefresh:
886 if (strcmp(getItemCommand(panel->editedItem), "REFRESH")!=0) {
887 changeItemCommand(panel->editedItem, "REFRESH");
888 updateForItemType(panel, TSimpleCommand);
890 break;
891 case CpInfo:
892 if (strcmp(getItemCommand(panel->editedItem), "INFO_PANEL")!=0) {
893 changeItemCommand(panel->editedItem, "INFO_PANEL");
894 updateForItemType(panel, TSimpleCommand);
896 break;
897 case CpLegal:
898 if (strcmp(getItemCommand(panel->editedItem), "LEGAL_PANEL")!=0) {
899 changeItemCommand(panel->editedItem, "LEGAL_PANEL");
900 updateForItemType(panel, TSimpleCommand);
902 break;
910 static char*
911 captureShortcut(Display *dpy, _Panel *panel)
913 XEvent ev;
914 KeySym ksym;
915 char buffer[64];
916 char *key = NULL;
918 while (panel->capturing) {
919 XAllowEvents(dpy, AsyncKeyboard, CurrentTime);
920 WMNextEvent(dpy, &ev);
921 if (ev.type==KeyPress && ev.xkey.keycode!=0) {
922 ksym = XKeycodeToKeysym(dpy, ev.xkey.keycode, 0);
923 if (!IsModifierKey(ksym)) {
924 key=XKeysymToString(ksym);
925 panel->capturing = 0;
926 break;
929 WMHandleEvent(&ev);
932 if (!key)
933 return NULL;
935 buffer[0] = 0;
937 if (ev.xkey.state & ControlMask) {
938 strcat(buffer, "Control+");
940 if (ev.xkey.state & ShiftMask) {
941 strcat(buffer, "Shift+");
943 if (ev.xkey.state & Mod1Mask) {
944 strcat(buffer, "Mod1+");
946 if (ev.xkey.state & Mod2Mask) {
947 strcat(buffer, "Mod2+");
949 if (ev.xkey.state & Mod3Mask) {
950 strcat(buffer, "Mod3+");
952 if (ev.xkey.state & Mod4Mask) {
953 strcat(buffer, "Mod4+");
955 if (ev.xkey.state & Mod5Mask) {
956 strcat(buffer, "Mod5+");
958 strcat(buffer, key);
960 return wstrdup(buffer);
964 static void
965 captureClick(WMWidget *w, void *data)
967 _Panel *panel = (_Panel*)data;
968 Display *dpy = WMScreenDisplay(WMWidgetScreen(panel->win));
969 char *shortcut;
971 if (!panel->capturing) {
972 panel->capturing = 1;
973 WMSetButtonText(w, _("Cancel"));
974 XGrabKeyboard(dpy, WMWidgetXID(panel->win), True, GrabModeAsync,
975 GrabModeAsync, CurrentTime);
976 shortcut = captureShortcut(dpy, panel);
977 if (shortcut) {
978 WMSetTextFieldText(panel->shoT, shortcut);
979 changeItemShortcut(panel->editedItem, shortcut);
980 panel->unsaved = 1;
982 free(shortcut);
984 panel->capturing = 0;
985 WMSetButtonText(w, _("Capture"));
986 XUngrabKeyboard(dpy, CurrentTime);
991 static void
992 scrolledBrowser(void *observerData, WMNotification *notification)
994 _Panel *panel = (_Panel*)observerData;
995 int column;
996 WMList *list;
997 proplist_t item;
999 column = WMGetBrowserFirstVisibleColumn(panel->browser);
1001 item = getSubmenuInColumn(panel, column);
1002 WMSetTextFieldText(panel->tit1T, getItemTitle(item));
1004 item = getSubmenuInColumn(panel, column + 1);
1005 if (item)
1006 WMSetTextFieldText(panel->tit2T, getItemTitle(item));
1010 static void
1011 confirmClicked(WMWidget *w, void *data)
1013 _Panel *panel = (_Panel*)data;
1015 if (WMGetButtonSelected(panel->noconfirmB)) {
1016 changeItemParameter(panel->editedItem, "QUICK");
1017 } else {
1018 changeItemParameter(panel->editedItem, "");
1020 panel->unsaved = 1;
1025 static void
1026 openGuru(WMWidget *w, void *data)
1028 _Panel *panel = (_Panel*)data;
1029 char *def;
1030 char *path, *cmd;
1032 def = OpenMenuGuru(GetWindow(panel));
1033 if (def) {
1034 changeItemParameter(panel->editedItem, def);
1035 splitOpenMenuParameter(def, &path, &cmd);
1036 free(def);
1037 WMSetTextFieldText(panel->pathT, path);
1038 if (path)
1039 free(path);
1041 WMSetTextFieldText(panel->proT, cmd);
1042 if (cmd)
1043 free(cmd);
1044 panel->unsaved = 1;
1049 static void
1050 createPanel(_Panel *p)
1052 _Panel *panel = (_Panel*)p;
1055 panel->frame = WMCreateFrame(panel->win);
1056 WMResizeWidget(panel->frame, FRAME_WIDTH, FRAME_HEIGHT);
1057 WMMoveWidget(panel->frame, FRAME_LEFT, FRAME_TOP);
1059 panel->cmd1P = WMCreatePopUpButton(panel->frame);
1060 WMSetPopUpButtonAction(panel->cmd1P, performCommand, panel);
1061 WMResizeWidget(panel->cmd1P, 144, 20);
1062 WMMoveWidget(panel->cmd1P, 15, 15);
1063 WMSetPopUpButtonPullsDown(panel->cmd1P, True);
1064 WMSetPopUpButtonText(panel->cmd1P, _("Commands"));
1065 WMAddPopUpButtonItem(panel->cmd1P, _("Add Command"));
1066 WMAddPopUpButtonItem(panel->cmd1P, _("Add Submenu"));
1067 WMAddPopUpButtonItem(panel->cmd1P, _("Add External Menu"));
1068 WMAddPopUpButtonItem(panel->cmd1P, _("Add Workspace Menu"));
1069 WMAddPopUpButtonItem(panel->cmd1P, _("Remove Item"));
1070 WMAddPopUpButtonItem(panel->cmd1P, _("Cut Item"));
1071 WMAddPopUpButtonItem(panel->cmd1P, _("Copy Item"));
1072 WMAddPopUpButtonItem(panel->cmd1P, _("Paste Item"));
1074 panel->cmd2P = WMCreatePopUpButton(panel->frame);
1075 WMSetPopUpButtonAction(panel->cmd2P, performCommand, panel);
1076 WMResizeWidget(panel->cmd2P, 144, 20);
1077 WMMoveWidget(panel->cmd2P, 164, 15);
1078 WMSetPopUpButtonPullsDown(panel->cmd2P, True);
1079 WMSetPopUpButtonText(panel->cmd2P, _("Commands"));
1080 WMAddPopUpButtonItem(panel->cmd2P, _("Add Command"));
1081 WMAddPopUpButtonItem(panel->cmd2P, _("Add Submenu"));
1082 WMAddPopUpButtonItem(panel->cmd2P, _("Add External Menu"));
1083 WMAddPopUpButtonItem(panel->cmd2P, _("Add Workspace Menu"));
1084 WMAddPopUpButtonItem(panel->cmd2P, _("Remove Item"));
1085 WMAddPopUpButtonItem(panel->cmd2P, _("Cut Item"));
1086 WMAddPopUpButtonItem(panel->cmd2P, _("Copy Item"));
1087 WMAddPopUpButtonItem(panel->cmd2P, _("Paste Item"));
1089 panel->tit1T = WMCreateTextField(panel->frame);
1090 WMResizeWidget(panel->tit1T, 144, 20);
1091 WMMoveWidget(panel->tit1T, 15, 40);
1092 WMAddNotificationObserver(changedTitle, panel, WMTextDidChangeNotification,
1093 panel->tit1T);
1095 panel->tit2T = WMCreateTextField(panel->frame);
1096 WMResizeWidget(panel->tit2T, 144, 20);
1097 WMMoveWidget(panel->tit2T, 164, 40);
1098 WMAddNotificationObserver(changedTitle, panel, WMTextDidChangeNotification,
1099 panel->tit2T);
1101 panel->browser = WMCreateBrowser(panel->frame);
1102 WMSetBrowserTitled(panel->browser, False);
1103 WMResizeWidget(panel->browser, 295, 160);
1104 WMMoveWidget(panel->browser, 15, 65);
1105 WMSetBrowserFillColumnProc(panel->browser, fillBrowserColumn);
1106 WMHangData(panel->browser, panel);
1107 WMSetBrowserPathSeparator(panel->browser, "\r");
1108 WMSetBrowserAction(panel->browser, browserClick, panel);
1109 WMAddNotificationObserver(scrolledBrowser, panel,
1110 WMBrowserDidScrollNotification, panel->browser);
1111 /**/
1113 panel->labF = WMCreateFrame(panel->frame);
1114 WMResizeWidget(panel->labF, 190, 50);
1115 WMMoveWidget(panel->labF, 320, 10);
1116 WMSetFrameTitle(panel->labF, _("Label"));
1118 panel->labT = WMCreateTextField(panel->labF);
1119 WMResizeWidget(panel->labT, 170, 20);
1120 WMMoveWidget(panel->labT, 10, 20);
1121 WMAddNotificationObserver(changedItem, panel, WMTextDidChangeNotification,
1122 panel->labT);
1124 WMMapSubwidgets(panel->labF);
1126 panel->cmdF = WMCreateFrame(panel->frame);
1127 WMResizeWidget(panel->cmdF, 190, 50);
1128 WMMoveWidget(panel->cmdF, 320, 65);
1129 WMSetFrameTitle(panel->cmdF, _("Command"));
1131 panel->cmdP = WMCreatePopUpButton(panel->cmdF);
1132 WMResizeWidget(panel->cmdP, 170, 20);
1133 WMMoveWidget(panel->cmdP, 10, 20);
1134 WMAddPopUpButtonItem(panel->cmdP, _("Run Program"));
1135 WMAddPopUpButtonItem(panel->cmdP, _("Arrange Icons"));
1136 WMAddPopUpButtonItem(panel->cmdP, _("Hide Others"));
1137 WMAddPopUpButtonItem(panel->cmdP, _("Show All Windows"));
1138 WMAddPopUpButtonItem(panel->cmdP, _("Exit WindowMaker"));
1139 WMAddPopUpButtonItem(panel->cmdP, _("Exit X Session"));
1140 WMAddPopUpButtonItem(panel->cmdP, _("Start window manager"));
1141 WMAddPopUpButtonItem(panel->cmdP, _("Restart WindowMaker"));
1142 WMAddPopUpButtonItem(panel->cmdP, _("Save Session"));
1143 WMAddPopUpButtonItem(panel->cmdP, _("Clear Session"));
1144 WMAddPopUpButtonItem(panel->cmdP, _("Refresh Screen"));
1145 WMAddPopUpButtonItem(panel->cmdP, _("Info Panel"));
1146 WMAddPopUpButtonItem(panel->cmdP, _("Legal Panel"));
1147 WMSetPopUpButtonAction(panel->cmdP, changedCommand, panel);
1149 WMMapSubwidgets(panel->cmdF);
1151 panel->infoL = WMCreateLabel(panel->frame);
1152 WMResizeWidget(panel->infoL, 190, 50);
1153 WMMoveWidget(panel->infoL, 320, 65);
1154 WMSetLabelText(panel->infoL, _("Open workspace menu"));
1155 WMSetLabelRelief(panel->infoL, WRGroove);
1156 WMSetLabelTextAlignment(panel->infoL, WACenter);
1158 panel->noconfirmB = WMCreateSwitchButton(panel->frame);
1159 WMResizeWidget(panel->noconfirmB, 190, 50);
1160 WMMoveWidget(panel->noconfirmB, 320, 120);
1161 WMSetButtonText(panel->noconfirmB, _("No confirmation panel"));
1162 WMSetButtonAction(panel->noconfirmB, confirmClicked, panel);
1164 panel->pathF = WMCreateFrame(panel->frame);
1165 WMResizeWidget(panel->pathF, 190, 50);
1166 WMMoveWidget(panel->pathF, 320, 65);
1167 WMSetFrameTitle(panel->pathF, _("Menu Path/Directory List"));
1169 panel->pathT = WMCreateTextField(panel->pathF);
1170 WMResizeWidget(panel->pathT, 170, 20);
1171 WMMoveWidget(panel->pathT, 10, 20);
1172 WMAddNotificationObserver(changedItem, panel, WMTextDidChangeNotification,
1173 panel->pathT);
1175 WMMapSubwidgets(panel->pathF);
1177 panel->proF = WMCreateFrame(panel->frame);
1178 WMResizeWidget(panel->proF, 190, 50);
1179 WMMoveWidget(panel->proF, 320, 120);
1180 WMSetFrameTitle(panel->proF, _("Program to Run"));
1182 panel->proT = WMCreateTextField(panel->proF);
1183 WMResizeWidget(panel->proT, 170, 20);
1184 WMMoveWidget(panel->proT, 10, 20);
1185 WMAddNotificationObserver(changedItem, panel, WMTextDidChangeNotification,
1186 panel->proT);
1188 WMMapSubwidgets(panel->proF);
1190 panel->shoF = WMCreateFrame(panel->frame);
1191 WMResizeWidget(panel->shoF, 190, 50);
1192 WMMoveWidget(panel->shoF, 320, 175);
1193 WMSetFrameTitle(panel->shoF, _("Shortcut"));
1195 panel->shoT = WMCreateTextField(panel->shoF);
1196 WMResizeWidget(panel->shoT, 95, 20);
1197 WMMoveWidget(panel->shoT, 10, 20);
1198 WMAddNotificationObserver(changedItem, panel, WMTextDidChangeNotification,
1199 panel->shoT);
1201 panel->shoB = WMCreateCommandButton(panel->shoF);
1202 WMResizeWidget(panel->shoB, 70, 24);
1203 WMMoveWidget(panel->shoB, 110, 18);
1204 WMSetButtonText(panel->shoB, _("Capture"));
1205 WMSetButtonAction(panel->shoB, captureClick, panel);
1207 WMMapSubwidgets(panel->shoF);
1209 panel->guruB = WMCreateCommandButton(panel->frame);
1210 WMResizeWidget(panel->guruB, 180, 24);
1211 WMMoveWidget(panel->guruB, 325, 190);
1212 WMSetButtonText(panel->guruB, _("Ask help to the Guru"));
1213 WMSetButtonAction(panel->guruB, openGuru, panel);
1215 WMRealizeWidget(panel->frame);
1216 WMMapSubwidgets(panel->frame);
1218 showData(panel);
1224 static proplist_t
1225 preProcessMenu(proplist_t menu, int *hasWSMenu)
1227 proplist_t pmenu;
1228 proplist_t item;
1229 int i;
1231 pmenu = PLDeepCopy(menu);
1232 if (PLGetNumberOfElements(pmenu)==1) {
1233 return pmenu;
1235 for (i=1; i<PLGetNumberOfElements(pmenu); i++) {
1236 item = PLGetArrayElement(pmenu, i);
1237 if (isMenu(item)) {
1238 PLInsertArrayElement(pmenu, preProcessMenu(item, hasWSMenu), i);
1239 PLRemoveArrayElement(pmenu, i+1);
1240 PLRelease(item);
1241 } else if (strcmp(getItemCommand(item), "RESTART")==0) {
1242 if (getItemShortcut(item)) {
1243 if (PLGetNumberOfElements(item) == 4) {
1244 changeItemCommand(item, "RESTARTW");
1245 PLAppendArrayElement(item, PLMakeString(""));
1247 } else {
1248 if (PLGetNumberOfElements(item) == 2) {
1249 changeItemCommand(item, "RESTARTW");
1250 PLAppendArrayElement(item, PLMakeString(""));
1253 } else {
1254 if (strcmp(getItemCommand(item),"WORKSPACE_MENU")==0)
1255 *hasWSMenu = 1;
1256 if (getItemShortcut(item)) {
1257 if (PLGetNumberOfElements(item) == 4)
1258 PLAppendArrayElement(item, PLMakeString(""));
1259 } else {
1260 if (PLGetNumberOfElements(item) == 2)
1261 PLAppendArrayElement(item, PLMakeString(""));
1266 return pmenu;
1271 static proplist_t
1272 postProcessMenu(proplist_t menu)
1274 proplist_t pmenu;
1275 proplist_t item;
1276 int i;
1277 int count;
1279 pmenu = PLDeepCopy(menu);
1280 if (PLGetNumberOfElements(pmenu)==1) {
1281 return pmenu;
1283 count = PLGetNumberOfElements(pmenu);
1284 for (i=1; i<count; i++) {
1285 char *cmd;
1286 item = PLGetArrayElement(pmenu, i);
1287 if (isMenu(item)) {
1288 PLInsertArrayElement(pmenu, postProcessMenu(item), i);
1289 PLRemoveArrayElement(pmenu, i+1);
1290 PLRelease(item);
1291 } else {
1292 cmd = getItemCommand(item);
1293 if (strcmp(cmd, "RESTARTW")==0) {
1294 changeItemCommand(item, "RESTART");
1295 removeParameter(item);
1296 } else if (strcmp(cmd, "EXEC")==0 || strcmp(cmd, "OPEN_MENU")==0) {
1297 /* do nothing */
1298 } else if (strcmp(cmd, "RESTART")==0 || strcmp(cmd, "SHUTDOWN")==0
1299 || strcmp(cmd, "EXIT")==0) {
1300 char *tmp = getItemParameter(item);
1301 if (tmp && strlen(tmp)==0)
1302 removeParameter(item);
1303 } else {
1304 removeParameter(item);
1309 return pmenu;
1313 static proplist_t
1314 getDefaultMenu(_Panel *panel, int *hasWSMenu)
1316 proplist_t menu, pmenu;
1317 char *menuPath, *gspath;
1319 gspath = wusergnusteppath();
1321 menuPath = wmalloc(strlen(gspath)+128);
1322 /* if there is a localized plmenu for the tongue put it's filename here */
1323 sprintf(menuPath, _("%s/Library/WindowMaker/plmenu"), gspath);
1325 menu = PLGetProplistWithPath(menuPath);
1326 if (!menu) {
1327 wwarning("%s:could not read property list menu", menuPath);
1329 if (strcmp("%s/Library/WindowMaker/plmenu",
1330 _("%s/Library/WindowMaker/plmenu"))!=0) {
1332 sprintf(menuPath, "%s/Library/WindowMaker/plmenu", gspath);
1333 menu = PLGetProplistWithPath(menuPath);
1334 wwarning("%s:could not read property list menu", menuPath);
1336 if (!menu) {
1337 char buffer[512];
1339 sprintf(buffer, _("Could not open default menu from '%s'"),
1340 menuPath);
1341 WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win,
1342 _("Error"), buffer, _("OK"), NULL, NULL);
1346 free(menuPath);
1348 if (menu) {
1349 pmenu = preProcessMenu(menu, hasWSMenu);
1350 PLRelease(menu);
1351 } else {
1352 pmenu = NULL;
1355 return pmenu;
1359 static void
1360 showData(_Panel *panel)
1362 char *gspath;
1363 char *menuPath;
1364 proplist_t menu, pmenu, plPath;
1365 int hasWSMenu = 0;
1367 gspath = wusergnusteppath();
1369 menuPath = wmalloc(strlen(gspath)+32);
1370 strcpy(menuPath, gspath);
1371 strcat(menuPath, "/Defaults/WMRootMenu");
1373 menu = PLGetProplistWithPath(menuPath);
1374 pmenu = NULL;
1376 if (!menu || !PLIsArray(menu)) {
1377 if (AskMenuCopy(panel->win)) {
1378 panel->dontSave = 0;
1379 panel->unsaved = 1;
1381 pmenu = getDefaultMenu(panel, &hasWSMenu);
1382 } else {
1383 WMSetPopUpButtonEnabled(panel->cmd1P, False);
1384 WMSetPopUpButtonEnabled(panel->cmd2P, False);
1385 panel->dontSave = 1;
1387 if (!pmenu) {
1388 pmenu = PLMakeArrayFromElements(PLMakeString("Applications"),
1389 NULL);
1391 } else {
1392 pmenu = preProcessMenu(menu, &hasWSMenu);
1394 plPath = PLMakeString(menuPath);
1395 free(menuPath);
1396 PLSetFilename(pmenu, plPath);
1397 PLRelease(plPath);
1399 if (menu)
1400 PLRelease(menu);
1402 if (panel->itemClipboard) {
1403 PLRelease(panel->itemClipboard);
1404 panel->itemClipboard = NULL;
1406 panel->menu = pmenu;
1407 panel->editedItem = NULL;
1408 panel->capturing = 0;
1410 WMSetPopUpButtonItemEnabled(panel->cmd1P, CPaste, False);
1411 WMSetPopUpButtonItemEnabled(panel->cmd2P, CPaste, False);
1412 if (hasWSMenu) {
1413 WMSetPopUpButtonItemEnabled(panel->cmd1P, CAddWorkspace, False);
1414 WMSetPopUpButtonItemEnabled(panel->cmd2P, CAddWorkspace, False);
1416 WMLoadBrowserColumnZero(panel->browser);
1418 updateForItemType(panel, TNothing);
1422 static void
1423 storeData(_Panel *panel)
1425 proplist_t menu;
1427 if (!panel->unsaved || panel->dontSave)
1428 return;
1429 panel->unsaved = 0;
1431 menu = postProcessMenu(panel->menu);
1433 PLSetFilename(menu, PLGetFilename(panel->menu));
1435 PLSave(menu, YES);
1437 PLRelease(menu);
1441 Panel*
1442 InitMenu(WMScreen *scr, WMWindow *win)
1444 _Panel *panel;
1446 panel = wmalloc(sizeof(_Panel));
1447 memset(panel, 0, sizeof(_Panel));
1449 panel->sectionName = _("Applications Menu Definition");
1451 panel->win = win;
1453 panel->callbacks.createWidgets = createPanel;
1454 panel->callbacks.updateDomain = storeData;
1456 AddSection(panel, ICON_FILE);
1458 return panel;