1 /*
2 * (C)opyright 2007-2009 Robert Manea <rob dot manea at gmail dot com>
3 * See LICENSE file for license details.
4 *
5 */
6 
7 #include "dzen.h"
8 #include "action.h"
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 
13 
14 struct event_lookup ev_lookup_table[] = {
15 	{ "onstart",        onstart},
16 	{ "onexit",         onexit},
17 	{ "onnewinput",     onnewinput},
18 	{ "button1",        button1},
19 	{ "button2",        button2},
20 	{ "button3",        button3},
21 	{ "button4",        button4},
22 	{ "button5",        button5},
23 	{ "button6",        button6},
24 	{ "button7",        button7},
25 	{ "entertitle",     entertitle},
26 	{ "leavetitle",     leavetitle},
27 	{ "enterslave",     enterslave},
28 	{ "leaveslave",     leaveslave},
29 	{ "sigusr1",        sigusr1},
30 	{ "sigusr2",        sigusr2},
31 	{ "keymarker",      keymarker},
32 	{ 0, 0 }
33 };
34 
35 struct action_lookup  ac_lookup_table[] = {
36 	{ "print",          a_print },
37 	{ "exec",           a_exec},
38 	{ "exit",           a_exit},
39 	{ "collapse",       a_collapse},
40 	{ "uncollapse",     a_uncollapse},
41 	{ "togglecollapse",	a_togglecollapse},
42 	{ "stick",          a_stick},
43 	{ "unstick",        a_unstick},
44 	{ "togglestick",    a_togglestick},
45 	{ "hide",           a_hide},
46 	{ "unhide",         a_unhide},
47 	{ "togglehide",     a_togglehide},
48 	{ "scrollup",       a_scrollup},
49 	{ "scrolldown",     a_scrolldown},
50 	{ "menuprint",      a_menuprint},
51 	{ "menuprint_noparse",      a_menuprint_noparse},
52 	{ "menuexec",       a_menuexec},
53 	{ "raise",          a_raise},
54 	{ "lower",          a_lower},
55 	{ "scrollhome",     a_scrollhome},
56 	{ "scrollend",      a_scrollend},
57 	{ "grabkeys",       a_grabkeys},
58 	{ "ungrabkeys",     a_ungrabkeys},
59 	{ "grabmouse",       a_grabmouse},
60 	{ "ungrabmouse",     a_ungrabmouse},
61 	{ 0, 0 }
62 };
63 
64 ev_list *head = NULL;
65 
66 static int
new_event(long evid)67 new_event(long evid) {
68 	ev_list *item, *newitem;
69 
70 	if(!head) {
71 		head = emalloc(sizeof (ev_list));
72 		head->id = evid;
73 		head->next = NULL;
74 	}
75 	else {
76 		item = head;
77 		/* check if we already handle this event */
78 		while(item) {
79 			if(item->id == evid)
80 				return 0;
81 			item = item->next;
82 		}
83 		item = head;
84 		while(item->next)
85 			item = item->next;
86 
87 		newitem = emalloc(sizeof (ev_list));
88 		newitem->id = evid;
89 		item->next = newitem;
90 		newitem->next = NULL;
91 	}
92 	return 0;
93 }
94 
95 static void
add_handler(long evid,int hpos,handlerf * hcb)96 add_handler(long evid, int hpos, handlerf* hcb) {
97 	ev_list *item;
98 
99 	item = head;
100 	while(item) {
101 		if(item->id == evid) {
102 			if(hpos < MAXACTIONS) {
103 				item->action[hpos] = emalloc(sizeof(As));
104 				item->action[hpos]->handler = hcb;
105 			}
106 			break;
107 		}
108 		item = item->next;
109 	}
110 }
111 
112 static void
add_option(long evid,int hpos,int opos,char * opt)113 add_option(long evid, int hpos, int opos, char* opt) {
114 	ev_list *item;
115 
116 	item = head;
117 	while(item) {
118 		if(item->id == evid) {
119 			if(opos < MAXOPTIONS) {
120 				item->action[hpos]->options[opos] = estrdup(opt);
121 				item->action[hpos]->options[opos+1] = NULL;
122 			}
123 			break;
124 		}
125 		item = item->next;
126 	}
127 }
128 
129 int
find_event(long evid)130 find_event(long evid) {
131 	ev_list *item;
132 
133 	item = head;
134 	while(item) {
135 		if(item->id == evid)
136 			return item->id;
137 		item = item->next;
138 	}
139 
140 	return -1;
141 }
142 
143 void
do_action(long evid)144 do_action(long evid) {
145 	int i;
146 	ev_list *item;
147 
148 	item = head;
149 	while(item) {
150 		if(item->id == evid)
151 			break;
152 		item = item->next;
153 	}
154 
155 	if(item) {
156 		for(i=0; item->action[i]->handler; i++) {
157 			item->action[i]->handler(item->action[i]->options);
158 		}
159 	}
160 }
161 
162 int
get_ev_id(const char * evname)163 get_ev_id(const char *evname) {
164 	int i;
165 	KeySym ks;
166 
167 	/* check for keyboard event */
168 	if((!strncmp(evname, "key_", 4))
169 			&& ((ks = XStringToKeysym(evname+4)) != NoSymbol)) {
170 		return ks+keymarker;
171 	}
172 
173 	/* own events */
174 	for(i=0; ev_lookup_table[i].name; i++) {
175 		if(strncmp(ev_lookup_table[i].name, evname, strlen(ev_lookup_table[i].name)) == 0)
176 			return ev_lookup_table[i].id;
177 	}
178 	return -1;
179 }
180 
181 handlerf *
get_action_handler(const char * acname)182 get_action_handler(const char *acname) {
183 	int i;
184 
185 	for(i=0; ac_lookup_table[i].name; i++) {
186 		if(strcmp(ac_lookup_table[i].name, acname) == 0)
187 			return ac_lookup_table[i].handler;
188 	}
189 	return NULL;
190 }
191 
192 
193 void
free_event_list(void)194 free_event_list(void) {
195 	int i;
196 	ev_list *item;
197 
198 	item = head;
199 	while(item) {
200 		for(i=0; item->action[i]->handler; i++)
201 			free(item->action[i]);
202 		item = item->next;
203 	}
204 }
205 
206 void
fill_ev_table(char * input)207 fill_ev_table(char *input) {
208 	char *str1, *str2, *str3, *str4,
209 		 *token, *subtoken, *kommatoken, *dptoken;
210 	char *saveptr1=NULL,
211 		 *saveptr2=NULL,
212 		 *saveptr3=NULL,
213 		 *saveptr4=NULL;
214 	int j, i=0, k=0;
215 	long eid=0;
216 	handlerf *ah=0;
217 
218 	for (j = 1, str1 = input; ; j++, str1 = NULL) {
219 		token = strtok_r(str1, ";", &saveptr1);
220 		if (token == NULL)
221 			break;
222 
223 		for (str2 = token; ; str2 = NULL) {
224 			subtoken = strtok_r(str2, "=", &saveptr2);
225 			if (subtoken == NULL)
226 				break;
227 			if( (str2 == token) && ((eid = get_ev_id(subtoken)) != -1))
228 				;
229 			else if(eid == -1)
230 				break;
231 
232 			for (str3 = subtoken; ; str3 = NULL) {
233 				kommatoken = strtok_r(str3, ",", &saveptr3);
234 				if (kommatoken == NULL)
235 					break;
236 
237 				for (str4 = kommatoken; ; str4 = NULL) {
238 					dptoken = strtok_r(str4, ":", &saveptr4);
239 					if (dptoken == NULL) {
240 						break;
241 					}
242 					if(str4 == kommatoken && str4 != token && eid != -1) {
243 						if((ah = get_action_handler(dptoken)) != NULL) {
244 							new_event(eid);
245 							add_handler(eid, i, ah);
246 							i++;
247 						}
248 					}
249 					else if(str4 != token && eid != -1 && ah) {
250 						add_option(eid, i-1, k, dptoken);
251 						k++;
252 					}
253 					else if(!ah)
254 						break;
255 				}
256 				k=0;
257 			}
258 			new_event(eid);
259 			add_handler(eid, i, NULL);
260 			i=0;
261 		}
262 	}
263 }
264 
265 
266 /* actions */
267 int
a_exit(char * opt[])268 a_exit(char * opt[]) {
269 	if(opt[0])
270 		dzen.ret_val = atoi(opt[0]);
271 	dzen.running = False;
272 	return 0;
273 }
274 
275 int
a_collapse(char * opt[])276 a_collapse(char * opt[]){
277 	(void)opt;
278 	if(!dzen.slave_win.ishmenu
279 			&& dzen.slave_win.max_lines
280 			&& !dzen.slave_win.issticky) {
281 		XUnmapWindow(dzen.dpy, dzen.slave_win.win);
282 	}
283 	return 0;
284 }
285 
286 int
a_uncollapse(char * opt[])287 a_uncollapse(char * opt[]){
288 	int i;
289 	(void)opt;
290 	if(!dzen.slave_win.ishmenu
291 			&& dzen.slave_win.max_lines
292 			&& !dzen.slave_win.issticky) {
293 		XMapRaised(dzen.dpy, dzen.slave_win.win);
294 		for(i=0; i < dzen.slave_win.max_lines; i++)
295 			XMapWindow(dzen.dpy, dzen.slave_win.line[i]);
296 	}
297 	return 0;
298 }
299 
300 int
a_togglecollapse(char * opt[])301 a_togglecollapse(char * opt[]){
302 	XWindowAttributes wa;
303 	(void)opt;
304 
305 	if(dzen.slave_win.max_lines &&
306 			(XGetWindowAttributes(dzen.dpy, dzen.slave_win.win, &wa), wa.map_state == IsUnmapped))
307 		a_uncollapse(NULL);
308 	else
309 		a_collapse(NULL);
310 
311 	return 0;
312 }
313 
314 int
a_stick(char * opt[])315 a_stick(char * opt[]) {
316 	(void)opt;
317 	if(!dzen.slave_win.ishmenu
318 			&& dzen.slave_win.max_lines)
319 		dzen.slave_win.issticky = True;
320 	return 0;
321 }
322 
323 int
a_unstick(char * opt[])324 a_unstick(char * opt[]) {
325 	(void)opt;
326 	if(!dzen.slave_win.ishmenu
327 			&& dzen.slave_win.max_lines)
328 		dzen.slave_win.issticky = False;
329 	return 0;
330 }
331 
332 int
a_togglestick(char * opt[])333 a_togglestick(char * opt[]) {
334 	(void)opt;
335 	if(!dzen.slave_win.ishmenu
336 			&& dzen.slave_win.max_lines)
337 		dzen.slave_win.issticky = dzen.slave_win.issticky ? False : True;
338 	return 0;
339 }
340 
341 static void
scroll(int n)342 scroll(int n) {
343 	if(dzen.slave_win.tcnt <= dzen.slave_win.max_lines)
344 		return;
345 	if(dzen.slave_win.first_line_vis + n < 0) {
346 		dzen.slave_win.first_line_vis = 0;
347 		dzen.slave_win.last_line_vis = dzen.slave_win.max_lines;
348 	}
349 	else if(dzen.slave_win.last_line_vis + n > dzen.slave_win.tcnt) {
350 		dzen.slave_win.first_line_vis = dzen.slave_win.tcnt - dzen.slave_win.max_lines;
351 		dzen.slave_win.last_line_vis = dzen.slave_win.tcnt;
352 	}
353 	else {
354 		dzen.slave_win.first_line_vis += n;
355 		dzen.slave_win.last_line_vis  += n;
356 	}
357 
358 	x_draw_body();
359 }
360 
361 int
a_scrollup(char * opt[])362 a_scrollup(char * opt[]) {
363 	int n=1;
364 
365 	if(opt[0])
366 		n = atoi(opt[0]);
367 	if(dzen.slave_win.max_lines)
368 			scroll(-1*n);
369 
370 	return 0;
371 }
372 
373 int
a_scrolldown(char * opt[])374 a_scrolldown(char * opt[]) {
375 	int n=1;
376 
377 	if(opt[0])
378 		n = atoi(opt[0]);
379 	if(dzen.slave_win.max_lines)
380 		scroll(n);
381 
382 	return 0;
383 }
384 
385 int
a_hide(char * opt[])386 a_hide(char * opt[]) {
387 	int n=1;
388 
389 
390 	printf("n:%d\n", n);
391 	if(!dzen.title_win.ishidden) {
392 		if(!dzen.slave_win.ishmenu)
393 			XResizeWindow(dzen.dpy, dzen.title_win.win, dzen.title_win.width, 1);
394 		else
395 			XResizeWindow(dzen.dpy, dzen.slave_win.win, dzen.title_win.width, 1);
396 
397 		dzen.title_win.ishidden = True;
398 	}
399 	return 0;
400 }
401 
402 int
a_unhide(char * opt[])403 a_unhide(char * opt[]) {
404 	(void)opt;
405 	if(dzen.title_win.ishidden) {
406 		if(!dzen.slave_win.ishmenu)
407 			XResizeWindow(dzen.dpy, dzen.title_win.win, dzen.title_win.width, dzen.line_height);
408 		else
409 			XResizeWindow(dzen.dpy, dzen.slave_win.win, dzen.title_win.width, dzen.line_height);
410 
411 		dzen.title_win.ishidden = False;
412 	}
413 	return 0;
414 }
415 
416 int
a_togglehide(char * opt[])417 a_togglehide(char * opt[]) {
418 
419 	dzen.title_win.ishidden ?
420 		a_unhide(NULL) :
421 		a_hide(opt);
422 
423 	return 0;
424 }
425 
426 int
a_exec(char * opt[])427 a_exec(char * opt[]) {
428 	int i;
429 
430 	if(opt)
431 		for(i=0; opt[i]; i++)
432 			if(opt[i]) spawn(opt[i]);
433 	return 0;
434 }
435 
436 int
a_print(char * opt[])437 a_print(char * opt[]) {
438 	int i;
439 
440 	if(opt)
441 		for(i=0; opt[i]; i++)
442 			puts(opt[i]);
443 	fflush(stdout);
444 	return 0;
445 }
446 
447 int
a_menuprint(char * opt[])448 a_menuprint(char * opt[]) {
449 	char *text;
450 	int i;
451 
452 	if(dzen.slave_win.ismenu && dzen.slave_win.sel_line != -1
453 			&& (dzen.slave_win.sel_line + dzen.slave_win.first_line_vis) < dzen.slave_win.tcnt) {
454 		text = parse_line(NULL, dzen.slave_win.sel_line, 0, 0, 1);
455 		printf("%s", text);
456 		if(opt)
457 			for(i=0; opt[i]; ++i)
458 				printf("%s", opt[i]);
459 		puts("");
460 		fflush(stdout);
461 		dzen.slave_win.sel_line = -1;
462 		free(text);
463 	}
464 	return 0;
465 }
466 
467 int
a_menuprint_noparse(char * opt[])468 a_menuprint_noparse(char * opt[]) {
469 	int i;
470 
471 	if(dzen.slave_win.ismenu && dzen.slave_win.sel_line != -1
472 			&& (dzen.slave_win.sel_line + dzen.slave_win.first_line_vis) < dzen.slave_win.tcnt) {
473 		printf("%s", dzen.slave_win.tbuf[dzen.slave_win.sel_line]);
474 		if(opt)
475 			for(i=0; opt[i]; ++i)
476 				printf("%s", opt[i]);
477 		puts("");
478 		fflush(stdout);
479 		dzen.slave_win.sel_line = -1;
480 	}
481 	return 0;
482 }
483 
484 int
a_menuexec(char * opt[])485 a_menuexec(char * opt[]) {
486 	char *text;
487 	(void)opt;
488 
489 	if(dzen.slave_win.ismenu && dzen.slave_win.sel_line != -1
490 			&& (dzen.slave_win.sel_line + dzen.slave_win.first_line_vis) < dzen.slave_win.tcnt) {
491 		text = parse_line(NULL, dzen.slave_win.sel_line, 0, 0, 1);
492 		spawn(text);
493 		dzen.slave_win.sel_line = -1;
494 		free(text);
495 	}
496 	return 0;
497 }
498 
499 int
a_raise(char * opt[])500 a_raise(char * opt[]) {
501 	(void)opt;
502 	XRaiseWindow(dzen.dpy, dzen.title_win.win);
503 
504 	if(dzen.slave_win.max_lines)
505 		XRaiseWindow(dzen.dpy, dzen.slave_win.win);
506 	return 0;
507 }
508 
509 int
a_lower(char * opt[])510 a_lower(char * opt[]) {
511 	(void)opt;
512 	XLowerWindow(dzen.dpy, dzen.title_win.win);
513 
514 	if(dzen.slave_win.max_lines)
515 		XLowerWindow(dzen.dpy, dzen.slave_win.win);
516 	return 0;
517 }
518 
519 int
a_scrollhome(char * opt[])520 a_scrollhome(char * opt[]) {
521 	(void)opt;
522 	if(dzen.slave_win.max_lines) {
523 		dzen.slave_win.first_line_vis = 0;
524 		dzen.slave_win.last_line_vis  = dzen.slave_win.max_lines;
525 
526 		x_draw_body();
527 	}
528 	return 0;
529 }
530 
531 int
a_scrollend(char * opt[])532 a_scrollend(char * opt[]) {
533 	(void)opt;
534 	if(dzen.slave_win.max_lines) {
535 		dzen.slave_win.first_line_vis = dzen.slave_win.tcnt - dzen.slave_win.max_lines ;
536 		dzen.slave_win.last_line_vis  = dzen.slave_win.tcnt;
537 
538 		x_draw_body();
539 	}
540 	return 0;
541 }
542 
543 int
a_grabkeys(char * opt[])544 a_grabkeys(char * opt[]) {
545 	(void)opt;
546 	XGrabKeyboard(dzen.dpy, RootWindow(dzen.dpy, dzen.screen),
547 			True, GrabModeAsync, GrabModeAsync, CurrentTime);
548 	return 0;
549 }
550 
551 int
a_ungrabkeys(char * opt[])552 a_ungrabkeys(char * opt[]) {
553 	(void)opt;
554 	XUngrabKeyboard(dzen.dpy, CurrentTime);
555 	return 0;
556 }
557 
558 int
a_grabmouse(char * opt[])559 a_grabmouse(char * opt[]) {
560 	(void)opt;
561 	XGrabPointer(dzen.dpy, RootWindow(dzen.dpy, dzen.screen),
562 			True, ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
563 	return 0;
564 }
565 
566 int
a_ungrabmouse(char * opt[])567 a_ungrabmouse(char * opt[]) {
568 	(void)opt;
569 	XUngrabPointer(dzen.dpy, CurrentTime);
570 	return 0;
571 }
572 
573