girara
shortcuts.c
Go to the documentation of this file.
00001 /* See LICENSE file for license and copyright information */
00002 
00003 #include "shortcuts.h"
00004 #include "datastructures.h"
00005 #include "internal.h"
00006 #include "session.h"
00007 #include "settings.h"
00008 #include "tabs.h"
00009 
00010 #include <string.h>
00011 #include <gtk/gtk.h>
00012 
00013 static void girara_toggle_widget_visibility(GtkWidget* widget);
00014 
00015 bool
00016 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)
00017 {
00018   g_return_val_if_fail(session != NULL, false);
00019   g_return_val_if_fail(buffer || key || modifier, false);
00020   g_return_val_if_fail(function != NULL, false);
00021 
00022   girara_argument_t argument = {argument_n, (argument_data != NULL) ?
00023     g_strdup(argument_data) : NULL};
00024 
00025   /* search for existing binding */
00026   bool found_existing_shortcut = false;
00027   GIRARA_LIST_FOREACH(session->bindings.shortcuts, girara_shortcut_t*, iter, shortcuts_it)
00028     if (((shortcuts_it->mask == modifier && shortcuts_it->key == key && (modifier != 0 || key != 0)) ||
00029        (buffer && shortcuts_it->buffered_command && !strcmp(shortcuts_it->buffered_command, buffer)))
00030         && ((shortcuts_it->mode == mode) || (mode == 0)))
00031     {
00032       if (shortcuts_it->argument.data != NULL) {
00033         g_free(shortcuts_it->argument.data);
00034       }
00035 
00036       shortcuts_it->function  = function;
00037       shortcuts_it->argument  = argument;
00038       found_existing_shortcut = true;
00039 
00040       if (mode != 0) {
00041         girara_list_iterator_free(iter);
00042         return true;
00043       }
00044     }
00045   GIRARA_LIST_FOREACH_END(session->bindings.shortcuts, girara_shortcut_t*, iter, shortcuts_it);
00046 
00047   if (found_existing_shortcut == true) {
00048     return true;
00049   }
00050 
00051   /* add new shortcut */
00052   girara_shortcut_t* shortcut = g_slice_new(girara_shortcut_t);
00053 
00054   shortcut->mask             = modifier;
00055   shortcut->key              = key;
00056   shortcut->buffered_command = buffer;
00057   shortcut->function         = function;
00058   shortcut->mode             = mode;
00059   shortcut->argument         = argument;
00060   girara_list_append(session->bindings.shortcuts, shortcut);
00061 
00062   return true;
00063 }
00064 
00065 bool
00066 girara_shortcut_remove(girara_session_t* session, guint modifier, guint key, const char* buffer, girara_mode_t mode)
00067 {
00068   g_return_val_if_fail(session != NULL, false);
00069   g_return_val_if_fail(buffer || key || modifier, false);
00070 
00071   /* search for existing binding */
00072   GIRARA_LIST_FOREACH(session->bindings.shortcuts, girara_shortcut_t*, iter, shortcuts_it)
00073     if (((shortcuts_it->mask == modifier && shortcuts_it->key == key && (modifier != 0 || key != 0)) ||
00074        (buffer && shortcuts_it->buffered_command && !strcmp(shortcuts_it->buffered_command, buffer)))
00075         && shortcuts_it->mode == mode)
00076     {
00077       girara_list_remove(session->bindings.shortcuts, shortcuts_it);
00078       girara_list_iterator_free(iter);
00079       return true;
00080     }
00081   GIRARA_LIST_FOREACH_END(session->bindings.shortcuts, girara_shortcut_t*, iter, shortcuts_it);
00082 
00083   return false;
00084 }
00085 
00086 void
00087 girara_shortcut_free(girara_shortcut_t* shortcut)
00088 {
00089   g_return_if_fail(shortcut != NULL);
00090   g_free(shortcut->argument.data);
00091   g_slice_free(girara_shortcut_t, shortcut);
00092 }
00093 
00094 bool
00095 girara_inputbar_shortcut_add(girara_session_t* session, guint modifier, guint key, girara_shortcut_function_t function, int argument_n, void* argument_data)
00096 {
00097   g_return_val_if_fail(session  != NULL, false);
00098   g_return_val_if_fail(function != NULL, false);
00099 
00100   girara_argument_t argument = {argument_n, argument_data};
00101 
00102   /* search for existing special command */
00103   GIRARA_LIST_FOREACH(session->bindings.inputbar_shortcuts, girara_inputbar_shortcut_t*, iter, inp_sh_it)
00104     if (inp_sh_it->mask == modifier && inp_sh_it->key == key) {
00105       inp_sh_it->function = function;
00106       inp_sh_it->argument = argument;
00107 
00108       girara_list_iterator_free(iter);
00109       return true;
00110     }
00111   GIRARA_LIST_FOREACH_END(session->bindings.inputbar_shortcuts, girara_inputbar_shortcut_t*, iter, inp_sh_it);
00112 
00113   /* create new inputbar shortcut */
00114   girara_inputbar_shortcut_t* inputbar_shortcut = g_slice_new(girara_inputbar_shortcut_t);
00115 
00116   inputbar_shortcut->mask     = modifier;
00117   inputbar_shortcut->key      = key;
00118   inputbar_shortcut->function = function;
00119   inputbar_shortcut->argument = argument;
00120 
00121   girara_list_append(session->bindings.inputbar_shortcuts, inputbar_shortcut);
00122   return true;
00123 }
00124 
00125 bool
00126 girara_inputbar_shortcut_remove(girara_session_t* session, guint modifier, guint key)
00127 {
00128   g_return_val_if_fail(session  != NULL, false);
00129 
00130   /* search for existing special command */
00131   GIRARA_LIST_FOREACH(session->bindings.inputbar_shortcuts, girara_inputbar_shortcut_t*, iter, inp_sh_it)
00132     if (inp_sh_it->mask == modifier && inp_sh_it->key == key) {
00133       girara_list_remove(session->bindings.inputbar_shortcuts, inp_sh_it);
00134       girara_list_iterator_free(iter);
00135       return true;
00136     }
00137   GIRARA_LIST_FOREACH_END(session->bindings.inputbar_shortcuts, girara_inputbar_shortcut_t*, iter, inp_sh_it);
00138 
00139   return true;
00140 }
00141 
00142 void
00143 girara_inputbar_shortcut_free(girara_inputbar_shortcut_t* inputbar_shortcut)
00144 {
00145   g_slice_free(girara_inputbar_shortcut_t, inputbar_shortcut);
00146 }
00147 bool
00148 girara_isc_abort(girara_session_t* session, girara_argument_t* UNUSED(argument), girara_event_t* UNUSED(event), unsigned int UNUSED(t))
00149 {
00150   /* hide completion */
00151   girara_argument_t arg = { GIRARA_HIDE, NULL };
00152   girara_isc_completion(session, &arg, NULL, 0);
00153 
00154   /* clear inputbar */
00155   gtk_editable_delete_text(GTK_EDITABLE(session->gtk.inputbar_entry), 0, -1);
00156 
00157   /* grab view */
00158   gtk_widget_grab_focus(GTK_WIDGET(session->gtk.view));
00159 
00160   /* hide inputbar */
00161   gtk_widget_hide(GTK_WIDGET(session->gtk.inputbar_dialog));
00162   gtk_widget_hide(GTK_WIDGET(session->gtk.inputbar));
00163 
00164   /* reset custom functions */
00165   session->signals.inputbar_custom_activate        = NULL;
00166   session->signals.inputbar_custom_key_press_event = NULL;
00167   gtk_entry_set_visibility(session->gtk.inputbar_entry, TRUE);
00168 
00169   return true;
00170 }
00171 
00172 bool
00173 girara_isc_string_manipulation(girara_session_t* session, girara_argument_t* argument, girara_event_t* UNUSED(event), unsigned int UNUSED(t))
00174 {
00175   gchar *separator = NULL;
00176   girara_setting_get(session, "word-separator", &separator);
00177   gchar *input  = gtk_editable_get_chars(GTK_EDITABLE(session->gtk.inputbar_entry), 0, -1);
00178   int    length = strlen(input);
00179   int pos       = gtk_editable_get_position(GTK_EDITABLE(session->gtk.inputbar_entry));
00180   int i;
00181 
00182   switch (argument->n) {
00183     case GIRARA_DELETE_LAST_WORD:
00184       i = pos - 1;
00185 
00186       if (!pos) {
00187         break;
00188       }
00189 
00190       /* remove trailing spaces */
00191       for (; i >= 0 && input[i] == ' '; i--);
00192 
00193       /* find the beginning of the word */
00194       while ((i == (pos - 1)) || ((i > 0) && !strchr(separator, input[i]))) {
00195         i--;
00196       }
00197 
00198       gtk_editable_delete_text(GTK_EDITABLE(session->gtk.inputbar_entry),  i + 1, pos);
00199       gtk_editable_set_position(GTK_EDITABLE(session->gtk.inputbar_entry), i + 1);
00200       break;
00201     case GIRARA_DELETE_LAST_CHAR:
00202       if ((length - 1) <= 0) {
00203         girara_isc_abort(session, argument, NULL, 0);
00204       }
00205       gtk_editable_delete_text(GTK_EDITABLE(session->gtk.inputbar_entry), pos - 1, pos);
00206       break;
00207     case GIRARA_DELETE_TO_LINE_START:
00208       gtk_editable_delete_text(GTK_EDITABLE(session->gtk.inputbar_entry), 1, pos);
00209       break;
00210     case GIRARA_NEXT_CHAR:
00211       gtk_editable_set_position(GTK_EDITABLE(session->gtk.inputbar_entry), pos + 1);
00212       break;
00213     case GIRARA_PREVIOUS_CHAR:
00214       gtk_editable_set_position(GTK_EDITABLE(session->gtk.inputbar_entry), (pos == 0) ? 0 : pos - 1);
00215       break;
00216     case GIRARA_DELETE_CURR_CHAR:
00217       if((length - 1) <= 0) {
00218         girara_isc_abort(session, argument, NULL, 0);
00219       }
00220       gtk_editable_delete_text(GTK_EDITABLE(session->gtk.inputbar_entry), pos, pos + 1);
00221       break;
00222     case GIRARA_DELETE_TO_LINE_END:
00223       gtk_editable_delete_text(GTK_EDITABLE(session->gtk.inputbar_entry), pos, length);
00224       break;
00225     case GIRARA_GOTO_START:
00226       gtk_editable_set_position(GTK_EDITABLE(session->gtk.inputbar_entry), 1);
00227       break;
00228     case GIRARA_GOTO_END:
00229       gtk_editable_set_position(GTK_EDITABLE(session->gtk.inputbar_entry), -1);
00230       break;
00231   }
00232 
00233   g_free(separator);
00234   g_free(input);
00235 
00236   return false;
00237 }
00238 
00239 /* default shortcut implementation */
00240 bool
00241 girara_sc_focus_inputbar(girara_session_t* session, girara_argument_t* argument, girara_event_t* UNUSED(event), unsigned int UNUSED(t))
00242 {
00243   g_return_val_if_fail(session != NULL, false);
00244   g_return_val_if_fail(session->gtk.inputbar_entry != NULL, false);
00245 
00246   if (gtk_widget_get_visible(GTK_WIDGET(session->gtk.inputbar)) == false) {
00247     gtk_widget_show(GTK_WIDGET(session->gtk.inputbar));
00248   }
00249 
00250   if (gtk_widget_get_visible(GTK_WIDGET(session->gtk.notification_area)) == true) {
00251     gtk_widget_hide(GTK_WIDGET(session->gtk.notification_area));
00252   }
00253 
00254   gtk_widget_grab_focus(GTK_WIDGET(session->gtk.inputbar_entry));
00255 
00256   if (argument != NULL && argument->data != NULL) {
00257     gtk_entry_set_text(session->gtk.inputbar_entry, (char*) argument->data);
00258 
00259     /* we save the X clipboard that will be clear by "grab_focus" */
00260     gchar* x_clipboard_text = gtk_clipboard_wait_for_text(gtk_clipboard_get(GDK_SELECTION_PRIMARY));
00261 
00262     gtk_editable_set_position(GTK_EDITABLE(session->gtk.inputbar_entry), -1);
00263 
00264     if (x_clipboard_text != NULL) {
00265       /* we reset the X clipboard with saved text */
00266       gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_PRIMARY), x_clipboard_text, -1);
00267       g_free(x_clipboard_text);
00268     }
00269   }
00270 
00271   return true;
00272 }
00273 
00274 bool
00275 girara_sc_abort(girara_session_t* session, girara_argument_t* UNUSED(argument), girara_event_t* UNUSED(event), unsigned int UNUSED(t))
00276 {
00277   g_return_val_if_fail(session != NULL, false);
00278 
00279   girara_isc_abort(session, NULL, NULL, 0);
00280   gtk_widget_hide(GTK_WIDGET(session->gtk.notification_area));
00281 
00282   return false;
00283 }
00284 
00285 bool
00286 girara_sc_quit(girara_session_t* session, girara_argument_t* UNUSED(argument), girara_event_t* UNUSED(event), unsigned int UNUSED(t))
00287 {
00288   g_return_val_if_fail(session != NULL, false);
00289 
00290   girara_argument_t arg = { GIRARA_HIDE, NULL };
00291   girara_isc_completion(session, &arg, NULL, 0);
00292 
00293   gtk_main_quit();
00294 
00295   return false;
00296 }
00297 
00298 bool
00299 girara_sc_tab_close(girara_session_t* session, girara_argument_t* UNUSED(argument), girara_event_t* UNUSED(event), unsigned int UNUSED(t))
00300 {
00301   g_return_val_if_fail(session != NULL, false);
00302 
00303   girara_tab_t* tab = girara_tab_current_get(session);
00304 
00305   if (tab != NULL) {
00306     girara_tab_remove(session, tab);
00307   }
00308 
00309   return false;
00310 }
00311 
00312 bool
00313 girara_sc_tab_navigate(girara_session_t* session, girara_argument_t* argument, girara_event_t* UNUSED(event), unsigned int t)
00314 {
00315   g_return_val_if_fail(session != NULL, false);
00316 
00317   unsigned int number_of_tabs = girara_get_number_of_tabs(session);
00318   unsigned int current_tab    = girara_tab_position_get(session, girara_tab_current_get(session));
00319   unsigned int step           = (argument->n == GIRARA_PREVIOUS) ? -1 : 1;
00320   unsigned int new_tab        = (current_tab + step) % number_of_tabs;
00321 
00322   if (t != 0 && t <= number_of_tabs) {
00323     new_tab = t - 1;
00324   }
00325 
00326   girara_tab_t* tab = girara_tab_get(session, new_tab);
00327 
00328   if (tab != NULL) {
00329     girara_tab_current_set(session, tab);
00330   }
00331 
00332   girara_tab_update(session);
00333 
00334   return false;
00335 }
00336 
00337 static void
00338 girara_toggle_widget_visibility(GtkWidget* widget)
00339 {
00340   if (widget == NULL) {
00341     return;
00342   }
00343 
00344   if (gtk_widget_get_visible(widget)) {
00345     gtk_widget_hide(widget);
00346   } else {
00347     gtk_widget_show(widget);
00348   }
00349 }
00350 
00351 bool
00352 girara_sc_toggle_inputbar(girara_session_t* session, girara_argument_t* UNUSED(argument), girara_event_t* UNUSED(event), unsigned int UNUSED(t))
00353 {
00354   g_return_val_if_fail(session != NULL, false);
00355 
00356   girara_toggle_widget_visibility(GTK_WIDGET(session->gtk.inputbar));
00357 
00358   return true;
00359 }
00360 
00361 bool
00362 girara_sc_toggle_statusbar(girara_session_t* session, girara_argument_t* UNUSED(argument), girara_event_t* UNUSED(event), unsigned int UNUSED(t))
00363 {
00364   g_return_val_if_fail(session != NULL, false);
00365 
00366   girara_toggle_widget_visibility(GTK_WIDGET(session->gtk.statusbar));
00367 
00368   return true;
00369 }
00370 
00371 bool
00372 girara_sc_toggle_tabbar(girara_session_t* session, girara_argument_t* UNUSED(argument), girara_event_t* UNUSED(event), unsigned int UNUSED(t))
00373 {
00374   g_return_val_if_fail(session != NULL, false);
00375 
00376   girara_toggle_widget_visibility(GTK_WIDGET(session->gtk.tabbar));
00377 
00378   return true;
00379 }
00380 
00381 bool
00382 girara_sc_set(girara_session_t* session, girara_argument_t* argument, girara_event_t* UNUSED(event), unsigned int UNUSED(t))
00383 {
00384   g_return_val_if_fail(session  != NULL, false);
00385 
00386   if (argument == NULL || argument->data == NULL) {
00387     return false;
00388   }
00389 
00390   /* create argument list */
00391   girara_list_t* argument_list = girara_list_new();
00392   if (argument_list == NULL) {
00393     return false;
00394   }
00395 
00396   gchar** argv = NULL;
00397   gint argc    = 0;
00398 
00399   girara_list_set_free_function(argument_list, g_free);
00400   if (g_shell_parse_argv((const gchar*) argument->data, &argc, &argv, NULL) != FALSE) {
00401     for(int i = 0; i < argc; i++) {
00402       char* argument = g_strdup(argv[i]);
00403       girara_list_append(argument_list, (void*) argument);
00404     }
00405   } else {
00406     girara_list_free(argument_list);
00407     return false;
00408   }
00409 
00410   /* call set */
00411   girara_cmd_set(session, argument_list);
00412 
00413   /* cleanup */
00414   girara_list_free(argument_list);
00415 
00416   return false;
00417 }
00418 
00419 bool girara_shortcut_mapping_add(girara_session_t* session, const char* identifier, girara_shortcut_function_t function)
00420 {
00421   g_return_val_if_fail(session  != NULL, false);
00422 
00423   if (function == NULL || identifier == NULL) {
00424     return false;
00425   }
00426 
00427   GIRARA_LIST_FOREACH(session->config.shortcut_mappings, girara_shortcut_mapping_t*, iter, data)
00428     if (strcmp(data->identifier, identifier) == 0) {
00429       data->function = function;
00430       girara_list_iterator_free(iter);
00431       return true;
00432     }
00433   GIRARA_LIST_FOREACH_END(session->config.shortcut_mappings, girara_shortcut_mapping_t*, iter, data);
00434 
00435   /* add new config handle */
00436   girara_shortcut_mapping_t* mapping = g_slice_new(girara_shortcut_mapping_t);
00437 
00438   mapping->identifier = g_strdup(identifier);
00439   mapping->function   = function;
00440   girara_list_append(session->config.shortcut_mappings, mapping);
00441 
00442   return true;
00443 }
00444 
00445 void
00446 girara_shortcut_mapping_free(girara_shortcut_mapping_t* mapping)
00447 {
00448   if (mapping == NULL) {
00449     return;
00450   }
00451 
00452   g_free(mapping->identifier);
00453   g_slice_free(girara_shortcut_mapping_t, mapping);
00454 }
00455 
00456 bool girara_argument_mapping_add(girara_session_t* session, const char* identifier, int value)
00457 {
00458   g_return_val_if_fail(session  != NULL, false);
00459 
00460   if (identifier == NULL) {
00461     return false;
00462   }
00463 
00464   GIRARA_LIST_FOREACH(session->config.argument_mappings, girara_argument_mapping_t*, iter, mapping);
00465     if (g_strcmp0(mapping->identifier, identifier) == 0) {
00466       mapping->value = value;
00467       girara_list_iterator_free(iter);
00468       return true;
00469     }
00470   GIRARA_LIST_FOREACH_END(session->config.argument_mappings, girara_argument_mapping_t*, iter, mapping);
00471 
00472   /* add new config handle */
00473   girara_argument_mapping_t* mapping = g_slice_new(girara_argument_mapping_t);
00474 
00475   mapping->identifier = g_strdup(identifier);
00476   mapping->value      = value;
00477   girara_list_append(session->config.argument_mappings, mapping);
00478 
00479   return true;
00480 }
00481 
00482 void
00483 girara_argument_mapping_free(girara_argument_mapping_t* argument_mapping)
00484 {
00485   if (argument_mapping == NULL) {
00486     return;
00487   }
00488 
00489   g_free(argument_mapping->identifier);
00490   g_slice_free(girara_argument_mapping_t, argument_mapping);
00491 }
00492 
00493 bool
00494 girara_mouse_event_add(girara_session_t* session, guint mask, guint button,
00495     girara_shortcut_function_t function, girara_mode_t mode, girara_event_type_t
00496     event_type, int argument_n, void* argument_data)
00497 {
00498   g_return_val_if_fail(session  != NULL, false);
00499   g_return_val_if_fail(function != NULL, false);
00500 
00501   girara_argument_t argument = {argument_n, argument_data};
00502 
00503   /* search for existing binding */
00504   GIRARA_LIST_FOREACH(session->bindings.mouse_events, girara_mouse_event_t*, iter, me_it)
00505     if (me_it->mask == mask && me_it->button == button &&
00506        me_it->mode == mode && me_it->event_type == event_type)
00507     {
00508       me_it->function = function;
00509       me_it->argument = argument;
00510       girara_list_iterator_free(iter);
00511       return true;
00512     }
00513   GIRARA_LIST_FOREACH_END(session->bindings.mouse_events, girara_mouse_event_t*, iter, me_it);
00514 
00515   /* add new mouse event */
00516   girara_mouse_event_t* mouse_event = g_slice_new(girara_mouse_event_t);
00517 
00518   mouse_event->mask       = mask;
00519   mouse_event->button     = button;
00520   mouse_event->function   = function;
00521   mouse_event->mode       = mode;
00522   mouse_event->event_type = event_type;
00523   mouse_event->argument   = argument;
00524   girara_list_append(session->bindings.mouse_events, mouse_event);
00525 
00526   return true;
00527 }
00528 
00529 bool
00530 girara_mouse_event_remove(girara_session_t* session, guint mask, guint button, girara_mode_t mode)
00531 {
00532   g_return_val_if_fail(session  != NULL, false);
00533 
00534   /* search for existing binding */
00535   GIRARA_LIST_FOREACH(session->bindings.mouse_events, girara_mouse_event_t*, iter, me_it)
00536     if (me_it->mask == mask && me_it->button == button &&
00537        me_it->mode == mode)
00538     {
00539       girara_list_remove(session->bindings.mouse_events, me_it);
00540       girara_list_iterator_free(iter);
00541       return true;
00542     }
00543   GIRARA_LIST_FOREACH_END(session->bindings.mouse_events, girara_mouse_event_t*, iter, me_it);
00544 
00545   return false;
00546 }
00547 
00548 void
00549 girara_mouse_event_free(girara_mouse_event_t* mouse_event)
00550 {
00551   if (mouse_event == NULL) {
00552     return;
00553   }
00554   g_slice_free(girara_mouse_event_t, mouse_event);
00555 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines