Initial update from my source tree. For 0.52.0
[wmaker-crm.git] / WPrefs.app / Menu.c
blob8804d8ae8afda68e7865ab013da3053ecebb62d8
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;
442 column = WMGetBrowserFirstVisibleColumn(panel->browser);
443 if (pop == panel->cmd2P) {
444 column++;
447 if (column >= WMGetBrowserNumberOfColumns(panel->browser))
448 return;
450 menu = getSubmenuInColumn(panel, column);
452 row = WMGetBrowserSelectedRowInColumn(panel->browser, column);
454 switch (WMGetPopUpButtonSelectedItem(pop)) {
455 case CAddCommand:
456 title = wmalloc(strlen(_("New Command %i"))+6);
457 sprintf(title, _("New Command %i"), cmdIndex++);
458 menuItem = PLMakeArrayFromElements(PLMakeString(title),
459 PLMakeString("EXEC"),
460 PLMakeString(""),
461 NULL);
462 break;
463 case CAddSubmenu:
464 title = wstrdup(_("New Submenu"));
465 menuItem = PLMakeArrayFromElements(PLMakeString(title),
466 NULL);
467 break;
468 case CAddExternal:
469 title = wstrdup(_("External Menu"));
470 menuItem = PLMakeArrayFromElements(PLMakeString(title),
471 PLMakeString("OPEN_MENU"),
472 PLMakeString(""),
473 NULL);
474 break;
475 case CAddWorkspace:
476 title = wstrdup(_("Workspaces"));
477 menuItem = PLMakeArrayFromElements(PLMakeString(title),
478 PLMakeString("WORKSPACE_MENU"),
479 NULL);
480 WMSetPopUpButtonItemEnabled(panel->cmd1P, CAddWorkspace, False);
481 WMSetPopUpButtonItemEnabled(panel->cmd2P, CAddWorkspace, False);
482 break;
483 case CRemove:
484 if (row < 0)
485 return;
486 WMRemoveBrowserItem(panel->browser, column, row);
487 menuItem = PLGetArrayElement(menu, row+1);
488 if (strcmp(getItemCommand(menuItem), "WORKSPACE_MENU")==0) {
489 WMSetPopUpButtonItemEnabled(panel->cmd1P, CAddWorkspace, True);
490 WMSetPopUpButtonItemEnabled(panel->cmd2P, CAddWorkspace, True);
492 PLRemoveArrayElement(menu, row+1);
493 PLRelease(menuItem);
494 updateForItemType(panel, TNothing);
495 panel->editedItem = NULL;
496 panel->unsaved = 1;
497 return;
498 case CCut:
499 if (row < 0)
500 return;
501 if (panel->itemClipboard
502 && strcmp(getItemCommand(panel->itemClipboard), "WORKSPACE_MENU")==0){
503 WMSetPopUpButtonItemEnabled(panel->cmd1P, CAddWorkspace, True);
504 WMSetPopUpButtonItemEnabled(panel->cmd2P, CAddWorkspace, True);
506 if (panel->itemClipboard)
507 PLRelease(panel->itemClipboard);
509 WMRemoveBrowserItem(panel->browser, column, row);
510 menuItem = PLGetArrayElement(menu, row+1);
511 PLRemoveArrayElement(menu, row+1);
512 updateForItemType(panel, TNothing);
514 panel->itemClipboard = menuItem;
516 WMSetPopUpButtonItemEnabled(panel->cmd1P, CPaste, True);
517 WMSetPopUpButtonItemEnabled(panel->cmd2P, CPaste, True);
518 panel->unsaved = 1;
519 return;
520 case CCopy:
521 if (row < 0)
522 return;
523 if (panel->itemClipboard
524 && strcmp(getItemCommand(panel->itemClipboard), "WORKSPACE_MENU")==0){
525 WMSetPopUpButtonItemEnabled(panel->cmd1P, CAddWorkspace, True);
526 WMSetPopUpButtonItemEnabled(panel->cmd2P, CAddWorkspace, True);
528 if (panel->itemClipboard)
529 PLRelease(panel->itemClipboard);
530 panel->itemClipboard = NULL;
531 menuItem = PLGetArrayElement(menu, row+1);
532 if (strcmp(getItemCommand(menuItem), "WORKSPACE_MENU")==0)
533 return;
534 panel->itemClipboard = PLDeepCopy(menuItem);
536 WMSetPopUpButtonItemEnabled(panel->cmd1P, CPaste, True);
537 WMSetPopUpButtonItemEnabled(panel->cmd2P, CPaste, True);
538 return;
539 case CPaste:
540 menuItem = panel->itemClipboard;
541 title = wstrdup(getItemTitle(menuItem));
542 panel->itemClipboard = NULL;
543 WMSetPopUpButtonItemEnabled(panel->cmd1P, CPaste, False);
544 WMSetPopUpButtonItemEnabled(panel->cmd2P, CPaste, False);
545 break;
548 if (row>=0) row++;
549 WMInsertBrowserItem(panel->browser, column, row, title, isMenu(menuItem));
550 if (row<0)
551 PLAppendArrayElement(menu, menuItem);
552 else
553 PLInsertArrayElement(menu, menuItem, row+1);
554 free(title);
555 panel->unsaved = 1;
559 static void
560 browserClick(WMWidget *w, void *data)
562 _Panel *panel = (_Panel*)data;
563 proplist_t item;
564 char *command;
566 /* stop shortcut capture */
567 panel->capturing = 0;
569 item = getItemOfSelectedEntry(panel->browser);
571 panel->editedItem = item;
573 /* set title */
574 WMSetTextFieldText(panel->labT, getItemTitle(item));
576 if (isMenu(item)) {
577 updateForItemType(panel, TNothing);
579 WMSetPopUpButtonEnabled(panel->cmd2P, True);
580 return;
581 } else {
582 int column = WMGetBrowserSelectedColumn(panel->browser);
584 if (column == WMGetBrowserNumberOfColumns(panel->browser)-1
585 && column > 0)
586 WMSetPopUpButtonEnabled(panel->cmd2P, True);
587 else
588 WMSetPopUpButtonEnabled(panel->cmd2P, False);
590 if (column==WMGetBrowserFirstVisibleColumn(panel->browser)) {
591 /* second column is empty, because selected item is not a submenu */
592 WMSetTextFieldText(panel->tit2T, NULL);
596 command = getItemCommand(item);
598 WMSetTextFieldText(panel->shoT, getItemShortcut(item));
600 if (strcmp(command, "OPEN_MENU")==0) {
601 char *p, *c;
603 splitOpenMenuParameter(getItemParameter(item), &p, &c);
604 WMSetTextFieldText(panel->pathT, p);
605 WMSetTextFieldText(panel->proT, c);
606 if (p)
607 free(p);
608 if (c)
609 free(c);
610 updateForItemType(panel, TExternalMenu);
611 } else if (strcmp(command, "EXEC")==0) {
612 WMSetTextFieldText(panel->proT, getItemParameter(item));
613 WMSetPopUpButtonSelectedItem(panel->cmdP, CpExec);
614 updateForItemType(panel, TExec);
615 } else if (strcmp(command, "WORKSPACE_MENU")==0) {
616 updateForItemType(panel, TWSMenu);
617 } else if (strcmp(command, "EXIT")==0) {
618 WMSetPopUpButtonSelectedItem(panel->cmdP, CpExit);
619 updateForItemType(panel, TExit);
620 } else if (strcmp(command, "SHUTDOWN")==0) {
621 WMSetPopUpButtonSelectedItem(panel->cmdP, CpShutdown);
622 updateForItemType(panel, TExit);
623 } else if (strcmp(command, "RESTARTW")==0) {
624 WMSetPopUpButtonSelectedItem(panel->cmdP, CpRestartWM);
625 updateForItemType(panel, TRestartWM);
626 } else if (strcmp(command, "RESTART")==0) {
627 WMSetPopUpButtonSelectedItem(panel->cmdP, CpRestart);
628 WMSetTextFieldText(panel->proT, getItemParameter(item));
629 updateForItemType(panel, TRestart);
630 } else {
631 /* simple commands */
632 if (strcmp(command, "ARRANGE_ICONS")==0)
633 WMSetPopUpButtonSelectedItem(panel->cmdP, CpArrange);
634 else if (strcmp(command, "HIDE_OTHERS")==0)
635 WMSetPopUpButtonSelectedItem(panel->cmdP, CpHide);
636 else if (strcmp(command, "SHOW_ALL")==0)
637 WMSetPopUpButtonSelectedItem(panel->cmdP, CpShow);
638 else if (strcmp(command, "SAVE_SESSION")==0)
639 WMSetPopUpButtonSelectedItem(panel->cmdP, CpSaveSession);
640 else if (strcmp(command, "CLEAR_SESSION")==0)
641 WMSetPopUpButtonSelectedItem(panel->cmdP, CpClearSession);
642 else if (strcmp(command, "REFRESH")==0)
643 WMSetPopUpButtonSelectedItem(panel->cmdP, CpRefresh);
644 else if (strcmp(command, "INFO_PANEL")==0)
645 WMSetPopUpButtonSelectedItem(panel->cmdP, CpInfo);
646 else if (strcmp(command, "LEGAL_PANEL")==0)
647 WMSetPopUpButtonSelectedItem(panel->cmdP, CpLegal);
648 updateForItemType(panel, TSimpleCommand);
654 static void
655 fillBrowserColumn(WMBrowser *bPtr, int column)
657 _Panel *panel = (_Panel*)WMGetHangedData(bPtr);
658 proplist_t menuItem;
659 proplist_t menuList = NULL;
660 int i;
663 menuList = getSubmenuInColumn(panel, column);
664 assert(menuList != NULL);
666 if (column > WMGetBrowserFirstVisibleColumn(bPtr)) {
667 WMSetTextFieldText(panel->tit2T, getItemTitle(menuList));
668 } else {
669 WMSetTextFieldText(panel->tit1T, getItemTitle(menuList));
672 for (i=1; i<PLGetNumberOfElements(menuList); i++) {
673 menuItem = PLGetArrayElement(menuList, i);
674 WMInsertBrowserItem(bPtr, column, -1, getItemTitle(menuItem),
675 isMenu(menuItem));
682 static void
683 changedItem(void *observerData, WMNotification *notification)
685 _Panel *panel = (_Panel*)observerData;
686 WMTextField *t = (WMTextField*)WMGetNotificationObject(notification);
687 proplist_t item = panel->editedItem;
688 WMList *list;
689 WMListItem *litem;
690 char *command;
691 char *str;
694 if (!item)
695 return;
697 panel->unsaved = 1;
698 if (!isMenu(item)) {
699 command = getItemCommand(item);
701 if (t == panel->shoT) {
702 str = WMGetTextFieldText(t);
703 if (strlen(str)==0) {
704 free(str);
705 str = NULL;
707 changeItemShortcut(item, str);
708 if (str)
709 free(str);
710 } else if (t == panel->labT) {
711 int column;
713 str = WMGetTextFieldText(t);
714 if (!str)
715 str = wstrdup("");
716 changeItemTitle(item, str);
717 column = WMGetBrowserSelectedColumn(panel->browser);
718 list = WMGetBrowserListInColumn(panel->browser, column);
719 litem = WMGetListSelectedItem(list);
721 free(litem->text);
722 litem->text = str;
724 WMRedisplayWidget(list);
725 } else if (strcmp(command, "EXEC")==0
726 || strcmp(command, "RESTART")==0) {
727 if (t == panel->proT) {
728 str = WMGetTextFieldText(t);
730 changeItemParameter(item, str);
732 free(str);
734 } else if (strcmp(command, "OPEN_MENU")==0) {
735 char *text;
736 char *str2;
738 str = WMGetTextFieldText(panel->pathT);
739 str2 = WMGetTextFieldText(panel->proT);
740 text = wmalloc(strlen(str)+strlen(str2)+16);
741 strcpy(text, str);
742 free(str);
743 if (strlen(str2)>0) {
744 strcat(text, " WITH ");
745 strcat(text, str2);
747 free(str2);
748 changeItemParameter(item, text);
749 free(text);
755 static void
756 changedTitle(void *observerData, WMNotification *notification)
758 _Panel *panel = (_Panel*)observerData;
759 WMTextField *t = (WMTextField*)WMGetNotificationObject(notification);
760 proplist_t menu;
761 WMList *list;
762 int column;
763 char *txt;
765 column = WMGetBrowserFirstVisibleColumn(panel->browser);
766 if (panel->tit2T == t)
767 column++;
769 menu = getSubmenuInColumn(panel, column);
770 if (!menu)
771 return;
773 txt = WMGetTextFieldText(t);
774 changeItemTitle(menu, txt);
776 if (column > 0) {
777 WMListItem *litem;
779 list = WMGetBrowserListInColumn(panel->browser, column-1);
780 litem = WMGetListSelectedItem(list);
782 free(litem->text);
783 litem->text = txt;
785 WMRedisplayWidget(list);
786 } else {
787 free(txt);
789 panel->unsaved = 1;
793 static void
794 changedCommand(WMWidget *w, void *data)
796 _Panel *panel = (_Panel*)data;
797 int i;
798 char *tmp;
800 panel->unsaved = 1;
801 i = WMGetPopUpButtonSelectedItem(panel->cmdP);
802 changeItemParameter(panel->editedItem, "");
803 switch (i) {
804 case CpExec:
805 if (strcmp(getItemCommand(panel->editedItem), "EXEC")!=0) {
806 changeItemCommand(panel->editedItem, "EXEC");
807 tmp = WMGetTextFieldText(panel->proT);
808 changeItemParameter(panel->editedItem, tmp);
809 free(tmp);
810 updateForItemType(panel, TExec);
812 break;
813 case CpArrange:
814 if (strcmp(getItemCommand(panel->editedItem), "ARRANGE_ICONS")!=0) {
815 changeItemCommand(panel->editedItem, "ARRANGE_ICONS");
816 updateForItemType(panel, TSimpleCommand);
818 break;
819 case CpHide:
820 if (strcmp(getItemCommand(panel->editedItem), "HIDE_OTHERS")!=0) {
821 changeItemCommand(panel->editedItem, "HIDE_OTHERS");
822 updateForItemType(panel, TSimpleCommand);
824 break;
825 case CpShow:
826 if (strcmp(getItemCommand(panel->editedItem), "SHOW_ALL")!=0) {
827 changeItemCommand(panel->editedItem, "SHOW_ALL");
828 updateForItemType(panel, TSimpleCommand);
830 break;
831 case CpExit:
832 if (strcmp(getItemCommand(panel->editedItem), "EXIT")!=0) {
833 changeItemCommand(panel->editedItem, "EXIT");
834 updateForItemType(panel, TExit);
836 if (WMGetButtonSelected(panel->noconfirmB))
837 changeItemParameter(panel->editedItem, "QUICK");
838 else
839 changeItemParameter(panel->editedItem, "");
840 break;
841 case CpShutdown:
842 if (strcmp(getItemCommand(panel->editedItem), "SHUTDOWN")!=0) {
843 changeItemCommand(panel->editedItem, "SHUTDOWN");
844 updateForItemType(panel, TExit);
846 if (WMGetButtonSelected(panel->noconfirmB))
847 changeItemParameter(panel->editedItem, "QUICK");
848 else
849 changeItemParameter(panel->editedItem, "");
850 break;
851 case CpRestartWM:
852 changeItemCommand(panel->editedItem, "RESTARTW");
853 updateForItemType(panel, TRestartWM);
854 break;
855 case CpRestart:
856 changeItemCommand(panel->editedItem, "RESTART");
857 updateForItemType(panel, TRestart);
858 tmp = WMGetTextFieldText(panel->proT);
859 changeItemParameter(panel->editedItem, tmp);
860 free(tmp);
861 break;
862 case CpSaveSession:
863 if (strcmp(getItemCommand(panel->editedItem), "SAVE_SESSION")!=0) {
864 changeItemCommand(panel->editedItem, "SAVE_SESSION");
865 updateForItemType(panel, TSimpleCommand);
867 break;
868 case CpClearSession:
869 if (strcmp(getItemCommand(panel->editedItem), "CLEAR_SESSION")!=0) {
870 changeItemCommand(panel->editedItem, "CLEAR_SESSION");
871 updateForItemType(panel, TSimpleCommand);
873 break;
874 case CpRefresh:
875 if (strcmp(getItemCommand(panel->editedItem), "REFRESH")!=0) {
876 changeItemCommand(panel->editedItem, "REFRESH");
877 updateForItemType(panel, TSimpleCommand);
879 break;
880 case CpInfo:
881 if (strcmp(getItemCommand(panel->editedItem), "INFO_PANEL")!=0) {
882 changeItemCommand(panel->editedItem, "INFO_PANEL");
883 updateForItemType(panel, TSimpleCommand);
885 break;
886 case CpLegal:
887 if (strcmp(getItemCommand(panel->editedItem), "LEGAL_PANEL")!=0) {
888 changeItemCommand(panel->editedItem, "LEGAL_PANEL");
889 updateForItemType(panel, TSimpleCommand);
891 break;
899 static char*
900 captureShortcut(Display *dpy, _Panel *panel)
902 XEvent ev;
903 KeySym ksym;
904 char buffer[64];
905 char *key = NULL;
907 while (panel->capturing) {
908 XAllowEvents(dpy, AsyncKeyboard, CurrentTime);
909 WMNextEvent(dpy, &ev);
910 if (ev.type==KeyPress && ev.xkey.keycode!=0) {
911 ksym = XKeycodeToKeysym(dpy, ev.xkey.keycode, 0);
912 if (!IsModifierKey(ksym)) {
913 key=XKeysymToString(ksym);
914 panel->capturing = 0;
915 break;
918 WMHandleEvent(&ev);
921 if (!key)
922 return NULL;
924 buffer[0] = 0;
926 if (ev.xkey.state & ControlMask) {
927 strcat(buffer, "Control+");
929 if (ev.xkey.state & ShiftMask) {
930 strcat(buffer, "Shift+");
932 if (ev.xkey.state & Mod1Mask) {
933 strcat(buffer, "Mod1+");
935 if (ev.xkey.state & Mod2Mask) {
936 strcat(buffer, "Mod2+");
938 if (ev.xkey.state & Mod3Mask) {
939 strcat(buffer, "Mod3+");
941 if (ev.xkey.state & Mod4Mask) {
942 strcat(buffer, "Mod4+");
944 if (ev.xkey.state & Mod5Mask) {
945 strcat(buffer, "Mod5+");
947 strcat(buffer, key);
949 return wstrdup(buffer);
953 static void
954 captureClick(WMWidget *w, void *data)
956 _Panel *panel = (_Panel*)data;
957 Display *dpy = WMScreenDisplay(WMWidgetScreen(panel->win));
958 char *shortcut;
960 if (!panel->capturing) {
961 panel->capturing = 1;
962 WMSetButtonText(w, _("Cancel"));
963 XGrabKeyboard(dpy, WMWidgetXID(panel->win), True, GrabModeAsync,
964 GrabModeAsync, CurrentTime);
965 shortcut = captureShortcut(dpy, panel);
966 if (shortcut) {
967 WMSetTextFieldText(panel->shoT, shortcut);
968 changeItemShortcut(panel->editedItem, shortcut);
969 panel->unsaved = 1;
971 free(shortcut);
973 panel->capturing = 0;
974 WMSetButtonText(w, _("Capture"));
975 XUngrabKeyboard(dpy, CurrentTime);
980 static void
981 scrolledBrowser(void *observerData, WMNotification *notification)
983 _Panel *panel = (_Panel*)observerData;
984 int column;
985 WMList *list;
986 proplist_t item;
988 column = WMGetBrowserFirstVisibleColumn(panel->browser);
990 item = getSubmenuInColumn(panel, column);
991 WMSetTextFieldText(panel->tit1T, getItemTitle(item));
993 item = getSubmenuInColumn(panel, column + 1);
994 if (item)
995 WMSetTextFieldText(panel->tit2T, getItemTitle(item));
999 static void
1000 confirmClicked(WMWidget *w, void *data)
1002 _Panel *panel = (_Panel*)data;
1004 if (WMGetButtonSelected(panel->noconfirmB)) {
1005 changeItemParameter(panel->editedItem, "QUICK");
1006 } else {
1007 changeItemParameter(panel->editedItem, "");
1009 panel->unsaved = 1;
1014 static void
1015 openGuru(WMWidget *w, void *data)
1017 _Panel *panel = (_Panel*)data;
1018 char *def;
1019 char *path, *cmd;
1021 def = OpenMenuGuru(GetWindow(panel));
1022 if (def) {
1023 changeItemParameter(panel->editedItem, def);
1024 splitOpenMenuParameter(def, &path, &cmd);
1025 free(def);
1026 WMSetTextFieldText(panel->pathT, path);
1027 if (path)
1028 free(path);
1030 WMSetTextFieldText(panel->proT, cmd);
1031 if (cmd)
1032 free(cmd);
1033 panel->unsaved = 1;
1038 static void
1039 createPanel(_Panel *p)
1041 _Panel *panel = (_Panel*)p;
1044 panel->frame = WMCreateFrame(panel->win);
1045 WMResizeWidget(panel->frame, FRAME_WIDTH, FRAME_HEIGHT);
1046 WMMoveWidget(panel->frame, FRAME_LEFT, FRAME_TOP);
1048 panel->cmd1P = WMCreatePopUpButton(panel->frame);
1049 WMSetPopUpButtonAction(panel->cmd1P, performCommand, panel);
1050 WMResizeWidget(panel->cmd1P, 144, 20);
1051 WMMoveWidget(panel->cmd1P, 15, 15);
1052 WMSetPopUpButtonPullsDown(panel->cmd1P, True);
1053 WMSetPopUpButtonText(panel->cmd1P, _("Commands"));
1054 WMAddPopUpButtonItem(panel->cmd1P, _("Add Command"));
1055 WMAddPopUpButtonItem(panel->cmd1P, _("Add Submenu"));
1056 WMAddPopUpButtonItem(panel->cmd1P, _("Add External Menu"));
1057 WMAddPopUpButtonItem(panel->cmd1P, _("Add Workspace Menu"));
1058 WMAddPopUpButtonItem(panel->cmd1P, _("Remove Item"));
1059 WMAddPopUpButtonItem(panel->cmd1P, _("Cut Item"));
1060 WMAddPopUpButtonItem(panel->cmd1P, _("Copy Item"));
1061 WMAddPopUpButtonItem(panel->cmd1P, _("Paste Item"));
1063 panel->cmd2P = WMCreatePopUpButton(panel->frame);
1064 WMSetPopUpButtonAction(panel->cmd2P, performCommand, panel);
1065 WMResizeWidget(panel->cmd2P, 144, 20);
1066 WMMoveWidget(panel->cmd2P, 164, 15);
1067 WMSetPopUpButtonPullsDown(panel->cmd2P, True);
1068 WMSetPopUpButtonText(panel->cmd2P, _("Commands"));
1069 WMAddPopUpButtonItem(panel->cmd2P, _("Add Command"));
1070 WMAddPopUpButtonItem(panel->cmd2P, _("Add Submenu"));
1071 WMAddPopUpButtonItem(panel->cmd2P, _("Add External Menu"));
1072 WMAddPopUpButtonItem(panel->cmd2P, _("Add Workspace Menu"));
1073 WMAddPopUpButtonItem(panel->cmd2P, _("Remove Item"));
1074 WMAddPopUpButtonItem(panel->cmd2P, _("Cut Item"));
1075 WMAddPopUpButtonItem(panel->cmd2P, _("Copy Item"));
1076 WMAddPopUpButtonItem(panel->cmd2P, _("Paste Item"));
1078 panel->tit1T = WMCreateTextField(panel->frame);
1079 WMResizeWidget(panel->tit1T, 144, 20);
1080 WMMoveWidget(panel->tit1T, 15, 40);
1081 WMAddNotificationObserver(changedTitle, panel, WMTextDidChangeNotification,
1082 panel->tit1T);
1084 panel->tit2T = WMCreateTextField(panel->frame);
1085 WMResizeWidget(panel->tit2T, 144, 20);
1086 WMMoveWidget(panel->tit2T, 164, 40);
1087 WMAddNotificationObserver(changedTitle, panel, WMTextDidChangeNotification,
1088 panel->tit2T);
1090 panel->browser = WMCreateBrowser(panel->frame);
1091 WMSetBrowserTitled(panel->browser, False);
1092 WMResizeWidget(panel->browser, 295, 160);
1093 WMMoveWidget(panel->browser, 15, 65);
1094 WMSetBrowserFillColumnProc(panel->browser, fillBrowserColumn);
1095 WMHangData(panel->browser, panel);
1096 WMSetBrowserPathSeparator(panel->browser, "\r");
1097 WMSetBrowserAction(panel->browser, browserClick, panel);
1098 WMAddNotificationObserver(scrolledBrowser, panel,
1099 WMBrowserDidScrollNotification, panel->browser);
1100 /**/
1102 panel->labF = WMCreateFrame(panel->frame);
1103 WMResizeWidget(panel->labF, 190, 50);
1104 WMMoveWidget(panel->labF, 320, 10);
1105 WMSetFrameTitle(panel->labF, _("Label"));
1107 panel->labT = WMCreateTextField(panel->labF);
1108 WMResizeWidget(panel->labT, 170, 20);
1109 WMMoveWidget(panel->labT, 10, 20);
1110 WMAddNotificationObserver(changedItem, panel, WMTextDidChangeNotification,
1111 panel->labT);
1113 WMMapSubwidgets(panel->labF);
1115 panel->cmdF = WMCreateFrame(panel->frame);
1116 WMResizeWidget(panel->cmdF, 190, 50);
1117 WMMoveWidget(panel->cmdF, 320, 65);
1118 WMSetFrameTitle(panel->cmdF, _("Command"));
1120 panel->cmdP = WMCreatePopUpButton(panel->cmdF);
1121 WMResizeWidget(panel->cmdP, 170, 20);
1122 WMMoveWidget(panel->cmdP, 10, 20);
1123 WMAddPopUpButtonItem(panel->cmdP, _("Run Program"));
1124 WMAddPopUpButtonItem(panel->cmdP, _("Arrange Icons"));
1125 WMAddPopUpButtonItem(panel->cmdP, _("Hide Others"));
1126 WMAddPopUpButtonItem(panel->cmdP, _("Show All Windows"));
1127 WMAddPopUpButtonItem(panel->cmdP, _("Exit WindowMaker"));
1128 WMAddPopUpButtonItem(panel->cmdP, _("Exit X Session"));
1129 WMAddPopUpButtonItem(panel->cmdP, _("Start window manager"));
1130 WMAddPopUpButtonItem(panel->cmdP, _("Restart WindowMaker"));
1131 WMAddPopUpButtonItem(panel->cmdP, _("Save Session"));
1132 WMAddPopUpButtonItem(panel->cmdP, _("Clear Session"));
1133 WMAddPopUpButtonItem(panel->cmdP, _("Refresh Screen"));
1134 WMAddPopUpButtonItem(panel->cmdP, _("Info Panel"));
1135 WMAddPopUpButtonItem(panel->cmdP, _("Legal Panel"));
1136 WMSetPopUpButtonAction(panel->cmdP, changedCommand, panel);
1138 WMMapSubwidgets(panel->cmdF);
1140 panel->infoL = WMCreateLabel(panel->frame);
1141 WMResizeWidget(panel->infoL, 190, 50);
1142 WMMoveWidget(panel->infoL, 320, 65);
1143 WMSetLabelText(panel->infoL, _("Open workspace menu"));
1144 WMSetLabelRelief(panel->infoL, WRGroove);
1145 WMSetLabelTextAlignment(panel->infoL, WACenter);
1147 panel->noconfirmB = WMCreateSwitchButton(panel->frame);
1148 WMResizeWidget(panel->noconfirmB, 190, 50);
1149 WMMoveWidget(panel->noconfirmB, 320, 120);
1150 WMSetButtonText(panel->noconfirmB, _("No confirmation panel"));
1151 WMSetButtonAction(panel->noconfirmB, confirmClicked, panel);
1153 panel->pathF = WMCreateFrame(panel->frame);
1154 WMResizeWidget(panel->pathF, 190, 50);
1155 WMMoveWidget(panel->pathF, 320, 65);
1156 WMSetFrameTitle(panel->pathF, _("Menu Path/Directory List"));
1158 panel->pathT = WMCreateTextField(panel->pathF);
1159 WMResizeWidget(panel->pathT, 170, 20);
1160 WMMoveWidget(panel->pathT, 10, 20);
1161 WMAddNotificationObserver(changedItem, panel, WMTextDidChangeNotification,
1162 panel->pathT);
1164 WMMapSubwidgets(panel->pathF);
1166 panel->proF = WMCreateFrame(panel->frame);
1167 WMResizeWidget(panel->proF, 190, 50);
1168 WMMoveWidget(panel->proF, 320, 120);
1169 WMSetFrameTitle(panel->proF, _("Program to Run"));
1171 panel->proT = WMCreateTextField(panel->proF);
1172 WMResizeWidget(panel->proT, 170, 20);
1173 WMMoveWidget(panel->proT, 10, 20);
1174 WMAddNotificationObserver(changedItem, panel, WMTextDidChangeNotification,
1175 panel->proT);
1177 WMMapSubwidgets(panel->proF);
1179 panel->shoF = WMCreateFrame(panel->frame);
1180 WMResizeWidget(panel->shoF, 190, 50);
1181 WMMoveWidget(panel->shoF, 320, 175);
1182 WMSetFrameTitle(panel->shoF, _("Shortcut"));
1184 panel->shoT = WMCreateTextField(panel->shoF);
1185 WMResizeWidget(panel->shoT, 95, 20);
1186 WMMoveWidget(panel->shoT, 10, 20);
1187 WMAddNotificationObserver(changedItem, panel, WMTextDidChangeNotification,
1188 panel->shoT);
1190 panel->shoB = WMCreateCommandButton(panel->shoF);
1191 WMResizeWidget(panel->shoB, 70, 24);
1192 WMMoveWidget(panel->shoB, 110, 18);
1193 WMSetButtonText(panel->shoB, _("Capture"));
1194 WMSetButtonAction(panel->shoB, captureClick, panel);
1196 WMMapSubwidgets(panel->shoF);
1198 panel->guruB = WMCreateCommandButton(panel->frame);
1199 WMResizeWidget(panel->guruB, 180, 24);
1200 WMMoveWidget(panel->guruB, 325, 190);
1201 WMSetButtonText(panel->guruB, _("Ask help to the Guru"));
1202 WMSetButtonAction(panel->guruB, openGuru, panel);
1204 WMRealizeWidget(panel->frame);
1205 WMMapSubwidgets(panel->frame);
1207 showData(panel);
1213 static proplist_t
1214 preProcessMenu(proplist_t menu, int *hasWSMenu)
1216 proplist_t pmenu;
1217 proplist_t item;
1218 int i;
1220 pmenu = PLDeepCopy(menu);
1221 if (PLGetNumberOfElements(pmenu)==1) {
1222 return pmenu;
1224 for (i=1; i<PLGetNumberOfElements(pmenu); i++) {
1225 item = PLGetArrayElement(pmenu, i);
1226 if (isMenu(item)) {
1227 PLInsertArrayElement(pmenu, preProcessMenu(item, hasWSMenu), i);
1228 PLRemoveArrayElement(pmenu, i+1);
1229 PLRelease(item);
1230 } else if (strcmp(getItemCommand(item), "RESTART")==0) {
1231 if (getItemShortcut(item)) {
1232 if (PLGetNumberOfElements(item) == 4) {
1233 changeItemCommand(item, "RESTARTW");
1234 PLAppendArrayElement(item, PLMakeString(""));
1236 } else {
1237 if (PLGetNumberOfElements(item) == 2) {
1238 changeItemCommand(item, "RESTARTW");
1239 PLAppendArrayElement(item, PLMakeString(""));
1242 } else {
1243 if (strcmp(getItemCommand(item),"WORKSPACE_MENU")==0)
1244 *hasWSMenu = 1;
1245 if (getItemShortcut(item)) {
1246 if (PLGetNumberOfElements(item) == 4)
1247 PLAppendArrayElement(item, PLMakeString(""));
1248 } else {
1249 if (PLGetNumberOfElements(item) == 2)
1250 PLAppendArrayElement(item, PLMakeString(""));
1255 return pmenu;
1260 static proplist_t
1261 postProcessMenu(proplist_t menu)
1263 proplist_t pmenu;
1264 proplist_t item;
1265 int i;
1266 int count;
1268 pmenu = PLDeepCopy(menu);
1269 if (PLGetNumberOfElements(pmenu)==1) {
1270 return pmenu;
1272 count = PLGetNumberOfElements(pmenu);
1273 for (i=1; i<count; i++) {
1274 char *cmd;
1275 item = PLGetArrayElement(pmenu, i);
1276 if (isMenu(item)) {
1277 PLInsertArrayElement(pmenu, postProcessMenu(item), i);
1278 PLRemoveArrayElement(pmenu, i+1);
1279 PLRelease(item);
1280 } else {
1281 cmd = getItemCommand(item);
1282 if (strcmp(cmd, "RESTARTW")==0) {
1283 changeItemCommand(item, "RESTART");
1284 removeParameter(item);
1285 } else if (strcmp(cmd, "EXEC")==0 || strcmp(cmd, "OPEN_MENU")==0) {
1286 /* do nothing */
1287 } else if (strcmp(cmd, "RESTART")==0 || strcmp(cmd, "SHUTDOWN")==0
1288 || strcmp(cmd, "EXIT")==0) {
1289 char *tmp = getItemParameter(item);
1290 if (tmp && strlen(tmp)==0)
1291 removeParameter(item);
1292 } else {
1293 removeParameter(item);
1298 return pmenu;
1302 static proplist_t
1303 getDefaultMenu(_Panel *panel, int *hasWSMenu)
1305 proplist_t menu, pmenu;
1306 char *menuPath, *gspath;
1308 gspath = wusergnusteppath();
1310 menuPath = wmalloc(strlen(gspath)+128);
1311 /* if there is a localized plmenu for the tongue put it's filename here */
1312 sprintf(menuPath, _("%s/Library/WindowMaker/plmenu"), gspath);
1314 menu = PLGetProplistWithPath(menuPath);
1315 if (!menu) {
1316 wwarning("%s:could not read property list menu", menuPath);
1318 if (strcmp("%s/Library/WindowMaker/plmenu",
1319 _("%s/Library/WindowMaker/plmenu"))!=0) {
1321 sprintf(menuPath, "%s/Library/WindowMaker/plmenu", gspath);
1322 menu = PLGetProplistWithPath(menuPath);
1323 wwarning("%s:could not read property list menu", menuPath);
1325 if (!menu) {
1326 char buffer[512];
1328 sprintf(buffer, _("Could not open default menu from '%s'"),
1329 menuPath);
1330 WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win,
1331 _("Error"), buffer, _("OK"), NULL, NULL);
1335 free(gspath);
1336 free(menuPath);
1338 if (menu) {
1339 pmenu = preProcessMenu(menu, hasWSMenu);
1340 PLRelease(menu);
1341 } else {
1342 pmenu = NULL;
1345 return pmenu;
1349 static void
1350 showData(_Panel *panel)
1352 char *gspath;
1353 char *menuPath;
1354 proplist_t menu, pmenu, plPath;
1355 int hasWSMenu = 0;
1357 gspath = wusergnusteppath();
1359 menuPath = wmalloc(strlen(gspath)+32);
1360 strcpy(menuPath, gspath);
1361 free(gspath);
1362 strcat(menuPath, "/Defaults/WMRootMenu");
1364 menu = PLGetProplistWithPath(menuPath);
1365 pmenu = NULL;
1367 if (!menu || !PLIsArray(menu)) {
1368 if (AskMenuCopy(panel->win)) {
1369 panel->dontSave = 0;
1370 panel->unsaved = 1;
1372 pmenu = getDefaultMenu(panel, &hasWSMenu);
1373 } else {
1374 WMSetPopUpButtonEnabled(panel->cmd1P, False);
1375 WMSetPopUpButtonEnabled(panel->cmd2P, False);
1376 panel->dontSave = 1;
1378 if (!pmenu) {
1379 pmenu = PLMakeArrayFromElements(PLMakeString("Applications"),
1380 NULL);
1382 } else {
1383 pmenu = preProcessMenu(menu, &hasWSMenu);
1385 plPath = PLMakeString(menuPath);
1386 free(menuPath);
1387 PLSetFilename(pmenu, plPath);
1388 PLRelease(plPath);
1390 if (menu)
1391 PLRelease(menu);
1393 if (panel->itemClipboard) {
1394 PLRelease(panel->itemClipboard);
1395 panel->itemClipboard = NULL;
1397 panel->menu = pmenu;
1398 panel->editedItem = NULL;
1399 panel->capturing = 0;
1401 WMSetPopUpButtonItemEnabled(panel->cmd1P, CPaste, False);
1402 WMSetPopUpButtonItemEnabled(panel->cmd2P, CPaste, False);
1403 if (hasWSMenu) {
1404 WMSetPopUpButtonItemEnabled(panel->cmd1P, CAddWorkspace, False);
1405 WMSetPopUpButtonItemEnabled(panel->cmd2P, CAddWorkspace, False);
1407 WMLoadBrowserColumnZero(panel->browser);
1409 updateForItemType(panel, TNothing);
1413 static void
1414 storeData(_Panel *panel)
1416 proplist_t menu;
1418 if (!panel->unsaved || panel->dontSave)
1419 return;
1420 panel->unsaved = 0;
1422 menu = postProcessMenu(panel->menu);
1424 PLSetFilename(menu, PLGetFilename(panel->menu));
1426 PLSave(menu, YES);
1428 PLRelease(menu);
1432 Panel*
1433 InitMenu(WMScreen *scr, WMWindow *win)
1435 _Panel *panel;
1437 panel = wmalloc(sizeof(_Panel));
1438 memset(panel, 0, sizeof(_Panel));
1440 panel->sectionName = _("Applications Menu Definition");
1442 panel->win = win;
1444 panel->callbacks.createWidgets = createPanel;
1445 panel->callbacks.updateDomain = storeData;
1447 AddSection(panel, ICON_FILE);
1449 return panel;