blob: 9cb3e6a475551ea6282e3ec1a25f0f6dbdabc4d6 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/* Hey EMACS -*- linux-c -*- */
2/*
3 *
4 * Copyright (C) 2002-2003 Romain Lievin <roms@tilp.info>
5 * Released under the terms of the GNU GPL v2.0.
6 *
7 */
8
9#ifdef HAVE_CONFIG_H
10# include <config.h>
11#endif
12
13#include "lkc.h"
14#include "images.c"
15
16#include <glade/glade.h>
17#include <gtk/gtk.h>
18#include <glib.h>
19#include <gdk/gdkkeysyms.h>
20
21#include <stdio.h>
22#include <string.h>
23#include <unistd.h>
24#include <time.h>
25#include <stdlib.h>
26
27//#define DEBUG
28
29enum {
30 SINGLE_VIEW, SPLIT_VIEW, FULL_VIEW
31};
32
33static gint view_mode = FULL_VIEW;
34static gboolean show_name = TRUE;
35static gboolean show_range = TRUE;
36static gboolean show_value = TRUE;
37static gboolean show_all = FALSE;
38static gboolean show_debug = FALSE;
39static gboolean resizeable = FALSE;
40
41static gboolean config_changed = FALSE;
42
43static char nohelp_text[] =
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -070044 N_("Sorry, no help available for this option yet.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -070045
46GtkWidget *main_wnd = NULL;
47GtkWidget *tree1_w = NULL; // left frame
48GtkWidget *tree2_w = NULL; // right frame
49GtkWidget *text_w = NULL;
50GtkWidget *hpaned = NULL;
51GtkWidget *vpaned = NULL;
52GtkWidget *back_btn = NULL;
53
54GtkTextTag *tag1, *tag2;
55GdkColor color;
56
57GtkTreeStore *tree1, *tree2, *tree;
58GtkTreeModel *model1, *model2;
59static GtkTreeIter *parents[256];
60static gint indent;
61
62static struct menu *current; // current node for SINGLE view
63static struct menu *browsed; // browsed node for SPLIT view
64
65enum {
66 COL_OPTION, COL_NAME, COL_NO, COL_MOD, COL_YES, COL_VALUE,
67 COL_MENU, COL_COLOR, COL_EDIT, COL_PIXBUF,
68 COL_PIXVIS, COL_BTNVIS, COL_BTNACT, COL_BTNINC, COL_BTNRAD,
69 COL_NUMBER
70};
71
72static void display_list(void);
73static void display_tree(struct menu *menu);
74static void display_tree_part(void);
75static void update_tree(struct menu *src, GtkTreeIter * dst);
76static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row);
77static gchar **fill_row(struct menu *menu);
78
79
80/* Helping/Debugging Functions */
81
82
83const char *dbg_print_stype(int val)
84{
85 static char buf[256];
86
87 bzero(buf, 256);
88
89 if (val == S_UNKNOWN)
90 strcpy(buf, "unknown");
91 if (val == S_BOOLEAN)
92 strcpy(buf, "boolean");
93 if (val == S_TRISTATE)
94 strcpy(buf, "tristate");
95 if (val == S_INT)
96 strcpy(buf, "int");
97 if (val == S_HEX)
98 strcpy(buf, "hex");
99 if (val == S_STRING)
100 strcpy(buf, "string");
101 if (val == S_OTHER)
102 strcpy(buf, "other");
103
104#ifdef DEBUG
105 printf("%s", buf);
106#endif
107
108 return buf;
109}
110
111const char *dbg_print_flags(int val)
112{
113 static char buf[256];
114
115 bzero(buf, 256);
116
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117 if (val & SYMBOL_CONST)
118 strcat(buf, "const/");
119 if (val & SYMBOL_CHECK)
120 strcat(buf, "check/");
121 if (val & SYMBOL_CHOICE)
122 strcat(buf, "choice/");
123 if (val & SYMBOL_CHOICEVAL)
124 strcat(buf, "choiceval/");
125 if (val & SYMBOL_PRINTED)
126 strcat(buf, "printed/");
127 if (val & SYMBOL_VALID)
128 strcat(buf, "valid/");
129 if (val & SYMBOL_OPTIONAL)
130 strcat(buf, "optional/");
131 if (val & SYMBOL_WRITE)
132 strcat(buf, "write/");
133 if (val & SYMBOL_CHANGED)
134 strcat(buf, "changed/");
135 if (val & SYMBOL_NEW)
136 strcat(buf, "new/");
137 if (val & SYMBOL_AUTO)
138 strcat(buf, "auto/");
139
140 buf[strlen(buf) - 1] = '\0';
141#ifdef DEBUG
142 printf("%s", buf);
143#endif
144
145 return buf;
146}
147
148const char *dbg_print_ptype(int val)
149{
150 static char buf[256];
151
152 bzero(buf, 256);
153
154 if (val == P_UNKNOWN)
155 strcpy(buf, "unknown");
156 if (val == P_PROMPT)
157 strcpy(buf, "prompt");
158 if (val == P_COMMENT)
159 strcpy(buf, "comment");
160 if (val == P_MENU)
161 strcpy(buf, "menu");
162 if (val == P_DEFAULT)
163 strcpy(buf, "default");
164 if (val == P_CHOICE)
165 strcpy(buf, "choice");
166
167#ifdef DEBUG
168 printf("%s", buf);
169#endif
170
171 return buf;
172}
173
174
Joachim Nilssonbafd2df2005-07-29 00:18:03 +0200175void replace_button_icon(GladeXML * xml, GdkDrawable * window,
176 GtkStyle * style, gchar * btn_name, gchar ** xpm)
177{
178 GdkPixmap *pixmap;
179 GdkBitmap *mask;
180 GtkToolButton *button;
181 GtkWidget *image;
182
183 pixmap = gdk_pixmap_create_from_xpm_d(window, &mask,
184 &style->bg[GTK_STATE_NORMAL],
185 xpm);
186
187 button = GTK_TOOL_BUTTON(glade_xml_get_widget(xml, btn_name));
188 image = gtk_image_new_from_pixmap(pixmap, mask);
189 gtk_widget_show(image);
190 gtk_tool_button_set_icon_widget(button, image);
191}
192
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193/* Main Window Initialization */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194void init_main_window(const gchar * glade_file)
195{
196 GladeXML *xml;
197 GtkWidget *widget;
198 GtkTextBuffer *txtbuf;
199 char title[256];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200 GtkStyle *style;
201
202 xml = glade_xml_new(glade_file, "window1", NULL);
203 if (!xml)
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700204 g_error(_("GUI loading failed !\n"));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205 glade_xml_signal_autoconnect(xml);
206
207 main_wnd = glade_xml_get_widget(xml, "window1");
208 hpaned = glade_xml_get_widget(xml, "hpaned1");
209 vpaned = glade_xml_get_widget(xml, "vpaned1");
210 tree1_w = glade_xml_get_widget(xml, "treeview1");
211 tree2_w = glade_xml_get_widget(xml, "treeview2");
212 text_w = glade_xml_get_widget(xml, "textview3");
213
214 back_btn = glade_xml_get_widget(xml, "button1");
215 gtk_widget_set_sensitive(back_btn, FALSE);
216
217 widget = glade_xml_get_widget(xml, "show_name1");
218 gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
219 show_name);
220
221 widget = glade_xml_get_widget(xml, "show_range1");
222 gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
223 show_range);
224
225 widget = glade_xml_get_widget(xml, "show_data1");
226 gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
227 show_value);
228
229 style = gtk_widget_get_style(main_wnd);
230 widget = glade_xml_get_widget(xml, "toolbar1");
231
Joachim Nilssonbafd2df2005-07-29 00:18:03 +0200232#if 0 /* Use stock Gtk icons instead */
233 replace_button_icon(xml, main_wnd->window, style,
234 "button1", (gchar **) xpm_back);
235 replace_button_icon(xml, main_wnd->window, style,
236 "button2", (gchar **) xpm_load);
237 replace_button_icon(xml, main_wnd->window, style,
238 "button3", (gchar **) xpm_save);
239#endif
240 replace_button_icon(xml, main_wnd->window, style,
241 "button4", (gchar **) xpm_single_view);
242 replace_button_icon(xml, main_wnd->window, style,
243 "button5", (gchar **) xpm_split_view);
244 replace_button_icon(xml, main_wnd->window, style,
245 "button6", (gchar **) xpm_tree_view);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246
Joachim Nilssonbafd2df2005-07-29 00:18:03 +0200247#if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248 switch (view_mode) {
249 case SINGLE_VIEW:
250 widget = glade_xml_get_widget(xml, "button4");
251 g_signal_emit_by_name(widget, "clicked");
252 break;
253 case SPLIT_VIEW:
254 widget = glade_xml_get_widget(xml, "button5");
255 g_signal_emit_by_name(widget, "clicked");
256 break;
257 case FULL_VIEW:
258 widget = glade_xml_get_widget(xml, "button6");
259 g_signal_emit_by_name(widget, "clicked");
260 break;
261 }
Joachim Nilssonbafd2df2005-07-29 00:18:03 +0200262#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263 txtbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
264 tag1 = gtk_text_buffer_create_tag(txtbuf, "mytag1",
265 "foreground", "red",
266 "weight", PANGO_WEIGHT_BOLD,
267 NULL);
268 tag2 = gtk_text_buffer_create_tag(txtbuf, "mytag2",
269 /*"style", PANGO_STYLE_OBLIQUE, */
270 NULL);
271
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700272 sprintf(title, _("Linux Kernel v%s Configuration"),
Sam Ravnborg2244cbd2006-01-16 12:12:12 +0100273 getenv("KERNELVERSION"));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274 gtk_window_set_title(GTK_WINDOW(main_wnd), title);
275
276 gtk_widget_show(main_wnd);
277}
278
279void init_tree_model(void)
280{
281 gint i;
282
283 tree = tree2 = gtk_tree_store_new(COL_NUMBER,
284 G_TYPE_STRING, G_TYPE_STRING,
285 G_TYPE_STRING, G_TYPE_STRING,
286 G_TYPE_STRING, G_TYPE_STRING,
287 G_TYPE_POINTER, GDK_TYPE_COLOR,
288 G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF,
289 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
290 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
291 G_TYPE_BOOLEAN);
292 model2 = GTK_TREE_MODEL(tree2);
293
294 for (parents[0] = NULL, i = 1; i < 256; i++)
295 parents[i] = (GtkTreeIter *) g_malloc(sizeof(GtkTreeIter));
296
297 tree1 = gtk_tree_store_new(COL_NUMBER,
298 G_TYPE_STRING, G_TYPE_STRING,
299 G_TYPE_STRING, G_TYPE_STRING,
300 G_TYPE_STRING, G_TYPE_STRING,
301 G_TYPE_POINTER, GDK_TYPE_COLOR,
302 G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF,
303 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
304 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
305 G_TYPE_BOOLEAN);
306 model1 = GTK_TREE_MODEL(tree1);
307}
308
309void init_left_tree(void)
310{
311 GtkTreeView *view = GTK_TREE_VIEW(tree1_w);
312 GtkCellRenderer *renderer;
313 GtkTreeSelection *sel;
314 GtkTreeViewColumn *column;
315
316 gtk_tree_view_set_model(view, model1);
317 gtk_tree_view_set_headers_visible(view, TRUE);
318 gtk_tree_view_set_rules_hint(view, FALSE);
Joachim Nilssonbafd2df2005-07-29 00:18:03 +0200319
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320 column = gtk_tree_view_column_new();
321 gtk_tree_view_append_column(view, column);
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700322 gtk_tree_view_column_set_title(column, _("Options"));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323
324 renderer = gtk_cell_renderer_toggle_new();
325 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
326 renderer, FALSE);
327 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
328 renderer,
329 "active", COL_BTNACT,
330 "inconsistent", COL_BTNINC,
Joachim Nilssonbafd2df2005-07-29 00:18:03 +0200331 "visible", COL_BTNVIS,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332 "radio", COL_BTNRAD, NULL);
333 renderer = gtk_cell_renderer_text_new();
334 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
Joachim Nilssonbafd2df2005-07-29 00:18:03 +0200335 renderer, FALSE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
337 renderer,
338 "text", COL_OPTION,
339 "foreground-gdk",
340 COL_COLOR, NULL);
341
342 sel = gtk_tree_view_get_selection(view);
343 gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
344 gtk_widget_realize(tree1_w);
345}
346
347static void renderer_edited(GtkCellRendererText * cell,
348 const gchar * path_string,
349 const gchar * new_text, gpointer user_data);
350static void renderer_toggled(GtkCellRendererToggle * cellrenderertoggle,
351 gchar * arg1, gpointer user_data);
352
353void init_right_tree(void)
354{
355 GtkTreeView *view = GTK_TREE_VIEW(tree2_w);
356 GtkCellRenderer *renderer;
357 GtkTreeSelection *sel;
358 GtkTreeViewColumn *column;
359 gint i;
360
361 gtk_tree_view_set_model(view, model2);
362 gtk_tree_view_set_headers_visible(view, TRUE);
363 gtk_tree_view_set_rules_hint(view, FALSE);
364
365 column = gtk_tree_view_column_new();
366 gtk_tree_view_append_column(view, column);
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700367 gtk_tree_view_column_set_title(column, _("Options"));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368
369 renderer = gtk_cell_renderer_pixbuf_new();
370 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
371 renderer, FALSE);
372 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
373 renderer,
374 "pixbuf", COL_PIXBUF,
375 "visible", COL_PIXVIS, NULL);
376 renderer = gtk_cell_renderer_toggle_new();
377 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
378 renderer, FALSE);
379 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
380 renderer,
381 "active", COL_BTNACT,
382 "inconsistent", COL_BTNINC,
Joachim Nilssonbafd2df2005-07-29 00:18:03 +0200383 "visible", COL_BTNVIS,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384 "radio", COL_BTNRAD, NULL);
385 /*g_signal_connect(G_OBJECT(renderer), "toggled",
386 G_CALLBACK(renderer_toggled), NULL); */
387 renderer = gtk_cell_renderer_text_new();
388 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
389 renderer, FALSE);
390 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
391 renderer,
392 "text", COL_OPTION,
393 "foreground-gdk",
394 COL_COLOR, NULL);
395
396 renderer = gtk_cell_renderer_text_new();
397 gtk_tree_view_insert_column_with_attributes(view, -1,
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700398 _("Name"), renderer,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399 "text", COL_NAME,
400 "foreground-gdk",
401 COL_COLOR, NULL);
402 renderer = gtk_cell_renderer_text_new();
403 gtk_tree_view_insert_column_with_attributes(view, -1,
404 "N", renderer,
405 "text", COL_NO,
406 "foreground-gdk",
407 COL_COLOR, NULL);
408 renderer = gtk_cell_renderer_text_new();
409 gtk_tree_view_insert_column_with_attributes(view, -1,
410 "M", renderer,
411 "text", COL_MOD,
412 "foreground-gdk",
413 COL_COLOR, NULL);
414 renderer = gtk_cell_renderer_text_new();
415 gtk_tree_view_insert_column_with_attributes(view, -1,
416 "Y", renderer,
417 "text", COL_YES,
418 "foreground-gdk",
419 COL_COLOR, NULL);
420 renderer = gtk_cell_renderer_text_new();
421 gtk_tree_view_insert_column_with_attributes(view, -1,
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700422 _("Value"), renderer,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423 "text", COL_VALUE,
424 "editable",
425 COL_EDIT,
426 "foreground-gdk",
427 COL_COLOR, NULL);
428 g_signal_connect(G_OBJECT(renderer), "edited",
429 G_CALLBACK(renderer_edited), NULL);
430
431 column = gtk_tree_view_get_column(view, COL_NAME);
432 gtk_tree_view_column_set_visible(column, show_name);
433 column = gtk_tree_view_get_column(view, COL_NO);
434 gtk_tree_view_column_set_visible(column, show_range);
435 column = gtk_tree_view_get_column(view, COL_MOD);
436 gtk_tree_view_column_set_visible(column, show_range);
437 column = gtk_tree_view_get_column(view, COL_YES);
438 gtk_tree_view_column_set_visible(column, show_range);
439 column = gtk_tree_view_get_column(view, COL_VALUE);
440 gtk_tree_view_column_set_visible(column, show_value);
441
442 if (resizeable) {
443 for (i = 0; i < COL_VALUE; i++) {
444 column = gtk_tree_view_get_column(view, i);
445 gtk_tree_view_column_set_resizable(column, TRUE);
446 }
447 }
448
449 sel = gtk_tree_view_get_selection(view);
450 gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
451}
452
453
454/* Utility Functions */
455
456
457static void text_insert_help(struct menu *menu)
458{
459 GtkTextBuffer *buffer;
460 GtkTextIter start, end;
461 const char *prompt = menu_get_prompt(menu);
462 gchar *name;
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700463 const char *help = _(nohelp_text);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464
465 if (!menu->sym)
466 help = "";
467 else if (menu->sym->help)
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700468 help = _(menu->sym->help);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469
470 if (menu->sym && menu->sym->name)
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700471 name = g_strdup_printf(_(menu->sym->name));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472 else
473 name = g_strdup("");
474
475 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
476 gtk_text_buffer_get_bounds(buffer, &start, &end);
477 gtk_text_buffer_delete(buffer, &start, &end);
478 gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15);
479
480 gtk_text_buffer_get_end_iter(buffer, &end);
481 gtk_text_buffer_insert_with_tags(buffer, &end, prompt, -1, tag1,
482 NULL);
483 gtk_text_buffer_insert_at_cursor(buffer, " ", 1);
484 gtk_text_buffer_get_end_iter(buffer, &end);
485 gtk_text_buffer_insert_with_tags(buffer, &end, name, -1, tag1,
486 NULL);
487 gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2);
488 gtk_text_buffer_get_end_iter(buffer, &end);
489 gtk_text_buffer_insert_with_tags(buffer, &end, help, -1, tag2,
490 NULL);
491}
492
493
494static void text_insert_msg(const char *title, const char *message)
495{
496 GtkTextBuffer *buffer;
497 GtkTextIter start, end;
498 const char *msg = message;
499
500 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
501 gtk_text_buffer_get_bounds(buffer, &start, &end);
502 gtk_text_buffer_delete(buffer, &start, &end);
503 gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15);
504
505 gtk_text_buffer_get_end_iter(buffer, &end);
506 gtk_text_buffer_insert_with_tags(buffer, &end, title, -1, tag1,
507 NULL);
508 gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2);
509 gtk_text_buffer_get_end_iter(buffer, &end);
510 gtk_text_buffer_insert_with_tags(buffer, &end, msg, -1, tag2,
511 NULL);
512}
513
514
515/* Main Windows Callbacks */
516
517void on_save1_activate(GtkMenuItem * menuitem, gpointer user_data);
518gboolean on_window1_delete_event(GtkWidget * widget, GdkEvent * event,
519 gpointer user_data)
520{
521 GtkWidget *dialog, *label;
522 gint result;
523
524 if (config_changed == FALSE)
525 return FALSE;
526
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700527 dialog = gtk_dialog_new_with_buttons(_("Warning !"),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528 GTK_WINDOW(main_wnd),
529 (GtkDialogFlags)
530 (GTK_DIALOG_MODAL |
531 GTK_DIALOG_DESTROY_WITH_PARENT),
532 GTK_STOCK_OK,
533 GTK_RESPONSE_YES,
534 GTK_STOCK_NO,
535 GTK_RESPONSE_NO,
536 GTK_STOCK_CANCEL,
537 GTK_RESPONSE_CANCEL, NULL);
538 gtk_dialog_set_default_response(GTK_DIALOG(dialog),
539 GTK_RESPONSE_CANCEL);
540
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700541 label = gtk_label_new(_("\nSave configuration ?\n"));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label);
543 gtk_widget_show(label);
544
545 result = gtk_dialog_run(GTK_DIALOG(dialog));
546 switch (result) {
547 case GTK_RESPONSE_YES:
548 on_save1_activate(NULL, NULL);
549 return FALSE;
550 case GTK_RESPONSE_NO:
551 return FALSE;
552 case GTK_RESPONSE_CANCEL:
553 case GTK_RESPONSE_DELETE_EVENT:
554 default:
555 gtk_widget_destroy(dialog);
556 return TRUE;
557 }
558
559 return FALSE;
560}
561
562
563void on_window1_destroy(GtkObject * object, gpointer user_data)
564{
565 gtk_main_quit();
566}
567
568
569void
570on_window1_size_request(GtkWidget * widget,
571 GtkRequisition * requisition, gpointer user_data)
572{
573 static gint old_h;
574 gint w, h;
575
576 if (widget->window == NULL)
577 gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h);
578 else
579 gdk_window_get_size(widget->window, &w, &h);
580
581 if (h == old_h)
582 return;
583 old_h = h;
584
585 gtk_paned_set_position(GTK_PANED(vpaned), 2 * h / 3);
586}
587
588
589/* Menu & Toolbar Callbacks */
590
591
592static void
593load_filename(GtkFileSelection * file_selector, gpointer user_data)
594{
595 const gchar *fn;
596
597 fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION
598 (user_data));
599
600 if (conf_read(fn))
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700601 text_insert_msg(_("Error"), _("Unable to load configuration !"));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602 else
603 display_tree(&rootmenu);
604}
605
606void on_load1_activate(GtkMenuItem * menuitem, gpointer user_data)
607{
608 GtkWidget *fs;
609
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700610 fs = gtk_file_selection_new(_("Load file..."));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611 g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button),
612 "clicked",
613 G_CALLBACK(load_filename), (gpointer) fs);
614 g_signal_connect_swapped(GTK_OBJECT
615 (GTK_FILE_SELECTION(fs)->ok_button),
616 "clicked", G_CALLBACK(gtk_widget_destroy),
617 (gpointer) fs);
618 g_signal_connect_swapped(GTK_OBJECT
619 (GTK_FILE_SELECTION(fs)->cancel_button),
620 "clicked", G_CALLBACK(gtk_widget_destroy),
621 (gpointer) fs);
622 gtk_widget_show(fs);
623}
624
625
626void on_save1_activate(GtkMenuItem * menuitem, gpointer user_data)
627{
628 if (conf_write(NULL))
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700629 text_insert_msg(_("Error"), _("Unable to save configuration !"));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630
631 config_changed = FALSE;
632}
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
Joachim Nilssonbafd2df2005-07-29 00:18:03 +0200824void on_save_clicked(GtkButton * button, gpointer user_data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825{
826 on_save1_activate(NULL, user_data);
827}
828
829
830void on_single_clicked(GtkButton * button, gpointer user_data)
831{
832 view_mode = SINGLE_VIEW;
833 gtk_paned_set_position(GTK_PANED(hpaned), 0);
834 gtk_widget_hide(tree1_w);
835 current = &rootmenu;
836 display_tree_part();
837}
838
839
840void on_split_clicked(GtkButton * button, gpointer user_data)
841{
842 gint w, h;
843 view_mode = SPLIT_VIEW;
844 gtk_widget_show(tree1_w);
845 gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h);
846 gtk_paned_set_position(GTK_PANED(hpaned), w / 2);
Joachim Nilssonbafd2df2005-07-29 00:18:03 +0200847 if (tree2)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848 gtk_tree_store_clear(tree2);
849 display_list();
Joachim Nilssonbafd2df2005-07-29 00:18:03 +0200850
851 /* Disable back btn, like in full mode. */
852 gtk_widget_set_sensitive(back_btn, FALSE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853}
854
855
856void on_full_clicked(GtkButton * button, gpointer user_data)
857{
858 view_mode = FULL_VIEW;
859 gtk_paned_set_position(GTK_PANED(hpaned), 0);
860 gtk_widget_hide(tree1_w);
861 if (tree2)
862 gtk_tree_store_clear(tree2);
863 display_tree(&rootmenu);
864 gtk_widget_set_sensitive(back_btn, FALSE);
865}
866
867
Joachim Nilssonbafd2df2005-07-29 00:18:03 +0200868void on_collapse_clicked(GtkButton * button, gpointer user_data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700869{
870 gtk_tree_view_collapse_all(GTK_TREE_VIEW(tree2_w));
871}
872
873
Joachim Nilssonbafd2df2005-07-29 00:18:03 +0200874void on_expand_clicked(GtkButton * button, gpointer user_data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875{
876 gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w));
877}
878
879
880/* CTree Callbacks */
881
882/* Change hex/int/string value in the cell */
883static void renderer_edited(GtkCellRendererText * cell,
884 const gchar * path_string,
885 const gchar * new_text, gpointer user_data)
886{
887 GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
888 GtkTreeIter iter;
889 const char *old_def, *new_def;
890 struct menu *menu;
891 struct symbol *sym;
892
893 if (!gtk_tree_model_get_iter(model2, &iter, path))
894 return;
895
896 gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
897 sym = menu->sym;
898
899 gtk_tree_model_get(model2, &iter, COL_VALUE, &old_def, -1);
900 new_def = new_text;
901
902 sym_set_string_value(sym, new_def);
903
904 config_changed = TRUE;
905 update_tree(&rootmenu, NULL);
906
907 gtk_tree_path_free(path);
908}
909
910/* Change the value of a symbol and update the tree */
911static void change_sym_value(struct menu *menu, gint col)
912{
913 struct symbol *sym = menu->sym;
914 tristate oldval, newval;
915
916 if (!sym)
917 return;
918
919 if (col == COL_NO)
920 newval = no;
921 else if (col == COL_MOD)
922 newval = mod;
923 else if (col == COL_YES)
924 newval = yes;
925 else
926 return;
927
928 switch (sym_get_type(sym)) {
929 case S_BOOLEAN:
930 case S_TRISTATE:
931 oldval = sym_get_tristate_value(sym);
932 if (!sym_tristate_within_range(sym, newval))
933 newval = yes;
934 sym_set_tristate_value(sym, newval);
935 config_changed = TRUE;
936 if (view_mode == FULL_VIEW)
937 update_tree(&rootmenu, NULL);
938 else if (view_mode == SPLIT_VIEW) {
939 update_tree(browsed, NULL);
940 display_list();
941 }
942 else if (view_mode == SINGLE_VIEW)
943 display_tree_part(); //fixme: keep exp/coll
944 break;
945 case S_INT:
946 case S_HEX:
947 case S_STRING:
948 default:
949 break;
950 }
951}
952
953static void toggle_sym_value(struct menu *menu)
954{
955 if (!menu->sym)
956 return;
957
958 sym_toggle_tristate_value(menu->sym);
959 if (view_mode == FULL_VIEW)
960 update_tree(&rootmenu, NULL);
961 else if (view_mode == SPLIT_VIEW) {
962 update_tree(browsed, NULL);
963 display_list();
964 }
965 else if (view_mode == SINGLE_VIEW)
966 display_tree_part(); //fixme: keep exp/coll
967}
968
969static void renderer_toggled(GtkCellRendererToggle * cell,
970 gchar * path_string, gpointer user_data)
971{
972 GtkTreePath *path, *sel_path = NULL;
973 GtkTreeIter iter, sel_iter;
974 GtkTreeSelection *sel;
975 struct menu *menu;
976
977 path = gtk_tree_path_new_from_string(path_string);
978 if (!gtk_tree_model_get_iter(model2, &iter, path))
979 return;
980
981 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree2_w));
982 if (gtk_tree_selection_get_selected(sel, NULL, &sel_iter))
983 sel_path = gtk_tree_model_get_path(model2, &sel_iter);
984 if (!sel_path)
985 goto out1;
986 if (gtk_tree_path_compare(path, sel_path))
987 goto out2;
988
989 gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
990 toggle_sym_value(menu);
991
992 out2:
993 gtk_tree_path_free(sel_path);
994 out1:
995 gtk_tree_path_free(path);
996}
997
998static gint column2index(GtkTreeViewColumn * column)
999{
1000 gint i;
1001
1002 for (i = 0; i < COL_NUMBER; i++) {
1003 GtkTreeViewColumn *col;
1004
1005 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), i);
1006 if (col == column)
1007 return i;
1008 }
1009
1010 return -1;
1011}
1012
1013
1014/* User click: update choice (full) or goes down (single) */
1015gboolean
1016on_treeview2_button_press_event(GtkWidget * widget,
1017 GdkEventButton * event, gpointer user_data)
1018{
1019 GtkTreeView *view = GTK_TREE_VIEW(widget);
1020 GtkTreePath *path;
1021 GtkTreeViewColumn *column;
1022 GtkTreeIter iter;
1023 struct menu *menu;
1024 gint col;
1025
1026#if GTK_CHECK_VERSION(2,1,4) // bug in ctree with earlier version of GTK
1027 gint tx = (gint) event->x;
1028 gint ty = (gint) event->y;
1029 gint cx, cy;
1030
1031 gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx,
1032 &cy);
1033#else
1034 gtk_tree_view_get_cursor(view, &path, &column);
1035#endif
1036 if (path == NULL)
1037 return FALSE;
1038
1039 if (!gtk_tree_model_get_iter(model2, &iter, path))
1040 return FALSE;
1041 gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
1042
1043 col = column2index(column);
1044 if (event->type == GDK_2BUTTON_PRESS) {
1045 enum prop_type ptype;
1046 ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
1047
1048 if (ptype == P_MENU && view_mode != FULL_VIEW && col == COL_OPTION) {
1049 // goes down into menu
1050 current = menu;
1051 display_tree_part();
1052 gtk_widget_set_sensitive(back_btn, TRUE);
1053 } else if ((col == COL_OPTION)) {
1054 toggle_sym_value(menu);
1055 gtk_tree_view_expand_row(view, path, TRUE);
1056 }
1057 } else {
1058 if (col == COL_VALUE) {
1059 toggle_sym_value(menu);
1060 gtk_tree_view_expand_row(view, path, TRUE);
1061 } else if (col == COL_NO || col == COL_MOD
1062 || col == COL_YES) {
1063 change_sym_value(menu, col);
1064 gtk_tree_view_expand_row(view, path, TRUE);
1065 }
1066 }
1067
1068 return FALSE;
1069}
1070
1071/* Key pressed: update choice */
1072gboolean
1073on_treeview2_key_press_event(GtkWidget * widget,
1074 GdkEventKey * event, gpointer user_data)
1075{
1076 GtkTreeView *view = GTK_TREE_VIEW(widget);
1077 GtkTreePath *path;
1078 GtkTreeViewColumn *column;
1079 GtkTreeIter iter;
1080 struct menu *menu;
1081 gint col;
1082
1083 gtk_tree_view_get_cursor(view, &path, &column);
1084 if (path == NULL)
1085 return FALSE;
1086
1087 if (event->keyval == GDK_space) {
1088 if (gtk_tree_view_row_expanded(view, path))
1089 gtk_tree_view_collapse_row(view, path);
1090 else
1091 gtk_tree_view_expand_row(view, path, FALSE);
1092 return TRUE;
1093 }
1094 if (event->keyval == GDK_KP_Enter) {
1095 }
1096 if (widget == tree1_w)
1097 return FALSE;
1098
1099 gtk_tree_model_get_iter(model2, &iter, path);
1100 gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
1101
1102 if (!strcasecmp(event->string, "n"))
1103 col = COL_NO;
1104 else if (!strcasecmp(event->string, "m"))
1105 col = COL_MOD;
1106 else if (!strcasecmp(event->string, "y"))
1107 col = COL_YES;
1108 else
1109 col = -1;
1110 change_sym_value(menu, col);
1111
1112 return FALSE;
1113}
1114
1115
1116/* Row selection changed: update help */
1117void
1118on_treeview2_cursor_changed(GtkTreeView * treeview, gpointer user_data)
1119{
1120 GtkTreeSelection *selection;
1121 GtkTreeIter iter;
1122 struct menu *menu;
1123
1124 selection = gtk_tree_view_get_selection(treeview);
1125 if (gtk_tree_selection_get_selected(selection, &model2, &iter)) {
1126 gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
1127 text_insert_help(menu);
1128 }
1129}
1130
1131
1132/* User click: display sub-tree in the right frame. */
1133gboolean
1134on_treeview1_button_press_event(GtkWidget * widget,
1135 GdkEventButton * event, gpointer user_data)
1136{
1137 GtkTreeView *view = GTK_TREE_VIEW(widget);
1138 GtkTreePath *path;
1139 GtkTreeViewColumn *column;
1140 GtkTreeIter iter;
1141 struct menu *menu;
1142
1143 gint tx = (gint) event->x;
1144 gint ty = (gint) event->y;
1145 gint cx, cy;
1146
1147 gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx,
1148 &cy);
1149 if (path == NULL)
1150 return FALSE;
1151
1152 gtk_tree_model_get_iter(model1, &iter, path);
1153 gtk_tree_model_get(model1, &iter, COL_MENU, &menu, -1);
1154
1155 if (event->type == GDK_2BUTTON_PRESS) {
1156 toggle_sym_value(menu);
1157 current = menu;
1158 display_tree_part();
1159 } else {
1160 browsed = menu;
1161 display_tree_part();
1162 }
1163
1164 gtk_widget_realize(tree2_w);
1165 gtk_tree_view_set_cursor(view, path, NULL, FALSE);
1166 gtk_widget_grab_focus(tree2_w);
1167
1168 return FALSE;
1169}
1170
1171
1172/* Fill a row of strings */
1173static gchar **fill_row(struct menu *menu)
1174{
1175 static gchar *row[COL_NUMBER];
1176 struct symbol *sym = menu->sym;
1177 const char *def;
1178 int stype;
1179 tristate val;
1180 enum prop_type ptype;
1181 int i;
1182
1183 for (i = COL_OPTION; i <= COL_COLOR; i++)
1184 g_free(row[i]);
1185 bzero(row, sizeof(row));
1186
1187 row[COL_OPTION] =
1188 g_strdup_printf("%s %s", menu_get_prompt(menu),
1189 sym ? (sym->
1190 flags & SYMBOL_NEW ? "(NEW)" : "") :
1191 "");
1192
1193 if (show_all && !menu_is_visible(menu))
1194 row[COL_COLOR] = g_strdup("DarkGray");
1195 else
1196 row[COL_COLOR] = g_strdup("Black");
1197
1198 ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
1199 switch (ptype) {
1200 case P_MENU:
1201 row[COL_PIXBUF] = (gchar *) xpm_menu;
1202 if (view_mode == SINGLE_VIEW)
1203 row[COL_PIXVIS] = GINT_TO_POINTER(TRUE);
1204 row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
1205 break;
1206 case P_COMMENT:
1207 row[COL_PIXBUF] = (gchar *) xpm_void;
1208 row[COL_PIXVIS] = GINT_TO_POINTER(FALSE);
1209 row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
1210 break;
1211 default:
1212 row[COL_PIXBUF] = (gchar *) xpm_void;
1213 row[COL_PIXVIS] = GINT_TO_POINTER(FALSE);
1214 row[COL_BTNVIS] = GINT_TO_POINTER(TRUE);
1215 break;
1216 }
1217
1218 if (!sym)
1219 return row;
1220 row[COL_NAME] = g_strdup(sym->name);
1221
1222 sym_calc_value(sym);
1223 sym->flags &= ~SYMBOL_CHANGED;
1224
1225 if (sym_is_choice(sym)) { // parse childs for getting final value
1226 struct menu *child;
1227 struct symbol *def_sym = sym_get_choice_value(sym);
1228 struct menu *def_menu = NULL;
1229
1230 row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
1231
1232 for (child = menu->list; child; child = child->next) {
1233 if (menu_is_visible(child)
1234 && child->sym == def_sym)
1235 def_menu = child;
1236 }
1237
1238 if (def_menu)
1239 row[COL_VALUE] =
1240 g_strdup(menu_get_prompt(def_menu));
1241 }
Joachim Nilssonbafd2df2005-07-29 00:18:03 +02001242 if (sym->flags & SYMBOL_CHOICEVAL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001243 row[COL_BTNRAD] = GINT_TO_POINTER(TRUE);
1244
1245 stype = sym_get_type(sym);
1246 switch (stype) {
1247 case S_BOOLEAN:
Joachim Nilssonbafd2df2005-07-29 00:18:03 +02001248 if (GPOINTER_TO_INT(row[COL_PIXVIS]) == FALSE)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001249 row[COL_BTNVIS] = GINT_TO_POINTER(TRUE);
1250 if (sym_is_choice(sym))
1251 break;
1252 case S_TRISTATE:
1253 val = sym_get_tristate_value(sym);
1254 switch (val) {
1255 case no:
1256 row[COL_NO] = g_strdup("N");
1257 row[COL_VALUE] = g_strdup("N");
1258 row[COL_BTNACT] = GINT_TO_POINTER(FALSE);
1259 row[COL_BTNINC] = GINT_TO_POINTER(FALSE);
1260 break;
1261 case mod:
1262 row[COL_MOD] = g_strdup("M");
1263 row[COL_VALUE] = g_strdup("M");
1264 row[COL_BTNINC] = GINT_TO_POINTER(TRUE);
1265 break;
1266 case yes:
1267 row[COL_YES] = g_strdup("Y");
1268 row[COL_VALUE] = g_strdup("Y");
1269 row[COL_BTNACT] = GINT_TO_POINTER(TRUE);
1270 row[COL_BTNINC] = GINT_TO_POINTER(FALSE);
1271 break;
1272 }
1273
1274 if (val != no && sym_tristate_within_range(sym, no))
1275 row[COL_NO] = g_strdup("_");
1276 if (val != mod && sym_tristate_within_range(sym, mod))
1277 row[COL_MOD] = g_strdup("_");
1278 if (val != yes && sym_tristate_within_range(sym, yes))
1279 row[COL_YES] = g_strdup("_");
1280 break;
1281 case S_INT:
1282 case S_HEX:
1283 case S_STRING:
1284 def = sym_get_string_value(sym);
1285 row[COL_VALUE] = g_strdup(def);
1286 row[COL_EDIT] = GINT_TO_POINTER(TRUE);
1287 row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
1288 break;
1289 }
1290
1291 return row;
1292}
1293
1294
1295/* Set the node content with a row of strings */
1296static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row)
1297{
1298 GdkColor color;
1299 gboolean success;
1300 GdkPixbuf *pix;
1301
1302 pix = gdk_pixbuf_new_from_xpm_data((const char **)
1303 row[COL_PIXBUF]);
1304
1305 gdk_color_parse(row[COL_COLOR], &color);
1306 gdk_colormap_alloc_colors(gdk_colormap_get_system(), &color, 1,
1307 FALSE, FALSE, &success);
1308
1309 gtk_tree_store_set(tree, node,
1310 COL_OPTION, row[COL_OPTION],
1311 COL_NAME, row[COL_NAME],
1312 COL_NO, row[COL_NO],
1313 COL_MOD, row[COL_MOD],
1314 COL_YES, row[COL_YES],
1315 COL_VALUE, row[COL_VALUE],
1316 COL_MENU, (gpointer) menu,
1317 COL_COLOR, &color,
1318 COL_EDIT, GPOINTER_TO_INT(row[COL_EDIT]),
1319 COL_PIXBUF, pix,
1320 COL_PIXVIS, GPOINTER_TO_INT(row[COL_PIXVIS]),
1321 COL_BTNVIS, GPOINTER_TO_INT(row[COL_BTNVIS]),
1322 COL_BTNACT, GPOINTER_TO_INT(row[COL_BTNACT]),
1323 COL_BTNINC, GPOINTER_TO_INT(row[COL_BTNINC]),
1324 COL_BTNRAD, GPOINTER_TO_INT(row[COL_BTNRAD]),
1325 -1);
1326
1327 g_object_unref(pix);
1328}
1329
1330
1331/* Add a node to the tree */
1332static void place_node(struct menu *menu, char **row)
1333{
1334 GtkTreeIter *parent = parents[indent - 1];
1335 GtkTreeIter *node = parents[indent];
1336
1337 gtk_tree_store_append(tree, node, parent);
1338 set_node(node, menu, row);
1339}
1340
1341
1342/* Find a node in the GTK+ tree */
1343static GtkTreeIter found;
1344
1345/*
1346 * Find a menu in the GtkTree starting at parent.
1347 */
1348GtkTreeIter *gtktree_iter_find_node(GtkTreeIter * parent,
1349 struct menu *tofind)
1350{
1351 GtkTreeIter iter;
1352 GtkTreeIter *child = &iter;
1353 gboolean valid;
1354 GtkTreeIter *ret;
1355
1356 valid = gtk_tree_model_iter_children(model2, child, parent);
1357 while (valid) {
1358 struct menu *menu;
1359
1360 gtk_tree_model_get(model2, child, 6, &menu, -1);
1361
1362 if (menu == tofind) {
1363 memcpy(&found, child, sizeof(GtkTreeIter));
1364 return &found;
1365 }
1366
1367 ret = gtktree_iter_find_node(child, tofind);
1368 if (ret)
1369 return ret;
1370
1371 valid = gtk_tree_model_iter_next(model2, child);
1372 }
1373
1374 return NULL;
1375}
1376
1377
1378/*
1379 * Update the tree by adding/removing entries
1380 * Does not change other nodes
1381 */
1382static void update_tree(struct menu *src, GtkTreeIter * dst)
1383{
1384 struct menu *child1;
1385 GtkTreeIter iter, tmp;
1386 GtkTreeIter *child2 = &iter;
1387 gboolean valid;
1388 GtkTreeIter *sibling;
1389 struct symbol *sym;
1390 struct property *prop;
1391 struct menu *menu1, *menu2;
1392
1393 if (src == &rootmenu)
1394 indent = 1;
1395
1396 valid = gtk_tree_model_iter_children(model2, child2, dst);
1397 for (child1 = src->list; child1; child1 = child1->next) {
1398
1399 prop = child1->prompt;
1400 sym = child1->sym;
1401
1402 reparse:
1403 menu1 = child1;
1404 if (valid)
1405 gtk_tree_model_get(model2, child2, COL_MENU,
1406 &menu2, -1);
1407 else
1408 menu2 = NULL; // force adding of a first child
1409
1410#ifdef DEBUG
1411 printf("%*c%s | %s\n", indent, ' ',
1412 menu1 ? menu_get_prompt(menu1) : "nil",
1413 menu2 ? menu_get_prompt(menu2) : "nil");
1414#endif
1415
1416 if (!menu_is_visible(child1) && !show_all) { // remove node
1417 if (gtktree_iter_find_node(dst, menu1) != NULL) {
1418 memcpy(&tmp, child2, sizeof(GtkTreeIter));
1419 valid = gtk_tree_model_iter_next(model2,
1420 child2);
1421 gtk_tree_store_remove(tree2, &tmp);
1422 if (!valid)
Joachim Nilssonbafd2df2005-07-29 00:18:03 +02001423 return; // next parent
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424 else
1425 goto reparse; // next child
1426 } else
1427 continue;
1428 }
1429
1430 if (menu1 != menu2) {
1431 if (gtktree_iter_find_node(dst, menu1) == NULL) { // add node
1432 if (!valid && !menu2)
1433 sibling = NULL;
1434 else
1435 sibling = child2;
1436 gtk_tree_store_insert_before(tree2,
1437 child2,
1438 dst, sibling);
1439 set_node(child2, menu1, fill_row(menu1));
1440 if (menu2 == NULL)
1441 valid = TRUE;
1442 } else { // remove node
1443 memcpy(&tmp, child2, sizeof(GtkTreeIter));
1444 valid = gtk_tree_model_iter_next(model2,
1445 child2);
1446 gtk_tree_store_remove(tree2, &tmp);
1447 if (!valid)
Joachim Nilssonbafd2df2005-07-29 00:18:03 +02001448 return; // next parent
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449 else
1450 goto reparse; // next child
1451 }
1452 } else if (sym && (sym->flags & SYMBOL_CHANGED)) {
1453 set_node(child2, menu1, fill_row(menu1));
1454 }
1455
1456 indent++;
1457 update_tree(child1, child2);
1458 indent--;
1459
1460 valid = gtk_tree_model_iter_next(model2, child2);
1461 }
1462}
1463
1464
1465/* Display the whole tree (single/split/full view) */
1466static void display_tree(struct menu *menu)
1467{
1468 struct symbol *sym;
1469 struct property *prop;
1470 struct menu *child;
1471 enum prop_type ptype;
1472
1473 if (menu == &rootmenu) {
1474 indent = 1;
1475 current = &rootmenu;
1476 }
1477
1478 for (child = menu->list; child; child = child->next) {
1479 prop = child->prompt;
1480 sym = child->sym;
1481 ptype = prop ? prop->type : P_UNKNOWN;
1482
1483 if (sym)
1484 sym->flags &= ~SYMBOL_CHANGED;
1485
Joachim Nilssonbafd2df2005-07-29 00:18:03 +02001486 if ((view_mode == SPLIT_VIEW)
1487 && !(child->flags & MENU_ROOT) && (tree == tree1))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001488 continue;
1489
Joachim Nilssonbafd2df2005-07-29 00:18:03 +02001490 if ((view_mode == SPLIT_VIEW) && (child->flags & MENU_ROOT)
1491 && (tree == tree2))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001492 continue;
1493
1494 if (menu_is_visible(child) || show_all)
1495 place_node(child, fill_row(child));
1496#ifdef DEBUG
1497 printf("%*c%s: ", indent, ' ', menu_get_prompt(child));
1498 printf("%s", child->flags & MENU_ROOT ? "rootmenu | " : "");
1499 dbg_print_ptype(ptype);
1500 printf(" | ");
1501 if (sym) {
1502 dbg_print_stype(sym->type);
1503 printf(" | ");
1504 dbg_print_flags(sym->flags);
1505 printf("\n");
1506 } else
1507 printf("\n");
1508#endif
1509 if ((view_mode != FULL_VIEW) && (ptype == P_MENU)
1510 && (tree == tree2))
1511 continue;
1512/*
Joachim Nilssonbafd2df2005-07-29 00:18:03 +02001513 if (((menu != &rootmenu) && !(menu->flags & MENU_ROOT))
1514 || (view_mode == FULL_VIEW)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515 || (view_mode == SPLIT_VIEW))*/
1516 if (((view_mode == SINGLE_VIEW) && (menu->flags & MENU_ROOT))
Joachim Nilssonbafd2df2005-07-29 00:18:03 +02001517 || (view_mode == FULL_VIEW)
1518 || (view_mode == SPLIT_VIEW)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519 indent++;
1520 display_tree(child);
1521 indent--;
1522 }
1523 }
1524}
1525
1526/* Display a part of the tree starting at current node (single/split view) */
1527static void display_tree_part(void)
1528{
1529 if (tree2)
1530 gtk_tree_store_clear(tree2);
Joachim Nilssonbafd2df2005-07-29 00:18:03 +02001531 if (view_mode == SINGLE_VIEW)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001532 display_tree(current);
Joachim Nilssonbafd2df2005-07-29 00:18:03 +02001533 else if (view_mode == SPLIT_VIEW)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001534 display_tree(browsed);
1535 gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w));
1536}
1537
1538/* Display the list in the left frame (split view) */
1539static void display_list(void)
1540{
1541 if (tree1)
1542 gtk_tree_store_clear(tree1);
1543
1544 tree = tree1;
1545 display_tree(&rootmenu);
1546 gtk_tree_view_expand_all(GTK_TREE_VIEW(tree1_w));
1547 tree = tree2;
1548}
1549
1550void fixup_rootmenu(struct menu *menu)
1551{
Joachim Nilssonbafd2df2005-07-29 00:18:03 +02001552 struct menu *child;
1553 static int menu_cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001554
Joachim Nilssonbafd2df2005-07-29 00:18:03 +02001555 menu->flags |= MENU_ROOT;
1556 for (child = menu->list; child; child = child->next) {
1557 if (child->prompt && child->prompt->type == P_MENU) {
1558 menu_cnt++;
1559 fixup_rootmenu(child);
1560 menu_cnt--;
1561 } else if (!menu_cnt)
1562 fixup_rootmenu(child);
1563 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001564}
1565
1566
1567/* Main */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001568int main(int ac, char *av[])
1569{
1570 const char *name;
1571 char *env;
1572 gchar *glade_file;
1573
1574#ifndef LKC_DIRECT_LINK
1575 kconfig_load();
1576#endif
1577
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -07001578 bindtextdomain(PACKAGE, LOCALEDIR);
1579 bind_textdomain_codeset(PACKAGE, "UTF-8");
1580 textdomain(PACKAGE);
1581
Linus Torvalds1da177e2005-04-16 15:20:36 -07001582 /* GTK stuffs */
1583 gtk_set_locale();
1584 gtk_init(&ac, &av);
1585 glade_init();
1586
1587 //add_pixmap_directory (PACKAGE_DATA_DIR "/" PACKAGE "/pixmaps");
1588 //add_pixmap_directory (PACKAGE_SOURCE_DIR "/pixmaps");
1589
1590 /* Determine GUI path */
1591 env = getenv(SRCTREE);
1592 if (env)
1593 glade_file = g_strconcat(env, "/scripts/kconfig/gconf.glade", NULL);
1594 else if (av[0][0] == '/')
1595 glade_file = g_strconcat(av[0], ".glade", NULL);
1596 else
1597 glade_file = g_strconcat(g_get_current_dir(), "/", av[0], ".glade", NULL);
1598
1599 /* Load the interface and connect signals */
1600 init_main_window(glade_file);
1601 init_tree_model();
1602 init_left_tree();
1603 init_right_tree();
1604
1605 /* Conf stuffs */
1606 if (ac > 1 && av[1][0] == '-') {
1607 switch (av[1][1]) {
1608 case 'a':
1609 //showAll = 1;
1610 break;
1611 case 'h':
1612 case '?':
1613 printf("%s <config>\n", av[0]);
1614 exit(0);
1615 }
1616 name = av[2];
1617 } else
1618 name = av[1];
1619
1620 conf_parse(name);
1621 fixup_rootmenu(&rootmenu);
1622 conf_read(NULL);
1623
1624 switch (view_mode) {
1625 case SINGLE_VIEW:
1626 display_tree_part();
1627 break;
1628 case SPLIT_VIEW:
1629 display_list();
1630 break;
1631 case FULL_VIEW:
1632 display_tree(&rootmenu);
1633 break;
1634 }
1635
1636 gtk_main();
1637
1638 return 0;
1639}