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 #include "input-history.h"
16 
17 #if GTK_MAJOR_VERSION == 2
18 #include "gtk2-compat.h"
19 #endif
20 
21 #if defined(__GNUC__) || defined(__clang__)
22 #define DO_PRAGMA(x) _Pragma(#x)
23 #else
24 #define DO_PRAGMA(x)
25 #endif
26 
27 #define IGNORE_DEPRECATED \
28  DO_PRAGMA(GCC diagnostic push) \
29  DO_PRAGMA(GCC diagnostic ignored "-Wdeprecated-declarations")
30 #define UNIGNORE \
31  DO_PRAGMA(GCC diagnostic pop)
32 
33 static int
34 cb_sort_settings(girara_setting_t* lhs, girara_setting_t* rhs)
35 {
36  return g_strcmp0(girara_setting_get_name(lhs), girara_setting_get_name(rhs));
37 }
38 
39 static void
40 ensure_gettext_initialized(void)
41 {
42  static gsize initialized = 0;
43  if (g_once_init_enter(&initialized) == TRUE) {
44  bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);
45  bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
46  g_once_init_leave(&initialized, 1);
47  }
48 }
49 
50 girara_session_t*
52 {
53  ensure_gettext_initialized();
54 
55  girara_session_t* session = g_slice_alloc0(sizeof(girara_session_t));
56  session->private_data = g_slice_alloc0(sizeof(girara_session_private_t));
57 
58  /* init values */
59  session->bindings.mouse_events = girara_list_new2(
61  session->bindings.commands = girara_list_new2(
63  session->bindings.special_commands = girara_list_new2(
65  session->bindings.shortcuts = girara_list_new2(
67  session->bindings.inputbar_shortcuts = girara_list_new2(
69 
70  session->elements.statusbar_items = girara_list_new2(
72 
73  /* settings */
74  session->private_data->settings = girara_sorted_list_new2(
75  (girara_compare_function_t) cb_sort_settings,
77 
78  /* init modes */
79  session->modes.identifiers = girara_list_new2(
81  girara_mode_t normal_mode = girara_mode_add(session, "normal");
82  girara_mode_t inputbar_mode = girara_mode_add(session, "inputbar");
83  session->modes.normal = normal_mode;
84  session->modes.current_mode = normal_mode;
85  session->modes.inputbar = inputbar_mode;
86 
87  /* config handles */
88  session->config.handles = girara_list_new2(
90  session->config.shortcut_mappings = girara_list_new2(
92  session->config.argument_mappings = girara_list_new2(
94 
95  /* command history */
96  session->command_history = girara_input_history_new(NULL);
97 
98  /* load default values */
100 
101  /* create widgets */
102 #if GTK_MAJOR_VERSION == 2
103  session->gtk.box = GTK_BOX(gtk_vbox_new(FALSE, 0));
104  session->private_data->gtk.bottom_box = GTK_BOX(gtk_vbox_new(FALSE, 0));
105  session->gtk.statusbar_entries = GTK_BOX(gtk_hbox_new(FALSE, 0));
106  session->gtk.tabbar = gtk_hbox_new(TRUE, 0);
107  session->gtk.inputbar_box = GTK_BOX(gtk_hbox_new(TRUE, 0));
108 #else
109  session->gtk.box = GTK_BOX(gtk_box_new(GTK_ORIENTATION_VERTICAL, 0));
110  session->private_data->gtk.overlay = gtk_overlay_new();
111  session->private_data->gtk.bottom_box = GTK_BOX(gtk_box_new(GTK_ORIENTATION_VERTICAL, 0));
112  session->gtk.statusbar_entries = GTK_BOX(gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0));
113  session->gtk.tabbar = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
114  session->gtk.inputbar_box = GTK_BOX(gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0));
115  gtk_box_set_homogeneous(GTK_BOX(session->gtk.tabbar), TRUE);
116  gtk_box_set_homogeneous(session->gtk.inputbar_box, TRUE);
117 #endif
118  session->gtk.view = gtk_scrolled_window_new(NULL, NULL);
119  session->gtk.viewport = gtk_viewport_new(NULL, NULL);
120 #if GTK_MAJOR_VERSION == 3 && GTK_MINOR_VERSION >= 4
121  gtk_widget_add_events(session->gtk.viewport, GDK_SCROLL_MASK);
122 #endif
123  session->gtk.statusbar = gtk_event_box_new();
124  session->gtk.notification_area = gtk_event_box_new();
125  session->gtk.notification_text = gtk_label_new(NULL);
126  session->gtk.inputbar_dialog = GTK_LABEL(gtk_label_new(NULL));
127  session->gtk.inputbar_entry = GTK_ENTRY(gtk_entry_new());
128  session->gtk.inputbar = gtk_event_box_new();
129  session->gtk.tabs = GTK_NOTEBOOK(gtk_notebook_new());
130 
131  /* deprecated members */
133  session->settings = session->private_data->settings;
134  session->global.command_history = girara_get_command_history(session);
135  UNIGNORE
136 
137  return session;
138 }
139 
140 bool
141 girara_session_init(girara_session_t* session, const char* sessionname)
142 {
143  if (session == NULL) {
144  return false;
145  }
146 
147  /* window */
148  if (session->gtk.embed){
149  session->gtk.window = gtk_plug_new(session->gtk.embed);
150  } else {
151  session->gtk.window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
152  }
153 
154  if (sessionname != NULL) {
155  gtk_widget_set_name(GTK_WIDGET(session->gtk.window), sessionname);
156  }
157 
158  GdkGeometry hints = {
159  .base_height = 1,
160  .base_width = 1,
161  .height_inc = 0,
162  .max_aspect = 0,
163  .max_height = 0,
164  .max_width = 0,
165  .min_aspect = 0,
166  .min_height = 0,
167  .min_width = 0,
168  .width_inc = 0
169  };
170 
171  gtk_window_set_geometry_hints(GTK_WINDOW(session->gtk.window), NULL, &hints, GDK_HINT_MIN_SIZE);
172 
173 #if (GTK_MAJOR_VERSION == 3)
174  gtk_window_set_has_resize_grip(GTK_WINDOW(session->gtk.window), FALSE);
175 #endif
176 
177 #if (GTK_MAJOR_VERSION == 3)
178  gtk_widget_override_background_color(GTK_WIDGET(session->gtk.window), GTK_STATE_NORMAL, &(session->style.default_background));
179 #else
180  gtk_widget_modify_bg(GTK_WIDGET(session->gtk.window), GTK_STATE_NORMAL, &(session->style.default_background));
181 #endif
182 
183  /* view */
184  session->signals.view_key_pressed = g_signal_connect(G_OBJECT(session->gtk.view), "key-press-event",
185  G_CALLBACK(girara_callback_view_key_press_event), session);
186 
187  session->signals.view_button_press_event = g_signal_connect(G_OBJECT(session->gtk.view), "button-press-event",
188  G_CALLBACK(girara_callback_view_button_press_event), session);
189 
190  session->signals.view_button_release_event = g_signal_connect(G_OBJECT(session->gtk.view), "button-release-event",
191  G_CALLBACK(girara_callback_view_button_release_event), session);
192 
193  session->signals.view_motion_notify_event = g_signal_connect(G_OBJECT(session->gtk.view), "motion-notify-event",
195 
196  session->signals.view_scroll_event = g_signal_connect(G_OBJECT(session->gtk.view), "scroll-event",
197  G_CALLBACK(girara_callback_view_scroll_event), session);
198 
199  bool show_hscrollbar = false;
200  bool show_vscrollbar = false;
201 
202  girara_setting_get(session, "show-h-scrollbar", &show_hscrollbar);
203  girara_setting_get(session, "show-v-scrollbar", &show_vscrollbar);
204 
205 #if (GTK_MAJOR_VERSION == 3)
206  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(session->gtk.view), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
207 
208  GtkWidget *vscrollbar = gtk_scrolled_window_get_vscrollbar(GTK_SCROLLED_WINDOW(session->gtk.view));
209  GtkWidget *hscrollbar = gtk_scrolled_window_get_hscrollbar(GTK_SCROLLED_WINDOW(session->gtk.view));
210 
211  if (vscrollbar != NULL) {
212  gtk_widget_set_visible(GTK_WIDGET(vscrollbar), show_vscrollbar);
213  }
214 
215  if (hscrollbar != NULL) {
216  gtk_widget_set_visible(GTK_WIDGET(hscrollbar), show_hscrollbar);
217  }
218 #else
219  GtkPolicyType h_policy, v_policy;
220  h_policy = show_hscrollbar ? GTK_POLICY_AUTOMATIC : GTK_POLICY_NEVER;
221  v_policy = show_vscrollbar ? GTK_POLICY_AUTOMATIC : GTK_POLICY_NEVER;
222  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(session->gtk.view), h_policy, v_policy);
223 #endif
224 
225  /* viewport */
226  gtk_container_add(GTK_CONTAINER(session->gtk.view), session->gtk.viewport);
227  gtk_viewport_set_shadow_type(GTK_VIEWPORT(session->gtk.viewport), GTK_SHADOW_NONE);
228 
229 #if (GTK_MAJOR_VERSION == 3)
230  gtk_widget_override_background_color(GTK_WIDGET(session->gtk.viewport), GTK_STATE_NORMAL, &(session->style.default_background));
231 #else
232  gtk_widget_modify_bg(GTK_WIDGET(session->gtk.viewport), GTK_STATE_NORMAL, &(session->style.default_background));
233 #endif
234 
235  /* statusbar */
236  gtk_container_add(GTK_CONTAINER(session->gtk.statusbar), GTK_WIDGET(session->gtk.statusbar_entries));
237 
238  /* notification area */
239  gtk_container_add(GTK_CONTAINER(session->gtk.notification_area), GTK_WIDGET(session->gtk.notification_text));
240  gtk_misc_set_alignment(GTK_MISC(session->gtk.notification_text), 0.0, 0.5);
241  gtk_label_set_use_markup(GTK_LABEL(session->gtk.notification_text), TRUE);
242 
243  /* inputbar */
244  gtk_entry_set_has_frame(session->gtk.inputbar_entry, FALSE);
245  gtk_editable_set_editable(GTK_EDITABLE(session->gtk.inputbar_entry), TRUE);
246 
247  /* we want inputbar_entry the same height as notification_text and statusbar,
248  so that when inputbar_entry is hidden, the size of the bottom_box remains
249  the same. We need to get rid of the builtin padding in the GtkEntry
250  widget. */
251 
252  guint ypadding = 2; /* total amount of padding (top + bottom) */
253  guint xpadding = 8; /* total amount of padding (left + right) */
254  girara_setting_get(session, "statusbar-h-padding", &xpadding);
255  girara_setting_get(session, "statusbar-v-padding", &ypadding);
256 
257 #if (GTK_MAJOR_VERSION == 3)
258  /* gtk_entry_set_inner_border is deprecated since gtk 3.4 and does nothing. */
259  GtkCssProvider* provider = gtk_css_provider_new();
260 
261  static const char CSS_PATTERN[] = "#bottom_box { border-style: none; margin: 0px 0px 0px 0px; padding:%dpx %dpx %dpx %dpx; }";
262  char* css = g_strdup_printf(CSS_PATTERN, ypadding - ypadding/2, xpadding/2, ypadding/2, xpadding - xpadding/2);
263  gtk_css_provider_load_from_data(provider, css, strlen(css), NULL);
264  g_free(css);
265 
266  GdkDisplay* display = gdk_display_get_default();
267  GdkScreen* screen = gdk_display_get_default_screen(display);
268  gtk_style_context_add_provider_for_screen(screen,
269  GTK_STYLE_PROVIDER(provider),
270  GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
271  g_object_unref(provider);
272 
273  gtk_widget_set_name(GTK_WIDGET(session->gtk.inputbar_entry), "bottom_box");
274  gtk_widget_set_name(GTK_WIDGET(session->gtk.notification_text), "bottom_box");
275 #else
276  GtkBorder inner_border = {
277  .left = xpadding - xpadding/2,
278  .right = xpadding/2,
279  .top = ypadding - ypadding/2,
280  .bottom = ypadding/2
281  };
282 
283  /* set inner borders for inputbar and notification_text */
284  gtk_entry_set_inner_border(session->gtk.inputbar_entry, &inner_border);
285  gtk_misc_set_padding(GTK_MISC(session->gtk.notification_text), xpadding/2, ypadding/2);
286 #endif
287 
288  session->signals.inputbar_key_pressed = g_signal_connect(
289  G_OBJECT(session->gtk.inputbar_entry),
290  "key-press-event",
292  session
293  );
294 
295  session->signals.inputbar_changed = g_signal_connect(
296  G_OBJECT(session->gtk.inputbar_entry),
297  "changed",
299  session
300  );
301 
302  session->signals.inputbar_activate = g_signal_connect(
303  G_OBJECT(session->gtk.inputbar_entry),
304  "activate",
306  session
307  );
308 
309  gtk_box_set_homogeneous(session->gtk.inputbar_box, FALSE);
310  gtk_box_set_spacing(session->gtk.inputbar_box, 5);
311 
312  /* inputbar box */
313  gtk_box_pack_start(GTK_BOX(session->gtk.inputbar_box), GTK_WIDGET(session->gtk.inputbar_dialog), FALSE, FALSE, 0);
314  gtk_box_pack_start(GTK_BOX(session->gtk.inputbar_box), GTK_WIDGET(session->gtk.inputbar_entry), TRUE, TRUE, 0);
315  gtk_container_add(GTK_CONTAINER(session->gtk.inputbar), GTK_WIDGET(session->gtk.inputbar_box));
316 
317  /* bottom box */
318  gtk_box_set_spacing(session->private_data->gtk.bottom_box, 0);
319 
320  gtk_box_pack_end(GTK_BOX(session->private_data->gtk.bottom_box), GTK_WIDGET(session->gtk.inputbar), TRUE, TRUE, 0);
321  gtk_box_pack_end(GTK_BOX(session->private_data->gtk.bottom_box), GTK_WIDGET(session->gtk.notification_area), TRUE, TRUE, 0);
322  gtk_box_pack_end(GTK_BOX(session->private_data->gtk.bottom_box), GTK_WIDGET(session->gtk.statusbar), TRUE, TRUE, 0);
323 
324  /* tabs */
325  gtk_notebook_set_show_border(session->gtk.tabs, FALSE);
326  gtk_notebook_set_show_tabs(session->gtk.tabs, FALSE);
327 
328 #if (GTK_MAJOR_VERSION == 3)
329  /* packing */
330  gtk_box_set_spacing(session->gtk.box, 0);
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 
334  /* box */
335  gtk_container_add(GTK_CONTAINER(session->private_data->gtk.overlay), GTK_WIDGET(session->gtk.box));
336  /* overlay */
337  g_object_set(session->private_data->gtk.bottom_box, "halign", GTK_ALIGN_FILL, NULL);
338  g_object_set(session->private_data->gtk.bottom_box, "valign", GTK_ALIGN_END, NULL);
339 
340  gtk_overlay_add_overlay(GTK_OVERLAY(session->private_data->gtk.overlay), GTK_WIDGET(session->private_data->gtk.bottom_box));
341  gtk_container_add(GTK_CONTAINER(session->gtk.window), GTK_WIDGET(session->private_data->gtk.overlay));
342 
343 #else
344  /* packing */
345  gtk_box_set_spacing(session->gtk.box, 0);
346  gtk_box_pack_start(session->gtk.box, GTK_WIDGET(session->gtk.tabbar), FALSE, FALSE, 0);
347  gtk_box_pack_start(session->gtk.box, GTK_WIDGET(session->gtk.view), TRUE, TRUE, 0);
348  gtk_box_pack_end(session->gtk.box, GTK_WIDGET(session->private_data->gtk.bottom_box), FALSE, FALSE, 0);
349 
350  /* box */
351  gtk_container_add(GTK_CONTAINER(session->gtk.window), GTK_WIDGET(session->gtk.box));
352 #endif
353 
354  /* parse color values */
355  typedef struct color_setting_mapping_s
356  {
357  char* identifier;
358  GdkRGBA *color;
359  } color_setting_mapping_t;
360 
361  const color_setting_mapping_t color_setting_mappings[] = {
362  {"default-fg", &(session->style.default_foreground)},
363  {"default-bg", &(session->style.default_background)},
364  {"inputbar-fg", &(session->style.inputbar_foreground)},
365  {"inputbar-bg", &(session->style.inputbar_background)},
366  {"statusbar-fg", &(session->style.statusbar_foreground)},
367  {"statusbar-bg", &(session->style.statusbar_background)},
368  {"completion-fg", &(session->style.completion_foreground)},
369  {"completion-bg", &(session->style.completion_background)},
370  {"completion-group-fg", &(session->style.completion_group_foreground)},
371  {"completion-group-bg", &(session->style.completion_group_background)},
372  {"completion-highlight-fg", &(session->style.completion_highlight_foreground)},
373  {"completion-highlight-bg", &(session->style.completion_highlight_background)},
374  {"notification-error-fg", &(session->style.notification_error_foreground)},
375  {"notification-error-bg", &(session->style.notification_error_background)},
376  {"notification-warning-fg", &(session->style.notification_warning_foreground)},
377  {"notification-warning-bg", &(session->style.notification_warning_background)},
378  {"notification-fg", &(session->style.notification_default_foreground)},
379  {"notification-bg", &(session->style.notification_default_background)},
380  {"tabbar-fg", &(session->style.tabbar_foreground)},
381  {"tabbar-bg", &(session->style.tabbar_background)},
382  {"tabbar-focus-fg", &(session->style.tabbar_focus_foreground)},
383  {"tabbar-focus-bg", &(session->style.tabbar_focus_background)},
384  };
385 
386  for (size_t i = 0; i < LENGTH(color_setting_mappings); i++) {
387  char* tmp_value = NULL;
388  girara_setting_get(session, color_setting_mappings[i].identifier, &tmp_value);
389  if (tmp_value != NULL) {
390  gdk_rgba_parse(color_setting_mappings[i].color, tmp_value);
391  g_free(tmp_value);
392  }
393  }
394 
395  /* view */
396  gtk_widget_override_background_color(GTK_WIDGET(session->gtk.viewport),
397  GTK_STATE_NORMAL, &(session->style.default_background));
398 
399  /* statusbar */
400  gtk_widget_override_background_color(GTK_WIDGET(session->gtk.statusbar),
401  GTK_STATE_NORMAL, &(session->style.statusbar_background));
402 
403  /* inputbar */
404 #if (GTK_MAJOR_VERSION == 3)
405  gtk_widget_override_background_color(GTK_WIDGET(session->gtk.inputbar_entry),
406  GTK_STATE_NORMAL, &(session->style.inputbar_background));
407  gtk_widget_override_color(GTK_WIDGET(session->gtk.inputbar_entry),
408  GTK_STATE_NORMAL, &(session->style.inputbar_foreground));
409 
410  gtk_widget_override_background_color(GTK_WIDGET(session->gtk.inputbar),
411  GTK_STATE_NORMAL, &(session->style.inputbar_background));
412  gtk_widget_override_color(GTK_WIDGET(session->gtk.inputbar_dialog),
413  GTK_STATE_NORMAL, &(session->style.inputbar_foreground));
414 
415  /* notification area */
416  gtk_widget_override_background_color(GTK_WIDGET(session->gtk.notification_area),
417  GTK_STATE_NORMAL, &(session->style.notification_default_background));
418  gtk_widget_override_color(GTK_WIDGET(session->gtk.notification_text),
419  GTK_STATE_NORMAL, &(session->style.notification_default_foreground));
420 #else
421  /* inputbar */
422  gtk_widget_modify_base(GTK_WIDGET(session->gtk.inputbar_entry), GTK_STATE_NORMAL, &(session->style.inputbar_background));
423  gtk_widget_modify_text(GTK_WIDGET(session->gtk.inputbar_entry), GTK_STATE_NORMAL, &(session->style.inputbar_foreground));
424 
425  gtk_widget_modify_bg(GTK_WIDGET(session->gtk.inputbar), GTK_STATE_NORMAL, &(session->style.inputbar_background));
426  gtk_widget_modify_fg(GTK_WIDGET(session->gtk.inputbar_dialog), GTK_STATE_NORMAL, &(session->style.inputbar_foreground));
427 
428  /* notification area */
429  gtk_widget_modify_bg(GTK_WIDGET(session->gtk.notification_area),
430  GTK_STATE_NORMAL, &(session->style.notification_default_background));
431  gtk_widget_modify_text(GTK_WIDGET(session->gtk.notification_text),
432  GTK_STATE_NORMAL, &(session->style.notification_default_foreground));
433 #endif
434 
435  if (session->style.font == NULL) {
436  /* set default font */
437  girara_setting_set(session, "font", "monospace normal 9");
438  } else {
439  gtk_widget_override_font(GTK_WIDGET(session->gtk.inputbar_entry), session->style.font);
440  gtk_widget_override_font(GTK_WIDGET(session->gtk.inputbar_dialog), session->style.font);
441  gtk_widget_override_font(GTK_WIDGET(session->gtk.notification_text), session->style.font);
442  }
443 
444  /* set window size */
445  int window_width = 0;
446  int window_height = 0;
447  girara_setting_get(session, "window-width", &window_width);
448  girara_setting_get(session, "window-height", &window_height);
449 
450  if (window_width > 0 && window_height > 0) {
451  gtk_window_set_default_size(GTK_WINDOW(session->gtk.window), window_width, window_height);
452  }
453 
454  gtk_widget_show_all(GTK_WIDGET(session->gtk.window));
455  gtk_widget_hide(GTK_WIDGET(session->gtk.notification_area));
456  gtk_widget_hide(GTK_WIDGET(session->gtk.inputbar_dialog));
457 
458  if (session->global.autohide_inputbar == true) {
459  gtk_widget_hide(GTK_WIDGET(session->gtk.inputbar));
460  }
461 
462  if (session->global.hide_statusbar == true) {
463  gtk_widget_hide(GTK_WIDGET(session->gtk.statusbar));
464  }
465 
466  char* window_icon = NULL;
467  girara_setting_get(session, "window-icon", &window_icon);
468  if (window_icon != NULL) {
469  if (strlen(window_icon) != 0) {
470  girara_setting_set(session, "window-icon", window_icon);
471  }
472  g_free(window_icon);
473  }
474 
475  gtk_widget_grab_focus(GTK_WIDGET(session->gtk.view));
476 
477  return true;
478 }
479 
480 static void
481 girara_session_private_free(girara_session_private_t* session)
482 {
483  g_return_if_fail(session != NULL);
484 
485  /* clean up settings */
486  girara_list_free(session->settings);
487  session->settings = NULL;
488 
489  g_slice_free(girara_session_private_t, session);
490 }
491 
492 bool
493 girara_session_destroy(girara_session_t* session)
494 {
495  g_return_val_if_fail(session != NULL, FALSE);
496 
497  /* clean up style */
498  if (session->style.font) {
499  pango_font_description_free(session->style.font);
500  }
501 
502  /* clean up shortcuts */
503  girara_list_free(session->bindings.shortcuts);
504  session->bindings.shortcuts = NULL;
505 
506  /* clean up inputbar shortcuts */
507  girara_list_free(session->bindings.inputbar_shortcuts);
508  session->bindings.inputbar_shortcuts = NULL;
509 
510  /* clean up commands */
511  girara_list_free(session->bindings.commands);
512  session->bindings.commands = NULL;
513 
514  /* clean up special commands */
515  girara_list_free(session->bindings.special_commands);
516  session->bindings.special_commands = NULL;
517 
518  /* clean up mouse events */
519  girara_list_free(session->bindings.mouse_events);
520  session->bindings.mouse_events = NULL;
521 
522  /* clean up input histry */
523  g_object_unref(session->command_history);
524  session->command_history = NULL;
525 
526  /* clean up statusbar items */
527  girara_list_free(session->elements.statusbar_items);
528  session->elements.statusbar_items = NULL;
529 
530  /* clean up config handles */
531  girara_list_free(session->config.handles);
532  session->config.handles = NULL;
533 
534  /* clean up shortcut mappings */
535  girara_list_free(session->config.shortcut_mappings);
536  session->config.shortcut_mappings = NULL;
537 
538  /* clean up argument mappings */
539  girara_list_free(session->config.argument_mappings);
540  session->config.argument_mappings = NULL;
541 
542  /* clean up modes */
543  girara_list_free(session->modes.identifiers);
544  session->modes.identifiers = NULL;
545 
546  /* clean up buffer */
547  if (session->buffer.command) {
548  g_string_free(session->buffer.command, TRUE);
549  }
550 
551  if (session->global.buffer) {
552  g_string_free(session->global.buffer, TRUE);
553  }
554 
555  session->buffer.command = NULL;
556  session->global.buffer = NULL;
557 
558  /* clean up private data */
559  girara_session_private_free(session->private_data);
560  session->private_data = NULL;
562  session->settings = NULL;
563  UNIGNORE
564 
565  /* clean up session */
566  g_slice_free(girara_session_t, session);
567 
568  return TRUE;
569 }
570 
571 char*
572 girara_buffer_get(girara_session_t* session)
573 {
574  g_return_val_if_fail(session != NULL, NULL);
575 
576  return (session->global.buffer) ? g_strdup(session->global.buffer->str) : NULL;
577 }
578 
579 void
580 girara_notify(girara_session_t* session, int level, const char* format, ...)
581 {
582  if (session == NULL
583  || session->gtk.notification_text == NULL
584  || session->gtk.notification_area == NULL
585  || session->gtk.inputbar == NULL
586  || session->gtk.view == NULL) {
587  return;
588  }
589 
590  const GdkRGBA* foreground = NULL;
591  const GdkRGBA* background = NULL;
592  switch (level) {
593  case GIRARA_ERROR:
594  foreground = &session->style.notification_error_foreground;
595  background = &session->style.notification_error_background;
596  break;
597  case GIRARA_WARNING:
598  foreground = &session->style.notification_warning_foreground;
599  background = &session->style.notification_warning_background;
600  break;
601  case GIRARA_INFO:
602  foreground = &session->style.notification_default_foreground;
603  background = &session->style.notification_default_background;
604  break;
605  default:
606  return;
607  }
608 
609  gtk_widget_override_background_color(GTK_WIDGET(session->gtk.notification_area),
610  GTK_STATE_NORMAL, background);
611  gtk_widget_override_background_color(GTK_WIDGET(session->gtk.notification_text),
612  GTK_STATE_NORMAL, background);
613  gtk_widget_override_color(GTK_WIDGET(session->gtk.notification_area),
614  GTK_STATE_NORMAL, foreground);
615  gtk_widget_override_color(GTK_WIDGET(session->gtk.notification_text),
616  GTK_STATE_NORMAL, foreground);
617 
618  /* prepare message */
619  va_list ap;
620  va_start(ap, format);
621  char* message = g_strdup_vprintf(format, ap);
622  va_end(ap);
623 
624  gtk_label_set_markup(GTK_LABEL(session->gtk.notification_text), message);
625  g_free(message);
626 
627  /* update visibility */
628  gtk_widget_show(GTK_WIDGET(session->gtk.notification_area));
629  gtk_widget_hide(GTK_WIDGET(session->gtk.inputbar));
630 
631  gtk_widget_grab_focus(GTK_WIDGET(session->gtk.view));
632 }
633 
634 void girara_dialog(girara_session_t* session, const char* dialog, bool
635  invisible, girara_callback_inputbar_key_press_event_t key_press_event,
636  girara_callback_inputbar_activate_t activate_event, void* data)
637 {
638  if (session == NULL || session->gtk.inputbar == NULL
639  || session->gtk.inputbar_dialog == NULL
640  || session->gtk.inputbar_entry == NULL) {
641  return;
642  }
643 
644  gtk_widget_show(GTK_WIDGET(session->gtk.inputbar_dialog));
645 
646  /* set dialog message */
647  if (dialog != NULL) {
648  gtk_label_set_markup(session->gtk.inputbar_dialog, dialog);
649  }
650 
651  /* set input visibility */
652  if (invisible == true) {
653  gtk_entry_set_visibility(session->gtk.inputbar_entry, FALSE);
654  } else {
655  gtk_entry_set_visibility(session->gtk.inputbar_entry, TRUE);
656  }
657 
658  /* set handler */
659  session->signals.inputbar_custom_activate = activate_event;
660  session->signals.inputbar_custom_key_press_event = key_press_event;
661  session->signals.inputbar_custom_data = data;
662 
663  /* focus inputbar */
664  girara_sc_focus_inputbar(session, NULL, NULL, 0);
665 }
666 
667 bool
668 girara_set_view(girara_session_t* session, GtkWidget* widget)
669 {
670  g_return_val_if_fail(session != NULL, false);
671 
672  GtkWidget* child = gtk_bin_get_child(GTK_BIN(session->gtk.viewport));
673 
674  if (child) {
675  g_object_ref(child);
676  gtk_container_remove(GTK_CONTAINER(session->gtk.viewport), child);
677  }
678 
679  gtk_container_add(GTK_CONTAINER(session->gtk.viewport), widget);
680  gtk_widget_show_all(widget);
681 
682  return true;
683 }
684 
685 void
686 girara_mode_set(girara_session_t* session, girara_mode_t mode)
687 {
688  g_return_if_fail(session != NULL);
689 
690  session->modes.current_mode = mode;
691 }
692 
694 girara_mode_add(girara_session_t* session, const char* name)
695 {
696  g_return_val_if_fail(session != NULL, FALSE);
697  g_return_val_if_fail(name != NULL && name[0] != 0x0, FALSE);
698 
699  girara_mode_t last_index = 0;
700  GIRARA_LIST_FOREACH(session->modes.identifiers, girara_mode_string_t*, iter, mode)
701  if (mode->index > last_index) {
702  last_index = mode->index;
703  }
704  GIRARA_LIST_FOREACH_END(session->modes.identifiers, girara_mode_string_t*, iter, mode);
705 
706  /* create new mode identifier */
707  girara_mode_string_t* mode = g_slice_new(girara_mode_string_t);
708  mode->index = last_index + 1;
709  mode->name = g_strdup(name);
710  girara_list_append(session->modes.identifiers, mode);
711 
712  return mode->index;
713 }
714 
715 void
716 girara_mode_string_free(girara_mode_string_t* mode)
717 {
718  if (mode == NULL) {
719  return;
720  }
721 
722  g_free(mode->name);
723  g_slice_free(girara_mode_string_t, mode);
724 }
725 
727 girara_mode_get(girara_session_t* session)
728 {
729  g_return_val_if_fail(session != NULL, 0);
730 
731  return session->modes.current_mode;
732 }
733 
734 bool
735 girara_set_window_title(girara_session_t* session, const char* name)
736 {
737  if (session == NULL || session->gtk.window == NULL || name == NULL) {
738  return false;
739  }
740 
741  gtk_window_set_title(GTK_WINDOW(session->gtk.window), name);
742 
743  return true;
744 }
745 
746 girara_list_t*
747 girara_get_command_history(girara_session_t* session)
748 {
749  g_return_val_if_fail(session != NULL, NULL);
750  return girara_input_history_list(session->command_history);
751 }
#define UNIGNORE
Definition: session.c:30
void girara_config_handle_free(girara_config_handle_t *handle)
Definition: config.c:319
int girara_mode_t
Definition: types.h:69
void girara_special_command_free(girara_special_command_t *special_command)
Definition: commands.c:598
#define LENGTH(x)
Definition: internal.h:18
bool girara_callback_view_button_motion_notify_event(GtkWidget *widget, GdkEventMotion *button, girara_session_t *session)
HIDDEN void girara_setting_free(girara_setting_t *setting)
Definition: settings.c:153
bool girara_session_init(girara_session_t *session, const char *sessionname)
Definition: session.c:141
bool girara_set_window_title(girara_session_t *session, const char *name)
Definition: session.c:735
void girara_list_append(girara_list_t *list, void *data)
HIDDEN void girara_argument_mapping_free(girara_argument_mapping_t *argument_mapping)
Definition: shortcuts.c:674
girara_session_t * session
Definition: tabs.c:263
void(* girara_free_function_t)(void *data)
Definition: types.h:118
bool girara_session_destroy(girara_session_t *session)
Definition: session.c:493
girara_list_t * girara_list_new2(girara_free_function_t gfree)
bool girara_callback_inputbar_changed_event(GtkEditable *entry, girara_session_t *session)
Definition: callbacks.c:557
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:283
HIDDEN void girara_statusbar_item_free(girara_statusbar_item_t *statusbaritem)
Definition: statusbar.c:62
bool girara_callback_view_key_press_event(GtkWidget *UNUSED(widget), GdkEventKey *event, girara_session_t *session)
Definition: callbacks.c:79
void girara_list_free(girara_list_t *list)
void girara_dialog(girara_session_t *session, const char *dialog, bool invisible, girara_callback_inputbar_key_press_event_t key_press_event, girara_callback_inputbar_activate_t activate_event, void *data)
Definition: session.c:634
bool girara_callback_inputbar_key_press_event(GtkWidget *entry, GdkEventKey *event, girara_session_t *session)
Definition: callbacks.c:506
girara_mode_t girara_mode_add(girara_session_t *session, const char *name)
Definition: session.c:694
HIDDEN void girara_inputbar_shortcut_free(girara_inputbar_shortcut_t *shortcut)
Definition: shortcuts.c:145
int(* girara_compare_function_t)(const void *data1, const void *data2)
Definition: types.h:134
void girara_config_load_default(girara_session_t *session)
Definition: config.c:184
bool(* girara_callback_inputbar_key_press_event_t)(GtkWidget *widget, GdkEventKey *event, void *data)
Definition: callbacks.h:17
bool girara_set_view(girara_session_t *session, GtkWidget *widget)
Definition: session.c:668
bool(* girara_callback_inputbar_activate_t)(GtkEntry *entry, void *data)
Definition: callbacks.h:27
HIDDEN void girara_mouse_event_free(girara_mouse_event_t *mouse_event)
Definition: shortcuts.c:740
HIDDEN void girara_shortcut_mapping_free(girara_shortcut_mapping_t *mapping)
Definition: shortcuts.c:636
bool girara_callback_view_scroll_event(GtkWidget *widget, GdkEventScroll *event, girara_session_t *session)
GIRARA_LIST_FOREACH_END(session->bindings.mouse_events, girara_mouse_event_t *, iter, mouse_event)
bool girara_setting_get(girara_session_t *session, const char *name, void *dest)
Definition: settings.c:140
girara_list_t * girara_sorted_list_new2(girara_compare_function_t cmp, girara_free_function_t gfree)
girara_list_t * girara_input_history_list(GiraraInputHistory *history)
g_return_val_if_fail(button!=NULL, false)
void girara_notify(girara_session_t *session, int level, const char *format,...)
Definition: session.c:580
void girara_command_free(girara_command_t *command)
Definition: commands.c:607
bool girara_callback_inputbar_activate(GtkEntry *entry, girara_session_t *session)
Definition: callbacks.c:363
#define IGNORE_DEPRECATED
Definition: session.c:27
bool girara_setting_set(girara_session_t *session, const char *name, void *value)
Definition: settings.c:95
GiraraInputHistory * girara_input_history_new(GiraraInputHistoryIO *io)
HIDDEN void girara_mode_string_free(girara_mode_string_t *mode)
Definition: session.c:716
const char * girara_setting_get_name(girara_setting_t *setting)
Definition: settings.c:185
void girara_mode_set(girara_session_t *session, girara_mode_t mode)
Definition: session.c:686
bool girara_callback_view_button_release_event(GtkWidget *widget, GdkEventButton *button, girara_session_t *session)
girara_session_t * girara_session_create()
Definition: session.c:51
bool girara_callback_view_button_press_event(GtkWidget *UNUSED(widget), GdkEventButton *button, girara_session_t *session)
Definition: callbacks.c:208
#define GIRARA_LIST_FOREACH(list, type, iter, data)
girara_list_t * girara_get_command_history(girara_session_t *session)
Definition: session.c:747
char * girara_buffer_get(girara_session_t *session)
Definition: session.c:572
girara_mode_t girara_mode_get(girara_session_t *session)
Definition: session.c:727
HIDDEN void girara_shortcut_free(girara_shortcut_t *shortcut)
Definition: shortcuts.c:89