Magellan Linux

Annotation of /trunk/mkinitrd-magellan/busybox/scripts/kconfig/gconf.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 532 - (hide annotations) (download)
Sat Sep 1 22:45:15 2007 UTC (16 years, 9 months ago) by niro
File MIME type: text/plain
File size: 41610 byte(s)
-import if magellan mkinitrd; it is a fork of redhats mkinitrd-5.0.8 with all magellan patches and features; deprecates magellan-src/mkinitrd

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