blob: 80fe9ca2cbb39df5c5b78653d6e6d0cefad7f728 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/* Hey EMACS -*- linux-c -*- */
2/*
3 *
4 * Copyright (C) 2002-2003 Romain Lievin <roms@tilp.info>
5 * Released under the terms of the GNU GPL v2.0.
6 *
7 */
8
9#ifdef HAVE_CONFIG_H
10# include <config.h>
11#endif
12
13#include "lkc.h"
14#include "images.c"
15
16#include <glade/glade.h>
17#include <gtk/gtk.h>
18#include <glib.h>
19#include <gdk/gdkkeysyms.h>
20
21#include <stdio.h>
22#include <string.h>
23#include <unistd.h>
24#include <time.h>
25#include <stdlib.h>
26
27//#define DEBUG
28
29enum {
30 SINGLE_VIEW, SPLIT_VIEW, FULL_VIEW
31};
32
33static gint view_mode = FULL_VIEW;
34static gboolean show_name = TRUE;
35static gboolean show_range = TRUE;
36static gboolean show_value = TRUE;
37static gboolean show_all = FALSE;
38static gboolean show_debug = FALSE;
39static gboolean resizeable = FALSE;
40
Linus Torvalds1da177e2005-04-16 15:20:36 -070041GtkWidget *main_wnd = NULL;
42GtkWidget *tree1_w = NULL; // left frame
43GtkWidget *tree2_w = NULL; // right frame
44GtkWidget *text_w = NULL;
45GtkWidget *hpaned = NULL;
46GtkWidget *vpaned = NULL;
47GtkWidget *back_btn = NULL;
Karsten Wiese0a0c5022006-12-13 00:34:09 -080048GtkWidget *save_btn = NULL;
49GtkWidget *save_menu_item = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -070050
51GtkTextTag *tag1, *tag2;
52GdkColor color;
53
54GtkTreeStore *tree1, *tree2, *tree;
55GtkTreeModel *model1, *model2;
56static GtkTreeIter *parents[256];
57static gint indent;
58
59static struct menu *current; // current node for SINGLE view
60static struct menu *browsed; // browsed node for SPLIT view
61
62enum {
63 COL_OPTION, COL_NAME, COL_NO, COL_MOD, COL_YES, COL_VALUE,
64 COL_MENU, COL_COLOR, COL_EDIT, COL_PIXBUF,
65 COL_PIXVIS, COL_BTNVIS, COL_BTNACT, COL_BTNINC, COL_BTNRAD,
66 COL_NUMBER
67};
68
69static void display_list(void);
70static void display_tree(struct menu *menu);
71static void display_tree_part(void);
72static void update_tree(struct menu *src, GtkTreeIter * dst);
73static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row);
74static gchar **fill_row(struct menu *menu);
Karsten Wiese0a0c5022006-12-13 00:34:09 -080075static void conf_changed(void);
Linus Torvalds1da177e2005-04-16 15:20:36 -070076
77/* Helping/Debugging Functions */
78
Li Zefan29442352010-04-14 11:44:34 +080079const char *dbg_sym_flags(int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -070080{
81 static char buf[256];
82
83 bzero(buf, 256);
84
Linus Torvalds1da177e2005-04-16 15:20:36 -070085 if (val & SYMBOL_CONST)
86 strcat(buf, "const/");
87 if (val & SYMBOL_CHECK)
88 strcat(buf, "check/");
89 if (val & SYMBOL_CHOICE)
90 strcat(buf, "choice/");
91 if (val & SYMBOL_CHOICEVAL)
92 strcat(buf, "choiceval/");
Linus Torvalds1da177e2005-04-16 15:20:36 -070093 if (val & SYMBOL_VALID)
94 strcat(buf, "valid/");
95 if (val & SYMBOL_OPTIONAL)
96 strcat(buf, "optional/");
97 if (val & SYMBOL_WRITE)
98 strcat(buf, "write/");
99 if (val & SYMBOL_CHANGED)
100 strcat(buf, "changed/");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101 if (val & SYMBOL_AUTO)
102 strcat(buf, "auto/");
103
104 buf[strlen(buf) - 1] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105
106 return buf;
107}
108
Joachim Nilssonbafd2df2005-07-29 00:18:03 +0200109void replace_button_icon(GladeXML * xml, GdkDrawable * window,
110 GtkStyle * style, gchar * btn_name, gchar ** xpm)
111{
112 GdkPixmap *pixmap;
113 GdkBitmap *mask;
114 GtkToolButton *button;
115 GtkWidget *image;
116
117 pixmap = gdk_pixmap_create_from_xpm_d(window, &mask,
118 &style->bg[GTK_STATE_NORMAL],
119 xpm);
120
121 button = GTK_TOOL_BUTTON(glade_xml_get_widget(xml, btn_name));
122 image = gtk_image_new_from_pixmap(pixmap, mask);
123 gtk_widget_show(image);
124 gtk_tool_button_set_icon_widget(button, image);
125}
126
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127/* Main Window Initialization */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128void init_main_window(const gchar * glade_file)
129{
130 GladeXML *xml;
131 GtkWidget *widget;
132 GtkTextBuffer *txtbuf;
133 char title[256];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700134 GtkStyle *style;
135
136 xml = glade_xml_new(glade_file, "window1", NULL);
137 if (!xml)
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700138 g_error(_("GUI loading failed !\n"));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139 glade_xml_signal_autoconnect(xml);
140
141 main_wnd = glade_xml_get_widget(xml, "window1");
142 hpaned = glade_xml_get_widget(xml, "hpaned1");
143 vpaned = glade_xml_get_widget(xml, "vpaned1");
144 tree1_w = glade_xml_get_widget(xml, "treeview1");
145 tree2_w = glade_xml_get_widget(xml, "treeview2");
146 text_w = glade_xml_get_widget(xml, "textview3");
147
148 back_btn = glade_xml_get_widget(xml, "button1");
149 gtk_widget_set_sensitive(back_btn, FALSE);
150
151 widget = glade_xml_get_widget(xml, "show_name1");
152 gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
153 show_name);
154
155 widget = glade_xml_get_widget(xml, "show_range1");
156 gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
157 show_range);
158
159 widget = glade_xml_get_widget(xml, "show_data1");
160 gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
161 show_value);
162
Karsten Wiese0a0c5022006-12-13 00:34:09 -0800163 save_btn = glade_xml_get_widget(xml, "button3");
164 save_menu_item = glade_xml_get_widget(xml, "save1");
165 conf_set_changed_callback(conf_changed);
166
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167 style = gtk_widget_get_style(main_wnd);
168 widget = glade_xml_get_widget(xml, "toolbar1");
169
Joachim Nilssonbafd2df2005-07-29 00:18:03 +0200170#if 0 /* Use stock Gtk icons instead */
171 replace_button_icon(xml, main_wnd->window, style,
172 "button1", (gchar **) xpm_back);
173 replace_button_icon(xml, main_wnd->window, style,
174 "button2", (gchar **) xpm_load);
175 replace_button_icon(xml, main_wnd->window, style,
176 "button3", (gchar **) xpm_save);
177#endif
178 replace_button_icon(xml, main_wnd->window, style,
179 "button4", (gchar **) xpm_single_view);
180 replace_button_icon(xml, main_wnd->window, style,
181 "button5", (gchar **) xpm_split_view);
182 replace_button_icon(xml, main_wnd->window, style,
183 "button6", (gchar **) xpm_tree_view);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184
Joachim Nilssonbafd2df2005-07-29 00:18:03 +0200185#if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700186 switch (view_mode) {
187 case SINGLE_VIEW:
188 widget = glade_xml_get_widget(xml, "button4");
189 g_signal_emit_by_name(widget, "clicked");
190 break;
191 case SPLIT_VIEW:
192 widget = glade_xml_get_widget(xml, "button5");
193 g_signal_emit_by_name(widget, "clicked");
194 break;
195 case FULL_VIEW:
196 widget = glade_xml_get_widget(xml, "button6");
197 g_signal_emit_by_name(widget, "clicked");
198 break;
199 }
Joachim Nilssonbafd2df2005-07-29 00:18:03 +0200200#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201 txtbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
202 tag1 = gtk_text_buffer_create_tag(txtbuf, "mytag1",
203 "foreground", "red",
204 "weight", PANGO_WEIGHT_BOLD,
205 NULL);
206 tag2 = gtk_text_buffer_create_tag(txtbuf, "mytag2",
207 /*"style", PANGO_STYLE_OBLIQUE, */
208 NULL);
209
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700210 sprintf(title, _("Linux Kernel v%s Configuration"),
Sam Ravnborg2244cbd2006-01-16 12:12:12 +0100211 getenv("KERNELVERSION"));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212 gtk_window_set_title(GTK_WINDOW(main_wnd), title);
213
214 gtk_widget_show(main_wnd);
215}
216
217void init_tree_model(void)
218{
219 gint i;
220
221 tree = tree2 = gtk_tree_store_new(COL_NUMBER,
222 G_TYPE_STRING, G_TYPE_STRING,
223 G_TYPE_STRING, G_TYPE_STRING,
224 G_TYPE_STRING, G_TYPE_STRING,
225 G_TYPE_POINTER, GDK_TYPE_COLOR,
226 G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF,
227 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
228 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
229 G_TYPE_BOOLEAN);
230 model2 = GTK_TREE_MODEL(tree2);
231
232 for (parents[0] = NULL, i = 1; i < 256; i++)
233 parents[i] = (GtkTreeIter *) g_malloc(sizeof(GtkTreeIter));
234
235 tree1 = gtk_tree_store_new(COL_NUMBER,
236 G_TYPE_STRING, G_TYPE_STRING,
237 G_TYPE_STRING, G_TYPE_STRING,
238 G_TYPE_STRING, G_TYPE_STRING,
239 G_TYPE_POINTER, GDK_TYPE_COLOR,
240 G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF,
241 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
242 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
243 G_TYPE_BOOLEAN);
244 model1 = GTK_TREE_MODEL(tree1);
245}
246
247void init_left_tree(void)
248{
249 GtkTreeView *view = GTK_TREE_VIEW(tree1_w);
250 GtkCellRenderer *renderer;
251 GtkTreeSelection *sel;
252 GtkTreeViewColumn *column;
253
254 gtk_tree_view_set_model(view, model1);
255 gtk_tree_view_set_headers_visible(view, TRUE);
256 gtk_tree_view_set_rules_hint(view, FALSE);
Joachim Nilssonbafd2df2005-07-29 00:18:03 +0200257
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258 column = gtk_tree_view_column_new();
259 gtk_tree_view_append_column(view, column);
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700260 gtk_tree_view_column_set_title(column, _("Options"));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261
262 renderer = gtk_cell_renderer_toggle_new();
263 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
264 renderer, FALSE);
265 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
266 renderer,
267 "active", COL_BTNACT,
268 "inconsistent", COL_BTNINC,
Joachim Nilssonbafd2df2005-07-29 00:18:03 +0200269 "visible", COL_BTNVIS,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270 "radio", COL_BTNRAD, NULL);
271 renderer = gtk_cell_renderer_text_new();
272 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
Joachim Nilssonbafd2df2005-07-29 00:18:03 +0200273 renderer, FALSE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
275 renderer,
276 "text", COL_OPTION,
277 "foreground-gdk",
278 COL_COLOR, NULL);
279
280 sel = gtk_tree_view_get_selection(view);
281 gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
282 gtk_widget_realize(tree1_w);
283}
284
285static void renderer_edited(GtkCellRendererText * cell,
286 const gchar * path_string,
287 const gchar * new_text, gpointer user_data);
288static void renderer_toggled(GtkCellRendererToggle * cellrenderertoggle,
289 gchar * arg1, gpointer user_data);
290
291void init_right_tree(void)
292{
293 GtkTreeView *view = GTK_TREE_VIEW(tree2_w);
294 GtkCellRenderer *renderer;
295 GtkTreeSelection *sel;
296 GtkTreeViewColumn *column;
297 gint i;
298
299 gtk_tree_view_set_model(view, model2);
300 gtk_tree_view_set_headers_visible(view, TRUE);
301 gtk_tree_view_set_rules_hint(view, FALSE);
302
303 column = gtk_tree_view_column_new();
304 gtk_tree_view_append_column(view, column);
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700305 gtk_tree_view_column_set_title(column, _("Options"));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306
307 renderer = gtk_cell_renderer_pixbuf_new();
308 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
309 renderer, FALSE);
310 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
311 renderer,
312 "pixbuf", COL_PIXBUF,
313 "visible", COL_PIXVIS, NULL);
314 renderer = gtk_cell_renderer_toggle_new();
315 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
316 renderer, FALSE);
317 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
318 renderer,
319 "active", COL_BTNACT,
320 "inconsistent", COL_BTNINC,
Joachim Nilssonbafd2df2005-07-29 00:18:03 +0200321 "visible", COL_BTNVIS,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322 "radio", COL_BTNRAD, NULL);
323 /*g_signal_connect(G_OBJECT(renderer), "toggled",
324 G_CALLBACK(renderer_toggled), NULL); */
325 renderer = gtk_cell_renderer_text_new();
326 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
327 renderer, FALSE);
328 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
329 renderer,
330 "text", COL_OPTION,
331 "foreground-gdk",
332 COL_COLOR, NULL);
333
334 renderer = gtk_cell_renderer_text_new();
335 gtk_tree_view_insert_column_with_attributes(view, -1,
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700336 _("Name"), renderer,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337 "text", COL_NAME,
338 "foreground-gdk",
339 COL_COLOR, NULL);
340 renderer = gtk_cell_renderer_text_new();
341 gtk_tree_view_insert_column_with_attributes(view, -1,
342 "N", renderer,
343 "text", COL_NO,
344 "foreground-gdk",
345 COL_COLOR, NULL);
346 renderer = gtk_cell_renderer_text_new();
347 gtk_tree_view_insert_column_with_attributes(view, -1,
348 "M", renderer,
349 "text", COL_MOD,
350 "foreground-gdk",
351 COL_COLOR, NULL);
352 renderer = gtk_cell_renderer_text_new();
353 gtk_tree_view_insert_column_with_attributes(view, -1,
354 "Y", renderer,
355 "text", COL_YES,
356 "foreground-gdk",
357 COL_COLOR, NULL);
358 renderer = gtk_cell_renderer_text_new();
359 gtk_tree_view_insert_column_with_attributes(view, -1,
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700360 _("Value"), renderer,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361 "text", COL_VALUE,
362 "editable",
363 COL_EDIT,
364 "foreground-gdk",
365 COL_COLOR, NULL);
366 g_signal_connect(G_OBJECT(renderer), "edited",
367 G_CALLBACK(renderer_edited), NULL);
368
369 column = gtk_tree_view_get_column(view, COL_NAME);
370 gtk_tree_view_column_set_visible(column, show_name);
371 column = gtk_tree_view_get_column(view, COL_NO);
372 gtk_tree_view_column_set_visible(column, show_range);
373 column = gtk_tree_view_get_column(view, COL_MOD);
374 gtk_tree_view_column_set_visible(column, show_range);
375 column = gtk_tree_view_get_column(view, COL_YES);
376 gtk_tree_view_column_set_visible(column, show_range);
377 column = gtk_tree_view_get_column(view, COL_VALUE);
378 gtk_tree_view_column_set_visible(column, show_value);
379
380 if (resizeable) {
381 for (i = 0; i < COL_VALUE; i++) {
382 column = gtk_tree_view_get_column(view, i);
383 gtk_tree_view_column_set_resizable(column, TRUE);
384 }
385 }
386
387 sel = gtk_tree_view_get_selection(view);
388 gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
389}
390
391
392/* Utility Functions */
393
394
395static void text_insert_help(struct menu *menu)
396{
397 GtkTextBuffer *buffer;
398 GtkTextIter start, end;
EGRY Gaborbb7ef392008-01-11 23:47:58 +0100399 const char *prompt = _(menu_get_prompt(menu));
Cheng Renquan47791052009-07-12 16:11:46 +0800400 struct gstr help = str_new();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401
Cheng Renquan47791052009-07-12 16:11:46 +0800402 menu_get_ext_help(menu, &help);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403
404 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
405 gtk_text_buffer_get_bounds(buffer, &start, &end);
406 gtk_text_buffer_delete(buffer, &start, &end);
407 gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15);
408
409 gtk_text_buffer_get_end_iter(buffer, &end);
410 gtk_text_buffer_insert_with_tags(buffer, &end, prompt, -1, tag1,
411 NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412 gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2);
413 gtk_text_buffer_get_end_iter(buffer, &end);
Cheng Renquan47791052009-07-12 16:11:46 +0800414 gtk_text_buffer_insert_with_tags(buffer, &end, str_get(&help), -1, tag2,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415 NULL);
Cheng Renquan47791052009-07-12 16:11:46 +0800416 str_free(&help);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417}
418
419
420static void text_insert_msg(const char *title, const char *message)
421{
422 GtkTextBuffer *buffer;
423 GtkTextIter start, end;
424 const char *msg = message;
425
426 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
427 gtk_text_buffer_get_bounds(buffer, &start, &end);
428 gtk_text_buffer_delete(buffer, &start, &end);
429 gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15);
430
431 gtk_text_buffer_get_end_iter(buffer, &end);
432 gtk_text_buffer_insert_with_tags(buffer, &end, title, -1, tag1,
433 NULL);
434 gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2);
435 gtk_text_buffer_get_end_iter(buffer, &end);
436 gtk_text_buffer_insert_with_tags(buffer, &end, msg, -1, tag2,
437 NULL);
438}
439
440
441/* Main Windows Callbacks */
442
Karsten Wiese0a0c5022006-12-13 00:34:09 -0800443void on_save_activate(GtkMenuItem * menuitem, gpointer user_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444gboolean on_window1_delete_event(GtkWidget * widget, GdkEvent * event,
445 gpointer user_data)
446{
447 GtkWidget *dialog, *label;
448 gint result;
449
Karsten Wiese0a0c5022006-12-13 00:34:09 -0800450 if (!conf_get_changed())
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451 return FALSE;
452
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700453 dialog = gtk_dialog_new_with_buttons(_("Warning !"),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454 GTK_WINDOW(main_wnd),
455 (GtkDialogFlags)
456 (GTK_DIALOG_MODAL |
457 GTK_DIALOG_DESTROY_WITH_PARENT),
458 GTK_STOCK_OK,
459 GTK_RESPONSE_YES,
460 GTK_STOCK_NO,
461 GTK_RESPONSE_NO,
462 GTK_STOCK_CANCEL,
463 GTK_RESPONSE_CANCEL, NULL);
464 gtk_dialog_set_default_response(GTK_DIALOG(dialog),
465 GTK_RESPONSE_CANCEL);
466
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700467 label = gtk_label_new(_("\nSave configuration ?\n"));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label);
469 gtk_widget_show(label);
470
471 result = gtk_dialog_run(GTK_DIALOG(dialog));
472 switch (result) {
473 case GTK_RESPONSE_YES:
Karsten Wiese0a0c5022006-12-13 00:34:09 -0800474 on_save_activate(NULL, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475 return FALSE;
476 case GTK_RESPONSE_NO:
477 return FALSE;
478 case GTK_RESPONSE_CANCEL:
479 case GTK_RESPONSE_DELETE_EVENT:
480 default:
481 gtk_widget_destroy(dialog);
482 return TRUE;
483 }
484
485 return FALSE;
486}
487
488
489void on_window1_destroy(GtkObject * object, gpointer user_data)
490{
491 gtk_main_quit();
492}
493
494
495void
496on_window1_size_request(GtkWidget * widget,
497 GtkRequisition * requisition, gpointer user_data)
498{
499 static gint old_h;
500 gint w, h;
501
502 if (widget->window == NULL)
503 gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h);
504 else
505 gdk_window_get_size(widget->window, &w, &h);
506
507 if (h == old_h)
508 return;
509 old_h = h;
510
511 gtk_paned_set_position(GTK_PANED(vpaned), 2 * h / 3);
512}
513
514
515/* Menu & Toolbar Callbacks */
516
517
518static void
519load_filename(GtkFileSelection * file_selector, gpointer user_data)
520{
521 const gchar *fn;
522
523 fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION
524 (user_data));
525
526 if (conf_read(fn))
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700527 text_insert_msg(_("Error"), _("Unable to load configuration !"));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528 else
529 display_tree(&rootmenu);
530}
531
532void on_load1_activate(GtkMenuItem * menuitem, gpointer user_data)
533{
534 GtkWidget *fs;
535
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700536 fs = gtk_file_selection_new(_("Load file..."));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537 g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button),
538 "clicked",
539 G_CALLBACK(load_filename), (gpointer) fs);
540 g_signal_connect_swapped(GTK_OBJECT
541 (GTK_FILE_SELECTION(fs)->ok_button),
542 "clicked", G_CALLBACK(gtk_widget_destroy),
543 (gpointer) fs);
544 g_signal_connect_swapped(GTK_OBJECT
545 (GTK_FILE_SELECTION(fs)->cancel_button),
546 "clicked", G_CALLBACK(gtk_widget_destroy),
547 (gpointer) fs);
548 gtk_widget_show(fs);
549}
550
551
Karsten Wiese0a0c5022006-12-13 00:34:09 -0800552void on_save_activate(GtkMenuItem * menuitem, gpointer user_data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553{
554 if (conf_write(NULL))
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700555 text_insert_msg(_("Error"), _("Unable to save configuration !"));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556}
557
558
559static void
560store_filename(GtkFileSelection * file_selector, gpointer user_data)
561{
562 const gchar *fn;
563
564 fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION
565 (user_data));
566
567 if (conf_write(fn))
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700568 text_insert_msg(_("Error"), _("Unable to save configuration !"));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569
570 gtk_widget_destroy(GTK_WIDGET(user_data));
571}
572
573void on_save_as1_activate(GtkMenuItem * menuitem, gpointer user_data)
574{
575 GtkWidget *fs;
576
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700577 fs = gtk_file_selection_new(_("Save file as..."));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700578 g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button),
579 "clicked",
580 G_CALLBACK(store_filename), (gpointer) fs);
581 g_signal_connect_swapped(GTK_OBJECT
582 (GTK_FILE_SELECTION(fs)->ok_button),
583 "clicked", G_CALLBACK(gtk_widget_destroy),
584 (gpointer) fs);
585 g_signal_connect_swapped(GTK_OBJECT
586 (GTK_FILE_SELECTION(fs)->cancel_button),
587 "clicked", G_CALLBACK(gtk_widget_destroy),
588 (gpointer) fs);
589 gtk_widget_show(fs);
590}
591
592
593void on_quit1_activate(GtkMenuItem * menuitem, gpointer user_data)
594{
595 if (!on_window1_delete_event(NULL, NULL, NULL))
596 gtk_widget_destroy(GTK_WIDGET(main_wnd));
597}
598
599
600void on_show_name1_activate(GtkMenuItem * menuitem, gpointer user_data)
601{
602 GtkTreeViewColumn *col;
603
604 show_name = GTK_CHECK_MENU_ITEM(menuitem)->active;
605 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NAME);
606 if (col)
607 gtk_tree_view_column_set_visible(col, show_name);
608}
609
610
611void on_show_range1_activate(GtkMenuItem * menuitem, gpointer user_data)
612{
613 GtkTreeViewColumn *col;
614
615 show_range = GTK_CHECK_MENU_ITEM(menuitem)->active;
616 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NO);
617 if (col)
618 gtk_tree_view_column_set_visible(col, show_range);
619 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_MOD);
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_YES);
623 if (col)
624 gtk_tree_view_column_set_visible(col, show_range);
625
626}
627
628
629void on_show_data1_activate(GtkMenuItem * menuitem, gpointer user_data)
630{
631 GtkTreeViewColumn *col;
632
633 show_value = GTK_CHECK_MENU_ITEM(menuitem)->active;
634 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_VALUE);
635 if (col)
636 gtk_tree_view_column_set_visible(col, show_value);
637}
638
639
640void
641on_show_all_options1_activate(GtkMenuItem * menuitem, gpointer user_data)
642{
643 show_all = GTK_CHECK_MENU_ITEM(menuitem)->active;
644
645 gtk_tree_store_clear(tree2);
646 display_tree(&rootmenu); // instead of update_tree to speed-up
647}
648
649
650void
651on_show_debug_info1_activate(GtkMenuItem * menuitem, gpointer user_data)
652{
653 show_debug = GTK_CHECK_MENU_ITEM(menuitem)->active;
654 update_tree(&rootmenu, NULL);
655}
656
657
658void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data)
659{
660 GtkWidget *dialog;
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700661 const gchar *intro_text = _(
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662 "Welcome to gkc, the GTK+ graphical kernel configuration tool\n"
663 "for Linux.\n"
664 "For each option, a blank box indicates the feature is disabled, a\n"
665 "check indicates it is enabled, and a dot indicates that it is to\n"
666 "be compiled as a module. Clicking on the box will cycle through the three states.\n"
667 "\n"
668 "If you do not see an option (e.g., a device driver) that you\n"
669 "believe should be present, try turning on Show All Options\n"
670 "under the Options menu.\n"
671 "Although there is no cross reference yet to help you figure out\n"
672 "what other options must be enabled to support the option you\n"
673 "are interested in, you can still view the help of a grayed-out\n"
674 "option.\n"
675 "\n"
676 "Toggling Show Debug Info under the Options menu will show \n"
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700677 "the dependencies, which you can then match by examining other options.");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678
679 dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
680 GTK_DIALOG_DESTROY_WITH_PARENT,
681 GTK_MESSAGE_INFO,
682 GTK_BUTTONS_CLOSE, intro_text);
683 g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
684 G_CALLBACK(gtk_widget_destroy),
685 GTK_OBJECT(dialog));
686 gtk_widget_show_all(dialog);
687}
688
689
690void on_about1_activate(GtkMenuItem * menuitem, gpointer user_data)
691{
692 GtkWidget *dialog;
693 const gchar *about_text =
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700694 _("gkc is copyright (c) 2002 Romain Lievin <roms@lpg.ticalc.org>.\n"
695 "Based on the source code from Roman Zippel.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696
697 dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
698 GTK_DIALOG_DESTROY_WITH_PARENT,
699 GTK_MESSAGE_INFO,
700 GTK_BUTTONS_CLOSE, about_text);
701 g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
702 G_CALLBACK(gtk_widget_destroy),
703 GTK_OBJECT(dialog));
704 gtk_widget_show_all(dialog);
705}
706
707
708void on_license1_activate(GtkMenuItem * menuitem, gpointer user_data)
709{
710 GtkWidget *dialog;
711 const gchar *license_text =
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700712 _("gkc is released under the terms of the GNU GPL v2.\n"
713 "For more information, please see the source code or\n"
714 "visit http://www.fsf.org/licenses/licenses.html\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700715
716 dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
717 GTK_DIALOG_DESTROY_WITH_PARENT,
718 GTK_MESSAGE_INFO,
719 GTK_BUTTONS_CLOSE, license_text);
720 g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
721 G_CALLBACK(gtk_widget_destroy),
722 GTK_OBJECT(dialog));
723 gtk_widget_show_all(dialog);
724}
725
726
Joachim Nilssonbafd2df2005-07-29 00:18:03 +0200727void on_back_clicked(GtkButton * button, gpointer user_data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728{
729 enum prop_type ptype;
730
731 current = current->parent;
732 ptype = current->prompt ? current->prompt->type : P_UNKNOWN;
733 if (ptype != P_MENU)
734 current = current->parent;
735 display_tree_part();
736
737 if (current == &rootmenu)
738 gtk_widget_set_sensitive(back_btn, FALSE);
739}
740
741
Joachim Nilssonbafd2df2005-07-29 00:18:03 +0200742void on_load_clicked(GtkButton * button, gpointer user_data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743{
744 on_load1_activate(NULL, user_data);
745}
746
747
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748void on_single_clicked(GtkButton * button, gpointer user_data)
749{
750 view_mode = SINGLE_VIEW;
751 gtk_paned_set_position(GTK_PANED(hpaned), 0);
752 gtk_widget_hide(tree1_w);
753 current = &rootmenu;
754 display_tree_part();
755}
756
757
758void on_split_clicked(GtkButton * button, gpointer user_data)
759{
760 gint w, h;
761 view_mode = SPLIT_VIEW;
762 gtk_widget_show(tree1_w);
763 gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h);
764 gtk_paned_set_position(GTK_PANED(hpaned), w / 2);
Joachim Nilssonbafd2df2005-07-29 00:18:03 +0200765 if (tree2)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766 gtk_tree_store_clear(tree2);
767 display_list();
Joachim Nilssonbafd2df2005-07-29 00:18:03 +0200768
769 /* Disable back btn, like in full mode. */
770 gtk_widget_set_sensitive(back_btn, FALSE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771}
772
773
774void on_full_clicked(GtkButton * button, gpointer user_data)
775{
776 view_mode = FULL_VIEW;
777 gtk_paned_set_position(GTK_PANED(hpaned), 0);
778 gtk_widget_hide(tree1_w);
779 if (tree2)
780 gtk_tree_store_clear(tree2);
781 display_tree(&rootmenu);
782 gtk_widget_set_sensitive(back_btn, FALSE);
783}
784
785
Joachim Nilssonbafd2df2005-07-29 00:18:03 +0200786void on_collapse_clicked(GtkButton * button, gpointer user_data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787{
788 gtk_tree_view_collapse_all(GTK_TREE_VIEW(tree2_w));
789}
790
791
Joachim Nilssonbafd2df2005-07-29 00:18:03 +0200792void on_expand_clicked(GtkButton * button, gpointer user_data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700793{
794 gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w));
795}
796
797
798/* CTree Callbacks */
799
800/* Change hex/int/string value in the cell */
801static void renderer_edited(GtkCellRendererText * cell,
802 const gchar * path_string,
803 const gchar * new_text, gpointer user_data)
804{
805 GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
806 GtkTreeIter iter;
807 const char *old_def, *new_def;
808 struct menu *menu;
809 struct symbol *sym;
810
811 if (!gtk_tree_model_get_iter(model2, &iter, path))
812 return;
813
814 gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
815 sym = menu->sym;
816
817 gtk_tree_model_get(model2, &iter, COL_VALUE, &old_def, -1);
818 new_def = new_text;
819
820 sym_set_string_value(sym, new_def);
821
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822 update_tree(&rootmenu, NULL);
823
824 gtk_tree_path_free(path);
825}
826
827/* Change the value of a symbol and update the tree */
828static void change_sym_value(struct menu *menu, gint col)
829{
830 struct symbol *sym = menu->sym;
831 tristate oldval, newval;
832
833 if (!sym)
834 return;
835
836 if (col == COL_NO)
837 newval = no;
838 else if (col == COL_MOD)
839 newval = mod;
840 else if (col == COL_YES)
841 newval = yes;
842 else
843 return;
844
845 switch (sym_get_type(sym)) {
846 case S_BOOLEAN:
847 case S_TRISTATE:
848 oldval = sym_get_tristate_value(sym);
849 if (!sym_tristate_within_range(sym, newval))
850 newval = yes;
851 sym_set_tristate_value(sym, newval);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852 if (view_mode == FULL_VIEW)
853 update_tree(&rootmenu, NULL);
854 else if (view_mode == SPLIT_VIEW) {
855 update_tree(browsed, NULL);
856 display_list();
857 }
858 else if (view_mode == SINGLE_VIEW)
859 display_tree_part(); //fixme: keep exp/coll
860 break;
861 case S_INT:
862 case S_HEX:
863 case S_STRING:
864 default:
865 break;
866 }
867}
868
869static void toggle_sym_value(struct menu *menu)
870{
871 if (!menu->sym)
872 return;
873
874 sym_toggle_tristate_value(menu->sym);
875 if (view_mode == FULL_VIEW)
876 update_tree(&rootmenu, NULL);
877 else if (view_mode == SPLIT_VIEW) {
878 update_tree(browsed, NULL);
879 display_list();
880 }
881 else if (view_mode == SINGLE_VIEW)
882 display_tree_part(); //fixme: keep exp/coll
883}
884
885static void renderer_toggled(GtkCellRendererToggle * cell,
886 gchar * path_string, gpointer user_data)
887{
888 GtkTreePath *path, *sel_path = NULL;
889 GtkTreeIter iter, sel_iter;
890 GtkTreeSelection *sel;
891 struct menu *menu;
892
893 path = gtk_tree_path_new_from_string(path_string);
894 if (!gtk_tree_model_get_iter(model2, &iter, path))
895 return;
896
897 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree2_w));
898 if (gtk_tree_selection_get_selected(sel, NULL, &sel_iter))
899 sel_path = gtk_tree_model_get_path(model2, &sel_iter);
900 if (!sel_path)
901 goto out1;
902 if (gtk_tree_path_compare(path, sel_path))
903 goto out2;
904
905 gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
906 toggle_sym_value(menu);
907
908 out2:
909 gtk_tree_path_free(sel_path);
910 out1:
911 gtk_tree_path_free(path);
912}
913
914static gint column2index(GtkTreeViewColumn * column)
915{
916 gint i;
917
918 for (i = 0; i < COL_NUMBER; i++) {
919 GtkTreeViewColumn *col;
920
921 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), i);
922 if (col == column)
923 return i;
924 }
925
926 return -1;
927}
928
929
930/* User click: update choice (full) or goes down (single) */
931gboolean
932on_treeview2_button_press_event(GtkWidget * widget,
933 GdkEventButton * event, gpointer user_data)
934{
935 GtkTreeView *view = GTK_TREE_VIEW(widget);
936 GtkTreePath *path;
937 GtkTreeViewColumn *column;
938 GtkTreeIter iter;
939 struct menu *menu;
940 gint col;
941
942#if GTK_CHECK_VERSION(2,1,4) // bug in ctree with earlier version of GTK
943 gint tx = (gint) event->x;
944 gint ty = (gint) event->y;
945 gint cx, cy;
946
947 gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx,
948 &cy);
949#else
950 gtk_tree_view_get_cursor(view, &path, &column);
951#endif
952 if (path == NULL)
953 return FALSE;
954
955 if (!gtk_tree_model_get_iter(model2, &iter, path))
956 return FALSE;
957 gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
958
959 col = column2index(column);
960 if (event->type == GDK_2BUTTON_PRESS) {
961 enum prop_type ptype;
962 ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
963
964 if (ptype == P_MENU && view_mode != FULL_VIEW && col == COL_OPTION) {
965 // goes down into menu
966 current = menu;
967 display_tree_part();
968 gtk_widget_set_sensitive(back_btn, TRUE);
969 } else if ((col == COL_OPTION)) {
970 toggle_sym_value(menu);
971 gtk_tree_view_expand_row(view, path, TRUE);
972 }
973 } else {
974 if (col == COL_VALUE) {
975 toggle_sym_value(menu);
976 gtk_tree_view_expand_row(view, path, TRUE);
977 } else if (col == COL_NO || col == COL_MOD
978 || col == COL_YES) {
979 change_sym_value(menu, col);
980 gtk_tree_view_expand_row(view, path, TRUE);
981 }
982 }
983
984 return FALSE;
985}
986
987/* Key pressed: update choice */
988gboolean
989on_treeview2_key_press_event(GtkWidget * widget,
990 GdkEventKey * event, gpointer user_data)
991{
992 GtkTreeView *view = GTK_TREE_VIEW(widget);
993 GtkTreePath *path;
994 GtkTreeViewColumn *column;
995 GtkTreeIter iter;
996 struct menu *menu;
997 gint col;
998
999 gtk_tree_view_get_cursor(view, &path, &column);
1000 if (path == NULL)
1001 return FALSE;
1002
1003 if (event->keyval == GDK_space) {
1004 if (gtk_tree_view_row_expanded(view, path))
1005 gtk_tree_view_collapse_row(view, path);
1006 else
1007 gtk_tree_view_expand_row(view, path, FALSE);
1008 return TRUE;
1009 }
1010 if (event->keyval == GDK_KP_Enter) {
1011 }
1012 if (widget == tree1_w)
1013 return FALSE;
1014
1015 gtk_tree_model_get_iter(model2, &iter, path);
1016 gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
1017
1018 if (!strcasecmp(event->string, "n"))
1019 col = COL_NO;
1020 else if (!strcasecmp(event->string, "m"))
1021 col = COL_MOD;
1022 else if (!strcasecmp(event->string, "y"))
1023 col = COL_YES;
1024 else
1025 col = -1;
1026 change_sym_value(menu, col);
1027
1028 return FALSE;
1029}
1030
1031
1032/* Row selection changed: update help */
1033void
1034on_treeview2_cursor_changed(GtkTreeView * treeview, gpointer user_data)
1035{
1036 GtkTreeSelection *selection;
1037 GtkTreeIter iter;
1038 struct menu *menu;
1039
1040 selection = gtk_tree_view_get_selection(treeview);
1041 if (gtk_tree_selection_get_selected(selection, &model2, &iter)) {
1042 gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
1043 text_insert_help(menu);
1044 }
1045}
1046
1047
1048/* User click: display sub-tree in the right frame. */
1049gboolean
1050on_treeview1_button_press_event(GtkWidget * widget,
1051 GdkEventButton * event, gpointer user_data)
1052{
1053 GtkTreeView *view = GTK_TREE_VIEW(widget);
1054 GtkTreePath *path;
1055 GtkTreeViewColumn *column;
1056 GtkTreeIter iter;
1057 struct menu *menu;
1058
1059 gint tx = (gint) event->x;
1060 gint ty = (gint) event->y;
1061 gint cx, cy;
1062
1063 gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx,
1064 &cy);
1065 if (path == NULL)
1066 return FALSE;
1067
1068 gtk_tree_model_get_iter(model1, &iter, path);
1069 gtk_tree_model_get(model1, &iter, COL_MENU, &menu, -1);
1070
1071 if (event->type == GDK_2BUTTON_PRESS) {
1072 toggle_sym_value(menu);
1073 current = menu;
1074 display_tree_part();
1075 } else {
1076 browsed = menu;
1077 display_tree_part();
1078 }
1079
1080 gtk_widget_realize(tree2_w);
1081 gtk_tree_view_set_cursor(view, path, NULL, FALSE);
1082 gtk_widget_grab_focus(tree2_w);
1083
1084 return FALSE;
1085}
1086
1087
1088/* Fill a row of strings */
1089static gchar **fill_row(struct menu *menu)
1090{
1091 static gchar *row[COL_NUMBER];
1092 struct symbol *sym = menu->sym;
1093 const char *def;
1094 int stype;
1095 tristate val;
1096 enum prop_type ptype;
1097 int i;
1098
1099 for (i = COL_OPTION; i <= COL_COLOR; i++)
1100 g_free(row[i]);
1101 bzero(row, sizeof(row));
1102
1103 row[COL_OPTION] =
EGRY Gaborbb7ef392008-01-11 23:47:58 +01001104 g_strdup_printf("%s %s", _(menu_get_prompt(menu)),
Roman Zippel669bfad2006-06-08 22:12:42 -07001105 sym && sym_has_value(sym) ? "(NEW)" : "");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106
1107 if (show_all && !menu_is_visible(menu))
1108 row[COL_COLOR] = g_strdup("DarkGray");
1109 else
1110 row[COL_COLOR] = g_strdup("Black");
1111
1112 ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
1113 switch (ptype) {
1114 case P_MENU:
1115 row[COL_PIXBUF] = (gchar *) xpm_menu;
1116 if (view_mode == SINGLE_VIEW)
1117 row[COL_PIXVIS] = GINT_TO_POINTER(TRUE);
1118 row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
1119 break;
1120 case P_COMMENT:
1121 row[COL_PIXBUF] = (gchar *) xpm_void;
1122 row[COL_PIXVIS] = GINT_TO_POINTER(FALSE);
1123 row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
1124 break;
1125 default:
1126 row[COL_PIXBUF] = (gchar *) xpm_void;
1127 row[COL_PIXVIS] = GINT_TO_POINTER(FALSE);
1128 row[COL_BTNVIS] = GINT_TO_POINTER(TRUE);
1129 break;
1130 }
1131
1132 if (!sym)
1133 return row;
1134 row[COL_NAME] = g_strdup(sym->name);
1135
1136 sym_calc_value(sym);
1137 sym->flags &= ~SYMBOL_CHANGED;
1138
1139 if (sym_is_choice(sym)) { // parse childs for getting final value
1140 struct menu *child;
1141 struct symbol *def_sym = sym_get_choice_value(sym);
1142 struct menu *def_menu = NULL;
1143
1144 row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
1145
1146 for (child = menu->list; child; child = child->next) {
1147 if (menu_is_visible(child)
1148 && child->sym == def_sym)
1149 def_menu = child;
1150 }
1151
1152 if (def_menu)
1153 row[COL_VALUE] =
EGRY Gaborbb7ef392008-01-11 23:47:58 +01001154 g_strdup(_(menu_get_prompt(def_menu)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001155 }
Joachim Nilssonbafd2df2005-07-29 00:18:03 +02001156 if (sym->flags & SYMBOL_CHOICEVAL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157 row[COL_BTNRAD] = GINT_TO_POINTER(TRUE);
1158
1159 stype = sym_get_type(sym);
1160 switch (stype) {
1161 case S_BOOLEAN:
Joachim Nilssonbafd2df2005-07-29 00:18:03 +02001162 if (GPOINTER_TO_INT(row[COL_PIXVIS]) == FALSE)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163 row[COL_BTNVIS] = GINT_TO_POINTER(TRUE);
1164 if (sym_is_choice(sym))
1165 break;
1166 case S_TRISTATE:
1167 val = sym_get_tristate_value(sym);
1168 switch (val) {
1169 case no:
1170 row[COL_NO] = g_strdup("N");
1171 row[COL_VALUE] = g_strdup("N");
1172 row[COL_BTNACT] = GINT_TO_POINTER(FALSE);
1173 row[COL_BTNINC] = GINT_TO_POINTER(FALSE);
1174 break;
1175 case mod:
1176 row[COL_MOD] = g_strdup("M");
1177 row[COL_VALUE] = g_strdup("M");
1178 row[COL_BTNINC] = GINT_TO_POINTER(TRUE);
1179 break;
1180 case yes:
1181 row[COL_YES] = g_strdup("Y");
1182 row[COL_VALUE] = g_strdup("Y");
1183 row[COL_BTNACT] = GINT_TO_POINTER(TRUE);
1184 row[COL_BTNINC] = GINT_TO_POINTER(FALSE);
1185 break;
1186 }
1187
1188 if (val != no && sym_tristate_within_range(sym, no))
1189 row[COL_NO] = g_strdup("_");
1190 if (val != mod && sym_tristate_within_range(sym, mod))
1191 row[COL_MOD] = g_strdup("_");
1192 if (val != yes && sym_tristate_within_range(sym, yes))
1193 row[COL_YES] = g_strdup("_");
1194 break;
1195 case S_INT:
1196 case S_HEX:
1197 case S_STRING:
1198 def = sym_get_string_value(sym);
1199 row[COL_VALUE] = g_strdup(def);
1200 row[COL_EDIT] = GINT_TO_POINTER(TRUE);
1201 row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
1202 break;
1203 }
1204
1205 return row;
1206}
1207
1208
1209/* Set the node content with a row of strings */
1210static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row)
1211{
1212 GdkColor color;
1213 gboolean success;
1214 GdkPixbuf *pix;
1215
1216 pix = gdk_pixbuf_new_from_xpm_data((const char **)
1217 row[COL_PIXBUF]);
1218
1219 gdk_color_parse(row[COL_COLOR], &color);
1220 gdk_colormap_alloc_colors(gdk_colormap_get_system(), &color, 1,
1221 FALSE, FALSE, &success);
1222
1223 gtk_tree_store_set(tree, node,
1224 COL_OPTION, row[COL_OPTION],
1225 COL_NAME, row[COL_NAME],
1226 COL_NO, row[COL_NO],
1227 COL_MOD, row[COL_MOD],
1228 COL_YES, row[COL_YES],
1229 COL_VALUE, row[COL_VALUE],
1230 COL_MENU, (gpointer) menu,
1231 COL_COLOR, &color,
1232 COL_EDIT, GPOINTER_TO_INT(row[COL_EDIT]),
1233 COL_PIXBUF, pix,
1234 COL_PIXVIS, GPOINTER_TO_INT(row[COL_PIXVIS]),
1235 COL_BTNVIS, GPOINTER_TO_INT(row[COL_BTNVIS]),
1236 COL_BTNACT, GPOINTER_TO_INT(row[COL_BTNACT]),
1237 COL_BTNINC, GPOINTER_TO_INT(row[COL_BTNINC]),
1238 COL_BTNRAD, GPOINTER_TO_INT(row[COL_BTNRAD]),
1239 -1);
1240
1241 g_object_unref(pix);
1242}
1243
1244
1245/* Add a node to the tree */
1246static void place_node(struct menu *menu, char **row)
1247{
1248 GtkTreeIter *parent = parents[indent - 1];
1249 GtkTreeIter *node = parents[indent];
1250
1251 gtk_tree_store_append(tree, node, parent);
1252 set_node(node, menu, row);
1253}
1254
1255
1256/* Find a node in the GTK+ tree */
1257static GtkTreeIter found;
1258
1259/*
1260 * Find a menu in the GtkTree starting at parent.
1261 */
1262GtkTreeIter *gtktree_iter_find_node(GtkTreeIter * parent,
1263 struct menu *tofind)
1264{
1265 GtkTreeIter iter;
1266 GtkTreeIter *child = &iter;
1267 gboolean valid;
1268 GtkTreeIter *ret;
1269
1270 valid = gtk_tree_model_iter_children(model2, child, parent);
1271 while (valid) {
1272 struct menu *menu;
1273
1274 gtk_tree_model_get(model2, child, 6, &menu, -1);
1275
1276 if (menu == tofind) {
1277 memcpy(&found, child, sizeof(GtkTreeIter));
1278 return &found;
1279 }
1280
1281 ret = gtktree_iter_find_node(child, tofind);
1282 if (ret)
1283 return ret;
1284
1285 valid = gtk_tree_model_iter_next(model2, child);
1286 }
1287
1288 return NULL;
1289}
1290
1291
1292/*
1293 * Update the tree by adding/removing entries
1294 * Does not change other nodes
1295 */
1296static void update_tree(struct menu *src, GtkTreeIter * dst)
1297{
1298 struct menu *child1;
1299 GtkTreeIter iter, tmp;
1300 GtkTreeIter *child2 = &iter;
1301 gboolean valid;
1302 GtkTreeIter *sibling;
1303 struct symbol *sym;
1304 struct property *prop;
1305 struct menu *menu1, *menu2;
1306
1307 if (src == &rootmenu)
1308 indent = 1;
1309
1310 valid = gtk_tree_model_iter_children(model2, child2, dst);
1311 for (child1 = src->list; child1; child1 = child1->next) {
1312
1313 prop = child1->prompt;
1314 sym = child1->sym;
1315
1316 reparse:
1317 menu1 = child1;
1318 if (valid)
1319 gtk_tree_model_get(model2, child2, COL_MENU,
1320 &menu2, -1);
1321 else
1322 menu2 = NULL; // force adding of a first child
1323
1324#ifdef DEBUG
1325 printf("%*c%s | %s\n", indent, ' ',
1326 menu1 ? menu_get_prompt(menu1) : "nil",
1327 menu2 ? menu_get_prompt(menu2) : "nil");
1328#endif
1329
1330 if (!menu_is_visible(child1) && !show_all) { // remove node
1331 if (gtktree_iter_find_node(dst, menu1) != NULL) {
1332 memcpy(&tmp, child2, sizeof(GtkTreeIter));
1333 valid = gtk_tree_model_iter_next(model2,
1334 child2);
1335 gtk_tree_store_remove(tree2, &tmp);
1336 if (!valid)
Joachim Nilssonbafd2df2005-07-29 00:18:03 +02001337 return; // next parent
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338 else
1339 goto reparse; // next child
1340 } else
1341 continue;
1342 }
1343
1344 if (menu1 != menu2) {
1345 if (gtktree_iter_find_node(dst, menu1) == NULL) { // add node
1346 if (!valid && !menu2)
1347 sibling = NULL;
1348 else
1349 sibling = child2;
1350 gtk_tree_store_insert_before(tree2,
1351 child2,
1352 dst, sibling);
1353 set_node(child2, menu1, fill_row(menu1));
1354 if (menu2 == NULL)
1355 valid = TRUE;
1356 } else { // remove node
1357 memcpy(&tmp, child2, sizeof(GtkTreeIter));
1358 valid = gtk_tree_model_iter_next(model2,
1359 child2);
1360 gtk_tree_store_remove(tree2, &tmp);
1361 if (!valid)
Joachim Nilssonbafd2df2005-07-29 00:18:03 +02001362 return; // next parent
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363 else
1364 goto reparse; // next child
1365 }
1366 } else if (sym && (sym->flags & SYMBOL_CHANGED)) {
1367 set_node(child2, menu1, fill_row(menu1));
1368 }
1369
1370 indent++;
1371 update_tree(child1, child2);
1372 indent--;
1373
1374 valid = gtk_tree_model_iter_next(model2, child2);
1375 }
1376}
1377
1378
1379/* Display the whole tree (single/split/full view) */
1380static void display_tree(struct menu *menu)
1381{
1382 struct symbol *sym;
1383 struct property *prop;
1384 struct menu *child;
1385 enum prop_type ptype;
1386
1387 if (menu == &rootmenu) {
1388 indent = 1;
1389 current = &rootmenu;
1390 }
1391
1392 for (child = menu->list; child; child = child->next) {
1393 prop = child->prompt;
1394 sym = child->sym;
1395 ptype = prop ? prop->type : P_UNKNOWN;
1396
1397 if (sym)
1398 sym->flags &= ~SYMBOL_CHANGED;
1399
Joachim Nilssonbafd2df2005-07-29 00:18:03 +02001400 if ((view_mode == SPLIT_VIEW)
1401 && !(child->flags & MENU_ROOT) && (tree == tree1))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001402 continue;
1403
Joachim Nilssonbafd2df2005-07-29 00:18:03 +02001404 if ((view_mode == SPLIT_VIEW) && (child->flags & MENU_ROOT)
1405 && (tree == tree2))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001406 continue;
1407
1408 if (menu_is_visible(child) || show_all)
1409 place_node(child, fill_row(child));
1410#ifdef DEBUG
1411 printf("%*c%s: ", indent, ' ', menu_get_prompt(child));
1412 printf("%s", child->flags & MENU_ROOT ? "rootmenu | " : "");
Li Zefan29442352010-04-14 11:44:34 +08001413 printf("%s", prop_get_type_name(ptype));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414 printf(" | ");
1415 if (sym) {
Li Zefan29442352010-04-14 11:44:34 +08001416 printf("%s", sym_type_name(sym->type));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417 printf(" | ");
Li Zefan29442352010-04-14 11:44:34 +08001418 printf("%s", dbg_sym_flags(sym->flags));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001419 printf("\n");
1420 } else
1421 printf("\n");
1422#endif
1423 if ((view_mode != FULL_VIEW) && (ptype == P_MENU)
1424 && (tree == tree2))
1425 continue;
1426/*
Joachim Nilssonbafd2df2005-07-29 00:18:03 +02001427 if (((menu != &rootmenu) && !(menu->flags & MENU_ROOT))
1428 || (view_mode == FULL_VIEW)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001429 || (view_mode == SPLIT_VIEW))*/
1430 if (((view_mode == SINGLE_VIEW) && (menu->flags & MENU_ROOT))
Joachim Nilssonbafd2df2005-07-29 00:18:03 +02001431 || (view_mode == FULL_VIEW)
1432 || (view_mode == SPLIT_VIEW)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001433 indent++;
1434 display_tree(child);
1435 indent--;
1436 }
1437 }
1438}
1439
1440/* Display a part of the tree starting at current node (single/split view) */
1441static void display_tree_part(void)
1442{
1443 if (tree2)
1444 gtk_tree_store_clear(tree2);
Joachim Nilssonbafd2df2005-07-29 00:18:03 +02001445 if (view_mode == SINGLE_VIEW)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001446 display_tree(current);
Joachim Nilssonbafd2df2005-07-29 00:18:03 +02001447 else if (view_mode == SPLIT_VIEW)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001448 display_tree(browsed);
1449 gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w));
1450}
1451
1452/* Display the list in the left frame (split view) */
1453static void display_list(void)
1454{
1455 if (tree1)
1456 gtk_tree_store_clear(tree1);
1457
1458 tree = tree1;
1459 display_tree(&rootmenu);
1460 gtk_tree_view_expand_all(GTK_TREE_VIEW(tree1_w));
1461 tree = tree2;
1462}
1463
1464void fixup_rootmenu(struct menu *menu)
1465{
Joachim Nilssonbafd2df2005-07-29 00:18:03 +02001466 struct menu *child;
1467 static int menu_cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468
Joachim Nilssonbafd2df2005-07-29 00:18:03 +02001469 menu->flags |= MENU_ROOT;
1470 for (child = menu->list; child; child = child->next) {
1471 if (child->prompt && child->prompt->type == P_MENU) {
1472 menu_cnt++;
1473 fixup_rootmenu(child);
1474 menu_cnt--;
1475 } else if (!menu_cnt)
1476 fixup_rootmenu(child);
1477 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001478}
1479
1480
1481/* Main */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001482int main(int ac, char *av[])
1483{
1484 const char *name;
1485 char *env;
1486 gchar *glade_file;
1487
1488#ifndef LKC_DIRECT_LINK
1489 kconfig_load();
1490#endif
1491
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -07001492 bindtextdomain(PACKAGE, LOCALEDIR);
1493 bind_textdomain_codeset(PACKAGE, "UTF-8");
1494 textdomain(PACKAGE);
1495
Linus Torvalds1da177e2005-04-16 15:20:36 -07001496 /* GTK stuffs */
1497 gtk_set_locale();
1498 gtk_init(&ac, &av);
1499 glade_init();
1500
1501 //add_pixmap_directory (PACKAGE_DATA_DIR "/" PACKAGE "/pixmaps");
1502 //add_pixmap_directory (PACKAGE_SOURCE_DIR "/pixmaps");
1503
1504 /* Determine GUI path */
1505 env = getenv(SRCTREE);
1506 if (env)
1507 glade_file = g_strconcat(env, "/scripts/kconfig/gconf.glade", NULL);
1508 else if (av[0][0] == '/')
1509 glade_file = g_strconcat(av[0], ".glade", NULL);
1510 else
1511 glade_file = g_strconcat(g_get_current_dir(), "/", av[0], ".glade", NULL);
1512
1513 /* Load the interface and connect signals */
1514 init_main_window(glade_file);
1515 init_tree_model();
1516 init_left_tree();
1517 init_right_tree();
1518
1519 /* Conf stuffs */
1520 if (ac > 1 && av[1][0] == '-') {
1521 switch (av[1][1]) {
1522 case 'a':
1523 //showAll = 1;
1524 break;
1525 case 'h':
1526 case '?':
1527 printf("%s <config>\n", av[0]);
1528 exit(0);
1529 }
1530 name = av[2];
1531 } else
1532 name = av[1];
1533
1534 conf_parse(name);
1535 fixup_rootmenu(&rootmenu);
1536 conf_read(NULL);
1537
1538 switch (view_mode) {
1539 case SINGLE_VIEW:
1540 display_tree_part();
1541 break;
1542 case SPLIT_VIEW:
1543 display_list();
1544 break;
1545 case FULL_VIEW:
1546 display_tree(&rootmenu);
1547 break;
1548 }
1549
1550 gtk_main();
1551
1552 return 0;
1553}
Karsten Wiese0a0c5022006-12-13 00:34:09 -08001554
1555static void conf_changed(void)
1556{
1557 bool changed = conf_get_changed();
1558 gtk_widget_set_sensitive(save_btn, changed);
1559 gtk_widget_set_sensitive(save_menu_item, changed);
1560}