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