start of showing/rendering menus. woot!
[dana/openbox.git] / plugins / keyboard / keyparse.c
1 #include "kernel/parse.h"
2 #include "keyboard.h"
3
4 void keyparse(ParseToken *token)
5 {
6     static char *top = NULL;
7     static Action *action = NULL;
8     static GList *chain = NULL;
9     static gboolean err = FALSE;
10     static char *arg_str = NULL;
11     static int arg_int = 0;
12     GList *it;
13
14     if (err) {
15         if (token->type == TOKEN_NEWLINE)
16             err = FALSE;
17         /* just fall through and free the token */
18     } else if (top == NULL) {
19         if (token->type == TOKEN_IDENTIFIER &&
20             !g_ascii_strcasecmp("kbind", token->data.identifier)) {
21             top = token->data.identifier;
22             return;
23         } else {
24             yyerror("syntax error (expected kbind)");
25             err = TRUE;
26         }
27     } else if (chain == NULL) {
28         if (token->type == TOKEN_LIST) {
29             for (it = token->data.list; it; it = it->next)
30                 if (((ParseToken*)it->data)->type != TOKEN_IDENTIFIER) break;
31             if (it == NULL) {
32                 chain = token->data.list;
33                 return;
34             } else {
35                 yyerror("invalid element in key chain");
36                 err = TRUE;
37             }
38         } else {
39             yyerror("syntax error (expected key chain)");
40             err = TRUE;
41         }
42     } else if (action == NULL) {
43         if (token->type == TOKEN_IDENTIFIER) {
44             action = action_from_string(token->data.identifier);
45
46             /* no move/resize with the keyboard */
47             if (action &&
48                 (action->func == action_move ||
49                  action->func == action_resize)) {
50                 action_free(action);
51                 action = NULL;
52             }
53
54             if (action != NULL) {
55                 parse_free_token(token); /* its data isnt saved */
56                 return;
57             } else {
58                 yyerror("invalid action");
59                 err = TRUE;
60             }
61         } else {
62             yyerror("syntax error (expected action)");
63             err = TRUE;
64         }
65     } else if (token->type == TOKEN_STRING) { /* string argument */
66         arg_str = token->data.string;
67         return;
68     } else if (token->type == TOKEN_INTEGER) { /* number argument */
69         arg_int = token->data.integer;
70         return;
71     } else if (token->type != TOKEN_NEWLINE) {
72         yyerror("syntax error (unexpected trailing token)");
73         err = TRUE;
74     } else {
75         GList *strchain = NULL;
76
77         /* build a list of just char*'s */
78         for (it = chain; it; it = it->next)
79             strchain = g_list_append(strchain,
80                                      ((ParseToken*)it->data)->data.identifier);
81
82         /* these use the argument */
83         if (action->func == action_execute || action->func == action_restart)
84             action->data.execute.path = g_strdup(arg_str);
85         else if (action->func == action_showmenu)
86             action->data.showmenu.name = g_strdup(arg_str);
87         if ((action->func == action_desktop ||
88              action->func == action_send_to_desktop) &&
89             arg_int)
90             action->data.desktop.desk = (unsigned) arg_int - 1;
91         if (action->func == action_move_relative_horz ||
92             action->func == action_move_relative_vert ||
93             action->func == action_resize_relative_horz ||
94             action->func == action_resize_relative_vert)
95             action->data.relative.delta = arg_int;
96
97         if (kbind(strchain, action))
98             action = NULL; /* don't free this if kbind succeeds */
99         else
100             yyerror("failed to add key binding");
101         /* free the char*'s */
102         g_list_free(strchain);
103
104         err = FALSE;
105     }    
106
107     g_free(top); top = NULL;
108     action_free(action); action = NULL;
109     g_free(arg_str); arg_str = NULL;
110     arg_int = 0;
111     for (it = chain; it; it = it->next) {
112         parse_free_token(it->data);
113         g_free(it->data);
114     }
115     g_list_free(chain); chain = NULL;
116     parse_free_token(token);
117 }