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
conf_changed(bool dirty)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
text_insert_msg(const char * title,const char * msg)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
text_insert_help(struct menu * menu)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
_select_menu(GtkTreeView * view,GtkTreeModel * model,GtkTreeIter * parent,struct menu * match)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
select_menu(GtkTreeView * view,struct menu * match)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
_update_row_visibility(GtkTreeView * view)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
update_row_visibility(void)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
set_node(GtkTreeStore * tree,GtkTreeIter * node,struct menu * menu)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
_update_tree(GtkTreeStore * store,GtkTreeIter * parent)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
update_tree(GtkTreeStore * store)271 static void update_tree(GtkTreeStore *store)
272 {
273 _update_tree(store, NULL);
274 update_row_visibility();
275 }
276
update_trees(void)277 static void update_trees(void)
278 {
279 if (view_mode == SPLIT_VIEW)
280 update_tree(tree1);
281 update_tree(tree2);
282 }
283
set_view_mode(enum view_mode mode)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
on_load1_activate(GtkMenuItem * menuitem,gpointer user_data)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
on_save_activate(GtkMenuItem * menuitem,gpointer user_data)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
on_save_as1_activate(GtkMenuItem * menuitem,gpointer user_data)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
on_show_name1_activate(GtkMenuItem * menuitem,gpointer user_data)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
on_show_range1_activate(GtkMenuItem * menuitem,gpointer user_data)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
on_show_data1_activate(GtkMenuItem * menuitem,gpointer user_data)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
on_set_option_mode1_activate(GtkMenuItem * menuitem,gpointer user_data)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
on_set_option_mode2_activate(GtkMenuItem * menuitem,gpointer user_data)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
on_set_option_mode3_activate(GtkMenuItem * menuitem,gpointer user_data)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
on_introduction1_activate(GtkMenuItem * menuitem,gpointer user_data)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
on_about1_activate(GtkMenuItem * menuitem,gpointer user_data)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
on_license1_activate(GtkMenuItem * menuitem,gpointer user_data)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 */
on_back_clicked(GtkButton * button,gpointer user_data)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
on_load_clicked(GtkButton * button,gpointer user_data)546 static void on_load_clicked(GtkButton *button, gpointer user_data)
547 {
548 on_load1_activate(NULL, user_data);
549 }
550
on_save_clicked(GtkButton * button,gpointer user_data)551 static void on_save_clicked(GtkButton *button, gpointer user_data)
552 {
553 on_save_activate(NULL, user_data);
554 }
555
on_single_clicked(GtkButton * button,gpointer user_data)556 static void on_single_clicked(GtkButton *button, gpointer user_data)
557 {
558 set_view_mode(SINGLE_VIEW);
559 }
560
on_split_clicked(GtkButton * button,gpointer user_data)561 static void on_split_clicked(GtkButton *button, gpointer user_data)
562 {
563 set_view_mode(SPLIT_VIEW);
564 }
565
on_full_clicked(GtkButton * button,gpointer user_data)566 static void on_full_clicked(GtkButton *button, gpointer user_data)
567 {
568 set_view_mode(FULL_VIEW);
569 }
570
on_collapse_clicked(GtkButton * button,gpointer user_data)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
on_expand_clicked(GtkButton * button,gpointer user_data)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
on_window1_destroy(GtkWidget * widget,gpointer user_data)583 static void on_window1_destroy(GtkWidget *widget, gpointer user_data)
584 {
585 gtk_main_quit();
586 }
587
on_window1_configure(GtkWidget * self,GdkEventConfigure * event,gpointer user_data)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
on_window1_delete_event(GtkWidget * widget,GdkEvent * event,gpointer user_data)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
on_quit1_activate(GtkMenuItem * menuitem,gpointer user_data)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 */
renderer_edited(GtkCellRendererText * cell,const gchar * path_string,const gchar * new_text,gpointer user_data)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 */
change_sym_value(struct menu * menu,gint col)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
toggle_sym_value(struct menu * menu)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
column2index(GtkTreeViewColumn * column)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) */
on_treeview2_button_press_event(GtkWidget * widget,GdkEventButton * event,gpointer user_data)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 */
on_treeview2_key_press_event(GtkWidget * widget,GdkEventKey * event,gpointer user_data)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 */
on_treeview2_cursor_changed(GtkTreeView * treeview,gpointer user_data)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. */
on_treeview1_button_press_event(GtkWidget * widget,GdkEventButton * event,gpointer user_data)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) */
_display_tree(GtkTreeStore * tree,struct menu * menu,GtkTreeIter * parent)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
display_tree(GtkTreeStore * store,struct menu * menu)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 */
recreate_tree(void)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
fixup_rootmenu(struct menu * menu)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 */
replace_button_icon(GtkWidget * widget,const char * const xpm[])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
init_main_window(const gchar * glade_file)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
visible_func(GtkTreeModel * model,GtkTreeIter * iter,gpointer data)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
init_left_tree(void)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
init_right_tree(void)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 */
main(int ac,char * av[])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