girara
commands.c
Go to the documentation of this file.
00001 /* See LICENSE file for license and copyright information */
00002 
00003 #include <string.h>
00004 #include <stdlib.h>
00005 #include <glib/gi18n-lib.h>
00006 
00007 #include "commands.h"
00008 #include "datastructures.h"
00009 #include "session.h"
00010 #include "internal.h"
00011 #include "utils.h"
00012 #include "settings.h"
00013 #include "shortcuts.h"
00014 
00015 #if GTK_MAJOR_VERSION == 2
00016 #include "gtk2-compat.h"
00017 #endif
00018 
00019 /* default commands implementation */
00020 bool
00021 girara_cmd_map_unmap(girara_session_t* session, girara_list_t* argument_list,
00022     bool unmap)
00023 {
00024   typedef struct gdk_keyboard_button_s
00025   {
00026     char* identifier;
00027     int keyval;
00028   } gdk_keyboard_button_t;
00029 
00030   static const gdk_keyboard_button_t gdk_keyboard_buttons[] = {
00031     {"BackSpace", GDK_KEY_BackSpace},
00032     {"CapsLock",  GDK_KEY_Caps_Lock},
00033     {"Down",      GDK_KEY_Down},
00034     {"Esc",       GDK_KEY_Escape},
00035     {"F10",       GDK_KEY_F10},
00036     {"F11",       GDK_KEY_F11},
00037     {"F12",       GDK_KEY_F12},
00038     {"F1",        GDK_KEY_F1},
00039     {"F2",        GDK_KEY_F2},
00040     {"F3",        GDK_KEY_F3},
00041     {"F4",        GDK_KEY_F4},
00042     {"F5",        GDK_KEY_F5},
00043     {"F6",        GDK_KEY_F6},
00044     {"F7",        GDK_KEY_F7},
00045     {"F8",        GDK_KEY_F8},
00046     {"F9",        GDK_KEY_F9},
00047     {"Left",      GDK_KEY_Left},
00048     {"PageDown",  GDK_KEY_Page_Down},
00049     {"PageUp",    GDK_KEY_Page_Up},
00050     {"Return",    GDK_KEY_Return},
00051     {"Right",     GDK_KEY_Right},
00052     {"Space",     GDK_KEY_space},
00053     {"Super",     GDK_KEY_Super_L},
00054     {"Tab",       GDK_KEY_Tab},
00055     {"ShiftTab",  GDK_KEY_ISO_Left_Tab},
00056     {"Up",        GDK_KEY_Up}
00057   };
00058 
00059   typedef struct gdk_mouse_button_s
00060   {
00061     char* identifier;
00062     int button;
00063   } gdk_mouse_button_t;
00064 
00065   static const gdk_mouse_button_t gdk_mouse_buttons[] = {
00066     {"Button1", GIRARA_MOUSE_BUTTON1},
00067     {"Button2", GIRARA_MOUSE_BUTTON2},
00068     {"Button3", GIRARA_MOUSE_BUTTON3},
00069     {"Button4", GIRARA_MOUSE_BUTTON4},
00070     {"Button5", GIRARA_MOUSE_BUTTON5},
00071     {"Button6", GIRARA_MOUSE_BUTTON6},
00072     {"Button7", GIRARA_MOUSE_BUTTON7},
00073     {"Button8", GIRARA_MOUSE_BUTTON8},
00074     {"Button9", GIRARA_MOUSE_BUTTON9}
00075   };
00076 
00077   typedef struct event_type_s
00078   {
00079     char* identifier;
00080     int event;
00081   } event_type_t;
00082 
00083   static const event_type_t event_types[] = {
00084     {"motion",       GIRARA_EVENT_MOTION_NOTIFY},
00085     {"scroll_up",    GIRARA_EVENT_SCROLL_UP},
00086     {"scroll_down",  GIRARA_EVENT_SCROLL_DOWN},
00087     {"scroll_left",  GIRARA_EVENT_SCROLL_LEFT},
00088     {"scroll_right", GIRARA_EVENT_SCROLL_RIGHT}
00089   };
00090 
00091   typedef struct mouse_event_s
00092   {
00093     char* identifier;
00094     int event;
00095   } mouse_event_t;
00096 
00097   static const mouse_event_t mouse_events[] = {
00098     {"button-pressed",   GIRARA_EVENT_BUTTON_PRESS},
00099     {"2-button-pressed", GIRARA_EVENT_2BUTTON_PRESS},
00100     {"3-button-pressed", GIRARA_EVENT_2BUTTON_PRESS},
00101     {"button-released",  GIRARA_EVENT_BUTTON_RELEASE}
00102   };
00103 
00104   size_t number_of_arguments = girara_list_size(argument_list);
00105 
00106   if (number_of_arguments < ((unmap == true) ? 1 : 2)) {
00107     if (unmap == true) {
00108       girara_notify(session, GIRARA_WARNING, _("Usage: unmap <binding>"));
00109     } else {
00110       girara_notify(session, GIRARA_WARNING, _("Usage: map <binding> <function>"));
00111     }
00112     return false;
00113   }
00114 
00115   int shortcut_mask                            = 0;
00116   int shortcut_key                             = 0;
00117   int shortcut_mouse_button                    = 0;
00118   girara_mode_t shortcut_mode                  = session->modes.normal;
00119   char* shortcut_argument_data                 = NULL;
00120   int shortcut_argument_n                      = 0;
00121   char* shortcut_buffer_command                = NULL;
00122   girara_event_type_t event_type               = GIRARA_EVENT_BUTTON_PRESS;
00123   girara_shortcut_function_t shortcut_function = NULL;
00124   bool mouse_event                             = false;
00125 
00126   size_t current_command = 0;
00127   char* tmp              = girara_list_nth(argument_list, current_command);
00128   size_t tmp_length      = strlen(tmp);
00129 
00130   /* Check first argument for mode */
00131   bool is_mode = false;
00132   if (tmp_length >= 3 && tmp[0] == '[' && tmp[tmp_length - 1] == ']') {
00133     char* tmp_inner = g_strndup(tmp + 1, tmp_length - 2);
00134 
00135     GIRARA_LIST_FOREACH(session->modes.identifiers, girara_mode_string_t*, iter, mode)
00136       if (!g_strcmp0(tmp_inner, mode->name)) {
00137         shortcut_mode = mode->index;
00138         is_mode       = true;
00139         break;
00140       }
00141     GIRARA_LIST_FOREACH_END(session->modes.identifiers, girara_mode_string_t*, iter, mode);
00142 
00143     if (is_mode == false) {
00144       girara_warning("Unregistered mode specified: %s", tmp_inner);
00145       girara_notify(session, GIRARA_ERROR, _("Unregistered mode specified: %s"), tmp_inner);
00146       g_free(tmp_inner);
00147       return false;
00148     }
00149     g_free(tmp_inner);
00150   }
00151 
00152   unsigned int limit = (unmap == true) ? 1 : 2;
00153   if (number_of_arguments < limit) {
00154     girara_warning("Invalid number of arguments passed: %zu instead of at least %u", number_of_arguments, limit);
00155     girara_notify(session, GIRARA_ERROR,
00156         _("Invalid number of arguments passed: %zu instead of at least %u"), number_of_arguments, limit);
00157     return false;
00158   }
00159 
00160   if (is_mode == true) {
00161     tmp = girara_list_nth(argument_list, ++current_command);
00162     tmp_length = strlen(tmp);
00163   }
00164 
00165   /* Check for multi key shortcut */
00166   if (tmp_length >= 3 && tmp[0] == '<' && tmp[tmp_length - 1] == '>') {
00167     tmp        = g_strndup(tmp + 1, tmp_length - 2);
00168     tmp_length = strlen(tmp);
00169 
00170     /* Multi key shortcut */
00171     if (strchr(tmp, '-') != NULL && tmp_length > 2) {
00172       switch (tmp[0]) {
00173         case 'S':
00174           shortcut_mask = GDK_SHIFT_MASK;
00175           break;
00176         case 'A':
00177           shortcut_mask = GDK_MOD1_MASK;
00178           break;
00179         case 'C':
00180           shortcut_mask = GDK_CONTROL_MASK;
00181           break;
00182         default:
00183           girara_warning("Invalid modifier in %s", tmp);
00184           girara_notify(session, GIRARA_ERROR, _("Invalid modifier in %s"), tmp);
00185           g_free(tmp);
00186           return false;
00187       }
00188 
00189       /* Single key */
00190       if (tmp_length == 3) {
00191         shortcut_key = tmp[2];
00192       /* Possible special key */
00193       } else {
00194         bool found = false;
00195         for (unsigned int i = 0; i < LENGTH(gdk_keyboard_buttons); i++) {
00196           if (g_strcmp0(tmp + 2, gdk_keyboard_buttons[i].identifier) == 0) {
00197             shortcut_key = gdk_keyboard_buttons[i].keyval;
00198             found = true;
00199             break;
00200           }
00201         }
00202 
00203         for (unsigned int i = 0; i < LENGTH(gdk_mouse_buttons); i++) {
00204           if (!g_strcmp0(tmp + 2, gdk_mouse_buttons[i].identifier)) {
00205             shortcut_mouse_button = gdk_mouse_buttons[i].button;
00206             mouse_event = true;
00207             found = true;
00208             break;
00209           }
00210         }
00211 
00212         for (unsigned int i = 0; i < LENGTH(event_types); i++) {
00213           if (!g_strcmp0(tmp + 2, event_types[i].identifier)) {
00214             event_type = event_types[i].event;
00215             mouse_event = true;
00216             found = true;
00217             break;
00218           }
00219         }
00220 
00221         if (found == false) {
00222           girara_warning("Invalid special key value or mode: %s", tmp);
00223           girara_notify(session, GIRARA_ERROR, _("Invalid special key value for %s"), tmp);
00224           g_free(tmp);
00225           return false;
00226         }
00227       }
00228     /* Possible special key */
00229     } else {
00230       bool found = false;
00231       for (unsigned int i = 0; i < LENGTH(gdk_keyboard_buttons); i++) {
00232         if (g_strcmp0(tmp, gdk_keyboard_buttons[i].identifier) == 0) {
00233           shortcut_key = gdk_keyboard_buttons[i].keyval;
00234           found = true;
00235           break;
00236         }
00237       }
00238 
00239       for (unsigned int i = 0; i < LENGTH(gdk_mouse_buttons); i++) {
00240         if (!g_strcmp0(tmp, gdk_mouse_buttons[i].identifier)) {
00241           shortcut_mouse_button = gdk_mouse_buttons[i].button;
00242           mouse_event = true;
00243           found = true;
00244           break;
00245         }
00246       }
00247 
00248       for (unsigned int i = 0; i < LENGTH(event_types); i++) {
00249         if (!g_strcmp0(tmp, event_types[i].identifier)) {
00250           event_type = event_types[i].event;
00251           mouse_event = true;
00252           found = true;
00253           break;
00254         }
00255       }
00256 
00257       if (found == false) {
00258         girara_warning("Invalid special key value or mode: %s", tmp);
00259         girara_notify(session, GIRARA_ERROR, _("Invalid special key value or mode %s"), tmp);
00260         g_free(tmp);
00261         return false;
00262       }
00263     }
00264 
00265     g_free(tmp);
00266   /* Single key shortcut */
00267   } else if (tmp_length == 1) {
00268     shortcut_key = tmp[0];
00269   /* Buffer command */
00270   } else {
00271     shortcut_buffer_command = g_strdup(tmp);
00272   }
00273 
00274   /* check for mouse mode */
00275   bool mouse_mode = false;
00276   if (unmap == false) {
00277     if (++current_command < number_of_arguments) {
00278       tmp = girara_list_nth(argument_list, current_command);
00279       tmp_length = strlen(tmp);
00280 
00281       if (tmp_length >= 3 && tmp[0] == '[' && tmp[tmp_length - 1] == ']') {
00282         mouse_mode = true;
00283         if (mouse_event == false) {
00284           girara_warning("Mode passed on non-mouse event: %s", tmp);
00285           return false;
00286         }
00287 
00288         char* tmp_inner = g_strndup(tmp + 1, tmp_length - 2);
00289 
00290         bool found = false;
00291         for (unsigned int i = 0; i < LENGTH(mouse_events); i++) {
00292           if (!g_strcmp0(tmp_inner, mouse_events[i].identifier)) {
00293             event_type = mouse_events[i].event;
00294             found = true;
00295             break;
00296           }
00297         }
00298 
00299         if (found == false) {
00300           girara_warning("Invalid mouse event mode has been passed: %s", tmp_inner);
00301           g_free(tmp_inner);
00302           return false;
00303         }
00304 
00305         g_free(tmp_inner);
00306       }
00307     } else {
00308       girara_warning("Invalid number of arguments passed");
00309       return false;
00310     }
00311   }
00312 
00313   if (unmap == false) {
00314     limit = (mouse_mode == true) ? 3 : 2;
00315     if (number_of_arguments < limit) {
00316       girara_warning("Invalid number of arguments passed: %zu instead of at least %u", number_of_arguments, limit);
00317       girara_notify(session, GIRARA_ERROR,
00318           _("Invalid number of arguments passed: %zu instead of at least %u"), number_of_arguments, limit);
00319       return false;
00320     }
00321 
00322     if (mouse_mode == true) {
00323       tmp = girara_list_nth(argument_list, ++current_command);
00324     }
00325   }
00326 
00327   /* Check for passed shortcut command */
00328   if (unmap == false) {
00329     bool found_mapping = false;
00330     GIRARA_LIST_FOREACH(session->config.shortcut_mappings, girara_shortcut_mapping_t*, iter, mapping)
00331       if (!g_strcmp0(tmp, mapping->identifier)) {
00332         shortcut_function = mapping->function;
00333         found_mapping = true;
00334         break;
00335       }
00336     GIRARA_LIST_FOREACH_END(session->config.shortcut_mappings, girara_shortcut_mapping_t*, iter, mapping);
00337 
00338     if (found_mapping == false) {
00339       girara_warning("Not a valid shortcut function: %s", tmp);
00340       girara_notify(session, GIRARA_ERROR, _("Not a valid shortcut function: %s"), tmp);
00341       if (shortcut_buffer_command) {
00342         g_free(shortcut_buffer_command);
00343       }
00344       return false;
00345     }
00346   }
00347 
00348   /* Check for passed argument */
00349   if (unmap == false) {
00350     if (++current_command < number_of_arguments) {
00351       tmp = (char*) girara_list_nth(argument_list, current_command);
00352 
00353       GIRARA_LIST_FOREACH(session->config.argument_mappings, girara_argument_mapping_t*, iter, mapping)
00354         if (!g_strcmp0(tmp, mapping->identifier)) {
00355           shortcut_argument_n = mapping->value;
00356           break;
00357         }
00358       GIRARA_LIST_FOREACH_END(session->config.argument_mappings, girara_argument_mapping_t*, iter, mapping);
00359 
00360       /* If no known argument is passed we save it in the data field */
00361       if (shortcut_argument_n == 0) {
00362         shortcut_argument_data = tmp;
00363       /* If a known argument is passed and there are still more arguments,
00364        * we save the next one in the data field */
00365       } else if (++current_command < number_of_arguments) {
00366         tmp = (char*) girara_list_nth(argument_list, current_command);
00367         shortcut_argument_data = tmp;
00368       }
00369     }
00370   }
00371 
00372   if (mouse_event == false) {
00373     if (unmap == true) {
00374       girara_shortcut_remove(session, shortcut_mask, shortcut_key,
00375           shortcut_buffer_command, shortcut_mode);
00376     } else {
00377       girara_shortcut_add(session, shortcut_mask, shortcut_key, shortcut_buffer_command,
00378           shortcut_function, shortcut_mode, shortcut_argument_n, shortcut_argument_data);
00379     }
00380   } else {
00381     if (unmap == true) {
00382       girara_mouse_event_remove(session, shortcut_mask, shortcut_mouse_button,
00383           shortcut_mode);
00384     } else {
00385       girara_mouse_event_add(session, shortcut_mask, shortcut_mouse_button,
00386           shortcut_function, shortcut_mode, event_type, shortcut_argument_n, shortcut_argument_data);
00387     }
00388   }
00389 
00390   if (shortcut_buffer_command) {
00391     g_free(shortcut_buffer_command);
00392   }
00393 
00394   return true;
00395 }
00396 
00397 bool
00398 girara_cmd_map(girara_session_t* session, girara_list_t* argument_list)
00399 {
00400   return girara_cmd_map_unmap(session, argument_list, false);
00401 }
00402 
00403 bool
00404 girara_cmd_unmap(girara_session_t* session, girara_list_t* argument_list)
00405 {
00406   return girara_cmd_map_unmap(session, argument_list, true);
00407 }
00408 
00409 
00410 bool
00411 girara_cmd_quit(girara_session_t* session, girara_list_t* UNUSED(argument_list))
00412 {
00413   girara_argument_t arg = { GIRARA_HIDE, NULL };
00414   girara_isc_completion(session, &arg, NULL, 0);
00415 
00416   gtk_main_quit();
00417 
00418   return true;
00419 }
00420 
00421 bool
00422 girara_cmd_set(girara_session_t* session, girara_list_t* argument_list)
00423 {
00424   const size_t number_of_arguments = girara_list_size(argument_list);
00425 
00426   if (number_of_arguments == 0) {
00427     girara_warning("Not enough arguments for :set.");
00428     girara_notify(session, GIRARA_ERROR, _("Not enough arguments."));
00429     return false;
00430   }
00431   if (number_of_arguments > 2) {
00432     girara_warning("Too many arguments for :set.");
00433     girara_notify(session, GIRARA_ERROR, _("Too many arguments."));
00434     return false;
00435   }
00436 
00437   /* search for existing setting */
00438   char* name = (char*) girara_list_nth(argument_list, 0);
00439   if (name == NULL) {
00440     return false;
00441   }
00442 
00443   girara_setting_t* setting = girara_setting_find(session, name);
00444   if (setting == NULL) {
00445     girara_warning("Unknown option: %s", name);
00446     girara_notify(session, GIRARA_ERROR, _("Unknown option: %s"), name);
00447     return false;
00448   }
00449 
00450   if (number_of_arguments == 1) {
00451     /* display setting*/
00452     switch (girara_setting_get_type(setting)) {
00453       case BOOLEAN:
00454       {
00455         /* for compatibility reasons: toogle the setting */
00456         bool value = false;
00457         girara_setting_get_value(setting, &value);
00458         bool tmp = !value;
00459         girara_setting_set_value(session, setting, &tmp);
00460         girara_notify(session, GIRARA_INFO, "%s: %s", name, tmp ? _("true") : _("false"));
00461         break;
00462       }
00463       case FLOAT:
00464       {
00465         float value = 0;
00466         girara_setting_get_value(setting, &value);
00467         girara_notify(session, GIRARA_INFO, "%s: %f", name, value);
00468         break;
00469       }
00470       case INT:
00471       {
00472         int value = 0;
00473         girara_setting_get_value(setting, &value);
00474         girara_notify(session, GIRARA_INFO, "%s: %i", name, value);
00475         break;
00476       }
00477       case STRING:
00478       {
00479         char* str = NULL;
00480         girara_setting_get_value(setting, &str);
00481         girara_notify(session, GIRARA_INFO, "%s: %s", name, str ? str : "(NULL)");
00482         g_free(str);
00483         break;
00484       }
00485       default:
00486         return false;
00487     }
00488   } else {
00489     char* value = (char*) girara_list_nth(argument_list, 1);
00490     if (value == NULL) {
00491       girara_warning("No value defined for option: %s", name);
00492       girara_notify(session, GIRARA_ERROR, _("No value defined for option: %s"), name);
00493       return false;
00494     }
00495 
00496     /* update value */
00497     switch (girara_setting_get_type(setting)) {
00498       case BOOLEAN:
00499         if (g_strcmp0(value, "false") == 0 || g_strcmp0(value, "0") == 0) {
00500           bool b = false;
00501           girara_setting_set_value(session, setting, &b);
00502         } else if (g_strcmp0(value, "true") == 0 || g_strcmp0(value, "1") == 0) {
00503           bool b = true;
00504           girara_setting_set_value(session, setting, &b);
00505         } else {
00506           girara_warning("Unknown value for option: %s", name);
00507           girara_notify(session, GIRARA_ERROR, _("Unknown value for option: %s"), name);
00508         }
00509         break;
00510       case FLOAT:
00511       {
00512         float f = strtof(value, NULL);
00513         girara_setting_set_value(session, setting, &f);
00514         break;
00515       }
00516       case INT:
00517       {
00518         int i = atoi(value);
00519         girara_setting_set_value(session, setting, &i);
00520         break;
00521       }
00522       case STRING:
00523         girara_setting_set_value(session, setting, value);
00524         break;
00525       default:
00526         return false;
00527     }
00528   }
00529 
00530   return true;
00531 }
00532 
00533 bool
00534 girara_inputbar_command_add(girara_session_t* session, const char* command,
00535     const char* abbreviation, girara_command_function_t function,
00536     girara_completion_function_t completion, const char* description)
00537 {
00538   g_return_val_if_fail(session  != NULL, false);
00539   g_return_val_if_fail(command  != NULL, false);
00540   g_return_val_if_fail(function != NULL, false);
00541 
00542   /* search for existing binding */
00543   GIRARA_LIST_FOREACH(session->bindings.commands, girara_command_t*, iter, commands_it)
00544     if (g_strcmp0(commands_it->command, command) == 0) {
00545       g_free(commands_it->abbr);
00546       g_free(commands_it->description);
00547 
00548       commands_it->abbr        = abbreviation ? g_strdup(abbreviation) : NULL;
00549       commands_it->function    = function;
00550       commands_it->completion  = completion;
00551       commands_it->description = description ? g_strdup(description) : NULL;
00552 
00553       girara_list_iterator_free(iter);
00554       return true;
00555     }
00556   GIRARA_LIST_FOREACH_END(session->bindings.commands, girara_command_t*, iter, commands_it);
00557 
00558   /* add new inputbar command */
00559   girara_command_t* new_command = g_slice_new(girara_command_t);
00560 
00561   new_command->command     = g_strdup(command);
00562   new_command->abbr        = abbreviation ? g_strdup(abbreviation) : NULL;
00563   new_command->function    = function;
00564   new_command->completion  = completion;
00565   new_command->description = description ? g_strdup(description) : NULL;
00566   girara_list_append(session->bindings.commands, new_command);
00567 
00568   return true;
00569 }
00570 
00571 bool
00572 girara_special_command_add(girara_session_t* session, char identifier, girara_inputbar_special_function_t function, bool always, int argument_n, void* argument_data)
00573 {
00574   g_return_val_if_fail(session  != NULL, false);
00575   g_return_val_if_fail(function != NULL, false);
00576 
00577   girara_argument_t argument = {argument_n, argument_data};
00578 
00579   /* search for existing special command */
00580   GIRARA_LIST_FOREACH(session->bindings.special_commands, girara_special_command_t*, iter, scommand_it)
00581     if (scommand_it->identifier == identifier) {
00582       scommand_it->function = function;
00583       scommand_it->always   = always;
00584       scommand_it->argument = argument;
00585       girara_list_iterator_free(iter);
00586       return true;
00587     }
00588   GIRARA_LIST_FOREACH_END(session->bindings.special_commands, girara_special_command_t*, iter, scommand_it);
00589 
00590   /* create new special command */
00591   girara_special_command_t* special_command = g_slice_new(girara_special_command_t);
00592 
00593   special_command->identifier = identifier;
00594   special_command->function   = function;
00595   special_command->always     = always;
00596   special_command->argument   = argument;
00597 
00598   girara_list_append(session->bindings.special_commands, special_command);
00599 
00600   return true;
00601 }
00602 
00603 void
00604 girara_special_command_free(girara_special_command_t* special_command)
00605 {
00606   if (special_command == NULL) {
00607     return;
00608   }
00609   g_slice_free(girara_special_command_t, special_command);
00610 }
00611 
00612 void
00613 girara_command_free(girara_command_t* command)
00614 {
00615   if (command == NULL) {
00616     return;
00617   }
00618 
00619   g_free(command->command);
00620   g_free(command->abbr);
00621   g_free(command->description);
00622   g_slice_free(girara_command_t, command);
00623 }
00624 
00625 bool
00626 girara_cmd_exec(girara_session_t* session, girara_list_t* argument_list)
00627 {
00628   char* cmd = NULL;
00629   girara_setting_get(session, "exec-command", &cmd);
00630   if (cmd == NULL || strlen(cmd) == 0) {
00631     girara_warning("exec-command is invalid.");
00632     girara_notify(session, GIRARA_ERROR, _("exec-command is invalid."));
00633     g_free(cmd);
00634     return false;
00635   }
00636 
00637   GString* command = g_string_new(cmd);
00638   g_free(cmd);
00639 
00640   GIRARA_LIST_FOREACH(argument_list, char*, iter, value)
00641     g_string_append_c(command, ' ');
00642     char* tmp = g_shell_quote(value);
00643     g_string_append(command, tmp);
00644     g_free(tmp);
00645   GIRARA_LIST_FOREACH_END(argument_list, char*, iter, value);
00646 
00647   GError* error = NULL;
00648   gboolean ret = g_spawn_command_line_async(command->str, &error);
00649   if (error != NULL) {
00650     girara_warning("Failed to execute command: %s", error->message);
00651     girara_notify(session, GIRARA_ERROR, _("Failed to execute command: %s"), error->message);
00652     g_error_free(error);
00653   }
00654 
00655   g_string_free(command, TRUE);
00656   return ret;
00657 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines