source: MondoRescue/branches/stable/mindi-busybox/scripts/kconfig/gconf.c@ 1770

Last change on this file since 1770 was 1765, checked in by Bruno Cornec, 16 years ago

Update to busybox 1.7.2

  • Property svn:eol-style set to native
File size: 40.6 KB
Line 
1/* 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
29enum {
30 SINGLE_VIEW, SPLIT_VIEW, FULL_VIEW
31};
32
33static gint view_mode = FULL_VIEW;
34static gboolean show_name = TRUE;
35static gboolean show_range = TRUE;
36static gboolean show_value = TRUE;
37static gboolean show_all = FALSE;
38static gboolean show_debug = FALSE;
39static gboolean resizeable = FALSE;
40
41static gboolean config_changed = FALSE;
42
43static char nohelp_text[] =
44 N_("Sorry, no help available for this option yet.\n");
45
46GtkWidget *main_wnd = NULL;
47GtkWidget *tree1_w = NULL; // left frame
48GtkWidget *tree2_w = NULL; // right frame
49GtkWidget *text_w = NULL;
50GtkWidget *hpaned = NULL;
51GtkWidget *vpaned = NULL;
52GtkWidget *back_btn = NULL;
53
54GtkTextTag *tag1, *tag2;
55GdkColor color;
56
57GtkTreeStore *tree1, *tree2, *tree;
58GtkTreeModel *model1, *model2;
59static GtkTreeIter *parents[256];
60static gint indent;
61
62static struct menu *current; // current node for SINGLE view
63static struct menu *browsed; // browsed node for SPLIT view
64
65enum {
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
72static void display_list(void);
73static void display_tree(struct menu *menu);
74static void display_tree_part(void);
75static void update_tree(struct menu *src, GtkTreeIter * dst);
76static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row);
77static gchar **fill_row(struct menu *menu);
78
79
80/* Helping/Debugging Functions */
81
82
83const 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
111const 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
154const 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
181void 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 */
200void 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
285void 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
315void 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
353static void renderer_edited(GtkCellRendererText * cell,
354 const gchar * path_string,
355 const gchar * new_text, gpointer user_data);
356static void renderer_toggled(GtkCellRendererToggle * cellrenderertoggle,
357 gchar * arg1, gpointer user_data);
358
359void 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
463static 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
500static 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
523void on_save1_activate(GtkMenuItem * menuitem, gpointer user_data);
524gboolean 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
569void on_window1_destroy(GtkObject * object, gpointer user_data)
570{
571 gtk_main_quit();
572}
573
574
575void
576on_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
598static void
599load_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
612void 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
632void 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
641static void
642store_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
655void 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
675void 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
682void 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
693void 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
711void 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
722void
723on_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
732void
733on_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
740void 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
772void 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
790void 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
809void 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
824void on_load_clicked(GtkButton * button, gpointer user_data)
825{
826 on_load1_activate(NULL, user_data);
827}
828
829
830void on_save_clicked(GtkButton * button, gpointer user_data)
831{
832 on_save1_activate(NULL, user_data);
833}
834
835
836void 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
846void 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
862void 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
874void on_collapse_clicked(GtkButton * button, gpointer user_data)
875{
876 gtk_tree_view_collapse_all(GTK_TREE_VIEW(tree2_w));
877}
878
879
880void 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 */
889static 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 */
917static 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
959static 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
975static 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
1004static 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) */
1021gboolean
1022on_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 */
1078gboolean
1079on_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 */
1123void
1124on_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. */
1139gboolean
1140on_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 */
1179static 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 */
1302static 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 */
1338static 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 */
1349static GtkTreeIter found;
1350
1351/*
1352 * Find a menu in the GtkTree starting at parent.
1353 */
1354GtkTreeIter *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 */
1388static 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) */
1472static 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) */
1533static 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) */
1545static 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
1556void 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 */
1574int 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}
Note: See TracBrowser for help on using the repository browser.