1/*
2 * Parser routines called from yacc code (gram.y)
3 *
4 * This is very similar to the meaning of parse_be.c; the two may be
5 * merged at some point.
6 */
7
8#include "ctwm.h"
9
10#include <stdio.h>
11#include <string.h>
12#include <strings.h>
13
14#include "functions_defs.h"
15#include "util.h"
16#include "screen.h"
17#include "parse.h"
18#include "parse_be.h"
19#include "parse_yacc.h"
20#include "win_decorations_init.h"
21
22#include "gram.tab.h"
23
24char *Action = "";
25char *Name = "";
26MenuRoot *root, *pull = NULL;
27
28int cont = 0;
29int mods = 0;
30unsigned int mods_used = (ShiftMask | ControlMask | Mod1Mask);
31
32
33void yyerror(char *s)
34{
35	twmrc_error_prefix();
36	fprintf(stderr, "error in input file:  %s\n", s ? s : "");
37	ParseError = true;
38}
39
40void InitGramVariables(void)
41{
42	mods = 0;
43}
44
45void RemoveDQuote(char *str)
46{
47	char *i, *o;
48	int n;
49	int count;
50
51	for(i = str + 1, o = str; *i && *i != '\"'; o++) {
52		if(*i == '\\') {
53			switch(*++i) {
54				case 'n':
55					*o = '\n';
56					i++;
57					break;
58				case 'b':
59					*o = '\b';
60					i++;
61					break;
62				case 'r':
63					*o = '\r';
64					i++;
65					break;
66				case 't':
67					*o = '\t';
68					i++;
69					break;
70				case 'f':
71					*o = '\f';
72					i++;
73					break;
74				case '0':
75					if(*++i == 'x') {
76						goto hex;
77					}
78					else {
79						--i;
80					}
81				case '1':
82				case '2':
83				case '3':
84				case '4':
85				case '5':
86				case '6':
87				case '7':
88					n = 0;
89					count = 0;
90					while(*i >= '0' && *i <= '7' && count < 3) {
91						n = (n << 3) + (*i++ - '0');
92						count++;
93					}
94					*o = n;
95					break;
96hex:
97				case 'x':
98					n = 0;
99					count = 0;
100					while(i++, count++ < 2) {
101						if(*i >= '0' && *i <= '9') {
102							n = (n << 4) + (*i - '0');
103						}
104						else if(*i >= 'a' && *i <= 'f') {
105							n = (n << 4) + (*i - 'a') + 10;
106						}
107						else if(*i >= 'A' && *i <= 'F') {
108							n = (n << 4) + (*i - 'A') + 10;
109						}
110						else {
111							break;
112						}
113					}
114					*o = n;
115					break;
116				case '\n':
117					i++;    /* punt */
118					o--;    /* to account for o++ at end of loop */
119					break;
120				case '\"':
121				case '\'':
122				case '\\':
123				default:
124					*o = *i++;
125					break;
126			}
127		}
128		else {
129			*o = *i++;
130		}
131	}
132	*o = '\0';
133}
134
135MenuRoot *GetRoot(char *name, char *fore, char *back)
136{
137	MenuRoot *tmp;
138
139	tmp = FindMenuRoot(name);
140	if(tmp == NULL) {
141		tmp = NewMenuRoot(name);
142	}
143
144	if(fore) {
145		bool save;
146
147		save = Scr->FirstTime;
148		Scr->FirstTime = true;
149		GetColor(COLOR, &tmp->highlight.fore, fore);
150		GetColor(COLOR, &tmp->highlight.back, back);
151		Scr->FirstTime = save;
152	}
153
154	return tmp;
155}
156
157void GotButton(int butt, int func)
158{
159	int i;
160	MenuItem *item;
161
162	for(i = 0; i < NUM_CONTEXTS; i++) {
163		if((cont & (1 << i)) == 0) {
164			continue;
165		}
166
167		if(func == F_MENU) {
168			pull->prev = NULL;
169			AddFuncButton(butt, i, mods, func, pull, NULL);
170		}
171		else {
172			root = GetRoot(TWM_ROOT, NULL, NULL);
173			item = AddToMenu(root, "x", Action, NULL, func, NULL, NULL);
174			AddFuncButton(butt, i, mods, func, NULL, item);
175		}
176	}
177
178	Action = "";
179	pull = NULL;
180	cont = 0;
181	mods_used |= mods;
182	mods = 0;
183}
184
185void GotKey(char *key, int func)
186{
187	int i;
188
189	for(i = 0; i < NUM_CONTEXTS; i++) {
190		if((cont & (1 << i)) == 0) {
191			continue;
192		}
193
194		if(func == F_MENU) {
195			pull->prev = NULL;
196			if(!AddFuncKey(key, i, mods, func, pull, Name, Action)) {
197				break;
198			}
199		}
200		else if(!AddFuncKey(key, i, mods, func, NULL, Name, Action)) {
201			break;
202		}
203	}
204
205	Action = "";
206	pull = NULL;
207	cont = 0;
208	mods_used |= mods;
209	mods = 0;
210}
211
212
213void GotTitleButton(char *bitmapname, int func, bool rightside)
214{
215	if(!CreateTitleButton(bitmapname, func, Action, pull, rightside, true)) {
216		twmrc_error_prefix();
217		fprintf(stderr,
218		        "unable to create %s titlebutton \"%s\"\n",
219		        rightside ? "right" : "left", bitmapname);
220	}
221	Action = "";
222	pull = NULL;
223}
224
225
226/* Check f.warptoscreen arg */
227bool
228CheckWarpScreenArg(const char *s)
229{
230	/* next/prev/back are valid */
231	if(strcasecmp(s, WARPSCREEN_NEXT) == 0 ||
232	                strcasecmp(s, WARPSCREEN_PREV) == 0 ||
233	                strcasecmp(s, WARPSCREEN_BACK) == 0) {
234		return true;
235	}
236
237	/* Or if the whole thing is numeric, it's valid too */
238	for(; *s && Isascii(*s) && Isdigit(*s); s++) {
239		/* nada */;
240	}
241	return (*s ? false : true);
242}
243
244
245/* f.warptoring arg */
246bool
247CheckWarpRingArg(const char *s)
248{
249	if(strcasecmp(s, WARPSCREEN_NEXT) == 0 ||
250	                strcasecmp(s, WARPSCREEN_PREV) == 0) {
251		return true;
252	}
253
254	return false;
255}
256
257
258/* f.colormap arg */
259bool
260CheckColormapArg(const char *s)
261{
262	if(strcasecmp(s, COLORMAP_NEXT) == 0 ||
263	                strcasecmp(s, COLORMAP_PREV) == 0 ||
264	                strcasecmp(s, COLORMAP_DEFAULT) == 0) {
265		return true;
266	}
267
268	return false;
269}
270