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