1 /*
2 * inspect.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 <stdlib.h>
26 #include <string.h>
27
28 #include "common.h"
29
30 enum
31 {
32 INSPECT_VAR1,
33 INSPECT_DISPLAY,
34 INSPECT_VALUE,
35 INSPECT_HB_MODE,
36 INSPECT_SCID,
37 INSPECT_EXPR,
38 INSPECT_NAME,
39 INSPECT_FRAME,
40 INSPECT_RUN_APPLY,
41 INSPECT_START,
42 INSPECT_COUNT,
43 INSPECT_EXPAND,
44 INSPECT_NUMCHILD,
45 INSPECT_FORMAT,
46 INSPECT_PATH_EXPR
47 };
48
49 enum
50 {
51 FORMAT_NATURAL,
52 FORMAT_DECIMAL,
53 FORMAT_HEX,
54 FORMAT_OCTAL,
55 FORMAT_BINARY,
56 FORMAT_COUNT
57 };
58
59 static GtkTreeView *tree;
60 static ScpTreeStore *store;
61 static GtkTreeSelection *selection;
62 static gint scid_gen = 0;
63
append_stub(GtkTreeIter * parent,const gchar * text,gboolean expand)64 static void append_stub(GtkTreeIter *parent, const gchar *text, gboolean expand)
65 {
66 scp_tree_store_append_with_values(store, NULL, parent, INSPECT_EXPR, text,
67 INSPECT_EXPAND, expand, -1);
68 }
69
70 #define append_ellipsis(parent, expand) append_stub((parent), _("..."), (expand))
71
inspect_find_recursive(GtkTreeIter * iter,gint i,const char * key)72 static gboolean inspect_find_recursive(GtkTreeIter *iter, gint i, const char *key)
73 {
74 do
75 {
76 gboolean flag = !key;
77
78 if (flag)
79 {
80 gint scid;
81
82 scp_tree_store_get(store, iter, INSPECT_SCID, &scid, -1);
83 if (scid == i)
84 return TRUE;
85 }
86 else
87 {
88 const char *var1;
89 size_t len;
90
91 scp_tree_store_get(store, iter, INSPECT_VAR1, &var1, -1);
92 len = var1 ? strlen(var1) : 0;
93
94 if (var1 && !strncmp(key, var1, len))
95 {
96 if (key[len] == '\0')
97 return TRUE;
98
99 flag = key[len] == '.' && key[len + 1];
100 }
101 }
102
103 if (flag)
104 {
105 GtkTreeIter child;
106
107 if (scp_tree_store_iter_children(store, &child, iter) &&
108 inspect_find_recursive(&child, i, key))
109 {
110 *iter = child;
111 return TRUE;
112 }
113 }
114 } while (scp_tree_store_iter_next(store, iter));
115
116 return FALSE;
117 }
118
inspect_find(GtkTreeIter * iter,gboolean string,const char * key)119 static gboolean inspect_find(GtkTreeIter *iter, gboolean string, const char *key)
120 {
121 if (scp_tree_store_get_iter_first(store, iter) &&
122 inspect_find_recursive(iter, atoi(key), string ? key : NULL))
123 {
124 return TRUE;
125 }
126
127 if (!string)
128 dc_error("%s: i_scid not found", key);
129
130 return FALSE;
131 }
132
inspect_get_scid(GtkTreeIter * iter)133 static gint inspect_get_scid(GtkTreeIter *iter)
134 {
135 gint scid;
136
137 scp_tree_store_get(store, iter, INSPECT_SCID, &scid, -1);
138 if (!scid)
139 scp_tree_store_set(store, iter, INSPECT_SCID, scid = ++scid_gen, -1);
140
141 return scid;
142 }
143
inspect_expand(GtkTreeIter * iter)144 static void inspect_expand(GtkTreeIter *iter)
145 {
146 const char *var1;
147 gint scid, start, count, numchild;
148 char *s;
149
150 scid = inspect_get_scid(iter);
151 scp_tree_store_get(store, iter, INSPECT_VAR1, &var1, INSPECT_START, &start,
152 INSPECT_COUNT, &count, INSPECT_NUMCHILD, &numchild, -1);
153 s = g_strdup_printf("%d", start);
154 debug_send_format(N, "07%c%d%d-var-list-children 1 %s %d %d", '0' + (int) strlen(s) - 1,
155 start, scid, var1, start, count ? start + count : numchild);
156 g_free(s);
157 }
158
on_jump_to_menu_item_activate(GtkMenuItem * menuitem,G_GNUC_UNUSED gpointer gdata)159 static void on_jump_to_menu_item_activate(GtkMenuItem *menuitem, G_GNUC_UNUSED gpointer gdata)
160 {
161 GtkTreeIter iter;
162 const gchar *expr = gtk_menu_item_get_label(menuitem);
163
164 if (store_find(store, &iter, INSPECT_EXPR, expr))
165 utils_tree_set_cursor(selection, &iter, 0);
166 }
167
168 static GtkWidget *jump_to_item;
169 static GtkContainer *jump_to_menu;
170 static gchar *jump_to_expr = NULL;
171
on_inspect_row_inserted(GtkTreeModel * model,GtkTreePath * path,GtkTreeIter * iter,G_GNUC_UNUSED gpointer gdata)172 static void on_inspect_row_inserted(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter,
173 G_GNUC_UNUSED gpointer gdata)
174 {
175 if (gtk_tree_path_get_depth(path) == 1)
176 {
177 GtkWidget *item;
178 const gint *index = gtk_tree_path_get_indices(path);
179
180 g_free(jump_to_expr);
181 gtk_tree_model_get(model, iter, INSPECT_EXPR, &jump_to_expr, -1);
182 item = gtk_menu_item_new_with_label(jump_to_expr ? jump_to_expr : "");
183 gtk_widget_show(item);
184 gtk_menu_shell_insert(GTK_MENU_SHELL(jump_to_menu), item, *index);
185 g_signal_connect(item, "activate", G_CALLBACK(on_jump_to_menu_item_activate), NULL);
186 }
187 }
188
on_inspect_row_changed(GtkTreeModel * model,GtkTreePath * path,GtkTreeIter * iter,G_GNUC_UNUSED gpointer gdata)189 static void on_inspect_row_changed(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter,
190 G_GNUC_UNUSED gpointer gdata)
191 {
192 if (!jump_to_expr && gtk_tree_path_get_depth(path) == 1)
193 {
194 const gint *index = gtk_tree_path_get_indices(path);
195 GList *list = gtk_container_get_children(jump_to_menu);
196 gpointer item = g_list_nth_data(list, *index);
197
198 gtk_tree_model_get(model, iter, INSPECT_EXPR, &jump_to_expr, -1);
199 if (jump_to_expr)
200 gtk_menu_item_set_label(GTK_MENU_ITEM(item), jump_to_expr);
201 g_list_free(list);
202 }
203 }
204
on_inspect_row_deleted(GtkTreeModel * model,GtkTreePath * path,G_GNUC_UNUSED gpointer gdata)205 static void on_inspect_row_deleted(GtkTreeModel *model, GtkTreePath *path,
206 G_GNUC_UNUSED gpointer gdata)
207 {
208 if (gtk_tree_path_get_depth(path) == 1)
209 {
210 const gint *index = gtk_tree_path_get_indices(path);
211 GList *list = gtk_container_get_children(jump_to_menu);
212 gpointer item = g_list_nth_data(list, *index);
213 GtkTreeIter iter;
214
215 gtk_container_remove(jump_to_menu, GTK_WIDGET(item));
216 if (!gtk_tree_model_get_iter_first(model, &iter))
217 gtk_widget_set_sensitive(jump_to_item, FALSE);
218 g_list_free(list);
219 }
220 }
221
222 static const MenuItem *apply_item;
223
inspect_redisplay(GtkTreeIter * iter,const char * value,gchar * display)224 static gchar *inspect_redisplay(GtkTreeIter *iter, const char *value, gchar *display)
225 {
226 gint hb_mode;
227
228 scp_tree_store_get(store, iter, INSPECT_HB_MODE, &hb_mode, -1);
229 g_free(display);
230 return value && *value ? utils_get_display_from_7bit(value, hb_mode) : g_strdup("??");
231 }
232
inspect_variable_store(GtkTreeIter * iter,const ParseVariable * var)233 static gint inspect_variable_store(GtkTreeIter *iter, const ParseVariable *var)
234 {
235 gint format;
236 gboolean expand;
237
238 scp_tree_store_get(store, iter, INSPECT_EXPAND, &expand, INSPECT_FORMAT, &format, -1);
239 scp_tree_store_set(store, iter, INSPECT_VAR1, var->name, INSPECT_DISPLAY, var->display,
240 INSPECT_VALUE, var->value, INSPECT_NUMCHILD, var->numchild, -1);
241
242 if (var->numchild)
243 {
244 append_ellipsis(iter, TRUE);
245 if (expand)
246 inspect_expand(iter);
247 }
248
249 return format;
250 }
251
252 static const char *const inspect_formats[FORMAT_COUNT] = { "natural", "decimal",
253 "hexadecimal", "octal", "binary" };
254
on_inspect_variable(GArray * nodes)255 void on_inspect_variable(GArray *nodes)
256 {
257 GtkTreeIter iter;
258 const char *token = parse_grab_token(nodes);
259
260 iff (store_find(store, &iter, INSPECT_SCID, token), "%s: no vid", token)
261 {
262 ParseVariable var;
263 gint format;
264
265 parse_variable(nodes, &var, "numchild");
266 var.display = inspect_redisplay(&iter, var.value, var.display);
267 scp_tree_store_clear_children(store, &iter, FALSE);
268
269 if ((format = inspect_variable_store(&iter, &var)) != FORMAT_NATURAL)
270 {
271 debug_send_format(N, "07%s-var-set-format %s %s", token, var.name,
272 inspect_formats[format]);
273 }
274
275 if (gtk_tree_selection_iter_is_selected(selection, &iter))
276 menu_item_set_active(apply_item, TRUE);
277
278 parse_variable_free(&var);
279 }
280 }
281
inspect_set(GArray * nodes,const char * value,gint format)282 static void inspect_set(GArray *nodes, const char *value, gint format)
283 {
284 const char *token = parse_grab_token(nodes);
285 GtkTreeIter iter;
286
287 if (inspect_find(&iter, FALSE, token))
288 {
289 if (!value || *value)
290 {
291 gchar *display = inspect_redisplay(&iter, value, NULL);
292
293 scp_tree_store_set(store, &iter, INSPECT_DISPLAY, display, INSPECT_VALUE,
294 value, -1);
295 g_free(display);
296 }
297 else
298 {
299 scp_tree_store_get(store, &iter, INSPECT_VALUE, &value, -1);
300
301 if (value)
302 {
303 scp_tree_store_set(store, &iter, INSPECT_DISPLAY, "??", INSPECT_VALUE,
304 NULL);
305 }
306 }
307
308 if (format < FORMAT_COUNT)
309 scp_tree_store_set(store, &iter, INSPECT_FORMAT, format, -1);
310 }
311 }
312
on_inspect_format(GArray * nodes)313 void on_inspect_format(GArray *nodes)
314 {
315 const char *fmtstr = parse_lead_value(nodes);
316 gint format;
317
318 for (format = FORMAT_NATURAL; format < FORMAT_COUNT; format++)
319 if (!strcmp(inspect_formats[format], fmtstr))
320 break;
321
322 iff (format < FORMAT_COUNT, "bad format")
323 inspect_set(nodes, parse_find_value(nodes, "value"), format);
324 }
325
on_inspect_evaluate(GArray * nodes)326 void on_inspect_evaluate(GArray *nodes)
327 {
328 inspect_set(nodes, parse_lead_value(nodes), FORMAT_COUNT);
329 }
330
on_inspect_assign(GArray * nodes)331 void on_inspect_assign(GArray *nodes)
332 {
333 on_inspect_evaluate(nodes);
334 views_data_dirty(DS_BUSY);
335 }
336
inspect_node_append(const ParseNode * node,GtkTreeIter * parent)337 static void inspect_node_append(const ParseNode *node, GtkTreeIter *parent)
338 {
339 GArray *nodes = (GArray *) node->value;
340 ParseVariable var;
341
342 if (node->type == PT_VALUE || !parse_variable(nodes, &var, "numchild"))
343 append_stub(parent, _("invalid data"), FALSE);
344 else
345 {
346 GtkTreeIter iter;
347
348 scp_tree_store_append(store, &iter, parent);
349 inspect_variable_store(&iter, &var);
350 scp_tree_store_set(store, &iter, INSPECT_EXPR, var.expr ? var.expr : var.name,
351 INSPECT_HB_MODE, var.hb_mode, INSPECT_FORMAT, FORMAT_NATURAL, -1);
352 parse_variable_free(&var);
353 }
354 }
355
on_inspect_children(GArray * nodes)356 void on_inspect_children(GArray *nodes)
357 {
358 char *token = (char *) parse_grab_token(nodes);
359 size_t size = *token - '0' + 2;
360
361 iff (strlen(token) >= size + 1, "bad token")
362 {
363 GtkTreeIter iter;
364
365 if (inspect_find(&iter, FALSE, token + size))
366 {
367 gint from;
368 GtkTreePath *path = scp_tree_store_get_path(store, &iter);
369
370 token[size] = '\0';
371 from = atoi(token + 1);
372 scp_tree_store_clear_children(store, &iter, FALSE);
373
374 if ((nodes = parse_find_array(nodes, "children")) == NULL)
375 append_stub(&iter, _("no children in range"), FALSE);
376 else
377 {
378 gint numchild, end;
379 const char *var1;
380
381 if (from)
382 append_ellipsis(&iter, FALSE);
383
384 scp_tree_store_get(store, &iter, INSPECT_VAR1, &var1,
385 INSPECT_NUMCHILD, &numchild, -1);
386
387 parse_foreach(nodes, (GFunc) inspect_node_append, &iter);
388 end = from + nodes->len;
389
390 if (nodes->len && (from || end < numchild))
391 {
392 debug_send_format(N, "04-var-set-update-range %s %d %d", var1,
393 from, end);
394 }
395
396 if (nodes->len ? end < numchild : !from)
397 append_ellipsis(&iter, FALSE);
398 }
399
400 gtk_tree_view_expand_row(tree, path, FALSE);
401 gtk_tree_path_free(path);
402 }
403 }
404 }
405
inspect_iter_clear(GtkTreeIter * iter,G_GNUC_UNUSED gpointer gdata)406 static void inspect_iter_clear(GtkTreeIter *iter, G_GNUC_UNUSED gpointer gdata)
407 {
408 scp_tree_store_clear_children(store, iter, FALSE);
409 scp_tree_store_set(store, iter, INSPECT_DISPLAY, NULL, INSPECT_VALUE, NULL,
410 INSPECT_VAR1, NULL, INSPECT_NUMCHILD, 0, INSPECT_PATH_EXPR, NULL, -1);
411
412 if (gtk_tree_selection_iter_is_selected(selection, iter))
413 menu_item_set_active(apply_item, FALSE);
414 }
415
on_inspect_ndeleted(GArray * nodes)416 void on_inspect_ndeleted(GArray *nodes)
417 {
418 const char *token = parse_grab_token(nodes);
419
420 iff (*token <= '1', "%s: invalid i_oper", token)
421 {
422 GtkTreeIter iter;
423
424 if (inspect_find(&iter, FALSE, token + 1))
425 {
426 if (*token == '0')
427 inspect_iter_clear(&iter, NULL);
428 else
429 scp_tree_store_remove(store, &iter);
430 }
431 }
432 }
433
on_inspect_path_expr(GArray * nodes)434 void on_inspect_path_expr(GArray *nodes)
435 {
436 const char *token = parse_grab_token(nodes);
437 GtkTreeIter iter;
438
439 if (inspect_find(&iter, FALSE, token))
440 scp_tree_store_set(store, &iter, INSPECT_PATH_EXPR, parse_lead_value(nodes), -1);
441 }
442
inspect_node_change(const ParseNode * node,G_GNUC_UNUSED gpointer gdata)443 static void inspect_node_change(const ParseNode *node, G_GNUC_UNUSED gpointer gdata)
444 {
445 iff (node->type == PT_ARRAY, "changelist: contains value")
446 {
447 GArray *nodes = (GArray *) node->value;
448 ParseVariable var;
449 GtkTreeIter iter;
450
451 if (parse_variable(nodes, &var, "new_num_children") &&
452 inspect_find(&iter, TRUE, var.name))
453 {
454 const char *in_scope = parse_find_value(nodes, "in_scope");
455
456 if (!g_strcmp0(in_scope, "false"))
457 {
458 scp_tree_store_set(store, &iter, INSPECT_DISPLAY, _("out of scope"),
459 INSPECT_VALUE, NULL, -1);
460 }
461 else if (!g_strcmp0(in_scope, "invalid"))
462 {
463 debug_send_format(N, "070%d-var-delete %s", inspect_get_scid(&iter),
464 var.name);
465 }
466 else
467 {
468 var.display = inspect_redisplay(&iter, var.value, var.display);
469
470 if (var.children)
471 {
472 scp_tree_store_clear_children(store, &iter, FALSE);
473 inspect_variable_store(&iter, &var);
474 }
475 else
476 {
477 scp_tree_store_set(store, &iter, INSPECT_DISPLAY, var.display,
478 INSPECT_VALUE, var.value, -1);
479 }
480 }
481 }
482
483 parse_variable_free(&var);
484 }
485 }
486
487 static gboolean query_all_inspects = FALSE;
488
on_inspect_changelist(GArray * nodes)489 void on_inspect_changelist(GArray *nodes)
490 {
491 GArray *changelist = parse_lead_array(nodes);
492 const char *token = parse_grab_token(nodes);
493
494 if (token)
495 {
496 iff (*token <= '1', "%s: invalid i_oper", token)
497 if (*token == '0')
498 parse_foreach(changelist, (GFunc) inspect_node_change, NULL);
499 }
500 else if (changelist->len)
501 query_all_inspects = TRUE;
502 }
503
inspect_apply(GtkTreeIter * iter)504 static void inspect_apply(GtkTreeIter *iter)
505 {
506 gint scid;
507 const gchar *expr;
508 const char *name, *frame;
509 char *locale;
510
511 scp_tree_store_get(store, iter, INSPECT_EXPR, &expr, INSPECT_SCID, &scid,
512 INSPECT_NAME, &name, INSPECT_FRAME, &frame, -1);
513 locale = utils_get_locale_from_utf8(expr);
514 debug_send_format(F, "07%d-var-create %s %s %s", scid, name, frame, locale);
515 g_free(locale);
516 }
517
on_inspect_signal(const char * name)518 void on_inspect_signal(const char *name)
519 {
520 GtkTreeIter iter;
521
522 iff (isalpha(*name), "%s: invalid var name", name)
523 {
524 iff (store_find(store, &iter, INSPECT_NAME, name), "%s: var not found", name)
525 {
526 const char *var1;
527
528 scp_tree_store_get(store, &iter, INSPECT_VAR1, &var1, -1);
529
530 iff (!var1, "%s: already applied", name)
531 inspect_apply(&iter);
532 }
533 }
534 }
535
inspects_clear(void)536 void inspects_clear(void)
537 {
538 store_foreach(store, (GFunc) inspect_iter_clear, NULL);
539 query_all_inspects = FALSE;
540 }
541
inspect_iter_refresh(ScpTreeStore * store,GtkTreeIter * iter,gpointer gdata)542 static gint inspect_iter_refresh(ScpTreeStore *store, GtkTreeIter *iter, gpointer gdata)
543 {
544 const char *var1;
545 gint numchild;
546
547 scp_tree_store_get(store, iter, INSPECT_VAR1, &var1, INSPECT_NUMCHILD, &numchild, -1);
548
549 if (var1 && !numchild)
550 {
551 debug_send_format(F, "0%c%d-var-evaluate-expression %s", GPOINTER_TO_INT(gdata),
552 inspect_get_scid(iter), var1);
553 }
554 return FALSE;
555 }
556
inspects_send_refresh(char token)557 static void inspects_send_refresh(char token)
558 {
559 scp_tree_store_traverse(store, TRUE, NULL, NULL, inspect_iter_refresh,
560 GINT_TO_POINTER((gint) token));
561 query_all_inspects = FALSE;
562 }
563
inspects_update(void)564 gboolean inspects_update(void)
565 {
566 if (query_all_inspects)
567 inspects_send_refresh('4');
568 else
569 debug_send_command(F, "040-var-update 1 *");
570
571 return TRUE;
572 }
573
inspect_iter_apply(GtkTreeIter * iter,G_GNUC_UNUSED gpointer gdata)574 static void inspect_iter_apply(GtkTreeIter *iter, G_GNUC_UNUSED gpointer gdata)
575 {
576 const char *var1, *frame;
577 gboolean run_apply;
578
579 scp_tree_store_get(store, iter, INSPECT_VAR1, &var1, INSPECT_FRAME, &frame,
580 INSPECT_RUN_APPLY, &run_apply, -1);
581
582 if (run_apply && !var1 && !isdigit(*frame))
583 inspect_apply(iter);
584 }
585
inspects_apply(void)586 void inspects_apply(void)
587 {
588 store_foreach(store, (GFunc) inspect_iter_apply, NULL);
589 }
590
inspect_name_valid(const char * name)591 static gboolean inspect_name_valid(const char *name)
592 {
593 return !strcmp(name, "-") || isalpha(*name);
594 }
595
inspect_frame_valid(const char * frame)596 static gboolean inspect_frame_valid(const char *frame)
597 {
598 char *end;
599 strtol(frame, &end, 0);
600 return !strcmp(frame, "*") || !strcmp(frame, "@") || (end > frame && *end == '\0');
601 }
602
603 static GtkWidget *inspect_dialog;
604 static GtkEntry *inspect_expr;
605 static GtkEntry *inspect_name;
606 static GtkEntry *inspect_frame;
607 static GtkToggleButton *inspect_run_apply;
608 static GtkWidget *inspect_ok;
609
on_inspect_entry_changed(G_GNUC_UNUSED GtkEditable * editable,G_GNUC_UNUSED gpointer gdata)610 static void on_inspect_entry_changed(G_GNUC_UNUSED GtkEditable *editable,
611 G_GNUC_UNUSED gpointer gdata)
612 {
613 const char *frame = gtk_entry_get_text(inspect_frame);
614 const char *expr = gtk_entry_get_text(inspect_expr);
615
616 gtk_widget_set_sensitive(GTK_WIDGET(inspect_run_apply), !isdigit(*frame));
617 gtk_widget_set_sensitive(inspect_ok,
618 inspect_name_valid(gtk_entry_get_text(inspect_name)) &&
619 inspect_frame_valid(frame) && *utils_skip_spaces(expr));
620 }
621
on_inspect_ok_button_clicked(G_GNUC_UNUSED GtkButton * button,G_GNUC_UNUSED gpointer gdata)622 static void on_inspect_ok_button_clicked(G_GNUC_UNUSED GtkButton *button,
623 G_GNUC_UNUSED gpointer gdata)
624 {
625 GtkTreeIter iter;
626 const char *name = gtk_entry_get_text(inspect_name);
627
628 if ((strcmp(name, "-") && store_find(store, &iter, INSPECT_NAME, name)) ||
629 inspect_find(&iter, TRUE, name))
630 {
631 show_error(_("Duplicate inspect variable name."));
632 }
633 else
634 gtk_dialog_response(GTK_DIALOG(inspect_dialog), GTK_RESPONSE_ACCEPT);
635 }
636
inspect_dialog_store(GtkTreeIter * iter)637 static void inspect_dialog_store(GtkTreeIter *iter)
638 {
639 const gchar *expr = gtk_entry_get_text(inspect_expr);
640
641 scp_tree_store_set(store, iter, INSPECT_EXPR, expr, INSPECT_PATH_EXPR, expr,
642 INSPECT_NAME, gtk_entry_get_text(inspect_name),
643 INSPECT_FRAME, gtk_entry_get_text(inspect_frame),
644 INSPECT_RUN_APPLY, gtk_toggle_button_get_active(inspect_run_apply), -1);
645 }
646
inspect_add(const gchar * text)647 void inspect_add(const gchar *text)
648 {
649 gtk_entry_set_text(inspect_expr, text ? text : "");
650 gtk_entry_set_text(inspect_name, "-");
651 gtk_toggle_button_set_active(inspect_run_apply, FALSE);
652 on_inspect_entry_changed(NULL, NULL);
653 gtk_widget_grab_focus(GTK_WIDGET(inspect_expr));
654
655 if (gtk_dialog_run(GTK_DIALOG(inspect_dialog)) == GTK_RESPONSE_ACCEPT)
656 {
657 GtkTreeIter iter;
658 const gchar *expr = gtk_entry_get_text(inspect_expr);
659
660 scp_tree_store_append_with_values(store, &iter, NULL, INSPECT_HB_MODE,
661 parse_mode_get(expr, MODE_HBIT), INSPECT_SCID, ++scid_gen, INSPECT_FORMAT,
662 FORMAT_NATURAL, INSPECT_COUNT, option_inspect_count, INSPECT_EXPAND,
663 option_inspect_expand, -1);
664 inspect_dialog_store(&iter);
665 utils_tree_set_cursor(selection, &iter, -1);
666
667 if (debug_state() != DS_INACTIVE)
668 gtk_widget_set_sensitive(jump_to_item, TRUE);
669
670 if (debug_state() & DS_DEBUG)
671 inspect_apply(&iter);
672 }
673 }
674
on_inspect_display_edited(G_GNUC_UNUSED GtkCellRendererText * renderer,gchar * path_str,gchar * new_text,G_GNUC_UNUSED gpointer gdata)675 static void on_inspect_display_edited(G_GNUC_UNUSED GtkCellRendererText *renderer,
676 gchar *path_str, gchar *new_text, G_GNUC_UNUSED gpointer gdata)
677 {
678 GtkTreeIter iter;
679 char *format;
680
681 scp_tree_store_get_iter_from_string(store, &iter, path_str);
682 format = g_strdup_printf("07%d-var-assign %%s %%s", inspect_get_scid(&iter));
683 view_display_edited(store, debug_state() & DS_VARIABLE, path_str, format, new_text);
684 g_free(format);
685 }
686
687 static const TreeCell inspect_cells[] =
688 {
689 { "inspect_display", G_CALLBACK(on_inspect_display_edited) },
690 { NULL, NULL }
691 };
692
693 static GObject *inspect_display;
694
inspects_update_state(DebugState state)695 void inspects_update_state(DebugState state)
696 {
697 static gboolean last_active = FALSE;
698 gboolean active = state != DS_INACTIVE;
699 GtkTreeIter iter;
700
701 if (gtk_tree_selection_get_selected(selection, NULL, &iter))
702 {
703 const char *var1 = NULL;
704 gint numchild = 0;
705
706 if (state & DS_VARIABLE)
707 {
708 scp_tree_store_get(store, &iter, INSPECT_VAR1, &var1, INSPECT_NUMCHILD,
709 &numchild, -1);
710 }
711 g_object_set(inspect_display, "editable", var1 && !numchild, NULL);
712 }
713
714 if (active != last_active)
715 {
716 gtk_widget_set_sensitive(jump_to_item, active &&
717 scp_tree_store_get_iter_first(store, &iter));
718 last_active = active;
719 }
720 }
721
inspects_delete_all(void)722 void inspects_delete_all(void)
723 {
724 store_clear(store);
725 scid_gen = 0;
726 }
727
inspect_load(GKeyFile * config,const char * section)728 static gboolean inspect_load(GKeyFile *config, const char *section)
729 {
730 char *name = utils_key_file_get_string(config, section, "name");
731 gchar *expr = utils_key_file_get_string(config, section, "expr");
732 gint hb_mode = utils_get_setting_integer(config, section, "hbit", HB_DEFAULT);
733 char *frame = utils_key_file_get_string(config, section, "frame");
734 gboolean run_apply = utils_get_setting_boolean(config, section, "run_apply", FALSE);
735 gint start = utils_get_setting_integer(config, section, "start", 0);
736 gint count = utils_get_setting_integer(config, section, "count", option_inspect_count);
737 gboolean expand = utils_get_setting_boolean(config, section, "expand",
738 option_inspect_expand);
739 gint format = utils_get_setting_integer(config, section, "format", FORMAT_NATURAL);
740 gboolean valid = FALSE;
741
742 if (name && inspect_name_valid(name) && expr && (unsigned) hb_mode < HB_COUNT &&
743 frame && inspect_frame_valid(frame) && (unsigned) start <= EXPAND_MAX &&
744 (unsigned) count <= EXPAND_MAX && (unsigned) format < FORMAT_COUNT)
745 {
746 scp_tree_store_append_with_values(store, NULL, NULL, INSPECT_EXPR, expr,
747 INSPECT_PATH_EXPR, expr, INSPECT_HB_MODE, hb_mode, INSPECT_SCID, ++scid_gen,
748 INSPECT_NAME, name, INSPECT_FRAME, frame, INSPECT_RUN_APPLY, run_apply,
749 INSPECT_START, start, INSPECT_COUNT, count, INSPECT_EXPAND, expand,
750 INSPECT_FORMAT, format, -1);
751 valid = TRUE;
752 }
753
754 g_free(frame);
755 g_free(expr);
756 g_free(name);
757 return valid;
758 }
759
inspects_load(GKeyFile * config)760 void inspects_load(GKeyFile *config)
761 {
762 inspects_delete_all();
763 utils_load(config, "inspect", inspect_load);
764 }
765
inspect_save(GKeyFile * config,const char * section,GtkTreeIter * iter)766 static gboolean inspect_save(GKeyFile *config, const char *section, GtkTreeIter *iter)
767 {
768 gint hb_mode, start, count, format;
769 const char *name, *frame;
770 const gchar *expr;
771 gboolean run_apply, expand;
772
773 scp_tree_store_get(store, iter, INSPECT_EXPR, &expr, INSPECT_HB_MODE, &hb_mode,
774 INSPECT_NAME, &name, INSPECT_FRAME, &frame, INSPECT_RUN_APPLY, &run_apply,
775 INSPECT_START, &start, INSPECT_COUNT, &count, INSPECT_EXPAND, &expand,
776 INSPECT_FORMAT, &format, -1);
777 g_key_file_set_string(config, section, "name", name);
778 g_key_file_set_string(config, section, "expr", expr);
779 g_key_file_set_integer(config, section, "hbit", hb_mode);
780 g_key_file_set_string(config, section, "frame", frame);
781 g_key_file_set_boolean(config, section, "run_apply", run_apply);
782 g_key_file_set_integer(config, section, "start", start);
783 g_key_file_set_integer(config, section, "count", count);
784 g_key_file_set_boolean(config, section, "expand", expand);
785 g_key_file_set_integer(config, section, "format", format);
786 return TRUE;
787 }
788
inspects_save(GKeyFile * config)789 void inspects_save(GKeyFile *config)
790 {
791 store_save(store, config, "inspect", inspect_save);
792 }
793
on_inspect_refresh(G_GNUC_UNUSED const MenuItem * menu_item)794 static void on_inspect_refresh(G_GNUC_UNUSED const MenuItem *menu_item)
795 {
796 debug_send_command(F, "041-var-update 1 *");
797 inspects_send_refresh('2');
798 }
799
on_inspect_add(G_GNUC_UNUSED const MenuItem * menu_item)800 static void on_inspect_add(G_GNUC_UNUSED const MenuItem *menu_item)
801 {
802 GtkTreeIter iter;
803 const gchar *expr = NULL;
804
805 if (gtk_tree_selection_get_selected(selection, NULL, &iter))
806 scp_tree_store_get(store, &iter, INSPECT_PATH_EXPR, &expr, -1);
807
808 inspect_add(expr);
809 }
810
on_inspect_edit(G_GNUC_UNUSED const MenuItem * menu_item)811 static void on_inspect_edit(G_GNUC_UNUSED const MenuItem *menu_item)
812 {
813 GtkTreeIter iter;
814 const gchar *expr;
815 const char *name, *frame;
816 gboolean run_apply;
817
818 if (gtk_tree_selection_get_selected(selection, NULL, &iter))
819 {
820 scp_tree_store_get(store, &iter, INSPECT_EXPR, &expr, INSPECT_NAME, &name,
821 INSPECT_FRAME, &frame, INSPECT_RUN_APPLY, &run_apply, -1);
822 scp_tree_store_set(store, &iter, INSPECT_NAME, "-", -1); /* for duplicate name check */
823
824 gtk_entry_set_text(inspect_expr, expr);
825 gtk_entry_set_text(inspect_name, name);
826 gtk_entry_set_text(inspect_frame, frame);
827 gtk_toggle_button_set_active(inspect_run_apply, run_apply);
828 on_inspect_entry_changed(NULL, NULL);
829
830 if (gtk_dialog_run(GTK_DIALOG(inspect_dialog)) == GTK_RESPONSE_ACCEPT)
831 {
832 g_free(jump_to_expr);
833 jump_to_expr = NULL;
834 inspect_dialog_store(&iter);
835 }
836 else
837 {
838 scp_tree_store_set(store, &iter, INSPECT_NAME, name, -1);
839 }
840 }
841 }
842
on_inspect_apply(G_GNUC_UNUSED const MenuItem * menu_item)843 static void on_inspect_apply(G_GNUC_UNUSED const MenuItem *menu_item)
844 {
845 GtkTreeIter iter;
846 const char *var1;
847 gint scid;
848
849 if (gtk_tree_selection_get_selected(selection, NULL, &iter))
850 {
851 scp_tree_store_get(store, &iter, INSPECT_SCID, &scid, INSPECT_VAR1, &var1, -1);
852
853 if (var1)
854 {
855 debug_send_format(N, "070%d-var-delete %s", scid, var1);
856 }
857 else
858 {
859 inspect_apply(&iter);
860 }
861 }
862 }
863
864 static GtkWidget *expand_dialog;
865 static GtkSpinButton *expand_start;
866 static GtkSpinButton *expand_count;
867 static GtkToggleButton *expand_automatic;
868
on_inspect_expand(G_GNUC_UNUSED const MenuItem * menu_item)869 static void on_inspect_expand(G_GNUC_UNUSED const MenuItem *menu_item)
870 {
871 GtkTreeIter iter;
872 const char *name;
873 gint start, count;
874 gboolean expand;
875
876 if (gtk_tree_selection_get_selected(selection, NULL, &iter))
877 {
878 scp_tree_store_get(store, &iter, INSPECT_NAME, &name, INSPECT_START, &start,
879 INSPECT_COUNT, &count, INSPECT_EXPAND, &expand, -1);
880 gtk_spin_button_set_value(expand_start, start);
881 gtk_spin_button_set_value(expand_count, count);
882 gtk_toggle_button_set_active(expand_automatic, expand);
883 gtk_widget_set_sensitive(GTK_WIDGET(expand_automatic), name != NULL);
884
885 if (gtk_dialog_run(GTK_DIALOG(expand_dialog)) == GTK_RESPONSE_ACCEPT)
886 {
887 scp_tree_store_set(store, &iter,
888 INSPECT_START, gtk_spin_button_get_value_as_int(expand_start),
889 INSPECT_COUNT, gtk_spin_button_get_value_as_int(expand_count),
890 INSPECT_EXPAND, gtk_toggle_button_get_active(expand_automatic), -1);
891
892 if (debug_state() & DS_VARIABLE)
893 {
894 inspect_expand(&iter);
895 }
896 else
897 {
898 plugin_beep();
899 }
900 }
901 }
902 }
903
on_inspect_copy(const MenuItem * menu_item)904 static void on_inspect_copy(const MenuItem *menu_item)
905 {
906 menu_copy(selection, menu_item);
907 }
908
on_inspect_format_display(const MenuItem * menu_item)909 static void on_inspect_format_display(const MenuItem *menu_item)
910 {
911 menu_mode_display(selection, menu_item, INSPECT_FORMAT);
912 }
913
on_inspect_format_update(const MenuItem * menu_item)914 static void on_inspect_format_update(const MenuItem *menu_item)
915 {
916 GtkTreeIter iter;
917 gint format = GPOINTER_TO_INT(menu_item->gdata);
918 const char *var1;
919
920 if (gtk_tree_selection_get_selected(selection, NULL, &iter))
921 {
922 scp_tree_store_get(store, &iter, INSPECT_VAR1, &var1, -1);
923
924 if (var1)
925 {
926 debug_send_format(N, "07%d-var-set-format %s %s", inspect_get_scid(&iter), var1,
927 inspect_formats[format]);
928 }
929 else
930 {
931 scp_tree_store_set(store, &iter, INSPECT_FORMAT, format, -1);
932 }
933 }
934 }
935
on_inspect_hbit_display(const MenuItem * menu_item)936 static void on_inspect_hbit_display(const MenuItem *menu_item)
937 {
938 menu_hbit_display(selection, menu_item);
939 }
940
inspect_hbit_update_iter(GtkTreeIter * iter,gint hb_mode)941 static void inspect_hbit_update_iter(GtkTreeIter *iter, gint hb_mode)
942 {
943 const char *var1, *value;
944
945 scp_tree_store_get(store, iter, INSPECT_VAR1, &var1, INSPECT_VALUE, &value, -1);
946 scp_tree_store_set(store, iter, INSPECT_HB_MODE, hb_mode, -1);
947
948 if (var1)
949 {
950 gchar *display = inspect_redisplay(iter, value, NULL);
951 scp_tree_store_set(store, iter, INSPECT_DISPLAY, display, -1);
952 g_free(display);
953 }
954 }
955
on_inspect_hbit_update(const MenuItem * menu_item)956 static void on_inspect_hbit_update(const MenuItem *menu_item)
957 {
958 GtkTreeIter iter;
959 const char *expr, *name;
960 gint hb_mode = GPOINTER_TO_INT(menu_item->gdata);
961
962 if (gtk_tree_selection_get_selected(selection, NULL, &iter))
963 {
964 scp_tree_store_get(store, &iter, INSPECT_EXPR, &expr, INSPECT_NAME, &name, -1);
965 inspect_hbit_update_iter(&iter, hb_mode);
966 parse_mode_update(expr, MODE_HBIT, hb_mode);
967
968 if (name)
969 {
970 char *reverse = parse_mode_reentry(expr);
971
972 if (store_find(store, &iter, INSPECT_EXPR, reverse))
973 inspect_hbit_update_iter(&iter, hb_mode);
974 g_free(reverse);
975 }
976 }
977 }
978
on_inspect_delete(G_GNUC_UNUSED const MenuItem * menu_item)979 static void on_inspect_delete(G_GNUC_UNUSED const MenuItem *menu_item)
980 {
981 GtkTreeIter iter;
982 const char *var1;
983
984 if (gtk_tree_selection_get_selected(selection, NULL, &iter))
985 {
986 scp_tree_store_get(store, &iter, INSPECT_VAR1, &var1, -1);
987
988 if (var1)
989 {
990 debug_send_format(N, "071%d-var-delete %s", inspect_get_scid(&iter), var1);
991 }
992 else
993 {
994 scp_tree_store_remove(store, &iter);
995 }
996 }
997 }
998
999 #define DS_EDITABLE (DS_BASICS | DS_EXTRA_2)
1000 #define DS_APPLIABLE (DS_VARIABLE | DS_EXTRA_3)
1001 #define DS_EXPANDABLE (DS_VARIABLE | DS_EXTRA_4)
1002 #define DS_COPYABLE (DS_BASICS | DS_EXTRA_1)
1003 #define DS_FORMATABLE (DS_INACTIVE | DS_VARIABLE | DS_EXTRA_1)
1004 #define DS_REPARSABLE (DS_BASICS | DS_EXTRA_1)
1005 #define DS_DELETABLE (DS_NOT_BUSY | DS_EXTRA_1)
1006
1007 #define FORMAT_ITEM(format, FORMAT) \
1008 { ("inspect_format_"format), on_inspect_format_update, DS_FORMATABLE, NULL, \
1009 GINT_TO_POINTER(FORMAT) }
1010
1011 static MenuItem inspect_menu_items[] =
1012 {
1013 { "inspect_refresh", on_inspect_refresh, DS_VARIABLE, NULL, NULL },
1014 { "inspect_add", on_inspect_add, DS_NOT_BUSY, NULL, NULL },
1015 { "inspect_edit", on_inspect_edit, DS_EDITABLE, NULL, NULL },
1016 { "inspect_apply", on_inspect_apply, DS_APPLIABLE, NULL, NULL },
1017 { "inspect_expand", on_inspect_expand, DS_EXPANDABLE, NULL, NULL },
1018 { "inspect_copy", on_inspect_copy, DS_COPYABLE, NULL, NULL },
1019 { "inspect_format", on_inspect_format_display, DS_FORMATABLE, NULL, NULL },
1020 FORMAT_ITEM("natural", FORMAT_NATURAL),
1021 FORMAT_ITEM("decimal", FORMAT_DECIMAL),
1022 FORMAT_ITEM("hex", FORMAT_HEX),
1023 FORMAT_ITEM("octal", FORMAT_OCTAL),
1024 FORMAT_ITEM("binary", FORMAT_BINARY),
1025 MENU_HBIT_ITEMS(inspect),
1026 { "inspect_delete", on_inspect_delete, DS_DELETABLE, NULL, NULL },
1027 { NULL, NULL, 0, NULL, NULL }
1028 };
1029
inspect_menu_extra_state(void)1030 static guint inspect_menu_extra_state(void)
1031 {
1032 GtkTreeIter iter;
1033
1034 if (gtk_tree_selection_get_selected(selection, NULL, &iter))
1035 {
1036 const char *var1, *name;
1037 gint numchild;
1038
1039 scp_tree_store_get(store, &iter, INSPECT_VAR1, &var1, INSPECT_NAME, &name,
1040 INSPECT_NUMCHILD, &numchild, -1);
1041
1042 if (name || var1)
1043 {
1044 return (1 << DS_INDEX_1) | ((name && !var1) << DS_INDEX_2) |
1045 ((name != NULL) << DS_INDEX_3) | ((numchild != 0) << DS_INDEX_4);
1046 }
1047 }
1048
1049 return 0;
1050 }
1051
1052 static MenuInfo inspect_menu_info = { inspect_menu_items, inspect_menu_extra_state, 0 };
1053
on_inspect_selection_changed(G_GNUC_UNUSED GtkTreeSelection * selection,G_GNUC_UNUSED gpointer gdata)1054 static void on_inspect_selection_changed(G_GNUC_UNUSED GtkTreeSelection *selection,
1055 G_GNUC_UNUSED gpointer gdata)
1056 {
1057 GtkTreeIter iter;
1058 const char *name = NULL;
1059
1060 if (gtk_widget_get_visible(inspect_dialog))
1061 gtk_widget_hide(inspect_dialog);
1062 else if (gtk_widget_get_visible(expand_dialog))
1063 gtk_widget_hide(expand_dialog);
1064
1065 if (gtk_tree_selection_get_selected(selection, NULL, &iter))
1066 scp_tree_store_get(store, &iter, INSPECT_NAME, &name, -1);
1067
1068 gtk_tree_view_set_reorderable(tree, name != NULL);
1069 inspects_update_state(debug_state());
1070 }
1071
inspect_test_expand_row(G_GNUC_UNUSED GtkTreeView * tree_view,GtkTreeIter * iter,G_GNUC_UNUSED GtkTreePath * path,G_GNUC_UNUSED gpointer gdata)1072 static gboolean inspect_test_expand_row(G_GNUC_UNUSED GtkTreeView *tree_view,
1073 GtkTreeIter *iter, G_GNUC_UNUSED GtkTreePath *path, G_GNUC_UNUSED gpointer gdata)
1074 {
1075 GtkTreeIter child;
1076 const char *var1;
1077 gboolean expand;
1078
1079 scp_tree_store_iter_children(store, &child, iter);
1080 scp_tree_store_get(store, &child, INSPECT_VAR1, &var1, INSPECT_EXPAND, &expand, -1);
1081
1082 if (var1 || !expand)
1083 return FALSE;
1084
1085 if (debug_state() & DS_VARIABLE)
1086 inspect_expand(iter);
1087 else
1088 plugin_blink();
1089
1090 return TRUE;
1091 }
1092
on_inspect_key_press(G_GNUC_UNUSED GtkWidget * widget,GdkEventKey * event,G_GNUC_UNUSED gpointer gdata)1093 static gboolean on_inspect_key_press(G_GNUC_UNUSED GtkWidget *widget, GdkEventKey *event,
1094 G_GNUC_UNUSED gpointer gdata)
1095 {
1096 if (ui_is_keyval_enter_or_return(event->keyval))
1097 {
1098 menu_item_execute(&inspect_menu_info, apply_item, FALSE);
1099 return TRUE;
1100 }
1101
1102 return menu_insert_delete(event, &inspect_menu_info, "inspect_add", "inspect_delete");
1103 }
1104
on_inspect_button_press(GtkWidget * widget,GdkEventButton * event,G_GNUC_UNUSED gpointer gdata)1105 gboolean on_inspect_button_press(GtkWidget *widget, GdkEventButton *event,
1106 G_GNUC_UNUSED gpointer gdata)
1107 {
1108 if (event->button == 1 && event->type == GDK_2BUTTON_PRESS)
1109 {
1110 utils_handle_button_press(widget, event);
1111 menu_item_execute(&inspect_menu_info, apply_item, FALSE);
1112 return TRUE;
1113 }
1114
1115 return FALSE;
1116 }
1117
on_inspect_drag_motion(G_GNUC_UNUSED GtkWidget * widget,G_GNUC_UNUSED GdkDragContext * context,gint x,gint y,G_GNUC_UNUSED guint time,G_GNUC_UNUSED gpointer gdata)1118 gboolean on_inspect_drag_motion(G_GNUC_UNUSED GtkWidget *widget,
1119 G_GNUC_UNUSED GdkDragContext *context, gint x, gint y, G_GNUC_UNUSED guint time,
1120 G_GNUC_UNUSED gpointer gdata)
1121 {
1122 GtkTreePath *path;
1123 GtkTreeViewDropPosition pos;
1124
1125 if (gtk_tree_view_get_dest_row_at_pos(tree, x, y, &path, &pos))
1126 {
1127 GtkTreeIter iter;
1128 const char *name;
1129
1130 scp_tree_store_get_iter(store, &iter, path);
1131 gtk_tree_path_free(path);
1132 scp_tree_store_get(store, &iter, INSPECT_NAME, &name, -1);
1133
1134 if (!name || pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE ||
1135 pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER)
1136 {
1137 g_signal_stop_emission_by_name(tree, "drag-motion");
1138 }
1139 }
1140
1141 return FALSE;
1142 }
1143
on_inspect_menu_show(G_GNUC_UNUSED GtkWidget * widget,G_GNUC_UNUSED gpointer gdata)1144 static void on_inspect_menu_show(G_GNUC_UNUSED GtkWidget *widget, G_GNUC_UNUSED gpointer gdata)
1145 {
1146 GtkTreeIter iter;
1147
1148 if (gtk_tree_selection_get_selected(selection, NULL, &iter))
1149 {
1150 const char *var1, *path_expr;
1151
1152 scp_tree_store_get(store, &iter, INSPECT_VAR1, &var1, INSPECT_PATH_EXPR,
1153 &path_expr, -1);
1154 menu_item_set_active(apply_item, var1 != NULL);
1155
1156 if (var1 && !path_expr && (debug_state() & DS_SENDABLE))
1157 {
1158 debug_send_format(N, "04%d-var-info-path-expression %s",
1159 inspect_get_scid(&iter), var1);
1160 }
1161 }
1162 }
1163
inspect_init(void)1164 void inspect_init(void)
1165 {
1166 GtkWidget *menu;
1167
1168 jump_to_item = get_widget("inspect_jump_to_item");
1169 jump_to_menu = GTK_CONTAINER(get_widget("inspect_jump_to_menu"));
1170 apply_item = menu_item_find(inspect_menu_items, "inspect_apply");
1171
1172 tree = view_connect("inspect_view", &store, &selection, inspect_cells, "inspect_window",
1173 &inspect_display);
1174 g_signal_connect(tree, "test-expand-row", G_CALLBACK(inspect_test_expand_row), NULL);
1175 g_signal_connect(tree, "key-press-event", G_CALLBACK(on_inspect_key_press), NULL);
1176 g_signal_connect(tree, "button-press-event", G_CALLBACK(on_inspect_button_press), NULL);
1177 g_signal_connect(tree, "drag-motion", G_CALLBACK(on_inspect_drag_motion), NULL);
1178
1179 g_signal_connect(store, "row-inserted", G_CALLBACK(on_inspect_row_inserted), NULL);
1180 g_signal_connect(store, "row-changed", G_CALLBACK(on_inspect_row_changed), NULL);
1181 g_signal_connect(store, "row-deleted", G_CALLBACK(on_inspect_row_deleted), NULL);
1182
1183 g_signal_connect(selection, "changed", G_CALLBACK(on_inspect_selection_changed), NULL);
1184 menu = menu_select("inspect_menu", &inspect_menu_info, selection);
1185 g_signal_connect(menu, "show", G_CALLBACK(on_inspect_menu_show), NULL);
1186 if (pref_var_update_bug)
1187 inspect_menu_items->state = DS_DEBUG;
1188
1189 inspect_dialog = dialog_connect("inspect_dialog");
1190 inspect_name = GTK_ENTRY(get_widget("inspect_name_entry"));
1191 validator_attach(GTK_EDITABLE(inspect_name), VALIDATOR_NOSPACE);
1192 g_signal_connect(inspect_name, "changed", G_CALLBACK(on_inspect_entry_changed), NULL);
1193 inspect_frame = GTK_ENTRY(get_widget("inspect_frame_entry"));
1194 validator_attach(GTK_EDITABLE(inspect_frame), VALIDATOR_VARFRAME);
1195 g_signal_connect(inspect_frame, "changed", G_CALLBACK(on_inspect_entry_changed), NULL);
1196 inspect_expr = GTK_ENTRY(get_widget("inspect_expr_entry"));
1197 g_signal_connect(inspect_expr, "changed", G_CALLBACK(on_inspect_entry_changed), NULL);
1198 inspect_run_apply = GTK_TOGGLE_BUTTON(get_widget("inspect_run_apply"));
1199 inspect_ok = get_widget("inspect_ok");
1200 g_signal_connect(inspect_ok, "clicked", G_CALLBACK(on_inspect_ok_button_clicked), NULL);
1201 gtk_widget_grab_default(inspect_ok);
1202
1203 expand_dialog = dialog_connect("expand_dialog");
1204 expand_start = GTK_SPIN_BUTTON(get_widget("expand_start_spin"));
1205 expand_count = GTK_SPIN_BUTTON(get_widget("expand_count_spin"));
1206 expand_automatic = GTK_TOGGLE_BUTTON(get_widget("expand_automatic"));
1207 gtk_widget_grab_default(get_widget("expand_ok"));
1208 }
1209
inspect_finalize(void)1210 void inspect_finalize(void)
1211 {
1212 gtk_widget_destroy(inspect_dialog);
1213 gtk_widget_destroy(expand_dialog);
1214 g_free(jump_to_expr);
1215 }
1216