~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/scripts/kconfig/gconf.c

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php