blob: 36f578415c4a64d37128d0a980a80e38c2da0994 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/* Hey EMACS -*- linux-c -*- */
2/*
3 *
4 * Copyright (C) 2002-2003 Romain Lievin <roms@tilp.info>
5 * Released under the terms of the GNU GPL v2.0.
6 *
7 */
8
9#ifdef HAVE_CONFIG_H
10# include <config.h>
11#endif
12
Yann E. MORIN9a926d42012-10-20 01:06:25 +020013#include <stdlib.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070014#include "lkc.h"
15#include "images.c"
16
17#include <glade/glade.h>
18#include <gtk/gtk.h>
19#include <glib.h>
20#include <gdk/gdkkeysyms.h>
21
22#include <stdio.h>
23#include <string.h>
24#include <unistd.h>
25#include <time.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070026
27//#define DEBUG
28
29enum {
30 SINGLE_VIEW, SPLIT_VIEW, FULL_VIEW
31};
32
Li Zefan06f9a552010-04-14 11:46:24 +080033enum {
34 OPT_NORMAL, OPT_ALL, OPT_PROMPT
35};
36
Linus Torvalds1da177e2005-04-16 15:20:36 -070037static gint view_mode = FULL_VIEW;
38static gboolean show_name = TRUE;
39static gboolean show_range = TRUE;
40static gboolean show_value = TRUE;
Linus Torvalds1da177e2005-04-16 15:20:36 -070041static gboolean resizeable = FALSE;
Li Zefan06f9a552010-04-14 11:46:24 +080042static int opt_mode = OPT_NORMAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -070043
Linus Torvalds1da177e2005-04-16 15:20:36 -070044GtkWidget *main_wnd = NULL;
45GtkWidget *tree1_w = NULL; // left frame
46GtkWidget *tree2_w = NULL; // right frame
47GtkWidget *text_w = NULL;
48GtkWidget *hpaned = NULL;
49GtkWidget *vpaned = NULL;
50GtkWidget *back_btn = NULL;
Karsten Wiese0a0c5022006-12-13 00:34:09 -080051GtkWidget *save_btn = NULL;
52GtkWidget *save_menu_item = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -070053
54GtkTextTag *tag1, *tag2;
55GdkColor color;
56
57GtkTreeStore *tree1, *tree2, *tree;
58GtkTreeModel *model1, *model2;
59static GtkTreeIter *parents[256];
60static gint indent;
61
62static struct menu *current; // current node for SINGLE view
63static struct menu *browsed; // browsed node for SPLIT view
64
65enum {
66 COL_OPTION, COL_NAME, COL_NO, COL_MOD, COL_YES, COL_VALUE,
67 COL_MENU, COL_COLOR, COL_EDIT, COL_PIXBUF,
68 COL_PIXVIS, COL_BTNVIS, COL_BTNACT, COL_BTNINC, COL_BTNRAD,
69 COL_NUMBER
70};
71
72static void display_list(void);
73static void display_tree(struct menu *menu);
74static void display_tree_part(void);
75static void update_tree(struct menu *src, GtkTreeIter * dst);
76static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row);
77static gchar **fill_row(struct menu *menu);
Karsten Wiese0a0c5022006-12-13 00:34:09 -080078static void conf_changed(void);
Linus Torvalds1da177e2005-04-16 15:20:36 -070079
80/* Helping/Debugging Functions */
81
Li Zefan29442352010-04-14 11:44:34 +080082const char *dbg_sym_flags(int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -070083{
84 static char buf[256];
85
86 bzero(buf, 256);
87
Linus Torvalds1da177e2005-04-16 15:20:36 -070088 if (val & SYMBOL_CONST)
89 strcat(buf, "const/");
90 if (val & SYMBOL_CHECK)
91 strcat(buf, "check/");
92 if (val & SYMBOL_CHOICE)
93 strcat(buf, "choice/");
94 if (val & SYMBOL_CHOICEVAL)
95 strcat(buf, "choiceval/");
Linus Torvalds1da177e2005-04-16 15:20:36 -070096 if (val & SYMBOL_VALID)
97 strcat(buf, "valid/");
98 if (val & SYMBOL_OPTIONAL)
99 strcat(buf, "optional/");
100 if (val & SYMBOL_WRITE)
101 strcat(buf, "write/");
102 if (val & SYMBOL_CHANGED)
103 strcat(buf, "changed/");
Dirk Gouders693359f2018-07-03 14:43:31 +0200104 if (val & SYMBOL_NO_WRITE)
105 strcat(buf, "no_write/");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106
107 buf[strlen(buf) - 1] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108
109 return buf;
110}
111
Joachim Nilssonbafd2df2005-07-29 00:18:03 +0200112void replace_button_icon(GladeXML * xml, GdkDrawable * window,
113 GtkStyle * style, gchar * btn_name, gchar ** xpm)
114{
115 GdkPixmap *pixmap;
116 GdkBitmap *mask;
117 GtkToolButton *button;
118 GtkWidget *image;
119
120 pixmap = gdk_pixmap_create_from_xpm_d(window, &mask,
121 &style->bg[GTK_STATE_NORMAL],
122 xpm);
123
124 button = GTK_TOOL_BUTTON(glade_xml_get_widget(xml, btn_name));
125 image = gtk_image_new_from_pixmap(pixmap, mask);
126 gtk_widget_show(image);
127 gtk_tool_button_set_icon_widget(button, image);
128}
129
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130/* Main Window Initialization */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131void init_main_window(const gchar * glade_file)
132{
133 GladeXML *xml;
134 GtkWidget *widget;
135 GtkTextBuffer *txtbuf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136 GtkStyle *style;
137
138 xml = glade_xml_new(glade_file, "window1", NULL);
139 if (!xml)
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200140 g_error("GUI loading failed !\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141 glade_xml_signal_autoconnect(xml);
142
143 main_wnd = glade_xml_get_widget(xml, "window1");
144 hpaned = glade_xml_get_widget(xml, "hpaned1");
145 vpaned = glade_xml_get_widget(xml, "vpaned1");
146 tree1_w = glade_xml_get_widget(xml, "treeview1");
147 tree2_w = glade_xml_get_widget(xml, "treeview2");
148 text_w = glade_xml_get_widget(xml, "textview3");
149
150 back_btn = glade_xml_get_widget(xml, "button1");
151 gtk_widget_set_sensitive(back_btn, FALSE);
152
153 widget = glade_xml_get_widget(xml, "show_name1");
154 gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
155 show_name);
156
157 widget = glade_xml_get_widget(xml, "show_range1");
158 gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
159 show_range);
160
161 widget = glade_xml_get_widget(xml, "show_data1");
162 gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
163 show_value);
164
Karsten Wiese0a0c5022006-12-13 00:34:09 -0800165 save_btn = glade_xml_get_widget(xml, "button3");
166 save_menu_item = glade_xml_get_widget(xml, "save1");
167 conf_set_changed_callback(conf_changed);
168
Linus Torvalds1da177e2005-04-16 15:20:36 -0700169 style = gtk_widget_get_style(main_wnd);
170 widget = glade_xml_get_widget(xml, "toolbar1");
171
Joachim Nilssonbafd2df2005-07-29 00:18:03 +0200172 replace_button_icon(xml, main_wnd->window, style,
173 "button4", (gchar **) xpm_single_view);
174 replace_button_icon(xml, main_wnd->window, style,
175 "button5", (gchar **) xpm_split_view);
176 replace_button_icon(xml, main_wnd->window, style,
177 "button6", (gchar **) xpm_tree_view);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700178
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179 txtbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
180 tag1 = gtk_text_buffer_create_tag(txtbuf, "mytag1",
181 "foreground", "red",
182 "weight", PANGO_WEIGHT_BOLD,
183 NULL);
184 tag2 = gtk_text_buffer_create_tag(txtbuf, "mytag2",
185 /*"style", PANGO_STYLE_OBLIQUE, */
186 NULL);
187
Arnaud Lacombe09548282010-08-18 01:57:13 -0400188 gtk_window_set_title(GTK_WINDOW(main_wnd), rootmenu.prompt->text);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189
190 gtk_widget_show(main_wnd);
191}
192
193void init_tree_model(void)
194{
195 gint i;
196
197 tree = tree2 = gtk_tree_store_new(COL_NUMBER,
198 G_TYPE_STRING, G_TYPE_STRING,
199 G_TYPE_STRING, G_TYPE_STRING,
200 G_TYPE_STRING, G_TYPE_STRING,
201 G_TYPE_POINTER, GDK_TYPE_COLOR,
202 G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF,
203 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
204 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
205 G_TYPE_BOOLEAN);
206 model2 = GTK_TREE_MODEL(tree2);
207
208 for (parents[0] = NULL, i = 1; i < 256; i++)
209 parents[i] = (GtkTreeIter *) g_malloc(sizeof(GtkTreeIter));
210
211 tree1 = gtk_tree_store_new(COL_NUMBER,
212 G_TYPE_STRING, G_TYPE_STRING,
213 G_TYPE_STRING, G_TYPE_STRING,
214 G_TYPE_STRING, G_TYPE_STRING,
215 G_TYPE_POINTER, GDK_TYPE_COLOR,
216 G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF,
217 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
218 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
219 G_TYPE_BOOLEAN);
220 model1 = GTK_TREE_MODEL(tree1);
221}
222
223void init_left_tree(void)
224{
225 GtkTreeView *view = GTK_TREE_VIEW(tree1_w);
226 GtkCellRenderer *renderer;
227 GtkTreeSelection *sel;
228 GtkTreeViewColumn *column;
229
230 gtk_tree_view_set_model(view, model1);
231 gtk_tree_view_set_headers_visible(view, TRUE);
Eduardo Silva2626e672011-05-19 08:37:01 -0400232 gtk_tree_view_set_rules_hint(view, TRUE);
Joachim Nilssonbafd2df2005-07-29 00:18:03 +0200233
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234 column = gtk_tree_view_column_new();
235 gtk_tree_view_append_column(view, column);
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200236 gtk_tree_view_column_set_title(column, "Options");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237
238 renderer = gtk_cell_renderer_toggle_new();
239 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
240 renderer, FALSE);
241 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
242 renderer,
243 "active", COL_BTNACT,
244 "inconsistent", COL_BTNINC,
Joachim Nilssonbafd2df2005-07-29 00:18:03 +0200245 "visible", COL_BTNVIS,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246 "radio", COL_BTNRAD, NULL);
247 renderer = gtk_cell_renderer_text_new();
248 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
Joachim Nilssonbafd2df2005-07-29 00:18:03 +0200249 renderer, FALSE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
251 renderer,
252 "text", COL_OPTION,
253 "foreground-gdk",
254 COL_COLOR, NULL);
255
256 sel = gtk_tree_view_get_selection(view);
257 gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
258 gtk_widget_realize(tree1_w);
259}
260
261static void renderer_edited(GtkCellRendererText * cell,
262 const gchar * path_string,
263 const gchar * new_text, gpointer user_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264
265void init_right_tree(void)
266{
267 GtkTreeView *view = GTK_TREE_VIEW(tree2_w);
268 GtkCellRenderer *renderer;
269 GtkTreeSelection *sel;
270 GtkTreeViewColumn *column;
271 gint i;
272
273 gtk_tree_view_set_model(view, model2);
274 gtk_tree_view_set_headers_visible(view, TRUE);
Eduardo Silva2626e672011-05-19 08:37:01 -0400275 gtk_tree_view_set_rules_hint(view, TRUE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276
277 column = gtk_tree_view_column_new();
278 gtk_tree_view_append_column(view, column);
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200279 gtk_tree_view_column_set_title(column, "Options");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280
281 renderer = gtk_cell_renderer_pixbuf_new();
282 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
283 renderer, FALSE);
284 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
285 renderer,
286 "pixbuf", COL_PIXBUF,
287 "visible", COL_PIXVIS, NULL);
288 renderer = gtk_cell_renderer_toggle_new();
289 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
290 renderer, FALSE);
291 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
292 renderer,
293 "active", COL_BTNACT,
294 "inconsistent", COL_BTNINC,
Joachim Nilssonbafd2df2005-07-29 00:18:03 +0200295 "visible", COL_BTNVIS,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296 "radio", COL_BTNRAD, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297 renderer = gtk_cell_renderer_text_new();
298 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
299 renderer, FALSE);
300 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
301 renderer,
302 "text", COL_OPTION,
303 "foreground-gdk",
304 COL_COLOR, NULL);
305
306 renderer = gtk_cell_renderer_text_new();
307 gtk_tree_view_insert_column_with_attributes(view, -1,
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200308 "Name", renderer,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309 "text", COL_NAME,
310 "foreground-gdk",
311 COL_COLOR, NULL);
312 renderer = gtk_cell_renderer_text_new();
313 gtk_tree_view_insert_column_with_attributes(view, -1,
314 "N", renderer,
315 "text", COL_NO,
316 "foreground-gdk",
317 COL_COLOR, NULL);
318 renderer = gtk_cell_renderer_text_new();
319 gtk_tree_view_insert_column_with_attributes(view, -1,
320 "M", renderer,
321 "text", COL_MOD,
322 "foreground-gdk",
323 COL_COLOR, NULL);
324 renderer = gtk_cell_renderer_text_new();
325 gtk_tree_view_insert_column_with_attributes(view, -1,
326 "Y", renderer,
327 "text", COL_YES,
328 "foreground-gdk",
329 COL_COLOR, NULL);
330 renderer = gtk_cell_renderer_text_new();
331 gtk_tree_view_insert_column_with_attributes(view, -1,
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200332 "Value", renderer,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333 "text", COL_VALUE,
334 "editable",
335 COL_EDIT,
336 "foreground-gdk",
337 COL_COLOR, NULL);
338 g_signal_connect(G_OBJECT(renderer), "edited",
339 G_CALLBACK(renderer_edited), NULL);
340
341 column = gtk_tree_view_get_column(view, COL_NAME);
342 gtk_tree_view_column_set_visible(column, show_name);
343 column = gtk_tree_view_get_column(view, COL_NO);
344 gtk_tree_view_column_set_visible(column, show_range);
345 column = gtk_tree_view_get_column(view, COL_MOD);
346 gtk_tree_view_column_set_visible(column, show_range);
347 column = gtk_tree_view_get_column(view, COL_YES);
348 gtk_tree_view_column_set_visible(column, show_range);
349 column = gtk_tree_view_get_column(view, COL_VALUE);
350 gtk_tree_view_column_set_visible(column, show_value);
351
352 if (resizeable) {
353 for (i = 0; i < COL_VALUE; i++) {
354 column = gtk_tree_view_get_column(view, i);
355 gtk_tree_view_column_set_resizable(column, TRUE);
356 }
357 }
358
359 sel = gtk_tree_view_get_selection(view);
360 gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
361}
362
363
364/* Utility Functions */
365
366
367static void text_insert_help(struct menu *menu)
368{
369 GtkTextBuffer *buffer;
370 GtkTextIter start, end;
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200371 const char *prompt = menu_get_prompt(menu);
Cheng Renquan47791052009-07-12 16:11:46 +0800372 struct gstr help = str_new();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373
Cheng Renquan47791052009-07-12 16:11:46 +0800374 menu_get_ext_help(menu, &help);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375
376 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
377 gtk_text_buffer_get_bounds(buffer, &start, &end);
378 gtk_text_buffer_delete(buffer, &start, &end);
379 gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15);
380
381 gtk_text_buffer_get_end_iter(buffer, &end);
382 gtk_text_buffer_insert_with_tags(buffer, &end, prompt, -1, tag1,
383 NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384 gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2);
385 gtk_text_buffer_get_end_iter(buffer, &end);
Cheng Renquan47791052009-07-12 16:11:46 +0800386 gtk_text_buffer_insert_with_tags(buffer, &end, str_get(&help), -1, tag2,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387 NULL);
Cheng Renquan47791052009-07-12 16:11:46 +0800388 str_free(&help);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389}
390
391
392static void text_insert_msg(const char *title, const char *message)
393{
394 GtkTextBuffer *buffer;
395 GtkTextIter start, end;
396 const char *msg = message;
397
398 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
399 gtk_text_buffer_get_bounds(buffer, &start, &end);
400 gtk_text_buffer_delete(buffer, &start, &end);
401 gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15);
402
403 gtk_text_buffer_get_end_iter(buffer, &end);
404 gtk_text_buffer_insert_with_tags(buffer, &end, title, -1, tag1,
405 NULL);
406 gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2);
407 gtk_text_buffer_get_end_iter(buffer, &end);
408 gtk_text_buffer_insert_with_tags(buffer, &end, msg, -1, tag2,
409 NULL);
410}
411
412
413/* Main Windows Callbacks */
414
Karsten Wiese0a0c5022006-12-13 00:34:09 -0800415void on_save_activate(GtkMenuItem * menuitem, gpointer user_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416gboolean on_window1_delete_event(GtkWidget * widget, GdkEvent * event,
417 gpointer user_data)
418{
419 GtkWidget *dialog, *label;
420 gint result;
421
Karsten Wiese0a0c5022006-12-13 00:34:09 -0800422 if (!conf_get_changed())
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423 return FALSE;
424
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200425 dialog = gtk_dialog_new_with_buttons("Warning !",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426 GTK_WINDOW(main_wnd),
427 (GtkDialogFlags)
428 (GTK_DIALOG_MODAL |
429 GTK_DIALOG_DESTROY_WITH_PARENT),
430 GTK_STOCK_OK,
431 GTK_RESPONSE_YES,
432 GTK_STOCK_NO,
433 GTK_RESPONSE_NO,
434 GTK_STOCK_CANCEL,
435 GTK_RESPONSE_CANCEL, NULL);
436 gtk_dialog_set_default_response(GTK_DIALOG(dialog),
437 GTK_RESPONSE_CANCEL);
438
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200439 label = gtk_label_new("\nSave configuration ?\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label);
441 gtk_widget_show(label);
442
443 result = gtk_dialog_run(GTK_DIALOG(dialog));
444 switch (result) {
445 case GTK_RESPONSE_YES:
Karsten Wiese0a0c5022006-12-13 00:34:09 -0800446 on_save_activate(NULL, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447 return FALSE;
448 case GTK_RESPONSE_NO:
449 return FALSE;
450 case GTK_RESPONSE_CANCEL:
451 case GTK_RESPONSE_DELETE_EVENT:
452 default:
453 gtk_widget_destroy(dialog);
454 return TRUE;
455 }
456
457 return FALSE;
458}
459
460
461void on_window1_destroy(GtkObject * object, gpointer user_data)
462{
463 gtk_main_quit();
464}
465
466
467void
468on_window1_size_request(GtkWidget * widget,
469 GtkRequisition * requisition, gpointer user_data)
470{
471 static gint old_h;
472 gint w, h;
473
474 if (widget->window == NULL)
475 gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h);
476 else
477 gdk_window_get_size(widget->window, &w, &h);
478
479 if (h == old_h)
480 return;
481 old_h = h;
482
483 gtk_paned_set_position(GTK_PANED(vpaned), 2 * h / 3);
484}
485
486
487/* Menu & Toolbar Callbacks */
488
489
490static void
491load_filename(GtkFileSelection * file_selector, gpointer user_data)
492{
493 const gchar *fn;
494
495 fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION
496 (user_data));
497
498 if (conf_read(fn))
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200499 text_insert_msg("Error", "Unable to load configuration !");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500 else
501 display_tree(&rootmenu);
502}
503
504void on_load1_activate(GtkMenuItem * menuitem, gpointer user_data)
505{
506 GtkWidget *fs;
507
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200508 fs = gtk_file_selection_new("Load file...");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509 g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button),
510 "clicked",
511 G_CALLBACK(load_filename), (gpointer) fs);
512 g_signal_connect_swapped(GTK_OBJECT
513 (GTK_FILE_SELECTION(fs)->ok_button),
514 "clicked", G_CALLBACK(gtk_widget_destroy),
515 (gpointer) fs);
516 g_signal_connect_swapped(GTK_OBJECT
517 (GTK_FILE_SELECTION(fs)->cancel_button),
518 "clicked", G_CALLBACK(gtk_widget_destroy),
519 (gpointer) fs);
520 gtk_widget_show(fs);
521}
522
523
Karsten Wiese0a0c5022006-12-13 00:34:09 -0800524void on_save_activate(GtkMenuItem * menuitem, gpointer user_data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525{
526 if (conf_write(NULL))
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200527 text_insert_msg("Error", "Unable to save configuration !");
Masahiro Yamada00c864f2018-07-20 16:46:31 +0900528 conf_write_autoconf(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700529}
530
531
532static void
533store_filename(GtkFileSelection * file_selector, gpointer user_data)
534{
535 const gchar *fn;
536
537 fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION
538 (user_data));
539
540 if (conf_write(fn))
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200541 text_insert_msg("Error", "Unable to save configuration !");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542
543 gtk_widget_destroy(GTK_WIDGET(user_data));
544}
545
546void on_save_as1_activate(GtkMenuItem * menuitem, gpointer user_data)
547{
548 GtkWidget *fs;
549
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200550 fs = gtk_file_selection_new("Save file as...");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551 g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button),
552 "clicked",
553 G_CALLBACK(store_filename), (gpointer) fs);
554 g_signal_connect_swapped(GTK_OBJECT
555 (GTK_FILE_SELECTION(fs)->ok_button),
556 "clicked", G_CALLBACK(gtk_widget_destroy),
557 (gpointer) fs);
558 g_signal_connect_swapped(GTK_OBJECT
559 (GTK_FILE_SELECTION(fs)->cancel_button),
560 "clicked", G_CALLBACK(gtk_widget_destroy),
561 (gpointer) fs);
562 gtk_widget_show(fs);
563}
564
565
566void on_quit1_activate(GtkMenuItem * menuitem, gpointer user_data)
567{
568 if (!on_window1_delete_event(NULL, NULL, NULL))
569 gtk_widget_destroy(GTK_WIDGET(main_wnd));
570}
571
572
573void on_show_name1_activate(GtkMenuItem * menuitem, gpointer user_data)
574{
575 GtkTreeViewColumn *col;
576
577 show_name = GTK_CHECK_MENU_ITEM(menuitem)->active;
578 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NAME);
579 if (col)
580 gtk_tree_view_column_set_visible(col, show_name);
581}
582
583
584void on_show_range1_activate(GtkMenuItem * menuitem, gpointer user_data)
585{
586 GtkTreeViewColumn *col;
587
588 show_range = GTK_CHECK_MENU_ITEM(menuitem)->active;
589 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NO);
590 if (col)
591 gtk_tree_view_column_set_visible(col, show_range);
592 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_MOD);
593 if (col)
594 gtk_tree_view_column_set_visible(col, show_range);
595 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_YES);
596 if (col)
597 gtk_tree_view_column_set_visible(col, show_range);
598
599}
600
601
602void on_show_data1_activate(GtkMenuItem * menuitem, gpointer user_data)
603{
604 GtkTreeViewColumn *col;
605
606 show_value = GTK_CHECK_MENU_ITEM(menuitem)->active;
607 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_VALUE);
608 if (col)
609 gtk_tree_view_column_set_visible(col, show_value);
610}
611
612
613void
Li Zefan06f9a552010-04-14 11:46:24 +0800614on_set_option_mode1_activate(GtkMenuItem *menuitem, gpointer user_data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615{
Li Zefan06f9a552010-04-14 11:46:24 +0800616 opt_mode = OPT_NORMAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617 gtk_tree_store_clear(tree2);
Li Zefan06f9a552010-04-14 11:46:24 +0800618 display_tree(&rootmenu); /* instead of update_tree to speed-up */
619}
620
621
622void
623on_set_option_mode2_activate(GtkMenuItem *menuitem, gpointer user_data)
624{
625 opt_mode = OPT_ALL;
626 gtk_tree_store_clear(tree2);
627 display_tree(&rootmenu); /* instead of update_tree to speed-up */
628}
629
630
631void
632on_set_option_mode3_activate(GtkMenuItem *menuitem, gpointer user_data)
633{
634 opt_mode = OPT_PROMPT;
635 gtk_tree_store_clear(tree2);
636 display_tree(&rootmenu); /* instead of update_tree to speed-up */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637}
638
639
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data)
641{
642 GtkWidget *dialog;
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200643 const gchar *intro_text =
Arnaud Lacombe652cf982010-08-14 23:51:40 -0400644 "Welcome to gkc, the GTK+ graphical configuration tool\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645 "For each option, a blank box indicates the feature is disabled, a\n"
646 "check indicates it is enabled, and a dot indicates that it is to\n"
647 "be compiled as a module. Clicking on the box will cycle through the three states.\n"
648 "\n"
649 "If you do not see an option (e.g., a device driver) that you\n"
650 "believe should be present, try turning on Show All Options\n"
651 "under the Options menu.\n"
652 "Although there is no cross reference yet to help you figure out\n"
653 "what other options must be enabled to support the option you\n"
654 "are interested in, you can still view the help of a grayed-out\n"
655 "option.\n"
656 "\n"
657 "Toggling Show Debug Info under the Options menu will show \n"
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200658 "the dependencies, which you can then match by examining other options.";
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659
660 dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
661 GTK_DIALOG_DESTROY_WITH_PARENT,
662 GTK_MESSAGE_INFO,
Peter Foleya7d6f6e2011-10-22 13:19:02 -0400663 GTK_BUTTONS_CLOSE, "%s", intro_text);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664 g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
665 G_CALLBACK(gtk_widget_destroy),
666 GTK_OBJECT(dialog));
667 gtk_widget_show_all(dialog);
668}
669
670
671void on_about1_activate(GtkMenuItem * menuitem, gpointer user_data)
672{
673 GtkWidget *dialog;
674 const gchar *about_text =
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200675 "gkc is copyright (c) 2002 Romain Lievin <roms@lpg.ticalc.org>.\n"
676 "Based on the source code from Roman Zippel.\n";
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677
678 dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
679 GTK_DIALOG_DESTROY_WITH_PARENT,
680 GTK_MESSAGE_INFO,
Peter Foleya7d6f6e2011-10-22 13:19:02 -0400681 GTK_BUTTONS_CLOSE, "%s", about_text);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682 g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
683 G_CALLBACK(gtk_widget_destroy),
684 GTK_OBJECT(dialog));
685 gtk_widget_show_all(dialog);
686}
687
688
689void on_license1_activate(GtkMenuItem * menuitem, gpointer user_data)
690{
691 GtkWidget *dialog;
692 const gchar *license_text =
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200693 "gkc is released under the terms of the GNU GPL v2.\n"
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700694 "For more information, please see the source code or\n"
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200695 "visit http://www.fsf.org/licenses/licenses.html\n";
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696
697 dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
698 GTK_DIALOG_DESTROY_WITH_PARENT,
699 GTK_MESSAGE_INFO,
Peter Foleya7d6f6e2011-10-22 13:19:02 -0400700 GTK_BUTTONS_CLOSE, "%s", license_text);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701 g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
702 G_CALLBACK(gtk_widget_destroy),
703 GTK_OBJECT(dialog));
704 gtk_widget_show_all(dialog);
705}
706
707
Joachim Nilssonbafd2df2005-07-29 00:18:03 +0200708void on_back_clicked(GtkButton * button, gpointer user_data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709{
710 enum prop_type ptype;
711
712 current = current->parent;
713 ptype = current->prompt ? current->prompt->type : P_UNKNOWN;
714 if (ptype != P_MENU)
715 current = current->parent;
716 display_tree_part();
717
718 if (current == &rootmenu)
719 gtk_widget_set_sensitive(back_btn, FALSE);
720}
721
722
Joachim Nilssonbafd2df2005-07-29 00:18:03 +0200723void on_load_clicked(GtkButton * button, gpointer user_data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724{
725 on_load1_activate(NULL, user_data);
726}
727
728
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729void on_single_clicked(GtkButton * button, gpointer user_data)
730{
731 view_mode = SINGLE_VIEW;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732 gtk_widget_hide(tree1_w);
733 current = &rootmenu;
734 display_tree_part();
735}
736
737
738void on_split_clicked(GtkButton * button, gpointer user_data)
739{
740 gint w, h;
741 view_mode = SPLIT_VIEW;
742 gtk_widget_show(tree1_w);
743 gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h);
744 gtk_paned_set_position(GTK_PANED(hpaned), w / 2);
Joachim Nilssonbafd2df2005-07-29 00:18:03 +0200745 if (tree2)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746 gtk_tree_store_clear(tree2);
747 display_list();
Joachim Nilssonbafd2df2005-07-29 00:18:03 +0200748
749 /* Disable back btn, like in full mode. */
750 gtk_widget_set_sensitive(back_btn, FALSE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751}
752
753
754void on_full_clicked(GtkButton * button, gpointer user_data)
755{
756 view_mode = FULL_VIEW;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700757 gtk_widget_hide(tree1_w);
758 if (tree2)
759 gtk_tree_store_clear(tree2);
760 display_tree(&rootmenu);
761 gtk_widget_set_sensitive(back_btn, FALSE);
762}
763
764
Joachim Nilssonbafd2df2005-07-29 00:18:03 +0200765void on_collapse_clicked(GtkButton * button, gpointer user_data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766{
767 gtk_tree_view_collapse_all(GTK_TREE_VIEW(tree2_w));
768}
769
770
Joachim Nilssonbafd2df2005-07-29 00:18:03 +0200771void on_expand_clicked(GtkButton * button, gpointer user_data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772{
773 gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w));
774}
775
776
777/* CTree Callbacks */
778
779/* Change hex/int/string value in the cell */
780static void renderer_edited(GtkCellRendererText * cell,
781 const gchar * path_string,
782 const gchar * new_text, gpointer user_data)
783{
784 GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
785 GtkTreeIter iter;
786 const char *old_def, *new_def;
787 struct menu *menu;
788 struct symbol *sym;
789
790 if (!gtk_tree_model_get_iter(model2, &iter, path))
791 return;
792
793 gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
794 sym = menu->sym;
795
796 gtk_tree_model_get(model2, &iter, COL_VALUE, &old_def, -1);
797 new_def = new_text;
798
799 sym_set_string_value(sym, new_def);
800
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801 update_tree(&rootmenu, NULL);
802
803 gtk_tree_path_free(path);
804}
805
806/* Change the value of a symbol and update the tree */
807static void change_sym_value(struct menu *menu, gint col)
808{
809 struct symbol *sym = menu->sym;
Peter Foley4f0c28f2011-10-22 14:01:24 -0400810 tristate newval;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811
812 if (!sym)
813 return;
814
815 if (col == COL_NO)
816 newval = no;
817 else if (col == COL_MOD)
818 newval = mod;
819 else if (col == COL_YES)
820 newval = yes;
821 else
822 return;
823
824 switch (sym_get_type(sym)) {
825 case S_BOOLEAN:
826 case S_TRISTATE:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827 if (!sym_tristate_within_range(sym, newval))
828 newval = yes;
829 sym_set_tristate_value(sym, newval);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830 if (view_mode == FULL_VIEW)
831 update_tree(&rootmenu, NULL);
832 else if (view_mode == SPLIT_VIEW) {
833 update_tree(browsed, NULL);
834 display_list();
835 }
836 else if (view_mode == SINGLE_VIEW)
837 display_tree_part(); //fixme: keep exp/coll
838 break;
839 case S_INT:
840 case S_HEX:
841 case S_STRING:
842 default:
843 break;
844 }
845}
846
847static void toggle_sym_value(struct menu *menu)
848{
849 if (!menu->sym)
850 return;
851
852 sym_toggle_tristate_value(menu->sym);
853 if (view_mode == FULL_VIEW)
854 update_tree(&rootmenu, NULL);
855 else if (view_mode == SPLIT_VIEW) {
856 update_tree(browsed, NULL);
857 display_list();
858 }
859 else if (view_mode == SINGLE_VIEW)
860 display_tree_part(); //fixme: keep exp/coll
861}
862
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863static gint column2index(GtkTreeViewColumn * column)
864{
865 gint i;
866
867 for (i = 0; i < COL_NUMBER; i++) {
868 GtkTreeViewColumn *col;
869
870 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), i);
871 if (col == column)
872 return i;
873 }
874
875 return -1;
876}
877
878
879/* User click: update choice (full) or goes down (single) */
880gboolean
881on_treeview2_button_press_event(GtkWidget * widget,
882 GdkEventButton * event, gpointer user_data)
883{
884 GtkTreeView *view = GTK_TREE_VIEW(widget);
885 GtkTreePath *path;
886 GtkTreeViewColumn *column;
887 GtkTreeIter iter;
888 struct menu *menu;
889 gint col;
890
891#if GTK_CHECK_VERSION(2,1,4) // bug in ctree with earlier version of GTK
892 gint tx = (gint) event->x;
893 gint ty = (gint) event->y;
894 gint cx, cy;
895
896 gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx,
897 &cy);
898#else
899 gtk_tree_view_get_cursor(view, &path, &column);
900#endif
901 if (path == NULL)
902 return FALSE;
903
904 if (!gtk_tree_model_get_iter(model2, &iter, path))
905 return FALSE;
906 gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
907
908 col = column2index(column);
909 if (event->type == GDK_2BUTTON_PRESS) {
910 enum prop_type ptype;
911 ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
912
913 if (ptype == P_MENU && view_mode != FULL_VIEW && col == COL_OPTION) {
914 // goes down into menu
915 current = menu;
916 display_tree_part();
917 gtk_widget_set_sensitive(back_btn, TRUE);
Nicolas Iooss9be32132017-03-13 20:33:41 +0100918 } else if (col == COL_OPTION) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919 toggle_sym_value(menu);
920 gtk_tree_view_expand_row(view, path, TRUE);
921 }
922 } else {
923 if (col == COL_VALUE) {
924 toggle_sym_value(menu);
925 gtk_tree_view_expand_row(view, path, TRUE);
926 } else if (col == COL_NO || col == COL_MOD
927 || col == COL_YES) {
928 change_sym_value(menu, col);
929 gtk_tree_view_expand_row(view, path, TRUE);
930 }
931 }
932
933 return FALSE;
934}
935
936/* Key pressed: update choice */
937gboolean
938on_treeview2_key_press_event(GtkWidget * widget,
939 GdkEventKey * event, gpointer user_data)
940{
941 GtkTreeView *view = GTK_TREE_VIEW(widget);
942 GtkTreePath *path;
943 GtkTreeViewColumn *column;
944 GtkTreeIter iter;
945 struct menu *menu;
946 gint col;
947
948 gtk_tree_view_get_cursor(view, &path, &column);
949 if (path == NULL)
950 return FALSE;
951
952 if (event->keyval == GDK_space) {
953 if (gtk_tree_view_row_expanded(view, path))
954 gtk_tree_view_collapse_row(view, path);
955 else
956 gtk_tree_view_expand_row(view, path, FALSE);
957 return TRUE;
958 }
959 if (event->keyval == GDK_KP_Enter) {
960 }
961 if (widget == tree1_w)
962 return FALSE;
963
964 gtk_tree_model_get_iter(model2, &iter, path);
965 gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
966
967 if (!strcasecmp(event->string, "n"))
968 col = COL_NO;
969 else if (!strcasecmp(event->string, "m"))
970 col = COL_MOD;
971 else if (!strcasecmp(event->string, "y"))
972 col = COL_YES;
973 else
974 col = -1;
975 change_sym_value(menu, col);
976
977 return FALSE;
978}
979
980
981/* Row selection changed: update help */
982void
983on_treeview2_cursor_changed(GtkTreeView * treeview, gpointer user_data)
984{
985 GtkTreeSelection *selection;
986 GtkTreeIter iter;
987 struct menu *menu;
988
989 selection = gtk_tree_view_get_selection(treeview);
990 if (gtk_tree_selection_get_selected(selection, &model2, &iter)) {
991 gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
992 text_insert_help(menu);
993 }
994}
995
996
997/* User click: display sub-tree in the right frame. */
998gboolean
999on_treeview1_button_press_event(GtkWidget * widget,
1000 GdkEventButton * event, gpointer user_data)
1001{
1002 GtkTreeView *view = GTK_TREE_VIEW(widget);
1003 GtkTreePath *path;
1004 GtkTreeViewColumn *column;
1005 GtkTreeIter iter;
1006 struct menu *menu;
1007
1008 gint tx = (gint) event->x;
1009 gint ty = (gint) event->y;
1010 gint cx, cy;
1011
1012 gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx,
1013 &cy);
1014 if (path == NULL)
1015 return FALSE;
1016
1017 gtk_tree_model_get_iter(model1, &iter, path);
1018 gtk_tree_model_get(model1, &iter, COL_MENU, &menu, -1);
1019
1020 if (event->type == GDK_2BUTTON_PRESS) {
1021 toggle_sym_value(menu);
1022 current = menu;
1023 display_tree_part();
1024 } else {
1025 browsed = menu;
1026 display_tree_part();
1027 }
1028
1029 gtk_widget_realize(tree2_w);
1030 gtk_tree_view_set_cursor(view, path, NULL, FALSE);
1031 gtk_widget_grab_focus(tree2_w);
1032
1033 return FALSE;
1034}
1035
1036
1037/* Fill a row of strings */
1038static gchar **fill_row(struct menu *menu)
1039{
1040 static gchar *row[COL_NUMBER];
1041 struct symbol *sym = menu->sym;
1042 const char *def;
1043 int stype;
1044 tristate val;
1045 enum prop_type ptype;
1046 int i;
1047
1048 for (i = COL_OPTION; i <= COL_COLOR; i++)
1049 g_free(row[i]);
1050 bzero(row, sizeof(row));
1051
1052 row[COL_OPTION] =
Sam Ravnborg694c49a2018-05-22 21:36:12 +02001053 g_strdup_printf("%s %s", menu_get_prompt(menu),
Li Zefane0bb7fe2010-05-07 13:57:35 +08001054 sym && !sym_has_value(sym) ? "(NEW)" : "");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055
Li Zefan06f9a552010-04-14 11:46:24 +08001056 if (opt_mode == OPT_ALL && !menu_is_visible(menu))
1057 row[COL_COLOR] = g_strdup("DarkGray");
1058 else if (opt_mode == OPT_PROMPT &&
1059 menu_has_prompt(menu) && !menu_is_visible(menu))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060 row[COL_COLOR] = g_strdup("DarkGray");
1061 else
1062 row[COL_COLOR] = g_strdup("Black");
1063
1064 ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
1065 switch (ptype) {
1066 case P_MENU:
1067 row[COL_PIXBUF] = (gchar *) xpm_menu;
1068 if (view_mode == SINGLE_VIEW)
1069 row[COL_PIXVIS] = GINT_TO_POINTER(TRUE);
1070 row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
1071 break;
1072 case P_COMMENT:
1073 row[COL_PIXBUF] = (gchar *) xpm_void;
1074 row[COL_PIXVIS] = GINT_TO_POINTER(FALSE);
1075 row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
1076 break;
1077 default:
1078 row[COL_PIXBUF] = (gchar *) xpm_void;
1079 row[COL_PIXVIS] = GINT_TO_POINTER(FALSE);
1080 row[COL_BTNVIS] = GINT_TO_POINTER(TRUE);
1081 break;
1082 }
1083
1084 if (!sym)
1085 return row;
1086 row[COL_NAME] = g_strdup(sym->name);
1087
1088 sym_calc_value(sym);
1089 sym->flags &= ~SYMBOL_CHANGED;
1090
1091 if (sym_is_choice(sym)) { // parse childs for getting final value
1092 struct menu *child;
1093 struct symbol *def_sym = sym_get_choice_value(sym);
1094 struct menu *def_menu = NULL;
1095
1096 row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
1097
1098 for (child = menu->list; child; child = child->next) {
1099 if (menu_is_visible(child)
1100 && child->sym == def_sym)
1101 def_menu = child;
1102 }
1103
1104 if (def_menu)
1105 row[COL_VALUE] =
Sam Ravnborg694c49a2018-05-22 21:36:12 +02001106 g_strdup(menu_get_prompt(def_menu));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107 }
Joachim Nilssonbafd2df2005-07-29 00:18:03 +02001108 if (sym->flags & SYMBOL_CHOICEVAL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109 row[COL_BTNRAD] = GINT_TO_POINTER(TRUE);
1110
1111 stype = sym_get_type(sym);
1112 switch (stype) {
1113 case S_BOOLEAN:
Joachim Nilssonbafd2df2005-07-29 00:18:03 +02001114 if (GPOINTER_TO_INT(row[COL_PIXVIS]) == FALSE)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115 row[COL_BTNVIS] = GINT_TO_POINTER(TRUE);
1116 if (sym_is_choice(sym))
1117 break;
Arnaud Lacombed8fc3202011-05-31 12:30:26 -04001118 /* fall through */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119 case S_TRISTATE:
1120 val = sym_get_tristate_value(sym);
1121 switch (val) {
1122 case no:
1123 row[COL_NO] = g_strdup("N");
1124 row[COL_VALUE] = g_strdup("N");
1125 row[COL_BTNACT] = GINT_TO_POINTER(FALSE);
1126 row[COL_BTNINC] = GINT_TO_POINTER(FALSE);
1127 break;
1128 case mod:
1129 row[COL_MOD] = g_strdup("M");
1130 row[COL_VALUE] = g_strdup("M");
1131 row[COL_BTNINC] = GINT_TO_POINTER(TRUE);
1132 break;
1133 case yes:
1134 row[COL_YES] = g_strdup("Y");
1135 row[COL_VALUE] = g_strdup("Y");
1136 row[COL_BTNACT] = GINT_TO_POINTER(TRUE);
1137 row[COL_BTNINC] = GINT_TO_POINTER(FALSE);
1138 break;
1139 }
1140
1141 if (val != no && sym_tristate_within_range(sym, no))
1142 row[COL_NO] = g_strdup("_");
1143 if (val != mod && sym_tristate_within_range(sym, mod))
1144 row[COL_MOD] = g_strdup("_");
1145 if (val != yes && sym_tristate_within_range(sym, yes))
1146 row[COL_YES] = g_strdup("_");
1147 break;
1148 case S_INT:
1149 case S_HEX:
1150 case S_STRING:
1151 def = sym_get_string_value(sym);
1152 row[COL_VALUE] = g_strdup(def);
1153 row[COL_EDIT] = GINT_TO_POINTER(TRUE);
1154 row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
1155 break;
1156 }
1157
1158 return row;
1159}
1160
1161
1162/* Set the node content with a row of strings */
1163static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row)
1164{
1165 GdkColor color;
1166 gboolean success;
1167 GdkPixbuf *pix;
1168
1169 pix = gdk_pixbuf_new_from_xpm_data((const char **)
1170 row[COL_PIXBUF]);
1171
1172 gdk_color_parse(row[COL_COLOR], &color);
1173 gdk_colormap_alloc_colors(gdk_colormap_get_system(), &color, 1,
1174 FALSE, FALSE, &success);
1175
1176 gtk_tree_store_set(tree, node,
1177 COL_OPTION, row[COL_OPTION],
1178 COL_NAME, row[COL_NAME],
1179 COL_NO, row[COL_NO],
1180 COL_MOD, row[COL_MOD],
1181 COL_YES, row[COL_YES],
1182 COL_VALUE, row[COL_VALUE],
1183 COL_MENU, (gpointer) menu,
1184 COL_COLOR, &color,
1185 COL_EDIT, GPOINTER_TO_INT(row[COL_EDIT]),
1186 COL_PIXBUF, pix,
1187 COL_PIXVIS, GPOINTER_TO_INT(row[COL_PIXVIS]),
1188 COL_BTNVIS, GPOINTER_TO_INT(row[COL_BTNVIS]),
1189 COL_BTNACT, GPOINTER_TO_INT(row[COL_BTNACT]),
1190 COL_BTNINC, GPOINTER_TO_INT(row[COL_BTNINC]),
1191 COL_BTNRAD, GPOINTER_TO_INT(row[COL_BTNRAD]),
1192 -1);
1193
1194 g_object_unref(pix);
1195}
1196
1197
1198/* Add a node to the tree */
1199static void place_node(struct menu *menu, char **row)
1200{
1201 GtkTreeIter *parent = parents[indent - 1];
1202 GtkTreeIter *node = parents[indent];
1203
1204 gtk_tree_store_append(tree, node, parent);
1205 set_node(node, menu, row);
1206}
1207
1208
1209/* Find a node in the GTK+ tree */
1210static GtkTreeIter found;
1211
1212/*
1213 * Find a menu in the GtkTree starting at parent.
1214 */
1215GtkTreeIter *gtktree_iter_find_node(GtkTreeIter * parent,
1216 struct menu *tofind)
1217{
1218 GtkTreeIter iter;
1219 GtkTreeIter *child = &iter;
1220 gboolean valid;
1221 GtkTreeIter *ret;
1222
1223 valid = gtk_tree_model_iter_children(model2, child, parent);
1224 while (valid) {
1225 struct menu *menu;
1226
1227 gtk_tree_model_get(model2, child, 6, &menu, -1);
1228
1229 if (menu == tofind) {
1230 memcpy(&found, child, sizeof(GtkTreeIter));
1231 return &found;
1232 }
1233
1234 ret = gtktree_iter_find_node(child, tofind);
1235 if (ret)
1236 return ret;
1237
1238 valid = gtk_tree_model_iter_next(model2, child);
1239 }
1240
1241 return NULL;
1242}
1243
1244
1245/*
1246 * Update the tree by adding/removing entries
1247 * Does not change other nodes
1248 */
1249static void update_tree(struct menu *src, GtkTreeIter * dst)
1250{
1251 struct menu *child1;
1252 GtkTreeIter iter, tmp;
1253 GtkTreeIter *child2 = &iter;
1254 gboolean valid;
1255 GtkTreeIter *sibling;
1256 struct symbol *sym;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257 struct menu *menu1, *menu2;
1258
1259 if (src == &rootmenu)
1260 indent = 1;
1261
1262 valid = gtk_tree_model_iter_children(model2, child2, dst);
1263 for (child1 = src->list; child1; child1 = child1->next) {
1264
Linus Torvalds1da177e2005-04-16 15:20:36 -07001265 sym = child1->sym;
1266
1267 reparse:
1268 menu1 = child1;
1269 if (valid)
1270 gtk_tree_model_get(model2, child2, COL_MENU,
1271 &menu2, -1);
1272 else
1273 menu2 = NULL; // force adding of a first child
1274
1275#ifdef DEBUG
1276 printf("%*c%s | %s\n", indent, ' ',
1277 menu1 ? menu_get_prompt(menu1) : "nil",
1278 menu2 ? menu_get_prompt(menu2) : "nil");
1279#endif
1280
Li Zefan06f9a552010-04-14 11:46:24 +08001281 if ((opt_mode == OPT_NORMAL && !menu_is_visible(child1)) ||
Li Zefanc10d03c2010-05-07 13:57:49 +08001282 (opt_mode == OPT_PROMPT && !menu_has_prompt(child1)) ||
1283 (opt_mode == OPT_ALL && !menu_get_prompt(child1))) {
Li Zefan06f9a552010-04-14 11:46:24 +08001284
1285 /* remove node */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286 if (gtktree_iter_find_node(dst, menu1) != NULL) {
1287 memcpy(&tmp, child2, sizeof(GtkTreeIter));
1288 valid = gtk_tree_model_iter_next(model2,
1289 child2);
1290 gtk_tree_store_remove(tree2, &tmp);
1291 if (!valid)
Li Zefan06f9a552010-04-14 11:46:24 +08001292 return; /* next parent */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001293 else
Li Zefan06f9a552010-04-14 11:46:24 +08001294 goto reparse; /* next child */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001295 } else
1296 continue;
1297 }
1298
1299 if (menu1 != menu2) {
1300 if (gtktree_iter_find_node(dst, menu1) == NULL) { // add node
1301 if (!valid && !menu2)
1302 sibling = NULL;
1303 else
1304 sibling = child2;
1305 gtk_tree_store_insert_before(tree2,
1306 child2,
1307 dst, sibling);
1308 set_node(child2, menu1, fill_row(menu1));
1309 if (menu2 == NULL)
1310 valid = TRUE;
1311 } else { // remove node
1312 memcpy(&tmp, child2, sizeof(GtkTreeIter));
1313 valid = gtk_tree_model_iter_next(model2,
1314 child2);
1315 gtk_tree_store_remove(tree2, &tmp);
1316 if (!valid)
Joachim Nilssonbafd2df2005-07-29 00:18:03 +02001317 return; // next parent
Linus Torvalds1da177e2005-04-16 15:20:36 -07001318 else
1319 goto reparse; // next child
1320 }
1321 } else if (sym && (sym->flags & SYMBOL_CHANGED)) {
1322 set_node(child2, menu1, fill_row(menu1));
1323 }
1324
1325 indent++;
1326 update_tree(child1, child2);
1327 indent--;
1328
1329 valid = gtk_tree_model_iter_next(model2, child2);
1330 }
1331}
1332
1333
1334/* Display the whole tree (single/split/full view) */
1335static void display_tree(struct menu *menu)
1336{
1337 struct symbol *sym;
1338 struct property *prop;
1339 struct menu *child;
1340 enum prop_type ptype;
1341
1342 if (menu == &rootmenu) {
1343 indent = 1;
1344 current = &rootmenu;
1345 }
1346
1347 for (child = menu->list; child; child = child->next) {
1348 prop = child->prompt;
1349 sym = child->sym;
1350 ptype = prop ? prop->type : P_UNKNOWN;
1351
1352 if (sym)
1353 sym->flags &= ~SYMBOL_CHANGED;
1354
Joachim Nilssonbafd2df2005-07-29 00:18:03 +02001355 if ((view_mode == SPLIT_VIEW)
1356 && !(child->flags & MENU_ROOT) && (tree == tree1))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357 continue;
1358
Joachim Nilssonbafd2df2005-07-29 00:18:03 +02001359 if ((view_mode == SPLIT_VIEW) && (child->flags & MENU_ROOT)
1360 && (tree == tree2))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361 continue;
1362
Li Zefan06f9a552010-04-14 11:46:24 +08001363 if ((opt_mode == OPT_NORMAL && menu_is_visible(child)) ||
1364 (opt_mode == OPT_PROMPT && menu_has_prompt(child)) ||
Li Zefanc10d03c2010-05-07 13:57:49 +08001365 (opt_mode == OPT_ALL && menu_get_prompt(child)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001366 place_node(child, fill_row(child));
1367#ifdef DEBUG
1368 printf("%*c%s: ", indent, ' ', menu_get_prompt(child));
1369 printf("%s", child->flags & MENU_ROOT ? "rootmenu | " : "");
Li Zefan29442352010-04-14 11:44:34 +08001370 printf("%s", prop_get_type_name(ptype));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371 printf(" | ");
1372 if (sym) {
Li Zefan29442352010-04-14 11:44:34 +08001373 printf("%s", sym_type_name(sym->type));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374 printf(" | ");
Li Zefan29442352010-04-14 11:44:34 +08001375 printf("%s", dbg_sym_flags(sym->flags));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001376 printf("\n");
1377 } else
1378 printf("\n");
1379#endif
1380 if ((view_mode != FULL_VIEW) && (ptype == P_MENU)
1381 && (tree == tree2))
1382 continue;
1383/*
Masahiro Yamadabb66fc62014-06-10 19:08:13 +09001384 if (((menu != &rootmenu) && !(menu->flags & MENU_ROOT))
Joachim Nilssonbafd2df2005-07-29 00:18:03 +02001385 || (view_mode == FULL_VIEW)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386 || (view_mode == SPLIT_VIEW))*/
Eduardo Silva6ef3d362011-05-19 08:38:25 -04001387
1388 /* Change paned position if the view is not in 'split mode' */
1389 if (view_mode == SINGLE_VIEW || view_mode == FULL_VIEW) {
1390 gtk_paned_set_position(GTK_PANED(hpaned), 0);
1391 }
1392
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393 if (((view_mode == SINGLE_VIEW) && (menu->flags & MENU_ROOT))
Joachim Nilssonbafd2df2005-07-29 00:18:03 +02001394 || (view_mode == FULL_VIEW)
1395 || (view_mode == SPLIT_VIEW)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001396 indent++;
1397 display_tree(child);
1398 indent--;
1399 }
1400 }
1401}
1402
1403/* Display a part of the tree starting at current node (single/split view) */
1404static void display_tree_part(void)
1405{
1406 if (tree2)
1407 gtk_tree_store_clear(tree2);
Joachim Nilssonbafd2df2005-07-29 00:18:03 +02001408 if (view_mode == SINGLE_VIEW)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001409 display_tree(current);
Joachim Nilssonbafd2df2005-07-29 00:18:03 +02001410 else if (view_mode == SPLIT_VIEW)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411 display_tree(browsed);
1412 gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w));
1413}
1414
1415/* Display the list in the left frame (split view) */
1416static void display_list(void)
1417{
1418 if (tree1)
1419 gtk_tree_store_clear(tree1);
1420
1421 tree = tree1;
1422 display_tree(&rootmenu);
1423 gtk_tree_view_expand_all(GTK_TREE_VIEW(tree1_w));
1424 tree = tree2;
1425}
1426
1427void fixup_rootmenu(struct menu *menu)
1428{
Joachim Nilssonbafd2df2005-07-29 00:18:03 +02001429 struct menu *child;
1430 static int menu_cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001431
Joachim Nilssonbafd2df2005-07-29 00:18:03 +02001432 menu->flags |= MENU_ROOT;
1433 for (child = menu->list; child; child = child->next) {
1434 if (child->prompt && child->prompt->type == P_MENU) {
1435 menu_cnt++;
1436 fixup_rootmenu(child);
1437 menu_cnt--;
1438 } else if (!menu_cnt)
1439 fixup_rootmenu(child);
1440 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441}
1442
1443
1444/* Main */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001445int main(int ac, char *av[])
1446{
1447 const char *name;
1448 char *env;
1449 gchar *glade_file;
1450
Linus Torvalds1da177e2005-04-16 15:20:36 -07001451 /* GTK stuffs */
1452 gtk_set_locale();
1453 gtk_init(&ac, &av);
1454 glade_init();
1455
1456 //add_pixmap_directory (PACKAGE_DATA_DIR "/" PACKAGE "/pixmaps");
1457 //add_pixmap_directory (PACKAGE_SOURCE_DIR "/pixmaps");
1458
1459 /* Determine GUI path */
1460 env = getenv(SRCTREE);
1461 if (env)
1462 glade_file = g_strconcat(env, "/scripts/kconfig/gconf.glade", NULL);
1463 else if (av[0][0] == '/')
1464 glade_file = g_strconcat(av[0], ".glade", NULL);
1465 else
1466 glade_file = g_strconcat(g_get_current_dir(), "/", av[0], ".glade", NULL);
1467
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468 /* Conf stuffs */
1469 if (ac > 1 && av[1][0] == '-') {
1470 switch (av[1][1]) {
1471 case 'a':
1472 //showAll = 1;
1473 break;
Michal Marek0a1f00a2015-04-08 13:30:42 +02001474 case 's':
1475 conf_set_message_callback(NULL);
1476 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001477 case 'h':
1478 case '?':
Michal Marek0a1f00a2015-04-08 13:30:42 +02001479 printf("%s [-s] <config>\n", av[0]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001480 exit(0);
1481 }
1482 name = av[2];
1483 } else
1484 name = av[1];
1485
1486 conf_parse(name);
1487 fixup_rootmenu(&rootmenu);
1488 conf_read(NULL);
1489
Arnaud Lacombec55c9d52010-09-19 22:47:17 -04001490 /* Load the interface and connect signals */
1491 init_main_window(glade_file);
1492 init_tree_model();
1493 init_left_tree();
1494 init_right_tree();
1495
Linus Torvalds1da177e2005-04-16 15:20:36 -07001496 switch (view_mode) {
1497 case SINGLE_VIEW:
1498 display_tree_part();
1499 break;
1500 case SPLIT_VIEW:
1501 display_list();
1502 break;
1503 case FULL_VIEW:
1504 display_tree(&rootmenu);
1505 break;
1506 }
1507
1508 gtk_main();
1509
1510 return 0;
1511}
Karsten Wiese0a0c5022006-12-13 00:34:09 -08001512
1513static void conf_changed(void)
1514{
1515 bool changed = conf_get_changed();
1516 gtk_widget_set_sensitive(save_btn, changed);
1517 gtk_widget_set_sensitive(save_menu_item, changed);
1518}