Update for 0.51.0
[wmaker-crm.git] / WPrefs.app / Menu.c
blob5e224c44327cf07b585dd5debaf5d95d53a32fff
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);
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);
134 static Bool
135 isMenu(proplist_t item)
137 if (PLGetNumberOfElements(item)==1)
138 return True;
140 return PLIsArray(PLGetArrayElement(item, 1));
144 static void
145 splitOpenMenuParameter(char *str, char **dirs, char **prog)
147 char *p;
149 if (!(p = strstr(str, " WITH "))) {
150 *dirs = wstrdup(str);
151 *prog = NULL;
152 } else {
153 int i, j;
155 i = strlen(str);
156 j = strlen(p);
157 *dirs = wmalloc(i-j+1);
158 strncpy(*dirs, str, i-j+1);
159 (*dirs)[i-j] = 0;
161 p += 6;
162 while (isspace(*p)) p++;
163 if (*p!=0) {
164 *prog = wmalloc(j);
165 strcpy(*prog, p);
166 } else {
167 *prog = NULL;
173 static void
174 changeItemTitle(proplist_t item, char *title)
176 proplist_t tmp;
178 tmp = PLGetArrayElement(item, 0);
179 PLRelease(tmp);
180 PLRemoveArrayElement(item, 0);
181 PLInsertArrayElement(item, title?PLMakeString(title):PLMakeString(""), 0);
185 static void
186 removeParameter(proplist_t item)
188 proplist_t tmp;
189 int index;
191 if (strcmp(PLGetString(PLGetArrayElement(item, 1)), "SHORTCUT")==0) {
192 index = 4;
193 } else {
194 index = 2;
196 tmp = PLGetArrayElement(item, index);
197 PLRemoveArrayElement(item, index);
198 if (tmp)
199 PLRelease(tmp);
203 static void
204 changeItemParameter(proplist_t item, char *param)
206 proplist_t tmp;
207 int index;
209 if (strcmp(PLGetString(PLGetArrayElement(item, 1)), "SHORTCUT")==0) {
210 index = 4;
211 } else {
212 index = 2;
214 tmp = PLGetArrayElement(item, index);
215 PLRemoveArrayElement(item, index);
216 PLRelease(tmp);
217 tmp = param?PLMakeString(param):PLMakeString("");
218 PLInsertArrayElement(item, tmp, index);
222 static void
223 changeItemShortcut(proplist_t item, char *shortcut)
225 proplist_t tmp;
227 if (strcmp(PLGetString(PLGetArrayElement(item, 1)), "SHORTCUT")==0) {
228 if (shortcut) {
229 tmp = PLGetArrayElement(item, 2);
230 PLRemoveArrayElement(item, 2);
231 PLRelease(tmp);
232 PLInsertArrayElement(item, PLMakeString(shortcut), 2);
233 } else {
234 /* remove SHORTCUT keyword */
235 tmp = PLGetArrayElement(item, 1);
236 PLRemoveArrayElement(item, 1);
237 PLRelease(tmp);
238 /* remove the shortcut */
239 tmp = PLGetArrayElement(item, 1);
240 PLRemoveArrayElement(item, 1);
241 PLRelease(tmp);
243 } else {
244 if (shortcut) {
245 PLInsertArrayElement(item, PLMakeString("SHORTCUT"), 1);
246 PLInsertArrayElement(item, PLMakeString(shortcut), 2);
247 } else {
248 /* do nothing */
254 static void
255 changeItemCommand(proplist_t item, char *command)
257 proplist_t tmp;
259 tmp = PLGetArrayElement(item, 1);
260 if (strcmp(PLGetString(tmp), "SHORTCUT")==0) {
261 PLRelease(tmp);
262 PLRemoveArrayElement(item, 3);
263 PLInsertArrayElement(item, PLMakeString(command), 3);
264 } else {
265 PLRelease(tmp);
266 PLRemoveArrayElement(item, 1);
267 PLInsertArrayElement(item, PLMakeString(command), 1);
272 static char*
273 getItemTitle(proplist_t item)
275 return PLGetString(PLGetArrayElement(item, 0));
279 static char*
280 getItemParameter(proplist_t item)
282 proplist_t tmp;
284 tmp = PLGetArrayElement(item, 1);
285 if (strcmp(PLGetString(tmp), "SHORTCUT")==0) {
286 tmp = PLGetArrayElement(item, 4);
287 return tmp ? PLGetString(tmp) : NULL;
288 } else {
289 tmp = PLGetArrayElement(item, 2);
290 return tmp ? PLGetString(tmp) : NULL;
296 static char*
297 getItemShortcut(proplist_t item)
299 proplist_t tmp;
301 tmp = PLGetArrayElement(item, 1);
302 if (strcmp(PLGetString(tmp), "SHORTCUT")==0) {
303 return PLGetString(PLGetArrayElement(item, 2));
304 } else {
305 return NULL;
311 static char*
312 getItemCommand(proplist_t item)
314 proplist_t tmp;
315 char *str;
317 tmp = PLGetArrayElement(item, 1);
318 if (!tmp)
319 return "";
320 if (strcmp(PLGetString(tmp), "SHORTCUT")==0) {
321 str = PLGetString(PLGetArrayElement(item,3));
322 } else {
323 str = PLGetString(tmp);
325 return str;
329 static void
330 updateForItemType(_Panel *panel, int type)
332 if (type==TNothing) {
333 WMUnmapWidget(panel->labF);
334 } else {
335 WMMapWidget(panel->labF);
337 if (type==TExternalMenu || type==TNothing) {
338 WMUnmapWidget(panel->cmdF);
339 } else {
340 WMMapWidget(panel->cmdF);
342 if (type==TNothing || type==TWSMenu || type==TExternalMenu) {
343 WMUnmapWidget(panel->shoF);
344 } else {
345 WMMapWidget(panel->shoF);
347 if (type==TExec || type==TRestart || type==TExternalMenu) {
348 WMMapWidget(panel->proF);
349 } else {
350 WMUnmapWidget(panel->proF);
352 if (type==TExternalMenu) {
353 WMMapWidget(panel->pathF);
354 } else {
355 WMUnmapWidget(panel->pathF);
357 if (type==TExit) {
358 WMMapWidget(panel->noconfirmB);
359 } else {
360 WMUnmapWidget(panel->noconfirmB);
362 if (type==TWSMenu) {
363 WMMapWidget(panel->infoL);
364 } else {
365 WMUnmapWidget(panel->infoL);
367 if (type==TExternalMenu) {
368 WMMapWidget(panel->guruB);
369 } else {
370 WMUnmapWidget(panel->guruB);
372 if (type == TRestart) {
373 WMSetFrameTitle(panel->proF, _("Window Manager"));
374 } else if (type == TExternalMenu) {
375 WMSetFrameTitle(panel->proF, _("Program to open files"));
376 } else {
377 WMSetFrameTitle(panel->proF, _("Program to Run"));
382 proplist_t
383 getItemOfSelectedEntry(WMBrowser *bPtr)
385 proplist_t item;
386 proplist_t menu;
387 int i;
389 i = WMGetBrowserSelectedColumn(bPtr);
390 menu = (proplist_t)WMGetHangedData(WMGetBrowserListInColumn(bPtr, i));
392 i = WMGetBrowserSelectedRowInColumn(bPtr, i);
393 item = PLGetArrayElement(menu, i+1);
395 return item;
399 static void
400 performCommand(WMWidget *w, void *data)
402 _Panel *panel = (_Panel*)data;
403 WMPopUpButton *pop = (WMPopUpButton*)w;
404 proplist_t menuItem = NULL;
405 proplist_t menu;
406 int column;
407 int row;
408 static int cmdIndex=0;
409 WMList *list;
410 char *title = NULL;
412 column = WMGetBrowserFirstVisibleColumn(panel->browser);
413 if (pop == panel->cmd2P) {
414 column++;
417 if (column >= WMGetBrowserNumberOfColumns(panel->browser))
418 return;
420 list = WMGetBrowserListInColumn(panel->browser, column);
421 menu = WMGetHangedData(list);
423 row = WMGetBrowserSelectedRowInColumn(panel->browser, column);
425 switch (WMGetPopUpButtonSelectedItem(pop)) {
426 case CAddCommand:
427 title = wmalloc(strlen(_("New Command %i"))+6);
428 sprintf(title, _("New Command %i"), cmdIndex++);
429 menuItem = PLMakeArrayFromElements(PLMakeString(title),
430 PLMakeString("EXEC"),
431 PLMakeString(""),
432 NULL);
433 break;
434 case CAddSubmenu:
435 title = wstrdup(_("New Submenu"));
436 menuItem = PLMakeArrayFromElements(PLMakeString(title),
437 NULL);
438 break;
439 case CAddExternal:
440 title = wstrdup(_("External Menu"));
441 menuItem = PLMakeArrayFromElements(PLMakeString(title),
442 PLMakeString("OPEN_MENU"),
443 PLMakeString(""),
444 NULL);
445 break;
446 case CAddWorkspace:
447 title = wstrdup(_("Workspaces"));
448 menuItem = PLMakeArrayFromElements(PLMakeString(title),
449 PLMakeString("WORKSPACE_MENU"),
450 NULL);
451 WMSetPopUpButtonItemEnabled(panel->cmd1P, CAddWorkspace, False);
452 WMSetPopUpButtonItemEnabled(panel->cmd2P, CAddWorkspace, False);
453 break;
454 case CRemove:
455 if (row < 0)
456 return;
457 WMRemoveBrowserItem(panel->browser, column, row);
458 menuItem = PLGetArrayElement(menu, row+1);
459 if (strcmp(getItemCommand(menuItem), "WORKSPACE_MENU")==0) {
460 WMSetPopUpButtonItemEnabled(panel->cmd1P, CAddWorkspace, True);
461 WMSetPopUpButtonItemEnabled(panel->cmd2P, CAddWorkspace, True);
463 PLRemoveArrayElement(menu, row+1);
464 PLRelease(menuItem);
465 updateForItemType(panel, TNothing);
466 panel->editedItem = NULL;
467 panel->unsaved = 1;
468 return;
469 case CCut:
470 if (row < 0)
471 return;
472 if (panel->itemClipboard
473 && strcmp(getItemCommand(panel->itemClipboard), "WORKSPACE_MENU")==0){
474 WMSetPopUpButtonItemEnabled(panel->cmd1P, CAddWorkspace, True);
475 WMSetPopUpButtonItemEnabled(panel->cmd2P, CAddWorkspace, True);
477 if (panel->itemClipboard)
478 PLRelease(panel->itemClipboard);
480 WMRemoveBrowserItem(panel->browser, column, row);
481 menuItem = PLGetArrayElement(menu, row+1);
482 PLRemoveArrayElement(menu, row+1);
483 updateForItemType(panel, TNothing);
485 panel->itemClipboard = menuItem;
487 WMSetPopUpButtonItemEnabled(panel->cmd1P, CPaste, True);
488 WMSetPopUpButtonItemEnabled(panel->cmd2P, CPaste, True);
489 panel->unsaved = 1;
490 return;
491 case CCopy:
492 if (row < 0)
493 return;
494 if (panel->itemClipboard
495 && strcmp(getItemCommand(panel->itemClipboard), "WORKSPACE_MENU")==0){
496 WMSetPopUpButtonItemEnabled(panel->cmd1P, CAddWorkspace, True);
497 WMSetPopUpButtonItemEnabled(panel->cmd2P, CAddWorkspace, True);
499 if (panel->itemClipboard)
500 PLRelease(panel->itemClipboard);
501 panel->itemClipboard = NULL;
502 menuItem = PLGetArrayElement(menu, row+1);
503 if (strcmp(getItemCommand(menuItem), "WORKSPACE_MENU")==0)
504 return;
505 panel->itemClipboard = PLDeepCopy(menuItem);
507 WMSetPopUpButtonItemEnabled(panel->cmd1P, CPaste, True);
508 WMSetPopUpButtonItemEnabled(panel->cmd2P, CPaste, True);
509 return;
510 case CPaste:
511 menuItem = panel->itemClipboard;
512 title = wstrdup(getItemTitle(menuItem));
513 panel->itemClipboard = NULL;
514 WMSetPopUpButtonItemEnabled(panel->cmd1P, CPaste, False);
515 WMSetPopUpButtonItemEnabled(panel->cmd2P, CPaste, False);
516 break;
519 if (row>=0) row++;
520 WMInsertBrowserItem(panel->browser, column, row, title, isMenu(menuItem));
521 if (row<0)
522 PLAppendArrayElement(menu, menuItem);
523 else
524 PLInsertArrayElement(menu, menuItem, row+1);
525 free(title);
526 panel->unsaved = 1;
530 static void
531 browserClick(WMWidget *w, void *data)
533 _Panel *panel = (_Panel*)data;
534 proplist_t item;
535 char *command;
537 /* stop shortcut capture */
538 panel->capturing = 0;
540 item = getItemOfSelectedEntry(panel->browser);
542 panel->editedItem = item;
544 /* set title */
545 WMSetTextFieldText(panel->labT, getItemTitle(item));
547 if (isMenu(item)) {
548 updateForItemType(panel, TNothing);
550 WMSetPopUpButtonEnabled(panel->cmd2P, True);
551 return;
552 } else {
553 int column = WMGetBrowserSelectedColumn(panel->browser);
555 if (column == WMGetBrowserNumberOfColumns(panel->browser)-1
556 && column > 0)
557 WMSetPopUpButtonEnabled(panel->cmd2P, True);
558 else
559 WMSetPopUpButtonEnabled(panel->cmd2P, False);
561 if (column==WMGetBrowserFirstVisibleColumn(panel->browser)) {
562 /* second column is empty, because selected item is not a submenu */
563 WMSetTextFieldText(panel->tit2T, NULL);
567 command = getItemCommand(item);
569 WMSetTextFieldText(panel->shoT, getItemShortcut(item));
571 if (strcmp(command, "OPEN_MENU")==0) {
572 char *p, *c;
574 splitOpenMenuParameter(getItemParameter(item), &p, &c);
575 WMSetTextFieldText(panel->pathT, p);
576 WMSetTextFieldText(panel->proT, c);
577 if (p)
578 free(p);
579 if (c)
580 free(c);
581 updateForItemType(panel, TExternalMenu);
582 } else if (strcmp(command, "EXEC")==0) {
583 WMSetTextFieldText(panel->proT, getItemParameter(item));
584 WMSetPopUpButtonSelectedItem(panel->cmdP, CpExec);
585 updateForItemType(panel, TExec);
586 } else if (strcmp(command, "WORKSPACE_MENU")==0) {
587 updateForItemType(panel, TWSMenu);
588 } else if (strcmp(command, "EXIT")==0) {
589 WMSetPopUpButtonSelectedItem(panel->cmdP, CpExit);
590 updateForItemType(panel, TExit);
591 } else if (strcmp(command, "SHUTDOWN")==0) {
592 WMSetPopUpButtonSelectedItem(panel->cmdP, CpShutdown);
593 updateForItemType(panel, TExit);
594 } else if (strcmp(command, "RESTARTW")==0) {
595 WMSetPopUpButtonSelectedItem(panel->cmdP, CpRestartWM);
596 updateForItemType(panel, TRestartWM);
597 } else if (strcmp(command, "RESTART")==0) {
598 WMSetPopUpButtonSelectedItem(panel->cmdP, CpRestart);
599 WMSetTextFieldText(panel->proT, getItemParameter(item));
600 updateForItemType(panel, TRestart);
601 } else {
602 /* simple commands */
603 if (strcmp(command, "ARRANGE_ICONS")==0)
604 WMSetPopUpButtonSelectedItem(panel->cmdP, CpArrange);
605 else if (strcmp(command, "HIDE_OTHERS")==0)
606 WMSetPopUpButtonSelectedItem(panel->cmdP, CpHide);
607 else if (strcmp(command, "SHOW_ALL")==0)
608 WMSetPopUpButtonSelectedItem(panel->cmdP, CpShow);
609 else if (strcmp(command, "SAVE_SESSION")==0)
610 WMSetPopUpButtonSelectedItem(panel->cmdP, CpSaveSession);
611 else if (strcmp(command, "CLEAR_SESSION")==0)
612 WMSetPopUpButtonSelectedItem(panel->cmdP, CpClearSession);
613 else if (strcmp(command, "REFRESH")==0)
614 WMSetPopUpButtonSelectedItem(panel->cmdP, CpRefresh);
615 else if (strcmp(command, "INFO_PANEL")==0)
616 WMSetPopUpButtonSelectedItem(panel->cmdP, CpInfo);
617 else if (strcmp(command, "LEGAL_PANEL")==0)
618 WMSetPopUpButtonSelectedItem(panel->cmdP, CpLegal);
619 updateForItemType(panel, TSimpleCommand);
624 static void
625 fillBrowserColumn(WMBrowser *bPtr, int column)
627 _Panel *panel = (_Panel*)WMGetHangedData(bPtr);
628 proplist_t menuItem;
629 proplist_t menuList = NULL;
630 int i;
632 if (column > 0) {
633 menuList = getItemOfSelectedEntry(panel->browser);
634 if (column > WMGetBrowserFirstVisibleColumn(bPtr))
635 WMSetTextFieldText(panel->tit2T, getItemTitle(menuList));
636 else
637 WMSetTextFieldText(panel->tit1T, getItemTitle(menuList));
638 } else {
639 menuList = panel->menu;
640 WMSetTextFieldText(panel->tit1T, getItemTitle(panel->menu));
643 WMHangData(WMGetBrowserListInColumn(bPtr, column), menuList);
644 for (i=1; i<PLGetNumberOfElements(menuList); i++) {
645 menuItem = PLGetArrayElement(menuList, i);
646 WMInsertBrowserItem(bPtr, column, -1, getItemTitle(menuItem),
647 isMenu(menuItem));
654 static void
655 changedItem(void *observerData, WMNotification *notification)
657 _Panel *panel = (_Panel*)observerData;
658 WMTextField *t = (WMTextField*)WMGetNotificationObject(notification);
659 proplist_t item = panel->editedItem;
660 WMList *list;
661 WMListItem *litem;
662 char *command;
663 char *str;
665 if (!item)
666 return;
668 panel->unsaved = 1;
669 if (!isMenu(item)) {
670 command = getItemCommand(item);
672 if (t == panel->shoT) {
673 str = WMGetTextFieldText(t);
674 if (strlen(str)==0) {
675 free(str);
676 str = NULL;
678 changeItemShortcut(item, str);
679 if (str)
680 free(str);
681 } else if (t == panel->labT) {
682 int column;
684 str = WMGetTextFieldText(t);
685 if (!str)
686 str = wstrdup("");
687 changeItemTitle(item, str);
688 column = WMGetBrowserSelectedColumn(panel->browser);
689 list = WMGetBrowserListInColumn(panel->browser, column);
690 litem = WMGetListSelectedItem(list);
692 free(litem->text);
693 litem->text = str;
695 WMRedisplayWidget(list);
696 } else if (strcmp(command, "EXEC")==0
697 || strcmp(command, "RESTART")==0) {
698 if (t == panel->proT) {
699 str = WMGetTextFieldText(t);
701 changeItemParameter(item, str);
703 free(str);
705 } else if (strcmp(command, "OPEN_MENU")==0) {
706 char *text;
707 char *str2;
709 str = WMGetTextFieldText(panel->pathT);
710 str2 = WMGetTextFieldText(panel->proT);
711 text = wmalloc(strlen(str)+strlen(str2)+16);
712 strcpy(text, str);
713 free(str);
714 if (strlen(str2)>0) {
715 strcat(text, " WITH ");
716 strcat(text, str2);
718 free(str2);
719 changeItemParameter(item, text);
720 free(text);
726 static void
727 changedTitle(void *observerData, WMNotification *notification)
729 _Panel *panel = (_Panel*)observerData;
730 WMTextField *t = (WMTextField*)WMGetNotificationObject(notification);
731 proplist_t menu;
732 WMList *list;
733 int column;
734 char *txt;
736 column = WMGetBrowserFirstVisibleColumn(panel->browser);
737 if (panel->tit2T == t)
738 column++;
740 list = WMGetBrowserListInColumn(panel->browser, column);
741 if (!list) {
742 return;
745 menu = (proplist_t)WMGetHangedData(list);
746 if (!menu)
747 return;
749 txt = WMGetTextFieldText(t);
750 changeItemTitle(menu, txt);
752 if (column > 0) {
753 WMListItem *litem;
755 list = WMGetBrowserListInColumn(panel->browser, column-1);
756 litem = WMGetListSelectedItem(list);
758 free(litem->text);
759 litem->text = txt;
761 WMRedisplayWidget(list);
762 } else {
763 free(txt);
765 panel->unsaved = 1;
769 static void
770 changedCommand(WMWidget *w, void *data)
772 _Panel *panel = (_Panel*)data;
773 int i;
774 char *tmp;
776 panel->unsaved = 1;
777 i = WMGetPopUpButtonSelectedItem(panel->cmdP);
778 changeItemParameter(panel->editedItem, "");
779 switch (i) {
780 case CpExec:
781 if (strcmp(getItemCommand(panel->editedItem), "EXEC")!=0) {
782 changeItemCommand(panel->editedItem, "EXEC");
783 tmp = WMGetTextFieldText(panel->proT);
784 changeItemParameter(panel->editedItem, tmp);
785 free(tmp);
786 updateForItemType(panel, TExec);
788 break;
789 case CpArrange:
790 if (strcmp(getItemCommand(panel->editedItem), "ARRANGE_ICONS")!=0) {
791 changeItemCommand(panel->editedItem, "ARRANGE_ICONS");
792 updateForItemType(panel, TSimpleCommand);
794 break;
795 case CpHide:
796 if (strcmp(getItemCommand(panel->editedItem), "HIDE_OTHERS")!=0) {
797 changeItemCommand(panel->editedItem, "HIDE_OTHERS");
798 updateForItemType(panel, TSimpleCommand);
800 break;
801 case CpShow:
802 if (strcmp(getItemCommand(panel->editedItem), "SHOW_ALL")!=0) {
803 changeItemCommand(panel->editedItem, "SHOW_ALL");
804 updateForItemType(panel, TSimpleCommand);
806 break;
807 case CpExit:
808 if (strcmp(getItemCommand(panel->editedItem), "EXIT")!=0) {
809 changeItemCommand(panel->editedItem, "EXIT");
810 updateForItemType(panel, TExit);
812 /* fall through */
813 case CpShutdown:
814 if (strcmp(getItemCommand(panel->editedItem), "SHUTDOWN")!=0) {
815 changeItemCommand(panel->editedItem, "SHUTDOWN");
816 updateForItemType(panel, TExit);
818 if (WMGetButtonSelected(panel->noconfirmB))
819 changeItemParameter(panel->editedItem, "QUICK");
820 else
821 changeItemParameter(panel->editedItem, "");
822 break;
823 case CpRestartWM:
824 changeItemCommand(panel->editedItem, "RESTARTW");
825 updateForItemType(panel, TRestartWM);
826 break;
827 case CpRestart:
828 changeItemCommand(panel->editedItem, "RESTART");
829 updateForItemType(panel, TRestart);
830 tmp = WMGetTextFieldText(panel->proT);
831 changeItemParameter(panel->editedItem, tmp);
832 free(tmp);
833 break;
834 case CpSaveSession:
835 if (strcmp(getItemCommand(panel->editedItem), "SAVE_SESSION")!=0) {
836 changeItemCommand(panel->editedItem, "SAVE_SESSION");
837 updateForItemType(panel, TSimpleCommand);
839 break;
840 case CpClearSession:
841 if (strcmp(getItemCommand(panel->editedItem), "CLEAR_SESSION")!=0) {
842 changeItemCommand(panel->editedItem, "CLEAR_SESSION");
843 updateForItemType(panel, TSimpleCommand);
845 break;
846 case CpRefresh:
847 if (strcmp(getItemCommand(panel->editedItem), "REFRESH")!=0) {
848 changeItemCommand(panel->editedItem, "REFRESH");
849 updateForItemType(panel, TSimpleCommand);
851 break;
852 case CpInfo:
853 if (strcmp(getItemCommand(panel->editedItem), "INFO_PANEL")!=0) {
854 changeItemCommand(panel->editedItem, "INFO_PANEL");
855 updateForItemType(panel, TSimpleCommand);
857 break;
858 case CpLegal:
859 if (strcmp(getItemCommand(panel->editedItem), "LEGAL_PANEL")!=0) {
860 changeItemCommand(panel->editedItem, "LEGAL_PANEL");
861 updateForItemType(panel, TSimpleCommand);
863 break;
871 static char*
872 captureShortcut(Display *dpy, _Panel *panel)
874 XEvent ev;
875 KeySym ksym;
876 char buffer[64];
877 char *key = NULL;
879 while (panel->capturing) {
880 XAllowEvents(dpy, AsyncKeyboard, CurrentTime);
881 WMNextEvent(dpy, &ev);
882 if (ev.type==KeyPress && ev.xkey.keycode!=0) {
883 ksym = XKeycodeToKeysym(dpy, ev.xkey.keycode, 0);
884 if (!IsModifierKey(ksym)) {
885 key=XKeysymToString(ksym);
886 panel->capturing = 0;
887 break;
890 WMHandleEvent(&ev);
893 if (!key)
894 return NULL;
896 buffer[0] = 0;
898 if (ev.xkey.state & ControlMask) {
899 strcat(buffer, "Control+");
901 if (ev.xkey.state & ShiftMask) {
902 strcat(buffer, "Shift+");
904 if (ev.xkey.state & Mod1Mask) {
905 strcat(buffer, "Mod1+");
907 if (ev.xkey.state & Mod2Mask) {
908 strcat(buffer, "Mod2+");
910 if (ev.xkey.state & Mod3Mask) {
911 strcat(buffer, "Mod3+");
913 if (ev.xkey.state & Mod4Mask) {
914 strcat(buffer, "Mod4+");
916 if (ev.xkey.state & Mod5Mask) {
917 strcat(buffer, "Mod5+");
919 strcat(buffer, key);
921 return wstrdup(buffer);
925 static void
926 captureClick(WMWidget *w, void *data)
928 _Panel *panel = (_Panel*)data;
929 Display *dpy = WMScreenDisplay(WMWidgetScreen(panel->win));
930 char *shortcut;
932 if (!panel->capturing) {
933 panel->capturing = 1;
934 WMSetButtonText(w, _("Cancel"));
935 XGrabKeyboard(dpy, WMWidgetXID(panel->win), True, GrabModeAsync,
936 GrabModeAsync, CurrentTime);
937 shortcut = captureShortcut(dpy, panel);
938 if (shortcut) {
939 WMSetTextFieldText(panel->shoT, shortcut);
940 changeItemShortcut(panel->editedItem, shortcut);
941 panel->unsaved = 1;
943 free(shortcut);
945 panel->capturing = 0;
946 WMSetButtonText(w, _("Capture"));
947 XUngrabKeyboard(dpy, CurrentTime);
952 static void
953 scrolledBrowser(void *observerData, WMNotification *notification)
955 _Panel *panel = (_Panel*)observerData;
956 int column;
957 WMList *list;
958 proplist_t item;
960 column = WMGetBrowserFirstVisibleColumn(panel->browser);
962 list = WMGetBrowserListInColumn(panel->browser, column);
963 item = WMGetHangedData(list);
964 WMSetTextFieldText(panel->tit1T, getItemTitle(item));
966 list = WMGetBrowserListInColumn(panel->browser, column+1);
967 if (list) {
968 item = WMGetHangedData(list);
969 WMSetTextFieldText(panel->tit2T, getItemTitle(item));
974 static void
975 confirmClicked(WMWidget *w, void *data)
977 _Panel *panel = (_Panel*)data;
979 if (WMGetButtonSelected(panel->noconfirmB)) {
980 changeItemParameter(panel->editedItem, "QUICK");
981 } else {
982 changeItemParameter(panel->editedItem, "");
984 panel->unsaved = 1;
989 static void
990 openGuru(WMWidget *w, void *data)
992 _Panel *panel = (_Panel*)data;
993 char *def;
994 char *path, *cmd;
996 def = OpenMenuGuru(GetWindow(panel));
997 if (def) {
998 changeItemParameter(panel->editedItem, def);
999 splitOpenMenuParameter(def, &path, &cmd);
1000 free(def);
1001 WMSetTextFieldText(panel->pathT, path);
1002 if (path)
1003 free(path);
1005 WMSetTextFieldText(panel->proT, cmd);
1006 if (cmd)
1007 free(cmd);
1008 panel->unsaved = 1;
1013 static void
1014 createPanel(_Panel *p)
1016 _Panel *panel = (_Panel*)p;
1019 panel->frame = WMCreateFrame(panel->win);
1020 WMResizeWidget(panel->frame, FRAME_WIDTH, FRAME_HEIGHT);
1021 WMMoveWidget(panel->frame, FRAME_LEFT, FRAME_TOP);
1023 panel->cmd1P = WMCreatePopUpButton(panel->frame);
1024 WMSetPopUpButtonAction(panel->cmd1P, performCommand, panel);
1025 WMResizeWidget(panel->cmd1P, 144, 20);
1026 WMMoveWidget(panel->cmd1P, 15, 15);
1027 WMSetPopUpButtonPullsDown(panel->cmd1P, True);
1028 WMSetPopUpButtonText(panel->cmd1P, _("Commands"));
1029 WMAddPopUpButtonItem(panel->cmd1P, _("Add Command"));
1030 WMAddPopUpButtonItem(panel->cmd1P, _("Add Submenu"));
1031 WMAddPopUpButtonItem(panel->cmd1P, _("Add External Menu"));
1032 WMAddPopUpButtonItem(panel->cmd1P, _("Add Workspace Menu"));
1033 WMAddPopUpButtonItem(panel->cmd1P, _("Remove Item"));
1034 WMAddPopUpButtonItem(panel->cmd1P, _("Cut Item"));
1035 WMAddPopUpButtonItem(panel->cmd1P, _("Copy Item"));
1036 WMAddPopUpButtonItem(panel->cmd1P, _("Paste Item"));
1038 panel->cmd2P = WMCreatePopUpButton(panel->frame);
1039 WMSetPopUpButtonAction(panel->cmd2P, performCommand, panel);
1040 WMResizeWidget(panel->cmd2P, 144, 20);
1041 WMMoveWidget(panel->cmd2P, 164, 15);
1042 WMSetPopUpButtonPullsDown(panel->cmd2P, True);
1043 WMSetPopUpButtonText(panel->cmd2P, _("Commands"));
1044 WMAddPopUpButtonItem(panel->cmd2P, _("Add Command"));
1045 WMAddPopUpButtonItem(panel->cmd2P, _("Add Submenu"));
1046 WMAddPopUpButtonItem(panel->cmd2P, _("Add External Menu"));
1047 WMAddPopUpButtonItem(panel->cmd2P, _("Add Workspace Menu"));
1048 WMAddPopUpButtonItem(panel->cmd2P, _("Remove Item"));
1049 WMAddPopUpButtonItem(panel->cmd2P, _("Cut Item"));
1050 WMAddPopUpButtonItem(panel->cmd2P, _("Copy Item"));
1051 WMAddPopUpButtonItem(panel->cmd2P, _("Paste Item"));
1053 panel->tit1T = WMCreateTextField(panel->frame);
1054 WMResizeWidget(panel->tit1T, 144, 20);
1055 WMMoveWidget(panel->tit1T, 15, 40);
1056 WMAddNotificationObserver(changedTitle, panel, WMTextDidChangeNotification,
1057 panel->tit1T);
1059 panel->tit2T = WMCreateTextField(panel->frame);
1060 WMResizeWidget(panel->tit2T, 144, 20);
1061 WMMoveWidget(panel->tit2T, 164, 40);
1062 WMAddNotificationObserver(changedTitle, panel, WMTextDidChangeNotification,
1063 panel->tit2T);
1065 panel->browser = WMCreateBrowser(panel->frame);
1066 WMSetBrowserTitled(panel->browser, False);
1067 WMResizeWidget(panel->browser, 295, 160);
1068 WMMoveWidget(panel->browser, 15, 65);
1069 WMSetBrowserFillColumnProc(panel->browser, fillBrowserColumn);
1070 WMHangData(panel->browser, panel);
1071 WMSetBrowserPathSeparator(panel->browser, "\r");
1072 WMSetBrowserAction(panel->browser, browserClick, panel);
1073 WMAddNotificationObserver(scrolledBrowser, panel,
1074 WMBrowserDidScrollNotification, panel->browser);
1075 /**/
1077 panel->labF = WMCreateFrame(panel->frame);
1078 WMResizeWidget(panel->labF, 190, 50);
1079 WMMoveWidget(panel->labF, 320, 10);
1080 WMSetFrameTitle(panel->labF, _("Label"));
1082 panel->labT = WMCreateTextField(panel->labF);
1083 WMResizeWidget(panel->labT, 170, 20);
1084 WMMoveWidget(panel->labT, 10, 20);
1085 WMAddNotificationObserver(changedItem, panel, WMTextDidChangeNotification,
1086 panel->labT);
1088 WMMapSubwidgets(panel->labF);
1090 panel->cmdF = WMCreateFrame(panel->frame);
1091 WMResizeWidget(panel->cmdF, 190, 50);
1092 WMMoveWidget(panel->cmdF, 320, 65);
1093 WMSetFrameTitle(panel->cmdF, _("Command"));
1095 panel->cmdP = WMCreatePopUpButton(panel->cmdF);
1096 WMResizeWidget(panel->cmdP, 170, 20);
1097 WMMoveWidget(panel->cmdP, 10, 20);
1098 WMAddPopUpButtonItem(panel->cmdP, _("Run Program"));
1099 WMAddPopUpButtonItem(panel->cmdP, _("Arrange Icons"));
1100 WMAddPopUpButtonItem(panel->cmdP, _("Hide Others"));
1101 WMAddPopUpButtonItem(panel->cmdP, _("Show All Windows"));
1102 WMAddPopUpButtonItem(panel->cmdP, _("Exit WindowMaker"));
1103 WMAddPopUpButtonItem(panel->cmdP, _("Exit X Session"));
1104 WMAddPopUpButtonItem(panel->cmdP, _("Start window manager"));
1105 WMAddPopUpButtonItem(panel->cmdP, _("Restart WindowMaker"));
1106 WMAddPopUpButtonItem(panel->cmdP, _("Save Session"));
1107 WMAddPopUpButtonItem(panel->cmdP, _("Clear Session"));
1108 WMAddPopUpButtonItem(panel->cmdP, _("Refresh Screen"));
1109 WMAddPopUpButtonItem(panel->cmdP, _("Info Panel"));
1110 WMAddPopUpButtonItem(panel->cmdP, _("Legal Panel"));
1111 WMSetPopUpButtonAction(panel->cmdP, changedCommand, panel);
1113 WMMapSubwidgets(panel->cmdF);
1115 panel->infoL = WMCreateLabel(panel->frame);
1116 WMResizeWidget(panel->infoL, 190, 50);
1117 WMMoveWidget(panel->infoL, 320, 65);
1118 WMSetLabelText(panel->infoL, _("Open workspace menu"));
1119 WMSetLabelRelief(panel->infoL, WRGroove);
1120 WMSetLabelTextAlignment(panel->infoL, WACenter);
1122 panel->noconfirmB = WMCreateSwitchButton(panel->frame);
1123 WMResizeWidget(panel->noconfirmB, 190, 50);
1124 WMMoveWidget(panel->noconfirmB, 320, 120);
1125 WMSetButtonText(panel->noconfirmB, _("No confirmation panel"));
1126 WMSetButtonAction(panel->noconfirmB, confirmClicked, panel);
1128 panel->pathF = WMCreateFrame(panel->frame);
1129 WMResizeWidget(panel->pathF, 190, 50);
1130 WMMoveWidget(panel->pathF, 320, 65);
1131 WMSetFrameTitle(panel->pathF, _("Menu Path/Directory List"));
1133 panel->pathT = WMCreateTextField(panel->pathF);
1134 WMResizeWidget(panel->pathT, 170, 20);
1135 WMMoveWidget(panel->pathT, 10, 20);
1136 WMAddNotificationObserver(changedItem, panel, WMTextDidChangeNotification,
1137 panel->pathT);
1139 WMMapSubwidgets(panel->pathF);
1141 panel->proF = WMCreateFrame(panel->frame);
1142 WMResizeWidget(panel->proF, 190, 50);
1143 WMMoveWidget(panel->proF, 320, 120);
1144 WMSetFrameTitle(panel->proF, _("Program to Run"));
1146 panel->proT = WMCreateTextField(panel->proF);
1147 WMResizeWidget(panel->proT, 170, 20);
1148 WMMoveWidget(panel->proT, 10, 20);
1149 WMAddNotificationObserver(changedItem, panel, WMTextDidChangeNotification,
1150 panel->proT);
1152 WMMapSubwidgets(panel->proF);
1154 panel->shoF = WMCreateFrame(panel->frame);
1155 WMResizeWidget(panel->shoF, 190, 50);
1156 WMMoveWidget(panel->shoF, 320, 175);
1157 WMSetFrameTitle(panel->shoF, _("Shortcut"));
1159 panel->shoT = WMCreateTextField(panel->shoF);
1160 WMResizeWidget(panel->shoT, 95, 20);
1161 WMMoveWidget(panel->shoT, 10, 20);
1162 WMAddNotificationObserver(changedItem, panel, WMTextDidChangeNotification,
1163 panel->shoT);
1165 panel->shoB = WMCreateCommandButton(panel->shoF);
1166 WMResizeWidget(panel->shoB, 70, 24);
1167 WMMoveWidget(panel->shoB, 110, 18);
1168 WMSetButtonText(panel->shoB, _("Capture"));
1169 WMSetButtonAction(panel->shoB, captureClick, panel);
1171 WMMapSubwidgets(panel->shoF);
1173 panel->guruB = WMCreateCommandButton(panel->frame);
1174 WMResizeWidget(panel->guruB, 180, 24);
1175 WMMoveWidget(panel->guruB, 325, 190);
1176 WMSetButtonText(panel->guruB, _("Ask help to the Guru"));
1177 WMSetButtonAction(panel->guruB, openGuru, panel);
1179 WMRealizeWidget(panel->frame);
1180 WMMapSubwidgets(panel->frame);
1182 showData(panel);
1188 static proplist_t
1189 preProcessMenu(proplist_t menu, int *hasWSMenu)
1191 proplist_t pmenu;
1192 proplist_t item;
1193 int i;
1195 pmenu = PLDeepCopy(menu);
1196 if (PLGetNumberOfElements(pmenu)==1) {
1197 return pmenu;
1199 for (i=1; i<PLGetNumberOfElements(pmenu); i++) {
1200 item = PLGetArrayElement(pmenu, i);
1201 if (isMenu(item)) {
1202 PLInsertArrayElement(pmenu, preProcessMenu(item, hasWSMenu), i);
1203 PLRemoveArrayElement(pmenu, i+1);
1204 PLRelease(item);
1205 } else if (strcmp(getItemCommand(item), "RESTART")==0) {
1206 if (getItemShortcut(item)) {
1207 if (PLGetNumberOfElements(item) == 4) {
1208 changeItemCommand(item, "RESTARTW");
1209 PLAppendArrayElement(item, PLMakeString(""));
1211 } else {
1212 if (PLGetNumberOfElements(item) == 2) {
1213 changeItemCommand(item, "RESTARTW");
1214 PLAppendArrayElement(item, PLMakeString(""));
1217 } else {
1218 if (strcmp(getItemCommand(item),"WORKSPACE_MENU")==0)
1219 *hasWSMenu = 1;
1220 if (getItemShortcut(item)) {
1221 if (PLGetNumberOfElements(item) == 4)
1222 PLAppendArrayElement(item, PLMakeString(""));
1223 } else {
1224 if (PLGetNumberOfElements(item) == 2)
1225 PLAppendArrayElement(item, PLMakeString(""));
1230 return pmenu;
1235 static proplist_t
1236 postProcessMenu(proplist_t menu)
1238 proplist_t pmenu;
1239 proplist_t item;
1240 int i;
1241 int count;
1243 pmenu = PLDeepCopy(menu);
1244 if (PLGetNumberOfElements(pmenu)==1) {
1245 return pmenu;
1247 count = PLGetNumberOfElements(pmenu);
1248 for (i=1; i<count; i++) {
1249 char *cmd;
1250 item = PLGetArrayElement(pmenu, i);
1251 if (isMenu(item)) {
1252 PLInsertArrayElement(pmenu, postProcessMenu(item), i);
1253 PLRemoveArrayElement(pmenu, i+1);
1254 PLRelease(item);
1255 } else {
1256 cmd = getItemCommand(item);
1257 if (strcmp(cmd, "RESTARTW")==0) {
1258 changeItemCommand(item, "RESTART");
1259 removeParameter(item);
1260 } else if (strcmp(cmd, "EXEC")==0 || strcmp(cmd, "OPEN_MENU")==0) {
1261 /* do nothing */
1262 } else if (strcmp(cmd, "RESTART")==0 || strcmp(cmd, "SHUTDOWN")==0
1263 || strcmp(cmd, "EXIT")==0) {
1264 char *tmp = getItemParameter(item);
1265 if (tmp && strlen(tmp)==0)
1266 removeParameter(item);
1267 } else {
1268 removeParameter(item);
1273 return pmenu;
1277 static proplist_t
1278 getDefaultMenu(_Panel *panel, int *hasWSMenu)
1280 proplist_t menu, pmenu;
1281 char *menuPath, *gspath;
1283 gspath = wusergnusteppath();
1285 menuPath = wmalloc(strlen(gspath)+128);
1286 /* if there is a localized plmenu for the tongue put it's filename here */
1287 sprintf(menuPath, _("%s/Library/WindowMaker/plmenu"), gspath);
1289 menu = PLGetProplistWithPath(menuPath);
1290 if (!menu) {
1291 wwarning("%s:could not read property list menu", menuPath);
1293 if (strcmp("%s/Library/WindowMaker/plmenu",
1294 _("%s/Library/WindowMaker/plmenu"))!=0) {
1296 sprintf(menuPath, "%s/Library/WindowMaker/plmenu", gspath);
1297 menu = PLGetProplistWithPath(menuPath);
1298 wwarning("%s:could not read property list menu", menuPath);
1300 if (!menu) {
1301 WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win,
1302 _("Error"), _("Could not copy default plmenu file "
1303 "from ~/GNUstep/Library/WindowMaker"),
1304 _("OK"), NULL, NULL);
1305 return NULL;
1309 free(gspath);
1310 free(menuPath);
1312 pmenu = preProcessMenu(menu, hasWSMenu);
1313 PLRelease(menu);
1315 return pmenu;
1319 static void
1320 showData(_Panel *panel)
1322 char *gspath;
1323 char *menuPath;
1324 proplist_t menu, pmenu, plPath;
1325 char buffer[512];
1326 int hasWSMenu=0;
1328 gspath = wusergnusteppath();
1330 menuPath = wmalloc(strlen(gspath)+32);
1331 strcpy(menuPath, gspath);
1332 free(gspath);
1333 strcat(menuPath, "/Defaults/WMRootMenu");
1335 menu = PLGetProplistWithPath(menuPath);
1336 pmenu = NULL;
1338 if (!menu || !PLIsArray(menu)) {
1339 sprintf(buffer, _("The format of the menu in ~/G/D/WMRootMenu is "
1340 "not recognized by WPrefs. It might be in a format different "
1341 "than the one supported by WPrefs or contain a syntax error. "
1342 "Do you want to continue using the current menu to edit "
1343 "it by hand later or replace it with a default menu in the new "
1344 "format?"));
1345 if (WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win,
1346 _("Warning"), buffer, _("Keep current menu"),
1347 _("Install default menu"), NULL)!=WAPRDefault) {
1348 panel->dontSave = 0;
1350 pmenu = getDefaultMenu(panel, &hasWSMenu);
1351 } else {
1352 WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win,
1353 _("Warning"), _("Any changes made in this section will not be saved"),
1354 _("OK"), NULL, NULL);
1355 panel->dontSave = 1;
1357 if (!pmenu) {
1358 pmenu = PLMakeArrayFromElements(PLMakeString("Applications"),
1359 NULL);
1361 } else {
1362 pmenu = preProcessMenu(menu, &hasWSMenu);
1364 plPath = PLMakeString(menuPath);
1365 free(menuPath);
1366 PLSetFilename(pmenu, plPath);
1367 PLRelease(plPath);
1369 if (menu)
1370 PLRelease(menu);
1372 if (panel->itemClipboard) {
1373 PLRelease(panel->itemClipboard);
1374 panel->itemClipboard = NULL;
1376 panel->menu = pmenu;
1377 panel->editedItem = NULL;
1378 panel->capturing = 0;
1380 WMSetPopUpButtonItemEnabled(panel->cmd1P, CPaste, False);
1381 WMSetPopUpButtonItemEnabled(panel->cmd2P, CPaste, False);
1382 if (hasWSMenu) {
1383 WMSetPopUpButtonItemEnabled(panel->cmd1P, CAddWorkspace, False);
1384 WMSetPopUpButtonItemEnabled(panel->cmd2P, CAddWorkspace, False);
1386 WMLoadBrowserColumnZero(panel->browser);
1388 updateForItemType(panel, TNothing);
1392 static void
1393 storeData(_Panel *panel)
1395 proplist_t menu;
1397 if (!panel->unsaved || panel->dontSave)
1398 return;
1399 panel->unsaved = 0;
1401 menu = postProcessMenu(panel->menu);
1403 PLSetFilename(menu, PLGetFilename(panel->menu));
1405 PLSave(menu, YES);
1407 PLRelease(menu);
1411 Panel*
1412 InitMenu(WMScreen *scr, WMWindow *win)
1414 _Panel *panel;
1416 panel = wmalloc(sizeof(_Panel));
1417 memset(panel, 0, sizeof(_Panel));
1419 panel->sectionName = _("Applications Menu Definition");
1421 panel->win = win;
1423 panel->callbacks.createWidgets = createPanel;
1424 panel->callbacks.updateDomain = storeData;
1426 AddSection(panel, ICON_FILE);
1428 return panel;