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