Linux 2.6.33-rc8
[linux-2.6/lguest.git] / scripts / kconfig / gconf.c
blob65464366fe389ab67e631c64646717c67303d05b
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, _("Linux Kernel v%s Configuration"),
270 getenv("KERNELVERSION"));
271 gtk_window_set_title(GTK_WINDOW(main_wnd), title);
273 gtk_widget_show(main_wnd);
276 void init_tree_model(void)
278 gint i;
280 tree = tree2 = gtk_tree_store_new(COL_NUMBER,
281 G_TYPE_STRING, G_TYPE_STRING,
282 G_TYPE_STRING, G_TYPE_STRING,
283 G_TYPE_STRING, G_TYPE_STRING,
284 G_TYPE_POINTER, GDK_TYPE_COLOR,
285 G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF,
286 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
287 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
288 G_TYPE_BOOLEAN);
289 model2 = GTK_TREE_MODEL(tree2);
291 for (parents[0] = NULL, i = 1; i < 256; i++)
292 parents[i] = (GtkTreeIter *) g_malloc(sizeof(GtkTreeIter));
294 tree1 = gtk_tree_store_new(COL_NUMBER,
295 G_TYPE_STRING, G_TYPE_STRING,
296 G_TYPE_STRING, G_TYPE_STRING,
297 G_TYPE_STRING, G_TYPE_STRING,
298 G_TYPE_POINTER, GDK_TYPE_COLOR,
299 G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF,
300 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
301 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
302 G_TYPE_BOOLEAN);
303 model1 = GTK_TREE_MODEL(tree1);
306 void init_left_tree(void)
308 GtkTreeView *view = GTK_TREE_VIEW(tree1_w);
309 GtkCellRenderer *renderer;
310 GtkTreeSelection *sel;
311 GtkTreeViewColumn *column;
313 gtk_tree_view_set_model(view, model1);
314 gtk_tree_view_set_headers_visible(view, TRUE);
315 gtk_tree_view_set_rules_hint(view, FALSE);
317 column = gtk_tree_view_column_new();
318 gtk_tree_view_append_column(view, column);
319 gtk_tree_view_column_set_title(column, _("Options"));
321 renderer = gtk_cell_renderer_toggle_new();
322 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
323 renderer, FALSE);
324 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
325 renderer,
326 "active", COL_BTNACT,
327 "inconsistent", COL_BTNINC,
328 "visible", COL_BTNVIS,
329 "radio", COL_BTNRAD, NULL);
330 renderer = gtk_cell_renderer_text_new();
331 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
332 renderer, FALSE);
333 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
334 renderer,
335 "text", COL_OPTION,
336 "foreground-gdk",
337 COL_COLOR, NULL);
339 sel = gtk_tree_view_get_selection(view);
340 gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
341 gtk_widget_realize(tree1_w);
344 static void renderer_edited(GtkCellRendererText * cell,
345 const gchar * path_string,
346 const gchar * new_text, gpointer user_data);
347 static void renderer_toggled(GtkCellRendererToggle * cellrenderertoggle,
348 gchar * arg1, gpointer user_data);
350 void init_right_tree(void)
352 GtkTreeView *view = GTK_TREE_VIEW(tree2_w);
353 GtkCellRenderer *renderer;
354 GtkTreeSelection *sel;
355 GtkTreeViewColumn *column;
356 gint i;
358 gtk_tree_view_set_model(view, model2);
359 gtk_tree_view_set_headers_visible(view, TRUE);
360 gtk_tree_view_set_rules_hint(view, FALSE);
362 column = gtk_tree_view_column_new();
363 gtk_tree_view_append_column(view, column);
364 gtk_tree_view_column_set_title(column, _("Options"));
366 renderer = gtk_cell_renderer_pixbuf_new();
367 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
368 renderer, FALSE);
369 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
370 renderer,
371 "pixbuf", COL_PIXBUF,
372 "visible", COL_PIXVIS, NULL);
373 renderer = gtk_cell_renderer_toggle_new();
374 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
375 renderer, FALSE);
376 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
377 renderer,
378 "active", COL_BTNACT,
379 "inconsistent", COL_BTNINC,
380 "visible", COL_BTNVIS,
381 "radio", COL_BTNRAD, NULL);
382 /*g_signal_connect(G_OBJECT(renderer), "toggled",
383 G_CALLBACK(renderer_toggled), NULL); */
384 renderer = gtk_cell_renderer_text_new();
385 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
386 renderer, FALSE);
387 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
388 renderer,
389 "text", COL_OPTION,
390 "foreground-gdk",
391 COL_COLOR, NULL);
393 renderer = gtk_cell_renderer_text_new();
394 gtk_tree_view_insert_column_with_attributes(view, -1,
395 _("Name"), renderer,
396 "text", COL_NAME,
397 "foreground-gdk",
398 COL_COLOR, NULL);
399 renderer = gtk_cell_renderer_text_new();
400 gtk_tree_view_insert_column_with_attributes(view, -1,
401 "N", renderer,
402 "text", COL_NO,
403 "foreground-gdk",
404 COL_COLOR, NULL);
405 renderer = gtk_cell_renderer_text_new();
406 gtk_tree_view_insert_column_with_attributes(view, -1,
407 "M", renderer,
408 "text", COL_MOD,
409 "foreground-gdk",
410 COL_COLOR, NULL);
411 renderer = gtk_cell_renderer_text_new();
412 gtk_tree_view_insert_column_with_attributes(view, -1,
413 "Y", renderer,
414 "text", COL_YES,
415 "foreground-gdk",
416 COL_COLOR, NULL);
417 renderer = gtk_cell_renderer_text_new();
418 gtk_tree_view_insert_column_with_attributes(view, -1,
419 _("Value"), renderer,
420 "text", COL_VALUE,
421 "editable",
422 COL_EDIT,
423 "foreground-gdk",
424 COL_COLOR, NULL);
425 g_signal_connect(G_OBJECT(renderer), "edited",
426 G_CALLBACK(renderer_edited), NULL);
428 column = gtk_tree_view_get_column(view, COL_NAME);
429 gtk_tree_view_column_set_visible(column, show_name);
430 column = gtk_tree_view_get_column(view, COL_NO);
431 gtk_tree_view_column_set_visible(column, show_range);
432 column = gtk_tree_view_get_column(view, COL_MOD);
433 gtk_tree_view_column_set_visible(column, show_range);
434 column = gtk_tree_view_get_column(view, COL_YES);
435 gtk_tree_view_column_set_visible(column, show_range);
436 column = gtk_tree_view_get_column(view, COL_VALUE);
437 gtk_tree_view_column_set_visible(column, show_value);
439 if (resizeable) {
440 for (i = 0; i < COL_VALUE; i++) {
441 column = gtk_tree_view_get_column(view, i);
442 gtk_tree_view_column_set_resizable(column, TRUE);
446 sel = gtk_tree_view_get_selection(view);
447 gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
451 /* Utility Functions */
454 static void text_insert_help(struct menu *menu)
456 GtkTextBuffer *buffer;
457 GtkTextIter start, end;
458 const char *prompt = _(menu_get_prompt(menu));
459 struct gstr help = str_new();
461 menu_get_ext_help(menu, &help);
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);
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, "\n\n", 2);
472 gtk_text_buffer_get_end_iter(buffer, &end);
473 gtk_text_buffer_insert_with_tags(buffer, &end, str_get(&help), -1, tag2,
474 NULL);
475 str_free(&help);
479 static void text_insert_msg(const char *title, const char *message)
481 GtkTextBuffer *buffer;
482 GtkTextIter start, end;
483 const char *msg = message;
485 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
486 gtk_text_buffer_get_bounds(buffer, &start, &end);
487 gtk_text_buffer_delete(buffer, &start, &end);
488 gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15);
490 gtk_text_buffer_get_end_iter(buffer, &end);
491 gtk_text_buffer_insert_with_tags(buffer, &end, title, -1, tag1,
492 NULL);
493 gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2);
494 gtk_text_buffer_get_end_iter(buffer, &end);
495 gtk_text_buffer_insert_with_tags(buffer, &end, msg, -1, tag2,
496 NULL);
500 /* Main Windows Callbacks */
502 void on_save_activate(GtkMenuItem * menuitem, gpointer user_data);
503 gboolean on_window1_delete_event(GtkWidget * widget, GdkEvent * event,
504 gpointer user_data)
506 GtkWidget *dialog, *label;
507 gint result;
509 if (!conf_get_changed())
510 return FALSE;
512 dialog = gtk_dialog_new_with_buttons(_("Warning !"),
513 GTK_WINDOW(main_wnd),
514 (GtkDialogFlags)
515 (GTK_DIALOG_MODAL |
516 GTK_DIALOG_DESTROY_WITH_PARENT),
517 GTK_STOCK_OK,
518 GTK_RESPONSE_YES,
519 GTK_STOCK_NO,
520 GTK_RESPONSE_NO,
521 GTK_STOCK_CANCEL,
522 GTK_RESPONSE_CANCEL, NULL);
523 gtk_dialog_set_default_response(GTK_DIALOG(dialog),
524 GTK_RESPONSE_CANCEL);
526 label = gtk_label_new(_("\nSave configuration ?\n"));
527 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label);
528 gtk_widget_show(label);
530 result = gtk_dialog_run(GTK_DIALOG(dialog));
531 switch (result) {
532 case GTK_RESPONSE_YES:
533 on_save_activate(NULL, NULL);
534 return FALSE;
535 case GTK_RESPONSE_NO:
536 return FALSE;
537 case GTK_RESPONSE_CANCEL:
538 case GTK_RESPONSE_DELETE_EVENT:
539 default:
540 gtk_widget_destroy(dialog);
541 return TRUE;
544 return FALSE;
548 void on_window1_destroy(GtkObject * object, gpointer user_data)
550 gtk_main_quit();
554 void
555 on_window1_size_request(GtkWidget * widget,
556 GtkRequisition * requisition, gpointer user_data)
558 static gint old_h;
559 gint w, h;
561 if (widget->window == NULL)
562 gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h);
563 else
564 gdk_window_get_size(widget->window, &w, &h);
566 if (h == old_h)
567 return;
568 old_h = h;
570 gtk_paned_set_position(GTK_PANED(vpaned), 2 * h / 3);
574 /* Menu & Toolbar Callbacks */
577 static void
578 load_filename(GtkFileSelection * file_selector, gpointer user_data)
580 const gchar *fn;
582 fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION
583 (user_data));
585 if (conf_read(fn))
586 text_insert_msg(_("Error"), _("Unable to load configuration !"));
587 else
588 display_tree(&rootmenu);
591 void on_load1_activate(GtkMenuItem * menuitem, gpointer user_data)
593 GtkWidget *fs;
595 fs = gtk_file_selection_new(_("Load file..."));
596 g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button),
597 "clicked",
598 G_CALLBACK(load_filename), (gpointer) fs);
599 g_signal_connect_swapped(GTK_OBJECT
600 (GTK_FILE_SELECTION(fs)->ok_button),
601 "clicked", G_CALLBACK(gtk_widget_destroy),
602 (gpointer) fs);
603 g_signal_connect_swapped(GTK_OBJECT
604 (GTK_FILE_SELECTION(fs)->cancel_button),
605 "clicked", G_CALLBACK(gtk_widget_destroy),
606 (gpointer) fs);
607 gtk_widget_show(fs);
611 void on_save_activate(GtkMenuItem * menuitem, gpointer user_data)
613 if (conf_write(NULL))
614 text_insert_msg(_("Error"), _("Unable to save configuration !"));
618 static void
619 store_filename(GtkFileSelection * file_selector, gpointer user_data)
621 const gchar *fn;
623 fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION
624 (user_data));
626 if (conf_write(fn))
627 text_insert_msg(_("Error"), _("Unable to save configuration !"));
629 gtk_widget_destroy(GTK_WIDGET(user_data));
632 void on_save_as1_activate(GtkMenuItem * menuitem, gpointer user_data)
634 GtkWidget *fs;
636 fs = gtk_file_selection_new(_("Save file as..."));
637 g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button),
638 "clicked",
639 G_CALLBACK(store_filename), (gpointer) fs);
640 g_signal_connect_swapped(GTK_OBJECT
641 (GTK_FILE_SELECTION(fs)->ok_button),
642 "clicked", G_CALLBACK(gtk_widget_destroy),
643 (gpointer) fs);
644 g_signal_connect_swapped(GTK_OBJECT
645 (GTK_FILE_SELECTION(fs)->cancel_button),
646 "clicked", G_CALLBACK(gtk_widget_destroy),
647 (gpointer) fs);
648 gtk_widget_show(fs);
652 void on_quit1_activate(GtkMenuItem * menuitem, gpointer user_data)
654 if (!on_window1_delete_event(NULL, NULL, NULL))
655 gtk_widget_destroy(GTK_WIDGET(main_wnd));
659 void on_show_name1_activate(GtkMenuItem * menuitem, gpointer user_data)
661 GtkTreeViewColumn *col;
663 show_name = GTK_CHECK_MENU_ITEM(menuitem)->active;
664 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NAME);
665 if (col)
666 gtk_tree_view_column_set_visible(col, show_name);
670 void on_show_range1_activate(GtkMenuItem * menuitem, gpointer user_data)
672 GtkTreeViewColumn *col;
674 show_range = GTK_CHECK_MENU_ITEM(menuitem)->active;
675 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NO);
676 if (col)
677 gtk_tree_view_column_set_visible(col, show_range);
678 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_MOD);
679 if (col)
680 gtk_tree_view_column_set_visible(col, show_range);
681 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_YES);
682 if (col)
683 gtk_tree_view_column_set_visible(col, show_range);
688 void on_show_data1_activate(GtkMenuItem * menuitem, gpointer user_data)
690 GtkTreeViewColumn *col;
692 show_value = GTK_CHECK_MENU_ITEM(menuitem)->active;
693 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_VALUE);
694 if (col)
695 gtk_tree_view_column_set_visible(col, show_value);
699 void
700 on_show_all_options1_activate(GtkMenuItem * menuitem, gpointer user_data)
702 show_all = GTK_CHECK_MENU_ITEM(menuitem)->active;
704 gtk_tree_store_clear(tree2);
705 display_tree(&rootmenu); // instead of update_tree to speed-up
709 void
710 on_show_debug_info1_activate(GtkMenuItem * menuitem, gpointer user_data)
712 show_debug = GTK_CHECK_MENU_ITEM(menuitem)->active;
713 update_tree(&rootmenu, NULL);
717 void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data)
719 GtkWidget *dialog;
720 const gchar *intro_text = _(
721 "Welcome to gkc, the GTK+ graphical kernel configuration tool\n"
722 "for Linux.\n"
723 "For each option, a blank box indicates the feature is disabled, a\n"
724 "check indicates it is enabled, and a dot indicates that it is to\n"
725 "be compiled as a module. Clicking on the box will cycle through the three states.\n"
726 "\n"
727 "If you do not see an option (e.g., a device driver) that you\n"
728 "believe should be present, try turning on Show All Options\n"
729 "under the Options menu.\n"
730 "Although there is no cross reference yet to help you figure out\n"
731 "what other options must be enabled to support the option you\n"
732 "are interested in, you can still view the help of a grayed-out\n"
733 "option.\n"
734 "\n"
735 "Toggling Show Debug Info under the Options menu will show \n"
736 "the dependencies, which you can then match by examining other options.");
738 dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
739 GTK_DIALOG_DESTROY_WITH_PARENT,
740 GTK_MESSAGE_INFO,
741 GTK_BUTTONS_CLOSE, intro_text);
742 g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
743 G_CALLBACK(gtk_widget_destroy),
744 GTK_OBJECT(dialog));
745 gtk_widget_show_all(dialog);
749 void on_about1_activate(GtkMenuItem * menuitem, gpointer user_data)
751 GtkWidget *dialog;
752 const gchar *about_text =
753 _("gkc is copyright (c) 2002 Romain Lievin <roms@lpg.ticalc.org>.\n"
754 "Based on the source code from Roman Zippel.\n");
756 dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
757 GTK_DIALOG_DESTROY_WITH_PARENT,
758 GTK_MESSAGE_INFO,
759 GTK_BUTTONS_CLOSE, about_text);
760 g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
761 G_CALLBACK(gtk_widget_destroy),
762 GTK_OBJECT(dialog));
763 gtk_widget_show_all(dialog);
767 void on_license1_activate(GtkMenuItem * menuitem, gpointer user_data)
769 GtkWidget *dialog;
770 const gchar *license_text =
771 _("gkc is released under the terms of the GNU GPL v2.\n"
772 "For more information, please see the source code or\n"
773 "visit http://www.fsf.org/licenses/licenses.html\n");
775 dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
776 GTK_DIALOG_DESTROY_WITH_PARENT,
777 GTK_MESSAGE_INFO,
778 GTK_BUTTONS_CLOSE, license_text);
779 g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
780 G_CALLBACK(gtk_widget_destroy),
781 GTK_OBJECT(dialog));
782 gtk_widget_show_all(dialog);
786 void on_back_clicked(GtkButton * button, gpointer user_data)
788 enum prop_type ptype;
790 current = current->parent;
791 ptype = current->prompt ? current->prompt->type : P_UNKNOWN;
792 if (ptype != P_MENU)
793 current = current->parent;
794 display_tree_part();
796 if (current == &rootmenu)
797 gtk_widget_set_sensitive(back_btn, FALSE);
801 void on_load_clicked(GtkButton * button, gpointer user_data)
803 on_load1_activate(NULL, user_data);
807 void on_single_clicked(GtkButton * button, gpointer user_data)
809 view_mode = SINGLE_VIEW;
810 gtk_paned_set_position(GTK_PANED(hpaned), 0);
811 gtk_widget_hide(tree1_w);
812 current = &rootmenu;
813 display_tree_part();
817 void on_split_clicked(GtkButton * button, gpointer user_data)
819 gint w, h;
820 view_mode = SPLIT_VIEW;
821 gtk_widget_show(tree1_w);
822 gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h);
823 gtk_paned_set_position(GTK_PANED(hpaned), w / 2);
824 if (tree2)
825 gtk_tree_store_clear(tree2);
826 display_list();
828 /* Disable back btn, like in full mode. */
829 gtk_widget_set_sensitive(back_btn, FALSE);
833 void on_full_clicked(GtkButton * button, gpointer user_data)
835 view_mode = FULL_VIEW;
836 gtk_paned_set_position(GTK_PANED(hpaned), 0);
837 gtk_widget_hide(tree1_w);
838 if (tree2)
839 gtk_tree_store_clear(tree2);
840 display_tree(&rootmenu);
841 gtk_widget_set_sensitive(back_btn, FALSE);
845 void on_collapse_clicked(GtkButton * button, gpointer user_data)
847 gtk_tree_view_collapse_all(GTK_TREE_VIEW(tree2_w));
851 void on_expand_clicked(GtkButton * button, gpointer user_data)
853 gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w));
857 /* CTree Callbacks */
859 /* Change hex/int/string value in the cell */
860 static void renderer_edited(GtkCellRendererText * cell,
861 const gchar * path_string,
862 const gchar * new_text, gpointer user_data)
864 GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
865 GtkTreeIter iter;
866 const char *old_def, *new_def;
867 struct menu *menu;
868 struct symbol *sym;
870 if (!gtk_tree_model_get_iter(model2, &iter, path))
871 return;
873 gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
874 sym = menu->sym;
876 gtk_tree_model_get(model2, &iter, COL_VALUE, &old_def, -1);
877 new_def = new_text;
879 sym_set_string_value(sym, new_def);
881 update_tree(&rootmenu, NULL);
883 gtk_tree_path_free(path);
886 /* Change the value of a symbol and update the tree */
887 static void change_sym_value(struct menu *menu, gint col)
889 struct symbol *sym = menu->sym;
890 tristate oldval, newval;
892 if (!sym)
893 return;
895 if (col == COL_NO)
896 newval = no;
897 else if (col == COL_MOD)
898 newval = mod;
899 else if (col == COL_YES)
900 newval = yes;
901 else
902 return;
904 switch (sym_get_type(sym)) {
905 case S_BOOLEAN:
906 case S_TRISTATE:
907 oldval = sym_get_tristate_value(sym);
908 if (!sym_tristate_within_range(sym, newval))
909 newval = yes;
910 sym_set_tristate_value(sym, newval);
911 if (view_mode == FULL_VIEW)
912 update_tree(&rootmenu, NULL);
913 else if (view_mode == SPLIT_VIEW) {
914 update_tree(browsed, NULL);
915 display_list();
917 else if (view_mode == SINGLE_VIEW)
918 display_tree_part(); //fixme: keep exp/coll
919 break;
920 case S_INT:
921 case S_HEX:
922 case S_STRING:
923 default:
924 break;
928 static void toggle_sym_value(struct menu *menu)
930 if (!menu->sym)
931 return;
933 sym_toggle_tristate_value(menu->sym);
934 if (view_mode == FULL_VIEW)
935 update_tree(&rootmenu, NULL);
936 else if (view_mode == SPLIT_VIEW) {
937 update_tree(browsed, NULL);
938 display_list();
940 else if (view_mode == SINGLE_VIEW)
941 display_tree_part(); //fixme: keep exp/coll
944 static void renderer_toggled(GtkCellRendererToggle * cell,
945 gchar * path_string, gpointer user_data)
947 GtkTreePath *path, *sel_path = NULL;
948 GtkTreeIter iter, sel_iter;
949 GtkTreeSelection *sel;
950 struct menu *menu;
952 path = gtk_tree_path_new_from_string(path_string);
953 if (!gtk_tree_model_get_iter(model2, &iter, path))
954 return;
956 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree2_w));
957 if (gtk_tree_selection_get_selected(sel, NULL, &sel_iter))
958 sel_path = gtk_tree_model_get_path(model2, &sel_iter);
959 if (!sel_path)
960 goto out1;
961 if (gtk_tree_path_compare(path, sel_path))
962 goto out2;
964 gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
965 toggle_sym_value(menu);
967 out2:
968 gtk_tree_path_free(sel_path);
969 out1:
970 gtk_tree_path_free(path);
973 static gint column2index(GtkTreeViewColumn * column)
975 gint i;
977 for (i = 0; i < COL_NUMBER; i++) {
978 GtkTreeViewColumn *col;
980 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), i);
981 if (col == column)
982 return i;
985 return -1;
989 /* User click: update choice (full) or goes down (single) */
990 gboolean
991 on_treeview2_button_press_event(GtkWidget * widget,
992 GdkEventButton * event, gpointer user_data)
994 GtkTreeView *view = GTK_TREE_VIEW(widget);
995 GtkTreePath *path;
996 GtkTreeViewColumn *column;
997 GtkTreeIter iter;
998 struct menu *menu;
999 gint col;
1001 #if GTK_CHECK_VERSION(2,1,4) // bug in ctree with earlier version of GTK
1002 gint tx = (gint) event->x;
1003 gint ty = (gint) event->y;
1004 gint cx, cy;
1006 gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx,
1007 &cy);
1008 #else
1009 gtk_tree_view_get_cursor(view, &path, &column);
1010 #endif
1011 if (path == NULL)
1012 return FALSE;
1014 if (!gtk_tree_model_get_iter(model2, &iter, path))
1015 return FALSE;
1016 gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
1018 col = column2index(column);
1019 if (event->type == GDK_2BUTTON_PRESS) {
1020 enum prop_type ptype;
1021 ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
1023 if (ptype == P_MENU && view_mode != FULL_VIEW && col == COL_OPTION) {
1024 // goes down into menu
1025 current = menu;
1026 display_tree_part();
1027 gtk_widget_set_sensitive(back_btn, TRUE);
1028 } else if ((col == COL_OPTION)) {
1029 toggle_sym_value(menu);
1030 gtk_tree_view_expand_row(view, path, TRUE);
1032 } else {
1033 if (col == COL_VALUE) {
1034 toggle_sym_value(menu);
1035 gtk_tree_view_expand_row(view, path, TRUE);
1036 } else if (col == COL_NO || col == COL_MOD
1037 || col == COL_YES) {
1038 change_sym_value(menu, col);
1039 gtk_tree_view_expand_row(view, path, TRUE);
1043 return FALSE;
1046 /* Key pressed: update choice */
1047 gboolean
1048 on_treeview2_key_press_event(GtkWidget * widget,
1049 GdkEventKey * event, gpointer user_data)
1051 GtkTreeView *view = GTK_TREE_VIEW(widget);
1052 GtkTreePath *path;
1053 GtkTreeViewColumn *column;
1054 GtkTreeIter iter;
1055 struct menu *menu;
1056 gint col;
1058 gtk_tree_view_get_cursor(view, &path, &column);
1059 if (path == NULL)
1060 return FALSE;
1062 if (event->keyval == GDK_space) {
1063 if (gtk_tree_view_row_expanded(view, path))
1064 gtk_tree_view_collapse_row(view, path);
1065 else
1066 gtk_tree_view_expand_row(view, path, FALSE);
1067 return TRUE;
1069 if (event->keyval == GDK_KP_Enter) {
1071 if (widget == tree1_w)
1072 return FALSE;
1074 gtk_tree_model_get_iter(model2, &iter, path);
1075 gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
1077 if (!strcasecmp(event->string, "n"))
1078 col = COL_NO;
1079 else if (!strcasecmp(event->string, "m"))
1080 col = COL_MOD;
1081 else if (!strcasecmp(event->string, "y"))
1082 col = COL_YES;
1083 else
1084 col = -1;
1085 change_sym_value(menu, col);
1087 return FALSE;
1091 /* Row selection changed: update help */
1092 void
1093 on_treeview2_cursor_changed(GtkTreeView * treeview, gpointer user_data)
1095 GtkTreeSelection *selection;
1096 GtkTreeIter iter;
1097 struct menu *menu;
1099 selection = gtk_tree_view_get_selection(treeview);
1100 if (gtk_tree_selection_get_selected(selection, &model2, &iter)) {
1101 gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
1102 text_insert_help(menu);
1107 /* User click: display sub-tree in the right frame. */
1108 gboolean
1109 on_treeview1_button_press_event(GtkWidget * widget,
1110 GdkEventButton * event, gpointer user_data)
1112 GtkTreeView *view = GTK_TREE_VIEW(widget);
1113 GtkTreePath *path;
1114 GtkTreeViewColumn *column;
1115 GtkTreeIter iter;
1116 struct menu *menu;
1118 gint tx = (gint) event->x;
1119 gint ty = (gint) event->y;
1120 gint cx, cy;
1122 gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx,
1123 &cy);
1124 if (path == NULL)
1125 return FALSE;
1127 gtk_tree_model_get_iter(model1, &iter, path);
1128 gtk_tree_model_get(model1, &iter, COL_MENU, &menu, -1);
1130 if (event->type == GDK_2BUTTON_PRESS) {
1131 toggle_sym_value(menu);
1132 current = menu;
1133 display_tree_part();
1134 } else {
1135 browsed = menu;
1136 display_tree_part();
1139 gtk_widget_realize(tree2_w);
1140 gtk_tree_view_set_cursor(view, path, NULL, FALSE);
1141 gtk_widget_grab_focus(tree2_w);
1143 return FALSE;
1147 /* Fill a row of strings */
1148 static gchar **fill_row(struct menu *menu)
1150 static gchar *row[COL_NUMBER];
1151 struct symbol *sym = menu->sym;
1152 const char *def;
1153 int stype;
1154 tristate val;
1155 enum prop_type ptype;
1156 int i;
1158 for (i = COL_OPTION; i <= COL_COLOR; i++)
1159 g_free(row[i]);
1160 bzero(row, sizeof(row));
1162 row[COL_OPTION] =
1163 g_strdup_printf("%s %s", _(menu_get_prompt(menu)),
1164 sym && sym_has_value(sym) ? "(NEW)" : "");
1166 if (show_all && !menu_is_visible(menu))
1167 row[COL_COLOR] = g_strdup("DarkGray");
1168 else
1169 row[COL_COLOR] = g_strdup("Black");
1171 ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
1172 switch (ptype) {
1173 case P_MENU:
1174 row[COL_PIXBUF] = (gchar *) xpm_menu;
1175 if (view_mode == SINGLE_VIEW)
1176 row[COL_PIXVIS] = GINT_TO_POINTER(TRUE);
1177 row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
1178 break;
1179 case P_COMMENT:
1180 row[COL_PIXBUF] = (gchar *) xpm_void;
1181 row[COL_PIXVIS] = GINT_TO_POINTER(FALSE);
1182 row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
1183 break;
1184 default:
1185 row[COL_PIXBUF] = (gchar *) xpm_void;
1186 row[COL_PIXVIS] = GINT_TO_POINTER(FALSE);
1187 row[COL_BTNVIS] = GINT_TO_POINTER(TRUE);
1188 break;
1191 if (!sym)
1192 return row;
1193 row[COL_NAME] = g_strdup(sym->name);
1195 sym_calc_value(sym);
1196 sym->flags &= ~SYMBOL_CHANGED;
1198 if (sym_is_choice(sym)) { // parse childs for getting final value
1199 struct menu *child;
1200 struct symbol *def_sym = sym_get_choice_value(sym);
1201 struct menu *def_menu = NULL;
1203 row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
1205 for (child = menu->list; child; child = child->next) {
1206 if (menu_is_visible(child)
1207 && child->sym == def_sym)
1208 def_menu = child;
1211 if (def_menu)
1212 row[COL_VALUE] =
1213 g_strdup(_(menu_get_prompt(def_menu)));
1215 if (sym->flags & SYMBOL_CHOICEVAL)
1216 row[COL_BTNRAD] = GINT_TO_POINTER(TRUE);
1218 stype = sym_get_type(sym);
1219 switch (stype) {
1220 case S_BOOLEAN:
1221 if (GPOINTER_TO_INT(row[COL_PIXVIS]) == FALSE)
1222 row[COL_BTNVIS] = GINT_TO_POINTER(TRUE);
1223 if (sym_is_choice(sym))
1224 break;
1225 case S_TRISTATE:
1226 val = sym_get_tristate_value(sym);
1227 switch (val) {
1228 case no:
1229 row[COL_NO] = g_strdup("N");
1230 row[COL_VALUE] = g_strdup("N");
1231 row[COL_BTNACT] = GINT_TO_POINTER(FALSE);
1232 row[COL_BTNINC] = GINT_TO_POINTER(FALSE);
1233 break;
1234 case mod:
1235 row[COL_MOD] = g_strdup("M");
1236 row[COL_VALUE] = g_strdup("M");
1237 row[COL_BTNINC] = GINT_TO_POINTER(TRUE);
1238 break;
1239 case yes:
1240 row[COL_YES] = g_strdup("Y");
1241 row[COL_VALUE] = g_strdup("Y");
1242 row[COL_BTNACT] = GINT_TO_POINTER(TRUE);
1243 row[COL_BTNINC] = GINT_TO_POINTER(FALSE);
1244 break;
1247 if (val != no && sym_tristate_within_range(sym, no))
1248 row[COL_NO] = g_strdup("_");
1249 if (val != mod && sym_tristate_within_range(sym, mod))
1250 row[COL_MOD] = g_strdup("_");
1251 if (val != yes && sym_tristate_within_range(sym, yes))
1252 row[COL_YES] = g_strdup("_");
1253 break;
1254 case S_INT:
1255 case S_HEX:
1256 case S_STRING:
1257 def = sym_get_string_value(sym);
1258 row[COL_VALUE] = g_strdup(def);
1259 row[COL_EDIT] = GINT_TO_POINTER(TRUE);
1260 row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
1261 break;
1264 return row;
1268 /* Set the node content with a row of strings */
1269 static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row)
1271 GdkColor color;
1272 gboolean success;
1273 GdkPixbuf *pix;
1275 pix = gdk_pixbuf_new_from_xpm_data((const char **)
1276 row[COL_PIXBUF]);
1278 gdk_color_parse(row[COL_COLOR], &color);
1279 gdk_colormap_alloc_colors(gdk_colormap_get_system(), &color, 1,
1280 FALSE, FALSE, &success);
1282 gtk_tree_store_set(tree, node,
1283 COL_OPTION, row[COL_OPTION],
1284 COL_NAME, row[COL_NAME],
1285 COL_NO, row[COL_NO],
1286 COL_MOD, row[COL_MOD],
1287 COL_YES, row[COL_YES],
1288 COL_VALUE, row[COL_VALUE],
1289 COL_MENU, (gpointer) menu,
1290 COL_COLOR, &color,
1291 COL_EDIT, GPOINTER_TO_INT(row[COL_EDIT]),
1292 COL_PIXBUF, pix,
1293 COL_PIXVIS, GPOINTER_TO_INT(row[COL_PIXVIS]),
1294 COL_BTNVIS, GPOINTER_TO_INT(row[COL_BTNVIS]),
1295 COL_BTNACT, GPOINTER_TO_INT(row[COL_BTNACT]),
1296 COL_BTNINC, GPOINTER_TO_INT(row[COL_BTNINC]),
1297 COL_BTNRAD, GPOINTER_TO_INT(row[COL_BTNRAD]),
1298 -1);
1300 g_object_unref(pix);
1304 /* Add a node to the tree */
1305 static void place_node(struct menu *menu, char **row)
1307 GtkTreeIter *parent = parents[indent - 1];
1308 GtkTreeIter *node = parents[indent];
1310 gtk_tree_store_append(tree, node, parent);
1311 set_node(node, menu, row);
1315 /* Find a node in the GTK+ tree */
1316 static GtkTreeIter found;
1319 * Find a menu in the GtkTree starting at parent.
1321 GtkTreeIter *gtktree_iter_find_node(GtkTreeIter * parent,
1322 struct menu *tofind)
1324 GtkTreeIter iter;
1325 GtkTreeIter *child = &iter;
1326 gboolean valid;
1327 GtkTreeIter *ret;
1329 valid = gtk_tree_model_iter_children(model2, child, parent);
1330 while (valid) {
1331 struct menu *menu;
1333 gtk_tree_model_get(model2, child, 6, &menu, -1);
1335 if (menu == tofind) {
1336 memcpy(&found, child, sizeof(GtkTreeIter));
1337 return &found;
1340 ret = gtktree_iter_find_node(child, tofind);
1341 if (ret)
1342 return ret;
1344 valid = gtk_tree_model_iter_next(model2, child);
1347 return NULL;
1352 * Update the tree by adding/removing entries
1353 * Does not change other nodes
1355 static void update_tree(struct menu *src, GtkTreeIter * dst)
1357 struct menu *child1;
1358 GtkTreeIter iter, tmp;
1359 GtkTreeIter *child2 = &iter;
1360 gboolean valid;
1361 GtkTreeIter *sibling;
1362 struct symbol *sym;
1363 struct property *prop;
1364 struct menu *menu1, *menu2;
1366 if (src == &rootmenu)
1367 indent = 1;
1369 valid = gtk_tree_model_iter_children(model2, child2, dst);
1370 for (child1 = src->list; child1; child1 = child1->next) {
1372 prop = child1->prompt;
1373 sym = child1->sym;
1375 reparse:
1376 menu1 = child1;
1377 if (valid)
1378 gtk_tree_model_get(model2, child2, COL_MENU,
1379 &menu2, -1);
1380 else
1381 menu2 = NULL; // force adding of a first child
1383 #ifdef DEBUG
1384 printf("%*c%s | %s\n", indent, ' ',
1385 menu1 ? menu_get_prompt(menu1) : "nil",
1386 menu2 ? menu_get_prompt(menu2) : "nil");
1387 #endif
1389 if (!menu_is_visible(child1) && !show_all) { // remove node
1390 if (gtktree_iter_find_node(dst, menu1) != NULL) {
1391 memcpy(&tmp, child2, sizeof(GtkTreeIter));
1392 valid = gtk_tree_model_iter_next(model2,
1393 child2);
1394 gtk_tree_store_remove(tree2, &tmp);
1395 if (!valid)
1396 return; // next parent
1397 else
1398 goto reparse; // next child
1399 } else
1400 continue;
1403 if (menu1 != menu2) {
1404 if (gtktree_iter_find_node(dst, menu1) == NULL) { // add node
1405 if (!valid && !menu2)
1406 sibling = NULL;
1407 else
1408 sibling = child2;
1409 gtk_tree_store_insert_before(tree2,
1410 child2,
1411 dst, sibling);
1412 set_node(child2, menu1, fill_row(menu1));
1413 if (menu2 == NULL)
1414 valid = TRUE;
1415 } else { // remove node
1416 memcpy(&tmp, child2, sizeof(GtkTreeIter));
1417 valid = gtk_tree_model_iter_next(model2,
1418 child2);
1419 gtk_tree_store_remove(tree2, &tmp);
1420 if (!valid)
1421 return; // next parent
1422 else
1423 goto reparse; // next child
1425 } else if (sym && (sym->flags & SYMBOL_CHANGED)) {
1426 set_node(child2, menu1, fill_row(menu1));
1429 indent++;
1430 update_tree(child1, child2);
1431 indent--;
1433 valid = gtk_tree_model_iter_next(model2, child2);
1438 /* Display the whole tree (single/split/full view) */
1439 static void display_tree(struct menu *menu)
1441 struct symbol *sym;
1442 struct property *prop;
1443 struct menu *child;
1444 enum prop_type ptype;
1446 if (menu == &rootmenu) {
1447 indent = 1;
1448 current = &rootmenu;
1451 for (child = menu->list; child; child = child->next) {
1452 prop = child->prompt;
1453 sym = child->sym;
1454 ptype = prop ? prop->type : P_UNKNOWN;
1456 if (sym)
1457 sym->flags &= ~SYMBOL_CHANGED;
1459 if ((view_mode == SPLIT_VIEW)
1460 && !(child->flags & MENU_ROOT) && (tree == tree1))
1461 continue;
1463 if ((view_mode == SPLIT_VIEW) && (child->flags & MENU_ROOT)
1464 && (tree == tree2))
1465 continue;
1467 if (menu_is_visible(child) || show_all)
1468 place_node(child, fill_row(child));
1469 #ifdef DEBUG
1470 printf("%*c%s: ", indent, ' ', menu_get_prompt(child));
1471 printf("%s", child->flags & MENU_ROOT ? "rootmenu | " : "");
1472 dbg_print_ptype(ptype);
1473 printf(" | ");
1474 if (sym) {
1475 dbg_print_stype(sym->type);
1476 printf(" | ");
1477 dbg_print_flags(sym->flags);
1478 printf("\n");
1479 } else
1480 printf("\n");
1481 #endif
1482 if ((view_mode != FULL_VIEW) && (ptype == P_MENU)
1483 && (tree == tree2))
1484 continue;
1486 if (((menu != &rootmenu) && !(menu->flags & MENU_ROOT))
1487 || (view_mode == FULL_VIEW)
1488 || (view_mode == SPLIT_VIEW))*/
1489 if (((view_mode == SINGLE_VIEW) && (menu->flags & MENU_ROOT))
1490 || (view_mode == FULL_VIEW)
1491 || (view_mode == SPLIT_VIEW)) {
1492 indent++;
1493 display_tree(child);
1494 indent--;
1499 /* Display a part of the tree starting at current node (single/split view) */
1500 static void display_tree_part(void)
1502 if (tree2)
1503 gtk_tree_store_clear(tree2);
1504 if (view_mode == SINGLE_VIEW)
1505 display_tree(current);
1506 else if (view_mode == SPLIT_VIEW)
1507 display_tree(browsed);
1508 gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w));
1511 /* Display the list in the left frame (split view) */
1512 static void display_list(void)
1514 if (tree1)
1515 gtk_tree_store_clear(tree1);
1517 tree = tree1;
1518 display_tree(&rootmenu);
1519 gtk_tree_view_expand_all(GTK_TREE_VIEW(tree1_w));
1520 tree = tree2;
1523 void fixup_rootmenu(struct menu *menu)
1525 struct menu *child;
1526 static int menu_cnt = 0;
1528 menu->flags |= MENU_ROOT;
1529 for (child = menu->list; child; child = child->next) {
1530 if (child->prompt && child->prompt->type == P_MENU) {
1531 menu_cnt++;
1532 fixup_rootmenu(child);
1533 menu_cnt--;
1534 } else if (!menu_cnt)
1535 fixup_rootmenu(child);
1540 /* Main */
1541 int main(int ac, char *av[])
1543 const char *name;
1544 char *env;
1545 gchar *glade_file;
1547 #ifndef LKC_DIRECT_LINK
1548 kconfig_load();
1549 #endif
1551 bindtextdomain(PACKAGE, LOCALEDIR);
1552 bind_textdomain_codeset(PACKAGE, "UTF-8");
1553 textdomain(PACKAGE);
1555 /* GTK stuffs */
1556 gtk_set_locale();
1557 gtk_init(&ac, &av);
1558 glade_init();
1560 //add_pixmap_directory (PACKAGE_DATA_DIR "/" PACKAGE "/pixmaps");
1561 //add_pixmap_directory (PACKAGE_SOURCE_DIR "/pixmaps");
1563 /* Determine GUI path */
1564 env = getenv(SRCTREE);
1565 if (env)
1566 glade_file = g_strconcat(env, "/scripts/kconfig/gconf.glade", NULL);
1567 else if (av[0][0] == '/')
1568 glade_file = g_strconcat(av[0], ".glade", NULL);
1569 else
1570 glade_file = g_strconcat(g_get_current_dir(), "/", av[0], ".glade", NULL);
1572 /* Load the interface and connect signals */
1573 init_main_window(glade_file);
1574 init_tree_model();
1575 init_left_tree();
1576 init_right_tree();
1578 /* Conf stuffs */
1579 if (ac > 1 && av[1][0] == '-') {
1580 switch (av[1][1]) {
1581 case 'a':
1582 //showAll = 1;
1583 break;
1584 case 'h':
1585 case '?':
1586 printf("%s <config>\n", av[0]);
1587 exit(0);
1589 name = av[2];
1590 } else
1591 name = av[1];
1593 conf_parse(name);
1594 fixup_rootmenu(&rootmenu);
1595 conf_read(NULL);
1597 switch (view_mode) {
1598 case SINGLE_VIEW:
1599 display_tree_part();
1600 break;
1601 case SPLIT_VIEW:
1602 display_list();
1603 break;
1604 case FULL_VIEW:
1605 display_tree(&rootmenu);
1606 break;
1609 gtk_main();
1611 return 0;
1614 static void conf_changed(void)
1616 bool changed = conf_get_changed();
1617 gtk_widget_set_sensitive(save_btn, changed);
1618 gtk_widget_set_sensitive(save_menu_item, changed);