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