1 %{
2 /**
3 *
4 * $Id: mwmparse.y,v 1.1 2004/08/28 19:27:39 dannybackx Exp $
5 *
6 * Copyright (C) 1995 Free Software Foundation, Inc.
7 * Copyright (C) 1995-2002 LessTif Development Team
8 *
9 * This file is part of the GNU LessTif Library.
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Library General Public
13 * License as published by the Free Software Foundation; either
14 * version 2 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Library General Public License for more details.
20 *
21 * You should have received a copy of the GNU Library General Public
22 * License along with this library; if not, write to the Free
23 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 **/
26
27 #include "LTconfig.h"
28
29 #include <stdlib.h>
30 #include <stdarg.h>
31 #include <stdio.h>
32 #include <string.h>
33 #ifdef HAVE_FCNTL_H
34 #include <fcntl.h>
35 #endif
36 #ifdef HAVE_UNISTD_H
37 #include <unistd.h>
38 #endif
39 #ifdef HAVE_SYS_TYPES_H
40 #include <sys/types.h>
41 #endif
42 #ifdef HAVE_SYS_STAT_H
43 #include <sys/stat.h>
44 #else
45 #error "you lose (I don't know how to fix this)"
46 #endif
47 #include <X11/Xfuncs.h>
48
49 #include <Xm/Xm.h>
50 #include <Xm/MwmUtil.h>
51
52 #include "mwm.h"
53
54
55 extern int yydebug;
56 extern int yylex(void);
57
58 static int num_items;
59 static MenuRoot *cur_menu;
60 static ScreenInfo *pscr;
61 static Boolean skip_test;
62 static Boolean button_bind_match;
63 static Boolean button_bind_found;
64 static Boolean key_bind_match;
65 static Boolean key_bind_found;
66
67 /*
68 * this must be here for the parser
69 */
70 static int lineno;
71
72 %}
73 %token ALT_TOK
74 APP_TOK
75 BACK_TOK
76 BORDER_TOK
77 BTN1_CLICK2_TOK
78 BTN1_CLICK_TOK
79 BTN1_DOWN_TOK
80 BTN1_UP_TOK
81 BTN2_CLICK2_TOK
82 BTN2_CLICK_TOK
83 BTN2_DOWN_TOK
84 BTN2_UP_TOK
85 BTN3_CLICK2_TOK
86 BTN3_CLICK_TOK
87 BTN3_DOWN_TOK
88 BTN3_UP_TOK
89 BTN4_CLICK2_TOK
90 BTN4_CLICK_TOK
91 BTN4_DOWN_TOK
92 BTN4_UP_TOK
93 BTN5_CLICK2_TOK
94 BTN5_CLICK_TOK
95 BTN5_DOWN_TOK
96 BTN5_UP_TOK
97 BUTTONS_TOK
98 CTRL_TOK
99 FBEEP_TOK
100 FCIRCLE_DOWN_TOK
101 FCIRCLE_UP_TOK
102 FEXEC_TOK
103 FFOCUS_COLOR_TOK
104 FFOCUS_KEY_TOK
105 FKILL_TOK
106 FLOWER_TOK
107 FMAXIMIZE_TOK
108 FMENU_TOK
109 FMINIMIZE_TOK
110 FMOVE_TOK
111 FNEXT_CMAP_TOK
112 FNEXT_KEY_TOK
113 FNOP_TOK
114 FNORMALIZE_TOK
115 FNORMANDRAISE_TOK
116 FPACK_ICONS_TOK
117 FPASS_KEYS_TOK
118 FPOST_WMENU_TOK
119 FPREV_CMAP_TOK
120 FPREV_KEY_TOK
121 FQUIT_MWM_TOK
122 FRAISE_LOWER_TOK
123 FRAISE_TOK
124 FRAME_TOK
125 FREE_FAMILY_TOK
126 FREFRESH_TOK
127 FREFRESH_WIN_TOK
128 FRESIZE_TOK
129 FRESTART_TOK
130 FRESTOREANDRAISE_TOK
131 FRESTORE_TOK
132 FSCREEN_TOK
133 FSEND_MSG_TOK
134 FSEPARATOR_TOK
135 FSET_BEHAVIOR_TOK
136 FTITLE_TOK
137 FWINDOWLIST_TOK
138 FDESK_TOK
139 FTOGGLE_PAGE_TOK
140 FGOTO_PAGE_TOK
141 ICON_TOK
142 KEY_TOK
143 KEYS_TOK
144 LOCK_TOK
145 MENU_TOK
146 MENUB_TOK
147 MINIMIZEB_TOK
148 MAXIMIZEB_TOK
149 MOD1_TOK
150 MOD2_TOK
151 MOD3_TOK
152 MOD4_TOK
153 MOD5_TOK
154 NEXT_TOK
155 PREV_TOK
156 ROOT_TOK
157 SHIFT_TOK
158 TITLE_TOK
159 TRANSIENT_TOK
160 WINDOW_TOK
161 WITHIN_TOK
162 STRING_TOK
163
164 %type <string>
165 STRING_TOK
166
167 %type <number>
168 FCIRCLE_DOWN_TOK
169 FCIRCLE_UP_TOK
170 FEXEC_TOK
171 FFOCUS_COLOR_TOK
172 FFOCUS_KEY_TOK
173 FKILL_TOK
174 FLOWER_TOK
175 FMAXIMIZE_TOK
176 FMENU_TOK
177 FMINIMIZE_TOK
178 FMOVE_TOK
179 FNEXT_CMAP_TOK
180 FNEXT_KEY_TOK
181 FNOP_TOK
182 FNORMALIZE_TOK
183 FNORMANDRAISE_TOK
184 FPACK_ICONS_TOK
185 FPASS_KEYS_TOK
186 FPOST_WMENU_TOK
187 FPREV_CMAP_TOK
188 FPREV_KEY_TOK
189 FQUIT_MWM_TOK
190 FRAISE_LOWER_TOK
191 FRAISE_TOK
192 FRAME_TOK
193 FREE_FAMILY_TOK
194 FREFRESH_TOK
195 FREFRESH_WIN_TOK
196 FRESIZE_TOK
197 FRESTART_TOK
198 FRESTOREANDRAISE_TOK
199 FRESTORE_TOK
200 FSCREEN_TOK
201 FSEND_MSG_TOK
202 FSEPARATOR_TOK
203 FSET_BEHAVIOR_TOK
204 FTITLE_TOK
205 ICON_TOK
206
207 %type <string>
208 bitmap_file
209 string
210
211 %type <label>
212 label
213
214 %type <number>
215 context
216 object
217
218 %type <function>
219 function
220
221 %type <modifiers>
222 modifier_name
223 modifier_list
224
225 %type <hotkey>
226 key
227
228 %union {
229 char *string;
230 int number;
231 KeySym key;
232 struct {
233 int func;
234 char *arg;
235 } function;
236 struct {
237 int type;
238 char *string;
239 } label;
240 long modifiers;
241 struct {
242 int button;
243 int event;
244 int count;
245 int modifiers;
246 } button;
247 struct {
248 int modifiers;
249 KeySym key;
250 } hotkey;
251 };
252
253 %%
254 res_file: res_file binding
255 |
256 ;
257
258 binding: button_bindings
259 | key_bindings
260 | menu_bindings
261 ;
262
263 button_bindings: BUTTONS_TOK string
264 {
265 if (!skip_test) {
266 if (button_bind_found == False) {
267 if (strcmp($2, pscr->button_bindings) == 0)
268 button_bind_match = True;
269 else
270 button_bind_match = False;
271 }
272 else if (strcmp($2, pscr->button_bindings) == 0) {
273 yyerror("Ignoring duplicate button bindings");
274 button_bind_match = False;
275 }
276 else
277 button_bind_match = False;
278 }
279 else
280 button_bind_match = True;
281 }
282 '{' button_list '}'
283 ;
284
285 button_list: button_list button_binding
286 | error
287 {
288 yyerror("Invalid button binding");
289 yyerrok;
290 yyclearin;
291 }
292 |
293 ;
294
295 button_binding: button context function
296 {
297 int contexts = $<number>2;
298 int mods, func;
299 MenuItem *mi = NULL;
300 MouseButton *temp = NULL, *ptr;
301
302 if (!button_bind_match)
303 break;
304
305 mods = $<button>1.modifiers;
306 if ((contexts & C_WINDOW) &&
307 (((mods == 0) || mods == AnyModifier))) {
308 pscr->buttons2grab &= ~($<button>1.button);
309 }
310
311 func = $<function>3.func;
312
313 if ((func == F_EXEC) ||
314 (func == F_RESTART) ||
315 (func == F_CIRCULATE_UP) ||
316 (func == F_CIRCULATE_DOWN) ||
317 (func == F_WARP)) {
318 mi = (MenuItem *)XtMalloc(sizeof(MenuItem));
319
320 mi->next = (MenuItem *) NULL;
321 mi->prev = (MenuItem *) NULL;
322 if ((func == F_EXEC) || (func == F_RESTART)) {
323 mi->item = XtNewString("DOIT");
324 mi->action = $<function>3.arg;
325 }
326 else {
327 mi->item = XtNewString("DONT DOIT");
328 mi->action = $<function>3.arg;
329 }
330 mi->item2 = "";
331 mi->state = 0;
332 mi->func = func;
333 mi->strlen = strlen(mi->item);
334 mi->strlen2 = 0;
335 mi->val1 = 0;
336 mi->val2 = 0;
337 mi->val1_unit = 1;
338 mi->val2_unit = 1;
339 }
340
341 temp = pscr->buttons;
342 pscr->buttons =
343 (MouseButton *)XtMalloc(sizeof(MouseButton));
344 pscr->buttons->func = func;
345 if (func == F_POPUP)
346 pscr->buttons->menu = (MenuRoot *)$<function>3.arg;
347 else if (func == F_W_POPUP)
348 pscr->buttons->menu = (MenuRoot *)DEFAULT_WIN_MENU_NAME;
349 else
350 pscr->buttons->menu = NULL;
351 pscr->buttons->item = mi;
352 pscr->buttons->button =
353 ffs($<button>1.button) - 8;
354 pscr->buttons->context = contexts;
355 pscr->buttons->modifier = mods;
356 pscr->buttons->mask = $<button>1.event;
357 pscr->buttons->count = $<button>1.count;
358 pscr->buttons->val1 = 0;
359 pscr->buttons->val2 = 0;
360 pscr->buttons->val1_unit = pscr->d_width;
361 pscr->buttons->val2_unit = pscr->d_height;
362
363 /* if duplicate, skip second */
364 for (ptr = temp;
365 ptr != NULL;
366 ptr = ptr->next) {
367 /* If everything is the same except for having
368 func's F_POPUP and F_WINDOWLIST, the
369 second is a duplicate */
370 if (((ptr->func == F_POPUP ||
371 ptr->func == F_WINDOWLIST) &&
372 (pscr->buttons->func == F_POPUP ||
373 pscr->buttons->func == F_WINDOWLIST)) &&
374 ptr->modifier == pscr->buttons->modifier &&
375 ptr->mask == pscr->buttons->mask &&
376 ptr->count == pscr->buttons->count &&
377 ptr->context == pscr->buttons->context &&
378 ptr->button == pscr->buttons->button) {
379
380 XtFree((char *)pscr->buttons);
381 pscr->buttons = temp;
382 break;
383 }
384
385 if (ptr->func == pscr->buttons->func &&
386 ptr->modifier == pscr->buttons->modifier &&
387 ptr->mask == pscr->buttons->mask &&
388 ptr->count == pscr->buttons->count &&
389 ptr->button == pscr->buttons->button) {
390 ptr->context |= pscr->buttons->context;
391 XtFree((char *)pscr->buttons);
392 pscr->buttons = temp;
393 break;
394 }
395 }
396 if (ptr == NULL)
397 pscr->buttons->next = temp;
398 }
399 ;
400
401 key_bindings: KEYS_TOK string
402 {
403 if (!skip_test) {
404 if (key_bind_found == False) {
405 if (strcmp($2, pscr->key_bindings) == 0)
406 key_bind_match = True;
407 else
408 key_bind_match = False;
409 }
410 else if (strcmp($2, pscr->key_bindings) == 0) {
411 yyerror("Ignoring duplicate key bindings");
412 key_bind_match = False;
413 }
414 else
415 key_bind_match = False;
416 }
417 else
418 key_bind_match = True;
419 }
420 '{' key_list '}'
421 ;
422
423 key_list: key_list key_binding
424 | error
425 {
426 yyerror("Invalid key binding");
427 yyerrok;
428 yyclearin;
429 }
430 |
431 ;
432
433 key_binding: key context function
434 {
435 FuncKey *tmp = NULL;
436 KeySym keysym;
437 KeyCode keycode;
438 int i, min, max;
439 int func, contexts;
440 char *ptr;
441
442 if (!key_bind_match)
443 break;
444
445 ptr = $<function>3.arg;
446 func = $<function>3.func;
447 contexts = $<number>2;
448
449 /*
450 * Don't let a 0 keycode go through, since that
451 * means AnyKey to the XGrabKey call in GrabKeys().
452 */
453 keysym = $<hotkey>1.key;
454 if (keysym == 0)
455 break;
456 if ((keycode = XKeysymToKeycode(dpy, $<hotkey>1.key)) == 0)
457 break;
458
459 XDisplayKeycodes(dpy, &min, &max);
460 for (i = min; i <= max; i++) {
461 if (XKeycodeToKeysym(dpy, i, 0) == keysym) {
462 tmp = (FuncKey *)XtMalloc(sizeof(FuncKey));
463 tmp->next = pscr->keys;
464 pscr->keys = tmp;
465
466 tmp->name = "HOTKEY";
467 tmp->keycode = i;
468 tmp->cont = contexts;
469 tmp->mods = $<hotkey>1.modifiers;
470 tmp->func = func;
471 if (func == F_W_POPUP)
472 tmp->action = DEFAULT_WIN_MENU_NAME;
473 else
474 tmp->action = ptr;
475 tmp->val1 = 0;
476 tmp->val2 = 0;
477 tmp->val1_unit = pscr->d_width;
478 tmp->val2_unit = pscr->d_height;
479 tmp->menu = NULL;
480 }
481 }
482 }
483 ;
484
485 menu_bindings: MENU_TOK string
486 {
487 num_items = 0;
488 cur_menu = MENU_Create($<string>2);
489 }
490 '{' item_list '}'
491 {
492 MENU_Add(pscr, cur_menu);
493 }
494 ;
495
496 item_list: item_list item_binding
497 | error
498 {
499 yyerror("Invalid menu item");
500 yyerrok;
501 yyclearin;
502 }
503 |
504 ;
505
506 item_binding: label mnemonic accelerator function
507 {
508 MenuItem *tmp;
509 int width, width2;
510 FuncKey *tmpk = NULL;
511 KeySym keysym;
512 KeyCode keycode;
513 int i, min, max;
514 int func, contexts;
515 char *ptr, *acc;
516
517 tmp = (MenuItem *)XtCalloc(1, sizeof(MenuItem));
518 if (cur_menu->first == NULL) {
519 cur_menu->first = tmp;
520 tmp->prev = NULL;
521 tmp->next = NULL;
522 }
523 else {
524 cur_menu->last->next = tmp;
525 tmp->prev = cur_menu->last;
526 }
527 cur_menu->last = tmp;
528 cur_menu->items++;
529
530 if ($<function>4.func == F_NOP)
531 tmp->item = "";
532 else
533 tmp->item = $<label>1.string;
534 tmp->item2 = "";
535 MENU_FindHotKey(tmp, $<key>2);
536 if (strcmp(tmp->item, "no-label") == 0)
537 tmp->strlen = 0;
538 else
539 tmp->strlen = strlen(tmp->item);
540
541 tmp->action = $<function>4.arg;
542 tmp->next = NULL;
543 tmp->state = 0;
544 tmp->func = $<function>4.func;
545 tmp->val1 = 0;
546 tmp->val2 = 0;
547 tmp->val1_unit = pscr->d_width;
548 tmp->val2_unit = pscr->d_height;
549
550 width = XTextWidth(pscr->components[MWM_MENU].font,
551 tmp->item, tmp->strlen);
552 if (tmp->func == F_POPUP)
553 width += 15;
554 if (width <= 0)
555 width = 1;
556 if (width > cur_menu->width)
557 cur_menu->width = width;
558
559 ptr = $<function>4.arg;
560 func = $<function>4.func;
561 contexts = C_WINDOW|C_ICON|C_FRAME|C_TITLE|C_LALL|C_RALL;
562
563 /*
564 * Don't let a 0 keycode go through, since that
565 * means AnyKey to the XGrabKey call in GrabKeys().
566 */
567 keysym = $<hotkey>3.key;
568 if (keysym == 0)
569 break;
570 if ((keycode = XKeysymToKeycode(dpy, $<hotkey>3.key)) == 0)
571 break;
572
573 acc = MENU_AcceleratorString(pscr,
574 $<hotkey>3.key,
575 $<hotkey>3.modifiers);
576 if (strlen(acc)) {
577 tmp->item2 = XtNewString(acc);
578 tmp->strlen2 = strlen(acc);
579 width2 = XTextWidth(pscr->components[MWM_MENU].font,
580 tmp->item2, tmp->strlen2);
581 if (width2 > cur_menu->width2)
582 cur_menu->width2 = width2;
583 }
584
585 XDisplayKeycodes(dpy, &min, &max);
586 for (i = min; i <= max; i++) {
587 if (XKeycodeToKeysym(dpy, i, 0) == keysym) {
588 tmpk = (FuncKey *)XtMalloc(sizeof(FuncKey));
589 tmpk->next = pscr->keys;
590 pscr->keys = tmpk;
591
592 tmpk->name = "HOTKEY";
593 tmpk->keycode = i;
594 tmpk->cont = contexts;
595 tmpk->mods = $<hotkey>3.modifiers;
596 tmpk->func = func;
597 tmpk->action = ptr;
598 tmpk->val1 = 0;
599 tmpk->val2 = 0;
600 tmpk->val1_unit = pscr->d_width;
601 tmpk->val2_unit = pscr->d_height;
602 tmpk->menu = NULL;
603 }
604 }
605 }
606 ;
607
608 accelerator: key
609 { $<hotkey>$ = $<hotkey>1; }
610 |
611 { $<hotkey>$.modifiers = 0; $<hotkey>$.key = 0; }
612 ;
613
614 context: context '|' object
615 { $<number>$ = $1 | $3; }
616 | object
617 { $<number>$ = $1; }
618 ;
619
620 object: ROOT_TOK
621 { $<number>$ = C_ROOT; }
622 | ICON_TOK
623 { $<number>$ = C_ICON; }
624 | MENUB_TOK
625 { $<number>$ = C_MENUB; }
626 | MINIMIZEB_TOK
627 { $<number>$ = C_MINIMIZEB; }
628 | MAXIMIZEB_TOK
629 { $<number>$ = C_MAXIMIZEB; }
630 | WINDOW_TOK
631 { $<number>$ = C_WINDOW|C_FRAME|C_TITLE|C_LALL|C_RALL|C_ICON; }
632 | TITLE_TOK
633 { $<number>$ = C_TITLE; }
634 | FRAME_TOK
635 { $<number>$ = C_FRAME|C_TITLE|C_LALL|C_RALL; }
636 | BORDER_TOK
637 { $<number>$ = C_FRAME; }
638 | APP_TOK
639 { $<number>$ = C_WINDOW; }
640 | error
641 { yyerror("Invalid context"); $<number>$ = 0; }
642 ;
643
644 button: modifier_list '<' button_event_name '>'
645 {
646 $<button>$ = $<button>3;
647 $<button>$.modifiers = $1;
648 }
649 | '<' button_event_name '>'
650 {
651 $<button>$ = $<button>2;
652 $<button>$.modifiers = 0;
653 }
654 ;
655
656 key: modifier_list '<' KEY_TOK '>' STRING_TOK
657 {
658 $<hotkey>$.modifiers = $<modifiers>1;
659 $<hotkey>$.key = XStringToKeysym($<string>5);
660 }
661 | '<' KEY_TOK '>' STRING_TOK
662 {
663 $<hotkey>$.modifiers = 0;
664 $<hotkey>$.key = XStringToKeysym($<string>4);
665 }
666 ;
667
668 modifier_list: modifier_list modifier_name
669 { $<modifiers>$ = $1 | $2; }
670 | modifier_name
671 { $<modifiers>$ = $1; }
672 ;
673
674 modifier_name: CTRL_TOK
675 { $<modifiers>$ = ControlMask; }
676 | SHIFT_TOK
677 { $<modifiers>$ = ShiftMask; }
678 | ALT_TOK
679 { $<modifiers>$ = pscr->alt_mask; }
680 | LOCK_TOK
681 { $<modifiers>$ = LockMask; }
682 | MOD1_TOK
683 { $<modifiers>$ = Mod1Mask; }
684 | MOD2_TOK
685 { $<modifiers>$ = Mod2Mask; }
686 | MOD3_TOK
687 { $<modifiers>$ = Mod3Mask; }
688 | MOD4_TOK
689 { $<modifiers>$ = Mod4Mask; }
690 | MOD5_TOK
691 { $<modifiers>$ = Mod5Mask; }
692 ;
693
694 button_event_name: BTN1_DOWN_TOK
695 {
696 $<button>$.button = Button1Mask;
697 $<button>$.event = ButtonPressMask;
698 $<button>$.count = 0;
699 }
700 | BTN1_UP_TOK
701 {
702 $<button>$.button = Button1Mask;
703 $<button>$.event = ButtonReleaseMask;
704 $<button>$.count = 0;
705 }
706 | BTN1_CLICK_TOK
707 {
708 $<button>$.button = Button1Mask;
709 $<button>$.event = ButtonPressMask|ButtonReleaseMask;
710 $<button>$.count = 1;
711 }
712 | BTN1_CLICK2_TOK
713 {
714 $<button>$.button = Button1Mask;
715 $<button>$.event = ButtonPressMask|ButtonReleaseMask;
716 $<button>$.count = 2;
717 }
718 | BTN2_DOWN_TOK
719 {
720 $<button>$.button = Button2Mask;
721 $<button>$.event = ButtonPressMask;
722 $<button>$.count = 0;
723 }
724 | BTN2_UP_TOK
725 {
726 $<button>$.button = Button2Mask;
727 $<button>$.event = ButtonReleaseMask;
728 $<button>$.count = 0;
729 }
730 | BTN2_CLICK_TOK
731 {
732 $<button>$.button = Button2Mask;
733 $<button>$.event = ButtonPressMask|ButtonReleaseMask;
734 $<button>$.count = 1;
735 }
736 | BTN2_CLICK2_TOK
737 {
738 $<button>$.button = Button2Mask;
739 $<button>$.event = ButtonPressMask|ButtonReleaseMask;
740 $<button>$.count = 2;
741 }
742 | BTN3_DOWN_TOK
743 {
744 $<button>$.button = Button3Mask;
745 $<button>$.event = ButtonPressMask;
746 $<button>$.count = 0;
747 }
748 | BTN3_UP_TOK
749 {
750 $<button>$.button = Button3Mask;
751 $<button>$.event = ButtonReleaseMask;
752 $<button>$.count = 0;
753 }
754 | BTN3_CLICK_TOK
755 {
756 $<button>$.button = Button3Mask;
757 $<button>$.event = ButtonPressMask|ButtonReleaseMask;
758 $<button>$.count = 1;
759 }
760 | BTN3_CLICK2_TOK
761 {
762 $<button>$.button = Button3Mask;
763 $<button>$.event = ButtonPressMask|ButtonReleaseMask;
764 $<button>$.count = 2;
765 }
766 | BTN4_DOWN_TOK
767 {
768 $<button>$.button = Button4Mask;
769 $<button>$.event = ButtonPressMask;
770 $<button>$.count = 0;
771 }
772 | BTN4_UP_TOK
773 {
774 $<button>$.button = Button4Mask;
775 $<button>$.event = ButtonReleaseMask;
776 $<button>$.count = 0;
777 }
778 | BTN4_CLICK_TOK
779 {
780 $<button>$.button = Button4Mask;
781 $<button>$.event = ButtonPressMask|ButtonReleaseMask;
782 $<button>$.count = 1;
783 }
784 | BTN4_CLICK2_TOK
785 {
786 $<button>$.button = Button4Mask;
787 $<button>$.event = ButtonPressMask|ButtonReleaseMask;
788 $<button>$.count = 2;
789 }
790 | BTN5_DOWN_TOK
791 {
792 $<button>$.button = Button5Mask;
793 $<button>$.event = ButtonPressMask;
794 $<button>$.count = 0;
795 }
796 | BTN5_UP_TOK
797 {
798 $<button>$.button = Button5Mask;
799 $<button>$.event = ButtonReleaseMask;
800 $<button>$.count = 0;
801 }
802 | BTN5_CLICK_TOK
803 {
804 $<button>$.button = Button5Mask;
805 $<button>$.event = ButtonPressMask|ButtonReleaseMask;
806 $<button>$.count = 1;
807 }
808 | BTN5_CLICK2_TOK
809 {
810 $<button>$.button = Button5Mask;
811 $<button>$.event = ButtonPressMask|ButtonReleaseMask;
812 $<button>$.count = 2;
813 }
814 | error
815 {
816 yyerror("Invalid button event name");
817 $<button>$.button = 0;
818 $<button>$.event = 0;
819 $<button>$.count = 0;
820 }
821 ;
822
823 label: string
824 { $<label>$.type = IS_STRING; $<label>$.string = $1; }
825 | bitmap_file
826 { $<label>$.type = IS_BITMAP; $<label>$.string = $1; }
827 | error
828 {
829 yyerror("Invalid label");
830 $<label>$.type = IS_STRING;
831 $<label>$.string = "";
832 }
833 ;
834
835 bitmap_file: '@' string
836 { $<string>$ = $2; }
837 ;
838
839 mnemonic: '_' string
840 {
841 if (strlen($<string>2) != 1) {
842 yyerror("Invalid mnemonic specification");
843 $<key>$ = 0;
844 }
845 else {
846 $<key>$ = XStringToKeysym($<string>2);
847 }
848 }
849 |
850 { $<key>$ = 0; }
851 ;
852
853 function: FBEEP_TOK
854 {
855 $<function>$.func = F_BEEP;
856 $<function>$.arg = "";
857 }
858 | FCIRCLE_DOWN_TOK optional_arg
859 {
860 $<function>$.func = F_CIRCULATE_DOWN;
861 $<function>$.arg = $<string>2;
862 }
863 | FCIRCLE_UP_TOK optional_arg
864 {
865 $<function>$.func = F_CIRCULATE_UP;
866 $<function>$.arg = $<string>2;
867 }
868 | FEXEC_TOK string
869 {
870 $<function>$.func = F_EXEC;
871 $<function>$.arg = $<string>2;
872 }
873 | '!' string
874 {
875 $<function>$.func = F_EXEC;
876 $<function>$.arg = $<string>2;
877 }
878 | FFOCUS_COLOR_TOK
879 {
880 $<function>$.func = F_FOCUS_COLOR;
881 $<function>$.arg = "";
882 }
883 | FFOCUS_KEY_TOK
884 {
885 $<function>$.func = F_FOCUS_KEY;
886 $<function>$.arg = "";
887 }
888 | FKILL_TOK
889 {
890 $<function>$.func = F_CLOSE;
891 $<function>$.arg = "";
892 }
893 | FLOWER_TOK optional_arg
894 {
895 $<function>$.func = F_LOWER;
896 $<function>$.arg = $<string>2;
897 }
898 | FMAXIMIZE_TOK
899 {
900 $<function>$.func = F_MAXIMIZE;
901 $<function>$.arg = "";
902 }
903 | FMENU_TOK string
904 {
905 $<function>$.func = F_POPUP;
906 $<function>$.arg = $<string>2;
907 }
908 | FMINIMIZE_TOK
909 {
910 $<function>$.func = F_ICONIFY;
911 $<function>$.arg = "";
912 }
913 | FMOVE_TOK
914 {
915 $<function>$.func = F_MOVE;
916 $<function>$.arg = "";
917 }
918 | FNEXT_CMAP_TOK
919 {
920 $<function>$.func = F_NEXT_CMAP;
921 $<function>$.arg = "";
922 }
923 | FNEXT_KEY_TOK optional_arg
924 {
925 $<function>$.func = F_NEXT_KEY;
926 $<function>$.arg = $<string>2;
927 }
928 | FNOP_TOK
929 {
930 $<function>$.func = F_NOP;
931 $<function>$.arg = "";
932 }
933 | FNORMALIZE_TOK
934 {
935 $<function>$.func = F_NORMALIZE;
936 $<function>$.arg = "";
937 }
938 | FNORMANDRAISE_TOK
939 {
940 $<function>$.func = F_NORM_AND_RAISE;
941 $<function>$.arg = "";
942 }
943 | FPACK_ICONS_TOK
944 {
945 $<function>$.func = F_PACK_ICONS;
946 $<function>$.arg = "";
947 }
948 | FPASS_KEYS_TOK
949 {
950 $<function>$.func = F_PASS_KEYS;
951 $<function>$.arg = "";
952 }
953 | FPOST_WMENU_TOK
954 {
955 $<function>$.func = F_W_POPUP;
956 $<function>$.arg = "";
957 }
958 | FPREV_CMAP_TOK
959 {
960 $<function>$.func = F_PREV_CMAP;
961 $<function>$.arg = "";
962 }
963 | FPREV_KEY_TOK optional_arg
964 {
965 $<function>$.func = F_PREV_KEY;
966 $<function>$.arg = $<string>2;
967 }
968 | FQUIT_MWM_TOK
969 {
970 $<function>$.func = F_QUIT;
971 $<function>$.arg = "";
972 }
973 | FRAISE_TOK optional_arg
974 {
975 $<function>$.func = F_RAISE;
976 $<function>$.arg = $<string>2;
977 }
978 | FRAISE_LOWER_TOK optional_arg
979 {
980 $<function>$.func = F_RAISELOWER;
981 $<function>$.arg = $<string>2;
982 }
983 | FREFRESH_TOK
984 {
985 $<function>$.func = F_REFRESH;
986 $<function>$.arg = "";
987 }
988 | FREFRESH_WIN_TOK
989 {
990 $<function>$.func = F_REFRESH_WIN;
991 $<function>$.arg = "";
992 }
993 | FRESIZE_TOK
994 {
995 $<function>$.func = F_RESIZE;
996 $<function>$.arg = "";
997 }
998 | FRESTORE_TOK
999 {
1000 $<function>$.func = F_ICONIFY;
1001 $<function>$.arg = "";
1002 }
1003 | FRESTOREANDRAISE_TOK
1004 {
1005 $<function>$.func = F_RESTORE_AND_RAISE;
1006 $<function>$.arg = "";
1007 }
1008 | FRESTART_TOK optional_arg
1009 {
1010 $<function>$.func = F_RESTART;
1011 $<function>$.arg = $<string>2;
1012 }
1013 | FSCREEN_TOK optional_arg
1014 {
1015 $<function>$.func = F_SCREEN;
1016 $<function>$.arg = $<string>2;
1017 }
1018 | FSEND_MSG_TOK string
1019 {
1020 $<function>$.func = F_SEND_MSG;
1021 $<function>$.arg = $<string>2;
1022 }
1023 | FSEPARATOR_TOK
1024 {
1025 $<function>$.func = F_NOP;
1026 $<function>$.arg = "";
1027 }
1028 | FSET_BEHAVIOR_TOK
1029 {
1030 $<function>$.func = F_SET_BEHAVIOR;
1031 $<function>$.arg = "";
1032 }
1033 | FTITLE_TOK
1034 {
1035 $<function>$.func = F_TITLE;
1036 $<function>$.arg = "";
1037 }
1038 | FWINDOWLIST_TOK
1039 {
1040 $<function>$.func = F_WINDOWLIST;
1041 $<function>$.arg = "";
1042 }
1043 | error
1044 {
1045 yyerror("Invalid mnemonic, accelerator, or function");
1046 $<function>$.func = F_NOP;
1047 $<function>$.arg = "";
1048 }
1049 ;
1050
1051 optional_arg: arg
1052 { $<string>$ = $<string>1; }
1053 |
1054 { $<string>$ = ""; }
1055 ;
1056
1057 arg: '-' string
1058 { $<string>$ = $<string>2; }
1059 | ROOT_TOK
1060 { $<string>$ = "ROOT"; }
1061 | WINDOW_TOK
1062 { $<string>$ = "WINDOW"; }
1063 | TRANSIENT_TOK
1064 { $<string>$ = "TRANSIENT"; }
1065 | ICON_TOK
1066 { $<string>$ = "ICON"; }
1067 | WITHIN_TOK
1068 { $<string>$ = "WITHIN"; }
1069 | FREE_FAMILY_TOK
1070 { $<string>$ = "FREE_FAMILY"; }
1071 | NEXT_TOK
1072 { $<string>$ = "NEXT"; }
1073 | PREV_TOK
1074 { $<string>$ = "PREV"; }
1075 | BACK_TOK
1076 { $<string>$ = "BACK"; }
1077 ;
1078 string: STRING_TOK
1079 { $<string>$ = $<string>1; }
1080 ;
1081 %%
1082
1083 /*
1084 * these to variables are used by the parser to control input
1085 */
1086 #define MAX_UNGET 1024
1087 static const char *curpos;
1088 static const char *endpos;
1089 static const char *input_buf;
1090 static char unget[MAX_UNGET];
1091 static int upos = 0;
1092
1093 static char *_MwmRootMenu = DEFAULT_MWM_ROOT_MENU;
1094 static char *_MwmKeyBindings = DEFAULT_MWM_KEY_BINDINGS;
1095 static char *_MwmWindowMenu = DEFAULT_MWM_WINDOW_MENU;
1096 static char *_MwmBehaviorKey = MWM_BEHAVIOR_KEY_BINDINGS;
1097 static char *_MwmBuiltinButtonBindings = BUILTIN_MWM_BUTTON_BINDINGS;
1098 static char *_MwmBuiltinMenuButtonBindings = BUILTIN_MENU_BUTTON_BINDINGS;
1099 static char *_MwmBuiltinKillButtonBindings = BUILTIN_KILL_BUTTON_BINDINGS;
1100 static char *_MwmBuiltinIconButtonBindings = BUILTIN_ICON_BUTTON_BINDINGS;
1101
1102 void
yyerror(const char * fmt,...)1103 yyerror(const char *fmt, ...) {
1104 va_list arg_list;
1105
1106 va_start(arg_list, fmt);
1107 vfprintf(stderr, fmt, arg_list);
1108 va_end(arg_list);
1109 fprintf(stderr, " at line %d\n", lineno);
1110 }
1111
1112
1113 char
mwm_getc(void)1114 mwm_getc(void) {
1115 char c;
1116
1117 if (upos) {
1118 upos--;
1119 c = unget[upos];
1120 if (c == '\n')
1121 lineno++;
1122 return c;
1123 }
1124 if (curpos >= endpos)
1125 return 0;
1126 else if (*curpos == 0) {
1127 curpos++;
1128 return 0;
1129 }
1130 c = *curpos;
1131 curpos++;
1132 if (c == '\n')
1133 lineno++;
1134 return c;
1135 }
1136
1137
1138 void
mwm_putc(char c)1139 mwm_putc(char c) {
1140 printf("OUTPUT: %c\n", c);
1141 }
1142
1143
1144 void
mwm_unputc(char c)1145 mwm_unputc(char c) {
1146 if (upos == MAX_UNGET) {
1147 yyerror("Lexer can't back up anymore.\n");
1148 return;
1149 }
1150 if (c == '\n')
1151 lineno--;
1152 unget[upos] = c;
1153 upos++;
1154 }
1155
1156
1157 int
PARSE_buf(ScreenInfo * scr,char * buffer)1158 PARSE_buf(ScreenInfo *scr, char *buffer) {
1159 pscr = scr;
1160 lineno = 1;
1161 curpos = input_buf = buffer;
1162 endpos = input_buf + strlen(input_buf);
1163 upos = 0;
1164 return yyparse();
1165 }
1166
1167
1168 static void
do_standard(ScreenInfo * scr)1169 do_standard(ScreenInfo *scr)
1170 {
1171 skip_test = True;
1172
1173 PARSE_buf(scr, _MwmRootMenu);
1174 PARSE_buf(scr, _MwmWindowMenu);
1175 PARSE_buf(scr, _MwmKeyBindings);
1176 PARSE_buf(scr, _MwmBehaviorKey);
1177
1178 /* a certain amount seems to be expected as builtin */
1179 PARSE_buf(scr, _MwmBuiltinButtonBindings);
1180 if (Mwm.w_menu_button_click)
1181 PARSE_buf(scr, _MwmBuiltinMenuButtonBindings);
1182 if (Mwm.w_menu_button_click_2)
1183 PARSE_buf(scr, _MwmBuiltinKillButtonBindings);
1184 if (Mwm.icon_click)
1185 PARSE_buf(scr, _MwmBuiltinIconButtonBindings);
1186
1187 PROP_SetBehavior(scr, False);
1188 }
1189
1190
1191 static void
do_custom(ScreenInfo * scr)1192 do_custom(ScreenInfo *scr)
1193 {
1194 char *configfile, *ptr;
1195 int fd;
1196
1197 configfile=find_config_file();
1198 if (configfile==NULL)
1199 {
1200 yyerror("Cannot find configuration file. "
1201 "Using builtin defaults.\n", configfile);
1202 do_standard(scr);
1203 return;
1204 }
1205
1206 #ifdef __EMX__
1207 if ((fd = open(configfile, O_RDONLY|O_TEXT)) < 0)
1208 #else
1209 if ((fd = open(configfile, O_RDONLY)) < 0)
1210 #endif
1211 {
1212 yyerror("Cannot open configuration file '%s'. "
1213 "Using builtin defaults.\n", configfile);
1214 do_standard(scr);
1215 }
1216 else {
1217 int bytes_read, statrc;
1218 struct stat st;
1219
1220 if (debugging)
1221 fprintf(stderr, "Reading configuration from '%s'\n", configfile);
1222
1223 statrc=stat(configfile, &st);
1224 ptr = XtMalloc(st.st_size + 1);
1225 bytes_read=read(fd, ptr, st.st_size);
1226 close(fd);
1227
1228 skip_test = False;
1229 ptr[bytes_read] = '\0';
1230 PARSE_buf(scr, ptr);
1231
1232 /* a certain amount seems to be expected as builtin */
1233 skip_test = True;
1234
1235 PARSE_buf(scr, _MwmBuiltinButtonBindings);
1236 if (Mwm.w_menu_button_click)
1237 PARSE_buf(scr, _MwmBuiltinMenuButtonBindings);
1238 if (Mwm.w_menu_button_click_2)
1239 PARSE_buf(scr, _MwmBuiltinKillButtonBindings);
1240 if (Mwm.icon_click)
1241 PARSE_buf(scr, _MwmBuiltinIconButtonBindings);
1242
1243 PROP_SetBehavior(scr, True);
1244
1245 XtFree(ptr);
1246 }
1247
1248 XtFree(configfile);
1249 }
1250
1251 void
PARSE_mwmrc(ScreenInfo * scr)1252 PARSE_mwmrc(ScreenInfo *scr) {
1253 int flag;
1254
1255 key_bind_found = False;
1256 button_bind_found = False;
1257 key_bind_match = False;
1258 button_bind_match = False;
1259
1260 if ((flag = PROP_GetBehavior(scr)) & MWM_INFO_STARTUP_CUSTOM) {
1261 if (debugging)
1262 printf("parsing custom file.\n");
1263 do_custom(scr);
1264 }
1265 else if (flag & MWM_INFO_STARTUP_STANDARD) {
1266 if (debugging)
1267 printf("parsing standard bindings.\n");
1268 do_standard(scr);
1269 }
1270 else {
1271 if (debugging)
1272 printf("parsing custom file by default.\n");
1273 do_custom(scr);
1274 }
1275
1276 return;
1277 }
1278