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