0001
0002
0003
0004
0005
0006 #include <stdlib.h>
0007 #include "lkc.h"
0008 #include "images.h"
0009
0010 #include <glade/glade.h>
0011 #include <gtk/gtk.h>
0012 #include <glib.h>
0013 #include <gdk/gdkkeysyms.h>
0014
0015 #include <stdio.h>
0016 #include <string.h>
0017 #include <strings.h>
0018 #include <unistd.h>
0019 #include <time.h>
0020
0021
0022
0023 enum {
0024 SINGLE_VIEW, SPLIT_VIEW, FULL_VIEW
0025 };
0026
0027 enum {
0028 OPT_NORMAL, OPT_ALL, OPT_PROMPT
0029 };
0030
0031 static gint view_mode = FULL_VIEW;
0032 static gboolean show_name = TRUE;
0033 static gboolean show_range = TRUE;
0034 static gboolean show_value = TRUE;
0035 static gboolean resizeable = FALSE;
0036 static int opt_mode = OPT_NORMAL;
0037
0038 GtkWidget *main_wnd = NULL;
0039 GtkWidget *tree1_w = NULL;
0040 GtkWidget *tree2_w = NULL;
0041 GtkWidget *text_w = NULL;
0042 GtkWidget *hpaned = NULL;
0043 GtkWidget *vpaned = NULL;
0044 GtkWidget *back_btn = NULL;
0045 GtkWidget *save_btn = NULL;
0046 GtkWidget *save_menu_item = NULL;
0047
0048 GtkTextTag *tag1, *tag2;
0049 GdkColor color;
0050
0051 GtkTreeStore *tree1, *tree2, *tree;
0052 GtkTreeModel *model1, *model2;
0053 static GtkTreeIter *parents[256];
0054 static gint indent;
0055
0056 static struct menu *current;
0057 static struct menu *browsed;
0058
0059 enum {
0060 COL_OPTION, COL_NAME, COL_NO, COL_MOD, COL_YES, COL_VALUE,
0061 COL_MENU, COL_COLOR, COL_EDIT, COL_PIXBUF,
0062 COL_PIXVIS, COL_BTNVIS, COL_BTNACT, COL_BTNINC, COL_BTNRAD,
0063 COL_NUMBER
0064 };
0065
0066 static void display_list(void);
0067 static void display_tree(struct menu *menu);
0068 static void display_tree_part(void);
0069 static void update_tree(struct menu *src, GtkTreeIter * dst);
0070 static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row);
0071 static gchar **fill_row(struct menu *menu);
0072 static void conf_changed(void);
0073
0074
0075 #ifdef DEBUG
0076 static const char *dbg_sym_flags(int val)
0077 {
0078 static char buf[256];
0079
0080 bzero(buf, 256);
0081
0082 if (val & SYMBOL_CONST)
0083 strcat(buf, "const/");
0084 if (val & SYMBOL_CHECK)
0085 strcat(buf, "check/");
0086 if (val & SYMBOL_CHOICE)
0087 strcat(buf, "choice/");
0088 if (val & SYMBOL_CHOICEVAL)
0089 strcat(buf, "choiceval/");
0090 if (val & SYMBOL_VALID)
0091 strcat(buf, "valid/");
0092 if (val & SYMBOL_OPTIONAL)
0093 strcat(buf, "optional/");
0094 if (val & SYMBOL_WRITE)
0095 strcat(buf, "write/");
0096 if (val & SYMBOL_CHANGED)
0097 strcat(buf, "changed/");
0098 if (val & SYMBOL_NO_WRITE)
0099 strcat(buf, "no_write/");
0100
0101 buf[strlen(buf) - 1] = '\0';
0102
0103 return buf;
0104 }
0105 #endif
0106
0107 static void replace_button_icon(GladeXML *xml, GdkDrawable *window,
0108 GtkStyle *style, gchar *btn_name, gchar **xpm)
0109 {
0110 GdkPixmap *pixmap;
0111 GdkBitmap *mask;
0112 GtkToolButton *button;
0113 GtkWidget *image;
0114
0115 pixmap = gdk_pixmap_create_from_xpm_d(window, &mask,
0116 &style->bg[GTK_STATE_NORMAL],
0117 xpm);
0118
0119 button = GTK_TOOL_BUTTON(glade_xml_get_widget(xml, btn_name));
0120 image = gtk_image_new_from_pixmap(pixmap, mask);
0121 gtk_widget_show(image);
0122 gtk_tool_button_set_icon_widget(button, image);
0123 }
0124
0125
0126 static void init_main_window(const gchar *glade_file)
0127 {
0128 GladeXML *xml;
0129 GtkWidget *widget;
0130 GtkTextBuffer *txtbuf;
0131 GtkStyle *style;
0132
0133 xml = glade_xml_new(glade_file, "window1", NULL);
0134 if (!xml)
0135 g_error("GUI loading failed !\n");
0136 glade_xml_signal_autoconnect(xml);
0137
0138 main_wnd = glade_xml_get_widget(xml, "window1");
0139 hpaned = glade_xml_get_widget(xml, "hpaned1");
0140 vpaned = glade_xml_get_widget(xml, "vpaned1");
0141 tree1_w = glade_xml_get_widget(xml, "treeview1");
0142 tree2_w = glade_xml_get_widget(xml, "treeview2");
0143 text_w = glade_xml_get_widget(xml, "textview3");
0144
0145 back_btn = glade_xml_get_widget(xml, "button1");
0146 gtk_widget_set_sensitive(back_btn, FALSE);
0147
0148 widget = glade_xml_get_widget(xml, "show_name1");
0149 gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
0150 show_name);
0151
0152 widget = glade_xml_get_widget(xml, "show_range1");
0153 gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
0154 show_range);
0155
0156 widget = glade_xml_get_widget(xml, "show_data1");
0157 gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
0158 show_value);
0159
0160 save_btn = glade_xml_get_widget(xml, "button3");
0161 save_menu_item = glade_xml_get_widget(xml, "save1");
0162 conf_set_changed_callback(conf_changed);
0163
0164 style = gtk_widget_get_style(main_wnd);
0165 widget = glade_xml_get_widget(xml, "toolbar1");
0166
0167 replace_button_icon(xml, main_wnd->window, style,
0168 "button4", (gchar **) xpm_single_view);
0169 replace_button_icon(xml, main_wnd->window, style,
0170 "button5", (gchar **) xpm_split_view);
0171 replace_button_icon(xml, main_wnd->window, style,
0172 "button6", (gchar **) xpm_tree_view);
0173
0174 txtbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
0175 tag1 = gtk_text_buffer_create_tag(txtbuf, "mytag1",
0176 "foreground", "red",
0177 "weight", PANGO_WEIGHT_BOLD,
0178 NULL);
0179 tag2 = gtk_text_buffer_create_tag(txtbuf, "mytag2",
0180
0181 NULL);
0182
0183 gtk_window_set_title(GTK_WINDOW(main_wnd), rootmenu.prompt->text);
0184
0185 gtk_widget_show(main_wnd);
0186 }
0187
0188 static void init_tree_model(void)
0189 {
0190 gint i;
0191
0192 tree = tree2 = gtk_tree_store_new(COL_NUMBER,
0193 G_TYPE_STRING, G_TYPE_STRING,
0194 G_TYPE_STRING, G_TYPE_STRING,
0195 G_TYPE_STRING, G_TYPE_STRING,
0196 G_TYPE_POINTER, GDK_TYPE_COLOR,
0197 G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF,
0198 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
0199 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
0200 G_TYPE_BOOLEAN);
0201 model2 = GTK_TREE_MODEL(tree2);
0202
0203 for (parents[0] = NULL, i = 1; i < 256; i++)
0204 parents[i] = (GtkTreeIter *) g_malloc(sizeof(GtkTreeIter));
0205
0206 tree1 = gtk_tree_store_new(COL_NUMBER,
0207 G_TYPE_STRING, G_TYPE_STRING,
0208 G_TYPE_STRING, G_TYPE_STRING,
0209 G_TYPE_STRING, G_TYPE_STRING,
0210 G_TYPE_POINTER, GDK_TYPE_COLOR,
0211 G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF,
0212 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
0213 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
0214 G_TYPE_BOOLEAN);
0215 model1 = GTK_TREE_MODEL(tree1);
0216 }
0217
0218 static void init_left_tree(void)
0219 {
0220 GtkTreeView *view = GTK_TREE_VIEW(tree1_w);
0221 GtkCellRenderer *renderer;
0222 GtkTreeSelection *sel;
0223 GtkTreeViewColumn *column;
0224
0225 gtk_tree_view_set_model(view, model1);
0226 gtk_tree_view_set_headers_visible(view, TRUE);
0227 gtk_tree_view_set_rules_hint(view, TRUE);
0228
0229 column = gtk_tree_view_column_new();
0230 gtk_tree_view_append_column(view, column);
0231 gtk_tree_view_column_set_title(column, "Options");
0232
0233 renderer = gtk_cell_renderer_toggle_new();
0234 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
0235 renderer, FALSE);
0236 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
0237 renderer,
0238 "active", COL_BTNACT,
0239 "inconsistent", COL_BTNINC,
0240 "visible", COL_BTNVIS,
0241 "radio", COL_BTNRAD, NULL);
0242 renderer = gtk_cell_renderer_text_new();
0243 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
0244 renderer, FALSE);
0245 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
0246 renderer,
0247 "text", COL_OPTION,
0248 "foreground-gdk",
0249 COL_COLOR, NULL);
0250
0251 sel = gtk_tree_view_get_selection(view);
0252 gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
0253 gtk_widget_realize(tree1_w);
0254 }
0255
0256 static void renderer_edited(GtkCellRendererText * cell,
0257 const gchar * path_string,
0258 const gchar * new_text, gpointer user_data);
0259
0260 static void init_right_tree(void)
0261 {
0262 GtkTreeView *view = GTK_TREE_VIEW(tree2_w);
0263 GtkCellRenderer *renderer;
0264 GtkTreeSelection *sel;
0265 GtkTreeViewColumn *column;
0266 gint i;
0267
0268 gtk_tree_view_set_model(view, model2);
0269 gtk_tree_view_set_headers_visible(view, TRUE);
0270 gtk_tree_view_set_rules_hint(view, TRUE);
0271
0272 column = gtk_tree_view_column_new();
0273 gtk_tree_view_append_column(view, column);
0274 gtk_tree_view_column_set_title(column, "Options");
0275
0276 renderer = gtk_cell_renderer_pixbuf_new();
0277 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
0278 renderer, FALSE);
0279 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
0280 renderer,
0281 "pixbuf", COL_PIXBUF,
0282 "visible", COL_PIXVIS, NULL);
0283 renderer = gtk_cell_renderer_toggle_new();
0284 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
0285 renderer, FALSE);
0286 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
0287 renderer,
0288 "active", COL_BTNACT,
0289 "inconsistent", COL_BTNINC,
0290 "visible", COL_BTNVIS,
0291 "radio", COL_BTNRAD, NULL);
0292 renderer = gtk_cell_renderer_text_new();
0293 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
0294 renderer, FALSE);
0295 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
0296 renderer,
0297 "text", COL_OPTION,
0298 "foreground-gdk",
0299 COL_COLOR, NULL);
0300
0301 renderer = gtk_cell_renderer_text_new();
0302 gtk_tree_view_insert_column_with_attributes(view, -1,
0303 "Name", renderer,
0304 "text", COL_NAME,
0305 "foreground-gdk",
0306 COL_COLOR, NULL);
0307 renderer = gtk_cell_renderer_text_new();
0308 gtk_tree_view_insert_column_with_attributes(view, -1,
0309 "N", renderer,
0310 "text", COL_NO,
0311 "foreground-gdk",
0312 COL_COLOR, NULL);
0313 renderer = gtk_cell_renderer_text_new();
0314 gtk_tree_view_insert_column_with_attributes(view, -1,
0315 "M", renderer,
0316 "text", COL_MOD,
0317 "foreground-gdk",
0318 COL_COLOR, NULL);
0319 renderer = gtk_cell_renderer_text_new();
0320 gtk_tree_view_insert_column_with_attributes(view, -1,
0321 "Y", renderer,
0322 "text", COL_YES,
0323 "foreground-gdk",
0324 COL_COLOR, NULL);
0325 renderer = gtk_cell_renderer_text_new();
0326 gtk_tree_view_insert_column_with_attributes(view, -1,
0327 "Value", renderer,
0328 "text", COL_VALUE,
0329 "editable",
0330 COL_EDIT,
0331 "foreground-gdk",
0332 COL_COLOR, NULL);
0333 g_signal_connect(G_OBJECT(renderer), "edited",
0334 G_CALLBACK(renderer_edited), NULL);
0335
0336 column = gtk_tree_view_get_column(view, COL_NAME);
0337 gtk_tree_view_column_set_visible(column, show_name);
0338 column = gtk_tree_view_get_column(view, COL_NO);
0339 gtk_tree_view_column_set_visible(column, show_range);
0340 column = gtk_tree_view_get_column(view, COL_MOD);
0341 gtk_tree_view_column_set_visible(column, show_range);
0342 column = gtk_tree_view_get_column(view, COL_YES);
0343 gtk_tree_view_column_set_visible(column, show_range);
0344 column = gtk_tree_view_get_column(view, COL_VALUE);
0345 gtk_tree_view_column_set_visible(column, show_value);
0346
0347 if (resizeable) {
0348 for (i = 0; i < COL_VALUE; i++) {
0349 column = gtk_tree_view_get_column(view, i);
0350 gtk_tree_view_column_set_resizable(column, TRUE);
0351 }
0352 }
0353
0354 sel = gtk_tree_view_get_selection(view);
0355 gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
0356 }
0357
0358
0359
0360
0361
0362 static void text_insert_help(struct menu *menu)
0363 {
0364 GtkTextBuffer *buffer;
0365 GtkTextIter start, end;
0366 const char *prompt = menu_get_prompt(menu);
0367 struct gstr help = str_new();
0368
0369 menu_get_ext_help(menu, &help);
0370
0371 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
0372 gtk_text_buffer_get_bounds(buffer, &start, &end);
0373 gtk_text_buffer_delete(buffer, &start, &end);
0374 gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15);
0375
0376 gtk_text_buffer_get_end_iter(buffer, &end);
0377 gtk_text_buffer_insert_with_tags(buffer, &end, prompt, -1, tag1,
0378 NULL);
0379 gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2);
0380 gtk_text_buffer_get_end_iter(buffer, &end);
0381 gtk_text_buffer_insert_with_tags(buffer, &end, str_get(&help), -1, tag2,
0382 NULL);
0383 str_free(&help);
0384 }
0385
0386
0387 static void text_insert_msg(const char *title, const char *message)
0388 {
0389 GtkTextBuffer *buffer;
0390 GtkTextIter start, end;
0391 const char *msg = message;
0392
0393 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
0394 gtk_text_buffer_get_bounds(buffer, &start, &end);
0395 gtk_text_buffer_delete(buffer, &start, &end);
0396 gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15);
0397
0398 gtk_text_buffer_get_end_iter(buffer, &end);
0399 gtk_text_buffer_insert_with_tags(buffer, &end, title, -1, tag1,
0400 NULL);
0401 gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2);
0402 gtk_text_buffer_get_end_iter(buffer, &end);
0403 gtk_text_buffer_insert_with_tags(buffer, &end, msg, -1, tag2,
0404 NULL);
0405 }
0406
0407
0408
0409
0410 void on_save_activate(GtkMenuItem * menuitem, gpointer user_data);
0411 gboolean on_window1_delete_event(GtkWidget * widget, GdkEvent * event,
0412 gpointer user_data)
0413 {
0414 GtkWidget *dialog, *label;
0415 gint result;
0416
0417 if (!conf_get_changed())
0418 return FALSE;
0419
0420 dialog = gtk_dialog_new_with_buttons("Warning !",
0421 GTK_WINDOW(main_wnd),
0422 (GtkDialogFlags)
0423 (GTK_DIALOG_MODAL |
0424 GTK_DIALOG_DESTROY_WITH_PARENT),
0425 GTK_STOCK_OK,
0426 GTK_RESPONSE_YES,
0427 GTK_STOCK_NO,
0428 GTK_RESPONSE_NO,
0429 GTK_STOCK_CANCEL,
0430 GTK_RESPONSE_CANCEL, NULL);
0431 gtk_dialog_set_default_response(GTK_DIALOG(dialog),
0432 GTK_RESPONSE_CANCEL);
0433
0434 label = gtk_label_new("\nSave configuration ?\n");
0435 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label);
0436 gtk_widget_show(label);
0437
0438 result = gtk_dialog_run(GTK_DIALOG(dialog));
0439 switch (result) {
0440 case GTK_RESPONSE_YES:
0441 on_save_activate(NULL, NULL);
0442 return FALSE;
0443 case GTK_RESPONSE_NO:
0444 return FALSE;
0445 case GTK_RESPONSE_CANCEL:
0446 case GTK_RESPONSE_DELETE_EVENT:
0447 default:
0448 gtk_widget_destroy(dialog);
0449 return TRUE;
0450 }
0451
0452 return FALSE;
0453 }
0454
0455
0456 void on_window1_destroy(GtkObject * object, gpointer user_data)
0457 {
0458 gtk_main_quit();
0459 }
0460
0461
0462 void
0463 on_window1_size_request(GtkWidget * widget,
0464 GtkRequisition * requisition, gpointer user_data)
0465 {
0466 static gint old_h;
0467 gint w, h;
0468
0469 if (widget->window == NULL)
0470 gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h);
0471 else
0472 gdk_window_get_size(widget->window, &w, &h);
0473
0474 if (h == old_h)
0475 return;
0476 old_h = h;
0477
0478 gtk_paned_set_position(GTK_PANED(vpaned), 2 * h / 3);
0479 }
0480
0481
0482
0483
0484
0485 static void
0486 load_filename(GtkFileSelection * file_selector, gpointer user_data)
0487 {
0488 const gchar *fn;
0489
0490 fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION
0491 (user_data));
0492
0493 if (conf_read(fn))
0494 text_insert_msg("Error", "Unable to load configuration !");
0495 else
0496 display_tree(&rootmenu);
0497 }
0498
0499 void on_load1_activate(GtkMenuItem * menuitem, gpointer user_data)
0500 {
0501 GtkWidget *fs;
0502
0503 fs = gtk_file_selection_new("Load file...");
0504 g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button),
0505 "clicked",
0506 G_CALLBACK(load_filename), (gpointer) fs);
0507 g_signal_connect_swapped(GTK_OBJECT
0508 (GTK_FILE_SELECTION(fs)->ok_button),
0509 "clicked", G_CALLBACK(gtk_widget_destroy),
0510 (gpointer) fs);
0511 g_signal_connect_swapped(GTK_OBJECT
0512 (GTK_FILE_SELECTION(fs)->cancel_button),
0513 "clicked", G_CALLBACK(gtk_widget_destroy),
0514 (gpointer) fs);
0515 gtk_widget_show(fs);
0516 }
0517
0518
0519 void on_save_activate(GtkMenuItem * menuitem, gpointer user_data)
0520 {
0521 if (conf_write(NULL))
0522 text_insert_msg("Error", "Unable to save configuration !");
0523 conf_write_autoconf(0);
0524 }
0525
0526
0527 static void
0528 store_filename(GtkFileSelection * file_selector, gpointer user_data)
0529 {
0530 const gchar *fn;
0531
0532 fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION
0533 (user_data));
0534
0535 if (conf_write(fn))
0536 text_insert_msg("Error", "Unable to save configuration !");
0537
0538 gtk_widget_destroy(GTK_WIDGET(user_data));
0539 }
0540
0541 void on_save_as1_activate(GtkMenuItem * menuitem, gpointer user_data)
0542 {
0543 GtkWidget *fs;
0544
0545 fs = gtk_file_selection_new("Save file as...");
0546 g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button),
0547 "clicked",
0548 G_CALLBACK(store_filename), (gpointer) fs);
0549 g_signal_connect_swapped(GTK_OBJECT
0550 (GTK_FILE_SELECTION(fs)->ok_button),
0551 "clicked", G_CALLBACK(gtk_widget_destroy),
0552 (gpointer) fs);
0553 g_signal_connect_swapped(GTK_OBJECT
0554 (GTK_FILE_SELECTION(fs)->cancel_button),
0555 "clicked", G_CALLBACK(gtk_widget_destroy),
0556 (gpointer) fs);
0557 gtk_widget_show(fs);
0558 }
0559
0560
0561 void on_quit1_activate(GtkMenuItem * menuitem, gpointer user_data)
0562 {
0563 if (!on_window1_delete_event(NULL, NULL, NULL))
0564 gtk_widget_destroy(GTK_WIDGET(main_wnd));
0565 }
0566
0567
0568 void on_show_name1_activate(GtkMenuItem * menuitem, gpointer user_data)
0569 {
0570 GtkTreeViewColumn *col;
0571
0572 show_name = GTK_CHECK_MENU_ITEM(menuitem)->active;
0573 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NAME);
0574 if (col)
0575 gtk_tree_view_column_set_visible(col, show_name);
0576 }
0577
0578
0579 void on_show_range1_activate(GtkMenuItem * menuitem, gpointer user_data)
0580 {
0581 GtkTreeViewColumn *col;
0582
0583 show_range = GTK_CHECK_MENU_ITEM(menuitem)->active;
0584 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NO);
0585 if (col)
0586 gtk_tree_view_column_set_visible(col, show_range);
0587 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_MOD);
0588 if (col)
0589 gtk_tree_view_column_set_visible(col, show_range);
0590 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_YES);
0591 if (col)
0592 gtk_tree_view_column_set_visible(col, show_range);
0593
0594 }
0595
0596
0597 void on_show_data1_activate(GtkMenuItem * menuitem, gpointer user_data)
0598 {
0599 GtkTreeViewColumn *col;
0600
0601 show_value = GTK_CHECK_MENU_ITEM(menuitem)->active;
0602 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_VALUE);
0603 if (col)
0604 gtk_tree_view_column_set_visible(col, show_value);
0605 }
0606
0607
0608 void
0609 on_set_option_mode1_activate(GtkMenuItem *menuitem, gpointer user_data)
0610 {
0611 opt_mode = OPT_NORMAL;
0612 gtk_tree_store_clear(tree2);
0613 display_tree(&rootmenu);
0614 }
0615
0616
0617 void
0618 on_set_option_mode2_activate(GtkMenuItem *menuitem, gpointer user_data)
0619 {
0620 opt_mode = OPT_ALL;
0621 gtk_tree_store_clear(tree2);
0622 display_tree(&rootmenu);
0623 }
0624
0625
0626 void
0627 on_set_option_mode3_activate(GtkMenuItem *menuitem, gpointer user_data)
0628 {
0629 opt_mode = OPT_PROMPT;
0630 gtk_tree_store_clear(tree2);
0631 display_tree(&rootmenu);
0632 }
0633
0634
0635 void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data)
0636 {
0637 GtkWidget *dialog;
0638 const gchar *intro_text =
0639 "Welcome to gkc, the GTK+ graphical configuration tool\n"
0640 "For each option, a blank box indicates the feature is disabled, a\n"
0641 "check indicates it is enabled, and a dot indicates that it is to\n"
0642 "be compiled as a module. Clicking on the box will cycle through the three states.\n"
0643 "\n"
0644 "If you do not see an option (e.g., a device driver) that you\n"
0645 "believe should be present, try turning on Show All Options\n"
0646 "under the Options menu.\n"
0647 "Although there is no cross reference yet to help you figure out\n"
0648 "what other options must be enabled to support the option you\n"
0649 "are interested in, you can still view the help of a grayed-out\n"
0650 "option.\n"
0651 "\n"
0652 "Toggling Show Debug Info under the Options menu will show \n"
0653 "the dependencies, which you can then match by examining other options.";
0654
0655 dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
0656 GTK_DIALOG_DESTROY_WITH_PARENT,
0657 GTK_MESSAGE_INFO,
0658 GTK_BUTTONS_CLOSE, "%s", intro_text);
0659 g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
0660 G_CALLBACK(gtk_widget_destroy),
0661 GTK_OBJECT(dialog));
0662 gtk_widget_show_all(dialog);
0663 }
0664
0665
0666 void on_about1_activate(GtkMenuItem * menuitem, gpointer user_data)
0667 {
0668 GtkWidget *dialog;
0669 const gchar *about_text =
0670 "gkc is copyright (c) 2002 Romain Lievin <roms@lpg.ticalc.org>.\n"
0671 "Based on the source code from Roman Zippel.\n";
0672
0673 dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
0674 GTK_DIALOG_DESTROY_WITH_PARENT,
0675 GTK_MESSAGE_INFO,
0676 GTK_BUTTONS_CLOSE, "%s", about_text);
0677 g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
0678 G_CALLBACK(gtk_widget_destroy),
0679 GTK_OBJECT(dialog));
0680 gtk_widget_show_all(dialog);
0681 }
0682
0683
0684 void on_license1_activate(GtkMenuItem * menuitem, gpointer user_data)
0685 {
0686 GtkWidget *dialog;
0687 const gchar *license_text =
0688 "gkc is released under the terms of the GNU GPL v2.\n"
0689 "For more information, please see the source code or\n"
0690 "visit http://www.fsf.org/licenses/licenses.html\n";
0691
0692 dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
0693 GTK_DIALOG_DESTROY_WITH_PARENT,
0694 GTK_MESSAGE_INFO,
0695 GTK_BUTTONS_CLOSE, "%s", license_text);
0696 g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
0697 G_CALLBACK(gtk_widget_destroy),
0698 GTK_OBJECT(dialog));
0699 gtk_widget_show_all(dialog);
0700 }
0701
0702
0703 void on_back_clicked(GtkButton * button, gpointer user_data)
0704 {
0705 enum prop_type ptype;
0706
0707 current = current->parent;
0708 ptype = current->prompt ? current->prompt->type : P_UNKNOWN;
0709 if (ptype != P_MENU)
0710 current = current->parent;
0711 display_tree_part();
0712
0713 if (current == &rootmenu)
0714 gtk_widget_set_sensitive(back_btn, FALSE);
0715 }
0716
0717
0718 void on_load_clicked(GtkButton * button, gpointer user_data)
0719 {
0720 on_load1_activate(NULL, user_data);
0721 }
0722
0723
0724 void on_single_clicked(GtkButton * button, gpointer user_data)
0725 {
0726 view_mode = SINGLE_VIEW;
0727 gtk_widget_hide(tree1_w);
0728 current = &rootmenu;
0729 display_tree_part();
0730 }
0731
0732
0733 void on_split_clicked(GtkButton * button, gpointer user_data)
0734 {
0735 gint w, h;
0736 view_mode = SPLIT_VIEW;
0737 gtk_widget_show(tree1_w);
0738 gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h);
0739 gtk_paned_set_position(GTK_PANED(hpaned), w / 2);
0740 if (tree2)
0741 gtk_tree_store_clear(tree2);
0742 display_list();
0743
0744
0745 gtk_widget_set_sensitive(back_btn, FALSE);
0746 }
0747
0748
0749 void on_full_clicked(GtkButton * button, gpointer user_data)
0750 {
0751 view_mode = FULL_VIEW;
0752 gtk_widget_hide(tree1_w);
0753 if (tree2)
0754 gtk_tree_store_clear(tree2);
0755 display_tree(&rootmenu);
0756 gtk_widget_set_sensitive(back_btn, FALSE);
0757 }
0758
0759
0760 void on_collapse_clicked(GtkButton * button, gpointer user_data)
0761 {
0762 gtk_tree_view_collapse_all(GTK_TREE_VIEW(tree2_w));
0763 }
0764
0765
0766 void on_expand_clicked(GtkButton * button, gpointer user_data)
0767 {
0768 gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w));
0769 }
0770
0771
0772
0773
0774
0775 static void renderer_edited(GtkCellRendererText * cell,
0776 const gchar * path_string,
0777 const gchar * new_text, gpointer user_data)
0778 {
0779 GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
0780 GtkTreeIter iter;
0781 const char *old_def, *new_def;
0782 struct menu *menu;
0783 struct symbol *sym;
0784
0785 if (!gtk_tree_model_get_iter(model2, &iter, path))
0786 return;
0787
0788 gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
0789 sym = menu->sym;
0790
0791 gtk_tree_model_get(model2, &iter, COL_VALUE, &old_def, -1);
0792 new_def = new_text;
0793
0794 sym_set_string_value(sym, new_def);
0795
0796 update_tree(&rootmenu, NULL);
0797
0798 gtk_tree_path_free(path);
0799 }
0800
0801
0802 static void change_sym_value(struct menu *menu, gint col)
0803 {
0804 struct symbol *sym = menu->sym;
0805 tristate newval;
0806
0807 if (!sym)
0808 return;
0809
0810 if (col == COL_NO)
0811 newval = no;
0812 else if (col == COL_MOD)
0813 newval = mod;
0814 else if (col == COL_YES)
0815 newval = yes;
0816 else
0817 return;
0818
0819 switch (sym_get_type(sym)) {
0820 case S_BOOLEAN:
0821 case S_TRISTATE:
0822 if (!sym_tristate_within_range(sym, newval))
0823 newval = yes;
0824 sym_set_tristate_value(sym, newval);
0825 if (view_mode == FULL_VIEW)
0826 update_tree(&rootmenu, NULL);
0827 else if (view_mode == SPLIT_VIEW) {
0828 update_tree(browsed, NULL);
0829 display_list();
0830 }
0831 else if (view_mode == SINGLE_VIEW)
0832 display_tree_part();
0833 break;
0834 case S_INT:
0835 case S_HEX:
0836 case S_STRING:
0837 default:
0838 break;
0839 }
0840 }
0841
0842 static void toggle_sym_value(struct menu *menu)
0843 {
0844 if (!menu->sym)
0845 return;
0846
0847 sym_toggle_tristate_value(menu->sym);
0848 if (view_mode == FULL_VIEW)
0849 update_tree(&rootmenu, NULL);
0850 else if (view_mode == SPLIT_VIEW) {
0851 update_tree(browsed, NULL);
0852 display_list();
0853 }
0854 else if (view_mode == SINGLE_VIEW)
0855 display_tree_part();
0856 }
0857
0858 static gint column2index(GtkTreeViewColumn * column)
0859 {
0860 gint i;
0861
0862 for (i = 0; i < COL_NUMBER; i++) {
0863 GtkTreeViewColumn *col;
0864
0865 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), i);
0866 if (col == column)
0867 return i;
0868 }
0869
0870 return -1;
0871 }
0872
0873
0874
0875 gboolean
0876 on_treeview2_button_press_event(GtkWidget * widget,
0877 GdkEventButton * event, gpointer user_data)
0878 {
0879 GtkTreeView *view = GTK_TREE_VIEW(widget);
0880 GtkTreePath *path;
0881 GtkTreeViewColumn *column;
0882 GtkTreeIter iter;
0883 struct menu *menu;
0884 gint col;
0885
0886 #if GTK_CHECK_VERSION(2,1,4)
0887 gint tx = (gint) event->x;
0888 gint ty = (gint) event->y;
0889 gint cx, cy;
0890
0891 gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx,
0892 &cy);
0893 #else
0894 gtk_tree_view_get_cursor(view, &path, &column);
0895 #endif
0896 if (path == NULL)
0897 return FALSE;
0898
0899 if (!gtk_tree_model_get_iter(model2, &iter, path))
0900 return FALSE;
0901 gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
0902
0903 col = column2index(column);
0904 if (event->type == GDK_2BUTTON_PRESS) {
0905 enum prop_type ptype;
0906 ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
0907
0908 if (ptype == P_MENU && view_mode != FULL_VIEW && col == COL_OPTION) {
0909
0910 current = menu;
0911 display_tree_part();
0912 gtk_widget_set_sensitive(back_btn, TRUE);
0913 } else if (col == COL_OPTION) {
0914 toggle_sym_value(menu);
0915 gtk_tree_view_expand_row(view, path, TRUE);
0916 }
0917 } else {
0918 if (col == COL_VALUE) {
0919 toggle_sym_value(menu);
0920 gtk_tree_view_expand_row(view, path, TRUE);
0921 } else if (col == COL_NO || col == COL_MOD
0922 || col == COL_YES) {
0923 change_sym_value(menu, col);
0924 gtk_tree_view_expand_row(view, path, TRUE);
0925 }
0926 }
0927
0928 return FALSE;
0929 }
0930
0931
0932 gboolean
0933 on_treeview2_key_press_event(GtkWidget * widget,
0934 GdkEventKey * event, gpointer user_data)
0935 {
0936 GtkTreeView *view = GTK_TREE_VIEW(widget);
0937 GtkTreePath *path;
0938 GtkTreeViewColumn *column;
0939 GtkTreeIter iter;
0940 struct menu *menu;
0941 gint col;
0942
0943 gtk_tree_view_get_cursor(view, &path, &column);
0944 if (path == NULL)
0945 return FALSE;
0946
0947 if (event->keyval == GDK_space) {
0948 if (gtk_tree_view_row_expanded(view, path))
0949 gtk_tree_view_collapse_row(view, path);
0950 else
0951 gtk_tree_view_expand_row(view, path, FALSE);
0952 return TRUE;
0953 }
0954 if (event->keyval == GDK_KP_Enter) {
0955 }
0956 if (widget == tree1_w)
0957 return FALSE;
0958
0959 gtk_tree_model_get_iter(model2, &iter, path);
0960 gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
0961
0962 if (!strcasecmp(event->string, "n"))
0963 col = COL_NO;
0964 else if (!strcasecmp(event->string, "m"))
0965 col = COL_MOD;
0966 else if (!strcasecmp(event->string, "y"))
0967 col = COL_YES;
0968 else
0969 col = -1;
0970 change_sym_value(menu, col);
0971
0972 return FALSE;
0973 }
0974
0975
0976
0977 void
0978 on_treeview2_cursor_changed(GtkTreeView * treeview, gpointer user_data)
0979 {
0980 GtkTreeSelection *selection;
0981 GtkTreeIter iter;
0982 struct menu *menu;
0983
0984 selection = gtk_tree_view_get_selection(treeview);
0985 if (gtk_tree_selection_get_selected(selection, &model2, &iter)) {
0986 gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
0987 text_insert_help(menu);
0988 }
0989 }
0990
0991
0992
0993 gboolean
0994 on_treeview1_button_press_event(GtkWidget * widget,
0995 GdkEventButton * event, gpointer user_data)
0996 {
0997 GtkTreeView *view = GTK_TREE_VIEW(widget);
0998 GtkTreePath *path;
0999 GtkTreeViewColumn *column;
1000 GtkTreeIter iter;
1001 struct menu *menu;
1002
1003 gint tx = (gint) event->x;
1004 gint ty = (gint) event->y;
1005 gint cx, cy;
1006
1007 gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx,
1008 &cy);
1009 if (path == NULL)
1010 return FALSE;
1011
1012 gtk_tree_model_get_iter(model1, &iter, path);
1013 gtk_tree_model_get(model1, &iter, COL_MENU, &menu, -1);
1014
1015 if (event->type == GDK_2BUTTON_PRESS) {
1016 toggle_sym_value(menu);
1017 current = menu;
1018 display_tree_part();
1019 } else {
1020 browsed = menu;
1021 display_tree_part();
1022 }
1023
1024 gtk_widget_realize(tree2_w);
1025 gtk_tree_view_set_cursor(view, path, NULL, FALSE);
1026 gtk_widget_grab_focus(tree2_w);
1027
1028 return FALSE;
1029 }
1030
1031
1032
1033 static gchar **fill_row(struct menu *menu)
1034 {
1035 static gchar *row[COL_NUMBER];
1036 struct symbol *sym = menu->sym;
1037 const char *def;
1038 int stype;
1039 tristate val;
1040 enum prop_type ptype;
1041 int i;
1042
1043 for (i = COL_OPTION; i <= COL_COLOR; i++)
1044 g_free(row[i]);
1045 bzero(row, sizeof(row));
1046
1047 ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
1048
1049 row[COL_OPTION] =
1050 g_strdup_printf("%s %s %s %s",
1051 ptype == P_COMMENT ? "***" : "",
1052 menu_get_prompt(menu),
1053 ptype == P_COMMENT ? "***" : "",
1054 sym && !sym_has_value(sym) ? "(NEW)" : "");
1055
1056 if (opt_mode == OPT_ALL && !menu_is_visible(menu))
1057 row[COL_COLOR] = g_strdup("DarkGray");
1058 else if (opt_mode == OPT_PROMPT &&
1059 menu_has_prompt(menu) && !menu_is_visible(menu))
1060 row[COL_COLOR] = g_strdup("DarkGray");
1061 else
1062 row[COL_COLOR] = g_strdup("Black");
1063
1064 switch (ptype) {
1065 case P_MENU:
1066 row[COL_PIXBUF] = (gchar *) xpm_menu;
1067 if (view_mode == SINGLE_VIEW)
1068 row[COL_PIXVIS] = GINT_TO_POINTER(TRUE);
1069 row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
1070 break;
1071 case P_COMMENT:
1072 row[COL_PIXBUF] = (gchar *) xpm_void;
1073 row[COL_PIXVIS] = GINT_TO_POINTER(FALSE);
1074 row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
1075 break;
1076 default:
1077 row[COL_PIXBUF] = (gchar *) xpm_void;
1078 row[COL_PIXVIS] = GINT_TO_POINTER(FALSE);
1079 row[COL_BTNVIS] = GINT_TO_POINTER(TRUE);
1080 break;
1081 }
1082
1083 if (!sym)
1084 return row;
1085 row[COL_NAME] = g_strdup(sym->name);
1086
1087 sym_calc_value(sym);
1088 sym->flags &= ~SYMBOL_CHANGED;
1089
1090 if (sym_is_choice(sym)) {
1091 struct menu *child;
1092 struct symbol *def_sym = sym_get_choice_value(sym);
1093 struct menu *def_menu = NULL;
1094
1095 row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
1096
1097 for (child = menu->list; child; child = child->next) {
1098 if (menu_is_visible(child)
1099 && child->sym == def_sym)
1100 def_menu = child;
1101 }
1102
1103 if (def_menu)
1104 row[COL_VALUE] =
1105 g_strdup(menu_get_prompt(def_menu));
1106 }
1107 if (sym->flags & SYMBOL_CHOICEVAL)
1108 row[COL_BTNRAD] = GINT_TO_POINTER(TRUE);
1109
1110 stype = sym_get_type(sym);
1111 switch (stype) {
1112 case S_BOOLEAN:
1113 if (GPOINTER_TO_INT(row[COL_PIXVIS]) == FALSE)
1114 row[COL_BTNVIS] = GINT_TO_POINTER(TRUE);
1115 if (sym_is_choice(sym))
1116 break;
1117
1118 case S_TRISTATE:
1119 val = sym_get_tristate_value(sym);
1120 switch (val) {
1121 case no:
1122 row[COL_NO] = g_strdup("N");
1123 row[COL_VALUE] = g_strdup("N");
1124 row[COL_BTNACT] = GINT_TO_POINTER(FALSE);
1125 row[COL_BTNINC] = GINT_TO_POINTER(FALSE);
1126 break;
1127 case mod:
1128 row[COL_MOD] = g_strdup("M");
1129 row[COL_VALUE] = g_strdup("M");
1130 row[COL_BTNINC] = GINT_TO_POINTER(TRUE);
1131 break;
1132 case yes:
1133 row[COL_YES] = g_strdup("Y");
1134 row[COL_VALUE] = g_strdup("Y");
1135 row[COL_BTNACT] = GINT_TO_POINTER(TRUE);
1136 row[COL_BTNINC] = GINT_TO_POINTER(FALSE);
1137 break;
1138 }
1139
1140 if (val != no && sym_tristate_within_range(sym, no))
1141 row[COL_NO] = g_strdup("_");
1142 if (val != mod && sym_tristate_within_range(sym, mod))
1143 row[COL_MOD] = g_strdup("_");
1144 if (val != yes && sym_tristate_within_range(sym, yes))
1145 row[COL_YES] = g_strdup("_");
1146 break;
1147 case S_INT:
1148 case S_HEX:
1149 case S_STRING:
1150 def = sym_get_string_value(sym);
1151 row[COL_VALUE] = g_strdup(def);
1152 row[COL_EDIT] = GINT_TO_POINTER(TRUE);
1153 row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
1154 break;
1155 }
1156
1157 return row;
1158 }
1159
1160
1161
1162 static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row)
1163 {
1164 GdkColor color;
1165 gboolean success;
1166 GdkPixbuf *pix;
1167
1168 pix = gdk_pixbuf_new_from_xpm_data((const char **)
1169 row[COL_PIXBUF]);
1170
1171 gdk_color_parse(row[COL_COLOR], &color);
1172 gdk_colormap_alloc_colors(gdk_colormap_get_system(), &color, 1,
1173 FALSE, FALSE, &success);
1174
1175 gtk_tree_store_set(tree, node,
1176 COL_OPTION, row[COL_OPTION],
1177 COL_NAME, row[COL_NAME],
1178 COL_NO, row[COL_NO],
1179 COL_MOD, row[COL_MOD],
1180 COL_YES, row[COL_YES],
1181 COL_VALUE, row[COL_VALUE],
1182 COL_MENU, (gpointer) menu,
1183 COL_COLOR, &color,
1184 COL_EDIT, GPOINTER_TO_INT(row[COL_EDIT]),
1185 COL_PIXBUF, pix,
1186 COL_PIXVIS, GPOINTER_TO_INT(row[COL_PIXVIS]),
1187 COL_BTNVIS, GPOINTER_TO_INT(row[COL_BTNVIS]),
1188 COL_BTNACT, GPOINTER_TO_INT(row[COL_BTNACT]),
1189 COL_BTNINC, GPOINTER_TO_INT(row[COL_BTNINC]),
1190 COL_BTNRAD, GPOINTER_TO_INT(row[COL_BTNRAD]),
1191 -1);
1192
1193 g_object_unref(pix);
1194 }
1195
1196
1197
1198 static void place_node(struct menu *menu, char **row)
1199 {
1200 GtkTreeIter *parent = parents[indent - 1];
1201 GtkTreeIter *node = parents[indent];
1202
1203 gtk_tree_store_append(tree, node, parent);
1204 set_node(node, menu, row);
1205 }
1206
1207
1208
1209 static GtkTreeIter found;
1210
1211
1212
1213
1214 static GtkTreeIter *gtktree_iter_find_node(GtkTreeIter *parent,
1215 struct menu *tofind)
1216 {
1217 GtkTreeIter iter;
1218 GtkTreeIter *child = &iter;
1219 gboolean valid;
1220 GtkTreeIter *ret;
1221
1222 valid = gtk_tree_model_iter_children(model2, child, parent);
1223 while (valid) {
1224 struct menu *menu;
1225
1226 gtk_tree_model_get(model2, child, 6, &menu, -1);
1227
1228 if (menu == tofind) {
1229 memcpy(&found, child, sizeof(GtkTreeIter));
1230 return &found;
1231 }
1232
1233 ret = gtktree_iter_find_node(child, tofind);
1234 if (ret)
1235 return ret;
1236
1237 valid = gtk_tree_model_iter_next(model2, child);
1238 }
1239
1240 return NULL;
1241 }
1242
1243
1244
1245
1246
1247
1248 static void update_tree(struct menu *src, GtkTreeIter * dst)
1249 {
1250 struct menu *child1;
1251 GtkTreeIter iter, tmp;
1252 GtkTreeIter *child2 = &iter;
1253 gboolean valid;
1254 GtkTreeIter *sibling;
1255 struct symbol *sym;
1256 struct menu *menu1, *menu2;
1257
1258 if (src == &rootmenu)
1259 indent = 1;
1260
1261 valid = gtk_tree_model_iter_children(model2, child2, dst);
1262 for (child1 = src->list; child1; child1 = child1->next) {
1263
1264 sym = child1->sym;
1265
1266 reparse:
1267 menu1 = child1;
1268 if (valid)
1269 gtk_tree_model_get(model2, child2, COL_MENU,
1270 &menu2, -1);
1271 else
1272 menu2 = NULL;
1273
1274 #ifdef DEBUG
1275 printf("%*c%s | %s\n", indent, ' ',
1276 menu1 ? menu_get_prompt(menu1) : "nil",
1277 menu2 ? menu_get_prompt(menu2) : "nil");
1278 #endif
1279
1280 if ((opt_mode == OPT_NORMAL && !menu_is_visible(child1)) ||
1281 (opt_mode == OPT_PROMPT && !menu_has_prompt(child1)) ||
1282 (opt_mode == OPT_ALL && !menu_get_prompt(child1))) {
1283
1284
1285 if (gtktree_iter_find_node(dst, menu1) != NULL) {
1286 memcpy(&tmp, child2, sizeof(GtkTreeIter));
1287 valid = gtk_tree_model_iter_next(model2,
1288 child2);
1289 gtk_tree_store_remove(tree2, &tmp);
1290 if (!valid)
1291 return;
1292 else
1293 goto reparse;
1294 } else
1295 continue;
1296 }
1297
1298 if (menu1 != menu2) {
1299 if (gtktree_iter_find_node(dst, menu1) == NULL) {
1300 if (!valid && !menu2)
1301 sibling = NULL;
1302 else
1303 sibling = child2;
1304 gtk_tree_store_insert_before(tree2,
1305 child2,
1306 dst, sibling);
1307 set_node(child2, menu1, fill_row(menu1));
1308 if (menu2 == NULL)
1309 valid = TRUE;
1310 } else {
1311 memcpy(&tmp, child2, sizeof(GtkTreeIter));
1312 valid = gtk_tree_model_iter_next(model2,
1313 child2);
1314 gtk_tree_store_remove(tree2, &tmp);
1315 if (!valid)
1316 return;
1317 else
1318 goto reparse;
1319 }
1320 } else if (sym && (sym->flags & SYMBOL_CHANGED)) {
1321 set_node(child2, menu1, fill_row(menu1));
1322 }
1323
1324 indent++;
1325 update_tree(child1, child2);
1326 indent--;
1327
1328 valid = gtk_tree_model_iter_next(model2, child2);
1329 }
1330 }
1331
1332
1333
1334 static void display_tree(struct menu *menu)
1335 {
1336 struct symbol *sym;
1337 struct property *prop;
1338 struct menu *child;
1339 enum prop_type ptype;
1340
1341 if (menu == &rootmenu) {
1342 indent = 1;
1343 current = &rootmenu;
1344 }
1345
1346 for (child = menu->list; child; child = child->next) {
1347 prop = child->prompt;
1348 sym = child->sym;
1349 ptype = prop ? prop->type : P_UNKNOWN;
1350
1351 if (sym)
1352 sym->flags &= ~SYMBOL_CHANGED;
1353
1354 if ((view_mode == SPLIT_VIEW)
1355 && !(child->flags & MENU_ROOT) && (tree == tree1))
1356 continue;
1357
1358 if ((view_mode == SPLIT_VIEW) && (child->flags & MENU_ROOT)
1359 && (tree == tree2))
1360 continue;
1361
1362 if ((opt_mode == OPT_NORMAL && menu_is_visible(child)) ||
1363 (opt_mode == OPT_PROMPT && menu_has_prompt(child)) ||
1364 (opt_mode == OPT_ALL && menu_get_prompt(child)))
1365 place_node(child, fill_row(child));
1366 #ifdef DEBUG
1367 printf("%*c%s: ", indent, ' ', menu_get_prompt(child));
1368 printf("%s", child->flags & MENU_ROOT ? "rootmenu | " : "");
1369 printf("%s", prop_get_type_name(ptype));
1370 printf(" | ");
1371 if (sym) {
1372 printf("%s", sym_type_name(sym->type));
1373 printf(" | ");
1374 printf("%s", dbg_sym_flags(sym->flags));
1375 printf("\n");
1376 } else
1377 printf("\n");
1378 #endif
1379 if ((view_mode != FULL_VIEW) && (ptype == P_MENU)
1380 && (tree == tree2))
1381 continue;
1382
1383
1384
1385
1386
1387
1388 if (view_mode == SINGLE_VIEW || view_mode == FULL_VIEW) {
1389 gtk_paned_set_position(GTK_PANED(hpaned), 0);
1390 }
1391
1392 if (((view_mode == SINGLE_VIEW) && (menu->flags & MENU_ROOT))
1393 || (view_mode == FULL_VIEW)
1394 || (view_mode == SPLIT_VIEW)) {
1395 indent++;
1396 display_tree(child);
1397 indent--;
1398 }
1399 }
1400 }
1401
1402
1403 static void display_tree_part(void)
1404 {
1405 if (tree2)
1406 gtk_tree_store_clear(tree2);
1407 if (view_mode == SINGLE_VIEW)
1408 display_tree(current);
1409 else if (view_mode == SPLIT_VIEW)
1410 display_tree(browsed);
1411 gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w));
1412 }
1413
1414
1415 static void display_list(void)
1416 {
1417 if (tree1)
1418 gtk_tree_store_clear(tree1);
1419
1420 tree = tree1;
1421 display_tree(&rootmenu);
1422 gtk_tree_view_expand_all(GTK_TREE_VIEW(tree1_w));
1423 tree = tree2;
1424 }
1425
1426 static void fixup_rootmenu(struct menu *menu)
1427 {
1428 struct menu *child;
1429 static int menu_cnt = 0;
1430
1431 menu->flags |= MENU_ROOT;
1432 for (child = menu->list; child; child = child->next) {
1433 if (child->prompt && child->prompt->type == P_MENU) {
1434 menu_cnt++;
1435 fixup_rootmenu(child);
1436 menu_cnt--;
1437 } else if (!menu_cnt)
1438 fixup_rootmenu(child);
1439 }
1440 }
1441
1442
1443
1444 int main(int ac, char *av[])
1445 {
1446 const char *name;
1447 char *env;
1448 gchar *glade_file;
1449
1450
1451 gtk_set_locale();
1452 gtk_init(&ac, &av);
1453 glade_init();
1454
1455
1456 env = getenv(SRCTREE);
1457 if (env)
1458 glade_file = g_strconcat(env, "/scripts/kconfig/gconf.glade", NULL);
1459 else if (av[0][0] == '/')
1460 glade_file = g_strconcat(av[0], ".glade", NULL);
1461 else
1462 glade_file = g_strconcat(g_get_current_dir(), "/", av[0], ".glade", NULL);
1463
1464
1465 if (ac > 1 && av[1][0] == '-') {
1466 switch (av[1][1]) {
1467 case 'a':
1468
1469 break;
1470 case 's':
1471 conf_set_message_callback(NULL);
1472 break;
1473 case 'h':
1474 case '?':
1475 printf("%s [-s] <config>\n", av[0]);
1476 exit(0);
1477 }
1478 name = av[2];
1479 } else
1480 name = av[1];
1481
1482 conf_parse(name);
1483 fixup_rootmenu(&rootmenu);
1484 conf_read(NULL);
1485
1486
1487 init_main_window(glade_file);
1488 init_tree_model();
1489 init_left_tree();
1490 init_right_tree();
1491
1492 switch (view_mode) {
1493 case SINGLE_VIEW:
1494 display_tree_part();
1495 break;
1496 case SPLIT_VIEW:
1497 display_list();
1498 break;
1499 case FULL_VIEW:
1500 display_tree(&rootmenu);
1501 break;
1502 }
1503
1504 gtk_main();
1505
1506 return 0;
1507 }
1508
1509 static void conf_changed(void)
1510 {
1511 bool changed = conf_get_changed();
1512 gtk_widget_set_sensitive(save_btn, changed);
1513 gtk_widget_set_sensitive(save_menu_item, changed);
1514 }