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