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