1 /*
2 * views.c
3 *
4 * Copyright 2012 Dimitar Toshkov Zhekov <dimitar.zhekov@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #ifdef HAVE_CONFIG_H
21 # include "config.h"
22 #endif
23
24 #include <ctype.h>
25 #include <string.h>
26 #include <gdk/gdkkeysyms.h>
27
28 #include "common.h"
29
30 typedef enum _ViewContext
31 {
32 VC_NONE,
33 VC_DATA,
34 VC_FRAME
35 } ViewContext;
36
37 typedef struct _ViewInfo
38 {
39 gboolean dirty;
40 ViewContext context;
41 void (*clear)(void);
42 gboolean (*update)(void);
43 gboolean flush;
44 DebugState state;
45 } ViewInfo;
46
47 static ViewInfo views[VIEW_COUNT] =
48 {
49 { FALSE, VC_NONE, NULL, NULL, FALSE, 0 },
50 { FALSE, VC_NONE, threads_clear, threads_update, FALSE, DS_SENDABLE },
51 { FALSE, VC_NONE, breaks_clear, breaks_update, FALSE, DS_SENDABLE },
52 { FALSE, VC_DATA, stack_clear, stack_update, TRUE, DS_DEBUG },
53 { FALSE, VC_FRAME, locals_clear, locals_update, TRUE, DS_DEBUG },
54 { FALSE, VC_FRAME, watches_clear, watches_update, FALSE, DS_VARIABLE },
55 { FALSE, VC_DATA, memory_clear, memory_update, FALSE, DS_VARIABLE },
56 { FALSE, VC_NONE, NULL, dc_update, FALSE, DS_DEBUG },
57 { FALSE, VC_FRAME, inspects_clear, inspects_update, FALSE, DS_VARIABLE },
58 { FALSE, VC_FRAME, registers_clear, registers_update, TRUE, DS_DEBUG },
59 { FALSE, VC_DATA, tooltip_clear, tooltip_update, FALSE, DS_SENDABLE },
60 { FALSE, VC_NONE, menu_clear, NULL, FALSE, 0 }
61 };
62
view_update_dirty(ViewIndex index,DebugState state)63 static void view_update_dirty(ViewIndex index, DebugState state)
64 {
65 ViewInfo *view = views + index;
66
67 if (view->state & state)
68 {
69 if (view->update())
70 view->dirty = FALSE;
71 }
72 else if (view->flush)
73 {
74 view->clear();
75 view->dirty = FALSE;
76 }
77 }
78
view_update(ViewIndex index,DebugState state)79 static void view_update(ViewIndex index, DebugState state)
80 {
81 if (views[index].dirty)
82 view_update_dirty(index, state);
83 }
84
85 static GtkNotebook *geany_sidebar;
86 static GtkWidget *inspect_page;
87 static GtkWidget *register_page;
88
views_sidebar_update(gint page_num,DebugState state)89 static void views_sidebar_update(gint page_num, DebugState state)
90 {
91 GtkWidget *page = gtk_notebook_get_nth_page(geany_sidebar, page_num);
92
93 if (page == inspect_page)
94 view_update(VIEW_INSPECT, state);
95 else if (page == register_page)
96 view_update(VIEW_REGISTERS, state);
97 }
98
view_dirty(ViewIndex index)99 void view_dirty(ViewIndex index)
100 {
101 views[index].dirty = TRUE;
102 }
103
views_context_dirty(DebugState state,gboolean frame_only)104 void views_context_dirty(DebugState state, gboolean frame_only)
105 {
106 ViewIndex i;
107
108 for (i = 0; i < VIEW_COUNT; i++)
109 if (views[i].context >= (frame_only ? VC_FRAME : VC_DATA))
110 view_dirty(i);
111
112 if (state != DS_BUSY)
113 {
114 if (option_update_all_views)
115 views_update(state);
116 else
117 views_sidebar_update(gtk_notebook_get_current_page(geany_sidebar), state);
118 }
119 }
120
121 #ifdef G_OS_UNIX
122 static ViewIndex view_current = VIEW_TERMINAL;
123 #else
124 static ViewIndex view_current = VIEW_THREADS;
125 #endif
126
views_clear(void)127 void views_clear(void)
128 {
129 ViewIndex i;
130 ViewInfo *view = views;
131
132 for (i = 0; i < VIEW_COUNT; i++, view++)
133 {
134 view->dirty = FALSE;
135
136 if (view->clear)
137 view->clear();
138 }
139 }
140
views_update(DebugState state)141 void views_update(DebugState state)
142 {
143 if (option_update_all_views)
144 {
145 ViewIndex i;
146 gboolean skip_frame = FALSE;
147
148 if (thread_state == THREAD_QUERY_FRAME)
149 {
150 if (!views[VIEW_THREADS].dirty)
151 thread_query_frame('4');
152
153 thread_state = THREAD_STOPPED;
154 }
155
156 for (i = 0; i < VIEW_COUNT; i++)
157 {
158 if (views[i].dirty && (!skip_frame || views[i].context != VC_FRAME))
159 {
160 view_update_dirty(i, state);
161
162 if (i == VIEW_STACK && thread_state >= THREAD_STOPPED)
163 skip_frame = TRUE;
164 }
165 }
166 }
167 else
168 {
169 if (thread_state == THREAD_QUERY_FRAME)
170 {
171 if (view_current != VIEW_THREADS || !views[VIEW_THREADS].dirty)
172 thread_query_frame('4');
173
174 thread_state = THREAD_STOPPED;
175 }
176
177 view_update(view_current, state);
178 view_update(VIEW_TOOLTIP, state);
179 views_sidebar_update(gtk_notebook_get_current_page(geany_sidebar), state);
180 }
181 }
182
view_stack_update(void)183 gboolean view_stack_update(void)
184 {
185 if (views[VIEW_STACK].dirty)
186 {
187 DebugState state = thread_state >= THREAD_STOPPED ? DS_DEBUG : DS_READY;
188 view_update_dirty(VIEW_STACK, state);
189 return state == DS_DEBUG;
190 }
191
192 return FALSE;
193 }
194
on_view_changed(G_GNUC_UNUSED GtkNotebook * notebook,G_GNUC_UNUSED gpointer page,gint page_num,G_GNUC_UNUSED gpointer gdata)195 void on_view_changed(G_GNUC_UNUSED GtkNotebook *notebook, G_GNUC_UNUSED gpointer page,
196 gint page_num, G_GNUC_UNUSED gpointer gdata)
197 {
198 view_current = page_num;
199 view_update(view_current, debug_state());
200 }
201
on_view_key_press(G_GNUC_UNUSED GtkWidget * widget,GdkEventKey * event,ViewSeeker seeker)202 gboolean on_view_key_press(G_GNUC_UNUSED GtkWidget *widget, GdkEventKey *event,
203 ViewSeeker seeker)
204 {
205 /* from msgwindow.c */
206 gboolean enter_or_return = ui_is_keyval_enter_or_return(event->keyval);
207
208 if (enter_or_return || event->keyval == GDK_space || event->keyval == GDK_KP_Space)
209 seeker(enter_or_return);
210
211 return FALSE;
212 }
213
on_view_button_1_press(GtkWidget * widget,GdkEventButton * event,ViewSeeker seeker)214 gboolean on_view_button_1_press(GtkWidget *widget, GdkEventButton *event, ViewSeeker seeker)
215 {
216 if (event->button == 1 && (pref_auto_view_source || event->type == GDK_2BUTTON_PRESS))
217 {
218 utils_handle_button_press(widget, event);
219 seeker(event->type == GDK_2BUTTON_PRESS);
220 return TRUE;
221 }
222
223 return FALSE;
224 }
225
on_view_query_base_tooltip(GtkWidget * widget,gint x,gint y,gboolean keyboard_tip,GtkTooltip * tooltip,GtkTreeViewColumn * base_name_column)226 gboolean on_view_query_base_tooltip(GtkWidget *widget, gint x, gint y, gboolean keyboard_tip,
227 GtkTooltip *tooltip, GtkTreeViewColumn *base_name_column)
228 {
229 GtkTreeView *tree = GTK_TREE_VIEW(widget);
230 GtkTreeIter iter;
231
232 if (gtk_tree_view_get_tooltip_context(tree, &x, &y, keyboard_tip, NULL, NULL, &iter))
233 {
234 const char *file;
235
236 gtk_tree_view_set_tooltip_cell(tree, tooltip, NULL, base_name_column, NULL);
237 scp_tree_store_get((ScpTreeStore *) gtk_tree_view_get_model(tree), &iter,
238 COLUMN_FILE, &file, -1);
239
240 if (file)
241 {
242 gchar *utf8 = utils_get_utf8_from_locale(file);
243
244 gtk_tooltip_set_text(tooltip, utf8);
245 g_free(utf8);
246 return TRUE;
247 }
248 }
249
250 return FALSE;
251 }
252
on_view_editable_map(GtkWidget * widget,gchar * replace)253 gboolean on_view_editable_map(GtkWidget *widget, gchar *replace)
254 {
255 iff (GTK_IS_EDITABLE(widget), "cell editable: not an editable")
256 {
257 gint position = 0;
258 GtkEditable *editable = GTK_EDITABLE(widget);
259
260 gtk_editable_delete_text(editable, 0, -1);
261 gtk_editable_insert_text(editable, replace ? replace : "", -1, &position);
262 gtk_editable_select_region(editable, -1, 0);
263 g_free(replace);
264 }
265
266 return FALSE;
267 }
268
view_create(const char * name,ScpTreeStore ** store,GtkTreeSelection ** selection)269 GtkTreeView *view_create(const char *name, ScpTreeStore **store, GtkTreeSelection **selection)
270 {
271 GtkTreeView *tree = GTK_TREE_VIEW(get_widget(name));
272
273 *store = SCP_TREE_STORE(gtk_tree_view_get_model(tree));
274 *selection = gtk_tree_view_get_selection(tree);
275 return tree;
276 }
277
on_editing_started(G_GNUC_UNUSED GtkCellRenderer * cell,GtkCellEditable * editable,G_GNUC_UNUSED const gchar * path,GtkAdjustment * hadjustment)278 static void on_editing_started(G_GNUC_UNUSED GtkCellRenderer *cell, GtkCellEditable *editable,
279 G_GNUC_UNUSED const gchar *path, GtkAdjustment *hadjustment)
280 {
281 if (GTK_IS_ENTRY(editable))
282 gtk_entry_set_cursor_hadjustment(GTK_ENTRY(editable), hadjustment);
283 }
284
on_display_editing_started(G_GNUC_UNUSED GtkCellRenderer * cell,GtkCellEditable * editable,const gchar * path_str,ScpTreeStore * store)285 static void on_display_editing_started(G_GNUC_UNUSED GtkCellRenderer *cell,
286 GtkCellEditable *editable, const gchar *path_str, ScpTreeStore *store)
287 {
288 GtkTreeIter iter;
289 const char *value;
290 gint hb_mode;
291
292 scp_tree_store_get_iter_from_string(store, &iter, path_str);
293 scp_tree_store_get(store, &iter, COLUMN_VALUE, &value, COLUMN_HB_MODE, &hb_mode, -1);
294 /* scrolling editable to the proper position is left as an exercise for the reader */
295 g_signal_connect(editable, "map", G_CALLBACK(on_view_editable_map),
296 parse_get_display_from_7bit(value, hb_mode, MR_EDITVC));
297 }
298
view_connect(const char * name,ScpTreeStore ** store,GtkTreeSelection ** selection,const TreeCell * cell_info,const char * window,GObject ** display_cell)299 GtkTreeView *view_connect(const char *name, ScpTreeStore **store, GtkTreeSelection **selection,
300 const TreeCell *cell_info, const char *window, GObject **display_cell)
301 {
302 guint i;
303 GtkScrolledWindow *scrolled = GTK_SCROLLED_WINDOW(get_widget(window));
304 GtkAdjustment *hadjustment = gtk_scrolled_window_get_hadjustment(scrolled);
305 GtkTreeView *tree = view_create(name, store, selection);
306
307 for (i = 0; cell_info->name; cell_info++, i++)
308 {
309 GtkCellRenderer *cell = GTK_CELL_RENDERER(get_object(cell_info->name));
310 const char *signame;
311 const char *property;
312
313 if (GTK_IS_CELL_RENDERER_TEXT(cell))
314 {
315 signame = "edited";
316 property = "editable";
317
318 g_signal_connect(cell, "editing-started", G_CALLBACK(on_editing_started),
319 hadjustment);
320
321 if (display_cell && i == 0)
322 {
323 g_signal_connect(cell, "editing-started",
324 G_CALLBACK(on_display_editing_started), *store);
325 *display_cell = G_OBJECT(cell);
326 }
327 }
328 else
329 {
330 g_assert(GTK_IS_CELL_RENDERER_TOGGLE(cell));
331 signame = "toggled";
332 property = "activatable";
333 }
334
335 g_signal_connect(cell, signame, cell_info->callback, GINT_TO_POINTER(i));
336 g_object_set(cell, property, TRUE, NULL);
337 }
338
339 return tree;
340 }
341
view_line_cell_data_func(G_GNUC_UNUSED GtkTreeViewColumn * column,GtkCellRenderer * cell,GtkTreeModel * model,GtkTreeIter * iter,gpointer gdata)342 static void view_line_cell_data_func(G_GNUC_UNUSED GtkTreeViewColumn *column,
343 GtkCellRenderer *cell, GtkTreeModel *model, GtkTreeIter *iter, gpointer gdata)
344 {
345 gint line;
346 gchar *s;
347
348 gtk_tree_model_get(model, iter, GPOINTER_TO_INT(gdata), &line, -1);
349 s = line ? g_strdup_printf("%d", line) : NULL;
350 g_object_set(cell, "text", s, NULL);
351 g_free(s);
352 }
353
view_set_line_data_func(const char * column,const char * cell,gint column_id)354 void view_set_line_data_func(const char *column, const char *cell, gint column_id)
355 {
356 gtk_tree_view_column_set_cell_data_func(get_column(column),
357 GTK_CELL_RENDERER(get_object(cell)), view_line_cell_data_func,
358 GINT_TO_POINTER(column_id), NULL);
359 }
360
view_display_edited(ScpTreeStore * store,gboolean condition,const gchar * path_str,const char * format,gchar * new_text)361 void view_display_edited(ScpTreeStore *store, gboolean condition, const gchar *path_str,
362 const char *format, gchar *new_text)
363 {
364 if (validate_column(new_text, TRUE))
365 {
366 if (condition)
367 {
368 GtkTreeIter iter;
369 const char *name;
370 gint hb_mode;
371 char *locale;
372
373 scp_tree_store_get_iter_from_string(store, &iter, path_str);
374 scp_tree_store_get(store, &iter, COLUMN_NAME, &name, COLUMN_HB_MODE,
375 &hb_mode, -1);
376 locale = utils_get_locale_from_display(new_text, hb_mode);
377 utils_strchrepl(locale, '\n', ' ');
378 debug_send_format(F, format, name, locale);
379 g_free(locale);
380 }
381 else
382 plugin_blink();
383 }
384 }
385
view_column_set_visible(const char * name,gboolean visible)386 void view_column_set_visible(const char *name, gboolean visible)
387 {
388 gtk_tree_view_column_set_visible(get_column(name), visible);
389 }
390
view_seek_selected(GtkTreeSelection * selection,gboolean focus,SeekerType seeker)391 void view_seek_selected(GtkTreeSelection *selection, gboolean focus, SeekerType seeker)
392 {
393 ScpTreeStore *store;
394 GtkTreeIter iter;
395
396 if (scp_tree_selection_get_selected(selection, &store, &iter))
397 {
398 const char *file;
399 gint line;
400
401 scp_tree_store_get(store, &iter, COLUMN_FILE, &file, COLUMN_LINE, &line, -1);
402
403 if (file)
404 utils_seek(file, line, focus, seeker);
405 }
406 }
407
408 enum
409 {
410 COMMAND_DISPLAY,
411 COMMAND_TEXT,
412 COMMAND_LOCALE
413 };
414
415 static GtkWidget *command_dialog;
416 static GtkWidget *command_view;
417 static GObject *command_cell;
418 static GtkTextBuffer *command_text;
419 static GtkComboBox *command_history;
420 static ScpTreeStore *command_store;
421 static GtkToggleButton *command_locale;
422 static GtkWidget *command_send;
423
on_command_text_changed(GtkTextBuffer * command_text,G_GNUC_UNUSED gpointer gdata)424 static void on_command_text_changed(GtkTextBuffer *command_text, G_GNUC_UNUSED gpointer gdata)
425 {
426 gchar *text = utils_text_buffer_get_text(command_text, -1);
427 const gchar *start = utils_skip_spaces(text);
428
429 gtk_widget_set_sensitive(command_send, *start != '0' || !isdigit(start[1]));
430 g_free(text);
431 }
432
on_command_dialog_configure(G_GNUC_UNUSED GtkWidget * widget,G_GNUC_UNUSED GdkEventButton * event,G_GNUC_UNUSED gpointer gdata)433 gboolean on_command_dialog_configure(G_GNUC_UNUSED GtkWidget *widget,
434 G_GNUC_UNUSED GdkEventButton *event, G_GNUC_UNUSED gpointer gdata)
435 {
436 gint width;
437
438 #if GTK_CHECK_VERSION(2, 24, 0)
439 width = gdk_window_get_width(gtk_widget_get_window(command_view));
440 #else
441 gint height;
442 gdk_drawable_get_size(GDK_DRAWABLE(command_view->window), &width, &height);
443 #endif
444 g_object_set(command_cell, "wrap-width", width, NULL);
445 return FALSE;
446 }
447
on_command_history_size_request(G_GNUC_UNUSED GtkWidget * widget,GtkRequisition * requisition,G_GNUC_UNUSED gpointer gdata)448 static void on_command_history_size_request(G_GNUC_UNUSED GtkWidget *widget,
449 GtkRequisition *requisition, G_GNUC_UNUSED gpointer gdata)
450 {
451 static gint empty_height;
452 GtkTreeIter iter;
453
454 if (scp_tree_store_get_iter_first(command_store, &iter))
455 requisition->height = empty_height;
456 else
457 empty_height = requisition->height;
458 }
459
on_command_history_changed(GtkComboBox * command_history,G_GNUC_UNUSED gpointer gdata)460 static void on_command_history_changed(GtkComboBox *command_history,
461 G_GNUC_UNUSED gpointer gdata)
462 {
463 GtkTreeIter iter;
464
465 if (gtk_combo_box_get_active_iter(command_history, &iter))
466 {
467 const gchar *text;
468 gboolean locale;
469
470 scp_tree_store_get(command_store, &iter, COMMAND_TEXT, &text, COMMAND_LOCALE,
471 &locale, -1);
472 gtk_text_buffer_set_text(command_text, text, -1);
473 gtk_toggle_button_set_active(command_locale, locale);
474 gtk_widget_grab_focus(command_view);
475 gtk_combo_box_set_active_iter(command_history, NULL);
476 }
477 }
478
on_command_insert_button_clicked(G_GNUC_UNUSED GtkButton * button,gpointer gdata)479 static void on_command_insert_button_clicked(G_GNUC_UNUSED GtkButton *button, gpointer gdata)
480 {
481 const char *prefix;
482 const char *id;
483 GString *text = g_string_new("--");
484
485 switch (GPOINTER_TO_INT(gdata))
486 {
487 case 't' : prefix = "thread"; id = thread_id; break;
488 case 'g' : prefix = "group"; id = thread_group_id(); break;
489 default : prefix = "frame"; id = frame_id;
490 }
491
492 g_string_append_printf(text, "%s ", prefix);
493 if (id)
494 g_string_append_printf(text, "%s ", id);
495
496 gtk_text_buffer_delete_selection(command_text, FALSE, TRUE);
497 gtk_text_buffer_insert_at_cursor(command_text, text->str, -1);
498 g_string_free(text, TRUE);
499 gtk_widget_grab_focus(command_view);
500 }
501
on_command_send_button_clicked(G_GNUC_UNUSED GtkButton * button,G_GNUC_UNUSED gpointer gdata)502 static void on_command_send_button_clicked(G_GNUC_UNUSED GtkButton *button,
503 G_GNUC_UNUSED gpointer gdata)
504 {
505 gchar *text = utils_text_buffer_get_text(command_text, -1);
506 const gchar *start;
507 char *locale;
508
509 thread_synchronize();
510 utils_strchrepl(text, '\n', ' ');
511 start = utils_skip_spaces(text);
512 locale = gtk_toggle_button_get_active(command_locale) ?
513 utils_get_locale_from_utf8(start) : g_strdup(start);
514 debug_send_command(N, locale);
515 g_free(locale);
516 gtk_text_buffer_set_text(command_text, "", -1);
517 gtk_widget_hide(command_dialog);
518
519 if (*start)
520 {
521 GtkTreePath *path;
522 GtkTreeIter iter;
523 gchar *display = g_strdup(start);
524
525 /* from ui_combo_box_add_to_history() */
526 if (store_find(command_store, &iter, COMMAND_TEXT, start))
527 scp_tree_store_remove(command_store, &iter);
528
529 if (strlen(display) >= 273)
530 strcpy(display + 270, _("\342\200\246")); /* For translators: ellipsis */
531
532 scp_tree_store_prepend(command_store, &iter, NULL);
533 scp_tree_store_set(command_store, &iter, COMMAND_DISPLAY, display, COMMAND_TEXT,
534 start, COMMAND_LOCALE, gtk_toggle_button_get_active(command_locale), -1);
535 g_free(display);
536
537 path = gtk_tree_path_new_from_indices(15, -1);
538 if (scp_tree_store_get_iter(command_store, &iter, path))
539 scp_tree_store_remove(command_store, &iter);
540 gtk_tree_path_free(path);
541 }
542
543 g_free(text);
544 }
545
command_line_update_state(DebugState state)546 static void command_line_update_state(DebugState state)
547 {
548 if (state == DS_INACTIVE)
549 gtk_widget_hide(command_dialog);
550 else
551 {
552 gtk_button_set_label(GTK_BUTTON(command_send),
553 state & DS_SENDABLE ? _("_Send") : _("_Busy"));
554 }
555 }
556
view_command_line(const gchar * text,const gchar * title,const gchar * seek,gboolean seek_after)557 void view_command_line(const gchar *text, const gchar *title, const gchar *seek,
558 gboolean seek_after)
559 {
560 GtkTextIter start, end;
561
562 gtk_window_set_title(GTK_WINDOW(command_dialog), title ? title : _("GDB Command"));
563 gtk_widget_grab_focus(command_view);
564
565 if (text)
566 {
567 const gchar *pos = seek ? strstr(text, seek) : NULL;
568 GtkTextIter iter;
569
570 gtk_text_buffer_set_text(command_text, text, -1);
571 gtk_text_buffer_get_iter_at_offset(command_text, &iter,
572 g_utf8_strlen(text, pos ? pos + strlen(seek) * seek_after - text : -1));
573 gtk_text_buffer_place_cursor(command_text, &iter);
574 }
575 else
576 {
577 gtk_text_buffer_get_start_iter(command_text, &start);
578 gtk_text_buffer_get_end_iter(command_text, &end);
579 gtk_text_buffer_select_range(command_text, &start, &end);
580 }
581
582 on_command_text_changed(command_text, NULL);
583 command_line_update_state(debug_state());
584 gtk_combo_box_set_active_iter(command_history, NULL);
585 gtk_dialog_run(GTK_DIALOG(command_dialog));
586 }
587
view_command_active(void)588 gboolean view_command_active(void)
589 {
590 return gtk_widget_get_visible(command_dialog);
591 }
592
views_update_state(DebugState state)593 void views_update_state(DebugState state)
594 {
595 static DebugState last_state = 0;
596
597 if (state != last_state)
598 {
599 if (gtk_widget_get_visible(command_dialog))
600 command_line_update_state(state);
601 locals_update_state(state);
602 watches_update_state(state);
603 inspects_update_state(state);
604 last_state = state;
605 }
606 }
607
on_geany_sidebar_switch_page(G_GNUC_UNUSED GtkNotebook * notebook,G_GNUC_UNUSED gpointer page,gint page_num,G_GNUC_UNUSED gpointer gdata)608 static void on_geany_sidebar_switch_page(G_GNUC_UNUSED GtkNotebook *notebook,
609 G_GNUC_UNUSED gpointer page, gint page_num, G_GNUC_UNUSED gpointer gdata)
610 {
611 views_sidebar_update(page_num, debug_state());
612 }
613
614 static gulong switch_sidebar_page_id;
615
views_init(void)616 void views_init(void)
617 {
618 if (pref_var_update_bug)
619 views[VIEW_INSPECT].state = DS_DEBUG;
620
621 command_dialog = dialog_connect("command_dialog");
622 command_view = get_widget("command_view");
623 command_text = gtk_text_view_get_buffer(GTK_TEXT_VIEW(command_view));
624 g_signal_connect(command_text, "changed", G_CALLBACK(on_command_text_changed), NULL);
625 command_history = GTK_COMBO_BOX(get_widget("command_history"));
626 command_store = SCP_TREE_STORE(gtk_combo_box_get_model(command_history));
627 command_cell = get_object("command_cell");
628 g_signal_connect(command_dialog, "configure-event",
629 G_CALLBACK(on_command_dialog_configure), NULL);
630 g_signal_connect(command_history, "size-request",
631 G_CALLBACK(on_command_history_size_request), NULL);
632 g_signal_connect(command_history, "changed", G_CALLBACK(on_command_history_changed),
633 NULL);
634 command_locale = GTK_TOGGLE_BUTTON(get_widget("command_locale"));
635
636 g_signal_connect(get_widget("command_thread"), "clicked",
637 G_CALLBACK(on_command_insert_button_clicked), GINT_TO_POINTER('t'));
638 g_signal_connect(get_widget("command_group"), "clicked",
639 G_CALLBACK(on_command_insert_button_clicked), GINT_TO_POINTER('g'));
640 g_signal_connect(get_widget("command_frame"), "clicked",
641 G_CALLBACK(on_command_insert_button_clicked), GINT_TO_POINTER('f'));
642 command_send = get_widget("command_send");
643 gtk_widget_grab_default(command_send);
644 g_signal_connect(command_send, "clicked", G_CALLBACK(on_command_send_button_clicked),
645 NULL);
646 utils_enter_to_clicked(command_view, command_send);
647
648 geany_sidebar = GTK_NOTEBOOK(geany->main_widgets->sidebar_notebook);
649 switch_sidebar_page_id = g_signal_connect(geany_sidebar, "switch-page",
650 G_CALLBACK(on_geany_sidebar_switch_page), NULL);
651 inspect_page = get_widget("inspect_page");
652 gtk_notebook_append_page(geany_sidebar, inspect_page, get_widget("inspect_label"));
653 register_page = get_widget("register_page");
654 gtk_notebook_append_page(geany_sidebar, register_page, get_widget("register_label"));
655 }
656
views_finalize(void)657 void views_finalize(void)
658 {
659 g_signal_handler_disconnect(geany_sidebar, switch_sidebar_page_id);
660 gtk_widget_destroy(GTK_WIDGET(command_dialog));
661 gtk_widget_destroy(inspect_page);
662 gtk_widget_destroy(register_page);
663 }
664