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