locks: trivial removal of unnecessary parentheses
[pv_ops_mirror.git] / scripts / kconfig / gconf.c
blob61d8166166ef86177cf28b65575a9004f7113c08
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 static char nohelp_text[] =
42 N_("Sorry, no help available for this option yet.\n");
44 GtkWidget *main_wnd = NULL;
45 GtkWidget *tree1_w = NULL; // left frame
46 GtkWidget *tree2_w = NULL; // right frame
47 GtkWidget *text_w = NULL;
48 GtkWidget *hpaned = NULL;
49 GtkWidget *vpaned = NULL;
50 GtkWidget *back_btn = NULL;
51 GtkWidget *save_btn = NULL;
52 GtkWidget *save_menu_item = NULL;
54 GtkTextTag *tag1, *tag2;
55 GdkColor color;
57 GtkTreeStore *tree1, *tree2, *tree;
58 GtkTreeModel *model1, *model2;
59 static GtkTreeIter *parents[256];
60 static gint indent;
62 static struct menu *current; // current node for SINGLE view
63 static struct menu *browsed; // browsed node for SPLIT view
65 enum {
66 COL_OPTION, COL_NAME, COL_NO, COL_MOD, COL_YES, COL_VALUE,
67 COL_MENU, COL_COLOR, COL_EDIT, COL_PIXBUF,
68 COL_PIXVIS, COL_BTNVIS, COL_BTNACT, COL_BTNINC, COL_BTNRAD,
69 COL_NUMBER
72 static void display_list(void);
73 static void display_tree(struct menu *menu);
74 static void display_tree_part(void);
75 static void update_tree(struct menu *src, GtkTreeIter * dst);
76 static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row);
77 static gchar **fill_row(struct menu *menu);
78 static void conf_changed(void);
80 /* Helping/Debugging Functions */
83 const char *dbg_print_stype(int val)
85 static char buf[256];
87 bzero(buf, 256);
89 if (val == S_UNKNOWN)
90 strcpy(buf, "unknown");
91 if (val == S_BOOLEAN)
92 strcpy(buf, "boolean");
93 if (val == S_TRISTATE)
94 strcpy(buf, "tristate");
95 if (val == S_INT)
96 strcpy(buf, "int");
97 if (val == S_HEX)
98 strcpy(buf, "hex");
99 if (val == S_STRING)
100 strcpy(buf, "string");
101 if (val == S_OTHER)
102 strcpy(buf, "other");
104 #ifdef DEBUG
105 printf("%s", buf);
106 #endif
108 return buf;
111 const char *dbg_print_flags(int val)
113 static char buf[256];
115 bzero(buf, 256);
117 if (val & SYMBOL_CONST)
118 strcat(buf, "const/");
119 if (val & SYMBOL_CHECK)
120 strcat(buf, "check/");
121 if (val & SYMBOL_CHOICE)
122 strcat(buf, "choice/");
123 if (val & SYMBOL_CHOICEVAL)
124 strcat(buf, "choiceval/");
125 if (val & SYMBOL_PRINTED)
126 strcat(buf, "printed/");
127 if (val & SYMBOL_VALID)
128 strcat(buf, "valid/");
129 if (val & SYMBOL_OPTIONAL)
130 strcat(buf, "optional/");
131 if (val & SYMBOL_WRITE)
132 strcat(buf, "write/");
133 if (val & SYMBOL_CHANGED)
134 strcat(buf, "changed/");
135 if (val & SYMBOL_AUTO)
136 strcat(buf, "auto/");
138 buf[strlen(buf) - 1] = '\0';
139 #ifdef DEBUG
140 printf("%s", buf);
141 #endif
143 return buf;
146 const char *dbg_print_ptype(int val)
148 static char buf[256];
150 bzero(buf, 256);
152 if (val == P_UNKNOWN)
153 strcpy(buf, "unknown");
154 if (val == P_PROMPT)
155 strcpy(buf, "prompt");
156 if (val == P_COMMENT)
157 strcpy(buf, "comment");
158 if (val == P_MENU)
159 strcpy(buf, "menu");
160 if (val == P_DEFAULT)
161 strcpy(buf, "default");
162 if (val == P_CHOICE)
163 strcpy(buf, "choice");
165 #ifdef DEBUG
166 printf("%s", buf);
167 #endif
169 return buf;
173 void replace_button_icon(GladeXML * xml, GdkDrawable * window,
174 GtkStyle * style, gchar * btn_name, gchar ** xpm)
176 GdkPixmap *pixmap;
177 GdkBitmap *mask;
178 GtkToolButton *button;
179 GtkWidget *image;
181 pixmap = gdk_pixmap_create_from_xpm_d(window, &mask,
182 &style->bg[GTK_STATE_NORMAL],
183 xpm);
185 button = GTK_TOOL_BUTTON(glade_xml_get_widget(xml, btn_name));
186 image = gtk_image_new_from_pixmap(pixmap, mask);
187 gtk_widget_show(image);
188 gtk_tool_button_set_icon_widget(button, image);
191 /* Main Window Initialization */
192 void init_main_window(const gchar * glade_file)
194 GladeXML *xml;
195 GtkWidget *widget;
196 GtkTextBuffer *txtbuf;
197 char title[256];
198 GtkStyle *style;
200 xml = glade_xml_new(glade_file, "window1", NULL);
201 if (!xml)
202 g_error(_("GUI loading failed !\n"));
203 glade_xml_signal_autoconnect(xml);
205 main_wnd = glade_xml_get_widget(xml, "window1");
206 hpaned = glade_xml_get_widget(xml, "hpaned1");
207 vpaned = glade_xml_get_widget(xml, "vpaned1");
208 tree1_w = glade_xml_get_widget(xml, "treeview1");
209 tree2_w = glade_xml_get_widget(xml, "treeview2");
210 text_w = glade_xml_get_widget(xml, "textview3");
212 back_btn = glade_xml_get_widget(xml, "button1");
213 gtk_widget_set_sensitive(back_btn, FALSE);
215 widget = glade_xml_get_widget(xml, "show_name1");
216 gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
217 show_name);
219 widget = glade_xml_get_widget(xml, "show_range1");
220 gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
221 show_range);
223 widget = glade_xml_get_widget(xml, "show_data1");
224 gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
225 show_value);
227 save_btn = glade_xml_get_widget(xml, "button3");
228 save_menu_item = glade_xml_get_widget(xml, "save1");
229 conf_set_changed_callback(conf_changed);
231 style = gtk_widget_get_style(main_wnd);
232 widget = glade_xml_get_widget(xml, "toolbar1");
234 #if 0 /* Use stock Gtk icons instead */
235 replace_button_icon(xml, main_wnd->window, style,
236 "button1", (gchar **) xpm_back);
237 replace_button_icon(xml, main_wnd->window, style,
238 "button2", (gchar **) xpm_load);
239 replace_button_icon(xml, main_wnd->window, style,
240 "button3", (gchar **) xpm_save);
241 #endif
242 replace_button_icon(xml, main_wnd->window, style,
243 "button4", (gchar **) xpm_single_view);
244 replace_button_icon(xml, main_wnd->window, style,
245 "button5", (gchar **) xpm_split_view);
246 replace_button_icon(xml, main_wnd->window, style,
247 "button6", (gchar **) xpm_tree_view);
249 #if 0
250 switch (view_mode) {
251 case SINGLE_VIEW:
252 widget = glade_xml_get_widget(xml, "button4");
253 g_signal_emit_by_name(widget, "clicked");
254 break;
255 case SPLIT_VIEW:
256 widget = glade_xml_get_widget(xml, "button5");
257 g_signal_emit_by_name(widget, "clicked");
258 break;
259 case FULL_VIEW:
260 widget = glade_xml_get_widget(xml, "button6");
261 g_signal_emit_by_name(widget, "clicked");
262 break;
264 #endif
265 txtbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
266 tag1 = gtk_text_buffer_create_tag(txtbuf, "mytag1",
267 "foreground", "red",
268 "weight", PANGO_WEIGHT_BOLD,
269 NULL);
270 tag2 = gtk_text_buffer_create_tag(txtbuf, "mytag2",
271 /*"style", PANGO_STYLE_OBLIQUE, */
272 NULL);
274 sprintf(title, _("Linux Kernel v%s Configuration"),
275 getenv("KERNELVERSION"));
276 gtk_window_set_title(GTK_WINDOW(main_wnd), title);
278 gtk_widget_show(main_wnd);
281 void init_tree_model(void)
283 gint i;
285 tree = tree2 = gtk_tree_store_new(COL_NUMBER,
286 G_TYPE_STRING, G_TYPE_STRING,
287 G_TYPE_STRING, G_TYPE_STRING,
288 G_TYPE_STRING, G_TYPE_STRING,
289 G_TYPE_POINTER, GDK_TYPE_COLOR,
290 G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF,
291 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
292 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
293 G_TYPE_BOOLEAN);
294 model2 = GTK_TREE_MODEL(tree2);
296 for (parents[0] = NULL, i = 1; i < 256; i++)
297 parents[i] = (GtkTreeIter *) g_malloc(sizeof(GtkTreeIter));
299 tree1 = gtk_tree_store_new(COL_NUMBER,
300 G_TYPE_STRING, G_TYPE_STRING,
301 G_TYPE_STRING, G_TYPE_STRING,
302 G_TYPE_STRING, G_TYPE_STRING,
303 G_TYPE_POINTER, GDK_TYPE_COLOR,
304 G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF,
305 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
306 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
307 G_TYPE_BOOLEAN);
308 model1 = GTK_TREE_MODEL(tree1);
311 void init_left_tree(void)
313 GtkTreeView *view = GTK_TREE_VIEW(tree1_w);
314 GtkCellRenderer *renderer;
315 GtkTreeSelection *sel;
316 GtkTreeViewColumn *column;
318 gtk_tree_view_set_model(view, model1);
319 gtk_tree_view_set_headers_visible(view, TRUE);
320 gtk_tree_view_set_rules_hint(view, FALSE);
322 column = gtk_tree_view_column_new();
323 gtk_tree_view_append_column(view, column);
324 gtk_tree_view_column_set_title(column, _("Options"));
326 renderer = gtk_cell_renderer_toggle_new();
327 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
328 renderer, FALSE);
329 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
330 renderer,
331 "active", COL_BTNACT,
332 "inconsistent", COL_BTNINC,
333 "visible", COL_BTNVIS,
334 "radio", COL_BTNRAD, NULL);
335 renderer = gtk_cell_renderer_text_new();
336 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
337 renderer, FALSE);
338 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
339 renderer,
340 "text", COL_OPTION,
341 "foreground-gdk",
342 COL_COLOR, NULL);
344 sel = gtk_tree_view_get_selection(view);
345 gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
346 gtk_widget_realize(tree1_w);
349 static void renderer_edited(GtkCellRendererText * cell,
350 const gchar * path_string,
351 const gchar * new_text, gpointer user_data);
352 static void renderer_toggled(GtkCellRendererToggle * cellrenderertoggle,
353 gchar * arg1, gpointer user_data);
355 void init_right_tree(void)
357 GtkTreeView *view = GTK_TREE_VIEW(tree2_w);
358 GtkCellRenderer *renderer;
359 GtkTreeSelection *sel;
360 GtkTreeViewColumn *column;
361 gint i;
363 gtk_tree_view_set_model(view, model2);
364 gtk_tree_view_set_headers_visible(view, TRUE);
365 gtk_tree_view_set_rules_hint(view, FALSE);
367 column = gtk_tree_view_column_new();
368 gtk_tree_view_append_column(view, column);
369 gtk_tree_view_column_set_title(column, _("Options"));
371 renderer = gtk_cell_renderer_pixbuf_new();
372 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
373 renderer, FALSE);
374 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
375 renderer,
376 "pixbuf", COL_PIXBUF,
377 "visible", COL_PIXVIS, NULL);
378 renderer = gtk_cell_renderer_toggle_new();
379 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
380 renderer, FALSE);
381 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
382 renderer,
383 "active", COL_BTNACT,
384 "inconsistent", COL_BTNINC,
385 "visible", COL_BTNVIS,
386 "radio", COL_BTNRAD, NULL);
387 /*g_signal_connect(G_OBJECT(renderer), "toggled",
388 G_CALLBACK(renderer_toggled), NULL); */
389 renderer = gtk_cell_renderer_text_new();
390 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
391 renderer, FALSE);
392 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
393 renderer,
394 "text", COL_OPTION,
395 "foreground-gdk",
396 COL_COLOR, NULL);
398 renderer = gtk_cell_renderer_text_new();
399 gtk_tree_view_insert_column_with_attributes(view, -1,
400 _("Name"), renderer,
401 "text", COL_NAME,
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 "N", renderer,
407 "text", COL_NO,
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 "M", renderer,
413 "text", COL_MOD,
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 "Y", renderer,
419 "text", COL_YES,
420 "foreground-gdk",
421 COL_COLOR, NULL);
422 renderer = gtk_cell_renderer_text_new();
423 gtk_tree_view_insert_column_with_attributes(view, -1,
424 _("Value"), renderer,
425 "text", COL_VALUE,
426 "editable",
427 COL_EDIT,
428 "foreground-gdk",
429 COL_COLOR, NULL);
430 g_signal_connect(G_OBJECT(renderer), "edited",
431 G_CALLBACK(renderer_edited), NULL);
433 column = gtk_tree_view_get_column(view, COL_NAME);
434 gtk_tree_view_column_set_visible(column, show_name);
435 column = gtk_tree_view_get_column(view, COL_NO);
436 gtk_tree_view_column_set_visible(column, show_range);
437 column = gtk_tree_view_get_column(view, COL_MOD);
438 gtk_tree_view_column_set_visible(column, show_range);
439 column = gtk_tree_view_get_column(view, COL_YES);
440 gtk_tree_view_column_set_visible(column, show_range);
441 column = gtk_tree_view_get_column(view, COL_VALUE);
442 gtk_tree_view_column_set_visible(column, show_value);
444 if (resizeable) {
445 for (i = 0; i < COL_VALUE; i++) {
446 column = gtk_tree_view_get_column(view, i);
447 gtk_tree_view_column_set_resizable(column, TRUE);
451 sel = gtk_tree_view_get_selection(view);
452 gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
456 /* Utility Functions */
459 static void text_insert_help(struct menu *menu)
461 GtkTextBuffer *buffer;
462 GtkTextIter start, end;
463 const char *prompt = menu_get_prompt(menu);
464 gchar *name;
465 const char *help = _(nohelp_text);
467 if (!menu->sym)
468 help = "";
469 else if (menu->sym->help)
470 help = _(menu->sym->help);
472 if (menu->sym && menu->sym->name)
473 name = g_strdup_printf(_(menu->sym->name));
474 else
475 name = g_strdup("");
477 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
478 gtk_text_buffer_get_bounds(buffer, &start, &end);
479 gtk_text_buffer_delete(buffer, &start, &end);
480 gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15);
482 gtk_text_buffer_get_end_iter(buffer, &end);
483 gtk_text_buffer_insert_with_tags(buffer, &end, prompt, -1, tag1,
484 NULL);
485 gtk_text_buffer_insert_at_cursor(buffer, " ", 1);
486 gtk_text_buffer_get_end_iter(buffer, &end);
487 gtk_text_buffer_insert_with_tags(buffer, &end, name, -1, tag1,
488 NULL);
489 gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2);
490 gtk_text_buffer_get_end_iter(buffer, &end);
491 gtk_text_buffer_insert_with_tags(buffer, &end, help, -1, tag2,
492 NULL);
496 static void text_insert_msg(const char *title, const char *message)
498 GtkTextBuffer *buffer;
499 GtkTextIter start, end;
500 const char *msg = message;
502 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
503 gtk_text_buffer_get_bounds(buffer, &start, &end);
504 gtk_text_buffer_delete(buffer, &start, &end);
505 gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15);
507 gtk_text_buffer_get_end_iter(buffer, &end);
508 gtk_text_buffer_insert_with_tags(buffer, &end, title, -1, tag1,
509 NULL);
510 gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2);
511 gtk_text_buffer_get_end_iter(buffer, &end);
512 gtk_text_buffer_insert_with_tags(buffer, &end, msg, -1, tag2,
513 NULL);
517 /* Main Windows Callbacks */
519 void on_save_activate(GtkMenuItem * menuitem, gpointer user_data);
520 gboolean on_window1_delete_event(GtkWidget * widget, GdkEvent * event,
521 gpointer user_data)
523 GtkWidget *dialog, *label;
524 gint result;
526 if (!conf_get_changed())
527 return FALSE;
529 dialog = gtk_dialog_new_with_buttons(_("Warning !"),
530 GTK_WINDOW(main_wnd),
531 (GtkDialogFlags)
532 (GTK_DIALOG_MODAL |
533 GTK_DIALOG_DESTROY_WITH_PARENT),
534 GTK_STOCK_OK,
535 GTK_RESPONSE_YES,
536 GTK_STOCK_NO,
537 GTK_RESPONSE_NO,
538 GTK_STOCK_CANCEL,
539 GTK_RESPONSE_CANCEL, NULL);
540 gtk_dialog_set_default_response(GTK_DIALOG(dialog),
541 GTK_RESPONSE_CANCEL);
543 label = gtk_label_new(_("\nSave configuration ?\n"));
544 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label);
545 gtk_widget_show(label);
547 result = gtk_dialog_run(GTK_DIALOG(dialog));
548 switch (result) {
549 case GTK_RESPONSE_YES:
550 on_save_activate(NULL, NULL);
551 return FALSE;
552 case GTK_RESPONSE_NO:
553 return FALSE;
554 case GTK_RESPONSE_CANCEL:
555 case GTK_RESPONSE_DELETE_EVENT:
556 default:
557 gtk_widget_destroy(dialog);
558 return TRUE;
561 return FALSE;
565 void on_window1_destroy(GtkObject * object, gpointer user_data)
567 gtk_main_quit();
571 void
572 on_window1_size_request(GtkWidget * widget,
573 GtkRequisition * requisition, gpointer user_data)
575 static gint old_h;
576 gint w, h;
578 if (widget->window == NULL)
579 gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h);
580 else
581 gdk_window_get_size(widget->window, &w, &h);
583 if (h == old_h)
584 return;
585 old_h = h;
587 gtk_paned_set_position(GTK_PANED(vpaned), 2 * h / 3);
591 /* Menu & Toolbar Callbacks */
594 static void
595 load_filename(GtkFileSelection * file_selector, gpointer user_data)
597 const gchar *fn;
599 fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION
600 (user_data));
602 if (conf_read(fn))
603 text_insert_msg(_("Error"), _("Unable to load configuration !"));
604 else
605 display_tree(&rootmenu);
608 void on_load1_activate(GtkMenuItem * menuitem, gpointer user_data)
610 GtkWidget *fs;
612 fs = gtk_file_selection_new(_("Load file..."));
613 g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button),
614 "clicked",
615 G_CALLBACK(load_filename), (gpointer) fs);
616 g_signal_connect_swapped(GTK_OBJECT
617 (GTK_FILE_SELECTION(fs)->ok_button),
618 "clicked", G_CALLBACK(gtk_widget_destroy),
619 (gpointer) fs);
620 g_signal_connect_swapped(GTK_OBJECT
621 (GTK_FILE_SELECTION(fs)->cancel_button),
622 "clicked", G_CALLBACK(gtk_widget_destroy),
623 (gpointer) fs);
624 gtk_widget_show(fs);
628 void on_save_activate(GtkMenuItem * menuitem, gpointer user_data)
630 if (conf_write(NULL))
631 text_insert_msg(_("Error"), _("Unable to save configuration !"));
635 static void
636 store_filename(GtkFileSelection * file_selector, gpointer user_data)
638 const gchar *fn;
640 fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION
641 (user_data));
643 if (conf_write(fn))
644 text_insert_msg(_("Error"), _("Unable to save configuration !"));
646 gtk_widget_destroy(GTK_WIDGET(user_data));
649 void on_save_as1_activate(GtkMenuItem * menuitem, gpointer user_data)
651 GtkWidget *fs;
653 fs = gtk_file_selection_new(_("Save file as..."));
654 g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button),
655 "clicked",
656 G_CALLBACK(store_filename), (gpointer) fs);
657 g_signal_connect_swapped(GTK_OBJECT
658 (GTK_FILE_SELECTION(fs)->ok_button),
659 "clicked", G_CALLBACK(gtk_widget_destroy),
660 (gpointer) fs);
661 g_signal_connect_swapped(GTK_OBJECT
662 (GTK_FILE_SELECTION(fs)->cancel_button),
663 "clicked", G_CALLBACK(gtk_widget_destroy),
664 (gpointer) fs);
665 gtk_widget_show(fs);
669 void on_quit1_activate(GtkMenuItem * menuitem, gpointer user_data)
671 if (!on_window1_delete_event(NULL, NULL, NULL))
672 gtk_widget_destroy(GTK_WIDGET(main_wnd));
676 void on_show_name1_activate(GtkMenuItem * menuitem, gpointer user_data)
678 GtkTreeViewColumn *col;
680 show_name = GTK_CHECK_MENU_ITEM(menuitem)->active;
681 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NAME);
682 if (col)
683 gtk_tree_view_column_set_visible(col, show_name);
687 void on_show_range1_activate(GtkMenuItem * menuitem, gpointer user_data)
689 GtkTreeViewColumn *col;
691 show_range = GTK_CHECK_MENU_ITEM(menuitem)->active;
692 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NO);
693 if (col)
694 gtk_tree_view_column_set_visible(col, show_range);
695 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_MOD);
696 if (col)
697 gtk_tree_view_column_set_visible(col, show_range);
698 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_YES);
699 if (col)
700 gtk_tree_view_column_set_visible(col, show_range);
705 void on_show_data1_activate(GtkMenuItem * menuitem, gpointer user_data)
707 GtkTreeViewColumn *col;
709 show_value = GTK_CHECK_MENU_ITEM(menuitem)->active;
710 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_VALUE);
711 if (col)
712 gtk_tree_view_column_set_visible(col, show_value);
716 void
717 on_show_all_options1_activate(GtkMenuItem * menuitem, gpointer user_data)
719 show_all = GTK_CHECK_MENU_ITEM(menuitem)->active;
721 gtk_tree_store_clear(tree2);
722 display_tree(&rootmenu); // instead of update_tree to speed-up
726 void
727 on_show_debug_info1_activate(GtkMenuItem * menuitem, gpointer user_data)
729 show_debug = GTK_CHECK_MENU_ITEM(menuitem)->active;
730 update_tree(&rootmenu, NULL);
734 void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data)
736 GtkWidget *dialog;
737 const gchar *intro_text = _(
738 "Welcome to gkc, the GTK+ graphical kernel configuration tool\n"
739 "for Linux.\n"
740 "For each option, a blank box indicates the feature is disabled, a\n"
741 "check indicates it is enabled, and a dot indicates that it is to\n"
742 "be compiled as a module. Clicking on the box will cycle through the three states.\n"
743 "\n"
744 "If you do not see an option (e.g., a device driver) that you\n"
745 "believe should be present, try turning on Show All Options\n"
746 "under the Options menu.\n"
747 "Although there is no cross reference yet to help you figure out\n"
748 "what other options must be enabled to support the option you\n"
749 "are interested in, you can still view the help of a grayed-out\n"
750 "option.\n"
751 "\n"
752 "Toggling Show Debug Info under the Options menu will show \n"
753 "the dependencies, which you can then match by examining other options.");
755 dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
756 GTK_DIALOG_DESTROY_WITH_PARENT,
757 GTK_MESSAGE_INFO,
758 GTK_BUTTONS_CLOSE, intro_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_about1_activate(GtkMenuItem * menuitem, gpointer user_data)
768 GtkWidget *dialog;
769 const gchar *about_text =
770 _("gkc is copyright (c) 2002 Romain Lievin <roms@lpg.ticalc.org>.\n"
771 "Based on the source code from Roman Zippel.\n");
773 dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
774 GTK_DIALOG_DESTROY_WITH_PARENT,
775 GTK_MESSAGE_INFO,
776 GTK_BUTTONS_CLOSE, about_text);
777 g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
778 G_CALLBACK(gtk_widget_destroy),
779 GTK_OBJECT(dialog));
780 gtk_widget_show_all(dialog);
784 void on_license1_activate(GtkMenuItem * menuitem, gpointer user_data)
786 GtkWidget *dialog;
787 const gchar *license_text =
788 _("gkc is released under the terms of the GNU GPL v2.\n"
789 "For more information, please see the source code or\n"
790 "visit http://www.fsf.org/licenses/licenses.html\n");
792 dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
793 GTK_DIALOG_DESTROY_WITH_PARENT,
794 GTK_MESSAGE_INFO,
795 GTK_BUTTONS_CLOSE, license_text);
796 g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
797 G_CALLBACK(gtk_widget_destroy),
798 GTK_OBJECT(dialog));
799 gtk_widget_show_all(dialog);
803 void on_back_clicked(GtkButton * button, gpointer user_data)
805 enum prop_type ptype;
807 current = current->parent;
808 ptype = current->prompt ? current->prompt->type : P_UNKNOWN;
809 if (ptype != P_MENU)
810 current = current->parent;
811 display_tree_part();
813 if (current == &rootmenu)
814 gtk_widget_set_sensitive(back_btn, FALSE);
818 void on_load_clicked(GtkButton * button, gpointer user_data)
820 on_load1_activate(NULL, user_data);
824 void on_single_clicked(GtkButton * button, gpointer user_data)
826 view_mode = SINGLE_VIEW;
827 gtk_paned_set_position(GTK_PANED(hpaned), 0);
828 gtk_widget_hide(tree1_w);
829 current = &rootmenu;
830 display_tree_part();
834 void on_split_clicked(GtkButton * button, gpointer user_data)
836 gint w, h;
837 view_mode = SPLIT_VIEW;
838 gtk_widget_show(tree1_w);
839 gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h);
840 gtk_paned_set_position(GTK_PANED(hpaned), w / 2);
841 if (tree2)
842 gtk_tree_store_clear(tree2);
843 display_list();
845 /* Disable back btn, like in full mode. */
846 gtk_widget_set_sensitive(back_btn, FALSE);
850 void on_full_clicked(GtkButton * button, gpointer user_data)
852 view_mode = FULL_VIEW;
853 gtk_paned_set_position(GTK_PANED(hpaned), 0);
854 gtk_widget_hide(tree1_w);
855 if (tree2)
856 gtk_tree_store_clear(tree2);
857 display_tree(&rootmenu);
858 gtk_widget_set_sensitive(back_btn, FALSE);
862 void on_collapse_clicked(GtkButton * button, gpointer user_data)
864 gtk_tree_view_collapse_all(GTK_TREE_VIEW(tree2_w));
868 void on_expand_clicked(GtkButton * button, gpointer user_data)
870 gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w));
874 /* CTree Callbacks */
876 /* Change hex/int/string value in the cell */
877 static void renderer_edited(GtkCellRendererText * cell,
878 const gchar * path_string,
879 const gchar * new_text, gpointer user_data)
881 GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
882 GtkTreeIter iter;
883 const char *old_def, *new_def;
884 struct menu *menu;
885 struct symbol *sym;
887 if (!gtk_tree_model_get_iter(model2, &iter, path))
888 return;
890 gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
891 sym = menu->sym;
893 gtk_tree_model_get(model2, &iter, COL_VALUE, &old_def, -1);
894 new_def = new_text;
896 sym_set_string_value(sym, new_def);
898 update_tree(&rootmenu, NULL);
900 gtk_tree_path_free(path);
903 /* Change the value of a symbol and update the tree */
904 static void change_sym_value(struct menu *menu, gint col)
906 struct symbol *sym = menu->sym;
907 tristate oldval, newval;
909 if (!sym)
910 return;
912 if (col == COL_NO)
913 newval = no;
914 else if (col == COL_MOD)
915 newval = mod;
916 else if (col == COL_YES)
917 newval = yes;
918 else
919 return;
921 switch (sym_get_type(sym)) {
922 case S_BOOLEAN:
923 case S_TRISTATE:
924 oldval = sym_get_tristate_value(sym);
925 if (!sym_tristate_within_range(sym, newval))
926 newval = yes;
927 sym_set_tristate_value(sym, newval);
928 if (view_mode == FULL_VIEW)
929 update_tree(&rootmenu, NULL);
930 else if (view_mode == SPLIT_VIEW) {
931 update_tree(browsed, NULL);
932 display_list();
934 else if (view_mode == SINGLE_VIEW)
935 display_tree_part(); //fixme: keep exp/coll
936 break;
937 case S_INT:
938 case S_HEX:
939 case S_STRING:
940 default:
941 break;
945 static void toggle_sym_value(struct menu *menu)
947 if (!menu->sym)
948 return;
950 sym_toggle_tristate_value(menu->sym);
951 if (view_mode == FULL_VIEW)
952 update_tree(&rootmenu, NULL);
953 else if (view_mode == SPLIT_VIEW) {
954 update_tree(browsed, NULL);
955 display_list();
957 else if (view_mode == SINGLE_VIEW)
958 display_tree_part(); //fixme: keep exp/coll
961 static void renderer_toggled(GtkCellRendererToggle * cell,
962 gchar * path_string, gpointer user_data)
964 GtkTreePath *path, *sel_path = NULL;
965 GtkTreeIter iter, sel_iter;
966 GtkTreeSelection *sel;
967 struct menu *menu;
969 path = gtk_tree_path_new_from_string(path_string);
970 if (!gtk_tree_model_get_iter(model2, &iter, path))
971 return;
973 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree2_w));
974 if (gtk_tree_selection_get_selected(sel, NULL, &sel_iter))
975 sel_path = gtk_tree_model_get_path(model2, &sel_iter);
976 if (!sel_path)
977 goto out1;
978 if (gtk_tree_path_compare(path, sel_path))
979 goto out2;
981 gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
982 toggle_sym_value(menu);
984 out2:
985 gtk_tree_path_free(sel_path);
986 out1:
987 gtk_tree_path_free(path);
990 static gint column2index(GtkTreeViewColumn * column)
992 gint i;
994 for (i = 0; i < COL_NUMBER; i++) {
995 GtkTreeViewColumn *col;
997 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), i);
998 if (col == column)
999 return i;
1002 return -1;
1006 /* User click: update choice (full) or goes down (single) */
1007 gboolean
1008 on_treeview2_button_press_event(GtkWidget * widget,
1009 GdkEventButton * event, gpointer user_data)
1011 GtkTreeView *view = GTK_TREE_VIEW(widget);
1012 GtkTreePath *path;
1013 GtkTreeViewColumn *column;
1014 GtkTreeIter iter;
1015 struct menu *menu;
1016 gint col;
1018 #if GTK_CHECK_VERSION(2,1,4) // bug in ctree with earlier version of GTK
1019 gint tx = (gint) event->x;
1020 gint ty = (gint) event->y;
1021 gint cx, cy;
1023 gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx,
1024 &cy);
1025 #else
1026 gtk_tree_view_get_cursor(view, &path, &column);
1027 #endif
1028 if (path == NULL)
1029 return FALSE;
1031 if (!gtk_tree_model_get_iter(model2, &iter, path))
1032 return FALSE;
1033 gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
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;
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);
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);
1060 return FALSE;
1063 /* Key pressed: update choice */
1064 gboolean
1065 on_treeview2_key_press_event(GtkWidget * widget,
1066 GdkEventKey * event, gpointer user_data)
1068 GtkTreeView *view = GTK_TREE_VIEW(widget);
1069 GtkTreePath *path;
1070 GtkTreeViewColumn *column;
1071 GtkTreeIter iter;
1072 struct menu *menu;
1073 gint col;
1075 gtk_tree_view_get_cursor(view, &path, &column);
1076 if (path == NULL)
1077 return FALSE;
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;
1086 if (event->keyval == GDK_KP_Enter) {
1088 if (widget == tree1_w)
1089 return FALSE;
1091 gtk_tree_model_get_iter(model2, &iter, path);
1092 gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
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);
1104 return FALSE;
1108 /* Row selection changed: update help */
1109 void
1110 on_treeview2_cursor_changed(GtkTreeView * treeview, gpointer user_data)
1112 GtkTreeSelection *selection;
1113 GtkTreeIter iter;
1114 struct menu *menu;
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);
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)
1129 GtkTreeView *view = GTK_TREE_VIEW(widget);
1130 GtkTreePath *path;
1131 GtkTreeViewColumn *column;
1132 GtkTreeIter iter;
1133 struct menu *menu;
1135 gint tx = (gint) event->x;
1136 gint ty = (gint) event->y;
1137 gint cx, cy;
1139 gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx,
1140 &cy);
1141 if (path == NULL)
1142 return FALSE;
1144 gtk_tree_model_get_iter(model1, &iter, path);
1145 gtk_tree_model_get(model1, &iter, COL_MENU, &menu, -1);
1147 if (event->type == GDK_2BUTTON_PRESS) {
1148 toggle_sym_value(menu);
1149 current = menu;
1150 display_tree_part();
1151 } else {
1152 browsed = menu;
1153 display_tree_part();
1156 gtk_widget_realize(tree2_w);
1157 gtk_tree_view_set_cursor(view, path, NULL, FALSE);
1158 gtk_widget_grab_focus(tree2_w);
1160 return FALSE;
1164 /* Fill a row of strings */
1165 static gchar **fill_row(struct menu *menu)
1167 static gchar *row[COL_NUMBER];
1168 struct symbol *sym = menu->sym;
1169 const char *def;
1170 int stype;
1171 tristate val;
1172 enum prop_type ptype;
1173 int i;
1175 for (i = COL_OPTION; i <= COL_COLOR; i++)
1176 g_free(row[i]);
1177 bzero(row, sizeof(row));
1179 row[COL_OPTION] =
1180 g_strdup_printf("%s %s", menu_get_prompt(menu),
1181 sym && sym_has_value(sym) ? "(NEW)" : "");
1183 if (show_all && !menu_is_visible(menu))
1184 row[COL_COLOR] = g_strdup("DarkGray");
1185 else
1186 row[COL_COLOR] = g_strdup("Black");
1188 ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
1189 switch (ptype) {
1190 case P_MENU:
1191 row[COL_PIXBUF] = (gchar *) xpm_menu;
1192 if (view_mode == SINGLE_VIEW)
1193 row[COL_PIXVIS] = GINT_TO_POINTER(TRUE);
1194 row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
1195 break;
1196 case P_COMMENT:
1197 row[COL_PIXBUF] = (gchar *) xpm_void;
1198 row[COL_PIXVIS] = GINT_TO_POINTER(FALSE);
1199 row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
1200 break;
1201 default:
1202 row[COL_PIXBUF] = (gchar *) xpm_void;
1203 row[COL_PIXVIS] = GINT_TO_POINTER(FALSE);
1204 row[COL_BTNVIS] = GINT_TO_POINTER(TRUE);
1205 break;
1208 if (!sym)
1209 return row;
1210 row[COL_NAME] = g_strdup(sym->name);
1212 sym_calc_value(sym);
1213 sym->flags &= ~SYMBOL_CHANGED;
1215 if (sym_is_choice(sym)) { // parse childs for getting final value
1216 struct menu *child;
1217 struct symbol *def_sym = sym_get_choice_value(sym);
1218 struct menu *def_menu = NULL;
1220 row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
1222 for (child = menu->list; child; child = child->next) {
1223 if (menu_is_visible(child)
1224 && child->sym == def_sym)
1225 def_menu = child;
1228 if (def_menu)
1229 row[COL_VALUE] =
1230 g_strdup(menu_get_prompt(def_menu));
1232 if (sym->flags & SYMBOL_CHOICEVAL)
1233 row[COL_BTNRAD] = GINT_TO_POINTER(TRUE);
1235 stype = sym_get_type(sym);
1236 switch (stype) {
1237 case S_BOOLEAN:
1238 if (GPOINTER_TO_INT(row[COL_PIXVIS]) == FALSE)
1239 row[COL_BTNVIS] = GINT_TO_POINTER(TRUE);
1240 if (sym_is_choice(sym))
1241 break;
1242 case S_TRISTATE:
1243 val = sym_get_tristate_value(sym);
1244 switch (val) {
1245 case no:
1246 row[COL_NO] = g_strdup("N");
1247 row[COL_VALUE] = g_strdup("N");
1248 row[COL_BTNACT] = GINT_TO_POINTER(FALSE);
1249 row[COL_BTNINC] = GINT_TO_POINTER(FALSE);
1250 break;
1251 case mod:
1252 row[COL_MOD] = g_strdup("M");
1253 row[COL_VALUE] = g_strdup("M");
1254 row[COL_BTNINC] = GINT_TO_POINTER(TRUE);
1255 break;
1256 case yes:
1257 row[COL_YES] = g_strdup("Y");
1258 row[COL_VALUE] = g_strdup("Y");
1259 row[COL_BTNACT] = GINT_TO_POINTER(TRUE);
1260 row[COL_BTNINC] = GINT_TO_POINTER(FALSE);
1261 break;
1264 if (val != no && sym_tristate_within_range(sym, no))
1265 row[COL_NO] = g_strdup("_");
1266 if (val != mod && sym_tristate_within_range(sym, mod))
1267 row[COL_MOD] = g_strdup("_");
1268 if (val != yes && sym_tristate_within_range(sym, yes))
1269 row[COL_YES] = g_strdup("_");
1270 break;
1271 case S_INT:
1272 case S_HEX:
1273 case S_STRING:
1274 def = sym_get_string_value(sym);
1275 row[COL_VALUE] = g_strdup(def);
1276 row[COL_EDIT] = GINT_TO_POINTER(TRUE);
1277 row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
1278 break;
1281 return row;
1285 /* Set the node content with a row of strings */
1286 static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row)
1288 GdkColor color;
1289 gboolean success;
1290 GdkPixbuf *pix;
1292 pix = gdk_pixbuf_new_from_xpm_data((const char **)
1293 row[COL_PIXBUF]);
1295 gdk_color_parse(row[COL_COLOR], &color);
1296 gdk_colormap_alloc_colors(gdk_colormap_get_system(), &color, 1,
1297 FALSE, FALSE, &success);
1299 gtk_tree_store_set(tree, node,
1300 COL_OPTION, row[COL_OPTION],
1301 COL_NAME, row[COL_NAME],
1302 COL_NO, row[COL_NO],
1303 COL_MOD, row[COL_MOD],
1304 COL_YES, row[COL_YES],
1305 COL_VALUE, row[COL_VALUE],
1306 COL_MENU, (gpointer) menu,
1307 COL_COLOR, &color,
1308 COL_EDIT, GPOINTER_TO_INT(row[COL_EDIT]),
1309 COL_PIXBUF, pix,
1310 COL_PIXVIS, GPOINTER_TO_INT(row[COL_PIXVIS]),
1311 COL_BTNVIS, GPOINTER_TO_INT(row[COL_BTNVIS]),
1312 COL_BTNACT, GPOINTER_TO_INT(row[COL_BTNACT]),
1313 COL_BTNINC, GPOINTER_TO_INT(row[COL_BTNINC]),
1314 COL_BTNRAD, GPOINTER_TO_INT(row[COL_BTNRAD]),
1315 -1);
1317 g_object_unref(pix);
1321 /* Add a node to the tree */
1322 static void place_node(struct menu *menu, char **row)
1324 GtkTreeIter *parent = parents[indent - 1];
1325 GtkTreeIter *node = parents[indent];
1327 gtk_tree_store_append(tree, node, parent);
1328 set_node(node, menu, row);
1332 /* Find a node in the GTK+ tree */
1333 static GtkTreeIter found;
1336 * Find a menu in the GtkTree starting at parent.
1338 GtkTreeIter *gtktree_iter_find_node(GtkTreeIter * parent,
1339 struct menu *tofind)
1341 GtkTreeIter iter;
1342 GtkTreeIter *child = &iter;
1343 gboolean valid;
1344 GtkTreeIter *ret;
1346 valid = gtk_tree_model_iter_children(model2, child, parent);
1347 while (valid) {
1348 struct menu *menu;
1350 gtk_tree_model_get(model2, child, 6, &menu, -1);
1352 if (menu == tofind) {
1353 memcpy(&found, child, sizeof(GtkTreeIter));
1354 return &found;
1357 ret = gtktree_iter_find_node(child, tofind);
1358 if (ret)
1359 return ret;
1361 valid = gtk_tree_model_iter_next(model2, child);
1364 return NULL;
1369 * Update the tree by adding/removing entries
1370 * Does not change other nodes
1372 static void update_tree(struct menu *src, GtkTreeIter * dst)
1374 struct menu *child1;
1375 GtkTreeIter iter, tmp;
1376 GtkTreeIter *child2 = &iter;
1377 gboolean valid;
1378 GtkTreeIter *sibling;
1379 struct symbol *sym;
1380 struct property *prop;
1381 struct menu *menu1, *menu2;
1383 if (src == &rootmenu)
1384 indent = 1;
1386 valid = gtk_tree_model_iter_children(model2, child2, dst);
1387 for (child1 = src->list; child1; child1 = child1->next) {
1389 prop = child1->prompt;
1390 sym = child1->sym;
1392 reparse:
1393 menu1 = child1;
1394 if (valid)
1395 gtk_tree_model_get(model2, child2, COL_MENU,
1396 &menu2, -1);
1397 else
1398 menu2 = NULL; // force adding of a first child
1400 #ifdef DEBUG
1401 printf("%*c%s | %s\n", indent, ' ',
1402 menu1 ? menu_get_prompt(menu1) : "nil",
1403 menu2 ? menu_get_prompt(menu2) : "nil");
1404 #endif
1406 if (!menu_is_visible(child1) && !show_all) { // remove node
1407 if (gtktree_iter_find_node(dst, menu1) != NULL) {
1408 memcpy(&tmp, child2, sizeof(GtkTreeIter));
1409 valid = gtk_tree_model_iter_next(model2,
1410 child2);
1411 gtk_tree_store_remove(tree2, &tmp);
1412 if (!valid)
1413 return; // next parent
1414 else
1415 goto reparse; // next child
1416 } else
1417 continue;
1420 if (menu1 != menu2) {
1421 if (gtktree_iter_find_node(dst, menu1) == NULL) { // add node
1422 if (!valid && !menu2)
1423 sibling = NULL;
1424 else
1425 sibling = child2;
1426 gtk_tree_store_insert_before(tree2,
1427 child2,
1428 dst, sibling);
1429 set_node(child2, menu1, fill_row(menu1));
1430 if (menu2 == NULL)
1431 valid = TRUE;
1432 } else { // remove node
1433 memcpy(&tmp, child2, sizeof(GtkTreeIter));
1434 valid = gtk_tree_model_iter_next(model2,
1435 child2);
1436 gtk_tree_store_remove(tree2, &tmp);
1437 if (!valid)
1438 return; // next parent
1439 else
1440 goto reparse; // next child
1442 } else if (sym && (sym->flags & SYMBOL_CHANGED)) {
1443 set_node(child2, menu1, fill_row(menu1));
1446 indent++;
1447 update_tree(child1, child2);
1448 indent--;
1450 valid = gtk_tree_model_iter_next(model2, child2);
1455 /* Display the whole tree (single/split/full view) */
1456 static void display_tree(struct menu *menu)
1458 struct symbol *sym;
1459 struct property *prop;
1460 struct menu *child;
1461 enum prop_type ptype;
1463 if (menu == &rootmenu) {
1464 indent = 1;
1465 current = &rootmenu;
1468 for (child = menu->list; child; child = child->next) {
1469 prop = child->prompt;
1470 sym = child->sym;
1471 ptype = prop ? prop->type : P_UNKNOWN;
1473 if (sym)
1474 sym->flags &= ~SYMBOL_CHANGED;
1476 if ((view_mode == SPLIT_VIEW)
1477 && !(child->flags & MENU_ROOT) && (tree == tree1))
1478 continue;
1480 if ((view_mode == SPLIT_VIEW) && (child->flags & MENU_ROOT)
1481 && (tree == tree2))
1482 continue;
1484 if (menu_is_visible(child) || show_all)
1485 place_node(child, fill_row(child));
1486 #ifdef DEBUG
1487 printf("%*c%s: ", indent, ' ', menu_get_prompt(child));
1488 printf("%s", child->flags & MENU_ROOT ? "rootmenu | " : "");
1489 dbg_print_ptype(ptype);
1490 printf(" | ");
1491 if (sym) {
1492 dbg_print_stype(sym->type);
1493 printf(" | ");
1494 dbg_print_flags(sym->flags);
1495 printf("\n");
1496 } else
1497 printf("\n");
1498 #endif
1499 if ((view_mode != FULL_VIEW) && (ptype == P_MENU)
1500 && (tree == tree2))
1501 continue;
1503 if (((menu != &rootmenu) && !(menu->flags & MENU_ROOT))
1504 || (view_mode == FULL_VIEW)
1505 || (view_mode == SPLIT_VIEW))*/
1506 if (((view_mode == SINGLE_VIEW) && (menu->flags & MENU_ROOT))
1507 || (view_mode == FULL_VIEW)
1508 || (view_mode == SPLIT_VIEW)) {
1509 indent++;
1510 display_tree(child);
1511 indent--;
1516 /* Display a part of the tree starting at current node (single/split view) */
1517 static void display_tree_part(void)
1519 if (tree2)
1520 gtk_tree_store_clear(tree2);
1521 if (view_mode == SINGLE_VIEW)
1522 display_tree(current);
1523 else if (view_mode == SPLIT_VIEW)
1524 display_tree(browsed);
1525 gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w));
1528 /* Display the list in the left frame (split view) */
1529 static void display_list(void)
1531 if (tree1)
1532 gtk_tree_store_clear(tree1);
1534 tree = tree1;
1535 display_tree(&rootmenu);
1536 gtk_tree_view_expand_all(GTK_TREE_VIEW(tree1_w));
1537 tree = tree2;
1540 void fixup_rootmenu(struct menu *menu)
1542 struct menu *child;
1543 static int menu_cnt = 0;
1545 menu->flags |= MENU_ROOT;
1546 for (child = menu->list; child; child = child->next) {
1547 if (child->prompt && child->prompt->type == P_MENU) {
1548 menu_cnt++;
1549 fixup_rootmenu(child);
1550 menu_cnt--;
1551 } else if (!menu_cnt)
1552 fixup_rootmenu(child);
1557 /* Main */
1558 int main(int ac, char *av[])
1560 const char *name;
1561 char *env;
1562 gchar *glade_file;
1564 #ifndef LKC_DIRECT_LINK
1565 kconfig_load();
1566 #endif
1568 bindtextdomain(PACKAGE, LOCALEDIR);
1569 bind_textdomain_codeset(PACKAGE, "UTF-8");
1570 textdomain(PACKAGE);
1572 /* GTK stuffs */
1573 gtk_set_locale();
1574 gtk_init(&ac, &av);
1575 glade_init();
1577 //add_pixmap_directory (PACKAGE_DATA_DIR "/" PACKAGE "/pixmaps");
1578 //add_pixmap_directory (PACKAGE_SOURCE_DIR "/pixmaps");
1580 /* Determine GUI path */
1581 env = getenv(SRCTREE);
1582 if (env)
1583 glade_file = g_strconcat(env, "/scripts/kconfig/gconf.glade", NULL);
1584 else if (av[0][0] == '/')
1585 glade_file = g_strconcat(av[0], ".glade", NULL);
1586 else
1587 glade_file = g_strconcat(g_get_current_dir(), "/", av[0], ".glade", NULL);
1589 /* Load the interface and connect signals */
1590 init_main_window(glade_file);
1591 init_tree_model();
1592 init_left_tree();
1593 init_right_tree();
1595 /* Conf stuffs */
1596 if (ac > 1 && av[1][0] == '-') {
1597 switch (av[1][1]) {
1598 case 'a':
1599 //showAll = 1;
1600 break;
1601 case 'h':
1602 case '?':
1603 printf("%s <config>\n", av[0]);
1604 exit(0);
1606 name = av[2];
1607 } else
1608 name = av[1];
1610 conf_parse(name);
1611 fixup_rootmenu(&rootmenu);
1612 conf_read(NULL);
1614 switch (view_mode) {
1615 case SINGLE_VIEW:
1616 display_tree_part();
1617 break;
1618 case SPLIT_VIEW:
1619 display_list();
1620 break;
1621 case FULL_VIEW:
1622 display_tree(&rootmenu);
1623 break;
1626 gtk_main();
1628 return 0;
1631 static void conf_changed(void)
1633 bool changed = conf_get_changed();
1634 gtk_widget_set_sensitive(save_btn, changed);
1635 gtk_widget_set_sensitive(save_menu_item, changed);