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