/*
* (C)opyright 2007-2009 Robert Manea <rob dot manea at gmail dot com>
* See LICENSE file for license details.
*
*/
#include "dzen.h"
#include "action.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct event_lookup ev_lookup_table[] = {
{ "onstart", onstart},
{ "onexit", onexit},
{ "onnewinput", onnewinput},
{ "button1", button1},
{ "button2", button2},
{ "button3", button3},
{ "button4", button4},
{ "button5", button5},
{ "button6", button6},
{ "button7", button7},
{ "entertitle", entertitle},
{ "leavetitle", leavetitle},
{ "enterslave", enterslave},
{ "leaveslave", leaveslave},
{ "sigusr1", sigusr1},
{ "sigusr2", sigusr2},
{ "keymarker", keymarker},
{ 0, 0 }
};
struct action_lookup ac_lookup_table[] = {
{ "print", a_print },
{ "exec", a_exec},
{ "exit", a_exit},
{ "collapse", a_collapse},
{ "uncollapse", a_uncollapse},
{ "togglecollapse", a_togglecollapse},
{ "stick", a_stick},
{ "unstick", a_unstick},
{ "togglestick", a_togglestick},
{ "hide", a_hide},
{ "unhide", a_unhide},
{ "togglehide", a_togglehide},
{ "scrollup", a_scrollup},
{ "scrolldown", a_scrolldown},
{ "menuprint", a_menuprint},
{ "menuprint_noparse", a_menuprint_noparse},
{ "menuexec", a_menuexec},
{ "raise", a_raise},
{ "lower", a_lower},
{ "scrollhome", a_scrollhome},
{ "scrollend", a_scrollend},
{ "grabkeys", a_grabkeys},
{ "ungrabkeys", a_ungrabkeys},
{ "grabmouse", a_grabmouse},
{ "ungrabmouse", a_ungrabmouse},
{ 0, 0 }
};
ev_list *head = NULL;
static int
new_event(long evid) {
ev_list *item, *newitem;
if(!head) {
head = emalloc(sizeof (ev_list));
head->id = evid;
head->next = NULL;
}
else {
item = head;
/* check if we already handle this event */
while(item) {
if(item->id == evid)
return 0;
item = item->next;
}
item = head;
while(item->next)
item = item->next;
newitem = emalloc(sizeof (ev_list));
newitem->id = evid;
item->next = newitem;
newitem->next = NULL;
}
return 0;
}
static void
add_handler(long evid, int hpos, handlerf* hcb) {
ev_list *item;
item = head;
while(item) {
if(item->id == evid) {
if(hpos < MAXACTIONS) {
item->action[hpos] = emalloc(sizeof(As));
item->action[hpos]->handler = hcb;
}
break;
}
item = item->next;
}
}
static void
add_option(long evid, int hpos, int opos, char* opt) {
ev_list *item;
item = head;
while(item) {
if(item->id == evid) {
if(opos < MAXOPTIONS) {
item->action[hpos]->options[opos] = estrdup(opt);
item->action[hpos]->options[opos+1] = NULL;
}
break;
}
item = item->next;
}
}
int
find_event(long evid) {
ev_list *item;
item = head;
while(item) {
if(item->id == evid)
return item->id;
item = item->next;
}
return -1;
}
void
do_action(long evid) {
int i;
ev_list *item;
item = head;
while(item) {
if(item->id == evid)
break;
item = item->next;
}
if(item) {
for(i=0; item->action[i]->handler; i++) {
item->action[i]->handler(item->action[i]->options);
}
}
}
int
get_ev_id(const char *evname) {
int i;
KeySym ks;
/* check for keyboard event */
if((!strncmp(evname, "key_", 4))
&& ((ks = XStringToKeysym(evname+4)) != NoSymbol)) {
return ks+keymarker;
}
/* own events */
for(i=0; ev_lookup_table[i].name; i++) {
if(strncmp(ev_lookup_table[i].name, evname, strlen(ev_lookup_table[i].name)) == 0)
return ev_lookup_table[i].id;
}
return -1;
}
handlerf *
get_action_handler(const char *acname) {
int i;
for(i=0; ac_lookup_table[i].name; i++) {
if(strcmp(ac_lookup_table[i].name, acname) == 0)
return ac_lookup_table[i].handler;
}
return NULL;
}
void
free_event_list(void) {
int i;
ev_list *item;
item = head;
while(item) {
for(i=0; item->action[i]->handler; i++)
free(item->action[i]);
item = item->next;
}
}
void
fill_ev_table(char *input) {
char *str1, *str2, *str3, *str4,
*token, *subtoken, *kommatoken, *dptoken;
char *saveptr1=NULL,
*saveptr2=NULL,
*saveptr3=NULL,
*saveptr4=NULL;
int j, i=0, k=0;
long eid=0;
handlerf *ah=0;
for (j = 1, str1 = input; ; j++, str1 = NULL) {
token = strtok_r(str1, ";", &saveptr1);
if (token == NULL)
break;
for (str2 = token; ; str2 = NULL) {
subtoken = strtok_r(str2, "=", &saveptr2);
if (subtoken == NULL)
break;
if( (str2 == token) && ((eid = get_ev_id(subtoken)) != -1))
;
else if(eid == -1)
break;
for (str3 = subtoken; ; str3 = NULL) {
kommatoken = strtok_r(str3, ",", &saveptr3);
if (kommatoken == NULL)
break;
for (str4 = kommatoken; ; str4 = NULL) {
dptoken = strtok_r(str4, ":", &saveptr4);
if (dptoken == NULL) {
break;
}
if(str4 == kommatoken && str4 != token && eid != -1) {
if((ah = get_action_handler(dptoken)) != NULL) {
new_event(eid);
add_handler(eid, i, ah);
i++;
}
}
else if(str4 != token && eid != -1 && ah) {
add_option(eid, i-1, k, dptoken);
k++;
}
else if(!ah)
break;
}
k=0;
}
new_event(eid);
add_handler(eid, i, NULL);
i=0;
}
}
}
/* actions */
int
a_exit(char * opt[]) {
if(opt[0])
dzen.ret_val = atoi(opt[0]);
dzen.running = False;
return 0;
}
int
a_collapse(char * opt[]){
(void)opt;
if(!dzen.slave_win.ishmenu
&& dzen.slave_win.max_lines
&& !dzen.slave_win.issticky) {
XUnmapWindow(dzen.dpy, dzen.slave_win.win);
}
return 0;
}
int
a_uncollapse(char * opt[]){
int i;
(void)opt;
if(!dzen.slave_win.ishmenu
&& dzen.slave_win.max_lines
&& !dzen.slave_win.issticky) {
XMapRaised(dzen.dpy, dzen.slave_win.win);
for(i=0; i < dzen.slave_win.max_lines; i++)
XMapWindow(dzen.dpy, dzen.slave_win.line[i]);
}
return 0;
}
int
a_togglecollapse(char * opt[]){
XWindowAttributes wa;
(void)opt;
if(dzen.slave_win.max_lines &&
(XGetWindowAttributes(dzen.dpy, dzen.slave_win.win, &wa), wa.map_state == IsUnmapped))
a_uncollapse(NULL);
else
a_collapse(NULL);
return 0;
}
int
a_stick(char * opt[]) {
(void)opt;
if(!dzen.slave_win.ishmenu
&& dzen.slave_win.max_lines)
dzen.slave_win.issticky = True;
return 0;
}
int
a_unstick(char * opt[]) {
(void)opt;
if(!dzen.slave_win.ishmenu
&& dzen.slave_win.max_lines)
dzen.slave_win.issticky = False;
return 0;
}
int
a_togglestick(char * opt[]) {
(void)opt;
if(!dzen.slave_win.ishmenu
&& dzen.slave_win.max_lines)
dzen.slave_win.issticky = dzen.slave_win.issticky ? False : True;
return 0;
}
static void
scroll(int n) {
if(dzen.slave_win.tcnt <= dzen.slave_win.max_lines)
return;
if(dzen.slave_win.first_line_vis + n < 0) {
dzen.slave_win.first_line_vis = 0;
dzen.slave_win.last_line_vis = dzen.slave_win.max_lines;
}
else if(dzen.slave_win.last_line_vis + n > dzen.slave_win.tcnt) {
dzen.slave_win.first_line_vis = dzen.slave_win.tcnt - dzen.slave_win.max_lines;
dzen.slave_win.last_line_vis = dzen.slave_win.tcnt;
}
else {
dzen.slave_win.first_line_vis += n;
dzen.slave_win.last_line_vis += n;
}
x_draw_body();
}
int
a_scrollup(char * opt[]) {
int n=1;
if(opt[0])
n = atoi(opt[0]);
if(dzen.slave_win.max_lines)
scroll(-1*n);
return 0;
}
int
a_scrolldown(char * opt[]) {
int n=1;
if(opt[0])
n = atoi(opt[0]);
if(dzen.slave_win.max_lines)
scroll(n);
return 0;
}
int
a_hide(char * opt[]) {
int n=1;
printf("n:%d\n", n);
if(!dzen.title_win.ishidden) {
if(!dzen.slave_win.ishmenu)
XResizeWindow(dzen.dpy, dzen.title_win.win, dzen.title_win.width, 1);
else
XResizeWindow(dzen.dpy, dzen.slave_win.win, dzen.title_win.width, 1);
dzen.title_win.ishidden = True;
}
return 0;
}
int
a_unhide(char * opt[]) {
(void)opt;
if(dzen.title_win.ishidden) {
if(!dzen.slave_win.ishmenu)
XResizeWindow(dzen.dpy, dzen.title_win.win, dzen.title_win.width, dzen.line_height);
else
XResizeWindow(dzen.dpy, dzen.slave_win.win, dzen.title_win.width, dzen.line_height);
dzen.title_win.ishidden = False;
}
return 0;
}
int
a_togglehide(char * opt[]) {
dzen.title_win.ishidden ?
a_unhide(NULL) :
a_hide(opt);
return 0;
}
int
a_exec(char * opt[]) {
int i;
if(opt)
for(i=0; opt[i]; i++)
if(opt[i]) spawn(opt[i]);
return 0;
}
int
a_print(char * opt[]) {
int i;
if(opt)
for(i=0; opt[i]; i++)
puts(opt[i]);
return 0;
}
int
a_menuprint(char * opt[]) {
char *text;
int i;
if(dzen.slave_win.ismenu && dzen.slave_win.sel_line != -1
&& (dzen.slave_win.sel_line + dzen.slave_win.first_line_vis) < dzen.slave_win.tcnt) {
text = parse_line(NULL, dzen.slave_win.sel_line, 0, 0, 1);
printf("%s", text);
if(opt)
for(i=0; opt[i]; ++i)
printf("%s", opt[i]);
puts("");
fflush(stdout);
dzen.slave_win.sel_line = -1;
free(text);
}
return 0;
}
int
a_menuprint_noparse(char * opt[]) {
int i;
if(dzen.slave_win.ismenu && dzen.slave_win.sel_line != -1
&& (dzen.slave_win.sel_line + dzen.slave_win.first_line_vis) < dzen.slave_win.tcnt) {
printf("%s", dzen.slave_win.tbuf[dzen.slave_win.sel_line]);
if(opt)
for(i=0; opt[i]; ++i)
printf("%s", opt[i]);
puts("");
fflush(stdout);
dzen.slave_win.sel_line = -1;
}
return 0;
}
int
a_menuexec(char * opt[]) {
char *text;
(void)opt;
if(dzen.slave_win.ismenu && dzen.slave_win.sel_line != -1
&& (dzen.slave_win.sel_line + dzen.slave_win.first_line_vis) < dzen.slave_win.tcnt) {
text = parse_line(NULL, dzen.slave_win.sel_line, 0, 0, 1);
spawn(text);
dzen.slave_win.sel_line = -1;
free(text);
}
return 0;
}
int
a_raise(char * opt[]) {
(void)opt;
XRaiseWindow(dzen.dpy, dzen.title_win.win);
if(dzen.slave_win.max_lines)
XRaiseWindow(dzen.dpy, dzen.slave_win.win);
return 0;
}
int
a_lower(char * opt[]) {
(void)opt;
XLowerWindow(dzen.dpy, dzen.title_win.win);
if(dzen.slave_win.max_lines)
XLowerWindow(dzen.dpy, dzen.slave_win.win);
return 0;
}
int
a_scrollhome(char * opt[]) {
(void)opt;
if(dzen.slave_win.max_lines) {
dzen.slave_win.first_line_vis = 0;
dzen.slave_win.last_line_vis = dzen.slave_win.max_lines;
x_draw_body();
}
return 0;
}
int
a_scrollend(char * opt[]) {
(void)opt;
if(dzen.slave_win.max_lines) {
dzen.slave_win.first_line_vis = dzen.slave_win.tcnt - dzen.slave_win.max_lines ;
dzen.slave_win.last_line_vis = dzen.slave_win.tcnt;
x_draw_body();
}
return 0;
}
int
a_grabkeys(char * opt[]) {
(void)opt;
XGrabKeyboard(dzen.dpy, RootWindow(dzen.dpy, dzen.screen),
True, GrabModeAsync, GrabModeAsync, CurrentTime);
return 0;
}
int
a_ungrabkeys(char * opt[]) {
(void)opt;
XUngrabKeyboard(dzen.dpy, CurrentTime);
return 0;
}
int
a_grabmouse(char * opt[]) {
(void)opt;
XGrabPointer(dzen.dpy, RootWindow(dzen.dpy, dzen.screen),
True, ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
return 0;
}
int
a_ungrabmouse(char * opt[]) {
(void)opt;
XUngrabPointer(dzen.dpy, CurrentTime);
return 0;
}