girara
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
session.c
Go to the documentation of this file.
1 /* See LICENSE file for license and copyright information */
2 
3 #include <stdlib.h>
4 #include <glib/gi18n-lib.h>
5 
6 #include "session.h"
7 #include "settings.h"
8 #include "datastructures.h"
9 #include "internal.h"
10 #include "commands.h"
11 #include "callbacks.h"
12 #include "shortcuts.h"
13 #include "config.h"
14 #include "utils.h"
15 
16 #if GTK_MAJOR_VERSION == 2
17 #include "gtk2-compat.h"
18 #endif
19 
20 static void
21 cb_window_icon(girara_session_t* session, const char* UNUSED(name), girara_setting_type_t UNUSED(type), void* value, void* UNUSED(data))
22 {
23  g_return_if_fail(session != NULL && value != NULL);
24 
25  if (session->gtk.window != NULL) {
26  GError* error = NULL;
27  gtk_window_set_icon_from_file(GTK_WINDOW(session->gtk.window), (const char*) value, &error);
28  if (error != NULL) {
29  girara_error("failed to load window icon: %s", error->message);
30  g_error_free(error);
31  }
32  }
33 }
34 
35 static void
36 cb_font(girara_session_t* session, const char* UNUSED(name), girara_setting_type_t UNUSED(type), void* value, void* UNUSED(data))
37 {
38  g_return_if_fail(session != NULL && value != NULL);
39 
40  pango_font_description_free(session->style.font);
41 
42  /* parse font */
43  PangoFontDescription* font = pango_font_description_from_string(value);
44  session->style.font = font;
45 
46  /* inputbar */
47  if (session->gtk.inputbar_entry != NULL) {
48  gtk_widget_override_font(GTK_WIDGET(session->gtk.inputbar_entry), font);
49  }
50 
51  if (session->gtk.inputbar_dialog != NULL) {
52  gtk_widget_override_font(GTK_WIDGET(session->gtk.inputbar_dialog), font);
53  }
54 
55  /* notification area */
56  if (session->gtk.notification_text != NULL) {
57  gtk_widget_override_font(GTK_WIDGET(session->gtk.notification_text), font);
58  }
59 }
60 
61 static int
62 cb_sort_settings(girara_setting_t* lhs, girara_setting_t* rhs)
63 {
64  return g_strcmp0(girara_setting_get_name(lhs), girara_setting_get_name(rhs));
65 }
66 
67 girara_session_t*
69 {
70  bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);
71  bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
72 
73  girara_session_t* session = g_slice_alloc0(sizeof(girara_session_t));
74 
75  /* init values */
76  session->bindings.mouse_events = girara_list_new2(
78  session->bindings.commands = girara_list_new2(
80  session->bindings.special_commands = girara_list_new2(
82  session->bindings.shortcuts = girara_list_new2(
84  session->bindings.inputbar_shortcuts = girara_list_new2(
86  session->elements.statusbar_items = girara_list_new2(
88  session->settings = girara_sorted_list_new2(
89  (girara_compare_function_t) cb_sort_settings,
91 
92  session->modes.identifiers = girara_list_new2(
94  girara_mode_t normal_mode = girara_mode_add(session, "normal");
95  session->modes.normal = normal_mode;
96  session->modes.current_mode = normal_mode;
97 
98  session->config.handles = girara_list_new2(
100  session->config.shortcut_mappings = girara_list_new2(
102  session->config.argument_mappings = girara_list_new2(
104 
105  session->style.font = NULL;
106 
107  /* default values */
108  int window_width = 800;
109  int window_height = 600;
110  int n_completion_items = 15;
111  bool show_scrollbars = false;
112 
113  /* add default settings */
114  girara_setting_add(session, "font", "monospace normal 9", STRING, FALSE, _("Font"), cb_font, NULL);
115  girara_setting_add(session, "default-fg", "#DDDDDD", STRING, TRUE, _("Default foreground color"), NULL, NULL);
116  girara_setting_add(session, "default-bg", "#000000", STRING, TRUE, _("Default background color"), NULL, NULL);
117  girara_setting_add(session, "inputbar-fg", "#9FBC00", STRING, TRUE, _("Inputbar foreground color"), NULL, NULL);
118  girara_setting_add(session, "inputbar-bg", "#131313", STRING, TRUE, _("Inputbar background color"), NULL, NULL);
119  girara_setting_add(session, "statusbar-fg", "#FFFFFF", STRING, TRUE, _("Statusbar foreground color"), NULL, NULL);
120  girara_setting_add(session, "statusbar-bg", "#000000", STRING, TRUE, _("Statsubar background color"), NULL, NULL);
121  girara_setting_add(session, "completion-fg", "#DDDDDD", STRING, TRUE, _("Completion foreground color"), NULL, NULL);
122  girara_setting_add(session, "completion-bg", "#232323", STRING, TRUE, _("Completion background color"), NULL, NULL);
123  girara_setting_add(session, "completion-group-fg", "#DEDEDE", STRING, TRUE, _("Completion group foreground color"), NULL, NULL);
124  girara_setting_add(session, "completion-group-bg", "#000000", STRING, TRUE, _("Completion group background color"), NULL, NULL);
125  girara_setting_add(session, "completion-highlight-fg", "#232323", STRING, TRUE, _("Completion highlight foreground color"), NULL, NULL);
126  girara_setting_add(session, "completion-highlight-bg", "#9FBC00", STRING, TRUE, _("Completion highlight background color"), NULL, NULL);
127  girara_setting_add(session, "notification-error-fg", "#FFFFFF", STRING, TRUE, _("Error notification foreground color"), NULL, NULL);
128  girara_setting_add(session, "notification-error-bg", "#FF1212", STRING, TRUE, _("Error notification background color"), NULL, NULL);
129  girara_setting_add(session, "notification-warning-fg", "#000000", STRING, TRUE, _("Warning notification foreground color"), NULL, NULL);
130  girara_setting_add(session, "notification-warning-bg", "#F3F000", STRING, TRUE, _("Warning notifaction background color"), NULL, NULL);
131  girara_setting_add(session, "notification-fg", "#000000", STRING, TRUE, _("Notification foreground color"), NULL, NULL);
132  girara_setting_add(session, "notification-bg", "#FFFFFF", STRING, TRUE, _("Notification background color"), NULL, NULL);
133  girara_setting_add(session, "tabbar-fg", "#939393", STRING, TRUE, _("Tab bar foreground color"), NULL, NULL);
134  girara_setting_add(session, "tabbar-bg", "#000000", STRING, TRUE, _("Tab bar background color"), NULL, NULL);
135  girara_setting_add(session, "tabbar-focus-fg", "#9FBC00", STRING, TRUE, _("Tab bar foreground color (active)"), NULL, NULL);
136  girara_setting_add(session, "tabbar-focus-bg", "#000000", STRING, TRUE, _("Tab bar background color (active)"), NULL, NULL);
137  girara_setting_add(session, "word-separator", " /.-=&#?", STRING, TRUE, NULL, NULL, NULL);
138  girara_setting_add(session, "window-width", &window_width, INT, TRUE, _("Initial window width"), NULL, NULL);
139  girara_setting_add(session, "window-height", &window_height, INT, TRUE, _("Initial window height"), NULL, NULL);
140  girara_setting_add(session, "n-completion-items", &n_completion_items, INT, TRUE, _("Number of completion items"), NULL, NULL);
141  girara_setting_add(session, "show-scrollbars", &show_scrollbars, BOOLEAN, TRUE, _("Show scrollbars"), NULL, NULL);
142 
143  /* window icon */
144  girara_setting_add(session, "window-icon", "", STRING, FALSE, _("Window icon"), cb_window_icon, NULL);
145  /* exec-command */
146  girara_setting_add(session, "exec-command", "", STRING, FALSE, _("Command to execute in :exec"), NULL, NULL);
147 
148  /* default shortcuts */
149  girara_shortcut_add(session, 0, GDK_KEY_Escape, NULL, girara_sc_abort, normal_mode, 0, NULL);
150  girara_shortcut_add(session, GDK_CONTROL_MASK, GDK_KEY_c, NULL, girara_sc_abort, normal_mode, 0, NULL);
151  girara_shortcut_add(session, GDK_CONTROL_MASK, GDK_KEY_q, NULL, girara_sc_quit, normal_mode, 0, NULL);
152  girara_shortcut_add(session, 0, GDK_KEY_colon, NULL, girara_sc_focus_inputbar, normal_mode, 0, ":");
153  girara_shortcut_add(session, GDK_CONTROL_MASK, GDK_KEY_w, NULL, girara_sc_tab_close, normal_mode, 0, NULL);
154  girara_shortcut_add(session, 0, 0, "gt", girara_sc_tab_navigate, normal_mode, GIRARA_NEXT, NULL);
155  girara_shortcut_add(session, 0, 0, "gT", girara_sc_tab_navigate, normal_mode, GIRARA_PREVIOUS, NULL);
156 
157  /* default inputbar shortcuts */
158  girara_inputbar_shortcut_add(session, 0, GDK_KEY_Escape, girara_isc_abort, 0, NULL);
159  girara_inputbar_shortcut_add(session, GDK_CONTROL_MASK, GDK_KEY_c, girara_isc_abort, 0, NULL);
160  girara_inputbar_shortcut_add(session, 0, GDK_KEY_Tab, girara_isc_completion, GIRARA_NEXT, NULL);
161  girara_inputbar_shortcut_add(session, GDK_CONTROL_MASK, GDK_KEY_Tab, girara_isc_completion, GIRARA_NEXT_GROUP, NULL);
162  girara_inputbar_shortcut_add(session, 0, GDK_KEY_ISO_Left_Tab, girara_isc_completion, GIRARA_PREVIOUS, NULL);
163  girara_inputbar_shortcut_add(session, GDK_CONTROL_MASK, GDK_KEY_ISO_Left_Tab, girara_isc_completion, GIRARA_PREVIOUS_GROUP, NULL);
165  girara_inputbar_shortcut_add(session, GDK_CONTROL_MASK, GDK_KEY_h, girara_isc_string_manipulation, GIRARA_DELETE_LAST_CHAR, NULL);
167  girara_inputbar_shortcut_add(session, GDK_CONTROL_MASK, GDK_KEY_k, girara_isc_string_manipulation, GIRARA_DELETE_TO_LINE_END, NULL);
168  girara_inputbar_shortcut_add(session, GDK_CONTROL_MASK, GDK_KEY_d, girara_isc_string_manipulation, GIRARA_DELETE_CURR_CHAR, NULL);
169  girara_inputbar_shortcut_add(session, GDK_CONTROL_MASK, GDK_KEY_w, girara_isc_string_manipulation, GIRARA_DELETE_LAST_WORD, NULL);
170  girara_inputbar_shortcut_add(session, GDK_CONTROL_MASK, GDK_KEY_f, girara_isc_string_manipulation, GIRARA_NEXT_CHAR, NULL);
171  girara_inputbar_shortcut_add(session, GDK_CONTROL_MASK, GDK_KEY_b, girara_isc_string_manipulation, GIRARA_PREVIOUS_CHAR, NULL);
172  girara_inputbar_shortcut_add(session, GDK_CONTROL_MASK, GDK_KEY_a, girara_isc_string_manipulation, GIRARA_GOTO_START, NULL);
173  girara_inputbar_shortcut_add(session, GDK_CONTROL_MASK, GDK_KEY_e, girara_isc_string_manipulation, GIRARA_GOTO_END, NULL);
174 
175  /* default commands */
176  girara_inputbar_command_add(session, "exec", NULL, girara_cmd_exec, NULL, _("Execute a command"));
177  girara_inputbar_command_add(session, "map", "m", girara_cmd_map, NULL, _("Map a key sequence"));
178  girara_inputbar_command_add(session, "quit", "q", girara_cmd_quit, NULL, _("Quit the program"));
179  girara_inputbar_command_add(session, "set", "s", girara_cmd_set, girara_cc_set, _("Set an option"));
180  girara_inputbar_command_add(session, "unmap", NULL, girara_cmd_unmap, NULL, _("Unmap a key sequence"));
181 
182  /* default config handle */
183  girara_config_handle_add(session, "map", girara_cmd_map);
184  girara_config_handle_add(session, "set", girara_cmd_set);
185  girara_config_handle_add(session, "unmap", girara_cmd_unmap);
186 
187  /* default shortcut mappings */
188  girara_shortcut_mapping_add(session, "focus_inputbar", girara_sc_focus_inputbar);
191 
192  return session;
193 }
194 
195 bool
196 girara_session_init(girara_session_t* session, const char* sessionname)
197 {
198  if (session->gtk.embed){
199  session->gtk.window = gtk_plug_new(session->gtk.embed);
200  } else {
201  session->gtk.window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
202  }
203  if (sessionname != NULL) {
204  gtk_widget_set_name(GTK_WIDGET(session->gtk.window), sessionname);
205  }
206 
207 #if GTK_MAJOR_VERSION == 2
208  session->gtk.box = GTK_BOX(gtk_vbox_new(FALSE, 0));
209  session->gtk.statusbar_entries = GTK_BOX(gtk_hbox_new(FALSE, 0));
210  session->gtk.tabbar = gtk_hbox_new(TRUE, 0);
211  session->gtk.inputbar_box = GTK_BOX(gtk_hbox_new(TRUE, 0));
212 #else
213  session->gtk.box = GTK_BOX(gtk_box_new(GTK_ORIENTATION_VERTICAL, 0));
214  session->gtk.statusbar_entries = GTK_BOX(gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0));
215  session->gtk.tabbar = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
216  session->gtk.inputbar_box = GTK_BOX(gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0));
217  gtk_box_set_homogeneous(GTK_BOX(session->gtk.tabbar), TRUE);
218  gtk_box_set_homogeneous(session->gtk.inputbar_box, TRUE);
219 #endif
220  session->gtk.view = gtk_scrolled_window_new(NULL, NULL);
221  session->gtk.viewport = gtk_viewport_new(NULL, NULL);
222  session->gtk.statusbar = gtk_event_box_new();
223  session->gtk.notification_area = gtk_event_box_new();
224  session->gtk.notification_text = gtk_label_new(NULL);
225  session->gtk.inputbar_dialog = GTK_LABEL(gtk_label_new(NULL));
226  session->gtk.inputbar_entry = GTK_ENTRY(gtk_entry_new());
227  session->gtk.inputbar = gtk_event_box_new();
228  session->gtk.tabs = GTK_NOTEBOOK(gtk_notebook_new());
229 
230  /* window */
231  GdkGeometry hints = {
232  .base_height = 1,
233  .base_width = 1,
234  .height_inc = 0,
235  .max_aspect = 0,
236  .max_height = 0,
237  .max_width = 0,
238  .min_aspect = 0,
239  .min_height = 0,
240  .min_width = 0,
241  .width_inc = 0
242  };
243 
244  gtk_window_set_geometry_hints(GTK_WINDOW(session->gtk.window), NULL, &hints, GDK_HINT_MIN_SIZE);
245 
246 #if (GTK_MAJOR_VERSION == 3)
247  gtk_window_set_has_resize_grip(GTK_WINDOW(session->gtk.window), FALSE);
248 #endif
249 
250  /* view */
251  session->signals.view_key_pressed = g_signal_connect(G_OBJECT(session->gtk.view), "key-press-event",
252  G_CALLBACK(girara_callback_view_key_press_event), session);
253 
254  session->signals.view_button_press_event = g_signal_connect(G_OBJECT(session->gtk.view), "button-press-event",
255  G_CALLBACK(girara_callback_view_button_press_event), session);
256 
257  session->signals.view_button_release_event = g_signal_connect(G_OBJECT(session->gtk.view), "button-release-event",
258  G_CALLBACK(girara_callback_view_button_release_event), session);
259 
260  session->signals.view_motion_notify_event = g_signal_connect(G_OBJECT(session->gtk.view), "motion-notify-event",
262 
263  session->signals.view_key_pressed = g_signal_connect(G_OBJECT(session->gtk.view), "scroll-event",
264  G_CALLBACK(girara_callback_view_scroll_event), session);
265 
266  bool tmp_bool_value = false;
267  girara_setting_get(session, "show-scrollbars", &tmp_bool_value);
268  if (tmp_bool_value == true) {
269  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(session->gtk.view),
270  GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
271  } else {
272  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(session->gtk.view),
273  GTK_POLICY_NEVER, GTK_POLICY_NEVER);
274  }
275 
276  /* viewport */
277  gtk_container_add(GTK_CONTAINER(session->gtk.view), session->gtk.viewport);
278  gtk_viewport_set_shadow_type(GTK_VIEWPORT(session->gtk.viewport), GTK_SHADOW_NONE);
279 
280  /* box */
281  gtk_box_set_spacing(session->gtk.box, 0);
282  gtk_container_add(GTK_CONTAINER(session->gtk.window), GTK_WIDGET(session->gtk.box));
283 
284  /* statusbar */
285  gtk_container_add(GTK_CONTAINER(session->gtk.statusbar), GTK_WIDGET(session->gtk.statusbar_entries));
286 
287  /* notification area */
288  gtk_container_add(GTK_CONTAINER(session->gtk.notification_area), GTK_WIDGET(session->gtk.notification_text));
289  gtk_misc_set_alignment(GTK_MISC(session->gtk.notification_text), 0.0, 0.0);
290  gtk_misc_set_padding(GTK_MISC(session->gtk.notification_text), 2, 2);
291  gtk_label_set_use_markup(GTK_LABEL(session->gtk.notification_text), TRUE);
292 
293  /* inputbar */
294  gtk_entry_set_inner_border(session->gtk.inputbar_entry, NULL);
295  gtk_entry_set_has_frame(session->gtk.inputbar_entry, FALSE);
296  gtk_editable_set_editable(GTK_EDITABLE(session->gtk.inputbar_entry), TRUE);
297 
298  session->signals.inputbar_key_pressed = g_signal_connect(
299  G_OBJECT(session->gtk.inputbar_entry),
300  "key-press-event",
302  session
303  );
304 
305  session->signals.inputbar_changed = g_signal_connect(
306  G_OBJECT(session->gtk.inputbar_entry),
307  "changed",
309  session
310  );
311 
312  session->signals.inputbar_activate = g_signal_connect(
313  G_OBJECT(session->gtk.inputbar_entry),
314  "activate",
316  session
317  );
318 
319  gtk_box_set_homogeneous(session->gtk.inputbar_box, FALSE);
320  gtk_box_set_spacing(session->gtk.inputbar_box, 5);
321 
322  gtk_box_pack_start(GTK_BOX(session->gtk.inputbar_box), GTK_WIDGET(session->gtk.inputbar_dialog), FALSE, FALSE, 0);
323  gtk_box_pack_start(GTK_BOX(session->gtk.inputbar_box), GTK_WIDGET(session->gtk.inputbar_entry), TRUE, TRUE, 0);
324  gtk_container_add(GTK_CONTAINER(session->gtk.inputbar), GTK_WIDGET(session->gtk.inputbar_box));
325 
326  /* tabs */
327  gtk_notebook_set_show_border(session->gtk.tabs, FALSE);
328  gtk_notebook_set_show_tabs(session->gtk.tabs, FALSE);
329 
330  /* packing */
331  gtk_box_pack_start(session->gtk.box, GTK_WIDGET(session->gtk.tabbar), FALSE, FALSE, 0);
332  gtk_box_pack_start(session->gtk.box, GTK_WIDGET(session->gtk.view), TRUE, TRUE, 0);
333  gtk_box_pack_start(session->gtk.box, GTK_WIDGET(session->gtk.statusbar), FALSE, FALSE, 0);
334  gtk_box_pack_start(session->gtk.box, GTK_WIDGET(session->gtk.notification_area), FALSE, FALSE, 0);
335  gtk_box_pack_end( session->gtk.box, GTK_WIDGET(session->gtk.inputbar), FALSE, FALSE, 0);
336 
337  /* parse color values */
338  typedef struct color_setting_mapping_s
339  {
340  char* identifier;
341  GdkRGBA *color;
342  } color_setting_mapping_t;
343 
344  const color_setting_mapping_t color_setting_mappings[] = {
345  {"default-fg", &(session->style.default_foreground)},
346  {"default-bg", &(session->style.default_background)},
347  {"inputbar-fg", &(session->style.inputbar_foreground)},
348  {"inputbar-bg", &(session->style.inputbar_background)},
349  {"statusbar-fg", &(session->style.statusbar_foreground)},
350  {"statusbar-bg", &(session->style.statusbar_background)},
351  {"completion-fg", &(session->style.completion_foreground)},
352  {"completion-bg", &(session->style.completion_background)},
353  {"completion-group-fg", &(session->style.completion_group_foreground)},
354  {"completion-group-bg", &(session->style.completion_group_background)},
355  {"completion-highlight-fg", &(session->style.completion_highlight_foreground)},
356  {"completion-highlight-bg", &(session->style.completion_highlight_background)},
357  {"notification-error-fg", &(session->style.notification_error_foreground)},
358  {"notification-error-bg", &(session->style.notification_error_background)},
359  {"notification-warning-fg", &(session->style.notification_warning_foreground)},
360  {"notification-warning-bg", &(session->style.notification_warning_background)},
361  {"notification-fg", &(session->style.notification_default_foreground)},
362  {"notification-bg", &(session->style.notification_default_background)},
363  {"tabbar-fg", &(session->style.tabbar_foreground)},
364  {"tabbar-bg", &(session->style.tabbar_background)},
365  {"tabbar-focus-fg", &(session->style.tabbar_focus_foreground)},
366  {"tabbar-focus-bg", &(session->style.tabbar_focus_background)},
367  };
368 
369  for (unsigned i = 0; i < LENGTH(color_setting_mappings); i++) {
370  char* tmp_value = NULL;
371  girara_setting_get(session, color_setting_mappings[i].identifier, &tmp_value);
372  if (tmp_value != NULL) {
373  gdk_rgba_parse(color_setting_mappings[i].color, tmp_value);
374  g_free(tmp_value);
375  }
376  }
377 
378  /* view */
379  gtk_widget_override_background_color(GTK_WIDGET(session->gtk.viewport),
380  GTK_STATE_NORMAL, &(session->style.default_background));
381 
382  /* statusbar */
383  gtk_widget_override_background_color(GTK_WIDGET(session->gtk.statusbar),
384  GTK_STATE_NORMAL, &(session->style.statusbar_background));
385 
386  /* inputbar */
387 #if (GTK_MAJOR_VERSION == 3)
388  gtk_widget_override_background_color(GTK_WIDGET(session->gtk.inputbar_entry),
389  GTK_STATE_NORMAL, &(session->style.inputbar_background));
390  gtk_widget_override_color(GTK_WIDGET(session->gtk.inputbar_entry),
391  GTK_STATE_NORMAL, &(session->style.inputbar_foreground));
392 
393  gtk_widget_override_background_color(GTK_WIDGET(session->gtk.inputbar),
394  GTK_STATE_NORMAL, &(session->style.inputbar_background));
395  gtk_widget_override_color(GTK_WIDGET(session->gtk.inputbar_dialog),
396  GTK_STATE_NORMAL, &(session->style.inputbar_foreground));
397 
398  /* notification area */
399  gtk_widget_override_background_color(GTK_WIDGET(session->gtk.notification_area),
400  GTK_STATE_NORMAL, &(session->style.notification_default_background));
401  gtk_widget_override_color(GTK_WIDGET(session->gtk.notification_text),
402  GTK_STATE_NORMAL, &(session->style.notification_default_foreground));
403 #else
404  /* inputbar */
405  gtk_widget_modify_base(GTK_WIDGET(session->gtk.inputbar_entry), GTK_STATE_NORMAL, &(session->style.inputbar_background));
406  gtk_widget_modify_text(GTK_WIDGET(session->gtk.inputbar_entry), GTK_STATE_NORMAL, &(session->style.inputbar_foreground));
407 
408  gtk_widget_modify_bg(GTK_WIDGET(session->gtk.inputbar), GTK_STATE_NORMAL, &(session->style.inputbar_background));
409  gtk_widget_modify_fg(GTK_WIDGET(session->gtk.inputbar_dialog), GTK_STATE_NORMAL, &(session->style.inputbar_foreground));
410 
411  /* notification area */
412  gtk_widget_modify_bg(GTK_WIDGET(session->gtk.notification_area),
413  GTK_STATE_NORMAL, &(session->style.notification_default_background));
414  gtk_widget_modify_text(GTK_WIDGET(session->gtk.notification_text),
415  GTK_STATE_NORMAL, &(session->style.notification_default_foreground));
416 #endif
417 
418  if (session->style.font == NULL) {
419  /* set default font */
420  girara_setting_set(session, "font", "monospace normal 9");
421  } else {
422  gtk_widget_override_font(GTK_WIDGET(session->gtk.inputbar_entry), session->style.font);
423  gtk_widget_override_font(GTK_WIDGET(session->gtk.inputbar_dialog), session->style.font);
424  gtk_widget_override_font(GTK_WIDGET(session->gtk.notification_text), session->style.font);
425  }
426 
427  /* set window size */
428  int window_width = 0;
429  int window_height = 0;
430  girara_setting_get(session, "window-width", &window_width);
431  girara_setting_get(session, "window-height", &window_height);
432 
433  if (window_width > 0&& window_height > 0) {
434  gtk_window_set_default_size(GTK_WINDOW(session->gtk.window), window_width, window_height);
435  }
436 
437  gtk_widget_show_all(GTK_WIDGET(session->gtk.window));
438  gtk_widget_hide(GTK_WIDGET(session->gtk.notification_area));
439  gtk_widget_hide(GTK_WIDGET(session->gtk.inputbar));
440  gtk_widget_hide(GTK_WIDGET(session->gtk.inputbar_dialog));
441 
442  char* window_icon = NULL;
443  girara_setting_get(session, "window-icon", &window_icon);
444  if (window_icon != NULL) {
445  if (strlen(window_icon) != 0) {
446  girara_setting_set(session, "window-icon", window_icon);
447  }
448  g_free(window_icon);
449  }
450 
451  return TRUE;
452 }
453 
454 bool
455 girara_session_destroy(girara_session_t* session)
456 {
457  g_return_val_if_fail(session != NULL, FALSE);
458 
459  /* clean up style */
460  pango_font_description_free(session->style.font);
461 
462  /* clean up shortcuts */
463  girara_list_free(session->bindings.shortcuts);
464  session->bindings.shortcuts = NULL;
465 
466  /* clean up inputbar shortcuts */
467  girara_list_free(session->bindings.inputbar_shortcuts);
468  session->bindings.inputbar_shortcuts = NULL;
469 
470  /* clean up commands */
471  girara_list_free(session->bindings.commands);
472  session->bindings.commands = NULL;
473 
474  /* clean up special commands */
475  girara_list_free(session->bindings.special_commands);
476  session->bindings.special_commands = NULL;
477 
478  /* clean up mouse events */
479  girara_list_free(session->bindings.mouse_events);
480  session->bindings.mouse_events = NULL;
481 
482  /* clean up settings */
483  girara_list_free(session->settings);
484  session->settings = NULL;
485 
486  /* clean up statusbar items */
487  girara_list_free(session->elements.statusbar_items);
488  session->elements.statusbar_items = NULL;
489 
490  /* clean up config handles */
491  girara_list_free(session->config.handles);
492  session->config.handles = NULL;
493 
494  /* clean up shortcut mappings */
495  girara_list_free(session->config.shortcut_mappings);
496  session->config.shortcut_mappings = NULL;
497 
498  /* clean up argument mappings */
499  girara_list_free(session->config.argument_mappings);
500  session->config.argument_mappings = NULL;
501 
502  /* clean up modes */
503  girara_list_free(session->modes.identifiers);
504  session->modes.identifiers = NULL;
505 
506  /* clean up buffer */
507  if (session->buffer.command) {
508  g_string_free(session->buffer.command, TRUE);
509  }
510 
511  if (session->global.buffer) {
512  g_string_free(session->global.buffer, TRUE);
513  }
514 
515  session->buffer.command = NULL;
516  session->global.buffer = NULL;
517 
518  /* clean up session */
519  g_slice_free(girara_session_t, session);
520 
521  return TRUE;
522 }
523 
524 char*
525 girara_buffer_get(girara_session_t* session)
526 {
527  g_return_val_if_fail(session != NULL, NULL);
528 
529  return (session->global.buffer) ? g_strdup(session->global.buffer->str) : NULL;
530 }
531 
532 void
533 girara_notify(girara_session_t* session, int level, const char* format, ...)
534 {
535  if (session == NULL
536  || session->gtk.notification_text == NULL
537  || session->gtk.notification_area == NULL
538  || session->gtk.inputbar == NULL
539  || session->gtk.view == NULL) {
540  return;
541  }
542 
543  switch (level) {
544  case GIRARA_ERROR:
545  gtk_widget_override_background_color(GTK_WIDGET(session->gtk.notification_area),
546  GTK_STATE_NORMAL, &(session->style.notification_error_background));
547  gtk_widget_override_color(GTK_WIDGET(session->gtk.notification_text),
548  GTK_STATE_NORMAL, &(session->style.notification_error_foreground));
549  break;
550  case GIRARA_WARNING:
551  gtk_widget_override_background_color(GTK_WIDGET(session->gtk.notification_area),
552  GTK_STATE_NORMAL, &(session->style.notification_warning_background));
553  gtk_widget_override_color(GTK_WIDGET(session->gtk.notification_text),
554  GTK_STATE_NORMAL, &(session->style.notification_warning_foreground));
555  break;
556  case GIRARA_INFO:
557  gtk_widget_override_background_color(GTK_WIDGET(session->gtk.notification_area),
558  GTK_STATE_NORMAL, &(session->style.notification_default_background));
559  gtk_widget_override_color(GTK_WIDGET(session->gtk.notification_text),
560  GTK_STATE_NORMAL, &(session->style.notification_default_foreground));
561  break;
562  default:
563  return;
564  }
565 
566  /* prepare message */
567  va_list ap;
568  va_start(ap, format);
569  char* message = g_strdup_vprintf(format, ap);
570  va_end(ap);
571 
572  gtk_label_set_markup(GTK_LABEL(session->gtk.notification_text), message);
573  g_free(message);
574 
575  /* update visibility */
576  gtk_widget_show(GTK_WIDGET(session->gtk.notification_area));
577  gtk_widget_hide(GTK_WIDGET(session->gtk.inputbar));
578 
579  gtk_widget_grab_focus(GTK_WIDGET(session->gtk.view));
580 }
581 
582 void girara_dialog(girara_session_t* session, const char* dialog, bool
583  invisible, girara_callback_inputbar_key_press_event_t key_press_event,
584  girara_callback_inputbar_activate_t activate_event, void* data)
585 {
586  if (session == NULL || session->gtk.inputbar == NULL
587  || session->gtk.inputbar_dialog == NULL
588  || session->gtk.inputbar_entry == NULL) {
589  return;
590  }
591 
592  gtk_widget_show(GTK_WIDGET(session->gtk.inputbar_dialog));
593 
594  /* set dialog message */
595  if (dialog != NULL) {
596  gtk_label_set_markup(session->gtk.inputbar_dialog, dialog);
597  }
598 
599  /* set input visibility */
600  if (invisible == true) {
601  gtk_entry_set_visibility(session->gtk.inputbar_entry, FALSE);
602  } else {
603  gtk_entry_set_visibility(session->gtk.inputbar_entry, TRUE);
604  }
605 
606  /* set handler */
607  session->signals.inputbar_custom_activate = activate_event;
608  session->signals.inputbar_custom_key_press_event = key_press_event;
609  session->signals.inputbar_custom_data = data;
610 
611  /* focus inputbar */
612  girara_sc_focus_inputbar(session, NULL, NULL, 0);
613 }
614 
615 bool
616 girara_set_view(girara_session_t* session, GtkWidget* widget)
617 {
618  g_return_val_if_fail(session != NULL, false);
619 
620  GtkWidget* child = gtk_bin_get_child(GTK_BIN(session->gtk.viewport));
621 
622  if (child) {
623  g_object_ref(child);
624  gtk_container_remove(GTK_CONTAINER(session->gtk.viewport), child);
625  }
626 
627  gtk_container_add(GTK_CONTAINER(session->gtk.viewport), widget);
628  gtk_widget_show_all(widget);
629 
630  return true;
631 }
632 
633 void
634 girara_mode_set(girara_session_t* session, girara_mode_t mode)
635 {
636  g_return_if_fail(session != NULL);
637 
638  session->modes.current_mode = mode;
639 }
640 
642 girara_mode_add(girara_session_t* session, const char* name)
643 {
644  g_return_val_if_fail(session != NULL, FALSE);
645  g_return_val_if_fail(name != NULL && name[0] != 0x0, FALSE);
646 
647  girara_mode_t last_index = 0;
648  GIRARA_LIST_FOREACH(session->modes.identifiers, girara_mode_string_t*, iter, mode)
649  if (mode->index > last_index) {
650  last_index = mode->index;
651  }
652  GIRARA_LIST_FOREACH_END(session->modes.identifiers, girara_mode_string_t*, iter, mode);
653 
654  /* create new mode identifier */
655  girara_mode_string_t* mode = g_slice_new(girara_mode_string_t);
656  mode->index = last_index + 1;
657  mode->name = g_strdup(name);
658  girara_list_append(session->modes.identifiers, mode);
659 
660  return mode->index;
661 }
662 
663 void
664 girara_mode_string_free(girara_mode_string_t* mode)
665 {
666  if (!mode) {
667  return;
668  }
669 
670  g_free(mode->name);
671  g_slice_free(girara_mode_string_t, mode);
672 }
673 
675 girara_mode_get(girara_session_t* session)
676 {
677  g_return_val_if_fail(session != NULL, 0);
678 
679  return session->modes.current_mode;
680 }
681 
682 bool
683 girara_set_window_title(girara_session_t* session, const char* name)
684 {
685  if (session == NULL || session->gtk.window == NULL || name == NULL) {
686  return false;
687  }
688 
689  gtk_window_set_title(GTK_WINDOW(session->gtk.window), name);
690 
691  return true;
692 }
693