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