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