1 /***************************************************************************
2         xbindkeys : a program to bind keys to commands under X11.
3                            -------------------
4     begin                : Sat Oct 13 14:11:34 CEST 2001
5     copyright            : (C) 2001 by Philippe Brochard
6     email                : hocwp@free.fr
7  ***************************************************************************/
8 
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version.                                   *
15  *                                                                         *
16  ***************************************************************************/
17 
18 #include "keys.h"
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <string.h>
23 #include <sys/types.h>
24 #include <sys/wait.h>
25 #include <X11/keysym.h>
26 #include "xbindkeys.h"
27 #include "keys.h"
28 #include "config.h"
29 #include "options.h"
30 #include "grab_key.h"
31 
32 
33 #define STR_KEY_LEN 1000
34 
35 int nb_keys;
36 Keys_t *keys;
37 
38 extern char rc_file[512];
39 
40 static char *modifier_string[] = { "Control", "Shift", "Alt", "Mod2",
41   "Mod3", "Mod4", "Mod5"
42 };
43 
44 
45 int
init_keys(void)46 init_keys (void)
47 {
48   nb_keys = 0;
49   keys = NULL;
50 
51   return 0;
52 }
53 
54 void
close_keys(void)55 close_keys (void)
56 {
57   int i;
58 
59   for (i = 0; i < nb_keys; i++)
60     free_key (&keys[i]);
61 
62   if (keys != NULL)
63     {
64       free (keys);
65       keys = NULL;
66     }
67 
68   nb_keys = 0;
69 }
70 
71 
72 
73 int
add_key(KeyType_t type,EventType_t event_type,KeySym keysym,KeyCode keycode,unsigned int button,unsigned int modifier,char * command,SCM function)74 add_key (KeyType_t type, EventType_t event_type, KeySym keysym, KeyCode keycode,
75 	 unsigned int button, unsigned int modifier, char *command, SCM function)
76 {
77   Keys_t *keys_bis = NULL;
78   int i;
79 
80   if (keysym == 0 && keycode == 0 && button == 0)
81     {
82       fprintf (stderr, "Warning: unkown key in RC file : %s\n", rc_file);
83       return (-1);
84     }
85 
86   /* make new array keys_bis */
87   keys_bis = (Keys_t *) malloc ((nb_keys + 1) * sizeof (Keys_t));
88   if (keys_bis == NULL)
89     return (-1);
90 
91   if (keys != NULL)
92     {
93       /* copy keys in keys_bis */
94       for (i = 0; i < nb_keys; i++)
95 	{
96 	  keys_bis[i] = keys[i];
97 	}
98 
99       /* delete old keys array */
100       free (keys);
101     }
102 
103   /* make keys_bis as keys */
104   keys = keys_bis;
105 
106   modifier &= ~(numlock_mask | capslock_mask | scrolllock_mask);
107 
108   /* set key */
109   if (type == SYM)
110     {
111       set_keysym (&keys[nb_keys], event_type, keysym, modifier, command, function);
112     }
113   else if (type == BUTTON)
114     {
115       set_button (&keys[nb_keys], event_type, button, modifier, command, function);
116     }
117   else
118     {
119       set_keycode (&keys[nb_keys], event_type, keycode, modifier, command, function);
120     }
121 
122   /* new key */
123   nb_keys += 1;
124 
125   return (0);
126 }
127 
128 
129 
130 
131 
132 
133 void
show_key_binding(Display * d)134 show_key_binding (Display * d)
135 {
136   int i;
137   int last_verbose = verbose;
138 
139   verbose = 1;
140 
141   for (i = 0; i < nb_keys; i++)
142     {
143       print_key (d, &keys[i]);
144     }
145 
146   verbose = last_verbose;
147 }
148 
149 
150 
151 void
modifier_to_string(unsigned int modifier,char * str)152 modifier_to_string (unsigned int modifier, char *str)
153 {
154   str[0] = '\0';
155 
156   if (modifier & ControlMask)
157     {
158       if (str[0])
159 	strncat (str, "+", STR_KEY_LEN);
160       strncat (str, modifier_string[0], STR_KEY_LEN);
161     }
162 
163   if (modifier & ShiftMask)
164     {
165       if (str[0])
166 	strncat (str, "+", STR_KEY_LEN);
167       strncat (str, modifier_string[1], STR_KEY_LEN);
168     }
169 
170 
171   if (modifier & Mod1Mask)
172     {
173       if (str[0])
174 	strncat (str, "+", STR_KEY_LEN);
175       strncat (str, modifier_string[2], STR_KEY_LEN);
176     }
177 
178   if (modifier & Mod2Mask)
179     {
180       if (str[0])
181 	strncat (str, "+", STR_KEY_LEN);
182       strncat (str, modifier_string[3], STR_KEY_LEN);
183     }
184 
185   if (modifier & Mod3Mask)
186     {
187       if (str[0])
188 	strncat (str, "+", STR_KEY_LEN);
189       strncat (str, modifier_string[4], STR_KEY_LEN);
190     }
191 
192   if (modifier & Mod4Mask)
193     {
194       if (str[0])
195 	strncat (str, "+", STR_KEY_LEN);
196       strncat (str, modifier_string[5], STR_KEY_LEN);
197     }
198 
199   if (modifier & Mod5Mask)
200     {
201       if (str[0])
202 	strncat (str, "+", STR_KEY_LEN);
203       strncat (str, modifier_string[6], STR_KEY_LEN);
204     }
205 }
206 
207 
208 void
print_key(Display * d,Keys_t * key)209 print_key (Display * d, Keys_t * key)
210 {
211   char str[STR_KEY_LEN];
212   int keysyms_per_keycode_return;
213 
214   if (verbose)
215     {
216       if (key->type == SYM)
217 	{
218 	  modifier_to_string (key->modifier, str);
219 
220 	  printf ("\"%s\"\n    %s%s%s%s\n",
221 		  key->command != NULL ? key->command : ( key->function != 0 ? "(Scheme function)" : "NoCommand" ),
222 		  key->event_type == PRESS ? "" : "Release + ",
223 		  str, str[0] ? " + " : "", XKeysymToString (key->key.sym));
224 	}
225       else if (key->type == BUTTON)
226 	{
227 	  printf ("\"%s\"\n    %sm:0x%x + b:%d   (mouse)\n",
228 		  key->command != NULL ? key->command : ( key->function != 0 ? "(Scheme function)" : "NoCommand" ),
229 		  key->event_type == PRESS ? "" : "Release + ",
230 		  key->modifier, key->key.button);
231 	}
232       else
233 	{
234 	  printf ("\"%s\"\n    %sm:0x%x + c:%d\n",
235 		  key->command != NULL ? key->command : ( key->function != 0 ? "(Scheme function)" : "NoCommand" ),
236 		  key->event_type == PRESS ? "" : "Release + ",
237 		  key->modifier, key->key.code);
238 	  if (d != NULL)
239 	    {
240 	      modifier_to_string (key->modifier, str);
241 	      printf ("    %s%s%s%s\n",
242 		      str,
243 		      str[0] ? " + " : "",
244 		      key->event_type == PRESS ? "" : "Release + ",
245 		      (XKeysymToString (*XGetKeyboardMapping(d, key->key.code, 1, &keysyms_per_keycode_return)) != NULL) ?
246                       XKeysymToString (*XGetKeyboardMapping(d, key->key.code, 1, &keysyms_per_keycode_return)) : "NoSymbol");
247 	    }
248 	}
249     }
250 }
251 
252 
253 void
set_keysym(Keys_t * key,EventType_t event_type,KeySym keysym,unsigned int modifier,char * command,SCM function)254 set_keysym (Keys_t * key, EventType_t event_type, KeySym keysym,
255 	    unsigned int modifier, char *command, SCM function)
256 {
257   key->type = SYM;
258   key->event_type = event_type;
259   key->key.sym = keysym;
260   key->modifier = modifier;
261 
262   if (command != NULL)
263     {
264       key->command = (char *) malloc ((strlen (command) + 1) * sizeof (char));
265 
266       if (key->command != NULL)
267 	strncpy (key->command, command, strlen (command) + 1);
268     }
269   else
270     {
271       key->command = NULL;
272     }
273 
274   key->function = function;
275 
276   //  printf("******************* ICICICICICI *********************\n");
277   //#ifdef GUILE_FLAG
278   //  printf("  name=%d\n", SCM_IMP (key->function));
279   //#endif
280 
281   //  scm_permanent_object (key->function);
282 }
283 
284 void
set_keycode(Keys_t * key,EventType_t event_type,KeyCode keycode,unsigned int modifier,char * command,SCM function)285 set_keycode (Keys_t * key, EventType_t event_type, KeyCode keycode,
286 	     unsigned int modifier, char *command, SCM function)
287 {
288   key->type = CODE;
289   key->event_type = event_type;
290   key->key.code = keycode;
291   key->modifier = modifier;
292 
293   if (command != NULL)
294     {
295       key->command = (char *) malloc ((strlen (command) + 1) * sizeof (char));
296 
297       if (key->command != NULL)
298 	strncpy (key->command, command, strlen (command) + 1);
299     }
300   else
301     {
302       key->command = NULL;
303     }
304 
305   key->function = function;
306 }
307 
308 
309 void
set_button(Keys_t * key,EventType_t event_type,unsigned int button,unsigned int modifier,char * command,SCM function)310 set_button (Keys_t * key, EventType_t event_type, unsigned int button,
311 	    unsigned int modifier, char *command, SCM function)
312 {
313   key->type = BUTTON;
314   key->event_type = event_type;
315   key->key.button = button;
316   key->modifier = modifier;
317 
318   if (command != NULL)
319     {
320       key->command = (char *) malloc ((strlen (command) + 1) * sizeof (char));
321 
322       if (key->command != NULL)
323 	strncpy (key->command, command, strlen (command) + 1);
324     }
325   else
326     {
327       key->command = NULL;
328     }
329 
330   key->function = function;
331 }
332 
333 
334 
335 
336 void
free_key(Keys_t * key)337 free_key (Keys_t * key)
338 {
339   key->type = SYM;
340   key->event_type = PRESS;
341   key->key.sym = 0;
342   key->modifier = 0;
343 
344   if (key->command != NULL)
345     free (key->command);
346 
347   key->function = 0;
348 }
349 
350 
351 
352 
353 int
remove_key(KeyType_t type,EventType_t event_type,KeySym keysym,KeyCode keycode,unsigned int button,unsigned int modifier)354 remove_key (KeyType_t type, EventType_t event_type, KeySym keysym, KeyCode keycode,
355 	    unsigned int button, unsigned int modifier)
356 {
357   int i, found_index = -1;
358   Keys_t *keys_bis = NULL;
359 
360   if (keys == NULL)
361     {
362       return (-1);
363     }
364 
365   modifier &= ~(numlock_mask | capslock_mask | scrolllock_mask);
366 
367   for (i = 0; i < nb_keys; i++)
368     {
369       if (keys[i].type == type &&
370 	  keys[i].event_type == event_type &&
371 	  keys[i].modifier == modifier &&
372 	  ((type == SYM && keys[i].key.sym == keysym) ||
373 	   (type == CODE && keys[i].key.code == keycode) ||
374 	   (type == BUTTON && keys[i].key.button == button)))
375 	found_index = i;
376     }
377 
378   if (found_index != -1)
379     {
380       if (verbose)
381 	printf ("Removing key index %d\n", found_index);
382 
383       /* make new array keys_bis */
384       keys_bis = (Keys_t *) malloc ((nb_keys - 1) * sizeof (Keys_t));
385       if (keys_bis == NULL)
386 	return (-1);
387 
388       for (i = 0; i < found_index; i++)
389 	keys_bis[i] = keys[i];
390 
391       for (i = found_index + 1; i < nb_keys; i++)
392 	keys_bis[i - 1] = keys[i];
393 
394       free_key (&keys[found_index]);
395       free (keys);
396 
397       /* make keys_bis as keys */
398       keys = keys_bis;
399 
400       nb_keys -= 1;
401     }
402 
403   return (0);
404 }
405 
406 
407 
408 
409 
410 
411 
412 void
run_command(char * command)413 run_command (char *command)
414 {
415 #ifdef FORK_FLAG
416   pid_t pid;
417 
418   if (verbose)
419     printf ("Start program with fork+exec call\n");
420 
421   //  if (fork() == 0)
422   //  execlp ("sh", "sh", "-c", key->command, NULL);
423   if (!(pid = fork()))
424     {
425       setsid();
426       switch (fork())
427 	{
428 	case 0: execlp ("sh", "sh", "-c", command, (char *) NULL);
429 	  break;
430 	default: _exit(0);
431 	  break;
432 	}
433     }
434   if (pid > 0)
435     wait(NULL);
436 #else
437   if (verbose)
438     printf ("Start program with system call\n");
439 
440   system (command);
441 #endif
442 }
443 
444 
445 void
start_command_key(Keys_t * key)446 start_command_key (Keys_t * key)
447 {
448   if (key->command == NULL)
449     {
450 #ifdef GUILE_FLAG
451       if (key->function != 0)
452 	{
453 	  scm_call_0 (key->function);
454 	}
455 #endif
456       return;
457     }
458 
459   run_command (key->command);
460 }
461