target/x86_64/Makefile: fix blocking typo
[openadk.git] / config / gconf.c
blob681125e1194e183624f58624927fe99c5483fc6e
1 /* Hey EMACS -*- linux-c -*- */
2 /*
4 * Copyright (C) 2002-2003 Romain Lievin <roms@tilp.info>
5 * Released under the terms of the GNU GPL v2.0.
7 */
9 #ifdef HAVE_CONFIG_H
10 # include <config.h>
11 #endif
13 #include "lkc.h"
14 #include "images.c"
16 #include <glade/glade.h>
17 #include <gtk/gtk.h>
18 #include <glib.h>
19 #include <gdk/gdkkeysyms.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <unistd.h>
24 #include <time.h>
25 #include <stdlib.h>
27 //#define DEBUG
29 enum {
30 SINGLE_VIEW, SPLIT_VIEW, FULL_VIEW
33 static gint view_mode = FULL_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;
41 GtkWidget *main_wnd = NULL;
42 GtkWidget *tree1_w = NULL; // left frame
43 GtkWidget *tree2_w = NULL; // right frame
44 GtkWidget *text_w = NULL;
45 GtkWidget *hpaned = NULL;
46 GtkWidget *vpaned = NULL;
47 GtkWidget *back_btn = NULL;
48 GtkWidget *save_btn = NULL;
49 GtkWidget *save_menu_item = NULL;
51 GtkTextTag *tag1, *tag2;
52 GdkColor color;
54 GtkTreeStore *tree1, *tree2, *tree;
55 GtkTreeModel *model1, *model2;
56 static GtkTreeIter *parents[256];
57 static gint indent;
59 static struct menu *current; // current node for SINGLE view
60 static struct menu *browsed; // browsed node for SPLIT view
62 enum {
63 COL_OPTION, COL_NAME, COL_NO, COL_MOD, COL_YES, COL_VALUE,
64 COL_MENU, COL_COLOR, COL_EDIT, COL_PIXBUF,
65 COL_PIXVIS, COL_BTNVIS, COL_BTNACT, COL_BTNINC, COL_BTNRAD,
66 COL_NUMBER
69 static void display_list(void);
70 static void display_tree(struct menu *menu);
71 static void display_tree_part(void);
72 static void update_tree(struct menu *src, GtkTreeIter * dst);
73 static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row);
74 static gchar **fill_row(struct menu *menu);
75 static void conf_changed(void);
77 /* Helping/Debugging Functions */
80 const char *dbg_print_stype(int val)
82 static char buf[256];
84 bzero(buf, 256);
86 if (val == S_UNKNOWN)
87 strcpy(buf, "unknown");
88 if (val == S_BOOLEAN)
89 strcpy(buf, "boolean");
90 if (val == S_TRISTATE)
91 strcpy(buf, "tristate");
92 if (val == S_INT)
93 strcpy(buf, "int");
94 if (val == S_HEX)
95 strcpy(buf, "hex");
96 if (val == S_STRING)
97 strcpy(buf, "string");
98 if (val == S_OTHER)
99 strcpy(buf, "other");
101 #ifdef DEBUG
102 printf("%s", buf);
103 #endif
105 return buf;
108 const char *dbg_print_flags(int val)
110 static char buf[256];
112 bzero(buf, 256);
114 if (val & SYMBOL_CONST)
115 strcat(buf, "const/");
116 if (val & SYMBOL_CHECK)
117 strcat(buf, "check/");
118 if (val & SYMBOL_CHOICE)
119 strcat(buf, "choice/");
120 if (val & SYMBOL_CHOICEVAL)
121 strcat(buf, "choiceval/");
122 if (val & SYMBOL_VALID)
123 strcat(buf, "valid/");
124 if (val & SYMBOL_OPTIONAL)
125 strcat(buf, "optional/");
126 if (val & SYMBOL_WRITE)
127 strcat(buf, "write/");
128 if (val & SYMBOL_CHANGED)
129 strcat(buf, "changed/");
130 if (val & SYMBOL_AUTO)
131 strcat(buf, "auto/");
133 buf[strlen(buf) - 1] = '\0';
134 #ifdef DEBUG
135 printf("%s", buf);
136 #endif
138 return buf;
141 const char *dbg_print_ptype(int val)
143 static char buf[256];
145 bzero(buf, 256);
147 if (val == P_UNKNOWN)
148 strcpy(buf, "unknown");
149 if (val == P_PROMPT)
150 strcpy(buf, "prompt");
151 if (val == P_COMMENT)
152 strcpy(buf, "comment");
153 if (val == P_MENU)
154 strcpy(buf, "menu");
155 if (val == P_DEFAULT)
156 strcpy(buf, "default");
157 if (val == P_CHOICE)
158 strcpy(buf, "choice");
160 #ifdef DEBUG
161 printf("%s", buf);
162 #endif
164 return buf;
168 void replace_button_icon(GladeXML * xml, GdkDrawable * window,
169 GtkStyle * style, gchar * btn_name, gchar ** xpm)
171 GdkPixmap *pixmap;
172 GdkBitmap *mask;
173 GtkToolButton *button;
174 GtkWidget *image;
176 pixmap = gdk_pixmap_create_from_xpm_d(window, &mask,
177 &style->bg[GTK_STATE_NORMAL],
178 xpm);
180 button = GTK_TOOL_BUTTON(glade_xml_get_widget(xml, btn_name));
181 image = gtk_image_new_from_pixmap(pixmap, mask);
182 gtk_widget_show(image);
183 gtk_tool_button_set_icon_widget(button, image);
186 /* Main Window Initialization */
187 void init_main_window(const gchar * glade_file)
189 GladeXML *xml;
190 GtkWidget *widget;
191 GtkTextBuffer *txtbuf;
192 char title[256];
193 GtkStyle *style;
195 xml = glade_xml_new(glade_file, "window1", NULL);
196 if (!xml)
197 g_error(_("GUI loading failed !\n"));
198 glade_xml_signal_autoconnect(xml);
200 main_wnd = glade_xml_get_widget(xml, "window1");
201 hpaned = glade_xml_get_widget(xml, "hpaned1");
202 vpaned = glade_xml_get_widget(xml, "vpaned1");
203 tree1_w = glade_xml_get_widget(xml, "treeview1");
204 tree2_w = glade_xml_get_widget(xml, "treeview2");
205 text_w = glade_xml_get_widget(xml, "textview3");
207 back_btn = glade_xml_get_widget(xml, "button1");
208 gtk_widget_set_sensitive(back_btn, FALSE);
210 widget = glade_xml_get_widget(xml, "show_name1");
211 gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
212 show_name);
214 widget = glade_xml_get_widget(xml, "show_range1");
215 gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
216 show_range);
218 widget = glade_xml_get_widget(xml, "show_data1");
219 gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
220 show_value);
222 save_btn = glade_xml_get_widget(xml, "button3");
223 save_menu_item = glade_xml_get_widget(xml, "save1");
224 conf_set_changed_callback(conf_changed);
226 style = gtk_widget_get_style(main_wnd);
227 widget = glade_xml_get_widget(xml, "toolbar1");
229 #if 0 /* Use stock Gtk icons instead */
230 replace_button_icon(xml, main_wnd->window, style,
231 "button1", (gchar **) xpm_back);
232 replace_button_icon(xml, main_wnd->window, style,
233 "button2", (gchar **) xpm_load);
234 replace_button_icon(xml, main_wnd->window, style,
235 "button3", (gchar **) xpm_save);
236 #endif
237 replace_button_icon(xml, main_wnd->window, style,
238 "button4", (gchar **) xpm_single_view);
239 replace_button_icon(xml, main_wnd->window, style,
240 "button5", (gchar **) xpm_split_view);
241 replace_button_icon(xml, main_wnd->window, style,
242 "button6", (gchar **) xpm_tree_view);
244 #if 0
245 switch (view_mode) {
246 case SINGLE_VIEW:
247 widget = glade_xml_get_widget(xml, "button4");
248 g_signal_emit_by_name(widget, "clicked");
249 break;
250 case SPLIT_VIEW:
251 widget = glade_xml_get_widget(xml, "button5");
252 g_signal_emit_by_name(widget, "clicked");
253 break;
254 case FULL_VIEW:
255 widget = glade_xml_get_widget(xml, "button6");
256 g_signal_emit_by_name(widget, "clicked");
257 break;
259 #endif
260 txtbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
261 tag1 = gtk_text_buffer_create_tag(txtbuf, "mytag1",
262 "foreground", "red",
263 "weight", PANGO_WEIGHT_BOLD,
264 NULL);
265 tag2 = gtk_text_buffer_create_tag(txtbuf, "mytag2",
266 /*"style", PANGO_STYLE_OBLIQUE, */
267 NULL);
269 sprintf(title, _("OpenADK Configuration"));
270 gtk_window_set_title(GTK_WINDOW(main_wnd), title);
272 gtk_widget_show(main_wnd);
275 void init_tree_model(void)
277 gint i;
279 tree = tree2 = gtk_tree_store_new(COL_NUMBER,
280 G_TYPE_STRING, G_TYPE_STRING,
281 G_TYPE_STRING, G_TYPE_STRING,
282 G_TYPE_STRING, G_TYPE_STRING,
283 G_TYPE_POINTER, GDK_TYPE_COLOR,
284 G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF,
285 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
286 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
287 G_TYPE_BOOLEAN);
288 model2 = GTK_TREE_MODEL(tree2);
290 for (parents[0] = NULL, i = 1; i < 256; i++)
291 parents[i] = (GtkTreeIter *) g_malloc(sizeof(GtkTreeIter));
293 tree1 = gtk_tree_store_new(COL_NUMBER,
294 G_TYPE_STRING, G_TYPE_STRING,
295 G_TYPE_STRING, G_TYPE_STRING,
296 G_TYPE_STRING, G_TYPE_STRING,
297 G_TYPE_POINTER, GDK_TYPE_COLOR,
298 G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF,
299 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
300 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
301 G_TYPE_BOOLEAN);
302 model1 = GTK_TREE_MODEL(tree1);
305 void init_left_tree(void)
307 GtkTreeView *view = GTK_TREE_VIEW(tree1_w);
308 GtkCellRenderer *renderer;
309 GtkTreeSelection *sel;
310 GtkTreeViewColumn *column;
312 gtk_tree_view_set_model(view, model1);
313 gtk_tree_view_set_headers_visible(view, TRUE);
314 gtk_tree_view_set_rules_hint(view, FALSE);
316 column = gtk_tree_view_column_new();
317 gtk_tree_view_append_column(view, column);
318 gtk_tree_view_column_set_title(column, _("Options"));
320 renderer = gtk_cell_renderer_toggle_new();
321 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
322 renderer, FALSE);
323 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
324 renderer,
325 "active", COL_BTNACT,
326 "inconsistent", COL_BTNINC,
327 "visible", COL_BTNVIS,
328 "radio", COL_BTNRAD, NULL);
329 renderer = gtk_cell_renderer_text_new();
330 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
331 renderer, FALSE);
332 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
333 renderer,
334 "text", COL_OPTION,
335 "foreground-gdk",
336 COL_COLOR, NULL);
338 sel = gtk_tree_view_get_selection(view);
339 gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
340 gtk_widget_realize(tree1_w);
343 static void renderer_edited(GtkCellRendererText * cell,
344 const gchar * path_string,
345 const gchar * new_text, gpointer user_data);
346 static void renderer_toggled(GtkCellRendererToggle * cellrenderertoggle,
347 gchar * arg1, gpointer user_data);
349 void init_right_tree(void)
351 GtkTreeView *view = GTK_TREE_VIEW(tree2_w);
352 GtkCellRenderer *renderer;
353 GtkTreeSelection *sel;
354 GtkTreeViewColumn *column;
355 gint i;
357 gtk_tree_view_set_model(view, model2);
358 gtk_tree_view_set_headers_visible(view, TRUE);
359 gtk_tree_view_set_rules_hint(view, FALSE);
361 column = gtk_tree_view_column_new();
362 gtk_tree_view_append_column(view, column);
363 gtk_tree_view_column_set_title(column, _("Options"));
365 renderer = gtk_cell_renderer_pixbuf_new();
366 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
367 renderer, FALSE);
368 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
369 renderer,
370 "pixbuf", COL_PIXBUF,
371 "visible", COL_PIXVIS, NULL);
372 renderer = gtk_cell_renderer_toggle_new();
373 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
374 renderer, FALSE);
375 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
376 renderer,
377 "active", COL_BTNACT,
378 "inconsistent", COL_BTNINC,
379 "visible", COL_BTNVIS,
380 "radio", COL_BTNRAD, NULL);
381 /*g_signal_connect(G_OBJECT(renderer), "toggled",
382 G_CALLBACK(renderer_toggled), NULL); */
383 renderer = gtk_cell_renderer_text_new();
384 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
385 renderer, FALSE);
386 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
387 renderer,
388 "text", COL_OPTION,
389 "foreground-gdk",
390 COL_COLOR, NULL);
392 renderer = gtk_cell_renderer_text_new();
393 gtk_tree_view_insert_column_with_attributes(view, -1,
394 _("Name"), renderer,
395 "text", COL_NAME,
396 "foreground-gdk",
397 COL_COLOR, NULL);
398 renderer = gtk_cell_renderer_text_new();
399 gtk_tree_view_insert_column_with_attributes(view, -1,
400 "N", renderer,
401 "text", COL_NO,
402 "foreground-gdk",
403 COL_COLOR, NULL);
404 renderer = gtk_cell_renderer_text_new();
405 gtk_tree_view_insert_column_with_attributes(view, -1,
406 "M", renderer,
407 "text", COL_MOD,
408 "foreground-gdk",
409 COL_COLOR, NULL);
410 renderer = gtk_cell_renderer_text_new();
411 gtk_tree_view_insert_column_with_attributes(view, -1,
412 "Y", renderer,
413 "text", COL_YES,
414 "foreground-gdk",
415 COL_COLOR, NULL);
416 renderer = gtk_cell_renderer_text_new();
417 gtk_tree_view_insert_column_with_attributes(view, -1,
418 _("Value"), renderer,
419 "text", COL_VALUE,
420 "editable",
421 COL_EDIT,
422 "foreground-gdk",
423 COL_COLOR, NULL);
424 g_signal_connect(G_OBJECT(renderer), "edited",
425 G_CALLBACK(renderer_edited), NULL);
427 column = gtk_tree_view_get_column(view, COL_NAME);
428 gtk_tree_view_column_set_visible(column, show_name);
429 column = gtk_tree_view_get_column(view, COL_NO);
430 gtk_tree_view_column_set_visible(column, show_range);
431 column = gtk_tree_view_get_column(view, COL_MOD);
432 gtk_tree_view_column_set_visible(column, show_range);
433 column = gtk_tree_view_get_column(view, COL_YES);
434 gtk_tree_view_column_set_visible(column, show_range);
435 column = gtk_tree_view_get_column(view, COL_VALUE);
436 gtk_tree_view_column_set_visible(column, show_value);
438 if (resizeable) {
439 for (i = 0; i < COL_VALUE; i++) {
440 column = gtk_tree_view_get_column(view, i);
441 gtk_tree_view_column_set_resizable(column, TRUE);
445 sel = gtk_tree_view_get_selection(view);
446 gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
450 /* Utility Functions */
453 static void text_insert_help(struct menu *menu)
455 GtkTextBuffer *buffer;
456 GtkTextIter start, end;
457 const char *prompt = _(menu_get_prompt(menu));
458 struct gstr help = str_new();
460 menu_get_ext_help(menu, &help);
462 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
463 gtk_text_buffer_get_bounds(buffer, &start, &end);
464 gtk_text_buffer_delete(buffer, &start, &end);
465 gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15);
467 gtk_text_buffer_get_end_iter(buffer, &end);
468 gtk_text_buffer_insert_with_tags(buffer, &end, prompt, -1, tag1,
469 NULL);
470 gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2);
471 gtk_text_buffer_get_end_iter(buffer, &end);
472 gtk_text_buffer_insert_with_tags(buffer, &end, str_get(&help), -1, tag2,
473 NULL);
474 str_free(&help);
478 static void text_insert_msg(const char *title, const char *message)
480 GtkTextBuffer *buffer;
481 GtkTextIter start, end;
482 const char *msg = message;
484 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
485 gtk_text_buffer_get_bounds(buffer, &start, &end);
486 gtk_text_buffer_delete(buffer, &start, &end);
487 gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15);
489 gtk_text_buffer_get_end_iter(buffer, &end);
490 gtk_text_buffer_insert_with_tags(buffer, &end, title, -1, tag1,
491 NULL);
492 gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2);
493 gtk_text_buffer_get_end_iter(buffer, &end);
494 gtk_text_buffer_insert_with_tags(buffer, &end, msg, -1, tag2,
495 NULL);
499 /* Main Windows Callbacks */
501 void on_save_activate(GtkMenuItem * menuitem, gpointer user_data);
502 gboolean on_window1_delete_event(GtkWidget * widget, GdkEvent * event,
503 gpointer user_data)
505 GtkWidget *dialog, *label;
506 gint result;
508 if (!conf_get_changed())
509 return FALSE;
511 dialog = gtk_dialog_new_with_buttons(_("Warning !"),
512 GTK_WINDOW(main_wnd),
513 (GtkDialogFlags)
514 (GTK_DIALOG_MODAL |
515 GTK_DIALOG_DESTROY_WITH_PARENT),
516 GTK_STOCK_OK,
517 GTK_RESPONSE_YES,
518 GTK_STOCK_NO,
519 GTK_RESPONSE_NO,
520 GTK_STOCK_CANCEL,
521 GTK_RESPONSE_CANCEL, NULL);
522 gtk_dialog_set_default_response(GTK_DIALOG(dialog),
523 GTK_RESPONSE_CANCEL);
525 label = gtk_label_new(_("\nSave configuration ?\n"));
526 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label);
527 gtk_widget_show(label);
529 result = gtk_dialog_run(GTK_DIALOG(dialog));
530 switch (result) {
531 case GTK_RESPONSE_YES:
532 on_save_activate(NULL, NULL);
533 return FALSE;
534 case GTK_RESPONSE_NO:
535 return FALSE;
536 case GTK_RESPONSE_CANCEL:
537 case GTK_RESPONSE_DELETE_EVENT:
538 default:
539 gtk_widget_destroy(dialog);
540 return TRUE;
543 return FALSE;
547 void on_window1_destroy(GtkObject * object, gpointer user_data)
549 gtk_main_quit();
553 void
554 on_window1_size_request(GtkWidget * widget,
555 GtkRequisition * requisition, gpointer user_data)
557 static gint old_h;
558 gint w, h;
560 if (widget->window == NULL)
561 gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h);
562 else
563 gdk_window_get_size(widget->window, &w, &h);
565 if (h == old_h)
566 return;
567 old_h = h;
569 gtk_paned_set_position(GTK_PANED(vpaned), 2 * h / 3);
573 /* Menu & Toolbar Callbacks */
576 static void
577 load_filename(GtkFileSelection * file_selector, gpointer user_data)
579 const gchar *fn;
581 fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION
582 (user_data));
584 if (conf_read(fn))
585 text_insert_msg(_("Error"), _("Unable to load configuration !"));
586 else
587 display_tree(&rootmenu);
590 void on_load1_activate(GtkMenuItem * menuitem, gpointer user_data)
592 GtkWidget *fs;
594 fs = gtk_file_selection_new(_("Load file..."));
595 g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button),
596 "clicked",
597 G_CALLBACK(load_filename), (gpointer) fs);
598 g_signal_connect_swapped(GTK_OBJECT
599 (GTK_FILE_SELECTION(fs)->ok_button),
600 "clicked", G_CALLBACK(gtk_widget_destroy),
601 (gpointer) fs);
602 g_signal_connect_swapped(GTK_OBJECT
603 (GTK_FILE_SELECTION(fs)->cancel_button),
604 "clicked", G_CALLBACK(gtk_widget_destroy),
605 (gpointer) fs);
606 gtk_widget_show(fs);
610 void on_save_activate(GtkMenuItem * menuitem, gpointer user_data)
612 if (conf_write(NULL))
613 text_insert_msg(_("Error"), _("Unable to save configuration !"));
617 static void
618 store_filename(GtkFileSelection * file_selector, gpointer user_data)
620 const gchar *fn;
622 fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION
623 (user_data));
625 if (conf_write(fn))
626 text_insert_msg(_("Error"), _("Unable to save configuration !"));
628 gtk_widget_destroy(GTK_WIDGET(user_data));
631 void on_save_as1_activate(GtkMenuItem * menuitem, gpointer user_data)
633 GtkWidget *fs;
635 fs = gtk_file_selection_new(_("Save file as..."));
636 g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button),
637 "clicked",
638 G_CALLBACK(store_filename), (gpointer) fs);
639 g_signal_connect_swapped(GTK_OBJECT
640 (GTK_FILE_SELECTION(fs)->ok_button),
641 "clicked", G_CALLBACK(gtk_widget_destroy),
642 (gpointer) fs);
643 g_signal_connect_swapped(GTK_OBJECT
644 (GTK_FILE_SELECTION(fs)->cancel_button),
645 "clicked", G_CALLBACK(gtk_widget_destroy),
646 (gpointer) fs);
647 gtk_widget_show(fs);
651 void on_quit1_activate(GtkMenuItem * menuitem, gpointer user_data)
653 if (!on_window1_delete_event(NULL, NULL, NULL))
654 gtk_widget_destroy(GTK_WIDGET(main_wnd));
658 void on_show_name1_activate(GtkMenuItem * menuitem, gpointer user_data)
660 GtkTreeViewColumn *col;
662 show_name = GTK_CHECK_MENU_ITEM(menuitem)->active;
663 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NAME);
664 if (col)
665 gtk_tree_view_column_set_visible(col, show_name);
669 void on_show_range1_activate(GtkMenuItem * menuitem, gpointer user_data)
671 GtkTreeViewColumn *col;
673 show_range = GTK_CHECK_MENU_ITEM(menuitem)->active;
674 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NO);
675 if (col)
676 gtk_tree_view_column_set_visible(col, show_range);
677 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_MOD);
678 if (col)
679 gtk_tree_view_column_set_visible(col, show_range);
680 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_YES);
681 if (col)
682 gtk_tree_view_column_set_visible(col, show_range);
687 void on_show_data1_activate(GtkMenuItem * menuitem, gpointer user_data)
689 GtkTreeViewColumn *col;
691 show_value = GTK_CHECK_MENU_ITEM(menuitem)->active;
692 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_VALUE);
693 if (col)
694 gtk_tree_view_column_set_visible(col, show_value);
698 void
699 on_show_all_options1_activate(GtkMenuItem * menuitem, gpointer user_data)
701 show_all = GTK_CHECK_MENU_ITEM(menuitem)->active;
703 gtk_tree_store_clear(tree2);
704 display_tree(&rootmenu); // instead of update_tree to speed-up
708 void
709 on_show_debug_info1_activate(GtkMenuItem * menuitem, gpointer user_data)
711 show_debug = GTK_CHECK_MENU_ITEM(menuitem)->active;
712 update_tree(&rootmenu, NULL);
716 void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data)
718 GtkWidget *dialog;
719 const gchar *intro_text = _(
720 "Welcome to gkc, the GTK+ graphical kernel configuration tool\n"
721 "for Linux.\n"
722 "For each option, a blank box indicates the feature is disabled, a\n"
723 "check indicates it is enabled, and a dot indicates that it is to\n"
724 "be compiled as a module. Clicking on the box will cycle through the three states.\n"
725 "\n"
726 "If you do not see an option (e.g., a device driver) that you\n"
727 "believe should be present, try turning on Show All Options\n"
728 "under the Options menu.\n"
729 "Although there is no cross reference yet to help you figure out\n"
730 "what other options must be enabled to support the option you\n"
731 "are interested in, you can still view the help of a grayed-out\n"
732 "option.\n"
733 "\n"
734 "Toggling Show Debug Info under the Options menu will show \n"
735 "the dependencies, which you can then match by examining other options.");
737 dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
738 GTK_DIALOG_DESTROY_WITH_PARENT,
739 GTK_MESSAGE_INFO,
740 GTK_BUTTONS_CLOSE, intro_text);
741 g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
742 G_CALLBACK(gtk_widget_destroy),
743 GTK_OBJECT(dialog));
744 gtk_widget_show_all(dialog);
748 void on_about1_activate(GtkMenuItem * menuitem, gpointer user_data)
750 GtkWidget *dialog;
751 const gchar *about_text =
752 _("gkc is copyright (c) 2002 Romain Lievin <roms@lpg.ticalc.org>.\n"
753 "Based on the source code from Roman Zippel.\n");
755 dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
756 GTK_DIALOG_DESTROY_WITH_PARENT,
757 GTK_MESSAGE_INFO,
758 GTK_BUTTONS_CLOSE, about_text);
759 g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
760 G_CALLBACK(gtk_widget_destroy),
761 GTK_OBJECT(dialog));
762 gtk_widget_show_all(dialog);
766 void on_license1_activate(GtkMenuItem * menuitem, gpointer user_data)
768 GtkWidget *dialog;
769 const gchar *license_text =
770 _("gkc is released under the terms of the GNU GPL v2.\n"
771 "For more information, please see the source code or\n"
772 "visit http://www.fsf.org/licenses/licenses.html\n");
774 dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
775 GTK_DIALOG_DESTROY_WITH_PARENT,
776 GTK_MESSAGE_INFO,
777 GTK_BUTTONS_CLOSE, license_text);
778 g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
779 G_CALLBACK(gtk_widget_destroy),
780 GTK_OBJECT(dialog));
781 gtk_widget_show_all(dialog);
785 void on_back_clicked(GtkButton * button, gpointer user_data)
787 enum prop_type ptype;
789 current = current->parent;
790 ptype = current->prompt ? current->prompt->type : P_UNKNOWN;
791 if (ptype != P_MENU)
792 current = current->parent;
793 display_tree_part();
795 if (current == &rootmenu)
796 gtk_widget_set_sensitive(back_btn, FALSE);
800 void on_load_clicked(GtkButton * button, gpointer user_data)
802 on_load1_activate(NULL, user_data);
806 void on_single_clicked(GtkButton * button, gpointer user_data)
808 view_mode = SINGLE_VIEW;
809 gtk_paned_set_position(GTK_PANED(hpaned), 0);
810 gtk_widget_hide(tree1_w);
811 current = &rootmenu;
812 display_tree_part();
816 void on_split_clicked(GtkButton * button, gpointer user_data)
818 gint w, h;
819 view_mode = SPLIT_VIEW;
820 gtk_widget_show(tree1_w);
821 gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h);
822 gtk_paned_set_position(GTK_PANED(hpaned), w / 2);
823 if (tree2)
824 gtk_tree_store_clear(tree2);
825 display_list();
827 /* Disable back btn, like in full mode. */
828 gtk_widget_set_sensitive(back_btn, FALSE);
832 void on_full_clicked(GtkButton * button, gpointer user_data)
834 view_mode = FULL_VIEW;
835 gtk_paned_set_position(GTK_PANED(hpaned), 0);
836 gtk_widget_hide(tree1_w);
837 if (tree2)
838 gtk_tree_store_clear(tree2);
839 display_tree(&rootmenu);
840 gtk_widget_set_sensitive(back_btn, FALSE);
844 void on_collapse_clicked(GtkButton * button, gpointer user_data)
846 gtk_tree_view_collapse_all(GTK_TREE_VIEW(tree2_w));
850 void on_expand_clicked(GtkButton * button, gpointer user_data)
852 gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w));
856 /* CTree Callbacks */
858 /* Change hex/int/string value in the cell */
859 static void renderer_edited(GtkCellRendererText * cell,
860 const gchar * path_string,
861 const gchar * new_text, gpointer user_data)
863 GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
864 GtkTreeIter iter;
865 const char *old_def, *new_def;
866 struct menu *menu;
867 struct symbol *sym;
869 if (!gtk_tree_model_get_iter(model2, &iter, path))
870 return;
872 gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
873 sym = menu->sym;
875 gtk_tree_model_get(model2, &iter, COL_VALUE, &old_def, -1);
876 new_def = new_text;
878 sym_set_string_value(sym, new_def);
880 update_tree(&rootmenu, NULL);
882 gtk_tree_path_free(path);
885 /* Change the value of a symbol and update the tree */
886 static void change_sym_value(struct menu *menu, gint col)
888 struct symbol *sym = menu->sym;
889 tristate oldval, newval;
891 if (!sym)
892 return;
894 if (col == COL_NO)
895 newval = no;
896 else if (col == COL_MOD)
897 newval = mod;
898 else if (col == COL_YES)
899 newval = yes;
900 else
901 return;
903 switch (sym_get_type(sym)) {
904 case S_BOOLEAN:
905 case S_TRISTATE:
906 oldval = sym_get_tristate_value(sym);
907 if (!sym_tristate_within_range(sym, newval))
908 newval = yes;
909 sym_set_tristate_value(sym, newval);
910 if (view_mode == FULL_VIEW)
911 update_tree(&rootmenu, NULL);
912 else if (view_mode == SPLIT_VIEW) {
913 update_tree(browsed, NULL);
914 display_list();
916 else if (view_mode == SINGLE_VIEW)
917 display_tree_part(); //fixme: keep exp/coll
918 break;
919 case S_INT:
920 case S_HEX:
921 case S_STRING:
922 default:
923 break;
927 static void toggle_sym_value(struct menu *menu)
929 if (!menu->sym)
930 return;
932 sym_toggle_tristate_value(menu->sym);
933 if (view_mode == FULL_VIEW)
934 update_tree(&rootmenu, NULL);
935 else if (view_mode == SPLIT_VIEW) {
936 update_tree(browsed, NULL);
937 display_list();
939 else if (view_mode == SINGLE_VIEW)
940 display_tree_part(); //fixme: keep exp/coll
943 static void renderer_toggled(GtkCellRendererToggle * cell,
944 gchar * path_string, gpointer user_data)
946 GtkTreePath *path, *sel_path = NULL;
947 GtkTreeIter iter, sel_iter;
948 GtkTreeSelection *sel;
949 struct menu *menu;
951 path = gtk_tree_path_new_from_string(path_string);
952 if (!gtk_tree_model_get_iter(model2, &iter, path))
953 return;
955 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree2_w));
956 if (gtk_tree_selection_get_selected(sel, NULL, &sel_iter))
957 sel_path = gtk_tree_model_get_path(model2, &sel_iter);
958 if (!sel_path)
959 goto out1;
960 if (gtk_tree_path_compare(path, sel_path))
961 goto out2;
963 gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
964 toggle_sym_value(menu);
966 out2:
967 gtk_tree_path_free(sel_path);
968 out1:
969 gtk_tree_path_free(path);
972 static gint column2index(GtkTreeViewColumn * column)
974 gint i;
976 for (i = 0; i < COL_NUMBER; i++) {
977 GtkTreeViewColumn *col;
979 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), i);
980 if (col == column)
981 return i;
984 return -1;
988 /* User click: update choice (full) or goes down (single) */
989 gboolean
990 on_treeview2_button_press_event(GtkWidget * widget,
991 GdkEventButton * event, gpointer user_data)
993 GtkTreeView *view = GTK_TREE_VIEW(widget);
994 GtkTreePath *path;
995 GtkTreeViewColumn *column;
996 GtkTreeIter iter;
997 struct menu *menu;
998 gint col;
1000 #if GTK_CHECK_VERSION(2,1,4) // bug in ctree with earlier version of GTK
1001 gint tx = (gint) event->x;
1002 gint ty = (gint) event->y;
1003 gint cx, cy;
1005 gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx,
1006 &cy);
1007 #else
1008 gtk_tree_view_get_cursor(view, &path, &column);
1009 #endif
1010 if (path == NULL)
1011 return FALSE;
1013 if (!gtk_tree_model_get_iter(model2, &iter, path))
1014 return FALSE;
1015 gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
1017 col = column2index(column);
1018 if (event->type == GDK_2BUTTON_PRESS) {
1019 enum prop_type ptype;
1020 ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
1022 if (ptype == P_MENU && view_mode != FULL_VIEW && col == COL_OPTION) {
1023 // goes down into menu
1024 current = menu;
1025 display_tree_part();
1026 gtk_widget_set_sensitive(back_btn, TRUE);
1027 } else if ((col == COL_OPTION)) {
1028 toggle_sym_value(menu);
1029 gtk_tree_view_expand_row(view, path, TRUE);
1031 } else {
1032 if (col == COL_VALUE) {
1033 toggle_sym_value(menu);
1034 gtk_tree_view_expand_row(view, path, TRUE);
1035 } else if (col == COL_NO || col == COL_MOD
1036 || col == COL_YES) {
1037 change_sym_value(menu, col);
1038 gtk_tree_view_expand_row(view, path, TRUE);
1042 return FALSE;
1045 /* Key pressed: update choice */
1046 gboolean
1047 on_treeview2_key_press_event(GtkWidget * widget,
1048 GdkEventKey * event, gpointer user_data)
1050 GtkTreeView *view = GTK_TREE_VIEW(widget);
1051 GtkTreePath *path;
1052 GtkTreeViewColumn *column;
1053 GtkTreeIter iter;
1054 struct menu *menu;
1055 gint col;
1057 gtk_tree_view_get_cursor(view, &path, &column);
1058 if (path == NULL)
1059 return FALSE;
1061 if (event->keyval == GDK_space) {
1062 if (gtk_tree_view_row_expanded(view, path))
1063 gtk_tree_view_collapse_row(view, path);
1064 else
1065 gtk_tree_view_expand_row(view, path, FALSE);
1066 return TRUE;
1068 if (event->keyval == GDK_KP_Enter) {
1070 if (widget == tree1_w)
1071 return FALSE;
1073 gtk_tree_model_get_iter(model2, &iter, path);
1074 gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
1076 if (!strcasecmp(event->string, "n"))
1077 col = COL_NO;
1078 else if (!strcasecmp(event->string, "m"))
1079 col = COL_MOD;
1080 else if (!strcasecmp(event->string, "y"))
1081 col = COL_YES;
1082 else
1083 col = -1;
1084 change_sym_value(menu, col);
1086 return FALSE;
1090 /* Row selection changed: update help */
1091 void
1092 on_treeview2_cursor_changed(GtkTreeView * treeview, gpointer user_data)
1094 GtkTreeSelection *selection;
1095 GtkTreeIter iter;
1096 struct menu *menu;
1098 selection = gtk_tree_view_get_selection(treeview);
1099 if (gtk_tree_selection_get_selected(selection, &model2, &iter)) {
1100 gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
1101 text_insert_help(menu);
1106 /* User click: display sub-tree in the right frame. */
1107 gboolean
1108 on_treeview1_button_press_event(GtkWidget * widget,
1109 GdkEventButton * event, gpointer user_data)
1111 GtkTreeView *view = GTK_TREE_VIEW(widget);
1112 GtkTreePath *path;
1113 GtkTreeViewColumn *column;
1114 GtkTreeIter iter;
1115 struct menu *menu;
1117 gint tx = (gint) event->x;
1118 gint ty = (gint) event->y;
1119 gint cx, cy;
1121 gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx,
1122 &cy);
1123 if (path == NULL)
1124 return FALSE;
1126 gtk_tree_model_get_iter(model1, &iter, path);
1127 gtk_tree_model_get(model1, &iter, COL_MENU, &menu, -1);
1129 if (event->type == GDK_2BUTTON_PRESS) {
1130 toggle_sym_value(menu);
1131 current = menu;
1132 display_tree_part();
1133 } else {
1134 browsed = menu;
1135 display_tree_part();
1138 gtk_widget_realize(tree2_w);
1139 gtk_tree_view_set_cursor(view, path, NULL, FALSE);
1140 gtk_widget_grab_focus(tree2_w);
1142 return FALSE;
1146 /* Fill a row of strings */
1147 static gchar **fill_row(struct menu *menu)
1149 static gchar *row[COL_NUMBER];
1150 struct symbol *sym = menu->sym;
1151 const char *def;
1152 int stype;
1153 tristate val;
1154 enum prop_type ptype;
1155 int i;
1157 for (i = COL_OPTION; i <= COL_COLOR; i++)
1158 g_free(row[i]);
1159 bzero(row, sizeof(row));
1161 row[COL_OPTION] =
1162 g_strdup_printf("%s %s", _(menu_get_prompt(menu)),
1163 sym && sym_has_value(sym) ? "(NEW)" : "");
1165 if (show_all && !menu_is_visible(menu))
1166 row[COL_COLOR] = g_strdup("DarkGray");
1167 else
1168 row[COL_COLOR] = g_strdup("Black");
1170 ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
1171 switch (ptype) {
1172 case P_MENU:
1173 row[COL_PIXBUF] = (gchar *) xpm_menu;
1174 if (view_mode == SINGLE_VIEW)
1175 row[COL_PIXVIS] = GINT_TO_POINTER(TRUE);
1176 row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
1177 break;
1178 case P_COMMENT:
1179 row[COL_PIXBUF] = (gchar *) xpm_void;
1180 row[COL_PIXVIS] = GINT_TO_POINTER(FALSE);
1181 row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
1182 break;
1183 default:
1184 row[COL_PIXBUF] = (gchar *) xpm_void;
1185 row[COL_PIXVIS] = GINT_TO_POINTER(FALSE);
1186 row[COL_BTNVIS] = GINT_TO_POINTER(TRUE);
1187 break;
1190 if (!sym)
1191 return row;
1192 row[COL_NAME] = g_strdup(sym->name);
1194 sym_calc_value(sym);
1195 sym->flags &= ~SYMBOL_CHANGED;
1197 if (sym_is_choice(sym)) { // parse childs for getting final value
1198 struct menu *child;
1199 struct symbol *def_sym = sym_get_choice_value(sym);
1200 struct menu *def_menu = NULL;
1202 row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
1204 for (child = menu->list; child; child = child->next) {
1205 if (menu_is_visible(child)
1206 && child->sym == def_sym)
1207 def_menu = child;
1210 if (def_menu)
1211 row[COL_VALUE] =
1212 g_strdup(_(menu_get_prompt(def_menu)));
1214 if (sym->flags & SYMBOL_CHOICEVAL)
1215 row[COL_BTNRAD] = GINT_TO_POINTER(TRUE);
1217 stype = sym_get_type(sym);
1218 switch (stype) {
1219 case S_BOOLEAN:
1220 if (GPOINTER_TO_INT(row[COL_PIXVIS]) == FALSE)
1221 row[COL_BTNVIS] = GINT_TO_POINTER(TRUE);
1222 if (sym_is_choice(sym))
1223 break;
1224 case S_TRISTATE:
1225 val = sym_get_tristate_value(sym);
1226 switch (val) {
1227 case no:
1228 row[COL_NO] = g_strdup("N");
1229 row[COL_VALUE] = g_strdup("N");
1230 row[COL_BTNACT] = GINT_TO_POINTER(FALSE);
1231 row[COL_BTNINC] = GINT_TO_POINTER(FALSE);
1232 break;
1233 case mod:
1234 row[COL_MOD] = g_strdup("M");
1235 row[COL_VALUE] = g_strdup("M");
1236 row[COL_BTNINC] = GINT_TO_POINTER(TRUE);
1237 break;
1238 case yes:
1239 row[COL_YES] = g_strdup("Y");
1240 row[COL_VALUE] = g_strdup("Y");
1241 row[COL_BTNACT] = GINT_TO_POINTER(TRUE);
1242 row[COL_BTNINC] = GINT_TO_POINTER(FALSE);
1243 break;
1246 if (val != no && sym_tristate_within_range(sym, no))
1247 row[COL_NO] = g_strdup("_");
1248 if (val != mod && sym_tristate_within_range(sym, mod))
1249 row[COL_MOD] = g_strdup("_");
1250 if (val != yes && sym_tristate_within_range(sym, yes))
1251 row[COL_YES] = g_strdup("_");
1252 break;
1253 case S_INT:
1254 case S_HEX:
1255 case S_STRING:
1256 def = sym_get_string_value(sym);
1257 row[COL_VALUE] = g_strdup(def);
1258 row[COL_EDIT] = GINT_TO_POINTER(TRUE);
1259 row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
1260 break;
1263 return row;
1267 /* Set the node content with a row of strings */
1268 static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row)
1270 GdkColor color;
1271 gboolean success;
1272 GdkPixbuf *pix;
1274 pix = gdk_pixbuf_new_from_xpm_data((const char **)
1275 row[COL_PIXBUF]);
1277 gdk_color_parse(row[COL_COLOR], &color);
1278 gdk_colormap_alloc_colors(gdk_colormap_get_system(), &color, 1,
1279 FALSE, FALSE, &success);
1281 gtk_tree_store_set(tree, node,
1282 COL_OPTION, row[COL_OPTION],
1283 COL_NAME, row[COL_NAME],
1284 COL_NO, row[COL_NO],
1285 COL_MOD, row[COL_MOD],
1286 COL_YES, row[COL_YES],
1287 COL_VALUE, row[COL_VALUE],
1288 COL_MENU, (gpointer) menu,
1289 COL_COLOR, &color,
1290 COL_EDIT, GPOINTER_TO_INT(row[COL_EDIT]),
1291 COL_PIXBUF, pix,
1292 COL_PIXVIS, GPOINTER_TO_INT(row[COL_PIXVIS]),
1293 COL_BTNVIS, GPOINTER_TO_INT(row[COL_BTNVIS]),
1294 COL_BTNACT, GPOINTER_TO_INT(row[COL_BTNACT]),
1295 COL_BTNINC, GPOINTER_TO_INT(row[COL_BTNINC]),
1296 COL_BTNRAD, GPOINTER_TO_INT(row[COL_BTNRAD]),
1297 -1);
1299 g_object_unref(pix);
1303 /* Add a node to the tree */
1304 static void place_node(struct menu *menu, char **row)
1306 GtkTreeIter *parent = parents[indent - 1];
1307 GtkTreeIter *node = parents[indent];
1309 gtk_tree_store_append(tree, node, parent);
1310 set_node(node, menu, row);
1314 /* Find a node in the GTK+ tree */
1315 static GtkTreeIter found;
1318 * Find a menu in the GtkTree starting at parent.
1320 GtkTreeIter *gtktree_iter_find_node(GtkTreeIter * parent,
1321 struct menu *tofind)
1323 GtkTreeIter iter;
1324 GtkTreeIter *child = &iter;
1325 gboolean valid;
1326 GtkTreeIter *ret;
1328 valid = gtk_tree_model_iter_children(model2, child, parent);
1329 while (valid) {
1330 struct menu *menu;
1332 gtk_tree_model_get(model2, child, 6, &menu, -1);
1334 if (menu == tofind) {
1335 memcpy(&found, child, sizeof(GtkTreeIter));
1336 return &found;
1339 ret = gtktree_iter_find_node(child, tofind);
1340 if (ret)
1341 return ret;
1343 valid = gtk_tree_model_iter_next(model2, child);
1346 return NULL;
1351 * Update the tree by adding/removing entries
1352 * Does not change other nodes
1354 static void update_tree(struct menu *src, GtkTreeIter * dst)
1356 struct menu *child1;
1357 GtkTreeIter iter, tmp;
1358 GtkTreeIter *child2 = &iter;
1359 gboolean valid;
1360 GtkTreeIter *sibling;
1361 struct symbol *sym;
1362 struct property *prop;
1363 struct menu *menu1, *menu2;
1365 if (src == &rootmenu)
1366 indent = 1;
1368 valid = gtk_tree_model_iter_children(model2, child2, dst);
1369 for (child1 = src->list; child1; child1 = child1->next) {
1371 prop = child1->prompt;
1372 sym = child1->sym;
1374 reparse:
1375 menu1 = child1;
1376 if (valid)
1377 gtk_tree_model_get(model2, child2, COL_MENU,
1378 &menu2, -1);
1379 else
1380 menu2 = NULL; // force adding of a first child
1382 #ifdef DEBUG
1383 printf("%*c%s | %s\n", indent, ' ',
1384 menu1 ? menu_get_prompt(menu1) : "nil",
1385 menu2 ? menu_get_prompt(menu2) : "nil");
1386 #endif
1388 if (!menu_is_visible(child1) && !show_all) { // remove node
1389 if (gtktree_iter_find_node(dst, menu1) != NULL) {
1390 memcpy(&tmp, child2, sizeof(GtkTreeIter));
1391 valid = gtk_tree_model_iter_next(model2,
1392 child2);
1393 gtk_tree_store_remove(tree2, &tmp);
1394 if (!valid)
1395 return; // next parent
1396 else
1397 goto reparse; // next child
1398 } else
1399 continue;
1402 if (menu1 != menu2) {
1403 if (gtktree_iter_find_node(dst, menu1) == NULL) { // add node
1404 if (!valid && !menu2)
1405 sibling = NULL;
1406 else
1407 sibling = child2;
1408 gtk_tree_store_insert_before(tree2,
1409 child2,
1410 dst, sibling);
1411 set_node(child2, menu1, fill_row(menu1));
1412 if (menu2 == NULL)
1413 valid = TRUE;
1414 } else { // remove node
1415 memcpy(&tmp, child2, sizeof(GtkTreeIter));
1416 valid = gtk_tree_model_iter_next(model2,
1417 child2);
1418 gtk_tree_store_remove(tree2, &tmp);
1419 if (!valid)
1420 return; // next parent
1421 else
1422 goto reparse; // next child
1424 } else if (sym && (sym->flags & SYMBOL_CHANGED)) {
1425 set_node(child2, menu1, fill_row(menu1));
1428 indent++;
1429 update_tree(child1, child2);
1430 indent--;
1432 valid = gtk_tree_model_iter_next(model2, child2);
1437 /* Display the whole tree (single/split/full view) */
1438 static void display_tree(struct menu *menu)
1440 struct symbol *sym;
1441 struct property *prop;
1442 struct menu *child;
1443 enum prop_type ptype;
1445 if (menu == &rootmenu) {
1446 indent = 1;
1447 current = &rootmenu;
1450 for (child = menu->list; child; child = child->next) {
1451 prop = child->prompt;
1452 sym = child->sym;
1453 ptype = prop ? prop->type : P_UNKNOWN;
1455 if (sym)
1456 sym->flags &= ~SYMBOL_CHANGED;
1458 if ((view_mode == SPLIT_VIEW)
1459 && !(child->flags & MENU_ROOT) && (tree == tree1))
1460 continue;
1462 if ((view_mode == SPLIT_VIEW) && (child->flags & MENU_ROOT)
1463 && (tree == tree2))
1464 continue;
1466 if (menu_is_visible(child) || show_all)
1467 place_node(child, fill_row(child));
1468 #ifdef DEBUG
1469 printf("%*c%s: ", indent, ' ', menu_get_prompt(child));
1470 printf("%s", child->flags & MENU_ROOT ? "rootmenu | " : "");
1471 dbg_print_ptype(ptype);
1472 printf(" | ");
1473 if (sym) {
1474 dbg_print_stype(sym->type);
1475 printf(" | ");
1476 dbg_print_flags(sym->flags);
1477 printf("\n");
1478 } else
1479 printf("\n");
1480 #endif
1481 if ((view_mode != FULL_VIEW) && (ptype == P_MENU)
1482 && (tree == tree2))
1483 continue;
1485 if (((menu != &rootmenu) && !(menu->flags & MENU_ROOT))
1486 || (view_mode == FULL_VIEW)
1487 || (view_mode == SPLIT_VIEW))*/
1488 if (((view_mode == SINGLE_VIEW) && (menu->flags & MENU_ROOT))
1489 || (view_mode == FULL_VIEW)
1490 || (view_mode == SPLIT_VIEW)) {
1491 indent++;
1492 display_tree(child);
1493 indent--;
1498 /* Display a part of the tree starting at current node (single/split view) */
1499 static void display_tree_part(void)
1501 if (tree2)
1502 gtk_tree_store_clear(tree2);
1503 if (view_mode == SINGLE_VIEW)
1504 display_tree(current);
1505 else if (view_mode == SPLIT_VIEW)
1506 display_tree(browsed);
1507 gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w));
1510 /* Display the list in the left frame (split view) */
1511 static void display_list(void)
1513 if (tree1)
1514 gtk_tree_store_clear(tree1);
1516 tree = tree1;
1517 display_tree(&rootmenu);
1518 gtk_tree_view_expand_all(GTK_TREE_VIEW(tree1_w));
1519 tree = tree2;
1522 void fixup_rootmenu(struct menu *menu)
1524 struct menu *child;
1525 static int menu_cnt = 0;
1527 menu->flags |= MENU_ROOT;
1528 for (child = menu->list; child; child = child->next) {
1529 if (child->prompt && child->prompt->type == P_MENU) {
1530 menu_cnt++;
1531 fixup_rootmenu(child);
1532 menu_cnt--;
1533 } else if (!menu_cnt)
1534 fixup_rootmenu(child);
1539 /* Main */
1540 int main(int ac, char *av[])
1542 const char *name;
1543 char *env;
1544 gchar *glade_file;
1546 #ifndef LKC_DIRECT_LINK
1547 kconfig_load();
1548 #endif
1550 bindtextdomain(PACKAGE, LOCALEDIR);
1551 bind_textdomain_codeset(PACKAGE, "UTF-8");
1552 textdomain(PACKAGE);
1554 /* GTK stuffs */
1555 gtk_set_locale();
1556 gtk_init(&ac, &av);
1557 glade_init();
1559 //add_pixmap_directory (PACKAGE_DATA_DIR "/" PACKAGE "/pixmaps");
1560 //add_pixmap_directory (PACKAGE_SOURCE_DIR "/pixmaps");
1562 /* Determine GUI path */
1563 env = getenv(SRCTREE);
1564 if (env)
1565 glade_file = g_strconcat(env, "/scripts/kconfig/gconf.glade", NULL);
1566 else if (av[0][0] == '/')
1567 glade_file = g_strconcat(av[0], ".glade", NULL);
1568 else
1569 glade_file = g_strconcat(g_get_current_dir(), "/", av[0], ".glade", NULL);
1571 /* Load the interface and connect signals */
1572 init_main_window(glade_file);
1573 init_tree_model();
1574 init_left_tree();
1575 init_right_tree();
1577 /* Conf stuffs */
1578 if (ac > 1 && av[1][0] == '-') {
1579 switch (av[1][1]) {
1580 case 'a':
1581 //showAll = 1;
1582 break;
1583 case 'h':
1584 case '?':
1585 printf("%s <config>\n", av[0]);
1586 exit(0);
1588 name = av[2];
1589 } else
1590 name = av[1];
1592 conf_parse(name);
1593 fixup_rootmenu(&rootmenu);
1594 conf_read(NULL);
1596 switch (view_mode) {
1597 case SINGLE_VIEW:
1598 display_tree_part();
1599 break;
1600 case SPLIT_VIEW:
1601 display_list();
1602 break;
1603 case FULL_VIEW:
1604 display_tree(&rootmenu);
1605 break;
1608 gtk_main();
1610 return 0;
1613 static void conf_changed(void)
1615 bool changed = conf_get_changed();
1616 gtk_widget_set_sensitive(save_btn, changed);
1617 gtk_widget_set_sensitive(save_menu_item, changed);