blob: b3d438c531fce8c2a7c3ade834dabc5da2132126 [file] [log] [blame]
Masahiro Yamada0c874102018-12-18 21:13:35 +09001// SPDX-License-Identifier: GPL-2.0
Linus Torvalds1da177e2005-04-16 15:20:36 -07002/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07003 * Copyright (C) 2002-2003 Romain Lievin <roms@tilp.info>
Linus Torvalds1da177e2005-04-16 15:20:36 -07004 */
5
6#ifdef HAVE_CONFIG_H
7# include <config.h>
8#endif
9
Yann E. MORIN9a926d42012-10-20 01:06:25 +020010#include <stdlib.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070011#include "lkc.h"
Masahiro Yamada3b541978562018-12-21 17:33:07 +090012#include "images.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070013
14#include <glade/glade.h>
15#include <gtk/gtk.h>
16#include <glib.h>
17#include <gdk/gdkkeysyms.h>
18
19#include <stdio.h>
20#include <string.h>
21#include <unistd.h>
22#include <time.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070023
24//#define DEBUG
25
26enum {
27 SINGLE_VIEW, SPLIT_VIEW, FULL_VIEW
28};
29
Li Zefan06f9a552010-04-14 11:46:24 +080030enum {
31 OPT_NORMAL, OPT_ALL, OPT_PROMPT
32};
33
Linus Torvalds1da177e2005-04-16 15:20:36 -070034static gint view_mode = FULL_VIEW;
35static gboolean show_name = TRUE;
36static gboolean show_range = TRUE;
37static gboolean show_value = TRUE;
Linus Torvalds1da177e2005-04-16 15:20:36 -070038static gboolean resizeable = FALSE;
Li Zefan06f9a552010-04-14 11:46:24 +080039static int opt_mode = OPT_NORMAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -070040
Linus Torvalds1da177e2005-04-16 15:20:36 -070041GtkWidget *main_wnd = NULL;
42GtkWidget *tree1_w = NULL; // left frame
43GtkWidget *tree2_w = NULL; // right frame
44GtkWidget *text_w = NULL;
45GtkWidget *hpaned = NULL;
46GtkWidget *vpaned = NULL;
47GtkWidget *back_btn = NULL;
Karsten Wiese0a0c5022006-12-13 00:34:09 -080048GtkWidget *save_btn = NULL;
49GtkWidget *save_menu_item = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -070050
51GtkTextTag *tag1, *tag2;
52GdkColor color;
53
54GtkTreeStore *tree1, *tree2, *tree;
55GtkTreeModel *model1, *model2;
56static GtkTreeIter *parents[256];
57static gint indent;
58
59static struct menu *current; // current node for SINGLE view
60static struct menu *browsed; // browsed node for SPLIT view
61
62enum {
63 COL_OPTION, COL_NAME, COL_NO, COL_MOD, COL_YES, COL_VALUE,
64 COL_MENU, COL_COLOR, COL_EDIT, COL_PIXBUF,
65 COL_PIXVIS, COL_BTNVIS, COL_BTNACT, COL_BTNINC, COL_BTNRAD,
66 COL_NUMBER
67};
68
69static void display_list(void);
70static void display_tree(struct menu *menu);
71static void display_tree_part(void);
72static void update_tree(struct menu *src, GtkTreeIter * dst);
73static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row);
74static gchar **fill_row(struct menu *menu);
Karsten Wiese0a0c5022006-12-13 00:34:09 -080075static void conf_changed(void);
Linus Torvalds1da177e2005-04-16 15:20:36 -070076
77/* Helping/Debugging Functions */
78
Masahiro Yamada9abe4232018-12-21 17:33:06 +090079static const char *dbg_sym_flags(int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -070080{
81 static char buf[256];
82
83 bzero(buf, 256);
84
Linus Torvalds1da177e2005-04-16 15:20:36 -070085 if (val & SYMBOL_CONST)
86 strcat(buf, "const/");
87 if (val & SYMBOL_CHECK)
88 strcat(buf, "check/");
89 if (val & SYMBOL_CHOICE)
90 strcat(buf, "choice/");
91 if (val & SYMBOL_CHOICEVAL)
92 strcat(buf, "choiceval/");
Linus Torvalds1da177e2005-04-16 15:20:36 -070093 if (val & SYMBOL_VALID)
94 strcat(buf, "valid/");
95 if (val & SYMBOL_OPTIONAL)
96 strcat(buf, "optional/");
97 if (val & SYMBOL_WRITE)
98 strcat(buf, "write/");
99 if (val & SYMBOL_CHANGED)
100 strcat(buf, "changed/");
Dirk Gouders693359f2018-07-03 14:43:31 +0200101 if (val & SYMBOL_NO_WRITE)
102 strcat(buf, "no_write/");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103
104 buf[strlen(buf) - 1] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105
106 return buf;
107}
108
Masahiro Yamada9abe4232018-12-21 17:33:06 +0900109static void replace_button_icon(GladeXML *xml, GdkDrawable *window,
110 GtkStyle *style, gchar *btn_name, gchar **xpm)
Joachim Nilssonbafd2df2005-07-29 00:18:03 +0200111{
112 GdkPixmap *pixmap;
113 GdkBitmap *mask;
114 GtkToolButton *button;
115 GtkWidget *image;
116
117 pixmap = gdk_pixmap_create_from_xpm_d(window, &mask,
118 &style->bg[GTK_STATE_NORMAL],
119 xpm);
120
121 button = GTK_TOOL_BUTTON(glade_xml_get_widget(xml, btn_name));
122 image = gtk_image_new_from_pixmap(pixmap, mask);
123 gtk_widget_show(image);
124 gtk_tool_button_set_icon_widget(button, image);
125}
126
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127/* Main Window Initialization */
Masahiro Yamada9abe4232018-12-21 17:33:06 +0900128static void init_main_window(const gchar *glade_file)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129{
130 GladeXML *xml;
131 GtkWidget *widget;
132 GtkTextBuffer *txtbuf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133 GtkStyle *style;
134
135 xml = glade_xml_new(glade_file, "window1", NULL);
136 if (!xml)
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200137 g_error("GUI loading failed !\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138 glade_xml_signal_autoconnect(xml);
139
140 main_wnd = glade_xml_get_widget(xml, "window1");
141 hpaned = glade_xml_get_widget(xml, "hpaned1");
142 vpaned = glade_xml_get_widget(xml, "vpaned1");
143 tree1_w = glade_xml_get_widget(xml, "treeview1");
144 tree2_w = glade_xml_get_widget(xml, "treeview2");
145 text_w = glade_xml_get_widget(xml, "textview3");
146
147 back_btn = glade_xml_get_widget(xml, "button1");
148 gtk_widget_set_sensitive(back_btn, FALSE);
149
150 widget = glade_xml_get_widget(xml, "show_name1");
151 gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
152 show_name);
153
154 widget = glade_xml_get_widget(xml, "show_range1");
155 gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
156 show_range);
157
158 widget = glade_xml_get_widget(xml, "show_data1");
159 gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
160 show_value);
161
Karsten Wiese0a0c5022006-12-13 00:34:09 -0800162 save_btn = glade_xml_get_widget(xml, "button3");
163 save_menu_item = glade_xml_get_widget(xml, "save1");
164 conf_set_changed_callback(conf_changed);
165
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166 style = gtk_widget_get_style(main_wnd);
167 widget = glade_xml_get_widget(xml, "toolbar1");
168
Joachim Nilssonbafd2df2005-07-29 00:18:03 +0200169 replace_button_icon(xml, main_wnd->window, style,
170 "button4", (gchar **) xpm_single_view);
171 replace_button_icon(xml, main_wnd->window, style,
172 "button5", (gchar **) xpm_split_view);
173 replace_button_icon(xml, main_wnd->window, style,
174 "button6", (gchar **) xpm_tree_view);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176 txtbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
177 tag1 = gtk_text_buffer_create_tag(txtbuf, "mytag1",
178 "foreground", "red",
179 "weight", PANGO_WEIGHT_BOLD,
180 NULL);
181 tag2 = gtk_text_buffer_create_tag(txtbuf, "mytag2",
182 /*"style", PANGO_STYLE_OBLIQUE, */
183 NULL);
184
Arnaud Lacombe09548282010-08-18 01:57:13 -0400185 gtk_window_set_title(GTK_WINDOW(main_wnd), rootmenu.prompt->text);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700186
187 gtk_widget_show(main_wnd);
188}
189
Masahiro Yamada9abe4232018-12-21 17:33:06 +0900190static void init_tree_model(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191{
192 gint i;
193
194 tree = tree2 = gtk_tree_store_new(COL_NUMBER,
195 G_TYPE_STRING, G_TYPE_STRING,
196 G_TYPE_STRING, G_TYPE_STRING,
197 G_TYPE_STRING, G_TYPE_STRING,
198 G_TYPE_POINTER, GDK_TYPE_COLOR,
199 G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF,
200 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
201 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
202 G_TYPE_BOOLEAN);
203 model2 = GTK_TREE_MODEL(tree2);
204
205 for (parents[0] = NULL, i = 1; i < 256; i++)
206 parents[i] = (GtkTreeIter *) g_malloc(sizeof(GtkTreeIter));
207
208 tree1 = gtk_tree_store_new(COL_NUMBER,
209 G_TYPE_STRING, G_TYPE_STRING,
210 G_TYPE_STRING, G_TYPE_STRING,
211 G_TYPE_STRING, G_TYPE_STRING,
212 G_TYPE_POINTER, GDK_TYPE_COLOR,
213 G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF,
214 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
215 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
216 G_TYPE_BOOLEAN);
217 model1 = GTK_TREE_MODEL(tree1);
218}
219
Masahiro Yamada9abe4232018-12-21 17:33:06 +0900220static void init_left_tree(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221{
222 GtkTreeView *view = GTK_TREE_VIEW(tree1_w);
223 GtkCellRenderer *renderer;
224 GtkTreeSelection *sel;
225 GtkTreeViewColumn *column;
226
227 gtk_tree_view_set_model(view, model1);
228 gtk_tree_view_set_headers_visible(view, TRUE);
Eduardo Silva2626e672011-05-19 08:37:01 -0400229 gtk_tree_view_set_rules_hint(view, TRUE);
Joachim Nilssonbafd2df2005-07-29 00:18:03 +0200230
Linus Torvalds1da177e2005-04-16 15:20:36 -0700231 column = gtk_tree_view_column_new();
232 gtk_tree_view_append_column(view, column);
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200233 gtk_tree_view_column_set_title(column, "Options");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234
235 renderer = gtk_cell_renderer_toggle_new();
236 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
237 renderer, FALSE);
238 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
239 renderer,
240 "active", COL_BTNACT,
241 "inconsistent", COL_BTNINC,
Joachim Nilssonbafd2df2005-07-29 00:18:03 +0200242 "visible", COL_BTNVIS,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243 "radio", COL_BTNRAD, NULL);
244 renderer = gtk_cell_renderer_text_new();
245 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
Joachim Nilssonbafd2df2005-07-29 00:18:03 +0200246 renderer, FALSE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
248 renderer,
249 "text", COL_OPTION,
250 "foreground-gdk",
251 COL_COLOR, NULL);
252
253 sel = gtk_tree_view_get_selection(view);
254 gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
255 gtk_widget_realize(tree1_w);
256}
257
258static void renderer_edited(GtkCellRendererText * cell,
259 const gchar * path_string,
260 const gchar * new_text, gpointer user_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261
Masahiro Yamada9abe4232018-12-21 17:33:06 +0900262static void init_right_tree(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263{
264 GtkTreeView *view = GTK_TREE_VIEW(tree2_w);
265 GtkCellRenderer *renderer;
266 GtkTreeSelection *sel;
267 GtkTreeViewColumn *column;
268 gint i;
269
270 gtk_tree_view_set_model(view, model2);
271 gtk_tree_view_set_headers_visible(view, TRUE);
Eduardo Silva2626e672011-05-19 08:37:01 -0400272 gtk_tree_view_set_rules_hint(view, TRUE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273
274 column = gtk_tree_view_column_new();
275 gtk_tree_view_append_column(view, column);
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200276 gtk_tree_view_column_set_title(column, "Options");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277
278 renderer = gtk_cell_renderer_pixbuf_new();
279 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
280 renderer, FALSE);
281 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
282 renderer,
283 "pixbuf", COL_PIXBUF,
284 "visible", COL_PIXVIS, NULL);
285 renderer = gtk_cell_renderer_toggle_new();
286 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
287 renderer, FALSE);
288 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
289 renderer,
290 "active", COL_BTNACT,
291 "inconsistent", COL_BTNINC,
Joachim Nilssonbafd2df2005-07-29 00:18:03 +0200292 "visible", COL_BTNVIS,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293 "radio", COL_BTNRAD, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294 renderer = gtk_cell_renderer_text_new();
295 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
296 renderer, FALSE);
297 gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
298 renderer,
299 "text", COL_OPTION,
300 "foreground-gdk",
301 COL_COLOR, NULL);
302
303 renderer = gtk_cell_renderer_text_new();
304 gtk_tree_view_insert_column_with_attributes(view, -1,
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200305 "Name", renderer,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306 "text", COL_NAME,
307 "foreground-gdk",
308 COL_COLOR, NULL);
309 renderer = gtk_cell_renderer_text_new();
310 gtk_tree_view_insert_column_with_attributes(view, -1,
311 "N", renderer,
312 "text", COL_NO,
313 "foreground-gdk",
314 COL_COLOR, NULL);
315 renderer = gtk_cell_renderer_text_new();
316 gtk_tree_view_insert_column_with_attributes(view, -1,
317 "M", renderer,
318 "text", COL_MOD,
319 "foreground-gdk",
320 COL_COLOR, NULL);
321 renderer = gtk_cell_renderer_text_new();
322 gtk_tree_view_insert_column_with_attributes(view, -1,
323 "Y", renderer,
324 "text", COL_YES,
325 "foreground-gdk",
326 COL_COLOR, NULL);
327 renderer = gtk_cell_renderer_text_new();
328 gtk_tree_view_insert_column_with_attributes(view, -1,
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200329 "Value", renderer,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330 "text", COL_VALUE,
331 "editable",
332 COL_EDIT,
333 "foreground-gdk",
334 COL_COLOR, NULL);
335 g_signal_connect(G_OBJECT(renderer), "edited",
336 G_CALLBACK(renderer_edited), NULL);
337
338 column = gtk_tree_view_get_column(view, COL_NAME);
339 gtk_tree_view_column_set_visible(column, show_name);
340 column = gtk_tree_view_get_column(view, COL_NO);
341 gtk_tree_view_column_set_visible(column, show_range);
342 column = gtk_tree_view_get_column(view, COL_MOD);
343 gtk_tree_view_column_set_visible(column, show_range);
344 column = gtk_tree_view_get_column(view, COL_YES);
345 gtk_tree_view_column_set_visible(column, show_range);
346 column = gtk_tree_view_get_column(view, COL_VALUE);
347 gtk_tree_view_column_set_visible(column, show_value);
348
349 if (resizeable) {
350 for (i = 0; i < COL_VALUE; i++) {
351 column = gtk_tree_view_get_column(view, i);
352 gtk_tree_view_column_set_resizable(column, TRUE);
353 }
354 }
355
356 sel = gtk_tree_view_get_selection(view);
357 gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
358}
359
360
361/* Utility Functions */
362
363
364static void text_insert_help(struct menu *menu)
365{
366 GtkTextBuffer *buffer;
367 GtkTextIter start, end;
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200368 const char *prompt = menu_get_prompt(menu);
Cheng Renquan47791052009-07-12 16:11:46 +0800369 struct gstr help = str_new();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370
Cheng Renquan47791052009-07-12 16:11:46 +0800371 menu_get_ext_help(menu, &help);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372
373 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
374 gtk_text_buffer_get_bounds(buffer, &start, &end);
375 gtk_text_buffer_delete(buffer, &start, &end);
376 gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15);
377
378 gtk_text_buffer_get_end_iter(buffer, &end);
379 gtk_text_buffer_insert_with_tags(buffer, &end, prompt, -1, tag1,
380 NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381 gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2);
382 gtk_text_buffer_get_end_iter(buffer, &end);
Cheng Renquan47791052009-07-12 16:11:46 +0800383 gtk_text_buffer_insert_with_tags(buffer, &end, str_get(&help), -1, tag2,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384 NULL);
Cheng Renquan47791052009-07-12 16:11:46 +0800385 str_free(&help);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386}
387
388
389static void text_insert_msg(const char *title, const char *message)
390{
391 GtkTextBuffer *buffer;
392 GtkTextIter start, end;
393 const char *msg = message;
394
395 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
396 gtk_text_buffer_get_bounds(buffer, &start, &end);
397 gtk_text_buffer_delete(buffer, &start, &end);
398 gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15);
399
400 gtk_text_buffer_get_end_iter(buffer, &end);
401 gtk_text_buffer_insert_with_tags(buffer, &end, title, -1, tag1,
402 NULL);
403 gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2);
404 gtk_text_buffer_get_end_iter(buffer, &end);
405 gtk_text_buffer_insert_with_tags(buffer, &end, msg, -1, tag2,
406 NULL);
407}
408
409
410/* Main Windows Callbacks */
411
Karsten Wiese0a0c5022006-12-13 00:34:09 -0800412void on_save_activate(GtkMenuItem * menuitem, gpointer user_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413gboolean on_window1_delete_event(GtkWidget * widget, GdkEvent * event,
414 gpointer user_data)
415{
416 GtkWidget *dialog, *label;
417 gint result;
418
Karsten Wiese0a0c5022006-12-13 00:34:09 -0800419 if (!conf_get_changed())
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420 return FALSE;
421
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200422 dialog = gtk_dialog_new_with_buttons("Warning !",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423 GTK_WINDOW(main_wnd),
424 (GtkDialogFlags)
425 (GTK_DIALOG_MODAL |
426 GTK_DIALOG_DESTROY_WITH_PARENT),
427 GTK_STOCK_OK,
428 GTK_RESPONSE_YES,
429 GTK_STOCK_NO,
430 GTK_RESPONSE_NO,
431 GTK_STOCK_CANCEL,
432 GTK_RESPONSE_CANCEL, NULL);
433 gtk_dialog_set_default_response(GTK_DIALOG(dialog),
434 GTK_RESPONSE_CANCEL);
435
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200436 label = gtk_label_new("\nSave configuration ?\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label);
438 gtk_widget_show(label);
439
440 result = gtk_dialog_run(GTK_DIALOG(dialog));
441 switch (result) {
442 case GTK_RESPONSE_YES:
Karsten Wiese0a0c5022006-12-13 00:34:09 -0800443 on_save_activate(NULL, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444 return FALSE;
445 case GTK_RESPONSE_NO:
446 return FALSE;
447 case GTK_RESPONSE_CANCEL:
448 case GTK_RESPONSE_DELETE_EVENT:
449 default:
450 gtk_widget_destroy(dialog);
451 return TRUE;
452 }
453
454 return FALSE;
455}
456
457
458void on_window1_destroy(GtkObject * object, gpointer user_data)
459{
460 gtk_main_quit();
461}
462
463
464void
465on_window1_size_request(GtkWidget * widget,
466 GtkRequisition * requisition, gpointer user_data)
467{
468 static gint old_h;
469 gint w, h;
470
471 if (widget->window == NULL)
472 gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h);
473 else
474 gdk_window_get_size(widget->window, &w, &h);
475
476 if (h == old_h)
477 return;
478 old_h = h;
479
480 gtk_paned_set_position(GTK_PANED(vpaned), 2 * h / 3);
481}
482
483
484/* Menu & Toolbar Callbacks */
485
486
487static void
488load_filename(GtkFileSelection * file_selector, gpointer user_data)
489{
490 const gchar *fn;
491
492 fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION
493 (user_data));
494
495 if (conf_read(fn))
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200496 text_insert_msg("Error", "Unable to load configuration !");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497 else
498 display_tree(&rootmenu);
499}
500
501void on_load1_activate(GtkMenuItem * menuitem, gpointer user_data)
502{
503 GtkWidget *fs;
504
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200505 fs = gtk_file_selection_new("Load file...");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506 g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button),
507 "clicked",
508 G_CALLBACK(load_filename), (gpointer) fs);
509 g_signal_connect_swapped(GTK_OBJECT
510 (GTK_FILE_SELECTION(fs)->ok_button),
511 "clicked", G_CALLBACK(gtk_widget_destroy),
512 (gpointer) fs);
513 g_signal_connect_swapped(GTK_OBJECT
514 (GTK_FILE_SELECTION(fs)->cancel_button),
515 "clicked", G_CALLBACK(gtk_widget_destroy),
516 (gpointer) fs);
517 gtk_widget_show(fs);
518}
519
520
Karsten Wiese0a0c5022006-12-13 00:34:09 -0800521void on_save_activate(GtkMenuItem * menuitem, gpointer user_data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522{
523 if (conf_write(NULL))
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200524 text_insert_msg("Error", "Unable to save configuration !");
Masahiro Yamada00c864f2018-07-20 16:46:31 +0900525 conf_write_autoconf(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526}
527
528
529static void
530store_filename(GtkFileSelection * file_selector, gpointer user_data)
531{
532 const gchar *fn;
533
534 fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION
535 (user_data));
536
537 if (conf_write(fn))
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200538 text_insert_msg("Error", "Unable to save configuration !");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539
540 gtk_widget_destroy(GTK_WIDGET(user_data));
541}
542
543void on_save_as1_activate(GtkMenuItem * menuitem, gpointer user_data)
544{
545 GtkWidget *fs;
546
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200547 fs = gtk_file_selection_new("Save file as...");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548 g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button),
549 "clicked",
550 G_CALLBACK(store_filename), (gpointer) fs);
551 g_signal_connect_swapped(GTK_OBJECT
552 (GTK_FILE_SELECTION(fs)->ok_button),
553 "clicked", G_CALLBACK(gtk_widget_destroy),
554 (gpointer) fs);
555 g_signal_connect_swapped(GTK_OBJECT
556 (GTK_FILE_SELECTION(fs)->cancel_button),
557 "clicked", G_CALLBACK(gtk_widget_destroy),
558 (gpointer) fs);
559 gtk_widget_show(fs);
560}
561
562
563void on_quit1_activate(GtkMenuItem * menuitem, gpointer user_data)
564{
565 if (!on_window1_delete_event(NULL, NULL, NULL))
566 gtk_widget_destroy(GTK_WIDGET(main_wnd));
567}
568
569
570void on_show_name1_activate(GtkMenuItem * menuitem, gpointer user_data)
571{
572 GtkTreeViewColumn *col;
573
574 show_name = GTK_CHECK_MENU_ITEM(menuitem)->active;
575 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NAME);
576 if (col)
577 gtk_tree_view_column_set_visible(col, show_name);
578}
579
580
581void on_show_range1_activate(GtkMenuItem * menuitem, gpointer user_data)
582{
583 GtkTreeViewColumn *col;
584
585 show_range = GTK_CHECK_MENU_ITEM(menuitem)->active;
586 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NO);
587 if (col)
588 gtk_tree_view_column_set_visible(col, show_range);
589 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_MOD);
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_YES);
593 if (col)
594 gtk_tree_view_column_set_visible(col, show_range);
595
596}
597
598
599void on_show_data1_activate(GtkMenuItem * menuitem, gpointer user_data)
600{
601 GtkTreeViewColumn *col;
602
603 show_value = GTK_CHECK_MENU_ITEM(menuitem)->active;
604 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_VALUE);
605 if (col)
606 gtk_tree_view_column_set_visible(col, show_value);
607}
608
609
610void
Li Zefan06f9a552010-04-14 11:46:24 +0800611on_set_option_mode1_activate(GtkMenuItem *menuitem, gpointer user_data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612{
Li Zefan06f9a552010-04-14 11:46:24 +0800613 opt_mode = OPT_NORMAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614 gtk_tree_store_clear(tree2);
Li Zefan06f9a552010-04-14 11:46:24 +0800615 display_tree(&rootmenu); /* instead of update_tree to speed-up */
616}
617
618
619void
620on_set_option_mode2_activate(GtkMenuItem *menuitem, gpointer user_data)
621{
622 opt_mode = OPT_ALL;
623 gtk_tree_store_clear(tree2);
624 display_tree(&rootmenu); /* instead of update_tree to speed-up */
625}
626
627
628void
629on_set_option_mode3_activate(GtkMenuItem *menuitem, gpointer user_data)
630{
631 opt_mode = OPT_PROMPT;
632 gtk_tree_store_clear(tree2);
633 display_tree(&rootmenu); /* instead of update_tree to speed-up */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634}
635
636
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data)
638{
639 GtkWidget *dialog;
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200640 const gchar *intro_text =
Arnaud Lacombe652cf982010-08-14 23:51:40 -0400641 "Welcome to gkc, the GTK+ graphical configuration tool\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642 "For each option, a blank box indicates the feature is disabled, a\n"
643 "check indicates it is enabled, and a dot indicates that it is to\n"
644 "be compiled as a module. Clicking on the box will cycle through the three states.\n"
645 "\n"
646 "If you do not see an option (e.g., a device driver) that you\n"
647 "believe should be present, try turning on Show All Options\n"
648 "under the Options menu.\n"
649 "Although there is no cross reference yet to help you figure out\n"
650 "what other options must be enabled to support the option you\n"
651 "are interested in, you can still view the help of a grayed-out\n"
652 "option.\n"
653 "\n"
654 "Toggling Show Debug Info under the Options menu will show \n"
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200655 "the dependencies, which you can then match by examining other options.";
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656
657 dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
658 GTK_DIALOG_DESTROY_WITH_PARENT,
659 GTK_MESSAGE_INFO,
Peter Foleya7d6f6e2011-10-22 13:19:02 -0400660 GTK_BUTTONS_CLOSE, "%s", intro_text);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661 g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
662 G_CALLBACK(gtk_widget_destroy),
663 GTK_OBJECT(dialog));
664 gtk_widget_show_all(dialog);
665}
666
667
668void on_about1_activate(GtkMenuItem * menuitem, gpointer user_data)
669{
670 GtkWidget *dialog;
671 const gchar *about_text =
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200672 "gkc is copyright (c) 2002 Romain Lievin <roms@lpg.ticalc.org>.\n"
673 "Based on the source code from Roman Zippel.\n";
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674
675 dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
676 GTK_DIALOG_DESTROY_WITH_PARENT,
677 GTK_MESSAGE_INFO,
Peter Foleya7d6f6e2011-10-22 13:19:02 -0400678 GTK_BUTTONS_CLOSE, "%s", about_text);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679 g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
680 G_CALLBACK(gtk_widget_destroy),
681 GTK_OBJECT(dialog));
682 gtk_widget_show_all(dialog);
683}
684
685
686void on_license1_activate(GtkMenuItem * menuitem, gpointer user_data)
687{
688 GtkWidget *dialog;
689 const gchar *license_text =
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200690 "gkc is released under the terms of the GNU GPL v2.\n"
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700691 "For more information, please see the source code or\n"
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200692 "visit http://www.fsf.org/licenses/licenses.html\n";
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693
694 dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
695 GTK_DIALOG_DESTROY_WITH_PARENT,
696 GTK_MESSAGE_INFO,
Peter Foleya7d6f6e2011-10-22 13:19:02 -0400697 GTK_BUTTONS_CLOSE, "%s", license_text);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698 g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
699 G_CALLBACK(gtk_widget_destroy),
700 GTK_OBJECT(dialog));
701 gtk_widget_show_all(dialog);
702}
703
704
Joachim Nilssonbafd2df2005-07-29 00:18:03 +0200705void on_back_clicked(GtkButton * button, gpointer user_data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706{
707 enum prop_type ptype;
708
709 current = current->parent;
710 ptype = current->prompt ? current->prompt->type : P_UNKNOWN;
711 if (ptype != P_MENU)
712 current = current->parent;
713 display_tree_part();
714
715 if (current == &rootmenu)
716 gtk_widget_set_sensitive(back_btn, FALSE);
717}
718
719
Joachim Nilssonbafd2df2005-07-29 00:18:03 +0200720void on_load_clicked(GtkButton * button, gpointer user_data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721{
722 on_load1_activate(NULL, user_data);
723}
724
725
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726void on_single_clicked(GtkButton * button, gpointer user_data)
727{
728 view_mode = SINGLE_VIEW;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729 gtk_widget_hide(tree1_w);
730 current = &rootmenu;
731 display_tree_part();
732}
733
734
735void on_split_clicked(GtkButton * button, gpointer user_data)
736{
737 gint w, h;
738 view_mode = SPLIT_VIEW;
739 gtk_widget_show(tree1_w);
740 gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h);
741 gtk_paned_set_position(GTK_PANED(hpaned), w / 2);
Joachim Nilssonbafd2df2005-07-29 00:18:03 +0200742 if (tree2)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743 gtk_tree_store_clear(tree2);
744 display_list();
Joachim Nilssonbafd2df2005-07-29 00:18:03 +0200745
746 /* Disable back btn, like in full mode. */
747 gtk_widget_set_sensitive(back_btn, FALSE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748}
749
750
751void on_full_clicked(GtkButton * button, gpointer user_data)
752{
753 view_mode = FULL_VIEW;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754 gtk_widget_hide(tree1_w);
755 if (tree2)
756 gtk_tree_store_clear(tree2);
757 display_tree(&rootmenu);
758 gtk_widget_set_sensitive(back_btn, FALSE);
759}
760
761
Joachim Nilssonbafd2df2005-07-29 00:18:03 +0200762void on_collapse_clicked(GtkButton * button, gpointer user_data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763{
764 gtk_tree_view_collapse_all(GTK_TREE_VIEW(tree2_w));
765}
766
767
Joachim Nilssonbafd2df2005-07-29 00:18:03 +0200768void on_expand_clicked(GtkButton * button, gpointer user_data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700769{
770 gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w));
771}
772
773
774/* CTree Callbacks */
775
776/* Change hex/int/string value in the cell */
777static void renderer_edited(GtkCellRendererText * cell,
778 const gchar * path_string,
779 const gchar * new_text, gpointer user_data)
780{
781 GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
782 GtkTreeIter iter;
783 const char *old_def, *new_def;
784 struct menu *menu;
785 struct symbol *sym;
786
787 if (!gtk_tree_model_get_iter(model2, &iter, path))
788 return;
789
790 gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
791 sym = menu->sym;
792
793 gtk_tree_model_get(model2, &iter, COL_VALUE, &old_def, -1);
794 new_def = new_text;
795
796 sym_set_string_value(sym, new_def);
797
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798 update_tree(&rootmenu, NULL);
799
800 gtk_tree_path_free(path);
801}
802
803/* Change the value of a symbol and update the tree */
804static void change_sym_value(struct menu *menu, gint col)
805{
806 struct symbol *sym = menu->sym;
Peter Foley4f0c28f2011-10-22 14:01:24 -0400807 tristate newval;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808
809 if (!sym)
810 return;
811
812 if (col == COL_NO)
813 newval = no;
814 else if (col == COL_MOD)
815 newval = mod;
816 else if (col == COL_YES)
817 newval = yes;
818 else
819 return;
820
821 switch (sym_get_type(sym)) {
822 case S_BOOLEAN:
823 case S_TRISTATE:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824 if (!sym_tristate_within_range(sym, newval))
825 newval = yes;
826 sym_set_tristate_value(sym, newval);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827 if (view_mode == FULL_VIEW)
828 update_tree(&rootmenu, NULL);
829 else if (view_mode == SPLIT_VIEW) {
830 update_tree(browsed, NULL);
831 display_list();
832 }
833 else if (view_mode == SINGLE_VIEW)
834 display_tree_part(); //fixme: keep exp/coll
835 break;
836 case S_INT:
837 case S_HEX:
838 case S_STRING:
839 default:
840 break;
841 }
842}
843
844static void toggle_sym_value(struct menu *menu)
845{
846 if (!menu->sym)
847 return;
848
849 sym_toggle_tristate_value(menu->sym);
850 if (view_mode == FULL_VIEW)
851 update_tree(&rootmenu, NULL);
852 else if (view_mode == SPLIT_VIEW) {
853 update_tree(browsed, NULL);
854 display_list();
855 }
856 else if (view_mode == SINGLE_VIEW)
857 display_tree_part(); //fixme: keep exp/coll
858}
859
Linus Torvalds1da177e2005-04-16 15:20:36 -0700860static gint column2index(GtkTreeViewColumn * column)
861{
862 gint i;
863
864 for (i = 0; i < COL_NUMBER; i++) {
865 GtkTreeViewColumn *col;
866
867 col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), i);
868 if (col == column)
869 return i;
870 }
871
872 return -1;
873}
874
875
876/* User click: update choice (full) or goes down (single) */
877gboolean
878on_treeview2_button_press_event(GtkWidget * widget,
879 GdkEventButton * event, gpointer user_data)
880{
881 GtkTreeView *view = GTK_TREE_VIEW(widget);
882 GtkTreePath *path;
883 GtkTreeViewColumn *column;
884 GtkTreeIter iter;
885 struct menu *menu;
886 gint col;
887
888#if GTK_CHECK_VERSION(2,1,4) // bug in ctree with earlier version of GTK
889 gint tx = (gint) event->x;
890 gint ty = (gint) event->y;
891 gint cx, cy;
892
893 gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx,
894 &cy);
895#else
896 gtk_tree_view_get_cursor(view, &path, &column);
897#endif
898 if (path == NULL)
899 return FALSE;
900
901 if (!gtk_tree_model_get_iter(model2, &iter, path))
902 return FALSE;
903 gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
904
905 col = column2index(column);
906 if (event->type == GDK_2BUTTON_PRESS) {
907 enum prop_type ptype;
908 ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
909
910 if (ptype == P_MENU && view_mode != FULL_VIEW && col == COL_OPTION) {
911 // goes down into menu
912 current = menu;
913 display_tree_part();
914 gtk_widget_set_sensitive(back_btn, TRUE);
Nicolas Iooss9be32132017-03-13 20:33:41 +0100915 } else if (col == COL_OPTION) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916 toggle_sym_value(menu);
917 gtk_tree_view_expand_row(view, path, TRUE);
918 }
919 } else {
920 if (col == COL_VALUE) {
921 toggle_sym_value(menu);
922 gtk_tree_view_expand_row(view, path, TRUE);
923 } else if (col == COL_NO || col == COL_MOD
924 || col == COL_YES) {
925 change_sym_value(menu, col);
926 gtk_tree_view_expand_row(view, path, TRUE);
927 }
928 }
929
930 return FALSE;
931}
932
933/* Key pressed: update choice */
934gboolean
935on_treeview2_key_press_event(GtkWidget * widget,
936 GdkEventKey * event, gpointer user_data)
937{
938 GtkTreeView *view = GTK_TREE_VIEW(widget);
939 GtkTreePath *path;
940 GtkTreeViewColumn *column;
941 GtkTreeIter iter;
942 struct menu *menu;
943 gint col;
944
945 gtk_tree_view_get_cursor(view, &path, &column);
946 if (path == NULL)
947 return FALSE;
948
949 if (event->keyval == GDK_space) {
950 if (gtk_tree_view_row_expanded(view, path))
951 gtk_tree_view_collapse_row(view, path);
952 else
953 gtk_tree_view_expand_row(view, path, FALSE);
954 return TRUE;
955 }
956 if (event->keyval == GDK_KP_Enter) {
957 }
958 if (widget == tree1_w)
959 return FALSE;
960
961 gtk_tree_model_get_iter(model2, &iter, path);
962 gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
963
964 if (!strcasecmp(event->string, "n"))
965 col = COL_NO;
966 else if (!strcasecmp(event->string, "m"))
967 col = COL_MOD;
968 else if (!strcasecmp(event->string, "y"))
969 col = COL_YES;
970 else
971 col = -1;
972 change_sym_value(menu, col);
973
974 return FALSE;
975}
976
977
978/* Row selection changed: update help */
979void
980on_treeview2_cursor_changed(GtkTreeView * treeview, gpointer user_data)
981{
982 GtkTreeSelection *selection;
983 GtkTreeIter iter;
984 struct menu *menu;
985
986 selection = gtk_tree_view_get_selection(treeview);
987 if (gtk_tree_selection_get_selected(selection, &model2, &iter)) {
988 gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
989 text_insert_help(menu);
990 }
991}
992
993
994/* User click: display sub-tree in the right frame. */
995gboolean
996on_treeview1_button_press_event(GtkWidget * widget,
997 GdkEventButton * event, gpointer user_data)
998{
999 GtkTreeView *view = GTK_TREE_VIEW(widget);
1000 GtkTreePath *path;
1001 GtkTreeViewColumn *column;
1002 GtkTreeIter iter;
1003 struct menu *menu;
1004
1005 gint tx = (gint) event->x;
1006 gint ty = (gint) event->y;
1007 gint cx, cy;
1008
1009 gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx,
1010 &cy);
1011 if (path == NULL)
1012 return FALSE;
1013
1014 gtk_tree_model_get_iter(model1, &iter, path);
1015 gtk_tree_model_get(model1, &iter, COL_MENU, &menu, -1);
1016
1017 if (event->type == GDK_2BUTTON_PRESS) {
1018 toggle_sym_value(menu);
1019 current = menu;
1020 display_tree_part();
1021 } else {
1022 browsed = menu;
1023 display_tree_part();
1024 }
1025
1026 gtk_widget_realize(tree2_w);
1027 gtk_tree_view_set_cursor(view, path, NULL, FALSE);
1028 gtk_widget_grab_focus(tree2_w);
1029
1030 return FALSE;
1031}
1032
1033
1034/* Fill a row of strings */
1035static gchar **fill_row(struct menu *menu)
1036{
1037 static gchar *row[COL_NUMBER];
1038 struct symbol *sym = menu->sym;
1039 const char *def;
1040 int stype;
1041 tristate val;
1042 enum prop_type ptype;
1043 int i;
1044
1045 for (i = COL_OPTION; i <= COL_COLOR; i++)
1046 g_free(row[i]);
1047 bzero(row, sizeof(row));
1048
1049 row[COL_OPTION] =
Sam Ravnborg694c49a2018-05-22 21:36:12 +02001050 g_strdup_printf("%s %s", menu_get_prompt(menu),
Li Zefane0bb7fe2010-05-07 13:57:35 +08001051 sym && !sym_has_value(sym) ? "(NEW)" : "");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052
Li Zefan06f9a552010-04-14 11:46:24 +08001053 if (opt_mode == OPT_ALL && !menu_is_visible(menu))
1054 row[COL_COLOR] = g_strdup("DarkGray");
1055 else if (opt_mode == OPT_PROMPT &&
1056 menu_has_prompt(menu) && !menu_is_visible(menu))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057 row[COL_COLOR] = g_strdup("DarkGray");
1058 else
1059 row[COL_COLOR] = g_strdup("Black");
1060
1061 ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
1062 switch (ptype) {
1063 case P_MENU:
1064 row[COL_PIXBUF] = (gchar *) xpm_menu;
1065 if (view_mode == SINGLE_VIEW)
1066 row[COL_PIXVIS] = GINT_TO_POINTER(TRUE);
1067 row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
1068 break;
1069 case P_COMMENT:
1070 row[COL_PIXBUF] = (gchar *) xpm_void;
1071 row[COL_PIXVIS] = GINT_TO_POINTER(FALSE);
1072 row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
1073 break;
1074 default:
1075 row[COL_PIXBUF] = (gchar *) xpm_void;
1076 row[COL_PIXVIS] = GINT_TO_POINTER(FALSE);
1077 row[COL_BTNVIS] = GINT_TO_POINTER(TRUE);
1078 break;
1079 }
1080
1081 if (!sym)
1082 return row;
1083 row[COL_NAME] = g_strdup(sym->name);
1084
1085 sym_calc_value(sym);
1086 sym->flags &= ~SYMBOL_CHANGED;
1087
1088 if (sym_is_choice(sym)) { // parse childs for getting final value
1089 struct menu *child;
1090 struct symbol *def_sym = sym_get_choice_value(sym);
1091 struct menu *def_menu = NULL;
1092
1093 row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
1094
1095 for (child = menu->list; child; child = child->next) {
1096 if (menu_is_visible(child)
1097 && child->sym == def_sym)
1098 def_menu = child;
1099 }
1100
1101 if (def_menu)
1102 row[COL_VALUE] =
Sam Ravnborg694c49a2018-05-22 21:36:12 +02001103 g_strdup(menu_get_prompt(def_menu));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104 }
Joachim Nilssonbafd2df2005-07-29 00:18:03 +02001105 if (sym->flags & SYMBOL_CHOICEVAL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106 row[COL_BTNRAD] = GINT_TO_POINTER(TRUE);
1107
1108 stype = sym_get_type(sym);
1109 switch (stype) {
1110 case S_BOOLEAN:
Joachim Nilssonbafd2df2005-07-29 00:18:03 +02001111 if (GPOINTER_TO_INT(row[COL_PIXVIS]) == FALSE)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112 row[COL_BTNVIS] = GINT_TO_POINTER(TRUE);
1113 if (sym_is_choice(sym))
1114 break;
Arnaud Lacombed8fc3202011-05-31 12:30:26 -04001115 /* fall through */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116 case S_TRISTATE:
1117 val = sym_get_tristate_value(sym);
1118 switch (val) {
1119 case no:
1120 row[COL_NO] = g_strdup("N");
1121 row[COL_VALUE] = g_strdup("N");
1122 row[COL_BTNACT] = GINT_TO_POINTER(FALSE);
1123 row[COL_BTNINC] = GINT_TO_POINTER(FALSE);
1124 break;
1125 case mod:
1126 row[COL_MOD] = g_strdup("M");
1127 row[COL_VALUE] = g_strdup("M");
1128 row[COL_BTNINC] = GINT_TO_POINTER(TRUE);
1129 break;
1130 case yes:
1131 row[COL_YES] = g_strdup("Y");
1132 row[COL_VALUE] = g_strdup("Y");
1133 row[COL_BTNACT] = GINT_TO_POINTER(TRUE);
1134 row[COL_BTNINC] = GINT_TO_POINTER(FALSE);
1135 break;
1136 }
1137
1138 if (val != no && sym_tristate_within_range(sym, no))
1139 row[COL_NO] = g_strdup("_");
1140 if (val != mod && sym_tristate_within_range(sym, mod))
1141 row[COL_MOD] = g_strdup("_");
1142 if (val != yes && sym_tristate_within_range(sym, yes))
1143 row[COL_YES] = g_strdup("_");
1144 break;
1145 case S_INT:
1146 case S_HEX:
1147 case S_STRING:
1148 def = sym_get_string_value(sym);
1149 row[COL_VALUE] = g_strdup(def);
1150 row[COL_EDIT] = GINT_TO_POINTER(TRUE);
1151 row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
1152 break;
1153 }
1154
1155 return row;
1156}
1157
1158
1159/* Set the node content with a row of strings */
1160static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row)
1161{
1162 GdkColor color;
1163 gboolean success;
1164 GdkPixbuf *pix;
1165
1166 pix = gdk_pixbuf_new_from_xpm_data((const char **)
1167 row[COL_PIXBUF]);
1168
1169 gdk_color_parse(row[COL_COLOR], &color);
1170 gdk_colormap_alloc_colors(gdk_colormap_get_system(), &color, 1,
1171 FALSE, FALSE, &success);
1172
1173 gtk_tree_store_set(tree, node,
1174 COL_OPTION, row[COL_OPTION],
1175 COL_NAME, row[COL_NAME],
1176 COL_NO, row[COL_NO],
1177 COL_MOD, row[COL_MOD],
1178 COL_YES, row[COL_YES],
1179 COL_VALUE, row[COL_VALUE],
1180 COL_MENU, (gpointer) menu,
1181 COL_COLOR, &color,
1182 COL_EDIT, GPOINTER_TO_INT(row[COL_EDIT]),
1183 COL_PIXBUF, pix,
1184 COL_PIXVIS, GPOINTER_TO_INT(row[COL_PIXVIS]),
1185 COL_BTNVIS, GPOINTER_TO_INT(row[COL_BTNVIS]),
1186 COL_BTNACT, GPOINTER_TO_INT(row[COL_BTNACT]),
1187 COL_BTNINC, GPOINTER_TO_INT(row[COL_BTNINC]),
1188 COL_BTNRAD, GPOINTER_TO_INT(row[COL_BTNRAD]),
1189 -1);
1190
1191 g_object_unref(pix);
1192}
1193
1194
1195/* Add a node to the tree */
1196static void place_node(struct menu *menu, char **row)
1197{
1198 GtkTreeIter *parent = parents[indent - 1];
1199 GtkTreeIter *node = parents[indent];
1200
1201 gtk_tree_store_append(tree, node, parent);
1202 set_node(node, menu, row);
1203}
1204
1205
1206/* Find a node in the GTK+ tree */
1207static GtkTreeIter found;
1208
1209/*
1210 * Find a menu in the GtkTree starting at parent.
1211 */
Masahiro Yamada9abe4232018-12-21 17:33:06 +09001212static GtkTreeIter *gtktree_iter_find_node(GtkTreeIter *parent,
1213 struct menu *tofind)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214{
1215 GtkTreeIter iter;
1216 GtkTreeIter *child = &iter;
1217 gboolean valid;
1218 GtkTreeIter *ret;
1219
1220 valid = gtk_tree_model_iter_children(model2, child, parent);
1221 while (valid) {
1222 struct menu *menu;
1223
1224 gtk_tree_model_get(model2, child, 6, &menu, -1);
1225
1226 if (menu == tofind) {
1227 memcpy(&found, child, sizeof(GtkTreeIter));
1228 return &found;
1229 }
1230
1231 ret = gtktree_iter_find_node(child, tofind);
1232 if (ret)
1233 return ret;
1234
1235 valid = gtk_tree_model_iter_next(model2, child);
1236 }
1237
1238 return NULL;
1239}
1240
1241
1242/*
1243 * Update the tree by adding/removing entries
1244 * Does not change other nodes
1245 */
1246static void update_tree(struct menu *src, GtkTreeIter * dst)
1247{
1248 struct menu *child1;
1249 GtkTreeIter iter, tmp;
1250 GtkTreeIter *child2 = &iter;
1251 gboolean valid;
1252 GtkTreeIter *sibling;
1253 struct symbol *sym;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001254 struct menu *menu1, *menu2;
1255
1256 if (src == &rootmenu)
1257 indent = 1;
1258
1259 valid = gtk_tree_model_iter_children(model2, child2, dst);
1260 for (child1 = src->list; child1; child1 = child1->next) {
1261
Linus Torvalds1da177e2005-04-16 15:20:36 -07001262 sym = child1->sym;
1263
1264 reparse:
1265 menu1 = child1;
1266 if (valid)
1267 gtk_tree_model_get(model2, child2, COL_MENU,
1268 &menu2, -1);
1269 else
1270 menu2 = NULL; // force adding of a first child
1271
1272#ifdef DEBUG
1273 printf("%*c%s | %s\n", indent, ' ',
1274 menu1 ? menu_get_prompt(menu1) : "nil",
1275 menu2 ? menu_get_prompt(menu2) : "nil");
1276#endif
1277
Li Zefan06f9a552010-04-14 11:46:24 +08001278 if ((opt_mode == OPT_NORMAL && !menu_is_visible(child1)) ||
Li Zefanc10d03c2010-05-07 13:57:49 +08001279 (opt_mode == OPT_PROMPT && !menu_has_prompt(child1)) ||
1280 (opt_mode == OPT_ALL && !menu_get_prompt(child1))) {
Li Zefan06f9a552010-04-14 11:46:24 +08001281
1282 /* remove node */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001283 if (gtktree_iter_find_node(dst, menu1) != NULL) {
1284 memcpy(&tmp, child2, sizeof(GtkTreeIter));
1285 valid = gtk_tree_model_iter_next(model2,
1286 child2);
1287 gtk_tree_store_remove(tree2, &tmp);
1288 if (!valid)
Li Zefan06f9a552010-04-14 11:46:24 +08001289 return; /* next parent */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001290 else
Li Zefan06f9a552010-04-14 11:46:24 +08001291 goto reparse; /* next child */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001292 } else
1293 continue;
1294 }
1295
1296 if (menu1 != menu2) {
1297 if (gtktree_iter_find_node(dst, menu1) == NULL) { // add node
1298 if (!valid && !menu2)
1299 sibling = NULL;
1300 else
1301 sibling = child2;
1302 gtk_tree_store_insert_before(tree2,
1303 child2,
1304 dst, sibling);
1305 set_node(child2, menu1, fill_row(menu1));
1306 if (menu2 == NULL)
1307 valid = TRUE;
1308 } else { // remove node
1309 memcpy(&tmp, child2, sizeof(GtkTreeIter));
1310 valid = gtk_tree_model_iter_next(model2,
1311 child2);
1312 gtk_tree_store_remove(tree2, &tmp);
1313 if (!valid)
Joachim Nilssonbafd2df2005-07-29 00:18:03 +02001314 return; // next parent
Linus Torvalds1da177e2005-04-16 15:20:36 -07001315 else
1316 goto reparse; // next child
1317 }
1318 } else if (sym && (sym->flags & SYMBOL_CHANGED)) {
1319 set_node(child2, menu1, fill_row(menu1));
1320 }
1321
1322 indent++;
1323 update_tree(child1, child2);
1324 indent--;
1325
1326 valid = gtk_tree_model_iter_next(model2, child2);
1327 }
1328}
1329
1330
1331/* Display the whole tree (single/split/full view) */
1332static void display_tree(struct menu *menu)
1333{
1334 struct symbol *sym;
1335 struct property *prop;
1336 struct menu *child;
1337 enum prop_type ptype;
1338
1339 if (menu == &rootmenu) {
1340 indent = 1;
1341 current = &rootmenu;
1342 }
1343
1344 for (child = menu->list; child; child = child->next) {
1345 prop = child->prompt;
1346 sym = child->sym;
1347 ptype = prop ? prop->type : P_UNKNOWN;
1348
1349 if (sym)
1350 sym->flags &= ~SYMBOL_CHANGED;
1351
Joachim Nilssonbafd2df2005-07-29 00:18:03 +02001352 if ((view_mode == SPLIT_VIEW)
1353 && !(child->flags & MENU_ROOT) && (tree == tree1))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354 continue;
1355
Joachim Nilssonbafd2df2005-07-29 00:18:03 +02001356 if ((view_mode == SPLIT_VIEW) && (child->flags & MENU_ROOT)
1357 && (tree == tree2))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358 continue;
1359
Li Zefan06f9a552010-04-14 11:46:24 +08001360 if ((opt_mode == OPT_NORMAL && menu_is_visible(child)) ||
1361 (opt_mode == OPT_PROMPT && menu_has_prompt(child)) ||
Li Zefanc10d03c2010-05-07 13:57:49 +08001362 (opt_mode == OPT_ALL && menu_get_prompt(child)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363 place_node(child, fill_row(child));
1364#ifdef DEBUG
1365 printf("%*c%s: ", indent, ' ', menu_get_prompt(child));
1366 printf("%s", child->flags & MENU_ROOT ? "rootmenu | " : "");
Li Zefan29442352010-04-14 11:44:34 +08001367 printf("%s", prop_get_type_name(ptype));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001368 printf(" | ");
1369 if (sym) {
Li Zefan29442352010-04-14 11:44:34 +08001370 printf("%s", sym_type_name(sym->type));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371 printf(" | ");
Li Zefan29442352010-04-14 11:44:34 +08001372 printf("%s", dbg_sym_flags(sym->flags));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373 printf("\n");
1374 } else
1375 printf("\n");
1376#endif
1377 if ((view_mode != FULL_VIEW) && (ptype == P_MENU)
1378 && (tree == tree2))
1379 continue;
1380/*
Masahiro Yamadabb66fc62014-06-10 19:08:13 +09001381 if (((menu != &rootmenu) && !(menu->flags & MENU_ROOT))
Joachim Nilssonbafd2df2005-07-29 00:18:03 +02001382 || (view_mode == FULL_VIEW)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001383 || (view_mode == SPLIT_VIEW))*/
Eduardo Silva6ef3d362011-05-19 08:38:25 -04001384
1385 /* Change paned position if the view is not in 'split mode' */
1386 if (view_mode == SINGLE_VIEW || view_mode == FULL_VIEW) {
1387 gtk_paned_set_position(GTK_PANED(hpaned), 0);
1388 }
1389
Linus Torvalds1da177e2005-04-16 15:20:36 -07001390 if (((view_mode == SINGLE_VIEW) && (menu->flags & MENU_ROOT))
Joachim Nilssonbafd2df2005-07-29 00:18:03 +02001391 || (view_mode == FULL_VIEW)
1392 || (view_mode == SPLIT_VIEW)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393 indent++;
1394 display_tree(child);
1395 indent--;
1396 }
1397 }
1398}
1399
1400/* Display a part of the tree starting at current node (single/split view) */
1401static void display_tree_part(void)
1402{
1403 if (tree2)
1404 gtk_tree_store_clear(tree2);
Joachim Nilssonbafd2df2005-07-29 00:18:03 +02001405 if (view_mode == SINGLE_VIEW)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001406 display_tree(current);
Joachim Nilssonbafd2df2005-07-29 00:18:03 +02001407 else if (view_mode == SPLIT_VIEW)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408 display_tree(browsed);
1409 gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w));
1410}
1411
1412/* Display the list in the left frame (split view) */
1413static void display_list(void)
1414{
1415 if (tree1)
1416 gtk_tree_store_clear(tree1);
1417
1418 tree = tree1;
1419 display_tree(&rootmenu);
1420 gtk_tree_view_expand_all(GTK_TREE_VIEW(tree1_w));
1421 tree = tree2;
1422}
1423
Masahiro Yamada9abe4232018-12-21 17:33:06 +09001424static void fixup_rootmenu(struct menu *menu)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001425{
Joachim Nilssonbafd2df2005-07-29 00:18:03 +02001426 struct menu *child;
1427 static int menu_cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428
Joachim Nilssonbafd2df2005-07-29 00:18:03 +02001429 menu->flags |= MENU_ROOT;
1430 for (child = menu->list; child; child = child->next) {
1431 if (child->prompt && child->prompt->type == P_MENU) {
1432 menu_cnt++;
1433 fixup_rootmenu(child);
1434 menu_cnt--;
1435 } else if (!menu_cnt)
1436 fixup_rootmenu(child);
1437 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001438}
1439
1440
1441/* Main */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001442int main(int ac, char *av[])
1443{
1444 const char *name;
1445 char *env;
1446 gchar *glade_file;
1447
Linus Torvalds1da177e2005-04-16 15:20:36 -07001448 /* GTK stuffs */
1449 gtk_set_locale();
1450 gtk_init(&ac, &av);
1451 glade_init();
1452
1453 //add_pixmap_directory (PACKAGE_DATA_DIR "/" PACKAGE "/pixmaps");
1454 //add_pixmap_directory (PACKAGE_SOURCE_DIR "/pixmaps");
1455
1456 /* Determine GUI path */
1457 env = getenv(SRCTREE);
1458 if (env)
1459 glade_file = g_strconcat(env, "/scripts/kconfig/gconf.glade", NULL);
1460 else if (av[0][0] == '/')
1461 glade_file = g_strconcat(av[0], ".glade", NULL);
1462 else
1463 glade_file = g_strconcat(g_get_current_dir(), "/", av[0], ".glade", NULL);
1464
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465 /* Conf stuffs */
1466 if (ac > 1 && av[1][0] == '-') {
1467 switch (av[1][1]) {
1468 case 'a':
1469 //showAll = 1;
1470 break;
Michal Marek0a1f00a2015-04-08 13:30:42 +02001471 case 's':
1472 conf_set_message_callback(NULL);
1473 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001474 case 'h':
1475 case '?':
Michal Marek0a1f00a2015-04-08 13:30:42 +02001476 printf("%s [-s] <config>\n", av[0]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001477 exit(0);
1478 }
1479 name = av[2];
1480 } else
1481 name = av[1];
1482
1483 conf_parse(name);
1484 fixup_rootmenu(&rootmenu);
1485 conf_read(NULL);
1486
Arnaud Lacombec55c9d52010-09-19 22:47:17 -04001487 /* Load the interface and connect signals */
1488 init_main_window(glade_file);
1489 init_tree_model();
1490 init_left_tree();
1491 init_right_tree();
1492
Linus Torvalds1da177e2005-04-16 15:20:36 -07001493 switch (view_mode) {
1494 case SINGLE_VIEW:
1495 display_tree_part();
1496 break;
1497 case SPLIT_VIEW:
1498 display_list();
1499 break;
1500 case FULL_VIEW:
1501 display_tree(&rootmenu);
1502 break;
1503 }
1504
1505 gtk_main();
1506
1507 return 0;
1508}
Karsten Wiese0a0c5022006-12-13 00:34:09 -08001509
1510static void conf_changed(void)
1511{
1512 bool changed = conf_get_changed();
1513 gtk_widget_set_sensitive(save_btn, changed);
1514 gtk_widget_set_sensitive(save_menu_item, changed);
1515}