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