girara
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
shortcuts.c
Go to the documentation of this file.
1 /* See LICENSE file for license and copyright information */
2 
3 #include "shortcuts.h"
4 #include "datastructures.h"
5 #include "internal.h"
6 #include "session.h"
7 #include "settings.h"
8 #include "tabs.h"
9 #include "input-history.h"
10 
11 #include <string.h>
12 #include <gtk/gtk.h>
13 
14 static void girara_toggle_widget_visibility(GtkWidget* widget);
15 static bool simulate_key_press(girara_session_t* session, int state, int key);
16 
17 bool
18 girara_shortcut_add(girara_session_t* session, guint modifier, guint key, const char* buffer, girara_shortcut_function_t function, girara_mode_t mode, int argument_n, void* argument_data)
19 {
20  g_return_val_if_fail(session != NULL, false);
21  g_return_val_if_fail(buffer || key || modifier, false);
22  g_return_val_if_fail(function != NULL, false);
23 
24  girara_argument_t argument = {argument_n, (argument_data != NULL) ?
25  g_strdup(argument_data) : NULL};
26 
27  /* search for existing binding */
28  bool found_existing_shortcut = false;
29  GIRARA_LIST_FOREACH(session->bindings.shortcuts, girara_shortcut_t*, iter, shortcuts_it)
30  if (((shortcuts_it->mask == modifier && shortcuts_it->key == key && (modifier != 0 || key != 0)) ||
31  (buffer && shortcuts_it->buffered_command && !strcmp(shortcuts_it->buffered_command, buffer)))
32  && ((shortcuts_it->mode == mode) || (mode == 0)))
33  {
34  if (shortcuts_it->argument.data != NULL) {
35  g_free(shortcuts_it->argument.data);
36  }
37 
38  shortcuts_it->function = function;
39  shortcuts_it->argument = argument;
40  found_existing_shortcut = true;
41 
42  if (mode != 0) {
44  return true;
45  }
46  }
47  GIRARA_LIST_FOREACH_END(session->bindings.shortcuts, girara_shortcut_t*, iter, shortcuts_it);
48 
49  if (found_existing_shortcut == true) {
50  return true;
51  }
52 
53  /* add new shortcut */
54  girara_shortcut_t* shortcut = g_slice_new(girara_shortcut_t);
55 
56  shortcut->mask = modifier;
57  shortcut->key = key;
58  shortcut->buffered_command = g_strdup(buffer);
59  shortcut->function = function;
60  shortcut->mode = mode;
61  shortcut->argument = argument;
62  girara_list_append(session->bindings.shortcuts, shortcut);
63 
64  return true;
65 }
66 
67 bool
68 girara_shortcut_remove(girara_session_t* session, guint modifier, guint key, const char* buffer, girara_mode_t mode)
69 {
70  g_return_val_if_fail(session != NULL, false);
71  g_return_val_if_fail(buffer || key || modifier, false);
72 
73  /* search for existing binding */
74  GIRARA_LIST_FOREACH(session->bindings.shortcuts, girara_shortcut_t*, iter, shortcuts_it)
75  if (((shortcuts_it->mask == modifier && shortcuts_it->key == key && (modifier != 0 || key != 0)) ||
76  (buffer && shortcuts_it->buffered_command && !strcmp(shortcuts_it->buffered_command, buffer)))
77  && shortcuts_it->mode == mode)
78  {
79  girara_list_remove(session->bindings.shortcuts, shortcuts_it);
81  return true;
82  }
83  GIRARA_LIST_FOREACH_END(session->bindings.shortcuts, girara_shortcut_t*, iter, shortcuts_it);
84 
85  return false;
86 }
87 
88 void
89 girara_shortcut_free(girara_shortcut_t* shortcut)
90 {
91  g_return_if_fail(shortcut != NULL);
92  g_free(shortcut->buffered_command);
93  g_free(shortcut->argument.data);
94  g_slice_free(girara_shortcut_t, shortcut);
95 }
96 
97 bool
98 girara_inputbar_shortcut_add(girara_session_t* session, guint modifier, guint key, girara_shortcut_function_t function, int argument_n, void* argument_data)
99 {
100  g_return_val_if_fail(session != NULL, false);
101  g_return_val_if_fail(function != NULL, false);
102 
103  girara_argument_t argument = {argument_n, argument_data};
104 
105  /* search for existing special command */
106  GIRARA_LIST_FOREACH(session->bindings.inputbar_shortcuts, girara_inputbar_shortcut_t*, iter, inp_sh_it)
107  if (inp_sh_it->mask == modifier && inp_sh_it->key == key) {
108  inp_sh_it->function = function;
109  inp_sh_it->argument = argument;
110 
112  return true;
113  }
114  GIRARA_LIST_FOREACH_END(session->bindings.inputbar_shortcuts, girara_inputbar_shortcut_t*, iter, inp_sh_it);
115 
116  /* create new inputbar shortcut */
117  girara_inputbar_shortcut_t* inputbar_shortcut = g_slice_new(girara_inputbar_shortcut_t);
118 
119  inputbar_shortcut->mask = modifier;
120  inputbar_shortcut->key = key;
121  inputbar_shortcut->function = function;
122  inputbar_shortcut->argument = argument;
123 
124  girara_list_append(session->bindings.inputbar_shortcuts, inputbar_shortcut);
125  return true;
126 }
127 
128 bool
129 girara_inputbar_shortcut_remove(girara_session_t* session, guint modifier, guint key)
130 {
131  g_return_val_if_fail(session != NULL, false);
132 
133  /* search for existing special command */
134  GIRARA_LIST_FOREACH(session->bindings.inputbar_shortcuts, girara_inputbar_shortcut_t*, iter, inp_sh_it)
135  if (inp_sh_it->mask == modifier && inp_sh_it->key == key) {
136  girara_list_remove(session->bindings.inputbar_shortcuts, inp_sh_it);
138  return true;
139  }
140  GIRARA_LIST_FOREACH_END(session->bindings.inputbar_shortcuts, girara_inputbar_shortcut_t*, iter, inp_sh_it);
141 
142  return true;
143 }
144 
145 void
146 girara_inputbar_shortcut_free(girara_inputbar_shortcut_t* inputbar_shortcut)
147 {
148  g_slice_free(girara_inputbar_shortcut_t, inputbar_shortcut);
149 }
150 
151 bool
152 girara_isc_abort(girara_session_t* session, girara_argument_t* UNUSED(argument), girara_event_t* UNUSED(event), unsigned int UNUSED(t))
153 {
154  g_return_val_if_fail(session != NULL, false);
155 
156  /* hide completion */
157  girara_argument_t arg = { GIRARA_HIDE, NULL };
158  girara_isc_completion(session, &arg, NULL, 0);
159 
160  /* clear inputbar */
161  gtk_editable_delete_text(GTK_EDITABLE(session->gtk.inputbar_entry), 0, -1);
162 
163  /* grab view */
164  gtk_widget_grab_focus(GTK_WIDGET(session->gtk.view));
165 
166  /* hide inputbar */
167  gtk_widget_hide(GTK_WIDGET(session->gtk.inputbar_dialog));
168  if (session->global.autohide_inputbar == true) {
169  gtk_widget_hide(GTK_WIDGET(session->gtk.inputbar));
170  }
171 
172  /* Begin from the last command when navigating through history */
173  girara_input_history_reset(session->command_history);
174 
175  /* reset custom functions */
176  session->signals.inputbar_custom_activate = NULL;
177  session->signals.inputbar_custom_key_press_event = NULL;
178  gtk_entry_set_visibility(session->gtk.inputbar_entry, TRUE);
179 
180  return true;
181 }
182 
183 bool
184 girara_isc_string_manipulation(girara_session_t* session, girara_argument_t* argument, girara_event_t* UNUSED(event), unsigned int UNUSED(t))
185 {
186  g_return_val_if_fail(session != NULL, false);
187 
188  gchar *separator = NULL;
189  girara_setting_get(session, "word-separator", &separator);
190  gchar *input = gtk_editable_get_chars(GTK_EDITABLE(session->gtk.inputbar_entry), 0, -1);
191  int length = strlen(input);
192  int pos = gtk_editable_get_position(GTK_EDITABLE(session->gtk.inputbar_entry));
193  int i;
194 
195  switch (argument->n) {
197  if (pos == 1 && (input[0] == ':' || input[0] == '/')) {
198  break;
199  }
200  if (pos == 0) {
201  break;
202  }
203 
204  i = pos - 1;
205 
206  /* remove trailing spaces */
207  for (; i >= 0 && input[i] == ' '; i--);
208 
209  /* find the beginning of the word */
210  while ((i == (pos - 1)) || ((i > 0) && !strchr(separator, input[i]))) {
211  i--;
212  }
213 
214  gtk_editable_delete_text(GTK_EDITABLE(session->gtk.inputbar_entry), i + 1, pos);
215  gtk_editable_set_position(GTK_EDITABLE(session->gtk.inputbar_entry), i + 1);
216  break;
218  if (length != 1 && pos == 1 && (input[0] == ':' || input[0] == '/')) {
219  break;
220  }
221  if (length == 1 && pos == 1) {
222  girara_isc_abort(session, argument, NULL, 0);
223  }
224  gtk_editable_delete_text(GTK_EDITABLE(session->gtk.inputbar_entry), pos - 1, pos);
225  break;
227  gtk_editable_delete_text(GTK_EDITABLE(session->gtk.inputbar_entry), 1, pos);
228  break;
229  case GIRARA_NEXT_CHAR:
230  gtk_editable_set_position(GTK_EDITABLE(session->gtk.inputbar_entry), pos + 1);
231  break;
233  gtk_editable_set_position(GTK_EDITABLE(session->gtk.inputbar_entry), (pos == 1) ? 1 : pos - 1);
234  break;
236  if (length != 1 && pos == 0 && (input[0] == ':' || input[0] == '/')){
237  break;
238  }
239  if(length == 1 && pos == 0) {
240  girara_isc_abort(session, argument, NULL, 0);
241  }
242  gtk_editable_delete_text(GTK_EDITABLE(session->gtk.inputbar_entry), pos, pos + 1);
243  break;
245  gtk_editable_delete_text(GTK_EDITABLE(session->gtk.inputbar_entry), pos, length);
246  break;
247  case GIRARA_GOTO_START:
248  gtk_editable_set_position(GTK_EDITABLE(session->gtk.inputbar_entry), 1);
249  break;
250  case GIRARA_GOTO_END:
251  gtk_editable_set_position(GTK_EDITABLE(session->gtk.inputbar_entry), -1);
252  break;
253  }
254 
255  g_free(separator);
256  g_free(input);
257 
258  return false;
259 }
260 
261 bool
262 girara_isc_command_history(girara_session_t* session, girara_argument_t*
263  argument, girara_event_t* UNUSED(event), unsigned int UNUSED(t))
264 {
265  g_return_val_if_fail(session != NULL, false);
266 
267  char* temp = gtk_editable_get_chars(GTK_EDITABLE(session->gtk.inputbar_entry), 0, -1);
268  const char* command = argument->n == GIRARA_NEXT ?
269  girara_input_history_next(session->command_history, temp) :
270  girara_input_history_previous(session->command_history, temp);
271  g_free(temp);
272 
273  if (command != NULL) {
274  gtk_entry_set_text(session->gtk.inputbar_entry, command);
275  gtk_widget_grab_focus(GTK_WIDGET(session->gtk.inputbar_entry));
276  gtk_editable_set_position(GTK_EDITABLE(session->gtk.inputbar_entry), -1);
277  }
278 
279  return true;
280 }
281 
282 /* default shortcut implementation */
283 bool
284 girara_sc_focus_inputbar(girara_session_t* session, girara_argument_t* argument, girara_event_t* UNUSED(event), unsigned int UNUSED(t))
285 {
286  g_return_val_if_fail(session != NULL, false);
287  g_return_val_if_fail(session->gtk.inputbar_entry != NULL, false);
288 
289  if (gtk_widget_get_visible(GTK_WIDGET(session->gtk.inputbar)) == false) {
290  gtk_widget_show(GTK_WIDGET(session->gtk.inputbar));
291  }
292 
293  if (gtk_widget_get_visible(GTK_WIDGET(session->gtk.notification_area)) == true) {
294  gtk_widget_hide(GTK_WIDGET(session->gtk.notification_area));
295  }
296 
297  gtk_widget_grab_focus(GTK_WIDGET(session->gtk.inputbar_entry));
298 
299  if (argument != NULL && argument->data != NULL) {
300  gtk_entry_set_text(session->gtk.inputbar_entry, (char*) argument->data);
301 
302  /* we save the X clipboard that will be clear by "grab_focus" */
303  gchar* x_clipboard_text = gtk_clipboard_wait_for_text(gtk_clipboard_get(GDK_SELECTION_PRIMARY));
304 
305  gtk_editable_set_position(GTK_EDITABLE(session->gtk.inputbar_entry), -1);
306 
307  if (x_clipboard_text != NULL) {
308  /* we reset the X clipboard with saved text */
309  gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_PRIMARY), x_clipboard_text, -1);
310  g_free(x_clipboard_text);
311  }
312  }
313 
314  return true;
315 }
316 
317 bool
318 girara_sc_abort(girara_session_t* session, girara_argument_t* UNUSED(argument), girara_event_t* UNUSED(event), unsigned int UNUSED(t))
319 {
320  g_return_val_if_fail(session != NULL, false);
321 
322  girara_isc_abort(session, NULL, NULL, 0);
323 
324  gtk_widget_hide(GTK_WIDGET(session->gtk.notification_area));
325 
326  if (session->global.autohide_inputbar == false) {
327  gtk_widget_show(GTK_WIDGET(session->gtk.inputbar));
328  }
329 
330  return false;
331 }
332 
333 bool
334 girara_sc_quit(girara_session_t* session, girara_argument_t* UNUSED(argument), girara_event_t* UNUSED(event), unsigned int UNUSED(t))
335 {
336  g_return_val_if_fail(session != NULL, false);
337 
338  girara_argument_t arg = { GIRARA_HIDE, NULL };
339  girara_isc_completion(session, &arg, NULL, 0);
340 
341  gtk_main_quit();
342 
343  return false;
344 }
345 
346 bool
347 girara_sc_tab_close(girara_session_t* session, girara_argument_t* UNUSED(argument), girara_event_t* UNUSED(event), unsigned int UNUSED(t))
348 {
349  g_return_val_if_fail(session != NULL, false);
350 
351  girara_tab_t* tab = girara_tab_current_get(session);
352 
353  if (tab != NULL) {
354  girara_tab_remove(session, tab);
355  }
356 
357  return false;
358 }
359 
360 bool
361 girara_sc_tab_navigate(girara_session_t* session, girara_argument_t* argument, girara_event_t* UNUSED(event), unsigned int t)
362 {
363  g_return_val_if_fail(session != NULL, false);
364 
365  const unsigned int number_of_tabs = girara_get_number_of_tabs(session);
366  if (number_of_tabs == 0) {
367  return false;
368  }
369 
370  unsigned int current_tab = girara_tab_position_get(session, girara_tab_current_get(session));
371  unsigned int step = (argument->n == GIRARA_PREVIOUS) ? -1 : 1;
372  unsigned int new_tab = (current_tab + step) % number_of_tabs;
373 
374  if (t != 0 && t <= number_of_tabs) {
375  new_tab = t - 1;
376  }
377 
378  girara_tab_t* tab = girara_tab_get(session, new_tab);
379 
380  if (tab != NULL) {
381  girara_tab_current_set(session, tab);
382  }
383 
384  girara_tab_update(session);
385 
386  return false;
387 }
388 
389 bool
390 girara_sc_tab_navigate_next(girara_session_t* session,
391  girara_argument_t* argument,
392  girara_event_t* event, unsigned int t)
393 {
394  argument->n = GIRARA_NEXT;
395  return girara_sc_tab_navigate(session, argument, event, t);
396 }
397 
398 bool
399 girara_sc_tab_navigate_prev(girara_session_t* session,
400  girara_argument_t* argument,
401  girara_event_t* event, unsigned int t)
402 {
403  argument->n = GIRARA_PREVIOUS;
404  return girara_sc_tab_navigate(session, argument, event, t);
405 }
406 
407 static void
408 girara_toggle_widget_visibility(GtkWidget* widget)
409 {
410  if (widget == NULL) {
411  return;
412  }
413 
414  if (gtk_widget_get_visible(widget) == TRUE) {
415  gtk_widget_hide(widget);
416  } else {
417  gtk_widget_show(widget);
418  }
419 }
420 
421 bool
422 girara_sc_toggle_inputbar(girara_session_t* session, girara_argument_t* UNUSED(argument), girara_event_t* UNUSED(event), unsigned int UNUSED(t))
423 {
424  g_return_val_if_fail(session != NULL, false);
425 
426  girara_toggle_widget_visibility(GTK_WIDGET(session->gtk.inputbar));
427 
428  return true;
429 }
430 
431 bool
432 girara_sc_toggle_statusbar(girara_session_t* session, girara_argument_t* UNUSED(argument), girara_event_t* UNUSED(event), unsigned int UNUSED(t))
433 {
434  g_return_val_if_fail(session != NULL, false);
435 
436  girara_toggle_widget_visibility(GTK_WIDGET(session->gtk.statusbar));
437 
438  return true;
439 }
440 
441 bool
442 girara_sc_toggle_tabbar(girara_session_t* session, girara_argument_t* UNUSED(argument), girara_event_t* UNUSED(event), unsigned int UNUSED(t))
443 {
444  g_return_val_if_fail(session != NULL, false);
445 
446  girara_toggle_widget_visibility(GTK_WIDGET(session->gtk.tabbar));
447 
448  return true;
449 }
450 
451 bool
452 girara_sc_set(girara_session_t* session, girara_argument_t* argument, girara_event_t* UNUSED(event), unsigned int UNUSED(t))
453 {
454  g_return_val_if_fail(session != NULL, false);
455 
456  if (argument == NULL || argument->data == NULL) {
457  return false;
458  }
459 
460  /* create argument list */
461  girara_list_t* argument_list = girara_list_new();
462  if (argument_list == NULL) {
463  return false;
464  }
465 
466  gchar** argv = NULL;
467  gint argc = 0;
468 
469  girara_list_set_free_function(argument_list, g_free);
470  if (g_shell_parse_argv((const gchar*) argument->data, &argc, &argv, NULL) != FALSE) {
471  for(int i = 0; i < argc; i++) {
472  char* argument = g_strdup(argv[i]);
473  girara_list_append(argument_list, (void*) argument);
474  }
475  } else {
476  girara_list_free(argument_list);
477  return false;
478  }
479 
480  /* call set */
481  girara_cmd_set(session, argument_list);
482 
483  /* cleanup */
484  girara_list_free(argument_list);
485 
486  return false;
487 }
488 
489 bool
490 girara_sc_feedkeys(girara_session_t* session, girara_argument_t* argument,
491  girara_event_t* UNUSED(event), unsigned int t)
492 {
493  if (session == NULL || argument == NULL) {
494  return false;
495  }
496 
497  typedef struct gdk_keyboard_button_s {
498  char* identifier;
499  int keyval;
500  } gdk_keyboard_button_t;
501 
502  static const gdk_keyboard_button_t gdk_keyboard_buttons[] = {
503  {"BackSpace", GDK_KEY_BackSpace},
504  {"CapsLock", GDK_KEY_Caps_Lock},
505  {"Down", GDK_KEY_Down},
506  {"Esc", GDK_KEY_Escape},
507  {"F10", GDK_KEY_F10},
508  {"F11", GDK_KEY_F11},
509  {"F12", GDK_KEY_F12},
510  {"F1", GDK_KEY_F1},
511  {"F2", GDK_KEY_F2},
512  {"F3", GDK_KEY_F3},
513  {"F4", GDK_KEY_F4},
514  {"F5", GDK_KEY_F5},
515  {"F6", GDK_KEY_F6},
516  {"F7", GDK_KEY_F7},
517  {"F8", GDK_KEY_F8},
518  {"F9", GDK_KEY_F9},
519  {"Left", GDK_KEY_Left},
520  {"PageDown", GDK_KEY_Page_Down},
521  {"PageUp", GDK_KEY_Page_Up},
522  {"Home", GDK_KEY_Home},
523  {"End", GDK_KEY_End},
524  {"Return", GDK_KEY_Return},
525  {"Right", GDK_KEY_Right},
526  {"Space", GDK_KEY_space},
527  {"Super", GDK_KEY_Super_L},
528  {"Tab", GDK_KEY_Tab},
529  {"ShiftTab", GDK_KEY_ISO_Left_Tab},
530  {"Up", GDK_KEY_Up}
531  };
532 
533  char* input = (char*) argument->data;
534  unsigned int input_length = strlen(input);
535 
536  t = (t == 0) ? 1 : t;
537  for (unsigned int c = 0; c < t; c++) {
538  for (unsigned i = 0; i < input_length; i++) {
539  int state = 0;
540  int keyval = input[i];
541 
542  /* possible special button */
543  if ((input_length - i) >= 3 && input[i] == '<') {
544  char* end = strchr(input + i, '>');
545  if (end == NULL) {
546  goto single_key;
547  }
548 
549  int length = end - (input + i) - 1;
550  char* tmp = g_strndup(input + i + 1, length);
551  bool found = false;
552 
553  /* Multi key shortcut */
554  if (length > 2 && tmp[1] == '-') {
555  switch (tmp[0]) {
556  case 'S':
557  state = GDK_SHIFT_MASK;
558  break;
559  case 'A':
560  state = GDK_MOD1_MASK;
561  break;
562  case 'C':
563  state = GDK_CONTROL_MASK;
564  break;
565  default:
566  break;
567  }
568 
569  if (length == 3) {
570  keyval = tmp[2];
571  found = true;
572  } else {
573  for (unsigned int i = 0; i < LENGTH(gdk_keyboard_buttons); i++) {
574  if (g_strcmp0(tmp + 2, gdk_keyboard_buttons[i].identifier) == 0) {
575  keyval = gdk_keyboard_buttons[i].keyval;
576  found = true;
577  break;
578  }
579  }
580  }
581  /* Possible special key */
582  } else {
583  for (unsigned int i = 0; i < LENGTH(gdk_keyboard_buttons); i++) {
584  if (g_strcmp0(tmp, gdk_keyboard_buttons[i].identifier) == 0) {
585  keyval = gdk_keyboard_buttons[i].keyval;
586  found = true;
587  break;
588  }
589  }
590  }
591 
592  g_free(tmp);
593 
594  /* parsed special key */
595  if (found == true) {
596  i += length + 1;
597  }
598  }
599 
600 single_key:
601 
602  update_state_by_keyval(&state, keyval);
603  simulate_key_press(session, state, keyval);
604  }
605  }
606 
607  return true;
608 }
609 
610 bool
611 girara_shortcut_mapping_add(girara_session_t* session, const char* identifier, girara_shortcut_function_t function)
612 {
613  g_return_val_if_fail(session != NULL, false);
614 
615  if (function == NULL || identifier == NULL) {
616  return false;
617  }
618 
619  GIRARA_LIST_FOREACH(session->config.shortcut_mappings, girara_shortcut_mapping_t*, iter, data)
620  if (strcmp(data->identifier, identifier) == 0) {
621  data->function = function;
623  return true;
624  }
625  GIRARA_LIST_FOREACH_END(session->config.shortcut_mappings, girara_shortcut_mapping_t*, iter, data);
626 
627  /* add new config handle */
628  girara_shortcut_mapping_t* mapping = g_slice_new(girara_shortcut_mapping_t);
629 
630  mapping->identifier = g_strdup(identifier);
631  mapping->function = function;
632  girara_list_append(session->config.shortcut_mappings, mapping);
633 
634  return true;
635 }
636 
637 void
638 girara_shortcut_mapping_free(girara_shortcut_mapping_t* mapping)
639 {
640  if (mapping == NULL) {
641  return;
642  }
643 
644  g_free(mapping->identifier);
645  g_slice_free(girara_shortcut_mapping_t, mapping);
646 }
647 
648 bool
649 girara_argument_mapping_add(girara_session_t* session, const char* identifier, int value)
650 {
651  g_return_val_if_fail(session != NULL, false);
652 
653  if (identifier == NULL) {
654  return false;
655  }
656 
657  GIRARA_LIST_FOREACH(session->config.argument_mappings, girara_argument_mapping_t*, iter, mapping);
658  if (g_strcmp0(mapping->identifier, identifier) == 0) {
659  mapping->value = value;
661  return true;
662  }
663  GIRARA_LIST_FOREACH_END(session->config.argument_mappings, girara_argument_mapping_t*, iter, mapping);
664 
665  /* add new config handle */
666  girara_argument_mapping_t* mapping = g_slice_new(girara_argument_mapping_t);
667 
668  mapping->identifier = g_strdup(identifier);
669  mapping->value = value;
670  girara_list_append(session->config.argument_mappings, mapping);
671 
672  return true;
673 }
674 
675 void
676 girara_argument_mapping_free(girara_argument_mapping_t* argument_mapping)
677 {
678  if (argument_mapping == NULL) {
679  return;
680  }
681 
682  g_free(argument_mapping->identifier);
683  g_slice_free(girara_argument_mapping_t, argument_mapping);
684 }
685 
686 bool
687 girara_mouse_event_add(girara_session_t* session, guint mask, guint button,
689  event_type, int argument_n, void* argument_data)
690 {
691  g_return_val_if_fail(session != NULL, false);
692  g_return_val_if_fail(function != NULL, false);
693 
694  girara_argument_t argument = {argument_n, argument_data};
695 
696  /* search for existing binding */
697  GIRARA_LIST_FOREACH(session->bindings.mouse_events, girara_mouse_event_t*, iter, me_it)
698  if (me_it->mask == mask && me_it->button == button &&
699  me_it->mode == mode && me_it->event_type == event_type)
700  {
701  me_it->function = function;
702  me_it->argument = argument;
704  return true;
705  }
706  GIRARA_LIST_FOREACH_END(session->bindings.mouse_events, girara_mouse_event_t*, iter, me_it);
707 
708  /* add new mouse event */
709  girara_mouse_event_t* mouse_event = g_slice_new(girara_mouse_event_t);
710 
711  mouse_event->mask = mask;
712  mouse_event->button = button;
713  mouse_event->function = function;
714  mouse_event->mode = mode;
715  mouse_event->event_type = event_type;
716  mouse_event->argument = argument;
717  girara_list_append(session->bindings.mouse_events, mouse_event);
718 
719  return true;
720 }
721 
722 bool
723 girara_mouse_event_remove(girara_session_t* session, guint mask, guint button, girara_mode_t mode)
724 {
725  g_return_val_if_fail(session != NULL, false);
726 
727  /* search for existing binding */
728  GIRARA_LIST_FOREACH(session->bindings.mouse_events, girara_mouse_event_t*, iter, me_it)
729  if (me_it->mask == mask && me_it->button == button &&
730  me_it->mode == mode)
731  {
732  girara_list_remove(session->bindings.mouse_events, me_it);
734  return true;
735  }
736  GIRARA_LIST_FOREACH_END(session->bindings.mouse_events, girara_mouse_event_t*, iter, me_it);
737 
738  return false;
739 }
740 
741 void
742 girara_mouse_event_free(girara_mouse_event_t* mouse_event)
743 {
744  if (mouse_event == NULL) {
745  return;
746  }
747  g_slice_free(girara_mouse_event_t, mouse_event);
748 }
749 
750 static bool
751 simulate_key_press(girara_session_t* session, int state, int key)
752 {
753  if (session == NULL || session->gtk.box == NULL) {
754  return false;
755  }
756 
757  GdkEvent* event = gdk_event_new(GDK_KEY_PRESS);
758 
759  event->key.type = GDK_KEY_PRESS;
760  event->key.window = gtk_widget_get_parent_window(GTK_WIDGET(session->gtk.box));
761  event->key.send_event = false;
762  event->key.time = GDK_CURRENT_TIME;
763  event->key.state = state;
764  event->key.keyval = key;
765 
766  g_object_ref(event->key.window);
767 
768  GdkKeymapKey* keys;
769  gint number_of_keys;
770 
771  if (gdk_keymap_get_entries_for_keyval(gdk_keymap_get_default(),
772  event->key.keyval, &keys, &number_of_keys) == FALSE) {
773  gdk_event_free(event);
774  return false;
775  }
776 
777  event->key.hardware_keycode = keys[0].keycode;
778  event->key.group = keys[0].group;
779 
780  g_free(keys);
781 
782  gdk_event_put(event);
783  gdk_event_free(event);
784 
785  gtk_main_iteration_do(FALSE);
786 
787  return true;
788 }
void girara_list_remove(girara_list_t *list, void *data)
bool girara_shortcut_add(girara_session_t *session, guint modifier, guint key, const char *buffer, girara_shortcut_function_t function, girara_mode_t mode, int argument_n, void *argument_data)
Definition: shortcuts.c:18
int girara_mode_t
Definition: types.h:69
#define LENGTH(x)
Definition: internal.h:18
bool girara_sc_abort(girara_session_t *session, girara_argument_t *UNUSED(argument), girara_event_t *UNUSED(event), unsigned int UNUSED(t))
Definition: shortcuts.c:318
void girara_mouse_event_free(girara_mouse_event_t *mouse_event)
Definition: shortcuts.c:742
bool girara_inputbar_shortcut_remove(girara_session_t *session, guint modifier, guint key)
Definition: shortcuts.c:129
void girara_inputbar_shortcut_free(girara_inputbar_shortcut_t *inputbar_shortcut)
Definition: shortcuts.c:146
void girara_list_append(girara_list_t *list, void *data)
void girara_tab_update(girara_session_t *session)
Definition: tabs.c:140
bool girara_sc_tab_navigate_prev(girara_session_t *session, girara_argument_t *argument, girara_event_t *event, unsigned int t)
Definition: shortcuts.c:399
girara_event_type_t
Definition: types.h:188
bool girara_sc_toggle_inputbar(girara_session_t *session, girara_argument_t *UNUSED(argument), girara_event_t *UNUSED(event), unsigned int UNUSED(t))
Definition: shortcuts.c:422
bool girara_argument_mapping_add(girara_session_t *session, const char *identifier, int value)
Definition: shortcuts.c:649
#define UNUSED(x)
Definition: internal.h:15
bool girara_sc_tab_navigate(girara_session_t *session, girara_argument_t *argument, girara_event_t *UNUSED(event), unsigned int t)
Definition: shortcuts.c:361
void girara_tab_remove(girara_session_t *session, girara_tab_t *tab)
Definition: tabs.c:91
bool girara_sc_focus_inputbar(girara_session_t *session, girara_argument_t *argument, girara_event_t *UNUSED(event), unsigned int UNUSED(t))
Definition: shortcuts.c:284
void girara_list_free(girara_list_t *list)
void girara_list_set_free_function(girara_list_t *list, girara_free_function_t gfree)
void girara_tab_current_set(girara_session_t *session, girara_tab_t *tab)
Definition: tabs.c:188
bool girara_cmd_set(girara_session_t *session, girara_list_t *argument_list)
Definition: commands.c:413
bool girara_isc_completion(girara_session_t *session, girara_argument_t *argument, girara_event_t *UNUSED(event), unsigned int UNUSED(t))
Definition: completion.c:139
girara_tab_t * girara_tab_current_get(girara_session_t *session)
Definition: tabs.c:171
bool girara_mouse_event_add(girara_session_t *session, guint mask, guint button, girara_shortcut_function_t function, girara_mode_t mode, girara_event_type_t event_type, int argument_n, void *argument_data)
Definition: shortcuts.c:687
void girara_input_history_reset(GiraraInputHistory *history)
const char * girara_input_history_previous(GiraraInputHistory *history, const char *current_input)
int girara_tab_position_get(girara_session_t *session, girara_tab_t *tab)
Definition: tabs.c:231
bool girara_sc_feedkeys(girara_session_t *session, girara_argument_t *argument, girara_event_t *UNUSED(event), unsigned int t)
Definition: shortcuts.c:490
bool girara_shortcut_mapping_add(girara_session_t *session, const char *identifier, girara_shortcut_function_t function)
Definition: shortcuts.c:611
bool(* girara_shortcut_function_t)(girara_session_t *, girara_argument_t *, girara_event_t *, unsigned int)
Definition: types.h:110
girara_list_t * girara_list_new(void)
bool girara_sc_set(girara_session_t *session, girara_argument_t *argument, girara_event_t *UNUSED(event), unsigned int UNUSED(t))
Definition: shortcuts.c:452
void girara_list_iterator_free(girara_list_iterator_t *iter)
bool girara_isc_command_history(girara_session_t *session, girara_argument_t *argument, girara_event_t *UNUSED(event), unsigned int UNUSED(t))
Definition: shortcuts.c:262
int girara_get_number_of_tabs(girara_session_t *session)
Definition: tabs.c:130
bool girara_setting_get(girara_session_t *session, const char *name, void *dest)
Definition: settings.c:140
girara_tab_t * girara_tab_get(girara_session_t *session, unsigned int index)
Definition: tabs.c:118
bool girara_sc_tab_close(girara_session_t *session, girara_argument_t *UNUSED(argument), girara_event_t *UNUSED(event), unsigned int UNUSED(t))
Definition: shortcuts.c:347
void girara_shortcut_free(girara_shortcut_t *shortcut)
Definition: shortcuts.c:89
bool girara_mouse_event_remove(girara_session_t *session, guint mask, guint button, girara_mode_t mode)
Definition: shortcuts.c:723
const char * girara_input_history_next(GiraraInputHistory *history, const char *current_input)
HIDDEN void update_state_by_keyval(int *state, int keyval)
Definition: utils.c:405
bool girara_isc_abort(girara_session_t *session, girara_argument_t *UNUSED(argument), girara_event_t *UNUSED(event), unsigned int UNUSED(t))
Definition: shortcuts.c:152
bool girara_sc_toggle_statusbar(girara_session_t *session, girara_argument_t *UNUSED(argument), girara_event_t *UNUSED(event), unsigned int UNUSED(t))
Definition: shortcuts.c:432
bool girara_sc_tab_navigate_next(girara_session_t *session, girara_argument_t *argument, girara_event_t *event, unsigned int t)
Definition: shortcuts.c:390
void girara_argument_mapping_free(girara_argument_mapping_t *argument_mapping)
Definition: shortcuts.c:676
bool girara_sc_toggle_tabbar(girara_session_t *session, girara_argument_t *UNUSED(argument), girara_event_t *UNUSED(event), unsigned int UNUSED(t))
Definition: shortcuts.c:442
void girara_shortcut_mapping_free(girara_shortcut_mapping_t *mapping)
Definition: shortcuts.c:638
bool girara_inputbar_shortcut_add(girara_session_t *session, guint modifier, guint key, girara_shortcut_function_t function, int argument_n, void *argument_data)
Definition: shortcuts.c:98
bool girara_shortcut_remove(girara_session_t *session, guint modifier, guint key, const char *buffer, girara_mode_t mode)
Definition: shortcuts.c:68
bool girara_sc_quit(girara_session_t *session, girara_argument_t *UNUSED(argument), girara_event_t *UNUSED(event), unsigned int UNUSED(t))
Definition: shortcuts.c:334
#define GIRARA_LIST_FOREACH_END(list, type, iter, data)
#define GIRARA_LIST_FOREACH(list, type, iter, data)
bool girara_isc_string_manipulation(girara_session_t *session, girara_argument_t *argument, girara_event_t *UNUSED(event), unsigned int UNUSED(t))
Definition: shortcuts.c:184