Magellan Linux

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 816 - (hide annotations) (download)
Fri Apr 24 18:33:46 2009 UTC (15 years, 1 month ago) by niro
File MIME type: text/plain
File size: 41569 byte(s)
-updated to busybox-1.13.4
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 niro 816 "Welcome to gkc, the GTK+ graphical configuration tool.\n"
745 niro 532 "For each option, a blank box indicates the feature is disabled, a\n"
746     "check indicates it is enabled, and a dot indicates that it is to\n"
747     "be compiled as a module. Clicking on the box will cycle through the three states.\n"
748     "\n"
749     "If you do not see an option (e.g., a device driver) that you\n"
750     "believe should be present, try turning on Show All Options\n"
751     "under the Options menu.\n"
752     "Although there is no cross reference yet to help you figure out\n"
753     "what other options must be enabled to support the option you\n"
754     "are interested in, you can still view the help of a grayed-out\n"
755     "option.\n"
756     "\n"
757     "Toggling Show Debug Info under the Options menu will show\n"
758     "the dependencies, which you can then match by examining other options.");
759    
760     dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
761     GTK_DIALOG_DESTROY_WITH_PARENT,
762     GTK_MESSAGE_INFO,
763     GTK_BUTTONS_CLOSE, intro_text);
764     g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
765     G_CALLBACK(gtk_widget_destroy),
766     GTK_OBJECT(dialog));
767     gtk_widget_show_all(dialog);
768     }
769    
770    
771     void on_about1_activate(GtkMenuItem * menuitem, gpointer user_data)
772     {
773     GtkWidget *dialog;
774     const gchar *about_text =
775     _("gkc is copyright (c) 2002 Romain Lievin <roms@lpg.ticalc.org>.\n"
776     "Based on the source code from Roman Zippel.\n");
777    
778     dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
779     GTK_DIALOG_DESTROY_WITH_PARENT,
780     GTK_MESSAGE_INFO,
781     GTK_BUTTONS_CLOSE, about_text);
782     g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
783     G_CALLBACK(gtk_widget_destroy),
784     GTK_OBJECT(dialog));
785     gtk_widget_show_all(dialog);
786     }
787    
788    
789     void on_license1_activate(GtkMenuItem * menuitem, gpointer user_data)
790     {
791     GtkWidget *dialog;
792     const gchar *license_text =
793     _("gkc is released under the terms of the GNU GPL v2.\n"
794     "For more information, please see the source code or\n"
795     "visit http://www.fsf.org/licenses/licenses.html\n");
796    
797     dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
798     GTK_DIALOG_DESTROY_WITH_PARENT,
799     GTK_MESSAGE_INFO,
800     GTK_BUTTONS_CLOSE, license_text);
801     g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
802     G_CALLBACK(gtk_widget_destroy),
803     GTK_OBJECT(dialog));
804     gtk_widget_show_all(dialog);
805     }
806    
807    
808     void on_back_clicked(GtkButton * button, gpointer user_data)
809     {
810     enum prop_type ptype;
811    
812     current = current->parent;
813     ptype = current->prompt ? current->prompt->type : P_UNKNOWN;
814     if (ptype != P_MENU)
815     current = current->parent;
816     display_tree_part();
817    
818     if (current == &rootmenu)
819     gtk_widget_set_sensitive(back_btn, FALSE);
820     }
821    
822    
823     void on_load_clicked(GtkButton * button, gpointer user_data)
824     {
825     on_load1_activate(NULL, user_data);
826     }
827    
828    
829     void on_save_clicked(GtkButton * button, gpointer user_data)
830     {
831     on_save1_activate(NULL, user_data);
832     }
833    
834    
835     void on_single_clicked(GtkButton * button, gpointer user_data)
836     {
837     view_mode = SINGLE_VIEW;
838     gtk_paned_set_position(GTK_PANED(hpaned), 0);
839     gtk_widget_hide(tree1_w);
840     current = &rootmenu;
841     display_tree_part();
842     }
843    
844    
845     void on_split_clicked(GtkButton * button, gpointer user_data)
846     {
847     gint w, h;
848     view_mode = SPLIT_VIEW;
849     gtk_widget_show(tree1_w);
850     gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h);
851     gtk_paned_set_position(GTK_PANED(hpaned), w / 2);
852     if (tree2)
853     gtk_tree_store_clear(tree2);
854     display_list();
855    
856     /* Disable back btn, like in full mode. */
857     gtk_widget_set_sensitive(back_btn, FALSE);
858     }
859    
860    
861     void on_full_clicked(GtkButton * button, gpointer user_data)
862     {
863     view_mode = FULL_VIEW;
864     gtk_paned_set_position(GTK_PANED(hpaned), 0);
865     gtk_widget_hide(tree1_w);
866     if (tree2)
867     gtk_tree_store_clear(tree2);
868     display_tree(&rootmenu);
869     gtk_widget_set_sensitive(back_btn, FALSE);
870     }
871    
872    
873     void on_collapse_clicked(GtkButton * button, gpointer user_data)
874     {
875     gtk_tree_view_collapse_all(GTK_TREE_VIEW(tree2_w));
876     }
877    
878    
879     void on_expand_clicked(GtkButton * button, gpointer user_data)
880     {
881     gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w));
882     }
883    
884    
885     /* CTree Callbacks */
886    
887     /* Change hex/int/string value in the cell */
888     static void renderer_edited(GtkCellRendererText * cell,
889     const gchar * path_string,
890     const gchar * new_text, gpointer user_data)
891     {
892     GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
893     GtkTreeIter iter;
894     const char *old_def, *new_def;
895     struct menu *menu;
896     struct symbol *sym;
897    
898     if (!gtk_tree_model_get_iter(model2, &iter, path))
899     return;
900    
901     gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
902     sym = menu->sym;
903    
904     gtk_tree_model_get(model2, &iter, COL_VALUE, &old_def, -1);
905     new_def = new_text;
906    
907     sym_set_string_value(sym, new_def);
908    
909     config_changed = TRUE;
910     update_tree(&rootmenu, NULL);
911    
912     gtk_tree_path_free(path);
913     }
914    
915     /* Change the value of a symbol and update the tree */
916     static void change_sym_value(struct menu *menu, gint col)
917     {
918     struct symbol *sym = menu->sym;
919     tristate oldval, newval;
920    
921     if (!sym)
922     return;
923    
924     if (col == COL_NO)
925     newval = no;
926     else if (col == COL_MOD)
927     newval = mod;
928     else if (col == COL_YES)
929     newval = yes;
930     else
931     return;
932    
933     switch (sym_get_type(sym)) {
934     case S_BOOLEAN:
935     case S_TRISTATE:
936     oldval = sym_get_tristate_value(sym);
937     if (!sym_tristate_within_range(sym, newval))
938     newval = yes;
939     sym_set_tristate_value(sym, newval);
940     config_changed = TRUE;
941     if (view_mode == FULL_VIEW)
942     update_tree(&rootmenu, NULL);
943     else if (view_mode == SPLIT_VIEW) {
944     update_tree(browsed, NULL);
945     display_list();
946     }
947     else if (view_mode == SINGLE_VIEW)
948     display_tree_part(); //fixme: keep exp/coll
949     break;
950     case S_INT:
951     case S_HEX:
952     case S_STRING:
953     default:
954     break;
955     }
956     }
957    
958     static void toggle_sym_value(struct menu *menu)
959     {
960     if (!menu->sym)
961     return;
962    
963     sym_toggle_tristate_value(menu->sym);
964     if (view_mode == FULL_VIEW)
965     update_tree(&rootmenu, NULL);
966     else if (view_mode == SPLIT_VIEW) {
967     update_tree(browsed, NULL);
968     display_list();
969     }
970     else if (view_mode == SINGLE_VIEW)
971     display_tree_part(); //fixme: keep exp/coll
972     }
973    
974     static void renderer_toggled(GtkCellRendererToggle * cell,
975     gchar * path_string, gpointer user_data)
976     {
977     GtkTreePath *path, *sel_path = NULL;
978     GtkTreeIter iter, sel_iter;
979     GtkTreeSelection *sel;
980     struct menu *menu;
981    
982     path = gtk_tree_path_new_from_string(path_string);
983     if (!gtk_tree_model_get_iter(model2, &iter, path))
984     return;
985    
986     sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree2_w));
987     if (gtk_tree_selection_get_selected(sel, NULL, &sel_iter))
988     sel_path = gtk_tree_model_get_path(model2, &sel_iter);
989     if (!sel_path)
990     goto out1;
991     if (gtk_tree_path_compare(path, sel_path))
992     goto out2;
993    
994     gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
995     toggle_sym_value(menu);
996    
997     out2:
998     gtk_tree_path_free(sel_path);
999     out1:
1000     gtk_tree_path_free(path);
1001     }
1002    
1003     static gint column2index(GtkTreeViewColumn * column)
1004     {
1005     gint i;
1006    
1007     for (i = 0; i < COL_NUMBER; i++) {
1008     GtkTreeViewColumn *col;
1009    
1010     col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), i);
1011     if (col == column)
1012     return i;
1013     }
1014    
1015     return -1;
1016     }
1017    
1018    
1019     /* User click: update choice (full) or goes down (single) */
1020     gboolean
1021     on_treeview2_button_press_event(GtkWidget * widget,
1022     GdkEventButton * event, gpointer user_data)
1023     {
1024     GtkTreeView *view = GTK_TREE_VIEW(widget);
1025     GtkTreePath *path;
1026     GtkTreeViewColumn *column;
1027     GtkTreeIter iter;
1028     struct menu *menu;
1029     gint col;
1030    
1031     #if GTK_CHECK_VERSION(2,1,4) // bug in ctree with earlier version of GTK
1032     gint tx = (gint) event->x;
1033     gint ty = (gint) event->y;
1034     gint cx, cy;
1035    
1036     gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx,
1037     &cy);
1038     #else
1039     gtk_tree_view_get_cursor(view, &path, &column);
1040     #endif
1041     if (path == NULL)
1042     return FALSE;
1043    
1044     if (!gtk_tree_model_get_iter(model2, &iter, path))
1045     return FALSE;
1046     gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
1047    
1048     col = column2index(column);
1049     if (event->type == GDK_2BUTTON_PRESS) {
1050     enum prop_type ptype;
1051     ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
1052    
1053     if (ptype == P_MENU && view_mode != FULL_VIEW && col == COL_OPTION) {
1054     // goes down into menu
1055     current = menu;
1056     display_tree_part();
1057     gtk_widget_set_sensitive(back_btn, TRUE);
1058     } else if ((col == COL_OPTION)) {
1059     toggle_sym_value(menu);
1060     gtk_tree_view_expand_row(view, path, TRUE);
1061     }
1062     } else {
1063     if (col == COL_VALUE) {
1064     toggle_sym_value(menu);
1065     gtk_tree_view_expand_row(view, path, TRUE);
1066     } else if (col == COL_NO || col == COL_MOD
1067     || col == COL_YES) {
1068     change_sym_value(menu, col);
1069     gtk_tree_view_expand_row(view, path, TRUE);
1070     }
1071     }
1072    
1073     return FALSE;
1074     }
1075    
1076     /* Key pressed: update choice */
1077     gboolean
1078     on_treeview2_key_press_event(GtkWidget * widget,
1079     GdkEventKey * event, gpointer user_data)
1080     {
1081     GtkTreeView *view = GTK_TREE_VIEW(widget);
1082     GtkTreePath *path;
1083     GtkTreeViewColumn *column;
1084     GtkTreeIter iter;
1085     struct menu *menu;
1086     gint col;
1087    
1088     gtk_tree_view_get_cursor(view, &path, &column);
1089     if (path == NULL)
1090     return FALSE;
1091    
1092     if (event->keyval == GDK_space) {
1093     if (gtk_tree_view_row_expanded(view, path))
1094     gtk_tree_view_collapse_row(view, path);
1095     else
1096     gtk_tree_view_expand_row(view, path, FALSE);
1097     return TRUE;
1098     }
1099     if (event->keyval == GDK_KP_Enter) {
1100     }
1101     if (widget == tree1_w)
1102     return FALSE;
1103    
1104     gtk_tree_model_get_iter(model2, &iter, path);
1105     gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
1106    
1107     if (!strcasecmp(event->string, "n"))
1108     col = COL_NO;
1109     else if (!strcasecmp(event->string, "m"))
1110     col = COL_MOD;
1111     else if (!strcasecmp(event->string, "y"))
1112     col = COL_YES;
1113     else
1114     col = -1;
1115     change_sym_value(menu, col);
1116    
1117     return FALSE;
1118     }
1119    
1120    
1121     /* Row selection changed: update help */
1122     void
1123     on_treeview2_cursor_changed(GtkTreeView * treeview, gpointer user_data)
1124     {
1125     GtkTreeSelection *selection;
1126     GtkTreeIter iter;
1127     struct menu *menu;
1128    
1129     selection = gtk_tree_view_get_selection(treeview);
1130     if (gtk_tree_selection_get_selected(selection, &model2, &iter)) {
1131     gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
1132     text_insert_help(menu);
1133     }
1134     }
1135    
1136    
1137     /* User click: display sub-tree in the right frame. */
1138     gboolean
1139     on_treeview1_button_press_event(GtkWidget * widget,
1140     GdkEventButton * event, gpointer user_data)
1141     {
1142     GtkTreeView *view = GTK_TREE_VIEW(widget);
1143     GtkTreePath *path;
1144     GtkTreeViewColumn *column;
1145     GtkTreeIter iter;
1146     struct menu *menu;
1147    
1148     gint tx = (gint) event->x;
1149     gint ty = (gint) event->y;
1150     gint cx, cy;
1151    
1152     gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx,
1153     &cy);
1154     if (path == NULL)
1155     return FALSE;
1156    
1157     gtk_tree_model_get_iter(model1, &iter, path);
1158     gtk_tree_model_get(model1, &iter, COL_MENU, &menu, -1);
1159    
1160     if (event->type == GDK_2BUTTON_PRESS) {
1161     toggle_sym_value(menu);
1162     current = menu;
1163     display_tree_part();
1164     } else {
1165     browsed = menu;
1166     display_tree_part();
1167     }
1168    
1169     gtk_widget_realize(tree2_w);
1170     gtk_tree_view_set_cursor(view, path, NULL, FALSE);
1171     gtk_widget_grab_focus(tree2_w);
1172    
1173     return FALSE;
1174     }
1175    
1176    
1177     /* Fill a row of strings */
1178     static gchar **fill_row(struct menu *menu)
1179     {
1180     static gchar *row[COL_NUMBER];
1181     struct symbol *sym = menu->sym;
1182     const char *def;
1183     int stype;
1184     tristate val;
1185     enum prop_type ptype;
1186     int i;
1187    
1188     for (i = COL_OPTION; i <= COL_COLOR; i++)
1189     g_free(row[i]);
1190     memset(row, 0, sizeof(row));
1191    
1192     row[COL_OPTION] =
1193     g_strdup_printf("%s %s", menu_get_prompt(menu),
1194     sym ? (sym->
1195     flags & SYMBOL_NEW ? "(NEW)" : "") :
1196     "");
1197    
1198     if (show_all && !menu_is_visible(menu))
1199     row[COL_COLOR] = g_strdup("DarkGray");
1200     else
1201     row[COL_COLOR] = g_strdup("Black");
1202    
1203     ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
1204     switch (ptype) {
1205     case P_MENU:
1206     row[COL_PIXBUF] = (gchar *) xpm_menu;
1207     if (view_mode == SINGLE_VIEW)
1208     row[COL_PIXVIS] = GINT_TO_POINTER(TRUE);
1209     row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
1210     break;
1211     case P_COMMENT:
1212     row[COL_PIXBUF] = (gchar *) xpm_void;
1213     row[COL_PIXVIS] = GINT_TO_POINTER(FALSE);
1214     row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
1215     break;
1216     default:
1217     row[COL_PIXBUF] = (gchar *) xpm_void;
1218     row[COL_PIXVIS] = GINT_TO_POINTER(FALSE);
1219     row[COL_BTNVIS] = GINT_TO_POINTER(TRUE);
1220     break;
1221     }
1222    
1223     if (!sym)
1224     return row;
1225     row[COL_NAME] = g_strdup(sym->name);
1226    
1227     sym_calc_value(sym);
1228     sym->flags &= ~SYMBOL_CHANGED;
1229    
1230     if (sym_is_choice(sym)) { // parse childs for getting final value
1231     struct menu *child;
1232     struct symbol *def_sym = sym_get_choice_value(sym);
1233     struct menu *def_menu = NULL;
1234    
1235     row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
1236    
1237     for (child = menu->list; child; child = child->next) {
1238     if (menu_is_visible(child)
1239     && child->sym == def_sym)
1240     def_menu = child;
1241     }
1242    
1243     if (def_menu)
1244     row[COL_VALUE] =
1245     g_strdup(menu_get_prompt(def_menu));
1246     }
1247     if (sym->flags & SYMBOL_CHOICEVAL)
1248     row[COL_BTNRAD] = GINT_TO_POINTER(TRUE);
1249    
1250     stype = sym_get_type(sym);
1251     switch (stype) {
1252     case S_BOOLEAN:
1253     if (GPOINTER_TO_INT(row[COL_PIXVIS]) == FALSE)
1254     row[COL_BTNVIS] = GINT_TO_POINTER(TRUE);
1255     if (sym_is_choice(sym))
1256     break;
1257     case S_TRISTATE:
1258     val = sym_get_tristate_value(sym);
1259     switch (val) {
1260     case no:
1261     row[COL_NO] = g_strdup("N");
1262     row[COL_VALUE] = g_strdup("N");
1263     row[COL_BTNACT] = GINT_TO_POINTER(FALSE);
1264     row[COL_BTNINC] = GINT_TO_POINTER(FALSE);
1265     break;
1266     case mod:
1267     row[COL_MOD] = g_strdup("M");
1268     row[COL_VALUE] = g_strdup("M");
1269     row[COL_BTNINC] = GINT_TO_POINTER(TRUE);
1270     break;
1271     case yes:
1272     row[COL_YES] = g_strdup("Y");
1273     row[COL_VALUE] = g_strdup("Y");
1274     row[COL_BTNACT] = GINT_TO_POINTER(TRUE);
1275     row[COL_BTNINC] = GINT_TO_POINTER(FALSE);
1276     break;
1277     }
1278    
1279     if (val != no && sym_tristate_within_range(sym, no))
1280     row[COL_NO] = g_strdup("_");
1281     if (val != mod && sym_tristate_within_range(sym, mod))
1282     row[COL_MOD] = g_strdup("_");
1283     if (val != yes && sym_tristate_within_range(sym, yes))
1284     row[COL_YES] = g_strdup("_");
1285     break;
1286     case S_INT:
1287     case S_HEX:
1288     case S_STRING:
1289     def = sym_get_string_value(sym);
1290     row[COL_VALUE] = g_strdup(def);
1291     row[COL_EDIT] = GINT_TO_POINTER(TRUE);
1292     row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
1293     break;
1294     }
1295    
1296     return row;
1297     }
1298    
1299    
1300     /* Set the node content with a row of strings */
1301     static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row)
1302     {
1303     GdkColor color;
1304     gboolean success;
1305     GdkPixbuf *pix;
1306    
1307     pix = gdk_pixbuf_new_from_xpm_data((const char **)
1308     row[COL_PIXBUF]);
1309    
1310     gdk_color_parse(row[COL_COLOR], &color);
1311     gdk_colormap_alloc_colors(gdk_colormap_get_system(), &color, 1,
1312     FALSE, FALSE, &success);
1313    
1314     gtk_tree_store_set(tree, node,
1315     COL_OPTION, row[COL_OPTION],
1316     COL_NAME, row[COL_NAME],
1317     COL_NO, row[COL_NO],
1318     COL_MOD, row[COL_MOD],
1319     COL_YES, row[COL_YES],
1320     COL_VALUE, row[COL_VALUE],
1321     COL_MENU, (gpointer) menu,
1322     COL_COLOR, &color,
1323     COL_EDIT, GPOINTER_TO_INT(row[COL_EDIT]),
1324     COL_PIXBUF, pix,
1325     COL_PIXVIS, GPOINTER_TO_INT(row[COL_PIXVIS]),
1326     COL_BTNVIS, GPOINTER_TO_INT(row[COL_BTNVIS]),
1327     COL_BTNACT, GPOINTER_TO_INT(row[COL_BTNACT]),
1328     COL_BTNINC, GPOINTER_TO_INT(row[COL_BTNINC]),
1329     COL_BTNRAD, GPOINTER_TO_INT(row[COL_BTNRAD]),
1330     -1);
1331    
1332     g_object_unref(pix);
1333     }
1334    
1335    
1336     /* Add a node to the tree */
1337     static void place_node(struct menu *menu, char **row)
1338     {
1339     GtkTreeIter *parent = parents[indent - 1];
1340     GtkTreeIter *node = parents[indent];
1341    
1342     gtk_tree_store_append(tree, node, parent);
1343     set_node(node, menu, row);
1344     }
1345    
1346    
1347     /* Find a node in the GTK+ tree */
1348     static GtkTreeIter found;
1349    
1350     /*
1351     * Find a menu in the GtkTree starting at parent.
1352     */
1353     GtkTreeIter *gtktree_iter_find_node(GtkTreeIter * parent,
1354     struct menu *tofind)
1355     {
1356     GtkTreeIter iter;
1357     GtkTreeIter *child = &iter;
1358     gboolean valid;
1359     GtkTreeIter *ret;
1360    
1361     valid = gtk_tree_model_iter_children(model2, child, parent);
1362     while (valid) {
1363     struct menu *menu;
1364    
1365     gtk_tree_model_get(model2, child, 6, &menu, -1);
1366    
1367     if (menu == tofind) {
1368     memcpy(&found, child, sizeof(GtkTreeIter));
1369     return &found;
1370     }
1371    
1372     ret = gtktree_iter_find_node(child, tofind);
1373     if (ret)
1374     return ret;
1375    
1376     valid = gtk_tree_model_iter_next(model2, child);
1377     }
1378    
1379     return NULL;
1380     }
1381    
1382    
1383     /*
1384     * Update the tree by adding/removing entries
1385     * Does not change other nodes
1386     */
1387     static void update_tree(struct menu *src, GtkTreeIter * dst)
1388     {
1389     struct menu *child1;
1390     GtkTreeIter iter, tmp;
1391     GtkTreeIter *child2 = &iter;
1392     gboolean valid;
1393     GtkTreeIter *sibling;
1394     struct symbol *sym;
1395     struct property *prop;
1396     struct menu *menu1, *menu2;
1397    
1398     if (src == &rootmenu)
1399     indent = 1;
1400    
1401     valid = gtk_tree_model_iter_children(model2, child2, dst);
1402     for (child1 = src->list; child1; child1 = child1->next) {
1403    
1404     prop = child1->prompt;
1405     sym = child1->sym;
1406    
1407     reparse:
1408     menu1 = child1;
1409     if (valid)
1410     gtk_tree_model_get(model2, child2, COL_MENU,
1411     &menu2, -1);
1412     else
1413     menu2 = NULL; // force adding of a first child
1414    
1415     #ifdef DEBUG
1416     printf("%*c%s | %s\n", indent, ' ',
1417     menu1 ? menu_get_prompt(menu1) : "nil",
1418     menu2 ? menu_get_prompt(menu2) : "nil");
1419     #endif
1420    
1421     if (!menu_is_visible(child1) && !show_all) { // remove node
1422     if (gtktree_iter_find_node(dst, menu1) != NULL) {
1423     memcpy(&tmp, child2, sizeof(GtkTreeIter));
1424     valid = gtk_tree_model_iter_next(model2,
1425     child2);
1426     gtk_tree_store_remove(tree2, &tmp);
1427     if (!valid)
1428     return; // next parent
1429     else
1430     goto reparse; // next child
1431     } else
1432     continue;
1433     }
1434    
1435     if (menu1 != menu2) {
1436     if (gtktree_iter_find_node(dst, menu1) == NULL) { // add node
1437     if (!valid && !menu2)
1438     sibling = NULL;
1439     else
1440     sibling = child2;
1441     gtk_tree_store_insert_before(tree2,
1442     child2,
1443     dst, sibling);
1444     set_node(child2, menu1, fill_row(menu1));
1445     if (menu2 == NULL)
1446     valid = TRUE;
1447     } else { // remove node
1448     memcpy(&tmp, child2, sizeof(GtkTreeIter));
1449     valid = gtk_tree_model_iter_next(model2,
1450     child2);
1451     gtk_tree_store_remove(tree2, &tmp);
1452     if (!valid)
1453     return; // next parent
1454     else
1455     goto reparse; // next child
1456     }
1457     } else if (sym && (sym->flags & SYMBOL_CHANGED)) {
1458     set_node(child2, menu1, fill_row(menu1));
1459     }
1460    
1461     indent++;
1462     update_tree(child1, child2);
1463     indent--;
1464    
1465     valid = gtk_tree_model_iter_next(model2, child2);
1466     }
1467     }
1468    
1469    
1470     /* Display the whole tree (single/split/full view) */
1471     static void display_tree(struct menu *menu)
1472     {
1473     struct symbol *sym;
1474     struct property *prop;
1475     struct menu *child;
1476     enum prop_type ptype;
1477    
1478     if (menu == &rootmenu) {
1479     indent = 1;
1480     current = &rootmenu;
1481     }
1482    
1483     for (child = menu->list; child; child = child->next) {
1484     prop = child->prompt;
1485     sym = child->sym;
1486     ptype = prop ? prop->type : P_UNKNOWN;
1487    
1488     if (sym)
1489     sym->flags &= ~SYMBOL_CHANGED;
1490    
1491     if ((view_mode == SPLIT_VIEW)
1492     && !(child->flags & MENU_ROOT) && (tree == tree1))
1493     continue;
1494    
1495     if ((view_mode == SPLIT_VIEW) && (child->flags & MENU_ROOT)
1496     && (tree == tree2))
1497     continue;
1498    
1499     if (menu_is_visible(child) || show_all)
1500     place_node(child, fill_row(child));
1501     #ifdef DEBUG
1502     printf("%*c%s: ", indent, ' ', menu_get_prompt(child));
1503     printf("%s", child->flags & MENU_ROOT ? "rootmenu | " : "");
1504     dbg_print_ptype(ptype);
1505     printf(" | ");
1506     if (sym) {
1507     dbg_print_stype(sym->type);
1508     printf(" | ");
1509     dbg_print_flags(sym->flags);
1510     printf("\n");
1511     } else
1512     printf("\n");
1513     #endif
1514     if ((view_mode != FULL_VIEW) && (ptype == P_MENU)
1515     && (tree == tree2))
1516     continue;
1517     /*
1518 niro 816 if (((menu != &rootmenu) && !(menu->flags & MENU_ROOT))
1519 niro 532 || (view_mode == FULL_VIEW)
1520     || (view_mode == SPLIT_VIEW))*/
1521     if (((view_mode == SINGLE_VIEW) && (menu->flags & MENU_ROOT))
1522     || (view_mode == FULL_VIEW)
1523     || (view_mode == SPLIT_VIEW)) {
1524     indent++;
1525     display_tree(child);
1526     indent--;
1527     }
1528     }
1529     }
1530    
1531     /* Display a part of the tree starting at current node (single/split view) */
1532     static void display_tree_part(void)
1533     {
1534     if (tree2)
1535     gtk_tree_store_clear(tree2);
1536     if (view_mode == SINGLE_VIEW)
1537     display_tree(current);
1538     else if (view_mode == SPLIT_VIEW)
1539     display_tree(browsed);
1540     gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w));
1541     }
1542    
1543     /* Display the list in the left frame (split view) */
1544     static void display_list(void)
1545     {
1546     if (tree1)
1547     gtk_tree_store_clear(tree1);
1548    
1549     tree = tree1;
1550     display_tree(&rootmenu);
1551     gtk_tree_view_expand_all(GTK_TREE_VIEW(tree1_w));
1552     tree = tree2;
1553     }
1554    
1555     void fixup_rootmenu(struct menu *menu)
1556     {
1557     struct menu *child;
1558     static int menu_cnt = 0;
1559    
1560     menu->flags |= MENU_ROOT;
1561     for (child = menu->list; child; child = child->next) {
1562     if (child->prompt && child->prompt->type == P_MENU) {
1563     menu_cnt++;
1564     fixup_rootmenu(child);
1565     menu_cnt--;
1566     } else if (!menu_cnt)
1567     fixup_rootmenu(child);
1568     }
1569     }
1570    
1571    
1572     /* Main */
1573     int main(int ac, char *av[])
1574     {
1575     const char *name;
1576     char *env;
1577     gchar *glade_file;
1578    
1579     #ifndef LKC_DIRECT_LINK
1580     kconfig_load();
1581     #endif
1582    
1583     bindtextdomain(PACKAGE, LOCALEDIR);
1584     bind_textdomain_codeset(PACKAGE, "UTF-8");
1585     textdomain(PACKAGE);
1586    
1587     /* GTK stuffs */
1588     gtk_set_locale();
1589     gtk_init(&ac, &av);
1590     glade_init();
1591    
1592     //add_pixmap_directory (PACKAGE_DATA_DIR "/" PACKAGE "/pixmaps");
1593     //add_pixmap_directory (PACKAGE_SOURCE_DIR "/pixmaps");
1594    
1595     /* Determine GUI path */
1596     env = getenv(SRCTREE);
1597     if (env)
1598     glade_file = g_strconcat(env, "/scripts/kconfig/gconf.glade", NULL);
1599     else if (av[0][0] == '/')
1600     glade_file = g_strconcat(av[0], ".glade", NULL);
1601     else
1602     glade_file = g_strconcat(g_get_current_dir(), "/", av[0], ".glade", NULL);
1603    
1604     /* Load the interface and connect signals */
1605     init_main_window(glade_file);
1606     init_tree_model();
1607     init_left_tree();
1608     init_right_tree();
1609    
1610     /* Conf stuffs */
1611     if (ac > 1 && av[1][0] == '-') {
1612     switch (av[1][1]) {
1613     case 'a':
1614     //showAll = 1;
1615     break;
1616     case 'h':
1617     case '?':
1618     printf("%s <config>\n", av[0]);
1619     exit(0);
1620     }
1621     name = av[2];
1622     } else
1623     name = av[1];
1624    
1625     conf_parse(name);
1626     fixup_rootmenu(&rootmenu);
1627     conf_read(NULL);
1628    
1629     switch (view_mode) {
1630     case SINGLE_VIEW:
1631     display_tree_part();
1632     break;
1633     case SPLIT_VIEW:
1634     display_list();
1635     break;
1636     case FULL_VIEW:
1637     display_tree(&rootmenu);
1638     break;
1639     }
1640    
1641     gtk_main();
1642    
1643     return 0;
1644     }