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