-rw-r--r-- | scripts/kconfig/gconf.c | 1618 |
1 files changed, 1618 insertions, 0 deletions
diff --git a/scripts/kconfig/gconf.c b/scripts/kconfig/gconf.c new file mode 100644 index 0000000..3227180 --- a/dev/null +++ b/scripts/kconfig/gconf.c | |||
@@ -0,0 +1,1618 @@ | |||
1 | /* Hey EMACS -*- linux-c -*- */ | ||
2 | /* | ||
3 | * | ||
4 | * Copyright (C) 2002-2003 Romain Lievin <roms@lpg.ticalc.org> | ||
5 | * Released under the terms of the GNU GPL v2.0. | ||
6 | * | ||
7 | */ | ||
8 | |||
9 | #ifdef HAVE_CONFIG_H | ||
10 | # include <config.h> | ||
11 | #endif | ||
12 | |||
13 | #include "lkc.h" | ||
14 | #include "images.c" | ||
15 | |||
16 | #include <glade/glade.h> | ||
17 | #include <gtk/gtk.h> | ||
18 | #include <glib.h> | ||
19 | #include <gdk/gdkkeysyms.h> | ||
20 | |||
21 | #include <stdio.h> | ||
22 | #include <string.h> | ||
23 | #include <unistd.h> | ||
24 | #include <time.h> | ||
25 | #include <stdlib.h> | ||
26 | |||
27 | //#define DEBUG | ||
28 | |||
29 | enum { | ||
30 | SINGLE_VIEW, SPLIT_VIEW, FULL_VIEW | ||
31 | }; | ||
32 | |||
33 | static gint view_mode = SPLIT_VIEW; | ||
34 | static gboolean show_name = TRUE; | ||
35 | static gboolean show_range = TRUE; | ||
36 | static gboolean show_value = TRUE; | ||
37 | static gboolean show_all = FALSE; | ||
38 | static gboolean show_debug = FALSE; | ||
39 | static gboolean resizeable = FALSE; | ||
40 | |||
41 | static gboolean config_changed = FALSE; | ||
42 | |||
43 | static char nohelp_text[] = | ||
44 | "Sorry, no help available for this option yet.\n"; | ||
45 | |||
46 | GtkWidget *main_wnd = NULL; | ||
47 | GtkWidget *tree1_w = NULL;// left frame | ||
48 | GtkWidget *tree2_w = NULL;// right frame | ||
49 | GtkWidget *text_w = NULL; | ||
50 | GtkWidget *hpaned = NULL; | ||
51 | GtkWidget *vpaned = NULL; | ||
52 | GtkWidget *back_btn = NULL; | ||
53 | |||
54 | GtkTextTag *tag1, *tag2; | ||
55 | GdkColor color; | ||
56 | |||
57 | GtkTreeStore *tree1, *tree2, *tree; | ||
58 | GtkTreeModel *model1, *model2; | ||
59 | static GtkTreeIter *parents[256] = { 0 }; | ||
60 | static gint indent; | ||
61 | |||
62 | static struct menu *current; | ||
63 | |||
64 | enum { | ||
65 | COL_OPTION, COL_NAME, COL_NO, COL_MOD, COL_YES, COL_VALUE, | ||
66 | COL_MENU, COL_COLOR, COL_EDIT, COL_PIXBUF, | ||
67 | COL_PIXVIS, COL_BTNVIS, COL_BTNACT, COL_BTNINC, COL_BTNRAD, | ||
68 | COL_NUMBER | ||
69 | }; | ||
70 | |||
71 | static void display_list(void); | ||
72 | static void display_tree(struct menu *menu); | ||
73 | static void display_tree_part(void); | ||
74 | static void update_tree(struct menu *src, GtkTreeIter * dst); | ||
75 | static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row); | ||
76 | static gchar **fill_row(struct menu *menu); | ||
77 | |||
78 | |||
79 | /* Helping/Debugging Functions */ | ||
80 | |||
81 | |||
82 | const char *dbg_print_stype(int val) | ||
83 | { | ||
84 | static char buf[256]; | ||
85 | |||
86 | bzero(buf, 256); | ||
87 | |||
88 | if (val == S_UNKNOWN) | ||
89 | strcpy(buf, "unknown"); | ||
90 | if (val == S_BOOLEAN) | ||
91 | strcpy(buf, "boolean"); | ||
92 | if (val == S_TRISTATE) | ||
93 | strcpy(buf, "tristate"); | ||
94 | if (val == S_INT) | ||
95 | strcpy(buf, "int"); | ||
96 | if (val == S_HEX) | ||
97 | strcpy(buf, "hex"); | ||
98 | if (val == S_STRING) | ||
99 | strcpy(buf, "string"); | ||
100 | if (val == S_OTHER) | ||
101 | strcpy(buf, "other"); | ||
102 | |||
103 | #ifdef DEBUG | ||
104 | printf("%s", buf); | ||
105 | #endif | ||
106 | |||
107 | return buf; | ||
108 | } | ||
109 | |||
110 | const char *dbg_print_flags(int val) | ||
111 | { | ||
112 | static char buf[256] = { 0 }; | ||
113 | |||
114 | bzero(buf, 256); | ||
115 | |||
116 | if (val & SYMBOL_YES) | ||
117 | strcat(buf, "yes/"); | ||
118 | if (val & SYMBOL_MOD) | ||
119 | strcat(buf, "mod/"); | ||
120 | if (val & SYMBOL_NO) | ||
121 | strcat(buf, "no/"); | ||
122 | if (val & SYMBOL_CONST) | ||
123 | strcat(buf, "const/"); | ||
124 | if (val & SYMBOL_CHECK) | ||
125 | strcat(buf, "check/"); | ||
126 | if (val & SYMBOL_CHOICE) | ||
127 | strcat(buf, "choice/"); | ||
128 | if (val & SYMBOL_CHOICEVAL) | ||
129 | strcat(buf, "choiceval/"); | ||
130 | if (val & SYMBOL_PRINTED) | ||
131 | strcat(buf, "printed/"); | ||
132 | if (val & SYMBOL_VALID) | ||
133 | strcat(buf, "valid/"); | ||
134 | if (val & SYMBOL_OPTIONAL) | ||
135 | strcat(buf, "optional/"); | ||
136 | if (val & SYMBOL_WRITE) | ||
137 | strcat(buf, "write/"); | ||
138 | if (val & SYMBOL_CHANGED) | ||
139 | strcat(buf, "changed/"); | ||
140 | if (val & SYMBOL_NEW) | ||
141 | strcat(buf, "new/"); | ||
142 | if (val & SYMBOL_AUTO) | ||
143 | strcat(buf, "auto/"); | ||
144 | |||
145 | buf[strlen(buf) - 1] = '\0'; | ||
146 | #ifdef DEBUG | ||
147 | printf("%s", buf); | ||
148 | #endif | ||
149 | |||
150 | return buf; | ||
151 | } | ||
152 | |||
153 | const char *dbg_print_ptype(int val) | ||
154 | { | ||
155 | static char buf[256]; | ||
156 | |||
157 | bzero(buf, 256); | ||
158 | |||
159 | if (val == P_UNKNOWN) | ||
160 | strcpy(buf, "unknown"); | ||
161 | if (val == P_PROMPT) | ||
162 | strcpy(buf, "prompt"); | ||
163 | if (val == P_COMMENT) | ||
164 | strcpy(buf, "comment"); | ||
165 | if (val == P_MENU) | ||
166 | strcpy(buf, "menu"); | ||
167 | if (val == P_DEFAULT) | ||
168 | strcpy(buf, "default"); | ||
169 | if (val == P_CHOICE) | ||
170 | strcpy(buf, "choice"); | ||
171 | |||
172 | #ifdef DEBUG | ||
173 | printf("%s", buf); | ||
174 | #endif | ||
175 | |||
176 | return buf; | ||
177 | } | ||
178 | |||
179 | |||
180 | /* Main Window Initialization */ | ||
181 | |||
182 | |||
183 | void init_main_window(const gchar * glade_file) | ||
184 | { | ||
185 | GladeXML *xml; | ||
186 | GtkWidget *widget; | ||
187 | GtkTextBuffer *txtbuf; | ||
188 | char title[256]; | ||
189 | GdkPixmap *pixmap; | ||
190 | GdkBitmap *mask; | ||
191 | GtkStyle *style; | ||
192 | |||
193 | xml = glade_xml_new(glade_file, "window1", NULL); | ||
194 | if (!xml) | ||
195 | g_error("GUI loading failed !\n"); | ||
196 | glade_xml_signal_autoconnect(xml); | ||
197 | |||
198 | main_wnd = glade_xml_get_widget(xml, "window1"); | ||
199 | hpaned = glade_xml_get_widget(xml, "hpaned1"); | ||
200 | vpaned = glade_xml_get_widget(xml, "vpaned1"); | ||
201 | tree1_w = glade_xml_get_widget(xml, "treeview1"); | ||
202 | tree2_w = glade_xml_get_widget(xml, "treeview2"); | ||
203 | text_w = glade_xml_get_widget(xml, "textview3"); | ||
204 | |||
205 | back_btn = glade_xml_get_widget(xml, "button1"); | ||
206 | gtk_widget_set_sensitive(back_btn, FALSE); | ||
207 | |||
208 | widget = glade_xml_get_widget(xml, "show_name1"); | ||
209 | gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget, | ||
210 | show_name); | ||
211 | |||
212 | widget = glade_xml_get_widget(xml, "show_range1"); | ||
213 | gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget, | ||
214 | show_range); | ||
215 | |||
216 | widget = glade_xml_get_widget(xml, "show_data1"); | ||
217 | gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget, | ||
218 | show_value); | ||
219 | |||
220 | style = gtk_widget_get_style(main_wnd); | ||
221 | widget = glade_xml_get_widget(xml, "toolbar1"); | ||
222 | |||
223 | pixmap = gdk_pixmap_create_from_xpm_d(main_wnd->window, &mask, | ||
224 | &style->bg[GTK_STATE_NORMAL], | ||
225 | (gchar **) xpm_single_view); | ||
226 | gtk_image_set_from_pixmap(GTK_IMAGE | ||
227 | (((GtkToolbarChild | ||
228 | *) (g_list_nth(GTK_TOOLBAR(widget)-> | ||
229 | children, | ||
230 | 5)->data))->icon), | ||
231 | pixmap, mask); | ||
232 | pixmap = | ||
233 | gdk_pixmap_create_from_xpm_d(main_wnd->window, &mask, | ||
234 | &style->bg[GTK_STATE_NORMAL], | ||
235 | (gchar **) xpm_split_view); | ||
236 | gtk_image_set_from_pixmap(GTK_IMAGE | ||
237 | (((GtkToolbarChild | ||
238 | *) (g_list_nth(GTK_TOOLBAR(widget)-> | ||
239 | children, | ||
240 | 6)->data))->icon), | ||
241 | pixmap, mask); | ||
242 | pixmap = | ||
243 | gdk_pixmap_create_from_xpm_d(main_wnd->window, &mask, | ||
244 | &style->bg[GTK_STATE_NORMAL], | ||
245 | (gchar **) xpm_tree_view); | ||
246 | gtk_image_set_from_pixmap(GTK_IMAGE | ||
247 | (((GtkToolbarChild | ||
248 | *) (g_list_nth(GTK_TOOLBAR(widget)-> | ||
249 | children, | ||
250 | 7)->data))->icon), | ||
251 | pixmap, mask); | ||
252 | |||
253 | switch (view_mode) { | ||
254 | case SINGLE_VIEW: | ||
255 | widget = glade_xml_get_widget(xml, "button4"); | ||
256 | gtk_button_clicked(GTK_BUTTON(widget)); | ||
257 | break; | ||
258 | case SPLIT_VIEW: | ||
259 | widget = glade_xml_get_widget(xml, "button5"); | ||
260 | gtk_button_clicked(GTK_BUTTON(widget)); | ||
261 | break; | ||
262 | case FULL_VIEW: | ||
263 | widget = glade_xml_get_widget(xml, "button6"); | ||
264 | gtk_button_clicked(GTK_BUTTON(widget)); | ||
265 | break; | ||
266 | } | ||
267 | |||
268 | txtbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w)); | ||
269 | tag1 = gtk_text_buffer_create_tag(txtbuf, "mytag1", | ||
270 | "foreground", "red", | ||
271 | "weight", PANGO_WEIGHT_BOLD, | ||
272 | NULL); | ||
273 | tag2 = gtk_text_buffer_create_tag(txtbuf, "mytag2", | ||
274 | /*"style", PANGO_STYLE_OBLIQUE, */ | ||
275 | NULL); | ||
276 | |||
277 | sprintf(title, "Build Configuration") | ||
278 | gtk_window_set_title(GTK_WINDOW(main_wnd), title); | ||
279 | |||
280 | gtk_widget_show(main_wnd); | ||
281 | } | ||
282 | |||
283 | void init_tree_model(void) | ||
284 | { | ||
285 | gint i; | ||
286 | |||
287 | tree = tree2 = gtk_tree_store_new(COL_NUMBER, | ||
288 | G_TYPE_STRING, G_TYPE_STRING, | ||
289 | G_TYPE_STRING, G_TYPE_STRING, | ||
290 | G_TYPE_STRING, G_TYPE_STRING, | ||
291 | G_TYPE_POINTER, GDK_TYPE_COLOR, | ||
292 | G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF, | ||
293 | G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, | ||
294 | G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, | ||
295 | G_TYPE_BOOLEAN); | ||
296 | model2 = GTK_TREE_MODEL(tree2); | ||
297 | |||
298 | for (parents[0] = NULL, i = 1; i < 256; i++) | ||
299 | parents[i] = (GtkTreeIter *) g_malloc(sizeof(GtkTreeIter)); | ||
300 | |||
301 | tree1 = gtk_tree_store_new(COL_NUMBER, | ||
302 | G_TYPE_STRING, G_TYPE_STRING, | ||
303 | G_TYPE_STRING, G_TYPE_STRING, | ||
304 | G_TYPE_STRING, G_TYPE_STRING, | ||
305 | G_TYPE_POINTER, GDK_TYPE_COLOR, | ||
306 | G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF, | ||
307 | G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, | ||
308 | G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, | ||
309 | G_TYPE_BOOLEAN); | ||
310 | model1 = GTK_TREE_MODEL(tree1); | ||
311 | } | ||
312 | |||
313 | void init_left_tree(void) | ||
314 | { | ||
315 | GtkTreeView *view = GTK_TREE_VIEW(tree1_w); | ||
316 | GtkCellRenderer *renderer; | ||
317 | GtkTreeSelection *sel; | ||
318 | |||
319 | gtk_tree_view_set_model(view, model1); | ||
320 | gtk_tree_view_set_headers_visible(view, TRUE); | ||
321 | gtk_tree_view_set_rules_hint(view, FALSE); | ||
322 | |||
323 | renderer = gtk_cell_renderer_text_new(); | ||
324 | gtk_tree_view_insert_column_with_attributes(view, -1, | ||
325 | "Options", renderer, | ||
326 | "text", COL_OPTION, | ||
327 | "foreground-gdk", | ||
328 | COL_COLOR, NULL); | ||
329 | |||
330 | sel = gtk_tree_view_get_selection(view); | ||
331 | gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE); | ||
332 | gtk_widget_realize(tree1_w); | ||
333 | } | ||
334 | |||
335 | static void renderer_edited(GtkCellRendererText * cell, | ||
336 | const gchar * path_string, | ||
337 | const gchar * new_text, gpointer user_data); | ||
338 | static void renderer_toggled(GtkCellRendererToggle * cellrenderertoggle, | ||
339 | gchar * arg1, gpointer user_data); | ||
340 | |||
341 | void init_right_tree(void) | ||
342 | { | ||
343 | GtkTreeView *view = GTK_TREE_VIEW(tree2_w); | ||
344 | GtkCellRenderer *renderer; | ||
345 | GtkTreeSelection *sel; | ||
346 | GtkTreeViewColumn *column; | ||
347 | gint i; | ||
348 | |||
349 | gtk_tree_view_set_model(view, model2); | ||
350 | gtk_tree_view_set_headers_visible(view, TRUE); | ||
351 | gtk_tree_view_set_rules_hint(view, FALSE); | ||
352 | |||
353 | column = gtk_tree_view_column_new(); | ||
354 | gtk_tree_view_append_column(view, column); | ||
355 | gtk_tree_view_column_set_title(column, "Options"); | ||
356 | |||
357 | renderer = gtk_cell_renderer_pixbuf_new(); | ||
358 | gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), | ||
359 | renderer, FALSE); | ||
360 | gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), | ||
361 | renderer, | ||
362 | "pixbuf", COL_PIXBUF, | ||
363 | "visible", COL_PIXVIS, NULL); | ||
364 | renderer = gtk_cell_renderer_toggle_new(); | ||
365 | gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), | ||
366 | renderer, FALSE); | ||
367 | gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), | ||
368 | renderer, | ||
369 | "active", COL_BTNACT, | ||
370 | "inconsistent", COL_BTNINC, | ||
371 | "visible", COL_BTNVIS, | ||
372 | "radio", COL_BTNRAD, NULL); | ||
373 | /*g_signal_connect(G_OBJECT(renderer), "toggled", | ||
374 | G_CALLBACK(renderer_toggled), NULL); */ | ||
375 | renderer = gtk_cell_renderer_text_new(); | ||
376 | gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), | ||
377 | renderer, FALSE); | ||
378 | gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), | ||
379 | renderer, | ||
380 | "text", COL_OPTION, | ||
381 | "foreground-gdk", | ||
382 | COL_COLOR, NULL); | ||
383 | |||
384 | renderer = gtk_cell_renderer_text_new(); | ||
385 | gtk_tree_view_insert_column_with_attributes(view, -1, | ||
386 | "Name", renderer, | ||
387 | "text", COL_NAME, | ||
388 | "foreground-gdk", | ||
389 | COL_COLOR, NULL); | ||
390 | renderer = gtk_cell_renderer_text_new(); | ||
391 | gtk_tree_view_insert_column_with_attributes(view, -1, | ||
392 | "N", renderer, | ||
393 | "text", COL_NO, | ||
394 | "foreground-gdk", | ||
395 | COL_COLOR, NULL); | ||
396 | renderer = gtk_cell_renderer_text_new(); | ||
397 | gtk_tree_view_insert_column_with_attributes(view, -1, | ||
398 | "M", renderer, | ||
399 | "text", COL_MOD, | ||
400 | "foreground-gdk", | ||
401 | COL_COLOR, NULL); | ||
402 | renderer = gtk_cell_renderer_text_new(); | ||
403 | gtk_tree_view_insert_column_with_attributes(view, -1, | ||
404 | "Y", renderer, | ||
405 | "text", COL_YES, | ||
406 | "foreground-gdk", | ||
407 | COL_COLOR, NULL); | ||
408 | renderer = gtk_cell_renderer_text_new(); | ||
409 | gtk_tree_view_insert_column_with_attributes(view, -1, | ||
410 | "Value", renderer, | ||
411 | "text", COL_VALUE, | ||
412 | "editable", | ||
413 | COL_EDIT, | ||
414 | "foreground-gdk", | ||
415 | COL_COLOR, NULL); | ||
416 | g_signal_connect(G_OBJECT(renderer), "edited", | ||
417 | G_CALLBACK(renderer_edited), NULL); | ||
418 | |||
419 | column = gtk_tree_view_get_column(view, COL_NAME); | ||
420 | gtk_tree_view_column_set_visible(column, show_name); | ||
421 | column = gtk_tree_view_get_column(view, COL_NO); | ||
422 | gtk_tree_view_column_set_visible(column, show_range); | ||
423 | column = gtk_tree_view_get_column(view, COL_MOD); | ||
424 | gtk_tree_view_column_set_visible(column, show_range); | ||
425 | column = gtk_tree_view_get_column(view, COL_YES); | ||
426 | gtk_tree_view_column_set_visible(column, show_range); | ||
427 | column = gtk_tree_view_get_column(view, COL_VALUE); | ||
428 | gtk_tree_view_column_set_visible(column, show_value); | ||
429 | |||
430 | if (resizeable) { | ||
431 | for (i = 0; i < COL_VALUE; i++) { | ||
432 | column = gtk_tree_view_get_column(view, i); | ||
433 | gtk_tree_view_column_set_resizable(column, TRUE); | ||
434 | } | ||
435 | } | ||
436 | |||
437 | sel = gtk_tree_view_get_selection(view); | ||
438 | gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE); | ||
439 | } | ||
440 | |||
441 | |||
442 | /* Utility Functions */ | ||
443 | |||
444 | |||
445 | static void text_insert_help(struct menu *menu) | ||
446 | { | ||
447 | GtkTextBuffer *buffer; | ||
448 | GtkTextIter start, end; | ||
449 | const char *prompt = menu_get_prompt(menu); | ||
450 | gchar *name; | ||
451 | const char *help = nohelp_text; | ||
452 | |||
453 | if (!menu->sym) | ||
454 | help = ""; | ||
455 | else if (menu->sym->help) | ||
456 | help = menu->sym->help; | ||
457 | |||
458 | if (menu->sym && menu->sym->name) | ||
459 | name = g_strdup_printf(menu->sym->name); | ||
460 | else | ||
461 | name = g_strdup(""); | ||
462 | |||
463 | buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w)); | ||
464 | gtk_text_buffer_get_bounds(buffer, &start, &end); | ||
465 | gtk_text_buffer_delete(buffer, &start, &end); | ||
466 | gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15); | ||
467 | |||
468 | gtk_text_buffer_get_end_iter(buffer, &end); | ||
469 | gtk_text_buffer_insert_with_tags(buffer, &end, prompt, -1, tag1, | ||
470 | NULL); | ||
471 | gtk_text_buffer_insert_at_cursor(buffer, " ", 1); | ||
472 | gtk_text_buffer_get_end_iter(buffer, &end); | ||
473 | gtk_text_buffer_insert_with_tags(buffer, &end, name, -1, tag1, | ||
474 | NULL); | ||
475 | gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2); | ||
476 | gtk_text_buffer_get_end_iter(buffer, &end); | ||
477 | gtk_text_buffer_insert_with_tags(buffer, &end, help, -1, tag2, | ||
478 | NULL); | ||
479 | } | ||
480 | |||
481 | |||
482 | static void text_insert_msg(const char *title, const char *message) | ||
483 | { | ||
484 | GtkTextBuffer *buffer; | ||
485 | GtkTextIter start, end; | ||
486 | const char *msg = message; | ||
487 | |||
488 | buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w)); | ||
489 | gtk_text_buffer_get_bounds(buffer, &start, &end); | ||
490 | gtk_text_buffer_delete(buffer, &start, &end); | ||
491 | gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15); | ||
492 | |||
493 | gtk_text_buffer_get_end_iter(buffer, &end); | ||
494 | gtk_text_buffer_insert_with_tags(buffer, &end, title, -1, tag1, | ||
495 | NULL); | ||
496 | gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2); | ||
497 | gtk_text_buffer_get_end_iter(buffer, &end); | ||
498 | gtk_text_buffer_insert_with_tags(buffer, &end, msg, -1, tag2, | ||
499 | NULL); | ||
500 | } | ||
501 | |||
502 | |||
503 | /* Main Windows Callbacks */ | ||
504 | |||
505 | void on_save1_activate(GtkMenuItem * menuitem, gpointer user_data); | ||
506 | gboolean on_window1_delete_event(GtkWidget * widget, GdkEvent * event, | ||
507 | gpointer user_data) | ||
508 | { | ||
509 | GtkWidget *dialog, *label; | ||
510 | gint result; | ||
511 | |||
512 | if (config_changed == FALSE) | ||
513 | return FALSE; | ||
514 | |||
515 | dialog = gtk_dialog_new_with_buttons("Warning !", | ||
516 | GTK_WINDOW(main_wnd), | ||
517 | (GtkDialogFlags) | ||
518 | (GTK_DIALOG_MODAL | | ||
519 | GTK_DIALOG_DESTROY_WITH_PARENT), | ||
520 | GTK_STOCK_OK, | ||
521 | GTK_RESPONSE_YES, | ||
522 | GTK_STOCK_NO, | ||
523 | GTK_RESPONSE_NO, | ||
524 | GTK_STOCK_CANCEL, | ||
525 | GTK_RESPONSE_CANCEL, NULL); | ||
526 | gtk_dialog_set_default_response(GTK_DIALOG(dialog), | ||
527 | GTK_RESPONSE_CANCEL); | ||
528 | |||
529 | label = gtk_label_new("\nSave configuration ?\n"); | ||
530 | gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label); | ||
531 | gtk_widget_show(label); | ||
532 | |||
533 | result = gtk_dialog_run(GTK_DIALOG(dialog)); | ||
534 | switch (result) { | ||
535 | case GTK_RESPONSE_YES: | ||
536 | on_save1_activate(NULL, NULL); | ||
537 | return FALSE; | ||
538 | case GTK_RESPONSE_NO: | ||
539 | return FALSE; | ||
540 | case GTK_RESPONSE_CANCEL: | ||
541 | case GTK_RESPONSE_DELETE_EVENT: | ||
542 | default: | ||
543 | gtk_widget_destroy(dialog); | ||
544 | return TRUE; | ||
545 | } | ||
546 | |||
547 | return FALSE; | ||
548 | } | ||
549 | |||
550 | |||
551 | void on_window1_destroy(GtkObject * object, gpointer user_data) | ||
552 | { | ||
553 | gtk_main_quit(); | ||
554 | } | ||
555 | |||
556 | |||
557 | void | ||
558 | on_window1_size_request(GtkWidget * widget, | ||
559 | GtkRequisition * requisition, gpointer user_data) | ||
560 | { | ||
561 | static gint old_h = 0; | ||
562 | gint w, h; | ||
563 | |||
564 | if (widget->window == NULL) | ||
565 | gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h); | ||
566 | else | ||
567 | gdk_window_get_size(widget->window, &w, &h); | ||
568 | |||
569 | if (h == old_h) | ||
570 | return; | ||
571 | old_h = h; | ||
572 | |||
573 | gtk_paned_set_position(GTK_PANED(vpaned), 2 * h / 3); | ||
574 | } | ||
575 | |||
576 | |||
577 | /* Menu & Toolbar Callbacks */ | ||
578 | |||
579 | |||
580 | static void | ||
581 | load_filename(GtkFileSelection * file_selector, gpointer user_data) | ||
582 | { | ||
583 | const gchar *fn; | ||
584 | |||
585 | fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION | ||
586 | (user_data)); | ||
587 | |||
588 | if (conf_read(fn)) | ||
589 | text_insert_msg("Error", "Unable to load configuration !"); | ||
590 | else | ||
591 | display_tree(&rootmenu); | ||
592 | } | ||
593 | |||
594 | void on_load1_activate(GtkMenuItem * menuitem, gpointer user_data) | ||
595 | { | ||
596 | GtkWidget *fs; | ||
597 | |||
598 | fs = gtk_file_selection_new("Load file..."); | ||
599 | g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button), | ||
600 | "clicked", | ||
601 | G_CALLBACK(load_filename), (gpointer) fs); | ||
602 | g_signal_connect_swapped(GTK_OBJECT | ||
603 | (GTK_FILE_SELECTION(fs)->ok_button), | ||
604 | "clicked", G_CALLBACK(gtk_widget_destroy), | ||
605 | (gpointer) fs); | ||
606 | g_signal_connect_swapped(GTK_OBJECT | ||
607 | (GTK_FILE_SELECTION(fs)->cancel_button), | ||
608 | "clicked", G_CALLBACK(gtk_widget_destroy), | ||
609 | (gpointer) fs); | ||
610 | gtk_widget_show(fs); | ||
611 | } | ||
612 | |||
613 | |||
614 | void on_save1_activate(GtkMenuItem * menuitem, gpointer user_data) | ||
615 | { | ||
616 | if (conf_write(NULL)) | ||
617 | text_insert_msg("Error", "Unable to save configuration !"); | ||
618 | |||
619 | config_changed = FALSE; | ||
620 | } | ||
621 | |||
622 | |||
623 | static void | ||
624 | store_filename(GtkFileSelection * file_selector, gpointer user_data) | ||
625 | { | ||
626 | const gchar *fn; | ||
627 | |||
628 | fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION | ||
629 | (user_data)); | ||
630 | |||
631 | if (conf_write(fn)) | ||
632 | text_insert_msg("Error", "Unable to save configuration !"); | ||
633 | |||
634 | gtk_widget_destroy(GTK_WIDGET(user_data)); | ||
635 | } | ||
636 | |||
637 | void on_save_as1_activate(GtkMenuItem * menuitem, gpointer user_data) | ||
638 | { | ||
639 | GtkWidget *fs; | ||
640 | |||
641 | fs = gtk_file_selection_new("Save file as..."); | ||
642 | g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button), | ||
643 | "clicked", | ||
644 | G_CALLBACK(store_filename), (gpointer) fs); | ||
645 | g_signal_connect_swapped(GTK_OBJECT | ||
646 | (GTK_FILE_SELECTION(fs)->ok_button), | ||
647 | "clicked", G_CALLBACK(gtk_widget_destroy), | ||
648 | (gpointer) fs); | ||
649 | g_signal_connect_swapped(GTK_OBJECT | ||
650 | (GTK_FILE_SELECTION(fs)->cancel_button), | ||
651 | "clicked", G_CALLBACK(gtk_widget_destroy), | ||
652 | (gpointer) fs); | ||
653 | gtk_widget_show(fs); | ||
654 | } | ||
655 | |||
656 | |||
657 | void on_quit1_activate(GtkMenuItem * menuitem, gpointer user_data) | ||
658 | { | ||
659 | if (!on_window1_delete_event(NULL, NULL, NULL)) | ||
660 | gtk_widget_destroy(GTK_WIDGET(main_wnd)); | ||
661 | } | ||
662 | |||
663 | |||
664 | void on_show_name1_activate(GtkMenuItem * menuitem, gpointer user_data) | ||
665 | { | ||
666 | GtkTreeViewColumn *col; | ||
667 | |||
668 | show_name = GTK_CHECK_MENU_ITEM(menuitem)->active; | ||
669 | col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NAME); | ||
670 | if (col) | ||
671 | gtk_tree_view_column_set_visible(col, show_name); | ||
672 | } | ||
673 | |||
674 | |||
675 | void on_show_range1_activate(GtkMenuItem * menuitem, gpointer user_data) | ||
676 | { | ||
677 | GtkTreeViewColumn *col; | ||
678 | |||
679 | show_range = GTK_CHECK_MENU_ITEM(menuitem)->active; | ||
680 | col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NO); | ||
681 | if (col) | ||
682 | gtk_tree_view_column_set_visible(col, show_range); | ||
683 | col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_MOD); | ||
684 | if (col) | ||
685 | gtk_tree_view_column_set_visible(col, show_range); | ||
686 | col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_YES); | ||
687 | if (col) | ||
688 | gtk_tree_view_column_set_visible(col, show_range); | ||
689 | |||
690 | } | ||
691 | |||
692 | |||
693 | void on_show_data1_activate(GtkMenuItem * menuitem, gpointer user_data) | ||
694 | { | ||
695 | GtkTreeViewColumn *col; | ||
696 | |||
697 | show_value = GTK_CHECK_MENU_ITEM(menuitem)->active; | ||
698 | col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_VALUE); | ||
699 | if (col) | ||
700 | gtk_tree_view_column_set_visible(col, show_value); | ||
701 | } | ||
702 | |||
703 | |||
704 | void | ||
705 | on_show_all_options1_activate(GtkMenuItem * menuitem, gpointer user_data) | ||
706 | { | ||
707 | show_all = GTK_CHECK_MENU_ITEM(menuitem)->active; | ||
708 | |||
709 | gtk_tree_store_clear(tree2); | ||
710 | display_tree(&rootmenu);// instead of update_tree for speed reasons | ||
711 | } | ||
712 | |||
713 | |||
714 | void | ||
715 | on_show_debug_info1_activate(GtkMenuItem * menuitem, gpointer user_data) | ||
716 | { | ||
717 | show_debug = GTK_CHECK_MENU_ITEM(menuitem)->active; | ||
718 | update_tree(&rootmenu, NULL); | ||
719 | } | ||
720 | |||
721 | |||
722 | void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data) | ||
723 | { | ||
724 | GtkWidget *dialog; | ||
725 | const gchar *intro_text = | ||
726 | "Welcome to gkc, the GTK+ graphical configuration tool\n" | ||
727 | "for Linux.\n" | ||
728 | "For each option, a blank box indicates the feature is disabled, a\n" | ||
729 | "check indicates it is enabled, and a dot indicates that it is to\n" | ||
730 | "be compiled as a module. Clicking on the box will cycle through the three states.\n" | ||
731 | "\n" | ||
732 | "If you do not see an option (e.g., a device driver) that you\n" | ||
733 | "believe should be present, try turning on Show All Options\n" | ||
734 | "under the Options menu.\n" | ||
735 | "Although there is no cross reference yet to help you figure out\n" | ||
736 | "what other options must be enabled to support the option you\n" | ||
737 | "are interested in, you can still view the help of a grayed-out\n" | ||
738 | "option.\n" | ||
739 | "\n" | ||
740 | "Toggling Show Debug Info under the Options menu will show \n" | ||
741 | "the dependencies, which you can then match by examining other options."; | ||
742 | |||
743 | dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd), | ||
744 | GTK_DIALOG_DESTROY_WITH_PARENT, | ||
745 | GTK_MESSAGE_INFO, | ||
746 | GTK_BUTTONS_CLOSE, intro_text); | ||
747 | g_signal_connect_swapped(GTK_OBJECT(dialog), "response", | ||
748 | G_CALLBACK(gtk_widget_destroy), | ||
749 | GTK_OBJECT(dialog)); | ||
750 | gtk_widget_show_all(dialog); | ||
751 | } | ||
752 | |||
753 | |||
754 | void on_about1_activate(GtkMenuItem * menuitem, gpointer user_data) | ||
755 | { | ||
756 | GtkWidget *dialog; | ||
757 | const gchar *about_text = | ||
758 | "gkc is copyright (c) 2002 Romain Lievin <roms@lpg.ticalc.org>.\n" | ||
759 | "Based on the source code from Roman Zippel.\n"; | ||
760 | |||
761 | dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd), | ||
762 | GTK_DIALOG_DESTROY_WITH_PARENT, | ||
763 | GTK_MESSAGE_INFO, | ||
764 | GTK_BUTTONS_CLOSE, about_text); | ||
765 | g_signal_connect_swapped(GTK_OBJECT(dialog), "response", | ||
766 | G_CALLBACK(gtk_widget_destroy), | ||
767 | GTK_OBJECT(dialog)); | ||
768 | gtk_widget_show_all(dialog); | ||
769 | } | ||
770 | |||
771 | |||
772 | void on_license1_activate(GtkMenuItem * menuitem, gpointer user_data) | ||
773 | { | ||
774 | GtkWidget *dialog; | ||
775 | const gchar *license_text = | ||
776 | "gkc is released under the terms of the GNU GPL v2.\n" | ||
777 | "For more information, please see the source code or\n" | ||
778 | "visit http://www.fsf.org/licenses/licenses.html\n"; | ||
779 | |||
780 | dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd), | ||
781 | GTK_DIALOG_DESTROY_WITH_PARENT, | ||
782 | GTK_MESSAGE_INFO, | ||
783 | GTK_BUTTONS_CLOSE, license_text); | ||
784 | g_signal_connect_swapped(GTK_OBJECT(dialog), "response", | ||
785 | G_CALLBACK(gtk_widget_destroy), | ||
786 | GTK_OBJECT(dialog)); | ||
787 | gtk_widget_show_all(dialog); | ||
788 | } | ||
789 | |||
790 | |||
791 | void on_back_pressed(GtkButton * button, gpointer user_data) | ||
792 | { | ||
793 | enum prop_type ptype; | ||
794 | |||
795 | current = current->parent; | ||
796 | ptype = current->prompt ? current->prompt->type : P_UNKNOWN; | ||
797 | if (ptype != P_MENU) | ||
798 | current = current->parent; | ||
799 | display_tree_part(); | ||
800 | |||
801 | if (current == &rootmenu) | ||
802 | gtk_widget_set_sensitive(back_btn, FALSE); | ||
803 | } | ||
804 | |||
805 | |||
806 | void on_load_pressed(GtkButton * button, gpointer user_data) | ||
807 | { | ||
808 | on_load1_activate(NULL, user_data); | ||
809 | } | ||
810 | |||
811 | |||
812 | void on_save_pressed(GtkButton * button, gpointer user_data) | ||
813 | { | ||
814 | on_save1_activate(NULL, user_data); | ||
815 | } | ||
816 | |||
817 | |||
818 | void on_single_clicked(GtkButton * button, gpointer user_data) | ||
819 | { | ||
820 | view_mode = SINGLE_VIEW; | ||
821 | gtk_paned_set_position(GTK_PANED(hpaned), 0); | ||
822 | gtk_widget_hide(tree1_w); | ||
823 | current = &rootmenu; | ||
824 | display_tree_part(); | ||
825 | } | ||
826 | |||
827 | |||
828 | void on_split_clicked(GtkButton * button, gpointer user_data) | ||
829 | { | ||
830 | gint w, h; | ||
831 | view_mode = SPLIT_VIEW; | ||
832 | gtk_widget_show(tree1_w); | ||
833 | gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h); | ||
834 | gtk_paned_set_position(GTK_PANED(hpaned), w / 2); | ||
835 | if (tree2) | ||
836 | gtk_tree_store_clear(tree2); | ||
837 | display_list(); | ||
838 | } | ||
839 | |||
840 | |||
841 | void on_full_clicked(GtkButton * button, gpointer user_data) | ||
842 | { | ||
843 | view_mode = FULL_VIEW; | ||
844 | gtk_paned_set_position(GTK_PANED(hpaned), 0); | ||
845 | gtk_widget_hide(tree1_w); | ||
846 | if (tree2) | ||
847 | gtk_tree_store_clear(tree2); | ||
848 | display_tree(&rootmenu); | ||
849 | gtk_widget_set_sensitive(back_btn, FALSE); | ||
850 | } | ||
851 | |||
852 | |||
853 | void on_collapse_pressed(GtkButton * button, gpointer user_data) | ||
854 | { | ||
855 | gtk_tree_view_collapse_all(GTK_TREE_VIEW(tree2_w)); | ||
856 | } | ||
857 | |||
858 | |||
859 | void on_expand_pressed(GtkButton * button, gpointer user_data) | ||
860 | { | ||
861 | gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w)); | ||
862 | } | ||
863 | |||
864 | |||
865 | /* CTree Callbacks */ | ||
866 | |||
867 | /* Change hex/int/string value in the cell */ | ||
868 | static void renderer_edited(GtkCellRendererText * cell, | ||
869 | const gchar * path_string, | ||
870 | const gchar * new_text, gpointer user_data) | ||
871 | { | ||
872 | GtkTreePath *path = gtk_tree_path_new_from_string(path_string); | ||
873 | GtkTreeIter iter; | ||
874 | const char *old_def, *new_def; | ||
875 | struct menu *menu; | ||
876 | struct symbol *sym; | ||
877 | |||
878 | if (!gtk_tree_model_get_iter(model2, &iter, path)) | ||
879 | return; | ||
880 | |||
881 | gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); | ||
882 | sym = menu->sym; | ||
883 | |||
884 | gtk_tree_model_get(model2, &iter, COL_VALUE, &old_def, -1); | ||
885 | new_def = new_text; | ||
886 | |||
887 | sym_set_string_value(sym, new_def); | ||
888 | |||
889 | config_changed = TRUE; | ||
890 | update_tree(&rootmenu, NULL); | ||
891 | |||
892 | gtk_tree_path_free(path); | ||
893 | } | ||
894 | |||
895 | /* Change the value of a symbol and update the tree */ | ||
896 | static void change_sym_value(struct menu *menu, gint col) | ||
897 | { | ||
898 | struct symbol *sym = menu->sym; | ||
899 | tristate oldval, newval; | ||
900 | |||
901 | if (!sym) | ||
902 | return; | ||
903 | |||
904 | if (col == COL_NO) | ||
905 | newval = no; | ||
906 | else if (col == COL_MOD) | ||
907 | newval = mod; | ||
908 | else if (col == COL_YES) | ||
909 | newval = yes; | ||
910 | else | ||
911 | return; | ||
912 | |||
913 | switch (sym_get_type(sym)) { | ||
914 | case S_BOOLEAN: | ||
915 | case S_TRISTATE: | ||
916 | oldval = sym_get_tristate_value(sym); | ||
917 | if (!sym_tristate_within_range(sym, newval)) | ||
918 | newval = yes; | ||
919 | sym_set_tristate_value(sym, newval); | ||
920 | config_changed = TRUE; | ||
921 | if (view_mode == FULL_VIEW) | ||
922 | update_tree(&rootmenu, NULL); | ||
923 | else if (view_mode == SPLIT_VIEW) { | ||
924 | update_tree(current, NULL); | ||
925 | display_list(); | ||
926 | } | ||
927 | else if (view_mode == SINGLE_VIEW) | ||
928 | display_tree_part();//fixme: keep exp/coll | ||
929 | break; | ||
930 | case S_INT: | ||
931 | case S_HEX: | ||
932 | case S_STRING: | ||
933 | default: | ||
934 | break; | ||
935 | } | ||
936 | } | ||
937 | |||
938 | static void toggle_sym_value(struct menu *menu) | ||
939 | { | ||
940 | const tristate next_val[3] = { no, mod, yes }; | ||
941 | tristate newval; | ||
942 | |||
943 | if (!menu->sym) | ||
944 | return; | ||
945 | |||
946 | newval = next_val[(sym_get_tristate_value(menu->sym) + 1) % 3]; | ||
947 | if (!sym_tristate_within_range(menu->sym, newval)) | ||
948 | newval = yes; | ||
949 | sym_set_tristate_value(menu->sym, newval); | ||
950 | if (view_mode == FULL_VIEW) | ||
951 | update_tree(&rootmenu, NULL); | ||
952 | else if (view_mode == SPLIT_VIEW) { | ||
953 | update_tree(current, NULL); | ||
954 | display_list(); | ||
955 | } | ||
956 | else if (view_mode == SINGLE_VIEW) | ||
957 | display_tree_part();//fixme: keep exp/coll | ||
958 | } | ||
959 | |||
960 | static void renderer_toggled(GtkCellRendererToggle * cell, | ||
961 | gchar * path_string, gpointer user_data) | ||
962 | { | ||
963 | GtkTreePath *path, *sel_path = NULL; | ||
964 | GtkTreeIter iter, sel_iter; | ||
965 | GtkTreeSelection *sel; | ||
966 | struct menu *menu; | ||
967 | |||
968 | path = gtk_tree_path_new_from_string(path_string); | ||
969 | if (!gtk_tree_model_get_iter(model2, &iter, path)) | ||
970 | return; | ||
971 | |||
972 | sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree2_w)); | ||
973 | if (gtk_tree_selection_get_selected(sel, NULL, &sel_iter)) | ||
974 | sel_path = gtk_tree_model_get_path(model2, &sel_iter); | ||
975 | if (!sel_path) | ||
976 | goto out1; | ||
977 | if (gtk_tree_path_compare(path, sel_path)) | ||
978 | goto out2; | ||
979 | |||
980 | gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); | ||
981 | toggle_sym_value(menu); | ||
982 | |||
983 | out2: | ||
984 | gtk_tree_path_free(sel_path); | ||
985 | out1: | ||
986 | gtk_tree_path_free(path); | ||
987 | } | ||
988 | |||
989 | static gint column2index(GtkTreeViewColumn * column) | ||
990 | { | ||
991 | gint i; | ||
992 | |||
993 | for (i = 0; i < COL_NUMBER; i++) { | ||
994 | GtkTreeViewColumn *col; | ||
995 | |||
996 | col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), i); | ||
997 | if (col == column) | ||
998 | return i; | ||
999 | } | ||
1000 | |||
1001 | return -1; | ||
1002 | } | ||
1003 | |||
1004 | |||
1005 | //#define GTK_BUG_FIXED // uncomment it for GTK+ >= 2.1.4 (2.2) | ||
1006 | |||
1007 | /* User click: update choice (full) or goes down (single) */ | ||
1008 | gboolean | ||
1009 | on_treeview2_button_press_event(GtkWidget * widget, | ||
1010 | GdkEventButton * event, gpointer user_data) | ||
1011 | { | ||
1012 | GtkTreeView *view = GTK_TREE_VIEW(widget); | ||
1013 | GtkTreePath *path; | ||
1014 | GtkTreeViewColumn *column; | ||
1015 | GtkTreeIter iter; | ||
1016 | struct menu *menu; | ||
1017 | gint col; | ||
1018 | |||
1019 | #ifdef GTK_BUG_FIXED | ||
1020 | gint tx = (gint) event->x; | ||
1021 | gint ty = (gint) event->y; | ||
1022 | gint cx, cy; | ||
1023 | |||
1024 | gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx, | ||
1025 | &cy); | ||
1026 | #else | ||
1027 | gtk_tree_view_get_cursor(view, &path, &column); | ||
1028 | #endif | ||
1029 | if (path == NULL) | ||
1030 | return FALSE; | ||
1031 | |||
1032 | gtk_tree_model_get_iter(model2, &iter, path); | ||
1033 | gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); | ||
1034 | |||
1035 | col = column2index(column); | ||
1036 | if (event->type == GDK_2BUTTON_PRESS) { | ||
1037 | enum prop_type ptype; | ||
1038 | ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN; | ||
1039 | |||
1040 | if (ptype == P_MENU && view_mode != FULL_VIEW && col == COL_OPTION) { | ||
1041 | // goes down into menu | ||
1042 | current = menu; | ||
1043 | display_tree_part(); | ||
1044 | gtk_widget_set_sensitive(back_btn, TRUE); | ||
1045 | } else if ((col == COL_OPTION)) { | ||
1046 | toggle_sym_value(menu); | ||
1047 | gtk_tree_view_expand_row(view, path, TRUE); | ||
1048 | } | ||
1049 | } else { | ||
1050 | if (col == COL_VALUE) { | ||
1051 | toggle_sym_value(menu); | ||
1052 | gtk_tree_view_expand_row(view, path, TRUE); | ||
1053 | } else if (col == COL_NO || col == COL_MOD | ||
1054 | || col == COL_YES) { | ||
1055 | change_sym_value(menu, col); | ||
1056 | gtk_tree_view_expand_row(view, path, TRUE); | ||
1057 | } | ||
1058 | } | ||
1059 | |||
1060 | return FALSE; | ||
1061 | } | ||
1062 | |||
1063 | /* Key pressed: update choice */ | ||
1064 | gboolean | ||
1065 | on_treeview2_key_press_event(GtkWidget * widget, | ||
1066 | GdkEventKey * event, gpointer user_data) | ||
1067 | { | ||
1068 | GtkTreeView *view = GTK_TREE_VIEW(widget); | ||
1069 | GtkTreePath *path; | ||
1070 | GtkTreeViewColumn *column; | ||
1071 | GtkTreeIter iter; | ||
1072 | struct menu *menu; | ||
1073 | gint col; | ||
1074 | |||
1075 | gtk_tree_view_get_cursor(view, &path, &column); | ||
1076 | if (path == NULL) | ||
1077 | return FALSE; | ||
1078 | |||
1079 | if (event->keyval == GDK_space) { | ||
1080 | if (gtk_tree_view_row_expanded(view, path)) | ||
1081 | gtk_tree_view_collapse_row(view, path); | ||
1082 | else | ||
1083 | gtk_tree_view_expand_row(view, path, FALSE); | ||
1084 | return TRUE; | ||
1085 | } | ||
1086 | if (event->keyval == GDK_KP_Enter) { | ||
1087 | } | ||
1088 | if (widget == tree1_w) | ||
1089 | return FALSE; | ||
1090 | |||
1091 | gtk_tree_model_get_iter(model2, &iter, path); | ||
1092 | gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); | ||
1093 | |||
1094 | if (!strcasecmp(event->string, "n")) | ||
1095 | col = COL_NO; | ||
1096 | else if (!strcasecmp(event->string, "m")) | ||
1097 | col = COL_MOD; | ||
1098 | else if (!strcasecmp(event->string, "y")) | ||
1099 | col = COL_YES; | ||
1100 | else | ||
1101 | col = -1; | ||
1102 | change_sym_value(menu, col); | ||
1103 | |||
1104 | return FALSE; | ||
1105 | } | ||
1106 | |||
1107 | |||
1108 | /* Row selection changed: update help */ | ||
1109 | void | ||
1110 | on_treeview2_cursor_changed(GtkTreeView * treeview, gpointer user_data) | ||
1111 | { | ||
1112 | GtkTreeSelection *selection; | ||
1113 | GtkTreeIter iter; | ||
1114 | struct menu *menu; | ||
1115 | |||
1116 | selection = gtk_tree_view_get_selection(treeview); | ||
1117 | if (gtk_tree_selection_get_selected(selection, &model2, &iter)) { | ||
1118 | gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); | ||
1119 | text_insert_help(menu); | ||
1120 | } | ||
1121 | } | ||
1122 | |||
1123 | |||
1124 | /* User click: display sub-tree in the right frame. */ | ||
1125 | gboolean | ||
1126 | on_treeview1_button_press_event(GtkWidget * widget, | ||
1127 | GdkEventButton * event, gpointer user_data) | ||
1128 | { | ||
1129 | GtkTreeView *view = GTK_TREE_VIEW(widget); | ||
1130 | GtkTreePath *path; | ||
1131 | GtkTreeViewColumn *column; | ||
1132 | GtkTreeIter iter; | ||
1133 | struct menu *menu; | ||
1134 | |||
1135 | gint tx = (gint) event->x; | ||
1136 | gint ty = (gint) event->y; | ||
1137 | gint cx, cy; | ||
1138 | |||
1139 | gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx, | ||
1140 | &cy); | ||
1141 | if (path == NULL) | ||
1142 | return FALSE; | ||
1143 | |||
1144 | gtk_tree_model_get_iter(model1, &iter, path); | ||
1145 | gtk_tree_model_get(model1, &iter, COL_MENU, &menu, -1); | ||
1146 | |||
1147 | if (event->type == GDK_2BUTTON_PRESS) { | ||
1148 | toggle_sym_value(menu); | ||
1149 | current = menu; | ||
1150 | display_tree_part(); | ||
1151 | } else { | ||
1152 | current = menu; | ||
1153 | display_tree_part(); | ||
1154 | } | ||
1155 | |||
1156 | gtk_widget_realize(tree2_w); | ||
1157 | gtk_tree_view_set_cursor(view, path, NULL, FALSE); | ||
1158 | gtk_widget_grab_focus(GTK_TREE_VIEW(tree2_w)); | ||
1159 | |||
1160 | return FALSE; | ||
1161 | } | ||
1162 | |||
1163 | |||
1164 | /* Conf management */ | ||
1165 | |||
1166 | |||
1167 | /* Fill a row of strings */ | ||
1168 | static gchar **fill_row(struct menu *menu) | ||
1169 | { | ||
1170 | static gchar *row[COL_NUMBER] = { 0 }; | ||
1171 | struct symbol *sym = menu->sym; | ||
1172 | const char *def; | ||
1173 | int stype; | ||
1174 | tristate val; | ||
1175 | enum prop_type ptype; | ||
1176 | int i; | ||
1177 | |||
1178 | for (i = COL_OPTION; i <= COL_COLOR; i++) | ||
1179 | g_free(row[i]); | ||
1180 | bzero(row, sizeof(row)); | ||
1181 | |||
1182 | row[COL_OPTION] = | ||
1183 | g_strdup_printf("%s %s", menu_get_prompt(menu), | ||
1184 | sym ? (sym-> | ||
1185 | flags & SYMBOL_NEW ? "(NEW)" : "") : | ||
1186 | ""); | ||
1187 | |||
1188 | if (show_all && !menu_is_visible(menu)) | ||
1189 | row[COL_COLOR] = g_strdup("DarkGray"); | ||
1190 | else | ||
1191 | row[COL_COLOR] = g_strdup("Black"); | ||
1192 | |||
1193 | ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN; | ||
1194 | switch (ptype) { | ||
1195 | case P_MENU: | ||
1196 | row[COL_PIXBUF] = (gchar *) xpm_menu; | ||
1197 | if (view_mode != FULL_VIEW) | ||
1198 | row[COL_PIXVIS] = GINT_TO_POINTER(TRUE); | ||
1199 | row[COL_BTNVIS] = GINT_TO_POINTER(FALSE); | ||
1200 | break; | ||
1201 | case P_COMMENT: | ||
1202 | row[COL_PIXBUF] = (gchar *) xpm_void; | ||
1203 | row[COL_PIXVIS] = GINT_TO_POINTER(FALSE); | ||
1204 | row[COL_BTNVIS] = GINT_TO_POINTER(FALSE); | ||
1205 | break; | ||
1206 | default: | ||
1207 | row[COL_PIXBUF] = (gchar *) xpm_void; | ||
1208 | row[COL_PIXVIS] = GINT_TO_POINTER(FALSE); | ||
1209 | row[COL_BTNVIS] = GINT_TO_POINTER(TRUE); | ||
1210 | break; | ||
1211 | } | ||
1212 | |||
1213 | if (!sym) | ||
1214 | return row; | ||
1215 | row[COL_NAME] = g_strdup(sym->name); | ||
1216 | |||
1217 | sym_calc_value(sym); | ||
1218 | sym->flags &= ~SYMBOL_CHANGED; | ||
1219 | |||
1220 | if (sym_is_choice(sym)) {// parse childs for getting final value | ||
1221 | struct menu *child; | ||
1222 | struct symbol *def_sym = sym_get_choice_value(sym); | ||
1223 | struct menu *def_menu = NULL; | ||
1224 | |||
1225 | row[COL_BTNVIS] = GINT_TO_POINTER(FALSE); | ||
1226 | |||
1227 | for (child = menu->list; child; child = child->next) { | ||
1228 | if (menu_is_visible(child) | ||
1229 | && child->sym == def_sym) | ||
1230 | def_menu = child; | ||
1231 | } | ||
1232 | |||
1233 | if (def_menu) | ||
1234 | row[COL_VALUE] = | ||
1235 | g_strdup(menu_get_prompt(def_menu)); | ||
1236 | } | ||
1237 | if(sym->flags & SYMBOL_CHOICEVAL) | ||
1238 | row[COL_BTNRAD] = GINT_TO_POINTER(TRUE); | ||
1239 | |||
1240 | stype = sym_get_type(sym); | ||
1241 | switch (stype) { | ||
1242 | case S_BOOLEAN: | ||
1243 | if (sym_is_choice(sym)) | ||
1244 | break; | ||
1245 | case S_TRISTATE: | ||
1246 | val = sym_get_tristate_value(sym); | ||
1247 | switch (val) { | ||
1248 | case no: | ||
1249 | row[COL_NO] = g_strdup("N"); | ||
1250 | row[COL_VALUE] = g_strdup("N"); | ||
1251 | row[COL_BTNACT] = GINT_TO_POINTER(FALSE); | ||
1252 | row[COL_BTNINC] = GINT_TO_POINTER(FALSE); | ||
1253 | break; | ||
1254 | case mod: | ||
1255 | row[COL_MOD] = g_strdup("M"); | ||
1256 | row[COL_VALUE] = g_strdup("M"); | ||
1257 | row[COL_BTNINC] = GINT_TO_POINTER(TRUE); | ||
1258 | break; | ||
1259 | case yes: | ||
1260 | row[COL_YES] = g_strdup("Y"); | ||
1261 | row[COL_VALUE] = g_strdup("Y"); | ||
1262 | row[COL_BTNACT] = GINT_TO_POINTER(TRUE); | ||
1263 | row[COL_BTNINC] = GINT_TO_POINTER(FALSE); | ||
1264 | break; | ||
1265 | } | ||
1266 | |||
1267 | if (val != no && sym_tristate_within_range(sym, no)) | ||
1268 | row[COL_NO] = g_strdup("_"); | ||
1269 | if (val != mod && sym_tristate_within_range(sym, mod)) | ||
1270 | row[COL_MOD] = g_strdup("_"); | ||
1271 | if (val != yes && sym_tristate_within_range(sym, yes)) | ||
1272 | row[COL_YES] = g_strdup("_"); | ||
1273 | break; | ||
1274 | case S_INT: | ||
1275 | case S_HEX: | ||
1276 | case S_STRING: | ||
1277 | def = sym_get_string_value(sym); | ||
1278 | row[COL_VALUE] = g_strdup(def); | ||
1279 | row[COL_EDIT] = GINT_TO_POINTER(TRUE); | ||
1280 | row[COL_BTNVIS] = GINT_TO_POINTER(FALSE); | ||
1281 | break; | ||
1282 | } | ||
1283 | |||
1284 | return row; | ||
1285 | } | ||
1286 | |||
1287 | |||
1288 | /* Set the node content with a row of strings */ | ||
1289 | static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row) | ||
1290 | { | ||
1291 | GdkColor color; | ||
1292 | gboolean success; | ||
1293 | GdkPixbuf *pix; | ||
1294 | |||
1295 | pix = gdk_pixbuf_new_from_xpm_data((const char **) | ||
1296 | row[COL_PIXBUF]); | ||
1297 | |||
1298 | gdk_color_parse(row[COL_COLOR], &color); | ||
1299 | gdk_colormap_alloc_colors(gdk_colormap_get_system(), &color, 1, | ||
1300 | FALSE, FALSE, &success); | ||
1301 | |||
1302 | gtk_tree_store_set(tree, node, | ||
1303 | COL_OPTION, row[COL_OPTION], | ||
1304 | COL_NAME, row[COL_NAME], | ||
1305 | COL_NO, row[COL_NO], | ||
1306 | COL_MOD, row[COL_MOD], | ||
1307 | COL_YES, row[COL_YES], | ||
1308 | COL_VALUE, row[COL_VALUE], | ||
1309 | COL_MENU, (gpointer) menu, | ||
1310 | COL_COLOR, &color, | ||
1311 | COL_EDIT, GPOINTER_TO_INT(row[COL_EDIT]), | ||
1312 | COL_PIXBUF, pix, | ||
1313 | COL_PIXVIS, GPOINTER_TO_INT(row[COL_PIXVIS]), | ||
1314 | COL_BTNVIS, GPOINTER_TO_INT(row[COL_BTNVIS]), | ||
1315 | COL_BTNACT, GPOINTER_TO_INT(row[COL_BTNACT]), | ||
1316 | COL_BTNINC, GPOINTER_TO_INT(row[COL_BTNINC]), | ||
1317 | COL_BTNRAD, GPOINTER_TO_INT(row[COL_BTNRAD]), | ||
1318 | -1); | ||
1319 | |||
1320 | g_object_unref(pix); | ||
1321 | } | ||
1322 | |||
1323 | |||
1324 | /* Add a node to the tree */ | ||
1325 | static void place_node(struct menu *menu, char **row) | ||
1326 | { | ||
1327 | GtkTreeIter *parent = parents[indent - 1]; | ||
1328 | GtkTreeIter *node = parents[indent]; | ||
1329 | |||
1330 | gtk_tree_store_append(tree, node, parent); | ||
1331 | set_node(node, menu, row); | ||
1332 | } | ||
1333 | |||
1334 | |||
1335 | /* Find a node in the GTK+ tree */ | ||
1336 | static GtkTreeIter found; | ||
1337 | |||
1338 | /* | ||
1339 | * Find a menu in the GtkTree starting at parent. | ||
1340 | */ | ||
1341 | GtkTreeIter *gtktree_iter_find_node(GtkTreeIter * parent, | ||
1342 | struct menu *tofind) | ||
1343 | { | ||
1344 | GtkTreeIter iter; | ||
1345 | GtkTreeIter *child = &iter; | ||
1346 | gboolean valid; | ||
1347 | GtkTreeIter *ret; | ||
1348 | |||
1349 | valid = gtk_tree_model_iter_children(model2, child, parent); | ||
1350 | while (valid) { | ||
1351 | struct menu *menu; | ||
1352 | |||
1353 | gtk_tree_model_get(model2, child, 6, &menu, -1); | ||
1354 | |||
1355 | if (menu == tofind) { | ||
1356 | memcpy(&found, child, sizeof(GtkTreeIter)); | ||
1357 | return &found; | ||
1358 | } | ||
1359 | |||
1360 | ret = gtktree_iter_find_node(child, tofind); | ||
1361 | if (ret) | ||
1362 | return ret; | ||
1363 | |||
1364 | valid = gtk_tree_model_iter_next(model2, child); | ||
1365 | } | ||
1366 | |||
1367 | return NULL; | ||
1368 | } | ||
1369 | |||
1370 | |||
1371 | /* | ||
1372 | * Update the tree by adding/removing entries | ||
1373 | * Does not change other nodes | ||
1374 | */ | ||
1375 | static void update_tree(struct menu *src, GtkTreeIter * dst) | ||
1376 | { | ||
1377 | struct menu *child1; | ||
1378 | GtkTreeIter iter, tmp; | ||
1379 | GtkTreeIter *child2 = &iter; | ||
1380 | gboolean valid; | ||
1381 | GtkTreeIter *sibling; | ||
1382 | struct symbol *sym; | ||
1383 | struct property *prop; | ||
1384 | struct menu *menu1, *menu2; | ||
1385 | static GtkTreePath *path = NULL; | ||
1386 | |||
1387 | if (src == &rootmenu) | ||
1388 | indent = 1; | ||
1389 | |||
1390 | valid = gtk_tree_model_iter_children(model2, child2, dst); | ||
1391 | for (child1 = src->list; child1; child1 = child1->next) { | ||
1392 | |||
1393 | prop = child1->prompt; | ||
1394 | sym = child1->sym; | ||
1395 | |||
1396 | reparse: | ||
1397 | menu1 = child1; | ||
1398 | if (valid) | ||
1399 | gtk_tree_model_get(model2, child2, COL_MENU, | ||
1400 | &menu2, -1); | ||
1401 | else | ||
1402 | menu2 = NULL;// force adding of a first child | ||
1403 | |||
1404 | #ifdef DEBUG | ||
1405 | printf("%*c%s | %s\n", indent, ' ', | ||
1406 | menu1 ? menu_get_prompt(menu1) : "nil", | ||
1407 | menu2 ? menu_get_prompt(menu2) : "nil"); | ||
1408 | #endif | ||
1409 | |||
1410 | if (!menu_is_visible(child1) && !show_all) {// remove node | ||
1411 | if (gtktree_iter_find_node(dst, menu1) != NULL) { | ||
1412 | memcpy(&tmp, child2, sizeof(GtkTreeIter)); | ||
1413 | valid = gtk_tree_model_iter_next(model2, | ||
1414 | child2); | ||
1415 | gtk_tree_store_remove(tree2, &tmp); | ||
1416 | if (!valid) | ||
1417 | return;// next parent | ||
1418 | else | ||
1419 | goto reparse;// next child | ||
1420 | } else | ||
1421 | continue; | ||
1422 | } | ||
1423 | |||
1424 | if (menu1 != menu2) { | ||
1425 | if (gtktree_iter_find_node(dst, menu1) == NULL) {// add node | ||
1426 | if (!valid && !menu2) | ||
1427 | sibling = NULL; | ||
1428 | else | ||
1429 | sibling = child2; | ||
1430 | gtk_tree_store_insert_before(tree2, | ||
1431 | child2, | ||
1432 | dst, sibling); | ||
1433 | set_node(child2, menu1, fill_row(menu1)); | ||
1434 | if (menu2 == NULL) | ||
1435 | valid = TRUE; | ||
1436 | } else {// remove node | ||
1437 | memcpy(&tmp, child2, sizeof(GtkTreeIter)); | ||
1438 | valid = gtk_tree_model_iter_next(model2, | ||
1439 | child2); | ||
1440 | gtk_tree_store_remove(tree2, &tmp); | ||
1441 | if (!valid) | ||
1442 | return;// next parent | ||
1443 | else | ||
1444 | goto reparse;// next child | ||
1445 | } | ||
1446 | } else if (sym && (sym->flags & SYMBOL_CHANGED)) { | ||
1447 | set_node(child2, menu1, fill_row(menu1)); | ||
1448 | } | ||
1449 | |||
1450 | indent++; | ||
1451 | update_tree(child1, child2); | ||
1452 | indent--; | ||
1453 | |||
1454 | valid = gtk_tree_model_iter_next(model2, child2); | ||
1455 | } | ||
1456 | } | ||
1457 | |||
1458 | |||
1459 | /* Display the whole tree (single/split/full view) */ | ||
1460 | static void display_tree(struct menu *menu) | ||
1461 | { | ||
1462 | struct symbol *sym; | ||
1463 | struct property *prop; | ||
1464 | struct menu *child; | ||
1465 | enum prop_type ptype; | ||
1466 | |||
1467 | if (menu == &rootmenu) { | ||
1468 | indent = 1; | ||
1469 | current = &rootmenu; | ||
1470 | } | ||
1471 | |||
1472 | for (child = menu->list; child; child = child->next) { | ||
1473 | prop = child->prompt; | ||
1474 | sym = child->sym; | ||
1475 | ptype = prop ? prop->type : P_UNKNOWN; | ||
1476 | |||
1477 | if (sym) | ||
1478 | sym->flags &= ~SYMBOL_CHANGED; | ||
1479 | |||
1480 | if ((view_mode == SPLIT_VIEW) && !(child->flags & MENU_ROOT) && | ||
1481 | (tree == tree1)) | ||
1482 | continue; | ||
1483 | |||
1484 | if ((view_mode == SPLIT_VIEW) && (child->flags & MENU_ROOT) && | ||
1485 | (tree == tree2)) | ||
1486 | continue; | ||
1487 | |||
1488 | if (menu_is_visible(child) || show_all) | ||
1489 | place_node(child, fill_row(child)); | ||
1490 | #ifdef DEBUG | ||
1491 | printf("%*c%s: ", indent, ' ', menu_get_prompt(child)); | ||
1492 | dbg_print_ptype(ptype); | ||
1493 | printf(" | "); | ||
1494 | if (sym) { | ||
1495 | dbg_print_stype(sym->type); | ||
1496 | printf(" | "); | ||
1497 | dbg_print_flags(sym->flags); | ||
1498 | printf("\n"); | ||
1499 | } else | ||
1500 | printf("\n"); | ||
1501 | #endif | ||
1502 | if ((view_mode != FULL_VIEW) && (ptype == P_MENU) | ||
1503 | && (tree == tree2)) | ||
1504 | continue; | ||
1505 | |||
1506 | if (((menu != &rootmenu) && !(menu->flags & MENU_ROOT)) || | ||
1507 | (view_mode == FULL_VIEW) | ||
1508 | || (view_mode == SPLIT_VIEW)) { | ||
1509 | indent++; | ||
1510 | display_tree(child); | ||
1511 | indent--; | ||
1512 | } | ||
1513 | } | ||
1514 | } | ||
1515 | |||
1516 | /* Display a part of the tree starting at current node (single/split view) */ | ||
1517 | static void display_tree_part(void) | ||
1518 | { | ||
1519 | if (tree2) | ||
1520 | gtk_tree_store_clear(tree2); | ||
1521 | display_tree(current); | ||
1522 | gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w)); | ||
1523 | } | ||
1524 | |||
1525 | /* Display the list in the left frame (split view) */ | ||
1526 | static void display_list(void) | ||
1527 | { | ||
1528 | if (tree1) | ||
1529 | gtk_tree_store_clear(tree1); | ||
1530 | |||
1531 | tree = tree1; | ||
1532 | display_tree(current = &rootmenu); | ||
1533 | gtk_tree_view_expand_all(GTK_TREE_VIEW(tree1_w)); | ||
1534 | tree = tree2; | ||
1535 | } | ||
1536 | |||
1537 | static void fixup_rootmenu(struct menu *menu) | ||
1538 | { | ||
1539 | struct menu *child; | ||
1540 | |||
1541 | if (!menu->prompt || menu->prompt->type != P_MENU) | ||
1542 | return; | ||
1543 | menu->flags |= MENU_ROOT; | ||
1544 | for (child = menu->list; child; child = child->next) | ||
1545 | fixup_rootmenu(child); | ||
1546 | } | ||
1547 | |||
1548 | |||
1549 | /* Main */ | ||
1550 | |||
1551 | |||
1552 | int main(int ac, char *av[]) | ||
1553 | { | ||
1554 | const char *name; | ||
1555 | gchar *cur_dir, *exe_path; | ||
1556 | gchar *glade_file; | ||
1557 | |||
1558 | #ifndef LKC_DIRECT_LINK | ||
1559 | kconfig_load(); | ||
1560 | #endif | ||
1561 | |||
1562 | /* GTK stuffs */ | ||
1563 | gtk_set_locale(); | ||
1564 | gtk_init(&ac, &av); | ||
1565 | glade_init(); | ||
1566 | |||
1567 | //add_pixmap_directory (PACKAGE_DATA_DIR "/" PACKAGE "/pixmaps"); | ||
1568 | //add_pixmap_directory (PACKAGE_SOURCE_DIR "/pixmaps"); | ||
1569 | |||
1570 | /* Determine GUI path */ | ||
1571 | cur_dir = g_get_current_dir(); | ||
1572 | exe_path = g_strdup(av[0]); | ||
1573 | exe_path[0] = '/'; | ||
1574 | glade_file = g_strconcat(cur_dir, exe_path, ".glade", NULL); | ||
1575 | g_free(cur_dir); | ||
1576 | g_free(exe_path); | ||
1577 | |||
1578 | /* Load the interface and connect signals */ | ||
1579 | init_main_window(glade_file); | ||
1580 | init_tree_model(); | ||
1581 | init_left_tree(); | ||
1582 | init_right_tree(); | ||
1583 | |||
1584 | /* Conf stuffs */ | ||
1585 | if (ac > 1 && av[1][0] == '-') { | ||
1586 | switch (av[1][1]) { | ||
1587 | case 'a': | ||
1588 | //showAll = 1; | ||
1589 | break; | ||
1590 | case 'h': | ||
1591 | case '?': | ||
1592 | printf("%s <config>\n", av[0]); | ||
1593 | exit(0); | ||
1594 | } | ||
1595 | name = av[2]; | ||
1596 | } else | ||
1597 | name = av[1]; | ||
1598 | |||
1599 | conf_parse(name); | ||
1600 | fixup_rootmenu(&rootmenu); | ||
1601 | conf_read(NULL); | ||
1602 | |||
1603 | switch (view_mode) { | ||
1604 | case SINGLE_VIEW: | ||
1605 | display_tree_part(); | ||
1606 | break; | ||
1607 | case SPLIT_VIEW: | ||
1608 | display_list(); | ||
1609 | break; | ||
1610 | case FULL_VIEW: | ||
1611 | display_tree(&rootmenu); | ||
1612 | break; | ||
1613 | } | ||
1614 | |||
1615 | gtk_main(); | ||
1616 | |||
1617 | return 0; | ||
1618 | } | ||