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