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