also pass TARGET_CC_FLAGS
[buildroot.git] / package / config / gconf.c
blobafbddec65d0320e6fdff7c9f745c7db6504ff5ed
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_PRINTED)
123 strcat(buf, "printed/");
124 if (val & SYMBOL_VALID)
125 strcat(buf, "valid/");
126 if (val & SYMBOL_OPTIONAL)
127 strcat(buf, "optional/");
128 if (val & SYMBOL_WRITE)
129 strcat(buf, "write/");
130 if (val & SYMBOL_CHANGED)
131 strcat(buf, "changed/");
132 if (val & SYMBOL_AUTO)
133 strcat(buf, "auto/");
135 buf[strlen(buf) - 1] = '\0';
136 #ifdef DEBUG
137 printf("%s", buf);
138 #endif
140 return buf;
143 const char *dbg_print_ptype(int val)
145 static char buf[256];
147 bzero(buf, 256);
149 if (val == P_UNKNOWN)
150 strcpy(buf, "unknown");
151 if (val == P_PROMPT)
152 strcpy(buf, "prompt");
153 if (val == P_COMMENT)
154 strcpy(buf, "comment");
155 if (val == P_MENU)
156 strcpy(buf, "menu");
157 if (val == P_DEFAULT)
158 strcpy(buf, "default");
159 if (val == P_CHOICE)
160 strcpy(buf, "choice");
162 #ifdef DEBUG
163 printf("%s", buf);
164 #endif
166 return buf;
170 void replace_button_icon(GladeXML * xml, GdkDrawable * window,
171 GtkStyle * style, gchar * btn_name, gchar ** xpm)
173 GdkPixmap *pixmap;
174 GdkBitmap *mask;
175 GtkToolButton *button;
176 GtkWidget *image;
178 pixmap = gdk_pixmap_create_from_xpm_d(window, &mask,
179 &style->bg[GTK_STATE_NORMAL],
180 xpm);
182 button = GTK_TOOL_BUTTON(glade_xml_get_widget(xml, btn_name));
183 image = gtk_image_new_from_pixmap(pixmap, mask);
184 gtk_widget_show(image);
185 gtk_tool_button_set_icon_widget(button, image);
188 /* Main Window Initialization */
189 void init_main_window(const gchar * glade_file)
191 GladeXML *xml;
192 GtkWidget *widget;
193 GtkTextBuffer *txtbuf;
194 char title[256];
195 GtkStyle *style;
197 xml = glade_xml_new(glade_file, "window1", NULL);
198 if (!xml)
199 g_error(_("GUI loading failed !\n"));
200 glade_xml_signal_autoconnect(xml);
202 main_wnd = glade_xml_get_widget(xml, "window1");
203 hpaned = glade_xml_get_widget(xml, "hpaned1");
204 vpaned = glade_xml_get_widget(xml, "vpaned1");
205 tree1_w = glade_xml_get_widget(xml, "treeview1");
206 tree2_w = glade_xml_get_widget(xml, "treeview2");
207 text_w = glade_xml_get_widget(xml, "textview3");
209 back_btn = glade_xml_get_widget(xml, "button1");
210 gtk_widget_set_sensitive(back_btn, FALSE);
212 widget = glade_xml_get_widget(xml, "show_name1");
213 gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
214 show_name);
216 widget = glade_xml_get_widget(xml, "show_range1");
217 gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
218 show_range);
220 widget = glade_xml_get_widget(xml, "show_data1");
221 gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
222 show_value);
224 save_btn = glade_xml_get_widget(xml, "button3");
225 save_menu_item = glade_xml_get_widget(xml, "save1");
226 conf_set_changed_callback(conf_changed);
228 style = gtk_widget_get_style(main_wnd);
229 widget = glade_xml_get_widget(xml, "toolbar1");
231 #if 0 /* Use stock Gtk icons instead */
232 replace_button_icon(xml, main_wnd->window, style,
233 "button1", (gchar **) xpm_back);
234 replace_button_icon(xml, main_wnd->window, style,
235 "button2", (gchar **) xpm_load);
236 replace_button_icon(xml, main_wnd->window, style,
237 "button3", (gchar **) xpm_save);
238 #endif
239 replace_button_icon(xml, main_wnd->window, style,
240 "button4", (gchar **) xpm_single_view);
241 replace_button_icon(xml, main_wnd->window, style,
242 "button5", (gchar **) xpm_split_view);
243 replace_button_icon(xml, main_wnd->window, style,
244 "button6", (gchar **) xpm_tree_view);
246 #if 0
247 switch (view_mode) {
248 case SINGLE_VIEW:
249 widget = glade_xml_get_widget(xml, "button4");
250 g_signal_emit_by_name(widget, "clicked");
251 break;
252 case SPLIT_VIEW:
253 widget = glade_xml_get_widget(xml, "button5");
254 g_signal_emit_by_name(widget, "clicked");
255 break;
256 case FULL_VIEW:
257 widget = glade_xml_get_widget(xml, "button6");
258 g_signal_emit_by_name(widget, "clicked");
259 break;
261 #endif
262 txtbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
263 tag1 = gtk_text_buffer_create_tag(txtbuf, "mytag1",
264 "foreground", "red",
265 "weight", PANGO_WEIGHT_BOLD,
266 NULL);
267 tag2 = gtk_text_buffer_create_tag(txtbuf, "mytag2",
268 /*"style", PANGO_STYLE_OBLIQUE, */
269 NULL);
271 sprintf(title, _("Buildroot v%s Configuration"),
272 getenv("BR2_VERSION"));
273 gtk_window_set_title(GTK_WINDOW(main_wnd), title);
275 gtk_widget_show(main_wnd);
278 void init_tree_model(void)
280 gint i;
282 tree = tree2 = gtk_tree_store_new(COL_NUMBER,
283 G_TYPE_STRING, G_TYPE_STRING,
284 G_TYPE_STRING, G_TYPE_STRING,
285 G_TYPE_STRING, G_TYPE_STRING,
286 G_TYPE_POINTER, GDK_TYPE_COLOR,
287 G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF,
288 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
289 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
290 G_TYPE_BOOLEAN);
291 model2 = GTK_TREE_MODEL(tree2);
293 for (parents[0] = NULL, i = 1; i < 256; i++)
294 parents[i] = (GtkTreeIter *) g_malloc(sizeof(GtkTreeIter));
296 tree1 = gtk_tree_store_new(COL_NUMBER,
297 G_TYPE_STRING, G_TYPE_STRING,
298 G_TYPE_STRING, G_TYPE_STRING,
299 G_TYPE_STRING, G_TYPE_STRING,
300 G_TYPE_POINTER, GDK_TYPE_COLOR,
301 G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF,
302 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
303 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
304 G_TYPE_BOOLEAN);
305 model1 = GTK_TREE_MODEL(tree1);
308 void init_left_tree(void)
310 GtkTreeView *view = GTK_TREE_VIEW(tree1_w);
311 GtkCellRenderer *renderer;
312 GtkTreeSelection *sel;
313 GtkTreeViewColumn *column;
315 gtk_tree_view_set_model(view, model1);
316 gtk_tree_view_set_headers_visible(view, TRUE);
317 gtk_tree_view_set_rules_hint(view, FALSE);
319 column = gtk_tree_view_column_new();
320 gtk_tree_view_append_column(view, column);
321 gtk_tree_view_column_set_title(column, _("Options"));
323 renderer = gtk_cell_renderer_toggle_new();
324 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
325 renderer, FALSE);
326 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
327 renderer,
328 "active", COL_BTNACT,
329 "inconsistent", COL_BTNINC,
330 "visible", COL_BTNVIS,
331 "radio", COL_BTNRAD, NULL);
332 renderer = gtk_cell_renderer_text_new();
333 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
334 renderer, FALSE);
335 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
336 renderer,
337 "text", COL_OPTION,
338 "foreground-gdk",
339 COL_COLOR, NULL);
341 sel = gtk_tree_view_get_selection(view);
342 gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
343 gtk_widget_realize(tree1_w);
346 static void renderer_edited(GtkCellRendererText * cell,
347 const gchar * path_string,
348 const gchar * new_text, gpointer user_data);
349 static void renderer_toggled(GtkCellRendererToggle * cellrenderertoggle,
350 gchar * arg1, gpointer user_data);
352 void init_right_tree(void)
354 GtkTreeView *view = GTK_TREE_VIEW(tree2_w);
355 GtkCellRenderer *renderer;
356 GtkTreeSelection *sel;
357 GtkTreeViewColumn *column;
358 gint i;
360 gtk_tree_view_set_model(view, model2);
361 gtk_tree_view_set_headers_visible(view, TRUE);
362 gtk_tree_view_set_rules_hint(view, FALSE);
364 column = gtk_tree_view_column_new();
365 gtk_tree_view_append_column(view, column);
366 gtk_tree_view_column_set_title(column, _("Options"));
368 renderer = gtk_cell_renderer_pixbuf_new();
369 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
370 renderer, FALSE);
371 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
372 renderer,
373 "pixbuf", COL_PIXBUF,
374 "visible", COL_PIXVIS, NULL);
375 renderer = gtk_cell_renderer_toggle_new();
376 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
377 renderer, FALSE);
378 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
379 renderer,
380 "active", COL_BTNACT,
381 "inconsistent", COL_BTNINC,
382 "visible", COL_BTNVIS,
383 "radio", COL_BTNRAD, NULL);
384 /*g_signal_connect(G_OBJECT(renderer), "toggled",
385 G_CALLBACK(renderer_toggled), NULL); */
386 renderer = gtk_cell_renderer_text_new();
387 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
388 renderer, FALSE);
389 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
390 renderer,
391 "text", COL_OPTION,
392 "foreground-gdk",
393 COL_COLOR, NULL);
395 renderer = gtk_cell_renderer_text_new();
396 gtk_tree_view_insert_column_with_attributes(view, -1,
397 _("Name"), renderer,
398 "text", COL_NAME,
399 "foreground-gdk",
400 COL_COLOR, NULL);
401 renderer = gtk_cell_renderer_text_new();
402 gtk_tree_view_insert_column_with_attributes(view, -1,
403 "N", renderer,
404 "text", COL_NO,
405 "foreground-gdk",
406 COL_COLOR, NULL);
407 renderer = gtk_cell_renderer_text_new();
408 gtk_tree_view_insert_column_with_attributes(view, -1,
409 "M", renderer,
410 "text", COL_MOD,
411 "foreground-gdk",
412 COL_COLOR, NULL);
413 renderer = gtk_cell_renderer_text_new();
414 gtk_tree_view_insert_column_with_attributes(view, -1,
415 "Y", renderer,
416 "text", COL_YES,
417 "foreground-gdk",
418 COL_COLOR, NULL);
419 renderer = gtk_cell_renderer_text_new();
420 gtk_tree_view_insert_column_with_attributes(view, -1,
421 _("Value"), renderer,
422 "text", COL_VALUE,
423 "editable",
424 COL_EDIT,
425 "foreground-gdk",
426 COL_COLOR, NULL);
427 g_signal_connect(G_OBJECT(renderer), "edited",
428 G_CALLBACK(renderer_edited), NULL);
430 column = gtk_tree_view_get_column(view, COL_NAME);
431 gtk_tree_view_column_set_visible(column, show_name);
432 column = gtk_tree_view_get_column(view, COL_NO);
433 gtk_tree_view_column_set_visible(column, show_range);
434 column = gtk_tree_view_get_column(view, COL_MOD);
435 gtk_tree_view_column_set_visible(column, show_range);
436 column = gtk_tree_view_get_column(view, COL_YES);
437 gtk_tree_view_column_set_visible(column, show_range);
438 column = gtk_tree_view_get_column(view, COL_VALUE);
439 gtk_tree_view_column_set_visible(column, show_value);
441 if (resizeable) {
442 for (i = 0; i < COL_VALUE; i++) {
443 column = gtk_tree_view_get_column(view, i);
444 gtk_tree_view_column_set_resizable(column, TRUE);
448 sel = gtk_tree_view_get_selection(view);
449 gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
453 /* Utility Functions */
456 static void text_insert_help(struct menu *menu)
458 GtkTextBuffer *buffer;
459 GtkTextIter start, end;
460 const char *prompt = menu_get_prompt(menu);
461 gchar *name;
462 const char *help;
464 help = _(menu_get_help(menu));
466 if (menu->sym && menu->sym->name)
467 name = g_strdup_printf(_(menu->sym->name));
468 else
469 name = g_strdup("");
471 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
472 gtk_text_buffer_get_bounds(buffer, &start, &end);
473 gtk_text_buffer_delete(buffer, &start, &end);
474 gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15);
476 gtk_text_buffer_get_end_iter(buffer, &end);
477 gtk_text_buffer_insert_with_tags(buffer, &end, prompt, -1, tag1,
478 NULL);
479 gtk_text_buffer_insert_at_cursor(buffer, " ", 1);
480 gtk_text_buffer_get_end_iter(buffer, &end);
481 gtk_text_buffer_insert_with_tags(buffer, &end, name, -1, tag1,
482 NULL);
483 gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2);
484 gtk_text_buffer_get_end_iter(buffer, &end);
485 gtk_text_buffer_insert_with_tags(buffer, &end, help, -1, tag2,
486 NULL);
490 static void text_insert_msg(const char *title, const char *message)
492 GtkTextBuffer *buffer;
493 GtkTextIter start, end;
494 const char *msg = message;
496 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
497 gtk_text_buffer_get_bounds(buffer, &start, &end);
498 gtk_text_buffer_delete(buffer, &start, &end);
499 gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15);
501 gtk_text_buffer_get_end_iter(buffer, &end);
502 gtk_text_buffer_insert_with_tags(buffer, &end, title, -1, tag1,
503 NULL);
504 gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2);
505 gtk_text_buffer_get_end_iter(buffer, &end);
506 gtk_text_buffer_insert_with_tags(buffer, &end, msg, -1, tag2,
507 NULL);
511 /* Main Windows Callbacks */
513 void on_save_activate(GtkMenuItem * menuitem, gpointer user_data);
514 gboolean on_window1_delete_event(GtkWidget * widget, GdkEvent * event,
515 gpointer user_data)
517 GtkWidget *dialog, *label;
518 gint result;
520 if (!conf_get_changed())
521 return FALSE;
523 dialog = gtk_dialog_new_with_buttons(_("Warning !"),
524 GTK_WINDOW(main_wnd),
525 (GtkDialogFlags)
526 (GTK_DIALOG_MODAL |
527 GTK_DIALOG_DESTROY_WITH_PARENT),
528 GTK_STOCK_OK,
529 GTK_RESPONSE_YES,
530 GTK_STOCK_NO,
531 GTK_RESPONSE_NO,
532 GTK_STOCK_CANCEL,
533 GTK_RESPONSE_CANCEL, NULL);
534 gtk_dialog_set_default_response(GTK_DIALOG(dialog),
535 GTK_RESPONSE_CANCEL);
537 label = gtk_label_new(_("\nSave configuration ?\n"));
538 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label);
539 gtk_widget_show(label);
541 result = gtk_dialog_run(GTK_DIALOG(dialog));
542 switch (result) {
543 case GTK_RESPONSE_YES:
544 on_save_activate(NULL, NULL);
545 return FALSE;
546 case GTK_RESPONSE_NO:
547 return FALSE;
548 case GTK_RESPONSE_CANCEL:
549 case GTK_RESPONSE_DELETE_EVENT:
550 default:
551 gtk_widget_destroy(dialog);
552 return TRUE;
555 return FALSE;
559 void on_window1_destroy(GtkObject * object, gpointer user_data)
561 gtk_main_quit();
565 void
566 on_window1_size_request(GtkWidget * widget,
567 GtkRequisition * requisition, gpointer user_data)
569 static gint old_h;
570 gint w, h;
572 if (widget->window == NULL)
573 gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h);
574 else
575 gdk_window_get_size(widget->window, &w, &h);
577 if (h == old_h)
578 return;
579 old_h = h;
581 gtk_paned_set_position(GTK_PANED(vpaned), 2 * h / 3);
585 /* Menu & Toolbar Callbacks */
588 static void
589 load_filename(GtkFileSelection * file_selector, gpointer user_data)
591 const gchar *fn;
593 fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION
594 (user_data));
596 if (conf_read(fn))
597 text_insert_msg(_("Error"), _("Unable to load configuration !"));
598 else
599 display_tree(&rootmenu);
602 void on_load1_activate(GtkMenuItem * menuitem, gpointer user_data)
604 GtkWidget *fs;
606 fs = gtk_file_selection_new(_("Load file..."));
607 g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button),
608 "clicked",
609 G_CALLBACK(load_filename), (gpointer) fs);
610 g_signal_connect_swapped(GTK_OBJECT
611 (GTK_FILE_SELECTION(fs)->ok_button),
612 "clicked", G_CALLBACK(gtk_widget_destroy),
613 (gpointer) fs);
614 g_signal_connect_swapped(GTK_OBJECT
615 (GTK_FILE_SELECTION(fs)->cancel_button),
616 "clicked", G_CALLBACK(gtk_widget_destroy),
617 (gpointer) fs);
618 gtk_widget_show(fs);
622 void on_save_activate(GtkMenuItem * menuitem, gpointer user_data)
624 if (conf_write(NULL))
625 text_insert_msg(_("Error"), _("Unable to save configuration !"));
629 static void
630 store_filename(GtkFileSelection * file_selector, gpointer user_data)
632 const gchar *fn;
634 fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION
635 (user_data));
637 if (conf_write(fn))
638 text_insert_msg(_("Error"), _("Unable to save configuration !"));
640 gtk_widget_destroy(GTK_WIDGET(user_data));
643 void on_save_as1_activate(GtkMenuItem * menuitem, gpointer user_data)
645 GtkWidget *fs;
647 fs = gtk_file_selection_new(_("Save file as..."));
648 g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button),
649 "clicked",
650 G_CALLBACK(store_filename), (gpointer) fs);
651 g_signal_connect_swapped(GTK_OBJECT
652 (GTK_FILE_SELECTION(fs)->ok_button),
653 "clicked", G_CALLBACK(gtk_widget_destroy),
654 (gpointer) fs);
655 g_signal_connect_swapped(GTK_OBJECT
656 (GTK_FILE_SELECTION(fs)->cancel_button),
657 "clicked", G_CALLBACK(gtk_widget_destroy),
658 (gpointer) fs);
659 gtk_widget_show(fs);
663 void on_quit1_activate(GtkMenuItem * menuitem, gpointer user_data)
665 if (!on_window1_delete_event(NULL, NULL, NULL))
666 gtk_widget_destroy(GTK_WIDGET(main_wnd));
670 void on_show_name1_activate(GtkMenuItem * menuitem, gpointer user_data)
672 GtkTreeViewColumn *col;
674 show_name = GTK_CHECK_MENU_ITEM(menuitem)->active;
675 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NAME);
676 if (col)
677 gtk_tree_view_column_set_visible(col, show_name);
681 void on_show_range1_activate(GtkMenuItem * menuitem, gpointer user_data)
683 GtkTreeViewColumn *col;
685 show_range = GTK_CHECK_MENU_ITEM(menuitem)->active;
686 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NO);
687 if (col)
688 gtk_tree_view_column_set_visible(col, show_range);
689 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_MOD);
690 if (col)
691 gtk_tree_view_column_set_visible(col, show_range);
692 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_YES);
693 if (col)
694 gtk_tree_view_column_set_visible(col, show_range);
699 void on_show_data1_activate(GtkMenuItem * menuitem, gpointer user_data)
701 GtkTreeViewColumn *col;
703 show_value = GTK_CHECK_MENU_ITEM(menuitem)->active;
704 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_VALUE);
705 if (col)
706 gtk_tree_view_column_set_visible(col, show_value);
710 void
711 on_show_all_options1_activate(GtkMenuItem * menuitem, gpointer user_data)
713 show_all = GTK_CHECK_MENU_ITEM(menuitem)->active;
715 gtk_tree_store_clear(tree2);
716 display_tree(&rootmenu); // instead of update_tree to speed-up
720 void
721 on_show_debug_info1_activate(GtkMenuItem * menuitem, gpointer user_data)
723 show_debug = GTK_CHECK_MENU_ITEM(menuitem)->active;
724 update_tree(&rootmenu, NULL);
728 void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data)
730 GtkWidget *dialog;
731 const gchar *intro_text = _(
732 "Welcome to gkc, the GTK+ graphical kernel configuration tool\n"
733 "for Linux.\n"
734 "For each option, a blank box indicates the feature is disabled, a\n"
735 "check indicates it is enabled, and a dot indicates that it is to\n"
736 "be compiled as a module. Clicking on the box will cycle through the three states.\n"
737 "\n"
738 "If you do not see an option (e.g., a device driver) that you\n"
739 "believe should be present, try turning on Show All Options\n"
740 "under the Options menu.\n"
741 "Although there is no cross reference yet to help you figure out\n"
742 "what other options must be enabled to support the option you\n"
743 "are interested in, you can still view the help of a grayed-out\n"
744 "option.\n"
745 "\n"
746 "Toggling Show Debug Info under the Options menu will show \n"
747 "the dependencies, which you can then match by examining other options.");
749 dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
750 GTK_DIALOG_DESTROY_WITH_PARENT,
751 GTK_MESSAGE_INFO,
752 GTK_BUTTONS_CLOSE, intro_text);
753 g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
754 G_CALLBACK(gtk_widget_destroy),
755 GTK_OBJECT(dialog));
756 gtk_widget_show_all(dialog);
760 void on_about1_activate(GtkMenuItem * menuitem, gpointer user_data)
762 GtkWidget *dialog;
763 const gchar *about_text =
764 _("gkc is copyright (c) 2002 Romain Lievin <roms@lpg.ticalc.org>.\n"
765 "Based on the source code from Roman Zippel.\n");
767 dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
768 GTK_DIALOG_DESTROY_WITH_PARENT,
769 GTK_MESSAGE_INFO,
770 GTK_BUTTONS_CLOSE, about_text);
771 g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
772 G_CALLBACK(gtk_widget_destroy),
773 GTK_OBJECT(dialog));
774 gtk_widget_show_all(dialog);
778 void on_license1_activate(GtkMenuItem * menuitem, gpointer user_data)
780 GtkWidget *dialog;
781 const gchar *license_text =
782 _("gkc is released under the terms of the GNU GPL v2.\n"
783 "For more information, please see the source code or\n"
784 "visit http://www.fsf.org/licenses/licenses.html\n");
786 dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
787 GTK_DIALOG_DESTROY_WITH_PARENT,
788 GTK_MESSAGE_INFO,
789 GTK_BUTTONS_CLOSE, license_text);
790 g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
791 G_CALLBACK(gtk_widget_destroy),
792 GTK_OBJECT(dialog));
793 gtk_widget_show_all(dialog);
797 void on_back_clicked(GtkButton * button, gpointer user_data)
799 enum prop_type ptype;
801 current = current->parent;
802 ptype = current->prompt ? current->prompt->type : P_UNKNOWN;
803 if (ptype != P_MENU)
804 current = current->parent;
805 display_tree_part();
807 if (current == &rootmenu)
808 gtk_widget_set_sensitive(back_btn, FALSE);
812 void on_load_clicked(GtkButton * button, gpointer user_data)
814 on_load1_activate(NULL, user_data);
818 void on_single_clicked(GtkButton * button, gpointer user_data)
820 view_mode = SINGLE_VIEW;
821 gtk_paned_set_position(GTK_PANED(hpaned), 0);
822 gtk_widget_hide(tree1_w);
823 current = &rootmenu;
824 display_tree_part();
828 void on_split_clicked(GtkButton * button, gpointer user_data)
830 gint w, h;
831 view_mode = SPLIT_VIEW;
832 gtk_widget_show(tree1_w);
833 gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h);
834 gtk_paned_set_position(GTK_PANED(hpaned), w / 2);
835 if (tree2)
836 gtk_tree_store_clear(tree2);
837 display_list();
839 /* Disable back btn, like in full mode. */
840 gtk_widget_set_sensitive(back_btn, FALSE);
844 void on_full_clicked(GtkButton * button, gpointer user_data)
846 view_mode = FULL_VIEW;
847 gtk_paned_set_position(GTK_PANED(hpaned), 0);
848 gtk_widget_hide(tree1_w);
849 if (tree2)
850 gtk_tree_store_clear(tree2);
851 display_tree(&rootmenu);
852 gtk_widget_set_sensitive(back_btn, FALSE);
856 void on_collapse_clicked(GtkButton * button, gpointer user_data)
858 gtk_tree_view_collapse_all(GTK_TREE_VIEW(tree2_w));
862 void on_expand_clicked(GtkButton * button, gpointer user_data)
864 gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w));
868 /* CTree Callbacks */
870 /* Change hex/int/string value in the cell */
871 static void renderer_edited(GtkCellRendererText * cell,
872 const gchar * path_string,
873 const gchar * new_text, gpointer user_data)
875 GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
876 GtkTreeIter iter;
877 const char *old_def, *new_def;
878 struct menu *menu;
879 struct symbol *sym;
881 if (!gtk_tree_model_get_iter(model2, &iter, path))
882 return;
884 gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
885 sym = menu->sym;
887 gtk_tree_model_get(model2, &iter, COL_VALUE, &old_def, -1);
888 new_def = new_text;
890 sym_set_string_value(sym, new_def);
892 update_tree(&rootmenu, NULL);
894 gtk_tree_path_free(path);
897 /* Change the value of a symbol and update the tree */
898 static void change_sym_value(struct menu *menu, gint col)
900 struct symbol *sym = menu->sym;
901 tristate oldval, newval;
903 if (!sym)
904 return;
906 if (col == COL_NO)
907 newval = no;
908 else if (col == COL_MOD)
909 newval = mod;
910 else if (col == COL_YES)
911 newval = yes;
912 else
913 return;
915 switch (sym_get_type(sym)) {
916 case S_BOOLEAN:
917 case S_TRISTATE:
918 oldval = sym_get_tristate_value(sym);
919 if (!sym_tristate_within_range(sym, newval))
920 newval = yes;
921 sym_set_tristate_value(sym, newval);
922 if (view_mode == FULL_VIEW)
923 update_tree(&rootmenu, NULL);
924 else if (view_mode == SPLIT_VIEW) {
925 update_tree(browsed, NULL);
926 display_list();
928 else if (view_mode == SINGLE_VIEW)
929 display_tree_part(); //fixme: keep exp/coll
930 break;
931 case S_INT:
932 case S_HEX:
933 case S_STRING:
934 default:
935 break;
939 static void toggle_sym_value(struct menu *menu)
941 if (!menu->sym)
942 return;
944 sym_toggle_tristate_value(menu->sym);
945 if (view_mode == FULL_VIEW)
946 update_tree(&rootmenu, NULL);
947 else if (view_mode == SPLIT_VIEW) {
948 update_tree(browsed, NULL);
949 display_list();
951 else if (view_mode == SINGLE_VIEW)
952 display_tree_part(); //fixme: keep exp/coll
955 static void renderer_toggled(GtkCellRendererToggle * cell,
956 gchar * path_string, gpointer user_data)
958 GtkTreePath *path, *sel_path = NULL;
959 GtkTreeIter iter, sel_iter;
960 GtkTreeSelection *sel;
961 struct menu *menu;
963 path = gtk_tree_path_new_from_string(path_string);
964 if (!gtk_tree_model_get_iter(model2, &iter, path))
965 return;
967 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree2_w));
968 if (gtk_tree_selection_get_selected(sel, NULL, &sel_iter))
969 sel_path = gtk_tree_model_get_path(model2, &sel_iter);
970 if (!sel_path)
971 goto out1;
972 if (gtk_tree_path_compare(path, sel_path))
973 goto out2;
975 gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
976 toggle_sym_value(menu);
978 out2:
979 gtk_tree_path_free(sel_path);
980 out1:
981 gtk_tree_path_free(path);
984 static gint column2index(GtkTreeViewColumn * column)
986 gint i;
988 for (i = 0; i < COL_NUMBER; i++) {
989 GtkTreeViewColumn *col;
991 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), i);
992 if (col == column)
993 return i;
996 return -1;
1000 /* User click: update choice (full) or goes down (single) */
1001 gboolean
1002 on_treeview2_button_press_event(GtkWidget * widget,
1003 GdkEventButton * event, gpointer user_data)
1005 GtkTreeView *view = GTK_TREE_VIEW(widget);
1006 GtkTreePath *path;
1007 GtkTreeViewColumn *column;
1008 GtkTreeIter iter;
1009 struct menu *menu;
1010 gint col;
1012 #if GTK_CHECK_VERSION(2,1,4) // bug in ctree with earlier version of GTK
1013 gint tx = (gint) event->x;
1014 gint ty = (gint) event->y;
1015 gint cx, cy;
1017 gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx,
1018 &cy);
1019 #else
1020 gtk_tree_view_get_cursor(view, &path, &column);
1021 #endif
1022 if (path == NULL)
1023 return FALSE;
1025 if (!gtk_tree_model_get_iter(model2, &iter, path))
1026 return FALSE;
1027 gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
1029 col = column2index(column);
1030 if (event->type == GDK_2BUTTON_PRESS) {
1031 enum prop_type ptype;
1032 ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
1034 if (ptype == P_MENU && view_mode != FULL_VIEW && col == COL_OPTION) {
1035 // goes down into menu
1036 current = menu;
1037 display_tree_part();
1038 gtk_widget_set_sensitive(back_btn, TRUE);
1039 } else if ((col == COL_OPTION)) {
1040 toggle_sym_value(menu);
1041 gtk_tree_view_expand_row(view, path, TRUE);
1043 } else {
1044 if (col == COL_VALUE) {
1045 toggle_sym_value(menu);
1046 gtk_tree_view_expand_row(view, path, TRUE);
1047 } else if (col == COL_NO || col == COL_MOD
1048 || col == COL_YES) {
1049 change_sym_value(menu, col);
1050 gtk_tree_view_expand_row(view, path, TRUE);
1054 return FALSE;
1057 /* Key pressed: update choice */
1058 gboolean
1059 on_treeview2_key_press_event(GtkWidget * widget,
1060 GdkEventKey * event, gpointer user_data)
1062 GtkTreeView *view = GTK_TREE_VIEW(widget);
1063 GtkTreePath *path;
1064 GtkTreeViewColumn *column;
1065 GtkTreeIter iter;
1066 struct menu *menu;
1067 gint col;
1069 gtk_tree_view_get_cursor(view, &path, &column);
1070 if (path == NULL)
1071 return FALSE;
1073 if (event->keyval == GDK_space) {
1074 if (gtk_tree_view_row_expanded(view, path))
1075 gtk_tree_view_collapse_row(view, path);
1076 else
1077 gtk_tree_view_expand_row(view, path, FALSE);
1078 return TRUE;
1080 if (event->keyval == GDK_KP_Enter) {
1082 if (widget == tree1_w)
1083 return FALSE;
1085 gtk_tree_model_get_iter(model2, &iter, path);
1086 gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
1088 if (!strcasecmp(event->string, "n"))
1089 col = COL_NO;
1090 else if (!strcasecmp(event->string, "m"))
1091 col = COL_MOD;
1092 else if (!strcasecmp(event->string, "y"))
1093 col = COL_YES;
1094 else
1095 col = -1;
1096 change_sym_value(menu, col);
1098 return FALSE;
1102 /* Row selection changed: update help */
1103 void
1104 on_treeview2_cursor_changed(GtkTreeView * treeview, gpointer user_data)
1106 GtkTreeSelection *selection;
1107 GtkTreeIter iter;
1108 struct menu *menu;
1110 selection = gtk_tree_view_get_selection(treeview);
1111 if (gtk_tree_selection_get_selected(selection, &model2, &iter)) {
1112 gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
1113 text_insert_help(menu);
1118 /* User click: display sub-tree in the right frame. */
1119 gboolean
1120 on_treeview1_button_press_event(GtkWidget * widget,
1121 GdkEventButton * event, gpointer user_data)
1123 GtkTreeView *view = GTK_TREE_VIEW(widget);
1124 GtkTreePath *path;
1125 GtkTreeViewColumn *column;
1126 GtkTreeIter iter;
1127 struct menu *menu;
1129 gint tx = (gint) event->x;
1130 gint ty = (gint) event->y;
1131 gint cx, cy;
1133 gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx,
1134 &cy);
1135 if (path == NULL)
1136 return FALSE;
1138 gtk_tree_model_get_iter(model1, &iter, path);
1139 gtk_tree_model_get(model1, &iter, COL_MENU, &menu, -1);
1141 if (event->type == GDK_2BUTTON_PRESS) {
1142 toggle_sym_value(menu);
1143 current = menu;
1144 display_tree_part();
1145 } else {
1146 browsed = menu;
1147 display_tree_part();
1150 gtk_widget_realize(tree2_w);
1151 gtk_tree_view_set_cursor(view, path, NULL, FALSE);
1152 gtk_widget_grab_focus(tree2_w);
1154 return FALSE;
1158 /* Fill a row of strings */
1159 static gchar **fill_row(struct menu *menu)
1161 static gchar *row[COL_NUMBER];
1162 struct symbol *sym = menu->sym;
1163 const char *def;
1164 int stype;
1165 tristate val;
1166 enum prop_type ptype;
1167 int i;
1169 for (i = COL_OPTION; i <= COL_COLOR; i++)
1170 g_free(row[i]);
1171 bzero(row, sizeof(row));
1173 row[COL_OPTION] =
1174 g_strdup_printf("%s %s", menu_get_prompt(menu),
1175 sym && sym_has_value(sym) ? "(NEW)" : "");
1177 if (show_all && !menu_is_visible(menu))
1178 row[COL_COLOR] = g_strdup("DarkGray");
1179 else
1180 row[COL_COLOR] = g_strdup("Black");
1182 ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
1183 switch (ptype) {
1184 case P_MENU:
1185 row[COL_PIXBUF] = (gchar *) xpm_menu;
1186 if (view_mode == SINGLE_VIEW)
1187 row[COL_PIXVIS] = GINT_TO_POINTER(TRUE);
1188 row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
1189 break;
1190 case P_COMMENT:
1191 row[COL_PIXBUF] = (gchar *) xpm_void;
1192 row[COL_PIXVIS] = GINT_TO_POINTER(FALSE);
1193 row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
1194 break;
1195 default:
1196 row[COL_PIXBUF] = (gchar *) xpm_void;
1197 row[COL_PIXVIS] = GINT_TO_POINTER(FALSE);
1198 row[COL_BTNVIS] = GINT_TO_POINTER(TRUE);
1199 break;
1202 if (!sym)
1203 return row;
1204 row[COL_NAME] = g_strdup(sym->name);
1206 sym_calc_value(sym);
1207 sym->flags &= ~SYMBOL_CHANGED;
1209 if (sym_is_choice(sym)) { // parse childs for getting final value
1210 struct menu *child;
1211 struct symbol *def_sym = sym_get_choice_value(sym);
1212 struct menu *def_menu = NULL;
1214 row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
1216 for (child = menu->list; child; child = child->next) {
1217 if (menu_is_visible(child)
1218 && child->sym == def_sym)
1219 def_menu = child;
1222 if (def_menu)
1223 row[COL_VALUE] =
1224 g_strdup(menu_get_prompt(def_menu));
1226 if (sym->flags & SYMBOL_CHOICEVAL)
1227 row[COL_BTNRAD] = GINT_TO_POINTER(TRUE);
1229 stype = sym_get_type(sym);
1230 switch (stype) {
1231 case S_BOOLEAN:
1232 if (GPOINTER_TO_INT(row[COL_PIXVIS]) == FALSE)
1233 row[COL_BTNVIS] = GINT_TO_POINTER(TRUE);
1234 if (sym_is_choice(sym))
1235 break;
1236 case S_TRISTATE:
1237 val = sym_get_tristate_value(sym);
1238 switch (val) {
1239 case no:
1240 row[COL_NO] = g_strdup("N");
1241 row[COL_VALUE] = g_strdup("N");
1242 row[COL_BTNACT] = GINT_TO_POINTER(FALSE);
1243 row[COL_BTNINC] = GINT_TO_POINTER(FALSE);
1244 break;
1245 case mod:
1246 row[COL_MOD] = g_strdup("M");
1247 row[COL_VALUE] = g_strdup("M");
1248 row[COL_BTNINC] = GINT_TO_POINTER(TRUE);
1249 break;
1250 case yes:
1251 row[COL_YES] = g_strdup("Y");
1252 row[COL_VALUE] = g_strdup("Y");
1253 row[COL_BTNACT] = GINT_TO_POINTER(TRUE);
1254 row[COL_BTNINC] = GINT_TO_POINTER(FALSE);
1255 break;
1258 if (val != no && sym_tristate_within_range(sym, no))
1259 row[COL_NO] = g_strdup("_");
1260 if (val != mod && sym_tristate_within_range(sym, mod))
1261 row[COL_MOD] = g_strdup("_");
1262 if (val != yes && sym_tristate_within_range(sym, yes))
1263 row[COL_YES] = g_strdup("_");
1264 break;
1265 case S_INT:
1266 case S_HEX:
1267 case S_STRING:
1268 def = sym_get_string_value(sym);
1269 row[COL_VALUE] = g_strdup(def);
1270 row[COL_EDIT] = GINT_TO_POINTER(TRUE);
1271 row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
1272 break;
1275 return row;
1279 /* Set the node content with a row of strings */
1280 static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row)
1282 GdkColor color;
1283 gboolean success;
1284 GdkPixbuf *pix;
1286 pix = gdk_pixbuf_new_from_xpm_data((const char **)
1287 row[COL_PIXBUF]);
1289 gdk_color_parse(row[COL_COLOR], &color);
1290 gdk_colormap_alloc_colors(gdk_colormap_get_system(), &color, 1,
1291 FALSE, FALSE, &success);
1293 gtk_tree_store_set(tree, node,
1294 COL_OPTION, row[COL_OPTION],
1295 COL_NAME, row[COL_NAME],
1296 COL_NO, row[COL_NO],
1297 COL_MOD, row[COL_MOD],
1298 COL_YES, row[COL_YES],
1299 COL_VALUE, row[COL_VALUE],
1300 COL_MENU, (gpointer) menu,
1301 COL_COLOR, &color,
1302 COL_EDIT, GPOINTER_TO_INT(row[COL_EDIT]),
1303 COL_PIXBUF, pix,
1304 COL_PIXVIS, GPOINTER_TO_INT(row[COL_PIXVIS]),
1305 COL_BTNVIS, GPOINTER_TO_INT(row[COL_BTNVIS]),
1306 COL_BTNACT, GPOINTER_TO_INT(row[COL_BTNACT]),
1307 COL_BTNINC, GPOINTER_TO_INT(row[COL_BTNINC]),
1308 COL_BTNRAD, GPOINTER_TO_INT(row[COL_BTNRAD]),
1309 -1);
1311 g_object_unref(pix);
1315 /* Add a node to the tree */
1316 static void place_node(struct menu *menu, char **row)
1318 GtkTreeIter *parent = parents[indent - 1];
1319 GtkTreeIter *node = parents[indent];
1321 gtk_tree_store_append(tree, node, parent);
1322 set_node(node, menu, row);
1326 /* Find a node in the GTK+ tree */
1327 static GtkTreeIter found;
1330 * Find a menu in the GtkTree starting at parent.
1332 GtkTreeIter *gtktree_iter_find_node(GtkTreeIter * parent,
1333 struct menu *tofind)
1335 GtkTreeIter iter;
1336 GtkTreeIter *child = &iter;
1337 gboolean valid;
1338 GtkTreeIter *ret;
1340 valid = gtk_tree_model_iter_children(model2, child, parent);
1341 while (valid) {
1342 struct menu *menu;
1344 gtk_tree_model_get(model2, child, 6, &menu, -1);
1346 if (menu == tofind) {
1347 memcpy(&found, child, sizeof(GtkTreeIter));
1348 return &found;
1351 ret = gtktree_iter_find_node(child, tofind);
1352 if (ret)
1353 return ret;
1355 valid = gtk_tree_model_iter_next(model2, child);
1358 return NULL;
1363 * Update the tree by adding/removing entries
1364 * Does not change other nodes
1366 static void update_tree(struct menu *src, GtkTreeIter * dst)
1368 struct menu *child1;
1369 GtkTreeIter iter, tmp;
1370 GtkTreeIter *child2 = &iter;
1371 gboolean valid;
1372 GtkTreeIter *sibling;
1373 struct symbol *sym;
1374 struct property *prop;
1375 struct menu *menu1, *menu2;
1377 if (src == &rootmenu)
1378 indent = 1;
1380 valid = gtk_tree_model_iter_children(model2, child2, dst);
1381 for (child1 = src->list; child1; child1 = child1->next) {
1383 prop = child1->prompt;
1384 sym = child1->sym;
1386 reparse:
1387 menu1 = child1;
1388 if (valid)
1389 gtk_tree_model_get(model2, child2, COL_MENU,
1390 &menu2, -1);
1391 else
1392 menu2 = NULL; // force adding of a first child
1394 #ifdef DEBUG
1395 printf("%*c%s | %s\n", indent, ' ',
1396 menu1 ? menu_get_prompt(menu1) : "nil",
1397 menu2 ? menu_get_prompt(menu2) : "nil");
1398 #endif
1400 if (!menu_is_visible(child1) && !show_all) { // remove node
1401 if (gtktree_iter_find_node(dst, menu1) != NULL) {
1402 memcpy(&tmp, child2, sizeof(GtkTreeIter));
1403 valid = gtk_tree_model_iter_next(model2,
1404 child2);
1405 gtk_tree_store_remove(tree2, &tmp);
1406 if (!valid)
1407 return; // next parent
1408 else
1409 goto reparse; // next child
1410 } else
1411 continue;
1414 if (menu1 != menu2) {
1415 if (gtktree_iter_find_node(dst, menu1) == NULL) { // add node
1416 if (!valid && !menu2)
1417 sibling = NULL;
1418 else
1419 sibling = child2;
1420 gtk_tree_store_insert_before(tree2,
1421 child2,
1422 dst, sibling);
1423 set_node(child2, menu1, fill_row(menu1));
1424 if (menu2 == NULL)
1425 valid = TRUE;
1426 } else { // remove node
1427 memcpy(&tmp, child2, sizeof(GtkTreeIter));
1428 valid = gtk_tree_model_iter_next(model2,
1429 child2);
1430 gtk_tree_store_remove(tree2, &tmp);
1431 if (!valid)
1432 return; // next parent
1433 else
1434 goto reparse; // next child
1436 } else if (sym && (sym->flags & SYMBOL_CHANGED)) {
1437 set_node(child2, menu1, fill_row(menu1));
1440 indent++;
1441 update_tree(child1, child2);
1442 indent--;
1444 valid = gtk_tree_model_iter_next(model2, child2);
1449 /* Display the whole tree (single/split/full view) */
1450 static void display_tree(struct menu *menu)
1452 struct symbol *sym;
1453 struct property *prop;
1454 struct menu *child;
1455 enum prop_type ptype;
1457 if (menu == &rootmenu) {
1458 indent = 1;
1459 current = &rootmenu;
1462 for (child = menu->list; child; child = child->next) {
1463 prop = child->prompt;
1464 sym = child->sym;
1465 ptype = prop ? prop->type : P_UNKNOWN;
1467 if (sym)
1468 sym->flags &= ~SYMBOL_CHANGED;
1470 if ((view_mode == SPLIT_VIEW)
1471 && !(child->flags & MENU_ROOT) && (tree == tree1))
1472 continue;
1474 if ((view_mode == SPLIT_VIEW) && (child->flags & MENU_ROOT)
1475 && (tree == tree2))
1476 continue;
1478 if (menu_is_visible(child) || show_all)
1479 place_node(child, fill_row(child));
1480 #ifdef DEBUG
1481 printf("%*c%s: ", indent, ' ', menu_get_prompt(child));
1482 printf("%s", child->flags & MENU_ROOT ? "rootmenu | " : "");
1483 dbg_print_ptype(ptype);
1484 printf(" | ");
1485 if (sym) {
1486 dbg_print_stype(sym->type);
1487 printf(" | ");
1488 dbg_print_flags(sym->flags);
1489 printf("\n");
1490 } else
1491 printf("\n");
1492 #endif
1493 if ((view_mode != FULL_VIEW) && (ptype == P_MENU)
1494 && (tree == tree2))
1495 continue;
1497 if (((menu != &rootmenu) && !(menu->flags & MENU_ROOT))
1498 || (view_mode == FULL_VIEW)
1499 || (view_mode == SPLIT_VIEW))*/
1500 if (((view_mode == SINGLE_VIEW) && (menu->flags & MENU_ROOT))
1501 || (view_mode == FULL_VIEW)
1502 || (view_mode == SPLIT_VIEW)) {
1503 indent++;
1504 display_tree(child);
1505 indent--;
1510 /* Display a part of the tree starting at current node (single/split view) */
1511 static void display_tree_part(void)
1513 if (tree2)
1514 gtk_tree_store_clear(tree2);
1515 if (view_mode == SINGLE_VIEW)
1516 display_tree(current);
1517 else if (view_mode == SPLIT_VIEW)
1518 display_tree(browsed);
1519 gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w));
1522 /* Display the list in the left frame (split view) */
1523 static void display_list(void)
1525 if (tree1)
1526 gtk_tree_store_clear(tree1);
1528 tree = tree1;
1529 display_tree(&rootmenu);
1530 gtk_tree_view_expand_all(GTK_TREE_VIEW(tree1_w));
1531 tree = tree2;
1534 void fixup_rootmenu(struct menu *menu)
1536 struct menu *child;
1537 static int menu_cnt = 0;
1539 menu->flags |= MENU_ROOT;
1540 for (child = menu->list; child; child = child->next) {
1541 if (child->prompt && child->prompt->type == P_MENU) {
1542 menu_cnt++;
1543 fixup_rootmenu(child);
1544 menu_cnt--;
1545 } else if (!menu_cnt)
1546 fixup_rootmenu(child);
1551 /* Main */
1552 int main(int ac, char *av[])
1554 const char *name;
1555 char *env;
1556 gchar *glade_file;
1558 #ifndef LKC_DIRECT_LINK
1559 kconfig_load();
1560 #endif
1562 bindtextdomain(PACKAGE, LOCALEDIR);
1563 bind_textdomain_codeset(PACKAGE, "UTF-8");
1564 textdomain(PACKAGE);
1566 /* GTK stuffs */
1567 gtk_set_locale();
1568 gtk_init(&ac, &av);
1569 glade_init();
1571 //add_pixmap_directory (PACKAGE_DATA_DIR "/" PACKAGE "/pixmaps");
1572 //add_pixmap_directory (PACKAGE_SOURCE_DIR "/pixmaps");
1574 /* Determine GUI path */
1575 env = getenv(SRCTREE);
1576 if (env)
1577 glade_file = g_strconcat(env, "/scripts/kconfig/gconf.glade", NULL);
1578 else if (av[0][0] == '/')
1579 glade_file = g_strconcat(av[0], ".glade", NULL);
1580 else
1581 glade_file = g_strconcat(g_get_current_dir(), "/", av[0], ".glade", NULL);
1583 /* Load the interface and connect signals */
1584 init_main_window(glade_file);
1585 init_tree_model();
1586 init_left_tree();
1587 init_right_tree();
1589 /* Conf stuffs */
1590 if (ac > 1 && av[1][0] == '-') {
1591 switch (av[1][1]) {
1592 case 'a':
1593 //showAll = 1;
1594 break;
1595 case 'h':
1596 case '?':
1597 printf("%s <config>\n", av[0]);
1598 exit(0);
1600 name = av[2];
1601 } else
1602 name = av[1];
1604 conf_parse(name);
1605 fixup_rootmenu(&rootmenu);
1606 conf_read(NULL);
1608 switch (view_mode) {
1609 case SINGLE_VIEW:
1610 display_tree_part();
1611 break;
1612 case SPLIT_VIEW:
1613 display_list();
1614 break;
1615 case FULL_VIEW:
1616 display_tree(&rootmenu);
1617 break;
1620 gtk_main();
1622 return 0;
1625 static void conf_changed(void)
1627 bool changed = conf_get_changed();
1628 gtk_widget_set_sensitive(save_btn, changed);
1629 gtk_widget_set_sensitive(save_menu_item, changed);