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