gram.y revision 645f5050
1/*****************************************************************************/
2/**       Copyright 1988 by Evans & Sutherland Computer Corporation,        **/
3/**                          Salt Lake City, Utah                           **/
4/**  Portions Copyright 1989 by the Massachusetts Institute of Technology   **/
5/**                        Cambridge, Massachusetts                         **/
6/**                                                                         **/
7/**                           All Rights Reserved                           **/
8/**                                                                         **/
9/**    Permission to use, copy, modify, and distribute this software and    **/
10/**    its documentation  for  any  purpose  and  without  fee is hereby    **/
11/**    granted, provided that the above copyright notice appear  in  all    **/
12/**    copies and that both  that  copyright  notice  and  this  permis-    **/
13/**    sion  notice appear in supporting  documentation,  and  that  the    **/
14/**    names of Evans & Sutherland and M.I.T. not be used in advertising    **/
15/**    in publicity pertaining to distribution of the  software  without    **/
16/**    specific, written prior permission.                                  **/
17/**                                                                         **/
18/**    EVANS & SUTHERLAND AND M.I.T. DISCLAIM ALL WARRANTIES WITH REGARD    **/
19/**    TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES  OF  MERCHANT-    **/
20/**    ABILITY  AND  FITNESS,  IN  NO  EVENT SHALL EVANS & SUTHERLAND OR    **/
21/**    M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL  DAM-    **/
22/**    AGES OR  ANY DAMAGES WHATSOEVER  RESULTING FROM LOSS OF USE, DATA    **/
23/**    OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER    **/
24/**    TORTIOUS ACTION, ARISING OUT OF OR IN  CONNECTION  WITH  THE  USE    **/
25/**    OR PERFORMANCE OF THIS SOFTWARE.                                     **/
26/*****************************************************************************/
27/*
28 *  [ ctwm ]
29 *
30 *  Copyright 1992 Claude Lecommandeur.
31 *
32 * Permission to use, copy, modify  and distribute this software  [ctwm] and
33 * its documentation for any purpose is hereby granted without fee, provided
34 * that the above  copyright notice appear  in all copies and that both that
35 * copyright notice and this permission notice appear in supporting documen-
36 * tation, and that the name of  Claude Lecommandeur not be used in adverti-
37 * sing or  publicity  pertaining to  distribution of  the software  without
38 * specific, written prior permission. Claude Lecommandeur make no represen-
39 * tations  about the suitability  of this software  for any purpose.  It is
40 * provided "as is" without express or implied warranty.
41 *
42 * Claude Lecommandeur DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
43 * INCLUDING ALL  IMPLIED WARRANTIES OF  MERCHANTABILITY AND FITNESS.  IN NO
44 * EVENT SHALL  Claude Lecommandeur  BE LIABLE FOR ANY SPECIAL,  INDIRECT OR
45 * CONSEQUENTIAL  DAMAGES OR ANY  DAMAGES WHATSOEVER  RESULTING FROM LOSS OF
46 * USE, DATA  OR PROFITS,  WHETHER IN AN ACTION  OF CONTRACT,  NEGLIGENCE OR
47 * OTHER  TORTIOUS ACTION,  ARISING OUT OF OR IN  CONNECTION WITH THE USE OR
48 * PERFORMANCE OF THIS SOFTWARE.
49 *
50 * Author:  Claude Lecommandeur [ lecom@sic.epfl.ch ][ April 1992 ]
51 */
52
53
54/***********************************************************************
55 *
56 * $XConsortium: gram.y,v 1.91 91/02/08 18:21:56 dave Exp $
57 *
58 * .twmrc command grammer
59 *
60 * 07-Jan-86 Thomas E. LaStrange	File created
61 * 11-Nov-90 Dave Sternlicht            Adding SaveColors
62 * 10-Oct-90 David M. Sternlicht        Storing saved colors on root
63 * 22-April-92 Claude Lecommandeur	modifications for ctwm.
64 *
65 ***********************************************************************/
66
67%{
68#include <stdio.h>
69#include <ctype.h>
70#include "twm.h"
71#include "menus.h"
72#include "icons.h"
73#include "windowbox.h"
74#include "add_window.h"
75#include "list.h"
76#include "util.h"
77#include "screen.h"
78#include "parse.h"
79#include "cursor.h"
80#ifdef VMS
81#  include <decw$include/Xos.h>
82#  include <X11Xmu/CharSet.h>
83#else
84#  include <X11/Xos.h>
85#  include <X11/Xmu/CharSet.h>
86#endif
87
88static char *Action = "";
89static char *Name = "";
90static char *defstring = "default";
91static MenuRoot	*root, *pull = NULL;
92static char *curWorkSpc;
93static char *client, *workspace;
94static MenuItem *lastmenuitem = (MenuItem*) 0;
95
96extern void yyerror(char *s);
97extern void RemoveDQuote(char *str);
98
99static MenuRoot *GetRoot(char *name, char *fore, char *back);
100
101static Bool CheckWarpScreenArg(register char *s);
102static Bool CheckWarpRingArg(register char *s);
103static Bool CheckColormapArg(register char *s);
104static void GotButton(int butt, int func);
105static void GotKey(char *key, int func);
106static void GotTitleButton(char *bitmapname, int func, Bool rightside);
107static char *ptr;
108static name_list **list;
109static int cont = 0;
110static int color;
111Bool donttoggleworkspacemanagerstate = FALSE;
112int mods = 0;
113unsigned int mods_used = (ShiftMask | ControlMask | Mod1Mask);
114
115extern void twmrc_error_prefix(void);
116
117extern int yylex(void);
118extern int yyparse(void);
119%}
120
121%union
122{
123    int num;
124    char *ptr;
125};
126
127
128%token <num> LB RB LP RP MENUS MENU BUTTON DEFAULT_FUNCTION PLUS MINUS
129%token <num> ALL OR CURSORS PIXMAPS ICONS COLOR SAVECOLOR MONOCHROME FUNCTION
130%token <num> ICONMGR_SHOW ICONMGR ALTER WINDOW_FUNCTION ZOOM ICONMGRS
131%token <num> ICONMGR_GEOMETRY ICONMGR_NOSHOW MAKE_TITLE
132%token <num> ICONIFY_BY_UNMAPPING DONT_ICONIFY_BY_UNMAPPING
133%token <num> NO_BORDER NO_ICON_TITLE NO_TITLE AUTO_RAISE NO_HILITE ICON_REGION
134%token <num> WINDOW_REGION META SHIFT LOCK CONTROL WINDOW TITLE ICON ROOT FRAME
135%token <num> COLON EQUALS SQUEEZE_TITLE DONT_SQUEEZE_TITLE
136%token <num> START_ICONIFIED NO_TITLE_HILITE TITLE_HILITE
137%token <num> MOVE RESIZE WAITC SELECT KILL LEFT_TITLEBUTTON RIGHT_TITLEBUTTON
138%token <num> NUMBER KEYWORD NKEYWORD CKEYWORD CLKEYWORD FKEYWORD FSKEYWORD
139%token <num> SKEYWORD SSKEYWORD DKEYWORD JKEYWORD WINDOW_RING WINDOW_RING_EXCLUDE WARP_CURSOR ERRORTOKEN
140%token <num> NO_STACKMODE ALWAYS_ON_TOP WORKSPACE WORKSPACES WORKSPCMGR_GEOMETRY
141%token <num> OCCUPYALL OCCUPYLIST MAPWINDOWCURRENTWORKSPACE MAPWINDOWDEFAULTWORKSPACE
142%token <num> UNMAPBYMOVINGFARAWAY OPAQUEMOVE NOOPAQUEMOVE OPAQUERESIZE NOOPAQUERESIZE
143%token <num> DONTSETINACTIVE CHANGE_WORKSPACE_FUNCTION DEICONIFY_FUNCTION ICONIFY_FUNCTION
144%token <num> AUTOSQUEEZE STARTSQUEEZED DONT_SAVE AUTO_LOWER ICONMENU_DONTSHOW WINDOW_BOX
145%token <num> IGNOREMODIFIER WINDOW_GEOMETRIES ALWAYSSQUEEZETOGRAVITY VIRTUAL_SCREENS
146%token <num> IGNORE_TRANSIENT DONTTOGGLEWORKSPACEMANAGERSTATE
147%token <ptr> STRING
148
149%type <ptr> string
150%type <num> action button number signed_number keyaction full fullkey
151
152%start twmrc
153
154%%
155twmrc		: stmts
156		;
157
158stmts		: /* Empty */
159		| stmts stmt
160		;
161
162stmt		: error
163		| noarg
164		| sarg
165		| narg
166		| squeeze
167		| ICON_REGION string DKEYWORD DKEYWORD number number {
168		      (void) AddIconRegion($2, $3, $4, $5, $6, "undef", "undef", "undef");
169		  }
170		| ICON_REGION string DKEYWORD DKEYWORD number number string {
171		      (void) AddIconRegion($2, $3, $4, $5, $6, $7, "undef", "undef");
172		  }
173		| ICON_REGION string DKEYWORD DKEYWORD number number string string {
174		      (void) AddIconRegion($2, $3, $4, $5, $6, $7, $8, "undef");
175		  }
176		| ICON_REGION string DKEYWORD DKEYWORD number number string string string {
177		      (void) AddIconRegion($2, $3, $4, $5, $6, $7, $8, $9);
178		  }
179		| ICON_REGION string DKEYWORD DKEYWORD number number {
180		      list = AddIconRegion($2, $3, $4, $5, $6, "undef", "undef", "undef");
181		  }
182		  win_list
183		| ICON_REGION string DKEYWORD DKEYWORD number number string {
184		      list = AddIconRegion($2, $3, $4, $5, $6, $7, "undef", "undef");
185		  }
186		  win_list
187		| ICON_REGION string DKEYWORD DKEYWORD number number string string {
188		      list = AddIconRegion($2, $3, $4, $5, $6, $7, $8, "undef");
189		  }
190		  win_list
191		| ICON_REGION string DKEYWORD DKEYWORD number number string string string {
192		      list = AddIconRegion($2, $3, $4, $5, $6, $7, $8, $9);
193		  }
194		  win_list
195
196		| WINDOW_REGION string DKEYWORD DKEYWORD {
197		      list = AddWindowRegion ($2, $3, $4);
198		  }
199		  win_list
200
201		| WINDOW_BOX string string {
202		      list = addWindowBox ($2, $3);
203		  }
204		  win_list
205
206		| ICONMGR_GEOMETRY string number	{ if (Scr->FirstTime)
207						  {
208						    Scr->iconmgr->geometry= (char*)$2;
209						    Scr->iconmgr->columns=$3;
210						  }
211						}
212		| ICONMGR_GEOMETRY string	{ if (Scr->FirstTime)
213						    Scr->iconmgr->geometry = (char*)$2;
214						}
215		| WORKSPCMGR_GEOMETRY string number	{ if (Scr->FirstTime)
216				{
217				    Scr->workSpaceMgr.geometry= (char*)$2;
218				    Scr->workSpaceMgr.columns=$3;
219				}
220						}
221		| WORKSPCMGR_GEOMETRY string	{ if (Scr->FirstTime)
222				    Scr->workSpaceMgr.geometry = (char*)$2;
223						}
224		| MAPWINDOWCURRENTWORKSPACE {}
225		  curwork
226
227		| MAPWINDOWDEFAULTWORKSPACE {}
228		  defwork
229
230		| ZOOM number		{ if (Scr->FirstTime)
231					  {
232						Scr->DoZoom = TRUE;
233						Scr->ZoomCount = $2;
234					  }
235					}
236		| ZOOM			{ if (Scr->FirstTime)
237						Scr->DoZoom = TRUE; }
238		| PIXMAPS pixmap_list	{}
239		| CURSORS cursor_list	{}
240		| ICONIFY_BY_UNMAPPING	{ list = &Scr->IconifyByUn; }
241		  win_list
242		| ICONIFY_BY_UNMAPPING	{ if (Scr->FirstTime)
243		    Scr->IconifyByUnmapping = TRUE; }
244
245		| OPAQUEMOVE	{ list = &Scr->OpaqueMoveList; }
246		  win_list
247		| OPAQUEMOVE	{ if (Scr->FirstTime) Scr->DoOpaqueMove = TRUE; }
248		| NOOPAQUEMOVE	{ list = &Scr->NoOpaqueMoveList; }
249		  win_list
250		| NOOPAQUEMOVE	{ if (Scr->FirstTime) Scr->DoOpaqueMove = FALSE; }
251		| OPAQUERESIZE	{ list = &Scr->OpaqueMoveList; }
252		  win_list
253		| OPAQUERESIZE	{ if (Scr->FirstTime) Scr->DoOpaqueResize = TRUE; }
254		| NOOPAQUERESIZE	{ list = &Scr->NoOpaqueResizeList; }
255		  win_list
256		| NOOPAQUERESIZE	{ if (Scr->FirstTime) Scr->DoOpaqueResize = FALSE; }
257
258		| LEFT_TITLEBUTTON string EQUALS action {
259					  GotTitleButton ($2, $4, False);
260					}
261		| RIGHT_TITLEBUTTON string EQUALS action {
262					  GotTitleButton ($2, $4, True);
263					}
264		| LEFT_TITLEBUTTON string { CreateTitleButton($2, 0, NULL, NULL, FALSE, TRUE); }
265		  binding_list
266		| RIGHT_TITLEBUTTON string { CreateTitleButton($2, 0, NULL, NULL, TRUE, TRUE); }
267		  binding_list
268		| button string		{
269		    root = GetRoot($2, NULLSTR, NULLSTR);
270		    AddFuncButton ($1, C_ROOT, 0, F_MENU, root, (MenuItem*) 0);
271		}
272		| button action		{
273			if ($2 == F_MENU) {
274			    pull->prev = NULL;
275			    AddFuncButton ($1, C_ROOT, 0, $2, pull, (MenuItem*) 0);
276			}
277			else {
278			    MenuItem *item;
279
280			    root = GetRoot(TWM_ROOT,NULLSTR,NULLSTR);
281			    item = AddToMenu (root, "x", Action,
282					NULL, $2, NULLSTR, NULLSTR);
283			    AddFuncButton ($1, C_ROOT, 0, $2, (MenuRoot*) 0, item);
284			}
285			Action = "";
286			pull = NULL;
287		}
288		| string fullkey	{ GotKey($1, $2); }
289		| button full		{ GotButton($1, $2); }
290
291		| DONT_ICONIFY_BY_UNMAPPING { list = &Scr->DontIconify; }
292		  win_list
293		| WORKSPACES {}
294		  workspc_list
295		| IGNOREMODIFIER {} LB keys  { Scr->IgnoreModifier = mods; mods = 0; } RB
296		| OCCUPYALL		{ list = &Scr->OccupyAll; }
297		  win_list
298		| ICONMENU_DONTSHOW	{ list = &Scr->IconMenuDontShow; }
299		  win_list
300		| OCCUPYLIST {}
301		  occupy_list
302		| UNMAPBYMOVINGFARAWAY	{ list = &Scr->UnmapByMovingFarAway; }
303		  win_list
304		| AUTOSQUEEZE		{ list = &Scr->AutoSqueeze; }
305		  win_list
306		| STARTSQUEEZED		{ list = &Scr->StartSqueezed; }
307		  win_list
308		| ALWAYSSQUEEZETOGRAVITY	{ Scr->AlwaysSqueezeToGravity = TRUE; }
309		| ALWAYSSQUEEZETOGRAVITY	{ list = &Scr->AlwaysSqueezeToGravityL; }
310		  win_list
311		| DONTSETINACTIVE	{ list = &Scr->DontSetInactive; }
312		  win_list
313		| ICONMGR_NOSHOW	{ list = &Scr->IconMgrNoShow; }
314		  win_list
315		| ICONMGR_NOSHOW	{ Scr->IconManagerDontShow = TRUE; }
316		| ICONMGRS		{ list = &Scr->IconMgrs; }
317		  iconm_list
318		| ICONMGR_SHOW		{ list = &Scr->IconMgrShow; }
319		  win_list
320		| NO_TITLE_HILITE	{ list = &Scr->NoTitleHighlight; }
321		  win_list
322		| NO_TITLE_HILITE	{ if (Scr->FirstTime)
323						Scr->TitleHighlight = FALSE; }
324		| NO_HILITE		{ list = &Scr->NoHighlight; }
325		  win_list
326		| NO_HILITE		{ if (Scr->FirstTime)
327						Scr->Highlight = FALSE; }
328		| ALWAYS_ON_TOP		{ list = &Scr->AlwaysOnTopL; }
329		  win_list
330		| NO_STACKMODE		{ list = &Scr->NoStackModeL; }
331		  win_list
332		| NO_STACKMODE		{ if (Scr->FirstTime)
333						Scr->StackMode = FALSE; }
334		| NO_BORDER		{ list = &Scr->NoBorder; }
335		  win_list
336		| DONT_SAVE		{ list = &Scr->DontSave; }
337		  win_list
338		| NO_ICON_TITLE		{ list = &Scr->NoIconTitle; }
339		  win_list
340		| NO_ICON_TITLE		{ if (Scr->FirstTime)
341						Scr->NoIconTitlebar = TRUE; }
342		| NO_TITLE		{ list = &Scr->NoTitle; }
343		  win_list
344		| NO_TITLE		{ if (Scr->FirstTime)
345						Scr->NoTitlebar = TRUE; }
346		| IGNORE_TRANSIENT	{ list = &Scr->IgnoreTransientL; }
347		  win_list
348		| DONTTOGGLEWORKSPACEMANAGERSTATE  { donttoggleworkspacemanagerstate = TRUE; }
349		| MAKE_TITLE		{ list = &Scr->MakeTitle; }
350		  win_list
351		| START_ICONIFIED	{ list = &Scr->StartIconified; }
352		  win_list
353		| AUTO_RAISE		{ list = &Scr->AutoRaise; }
354		  win_list
355		| AUTO_RAISE		{ Scr->AutoRaiseDefault = TRUE; }
356		| AUTO_LOWER		{ list = &Scr->AutoLower; }
357		  win_list
358		| AUTO_LOWER		{ Scr->AutoLowerDefault = TRUE; }
359		| MENU string LP string COLON string RP	{
360					root = GetRoot($2, $4, $6); }
361		  menu			{ root->real_menu = TRUE;}
362		| MENU string		{ root = GetRoot($2, NULLSTR, NULLSTR); }
363		  menu			{ root->real_menu = TRUE; }
364		| FUNCTION string	{ root = GetRoot($2, NULLSTR, NULLSTR); }
365		  function
366		| ICONS			{ list = &Scr->IconNames; }
367		  icon_list
368		| COLOR			{ color = COLOR; }
369		  color_list
370		| SAVECOLOR		{}
371		  save_color_list
372		| MONOCHROME		{ color = MONOCHROME; }
373		  color_list
374		| DEFAULT_FUNCTION action { Scr->DefaultFunction.func = $2;
375					  if ($2 == F_MENU)
376					  {
377					    pull->prev = NULL;
378					    Scr->DefaultFunction.menu = pull;
379					  }
380					  else
381					  {
382					    root = GetRoot(TWM_ROOT,NULLSTR,NULLSTR);
383					    Scr->DefaultFunction.item =
384						AddToMenu(root,"x",Action,
385							  NULL,$2, NULLSTR, NULLSTR);
386					  }
387					  Action = "";
388					  pull = NULL;
389					}
390		| WINDOW_FUNCTION action { Scr->WindowFunction.func = $2;
391					   root = GetRoot(TWM_ROOT,NULLSTR,NULLSTR);
392					   Scr->WindowFunction.item =
393						AddToMenu(root,"x",Action,
394							  NULL,$2, NULLSTR, NULLSTR);
395					   Action = "";
396					   pull = NULL;
397					}
398		| CHANGE_WORKSPACE_FUNCTION action { Scr->ChangeWorkspaceFunction.func = $2;
399					   root = GetRoot(TWM_ROOT,NULLSTR,NULLSTR);
400					   Scr->ChangeWorkspaceFunction.item =
401						AddToMenu(root,"x",Action,
402							  NULL,$2, NULLSTR, NULLSTR);
403					   Action = "";
404					   pull = NULL;
405					}
406		| DEICONIFY_FUNCTION action { Scr->DeIconifyFunction.func = $2;
407					   root = GetRoot(TWM_ROOT,NULLSTR,NULLSTR);
408					   Scr->DeIconifyFunction.item =
409						AddToMenu(root,"x",Action,
410							  NULL,$2, NULLSTR, NULLSTR);
411					   Action = "";
412					   pull = NULL;
413					}
414		| ICONIFY_FUNCTION action { Scr->IconifyFunction.func = $2;
415					   root = GetRoot(TWM_ROOT,NULLSTR,NULLSTR);
416					   Scr->IconifyFunction.item =
417						AddToMenu(root,"x",Action,
418							  NULL,$2, NULLSTR, NULLSTR);
419					   Action = "";
420					   pull = NULL;
421					}
422		| WARP_CURSOR		{ list = &Scr->WarpCursorL; }
423		  win_list
424		| WARP_CURSOR		{ if (Scr->FirstTime)
425					    Scr->WarpCursor = TRUE; }
426		| WINDOW_RING		{ list = &Scr->WindowRingL; }
427		  win_list
428		| WINDOW_RING		{ Scr->WindowRingAll = TRUE; }
429		| WINDOW_RING_EXCLUDE	{ if (!Scr->WindowRingL)
430					    Scr->WindowRingAll = TRUE;
431					  list = &Scr->WindowRingExcludeL; }
432		  win_list
433		| WINDOW_GEOMETRIES	{  }
434		  wingeom_list
435		| VIRTUAL_SCREENS	{ }
436		  geom_list
437		;
438
439noarg		: KEYWORD		{ if (!do_single_keyword ($1)) {
440					    twmrc_error_prefix();
441					    fprintf (stderr,
442					"unknown singleton keyword %d\n",
443						     $1);
444					    ParseError = 1;
445					  }
446					}
447		;
448
449sarg		: SKEYWORD string	{ if (!do_string_keyword ($1, $2)) {
450					    twmrc_error_prefix();
451					    fprintf (stderr,
452				"unknown string keyword %d (value \"%s\")\n",
453						     $1, $2);
454					    ParseError = 1;
455					  }
456					}
457		| SKEYWORD		{ if (!do_string_keyword ($1, defstring)) {
458					    twmrc_error_prefix();
459					    fprintf (stderr,
460				"unknown string keyword %d (no value)\n",
461						     $1);
462					    ParseError = 1;
463					  }
464					}
465		;
466
467sarg		: SSKEYWORD string string
468					{ if (!do_string_string_keyword ($1, $2, $3)) {
469					    twmrc_error_prefix();
470					    fprintf (stderr,
471				"unknown strings keyword %d (value \"%s\" and \"%s\")\n",
472						     $1, $2, $3);
473					    ParseError = 1;
474					  }
475					}
476		| SSKEYWORD string	{ if (!do_string_string_keyword ($1, $2, defstring)) {
477					    twmrc_error_prefix();
478					    fprintf (stderr,
479				"unknown string keyword %d (value \"%s\")\n",
480						     $1, $2);
481					    ParseError = 1;
482					  }
483					}
484		| SSKEYWORD		{ if (!do_string_string_keyword ($1, defstring, defstring)) {
485					    twmrc_error_prefix();
486					    fprintf (stderr,
487				"unknown string keyword %d (no value)\n",
488						     $1);
489					    ParseError = 1;
490					  }
491					}
492		;
493
494narg		: NKEYWORD number	{ if (!do_number_keyword ($1, $2)) {
495					    twmrc_error_prefix();
496					    fprintf (stderr,
497				"unknown numeric keyword %d (value %d)\n",
498						     $1, $2);
499					    ParseError = 1;
500					  }
501					}
502		;
503
504
505
506keyaction	: EQUALS keys COLON action  { $$ = $4; }
507		;
508
509full		: EQUALS keys COLON contexts COLON action  { $$ = $6; }
510		;
511
512fullkey		: EQUALS keys COLON contextkeys COLON action  { $$ = $6; }
513		;
514
515keys		: /* Empty */
516		| keys key
517		;
518
519key		: META			{ mods |= Mod1Mask; }
520		| SHIFT			{ mods |= ShiftMask; }
521		| LOCK			{ mods |= LockMask; }
522		| CONTROL		{ mods |= ControlMask; }
523		| ALTER number		{ if ($2 < 1 || $2 > 5) {
524					     twmrc_error_prefix();
525					     fprintf (stderr,
526				"bad modifier number (%d), must be 1-5\n",
527						      $2);
528					     ParseError = 1;
529					  } else {
530					     mods |= (Alt1Mask << ($2 - 1));
531					  }
532					}
533		| META number		{ if ($2 < 1 || $2 > 5) {
534					     twmrc_error_prefix();
535					     fprintf (stderr,
536				"bad modifier number (%d), must be 1-5\n",
537						      $2);
538					     ParseError = 1;
539					  } else {
540					     mods |= (Mod1Mask << ($2 - 1));
541					  }
542					}
543		| OR			{ }
544		;
545
546contexts	: /* Empty */
547		| contexts context
548		;
549
550context		: WINDOW		{ cont |= C_WINDOW_BIT; }
551		| TITLE			{ cont |= C_TITLE_BIT; }
552		| ICON			{ cont |= C_ICON_BIT; }
553		| ROOT			{ cont |= C_ROOT_BIT; }
554		| FRAME			{ cont |= C_FRAME_BIT; }
555		| WORKSPACE		{ cont |= C_WORKSPACE_BIT; }
556		| ICONMGR		{ cont |= C_ICONMGR_BIT; }
557		| META			{ cont |= C_ICONMGR_BIT; }
558		| ALTER			{ cont |= C_ALTER_BIT; }
559		| ALL			{ cont |= C_ALL_BITS; }
560		| OR			{  }
561		;
562
563contextkeys	: /* Empty */
564		| contextkeys contextkey
565		;
566
567contextkey	: WINDOW		{ cont |= C_WINDOW_BIT; }
568		| TITLE			{ cont |= C_TITLE_BIT; }
569		| ICON			{ cont |= C_ICON_BIT; }
570		| ROOT			{ cont |= C_ROOT_BIT; }
571		| FRAME			{ cont |= C_FRAME_BIT; }
572		| WORKSPACE		{ cont |= C_WORKSPACE_BIT; }
573		| ICONMGR		{ cont |= C_ICONMGR_BIT; }
574		| META			{ cont |= C_ICONMGR_BIT; }
575		| ALL			{ cont |= C_ALL_BITS; }
576		| ALTER			{ cont |= C_ALTER_BIT; }
577		| OR			{ }
578		| string		{ Name = (char*)$1; cont |= C_NAME_BIT; }
579		;
580
581
582binding_list    : LB binding_entries RB {}
583		;
584
585binding_entries : /* Empty */
586		| binding_entries binding_entry
587		;
588
589binding_entry   : button keyaction { ModifyCurrentTB($1, mods, $2, Action, pull); mods = 0;}
590		| button EQUALS action { ModifyCurrentTB($1, 0, $3, Action, pull);}
591		/* The following is deprecated! */
592		| button COLON action { ModifyCurrentTB($1, 0, $3, Action, pull);}
593		;
594
595
596pixmap_list	: LB pixmap_entries RB {}
597		;
598
599pixmap_entries	: /* Empty */
600		| pixmap_entries pixmap_entry
601		;
602
603pixmap_entry	: TITLE_HILITE string { SetHighlightPixmap ($2); }
604		;
605
606
607cursor_list	: LB cursor_entries RB {}
608		;
609
610cursor_entries	: /* Empty */
611		| cursor_entries cursor_entry
612		;
613
614cursor_entry	: FRAME string string {
615			NewBitmapCursor(&Scr->FrameCursor, $2, $3); }
616		| FRAME string	{
617			NewFontCursor(&Scr->FrameCursor, $2); }
618		| TITLE string string {
619			NewBitmapCursor(&Scr->TitleCursor, $2, $3); }
620		| TITLE string {
621			NewFontCursor(&Scr->TitleCursor, $2); }
622		| ICON string string {
623			NewBitmapCursor(&Scr->IconCursor, $2, $3); }
624		| ICON string {
625			NewFontCursor(&Scr->IconCursor, $2); }
626		| ICONMGR string string {
627			NewBitmapCursor(&Scr->IconMgrCursor, $2, $3); }
628		| ICONMGR string {
629			NewFontCursor(&Scr->IconMgrCursor, $2); }
630		| BUTTON string string {
631			NewBitmapCursor(&Scr->ButtonCursor, $2, $3); }
632		| BUTTON string {
633			NewFontCursor(&Scr->ButtonCursor, $2); }
634		| MOVE string string {
635			NewBitmapCursor(&Scr->MoveCursor, $2, $3); }
636		| MOVE string {
637			NewFontCursor(&Scr->MoveCursor, $2); }
638		| RESIZE string string {
639			NewBitmapCursor(&Scr->ResizeCursor, $2, $3); }
640		| RESIZE string {
641			NewFontCursor(&Scr->ResizeCursor, $2); }
642		| WAITC string string {
643			NewBitmapCursor(&Scr->WaitCursor, $2, $3); }
644		| WAITC string {
645			NewFontCursor(&Scr->WaitCursor, $2); }
646		| MENU string string {
647			NewBitmapCursor(&Scr->MenuCursor, $2, $3); }
648		| MENU string {
649			NewFontCursor(&Scr->MenuCursor, $2); }
650		| SELECT string string {
651			NewBitmapCursor(&Scr->SelectCursor, $2, $3); }
652		| SELECT string {
653			NewFontCursor(&Scr->SelectCursor, $2); }
654		| KILL string string {
655			NewBitmapCursor(&Scr->DestroyCursor, $2, $3); }
656		| KILL string {
657			NewFontCursor(&Scr->DestroyCursor, $2); }
658		;
659
660color_list	: LB color_entries RB {}
661		;
662
663
664color_entries	: /* Empty */
665		| color_entries color_entry
666		;
667
668color_entry	: CLKEYWORD string	{ if (!do_colorlist_keyword ($1, color,
669								     $2)) {
670					    twmrc_error_prefix();
671					    fprintf (stderr,
672			"unhandled list color keyword %d (string \"%s\")\n",
673						     $1, $2);
674					    ParseError = 1;
675					  }
676					}
677		| CLKEYWORD string	{ list = do_colorlist_keyword($1,color,
678								      $2);
679					  if (!list) {
680					    twmrc_error_prefix();
681					    fprintf (stderr,
682			"unhandled color list keyword %d (string \"%s\")\n",
683						     $1, $2);
684					    ParseError = 1;
685					  }
686					}
687		  win_color_list
688		| CKEYWORD string	{ if (!do_color_keyword ($1, color,
689								 $2)) {
690					    twmrc_error_prefix();
691					    fprintf (stderr,
692			"unhandled color keyword %d (string \"%s\")\n",
693						     $1, $2);
694					    ParseError = 1;
695					  }
696					}
697		;
698
699save_color_list : LB s_color_entries RB {}
700		;
701
702s_color_entries : /* Empty */
703		| s_color_entries s_color_entry
704		;
705
706s_color_entry   : string		{ do_string_savecolor(color, $1); }
707		| CLKEYWORD		{ do_var_savecolor($1); }
708		;
709
710win_color_list	: LB win_color_entries RB {}
711		;
712
713win_color_entries	: /* Empty */
714		| win_color_entries win_color_entry
715		;
716
717win_color_entry	: string string		{ if (Scr->FirstTime &&
718					      color == Scr->Monochrome)
719					    AddToList(list, $1, $2); }
720		;
721
722wingeom_list	: LB wingeom_entries RB {}
723		;
724
725wingeom_entries	: /* Empty */
726		| wingeom_entries wingeom_entry
727		;
728/* added a ';' after call to AddToList */
729wingeom_entry	: string string	{ AddToList (&Scr->WindowGeometries, $1, $2); }
730		;
731
732geom_list	: LB geom_entries RB {}
733		;
734
735geom_entries	: /* Empty */
736		| geom_entries geom_entry
737		;
738
739geom_entry	: string { AddToList (&Scr->VirtualScreens, $1, ""); }
740		;
741
742squeeze		: SQUEEZE_TITLE {
743				    if (HasShape) Scr->SqueezeTitle = TRUE;
744				}
745		| SQUEEZE_TITLE { list = &Scr->SqueezeTitleL;
746				  if (HasShape && Scr->SqueezeTitle == -1)
747				    Scr->SqueezeTitle = TRUE;
748				}
749		  LB win_sqz_entries RB
750		| DONT_SQUEEZE_TITLE { Scr->SqueezeTitle = FALSE; }
751		| DONT_SQUEEZE_TITLE { list = &Scr->DontSqueezeTitleL; }
752		  win_list
753		;
754
755win_sqz_entries	: /* Empty */
756		| win_sqz_entries string JKEYWORD signed_number number	{
757				if (Scr->FirstTime) {
758				   do_squeeze_entry (list, $2, $3, $4, $5);
759				}
760			}
761		;
762
763
764iconm_list	: LB iconm_entries RB {}
765		;
766
767iconm_entries	: /* Empty */
768		| iconm_entries iconm_entry
769		;
770
771iconm_entry	: string string number	{ if (Scr->FirstTime)
772					    AddToList(list, $1, (char *)
773						AllocateIconManager($1, NULLSTR,
774							$2,$3));
775					}
776		| string string string number
777					{ if (Scr->FirstTime)
778					    AddToList(list, $1, (char *)
779						AllocateIconManager($1,$2,
780						$3, $4));
781					}
782		;
783
784workspc_list	: LB workspc_entries RB {}
785		;
786
787workspc_entries	: /* Empty */
788		| workspc_entries workspc_entry
789		;
790
791workspc_entry	: string	{
792			AddWorkSpace ($1, NULLSTR, NULLSTR, NULLSTR, NULLSTR, NULLSTR);
793		}
794		| string	{
795			curWorkSpc = (char*)$1;
796		}
797		workapp_list
798		;
799
800workapp_list	: LB workapp_entries RB {}
801		;
802
803workapp_entries	: /* Empty */
804		| workapp_entries workapp_entry
805		;
806
807workapp_entry	: string		{
808			AddWorkSpace (curWorkSpc, $1, NULLSTR, NULLSTR, NULLSTR, NULLSTR);
809		}
810		| string string		{
811			AddWorkSpace (curWorkSpc, $1, $2, NULLSTR, NULLSTR, NULLSTR);
812		}
813		| string string string	{
814			AddWorkSpace (curWorkSpc, $1, $2, $3, NULLSTR, NULLSTR);
815		}
816		| string string string string	{
817			AddWorkSpace (curWorkSpc, $1, $2, $3, $4, NULLSTR);
818		}
819		| string string string string string	{
820			AddWorkSpace (curWorkSpc, $1, $2, $3, $4, $5);
821		}
822		;
823
824curwork		: LB string RB {
825		    WMapCreateCurrentBackGround ($2, NULL, NULL, NULL);
826		}
827		| LB string string RB {
828		    WMapCreateCurrentBackGround ($2, $3, NULL, NULL);
829		}
830		| LB string string string RB {
831		    WMapCreateCurrentBackGround ($2, $3, $4, NULL);
832		}
833		| LB string string string string RB {
834		    WMapCreateCurrentBackGround ($2, $3, $4, $5);
835		}
836		;
837
838defwork		: LB string RB {
839		    WMapCreateDefaultBackGround ($2, NULL, NULL, NULL);
840		}
841		| LB string string RB {
842		    WMapCreateDefaultBackGround ($2, $3, NULL, NULL);
843		}
844		| LB string string string RB {
845		    WMapCreateDefaultBackGround ($2, $3, $4, NULL);
846		}
847		| LB string string string string RB {
848		    WMapCreateDefaultBackGround ($2, $3, $4, $5);
849		}
850		;
851
852win_list	: LB win_entries RB {}
853		;
854
855win_entries	: /* Empty */
856		| win_entries win_entry
857		;
858
859win_entry	: string		{ if (Scr->FirstTime)
860					    AddToList(list, $1, 0);
861					}
862		;
863
864occupy_list	: LB occupy_entries RB {}
865		;
866
867occupy_entries	:  /* Empty */
868		| occupy_entries occupy_entry
869		;
870
871occupy_entry	: string {client = (char*)$1;}
872		  occupy_workspc_list
873		| WINDOW    string {client = (char*)$2;}
874		  occupy_workspc_list
875		| WORKSPACE string {workspace = (char*)$2;}
876		  occupy_window_list
877		;
878
879occupy_workspc_list	: LB occupy_workspc_entries RB {}
880			;
881
882occupy_workspc_entries	:   /* Empty */
883			| occupy_workspc_entries occupy_workspc_entry
884			;
885
886occupy_workspc_entry	: string {
887				AddToClientsList ($1, client);
888			  }
889			;
890
891occupy_window_list	: LB occupy_window_entries RB {}
892			;
893
894occupy_window_entries	:   /* Empty */
895			| occupy_window_entries occupy_window_entry
896			;
897
898occupy_window_entry	: string {
899				AddToClientsList (workspace, $1);
900			  }
901			;
902
903icon_list	: LB icon_entries RB {}
904		;
905
906icon_entries	: /* Empty */
907		| icon_entries icon_entry
908		;
909
910icon_entry	: string string		{ if (Scr->FirstTime) AddToList(list, $1, $2); }
911		;
912
913function	: LB function_entries RB {}
914		;
915
916function_entries: /* Empty */
917		| function_entries function_entry
918		;
919
920function_entry	: action		{ AddToMenu(root, "", Action, NULL, $1,
921						    NULLSTR, NULLSTR);
922					  Action = "";
923					}
924		;
925
926menu		: LB menu_entries RB {lastmenuitem = (MenuItem*) 0;}
927		;
928
929menu_entries	: /* Empty */
930		| menu_entries menu_entry
931		;
932
933menu_entry	: string action		{
934			if ($2 == F_SEPARATOR) {
935			    if (lastmenuitem) lastmenuitem->separated = 1;
936			}
937			else {
938			    lastmenuitem = AddToMenu(root, $1, Action, pull, $2, NULLSTR, NULLSTR);
939			    Action = "";
940			    pull = NULL;
941			}
942		}
943		| string LP string COLON string RP action {
944			if ($7 == F_SEPARATOR) {
945			    if (lastmenuitem) lastmenuitem->separated = 1;
946			}
947			else {
948			    lastmenuitem = AddToMenu(root, $1, Action, pull, $7, $3, $5);
949			    Action = "";
950			    pull = NULL;
951			}
952		}
953		;
954
955action		: FKEYWORD	{ $$ = $1; }
956		| FSKEYWORD string {
957				$$ = $1;
958				Action = (char*)$2;
959				switch ($1) {
960				  case F_MENU:
961				    pull = GetRoot ($2, NULLSTR,NULLSTR);
962				    pull->prev = root;
963				    break;
964				  case F_WARPRING:
965				    if (!CheckWarpRingArg (Action)) {
966					twmrc_error_prefix();
967					fprintf (stderr,
968			"ignoring invalid f.warptoring argument \"%s\"\n",
969						 Action);
970					$$ = F_NOP;
971				    }
972				  case F_WARPTOSCREEN:
973				    if (!CheckWarpScreenArg (Action)) {
974					twmrc_error_prefix();
975					fprintf (stderr,
976			"ignoring invalid f.warptoscreen argument \"%s\"\n",
977						 Action);
978					$$ = F_NOP;
979				    }
980				    break;
981				  case F_COLORMAP:
982				    if (CheckColormapArg (Action)) {
983					$$ = F_COLORMAP;
984				    } else {
985					twmrc_error_prefix();
986					fprintf (stderr,
987			"ignoring invalid f.colormap argument \"%s\"\n",
988						 Action);
989					$$ = F_NOP;
990				    }
991				    break;
992				} /* end switch */
993				   }
994		;
995
996
997signed_number	: number		{ $$ = $1; }
998		| PLUS number		{ $$ = $2; }
999		| MINUS number		{ $$ = -($2); }
1000		;
1001
1002button		: BUTTON number		{ $$ = $2;
1003					  if ($2 == 0)
1004						yyerror("bad button 0");
1005
1006					  if ($2 > MAX_BUTTONS)
1007					  {
1008						$$ = 0;
1009						yyerror("button number too large");
1010					  }
1011					}
1012		;
1013
1014string		: STRING		{ ptr = (char *)malloc(strlen((char*)$1)+1);
1015					  strcpy(ptr, $1);
1016					  RemoveDQuote(ptr);
1017					  $$ = ptr;
1018					}
1019		;
1020
1021number		: NUMBER		{ $$ = $1; }
1022		;
1023
1024%%
1025void yyerror(char *s)
1026{
1027    twmrc_error_prefix();
1028    fprintf (stderr, "error in input file:  %s\n", s ? s : "");
1029    ParseError = 1;
1030}
1031
1032void RemoveDQuote(char *str)
1033{
1034    register char *i, *o;
1035    register int n;
1036    register int count;
1037
1038    for (i=str+1, o=str; *i && *i != '\"'; o++)
1039    {
1040	if (*i == '\\')
1041	{
1042	    switch (*++i)
1043	    {
1044	    case 'n':
1045		*o = '\n';
1046		i++;
1047		break;
1048	    case 'b':
1049		*o = '\b';
1050		i++;
1051		break;
1052	    case 'r':
1053		*o = '\r';
1054		i++;
1055		break;
1056	    case 't':
1057		*o = '\t';
1058		i++;
1059		break;
1060	    case 'f':
1061		*o = '\f';
1062		i++;
1063		break;
1064	    case '0':
1065		if (*++i == 'x')
1066		    goto hex;
1067		else
1068		    --i;
1069	    case '1': case '2': case '3':
1070	    case '4': case '5': case '6': case '7':
1071		n = 0;
1072		count = 0;
1073		while (*i >= '0' && *i <= '7' && count < 3)
1074		{
1075		    n = (n<<3) + (*i++ - '0');
1076		    count++;
1077		}
1078		*o = n;
1079		break;
1080	    hex:
1081	    case 'x':
1082		n = 0;
1083		count = 0;
1084		while (i++, count++ < 2)
1085		{
1086		    if (*i >= '0' && *i <= '9')
1087			n = (n<<4) + (*i - '0');
1088		    else if (*i >= 'a' && *i <= 'f')
1089			n = (n<<4) + (*i - 'a') + 10;
1090		    else if (*i >= 'A' && *i <= 'F')
1091			n = (n<<4) + (*i - 'A') + 10;
1092		    else
1093			break;
1094		}
1095		*o = n;
1096		break;
1097	    case '\n':
1098		i++;	/* punt */
1099		o--;	/* to account for o++ at end of loop */
1100		break;
1101	    case '\"':
1102	    case '\'':
1103	    case '\\':
1104	    default:
1105		*o = *i++;
1106		break;
1107	    }
1108	}
1109	else
1110	    *o = *i++;
1111    }
1112    *o = '\0';
1113}
1114
1115static MenuRoot *GetRoot(char *name, char *fore, char *back)
1116{
1117    MenuRoot *tmp;
1118
1119    tmp = FindMenuRoot(name);
1120    if (tmp == NULL)
1121	tmp = NewMenuRoot(name);
1122
1123    if (fore)
1124    {
1125	int save;
1126
1127	save = Scr->FirstTime;
1128	Scr->FirstTime = TRUE;
1129	GetColor(COLOR, &tmp->highlight.fore, fore);
1130	GetColor(COLOR, &tmp->highlight.back, back);
1131	Scr->FirstTime = save;
1132    }
1133
1134    return tmp;
1135}
1136
1137static void GotButton (int butt, int func)
1138{
1139    int i;
1140    MenuItem *item;
1141
1142    for (i = 0; i < NUM_CONTEXTS; i++) {
1143	if ((cont & (1 << i)) == 0) continue;
1144
1145	if (func == F_MENU) {
1146	    pull->prev = NULL;
1147	    AddFuncButton (butt, i, mods, func, pull, (MenuItem*) 0);
1148	}
1149	else {
1150	    root = GetRoot (TWM_ROOT, NULLSTR, NULLSTR);
1151	    item = AddToMenu (root, "x", Action, NULL, func, NULLSTR, NULLSTR);
1152	    AddFuncButton (butt, i, mods, func, (MenuRoot*) 0, item);
1153	}
1154    }
1155
1156    Action = "";
1157    pull = NULL;
1158    cont = 0;
1159    mods_used |= mods;
1160    mods = 0;
1161}
1162
1163static void GotKey(char *key, int func)
1164{
1165    int i;
1166
1167    for (i = 0; i < NUM_CONTEXTS; i++)
1168    {
1169	if ((cont & (1 << i)) == 0)
1170	  continue;
1171
1172	if (func == F_MENU) {
1173	    pull->prev = NULL;
1174	    if (!AddFuncKey (key, i, mods, func, pull, Name, Action)) break;
1175	}
1176	else
1177	if (!AddFuncKey(key, i, mods, func, (MenuRoot*) 0, Name, Action))
1178	  break;
1179    }
1180
1181    Action = "";
1182    pull = NULL;
1183    cont = 0;
1184    mods_used |= mods;
1185    mods = 0;
1186}
1187
1188
1189static void GotTitleButton (char *bitmapname, int func, Bool rightside)
1190{
1191    if (!CreateTitleButton (bitmapname, func, Action, pull, rightside, True)) {
1192	twmrc_error_prefix();
1193	fprintf (stderr,
1194		 "unable to create %s titlebutton \"%s\"\n",
1195		 rightside ? "right" : "left", bitmapname);
1196    }
1197    Action = "";
1198    pull = NULL;
1199}
1200
1201static Bool CheckWarpScreenArg (register char *s)
1202{
1203    XmuCopyISOLatin1Lowered (s, s);
1204
1205    if (strcmp (s,  WARPSCREEN_NEXT) == 0 ||
1206	strcmp (s,  WARPSCREEN_PREV) == 0 ||
1207	strcmp (s,  WARPSCREEN_BACK) == 0)
1208      return True;
1209
1210    for (; *s && Isascii(*s) && Isdigit(*s); s++) ; /* SUPPRESS 530 */
1211    return (*s ? False : True);
1212}
1213
1214
1215static Bool CheckWarpRingArg (register char *s)
1216{
1217    XmuCopyISOLatin1Lowered (s, s);
1218
1219    if (strcmp (s,  WARPSCREEN_NEXT) == 0 ||
1220	strcmp (s,  WARPSCREEN_PREV) == 0)
1221      return True;
1222
1223    return False;
1224}
1225
1226
1227static Bool CheckColormapArg (register char *s)
1228{
1229    XmuCopyISOLatin1Lowered (s, s);
1230
1231    if (strcmp (s, COLORMAP_NEXT) == 0 ||
1232	strcmp (s, COLORMAP_PREV) == 0 ||
1233	strcmp (s, COLORMAP_DEFAULT) == 0)
1234      return True;
1235
1236    return False;
1237}
1238
1239
1240void twmrc_error_prefix (void)
1241{
1242    fprintf (stderr, "%s:  line %d:  ", ProgramName, twmrc_lineno);
1243}
1244