[ci:skip-build]: already built successfully in CI Part-of: <https://gitlab.postmarketos.org/postmarketOS/pmaports/-/merge_requests/7195>
12963 lines
333 KiB
Diff
12963 lines
333 KiB
Diff
From f3e4dbe91af44467209d5e2e301643ff8c7360c1 Mon Sep 17 00:00:00 2001
|
|
From: user0-07161 <user0thenyancat@proton.me>
|
|
Date: Wed, 8 Oct 2025 18:47:29 +0200
|
|
Subject: [PATCH] Add missing kconfig files
|
|
|
|
---
|
|
scripts/kconfig/POTFILES.in | 12 +
|
|
scripts/kconfig/gconf.c | 1542 +++++++++++++++++++
|
|
scripts/kconfig/gconf.glade | 661 ++++++++
|
|
scripts/kconfig/images.c | 326 ++++
|
|
scripts/kconfig/kxgettext.c | 235 +++
|
|
scripts/kconfig/lxdialog/BIG.FAT.WARNING | 4 +
|
|
scripts/kconfig/lxdialog/checklist.c | 332 ++++
|
|
scripts/kconfig/lxdialog/dialog.h | 257 ++++
|
|
scripts/kconfig/lxdialog/inputbox.c | 301 ++++
|
|
scripts/kconfig/lxdialog/menubox.c | 437 ++++++
|
|
scripts/kconfig/lxdialog/textbox.c | 408 +++++
|
|
scripts/kconfig/lxdialog/util.c | 713 +++++++++
|
|
scripts/kconfig/lxdialog/yesno.c | 114 ++
|
|
scripts/kconfig/mconf.c | 1036 +++++++++++++
|
|
scripts/kconfig/merge_config.sh | 150 ++
|
|
scripts/kconfig/nconf.c | 1556 +++++++++++++++++++
|
|
scripts/kconfig/nconf.gui.c | 656 ++++++++
|
|
scripts/kconfig/nconf.h | 96 ++
|
|
scripts/kconfig/qconf.cc | 1795 ++++++++++++++++++++++
|
|
scripts/kconfig/qconf.h | 338 ++++
|
|
scripts/kconfig/streamline_config.pl | 647 ++++++++
|
|
scripts/kconfig/zconf.gperf | 48 +
|
|
scripts/kconfig/zconf.l | 363 +++++
|
|
scripts/kconfig/zconf.y | 733 +++++++++
|
|
24 files changed, 12760 insertions(+)
|
|
create mode 100644 scripts/kconfig/POTFILES.in
|
|
create mode 100644 scripts/kconfig/gconf.c
|
|
create mode 100644 scripts/kconfig/gconf.glade
|
|
create mode 100644 scripts/kconfig/images.c
|
|
create mode 100644 scripts/kconfig/kxgettext.c
|
|
create mode 100644 scripts/kconfig/lxdialog/BIG.FAT.WARNING
|
|
create mode 100644 scripts/kconfig/lxdialog/checklist.c
|
|
create mode 100644 scripts/kconfig/lxdialog/dialog.h
|
|
create mode 100644 scripts/kconfig/lxdialog/inputbox.c
|
|
create mode 100644 scripts/kconfig/lxdialog/menubox.c
|
|
create mode 100644 scripts/kconfig/lxdialog/textbox.c
|
|
create mode 100644 scripts/kconfig/lxdialog/util.c
|
|
create mode 100644 scripts/kconfig/lxdialog/yesno.c
|
|
create mode 100644 scripts/kconfig/mconf.c
|
|
create mode 100755 scripts/kconfig/merge_config.sh
|
|
create mode 100644 scripts/kconfig/nconf.c
|
|
create mode 100644 scripts/kconfig/nconf.gui.c
|
|
create mode 100644 scripts/kconfig/nconf.h
|
|
create mode 100644 scripts/kconfig/qconf.cc
|
|
create mode 100644 scripts/kconfig/qconf.h
|
|
create mode 100755 scripts/kconfig/streamline_config.pl
|
|
create mode 100644 scripts/kconfig/zconf.gperf
|
|
create mode 100644 scripts/kconfig/zconf.l
|
|
create mode 100644 scripts/kconfig/zconf.y
|
|
|
|
diff --git a/scripts/kconfig/POTFILES.in b/scripts/kconfig/POTFILES.in
|
|
new file mode 100644
|
|
index 0000000..9674573
|
|
--- /dev/null
|
|
+++ b/scripts/kconfig/POTFILES.in
|
|
@@ -0,0 +1,12 @@
|
|
+scripts/kconfig/lxdialog/checklist.c
|
|
+scripts/kconfig/lxdialog/inputbox.c
|
|
+scripts/kconfig/lxdialog/menubox.c
|
|
+scripts/kconfig/lxdialog/textbox.c
|
|
+scripts/kconfig/lxdialog/util.c
|
|
+scripts/kconfig/lxdialog/yesno.c
|
|
+scripts/kconfig/mconf.c
|
|
+scripts/kconfig/conf.c
|
|
+scripts/kconfig/confdata.c
|
|
+scripts/kconfig/gconf.c
|
|
+scripts/kconfig/gconf.glade.h
|
|
+scripts/kconfig/qconf.cc
|
|
diff --git a/scripts/kconfig/gconf.c b/scripts/kconfig/gconf.c
|
|
new file mode 100644
|
|
index 0000000..d0a35b2
|
|
--- /dev/null
|
|
+++ b/scripts/kconfig/gconf.c
|
|
@@ -0,0 +1,1542 @@
|
|
+/* Hey EMACS -*- linux-c -*- */
|
|
+/*
|
|
+ *
|
|
+ * Copyright (C) 2002-2003 Romain Lievin <roms@tilp.info>
|
|
+ * Released under the terms of the GNU GPL v2.0.
|
|
+ *
|
|
+ */
|
|
+
|
|
+#ifdef HAVE_CONFIG_H
|
|
+# include <config.h>
|
|
+#endif
|
|
+
|
|
+#include <stdlib.h>
|
|
+#include "lkc.h"
|
|
+#include "images.c"
|
|
+
|
|
+#include <glade/glade.h>
|
|
+#include <gtk/gtk.h>
|
|
+#include <glib.h>
|
|
+#include <gdk/gdkkeysyms.h>
|
|
+
|
|
+#include <stdio.h>
|
|
+#include <string.h>
|
|
+#include <unistd.h>
|
|
+#include <time.h>
|
|
+
|
|
+//#define DEBUG
|
|
+
|
|
+enum {
|
|
+ SINGLE_VIEW, SPLIT_VIEW, FULL_VIEW
|
|
+};
|
|
+
|
|
+enum {
|
|
+ OPT_NORMAL, OPT_ALL, OPT_PROMPT
|
|
+};
|
|
+
|
|
+static gint view_mode = FULL_VIEW;
|
|
+static gboolean show_name = TRUE;
|
|
+static gboolean show_range = TRUE;
|
|
+static gboolean show_value = TRUE;
|
|
+static gboolean resizeable = FALSE;
|
|
+static int opt_mode = OPT_NORMAL;
|
|
+
|
|
+GtkWidget *main_wnd = NULL;
|
|
+GtkWidget *tree1_w = NULL; // left frame
|
|
+GtkWidget *tree2_w = NULL; // right frame
|
|
+GtkWidget *text_w = NULL;
|
|
+GtkWidget *hpaned = NULL;
|
|
+GtkWidget *vpaned = NULL;
|
|
+GtkWidget *back_btn = NULL;
|
|
+GtkWidget *save_btn = NULL;
|
|
+GtkWidget *save_menu_item = NULL;
|
|
+
|
|
+GtkTextTag *tag1, *tag2;
|
|
+GdkColor color;
|
|
+
|
|
+GtkTreeStore *tree1, *tree2, *tree;
|
|
+GtkTreeModel *model1, *model2;
|
|
+static GtkTreeIter *parents[256];
|
|
+static gint indent;
|
|
+
|
|
+static struct menu *current; // current node for SINGLE view
|
|
+static struct menu *browsed; // browsed node for SPLIT view
|
|
+
|
|
+enum {
|
|
+ COL_OPTION, COL_NAME, COL_NO, COL_MOD, COL_YES, COL_VALUE,
|
|
+ COL_MENU, COL_COLOR, COL_EDIT, COL_PIXBUF,
|
|
+ COL_PIXVIS, COL_BTNVIS, COL_BTNACT, COL_BTNINC, COL_BTNRAD,
|
|
+ COL_NUMBER
|
|
+};
|
|
+
|
|
+static void display_list(void);
|
|
+static void display_tree(struct menu *menu);
|
|
+static void display_tree_part(void);
|
|
+static void update_tree(struct menu *src, GtkTreeIter * dst);
|
|
+static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row);
|
|
+static gchar **fill_row(struct menu *menu);
|
|
+static void conf_changed(void);
|
|
+
|
|
+/* Helping/Debugging Functions */
|
|
+
|
|
+const char *dbg_sym_flags(int val)
|
|
+{
|
|
+ static char buf[256];
|
|
+
|
|
+ bzero(buf, 256);
|
|
+
|
|
+ if (val & SYMBOL_CONST)
|
|
+ strcat(buf, "const/");
|
|
+ if (val & SYMBOL_CHECK)
|
|
+ strcat(buf, "check/");
|
|
+ if (val & SYMBOL_CHOICE)
|
|
+ strcat(buf, "choice/");
|
|
+ if (val & SYMBOL_CHOICEVAL)
|
|
+ strcat(buf, "choiceval/");
|
|
+ if (val & SYMBOL_VALID)
|
|
+ strcat(buf, "valid/");
|
|
+ if (val & SYMBOL_OPTIONAL)
|
|
+ strcat(buf, "optional/");
|
|
+ if (val & SYMBOL_WRITE)
|
|
+ strcat(buf, "write/");
|
|
+ if (val & SYMBOL_CHANGED)
|
|
+ strcat(buf, "changed/");
|
|
+ if (val & SYMBOL_AUTO)
|
|
+ strcat(buf, "auto/");
|
|
+
|
|
+ buf[strlen(buf) - 1] = '\0';
|
|
+
|
|
+ return buf;
|
|
+}
|
|
+
|
|
+void replace_button_icon(GladeXML * xml, GdkDrawable * window,
|
|
+ GtkStyle * style, gchar * btn_name, gchar ** xpm)
|
|
+{
|
|
+ GdkPixmap *pixmap;
|
|
+ GdkBitmap *mask;
|
|
+ GtkToolButton *button;
|
|
+ GtkWidget *image;
|
|
+
|
|
+ pixmap = gdk_pixmap_create_from_xpm_d(window, &mask,
|
|
+ &style->bg[GTK_STATE_NORMAL],
|
|
+ xpm);
|
|
+
|
|
+ button = GTK_TOOL_BUTTON(glade_xml_get_widget(xml, btn_name));
|
|
+ image = gtk_image_new_from_pixmap(pixmap, mask);
|
|
+ gtk_widget_show(image);
|
|
+ gtk_tool_button_set_icon_widget(button, image);
|
|
+}
|
|
+
|
|
+/* Main Window Initialization */
|
|
+void init_main_window(const gchar * glade_file)
|
|
+{
|
|
+ GladeXML *xml;
|
|
+ GtkWidget *widget;
|
|
+ GtkTextBuffer *txtbuf;
|
|
+ GtkStyle *style;
|
|
+
|
|
+ xml = glade_xml_new(glade_file, "window1", NULL);
|
|
+ if (!xml)
|
|
+ g_error(_("GUI loading failed !\n"));
|
|
+ glade_xml_signal_autoconnect(xml);
|
|
+
|
|
+ main_wnd = glade_xml_get_widget(xml, "window1");
|
|
+ hpaned = glade_xml_get_widget(xml, "hpaned1");
|
|
+ vpaned = glade_xml_get_widget(xml, "vpaned1");
|
|
+ tree1_w = glade_xml_get_widget(xml, "treeview1");
|
|
+ tree2_w = glade_xml_get_widget(xml, "treeview2");
|
|
+ text_w = glade_xml_get_widget(xml, "textview3");
|
|
+
|
|
+ back_btn = glade_xml_get_widget(xml, "button1");
|
|
+ gtk_widget_set_sensitive(back_btn, FALSE);
|
|
+
|
|
+ widget = glade_xml_get_widget(xml, "show_name1");
|
|
+ gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
|
|
+ show_name);
|
|
+
|
|
+ widget = glade_xml_get_widget(xml, "show_range1");
|
|
+ gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
|
|
+ show_range);
|
|
+
|
|
+ widget = glade_xml_get_widget(xml, "show_data1");
|
|
+ gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
|
|
+ show_value);
|
|
+
|
|
+ save_btn = glade_xml_get_widget(xml, "button3");
|
|
+ save_menu_item = glade_xml_get_widget(xml, "save1");
|
|
+ conf_set_changed_callback(conf_changed);
|
|
+
|
|
+ style = gtk_widget_get_style(main_wnd);
|
|
+ widget = glade_xml_get_widget(xml, "toolbar1");
|
|
+
|
|
+#if 0 /* Use stock Gtk icons instead */
|
|
+ replace_button_icon(xml, main_wnd->window, style,
|
|
+ "button1", (gchar **) xpm_back);
|
|
+ replace_button_icon(xml, main_wnd->window, style,
|
|
+ "button2", (gchar **) xpm_load);
|
|
+ replace_button_icon(xml, main_wnd->window, style,
|
|
+ "button3", (gchar **) xpm_save);
|
|
+#endif
|
|
+ replace_button_icon(xml, main_wnd->window, style,
|
|
+ "button4", (gchar **) xpm_single_view);
|
|
+ replace_button_icon(xml, main_wnd->window, style,
|
|
+ "button5", (gchar **) xpm_split_view);
|
|
+ replace_button_icon(xml, main_wnd->window, style,
|
|
+ "button6", (gchar **) xpm_tree_view);
|
|
+
|
|
+#if 0
|
|
+ switch (view_mode) {
|
|
+ case SINGLE_VIEW:
|
|
+ widget = glade_xml_get_widget(xml, "button4");
|
|
+ g_signal_emit_by_name(widget, "clicked");
|
|
+ break;
|
|
+ case SPLIT_VIEW:
|
|
+ widget = glade_xml_get_widget(xml, "button5");
|
|
+ g_signal_emit_by_name(widget, "clicked");
|
|
+ break;
|
|
+ case FULL_VIEW:
|
|
+ widget = glade_xml_get_widget(xml, "button6");
|
|
+ g_signal_emit_by_name(widget, "clicked");
|
|
+ break;
|
|
+ }
|
|
+#endif
|
|
+ txtbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
|
|
+ tag1 = gtk_text_buffer_create_tag(txtbuf, "mytag1",
|
|
+ "foreground", "red",
|
|
+ "weight", PANGO_WEIGHT_BOLD,
|
|
+ NULL);
|
|
+ tag2 = gtk_text_buffer_create_tag(txtbuf, "mytag2",
|
|
+ /*"style", PANGO_STYLE_OBLIQUE, */
|
|
+ NULL);
|
|
+
|
|
+ gtk_window_set_title(GTK_WINDOW(main_wnd), rootmenu.prompt->text);
|
|
+
|
|
+ gtk_widget_show(main_wnd);
|
|
+}
|
|
+
|
|
+void init_tree_model(void)
|
|
+{
|
|
+ gint i;
|
|
+
|
|
+ tree = tree2 = gtk_tree_store_new(COL_NUMBER,
|
|
+ G_TYPE_STRING, G_TYPE_STRING,
|
|
+ G_TYPE_STRING, G_TYPE_STRING,
|
|
+ G_TYPE_STRING, G_TYPE_STRING,
|
|
+ G_TYPE_POINTER, GDK_TYPE_COLOR,
|
|
+ G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF,
|
|
+ G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
|
|
+ G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
|
|
+ G_TYPE_BOOLEAN);
|
|
+ model2 = GTK_TREE_MODEL(tree2);
|
|
+
|
|
+ for (parents[0] = NULL, i = 1; i < 256; i++)
|
|
+ parents[i] = (GtkTreeIter *) g_malloc(sizeof(GtkTreeIter));
|
|
+
|
|
+ tree1 = gtk_tree_store_new(COL_NUMBER,
|
|
+ G_TYPE_STRING, G_TYPE_STRING,
|
|
+ G_TYPE_STRING, G_TYPE_STRING,
|
|
+ G_TYPE_STRING, G_TYPE_STRING,
|
|
+ G_TYPE_POINTER, GDK_TYPE_COLOR,
|
|
+ G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF,
|
|
+ G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
|
|
+ G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
|
|
+ G_TYPE_BOOLEAN);
|
|
+ model1 = GTK_TREE_MODEL(tree1);
|
|
+}
|
|
+
|
|
+void init_left_tree(void)
|
|
+{
|
|
+ GtkTreeView *view = GTK_TREE_VIEW(tree1_w);
|
|
+ GtkCellRenderer *renderer;
|
|
+ GtkTreeSelection *sel;
|
|
+ GtkTreeViewColumn *column;
|
|
+
|
|
+ gtk_tree_view_set_model(view, model1);
|
|
+ gtk_tree_view_set_headers_visible(view, TRUE);
|
|
+ gtk_tree_view_set_rules_hint(view, TRUE);
|
|
+
|
|
+ column = gtk_tree_view_column_new();
|
|
+ gtk_tree_view_append_column(view, column);
|
|
+ gtk_tree_view_column_set_title(column, _("Options"));
|
|
+
|
|
+ renderer = gtk_cell_renderer_toggle_new();
|
|
+ gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
|
|
+ renderer, FALSE);
|
|
+ gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
|
|
+ renderer,
|
|
+ "active", COL_BTNACT,
|
|
+ "inconsistent", COL_BTNINC,
|
|
+ "visible", COL_BTNVIS,
|
|
+ "radio", COL_BTNRAD, NULL);
|
|
+ renderer = gtk_cell_renderer_text_new();
|
|
+ gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
|
|
+ renderer, FALSE);
|
|
+ gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
|
|
+ renderer,
|
|
+ "text", COL_OPTION,
|
|
+ "foreground-gdk",
|
|
+ COL_COLOR, NULL);
|
|
+
|
|
+ sel = gtk_tree_view_get_selection(view);
|
|
+ gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
|
|
+ gtk_widget_realize(tree1_w);
|
|
+}
|
|
+
|
|
+static void renderer_edited(GtkCellRendererText * cell,
|
|
+ const gchar * path_string,
|
|
+ const gchar * new_text, gpointer user_data);
|
|
+
|
|
+void init_right_tree(void)
|
|
+{
|
|
+ GtkTreeView *view = GTK_TREE_VIEW(tree2_w);
|
|
+ GtkCellRenderer *renderer;
|
|
+ GtkTreeSelection *sel;
|
|
+ GtkTreeViewColumn *column;
|
|
+ gint i;
|
|
+
|
|
+ gtk_tree_view_set_model(view, model2);
|
|
+ gtk_tree_view_set_headers_visible(view, TRUE);
|
|
+ gtk_tree_view_set_rules_hint(view, TRUE);
|
|
+
|
|
+ column = gtk_tree_view_column_new();
|
|
+ gtk_tree_view_append_column(view, column);
|
|
+ gtk_tree_view_column_set_title(column, _("Options"));
|
|
+
|
|
+ renderer = gtk_cell_renderer_pixbuf_new();
|
|
+ gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
|
|
+ renderer, FALSE);
|
|
+ gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
|
|
+ renderer,
|
|
+ "pixbuf", COL_PIXBUF,
|
|
+ "visible", COL_PIXVIS, NULL);
|
|
+ renderer = gtk_cell_renderer_toggle_new();
|
|
+ gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
|
|
+ renderer, FALSE);
|
|
+ gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
|
|
+ renderer,
|
|
+ "active", COL_BTNACT,
|
|
+ "inconsistent", COL_BTNINC,
|
|
+ "visible", COL_BTNVIS,
|
|
+ "radio", COL_BTNRAD, NULL);
|
|
+ renderer = gtk_cell_renderer_text_new();
|
|
+ gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
|
|
+ renderer, FALSE);
|
|
+ gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),
|
|
+ renderer,
|
|
+ "text", COL_OPTION,
|
|
+ "foreground-gdk",
|
|
+ COL_COLOR, NULL);
|
|
+
|
|
+ renderer = gtk_cell_renderer_text_new();
|
|
+ gtk_tree_view_insert_column_with_attributes(view, -1,
|
|
+ _("Name"), renderer,
|
|
+ "text", COL_NAME,
|
|
+ "foreground-gdk",
|
|
+ COL_COLOR, NULL);
|
|
+ renderer = gtk_cell_renderer_text_new();
|
|
+ gtk_tree_view_insert_column_with_attributes(view, -1,
|
|
+ "N", renderer,
|
|
+ "text", COL_NO,
|
|
+ "foreground-gdk",
|
|
+ COL_COLOR, NULL);
|
|
+ renderer = gtk_cell_renderer_text_new();
|
|
+ gtk_tree_view_insert_column_with_attributes(view, -1,
|
|
+ "M", renderer,
|
|
+ "text", COL_MOD,
|
|
+ "foreground-gdk",
|
|
+ COL_COLOR, NULL);
|
|
+ renderer = gtk_cell_renderer_text_new();
|
|
+ gtk_tree_view_insert_column_with_attributes(view, -1,
|
|
+ "Y", renderer,
|
|
+ "text", COL_YES,
|
|
+ "foreground-gdk",
|
|
+ COL_COLOR, NULL);
|
|
+ renderer = gtk_cell_renderer_text_new();
|
|
+ gtk_tree_view_insert_column_with_attributes(view, -1,
|
|
+ _("Value"), renderer,
|
|
+ "text", COL_VALUE,
|
|
+ "editable",
|
|
+ COL_EDIT,
|
|
+ "foreground-gdk",
|
|
+ COL_COLOR, NULL);
|
|
+ g_signal_connect(G_OBJECT(renderer), "edited",
|
|
+ G_CALLBACK(renderer_edited), NULL);
|
|
+
|
|
+ column = gtk_tree_view_get_column(view, COL_NAME);
|
|
+ gtk_tree_view_column_set_visible(column, show_name);
|
|
+ column = gtk_tree_view_get_column(view, COL_NO);
|
|
+ gtk_tree_view_column_set_visible(column, show_range);
|
|
+ column = gtk_tree_view_get_column(view, COL_MOD);
|
|
+ gtk_tree_view_column_set_visible(column, show_range);
|
|
+ column = gtk_tree_view_get_column(view, COL_YES);
|
|
+ gtk_tree_view_column_set_visible(column, show_range);
|
|
+ column = gtk_tree_view_get_column(view, COL_VALUE);
|
|
+ gtk_tree_view_column_set_visible(column, show_value);
|
|
+
|
|
+ if (resizeable) {
|
|
+ for (i = 0; i < COL_VALUE; i++) {
|
|
+ column = gtk_tree_view_get_column(view, i);
|
|
+ gtk_tree_view_column_set_resizable(column, TRUE);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ sel = gtk_tree_view_get_selection(view);
|
|
+ gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
|
|
+}
|
|
+
|
|
+
|
|
+/* Utility Functions */
|
|
+
|
|
+
|
|
+static void text_insert_help(struct menu *menu)
|
|
+{
|
|
+ GtkTextBuffer *buffer;
|
|
+ GtkTextIter start, end;
|
|
+ const char *prompt = _(menu_get_prompt(menu));
|
|
+ struct gstr help = str_new();
|
|
+
|
|
+ menu_get_ext_help(menu, &help);
|
|
+
|
|
+ buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
|
|
+ gtk_text_buffer_get_bounds(buffer, &start, &end);
|
|
+ gtk_text_buffer_delete(buffer, &start, &end);
|
|
+ gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15);
|
|
+
|
|
+ gtk_text_buffer_get_end_iter(buffer, &end);
|
|
+ gtk_text_buffer_insert_with_tags(buffer, &end, prompt, -1, tag1,
|
|
+ NULL);
|
|
+ gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2);
|
|
+ gtk_text_buffer_get_end_iter(buffer, &end);
|
|
+ gtk_text_buffer_insert_with_tags(buffer, &end, str_get(&help), -1, tag2,
|
|
+ NULL);
|
|
+ str_free(&help);
|
|
+}
|
|
+
|
|
+
|
|
+static void text_insert_msg(const char *title, const char *message)
|
|
+{
|
|
+ GtkTextBuffer *buffer;
|
|
+ GtkTextIter start, end;
|
|
+ const char *msg = message;
|
|
+
|
|
+ buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));
|
|
+ gtk_text_buffer_get_bounds(buffer, &start, &end);
|
|
+ gtk_text_buffer_delete(buffer, &start, &end);
|
|
+ gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15);
|
|
+
|
|
+ gtk_text_buffer_get_end_iter(buffer, &end);
|
|
+ gtk_text_buffer_insert_with_tags(buffer, &end, title, -1, tag1,
|
|
+ NULL);
|
|
+ gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2);
|
|
+ gtk_text_buffer_get_end_iter(buffer, &end);
|
|
+ gtk_text_buffer_insert_with_tags(buffer, &end, msg, -1, tag2,
|
|
+ NULL);
|
|
+}
|
|
+
|
|
+
|
|
+/* Main Windows Callbacks */
|
|
+
|
|
+void on_save_activate(GtkMenuItem * menuitem, gpointer user_data);
|
|
+gboolean on_window1_delete_event(GtkWidget * widget, GdkEvent * event,
|
|
+ gpointer user_data)
|
|
+{
|
|
+ GtkWidget *dialog, *label;
|
|
+ gint result;
|
|
+
|
|
+ if (!conf_get_changed())
|
|
+ return FALSE;
|
|
+
|
|
+ dialog = gtk_dialog_new_with_buttons(_("Warning !"),
|
|
+ GTK_WINDOW(main_wnd),
|
|
+ (GtkDialogFlags)
|
|
+ (GTK_DIALOG_MODAL |
|
|
+ GTK_DIALOG_DESTROY_WITH_PARENT),
|
|
+ GTK_STOCK_OK,
|
|
+ GTK_RESPONSE_YES,
|
|
+ GTK_STOCK_NO,
|
|
+ GTK_RESPONSE_NO,
|
|
+ GTK_STOCK_CANCEL,
|
|
+ GTK_RESPONSE_CANCEL, NULL);
|
|
+ gtk_dialog_set_default_response(GTK_DIALOG(dialog),
|
|
+ GTK_RESPONSE_CANCEL);
|
|
+
|
|
+ label = gtk_label_new(_("\nSave configuration ?\n"));
|
|
+ gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label);
|
|
+ gtk_widget_show(label);
|
|
+
|
|
+ result = gtk_dialog_run(GTK_DIALOG(dialog));
|
|
+ switch (result) {
|
|
+ case GTK_RESPONSE_YES:
|
|
+ on_save_activate(NULL, NULL);
|
|
+ return FALSE;
|
|
+ case GTK_RESPONSE_NO:
|
|
+ return FALSE;
|
|
+ case GTK_RESPONSE_CANCEL:
|
|
+ case GTK_RESPONSE_DELETE_EVENT:
|
|
+ default:
|
|
+ gtk_widget_destroy(dialog);
|
|
+ return TRUE;
|
|
+ }
|
|
+
|
|
+ return FALSE;
|
|
+}
|
|
+
|
|
+
|
|
+void on_window1_destroy(GtkObject * object, gpointer user_data)
|
|
+{
|
|
+ gtk_main_quit();
|
|
+}
|
|
+
|
|
+
|
|
+void
|
|
+on_window1_size_request(GtkWidget * widget,
|
|
+ GtkRequisition * requisition, gpointer user_data)
|
|
+{
|
|
+ static gint old_h;
|
|
+ gint w, h;
|
|
+
|
|
+ if (widget->window == NULL)
|
|
+ gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h);
|
|
+ else
|
|
+ gdk_window_get_size(widget->window, &w, &h);
|
|
+
|
|
+ if (h == old_h)
|
|
+ return;
|
|
+ old_h = h;
|
|
+
|
|
+ gtk_paned_set_position(GTK_PANED(vpaned), 2 * h / 3);
|
|
+}
|
|
+
|
|
+
|
|
+/* Menu & Toolbar Callbacks */
|
|
+
|
|
+
|
|
+static void
|
|
+load_filename(GtkFileSelection * file_selector, gpointer user_data)
|
|
+{
|
|
+ const gchar *fn;
|
|
+
|
|
+ fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION
|
|
+ (user_data));
|
|
+
|
|
+ if (conf_read(fn))
|
|
+ text_insert_msg(_("Error"), _("Unable to load configuration !"));
|
|
+ else
|
|
+ display_tree(&rootmenu);
|
|
+}
|
|
+
|
|
+void on_load1_activate(GtkMenuItem * menuitem, gpointer user_data)
|
|
+{
|
|
+ GtkWidget *fs;
|
|
+
|
|
+ fs = gtk_file_selection_new(_("Load file..."));
|
|
+ g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button),
|
|
+ "clicked",
|
|
+ G_CALLBACK(load_filename), (gpointer) fs);
|
|
+ g_signal_connect_swapped(GTK_OBJECT
|
|
+ (GTK_FILE_SELECTION(fs)->ok_button),
|
|
+ "clicked", G_CALLBACK(gtk_widget_destroy),
|
|
+ (gpointer) fs);
|
|
+ g_signal_connect_swapped(GTK_OBJECT
|
|
+ (GTK_FILE_SELECTION(fs)->cancel_button),
|
|
+ "clicked", G_CALLBACK(gtk_widget_destroy),
|
|
+ (gpointer) fs);
|
|
+ gtk_widget_show(fs);
|
|
+}
|
|
+
|
|
+
|
|
+void on_save_activate(GtkMenuItem * menuitem, gpointer user_data)
|
|
+{
|
|
+ if (conf_write(NULL))
|
|
+ text_insert_msg(_("Error"), _("Unable to save configuration !"));
|
|
+}
|
|
+
|
|
+
|
|
+static void
|
|
+store_filename(GtkFileSelection * file_selector, gpointer user_data)
|
|
+{
|
|
+ const gchar *fn;
|
|
+
|
|
+ fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION
|
|
+ (user_data));
|
|
+
|
|
+ if (conf_write(fn))
|
|
+ text_insert_msg(_("Error"), _("Unable to save configuration !"));
|
|
+
|
|
+ gtk_widget_destroy(GTK_WIDGET(user_data));
|
|
+}
|
|
+
|
|
+void on_save_as1_activate(GtkMenuItem * menuitem, gpointer user_data)
|
|
+{
|
|
+ GtkWidget *fs;
|
|
+
|
|
+ fs = gtk_file_selection_new(_("Save file as..."));
|
|
+ g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button),
|
|
+ "clicked",
|
|
+ G_CALLBACK(store_filename), (gpointer) fs);
|
|
+ g_signal_connect_swapped(GTK_OBJECT
|
|
+ (GTK_FILE_SELECTION(fs)->ok_button),
|
|
+ "clicked", G_CALLBACK(gtk_widget_destroy),
|
|
+ (gpointer) fs);
|
|
+ g_signal_connect_swapped(GTK_OBJECT
|
|
+ (GTK_FILE_SELECTION(fs)->cancel_button),
|
|
+ "clicked", G_CALLBACK(gtk_widget_destroy),
|
|
+ (gpointer) fs);
|
|
+ gtk_widget_show(fs);
|
|
+}
|
|
+
|
|
+
|
|
+void on_quit1_activate(GtkMenuItem * menuitem, gpointer user_data)
|
|
+{
|
|
+ if (!on_window1_delete_event(NULL, NULL, NULL))
|
|
+ gtk_widget_destroy(GTK_WIDGET(main_wnd));
|
|
+}
|
|
+
|
|
+
|
|
+void on_show_name1_activate(GtkMenuItem * menuitem, gpointer user_data)
|
|
+{
|
|
+ GtkTreeViewColumn *col;
|
|
+
|
|
+ show_name = GTK_CHECK_MENU_ITEM(menuitem)->active;
|
|
+ col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NAME);
|
|
+ if (col)
|
|
+ gtk_tree_view_column_set_visible(col, show_name);
|
|
+}
|
|
+
|
|
+
|
|
+void on_show_range1_activate(GtkMenuItem * menuitem, gpointer user_data)
|
|
+{
|
|
+ GtkTreeViewColumn *col;
|
|
+
|
|
+ show_range = GTK_CHECK_MENU_ITEM(menuitem)->active;
|
|
+ col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NO);
|
|
+ if (col)
|
|
+ gtk_tree_view_column_set_visible(col, show_range);
|
|
+ col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_MOD);
|
|
+ if (col)
|
|
+ gtk_tree_view_column_set_visible(col, show_range);
|
|
+ col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_YES);
|
|
+ if (col)
|
|
+ gtk_tree_view_column_set_visible(col, show_range);
|
|
+
|
|
+}
|
|
+
|
|
+
|
|
+void on_show_data1_activate(GtkMenuItem * menuitem, gpointer user_data)
|
|
+{
|
|
+ GtkTreeViewColumn *col;
|
|
+
|
|
+ show_value = GTK_CHECK_MENU_ITEM(menuitem)->active;
|
|
+ col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_VALUE);
|
|
+ if (col)
|
|
+ gtk_tree_view_column_set_visible(col, show_value);
|
|
+}
|
|
+
|
|
+
|
|
+void
|
|
+on_set_option_mode1_activate(GtkMenuItem *menuitem, gpointer user_data)
|
|
+{
|
|
+ opt_mode = OPT_NORMAL;
|
|
+ gtk_tree_store_clear(tree2);
|
|
+ display_tree(&rootmenu); /* instead of update_tree to speed-up */
|
|
+}
|
|
+
|
|
+
|
|
+void
|
|
+on_set_option_mode2_activate(GtkMenuItem *menuitem, gpointer user_data)
|
|
+{
|
|
+ opt_mode = OPT_ALL;
|
|
+ gtk_tree_store_clear(tree2);
|
|
+ display_tree(&rootmenu); /* instead of update_tree to speed-up */
|
|
+}
|
|
+
|
|
+
|
|
+void
|
|
+on_set_option_mode3_activate(GtkMenuItem *menuitem, gpointer user_data)
|
|
+{
|
|
+ opt_mode = OPT_PROMPT;
|
|
+ gtk_tree_store_clear(tree2);
|
|
+ display_tree(&rootmenu); /* instead of update_tree to speed-up */
|
|
+}
|
|
+
|
|
+
|
|
+void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data)
|
|
+{
|
|
+ GtkWidget *dialog;
|
|
+ const gchar *intro_text = _(
|
|
+ "Welcome to gkc, the GTK+ graphical configuration tool\n"
|
|
+ "For each option, a blank box indicates the feature is disabled, a\n"
|
|
+ "check indicates it is enabled, and a dot indicates that it is to\n"
|
|
+ "be compiled as a module. Clicking on the box will cycle through the three states.\n"
|
|
+ "\n"
|
|
+ "If you do not see an option (e.g., a device driver) that you\n"
|
|
+ "believe should be present, try turning on Show All Options\n"
|
|
+ "under the Options menu.\n"
|
|
+ "Although there is no cross reference yet to help you figure out\n"
|
|
+ "what other options must be enabled to support the option you\n"
|
|
+ "are interested in, you can still view the help of a grayed-out\n"
|
|
+ "option.\n"
|
|
+ "\n"
|
|
+ "Toggling Show Debug Info under the Options menu will show \n"
|
|
+ "the dependencies, which you can then match by examining other options.");
|
|
+
|
|
+ dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
|
|
+ GTK_DIALOG_DESTROY_WITH_PARENT,
|
|
+ GTK_MESSAGE_INFO,
|
|
+ GTK_BUTTONS_CLOSE, "%s", intro_text);
|
|
+ g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
|
|
+ G_CALLBACK(gtk_widget_destroy),
|
|
+ GTK_OBJECT(dialog));
|
|
+ gtk_widget_show_all(dialog);
|
|
+}
|
|
+
|
|
+
|
|
+void on_about1_activate(GtkMenuItem * menuitem, gpointer user_data)
|
|
+{
|
|
+ GtkWidget *dialog;
|
|
+ const gchar *about_text =
|
|
+ _("gkc is copyright (c) 2002 Romain Lievin <roms@lpg.ticalc.org>.\n"
|
|
+ "Based on the source code from Roman Zippel.\n");
|
|
+
|
|
+ dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
|
|
+ GTK_DIALOG_DESTROY_WITH_PARENT,
|
|
+ GTK_MESSAGE_INFO,
|
|
+ GTK_BUTTONS_CLOSE, "%s", about_text);
|
|
+ g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
|
|
+ G_CALLBACK(gtk_widget_destroy),
|
|
+ GTK_OBJECT(dialog));
|
|
+ gtk_widget_show_all(dialog);
|
|
+}
|
|
+
|
|
+
|
|
+void on_license1_activate(GtkMenuItem * menuitem, gpointer user_data)
|
|
+{
|
|
+ GtkWidget *dialog;
|
|
+ const gchar *license_text =
|
|
+ _("gkc is released under the terms of the GNU GPL v2.\n"
|
|
+ "For more information, please see the source code or\n"
|
|
+ "visit http://www.fsf.org/licenses/licenses.html\n");
|
|
+
|
|
+ dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
|
|
+ GTK_DIALOG_DESTROY_WITH_PARENT,
|
|
+ GTK_MESSAGE_INFO,
|
|
+ GTK_BUTTONS_CLOSE, "%s", license_text);
|
|
+ g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
|
|
+ G_CALLBACK(gtk_widget_destroy),
|
|
+ GTK_OBJECT(dialog));
|
|
+ gtk_widget_show_all(dialog);
|
|
+}
|
|
+
|
|
+
|
|
+void on_back_clicked(GtkButton * button, gpointer user_data)
|
|
+{
|
|
+ enum prop_type ptype;
|
|
+
|
|
+ current = current->parent;
|
|
+ ptype = current->prompt ? current->prompt->type : P_UNKNOWN;
|
|
+ if (ptype != P_MENU)
|
|
+ current = current->parent;
|
|
+ display_tree_part();
|
|
+
|
|
+ if (current == &rootmenu)
|
|
+ gtk_widget_set_sensitive(back_btn, FALSE);
|
|
+}
|
|
+
|
|
+
|
|
+void on_load_clicked(GtkButton * button, gpointer user_data)
|
|
+{
|
|
+ on_load1_activate(NULL, user_data);
|
|
+}
|
|
+
|
|
+
|
|
+void on_single_clicked(GtkButton * button, gpointer user_data)
|
|
+{
|
|
+ view_mode = SINGLE_VIEW;
|
|
+ gtk_widget_hide(tree1_w);
|
|
+ current = &rootmenu;
|
|
+ display_tree_part();
|
|
+}
|
|
+
|
|
+
|
|
+void on_split_clicked(GtkButton * button, gpointer user_data)
|
|
+{
|
|
+ gint w, h;
|
|
+ view_mode = SPLIT_VIEW;
|
|
+ gtk_widget_show(tree1_w);
|
|
+ gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h);
|
|
+ gtk_paned_set_position(GTK_PANED(hpaned), w / 2);
|
|
+ if (tree2)
|
|
+ gtk_tree_store_clear(tree2);
|
|
+ display_list();
|
|
+
|
|
+ /* Disable back btn, like in full mode. */
|
|
+ gtk_widget_set_sensitive(back_btn, FALSE);
|
|
+}
|
|
+
|
|
+
|
|
+void on_full_clicked(GtkButton * button, gpointer user_data)
|
|
+{
|
|
+ view_mode = FULL_VIEW;
|
|
+ gtk_widget_hide(tree1_w);
|
|
+ if (tree2)
|
|
+ gtk_tree_store_clear(tree2);
|
|
+ display_tree(&rootmenu);
|
|
+ gtk_widget_set_sensitive(back_btn, FALSE);
|
|
+}
|
|
+
|
|
+
|
|
+void on_collapse_clicked(GtkButton * button, gpointer user_data)
|
|
+{
|
|
+ gtk_tree_view_collapse_all(GTK_TREE_VIEW(tree2_w));
|
|
+}
|
|
+
|
|
+
|
|
+void on_expand_clicked(GtkButton * button, gpointer user_data)
|
|
+{
|
|
+ gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w));
|
|
+}
|
|
+
|
|
+
|
|
+/* CTree Callbacks */
|
|
+
|
|
+/* Change hex/int/string value in the cell */
|
|
+static void renderer_edited(GtkCellRendererText * cell,
|
|
+ const gchar * path_string,
|
|
+ const gchar * new_text, gpointer user_data)
|
|
+{
|
|
+ GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
|
|
+ GtkTreeIter iter;
|
|
+ const char *old_def, *new_def;
|
|
+ struct menu *menu;
|
|
+ struct symbol *sym;
|
|
+
|
|
+ if (!gtk_tree_model_get_iter(model2, &iter, path))
|
|
+ return;
|
|
+
|
|
+ gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
|
|
+ sym = menu->sym;
|
|
+
|
|
+ gtk_tree_model_get(model2, &iter, COL_VALUE, &old_def, -1);
|
|
+ new_def = new_text;
|
|
+
|
|
+ sym_set_string_value(sym, new_def);
|
|
+
|
|
+ update_tree(&rootmenu, NULL);
|
|
+
|
|
+ gtk_tree_path_free(path);
|
|
+}
|
|
+
|
|
+/* Change the value of a symbol and update the tree */
|
|
+static void change_sym_value(struct menu *menu, gint col)
|
|
+{
|
|
+ struct symbol *sym = menu->sym;
|
|
+ tristate newval;
|
|
+
|
|
+ if (!sym)
|
|
+ return;
|
|
+
|
|
+ if (col == COL_NO)
|
|
+ newval = no;
|
|
+ else if (col == COL_MOD)
|
|
+ newval = mod;
|
|
+ else if (col == COL_YES)
|
|
+ newval = yes;
|
|
+ else
|
|
+ return;
|
|
+
|
|
+ switch (sym_get_type(sym)) {
|
|
+ case S_BOOLEAN:
|
|
+ case S_TRISTATE:
|
|
+ if (!sym_tristate_within_range(sym, newval))
|
|
+ newval = yes;
|
|
+ sym_set_tristate_value(sym, newval);
|
|
+ if (view_mode == FULL_VIEW)
|
|
+ update_tree(&rootmenu, NULL);
|
|
+ else if (view_mode == SPLIT_VIEW) {
|
|
+ update_tree(browsed, NULL);
|
|
+ display_list();
|
|
+ }
|
|
+ else if (view_mode == SINGLE_VIEW)
|
|
+ display_tree_part(); //fixme: keep exp/coll
|
|
+ break;
|
|
+ case S_INT:
|
|
+ case S_HEX:
|
|
+ case S_STRING:
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+}
|
|
+
|
|
+static void toggle_sym_value(struct menu *menu)
|
|
+{
|
|
+ if (!menu->sym)
|
|
+ return;
|
|
+
|
|
+ sym_toggle_tristate_value(menu->sym);
|
|
+ if (view_mode == FULL_VIEW)
|
|
+ update_tree(&rootmenu, NULL);
|
|
+ else if (view_mode == SPLIT_VIEW) {
|
|
+ update_tree(browsed, NULL);
|
|
+ display_list();
|
|
+ }
|
|
+ else if (view_mode == SINGLE_VIEW)
|
|
+ display_tree_part(); //fixme: keep exp/coll
|
|
+}
|
|
+
|
|
+static gint column2index(GtkTreeViewColumn * column)
|
|
+{
|
|
+ gint i;
|
|
+
|
|
+ for (i = 0; i < COL_NUMBER; i++) {
|
|
+ GtkTreeViewColumn *col;
|
|
+
|
|
+ col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), i);
|
|
+ if (col == column)
|
|
+ return i;
|
|
+ }
|
|
+
|
|
+ return -1;
|
|
+}
|
|
+
|
|
+
|
|
+/* User click: update choice (full) or goes down (single) */
|
|
+gboolean
|
|
+on_treeview2_button_press_event(GtkWidget * widget,
|
|
+ GdkEventButton * event, gpointer user_data)
|
|
+{
|
|
+ GtkTreeView *view = GTK_TREE_VIEW(widget);
|
|
+ GtkTreePath *path;
|
|
+ GtkTreeViewColumn *column;
|
|
+ GtkTreeIter iter;
|
|
+ struct menu *menu;
|
|
+ gint col;
|
|
+
|
|
+#if GTK_CHECK_VERSION(2,1,4) // bug in ctree with earlier version of GTK
|
|
+ gint tx = (gint) event->x;
|
|
+ gint ty = (gint) event->y;
|
|
+ gint cx, cy;
|
|
+
|
|
+ gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx,
|
|
+ &cy);
|
|
+#else
|
|
+ gtk_tree_view_get_cursor(view, &path, &column);
|
|
+#endif
|
|
+ if (path == NULL)
|
|
+ return FALSE;
|
|
+
|
|
+ if (!gtk_tree_model_get_iter(model2, &iter, path))
|
|
+ return FALSE;
|
|
+ gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
|
|
+
|
|
+ col = column2index(column);
|
|
+ if (event->type == GDK_2BUTTON_PRESS) {
|
|
+ enum prop_type ptype;
|
|
+ ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
|
|
+
|
|
+ if (ptype == P_MENU && view_mode != FULL_VIEW && col == COL_OPTION) {
|
|
+ // goes down into menu
|
|
+ current = menu;
|
|
+ display_tree_part();
|
|
+ gtk_widget_set_sensitive(back_btn, TRUE);
|
|
+ } else if ((col == COL_OPTION)) {
|
|
+ toggle_sym_value(menu);
|
|
+ gtk_tree_view_expand_row(view, path, TRUE);
|
|
+ }
|
|
+ } else {
|
|
+ if (col == COL_VALUE) {
|
|
+ toggle_sym_value(menu);
|
|
+ gtk_tree_view_expand_row(view, path, TRUE);
|
|
+ } else if (col == COL_NO || col == COL_MOD
|
|
+ || col == COL_YES) {
|
|
+ change_sym_value(menu, col);
|
|
+ gtk_tree_view_expand_row(view, path, TRUE);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return FALSE;
|
|
+}
|
|
+
|
|
+/* Key pressed: update choice */
|
|
+gboolean
|
|
+on_treeview2_key_press_event(GtkWidget * widget,
|
|
+ GdkEventKey * event, gpointer user_data)
|
|
+{
|
|
+ GtkTreeView *view = GTK_TREE_VIEW(widget);
|
|
+ GtkTreePath *path;
|
|
+ GtkTreeViewColumn *column;
|
|
+ GtkTreeIter iter;
|
|
+ struct menu *menu;
|
|
+ gint col;
|
|
+
|
|
+ gtk_tree_view_get_cursor(view, &path, &column);
|
|
+ if (path == NULL)
|
|
+ return FALSE;
|
|
+
|
|
+ if (event->keyval == GDK_space) {
|
|
+ if (gtk_tree_view_row_expanded(view, path))
|
|
+ gtk_tree_view_collapse_row(view, path);
|
|
+ else
|
|
+ gtk_tree_view_expand_row(view, path, FALSE);
|
|
+ return TRUE;
|
|
+ }
|
|
+ if (event->keyval == GDK_KP_Enter) {
|
|
+ }
|
|
+ if (widget == tree1_w)
|
|
+ return FALSE;
|
|
+
|
|
+ gtk_tree_model_get_iter(model2, &iter, path);
|
|
+ gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
|
|
+
|
|
+ if (!strcasecmp(event->string, "n"))
|
|
+ col = COL_NO;
|
|
+ else if (!strcasecmp(event->string, "m"))
|
|
+ col = COL_MOD;
|
|
+ else if (!strcasecmp(event->string, "y"))
|
|
+ col = COL_YES;
|
|
+ else
|
|
+ col = -1;
|
|
+ change_sym_value(menu, col);
|
|
+
|
|
+ return FALSE;
|
|
+}
|
|
+
|
|
+
|
|
+/* Row selection changed: update help */
|
|
+void
|
|
+on_treeview2_cursor_changed(GtkTreeView * treeview, gpointer user_data)
|
|
+{
|
|
+ GtkTreeSelection *selection;
|
|
+ GtkTreeIter iter;
|
|
+ struct menu *menu;
|
|
+
|
|
+ selection = gtk_tree_view_get_selection(treeview);
|
|
+ if (gtk_tree_selection_get_selected(selection, &model2, &iter)) {
|
|
+ gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
|
|
+ text_insert_help(menu);
|
|
+ }
|
|
+}
|
|
+
|
|
+
|
|
+/* User click: display sub-tree in the right frame. */
|
|
+gboolean
|
|
+on_treeview1_button_press_event(GtkWidget * widget,
|
|
+ GdkEventButton * event, gpointer user_data)
|
|
+{
|
|
+ GtkTreeView *view = GTK_TREE_VIEW(widget);
|
|
+ GtkTreePath *path;
|
|
+ GtkTreeViewColumn *column;
|
|
+ GtkTreeIter iter;
|
|
+ struct menu *menu;
|
|
+
|
|
+ gint tx = (gint) event->x;
|
|
+ gint ty = (gint) event->y;
|
|
+ gint cx, cy;
|
|
+
|
|
+ gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx,
|
|
+ &cy);
|
|
+ if (path == NULL)
|
|
+ return FALSE;
|
|
+
|
|
+ gtk_tree_model_get_iter(model1, &iter, path);
|
|
+ gtk_tree_model_get(model1, &iter, COL_MENU, &menu, -1);
|
|
+
|
|
+ if (event->type == GDK_2BUTTON_PRESS) {
|
|
+ toggle_sym_value(menu);
|
|
+ current = menu;
|
|
+ display_tree_part();
|
|
+ } else {
|
|
+ browsed = menu;
|
|
+ display_tree_part();
|
|
+ }
|
|
+
|
|
+ gtk_widget_realize(tree2_w);
|
|
+ gtk_tree_view_set_cursor(view, path, NULL, FALSE);
|
|
+ gtk_widget_grab_focus(tree2_w);
|
|
+
|
|
+ return FALSE;
|
|
+}
|
|
+
|
|
+
|
|
+/* Fill a row of strings */
|
|
+static gchar **fill_row(struct menu *menu)
|
|
+{
|
|
+ static gchar *row[COL_NUMBER];
|
|
+ struct symbol *sym = menu->sym;
|
|
+ const char *def;
|
|
+ int stype;
|
|
+ tristate val;
|
|
+ enum prop_type ptype;
|
|
+ int i;
|
|
+
|
|
+ for (i = COL_OPTION; i <= COL_COLOR; i++)
|
|
+ g_free(row[i]);
|
|
+ bzero(row, sizeof(row));
|
|
+
|
|
+ row[COL_OPTION] =
|
|
+ g_strdup_printf("%s %s", _(menu_get_prompt(menu)),
|
|
+ sym && !sym_has_value(sym) ? "(NEW)" : "");
|
|
+
|
|
+ if (opt_mode == OPT_ALL && !menu_is_visible(menu))
|
|
+ row[COL_COLOR] = g_strdup("DarkGray");
|
|
+ else if (opt_mode == OPT_PROMPT &&
|
|
+ menu_has_prompt(menu) && !menu_is_visible(menu))
|
|
+ row[COL_COLOR] = g_strdup("DarkGray");
|
|
+ else
|
|
+ row[COL_COLOR] = g_strdup("Black");
|
|
+
|
|
+ ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
|
|
+ switch (ptype) {
|
|
+ case P_MENU:
|
|
+ row[COL_PIXBUF] = (gchar *) xpm_menu;
|
|
+ if (view_mode == SINGLE_VIEW)
|
|
+ row[COL_PIXVIS] = GINT_TO_POINTER(TRUE);
|
|
+ row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
|
|
+ break;
|
|
+ case P_COMMENT:
|
|
+ row[COL_PIXBUF] = (gchar *) xpm_void;
|
|
+ row[COL_PIXVIS] = GINT_TO_POINTER(FALSE);
|
|
+ row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
|
|
+ break;
|
|
+ default:
|
|
+ row[COL_PIXBUF] = (gchar *) xpm_void;
|
|
+ row[COL_PIXVIS] = GINT_TO_POINTER(FALSE);
|
|
+ row[COL_BTNVIS] = GINT_TO_POINTER(TRUE);
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if (!sym)
|
|
+ return row;
|
|
+ row[COL_NAME] = g_strdup(sym->name);
|
|
+
|
|
+ sym_calc_value(sym);
|
|
+ sym->flags &= ~SYMBOL_CHANGED;
|
|
+
|
|
+ if (sym_is_choice(sym)) { // parse childs for getting final value
|
|
+ struct menu *child;
|
|
+ struct symbol *def_sym = sym_get_choice_value(sym);
|
|
+ struct menu *def_menu = NULL;
|
|
+
|
|
+ row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
|
|
+
|
|
+ for (child = menu->list; child; child = child->next) {
|
|
+ if (menu_is_visible(child)
|
|
+ && child->sym == def_sym)
|
|
+ def_menu = child;
|
|
+ }
|
|
+
|
|
+ if (def_menu)
|
|
+ row[COL_VALUE] =
|
|
+ g_strdup(_(menu_get_prompt(def_menu)));
|
|
+ }
|
|
+ if (sym->flags & SYMBOL_CHOICEVAL)
|
|
+ row[COL_BTNRAD] = GINT_TO_POINTER(TRUE);
|
|
+
|
|
+ stype = sym_get_type(sym);
|
|
+ switch (stype) {
|
|
+ case S_BOOLEAN:
|
|
+ if (GPOINTER_TO_INT(row[COL_PIXVIS]) == FALSE)
|
|
+ row[COL_BTNVIS] = GINT_TO_POINTER(TRUE);
|
|
+ if (sym_is_choice(sym))
|
|
+ break;
|
|
+ /* fall through */
|
|
+ case S_TRISTATE:
|
|
+ val = sym_get_tristate_value(sym);
|
|
+ switch (val) {
|
|
+ case no:
|
|
+ row[COL_NO] = g_strdup("N");
|
|
+ row[COL_VALUE] = g_strdup("N");
|
|
+ row[COL_BTNACT] = GINT_TO_POINTER(FALSE);
|
|
+ row[COL_BTNINC] = GINT_TO_POINTER(FALSE);
|
|
+ break;
|
|
+ case mod:
|
|
+ row[COL_MOD] = g_strdup("M");
|
|
+ row[COL_VALUE] = g_strdup("M");
|
|
+ row[COL_BTNINC] = GINT_TO_POINTER(TRUE);
|
|
+ break;
|
|
+ case yes:
|
|
+ row[COL_YES] = g_strdup("Y");
|
|
+ row[COL_VALUE] = g_strdup("Y");
|
|
+ row[COL_BTNACT] = GINT_TO_POINTER(TRUE);
|
|
+ row[COL_BTNINC] = GINT_TO_POINTER(FALSE);
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if (val != no && sym_tristate_within_range(sym, no))
|
|
+ row[COL_NO] = g_strdup("_");
|
|
+ if (val != mod && sym_tristate_within_range(sym, mod))
|
|
+ row[COL_MOD] = g_strdup("_");
|
|
+ if (val != yes && sym_tristate_within_range(sym, yes))
|
|
+ row[COL_YES] = g_strdup("_");
|
|
+ break;
|
|
+ case S_INT:
|
|
+ case S_HEX:
|
|
+ case S_STRING:
|
|
+ def = sym_get_string_value(sym);
|
|
+ row[COL_VALUE] = g_strdup(def);
|
|
+ row[COL_EDIT] = GINT_TO_POINTER(TRUE);
|
|
+ row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ return row;
|
|
+}
|
|
+
|
|
+
|
|
+/* Set the node content with a row of strings */
|
|
+static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row)
|
|
+{
|
|
+ GdkColor color;
|
|
+ gboolean success;
|
|
+ GdkPixbuf *pix;
|
|
+
|
|
+ pix = gdk_pixbuf_new_from_xpm_data((const char **)
|
|
+ row[COL_PIXBUF]);
|
|
+
|
|
+ gdk_color_parse(row[COL_COLOR], &color);
|
|
+ gdk_colormap_alloc_colors(gdk_colormap_get_system(), &color, 1,
|
|
+ FALSE, FALSE, &success);
|
|
+
|
|
+ gtk_tree_store_set(tree, node,
|
|
+ COL_OPTION, row[COL_OPTION],
|
|
+ COL_NAME, row[COL_NAME],
|
|
+ COL_NO, row[COL_NO],
|
|
+ COL_MOD, row[COL_MOD],
|
|
+ COL_YES, row[COL_YES],
|
|
+ COL_VALUE, row[COL_VALUE],
|
|
+ COL_MENU, (gpointer) menu,
|
|
+ COL_COLOR, &color,
|
|
+ COL_EDIT, GPOINTER_TO_INT(row[COL_EDIT]),
|
|
+ COL_PIXBUF, pix,
|
|
+ COL_PIXVIS, GPOINTER_TO_INT(row[COL_PIXVIS]),
|
|
+ COL_BTNVIS, GPOINTER_TO_INT(row[COL_BTNVIS]),
|
|
+ COL_BTNACT, GPOINTER_TO_INT(row[COL_BTNACT]),
|
|
+ COL_BTNINC, GPOINTER_TO_INT(row[COL_BTNINC]),
|
|
+ COL_BTNRAD, GPOINTER_TO_INT(row[COL_BTNRAD]),
|
|
+ -1);
|
|
+
|
|
+ g_object_unref(pix);
|
|
+}
|
|
+
|
|
+
|
|
+/* Add a node to the tree */
|
|
+static void place_node(struct menu *menu, char **row)
|
|
+{
|
|
+ GtkTreeIter *parent = parents[indent - 1];
|
|
+ GtkTreeIter *node = parents[indent];
|
|
+
|
|
+ gtk_tree_store_append(tree, node, parent);
|
|
+ set_node(node, menu, row);
|
|
+}
|
|
+
|
|
+
|
|
+/* Find a node in the GTK+ tree */
|
|
+static GtkTreeIter found;
|
|
+
|
|
+/*
|
|
+ * Find a menu in the GtkTree starting at parent.
|
|
+ */
|
|
+GtkTreeIter *gtktree_iter_find_node(GtkTreeIter * parent,
|
|
+ struct menu *tofind)
|
|
+{
|
|
+ GtkTreeIter iter;
|
|
+ GtkTreeIter *child = &iter;
|
|
+ gboolean valid;
|
|
+ GtkTreeIter *ret;
|
|
+
|
|
+ valid = gtk_tree_model_iter_children(model2, child, parent);
|
|
+ while (valid) {
|
|
+ struct menu *menu;
|
|
+
|
|
+ gtk_tree_model_get(model2, child, 6, &menu, -1);
|
|
+
|
|
+ if (menu == tofind) {
|
|
+ memcpy(&found, child, sizeof(GtkTreeIter));
|
|
+ return &found;
|
|
+ }
|
|
+
|
|
+ ret = gtktree_iter_find_node(child, tofind);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ valid = gtk_tree_model_iter_next(model2, child);
|
|
+ }
|
|
+
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+
|
|
+/*
|
|
+ * Update the tree by adding/removing entries
|
|
+ * Does not change other nodes
|
|
+ */
|
|
+static void update_tree(struct menu *src, GtkTreeIter * dst)
|
|
+{
|
|
+ struct menu *child1;
|
|
+ GtkTreeIter iter, tmp;
|
|
+ GtkTreeIter *child2 = &iter;
|
|
+ gboolean valid;
|
|
+ GtkTreeIter *sibling;
|
|
+ struct symbol *sym;
|
|
+ struct menu *menu1, *menu2;
|
|
+
|
|
+ if (src == &rootmenu)
|
|
+ indent = 1;
|
|
+
|
|
+ valid = gtk_tree_model_iter_children(model2, child2, dst);
|
|
+ for (child1 = src->list; child1; child1 = child1->next) {
|
|
+
|
|
+ sym = child1->sym;
|
|
+
|
|
+ reparse:
|
|
+ menu1 = child1;
|
|
+ if (valid)
|
|
+ gtk_tree_model_get(model2, child2, COL_MENU,
|
|
+ &menu2, -1);
|
|
+ else
|
|
+ menu2 = NULL; // force adding of a first child
|
|
+
|
|
+#ifdef DEBUG
|
|
+ printf("%*c%s | %s\n", indent, ' ',
|
|
+ menu1 ? menu_get_prompt(menu1) : "nil",
|
|
+ menu2 ? menu_get_prompt(menu2) : "nil");
|
|
+#endif
|
|
+
|
|
+ if ((opt_mode == OPT_NORMAL && !menu_is_visible(child1)) ||
|
|
+ (opt_mode == OPT_PROMPT && !menu_has_prompt(child1)) ||
|
|
+ (opt_mode == OPT_ALL && !menu_get_prompt(child1))) {
|
|
+
|
|
+ /* remove node */
|
|
+ if (gtktree_iter_find_node(dst, menu1) != NULL) {
|
|
+ memcpy(&tmp, child2, sizeof(GtkTreeIter));
|
|
+ valid = gtk_tree_model_iter_next(model2,
|
|
+ child2);
|
|
+ gtk_tree_store_remove(tree2, &tmp);
|
|
+ if (!valid)
|
|
+ return; /* next parent */
|
|
+ else
|
|
+ goto reparse; /* next child */
|
|
+ } else
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ if (menu1 != menu2) {
|
|
+ if (gtktree_iter_find_node(dst, menu1) == NULL) { // add node
|
|
+ if (!valid && !menu2)
|
|
+ sibling = NULL;
|
|
+ else
|
|
+ sibling = child2;
|
|
+ gtk_tree_store_insert_before(tree2,
|
|
+ child2,
|
|
+ dst, sibling);
|
|
+ set_node(child2, menu1, fill_row(menu1));
|
|
+ if (menu2 == NULL)
|
|
+ valid = TRUE;
|
|
+ } else { // remove node
|
|
+ memcpy(&tmp, child2, sizeof(GtkTreeIter));
|
|
+ valid = gtk_tree_model_iter_next(model2,
|
|
+ child2);
|
|
+ gtk_tree_store_remove(tree2, &tmp);
|
|
+ if (!valid)
|
|
+ return; // next parent
|
|
+ else
|
|
+ goto reparse; // next child
|
|
+ }
|
|
+ } else if (sym && (sym->flags & SYMBOL_CHANGED)) {
|
|
+ set_node(child2, menu1, fill_row(menu1));
|
|
+ }
|
|
+
|
|
+ indent++;
|
|
+ update_tree(child1, child2);
|
|
+ indent--;
|
|
+
|
|
+ valid = gtk_tree_model_iter_next(model2, child2);
|
|
+ }
|
|
+}
|
|
+
|
|
+
|
|
+/* Display the whole tree (single/split/full view) */
|
|
+static void display_tree(struct menu *menu)
|
|
+{
|
|
+ struct symbol *sym;
|
|
+ struct property *prop;
|
|
+ struct menu *child;
|
|
+ enum prop_type ptype;
|
|
+
|
|
+ if (menu == &rootmenu) {
|
|
+ indent = 1;
|
|
+ current = &rootmenu;
|
|
+ }
|
|
+
|
|
+ for (child = menu->list; child; child = child->next) {
|
|
+ prop = child->prompt;
|
|
+ sym = child->sym;
|
|
+ ptype = prop ? prop->type : P_UNKNOWN;
|
|
+
|
|
+ if (sym)
|
|
+ sym->flags &= ~SYMBOL_CHANGED;
|
|
+
|
|
+ if ((view_mode == SPLIT_VIEW)
|
|
+ && !(child->flags & MENU_ROOT) && (tree == tree1))
|
|
+ continue;
|
|
+
|
|
+ if ((view_mode == SPLIT_VIEW) && (child->flags & MENU_ROOT)
|
|
+ && (tree == tree2))
|
|
+ continue;
|
|
+
|
|
+ if ((opt_mode == OPT_NORMAL && menu_is_visible(child)) ||
|
|
+ (opt_mode == OPT_PROMPT && menu_has_prompt(child)) ||
|
|
+ (opt_mode == OPT_ALL && menu_get_prompt(child)))
|
|
+ place_node(child, fill_row(child));
|
|
+#ifdef DEBUG
|
|
+ printf("%*c%s: ", indent, ' ', menu_get_prompt(child));
|
|
+ printf("%s", child->flags & MENU_ROOT ? "rootmenu | " : "");
|
|
+ printf("%s", prop_get_type_name(ptype));
|
|
+ printf(" | ");
|
|
+ if (sym) {
|
|
+ printf("%s", sym_type_name(sym->type));
|
|
+ printf(" | ");
|
|
+ printf("%s", dbg_sym_flags(sym->flags));
|
|
+ printf("\n");
|
|
+ } else
|
|
+ printf("\n");
|
|
+#endif
|
|
+ if ((view_mode != FULL_VIEW) && (ptype == P_MENU)
|
|
+ && (tree == tree2))
|
|
+ continue;
|
|
+/*
|
|
+ if (((menu != &rootmenu) && !(menu->flags & MENU_ROOT))
|
|
+ || (view_mode == FULL_VIEW)
|
|
+ || (view_mode == SPLIT_VIEW))*/
|
|
+
|
|
+ /* Change paned position if the view is not in 'split mode' */
|
|
+ if (view_mode == SINGLE_VIEW || view_mode == FULL_VIEW) {
|
|
+ gtk_paned_set_position(GTK_PANED(hpaned), 0);
|
|
+ }
|
|
+
|
|
+ if (((view_mode == SINGLE_VIEW) && (menu->flags & MENU_ROOT))
|
|
+ || (view_mode == FULL_VIEW)
|
|
+ || (view_mode == SPLIT_VIEW)) {
|
|
+ indent++;
|
|
+ display_tree(child);
|
|
+ indent--;
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+/* Display a part of the tree starting at current node (single/split view) */
|
|
+static void display_tree_part(void)
|
|
+{
|
|
+ if (tree2)
|
|
+ gtk_tree_store_clear(tree2);
|
|
+ if (view_mode == SINGLE_VIEW)
|
|
+ display_tree(current);
|
|
+ else if (view_mode == SPLIT_VIEW)
|
|
+ display_tree(browsed);
|
|
+ gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w));
|
|
+}
|
|
+
|
|
+/* Display the list in the left frame (split view) */
|
|
+static void display_list(void)
|
|
+{
|
|
+ if (tree1)
|
|
+ gtk_tree_store_clear(tree1);
|
|
+
|
|
+ tree = tree1;
|
|
+ display_tree(&rootmenu);
|
|
+ gtk_tree_view_expand_all(GTK_TREE_VIEW(tree1_w));
|
|
+ tree = tree2;
|
|
+}
|
|
+
|
|
+void fixup_rootmenu(struct menu *menu)
|
|
+{
|
|
+ struct menu *child;
|
|
+ static int menu_cnt = 0;
|
|
+
|
|
+ menu->flags |= MENU_ROOT;
|
|
+ for (child = menu->list; child; child = child->next) {
|
|
+ if (child->prompt && child->prompt->type == P_MENU) {
|
|
+ menu_cnt++;
|
|
+ fixup_rootmenu(child);
|
|
+ menu_cnt--;
|
|
+ } else if (!menu_cnt)
|
|
+ fixup_rootmenu(child);
|
|
+ }
|
|
+}
|
|
+
|
|
+
|
|
+/* Main */
|
|
+int main(int ac, char *av[])
|
|
+{
|
|
+ const char *name;
|
|
+ char *env;
|
|
+ gchar *glade_file;
|
|
+
|
|
+ bindtextdomain(PACKAGE, LOCALEDIR);
|
|
+ bind_textdomain_codeset(PACKAGE, "UTF-8");
|
|
+ textdomain(PACKAGE);
|
|
+
|
|
+ /* GTK stuffs */
|
|
+ gtk_set_locale();
|
|
+ gtk_init(&ac, &av);
|
|
+ glade_init();
|
|
+
|
|
+ //add_pixmap_directory (PACKAGE_DATA_DIR "/" PACKAGE "/pixmaps");
|
|
+ //add_pixmap_directory (PACKAGE_SOURCE_DIR "/pixmaps");
|
|
+
|
|
+ /* Determine GUI path */
|
|
+ env = getenv(SRCTREE);
|
|
+ if (env)
|
|
+ glade_file = g_strconcat(env, "/scripts/kconfig/gconf.glade", NULL);
|
|
+ else if (av[0][0] == '/')
|
|
+ glade_file = g_strconcat(av[0], ".glade", NULL);
|
|
+ else
|
|
+ glade_file = g_strconcat(g_get_current_dir(), "/", av[0], ".glade", NULL);
|
|
+
|
|
+ /* Conf stuffs */
|
|
+ if (ac > 1 && av[1][0] == '-') {
|
|
+ switch (av[1][1]) {
|
|
+ case 'a':
|
|
+ //showAll = 1;
|
|
+ break;
|
|
+ case 'h':
|
|
+ case '?':
|
|
+ printf("%s <config>\n", av[0]);
|
|
+ exit(0);
|
|
+ }
|
|
+ name = av[2];
|
|
+ } else
|
|
+ name = av[1];
|
|
+
|
|
+ conf_parse(name);
|
|
+ fixup_rootmenu(&rootmenu);
|
|
+ conf_read(NULL);
|
|
+
|
|
+ /* Load the interface and connect signals */
|
|
+ init_main_window(glade_file);
|
|
+ init_tree_model();
|
|
+ init_left_tree();
|
|
+ init_right_tree();
|
|
+
|
|
+ switch (view_mode) {
|
|
+ case SINGLE_VIEW:
|
|
+ display_tree_part();
|
|
+ break;
|
|
+ case SPLIT_VIEW:
|
|
+ display_list();
|
|
+ break;
|
|
+ case FULL_VIEW:
|
|
+ display_tree(&rootmenu);
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ gtk_main();
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static void conf_changed(void)
|
|
+{
|
|
+ bool changed = conf_get_changed();
|
|
+ gtk_widget_set_sensitive(save_btn, changed);
|
|
+ gtk_widget_set_sensitive(save_menu_item, changed);
|
|
+}
|
|
diff --git a/scripts/kconfig/gconf.glade b/scripts/kconfig/gconf.glade
|
|
new file mode 100644
|
|
index 0000000..aa483cb
|
|
--- /dev/null
|
|
+++ b/scripts/kconfig/gconf.glade
|
|
@@ -0,0 +1,661 @@
|
|
+<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
|
|
+
|
|
+<glade-interface>
|
|
+
|
|
+<widget class="GtkWindow" id="window1">
|
|
+ <property name="visible">True</property>
|
|
+ <property name="title" translatable="yes">Gtk Kernel Configurator</property>
|
|
+ <property name="type">GTK_WINDOW_TOPLEVEL</property>
|
|
+ <property name="window_position">GTK_WIN_POS_NONE</property>
|
|
+ <property name="modal">False</property>
|
|
+ <property name="default_width">640</property>
|
|
+ <property name="default_height">480</property>
|
|
+ <property name="resizable">True</property>
|
|
+ <property name="destroy_with_parent">False</property>
|
|
+ <property name="decorated">True</property>
|
|
+ <property name="skip_taskbar_hint">False</property>
|
|
+ <property name="skip_pager_hint">False</property>
|
|
+ <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
|
|
+ <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
|
|
+ <signal name="destroy" handler="on_window1_destroy" object="window1"/>
|
|
+ <signal name="size_request" handler="on_window1_size_request" object="vpaned1" last_modification_time="Fri, 11 Jan 2002 16:17:11 GMT"/>
|
|
+ <signal name="delete_event" handler="on_window1_delete_event" object="window1" last_modification_time="Sun, 09 Mar 2003 19:42:46 GMT"/>
|
|
+
|
|
+ <child>
|
|
+ <widget class="GtkVBox" id="vbox1">
|
|
+ <property name="visible">True</property>
|
|
+ <property name="homogeneous">False</property>
|
|
+ <property name="spacing">0</property>
|
|
+
|
|
+ <child>
|
|
+ <widget class="GtkMenuBar" id="menubar1">
|
|
+ <property name="visible">True</property>
|
|
+
|
|
+ <child>
|
|
+ <widget class="GtkMenuItem" id="file1">
|
|
+ <property name="visible">True</property>
|
|
+ <property name="label" translatable="yes">_File</property>
|
|
+ <property name="use_underline">True</property>
|
|
+
|
|
+ <child>
|
|
+ <widget class="GtkMenu" id="file1_menu">
|
|
+
|
|
+ <child>
|
|
+ <widget class="GtkImageMenuItem" id="load1">
|
|
+ <property name="visible">True</property>
|
|
+ <property name="tooltip" translatable="yes">Load a config file</property>
|
|
+ <property name="label" translatable="yes">_Load</property>
|
|
+ <property name="use_underline">True</property>
|
|
+ <signal name="activate" handler="on_load1_activate"/>
|
|
+ <accelerator key="L" modifiers="GDK_CONTROL_MASK" signal="activate"/>
|
|
+
|
|
+ <child internal-child="image">
|
|
+ <widget class="GtkImage" id="image39">
|
|
+ <property name="visible">True</property>
|
|
+ <property name="stock">gtk-open</property>
|
|
+ <property name="icon_size">1</property>
|
|
+ <property name="xalign">0.5</property>
|
|
+ <property name="yalign">0.5</property>
|
|
+ <property name="xpad">0</property>
|
|
+ <property name="ypad">0</property>
|
|
+ </widget>
|
|
+ </child>
|
|
+ </widget>
|
|
+ </child>
|
|
+
|
|
+ <child>
|
|
+ <widget class="GtkImageMenuItem" id="save1">
|
|
+ <property name="visible">True</property>
|
|
+ <property name="tooltip" translatable="yes">Save the config in .config</property>
|
|
+ <property name="label" translatable="yes">_Save</property>
|
|
+ <property name="use_underline">True</property>
|
|
+ <signal name="activate" handler="on_save_activate"/>
|
|
+ <accelerator key="S" modifiers="GDK_CONTROL_MASK" signal="activate"/>
|
|
+
|
|
+ <child internal-child="image">
|
|
+ <widget class="GtkImage" id="image40">
|
|
+ <property name="visible">True</property>
|
|
+ <property name="stock">gtk-save</property>
|
|
+ <property name="icon_size">1</property>
|
|
+ <property name="xalign">0.5</property>
|
|
+ <property name="yalign">0.5</property>
|
|
+ <property name="xpad">0</property>
|
|
+ <property name="ypad">0</property>
|
|
+ </widget>
|
|
+ </child>
|
|
+ </widget>
|
|
+ </child>
|
|
+
|
|
+ <child>
|
|
+ <widget class="GtkImageMenuItem" id="save_as1">
|
|
+ <property name="visible">True</property>
|
|
+ <property name="tooltip" translatable="yes">Save the config in a file</property>
|
|
+ <property name="label" translatable="yes">Save _as</property>
|
|
+ <property name="use_underline">True</property>
|
|
+ <signal name="activate" handler="on_save_as1_activate"/>
|
|
+
|
|
+ <child internal-child="image">
|
|
+ <widget class="GtkImage" id="image41">
|
|
+ <property name="visible">True</property>
|
|
+ <property name="stock">gtk-save-as</property>
|
|
+ <property name="icon_size">1</property>
|
|
+ <property name="xalign">0.5</property>
|
|
+ <property name="yalign">0.5</property>
|
|
+ <property name="xpad">0</property>
|
|
+ <property name="ypad">0</property>
|
|
+ </widget>
|
|
+ </child>
|
|
+ </widget>
|
|
+ </child>
|
|
+
|
|
+ <child>
|
|
+ <widget class="GtkSeparatorMenuItem" id="separator1">
|
|
+ <property name="visible">True</property>
|
|
+ </widget>
|
|
+ </child>
|
|
+
|
|
+ <child>
|
|
+ <widget class="GtkImageMenuItem" id="quit1">
|
|
+ <property name="visible">True</property>
|
|
+ <property name="label" translatable="yes">_Quit</property>
|
|
+ <property name="use_underline">True</property>
|
|
+ <signal name="activate" handler="on_quit1_activate"/>
|
|
+ <accelerator key="Q" modifiers="GDK_CONTROL_MASK" signal="activate"/>
|
|
+
|
|
+ <child internal-child="image">
|
|
+ <widget class="GtkImage" id="image42">
|
|
+ <property name="visible">True</property>
|
|
+ <property name="stock">gtk-quit</property>
|
|
+ <property name="icon_size">1</property>
|
|
+ <property name="xalign">0.5</property>
|
|
+ <property name="yalign">0.5</property>
|
|
+ <property name="xpad">0</property>
|
|
+ <property name="ypad">0</property>
|
|
+ </widget>
|
|
+ </child>
|
|
+ </widget>
|
|
+ </child>
|
|
+ </widget>
|
|
+ </child>
|
|
+ </widget>
|
|
+ </child>
|
|
+
|
|
+ <child>
|
|
+ <widget class="GtkMenuItem" id="options1">
|
|
+ <property name="visible">True</property>
|
|
+ <property name="label" translatable="yes">_Options</property>
|
|
+ <property name="use_underline">True</property>
|
|
+
|
|
+ <child>
|
|
+ <widget class="GtkMenu" id="options1_menu">
|
|
+
|
|
+ <child>
|
|
+ <widget class="GtkCheckMenuItem" id="show_name1">
|
|
+ <property name="visible">True</property>
|
|
+ <property name="tooltip" translatable="yes">Show name</property>
|
|
+ <property name="label" translatable="yes">Show _name</property>
|
|
+ <property name="use_underline">True</property>
|
|
+ <property name="active">False</property>
|
|
+ <signal name="activate" handler="on_show_name1_activate"/>
|
|
+ </widget>
|
|
+ </child>
|
|
+
|
|
+ <child>
|
|
+ <widget class="GtkCheckMenuItem" id="show_range1">
|
|
+ <property name="visible">True</property>
|
|
+ <property name="tooltip" translatable="yes">Show range (Y/M/N)</property>
|
|
+ <property name="label" translatable="yes">Show _range</property>
|
|
+ <property name="use_underline">True</property>
|
|
+ <property name="active">False</property>
|
|
+ <signal name="activate" handler="on_show_range1_activate"/>
|
|
+ </widget>
|
|
+ </child>
|
|
+
|
|
+ <child>
|
|
+ <widget class="GtkCheckMenuItem" id="show_data1">
|
|
+ <property name="visible">True</property>
|
|
+ <property name="tooltip" translatable="yes">Show value of the option</property>
|
|
+ <property name="label" translatable="yes">Show _data</property>
|
|
+ <property name="use_underline">True</property>
|
|
+ <property name="active">False</property>
|
|
+ <signal name="activate" handler="on_show_data1_activate"/>
|
|
+ </widget>
|
|
+ </child>
|
|
+
|
|
+ <child>
|
|
+ <widget class="GtkSeparatorMenuItem" id="separator2">
|
|
+ <property name="visible">True</property>
|
|
+ </widget>
|
|
+ </child>
|
|
+
|
|
+ <child>
|
|
+ <widget class="GtkRadioMenuItem" id="set_option_mode1">
|
|
+ <property name="visible">True</property>
|
|
+ <property name="tooltip" translatable="yes">Show normal options</property>
|
|
+ <property name="label" translatable="yes">Show normal options</property>
|
|
+ <property name="use_underline">True</property>
|
|
+ <property name="active">True</property>
|
|
+ <signal name="activate" handler="on_set_option_mode1_activate"/>
|
|
+ </widget>
|
|
+ </child>
|
|
+
|
|
+ <child>
|
|
+ <widget class="GtkRadioMenuItem" id="set_option_mode2">
|
|
+ <property name="visible">True</property>
|
|
+ <property name="tooltip" translatable="yes">Show all options</property>
|
|
+ <property name="label" translatable="yes">Show all _options</property>
|
|
+ <property name="use_underline">True</property>
|
|
+ <property name="active">False</property>
|
|
+ <property name="group">set_option_mode1</property>
|
|
+ <signal name="activate" handler="on_set_option_mode2_activate"/>
|
|
+ </widget>
|
|
+ </child>
|
|
+
|
|
+ <child>
|
|
+ <widget class="GtkRadioMenuItem" id="set_option_mode3">
|
|
+ <property name="visible">True</property>
|
|
+ <property name="tooltip" translatable="yes">Show all options with prompts</property>
|
|
+ <property name="label" translatable="yes">Show all prompt options</property>
|
|
+ <property name="use_underline">True</property>
|
|
+ <property name="active">False</property>
|
|
+ <property name="group">set_option_mode1</property>
|
|
+ <signal name="activate" handler="on_set_option_mode3_activate"/>
|
|
+ </widget>
|
|
+ </child>
|
|
+
|
|
+ </widget>
|
|
+ </child>
|
|
+ </widget>
|
|
+ </child>
|
|
+
|
|
+ <child>
|
|
+ <widget class="GtkMenuItem" id="help1">
|
|
+ <property name="visible">True</property>
|
|
+ <property name="label" translatable="yes">_Help</property>
|
|
+ <property name="use_underline">True</property>
|
|
+
|
|
+ <child>
|
|
+ <widget class="GtkMenu" id="help1_menu">
|
|
+
|
|
+ <child>
|
|
+ <widget class="GtkImageMenuItem" id="introduction1">
|
|
+ <property name="visible">True</property>
|
|
+ <property name="label" translatable="yes">_Introduction</property>
|
|
+ <property name="use_underline">True</property>
|
|
+ <signal name="activate" handler="on_introduction1_activate" last_modification_time="Fri, 15 Nov 2002 20:26:30 GMT"/>
|
|
+ <accelerator key="I" modifiers="GDK_CONTROL_MASK" signal="activate"/>
|
|
+
|
|
+ <child internal-child="image">
|
|
+ <widget class="GtkImage" id="image43">
|
|
+ <property name="visible">True</property>
|
|
+ <property name="stock">gtk-dialog-question</property>
|
|
+ <property name="icon_size">1</property>
|
|
+ <property name="xalign">0.5</property>
|
|
+ <property name="yalign">0.5</property>
|
|
+ <property name="xpad">0</property>
|
|
+ <property name="ypad">0</property>
|
|
+ </widget>
|
|
+ </child>
|
|
+ </widget>
|
|
+ </child>
|
|
+
|
|
+ <child>
|
|
+ <widget class="GtkImageMenuItem" id="about1">
|
|
+ <property name="visible">True</property>
|
|
+ <property name="label" translatable="yes">_About</property>
|
|
+ <property name="use_underline">True</property>
|
|
+ <signal name="activate" handler="on_about1_activate" last_modification_time="Fri, 15 Nov 2002 20:26:30 GMT"/>
|
|
+ <accelerator key="A" modifiers="GDK_CONTROL_MASK" signal="activate"/>
|
|
+
|
|
+ <child internal-child="image">
|
|
+ <widget class="GtkImage" id="image44">
|
|
+ <property name="visible">True</property>
|
|
+ <property name="stock">gtk-properties</property>
|
|
+ <property name="icon_size">1</property>
|
|
+ <property name="xalign">0.5</property>
|
|
+ <property name="yalign">0.5</property>
|
|
+ <property name="xpad">0</property>
|
|
+ <property name="ypad">0</property>
|
|
+ </widget>
|
|
+ </child>
|
|
+ </widget>
|
|
+ </child>
|
|
+
|
|
+ <child>
|
|
+ <widget class="GtkImageMenuItem" id="license1">
|
|
+ <property name="visible">True</property>
|
|
+ <property name="label" translatable="yes">_License</property>
|
|
+ <property name="use_underline">True</property>
|
|
+ <signal name="activate" handler="on_license1_activate" last_modification_time="Fri, 15 Nov 2002 20:26:30 GMT"/>
|
|
+
|
|
+ <child internal-child="image">
|
|
+ <widget class="GtkImage" id="image45">
|
|
+ <property name="visible">True</property>
|
|
+ <property name="stock">gtk-justify-fill</property>
|
|
+ <property name="icon_size">1</property>
|
|
+ <property name="xalign">0.5</property>
|
|
+ <property name="yalign">0.5</property>
|
|
+ <property name="xpad">0</property>
|
|
+ <property name="ypad">0</property>
|
|
+ </widget>
|
|
+ </child>
|
|
+ </widget>
|
|
+ </child>
|
|
+ </widget>
|
|
+ </child>
|
|
+ </widget>
|
|
+ </child>
|
|
+ </widget>
|
|
+ <packing>
|
|
+ <property name="padding">0</property>
|
|
+ <property name="expand">False</property>
|
|
+ <property name="fill">False</property>
|
|
+ </packing>
|
|
+ </child>
|
|
+
|
|
+ <child>
|
|
+ <widget class="GtkHandleBox" id="handlebox1">
|
|
+ <property name="visible">True</property>
|
|
+ <property name="shadow_type">GTK_SHADOW_OUT</property>
|
|
+ <property name="handle_position">GTK_POS_LEFT</property>
|
|
+ <property name="snap_edge">GTK_POS_TOP</property>
|
|
+
|
|
+ <child>
|
|
+ <widget class="GtkToolbar" id="toolbar1">
|
|
+ <property name="visible">True</property>
|
|
+ <property name="orientation">GTK_ORIENTATION_HORIZONTAL</property>
|
|
+ <property name="toolbar_style">GTK_TOOLBAR_BOTH</property>
|
|
+ <property name="tooltips">True</property>
|
|
+ <property name="show_arrow">True</property>
|
|
+
|
|
+ <child>
|
|
+ <widget class="GtkToolButton" id="button1">
|
|
+ <property name="visible">True</property>
|
|
+ <property name="tooltip" translatable="yes">Goes up of one level (single view)</property>
|
|
+ <property name="label" translatable="yes">Back</property>
|
|
+ <property name="use_underline">True</property>
|
|
+ <property name="stock_id">gtk-undo</property>
|
|
+ <property name="visible_horizontal">True</property>
|
|
+ <property name="visible_vertical">True</property>
|
|
+ <property name="is_important">False</property>
|
|
+ <signal name="clicked" handler="on_back_clicked"/>
|
|
+ </widget>
|
|
+ <packing>
|
|
+ <property name="expand">False</property>
|
|
+ <property name="homogeneous">True</property>
|
|
+ </packing>
|
|
+ </child>
|
|
+
|
|
+ <child>
|
|
+ <widget class="GtkToolItem" id="toolitem1">
|
|
+ <property name="visible">True</property>
|
|
+ <property name="visible_horizontal">True</property>
|
|
+ <property name="visible_vertical">True</property>
|
|
+ <property name="is_important">False</property>
|
|
+
|
|
+ <child>
|
|
+ <widget class="GtkVSeparator" id="vseparator1">
|
|
+ <property name="visible">True</property>
|
|
+ </widget>
|
|
+ </child>
|
|
+ </widget>
|
|
+ <packing>
|
|
+ <property name="expand">False</property>
|
|
+ <property name="homogeneous">False</property>
|
|
+ </packing>
|
|
+ </child>
|
|
+
|
|
+ <child>
|
|
+ <widget class="GtkToolButton" id="button2">
|
|
+ <property name="visible">True</property>
|
|
+ <property name="tooltip" translatable="yes">Load a config file</property>
|
|
+ <property name="label" translatable="yes">Load</property>
|
|
+ <property name="use_underline">True</property>
|
|
+ <property name="stock_id">gtk-open</property>
|
|
+ <property name="visible_horizontal">True</property>
|
|
+ <property name="visible_vertical">True</property>
|
|
+ <property name="is_important">False</property>
|
|
+ <signal name="clicked" handler="on_load_clicked"/>
|
|
+ </widget>
|
|
+ <packing>
|
|
+ <property name="expand">False</property>
|
|
+ <property name="homogeneous">True</property>
|
|
+ </packing>
|
|
+ </child>
|
|
+
|
|
+ <child>
|
|
+ <widget class="GtkToolButton" id="button3">
|
|
+ <property name="visible">True</property>
|
|
+ <property name="tooltip" translatable="yes">Save a config file</property>
|
|
+ <property name="label" translatable="yes">Save</property>
|
|
+ <property name="use_underline">True</property>
|
|
+ <property name="stock_id">gtk-save</property>
|
|
+ <property name="visible_horizontal">True</property>
|
|
+ <property name="visible_vertical">True</property>
|
|
+ <property name="is_important">False</property>
|
|
+ <signal name="clicked" handler="on_save_activate"/>
|
|
+ </widget>
|
|
+ <packing>
|
|
+ <property name="expand">False</property>
|
|
+ <property name="homogeneous">True</property>
|
|
+ </packing>
|
|
+ </child>
|
|
+
|
|
+ <child>
|
|
+ <widget class="GtkToolItem" id="toolitem2">
|
|
+ <property name="visible">True</property>
|
|
+ <property name="visible_horizontal">True</property>
|
|
+ <property name="visible_vertical">True</property>
|
|
+ <property name="is_important">False</property>
|
|
+
|
|
+ <child>
|
|
+ <widget class="GtkVSeparator" id="vseparator2">
|
|
+ <property name="visible">True</property>
|
|
+ </widget>
|
|
+ </child>
|
|
+ </widget>
|
|
+ <packing>
|
|
+ <property name="expand">False</property>
|
|
+ <property name="homogeneous">False</property>
|
|
+ </packing>
|
|
+ </child>
|
|
+
|
|
+ <child>
|
|
+ <widget class="GtkToolButton" id="button4">
|
|
+ <property name="visible">True</property>
|
|
+ <property name="tooltip" translatable="yes">Single view</property>
|
|
+ <property name="label" translatable="yes">Single</property>
|
|
+ <property name="use_underline">True</property>
|
|
+ <property name="stock_id">gtk-missing-image</property>
|
|
+ <property name="visible_horizontal">True</property>
|
|
+ <property name="visible_vertical">True</property>
|
|
+ <property name="is_important">False</property>
|
|
+ <signal name="clicked" handler="on_single_clicked" last_modification_time="Sun, 12 Jan 2003 14:28:39 GMT"/>
|
|
+ </widget>
|
|
+ <packing>
|
|
+ <property name="expand">False</property>
|
|
+ <property name="homogeneous">True</property>
|
|
+ </packing>
|
|
+ </child>
|
|
+
|
|
+ <child>
|
|
+ <widget class="GtkToolButton" id="button5">
|
|
+ <property name="visible">True</property>
|
|
+ <property name="tooltip" translatable="yes">Split view</property>
|
|
+ <property name="label" translatable="yes">Split</property>
|
|
+ <property name="use_underline">True</property>
|
|
+ <property name="stock_id">gtk-missing-image</property>
|
|
+ <property name="visible_horizontal">True</property>
|
|
+ <property name="visible_vertical">True</property>
|
|
+ <property name="is_important">False</property>
|
|
+ <signal name="clicked" handler="on_split_clicked" last_modification_time="Sun, 12 Jan 2003 14:28:45 GMT"/>
|
|
+ </widget>
|
|
+ <packing>
|
|
+ <property name="expand">False</property>
|
|
+ <property name="homogeneous">True</property>
|
|
+ </packing>
|
|
+ </child>
|
|
+
|
|
+ <child>
|
|
+ <widget class="GtkToolButton" id="button6">
|
|
+ <property name="visible">True</property>
|
|
+ <property name="tooltip" translatable="yes">Full view</property>
|
|
+ <property name="label" translatable="yes">Full</property>
|
|
+ <property name="use_underline">True</property>
|
|
+ <property name="stock_id">gtk-missing-image</property>
|
|
+ <property name="visible_horizontal">True</property>
|
|
+ <property name="visible_vertical">True</property>
|
|
+ <property name="is_important">False</property>
|
|
+ <signal name="clicked" handler="on_full_clicked" last_modification_time="Sun, 12 Jan 2003 14:28:50 GMT"/>
|
|
+ </widget>
|
|
+ <packing>
|
|
+ <property name="expand">False</property>
|
|
+ <property name="homogeneous">True</property>
|
|
+ </packing>
|
|
+ </child>
|
|
+
|
|
+ <child>
|
|
+ <widget class="GtkToolItem" id="toolitem3">
|
|
+ <property name="visible">True</property>
|
|
+ <property name="visible_horizontal">True</property>
|
|
+ <property name="visible_vertical">True</property>
|
|
+ <property name="is_important">False</property>
|
|
+
|
|
+ <child>
|
|
+ <widget class="GtkVSeparator" id="vseparator3">
|
|
+ <property name="visible">True</property>
|
|
+ </widget>
|
|
+ </child>
|
|
+ </widget>
|
|
+ <packing>
|
|
+ <property name="expand">False</property>
|
|
+ <property name="homogeneous">False</property>
|
|
+ </packing>
|
|
+ </child>
|
|
+
|
|
+ <child>
|
|
+ <widget class="GtkToolButton" id="button7">
|
|
+ <property name="visible">True</property>
|
|
+ <property name="tooltip" translatable="yes">Collapse the whole tree in the right frame</property>
|
|
+ <property name="label" translatable="yes">Collapse</property>
|
|
+ <property name="use_underline">True</property>
|
|
+ <property name="stock_id">gtk-remove</property>
|
|
+ <property name="visible_horizontal">True</property>
|
|
+ <property name="visible_vertical">True</property>
|
|
+ <property name="is_important">False</property>
|
|
+ <signal name="clicked" handler="on_collapse_clicked"/>
|
|
+ </widget>
|
|
+ <packing>
|
|
+ <property name="expand">False</property>
|
|
+ <property name="homogeneous">True</property>
|
|
+ </packing>
|
|
+ </child>
|
|
+
|
|
+ <child>
|
|
+ <widget class="GtkToolButton" id="button8">
|
|
+ <property name="visible">True</property>
|
|
+ <property name="tooltip" translatable="yes">Expand the whole tree in the right frame</property>
|
|
+ <property name="label" translatable="yes">Expand</property>
|
|
+ <property name="use_underline">True</property>
|
|
+ <property name="stock_id">gtk-add</property>
|
|
+ <property name="visible_horizontal">True</property>
|
|
+ <property name="visible_vertical">True</property>
|
|
+ <property name="is_important">False</property>
|
|
+ <signal name="clicked" handler="on_expand_clicked"/>
|
|
+ </widget>
|
|
+ <packing>
|
|
+ <property name="expand">False</property>
|
|
+ <property name="homogeneous">True</property>
|
|
+ </packing>
|
|
+ </child>
|
|
+ </widget>
|
|
+ </child>
|
|
+ </widget>
|
|
+ <packing>
|
|
+ <property name="padding">0</property>
|
|
+ <property name="expand">False</property>
|
|
+ <property name="fill">False</property>
|
|
+ </packing>
|
|
+ </child>
|
|
+
|
|
+ <child>
|
|
+ <widget class="GtkHPaned" id="hpaned1">
|
|
+ <property name="width_request">1</property>
|
|
+ <property name="visible">True</property>
|
|
+ <property name="can_focus">True</property>
|
|
+ <property name="position">0</property>
|
|
+
|
|
+ <child>
|
|
+ <widget class="GtkScrolledWindow" id="scrolledwindow1">
|
|
+ <property name="visible">True</property>
|
|
+ <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
|
|
+ <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
|
|
+ <property name="shadow_type">GTK_SHADOW_IN</property>
|
|
+ <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
|
|
+
|
|
+ <child>
|
|
+ <widget class="GtkTreeView" id="treeview1">
|
|
+ <property name="visible">True</property>
|
|
+ <property name="can_focus">True</property>
|
|
+ <property name="headers_visible">True</property>
|
|
+ <property name="rules_hint">False</property>
|
|
+ <property name="reorderable">False</property>
|
|
+ <property name="enable_search">False</property>
|
|
+ <signal name="cursor_changed" handler="on_treeview2_cursor_changed" last_modification_time="Sun, 12 Jan 2003 15:58:22 GMT"/>
|
|
+ <signal name="button_press_event" handler="on_treeview1_button_press_event" last_modification_time="Sun, 12 Jan 2003 16:03:52 GMT"/>
|
|
+ <signal name="key_press_event" handler="on_treeview2_key_press_event" last_modification_time="Sun, 12 Jan 2003 16:11:44 GMT"/>
|
|
+ </widget>
|
|
+ </child>
|
|
+ </widget>
|
|
+ <packing>
|
|
+ <property name="shrink">True</property>
|
|
+ <property name="resize">False</property>
|
|
+ </packing>
|
|
+ </child>
|
|
+
|
|
+ <child>
|
|
+ <widget class="GtkVPaned" id="vpaned1">
|
|
+ <property name="visible">True</property>
|
|
+ <property name="can_focus">True</property>
|
|
+ <property name="position">0</property>
|
|
+
|
|
+ <child>
|
|
+ <widget class="GtkScrolledWindow" id="scrolledwindow2">
|
|
+ <property name="visible">True</property>
|
|
+ <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
|
|
+ <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
|
|
+ <property name="shadow_type">GTK_SHADOW_IN</property>
|
|
+ <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
|
|
+
|
|
+ <child>
|
|
+ <widget class="GtkTreeView" id="treeview2">
|
|
+ <property name="visible">True</property>
|
|
+ <property name="can_focus">True</property>
|
|
+ <property name="has_focus">True</property>
|
|
+ <property name="headers_visible">True</property>
|
|
+ <property name="rules_hint">False</property>
|
|
+ <property name="reorderable">False</property>
|
|
+ <property name="enable_search">False</property>
|
|
+ <signal name="cursor_changed" handler="on_treeview2_cursor_changed" last_modification_time="Sun, 12 Jan 2003 15:57:55 GMT"/>
|
|
+ <signal name="button_press_event" handler="on_treeview2_button_press_event" last_modification_time="Sun, 12 Jan 2003 15:57:58 GMT"/>
|
|
+ <signal name="key_press_event" handler="on_treeview2_key_press_event" last_modification_time="Sun, 12 Jan 2003 15:58:01 GMT"/>
|
|
+ </widget>
|
|
+ </child>
|
|
+ </widget>
|
|
+ <packing>
|
|
+ <property name="shrink">True</property>
|
|
+ <property name="resize">False</property>
|
|
+ </packing>
|
|
+ </child>
|
|
+
|
|
+ <child>
|
|
+ <widget class="GtkScrolledWindow" id="scrolledwindow3">
|
|
+ <property name="visible">True</property>
|
|
+ <property name="hscrollbar_policy">GTK_POLICY_NEVER</property>
|
|
+ <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
|
|
+ <property name="shadow_type">GTK_SHADOW_IN</property>
|
|
+ <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
|
|
+
|
|
+ <child>
|
|
+ <widget class="GtkTextView" id="textview3">
|
|
+ <property name="visible">True</property>
|
|
+ <property name="can_focus">True</property>
|
|
+ <property name="editable">False</property>
|
|
+ <property name="overwrite">False</property>
|
|
+ <property name="accepts_tab">True</property>
|
|
+ <property name="justification">GTK_JUSTIFY_LEFT</property>
|
|
+ <property name="wrap_mode">GTK_WRAP_WORD</property>
|
|
+ <property name="cursor_visible">True</property>
|
|
+ <property name="pixels_above_lines">0</property>
|
|
+ <property name="pixels_below_lines">0</property>
|
|
+ <property name="pixels_inside_wrap">0</property>
|
|
+ <property name="left_margin">0</property>
|
|
+ <property name="right_margin">0</property>
|
|
+ <property name="indent">0</property>
|
|
+ <property name="text" translatable="yes">Sorry, no help available for this option yet.</property>
|
|
+ </widget>
|
|
+ </child>
|
|
+ </widget>
|
|
+ <packing>
|
|
+ <property name="shrink">True</property>
|
|
+ <property name="resize">True</property>
|
|
+ </packing>
|
|
+ </child>
|
|
+ </widget>
|
|
+ <packing>
|
|
+ <property name="shrink">True</property>
|
|
+ <property name="resize">True</property>
|
|
+ </packing>
|
|
+ </child>
|
|
+ </widget>
|
|
+ <packing>
|
|
+ <property name="padding">0</property>
|
|
+ <property name="expand">True</property>
|
|
+ <property name="fill">True</property>
|
|
+ </packing>
|
|
+ </child>
|
|
+ </widget>
|
|
+ </child>
|
|
+</widget>
|
|
+
|
|
+</glade-interface>
|
|
diff --git a/scripts/kconfig/images.c b/scripts/kconfig/images.c
|
|
new file mode 100644
|
|
index 0000000..d4f84bd
|
|
--- /dev/null
|
|
+++ b/scripts/kconfig/images.c
|
|
@@ -0,0 +1,326 @@
|
|
+/*
|
|
+ * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
|
|
+ * Released under the terms of the GNU GPL v2.0.
|
|
+ */
|
|
+
|
|
+static const char *xpm_load[] = {
|
|
+"22 22 5 1",
|
|
+". c None",
|
|
+"# c #000000",
|
|
+"c c #838100",
|
|
+"a c #ffff00",
|
|
+"b c #ffffff",
|
|
+"......................",
|
|
+"......................",
|
|
+"......................",
|
|
+"............####....#.",
|
|
+"...........#....##.##.",
|
|
+"..................###.",
|
|
+".................####.",
|
|
+".####...........#####.",
|
|
+"#abab##########.......",
|
|
+"#babababababab#.......",
|
|
+"#ababababababa#.......",
|
|
+"#babababababab#.......",
|
|
+"#ababab###############",
|
|
+"#babab##cccccccccccc##",
|
|
+"#abab##cccccccccccc##.",
|
|
+"#bab##cccccccccccc##..",
|
|
+"#ab##cccccccccccc##...",
|
|
+"#b##cccccccccccc##....",
|
|
+"###cccccccccccc##.....",
|
|
+"##cccccccccccc##......",
|
|
+"###############.......",
|
|
+"......................"};
|
|
+
|
|
+static const char *xpm_save[] = {
|
|
+"22 22 5 1",
|
|
+". c None",
|
|
+"# c #000000",
|
|
+"a c #838100",
|
|
+"b c #c5c2c5",
|
|
+"c c #cdb6d5",
|
|
+"......................",
|
|
+".####################.",
|
|
+".#aa#bbbbbbbbbbbb#bb#.",
|
|
+".#aa#bbbbbbbbbbbb#bb#.",
|
|
+".#aa#bbbbbbbbbcbb####.",
|
|
+".#aa#bbbccbbbbbbb#aa#.",
|
|
+".#aa#bbbccbbbbbbb#aa#.",
|
|
+".#aa#bbbbbbbbbbbb#aa#.",
|
|
+".#aa#bbbbbbbbbbbb#aa#.",
|
|
+".#aa#bbbbbbbbbbbb#aa#.",
|
|
+".#aa#bbbbbbbbbbbb#aa#.",
|
|
+".#aaa############aaa#.",
|
|
+".#aaaaaaaaaaaaaaaaaa#.",
|
|
+".#aaaaaaaaaaaaaaaaaa#.",
|
|
+".#aaa#############aa#.",
|
|
+".#aaa#########bbb#aa#.",
|
|
+".#aaa#########bbb#aa#.",
|
|
+".#aaa#########bbb#aa#.",
|
|
+".#aaa#########bbb#aa#.",
|
|
+".#aaa#########bbb#aa#.",
|
|
+"..##################..",
|
|
+"......................"};
|
|
+
|
|
+static const char *xpm_back[] = {
|
|
+"22 22 3 1",
|
|
+". c None",
|
|
+"# c #000083",
|
|
+"a c #838183",
|
|
+"......................",
|
|
+"......................",
|
|
+"......................",
|
|
+"......................",
|
|
+"......................",
|
|
+"...........######a....",
|
|
+"..#......##########...",
|
|
+"..##...####......##a..",
|
|
+"..###.###.........##..",
|
|
+"..######..........##..",
|
|
+"..#####...........##..",
|
|
+"..######..........##..",
|
|
+"..#######.........##..",
|
|
+"..########.......##a..",
|
|
+"...............a###...",
|
|
+"...............###....",
|
|
+"......................",
|
|
+"......................",
|
|
+"......................",
|
|
+"......................",
|
|
+"......................",
|
|
+"......................"};
|
|
+
|
|
+static const char *xpm_tree_view[] = {
|
|
+"22 22 2 1",
|
|
+". c None",
|
|
+"# c #000000",
|
|
+"......................",
|
|
+"......................",
|
|
+"......#...............",
|
|
+"......#...............",
|
|
+"......#...............",
|
|
+"......#...............",
|
|
+"......#...............",
|
|
+"......########........",
|
|
+"......#...............",
|
|
+"......#...............",
|
|
+"......#...............",
|
|
+"......#...............",
|
|
+"......#...............",
|
|
+"......########........",
|
|
+"......#...............",
|
|
+"......#...............",
|
|
+"......#...............",
|
|
+"......#...............",
|
|
+"......#...............",
|
|
+"......########........",
|
|
+"......................",
|
|
+"......................"};
|
|
+
|
|
+static const char *xpm_single_view[] = {
|
|
+"22 22 2 1",
|
|
+". c None",
|
|
+"# c #000000",
|
|
+"......................",
|
|
+"......................",
|
|
+"..........#...........",
|
|
+"..........#...........",
|
|
+"..........#...........",
|
|
+"..........#...........",
|
|
+"..........#...........",
|
|
+"..........#...........",
|
|
+"..........#...........",
|
|
+"..........#...........",
|
|
+"..........#...........",
|
|
+"..........#...........",
|
|
+"..........#...........",
|
|
+"..........#...........",
|
|
+"..........#...........",
|
|
+"..........#...........",
|
|
+"..........#...........",
|
|
+"..........#...........",
|
|
+"..........#...........",
|
|
+"..........#...........",
|
|
+"......................",
|
|
+"......................"};
|
|
+
|
|
+static const char *xpm_split_view[] = {
|
|
+"22 22 2 1",
|
|
+". c None",
|
|
+"# c #000000",
|
|
+"......................",
|
|
+"......................",
|
|
+"......#......#........",
|
|
+"......#......#........",
|
|
+"......#......#........",
|
|
+"......#......#........",
|
|
+"......#......#........",
|
|
+"......#......#........",
|
|
+"......#......#........",
|
|
+"......#......#........",
|
|
+"......#......#........",
|
|
+"......#......#........",
|
|
+"......#......#........",
|
|
+"......#......#........",
|
|
+"......#......#........",
|
|
+"......#......#........",
|
|
+"......#......#........",
|
|
+"......#......#........",
|
|
+"......#......#........",
|
|
+"......#......#........",
|
|
+"......................",
|
|
+"......................"};
|
|
+
|
|
+static const char *xpm_symbol_no[] = {
|
|
+"12 12 2 1",
|
|
+" c white",
|
|
+". c black",
|
|
+" ",
|
|
+" .......... ",
|
|
+" . . ",
|
|
+" . . ",
|
|
+" . . ",
|
|
+" . . ",
|
|
+" . . ",
|
|
+" . . ",
|
|
+" . . ",
|
|
+" . . ",
|
|
+" .......... ",
|
|
+" "};
|
|
+
|
|
+static const char *xpm_symbol_mod[] = {
|
|
+"12 12 2 1",
|
|
+" c white",
|
|
+". c black",
|
|
+" ",
|
|
+" .......... ",
|
|
+" . . ",
|
|
+" . . ",
|
|
+" . .. . ",
|
|
+" . .... . ",
|
|
+" . .... . ",
|
|
+" . .. . ",
|
|
+" . . ",
|
|
+" . . ",
|
|
+" .......... ",
|
|
+" "};
|
|
+
|
|
+static const char *xpm_symbol_yes[] = {
|
|
+"12 12 2 1",
|
|
+" c white",
|
|
+". c black",
|
|
+" ",
|
|
+" .......... ",
|
|
+" . . ",
|
|
+" . . ",
|
|
+" . . . ",
|
|
+" . .. . ",
|
|
+" . . .. . ",
|
|
+" . .... . ",
|
|
+" . .. . ",
|
|
+" . . ",
|
|
+" .......... ",
|
|
+" "};
|
|
+
|
|
+static const char *xpm_choice_no[] = {
|
|
+"12 12 2 1",
|
|
+" c white",
|
|
+". c black",
|
|
+" ",
|
|
+" .... ",
|
|
+" .. .. ",
|
|
+" . . ",
|
|
+" . . ",
|
|
+" . . ",
|
|
+" . . ",
|
|
+" . . ",
|
|
+" . . ",
|
|
+" .. .. ",
|
|
+" .... ",
|
|
+" "};
|
|
+
|
|
+static const char *xpm_choice_yes[] = {
|
|
+"12 12 2 1",
|
|
+" c white",
|
|
+". c black",
|
|
+" ",
|
|
+" .... ",
|
|
+" .. .. ",
|
|
+" . . ",
|
|
+" . .. . ",
|
|
+" . .... . ",
|
|
+" . .... . ",
|
|
+" . .. . ",
|
|
+" . . ",
|
|
+" .. .. ",
|
|
+" .... ",
|
|
+" "};
|
|
+
|
|
+static const char *xpm_menu[] = {
|
|
+"12 12 2 1",
|
|
+" c white",
|
|
+". c black",
|
|
+" ",
|
|
+" .......... ",
|
|
+" . . ",
|
|
+" . .. . ",
|
|
+" . .... . ",
|
|
+" . ...... . ",
|
|
+" . ...... . ",
|
|
+" . .... . ",
|
|
+" . .. . ",
|
|
+" . . ",
|
|
+" .......... ",
|
|
+" "};
|
|
+
|
|
+static const char *xpm_menu_inv[] = {
|
|
+"12 12 2 1",
|
|
+" c white",
|
|
+". c black",
|
|
+" ",
|
|
+" .......... ",
|
|
+" .......... ",
|
|
+" .. ...... ",
|
|
+" .. .... ",
|
|
+" .. .. ",
|
|
+" .. .. ",
|
|
+" .. .... ",
|
|
+" .. ...... ",
|
|
+" .......... ",
|
|
+" .......... ",
|
|
+" "};
|
|
+
|
|
+static const char *xpm_menuback[] = {
|
|
+"12 12 2 1",
|
|
+" c white",
|
|
+". c black",
|
|
+" ",
|
|
+" .......... ",
|
|
+" . . ",
|
|
+" . .. . ",
|
|
+" . .... . ",
|
|
+" . ...... . ",
|
|
+" . ...... . ",
|
|
+" . .... . ",
|
|
+" . .. . ",
|
|
+" . . ",
|
|
+" .......... ",
|
|
+" "};
|
|
+
|
|
+static const char *xpm_void[] = {
|
|
+"12 12 2 1",
|
|
+" c white",
|
|
+". c black",
|
|
+" ",
|
|
+" ",
|
|
+" ",
|
|
+" ",
|
|
+" ",
|
|
+" ",
|
|
+" ",
|
|
+" ",
|
|
+" ",
|
|
+" ",
|
|
+" ",
|
|
+" "};
|
|
diff --git a/scripts/kconfig/kxgettext.c b/scripts/kconfig/kxgettext.c
|
|
new file mode 100644
|
|
index 0000000..2858738
|
|
--- /dev/null
|
|
+++ b/scripts/kconfig/kxgettext.c
|
|
@@ -0,0 +1,235 @@
|
|
+/*
|
|
+ * Arnaldo Carvalho de Melo <acme@conectiva.com.br>, 2005
|
|
+ *
|
|
+ * Released under the terms of the GNU GPL v2.0
|
|
+ */
|
|
+
|
|
+#include <stdlib.h>
|
|
+#include <string.h>
|
|
+
|
|
+#include "lkc.h"
|
|
+
|
|
+static char *escape(const char* text, char *bf, int len)
|
|
+{
|
|
+ char *bfp = bf;
|
|
+ int multiline = strchr(text, '\n') != NULL;
|
|
+ int eol = 0;
|
|
+ int textlen = strlen(text);
|
|
+
|
|
+ if ((textlen > 0) && (text[textlen-1] == '\n'))
|
|
+ eol = 1;
|
|
+
|
|
+ *bfp++ = '"';
|
|
+ --len;
|
|
+
|
|
+ if (multiline) {
|
|
+ *bfp++ = '"';
|
|
+ *bfp++ = '\n';
|
|
+ *bfp++ = '"';
|
|
+ len -= 3;
|
|
+ }
|
|
+
|
|
+ while (*text != '\0' && len > 1) {
|
|
+ if (*text == '"')
|
|
+ *bfp++ = '\\';
|
|
+ else if (*text == '\n') {
|
|
+ *bfp++ = '\\';
|
|
+ *bfp++ = 'n';
|
|
+ *bfp++ = '"';
|
|
+ *bfp++ = '\n';
|
|
+ *bfp++ = '"';
|
|
+ len -= 5;
|
|
+ ++text;
|
|
+ goto next;
|
|
+ }
|
|
+ else if (*text == '\\') {
|
|
+ *bfp++ = '\\';
|
|
+ len--;
|
|
+ }
|
|
+ *bfp++ = *text++;
|
|
+next:
|
|
+ --len;
|
|
+ }
|
|
+
|
|
+ if (multiline && eol)
|
|
+ bfp -= 3;
|
|
+
|
|
+ *bfp++ = '"';
|
|
+ *bfp = '\0';
|
|
+
|
|
+ return bf;
|
|
+}
|
|
+
|
|
+struct file_line {
|
|
+ struct file_line *next;
|
|
+ const char *file;
|
|
+ int lineno;
|
|
+};
|
|
+
|
|
+static struct file_line *file_line__new(const char *file, int lineno)
|
|
+{
|
|
+ struct file_line *self = malloc(sizeof(*self));
|
|
+
|
|
+ if (self == NULL)
|
|
+ goto out;
|
|
+
|
|
+ self->file = file;
|
|
+ self->lineno = lineno;
|
|
+ self->next = NULL;
|
|
+out:
|
|
+ return self;
|
|
+}
|
|
+
|
|
+struct message {
|
|
+ const char *msg;
|
|
+ const char *option;
|
|
+ struct message *next;
|
|
+ struct file_line *files;
|
|
+};
|
|
+
|
|
+static struct message *message__list;
|
|
+
|
|
+static struct message *message__new(const char *msg, char *option,
|
|
+ const char *file, int lineno)
|
|
+{
|
|
+ struct message *self = malloc(sizeof(*self));
|
|
+
|
|
+ if (self == NULL)
|
|
+ goto out;
|
|
+
|
|
+ self->files = file_line__new(file, lineno);
|
|
+ if (self->files == NULL)
|
|
+ goto out_fail;
|
|
+
|
|
+ self->msg = strdup(msg);
|
|
+ if (self->msg == NULL)
|
|
+ goto out_fail_msg;
|
|
+
|
|
+ self->option = option;
|
|
+ self->next = NULL;
|
|
+out:
|
|
+ return self;
|
|
+out_fail_msg:
|
|
+ free(self->files);
|
|
+out_fail:
|
|
+ free(self);
|
|
+ self = NULL;
|
|
+ goto out;
|
|
+}
|
|
+
|
|
+static struct message *mesage__find(const char *msg)
|
|
+{
|
|
+ struct message *m = message__list;
|
|
+
|
|
+ while (m != NULL) {
|
|
+ if (strcmp(m->msg, msg) == 0)
|
|
+ break;
|
|
+ m = m->next;
|
|
+ }
|
|
+
|
|
+ return m;
|
|
+}
|
|
+
|
|
+static int message__add_file_line(struct message *self, const char *file,
|
|
+ int lineno)
|
|
+{
|
|
+ int rc = -1;
|
|
+ struct file_line *fl = file_line__new(file, lineno);
|
|
+
|
|
+ if (fl == NULL)
|
|
+ goto out;
|
|
+
|
|
+ fl->next = self->files;
|
|
+ self->files = fl;
|
|
+ rc = 0;
|
|
+out:
|
|
+ return rc;
|
|
+}
|
|
+
|
|
+static int message__add(const char *msg, char *option, const char *file,
|
|
+ int lineno)
|
|
+{
|
|
+ int rc = 0;
|
|
+ char bf[16384];
|
|
+ char *escaped = escape(msg, bf, sizeof(bf));
|
|
+ struct message *m = mesage__find(escaped);
|
|
+
|
|
+ if (m != NULL)
|
|
+ rc = message__add_file_line(m, file, lineno);
|
|
+ else {
|
|
+ m = message__new(escaped, option, file, lineno);
|
|
+
|
|
+ if (m != NULL) {
|
|
+ m->next = message__list;
|
|
+ message__list = m;
|
|
+ } else
|
|
+ rc = -1;
|
|
+ }
|
|
+ return rc;
|
|
+}
|
|
+
|
|
+static void menu_build_message_list(struct menu *menu)
|
|
+{
|
|
+ struct menu *child;
|
|
+
|
|
+ message__add(menu_get_prompt(menu), NULL,
|
|
+ menu->file == NULL ? "Root Menu" : menu->file->name,
|
|
+ menu->lineno);
|
|
+
|
|
+ if (menu->sym != NULL && menu_has_help(menu))
|
|
+ message__add(menu_get_help(menu), menu->sym->name,
|
|
+ menu->file == NULL ? "Root Menu" : menu->file->name,
|
|
+ menu->lineno);
|
|
+
|
|
+ for (child = menu->list; child != NULL; child = child->next)
|
|
+ if (child->prompt != NULL)
|
|
+ menu_build_message_list(child);
|
|
+}
|
|
+
|
|
+static void message__print_file_lineno(struct message *self)
|
|
+{
|
|
+ struct file_line *fl = self->files;
|
|
+
|
|
+ putchar('\n');
|
|
+ if (self->option != NULL)
|
|
+ printf("# %s:00000\n", self->option);
|
|
+
|
|
+ printf("#: %s:%d", fl->file, fl->lineno);
|
|
+ fl = fl->next;
|
|
+
|
|
+ while (fl != NULL) {
|
|
+ printf(", %s:%d", fl->file, fl->lineno);
|
|
+ fl = fl->next;
|
|
+ }
|
|
+
|
|
+ putchar('\n');
|
|
+}
|
|
+
|
|
+static void message__print_gettext_msgid_msgstr(struct message *self)
|
|
+{
|
|
+ message__print_file_lineno(self);
|
|
+
|
|
+ printf("msgid %s\n"
|
|
+ "msgstr \"\"\n", self->msg);
|
|
+}
|
|
+
|
|
+static void menu__xgettext(void)
|
|
+{
|
|
+ struct message *m = message__list;
|
|
+
|
|
+ while (m != NULL) {
|
|
+ /* skip empty lines ("") */
|
|
+ if (strlen(m->msg) > sizeof("\"\""))
|
|
+ message__print_gettext_msgid_msgstr(m);
|
|
+ m = m->next;
|
|
+ }
|
|
+}
|
|
+
|
|
+int main(int ac, char **av)
|
|
+{
|
|
+ conf_parse(av[1]);
|
|
+
|
|
+ menu_build_message_list(menu_get_root_menu(NULL));
|
|
+ menu__xgettext();
|
|
+ return 0;
|
|
+}
|
|
diff --git a/scripts/kconfig/lxdialog/BIG.FAT.WARNING b/scripts/kconfig/lxdialog/BIG.FAT.WARNING
|
|
new file mode 100644
|
|
index 0000000..a8999d8
|
|
--- /dev/null
|
|
+++ b/scripts/kconfig/lxdialog/BIG.FAT.WARNING
|
|
@@ -0,0 +1,4 @@
|
|
+This is NOT the official version of dialog. This version has been
|
|
+significantly modified from the original. It is for use by the Linux
|
|
+kernel configuration script. Please do not bother Savio Lam with
|
|
+questions about this program.
|
|
diff --git a/scripts/kconfig/lxdialog/checklist.c b/scripts/kconfig/lxdialog/checklist.c
|
|
new file mode 100644
|
|
index 0000000..8d016fa
|
|
--- /dev/null
|
|
+++ b/scripts/kconfig/lxdialog/checklist.c
|
|
@@ -0,0 +1,332 @@
|
|
+/*
|
|
+ * checklist.c -- implements the checklist box
|
|
+ *
|
|
+ * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
|
|
+ * Stuart Herbert - S.Herbert@sheffield.ac.uk: radiolist extension
|
|
+ * Alessandro Rubini - rubini@ipvvis.unipv.it: merged the two
|
|
+ * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
|
|
+ *
|
|
+ * This program is free software; you can redistribute it and/or
|
|
+ * modify it under the terms of the GNU General Public License
|
|
+ * as published by the Free Software Foundation; either version 2
|
|
+ * of the License, or (at your option) any later version.
|
|
+ *
|
|
+ * This program is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
+ * GNU General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU General Public License
|
|
+ * along with this program; if not, write to the Free Software
|
|
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
+ */
|
|
+
|
|
+#include "dialog.h"
|
|
+
|
|
+static int list_width, check_x, item_x;
|
|
+
|
|
+/*
|
|
+ * Print list item
|
|
+ */
|
|
+static void print_item(WINDOW * win, int choice, int selected)
|
|
+{
|
|
+ int i;
|
|
+ char *list_item = malloc(list_width + 1);
|
|
+
|
|
+ strncpy(list_item, item_str(), list_width - item_x);
|
|
+ list_item[list_width - item_x] = '\0';
|
|
+
|
|
+ /* Clear 'residue' of last item */
|
|
+ wattrset(win, dlg.menubox.atr);
|
|
+ wmove(win, choice, 0);
|
|
+ for (i = 0; i < list_width; i++)
|
|
+ waddch(win, ' ');
|
|
+
|
|
+ wmove(win, choice, check_x);
|
|
+ wattrset(win, selected ? dlg.check_selected.atr
|
|
+ : dlg.check.atr);
|
|
+ if (!item_is_tag(':'))
|
|
+ wprintw(win, "(%c)", item_is_tag('X') ? 'X' : ' ');
|
|
+
|
|
+ wattrset(win, selected ? dlg.tag_selected.atr : dlg.tag.atr);
|
|
+ mvwaddch(win, choice, item_x, list_item[0]);
|
|
+ wattrset(win, selected ? dlg.item_selected.atr : dlg.item.atr);
|
|
+ waddstr(win, list_item + 1);
|
|
+ if (selected) {
|
|
+ wmove(win, choice, check_x + 1);
|
|
+ wrefresh(win);
|
|
+ }
|
|
+ free(list_item);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Print the scroll indicators.
|
|
+ */
|
|
+static void print_arrows(WINDOW * win, int choice, int item_no, int scroll,
|
|
+ int y, int x, int height)
|
|
+{
|
|
+ wmove(win, y, x);
|
|
+
|
|
+ if (scroll > 0) {
|
|
+ wattrset(win, dlg.uarrow.atr);
|
|
+ waddch(win, ACS_UARROW);
|
|
+ waddstr(win, "(-)");
|
|
+ } else {
|
|
+ wattrset(win, dlg.menubox.atr);
|
|
+ waddch(win, ACS_HLINE);
|
|
+ waddch(win, ACS_HLINE);
|
|
+ waddch(win, ACS_HLINE);
|
|
+ waddch(win, ACS_HLINE);
|
|
+ }
|
|
+
|
|
+ y = y + height + 1;
|
|
+ wmove(win, y, x);
|
|
+
|
|
+ if ((height < item_no) && (scroll + choice < item_no - 1)) {
|
|
+ wattrset(win, dlg.darrow.atr);
|
|
+ waddch(win, ACS_DARROW);
|
|
+ waddstr(win, "(+)");
|
|
+ } else {
|
|
+ wattrset(win, dlg.menubox_border.atr);
|
|
+ waddch(win, ACS_HLINE);
|
|
+ waddch(win, ACS_HLINE);
|
|
+ waddch(win, ACS_HLINE);
|
|
+ waddch(win, ACS_HLINE);
|
|
+ }
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Display the termination buttons
|
|
+ */
|
|
+static void print_buttons(WINDOW * dialog, int height, int width, int selected)
|
|
+{
|
|
+ int x = width / 2 - 11;
|
|
+ int y = height - 2;
|
|
+
|
|
+ print_button(dialog, gettext("Select"), y, x, selected == 0);
|
|
+ print_button(dialog, gettext(" Help "), y, x + 14, selected == 1);
|
|
+
|
|
+ wmove(dialog, y, x + 1 + 14 * selected);
|
|
+ wrefresh(dialog);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Display a dialog box with a list of options that can be turned on or off
|
|
+ * in the style of radiolist (only one option turned on at a time).
|
|
+ */
|
|
+int dialog_checklist(const char *title, const char *prompt, int height,
|
|
+ int width, int list_height)
|
|
+{
|
|
+ int i, x, y, box_x, box_y;
|
|
+ int key = 0, button = 0, choice = 0, scroll = 0, max_choice;
|
|
+ WINDOW *dialog, *list;
|
|
+
|
|
+ /* which item to highlight */
|
|
+ item_foreach() {
|
|
+ if (item_is_tag('X'))
|
|
+ choice = item_n();
|
|
+ if (item_is_selected()) {
|
|
+ choice = item_n();
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+do_resize:
|
|
+ if (getmaxy(stdscr) < (height + CHECKLIST_HEIGTH_MIN))
|
|
+ return -ERRDISPLAYTOOSMALL;
|
|
+ if (getmaxx(stdscr) < (width + CHECKLIST_WIDTH_MIN))
|
|
+ return -ERRDISPLAYTOOSMALL;
|
|
+
|
|
+ max_choice = MIN(list_height, item_count());
|
|
+
|
|
+ /* center dialog box on screen */
|
|
+ x = (getmaxx(stdscr) - width) / 2;
|
|
+ y = (getmaxy(stdscr) - height) / 2;
|
|
+
|
|
+ draw_shadow(stdscr, y, x, height, width);
|
|
+
|
|
+ dialog = newwin(height, width, y, x);
|
|
+ keypad(dialog, TRUE);
|
|
+
|
|
+ draw_box(dialog, 0, 0, height, width,
|
|
+ dlg.dialog.atr, dlg.border.atr);
|
|
+ wattrset(dialog, dlg.border.atr);
|
|
+ mvwaddch(dialog, height - 3, 0, ACS_LTEE);
|
|
+ for (i = 0; i < width - 2; i++)
|
|
+ waddch(dialog, ACS_HLINE);
|
|
+ wattrset(dialog, dlg.dialog.atr);
|
|
+ waddch(dialog, ACS_RTEE);
|
|
+
|
|
+ print_title(dialog, title, width);
|
|
+
|
|
+ wattrset(dialog, dlg.dialog.atr);
|
|
+ print_autowrap(dialog, prompt, width - 2, 1, 3);
|
|
+
|
|
+ list_width = width - 6;
|
|
+ box_y = height - list_height - 5;
|
|
+ box_x = (width - list_width) / 2 - 1;
|
|
+
|
|
+ /* create new window for the list */
|
|
+ list = subwin(dialog, list_height, list_width, y + box_y + 1,
|
|
+ x + box_x + 1);
|
|
+
|
|
+ keypad(list, TRUE);
|
|
+
|
|
+ /* draw a box around the list items */
|
|
+ draw_box(dialog, box_y, box_x, list_height + 2, list_width + 2,
|
|
+ dlg.menubox_border.atr, dlg.menubox.atr);
|
|
+
|
|
+ /* Find length of longest item in order to center checklist */
|
|
+ check_x = 0;
|
|
+ item_foreach()
|
|
+ check_x = MAX(check_x, strlen(item_str()) + 4);
|
|
+ check_x = MIN(check_x, list_width);
|
|
+
|
|
+ check_x = (list_width - check_x) / 2;
|
|
+ item_x = check_x + 4;
|
|
+
|
|
+ if (choice >= list_height) {
|
|
+ scroll = choice - list_height + 1;
|
|
+ choice -= scroll;
|
|
+ }
|
|
+
|
|
+ /* Print the list */
|
|
+ for (i = 0; i < max_choice; i++) {
|
|
+ item_set(scroll + i);
|
|
+ print_item(list, i, i == choice);
|
|
+ }
|
|
+
|
|
+ print_arrows(dialog, choice, item_count(), scroll,
|
|
+ box_y, box_x + check_x + 5, list_height);
|
|
+
|
|
+ print_buttons(dialog, height, width, 0);
|
|
+
|
|
+ wnoutrefresh(dialog);
|
|
+ wnoutrefresh(list);
|
|
+ doupdate();
|
|
+
|
|
+ while (key != KEY_ESC) {
|
|
+ key = wgetch(dialog);
|
|
+
|
|
+ for (i = 0; i < max_choice; i++) {
|
|
+ item_set(i + scroll);
|
|
+ if (toupper(key) == toupper(item_str()[0]))
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if (i < max_choice || key == KEY_UP || key == KEY_DOWN ||
|
|
+ key == '+' || key == '-') {
|
|
+ if (key == KEY_UP || key == '-') {
|
|
+ if (!choice) {
|
|
+ if (!scroll)
|
|
+ continue;
|
|
+ /* Scroll list down */
|
|
+ if (list_height > 1) {
|
|
+ /* De-highlight current first item */
|
|
+ item_set(scroll);
|
|
+ print_item(list, 0, FALSE);
|
|
+ scrollok(list, TRUE);
|
|
+ wscrl(list, -1);
|
|
+ scrollok(list, FALSE);
|
|
+ }
|
|
+ scroll--;
|
|
+ item_set(scroll);
|
|
+ print_item(list, 0, TRUE);
|
|
+ print_arrows(dialog, choice, item_count(),
|
|
+ scroll, box_y, box_x + check_x + 5, list_height);
|
|
+
|
|
+ wnoutrefresh(dialog);
|
|
+ wrefresh(list);
|
|
+
|
|
+ continue; /* wait for another key press */
|
|
+ } else
|
|
+ i = choice - 1;
|
|
+ } else if (key == KEY_DOWN || key == '+') {
|
|
+ if (choice == max_choice - 1) {
|
|
+ if (scroll + choice >= item_count() - 1)
|
|
+ continue;
|
|
+ /* Scroll list up */
|
|
+ if (list_height > 1) {
|
|
+ /* De-highlight current last item before scrolling up */
|
|
+ item_set(scroll + max_choice - 1);
|
|
+ print_item(list,
|
|
+ max_choice - 1,
|
|
+ FALSE);
|
|
+ scrollok(list, TRUE);
|
|
+ wscrl(list, 1);
|
|
+ scrollok(list, FALSE);
|
|
+ }
|
|
+ scroll++;
|
|
+ item_set(scroll + max_choice - 1);
|
|
+ print_item(list, max_choice - 1, TRUE);
|
|
+
|
|
+ print_arrows(dialog, choice, item_count(),
|
|
+ scroll, box_y, box_x + check_x + 5, list_height);
|
|
+
|
|
+ wnoutrefresh(dialog);
|
|
+ wrefresh(list);
|
|
+
|
|
+ continue; /* wait for another key press */
|
|
+ } else
|
|
+ i = choice + 1;
|
|
+ }
|
|
+ if (i != choice) {
|
|
+ /* De-highlight current item */
|
|
+ item_set(scroll + choice);
|
|
+ print_item(list, choice, FALSE);
|
|
+ /* Highlight new item */
|
|
+ choice = i;
|
|
+ item_set(scroll + choice);
|
|
+ print_item(list, choice, TRUE);
|
|
+ wnoutrefresh(dialog);
|
|
+ wrefresh(list);
|
|
+ }
|
|
+ continue; /* wait for another key press */
|
|
+ }
|
|
+ switch (key) {
|
|
+ case 'H':
|
|
+ case 'h':
|
|
+ case '?':
|
|
+ button = 1;
|
|
+ /* fall-through */
|
|
+ case 'S':
|
|
+ case 's':
|
|
+ case ' ':
|
|
+ case '\n':
|
|
+ item_foreach()
|
|
+ item_set_selected(0);
|
|
+ item_set(scroll + choice);
|
|
+ item_set_selected(1);
|
|
+ delwin(list);
|
|
+ delwin(dialog);
|
|
+ return button;
|
|
+ case TAB:
|
|
+ case KEY_LEFT:
|
|
+ case KEY_RIGHT:
|
|
+ button = ((key == KEY_LEFT ? --button : ++button) < 0)
|
|
+ ? 1 : (button > 1 ? 0 : button);
|
|
+
|
|
+ print_buttons(dialog, height, width, button);
|
|
+ wrefresh(dialog);
|
|
+ break;
|
|
+ case 'X':
|
|
+ case 'x':
|
|
+ key = KEY_ESC;
|
|
+ break;
|
|
+ case KEY_ESC:
|
|
+ key = on_key_esc(dialog);
|
|
+ break;
|
|
+ case KEY_RESIZE:
|
|
+ delwin(list);
|
|
+ delwin(dialog);
|
|
+ on_key_resize();
|
|
+ goto do_resize;
|
|
+ }
|
|
+
|
|
+ /* Now, update everything... */
|
|
+ doupdate();
|
|
+ }
|
|
+ delwin(list);
|
|
+ delwin(dialog);
|
|
+ return key; /* ESC pressed */
|
|
+}
|
|
diff --git a/scripts/kconfig/lxdialog/dialog.h b/scripts/kconfig/lxdialog/dialog.h
|
|
new file mode 100644
|
|
index 0000000..fcffd5b
|
|
--- /dev/null
|
|
+++ b/scripts/kconfig/lxdialog/dialog.h
|
|
@@ -0,0 +1,257 @@
|
|
+/*
|
|
+ * dialog.h -- common declarations for all dialog modules
|
|
+ *
|
|
+ * AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
|
|
+ *
|
|
+ * This program is free software; you can redistribute it and/or
|
|
+ * modify it under the terms of the GNU General Public License
|
|
+ * as published by the Free Software Foundation; either version 2
|
|
+ * of the License, or (at your option) any later version.
|
|
+ *
|
|
+ * This program is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
+ * GNU General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU General Public License
|
|
+ * along with this program; if not, write to the Free Software
|
|
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
+ */
|
|
+
|
|
+#include <sys/types.h>
|
|
+#include <fcntl.h>
|
|
+#include <unistd.h>
|
|
+#include <ctype.h>
|
|
+#include <stdlib.h>
|
|
+#include <string.h>
|
|
+#include <stdbool.h>
|
|
+
|
|
+#ifndef KBUILD_NO_NLS
|
|
+# include <libintl.h>
|
|
+#else
|
|
+# define gettext(Msgid) ((const char *) (Msgid))
|
|
+#endif
|
|
+
|
|
+#ifdef __sun__
|
|
+#define CURS_MACROS
|
|
+#endif
|
|
+#include CURSES_LOC
|
|
+
|
|
+/*
|
|
+ * Colors in ncurses 1.9.9e do not work properly since foreground and
|
|
+ * background colors are OR'd rather than separately masked. This version
|
|
+ * of dialog was hacked to work with ncurses 1.9.9e, making it incompatible
|
|
+ * with standard curses. The simplest fix (to make this work with standard
|
|
+ * curses) uses the wbkgdset() function, not used in the original hack.
|
|
+ * Turn it off if we're building with 1.9.9e, since it just confuses things.
|
|
+ */
|
|
+#if defined(NCURSES_VERSION) && defined(_NEED_WRAP) && !defined(GCC_PRINTFLIKE)
|
|
+#define OLD_NCURSES 1
|
|
+#undef wbkgdset
|
|
+#define wbkgdset(w,p) /*nothing */
|
|
+#else
|
|
+#define OLD_NCURSES 0
|
|
+#endif
|
|
+
|
|
+#define TR(params) _tracef params
|
|
+
|
|
+#define KEY_ESC 27
|
|
+#define TAB 9
|
|
+#define MAX_LEN 2048
|
|
+#define BUF_SIZE (10*1024)
|
|
+#define MIN(x,y) (x < y ? x : y)
|
|
+#define MAX(x,y) (x > y ? x : y)
|
|
+
|
|
+#ifndef ACS_ULCORNER
|
|
+#define ACS_ULCORNER '+'
|
|
+#endif
|
|
+#ifndef ACS_LLCORNER
|
|
+#define ACS_LLCORNER '+'
|
|
+#endif
|
|
+#ifndef ACS_URCORNER
|
|
+#define ACS_URCORNER '+'
|
|
+#endif
|
|
+#ifndef ACS_LRCORNER
|
|
+#define ACS_LRCORNER '+'
|
|
+#endif
|
|
+#ifndef ACS_HLINE
|
|
+#define ACS_HLINE '-'
|
|
+#endif
|
|
+#ifndef ACS_VLINE
|
|
+#define ACS_VLINE '|'
|
|
+#endif
|
|
+#ifndef ACS_LTEE
|
|
+#define ACS_LTEE '+'
|
|
+#endif
|
|
+#ifndef ACS_RTEE
|
|
+#define ACS_RTEE '+'
|
|
+#endif
|
|
+#ifndef ACS_UARROW
|
|
+#define ACS_UARROW '^'
|
|
+#endif
|
|
+#ifndef ACS_DARROW
|
|
+#define ACS_DARROW 'v'
|
|
+#endif
|
|
+
|
|
+/* error return codes */
|
|
+#define ERRDISPLAYTOOSMALL (KEY_MAX + 1)
|
|
+
|
|
+/*
|
|
+ * Color definitions
|
|
+ */
|
|
+struct dialog_color {
|
|
+ chtype atr; /* Color attribute */
|
|
+ int fg; /* foreground */
|
|
+ int bg; /* background */
|
|
+ int hl; /* highlight this item */
|
|
+};
|
|
+
|
|
+struct subtitle_list {
|
|
+ struct subtitle_list *next;
|
|
+ const char *text;
|
|
+};
|
|
+
|
|
+struct dialog_info {
|
|
+ const char *backtitle;
|
|
+ struct subtitle_list *subtitles;
|
|
+ struct dialog_color screen;
|
|
+ struct dialog_color shadow;
|
|
+ struct dialog_color dialog;
|
|
+ struct dialog_color title;
|
|
+ struct dialog_color border;
|
|
+ struct dialog_color button_active;
|
|
+ struct dialog_color button_inactive;
|
|
+ struct dialog_color button_key_active;
|
|
+ struct dialog_color button_key_inactive;
|
|
+ struct dialog_color button_label_active;
|
|
+ struct dialog_color button_label_inactive;
|
|
+ struct dialog_color inputbox;
|
|
+ struct dialog_color inputbox_border;
|
|
+ struct dialog_color searchbox;
|
|
+ struct dialog_color searchbox_title;
|
|
+ struct dialog_color searchbox_border;
|
|
+ struct dialog_color position_indicator;
|
|
+ struct dialog_color menubox;
|
|
+ struct dialog_color menubox_border;
|
|
+ struct dialog_color item;
|
|
+ struct dialog_color item_selected;
|
|
+ struct dialog_color tag;
|
|
+ struct dialog_color tag_selected;
|
|
+ struct dialog_color tag_key;
|
|
+ struct dialog_color tag_key_selected;
|
|
+ struct dialog_color check;
|
|
+ struct dialog_color check_selected;
|
|
+ struct dialog_color uarrow;
|
|
+ struct dialog_color darrow;
|
|
+};
|
|
+
|
|
+/*
|
|
+ * Global variables
|
|
+ */
|
|
+extern struct dialog_info dlg;
|
|
+extern char dialog_input_result[];
|
|
+extern int saved_x, saved_y; /* Needed in signal handler in mconf.c */
|
|
+
|
|
+/*
|
|
+ * Function prototypes
|
|
+ */
|
|
+
|
|
+/* item list as used by checklist and menubox */
|
|
+void item_reset(void);
|
|
+void item_make(const char *fmt, ...);
|
|
+void item_add_str(const char *fmt, ...);
|
|
+void item_set_tag(char tag);
|
|
+void item_set_data(void *p);
|
|
+void item_set_selected(int val);
|
|
+int item_activate_selected(void);
|
|
+void *item_data(void);
|
|
+char item_tag(void);
|
|
+
|
|
+/* item list manipulation for lxdialog use */
|
|
+#define MAXITEMSTR 200
|
|
+struct dialog_item {
|
|
+ char str[MAXITEMSTR]; /* prompt displayed */
|
|
+ char tag;
|
|
+ void *data; /* pointer to menu item - used by menubox+checklist */
|
|
+ int selected; /* Set to 1 by dialog_*() function if selected. */
|
|
+};
|
|
+
|
|
+/* list of lialog_items */
|
|
+struct dialog_list {
|
|
+ struct dialog_item node;
|
|
+ struct dialog_list *next;
|
|
+};
|
|
+
|
|
+extern struct dialog_list *item_cur;
|
|
+extern struct dialog_list item_nil;
|
|
+extern struct dialog_list *item_head;
|
|
+
|
|
+int item_count(void);
|
|
+void item_set(int n);
|
|
+int item_n(void);
|
|
+const char *item_str(void);
|
|
+int item_is_selected(void);
|
|
+int item_is_tag(char tag);
|
|
+#define item_foreach() \
|
|
+ for (item_cur = item_head ? item_head: item_cur; \
|
|
+ item_cur && (item_cur != &item_nil); item_cur = item_cur->next)
|
|
+
|
|
+/* generic key handlers */
|
|
+int on_key_esc(WINDOW *win);
|
|
+int on_key_resize(void);
|
|
+
|
|
+/* minimum (re)size values */
|
|
+#define CHECKLIST_HEIGTH_MIN 6 /* For dialog_checklist() */
|
|
+#define CHECKLIST_WIDTH_MIN 6
|
|
+#define INPUTBOX_HEIGTH_MIN 2 /* For dialog_inputbox() */
|
|
+#define INPUTBOX_WIDTH_MIN 2
|
|
+#define MENUBOX_HEIGTH_MIN 15 /* For dialog_menu() */
|
|
+#define MENUBOX_WIDTH_MIN 65
|
|
+#define TEXTBOX_HEIGTH_MIN 8 /* For dialog_textbox() */
|
|
+#define TEXTBOX_WIDTH_MIN 8
|
|
+#define YESNO_HEIGTH_MIN 4 /* For dialog_yesno() */
|
|
+#define YESNO_WIDTH_MIN 4
|
|
+#define WINDOW_HEIGTH_MIN 19 /* For init_dialog() */
|
|
+#define WINDOW_WIDTH_MIN 80
|
|
+
|
|
+int init_dialog(const char *backtitle);
|
|
+void set_dialog_backtitle(const char *backtitle);
|
|
+void set_dialog_subtitles(struct subtitle_list *subtitles);
|
|
+void end_dialog(int x, int y);
|
|
+void attr_clear(WINDOW * win, int height, int width, chtype attr);
|
|
+void dialog_clear(void);
|
|
+void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x);
|
|
+void print_button(WINDOW * win, const char *label, int y, int x, int selected);
|
|
+void print_title(WINDOW *dialog, const char *title, int width);
|
|
+void draw_box(WINDOW * win, int y, int x, int height, int width, chtype box,
|
|
+ chtype border);
|
|
+void draw_shadow(WINDOW * win, int y, int x, int height, int width);
|
|
+
|
|
+int first_alpha(const char *string, const char *exempt);
|
|
+int dialog_yesno(const char *title, const char *prompt, int height, int width);
|
|
+int dialog_msgbox(const char *title, const char *prompt, int height,
|
|
+ int width, int pause);
|
|
+
|
|
+
|
|
+typedef void (*update_text_fn)(char *buf, size_t start, size_t end, void
|
|
+ *_data);
|
|
+int dialog_textbox(const char *title, char *tbuf, int initial_height,
|
|
+ int initial_width, int *keys, int *_vscroll, int *_hscroll,
|
|
+ update_text_fn update_text, void *data);
|
|
+int dialog_menu(const char *title, const char *prompt,
|
|
+ const void *selected, int *s_scroll);
|
|
+int dialog_checklist(const char *title, const char *prompt, int height,
|
|
+ int width, int list_height);
|
|
+int dialog_inputbox(const char *title, const char *prompt, int height,
|
|
+ int width, const char *init);
|
|
+
|
|
+/*
|
|
+ * This is the base for fictitious keys, which activate
|
|
+ * the buttons.
|
|
+ *
|
|
+ * Mouse-generated keys are the following:
|
|
+ * -- the first 32 are used as numbers, in addition to '0'-'9'
|
|
+ * -- the lowercase are used to signal mouse-enter events (M_EVENT + 'o')
|
|
+ * -- uppercase chars are used to invoke the button (M_EVENT + 'O')
|
|
+ */
|
|
+#define M_EVENT (KEY_MAX+1)
|
|
diff --git a/scripts/kconfig/lxdialog/inputbox.c b/scripts/kconfig/lxdialog/inputbox.c
|
|
new file mode 100644
|
|
index 0000000..d58de1d
|
|
--- /dev/null
|
|
+++ b/scripts/kconfig/lxdialog/inputbox.c
|
|
@@ -0,0 +1,301 @@
|
|
+/*
|
|
+ * inputbox.c -- implements the input box
|
|
+ *
|
|
+ * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
|
|
+ * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
|
|
+ *
|
|
+ * This program is free software; you can redistribute it and/or
|
|
+ * modify it under the terms of the GNU General Public License
|
|
+ * as published by the Free Software Foundation; either version 2
|
|
+ * of the License, or (at your option) any later version.
|
|
+ *
|
|
+ * This program is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
+ * GNU General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU General Public License
|
|
+ * along with this program; if not, write to the Free Software
|
|
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
+ */
|
|
+
|
|
+#include "dialog.h"
|
|
+
|
|
+char dialog_input_result[MAX_LEN + 1];
|
|
+
|
|
+/*
|
|
+ * Print the termination buttons
|
|
+ */
|
|
+static void print_buttons(WINDOW * dialog, int height, int width, int selected)
|
|
+{
|
|
+ int x = width / 2 - 11;
|
|
+ int y = height - 2;
|
|
+
|
|
+ print_button(dialog, gettext(" Ok "), y, x, selected == 0);
|
|
+ print_button(dialog, gettext(" Help "), y, x + 14, selected == 1);
|
|
+
|
|
+ wmove(dialog, y, x + 1 + 14 * selected);
|
|
+ wrefresh(dialog);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Display a dialog box for inputing a string
|
|
+ */
|
|
+int dialog_inputbox(const char *title, const char *prompt, int height, int width,
|
|
+ const char *init)
|
|
+{
|
|
+ int i, x, y, box_y, box_x, box_width;
|
|
+ int input_x = 0, key = 0, button = -1;
|
|
+ int show_x, len, pos;
|
|
+ char *instr = dialog_input_result;
|
|
+ WINDOW *dialog;
|
|
+
|
|
+ if (!init)
|
|
+ instr[0] = '\0';
|
|
+ else
|
|
+ strcpy(instr, init);
|
|
+
|
|
+do_resize:
|
|
+ if (getmaxy(stdscr) <= (height - INPUTBOX_HEIGTH_MIN))
|
|
+ return -ERRDISPLAYTOOSMALL;
|
|
+ if (getmaxx(stdscr) <= (width - INPUTBOX_WIDTH_MIN))
|
|
+ return -ERRDISPLAYTOOSMALL;
|
|
+
|
|
+ /* center dialog box on screen */
|
|
+ x = (getmaxx(stdscr) - width) / 2;
|
|
+ y = (getmaxy(stdscr) - height) / 2;
|
|
+
|
|
+ draw_shadow(stdscr, y, x, height, width);
|
|
+
|
|
+ dialog = newwin(height, width, y, x);
|
|
+ keypad(dialog, TRUE);
|
|
+
|
|
+ draw_box(dialog, 0, 0, height, width,
|
|
+ dlg.dialog.atr, dlg.border.atr);
|
|
+ wattrset(dialog, dlg.border.atr);
|
|
+ mvwaddch(dialog, height - 3, 0, ACS_LTEE);
|
|
+ for (i = 0; i < width - 2; i++)
|
|
+ waddch(dialog, ACS_HLINE);
|
|
+ wattrset(dialog, dlg.dialog.atr);
|
|
+ waddch(dialog, ACS_RTEE);
|
|
+
|
|
+ print_title(dialog, title, width);
|
|
+
|
|
+ wattrset(dialog, dlg.dialog.atr);
|
|
+ print_autowrap(dialog, prompt, width - 2, 1, 3);
|
|
+
|
|
+ /* Draw the input field box */
|
|
+ box_width = width - 6;
|
|
+ getyx(dialog, y, x);
|
|
+ box_y = y + 2;
|
|
+ box_x = (width - box_width) / 2;
|
|
+ draw_box(dialog, y + 1, box_x - 1, 3, box_width + 2,
|
|
+ dlg.dialog.atr, dlg.border.atr);
|
|
+
|
|
+ print_buttons(dialog, height, width, 0);
|
|
+
|
|
+ /* Set up the initial value */
|
|
+ wmove(dialog, box_y, box_x);
|
|
+ wattrset(dialog, dlg.inputbox.atr);
|
|
+
|
|
+ len = strlen(instr);
|
|
+ pos = len;
|
|
+
|
|
+ if (len >= box_width) {
|
|
+ show_x = len - box_width + 1;
|
|
+ input_x = box_width - 1;
|
|
+ for (i = 0; i < box_width - 1; i++)
|
|
+ waddch(dialog, instr[show_x + i]);
|
|
+ } else {
|
|
+ show_x = 0;
|
|
+ input_x = len;
|
|
+ waddstr(dialog, instr);
|
|
+ }
|
|
+
|
|
+ wmove(dialog, box_y, box_x + input_x);
|
|
+
|
|
+ wrefresh(dialog);
|
|
+
|
|
+ while (key != KEY_ESC) {
|
|
+ key = wgetch(dialog);
|
|
+
|
|
+ if (button == -1) { /* Input box selected */
|
|
+ switch (key) {
|
|
+ case TAB:
|
|
+ case KEY_UP:
|
|
+ case KEY_DOWN:
|
|
+ break;
|
|
+ case KEY_BACKSPACE:
|
|
+ case 127:
|
|
+ if (pos) {
|
|
+ wattrset(dialog, dlg.inputbox.atr);
|
|
+ if (input_x == 0) {
|
|
+ show_x--;
|
|
+ } else
|
|
+ input_x--;
|
|
+
|
|
+ if (pos < len) {
|
|
+ for (i = pos - 1; i < len; i++) {
|
|
+ instr[i] = instr[i+1];
|
|
+ }
|
|
+ }
|
|
+
|
|
+ pos--;
|
|
+ len--;
|
|
+ instr[len] = '\0';
|
|
+ wmove(dialog, box_y, box_x);
|
|
+ for (i = 0; i < box_width; i++) {
|
|
+ if (!instr[show_x + i]) {
|
|
+ waddch(dialog, ' ');
|
|
+ break;
|
|
+ }
|
|
+ waddch(dialog, instr[show_x + i]);
|
|
+ }
|
|
+ wmove(dialog, box_y, input_x + box_x);
|
|
+ wrefresh(dialog);
|
|
+ }
|
|
+ continue;
|
|
+ case KEY_LEFT:
|
|
+ if (pos > 0) {
|
|
+ if (input_x > 0) {
|
|
+ wmove(dialog, box_y, --input_x + box_x);
|
|
+ } else if (input_x == 0) {
|
|
+ show_x--;
|
|
+ wmove(dialog, box_y, box_x);
|
|
+ for (i = 0; i < box_width; i++) {
|
|
+ if (!instr[show_x + i]) {
|
|
+ waddch(dialog, ' ');
|
|
+ break;
|
|
+ }
|
|
+ waddch(dialog, instr[show_x + i]);
|
|
+ }
|
|
+ wmove(dialog, box_y, box_x);
|
|
+ }
|
|
+ pos--;
|
|
+ }
|
|
+ continue;
|
|
+ case KEY_RIGHT:
|
|
+ if (pos < len) {
|
|
+ if (input_x < box_width - 1) {
|
|
+ wmove(dialog, box_y, ++input_x + box_x);
|
|
+ } else if (input_x == box_width - 1) {
|
|
+ show_x++;
|
|
+ wmove(dialog, box_y, box_x);
|
|
+ for (i = 0; i < box_width; i++) {
|
|
+ if (!instr[show_x + i]) {
|
|
+ waddch(dialog, ' ');
|
|
+ break;
|
|
+ }
|
|
+ waddch(dialog, instr[show_x + i]);
|
|
+ }
|
|
+ wmove(dialog, box_y, input_x + box_x);
|
|
+ }
|
|
+ pos++;
|
|
+ }
|
|
+ continue;
|
|
+ default:
|
|
+ if (key < 0x100 && isprint(key)) {
|
|
+ if (len < MAX_LEN) {
|
|
+ wattrset(dialog, dlg.inputbox.atr);
|
|
+ if (pos < len) {
|
|
+ for (i = len; i > pos; i--)
|
|
+ instr[i] = instr[i-1];
|
|
+ instr[pos] = key;
|
|
+ } else {
|
|
+ instr[len] = key;
|
|
+ }
|
|
+ pos++;
|
|
+ len++;
|
|
+ instr[len] = '\0';
|
|
+
|
|
+ if (input_x == box_width - 1) {
|
|
+ show_x++;
|
|
+ } else {
|
|
+ input_x++;
|
|
+ }
|
|
+
|
|
+ wmove(dialog, box_y, box_x);
|
|
+ for (i = 0; i < box_width; i++) {
|
|
+ if (!instr[show_x + i]) {
|
|
+ waddch(dialog, ' ');
|
|
+ break;
|
|
+ }
|
|
+ waddch(dialog, instr[show_x + i]);
|
|
+ }
|
|
+ wmove(dialog, box_y, input_x + box_x);
|
|
+ wrefresh(dialog);
|
|
+ } else
|
|
+ flash(); /* Alarm user about overflow */
|
|
+ continue;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ switch (key) {
|
|
+ case 'O':
|
|
+ case 'o':
|
|
+ delwin(dialog);
|
|
+ return 0;
|
|
+ case 'H':
|
|
+ case 'h':
|
|
+ delwin(dialog);
|
|
+ return 1;
|
|
+ case KEY_UP:
|
|
+ case KEY_LEFT:
|
|
+ switch (button) {
|
|
+ case -1:
|
|
+ button = 1; /* Indicates "Help" button is selected */
|
|
+ print_buttons(dialog, height, width, 1);
|
|
+ break;
|
|
+ case 0:
|
|
+ button = -1; /* Indicates input box is selected */
|
|
+ print_buttons(dialog, height, width, 0);
|
|
+ wmove(dialog, box_y, box_x + input_x);
|
|
+ wrefresh(dialog);
|
|
+ break;
|
|
+ case 1:
|
|
+ button = 0; /* Indicates "OK" button is selected */
|
|
+ print_buttons(dialog, height, width, 0);
|
|
+ break;
|
|
+ }
|
|
+ break;
|
|
+ case TAB:
|
|
+ case KEY_DOWN:
|
|
+ case KEY_RIGHT:
|
|
+ switch (button) {
|
|
+ case -1:
|
|
+ button = 0; /* Indicates "OK" button is selected */
|
|
+ print_buttons(dialog, height, width, 0);
|
|
+ break;
|
|
+ case 0:
|
|
+ button = 1; /* Indicates "Help" button is selected */
|
|
+ print_buttons(dialog, height, width, 1);
|
|
+ break;
|
|
+ case 1:
|
|
+ button = -1; /* Indicates input box is selected */
|
|
+ print_buttons(dialog, height, width, 0);
|
|
+ wmove(dialog, box_y, box_x + input_x);
|
|
+ wrefresh(dialog);
|
|
+ break;
|
|
+ }
|
|
+ break;
|
|
+ case ' ':
|
|
+ case '\n':
|
|
+ delwin(dialog);
|
|
+ return (button == -1 ? 0 : button);
|
|
+ case 'X':
|
|
+ case 'x':
|
|
+ key = KEY_ESC;
|
|
+ break;
|
|
+ case KEY_ESC:
|
|
+ key = on_key_esc(dialog);
|
|
+ break;
|
|
+ case KEY_RESIZE:
|
|
+ delwin(dialog);
|
|
+ on_key_resize();
|
|
+ goto do_resize;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ delwin(dialog);
|
|
+ return KEY_ESC; /* ESC pressed */
|
|
+}
|
|
diff --git a/scripts/kconfig/lxdialog/menubox.c b/scripts/kconfig/lxdialog/menubox.c
|
|
new file mode 100644
|
|
index 0000000..11ae9ad
|
|
--- /dev/null
|
|
+++ b/scripts/kconfig/lxdialog/menubox.c
|
|
@@ -0,0 +1,437 @@
|
|
+/*
|
|
+ * menubox.c -- implements the menu box
|
|
+ *
|
|
+ * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
|
|
+ * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcapw@cfw.com)
|
|
+ *
|
|
+ * This program is free software; you can redistribute it and/or
|
|
+ * modify it under the terms of the GNU General Public License
|
|
+ * as published by the Free Software Foundation; either version 2
|
|
+ * of the License, or (at your option) any later version.
|
|
+ *
|
|
+ * This program is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
+ * GNU General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU General Public License
|
|
+ * along with this program; if not, write to the Free Software
|
|
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
+ */
|
|
+
|
|
+/*
|
|
+ * Changes by Clifford Wolf (god@clifford.at)
|
|
+ *
|
|
+ * [ 1998-06-13 ]
|
|
+ *
|
|
+ * *) A bugfix for the Page-Down problem
|
|
+ *
|
|
+ * *) Formerly when I used Page Down and Page Up, the cursor would be set
|
|
+ * to the first position in the menu box. Now lxdialog is a bit
|
|
+ * smarter and works more like other menu systems (just have a look at
|
|
+ * it).
|
|
+ *
|
|
+ * *) Formerly if I selected something my scrolling would be broken because
|
|
+ * lxdialog is re-invoked by the Menuconfig shell script, can't
|
|
+ * remember the last scrolling position, and just sets it so that the
|
|
+ * cursor is at the bottom of the box. Now it writes the temporary file
|
|
+ * lxdialog.scrltmp which contains this information. The file is
|
|
+ * deleted by lxdialog if the user leaves a submenu or enters a new
|
|
+ * one, but it would be nice if Menuconfig could make another "rm -f"
|
|
+ * just to be sure. Just try it out - you will recognise a difference!
|
|
+ *
|
|
+ * [ 1998-06-14 ]
|
|
+ *
|
|
+ * *) Now lxdialog is crash-safe against broken "lxdialog.scrltmp" files
|
|
+ * and menus change their size on the fly.
|
|
+ *
|
|
+ * *) If for some reason the last scrolling position is not saved by
|
|
+ * lxdialog, it sets the scrolling so that the selected item is in the
|
|
+ * middle of the menu box, not at the bottom.
|
|
+ *
|
|
+ * 02 January 1999, Michael Elizabeth Chastain (mec@shout.net)
|
|
+ * Reset 'scroll' to 0 if the value from lxdialog.scrltmp is bogus.
|
|
+ * This fixes a bug in Menuconfig where using ' ' to descend into menus
|
|
+ * would leave mis-synchronized lxdialog.scrltmp files lying around,
|
|
+ * fscanf would read in 'scroll', and eventually that value would get used.
|
|
+ */
|
|
+
|
|
+#include "dialog.h"
|
|
+
|
|
+static int menu_width, item_x;
|
|
+
|
|
+/*
|
|
+ * Print menu item
|
|
+ */
|
|
+static void do_print_item(WINDOW * win, const char *item, int line_y,
|
|
+ int selected, int hotkey)
|
|
+{
|
|
+ int j;
|
|
+ char *menu_item = malloc(menu_width + 1);
|
|
+
|
|
+ strncpy(menu_item, item, menu_width - item_x);
|
|
+ menu_item[menu_width - item_x] = '\0';
|
|
+ j = first_alpha(menu_item, "YyNnMmHh");
|
|
+
|
|
+ /* Clear 'residue' of last item */
|
|
+ wattrset(win, dlg.menubox.atr);
|
|
+ wmove(win, line_y, 0);
|
|
+#if OLD_NCURSES
|
|
+ {
|
|
+ int i;
|
|
+ for (i = 0; i < menu_width; i++)
|
|
+ waddch(win, ' ');
|
|
+ }
|
|
+#else
|
|
+ wclrtoeol(win);
|
|
+#endif
|
|
+ wattrset(win, selected ? dlg.item_selected.atr : dlg.item.atr);
|
|
+ mvwaddstr(win, line_y, item_x, menu_item);
|
|
+ if (hotkey) {
|
|
+ wattrset(win, selected ? dlg.tag_key_selected.atr
|
|
+ : dlg.tag_key.atr);
|
|
+ mvwaddch(win, line_y, item_x + j, menu_item[j]);
|
|
+ }
|
|
+ if (selected) {
|
|
+ wmove(win, line_y, item_x + 1);
|
|
+ }
|
|
+ free(menu_item);
|
|
+ wrefresh(win);
|
|
+}
|
|
+
|
|
+#define print_item(index, choice, selected) \
|
|
+do { \
|
|
+ item_set(index); \
|
|
+ do_print_item(menu, item_str(), choice, selected, !item_is_tag(':')); \
|
|
+} while (0)
|
|
+
|
|
+/*
|
|
+ * Print the scroll indicators.
|
|
+ */
|
|
+static void print_arrows(WINDOW * win, int item_no, int scroll, int y, int x,
|
|
+ int height)
|
|
+{
|
|
+ int cur_y, cur_x;
|
|
+
|
|
+ getyx(win, cur_y, cur_x);
|
|
+
|
|
+ wmove(win, y, x);
|
|
+
|
|
+ if (scroll > 0) {
|
|
+ wattrset(win, dlg.uarrow.atr);
|
|
+ waddch(win, ACS_UARROW);
|
|
+ waddstr(win, "(-)");
|
|
+ } else {
|
|
+ wattrset(win, dlg.menubox.atr);
|
|
+ waddch(win, ACS_HLINE);
|
|
+ waddch(win, ACS_HLINE);
|
|
+ waddch(win, ACS_HLINE);
|
|
+ waddch(win, ACS_HLINE);
|
|
+ }
|
|
+
|
|
+ y = y + height + 1;
|
|
+ wmove(win, y, x);
|
|
+ wrefresh(win);
|
|
+
|
|
+ if ((height < item_no) && (scroll + height < item_no)) {
|
|
+ wattrset(win, dlg.darrow.atr);
|
|
+ waddch(win, ACS_DARROW);
|
|
+ waddstr(win, "(+)");
|
|
+ } else {
|
|
+ wattrset(win, dlg.menubox_border.atr);
|
|
+ waddch(win, ACS_HLINE);
|
|
+ waddch(win, ACS_HLINE);
|
|
+ waddch(win, ACS_HLINE);
|
|
+ waddch(win, ACS_HLINE);
|
|
+ }
|
|
+
|
|
+ wmove(win, cur_y, cur_x);
|
|
+ wrefresh(win);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Display the termination buttons.
|
|
+ */
|
|
+static void print_buttons(WINDOW * win, int height, int width, int selected)
|
|
+{
|
|
+ int x = width / 2 - 28;
|
|
+ int y = height - 2;
|
|
+
|
|
+ print_button(win, gettext("Select"), y, x, selected == 0);
|
|
+ print_button(win, gettext(" Exit "), y, x + 12, selected == 1);
|
|
+ print_button(win, gettext(" Help "), y, x + 24, selected == 2);
|
|
+ print_button(win, gettext(" Save "), y, x + 36, selected == 3);
|
|
+ print_button(win, gettext(" Load "), y, x + 48, selected == 4);
|
|
+
|
|
+ wmove(win, y, x + 1 + 12 * selected);
|
|
+ wrefresh(win);
|
|
+}
|
|
+
|
|
+/* scroll up n lines (n may be negative) */
|
|
+static void do_scroll(WINDOW *win, int *scroll, int n)
|
|
+{
|
|
+ /* Scroll menu up */
|
|
+ scrollok(win, TRUE);
|
|
+ wscrl(win, n);
|
|
+ scrollok(win, FALSE);
|
|
+ *scroll = *scroll + n;
|
|
+ wrefresh(win);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Display a menu for choosing among a number of options
|
|
+ */
|
|
+int dialog_menu(const char *title, const char *prompt,
|
|
+ const void *selected, int *s_scroll)
|
|
+{
|
|
+ int i, j, x, y, box_x, box_y;
|
|
+ int height, width, menu_height;
|
|
+ int key = 0, button = 0, scroll = 0, choice = 0;
|
|
+ int first_item = 0, max_choice;
|
|
+ WINDOW *dialog, *menu;
|
|
+
|
|
+do_resize:
|
|
+ height = getmaxy(stdscr);
|
|
+ width = getmaxx(stdscr);
|
|
+ if (height < MENUBOX_HEIGTH_MIN || width < MENUBOX_WIDTH_MIN)
|
|
+ return -ERRDISPLAYTOOSMALL;
|
|
+
|
|
+ height -= 4;
|
|
+ width -= 5;
|
|
+ menu_height = height - 10;
|
|
+
|
|
+ max_choice = MIN(menu_height, item_count());
|
|
+
|
|
+ /* center dialog box on screen */
|
|
+ x = (getmaxx(stdscr) - width) / 2;
|
|
+ y = (getmaxy(stdscr) - height) / 2;
|
|
+
|
|
+ draw_shadow(stdscr, y, x, height, width);
|
|
+
|
|
+ dialog = newwin(height, width, y, x);
|
|
+ keypad(dialog, TRUE);
|
|
+
|
|
+ draw_box(dialog, 0, 0, height, width,
|
|
+ dlg.dialog.atr, dlg.border.atr);
|
|
+ wattrset(dialog, dlg.border.atr);
|
|
+ mvwaddch(dialog, height - 3, 0, ACS_LTEE);
|
|
+ for (i = 0; i < width - 2; i++)
|
|
+ waddch(dialog, ACS_HLINE);
|
|
+ wattrset(dialog, dlg.dialog.atr);
|
|
+ wbkgdset(dialog, dlg.dialog.atr & A_COLOR);
|
|
+ waddch(dialog, ACS_RTEE);
|
|
+
|
|
+ print_title(dialog, title, width);
|
|
+
|
|
+ wattrset(dialog, dlg.dialog.atr);
|
|
+ print_autowrap(dialog, prompt, width - 2, 1, 3);
|
|
+
|
|
+ menu_width = width - 6;
|
|
+ box_y = height - menu_height - 5;
|
|
+ box_x = (width - menu_width) / 2 - 1;
|
|
+
|
|
+ /* create new window for the menu */
|
|
+ menu = subwin(dialog, menu_height, menu_width,
|
|
+ y + box_y + 1, x + box_x + 1);
|
|
+ keypad(menu, TRUE);
|
|
+
|
|
+ /* draw a box around the menu items */
|
|
+ draw_box(dialog, box_y, box_x, menu_height + 2, menu_width + 2,
|
|
+ dlg.menubox_border.atr, dlg.menubox.atr);
|
|
+
|
|
+ if (menu_width >= 80)
|
|
+ item_x = (menu_width - 70) / 2;
|
|
+ else
|
|
+ item_x = 4;
|
|
+
|
|
+ /* Set choice to default item */
|
|
+ item_foreach()
|
|
+ if (selected && (selected == item_data()))
|
|
+ choice = item_n();
|
|
+ /* get the saved scroll info */
|
|
+ scroll = *s_scroll;
|
|
+ if ((scroll <= choice) && (scroll + max_choice > choice) &&
|
|
+ (scroll >= 0) && (scroll + max_choice <= item_count())) {
|
|
+ first_item = scroll;
|
|
+ choice = choice - scroll;
|
|
+ } else {
|
|
+ scroll = 0;
|
|
+ }
|
|
+ if ((choice >= max_choice)) {
|
|
+ if (choice >= item_count() - max_choice / 2)
|
|
+ scroll = first_item = item_count() - max_choice;
|
|
+ else
|
|
+ scroll = first_item = choice - max_choice / 2;
|
|
+ choice = choice - scroll;
|
|
+ }
|
|
+
|
|
+ /* Print the menu */
|
|
+ for (i = 0; i < max_choice; i++) {
|
|
+ print_item(first_item + i, i, i == choice);
|
|
+ }
|
|
+
|
|
+ wnoutrefresh(menu);
|
|
+
|
|
+ print_arrows(dialog, item_count(), scroll,
|
|
+ box_y, box_x + item_x + 1, menu_height);
|
|
+
|
|
+ print_buttons(dialog, height, width, 0);
|
|
+ wmove(menu, choice, item_x + 1);
|
|
+ wrefresh(menu);
|
|
+
|
|
+ while (key != KEY_ESC) {
|
|
+ key = wgetch(menu);
|
|
+
|
|
+ if (key < 256 && isalpha(key))
|
|
+ key = tolower(key);
|
|
+
|
|
+ if (strchr("ynmh", key))
|
|
+ i = max_choice;
|
|
+ else {
|
|
+ for (i = choice + 1; i < max_choice; i++) {
|
|
+ item_set(scroll + i);
|
|
+ j = first_alpha(item_str(), "YyNnMmHh");
|
|
+ if (key == tolower(item_str()[j]))
|
|
+ break;
|
|
+ }
|
|
+ if (i == max_choice)
|
|
+ for (i = 0; i < max_choice; i++) {
|
|
+ item_set(scroll + i);
|
|
+ j = first_alpha(item_str(), "YyNnMmHh");
|
|
+ if (key == tolower(item_str()[j]))
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (item_count() != 0 &&
|
|
+ (i < max_choice ||
|
|
+ key == KEY_UP || key == KEY_DOWN ||
|
|
+ key == '-' || key == '+' ||
|
|
+ key == KEY_PPAGE || key == KEY_NPAGE)) {
|
|
+ /* Remove highligt of current item */
|
|
+ print_item(scroll + choice, choice, FALSE);
|
|
+
|
|
+ if (key == KEY_UP || key == '-') {
|
|
+ if (choice < 2 && scroll) {
|
|
+ /* Scroll menu down */
|
|
+ do_scroll(menu, &scroll, -1);
|
|
+
|
|
+ print_item(scroll, 0, FALSE);
|
|
+ } else
|
|
+ choice = MAX(choice - 1, 0);
|
|
+
|
|
+ } else if (key == KEY_DOWN || key == '+') {
|
|
+ print_item(scroll+choice, choice, FALSE);
|
|
+
|
|
+ if ((choice > max_choice - 3) &&
|
|
+ (scroll + max_choice < item_count())) {
|
|
+ /* Scroll menu up */
|
|
+ do_scroll(menu, &scroll, 1);
|
|
+
|
|
+ print_item(scroll+max_choice - 1,
|
|
+ max_choice - 1, FALSE);
|
|
+ } else
|
|
+ choice = MIN(choice + 1, max_choice - 1);
|
|
+
|
|
+ } else if (key == KEY_PPAGE) {
|
|
+ scrollok(menu, TRUE);
|
|
+ for (i = 0; (i < max_choice); i++) {
|
|
+ if (scroll > 0) {
|
|
+ do_scroll(menu, &scroll, -1);
|
|
+ print_item(scroll, 0, FALSE);
|
|
+ } else {
|
|
+ if (choice > 0)
|
|
+ choice--;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ } else if (key == KEY_NPAGE) {
|
|
+ for (i = 0; (i < max_choice); i++) {
|
|
+ if (scroll + max_choice < item_count()) {
|
|
+ do_scroll(menu, &scroll, 1);
|
|
+ print_item(scroll+max_choice-1,
|
|
+ max_choice - 1, FALSE);
|
|
+ } else {
|
|
+ if (choice + 1 < max_choice)
|
|
+ choice++;
|
|
+ }
|
|
+ }
|
|
+ } else
|
|
+ choice = i;
|
|
+
|
|
+ print_item(scroll + choice, choice, TRUE);
|
|
+
|
|
+ print_arrows(dialog, item_count(), scroll,
|
|
+ box_y, box_x + item_x + 1, menu_height);
|
|
+
|
|
+ wnoutrefresh(dialog);
|
|
+ wrefresh(menu);
|
|
+
|
|
+ continue; /* wait for another key press */
|
|
+ }
|
|
+
|
|
+ switch (key) {
|
|
+ case KEY_LEFT:
|
|
+ case TAB:
|
|
+ case KEY_RIGHT:
|
|
+ button = ((key == KEY_LEFT ? --button : ++button) < 0)
|
|
+ ? 4 : (button > 4 ? 0 : button);
|
|
+
|
|
+ print_buttons(dialog, height, width, button);
|
|
+ wrefresh(menu);
|
|
+ break;
|
|
+ case ' ':
|
|
+ case 's':
|
|
+ case 'y':
|
|
+ case 'n':
|
|
+ case 'm':
|
|
+ case '/':
|
|
+ case 'h':
|
|
+ case '?':
|
|
+ case 'z':
|
|
+ case '\n':
|
|
+ /* save scroll info */
|
|
+ *s_scroll = scroll;
|
|
+ delwin(menu);
|
|
+ delwin(dialog);
|
|
+ item_set(scroll + choice);
|
|
+ item_set_selected(1);
|
|
+ switch (key) {
|
|
+ case 'h':
|
|
+ case '?':
|
|
+ return 2;
|
|
+ case 's':
|
|
+ case 'y':
|
|
+ return 5;
|
|
+ case 'n':
|
|
+ return 6;
|
|
+ case 'm':
|
|
+ return 7;
|
|
+ case ' ':
|
|
+ return 8;
|
|
+ case '/':
|
|
+ return 9;
|
|
+ case 'z':
|
|
+ return 10;
|
|
+ case '\n':
|
|
+ return button;
|
|
+ }
|
|
+ return 0;
|
|
+ case 'e':
|
|
+ case 'x':
|
|
+ key = KEY_ESC;
|
|
+ break;
|
|
+ case KEY_ESC:
|
|
+ key = on_key_esc(menu);
|
|
+ break;
|
|
+ case KEY_RESIZE:
|
|
+ on_key_resize();
|
|
+ delwin(menu);
|
|
+ delwin(dialog);
|
|
+ goto do_resize;
|
|
+ }
|
|
+ }
|
|
+ delwin(menu);
|
|
+ delwin(dialog);
|
|
+ return key; /* ESC pressed */
|
|
+}
|
|
diff --git a/scripts/kconfig/lxdialog/textbox.c b/scripts/kconfig/lxdialog/textbox.c
|
|
new file mode 100644
|
|
index 0000000..1773319
|
|
--- /dev/null
|
|
+++ b/scripts/kconfig/lxdialog/textbox.c
|
|
@@ -0,0 +1,408 @@
|
|
+/*
|
|
+ * textbox.c -- implements the text box
|
|
+ *
|
|
+ * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
|
|
+ * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
|
|
+ *
|
|
+ * This program is free software; you can redistribute it and/or
|
|
+ * modify it under the terms of the GNU General Public License
|
|
+ * as published by the Free Software Foundation; either version 2
|
|
+ * of the License, or (at your option) any later version.
|
|
+ *
|
|
+ * This program is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
+ * GNU General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU General Public License
|
|
+ * along with this program; if not, write to the Free Software
|
|
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
+ */
|
|
+
|
|
+#include "dialog.h"
|
|
+
|
|
+static void back_lines(int n);
|
|
+static void print_page(WINDOW *win, int height, int width, update_text_fn
|
|
+ update_text, void *data);
|
|
+static void print_line(WINDOW *win, int row, int width);
|
|
+static char *get_line(void);
|
|
+static void print_position(WINDOW * win);
|
|
+
|
|
+static int hscroll;
|
|
+static int begin_reached, end_reached, page_length;
|
|
+static char *buf;
|
|
+static char *page;
|
|
+
|
|
+/*
|
|
+ * refresh window content
|
|
+ */
|
|
+static void refresh_text_box(WINDOW *dialog, WINDOW *box, int boxh, int boxw,
|
|
+ int cur_y, int cur_x, update_text_fn update_text,
|
|
+ void *data)
|
|
+{
|
|
+ print_page(box, boxh, boxw, update_text, data);
|
|
+ print_position(dialog);
|
|
+ wmove(dialog, cur_y, cur_x); /* Restore cursor position */
|
|
+ wrefresh(dialog);
|
|
+}
|
|
+
|
|
+
|
|
+/*
|
|
+ * Display text from a file in a dialog box.
|
|
+ *
|
|
+ * keys is a null-terminated array
|
|
+ * update_text() may not add or remove any '\n' or '\0' in tbuf
|
|
+ */
|
|
+int dialog_textbox(const char *title, char *tbuf, int initial_height,
|
|
+ int initial_width, int *keys, int *_vscroll, int *_hscroll,
|
|
+ update_text_fn update_text, void *data)
|
|
+{
|
|
+ int i, x, y, cur_x, cur_y, key = 0;
|
|
+ int height, width, boxh, boxw;
|
|
+ WINDOW *dialog, *box;
|
|
+ bool done = false;
|
|
+
|
|
+ begin_reached = 1;
|
|
+ end_reached = 0;
|
|
+ page_length = 0;
|
|
+ hscroll = 0;
|
|
+ buf = tbuf;
|
|
+ page = buf; /* page is pointer to start of page to be displayed */
|
|
+
|
|
+ if (_vscroll && *_vscroll) {
|
|
+ begin_reached = 0;
|
|
+
|
|
+ for (i = 0; i < *_vscroll; i++)
|
|
+ get_line();
|
|
+ }
|
|
+ if (_hscroll)
|
|
+ hscroll = *_hscroll;
|
|
+
|
|
+do_resize:
|
|
+ getmaxyx(stdscr, height, width);
|
|
+ if (height < TEXTBOX_HEIGTH_MIN || width < TEXTBOX_WIDTH_MIN)
|
|
+ return -ERRDISPLAYTOOSMALL;
|
|
+ if (initial_height != 0)
|
|
+ height = initial_height;
|
|
+ else
|
|
+ if (height > 4)
|
|
+ height -= 4;
|
|
+ else
|
|
+ height = 0;
|
|
+ if (initial_width != 0)
|
|
+ width = initial_width;
|
|
+ else
|
|
+ if (width > 5)
|
|
+ width -= 5;
|
|
+ else
|
|
+ width = 0;
|
|
+
|
|
+ /* center dialog box on screen */
|
|
+ x = (getmaxx(stdscr) - width) / 2;
|
|
+ y = (getmaxy(stdscr) - height) / 2;
|
|
+
|
|
+ draw_shadow(stdscr, y, x, height, width);
|
|
+
|
|
+ dialog = newwin(height, width, y, x);
|
|
+ keypad(dialog, TRUE);
|
|
+
|
|
+ /* Create window for box region, used for scrolling text */
|
|
+ boxh = height - 4;
|
|
+ boxw = width - 2;
|
|
+ box = subwin(dialog, boxh, boxw, y + 1, x + 1);
|
|
+ wattrset(box, dlg.dialog.atr);
|
|
+ wbkgdset(box, dlg.dialog.atr & A_COLOR);
|
|
+
|
|
+ keypad(box, TRUE);
|
|
+
|
|
+ /* register the new window, along with its borders */
|
|
+ draw_box(dialog, 0, 0, height, width,
|
|
+ dlg.dialog.atr, dlg.border.atr);
|
|
+
|
|
+ wattrset(dialog, dlg.border.atr);
|
|
+ mvwaddch(dialog, height - 3, 0, ACS_LTEE);
|
|
+ for (i = 0; i < width - 2; i++)
|
|
+ waddch(dialog, ACS_HLINE);
|
|
+ wattrset(dialog, dlg.dialog.atr);
|
|
+ wbkgdset(dialog, dlg.dialog.atr & A_COLOR);
|
|
+ waddch(dialog, ACS_RTEE);
|
|
+
|
|
+ print_title(dialog, title, width);
|
|
+
|
|
+ print_button(dialog, gettext(" Exit "), height - 2, width / 2 - 4, TRUE);
|
|
+ wnoutrefresh(dialog);
|
|
+ getyx(dialog, cur_y, cur_x); /* Save cursor position */
|
|
+
|
|
+ /* Print first page of text */
|
|
+ attr_clear(box, boxh, boxw, dlg.dialog.atr);
|
|
+ refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x, update_text,
|
|
+ data);
|
|
+
|
|
+ while (!done) {
|
|
+ key = wgetch(dialog);
|
|
+ switch (key) {
|
|
+ case 'E': /* Exit */
|
|
+ case 'e':
|
|
+ case 'X':
|
|
+ case 'x':
|
|
+ case 'q':
|
|
+ case '\n':
|
|
+ done = true;
|
|
+ break;
|
|
+ case 'g': /* First page */
|
|
+ case KEY_HOME:
|
|
+ if (!begin_reached) {
|
|
+ begin_reached = 1;
|
|
+ page = buf;
|
|
+ refresh_text_box(dialog, box, boxh, boxw,
|
|
+ cur_y, cur_x, update_text,
|
|
+ data);
|
|
+ }
|
|
+ break;
|
|
+ case 'G': /* Last page */
|
|
+ case KEY_END:
|
|
+
|
|
+ end_reached = 1;
|
|
+ /* point to last char in buf */
|
|
+ page = buf + strlen(buf);
|
|
+ back_lines(boxh);
|
|
+ refresh_text_box(dialog, box, boxh, boxw, cur_y,
|
|
+ cur_x, update_text, data);
|
|
+ break;
|
|
+ case 'K': /* Previous line */
|
|
+ case 'k':
|
|
+ case KEY_UP:
|
|
+ if (begin_reached)
|
|
+ break;
|
|
+
|
|
+ back_lines(page_length + 1);
|
|
+ refresh_text_box(dialog, box, boxh, boxw, cur_y,
|
|
+ cur_x, update_text, data);
|
|
+ break;
|
|
+ case 'B': /* Previous page */
|
|
+ case 'b':
|
|
+ case 'u':
|
|
+ case KEY_PPAGE:
|
|
+ if (begin_reached)
|
|
+ break;
|
|
+ back_lines(page_length + boxh);
|
|
+ refresh_text_box(dialog, box, boxh, boxw, cur_y,
|
|
+ cur_x, update_text, data);
|
|
+ break;
|
|
+ case 'J': /* Next line */
|
|
+ case 'j':
|
|
+ case KEY_DOWN:
|
|
+ if (end_reached)
|
|
+ break;
|
|
+
|
|
+ back_lines(page_length - 1);
|
|
+ refresh_text_box(dialog, box, boxh, boxw, cur_y,
|
|
+ cur_x, update_text, data);
|
|
+ break;
|
|
+ case KEY_NPAGE: /* Next page */
|
|
+ case ' ':
|
|
+ case 'd':
|
|
+ if (end_reached)
|
|
+ break;
|
|
+
|
|
+ begin_reached = 0;
|
|
+ refresh_text_box(dialog, box, boxh, boxw, cur_y,
|
|
+ cur_x, update_text, data);
|
|
+ break;
|
|
+ case '0': /* Beginning of line */
|
|
+ case 'H': /* Scroll left */
|
|
+ case 'h':
|
|
+ case KEY_LEFT:
|
|
+ if (hscroll <= 0)
|
|
+ break;
|
|
+
|
|
+ if (key == '0')
|
|
+ hscroll = 0;
|
|
+ else
|
|
+ hscroll--;
|
|
+ /* Reprint current page to scroll horizontally */
|
|
+ back_lines(page_length);
|
|
+ refresh_text_box(dialog, box, boxh, boxw, cur_y,
|
|
+ cur_x, update_text, data);
|
|
+ break;
|
|
+ case 'L': /* Scroll right */
|
|
+ case 'l':
|
|
+ case KEY_RIGHT:
|
|
+ if (hscroll >= MAX_LEN)
|
|
+ break;
|
|
+ hscroll++;
|
|
+ /* Reprint current page to scroll horizontally */
|
|
+ back_lines(page_length);
|
|
+ refresh_text_box(dialog, box, boxh, boxw, cur_y,
|
|
+ cur_x, update_text, data);
|
|
+ break;
|
|
+ case KEY_ESC:
|
|
+ if (on_key_esc(dialog) == KEY_ESC)
|
|
+ done = true;
|
|
+ break;
|
|
+ case KEY_RESIZE:
|
|
+ back_lines(height);
|
|
+ delwin(box);
|
|
+ delwin(dialog);
|
|
+ on_key_resize();
|
|
+ goto do_resize;
|
|
+ default:
|
|
+ for (i = 0; keys[i]; i++) {
|
|
+ if (key == keys[i]) {
|
|
+ done = true;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ delwin(box);
|
|
+ delwin(dialog);
|
|
+ if (_vscroll) {
|
|
+ const char *s;
|
|
+
|
|
+ s = buf;
|
|
+ *_vscroll = 0;
|
|
+ back_lines(page_length);
|
|
+ while (s < page && (s = strchr(s, '\n'))) {
|
|
+ (*_vscroll)++;
|
|
+ s++;
|
|
+ }
|
|
+ }
|
|
+ if (_hscroll)
|
|
+ *_hscroll = hscroll;
|
|
+ return key;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Go back 'n' lines in text. Called by dialog_textbox().
|
|
+ * 'page' will be updated to point to the desired line in 'buf'.
|
|
+ */
|
|
+static void back_lines(int n)
|
|
+{
|
|
+ int i;
|
|
+
|
|
+ begin_reached = 0;
|
|
+ /* Go back 'n' lines */
|
|
+ for (i = 0; i < n; i++) {
|
|
+ if (*page == '\0') {
|
|
+ if (end_reached) {
|
|
+ end_reached = 0;
|
|
+ continue;
|
|
+ }
|
|
+ }
|
|
+ if (page == buf) {
|
|
+ begin_reached = 1;
|
|
+ return;
|
|
+ }
|
|
+ page--;
|
|
+ do {
|
|
+ if (page == buf) {
|
|
+ begin_reached = 1;
|
|
+ return;
|
|
+ }
|
|
+ page--;
|
|
+ } while (*page != '\n');
|
|
+ page++;
|
|
+ }
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Print a new page of text.
|
|
+ */
|
|
+static void print_page(WINDOW *win, int height, int width, update_text_fn
|
|
+ update_text, void *data)
|
|
+{
|
|
+ int i, passed_end = 0;
|
|
+
|
|
+ if (update_text) {
|
|
+ char *end;
|
|
+
|
|
+ for (i = 0; i < height; i++)
|
|
+ get_line();
|
|
+ end = page;
|
|
+ back_lines(height);
|
|
+ update_text(buf, page - buf, end - buf, data);
|
|
+ }
|
|
+
|
|
+ page_length = 0;
|
|
+ for (i = 0; i < height; i++) {
|
|
+ print_line(win, i, width);
|
|
+ if (!passed_end)
|
|
+ page_length++;
|
|
+ if (end_reached && !passed_end)
|
|
+ passed_end = 1;
|
|
+ }
|
|
+ wnoutrefresh(win);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Print a new line of text.
|
|
+ */
|
|
+static void print_line(WINDOW * win, int row, int width)
|
|
+{
|
|
+ char *line;
|
|
+
|
|
+ line = get_line();
|
|
+ line += MIN(strlen(line), hscroll); /* Scroll horizontally */
|
|
+ wmove(win, row, 0); /* move cursor to correct line */
|
|
+ waddch(win, ' ');
|
|
+ waddnstr(win, line, MIN(strlen(line), width - 2));
|
|
+
|
|
+ /* Clear 'residue' of previous line */
|
|
+#if OLD_NCURSES
|
|
+ {
|
|
+ int x = getcurx(win);
|
|
+ int i;
|
|
+ for (i = 0; i < width - x; i++)
|
|
+ waddch(win, ' ');
|
|
+ }
|
|
+#else
|
|
+ wclrtoeol(win);
|
|
+#endif
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Return current line of text. Called by dialog_textbox() and print_line().
|
|
+ * 'page' should point to start of current line before calling, and will be
|
|
+ * updated to point to start of next line.
|
|
+ */
|
|
+static char *get_line(void)
|
|
+{
|
|
+ int i = 0;
|
|
+ static char line[MAX_LEN + 1];
|
|
+
|
|
+ end_reached = 0;
|
|
+ while (*page != '\n') {
|
|
+ if (*page == '\0') {
|
|
+ end_reached = 1;
|
|
+ break;
|
|
+ } else if (i < MAX_LEN)
|
|
+ line[i++] = *(page++);
|
|
+ else {
|
|
+ /* Truncate lines longer than MAX_LEN characters */
|
|
+ if (i == MAX_LEN)
|
|
+ line[i++] = '\0';
|
|
+ page++;
|
|
+ }
|
|
+ }
|
|
+ if (i <= MAX_LEN)
|
|
+ line[i] = '\0';
|
|
+ if (!end_reached)
|
|
+ page++; /* move past '\n' */
|
|
+
|
|
+ return line;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Print current position
|
|
+ */
|
|
+static void print_position(WINDOW * win)
|
|
+{
|
|
+ int percent;
|
|
+
|
|
+ wattrset(win, dlg.position_indicator.atr);
|
|
+ wbkgdset(win, dlg.position_indicator.atr & A_COLOR);
|
|
+ percent = (page - buf) * 100 / strlen(buf);
|
|
+ wmove(win, getmaxy(win) - 3, getmaxx(win) - 9);
|
|
+ wprintw(win, "(%3d%%)", percent);
|
|
+}
|
|
diff --git a/scripts/kconfig/lxdialog/util.c b/scripts/kconfig/lxdialog/util.c
|
|
new file mode 100644
|
|
index 0000000..f7abdeb
|
|
--- /dev/null
|
|
+++ b/scripts/kconfig/lxdialog/util.c
|
|
@@ -0,0 +1,713 @@
|
|
+/*
|
|
+ * util.c
|
|
+ *
|
|
+ * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
|
|
+ * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
|
|
+ *
|
|
+ * This program is free software; you can redistribute it and/or
|
|
+ * modify it under the terms of the GNU General Public License
|
|
+ * as published by the Free Software Foundation; either version 2
|
|
+ * of the License, or (at your option) any later version.
|
|
+ *
|
|
+ * This program is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
+ * GNU General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU General Public License
|
|
+ * along with this program; if not, write to the Free Software
|
|
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
+ */
|
|
+
|
|
+#include <stdarg.h>
|
|
+
|
|
+#include "dialog.h"
|
|
+
|
|
+/* Needed in signal handler in mconf.c */
|
|
+int saved_x, saved_y;
|
|
+
|
|
+struct dialog_info dlg;
|
|
+
|
|
+static void set_mono_theme(void)
|
|
+{
|
|
+ dlg.screen.atr = A_NORMAL;
|
|
+ dlg.shadow.atr = A_NORMAL;
|
|
+ dlg.dialog.atr = A_NORMAL;
|
|
+ dlg.title.atr = A_BOLD;
|
|
+ dlg.border.atr = A_NORMAL;
|
|
+ dlg.button_active.atr = A_REVERSE;
|
|
+ dlg.button_inactive.atr = A_DIM;
|
|
+ dlg.button_key_active.atr = A_REVERSE;
|
|
+ dlg.button_key_inactive.atr = A_BOLD;
|
|
+ dlg.button_label_active.atr = A_REVERSE;
|
|
+ dlg.button_label_inactive.atr = A_NORMAL;
|
|
+ dlg.inputbox.atr = A_NORMAL;
|
|
+ dlg.inputbox_border.atr = A_NORMAL;
|
|
+ dlg.searchbox.atr = A_NORMAL;
|
|
+ dlg.searchbox_title.atr = A_BOLD;
|
|
+ dlg.searchbox_border.atr = A_NORMAL;
|
|
+ dlg.position_indicator.atr = A_BOLD;
|
|
+ dlg.menubox.atr = A_NORMAL;
|
|
+ dlg.menubox_border.atr = A_NORMAL;
|
|
+ dlg.item.atr = A_NORMAL;
|
|
+ dlg.item_selected.atr = A_REVERSE;
|
|
+ dlg.tag.atr = A_BOLD;
|
|
+ dlg.tag_selected.atr = A_REVERSE;
|
|
+ dlg.tag_key.atr = A_BOLD;
|
|
+ dlg.tag_key_selected.atr = A_REVERSE;
|
|
+ dlg.check.atr = A_BOLD;
|
|
+ dlg.check_selected.atr = A_REVERSE;
|
|
+ dlg.uarrow.atr = A_BOLD;
|
|
+ dlg.darrow.atr = A_BOLD;
|
|
+}
|
|
+
|
|
+#define DLG_COLOR(dialog, f, b, h) \
|
|
+do { \
|
|
+ dlg.dialog.fg = (f); \
|
|
+ dlg.dialog.bg = (b); \
|
|
+ dlg.dialog.hl = (h); \
|
|
+} while (0)
|
|
+
|
|
+static void set_classic_theme(void)
|
|
+{
|
|
+ DLG_COLOR(screen, COLOR_CYAN, COLOR_BLUE, true);
|
|
+ DLG_COLOR(shadow, COLOR_BLACK, COLOR_BLACK, true);
|
|
+ DLG_COLOR(dialog, COLOR_BLACK, COLOR_WHITE, false);
|
|
+ DLG_COLOR(title, COLOR_YELLOW, COLOR_WHITE, true);
|
|
+ DLG_COLOR(border, COLOR_WHITE, COLOR_WHITE, true);
|
|
+ DLG_COLOR(button_active, COLOR_WHITE, COLOR_BLUE, true);
|
|
+ DLG_COLOR(button_inactive, COLOR_BLACK, COLOR_WHITE, false);
|
|
+ DLG_COLOR(button_key_active, COLOR_WHITE, COLOR_BLUE, true);
|
|
+ DLG_COLOR(button_key_inactive, COLOR_RED, COLOR_WHITE, false);
|
|
+ DLG_COLOR(button_label_active, COLOR_YELLOW, COLOR_BLUE, true);
|
|
+ DLG_COLOR(button_label_inactive, COLOR_BLACK, COLOR_WHITE, true);
|
|
+ DLG_COLOR(inputbox, COLOR_BLACK, COLOR_WHITE, false);
|
|
+ DLG_COLOR(inputbox_border, COLOR_BLACK, COLOR_WHITE, false);
|
|
+ DLG_COLOR(searchbox, COLOR_BLACK, COLOR_WHITE, false);
|
|
+ DLG_COLOR(searchbox_title, COLOR_YELLOW, COLOR_WHITE, true);
|
|
+ DLG_COLOR(searchbox_border, COLOR_WHITE, COLOR_WHITE, true);
|
|
+ DLG_COLOR(position_indicator, COLOR_YELLOW, COLOR_WHITE, true);
|
|
+ DLG_COLOR(menubox, COLOR_BLACK, COLOR_WHITE, false);
|
|
+ DLG_COLOR(menubox_border, COLOR_WHITE, COLOR_WHITE, true);
|
|
+ DLG_COLOR(item, COLOR_BLACK, COLOR_WHITE, false);
|
|
+ DLG_COLOR(item_selected, COLOR_WHITE, COLOR_BLUE, true);
|
|
+ DLG_COLOR(tag, COLOR_YELLOW, COLOR_WHITE, true);
|
|
+ DLG_COLOR(tag_selected, COLOR_YELLOW, COLOR_BLUE, true);
|
|
+ DLG_COLOR(tag_key, COLOR_YELLOW, COLOR_WHITE, true);
|
|
+ DLG_COLOR(tag_key_selected, COLOR_YELLOW, COLOR_BLUE, true);
|
|
+ DLG_COLOR(check, COLOR_BLACK, COLOR_WHITE, false);
|
|
+ DLG_COLOR(check_selected, COLOR_WHITE, COLOR_BLUE, true);
|
|
+ DLG_COLOR(uarrow, COLOR_GREEN, COLOR_WHITE, true);
|
|
+ DLG_COLOR(darrow, COLOR_GREEN, COLOR_WHITE, true);
|
|
+}
|
|
+
|
|
+static void set_blackbg_theme(void)
|
|
+{
|
|
+ DLG_COLOR(screen, COLOR_RED, COLOR_BLACK, true);
|
|
+ DLG_COLOR(shadow, COLOR_BLACK, COLOR_BLACK, false);
|
|
+ DLG_COLOR(dialog, COLOR_WHITE, COLOR_BLACK, false);
|
|
+ DLG_COLOR(title, COLOR_RED, COLOR_BLACK, false);
|
|
+ DLG_COLOR(border, COLOR_BLACK, COLOR_BLACK, true);
|
|
+
|
|
+ DLG_COLOR(button_active, COLOR_YELLOW, COLOR_RED, false);
|
|
+ DLG_COLOR(button_inactive, COLOR_YELLOW, COLOR_BLACK, false);
|
|
+ DLG_COLOR(button_key_active, COLOR_YELLOW, COLOR_RED, true);
|
|
+ DLG_COLOR(button_key_inactive, COLOR_RED, COLOR_BLACK, false);
|
|
+ DLG_COLOR(button_label_active, COLOR_WHITE, COLOR_RED, false);
|
|
+ DLG_COLOR(button_label_inactive, COLOR_BLACK, COLOR_BLACK, true);
|
|
+
|
|
+ DLG_COLOR(inputbox, COLOR_YELLOW, COLOR_BLACK, false);
|
|
+ DLG_COLOR(inputbox_border, COLOR_YELLOW, COLOR_BLACK, false);
|
|
+
|
|
+ DLG_COLOR(searchbox, COLOR_YELLOW, COLOR_BLACK, false);
|
|
+ DLG_COLOR(searchbox_title, COLOR_YELLOW, COLOR_BLACK, true);
|
|
+ DLG_COLOR(searchbox_border, COLOR_BLACK, COLOR_BLACK, true);
|
|
+
|
|
+ DLG_COLOR(position_indicator, COLOR_RED, COLOR_BLACK, false);
|
|
+
|
|
+ DLG_COLOR(menubox, COLOR_YELLOW, COLOR_BLACK, false);
|
|
+ DLG_COLOR(menubox_border, COLOR_BLACK, COLOR_BLACK, true);
|
|
+
|
|
+ DLG_COLOR(item, COLOR_WHITE, COLOR_BLACK, false);
|
|
+ DLG_COLOR(item_selected, COLOR_WHITE, COLOR_RED, false);
|
|
+
|
|
+ DLG_COLOR(tag, COLOR_RED, COLOR_BLACK, false);
|
|
+ DLG_COLOR(tag_selected, COLOR_YELLOW, COLOR_RED, true);
|
|
+ DLG_COLOR(tag_key, COLOR_RED, COLOR_BLACK, false);
|
|
+ DLG_COLOR(tag_key_selected, COLOR_YELLOW, COLOR_RED, true);
|
|
+
|
|
+ DLG_COLOR(check, COLOR_YELLOW, COLOR_BLACK, false);
|
|
+ DLG_COLOR(check_selected, COLOR_YELLOW, COLOR_RED, true);
|
|
+
|
|
+ DLG_COLOR(uarrow, COLOR_RED, COLOR_BLACK, false);
|
|
+ DLG_COLOR(darrow, COLOR_RED, COLOR_BLACK, false);
|
|
+}
|
|
+
|
|
+static void set_bluetitle_theme(void)
|
|
+{
|
|
+ set_classic_theme();
|
|
+ DLG_COLOR(title, COLOR_BLUE, COLOR_WHITE, true);
|
|
+ DLG_COLOR(button_key_active, COLOR_YELLOW, COLOR_BLUE, true);
|
|
+ DLG_COLOR(button_label_active, COLOR_WHITE, COLOR_BLUE, true);
|
|
+ DLG_COLOR(searchbox_title, COLOR_BLUE, COLOR_WHITE, true);
|
|
+ DLG_COLOR(position_indicator, COLOR_BLUE, COLOR_WHITE, true);
|
|
+ DLG_COLOR(tag, COLOR_BLUE, COLOR_WHITE, true);
|
|
+ DLG_COLOR(tag_key, COLOR_BLUE, COLOR_WHITE, true);
|
|
+
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Select color theme
|
|
+ */
|
|
+static int set_theme(const char *theme)
|
|
+{
|
|
+ int use_color = 1;
|
|
+ if (!theme)
|
|
+ set_bluetitle_theme();
|
|
+ else if (strcmp(theme, "classic") == 0)
|
|
+ set_classic_theme();
|
|
+ else if (strcmp(theme, "bluetitle") == 0)
|
|
+ set_bluetitle_theme();
|
|
+ else if (strcmp(theme, "blackbg") == 0)
|
|
+ set_blackbg_theme();
|
|
+ else if (strcmp(theme, "mono") == 0)
|
|
+ use_color = 0;
|
|
+
|
|
+ return use_color;
|
|
+}
|
|
+
|
|
+static void init_one_color(struct dialog_color *color)
|
|
+{
|
|
+ static int pair = 0;
|
|
+
|
|
+ pair++;
|
|
+ init_pair(pair, color->fg, color->bg);
|
|
+ if (color->hl)
|
|
+ color->atr = A_BOLD | COLOR_PAIR(pair);
|
|
+ else
|
|
+ color->atr = COLOR_PAIR(pair);
|
|
+}
|
|
+
|
|
+static void init_dialog_colors(void)
|
|
+{
|
|
+ init_one_color(&dlg.screen);
|
|
+ init_one_color(&dlg.shadow);
|
|
+ init_one_color(&dlg.dialog);
|
|
+ init_one_color(&dlg.title);
|
|
+ init_one_color(&dlg.border);
|
|
+ init_one_color(&dlg.button_active);
|
|
+ init_one_color(&dlg.button_inactive);
|
|
+ init_one_color(&dlg.button_key_active);
|
|
+ init_one_color(&dlg.button_key_inactive);
|
|
+ init_one_color(&dlg.button_label_active);
|
|
+ init_one_color(&dlg.button_label_inactive);
|
|
+ init_one_color(&dlg.inputbox);
|
|
+ init_one_color(&dlg.inputbox_border);
|
|
+ init_one_color(&dlg.searchbox);
|
|
+ init_one_color(&dlg.searchbox_title);
|
|
+ init_one_color(&dlg.searchbox_border);
|
|
+ init_one_color(&dlg.position_indicator);
|
|
+ init_one_color(&dlg.menubox);
|
|
+ init_one_color(&dlg.menubox_border);
|
|
+ init_one_color(&dlg.item);
|
|
+ init_one_color(&dlg.item_selected);
|
|
+ init_one_color(&dlg.tag);
|
|
+ init_one_color(&dlg.tag_selected);
|
|
+ init_one_color(&dlg.tag_key);
|
|
+ init_one_color(&dlg.tag_key_selected);
|
|
+ init_one_color(&dlg.check);
|
|
+ init_one_color(&dlg.check_selected);
|
|
+ init_one_color(&dlg.uarrow);
|
|
+ init_one_color(&dlg.darrow);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Setup for color display
|
|
+ */
|
|
+static void color_setup(const char *theme)
|
|
+{
|
|
+ int use_color;
|
|
+
|
|
+ use_color = set_theme(theme);
|
|
+ if (use_color && has_colors()) {
|
|
+ start_color();
|
|
+ init_dialog_colors();
|
|
+ } else
|
|
+ set_mono_theme();
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Set window to attribute 'attr'
|
|
+ */
|
|
+void attr_clear(WINDOW * win, int height, int width, chtype attr)
|
|
+{
|
|
+ int i, j;
|
|
+
|
|
+ wattrset(win, attr);
|
|
+ for (i = 0; i < height; i++) {
|
|
+ wmove(win, i, 0);
|
|
+ for (j = 0; j < width; j++)
|
|
+ waddch(win, ' ');
|
|
+ }
|
|
+ touchwin(win);
|
|
+}
|
|
+
|
|
+void dialog_clear(void)
|
|
+{
|
|
+ int lines, columns;
|
|
+
|
|
+ lines = getmaxy(stdscr);
|
|
+ columns = getmaxx(stdscr);
|
|
+
|
|
+ attr_clear(stdscr, lines, columns, dlg.screen.atr);
|
|
+ /* Display background title if it exists ... - SLH */
|
|
+ if (dlg.backtitle != NULL) {
|
|
+ int i, len = 0, skip = 0;
|
|
+ struct subtitle_list *pos;
|
|
+
|
|
+ wattrset(stdscr, dlg.screen.atr);
|
|
+ mvwaddstr(stdscr, 0, 1, (char *)dlg.backtitle);
|
|
+
|
|
+ for (pos = dlg.subtitles; pos != NULL; pos = pos->next) {
|
|
+ /* 3 is for the arrow and spaces */
|
|
+ len += strlen(pos->text) + 3;
|
|
+ }
|
|
+
|
|
+ wmove(stdscr, 1, 1);
|
|
+ if (len > columns - 2) {
|
|
+ const char *ellipsis = "[...] ";
|
|
+ waddstr(stdscr, ellipsis);
|
|
+ skip = len - (columns - 2 - strlen(ellipsis));
|
|
+ }
|
|
+
|
|
+ for (pos = dlg.subtitles; pos != NULL; pos = pos->next) {
|
|
+ if (skip == 0)
|
|
+ waddch(stdscr, ACS_RARROW);
|
|
+ else
|
|
+ skip--;
|
|
+
|
|
+ if (skip == 0)
|
|
+ waddch(stdscr, ' ');
|
|
+ else
|
|
+ skip--;
|
|
+
|
|
+ if (skip < strlen(pos->text)) {
|
|
+ waddstr(stdscr, pos->text + skip);
|
|
+ skip = 0;
|
|
+ } else
|
|
+ skip -= strlen(pos->text);
|
|
+
|
|
+ if (skip == 0)
|
|
+ waddch(stdscr, ' ');
|
|
+ else
|
|
+ skip--;
|
|
+ }
|
|
+
|
|
+ for (i = len + 1; i < columns - 1; i++)
|
|
+ waddch(stdscr, ACS_HLINE);
|
|
+ }
|
|
+ wnoutrefresh(stdscr);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Do some initialization for dialog
|
|
+ */
|
|
+int init_dialog(const char *backtitle)
|
|
+{
|
|
+ int height, width;
|
|
+
|
|
+ initscr(); /* Init curses */
|
|
+
|
|
+ /* Get current cursor position for signal handler in mconf.c */
|
|
+ getyx(stdscr, saved_y, saved_x);
|
|
+
|
|
+ getmaxyx(stdscr, height, width);
|
|
+ if (height < WINDOW_HEIGTH_MIN || width < WINDOW_WIDTH_MIN) {
|
|
+ endwin();
|
|
+ return -ERRDISPLAYTOOSMALL;
|
|
+ }
|
|
+
|
|
+ dlg.backtitle = backtitle;
|
|
+ color_setup(getenv("MENUCONFIG_COLOR"));
|
|
+
|
|
+ keypad(stdscr, TRUE);
|
|
+ cbreak();
|
|
+ noecho();
|
|
+ dialog_clear();
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+void set_dialog_backtitle(const char *backtitle)
|
|
+{
|
|
+ dlg.backtitle = backtitle;
|
|
+}
|
|
+
|
|
+void set_dialog_subtitles(struct subtitle_list *subtitles)
|
|
+{
|
|
+ dlg.subtitles = subtitles;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * End using dialog functions.
|
|
+ */
|
|
+void end_dialog(int x, int y)
|
|
+{
|
|
+ /* move cursor back to original position */
|
|
+ move(y, x);
|
|
+ refresh();
|
|
+ endwin();
|
|
+}
|
|
+
|
|
+/* Print the title of the dialog. Center the title and truncate
|
|
+ * tile if wider than dialog (- 2 chars).
|
|
+ **/
|
|
+void print_title(WINDOW *dialog, const char *title, int width)
|
|
+{
|
|
+ if (title) {
|
|
+ int tlen = MIN(width - 2, strlen(title));
|
|
+ wattrset(dialog, dlg.title.atr);
|
|
+ mvwaddch(dialog, 0, (width - tlen) / 2 - 1, ' ');
|
|
+ mvwaddnstr(dialog, 0, (width - tlen)/2, title, tlen);
|
|
+ waddch(dialog, ' ');
|
|
+ }
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Print a string of text in a window, automatically wrap around to the
|
|
+ * next line if the string is too long to fit on one line. Newline
|
|
+ * characters '\n' are propperly processed. We start on a new line
|
|
+ * if there is no room for at least 4 nonblanks following a double-space.
|
|
+ */
|
|
+void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x)
|
|
+{
|
|
+ int newl, cur_x, cur_y;
|
|
+ int prompt_len, room, wlen;
|
|
+ char tempstr[MAX_LEN + 1], *word, *sp, *sp2, *newline_separator = 0;
|
|
+
|
|
+ strcpy(tempstr, prompt);
|
|
+
|
|
+ prompt_len = strlen(tempstr);
|
|
+
|
|
+ if (prompt_len <= width - x * 2) { /* If prompt is short */
|
|
+ wmove(win, y, (width - prompt_len) / 2);
|
|
+ waddstr(win, tempstr);
|
|
+ } else {
|
|
+ cur_x = x;
|
|
+ cur_y = y;
|
|
+ newl = 1;
|
|
+ word = tempstr;
|
|
+ while (word && *word) {
|
|
+ sp = strpbrk(word, "\n ");
|
|
+ if (sp && *sp == '\n')
|
|
+ newline_separator = sp;
|
|
+
|
|
+ if (sp)
|
|
+ *sp++ = 0;
|
|
+
|
|
+ /* Wrap to next line if either the word does not fit,
|
|
+ or it is the first word of a new sentence, and it is
|
|
+ short, and the next word does not fit. */
|
|
+ room = width - cur_x;
|
|
+ wlen = strlen(word);
|
|
+ if (wlen > room ||
|
|
+ (newl && wlen < 4 && sp
|
|
+ && wlen + 1 + strlen(sp) > room
|
|
+ && (!(sp2 = strpbrk(sp, "\n "))
|
|
+ || wlen + 1 + (sp2 - sp) > room))) {
|
|
+ cur_y++;
|
|
+ cur_x = x;
|
|
+ }
|
|
+ wmove(win, cur_y, cur_x);
|
|
+ waddstr(win, word);
|
|
+ getyx(win, cur_y, cur_x);
|
|
+
|
|
+ /* Move to the next line if the word separator was a newline */
|
|
+ if (newline_separator) {
|
|
+ cur_y++;
|
|
+ cur_x = x;
|
|
+ newline_separator = 0;
|
|
+ } else
|
|
+ cur_x++;
|
|
+
|
|
+ if (sp && *sp == ' ') {
|
|
+ cur_x++; /* double space */
|
|
+ while (*++sp == ' ') ;
|
|
+ newl = 1;
|
|
+ } else
|
|
+ newl = 0;
|
|
+ word = sp;
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Print a button
|
|
+ */
|
|
+void print_button(WINDOW * win, const char *label, int y, int x, int selected)
|
|
+{
|
|
+ int i, temp;
|
|
+
|
|
+ wmove(win, y, x);
|
|
+ wattrset(win, selected ? dlg.button_active.atr
|
|
+ : dlg.button_inactive.atr);
|
|
+ waddstr(win, "<");
|
|
+ temp = strspn(label, " ");
|
|
+ label += temp;
|
|
+ wattrset(win, selected ? dlg.button_label_active.atr
|
|
+ : dlg.button_label_inactive.atr);
|
|
+ for (i = 0; i < temp; i++)
|
|
+ waddch(win, ' ');
|
|
+ wattrset(win, selected ? dlg.button_key_active.atr
|
|
+ : dlg.button_key_inactive.atr);
|
|
+ waddch(win, label[0]);
|
|
+ wattrset(win, selected ? dlg.button_label_active.atr
|
|
+ : dlg.button_label_inactive.atr);
|
|
+ waddstr(win, (char *)label + 1);
|
|
+ wattrset(win, selected ? dlg.button_active.atr
|
|
+ : dlg.button_inactive.atr);
|
|
+ waddstr(win, ">");
|
|
+ wmove(win, y, x + temp + 1);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Draw a rectangular box with line drawing characters
|
|
+ */
|
|
+void
|
|
+draw_box(WINDOW * win, int y, int x, int height, int width,
|
|
+ chtype box, chtype border)
|
|
+{
|
|
+ int i, j;
|
|
+
|
|
+ wattrset(win, 0);
|
|
+ for (i = 0; i < height; i++) {
|
|
+ wmove(win, y + i, x);
|
|
+ for (j = 0; j < width; j++)
|
|
+ if (!i && !j)
|
|
+ waddch(win, border | ACS_ULCORNER);
|
|
+ else if (i == height - 1 && !j)
|
|
+ waddch(win, border | ACS_LLCORNER);
|
|
+ else if (!i && j == width - 1)
|
|
+ waddch(win, box | ACS_URCORNER);
|
|
+ else if (i == height - 1 && j == width - 1)
|
|
+ waddch(win, box | ACS_LRCORNER);
|
|
+ else if (!i)
|
|
+ waddch(win, border | ACS_HLINE);
|
|
+ else if (i == height - 1)
|
|
+ waddch(win, box | ACS_HLINE);
|
|
+ else if (!j)
|
|
+ waddch(win, border | ACS_VLINE);
|
|
+ else if (j == width - 1)
|
|
+ waddch(win, box | ACS_VLINE);
|
|
+ else
|
|
+ waddch(win, box | ' ');
|
|
+ }
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Draw shadows along the right and bottom edge to give a more 3D look
|
|
+ * to the boxes
|
|
+ */
|
|
+void draw_shadow(WINDOW * win, int y, int x, int height, int width)
|
|
+{
|
|
+ int i;
|
|
+
|
|
+ if (has_colors()) { /* Whether terminal supports color? */
|
|
+ wattrset(win, dlg.shadow.atr);
|
|
+ wmove(win, y + height, x + 2);
|
|
+ for (i = 0; i < width; i++)
|
|
+ waddch(win, winch(win) & A_CHARTEXT);
|
|
+ for (i = y + 1; i < y + height + 1; i++) {
|
|
+ wmove(win, i, x + width);
|
|
+ waddch(win, winch(win) & A_CHARTEXT);
|
|
+ waddch(win, winch(win) & A_CHARTEXT);
|
|
+ }
|
|
+ wnoutrefresh(win);
|
|
+ }
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Return the position of the first alphabetic character in a string.
|
|
+ */
|
|
+int first_alpha(const char *string, const char *exempt)
|
|
+{
|
|
+ int i, in_paren = 0, c;
|
|
+
|
|
+ for (i = 0; i < strlen(string); i++) {
|
|
+ c = tolower(string[i]);
|
|
+
|
|
+ if (strchr("<[(", c))
|
|
+ ++in_paren;
|
|
+ if (strchr(">])", c) && in_paren > 0)
|
|
+ --in_paren;
|
|
+
|
|
+ if ((!in_paren) && isalpha(c) && strchr(exempt, c) == 0)
|
|
+ return i;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * ncurses uses ESC to detect escaped char sequences. This resutl in
|
|
+ * a small timeout before ESC is actually delivered to the application.
|
|
+ * lxdialog suggest <ESC> <ESC> which is correctly translated to two
|
|
+ * times esc. But then we need to ignore the second esc to avoid stepping
|
|
+ * out one menu too much. Filter away all escaped key sequences since
|
|
+ * keypad(FALSE) turn off ncurses support for escape sequences - and thats
|
|
+ * needed to make notimeout() do as expected.
|
|
+ */
|
|
+int on_key_esc(WINDOW *win)
|
|
+{
|
|
+ int key;
|
|
+ int key2;
|
|
+ int key3;
|
|
+
|
|
+ nodelay(win, TRUE);
|
|
+ keypad(win, FALSE);
|
|
+ key = wgetch(win);
|
|
+ key2 = wgetch(win);
|
|
+ do {
|
|
+ key3 = wgetch(win);
|
|
+ } while (key3 != ERR);
|
|
+ nodelay(win, FALSE);
|
|
+ keypad(win, TRUE);
|
|
+ if (key == KEY_ESC && key2 == ERR)
|
|
+ return KEY_ESC;
|
|
+ else if (key != ERR && key != KEY_ESC && key2 == ERR)
|
|
+ ungetch(key);
|
|
+
|
|
+ return -1;
|
|
+}
|
|
+
|
|
+/* redraw screen in new size */
|
|
+int on_key_resize(void)
|
|
+{
|
|
+ dialog_clear();
|
|
+ return KEY_RESIZE;
|
|
+}
|
|
+
|
|
+struct dialog_list *item_cur;
|
|
+struct dialog_list item_nil;
|
|
+struct dialog_list *item_head;
|
|
+
|
|
+void item_reset(void)
|
|
+{
|
|
+ struct dialog_list *p, *next;
|
|
+
|
|
+ for (p = item_head; p; p = next) {
|
|
+ next = p->next;
|
|
+ free(p);
|
|
+ }
|
|
+ item_head = NULL;
|
|
+ item_cur = &item_nil;
|
|
+}
|
|
+
|
|
+void item_make(const char *fmt, ...)
|
|
+{
|
|
+ va_list ap;
|
|
+ struct dialog_list *p = malloc(sizeof(*p));
|
|
+
|
|
+ if (item_head)
|
|
+ item_cur->next = p;
|
|
+ else
|
|
+ item_head = p;
|
|
+ item_cur = p;
|
|
+ memset(p, 0, sizeof(*p));
|
|
+
|
|
+ va_start(ap, fmt);
|
|
+ vsnprintf(item_cur->node.str, sizeof(item_cur->node.str), fmt, ap);
|
|
+ va_end(ap);
|
|
+}
|
|
+
|
|
+void item_add_str(const char *fmt, ...)
|
|
+{
|
|
+ va_list ap;
|
|
+ size_t avail;
|
|
+
|
|
+ avail = sizeof(item_cur->node.str) - strlen(item_cur->node.str);
|
|
+
|
|
+ va_start(ap, fmt);
|
|
+ vsnprintf(item_cur->node.str + strlen(item_cur->node.str),
|
|
+ avail, fmt, ap);
|
|
+ item_cur->node.str[sizeof(item_cur->node.str) - 1] = '\0';
|
|
+ va_end(ap);
|
|
+}
|
|
+
|
|
+void item_set_tag(char tag)
|
|
+{
|
|
+ item_cur->node.tag = tag;
|
|
+}
|
|
+void item_set_data(void *ptr)
|
|
+{
|
|
+ item_cur->node.data = ptr;
|
|
+}
|
|
+
|
|
+void item_set_selected(int val)
|
|
+{
|
|
+ item_cur->node.selected = val;
|
|
+}
|
|
+
|
|
+int item_activate_selected(void)
|
|
+{
|
|
+ item_foreach()
|
|
+ if (item_is_selected())
|
|
+ return 1;
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+void *item_data(void)
|
|
+{
|
|
+ return item_cur->node.data;
|
|
+}
|
|
+
|
|
+char item_tag(void)
|
|
+{
|
|
+ return item_cur->node.tag;
|
|
+}
|
|
+
|
|
+int item_count(void)
|
|
+{
|
|
+ int n = 0;
|
|
+ struct dialog_list *p;
|
|
+
|
|
+ for (p = item_head; p; p = p->next)
|
|
+ n++;
|
|
+ return n;
|
|
+}
|
|
+
|
|
+void item_set(int n)
|
|
+{
|
|
+ int i = 0;
|
|
+ item_foreach()
|
|
+ if (i++ == n)
|
|
+ return;
|
|
+}
|
|
+
|
|
+int item_n(void)
|
|
+{
|
|
+ int n = 0;
|
|
+ struct dialog_list *p;
|
|
+
|
|
+ for (p = item_head; p; p = p->next) {
|
|
+ if (p == item_cur)
|
|
+ return n;
|
|
+ n++;
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+const char *item_str(void)
|
|
+{
|
|
+ return item_cur->node.str;
|
|
+}
|
|
+
|
|
+int item_is_selected(void)
|
|
+{
|
|
+ return (item_cur->node.selected != 0);
|
|
+}
|
|
+
|
|
+int item_is_tag(char tag)
|
|
+{
|
|
+ return (item_cur->node.tag == tag);
|
|
+}
|
|
diff --git a/scripts/kconfig/lxdialog/yesno.c b/scripts/kconfig/lxdialog/yesno.c
|
|
new file mode 100644
|
|
index 0000000..676fb2f
|
|
--- /dev/null
|
|
+++ b/scripts/kconfig/lxdialog/yesno.c
|
|
@@ -0,0 +1,114 @@
|
|
+/*
|
|
+ * yesno.c -- implements the yes/no box
|
|
+ *
|
|
+ * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
|
|
+ * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
|
|
+ *
|
|
+ * This program is free software; you can redistribute it and/or
|
|
+ * modify it under the terms of the GNU General Public License
|
|
+ * as published by the Free Software Foundation; either version 2
|
|
+ * of the License, or (at your option) any later version.
|
|
+ *
|
|
+ * This program is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
+ * GNU General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU General Public License
|
|
+ * along with this program; if not, write to the Free Software
|
|
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
+ */
|
|
+
|
|
+#include "dialog.h"
|
|
+
|
|
+/*
|
|
+ * Display termination buttons
|
|
+ */
|
|
+static void print_buttons(WINDOW * dialog, int height, int width, int selected)
|
|
+{
|
|
+ int x = width / 2 - 10;
|
|
+ int y = height - 2;
|
|
+
|
|
+ print_button(dialog, gettext(" Yes "), y, x, selected == 0);
|
|
+ print_button(dialog, gettext(" No "), y, x + 13, selected == 1);
|
|
+
|
|
+ wmove(dialog, y, x + 1 + 13 * selected);
|
|
+ wrefresh(dialog);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Display a dialog box with two buttons - Yes and No
|
|
+ */
|
|
+int dialog_yesno(const char *title, const char *prompt, int height, int width)
|
|
+{
|
|
+ int i, x, y, key = 0, button = 0;
|
|
+ WINDOW *dialog;
|
|
+
|
|
+do_resize:
|
|
+ if (getmaxy(stdscr) < (height + YESNO_HEIGTH_MIN))
|
|
+ return -ERRDISPLAYTOOSMALL;
|
|
+ if (getmaxx(stdscr) < (width + YESNO_WIDTH_MIN))
|
|
+ return -ERRDISPLAYTOOSMALL;
|
|
+
|
|
+ /* center dialog box on screen */
|
|
+ x = (getmaxx(stdscr) - width) / 2;
|
|
+ y = (getmaxy(stdscr) - height) / 2;
|
|
+
|
|
+ draw_shadow(stdscr, y, x, height, width);
|
|
+
|
|
+ dialog = newwin(height, width, y, x);
|
|
+ keypad(dialog, TRUE);
|
|
+
|
|
+ draw_box(dialog, 0, 0, height, width,
|
|
+ dlg.dialog.atr, dlg.border.atr);
|
|
+ wattrset(dialog, dlg.border.atr);
|
|
+ mvwaddch(dialog, height - 3, 0, ACS_LTEE);
|
|
+ for (i = 0; i < width - 2; i++)
|
|
+ waddch(dialog, ACS_HLINE);
|
|
+ wattrset(dialog, dlg.dialog.atr);
|
|
+ waddch(dialog, ACS_RTEE);
|
|
+
|
|
+ print_title(dialog, title, width);
|
|
+
|
|
+ wattrset(dialog, dlg.dialog.atr);
|
|
+ print_autowrap(dialog, prompt, width - 2, 1, 3);
|
|
+
|
|
+ print_buttons(dialog, height, width, 0);
|
|
+
|
|
+ while (key != KEY_ESC) {
|
|
+ key = wgetch(dialog);
|
|
+ switch (key) {
|
|
+ case 'Y':
|
|
+ case 'y':
|
|
+ delwin(dialog);
|
|
+ return 0;
|
|
+ case 'N':
|
|
+ case 'n':
|
|
+ delwin(dialog);
|
|
+ return 1;
|
|
+
|
|
+ case TAB:
|
|
+ case KEY_LEFT:
|
|
+ case KEY_RIGHT:
|
|
+ button = ((key == KEY_LEFT ? --button : ++button) < 0) ? 1 : (button > 1 ? 0 : button);
|
|
+
|
|
+ print_buttons(dialog, height, width, button);
|
|
+ wrefresh(dialog);
|
|
+ break;
|
|
+ case ' ':
|
|
+ case '\n':
|
|
+ delwin(dialog);
|
|
+ return button;
|
|
+ case KEY_ESC:
|
|
+ key = on_key_esc(dialog);
|
|
+ break;
|
|
+ case KEY_RESIZE:
|
|
+ delwin(dialog);
|
|
+ on_key_resize();
|
|
+ goto do_resize;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ delwin(dialog);
|
|
+ return key; /* ESC pressed */
|
|
+}
|
|
diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c
|
|
new file mode 100644
|
|
index 0000000..14cea74
|
|
--- /dev/null
|
|
+++ b/scripts/kconfig/mconf.c
|
|
@@ -0,0 +1,1036 @@
|
|
+/*
|
|
+ * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
|
|
+ * Released under the terms of the GNU GPL v2.0.
|
|
+ *
|
|
+ * Introduced single menu mode (show all sub-menus in one large tree).
|
|
+ * 2002-11-06 Petr Baudis <pasky@ucw.cz>
|
|
+ *
|
|
+ * i18n, 2005, Arnaldo Carvalho de Melo <acme@conectiva.com.br>
|
|
+ */
|
|
+
|
|
+#include <ctype.h>
|
|
+#include <errno.h>
|
|
+#include <fcntl.h>
|
|
+#include <limits.h>
|
|
+#include <stdarg.h>
|
|
+#include <stdlib.h>
|
|
+#include <string.h>
|
|
+#include <signal.h>
|
|
+#include <unistd.h>
|
|
+#include <locale.h>
|
|
+
|
|
+#include "lkc.h"
|
|
+#include "lxdialog/dialog.h"
|
|
+
|
|
+static const char mconf_readme[] = N_(
|
|
+"Overview\n"
|
|
+"--------\n"
|
|
+"This interface lets you select features and parameters for the build.\n"
|
|
+"Features can either be built-in, modularized, or ignored. Parameters\n"
|
|
+"must be entered in as decimal or hexadecimal numbers or text.\n"
|
|
+"\n"
|
|
+"Menu items beginning with following braces represent features that\n"
|
|
+" [ ] can be built in or removed\n"
|
|
+" < > can be built in, modularized or removed\n"
|
|
+" { } can be built in or modularized (selected by other feature)\n"
|
|
+" - - are selected by other feature,\n"
|
|
+"while *, M or whitespace inside braces means to build in, build as\n"
|
|
+"a module or to exclude the feature respectively.\n"
|
|
+"\n"
|
|
+"To change any of these features, highlight it with the cursor\n"
|
|
+"keys and press <Y> to build it in, <M> to make it a module or\n"
|
|
+"<N> to remove it. You may also press the <Space Bar> to cycle\n"
|
|
+"through the available options (i.e. Y->N->M->Y).\n"
|
|
+"\n"
|
|
+"Some additional keyboard hints:\n"
|
|
+"\n"
|
|
+"Menus\n"
|
|
+"----------\n"
|
|
+"o Use the Up/Down arrow keys (cursor keys) to highlight the item you\n"
|
|
+" wish to change or the submenu you wish to select and press <Enter>.\n"
|
|
+" Submenus are designated by \"--->\", empty ones by \"----\".\n"
|
|
+"\n"
|
|
+" Shortcut: Press the option's highlighted letter (hotkey).\n"
|
|
+" Pressing a hotkey more than once will sequence\n"
|
|
+" through all visible items which use that hotkey.\n"
|
|
+"\n"
|
|
+" You may also use the <PAGE UP> and <PAGE DOWN> keys to scroll\n"
|
|
+" unseen options into view.\n"
|
|
+"\n"
|
|
+"o To exit a menu use the cursor keys to highlight the <Exit> button\n"
|
|
+" and press <ENTER>.\n"
|
|
+"\n"
|
|
+" Shortcut: Press <ESC><ESC> or <E> or <X> if there is no hotkey\n"
|
|
+" using those letters. You may press a single <ESC>, but\n"
|
|
+" there is a delayed response which you may find annoying.\n"
|
|
+"\n"
|
|
+" Also, the <TAB> and cursor keys will cycle between <Select>,\n"
|
|
+" <Exit>, <Help>, <Save>, and <Load>.\n"
|
|
+"\n"
|
|
+"o To get help with an item, use the cursor keys to highlight <Help>\n"
|
|
+" and press <ENTER>.\n"
|
|
+"\n"
|
|
+" Shortcut: Press <H> or <?>.\n"
|
|
+"\n"
|
|
+"o To toggle the display of hidden options, press <Z>.\n"
|
|
+"\n"
|
|
+"\n"
|
|
+"Radiolists (Choice lists)\n"
|
|
+"-----------\n"
|
|
+"o Use the cursor keys to select the option you wish to set and press\n"
|
|
+" <S> or the <SPACE BAR>.\n"
|
|
+"\n"
|
|
+" Shortcut: Press the first letter of the option you wish to set then\n"
|
|
+" press <S> or <SPACE BAR>.\n"
|
|
+"\n"
|
|
+"o To see available help for the item, use the cursor keys to highlight\n"
|
|
+" <Help> and Press <ENTER>.\n"
|
|
+"\n"
|
|
+" Shortcut: Press <H> or <?>.\n"
|
|
+"\n"
|
|
+" Also, the <TAB> and cursor keys will cycle between <Select> and\n"
|
|
+" <Help>\n"
|
|
+"\n"
|
|
+"\n"
|
|
+"Data Entry\n"
|
|
+"-----------\n"
|
|
+"o Enter the requested information and press <ENTER>\n"
|
|
+" If you are entering hexadecimal values, it is not necessary to\n"
|
|
+" add the '0x' prefix to the entry.\n"
|
|
+"\n"
|
|
+"o For help, use the <TAB> or cursor keys to highlight the help option\n"
|
|
+" and press <ENTER>. You can try <TAB><H> as well.\n"
|
|
+"\n"
|
|
+"\n"
|
|
+"Text Box (Help Window)\n"
|
|
+"--------\n"
|
|
+"o Use the cursor keys to scroll up/down/left/right. The VI editor\n"
|
|
+" keys h,j,k,l function here as do <u>, <d>, <SPACE BAR> and <B> for\n"
|
|
+" those who are familiar with less and lynx.\n"
|
|
+"\n"
|
|
+"o Press <E>, <X>, <q>, <Enter> or <Esc><Esc> to exit.\n"
|
|
+"\n"
|
|
+"\n"
|
|
+"Alternate Configuration Files\n"
|
|
+"-----------------------------\n"
|
|
+"Menuconfig supports the use of alternate configuration files for\n"
|
|
+"those who, for various reasons, find it necessary to switch\n"
|
|
+"between different configurations.\n"
|
|
+"\n"
|
|
+"The <Save> button will let you save the current configuration to\n"
|
|
+"a file of your choosing. Use the <Load> button to load a previously\n"
|
|
+"saved alternate configuration.\n"
|
|
+"\n"
|
|
+"Even if you don't use alternate configuration files, but you find\n"
|
|
+"during a Menuconfig session that you have completely messed up your\n"
|
|
+"settings, you may use the <Load> button to restore your previously\n"
|
|
+"saved settings from \".config\" without restarting Menuconfig.\n"
|
|
+"\n"
|
|
+"Other information\n"
|
|
+"-----------------\n"
|
|
+"If you use Menuconfig in an XTERM window, make sure you have your\n"
|
|
+"$TERM variable set to point to an xterm definition which supports\n"
|
|
+"color. Otherwise, Menuconfig will look rather bad. Menuconfig will\n"
|
|
+"not display correctly in an RXVT window because rxvt displays only one\n"
|
|
+"intensity of color, bright.\n"
|
|
+"\n"
|
|
+"Menuconfig will display larger menus on screens or xterms which are\n"
|
|
+"set to display more than the standard 25 row by 80 column geometry.\n"
|
|
+"In order for this to work, the \"stty size\" command must be able to\n"
|
|
+"display the screen's current row and column geometry. I STRONGLY\n"
|
|
+"RECOMMEND that you make sure you do NOT have the shell variables\n"
|
|
+"LINES and COLUMNS exported into your environment. Some distributions\n"
|
|
+"export those variables via /etc/profile. Some ncurses programs can\n"
|
|
+"become confused when those variables (LINES & COLUMNS) don't reflect\n"
|
|
+"the true screen size.\n"
|
|
+"\n"
|
|
+"Optional personality available\n"
|
|
+"------------------------------\n"
|
|
+"If you prefer to have all of the options listed in a single menu,\n"
|
|
+"rather than the default multimenu hierarchy, run the menuconfig with\n"
|
|
+"MENUCONFIG_MODE environment variable set to single_menu. Example:\n"
|
|
+"\n"
|
|
+"make MENUCONFIG_MODE=single_menu menuconfig\n"
|
|
+"\n"
|
|
+"<Enter> will then unroll the appropriate category, or enfold it if it\n"
|
|
+"is already unrolled.\n"
|
|
+"\n"
|
|
+"Note that this mode can eventually be a little more CPU expensive\n"
|
|
+"(especially with a larger number of unrolled categories) than the\n"
|
|
+"default mode.\n"
|
|
+"\n"
|
|
+"Different color themes available\n"
|
|
+"--------------------------------\n"
|
|
+"It is possible to select different color themes using the variable\n"
|
|
+"MENUCONFIG_COLOR. To select a theme use:\n"
|
|
+"\n"
|
|
+"make MENUCONFIG_COLOR=<theme> menuconfig\n"
|
|
+"\n"
|
|
+"Available themes are\n"
|
|
+" mono => selects colors suitable for monochrome displays\n"
|
|
+" blackbg => selects a color scheme with black background\n"
|
|
+" classic => theme with blue background. The classic look\n"
|
|
+" bluetitle => an LCD friendly version of classic. (default)\n"
|
|
+"\n"),
|
|
+menu_instructions[] = N_(
|
|
+ "Arrow keys navigate the menu. "
|
|
+ "<Enter> selects submenus ---> (or empty submenus ----). "
|
|
+ "Highlighted letters are hotkeys. "
|
|
+ "Pressing <Y> includes, <N> excludes, <M> modularizes features. "
|
|
+ "Press <Esc><Esc> to exit, <?> for Help, </> for Search. "
|
|
+ "Legend: [*] built-in [ ] excluded <M> module < > module capable"),
|
|
+radiolist_instructions[] = N_(
|
|
+ "Use the arrow keys to navigate this window or "
|
|
+ "press the hotkey of the item you wish to select "
|
|
+ "followed by the <SPACE BAR>. "
|
|
+ "Press <?> for additional information about this option."),
|
|
+inputbox_instructions_int[] = N_(
|
|
+ "Please enter a decimal value. "
|
|
+ "Fractions will not be accepted. "
|
|
+ "Use the <TAB> key to move from the input field to the buttons below it."),
|
|
+inputbox_instructions_hex[] = N_(
|
|
+ "Please enter a hexadecimal value. "
|
|
+ "Use the <TAB> key to move from the input field to the buttons below it."),
|
|
+inputbox_instructions_string[] = N_(
|
|
+ "Please enter a string value. "
|
|
+ "Use the <TAB> key to move from the input field to the buttons below it."),
|
|
+setmod_text[] = N_(
|
|
+ "This feature depends on another which has been configured as a module.\n"
|
|
+ "As a result, this feature will be built as a module."),
|
|
+load_config_text[] = N_(
|
|
+ "Enter the name of the configuration file you wish to load. "
|
|
+ "Accept the name shown to restore the configuration you "
|
|
+ "last retrieved. Leave blank to abort."),
|
|
+load_config_help[] = N_(
|
|
+ "\n"
|
|
+ "For various reasons, one may wish to keep several different\n"
|
|
+ "configurations available on a single machine.\n"
|
|
+ "\n"
|
|
+ "If you have saved a previous configuration in a file other than the\n"
|
|
+ "default one, entering its name here will allow you to modify that\n"
|
|
+ "configuration.\n"
|
|
+ "\n"
|
|
+ "If you are uncertain, then you have probably never used alternate\n"
|
|
+ "configuration files. You should therefore leave this blank to abort.\n"),
|
|
+save_config_text[] = N_(
|
|
+ "Enter a filename to which this configuration should be saved "
|
|
+ "as an alternate. Leave blank to abort."),
|
|
+save_config_help[] = N_(
|
|
+ "\n"
|
|
+ "For various reasons, one may wish to keep different configurations\n"
|
|
+ "available on a single machine.\n"
|
|
+ "\n"
|
|
+ "Entering a file name here will allow you to later retrieve, modify\n"
|
|
+ "and use the current configuration as an alternate to whatever\n"
|
|
+ "configuration options you have selected at that time.\n"
|
|
+ "\n"
|
|
+ "If you are uncertain what all this means then you should probably\n"
|
|
+ "leave this blank.\n"),
|
|
+search_help[] = N_(
|
|
+ "\n"
|
|
+ "Search for symbols and display their relations.\n"
|
|
+ "Regular expressions are allowed.\n"
|
|
+ "Example: search for \"^FOO\"\n"
|
|
+ "Result:\n"
|
|
+ "-----------------------------------------------------------------\n"
|
|
+ "Symbol: FOO [=m]\n"
|
|
+ "Type : tristate\n"
|
|
+ "Prompt: Foo bus is used to drive the bar HW\n"
|
|
+ " Location:\n"
|
|
+ " -> Bus options (PCI, PCMCIA, EISA, ISA)\n"
|
|
+ " -> PCI support (PCI [=y])\n"
|
|
+ "(1) -> PCI access mode (<choice> [=y])\n"
|
|
+ " Defined at drivers/pci/Kconfig:47\n"
|
|
+ " Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n"
|
|
+ " Selects: LIBCRC32\n"
|
|
+ " Selected by: BAR [=n]\n"
|
|
+ "-----------------------------------------------------------------\n"
|
|
+ "o The line 'Type:' shows the type of the configuration option for\n"
|
|
+ " this symbol (boolean, tristate, string, ...)\n"
|
|
+ "o The line 'Prompt:' shows the text used in the menu structure for\n"
|
|
+ " this symbol\n"
|
|
+ "o The 'Defined at' line tells at what file / line number the symbol\n"
|
|
+ " is defined\n"
|
|
+ "o The 'Depends on:' line tells what symbols need to be defined for\n"
|
|
+ " this symbol to be visible in the menu (selectable)\n"
|
|
+ "o The 'Location:' lines tells where in the menu structure this symbol\n"
|
|
+ " is located\n"
|
|
+ " A location followed by a [=y] indicates that this is a\n"
|
|
+ " selectable menu item - and the current value is displayed inside\n"
|
|
+ " brackets.\n"
|
|
+ " Press the key in the (#) prefix to jump directly to that\n"
|
|
+ " location. You will be returned to the current search results\n"
|
|
+ " after exiting this new menu.\n"
|
|
+ "o The 'Selects:' line tells what symbols will be automatically\n"
|
|
+ " selected if this symbol is selected (y or m)\n"
|
|
+ "o The 'Selected by' line tells what symbol has selected this symbol\n"
|
|
+ "\n"
|
|
+ "Only relevant lines are shown.\n"
|
|
+ "\n\n"
|
|
+ "Search examples:\n"
|
|
+ "Examples: USB => find all symbols containing USB\n"
|
|
+ " ^USB => find all symbols starting with USB\n"
|
|
+ " USB$ => find all symbols ending with USB\n"
|
|
+ "\n");
|
|
+
|
|
+static int indent;
|
|
+static struct menu *current_menu;
|
|
+static int child_count;
|
|
+static int single_menu_mode;
|
|
+static int show_all_options;
|
|
+static int save_and_exit;
|
|
+
|
|
+static void conf(struct menu *menu, struct menu *active_menu);
|
|
+static void conf_choice(struct menu *menu);
|
|
+static void conf_string(struct menu *menu);
|
|
+static void conf_load(void);
|
|
+static void conf_save(void);
|
|
+static int show_textbox_ext(const char *title, char *text, int r, int c,
|
|
+ int *keys, int *vscroll, int *hscroll,
|
|
+ update_text_fn update_text, void *data);
|
|
+static void show_textbox(const char *title, const char *text, int r, int c);
|
|
+static void show_helptext(const char *title, const char *text);
|
|
+static void show_help(struct menu *menu);
|
|
+
|
|
+static char filename[PATH_MAX+1];
|
|
+static void set_config_filename(const char *config_filename)
|
|
+{
|
|
+ static char menu_backtitle[PATH_MAX+128];
|
|
+ int size;
|
|
+
|
|
+ size = snprintf(menu_backtitle, sizeof(menu_backtitle),
|
|
+ "%s - %s", config_filename, rootmenu.prompt->text);
|
|
+ if (size >= sizeof(menu_backtitle))
|
|
+ menu_backtitle[sizeof(menu_backtitle)-1] = '\0';
|
|
+ set_dialog_backtitle(menu_backtitle);
|
|
+
|
|
+ size = snprintf(filename, sizeof(filename), "%s", config_filename);
|
|
+ if (size >= sizeof(filename))
|
|
+ filename[sizeof(filename)-1] = '\0';
|
|
+}
|
|
+
|
|
+struct subtitle_part {
|
|
+ struct list_head entries;
|
|
+ const char *text;
|
|
+};
|
|
+static LIST_HEAD(trail);
|
|
+
|
|
+static struct subtitle_list *subtitles;
|
|
+static void set_subtitle(void)
|
|
+{
|
|
+ struct subtitle_part *sp;
|
|
+ struct subtitle_list *pos, *tmp;
|
|
+
|
|
+ for (pos = subtitles; pos != NULL; pos = tmp) {
|
|
+ tmp = pos->next;
|
|
+ free(pos);
|
|
+ }
|
|
+
|
|
+ subtitles = NULL;
|
|
+ list_for_each_entry(sp, &trail, entries) {
|
|
+ if (sp->text) {
|
|
+ if (pos) {
|
|
+ pos->next = xcalloc(sizeof(*pos), 1);
|
|
+ pos = pos->next;
|
|
+ } else {
|
|
+ subtitles = pos = xcalloc(sizeof(*pos), 1);
|
|
+ }
|
|
+ pos->text = sp->text;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ set_dialog_subtitles(subtitles);
|
|
+}
|
|
+
|
|
+static void reset_subtitle(void)
|
|
+{
|
|
+ struct subtitle_list *pos, *tmp;
|
|
+
|
|
+ for (pos = subtitles; pos != NULL; pos = tmp) {
|
|
+ tmp = pos->next;
|
|
+ free(pos);
|
|
+ }
|
|
+ subtitles = NULL;
|
|
+ set_dialog_subtitles(subtitles);
|
|
+}
|
|
+
|
|
+struct search_data {
|
|
+ struct list_head *head;
|
|
+ struct menu **targets;
|
|
+ int *keys;
|
|
+};
|
|
+
|
|
+static void update_text(char *buf, size_t start, size_t end, void *_data)
|
|
+{
|
|
+ struct search_data *data = _data;
|
|
+ struct jump_key *pos;
|
|
+ int k = 0;
|
|
+
|
|
+ list_for_each_entry(pos, data->head, entries) {
|
|
+ if (pos->offset >= start && pos->offset < end) {
|
|
+ char header[4];
|
|
+
|
|
+ if (k < JUMP_NB) {
|
|
+ int key = '0' + (pos->index % JUMP_NB) + 1;
|
|
+
|
|
+ sprintf(header, "(%c)", key);
|
|
+ data->keys[k] = key;
|
|
+ data->targets[k] = pos->target;
|
|
+ k++;
|
|
+ } else {
|
|
+ sprintf(header, " ");
|
|
+ }
|
|
+
|
|
+ memcpy(buf + pos->offset, header, sizeof(header) - 1);
|
|
+ }
|
|
+ }
|
|
+ data->keys[k] = 0;
|
|
+}
|
|
+
|
|
+static void search_conf(void)
|
|
+{
|
|
+ struct symbol **sym_arr;
|
|
+ struct gstr res;
|
|
+ struct gstr title;
|
|
+ char *dialog_input;
|
|
+ int dres, vscroll = 0, hscroll = 0;
|
|
+ bool again;
|
|
+ struct gstr sttext;
|
|
+ struct subtitle_part stpart;
|
|
+
|
|
+ title = str_new();
|
|
+ str_printf( &title, _("Enter (sub)string or regexp to search for "
|
|
+ "(with or without \"%s\")"), CONFIG_);
|
|
+
|
|
+again:
|
|
+ dialog_clear();
|
|
+ dres = dialog_inputbox(_("Search Configuration Parameter"),
|
|
+ str_get(&title),
|
|
+ 10, 75, "");
|
|
+ switch (dres) {
|
|
+ case 0:
|
|
+ break;
|
|
+ case 1:
|
|
+ show_helptext(_("Search Configuration"), search_help);
|
|
+ goto again;
|
|
+ default:
|
|
+ str_free(&title);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ /* strip the prefix if necessary */
|
|
+ dialog_input = dialog_input_result;
|
|
+ if (strncasecmp(dialog_input_result, CONFIG_, strlen(CONFIG_)) == 0)
|
|
+ dialog_input += strlen(CONFIG_);
|
|
+
|
|
+ sttext = str_new();
|
|
+ str_printf(&sttext, "Search (%s)", dialog_input_result);
|
|
+ stpart.text = str_get(&sttext);
|
|
+ list_add_tail(&stpart.entries, &trail);
|
|
+
|
|
+ sym_arr = sym_re_search(dialog_input);
|
|
+ do {
|
|
+ LIST_HEAD(head);
|
|
+ struct menu *targets[JUMP_NB];
|
|
+ int keys[JUMP_NB + 1], i;
|
|
+ struct search_data data = {
|
|
+ .head = &head,
|
|
+ .targets = targets,
|
|
+ .keys = keys,
|
|
+ };
|
|
+ struct jump_key *pos, *tmp;
|
|
+
|
|
+ res = get_relations_str(sym_arr, &head);
|
|
+ set_subtitle();
|
|
+ dres = show_textbox_ext(_("Search Results"), (char *)
|
|
+ str_get(&res), 0, 0, keys, &vscroll,
|
|
+ &hscroll, &update_text, (void *)
|
|
+ &data);
|
|
+ again = false;
|
|
+ for (i = 0; i < JUMP_NB && keys[i]; i++)
|
|
+ if (dres == keys[i]) {
|
|
+ conf(targets[i]->parent, targets[i]);
|
|
+ again = true;
|
|
+ }
|
|
+ str_free(&res);
|
|
+ list_for_each_entry_safe(pos, tmp, &head, entries)
|
|
+ free(pos);
|
|
+ } while (again);
|
|
+ free(sym_arr);
|
|
+ str_free(&title);
|
|
+ list_del(trail.prev);
|
|
+ str_free(&sttext);
|
|
+}
|
|
+
|
|
+static void build_conf(struct menu *menu)
|
|
+{
|
|
+ struct symbol *sym;
|
|
+ struct property *prop;
|
|
+ struct menu *child;
|
|
+ int type, tmp, doint = 2;
|
|
+ tristate val;
|
|
+ char ch;
|
|
+ bool visible;
|
|
+
|
|
+ /*
|
|
+ * note: menu_is_visible() has side effect that it will
|
|
+ * recalc the value of the symbol.
|
|
+ */
|
|
+ visible = menu_is_visible(menu);
|
|
+ if (show_all_options && !menu_has_prompt(menu))
|
|
+ return;
|
|
+ else if (!show_all_options && !visible)
|
|
+ return;
|
|
+
|
|
+ sym = menu->sym;
|
|
+ prop = menu->prompt;
|
|
+ if (!sym) {
|
|
+ if (prop && menu != current_menu) {
|
|
+ const char *prompt = menu_get_prompt(menu);
|
|
+ switch (prop->type) {
|
|
+ case P_MENU:
|
|
+ child_count++;
|
|
+ prompt = _(prompt);
|
|
+ if (single_menu_mode) {
|
|
+ item_make("%s%*c%s",
|
|
+ menu->data ? "-->" : "++>",
|
|
+ indent + 1, ' ', prompt);
|
|
+ } else
|
|
+ item_make(" %*c%s %s",
|
|
+ indent + 1, ' ', prompt,
|
|
+ menu_is_empty(menu) ? "----" : "--->");
|
|
+ item_set_tag('m');
|
|
+ item_set_data(menu);
|
|
+ if (single_menu_mode && menu->data)
|
|
+ goto conf_childs;
|
|
+ return;
|
|
+ case P_COMMENT:
|
|
+ if (prompt) {
|
|
+ child_count++;
|
|
+ item_make(" %*c*** %s ***", indent + 1, ' ', _(prompt));
|
|
+ item_set_tag(':');
|
|
+ item_set_data(menu);
|
|
+ }
|
|
+ break;
|
|
+ default:
|
|
+ if (prompt) {
|
|
+ child_count++;
|
|
+ item_make("---%*c%s", indent + 1, ' ', _(prompt));
|
|
+ item_set_tag(':');
|
|
+ item_set_data(menu);
|
|
+ }
|
|
+ }
|
|
+ } else
|
|
+ doint = 0;
|
|
+ goto conf_childs;
|
|
+ }
|
|
+
|
|
+ type = sym_get_type(sym);
|
|
+ if (sym_is_choice(sym)) {
|
|
+ struct symbol *def_sym = sym_get_choice_value(sym);
|
|
+ struct menu *def_menu = NULL;
|
|
+
|
|
+ child_count++;
|
|
+ for (child = menu->list; child; child = child->next) {
|
|
+ if (menu_is_visible(child) && child->sym == def_sym)
|
|
+ def_menu = child;
|
|
+ }
|
|
+
|
|
+ val = sym_get_tristate_value(sym);
|
|
+ if (sym_is_changable(sym)) {
|
|
+ switch (type) {
|
|
+ case S_BOOLEAN:
|
|
+ item_make("[%c]", val == no ? ' ' : '*');
|
|
+ break;
|
|
+ case S_TRISTATE:
|
|
+ switch (val) {
|
|
+ case yes: ch = '*'; break;
|
|
+ case mod: ch = 'M'; break;
|
|
+ default: ch = ' '; break;
|
|
+ }
|
|
+ item_make("<%c>", ch);
|
|
+ break;
|
|
+ }
|
|
+ item_set_tag('t');
|
|
+ item_set_data(menu);
|
|
+ } else {
|
|
+ item_make(" ");
|
|
+ item_set_tag(def_menu ? 't' : ':');
|
|
+ item_set_data(menu);
|
|
+ }
|
|
+
|
|
+ item_add_str("%*c%s", indent + 1, ' ', _(menu_get_prompt(menu)));
|
|
+ if (val == yes) {
|
|
+ if (def_menu) {
|
|
+ item_add_str(" (%s)", _(menu_get_prompt(def_menu)));
|
|
+ item_add_str(" --->");
|
|
+ if (def_menu->list) {
|
|
+ indent += 2;
|
|
+ build_conf(def_menu);
|
|
+ indent -= 2;
|
|
+ }
|
|
+ }
|
|
+ return;
|
|
+ }
|
|
+ } else {
|
|
+ if (menu == current_menu) {
|
|
+ item_make("---%*c%s", indent + 1, ' ', _(menu_get_prompt(menu)));
|
|
+ item_set_tag(':');
|
|
+ item_set_data(menu);
|
|
+ goto conf_childs;
|
|
+ }
|
|
+ child_count++;
|
|
+ val = sym_get_tristate_value(sym);
|
|
+ if (sym_is_choice_value(sym) && val == yes) {
|
|
+ item_make(" ");
|
|
+ item_set_tag(':');
|
|
+ item_set_data(menu);
|
|
+ } else {
|
|
+ switch (type) {
|
|
+ case S_BOOLEAN:
|
|
+ if (sym_is_changable(sym))
|
|
+ item_make("[%c]", val == no ? ' ' : '*');
|
|
+ else
|
|
+ item_make("-%c-", val == no ? ' ' : '*');
|
|
+ item_set_tag('t');
|
|
+ item_set_data(menu);
|
|
+ break;
|
|
+ case S_TRISTATE:
|
|
+ switch (val) {
|
|
+ case yes: ch = '*'; break;
|
|
+ case mod: ch = 'M'; break;
|
|
+ default: ch = ' '; break;
|
|
+ }
|
|
+ if (sym_is_changable(sym)) {
|
|
+ if (sym->rev_dep.tri == mod)
|
|
+ item_make("{%c}", ch);
|
|
+ else
|
|
+ item_make("<%c>", ch);
|
|
+ } else
|
|
+ item_make("-%c-", ch);
|
|
+ item_set_tag('t');
|
|
+ item_set_data(menu);
|
|
+ break;
|
|
+ default:
|
|
+ tmp = 2 + strlen(sym_get_string_value(sym)); /* () = 2 */
|
|
+ item_make("(%s)", sym_get_string_value(sym));
|
|
+ tmp = indent - tmp + 4;
|
|
+ if (tmp < 0)
|
|
+ tmp = 0;
|
|
+ item_add_str("%*c%s%s", tmp, ' ', _(menu_get_prompt(menu)),
|
|
+ (sym_has_value(sym) || !sym_is_changable(sym)) ?
|
|
+ "" : _(" (NEW)"));
|
|
+ item_set_tag('s');
|
|
+ item_set_data(menu);
|
|
+ goto conf_childs;
|
|
+ }
|
|
+ }
|
|
+ item_add_str("%*c%s%s", indent + 1, ' ', _(menu_get_prompt(menu)),
|
|
+ (sym_has_value(sym) || !sym_is_changable(sym)) ?
|
|
+ "" : _(" (NEW)"));
|
|
+ if (menu->prompt->type == P_MENU) {
|
|
+ item_add_str(" %s", menu_is_empty(menu) ? "----" : "--->");
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+
|
|
+conf_childs:
|
|
+ indent += doint;
|
|
+ for (child = menu->list; child; child = child->next)
|
|
+ build_conf(child);
|
|
+ indent -= doint;
|
|
+}
|
|
+
|
|
+static void conf(struct menu *menu, struct menu *active_menu)
|
|
+{
|
|
+ struct menu *submenu;
|
|
+ const char *prompt = menu_get_prompt(menu);
|
|
+ struct subtitle_part stpart;
|
|
+ struct symbol *sym;
|
|
+ int res;
|
|
+ int s_scroll = 0;
|
|
+
|
|
+ if (menu != &rootmenu)
|
|
+ stpart.text = menu_get_prompt(menu);
|
|
+ else
|
|
+ stpart.text = NULL;
|
|
+ list_add_tail(&stpart.entries, &trail);
|
|
+
|
|
+ while (1) {
|
|
+ item_reset();
|
|
+ current_menu = menu;
|
|
+ build_conf(menu);
|
|
+ if (!child_count)
|
|
+ break;
|
|
+ set_subtitle();
|
|
+ dialog_clear();
|
|
+ res = dialog_menu(prompt ? _(prompt) : _("Main Menu"),
|
|
+ _(menu_instructions),
|
|
+ active_menu, &s_scroll);
|
|
+ if (res == 1 || res == KEY_ESC || res == -ERRDISPLAYTOOSMALL)
|
|
+ break;
|
|
+ if (item_count() != 0) {
|
|
+ if (!item_activate_selected())
|
|
+ continue;
|
|
+ if (!item_tag())
|
|
+ continue;
|
|
+ }
|
|
+ submenu = item_data();
|
|
+ active_menu = item_data();
|
|
+ if (submenu)
|
|
+ sym = submenu->sym;
|
|
+ else
|
|
+ sym = NULL;
|
|
+
|
|
+ switch (res) {
|
|
+ case 0:
|
|
+ switch (item_tag()) {
|
|
+ case 'm':
|
|
+ if (single_menu_mode)
|
|
+ submenu->data = (void *) (long) !submenu->data;
|
|
+ else
|
|
+ conf(submenu, NULL);
|
|
+ break;
|
|
+ case 't':
|
|
+ if (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)
|
|
+ conf_choice(submenu);
|
|
+ else if (submenu->prompt->type == P_MENU)
|
|
+ conf(submenu, NULL);
|
|
+ break;
|
|
+ case 's':
|
|
+ conf_string(submenu);
|
|
+ break;
|
|
+ }
|
|
+ break;
|
|
+ case 2:
|
|
+ if (sym)
|
|
+ show_help(submenu);
|
|
+ else {
|
|
+ reset_subtitle();
|
|
+ show_helptext(_("README"), _(mconf_readme));
|
|
+ }
|
|
+ break;
|
|
+ case 3:
|
|
+ reset_subtitle();
|
|
+ conf_save();
|
|
+ break;
|
|
+ case 4:
|
|
+ reset_subtitle();
|
|
+ conf_load();
|
|
+ break;
|
|
+ case 5:
|
|
+ if (item_is_tag('t')) {
|
|
+ if (sym_set_tristate_value(sym, yes))
|
|
+ break;
|
|
+ if (sym_set_tristate_value(sym, mod))
|
|
+ show_textbox(NULL, setmod_text, 6, 74);
|
|
+ }
|
|
+ break;
|
|
+ case 6:
|
|
+ if (item_is_tag('t'))
|
|
+ sym_set_tristate_value(sym, no);
|
|
+ break;
|
|
+ case 7:
|
|
+ if (item_is_tag('t'))
|
|
+ sym_set_tristate_value(sym, mod);
|
|
+ break;
|
|
+ case 8:
|
|
+ if (item_is_tag('t'))
|
|
+ sym_toggle_tristate_value(sym);
|
|
+ else if (item_is_tag('m'))
|
|
+ conf(submenu, NULL);
|
|
+ break;
|
|
+ case 9:
|
|
+ search_conf();
|
|
+ break;
|
|
+ case 10:
|
|
+ show_all_options = !show_all_options;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ list_del(trail.prev);
|
|
+}
|
|
+
|
|
+static int show_textbox_ext(const char *title, char *text, int r, int c, int
|
|
+ *keys, int *vscroll, int *hscroll, update_text_fn
|
|
+ update_text, void *data)
|
|
+{
|
|
+ dialog_clear();
|
|
+ return dialog_textbox(title, text, r, c, keys, vscroll, hscroll,
|
|
+ update_text, data);
|
|
+}
|
|
+
|
|
+static void show_textbox(const char *title, const char *text, int r, int c)
|
|
+{
|
|
+ show_textbox_ext(title, (char *) text, r, c, (int []) {0}, NULL, NULL,
|
|
+ NULL, NULL);
|
|
+}
|
|
+
|
|
+static void show_helptext(const char *title, const char *text)
|
|
+{
|
|
+ show_textbox(title, text, 0, 0);
|
|
+}
|
|
+
|
|
+static void conf_message_callback(const char *fmt, va_list ap)
|
|
+{
|
|
+ char buf[PATH_MAX+1];
|
|
+
|
|
+ vsnprintf(buf, sizeof(buf), fmt, ap);
|
|
+ if (save_and_exit)
|
|
+ printf("%s", buf);
|
|
+ else
|
|
+ show_textbox(NULL, buf, 6, 60);
|
|
+}
|
|
+
|
|
+static void show_help(struct menu *menu)
|
|
+{
|
|
+ struct gstr help = str_new();
|
|
+
|
|
+ help.max_width = getmaxx(stdscr) - 10;
|
|
+ menu_get_ext_help(menu, &help);
|
|
+
|
|
+ show_helptext(_(menu_get_prompt(menu)), str_get(&help));
|
|
+ str_free(&help);
|
|
+}
|
|
+
|
|
+static void conf_choice(struct menu *menu)
|
|
+{
|
|
+ const char *prompt = _(menu_get_prompt(menu));
|
|
+ struct menu *child;
|
|
+ struct symbol *active;
|
|
+
|
|
+ active = sym_get_choice_value(menu->sym);
|
|
+ while (1) {
|
|
+ int res;
|
|
+ int selected;
|
|
+ item_reset();
|
|
+
|
|
+ current_menu = menu;
|
|
+ for (child = menu->list; child; child = child->next) {
|
|
+ if (!menu_is_visible(child))
|
|
+ continue;
|
|
+ if (child->sym)
|
|
+ item_make("%s", _(menu_get_prompt(child)));
|
|
+ else {
|
|
+ item_make("*** %s ***", _(menu_get_prompt(child)));
|
|
+ item_set_tag(':');
|
|
+ }
|
|
+ item_set_data(child);
|
|
+ if (child->sym == active)
|
|
+ item_set_selected(1);
|
|
+ if (child->sym == sym_get_choice_value(menu->sym))
|
|
+ item_set_tag('X');
|
|
+ }
|
|
+ dialog_clear();
|
|
+ res = dialog_checklist(prompt ? _(prompt) : _("Main Menu"),
|
|
+ _(radiolist_instructions),
|
|
+ MENUBOX_HEIGTH_MIN,
|
|
+ MENUBOX_WIDTH_MIN,
|
|
+ CHECKLIST_HEIGTH_MIN);
|
|
+ selected = item_activate_selected();
|
|
+ switch (res) {
|
|
+ case 0:
|
|
+ if (selected) {
|
|
+ child = item_data();
|
|
+ if (!child->sym)
|
|
+ break;
|
|
+
|
|
+ sym_set_tristate_value(child->sym, yes);
|
|
+ }
|
|
+ return;
|
|
+ case 1:
|
|
+ if (selected) {
|
|
+ child = item_data();
|
|
+ show_help(child);
|
|
+ active = child->sym;
|
|
+ } else
|
|
+ show_help(menu);
|
|
+ break;
|
|
+ case KEY_ESC:
|
|
+ return;
|
|
+ case -ERRDISPLAYTOOSMALL:
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+static void conf_string(struct menu *menu)
|
|
+{
|
|
+ const char *prompt = menu_get_prompt(menu);
|
|
+
|
|
+ while (1) {
|
|
+ int res;
|
|
+ const char *heading;
|
|
+
|
|
+ switch (sym_get_type(menu->sym)) {
|
|
+ case S_INT:
|
|
+ heading = _(inputbox_instructions_int);
|
|
+ break;
|
|
+ case S_HEX:
|
|
+ heading = _(inputbox_instructions_hex);
|
|
+ break;
|
|
+ case S_STRING:
|
|
+ heading = _(inputbox_instructions_string);
|
|
+ break;
|
|
+ default:
|
|
+ heading = _("Internal mconf error!");
|
|
+ }
|
|
+ dialog_clear();
|
|
+ res = dialog_inputbox(prompt ? _(prompt) : _("Main Menu"),
|
|
+ heading, 10, 75,
|
|
+ sym_get_string_value(menu->sym));
|
|
+ switch (res) {
|
|
+ case 0:
|
|
+ if (sym_set_string_value(menu->sym, dialog_input_result))
|
|
+ return;
|
|
+ show_textbox(NULL, _("You have made an invalid entry."), 5, 43);
|
|
+ break;
|
|
+ case 1:
|
|
+ show_help(menu);
|
|
+ break;
|
|
+ case KEY_ESC:
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+static void conf_load(void)
|
|
+{
|
|
+
|
|
+ while (1) {
|
|
+ int res;
|
|
+ dialog_clear();
|
|
+ res = dialog_inputbox(NULL, load_config_text,
|
|
+ 11, 55, filename);
|
|
+ switch(res) {
|
|
+ case 0:
|
|
+ if (!dialog_input_result[0])
|
|
+ return;
|
|
+ if (!conf_read(dialog_input_result)) {
|
|
+ set_config_filename(dialog_input_result);
|
|
+ sym_set_change_count(1);
|
|
+ return;
|
|
+ }
|
|
+ show_textbox(NULL, _("File does not exist!"), 5, 38);
|
|
+ break;
|
|
+ case 1:
|
|
+ show_helptext(_("Load Alternate Configuration"), load_config_help);
|
|
+ break;
|
|
+ case KEY_ESC:
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+static void conf_save(void)
|
|
+{
|
|
+ while (1) {
|
|
+ int res;
|
|
+ dialog_clear();
|
|
+ res = dialog_inputbox(NULL, save_config_text,
|
|
+ 11, 55, filename);
|
|
+ switch(res) {
|
|
+ case 0:
|
|
+ if (!dialog_input_result[0])
|
|
+ return;
|
|
+ if (!conf_write(dialog_input_result)) {
|
|
+ set_config_filename(dialog_input_result);
|
|
+ return;
|
|
+ }
|
|
+ show_textbox(NULL, _("Can't create file! Probably a nonexistent directory."), 5, 60);
|
|
+ break;
|
|
+ case 1:
|
|
+ show_helptext(_("Save Alternate Configuration"), save_config_help);
|
|
+ break;
|
|
+ case KEY_ESC:
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+static int handle_exit(void)
|
|
+{
|
|
+ int res;
|
|
+
|
|
+ save_and_exit = 1;
|
|
+ reset_subtitle();
|
|
+ dialog_clear();
|
|
+ if (conf_get_changed())
|
|
+ res = dialog_yesno(NULL,
|
|
+ _("Do you wish to save your new configuration?\n"
|
|
+ "(Press <ESC><ESC> to continue kernel configuration.)"),
|
|
+ 6, 60);
|
|
+ else
|
|
+ res = -1;
|
|
+
|
|
+ end_dialog(saved_x, saved_y);
|
|
+
|
|
+ switch (res) {
|
|
+ case 0:
|
|
+ if (conf_write(filename)) {
|
|
+ fprintf(stderr, _("\n\n"
|
|
+ "Error while writing of the configuration.\n"
|
|
+ "Your configuration changes were NOT saved."
|
|
+ "\n\n"));
|
|
+ return 1;
|
|
+ }
|
|
+ /* fall through */
|
|
+ case -1:
|
|
+ printf(_("\n\n"
|
|
+ "*** End of the configuration.\n"
|
|
+ "*** Execute 'make' to start the build or try 'make help'."
|
|
+ "\n\n"));
|
|
+ res = 0;
|
|
+ break;
|
|
+ default:
|
|
+ fprintf(stderr, _("\n\n"
|
|
+ "Your configuration changes were NOT saved."
|
|
+ "\n\n"));
|
|
+ if (res != KEY_ESC)
|
|
+ res = 0;
|
|
+ }
|
|
+
|
|
+ return res;
|
|
+}
|
|
+
|
|
+static void sig_handler(int signo)
|
|
+{
|
|
+ exit(handle_exit());
|
|
+}
|
|
+
|
|
+int main(int ac, char **av)
|
|
+{
|
|
+ char *mode;
|
|
+ int res;
|
|
+
|
|
+ setlocale(LC_ALL, "");
|
|
+ bindtextdomain(PACKAGE, LOCALEDIR);
|
|
+ textdomain(PACKAGE);
|
|
+
|
|
+ signal(SIGINT, sig_handler);
|
|
+
|
|
+ conf_parse(av[1]);
|
|
+ conf_read(NULL);
|
|
+
|
|
+ mode = getenv("MENUCONFIG_MODE");
|
|
+ if (mode) {
|
|
+ if (!strcasecmp(mode, "single_menu"))
|
|
+ single_menu_mode = 1;
|
|
+ }
|
|
+
|
|
+ if (init_dialog(NULL)) {
|
|
+ fprintf(stderr, N_("Your display is too small to run Menuconfig!\n"));
|
|
+ fprintf(stderr, N_("It must be at least 19 lines by 80 columns.\n"));
|
|
+ return 1;
|
|
+ }
|
|
+
|
|
+ set_config_filename(conf_get_configname());
|
|
+ conf_set_message_callback(conf_message_callback);
|
|
+ do {
|
|
+ conf(&rootmenu, NULL);
|
|
+ res = handle_exit();
|
|
+ } while (res == KEY_ESC);
|
|
+
|
|
+ return res;
|
|
+}
|
|
diff --git a/scripts/kconfig/merge_config.sh b/scripts/kconfig/merge_config.sh
|
|
new file mode 100755
|
|
index 0000000..81b0c61
|
|
--- /dev/null
|
|
+++ b/scripts/kconfig/merge_config.sh
|
|
@@ -0,0 +1,150 @@
|
|
+#!/bin/sh
|
|
+# merge_config.sh - Takes a list of config fragment values, and merges
|
|
+# them one by one. Provides warnings on overridden values, and specified
|
|
+# values that did not make it to the resulting .config file (due to missed
|
|
+# dependencies or config symbol removal).
|
|
+#
|
|
+# Portions reused from kconf_check and generate_cfg:
|
|
+# http://git.yoctoproject.org/cgit/cgit.cgi/yocto-kernel-tools/tree/tools/kconf_check
|
|
+# http://git.yoctoproject.org/cgit/cgit.cgi/yocto-kernel-tools/tree/tools/generate_cfg
|
|
+#
|
|
+# Copyright (c) 2009-2010 Wind River Systems, Inc.
|
|
+# Copyright 2011 Linaro
|
|
+#
|
|
+# This program is free software; you can redistribute it and/or modify
|
|
+# it under the terms of the GNU General Public License version 2 as
|
|
+# published by the Free Software Foundation.
|
|
+#
|
|
+# This program is distributed in the hope that it will be useful,
|
|
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
+# See the GNU General Public License for more details.
|
|
+
|
|
+clean_up() {
|
|
+ rm -f $TMP_FILE
|
|
+ exit
|
|
+}
|
|
+trap clean_up HUP INT TERM
|
|
+
|
|
+usage() {
|
|
+ echo "Usage: $0 [OPTIONS] [CONFIG [...]]"
|
|
+ echo " -h display this help text"
|
|
+ echo " -m only merge the fragments, do not execute the make command"
|
|
+ echo " -n use allnoconfig instead of alldefconfig"
|
|
+ echo " -r list redundant entries when merging fragments"
|
|
+ echo " -O dir to put generated output files"
|
|
+}
|
|
+
|
|
+MAKE=true
|
|
+ALLTARGET=alldefconfig
|
|
+WARNREDUN=false
|
|
+OUTPUT=.
|
|
+
|
|
+while true; do
|
|
+ case $1 in
|
|
+ "-n")
|
|
+ ALLTARGET=allnoconfig
|
|
+ shift
|
|
+ continue
|
|
+ ;;
|
|
+ "-m")
|
|
+ MAKE=false
|
|
+ shift
|
|
+ continue
|
|
+ ;;
|
|
+ "-h")
|
|
+ usage
|
|
+ exit
|
|
+ ;;
|
|
+ "-r")
|
|
+ WARNREDUN=true
|
|
+ shift
|
|
+ continue
|
|
+ ;;
|
|
+ "-O")
|
|
+ if [ -d $2 ];then
|
|
+ OUTPUT=$(echo $2 | sed 's/\/*$//')
|
|
+ else
|
|
+ echo "output directory $2 does not exist" 1>&2
|
|
+ exit 1
|
|
+ fi
|
|
+ shift 2
|
|
+ continue
|
|
+ ;;
|
|
+ *)
|
|
+ break
|
|
+ ;;
|
|
+ esac
|
|
+done
|
|
+
|
|
+INITFILE=$1
|
|
+shift;
|
|
+
|
|
+MERGE_LIST=$*
|
|
+SED_CONFIG_EXP="s/^\(# \)\{0,1\}\(CONFIG_[a-zA-Z0-9_]*\)[= ].*/\2/p"
|
|
+TMP_FILE=$(mktemp ./.tmp.config.XXXXXXXXXX)
|
|
+
|
|
+echo "Using $INITFILE as base"
|
|
+cat $INITFILE > $TMP_FILE
|
|
+
|
|
+# Merge files, printing warnings on overrided values
|
|
+for MERGE_FILE in $MERGE_LIST ; do
|
|
+ echo "Merging $MERGE_FILE"
|
|
+ CFG_LIST=$(sed -n "$SED_CONFIG_EXP" $MERGE_FILE)
|
|
+
|
|
+ for CFG in $CFG_LIST ; do
|
|
+ grep -q -w $CFG $TMP_FILE
|
|
+ if [ $? -eq 0 ] ; then
|
|
+ PREV_VAL=$(grep -w $CFG $TMP_FILE)
|
|
+ NEW_VAL=$(grep -w $CFG $MERGE_FILE)
|
|
+ if [ "x$PREV_VAL" != "x$NEW_VAL" ] ; then
|
|
+ echo Value of $CFG is redefined by fragment $MERGE_FILE:
|
|
+ echo Previous value: $PREV_VAL
|
|
+ echo New value: $NEW_VAL
|
|
+ echo
|
|
+ elif [ "$WARNREDUN" = "true" ]; then
|
|
+ echo Value of $CFG is redundant by fragment $MERGE_FILE:
|
|
+ fi
|
|
+ sed -i "/$CFG[ =]/d" $TMP_FILE
|
|
+ fi
|
|
+ done
|
|
+ cat $MERGE_FILE >> $TMP_FILE
|
|
+done
|
|
+
|
|
+if [ "$MAKE" = "false" ]; then
|
|
+ cp $TMP_FILE $OUTPUT/.config
|
|
+ echo "#"
|
|
+ echo "# merged configuration written to $OUTPUT/.config (needs make)"
|
|
+ echo "#"
|
|
+ clean_up
|
|
+ exit
|
|
+fi
|
|
+
|
|
+# If we have an output dir, setup the O= argument, otherwise leave
|
|
+# it blank, since O=. will create an unnecessary ./source softlink
|
|
+OUTPUT_ARG=""
|
|
+if [ "$OUTPUT" != "." ] ; then
|
|
+ OUTPUT_ARG="O=$OUTPUT"
|
|
+fi
|
|
+
|
|
+
|
|
+# Use the merged file as the starting point for:
|
|
+# alldefconfig: Fills in any missing symbols with Kconfig default
|
|
+# allnoconfig: Fills in any missing symbols with # CONFIG_* is not set
|
|
+make KCONFIG_ALLCONFIG=$TMP_FILE $OUTPUT_ARG $ALLTARGET
|
|
+
|
|
+
|
|
+# Check all specified config values took (might have missed-dependency issues)
|
|
+for CFG in $(sed -n "$SED_CONFIG_EXP" $TMP_FILE); do
|
|
+
|
|
+ REQUESTED_VAL=$(grep -w -e "$CFG" $TMP_FILE)
|
|
+ ACTUAL_VAL=$(grep -w -e "$CFG" $OUTPUT/.config)
|
|
+ if [ "x$REQUESTED_VAL" != "x$ACTUAL_VAL" ] ; then
|
|
+ echo "Value requested for $CFG not in final .config"
|
|
+ echo "Requested value: $REQUESTED_VAL"
|
|
+ echo "Actual value: $ACTUAL_VAL"
|
|
+ echo ""
|
|
+ fi
|
|
+done
|
|
+
|
|
+clean_up
|
|
diff --git a/scripts/kconfig/nconf.c b/scripts/kconfig/nconf.c
|
|
new file mode 100644
|
|
index 0000000..984489e
|
|
--- /dev/null
|
|
+++ b/scripts/kconfig/nconf.c
|
|
@@ -0,0 +1,1556 @@
|
|
+/*
|
|
+ * Copyright (C) 2008 Nir Tzachar <nir.tzachar@gmail.com?
|
|
+ * Released under the terms of the GNU GPL v2.0.
|
|
+ *
|
|
+ * Derived from menuconfig.
|
|
+ *
|
|
+ */
|
|
+#define _GNU_SOURCE
|
|
+#include <string.h>
|
|
+#include <stdlib.h>
|
|
+
|
|
+#include "lkc.h"
|
|
+#include "nconf.h"
|
|
+#include <ctype.h>
|
|
+
|
|
+static const char nconf_global_help[] = N_(
|
|
+"Help windows\n"
|
|
+"------------\n"
|
|
+"o Global help: Unless in a data entry window, pressing <F1> will give \n"
|
|
+" you the global help window, which you are just reading.\n"
|
|
+"\n"
|
|
+"o A short version of the global help is available by pressing <F3>.\n"
|
|
+"\n"
|
|
+"o Local help: To get help related to the current menu entry, use any\n"
|
|
+" of <?> <h>, or if in a data entry window then press <F1>.\n"
|
|
+"\n"
|
|
+"\n"
|
|
+"Menu entries\n"
|
|
+"------------\n"
|
|
+"This interface lets you select features and parameters for the kernel\n"
|
|
+"build. Kernel features can either be built-in, modularized, or removed.\n"
|
|
+"Parameters must be entered as text or decimal or hexadecimal numbers.\n"
|
|
+"\n"
|
|
+"Menu entries beginning with following braces represent features that\n"
|
|
+" [ ] can be built in or removed\n"
|
|
+" < > can be built in, modularized or removed\n"
|
|
+" { } can be built in or modularized, are selected by another feature\n"
|
|
+" - - are selected by another feature\n"
|
|
+" XXX cannot be selected. Symbol Info <F2> tells you why.\n"
|
|
+"*, M or whitespace inside braces means to build in, build as a module\n"
|
|
+"or to exclude the feature respectively.\n"
|
|
+"\n"
|
|
+"To change any of these features, highlight it with the movement keys\n"
|
|
+"listed below and press <y> to build it in, <m> to make it a module or\n"
|
|
+"<n> to remove it. You may press the <Space> key to cycle through the\n"
|
|
+"available options.\n"
|
|
+"\n"
|
|
+"A trailing \"--->\" designates a submenu, a trailing \"----\" an\n"
|
|
+"empty submenu.\n"
|
|
+"\n"
|
|
+"Menu navigation keys\n"
|
|
+"----------------------------------------------------------------------\n"
|
|
+"Linewise up <Up>\n"
|
|
+"Linewise down <Down>\n"
|
|
+"Pagewise up <Page Up>\n"
|
|
+"Pagewise down <Page Down>\n"
|
|
+"First entry <Home>\n"
|
|
+"Last entry <End>\n"
|
|
+"Enter a submenu <Right> <Enter>\n"
|
|
+"Go back to parent menu <Left> <Esc> <F5>\n"
|
|
+"Close a help window <Enter> <Esc> <F5>\n"
|
|
+"Close entry window, apply <Enter>\n"
|
|
+"Close entry window, forget <Esc> <F5>\n"
|
|
+"Start incremental, case-insensitive search for STRING in menu entries,\n"
|
|
+" no regex support, STRING is displayed in upper left corner\n"
|
|
+" </>STRING\n"
|
|
+" Remove last character <Backspace>\n"
|
|
+" Jump to next hit <Down>\n"
|
|
+" Jump to previous hit <Up>\n"
|
|
+"Exit menu search mode </> <Esc>\n"
|
|
+"Search for configuration variables with or without leading CONFIG_\n"
|
|
+" <F8>RegExpr<Enter>\n"
|
|
+"Verbose search help <F8><F1>\n"
|
|
+"----------------------------------------------------------------------\n"
|
|
+"\n"
|
|
+"Unless in a data entry window, key <1> may be used instead of <F1>,\n"
|
|
+"<2> instead of <F2>, etc.\n"
|
|
+"\n"
|
|
+"\n"
|
|
+"Radiolist (Choice list)\n"
|
|
+"-----------------------\n"
|
|
+"Use the movement keys listed above to select the option you wish to set\n"
|
|
+"and press <Space>.\n"
|
|
+"\n"
|
|
+"\n"
|
|
+"Data entry\n"
|
|
+"----------\n"
|
|
+"Enter the requested information and press <Enter>. Hexadecimal values\n"
|
|
+"may be entered without the \"0x\" prefix.\n"
|
|
+"\n"
|
|
+"\n"
|
|
+"Text Box (Help Window)\n"
|
|
+"----------------------\n"
|
|
+"Use movement keys as listed in table above.\n"
|
|
+"\n"
|
|
+"Press any of <Enter> <Esc> <q> <F5> <F9> to exit.\n"
|
|
+"\n"
|
|
+"\n"
|
|
+"Alternate configuration files\n"
|
|
+"-----------------------------\n"
|
|
+"nconfig supports switching between different configurations.\n"
|
|
+"Press <F6> to save your current configuration. Press <F7> and enter\n"
|
|
+"a file name to load a previously saved configuration.\n"
|
|
+"\n"
|
|
+"\n"
|
|
+"Terminal configuration\n"
|
|
+"----------------------\n"
|
|
+"If you use nconfig in a xterm window, make sure your TERM environment\n"
|
|
+"variable specifies a terminal configuration which supports at least\n"
|
|
+"16 colors. Otherwise nconfig will look rather bad.\n"
|
|
+"\n"
|
|
+"If the \"stty size\" command reports the current terminalsize correctly,\n"
|
|
+"nconfig will adapt to sizes larger than the traditional 80x25 \"standard\"\n"
|
|
+"and display longer menus properly.\n"
|
|
+"\n"
|
|
+"\n"
|
|
+"Single menu mode\n"
|
|
+"----------------\n"
|
|
+"If you prefer to have all of the menu entries listed in a single menu,\n"
|
|
+"rather than the default multimenu hierarchy, run nconfig with\n"
|
|
+"NCONFIG_MODE environment variable set to single_menu. Example:\n"
|
|
+"\n"
|
|
+"make NCONFIG_MODE=single_menu nconfig\n"
|
|
+"\n"
|
|
+"<Enter> will then unfold the appropriate category, or fold it if it\n"
|
|
+"is already unfolded. Folded menu entries will be designated by a\n"
|
|
+"leading \"++>\" and unfolded entries by a leading \"-->\".\n"
|
|
+"\n"
|
|
+"Note that this mode can eventually be a little more CPU expensive than\n"
|
|
+"the default mode, especially with a larger number of unfolded submenus.\n"
|
|
+"\n"),
|
|
+menu_no_f_instructions[] = N_(
|
|
+"Legend: [*] built-in [ ] excluded <M> module < > module capable.\n"
|
|
+"Submenus are designated by a trailing \"--->\", empty ones by \"----\".\n"
|
|
+"\n"
|
|
+"Use the following keys to navigate the menus:\n"
|
|
+"Move up or down with <Up> and <Down>.\n"
|
|
+"Enter a submenu with <Enter> or <Right>.\n"
|
|
+"Exit a submenu to its parent menu with <Esc> or <Left>.\n"
|
|
+"Pressing <y> includes, <n> excludes, <m> modularizes features.\n"
|
|
+"Pressing <Space> cycles through the available options.\n"
|
|
+"To search for menu entries press </>.\n"
|
|
+"<Esc> always leaves the current window.\n"
|
|
+"\n"
|
|
+"You do not have function keys support.\n"
|
|
+"Press <1> instead of <F1>, <2> instead of <F2>, etc.\n"
|
|
+"For verbose global help use key <1>.\n"
|
|
+"For help related to the current menu entry press <?> or <h>.\n"),
|
|
+menu_instructions[] = N_(
|
|
+"Legend: [*] built-in [ ] excluded <M> module < > module capable.\n"
|
|
+"Submenus are designated by a trailing \"--->\", empty ones by \"----\".\n"
|
|
+"\n"
|
|
+"Use the following keys to navigate the menus:\n"
|
|
+"Move up or down with <Up> or <Down>.\n"
|
|
+"Enter a submenu with <Enter> or <Right>.\n"
|
|
+"Exit a submenu to its parent menu with <Esc> or <Left>.\n"
|
|
+"Pressing <y> includes, <n> excludes, <m> modularizes features.\n"
|
|
+"Pressing <Space> cycles through the available options.\n"
|
|
+"To search for menu entries press </>.\n"
|
|
+"<Esc> always leaves the current window.\n"
|
|
+"\n"
|
|
+"Pressing <1> may be used instead of <F1>, <2> instead of <F2>, etc.\n"
|
|
+"For verbose global help press <F1>.\n"
|
|
+"For help related to the current menu entry press <?> or <h>.\n"),
|
|
+radiolist_instructions[] = N_(
|
|
+"Press <Up>, <Down>, <Home> or <End> to navigate a radiolist, select\n"
|
|
+"with <Space>.\n"
|
|
+"For help related to the current entry press <?> or <h>.\n"
|
|
+"For global help press <F1>.\n"),
|
|
+inputbox_instructions_int[] = N_(
|
|
+"Please enter a decimal value.\n"
|
|
+"Fractions will not be accepted.\n"
|
|
+"Press <Enter> to apply, <Esc> to cancel."),
|
|
+inputbox_instructions_hex[] = N_(
|
|
+"Please enter a hexadecimal value.\n"
|
|
+"Press <Enter> to apply, <Esc> to cancel."),
|
|
+inputbox_instructions_string[] = N_(
|
|
+"Please enter a string value.\n"
|
|
+"Press <Enter> to apply, <Esc> to cancel."),
|
|
+setmod_text[] = N_(
|
|
+"This feature depends on another feature which has been configured as a\n"
|
|
+"module. As a result, the current feature will be built as a module too."),
|
|
+load_config_text[] = N_(
|
|
+"Enter the name of the configuration file you wish to load.\n"
|
|
+"Accept the name shown to restore the configuration you last\n"
|
|
+"retrieved. Leave empty to abort."),
|
|
+load_config_help[] = N_(
|
|
+"For various reasons, one may wish to keep several different\n"
|
|
+"configurations available on a single machine.\n"
|
|
+"\n"
|
|
+"If you have saved a previous configuration in a file other than the\n"
|
|
+"default one, entering its name here will allow you to load and modify\n"
|
|
+"that configuration.\n"
|
|
+"\n"
|
|
+"Leave empty to abort.\n"),
|
|
+save_config_text[] = N_(
|
|
+"Enter a filename to which this configuration should be saved\n"
|
|
+"as an alternate. Leave empty to abort."),
|
|
+save_config_help[] = N_(
|
|
+"For various reasons, one may wish to keep several different\n"
|
|
+"configurations available on a single machine.\n"
|
|
+"\n"
|
|
+"Entering a file name here will allow you to later retrieve, modify\n"
|
|
+"and use the current configuration as an alternate to whatever\n"
|
|
+"configuration options you have selected at that time.\n"
|
|
+"\n"
|
|
+"Leave empty to abort.\n"),
|
|
+search_help[] = N_(
|
|
+"Search for symbols (configuration variable names CONFIG_*) and display\n"
|
|
+"their relations. Regular expressions are supported.\n"
|
|
+"Example: Search for \"^FOO\".\n"
|
|
+"Result:\n"
|
|
+"-----------------------------------------------------------------\n"
|
|
+"Symbol: FOO [ = m]\n"
|
|
+"Prompt: Foo bus is used to drive the bar HW\n"
|
|
+"Defined at drivers/pci/Kconfig:47\n"
|
|
+"Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n"
|
|
+"Location:\n"
|
|
+" -> Bus options (PCI, PCMCIA, EISA, ISA)\n"
|
|
+" -> PCI support (PCI [ = y])\n"
|
|
+" -> PCI access mode (<choice> [ = y])\n"
|
|
+"Selects: LIBCRC32\n"
|
|
+"Selected by: BAR\n"
|
|
+"-----------------------------------------------------------------\n"
|
|
+"o The line 'Prompt:' shows the text displayed for this symbol in\n"
|
|
+" the menu hierarchy.\n"
|
|
+"o The 'Defined at' line tells at what file / line number the symbol is\n"
|
|
+" defined.\n"
|
|
+"o The 'Depends on:' line lists symbols that need to be defined for\n"
|
|
+" this symbol to be visible and selectable in the menu.\n"
|
|
+"o The 'Location:' lines tell, where in the menu structure this symbol\n"
|
|
+" is located. A location followed by a [ = y] indicates that this is\n"
|
|
+" a selectable menu item, and the current value is displayed inside\n"
|
|
+" brackets.\n"
|
|
+"o The 'Selects:' line tells, what symbol will be automatically selected\n"
|
|
+" if this symbol is selected (y or m).\n"
|
|
+"o The 'Selected by' line tells what symbol has selected this symbol.\n"
|
|
+"\n"
|
|
+"Only relevant lines are shown.\n"
|
|
+"\n\n"
|
|
+"Search examples:\n"
|
|
+"USB => find all symbols containing USB\n"
|
|
+"^USB => find all symbols starting with USB\n"
|
|
+"USB$ => find all symbols ending with USB\n"
|
|
+"\n");
|
|
+
|
|
+struct mitem {
|
|
+ char str[256];
|
|
+ char tag;
|
|
+ void *usrptr;
|
|
+ int is_visible;
|
|
+};
|
|
+
|
|
+#define MAX_MENU_ITEMS 4096
|
|
+static int show_all_items;
|
|
+static int indent;
|
|
+static struct menu *current_menu;
|
|
+static int child_count;
|
|
+static int single_menu_mode;
|
|
+/* the window in which all information appears */
|
|
+static WINDOW *main_window;
|
|
+/* the largest size of the menu window */
|
|
+static int mwin_max_lines;
|
|
+static int mwin_max_cols;
|
|
+/* the window in which we show option buttons */
|
|
+static MENU *curses_menu;
|
|
+static ITEM *curses_menu_items[MAX_MENU_ITEMS];
|
|
+static struct mitem k_menu_items[MAX_MENU_ITEMS];
|
|
+static int items_num;
|
|
+static int global_exit;
|
|
+/* the currently selected button */
|
|
+const char *current_instructions = menu_instructions;
|
|
+
|
|
+static char *dialog_input_result;
|
|
+static int dialog_input_result_len;
|
|
+
|
|
+static void conf(struct menu *menu);
|
|
+static void conf_choice(struct menu *menu);
|
|
+static void conf_string(struct menu *menu);
|
|
+static void conf_load(void);
|
|
+static void conf_save(void);
|
|
+static void show_help(struct menu *menu);
|
|
+static int do_exit(void);
|
|
+static void setup_windows(void);
|
|
+static void search_conf(void);
|
|
+
|
|
+typedef void (*function_key_handler_t)(int *key, struct menu *menu);
|
|
+static void handle_f1(int *key, struct menu *current_item);
|
|
+static void handle_f2(int *key, struct menu *current_item);
|
|
+static void handle_f3(int *key, struct menu *current_item);
|
|
+static void handle_f4(int *key, struct menu *current_item);
|
|
+static void handle_f5(int *key, struct menu *current_item);
|
|
+static void handle_f6(int *key, struct menu *current_item);
|
|
+static void handle_f7(int *key, struct menu *current_item);
|
|
+static void handle_f8(int *key, struct menu *current_item);
|
|
+static void handle_f9(int *key, struct menu *current_item);
|
|
+
|
|
+struct function_keys {
|
|
+ const char *key_str;
|
|
+ const char *func;
|
|
+ function_key key;
|
|
+ function_key_handler_t handler;
|
|
+};
|
|
+
|
|
+static const int function_keys_num = 9;
|
|
+struct function_keys function_keys[] = {
|
|
+ {
|
|
+ .key_str = "F1",
|
|
+ .func = "Help",
|
|
+ .key = F_HELP,
|
|
+ .handler = handle_f1,
|
|
+ },
|
|
+ {
|
|
+ .key_str = "F2",
|
|
+ .func = "SymInfo",
|
|
+ .key = F_SYMBOL,
|
|
+ .handler = handle_f2,
|
|
+ },
|
|
+ {
|
|
+ .key_str = "F3",
|
|
+ .func = "Help 2",
|
|
+ .key = F_INSTS,
|
|
+ .handler = handle_f3,
|
|
+ },
|
|
+ {
|
|
+ .key_str = "F4",
|
|
+ .func = "ShowAll",
|
|
+ .key = F_CONF,
|
|
+ .handler = handle_f4,
|
|
+ },
|
|
+ {
|
|
+ .key_str = "F5",
|
|
+ .func = "Back",
|
|
+ .key = F_BACK,
|
|
+ .handler = handle_f5,
|
|
+ },
|
|
+ {
|
|
+ .key_str = "F6",
|
|
+ .func = "Save",
|
|
+ .key = F_SAVE,
|
|
+ .handler = handle_f6,
|
|
+ },
|
|
+ {
|
|
+ .key_str = "F7",
|
|
+ .func = "Load",
|
|
+ .key = F_LOAD,
|
|
+ .handler = handle_f7,
|
|
+ },
|
|
+ {
|
|
+ .key_str = "F8",
|
|
+ .func = "SymSearch",
|
|
+ .key = F_SEARCH,
|
|
+ .handler = handle_f8,
|
|
+ },
|
|
+ {
|
|
+ .key_str = "F9",
|
|
+ .func = "Exit",
|
|
+ .key = F_EXIT,
|
|
+ .handler = handle_f9,
|
|
+ },
|
|
+};
|
|
+
|
|
+static void print_function_line(void)
|
|
+{
|
|
+ int i;
|
|
+ int offset = 1;
|
|
+ const int skip = 1;
|
|
+ int lines = getmaxy(stdscr);
|
|
+
|
|
+ for (i = 0; i < function_keys_num; i++) {
|
|
+ (void) wattrset(main_window, attributes[FUNCTION_HIGHLIGHT]);
|
|
+ mvwprintw(main_window, lines-3, offset,
|
|
+ "%s",
|
|
+ function_keys[i].key_str);
|
|
+ (void) wattrset(main_window, attributes[FUNCTION_TEXT]);
|
|
+ offset += strlen(function_keys[i].key_str);
|
|
+ mvwprintw(main_window, lines-3,
|
|
+ offset, "%s",
|
|
+ function_keys[i].func);
|
|
+ offset += strlen(function_keys[i].func) + skip;
|
|
+ }
|
|
+ (void) wattrset(main_window, attributes[NORMAL]);
|
|
+}
|
|
+
|
|
+/* help */
|
|
+static void handle_f1(int *key, struct menu *current_item)
|
|
+{
|
|
+ show_scroll_win(main_window,
|
|
+ _("Global help"), _(nconf_global_help));
|
|
+ return;
|
|
+}
|
|
+
|
|
+/* symbole help */
|
|
+static void handle_f2(int *key, struct menu *current_item)
|
|
+{
|
|
+ show_help(current_item);
|
|
+ return;
|
|
+}
|
|
+
|
|
+/* instructions */
|
|
+static void handle_f3(int *key, struct menu *current_item)
|
|
+{
|
|
+ show_scroll_win(main_window,
|
|
+ _("Short help"),
|
|
+ _(current_instructions));
|
|
+ return;
|
|
+}
|
|
+
|
|
+/* config */
|
|
+static void handle_f4(int *key, struct menu *current_item)
|
|
+{
|
|
+ int res = btn_dialog(main_window,
|
|
+ _("Show all symbols?"),
|
|
+ 2,
|
|
+ " <Show All> ",
|
|
+ "<Don't show all>");
|
|
+ if (res == 0)
|
|
+ show_all_items = 1;
|
|
+ else if (res == 1)
|
|
+ show_all_items = 0;
|
|
+
|
|
+ return;
|
|
+}
|
|
+
|
|
+/* back */
|
|
+static void handle_f5(int *key, struct menu *current_item)
|
|
+{
|
|
+ *key = KEY_LEFT;
|
|
+ return;
|
|
+}
|
|
+
|
|
+/* save */
|
|
+static void handle_f6(int *key, struct menu *current_item)
|
|
+{
|
|
+ conf_save();
|
|
+ return;
|
|
+}
|
|
+
|
|
+/* load */
|
|
+static void handle_f7(int *key, struct menu *current_item)
|
|
+{
|
|
+ conf_load();
|
|
+ return;
|
|
+}
|
|
+
|
|
+/* search */
|
|
+static void handle_f8(int *key, struct menu *current_item)
|
|
+{
|
|
+ search_conf();
|
|
+ return;
|
|
+}
|
|
+
|
|
+/* exit */
|
|
+static void handle_f9(int *key, struct menu *current_item)
|
|
+{
|
|
+ do_exit();
|
|
+ return;
|
|
+}
|
|
+
|
|
+/* return != 0 to indicate the key was handles */
|
|
+static int process_special_keys(int *key, struct menu *menu)
|
|
+{
|
|
+ int i;
|
|
+
|
|
+ if (*key == KEY_RESIZE) {
|
|
+ setup_windows();
|
|
+ return 1;
|
|
+ }
|
|
+
|
|
+ for (i = 0; i < function_keys_num; i++) {
|
|
+ if (*key == KEY_F(function_keys[i].key) ||
|
|
+ *key == '0' + function_keys[i].key){
|
|
+ function_keys[i].handler(key, menu);
|
|
+ return 1;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static void clean_items(void)
|
|
+{
|
|
+ int i;
|
|
+ for (i = 0; curses_menu_items[i]; i++)
|
|
+ free_item(curses_menu_items[i]);
|
|
+ bzero(curses_menu_items, sizeof(curses_menu_items));
|
|
+ bzero(k_menu_items, sizeof(k_menu_items));
|
|
+ items_num = 0;
|
|
+}
|
|
+
|
|
+typedef enum {MATCH_TINKER_PATTERN_UP, MATCH_TINKER_PATTERN_DOWN,
|
|
+ FIND_NEXT_MATCH_DOWN, FIND_NEXT_MATCH_UP} match_f;
|
|
+
|
|
+/* return the index of the matched item, or -1 if no such item exists */
|
|
+static int get_mext_match(const char *match_str, match_f flag)
|
|
+{
|
|
+ int match_start = item_index(current_item(curses_menu));
|
|
+ int index;
|
|
+
|
|
+ if (flag == FIND_NEXT_MATCH_DOWN)
|
|
+ ++match_start;
|
|
+ else if (flag == FIND_NEXT_MATCH_UP)
|
|
+ --match_start;
|
|
+
|
|
+ index = match_start;
|
|
+ index = (index + items_num) % items_num;
|
|
+ while (true) {
|
|
+ char *str = k_menu_items[index].str;
|
|
+ if (strcasestr(str, match_str) != 0)
|
|
+ return index;
|
|
+ if (flag == FIND_NEXT_MATCH_UP ||
|
|
+ flag == MATCH_TINKER_PATTERN_UP)
|
|
+ --index;
|
|
+ else
|
|
+ ++index;
|
|
+ index = (index + items_num) % items_num;
|
|
+ if (index == match_start)
|
|
+ return -1;
|
|
+ }
|
|
+}
|
|
+
|
|
+/* Make a new item. */
|
|
+static void item_make(struct menu *menu, char tag, const char *fmt, ...)
|
|
+{
|
|
+ va_list ap;
|
|
+
|
|
+ if (items_num > MAX_MENU_ITEMS-1)
|
|
+ return;
|
|
+
|
|
+ bzero(&k_menu_items[items_num], sizeof(k_menu_items[0]));
|
|
+ k_menu_items[items_num].tag = tag;
|
|
+ k_menu_items[items_num].usrptr = menu;
|
|
+ if (menu != NULL)
|
|
+ k_menu_items[items_num].is_visible =
|
|
+ menu_is_visible(menu);
|
|
+ else
|
|
+ k_menu_items[items_num].is_visible = 1;
|
|
+
|
|
+ va_start(ap, fmt);
|
|
+ vsnprintf(k_menu_items[items_num].str,
|
|
+ sizeof(k_menu_items[items_num].str),
|
|
+ fmt, ap);
|
|
+ va_end(ap);
|
|
+
|
|
+ if (!k_menu_items[items_num].is_visible)
|
|
+ memcpy(k_menu_items[items_num].str, "XXX", 3);
|
|
+
|
|
+ curses_menu_items[items_num] = new_item(
|
|
+ k_menu_items[items_num].str,
|
|
+ k_menu_items[items_num].str);
|
|
+ set_item_userptr(curses_menu_items[items_num],
|
|
+ &k_menu_items[items_num]);
|
|
+ /*
|
|
+ if (!k_menu_items[items_num].is_visible)
|
|
+ item_opts_off(curses_menu_items[items_num], O_SELECTABLE);
|
|
+ */
|
|
+
|
|
+ items_num++;
|
|
+ curses_menu_items[items_num] = NULL;
|
|
+}
|
|
+
|
|
+/* very hackish. adds a string to the last item added */
|
|
+static void item_add_str(const char *fmt, ...)
|
|
+{
|
|
+ va_list ap;
|
|
+ int index = items_num-1;
|
|
+ char new_str[256];
|
|
+ char tmp_str[256];
|
|
+
|
|
+ if (index < 0)
|
|
+ return;
|
|
+
|
|
+ va_start(ap, fmt);
|
|
+ vsnprintf(new_str, sizeof(new_str), fmt, ap);
|
|
+ va_end(ap);
|
|
+ snprintf(tmp_str, sizeof(tmp_str), "%s%s",
|
|
+ k_menu_items[index].str, new_str);
|
|
+ strncpy(k_menu_items[index].str,
|
|
+ tmp_str,
|
|
+ sizeof(k_menu_items[index].str));
|
|
+
|
|
+ free_item(curses_menu_items[index]);
|
|
+ curses_menu_items[index] = new_item(
|
|
+ k_menu_items[index].str,
|
|
+ k_menu_items[index].str);
|
|
+ set_item_userptr(curses_menu_items[index],
|
|
+ &k_menu_items[index]);
|
|
+}
|
|
+
|
|
+/* get the tag of the currently selected item */
|
|
+static char item_tag(void)
|
|
+{
|
|
+ ITEM *cur;
|
|
+ struct mitem *mcur;
|
|
+
|
|
+ cur = current_item(curses_menu);
|
|
+ if (cur == NULL)
|
|
+ return 0;
|
|
+ mcur = (struct mitem *) item_userptr(cur);
|
|
+ return mcur->tag;
|
|
+}
|
|
+
|
|
+static int curses_item_index(void)
|
|
+{
|
|
+ return item_index(current_item(curses_menu));
|
|
+}
|
|
+
|
|
+static void *item_data(void)
|
|
+{
|
|
+ ITEM *cur;
|
|
+ struct mitem *mcur;
|
|
+
|
|
+ cur = current_item(curses_menu);
|
|
+ if (!cur)
|
|
+ return NULL;
|
|
+ mcur = (struct mitem *) item_userptr(cur);
|
|
+ return mcur->usrptr;
|
|
+
|
|
+}
|
|
+
|
|
+static int item_is_tag(char tag)
|
|
+{
|
|
+ return item_tag() == tag;
|
|
+}
|
|
+
|
|
+static char filename[PATH_MAX+1];
|
|
+static char menu_backtitle[PATH_MAX+128];
|
|
+static const char *set_config_filename(const char *config_filename)
|
|
+{
|
|
+ int size;
|
|
+
|
|
+ size = snprintf(menu_backtitle, sizeof(menu_backtitle),
|
|
+ "%s - %s", config_filename, rootmenu.prompt->text);
|
|
+ if (size >= sizeof(menu_backtitle))
|
|
+ menu_backtitle[sizeof(menu_backtitle)-1] = '\0';
|
|
+
|
|
+ size = snprintf(filename, sizeof(filename), "%s", config_filename);
|
|
+ if (size >= sizeof(filename))
|
|
+ filename[sizeof(filename)-1] = '\0';
|
|
+ return menu_backtitle;
|
|
+}
|
|
+
|
|
+/* return = 0 means we are successful.
|
|
+ * -1 means go on doing what you were doing
|
|
+ */
|
|
+static int do_exit(void)
|
|
+{
|
|
+ int res;
|
|
+ if (!conf_get_changed()) {
|
|
+ global_exit = 1;
|
|
+ return 0;
|
|
+ }
|
|
+ res = btn_dialog(main_window,
|
|
+ _("Do you wish to save your new configuration?\n"
|
|
+ "<ESC> to cancel and resume nconfig."),
|
|
+ 2,
|
|
+ " <save> ",
|
|
+ "<don't save>");
|
|
+ if (res == KEY_EXIT) {
|
|
+ global_exit = 0;
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ /* if we got here, the user really wants to exit */
|
|
+ switch (res) {
|
|
+ case 0:
|
|
+ res = conf_write(filename);
|
|
+ if (res)
|
|
+ btn_dialog(
|
|
+ main_window,
|
|
+ _("Error during writing of configuration.\n"
|
|
+ "Your configuration changes were NOT saved."),
|
|
+ 1,
|
|
+ "<OK>");
|
|
+ break;
|
|
+ default:
|
|
+ btn_dialog(
|
|
+ main_window,
|
|
+ _("Your configuration changes were NOT saved."),
|
|
+ 1,
|
|
+ "<OK>");
|
|
+ break;
|
|
+ }
|
|
+ global_exit = 1;
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+
|
|
+static void search_conf(void)
|
|
+{
|
|
+ struct symbol **sym_arr;
|
|
+ struct gstr res;
|
|
+ struct gstr title;
|
|
+ char *dialog_input;
|
|
+ int dres;
|
|
+
|
|
+ title = str_new();
|
|
+ str_printf( &title, _("Enter (sub)string or regexp to search for "
|
|
+ "(with or without \"%s\")"), CONFIG_);
|
|
+
|
|
+again:
|
|
+ dres = dialog_inputbox(main_window,
|
|
+ _("Search Configuration Parameter"),
|
|
+ str_get(&title),
|
|
+ "", &dialog_input_result, &dialog_input_result_len);
|
|
+ switch (dres) {
|
|
+ case 0:
|
|
+ break;
|
|
+ case 1:
|
|
+ show_scroll_win(main_window,
|
|
+ _("Search Configuration"), search_help);
|
|
+ goto again;
|
|
+ default:
|
|
+ str_free(&title);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ /* strip the prefix if necessary */
|
|
+ dialog_input = dialog_input_result;
|
|
+ if (strncasecmp(dialog_input_result, CONFIG_, strlen(CONFIG_)) == 0)
|
|
+ dialog_input += strlen(CONFIG_);
|
|
+
|
|
+ sym_arr = sym_re_search(dialog_input);
|
|
+ res = get_relations_str(sym_arr, NULL);
|
|
+ free(sym_arr);
|
|
+ show_scroll_win(main_window,
|
|
+ _("Search Results"), str_get(&res));
|
|
+ str_free(&res);
|
|
+ str_free(&title);
|
|
+}
|
|
+
|
|
+
|
|
+static void build_conf(struct menu *menu)
|
|
+{
|
|
+ struct symbol *sym;
|
|
+ struct property *prop;
|
|
+ struct menu *child;
|
|
+ int type, tmp, doint = 2;
|
|
+ tristate val;
|
|
+ char ch;
|
|
+
|
|
+ if (!menu || (!show_all_items && !menu_is_visible(menu)))
|
|
+ return;
|
|
+
|
|
+ sym = menu->sym;
|
|
+ prop = menu->prompt;
|
|
+ if (!sym) {
|
|
+ if (prop && menu != current_menu) {
|
|
+ const char *prompt = menu_get_prompt(menu);
|
|
+ enum prop_type ptype;
|
|
+ ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
|
|
+ switch (ptype) {
|
|
+ case P_MENU:
|
|
+ child_count++;
|
|
+ prompt = _(prompt);
|
|
+ if (single_menu_mode) {
|
|
+ item_make(menu, 'm',
|
|
+ "%s%*c%s",
|
|
+ menu->data ? "-->" : "++>",
|
|
+ indent + 1, ' ', prompt);
|
|
+ } else
|
|
+ item_make(menu, 'm',
|
|
+ " %*c%s %s",
|
|
+ indent + 1, ' ', prompt,
|
|
+ menu_is_empty(menu) ? "----" : "--->");
|
|
+
|
|
+ if (single_menu_mode && menu->data)
|
|
+ goto conf_childs;
|
|
+ return;
|
|
+ case P_COMMENT:
|
|
+ if (prompt) {
|
|
+ child_count++;
|
|
+ item_make(menu, ':',
|
|
+ " %*c*** %s ***",
|
|
+ indent + 1, ' ',
|
|
+ _(prompt));
|
|
+ }
|
|
+ break;
|
|
+ default:
|
|
+ if (prompt) {
|
|
+ child_count++;
|
|
+ item_make(menu, ':', "---%*c%s",
|
|
+ indent + 1, ' ',
|
|
+ _(prompt));
|
|
+ }
|
|
+ }
|
|
+ } else
|
|
+ doint = 0;
|
|
+ goto conf_childs;
|
|
+ }
|
|
+
|
|
+ type = sym_get_type(sym);
|
|
+ if (sym_is_choice(sym)) {
|
|
+ struct symbol *def_sym = sym_get_choice_value(sym);
|
|
+ struct menu *def_menu = NULL;
|
|
+
|
|
+ child_count++;
|
|
+ for (child = menu->list; child; child = child->next) {
|
|
+ if (menu_is_visible(child) && child->sym == def_sym)
|
|
+ def_menu = child;
|
|
+ }
|
|
+
|
|
+ val = sym_get_tristate_value(sym);
|
|
+ if (sym_is_changable(sym)) {
|
|
+ switch (type) {
|
|
+ case S_BOOLEAN:
|
|
+ item_make(menu, 't', "[%c]",
|
|
+ val == no ? ' ' : '*');
|
|
+ break;
|
|
+ case S_TRISTATE:
|
|
+ switch (val) {
|
|
+ case yes:
|
|
+ ch = '*';
|
|
+ break;
|
|
+ case mod:
|
|
+ ch = 'M';
|
|
+ break;
|
|
+ default:
|
|
+ ch = ' ';
|
|
+ break;
|
|
+ }
|
|
+ item_make(menu, 't', "<%c>", ch);
|
|
+ break;
|
|
+ }
|
|
+ } else {
|
|
+ item_make(menu, def_menu ? 't' : ':', " ");
|
|
+ }
|
|
+
|
|
+ item_add_str("%*c%s", indent + 1,
|
|
+ ' ', _(menu_get_prompt(menu)));
|
|
+ if (val == yes) {
|
|
+ if (def_menu) {
|
|
+ item_add_str(" (%s)",
|
|
+ _(menu_get_prompt(def_menu)));
|
|
+ item_add_str(" --->");
|
|
+ if (def_menu->list) {
|
|
+ indent += 2;
|
|
+ build_conf(def_menu);
|
|
+ indent -= 2;
|
|
+ }
|
|
+ }
|
|
+ return;
|
|
+ }
|
|
+ } else {
|
|
+ if (menu == current_menu) {
|
|
+ item_make(menu, ':',
|
|
+ "---%*c%s", indent + 1,
|
|
+ ' ', _(menu_get_prompt(menu)));
|
|
+ goto conf_childs;
|
|
+ }
|
|
+ child_count++;
|
|
+ val = sym_get_tristate_value(sym);
|
|
+ if (sym_is_choice_value(sym) && val == yes) {
|
|
+ item_make(menu, ':', " ");
|
|
+ } else {
|
|
+ switch (type) {
|
|
+ case S_BOOLEAN:
|
|
+ if (sym_is_changable(sym))
|
|
+ item_make(menu, 't', "[%c]",
|
|
+ val == no ? ' ' : '*');
|
|
+ else
|
|
+ item_make(menu, 't', "-%c-",
|
|
+ val == no ? ' ' : '*');
|
|
+ break;
|
|
+ case S_TRISTATE:
|
|
+ switch (val) {
|
|
+ case yes:
|
|
+ ch = '*';
|
|
+ break;
|
|
+ case mod:
|
|
+ ch = 'M';
|
|
+ break;
|
|
+ default:
|
|
+ ch = ' ';
|
|
+ break;
|
|
+ }
|
|
+ if (sym_is_changable(sym)) {
|
|
+ if (sym->rev_dep.tri == mod)
|
|
+ item_make(menu,
|
|
+ 't', "{%c}", ch);
|
|
+ else
|
|
+ item_make(menu,
|
|
+ 't', "<%c>", ch);
|
|
+ } else
|
|
+ item_make(menu, 't', "-%c-", ch);
|
|
+ break;
|
|
+ default:
|
|
+ tmp = 2 + strlen(sym_get_string_value(sym));
|
|
+ item_make(menu, 's', " (%s)",
|
|
+ sym_get_string_value(sym));
|
|
+ tmp = indent - tmp + 4;
|
|
+ if (tmp < 0)
|
|
+ tmp = 0;
|
|
+ item_add_str("%*c%s%s", tmp, ' ',
|
|
+ _(menu_get_prompt(menu)),
|
|
+ (sym_has_value(sym) ||
|
|
+ !sym_is_changable(sym)) ? "" :
|
|
+ _(" (NEW)"));
|
|
+ goto conf_childs;
|
|
+ }
|
|
+ }
|
|
+ item_add_str("%*c%s%s", indent + 1, ' ',
|
|
+ _(menu_get_prompt(menu)),
|
|
+ (sym_has_value(sym) || !sym_is_changable(sym)) ?
|
|
+ "" : _(" (NEW)"));
|
|
+ if (menu->prompt && menu->prompt->type == P_MENU) {
|
|
+ item_add_str(" %s", menu_is_empty(menu) ? "----" : "--->");
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+
|
|
+conf_childs:
|
|
+ indent += doint;
|
|
+ for (child = menu->list; child; child = child->next)
|
|
+ build_conf(child);
|
|
+ indent -= doint;
|
|
+}
|
|
+
|
|
+static void reset_menu(void)
|
|
+{
|
|
+ unpost_menu(curses_menu);
|
|
+ clean_items();
|
|
+}
|
|
+
|
|
+/* adjust the menu to show this item.
|
|
+ * prefer not to scroll the menu if possible*/
|
|
+static void center_item(int selected_index, int *last_top_row)
|
|
+{
|
|
+ int toprow;
|
|
+
|
|
+ set_top_row(curses_menu, *last_top_row);
|
|
+ toprow = top_row(curses_menu);
|
|
+ if (selected_index < toprow ||
|
|
+ selected_index >= toprow+mwin_max_lines) {
|
|
+ toprow = max(selected_index-mwin_max_lines/2, 0);
|
|
+ if (toprow >= item_count(curses_menu)-mwin_max_lines)
|
|
+ toprow = item_count(curses_menu)-mwin_max_lines;
|
|
+ set_top_row(curses_menu, toprow);
|
|
+ }
|
|
+ set_current_item(curses_menu,
|
|
+ curses_menu_items[selected_index]);
|
|
+ *last_top_row = toprow;
|
|
+ post_menu(curses_menu);
|
|
+ refresh_all_windows(main_window);
|
|
+}
|
|
+
|
|
+/* this function assumes reset_menu has been called before */
|
|
+static void show_menu(const char *prompt, const char *instructions,
|
|
+ int selected_index, int *last_top_row)
|
|
+{
|
|
+ int maxx, maxy;
|
|
+ WINDOW *menu_window;
|
|
+
|
|
+ current_instructions = instructions;
|
|
+
|
|
+ clear();
|
|
+ (void) wattrset(main_window, attributes[NORMAL]);
|
|
+ print_in_middle(stdscr, 1, 0, getmaxx(stdscr),
|
|
+ menu_backtitle,
|
|
+ attributes[MAIN_HEADING]);
|
|
+
|
|
+ (void) wattrset(main_window, attributes[MAIN_MENU_BOX]);
|
|
+ box(main_window, 0, 0);
|
|
+ (void) wattrset(main_window, attributes[MAIN_MENU_HEADING]);
|
|
+ mvwprintw(main_window, 0, 3, " %s ", prompt);
|
|
+ (void) wattrset(main_window, attributes[NORMAL]);
|
|
+
|
|
+ set_menu_items(curses_menu, curses_menu_items);
|
|
+
|
|
+ /* position the menu at the middle of the screen */
|
|
+ scale_menu(curses_menu, &maxy, &maxx);
|
|
+ maxx = min(maxx, mwin_max_cols-2);
|
|
+ maxy = mwin_max_lines;
|
|
+ menu_window = derwin(main_window,
|
|
+ maxy,
|
|
+ maxx,
|
|
+ 2,
|
|
+ (mwin_max_cols-maxx)/2);
|
|
+ keypad(menu_window, TRUE);
|
|
+ set_menu_win(curses_menu, menu_window);
|
|
+ set_menu_sub(curses_menu, menu_window);
|
|
+
|
|
+ /* must reassert this after changing items, otherwise returns to a
|
|
+ * default of 16
|
|
+ */
|
|
+ set_menu_format(curses_menu, maxy, 1);
|
|
+ center_item(selected_index, last_top_row);
|
|
+ set_menu_format(curses_menu, maxy, 1);
|
|
+
|
|
+ print_function_line();
|
|
+
|
|
+ /* Post the menu */
|
|
+ post_menu(curses_menu);
|
|
+ refresh_all_windows(main_window);
|
|
+}
|
|
+
|
|
+static void adj_match_dir(match_f *match_direction)
|
|
+{
|
|
+ if (*match_direction == FIND_NEXT_MATCH_DOWN)
|
|
+ *match_direction =
|
|
+ MATCH_TINKER_PATTERN_DOWN;
|
|
+ else if (*match_direction == FIND_NEXT_MATCH_UP)
|
|
+ *match_direction =
|
|
+ MATCH_TINKER_PATTERN_UP;
|
|
+ /* else, do no change.. */
|
|
+}
|
|
+
|
|
+struct match_state
|
|
+{
|
|
+ int in_search;
|
|
+ match_f match_direction;
|
|
+ char pattern[256];
|
|
+};
|
|
+
|
|
+/* Return 0 means I have handled the key. In such a case, ans should hold the
|
|
+ * item to center, or -1 otherwise.
|
|
+ * Else return -1 .
|
|
+ */
|
|
+static int do_match(int key, struct match_state *state, int *ans)
|
|
+{
|
|
+ char c = (char) key;
|
|
+ int terminate_search = 0;
|
|
+ *ans = -1;
|
|
+ if (key == '/' || (state->in_search && key == 27)) {
|
|
+ move(0, 0);
|
|
+ refresh();
|
|
+ clrtoeol();
|
|
+ state->in_search = 1-state->in_search;
|
|
+ bzero(state->pattern, sizeof(state->pattern));
|
|
+ state->match_direction = MATCH_TINKER_PATTERN_DOWN;
|
|
+ return 0;
|
|
+ } else if (!state->in_search)
|
|
+ return 1;
|
|
+
|
|
+ if (isalnum(c) || isgraph(c) || c == ' ') {
|
|
+ state->pattern[strlen(state->pattern)] = c;
|
|
+ state->pattern[strlen(state->pattern)] = '\0';
|
|
+ adj_match_dir(&state->match_direction);
|
|
+ *ans = get_mext_match(state->pattern,
|
|
+ state->match_direction);
|
|
+ } else if (key == KEY_DOWN) {
|
|
+ state->match_direction = FIND_NEXT_MATCH_DOWN;
|
|
+ *ans = get_mext_match(state->pattern,
|
|
+ state->match_direction);
|
|
+ } else if (key == KEY_UP) {
|
|
+ state->match_direction = FIND_NEXT_MATCH_UP;
|
|
+ *ans = get_mext_match(state->pattern,
|
|
+ state->match_direction);
|
|
+ } else if (key == KEY_BACKSPACE || key == 127) {
|
|
+ state->pattern[strlen(state->pattern)-1] = '\0';
|
|
+ adj_match_dir(&state->match_direction);
|
|
+ } else
|
|
+ terminate_search = 1;
|
|
+
|
|
+ if (terminate_search) {
|
|
+ state->in_search = 0;
|
|
+ bzero(state->pattern, sizeof(state->pattern));
|
|
+ move(0, 0);
|
|
+ refresh();
|
|
+ clrtoeol();
|
|
+ return -1;
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static void conf(struct menu *menu)
|
|
+{
|
|
+ struct menu *submenu = 0;
|
|
+ const char *prompt = menu_get_prompt(menu);
|
|
+ struct symbol *sym;
|
|
+ int res;
|
|
+ int current_index = 0;
|
|
+ int last_top_row = 0;
|
|
+ struct match_state match_state = {
|
|
+ .in_search = 0,
|
|
+ .match_direction = MATCH_TINKER_PATTERN_DOWN,
|
|
+ .pattern = "",
|
|
+ };
|
|
+
|
|
+ while (!global_exit) {
|
|
+ reset_menu();
|
|
+ current_menu = menu;
|
|
+ build_conf(menu);
|
|
+ if (!child_count)
|
|
+ break;
|
|
+
|
|
+ show_menu(prompt ? _(prompt) : _("Main Menu"),
|
|
+ _(menu_instructions),
|
|
+ current_index, &last_top_row);
|
|
+ keypad((menu_win(curses_menu)), TRUE);
|
|
+ while (!global_exit) {
|
|
+ if (match_state.in_search) {
|
|
+ mvprintw(0, 0,
|
|
+ "searching: %s", match_state.pattern);
|
|
+ clrtoeol();
|
|
+ }
|
|
+ refresh_all_windows(main_window);
|
|
+ res = wgetch(menu_win(curses_menu));
|
|
+ if (!res)
|
|
+ break;
|
|
+ if (do_match(res, &match_state, ¤t_index) == 0) {
|
|
+ if (current_index != -1)
|
|
+ center_item(current_index,
|
|
+ &last_top_row);
|
|
+ continue;
|
|
+ }
|
|
+ if (process_special_keys(&res,
|
|
+ (struct menu *) item_data()))
|
|
+ break;
|
|
+ switch (res) {
|
|
+ case KEY_DOWN:
|
|
+ menu_driver(curses_menu, REQ_DOWN_ITEM);
|
|
+ break;
|
|
+ case KEY_UP:
|
|
+ menu_driver(curses_menu, REQ_UP_ITEM);
|
|
+ break;
|
|
+ case KEY_NPAGE:
|
|
+ menu_driver(curses_menu, REQ_SCR_DPAGE);
|
|
+ break;
|
|
+ case KEY_PPAGE:
|
|
+ menu_driver(curses_menu, REQ_SCR_UPAGE);
|
|
+ break;
|
|
+ case KEY_HOME:
|
|
+ menu_driver(curses_menu, REQ_FIRST_ITEM);
|
|
+ break;
|
|
+ case KEY_END:
|
|
+ menu_driver(curses_menu, REQ_LAST_ITEM);
|
|
+ break;
|
|
+ case 'h':
|
|
+ case '?':
|
|
+ show_help((struct menu *) item_data());
|
|
+ break;
|
|
+ }
|
|
+ if (res == 10 || res == 27 ||
|
|
+ res == 32 || res == 'n' || res == 'y' ||
|
|
+ res == KEY_LEFT || res == KEY_RIGHT ||
|
|
+ res == 'm')
|
|
+ break;
|
|
+ refresh_all_windows(main_window);
|
|
+ }
|
|
+
|
|
+ refresh_all_windows(main_window);
|
|
+ /* if ESC or left*/
|
|
+ if (res == 27 || (menu != &rootmenu && res == KEY_LEFT))
|
|
+ break;
|
|
+
|
|
+ /* remember location in the menu */
|
|
+ last_top_row = top_row(curses_menu);
|
|
+ current_index = curses_item_index();
|
|
+
|
|
+ if (!item_tag())
|
|
+ continue;
|
|
+
|
|
+ submenu = (struct menu *) item_data();
|
|
+ if (!submenu || !menu_is_visible(submenu))
|
|
+ continue;
|
|
+ sym = submenu->sym;
|
|
+
|
|
+ switch (res) {
|
|
+ case ' ':
|
|
+ if (item_is_tag('t'))
|
|
+ sym_toggle_tristate_value(sym);
|
|
+ else if (item_is_tag('m'))
|
|
+ conf(submenu);
|
|
+ break;
|
|
+ case KEY_RIGHT:
|
|
+ case 10: /* ENTER WAS PRESSED */
|
|
+ switch (item_tag()) {
|
|
+ case 'm':
|
|
+ if (single_menu_mode)
|
|
+ submenu->data =
|
|
+ (void *) (long) !submenu->data;
|
|
+ else
|
|
+ conf(submenu);
|
|
+ break;
|
|
+ case 't':
|
|
+ if (sym_is_choice(sym) &&
|
|
+ sym_get_tristate_value(sym) == yes)
|
|
+ conf_choice(submenu);
|
|
+ else if (submenu->prompt &&
|
|
+ submenu->prompt->type == P_MENU)
|
|
+ conf(submenu);
|
|
+ else if (res == 10)
|
|
+ sym_toggle_tristate_value(sym);
|
|
+ break;
|
|
+ case 's':
|
|
+ conf_string(submenu);
|
|
+ break;
|
|
+ }
|
|
+ break;
|
|
+ case 'y':
|
|
+ if (item_is_tag('t')) {
|
|
+ if (sym_set_tristate_value(sym, yes))
|
|
+ break;
|
|
+ if (sym_set_tristate_value(sym, mod))
|
|
+ btn_dialog(main_window, setmod_text, 0);
|
|
+ }
|
|
+ break;
|
|
+ case 'n':
|
|
+ if (item_is_tag('t'))
|
|
+ sym_set_tristate_value(sym, no);
|
|
+ break;
|
|
+ case 'm':
|
|
+ if (item_is_tag('t'))
|
|
+ sym_set_tristate_value(sym, mod);
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+static void conf_message_callback(const char *fmt, va_list ap)
|
|
+{
|
|
+ char buf[1024];
|
|
+
|
|
+ vsnprintf(buf, sizeof(buf), fmt, ap);
|
|
+ btn_dialog(main_window, buf, 1, "<OK>");
|
|
+}
|
|
+
|
|
+static void show_help(struct menu *menu)
|
|
+{
|
|
+ struct gstr help;
|
|
+
|
|
+ if (!menu)
|
|
+ return;
|
|
+
|
|
+ help = str_new();
|
|
+ menu_get_ext_help(menu, &help);
|
|
+ show_scroll_win(main_window, _(menu_get_prompt(menu)), str_get(&help));
|
|
+ str_free(&help);
|
|
+}
|
|
+
|
|
+static void conf_choice(struct menu *menu)
|
|
+{
|
|
+ const char *prompt = _(menu_get_prompt(menu));
|
|
+ struct menu *child = 0;
|
|
+ struct symbol *active;
|
|
+ int selected_index = 0;
|
|
+ int last_top_row = 0;
|
|
+ int res, i = 0;
|
|
+ struct match_state match_state = {
|
|
+ .in_search = 0,
|
|
+ .match_direction = MATCH_TINKER_PATTERN_DOWN,
|
|
+ .pattern = "",
|
|
+ };
|
|
+
|
|
+ active = sym_get_choice_value(menu->sym);
|
|
+ /* this is mostly duplicated from the conf() function. */
|
|
+ while (!global_exit) {
|
|
+ reset_menu();
|
|
+
|
|
+ for (i = 0, child = menu->list; child; child = child->next) {
|
|
+ if (!show_all_items && !menu_is_visible(child))
|
|
+ continue;
|
|
+
|
|
+ if (child->sym == sym_get_choice_value(menu->sym))
|
|
+ item_make(child, ':', "<X> %s",
|
|
+ _(menu_get_prompt(child)));
|
|
+ else if (child->sym)
|
|
+ item_make(child, ':', " %s",
|
|
+ _(menu_get_prompt(child)));
|
|
+ else
|
|
+ item_make(child, ':', "*** %s ***",
|
|
+ _(menu_get_prompt(child)));
|
|
+
|
|
+ if (child->sym == active){
|
|
+ last_top_row = top_row(curses_menu);
|
|
+ selected_index = i;
|
|
+ }
|
|
+ i++;
|
|
+ }
|
|
+ show_menu(prompt ? _(prompt) : _("Choice Menu"),
|
|
+ _(radiolist_instructions),
|
|
+ selected_index,
|
|
+ &last_top_row);
|
|
+ while (!global_exit) {
|
|
+ if (match_state.in_search) {
|
|
+ mvprintw(0, 0, "searching: %s",
|
|
+ match_state.pattern);
|
|
+ clrtoeol();
|
|
+ }
|
|
+ refresh_all_windows(main_window);
|
|
+ res = wgetch(menu_win(curses_menu));
|
|
+ if (!res)
|
|
+ break;
|
|
+ if (do_match(res, &match_state, &selected_index) == 0) {
|
|
+ if (selected_index != -1)
|
|
+ center_item(selected_index,
|
|
+ &last_top_row);
|
|
+ continue;
|
|
+ }
|
|
+ if (process_special_keys(
|
|
+ &res,
|
|
+ (struct menu *) item_data()))
|
|
+ break;
|
|
+ switch (res) {
|
|
+ case KEY_DOWN:
|
|
+ menu_driver(curses_menu, REQ_DOWN_ITEM);
|
|
+ break;
|
|
+ case KEY_UP:
|
|
+ menu_driver(curses_menu, REQ_UP_ITEM);
|
|
+ break;
|
|
+ case KEY_NPAGE:
|
|
+ menu_driver(curses_menu, REQ_SCR_DPAGE);
|
|
+ break;
|
|
+ case KEY_PPAGE:
|
|
+ menu_driver(curses_menu, REQ_SCR_UPAGE);
|
|
+ break;
|
|
+ case KEY_HOME:
|
|
+ menu_driver(curses_menu, REQ_FIRST_ITEM);
|
|
+ break;
|
|
+ case KEY_END:
|
|
+ menu_driver(curses_menu, REQ_LAST_ITEM);
|
|
+ break;
|
|
+ case 'h':
|
|
+ case '?':
|
|
+ show_help((struct menu *) item_data());
|
|
+ break;
|
|
+ }
|
|
+ if (res == 10 || res == 27 || res == ' ' ||
|
|
+ res == KEY_LEFT){
|
|
+ break;
|
|
+ }
|
|
+ refresh_all_windows(main_window);
|
|
+ }
|
|
+ /* if ESC or left */
|
|
+ if (res == 27 || res == KEY_LEFT)
|
|
+ break;
|
|
+
|
|
+ child = item_data();
|
|
+ if (!child || !menu_is_visible(child) || !child->sym)
|
|
+ continue;
|
|
+ switch (res) {
|
|
+ case ' ':
|
|
+ case 10:
|
|
+ case KEY_RIGHT:
|
|
+ sym_set_tristate_value(child->sym, yes);
|
|
+ return;
|
|
+ case 'h':
|
|
+ case '?':
|
|
+ show_help(child);
|
|
+ active = child->sym;
|
|
+ break;
|
|
+ case KEY_EXIT:
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+static void conf_string(struct menu *menu)
|
|
+{
|
|
+ const char *prompt = menu_get_prompt(menu);
|
|
+
|
|
+ while (1) {
|
|
+ int res;
|
|
+ const char *heading;
|
|
+
|
|
+ switch (sym_get_type(menu->sym)) {
|
|
+ case S_INT:
|
|
+ heading = _(inputbox_instructions_int);
|
|
+ break;
|
|
+ case S_HEX:
|
|
+ heading = _(inputbox_instructions_hex);
|
|
+ break;
|
|
+ case S_STRING:
|
|
+ heading = _(inputbox_instructions_string);
|
|
+ break;
|
|
+ default:
|
|
+ heading = _("Internal nconf error!");
|
|
+ }
|
|
+ res = dialog_inputbox(main_window,
|
|
+ prompt ? _(prompt) : _("Main Menu"),
|
|
+ heading,
|
|
+ sym_get_string_value(menu->sym),
|
|
+ &dialog_input_result,
|
|
+ &dialog_input_result_len);
|
|
+ switch (res) {
|
|
+ case 0:
|
|
+ if (sym_set_string_value(menu->sym,
|
|
+ dialog_input_result))
|
|
+ return;
|
|
+ btn_dialog(main_window,
|
|
+ _("You have made an invalid entry."), 0);
|
|
+ break;
|
|
+ case 1:
|
|
+ show_help(menu);
|
|
+ break;
|
|
+ case KEY_EXIT:
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+static void conf_load(void)
|
|
+{
|
|
+ while (1) {
|
|
+ int res;
|
|
+ res = dialog_inputbox(main_window,
|
|
+ NULL, load_config_text,
|
|
+ filename,
|
|
+ &dialog_input_result,
|
|
+ &dialog_input_result_len);
|
|
+ switch (res) {
|
|
+ case 0:
|
|
+ if (!dialog_input_result[0])
|
|
+ return;
|
|
+ if (!conf_read(dialog_input_result)) {
|
|
+ set_config_filename(dialog_input_result);
|
|
+ sym_set_change_count(1);
|
|
+ return;
|
|
+ }
|
|
+ btn_dialog(main_window, _("File does not exist!"), 0);
|
|
+ break;
|
|
+ case 1:
|
|
+ show_scroll_win(main_window,
|
|
+ _("Load Alternate Configuration"),
|
|
+ load_config_help);
|
|
+ break;
|
|
+ case KEY_EXIT:
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+static void conf_save(void)
|
|
+{
|
|
+ while (1) {
|
|
+ int res;
|
|
+ res = dialog_inputbox(main_window,
|
|
+ NULL, save_config_text,
|
|
+ filename,
|
|
+ &dialog_input_result,
|
|
+ &dialog_input_result_len);
|
|
+ switch (res) {
|
|
+ case 0:
|
|
+ if (!dialog_input_result[0])
|
|
+ return;
|
|
+ res = conf_write(dialog_input_result);
|
|
+ if (!res) {
|
|
+ set_config_filename(dialog_input_result);
|
|
+ return;
|
|
+ }
|
|
+ btn_dialog(main_window, _("Can't create file! "
|
|
+ "Probably a nonexistent directory."),
|
|
+ 1, "<OK>");
|
|
+ break;
|
|
+ case 1:
|
|
+ show_scroll_win(main_window,
|
|
+ _("Save Alternate Configuration"),
|
|
+ save_config_help);
|
|
+ break;
|
|
+ case KEY_EXIT:
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+void setup_windows(void)
|
|
+{
|
|
+ int lines, columns;
|
|
+
|
|
+ getmaxyx(stdscr, lines, columns);
|
|
+
|
|
+ if (main_window != NULL)
|
|
+ delwin(main_window);
|
|
+
|
|
+ /* set up the menu and menu window */
|
|
+ main_window = newwin(lines-2, columns-2, 2, 1);
|
|
+ keypad(main_window, TRUE);
|
|
+ mwin_max_lines = lines-7;
|
|
+ mwin_max_cols = columns-6;
|
|
+
|
|
+ /* panels order is from bottom to top */
|
|
+ new_panel(main_window);
|
|
+}
|
|
+
|
|
+int main(int ac, char **av)
|
|
+{
|
|
+ int lines, columns;
|
|
+ char *mode;
|
|
+
|
|
+ setlocale(LC_ALL, "");
|
|
+ bindtextdomain(PACKAGE, LOCALEDIR);
|
|
+ textdomain(PACKAGE);
|
|
+
|
|
+ conf_parse(av[1]);
|
|
+ conf_read(NULL);
|
|
+
|
|
+ mode = getenv("NCONFIG_MODE");
|
|
+ if (mode) {
|
|
+ if (!strcasecmp(mode, "single_menu"))
|
|
+ single_menu_mode = 1;
|
|
+ }
|
|
+
|
|
+ /* Initialize curses */
|
|
+ initscr();
|
|
+ /* set color theme */
|
|
+ set_colors();
|
|
+
|
|
+ cbreak();
|
|
+ noecho();
|
|
+ keypad(stdscr, TRUE);
|
|
+ curs_set(0);
|
|
+
|
|
+ getmaxyx(stdscr, lines, columns);
|
|
+ if (columns < 75 || lines < 20) {
|
|
+ endwin();
|
|
+ printf("Your terminal should have at "
|
|
+ "least 20 lines and 75 columns\n");
|
|
+ return 1;
|
|
+ }
|
|
+
|
|
+ notimeout(stdscr, FALSE);
|
|
+#if NCURSES_REENTRANT
|
|
+ set_escdelay(1);
|
|
+#else
|
|
+ ESCDELAY = 1;
|
|
+#endif
|
|
+
|
|
+ /* set btns menu */
|
|
+ curses_menu = new_menu(curses_menu_items);
|
|
+ menu_opts_off(curses_menu, O_SHOWDESC);
|
|
+ menu_opts_on(curses_menu, O_SHOWMATCH);
|
|
+ menu_opts_on(curses_menu, O_ONEVALUE);
|
|
+ menu_opts_on(curses_menu, O_NONCYCLIC);
|
|
+ menu_opts_on(curses_menu, O_IGNORECASE);
|
|
+ set_menu_mark(curses_menu, " ");
|
|
+ set_menu_fore(curses_menu, attributes[MAIN_MENU_FORE]);
|
|
+ set_menu_back(curses_menu, attributes[MAIN_MENU_BACK]);
|
|
+ set_menu_grey(curses_menu, attributes[MAIN_MENU_GREY]);
|
|
+
|
|
+ set_config_filename(conf_get_configname());
|
|
+ setup_windows();
|
|
+
|
|
+ /* check for KEY_FUNC(1) */
|
|
+ if (has_key(KEY_F(1)) == FALSE) {
|
|
+ show_scroll_win(main_window,
|
|
+ _("Instructions"),
|
|
+ _(menu_no_f_instructions));
|
|
+ }
|
|
+
|
|
+ conf_set_message_callback(conf_message_callback);
|
|
+ /* do the work */
|
|
+ while (!global_exit) {
|
|
+ conf(&rootmenu);
|
|
+ if (!global_exit && do_exit() == 0)
|
|
+ break;
|
|
+ }
|
|
+ /* ok, we are done */
|
|
+ unpost_menu(curses_menu);
|
|
+ free_menu(curses_menu);
|
|
+ delwin(main_window);
|
|
+ clear();
|
|
+ refresh();
|
|
+ endwin();
|
|
+ return 0;
|
|
+}
|
|
diff --git a/scripts/kconfig/nconf.gui.c b/scripts/kconfig/nconf.gui.c
|
|
new file mode 100644
|
|
index 0000000..8275f0e
|
|
--- /dev/null
|
|
+++ b/scripts/kconfig/nconf.gui.c
|
|
@@ -0,0 +1,656 @@
|
|
+/*
|
|
+ * Copyright (C) 2008 Nir Tzachar <nir.tzachar@gmail.com?
|
|
+ * Released under the terms of the GNU GPL v2.0.
|
|
+ *
|
|
+ * Derived from menuconfig.
|
|
+ *
|
|
+ */
|
|
+#include "nconf.h"
|
|
+
|
|
+/* a list of all the different widgets we use */
|
|
+attributes_t attributes[ATTR_MAX+1] = {0};
|
|
+
|
|
+/* available colors:
|
|
+ COLOR_BLACK 0
|
|
+ COLOR_RED 1
|
|
+ COLOR_GREEN 2
|
|
+ COLOR_YELLOW 3
|
|
+ COLOR_BLUE 4
|
|
+ COLOR_MAGENTA 5
|
|
+ COLOR_CYAN 6
|
|
+ COLOR_WHITE 7
|
|
+ */
|
|
+static void set_normal_colors(void)
|
|
+{
|
|
+ init_pair(NORMAL, -1, -1);
|
|
+ init_pair(MAIN_HEADING, COLOR_MAGENTA, -1);
|
|
+
|
|
+ /* FORE is for the selected item */
|
|
+ init_pair(MAIN_MENU_FORE, -1, -1);
|
|
+ /* BACK for all the rest */
|
|
+ init_pair(MAIN_MENU_BACK, -1, -1);
|
|
+ init_pair(MAIN_MENU_GREY, -1, -1);
|
|
+ init_pair(MAIN_MENU_HEADING, COLOR_GREEN, -1);
|
|
+ init_pair(MAIN_MENU_BOX, COLOR_YELLOW, -1);
|
|
+
|
|
+ init_pair(SCROLLWIN_TEXT, -1, -1);
|
|
+ init_pair(SCROLLWIN_HEADING, COLOR_GREEN, -1);
|
|
+ init_pair(SCROLLWIN_BOX, COLOR_YELLOW, -1);
|
|
+
|
|
+ init_pair(DIALOG_TEXT, -1, -1);
|
|
+ init_pair(DIALOG_BOX, COLOR_YELLOW, -1);
|
|
+ init_pair(DIALOG_MENU_BACK, COLOR_YELLOW, -1);
|
|
+ init_pair(DIALOG_MENU_FORE, COLOR_RED, -1);
|
|
+
|
|
+ init_pair(INPUT_BOX, COLOR_YELLOW, -1);
|
|
+ init_pair(INPUT_HEADING, COLOR_GREEN, -1);
|
|
+ init_pair(INPUT_TEXT, -1, -1);
|
|
+ init_pair(INPUT_FIELD, -1, -1);
|
|
+
|
|
+ init_pair(FUNCTION_HIGHLIGHT, -1, -1);
|
|
+ init_pair(FUNCTION_TEXT, COLOR_YELLOW, -1);
|
|
+}
|
|
+
|
|
+/* available attributes:
|
|
+ A_NORMAL Normal display (no highlight)
|
|
+ A_STANDOUT Best highlighting mode of the terminal.
|
|
+ A_UNDERLINE Underlining
|
|
+ A_REVERSE Reverse video
|
|
+ A_BLINK Blinking
|
|
+ A_DIM Half bright
|
|
+ A_BOLD Extra bright or bold
|
|
+ A_PROTECT Protected mode
|
|
+ A_INVIS Invisible or blank mode
|
|
+ A_ALTCHARSET Alternate character set
|
|
+ A_CHARTEXT Bit-mask to extract a character
|
|
+ COLOR_PAIR(n) Color-pair number n
|
|
+ */
|
|
+static void normal_color_theme(void)
|
|
+{
|
|
+ /* automatically add color... */
|
|
+#define mkattr(name, attr) do { \
|
|
+attributes[name] = attr | COLOR_PAIR(name); } while (0)
|
|
+ mkattr(NORMAL, NORMAL);
|
|
+ mkattr(MAIN_HEADING, A_BOLD | A_UNDERLINE);
|
|
+
|
|
+ mkattr(MAIN_MENU_FORE, A_REVERSE);
|
|
+ mkattr(MAIN_MENU_BACK, A_NORMAL);
|
|
+ mkattr(MAIN_MENU_GREY, A_NORMAL);
|
|
+ mkattr(MAIN_MENU_HEADING, A_BOLD);
|
|
+ mkattr(MAIN_MENU_BOX, A_NORMAL);
|
|
+
|
|
+ mkattr(SCROLLWIN_TEXT, A_NORMAL);
|
|
+ mkattr(SCROLLWIN_HEADING, A_BOLD);
|
|
+ mkattr(SCROLLWIN_BOX, A_BOLD);
|
|
+
|
|
+ mkattr(DIALOG_TEXT, A_BOLD);
|
|
+ mkattr(DIALOG_BOX, A_BOLD);
|
|
+ mkattr(DIALOG_MENU_FORE, A_STANDOUT);
|
|
+ mkattr(DIALOG_MENU_BACK, A_NORMAL);
|
|
+
|
|
+ mkattr(INPUT_BOX, A_NORMAL);
|
|
+ mkattr(INPUT_HEADING, A_BOLD);
|
|
+ mkattr(INPUT_TEXT, A_NORMAL);
|
|
+ mkattr(INPUT_FIELD, A_UNDERLINE);
|
|
+
|
|
+ mkattr(FUNCTION_HIGHLIGHT, A_BOLD);
|
|
+ mkattr(FUNCTION_TEXT, A_REVERSE);
|
|
+}
|
|
+
|
|
+static void no_colors_theme(void)
|
|
+{
|
|
+ /* automatically add highlight, no color */
|
|
+#define mkattrn(name, attr) { attributes[name] = attr; }
|
|
+
|
|
+ mkattrn(NORMAL, NORMAL);
|
|
+ mkattrn(MAIN_HEADING, A_BOLD | A_UNDERLINE);
|
|
+
|
|
+ mkattrn(MAIN_MENU_FORE, A_STANDOUT);
|
|
+ mkattrn(MAIN_MENU_BACK, A_NORMAL);
|
|
+ mkattrn(MAIN_MENU_GREY, A_NORMAL);
|
|
+ mkattrn(MAIN_MENU_HEADING, A_BOLD);
|
|
+ mkattrn(MAIN_MENU_BOX, A_NORMAL);
|
|
+
|
|
+ mkattrn(SCROLLWIN_TEXT, A_NORMAL);
|
|
+ mkattrn(SCROLLWIN_HEADING, A_BOLD);
|
|
+ mkattrn(SCROLLWIN_BOX, A_BOLD);
|
|
+
|
|
+ mkattrn(DIALOG_TEXT, A_NORMAL);
|
|
+ mkattrn(DIALOG_BOX, A_BOLD);
|
|
+ mkattrn(DIALOG_MENU_FORE, A_STANDOUT);
|
|
+ mkattrn(DIALOG_MENU_BACK, A_NORMAL);
|
|
+
|
|
+ mkattrn(INPUT_BOX, A_BOLD);
|
|
+ mkattrn(INPUT_HEADING, A_BOLD);
|
|
+ mkattrn(INPUT_TEXT, A_NORMAL);
|
|
+ mkattrn(INPUT_FIELD, A_UNDERLINE);
|
|
+
|
|
+ mkattrn(FUNCTION_HIGHLIGHT, A_BOLD);
|
|
+ mkattrn(FUNCTION_TEXT, A_REVERSE);
|
|
+}
|
|
+
|
|
+void set_colors()
|
|
+{
|
|
+ start_color();
|
|
+ use_default_colors();
|
|
+ set_normal_colors();
|
|
+ if (has_colors()) {
|
|
+ normal_color_theme();
|
|
+ } else {
|
|
+ /* give defaults */
|
|
+ no_colors_theme();
|
|
+ }
|
|
+}
|
|
+
|
|
+
|
|
+/* this changes the windows attributes !!! */
|
|
+void print_in_middle(WINDOW *win,
|
|
+ int starty,
|
|
+ int startx,
|
|
+ int width,
|
|
+ const char *string,
|
|
+ chtype color)
|
|
+{ int length, x, y;
|
|
+ float temp;
|
|
+
|
|
+
|
|
+ if (win == NULL)
|
|
+ win = stdscr;
|
|
+ getyx(win, y, x);
|
|
+ if (startx != 0)
|
|
+ x = startx;
|
|
+ if (starty != 0)
|
|
+ y = starty;
|
|
+ if (width == 0)
|
|
+ width = 80;
|
|
+
|
|
+ length = strlen(string);
|
|
+ temp = (width - length) / 2;
|
|
+ x = startx + (int)temp;
|
|
+ (void) wattrset(win, color);
|
|
+ mvwprintw(win, y, x, "%s", string);
|
|
+ refresh();
|
|
+}
|
|
+
|
|
+int get_line_no(const char *text)
|
|
+{
|
|
+ int i;
|
|
+ int total = 1;
|
|
+
|
|
+ if (!text)
|
|
+ return 0;
|
|
+
|
|
+ for (i = 0; text[i] != '\0'; i++)
|
|
+ if (text[i] == '\n')
|
|
+ total++;
|
|
+ return total;
|
|
+}
|
|
+
|
|
+const char *get_line(const char *text, int line_no)
|
|
+{
|
|
+ int i;
|
|
+ int lines = 0;
|
|
+
|
|
+ if (!text)
|
|
+ return 0;
|
|
+
|
|
+ for (i = 0; text[i] != '\0' && lines < line_no; i++)
|
|
+ if (text[i] == '\n')
|
|
+ lines++;
|
|
+ return text+i;
|
|
+}
|
|
+
|
|
+int get_line_length(const char *line)
|
|
+{
|
|
+ int res = 0;
|
|
+ while (*line != '\0' && *line != '\n') {
|
|
+ line++;
|
|
+ res++;
|
|
+ }
|
|
+ return res;
|
|
+}
|
|
+
|
|
+/* print all lines to the window. */
|
|
+void fill_window(WINDOW *win, const char *text)
|
|
+{
|
|
+ int x, y;
|
|
+ int total_lines = get_line_no(text);
|
|
+ int i;
|
|
+
|
|
+ getmaxyx(win, y, x);
|
|
+ /* do not go over end of line */
|
|
+ total_lines = min(total_lines, y);
|
|
+ for (i = 0; i < total_lines; i++) {
|
|
+ char tmp[x+10];
|
|
+ const char *line = get_line(text, i);
|
|
+ int len = get_line_length(line);
|
|
+ strncpy(tmp, line, min(len, x));
|
|
+ tmp[len] = '\0';
|
|
+ mvwprintw(win, i, 0, "%s", tmp);
|
|
+ }
|
|
+}
|
|
+
|
|
+/* get the message, and buttons.
|
|
+ * each button must be a char*
|
|
+ * return the selected button
|
|
+ *
|
|
+ * this dialog is used for 2 different things:
|
|
+ * 1) show a text box, no buttons.
|
|
+ * 2) show a dialog, with horizontal buttons
|
|
+ */
|
|
+int btn_dialog(WINDOW *main_window, const char *msg, int btn_num, ...)
|
|
+{
|
|
+ va_list ap;
|
|
+ char *btn;
|
|
+ int btns_width = 0;
|
|
+ int msg_lines = 0;
|
|
+ int msg_width = 0;
|
|
+ int total_width;
|
|
+ int win_rows = 0;
|
|
+ WINDOW *win;
|
|
+ WINDOW *msg_win;
|
|
+ WINDOW *menu_win;
|
|
+ MENU *menu;
|
|
+ ITEM *btns[btn_num+1];
|
|
+ int i, x, y;
|
|
+ int res = -1;
|
|
+
|
|
+
|
|
+ va_start(ap, btn_num);
|
|
+ for (i = 0; i < btn_num; i++) {
|
|
+ btn = va_arg(ap, char *);
|
|
+ btns[i] = new_item(btn, "");
|
|
+ btns_width += strlen(btn)+1;
|
|
+ }
|
|
+ va_end(ap);
|
|
+ btns[btn_num] = NULL;
|
|
+
|
|
+ /* find the widest line of msg: */
|
|
+ msg_lines = get_line_no(msg);
|
|
+ for (i = 0; i < msg_lines; i++) {
|
|
+ const char *line = get_line(msg, i);
|
|
+ int len = get_line_length(line);
|
|
+ if (msg_width < len)
|
|
+ msg_width = len;
|
|
+ }
|
|
+
|
|
+ total_width = max(msg_width, btns_width);
|
|
+ /* place dialog in middle of screen */
|
|
+ y = (getmaxy(stdscr)-(msg_lines+4))/2;
|
|
+ x = (getmaxx(stdscr)-(total_width+4))/2;
|
|
+
|
|
+
|
|
+ /* create the windows */
|
|
+ if (btn_num > 0)
|
|
+ win_rows = msg_lines+4;
|
|
+ else
|
|
+ win_rows = msg_lines+2;
|
|
+
|
|
+ win = newwin(win_rows, total_width+4, y, x);
|
|
+ keypad(win, TRUE);
|
|
+ menu_win = derwin(win, 1, btns_width, win_rows-2,
|
|
+ 1+(total_width+2-btns_width)/2);
|
|
+ menu = new_menu(btns);
|
|
+ msg_win = derwin(win, win_rows-2, msg_width, 1,
|
|
+ 1+(total_width+2-msg_width)/2);
|
|
+
|
|
+ set_menu_fore(menu, attributes[DIALOG_MENU_FORE]);
|
|
+ set_menu_back(menu, attributes[DIALOG_MENU_BACK]);
|
|
+
|
|
+ (void) wattrset(win, attributes[DIALOG_BOX]);
|
|
+ box(win, 0, 0);
|
|
+
|
|
+ /* print message */
|
|
+ (void) wattrset(msg_win, attributes[DIALOG_TEXT]);
|
|
+ fill_window(msg_win, msg);
|
|
+
|
|
+ set_menu_win(menu, win);
|
|
+ set_menu_sub(menu, menu_win);
|
|
+ set_menu_format(menu, 1, btn_num);
|
|
+ menu_opts_off(menu, O_SHOWDESC);
|
|
+ menu_opts_off(menu, O_SHOWMATCH);
|
|
+ menu_opts_on(menu, O_ONEVALUE);
|
|
+ menu_opts_on(menu, O_NONCYCLIC);
|
|
+ set_menu_mark(menu, "");
|
|
+ post_menu(menu);
|
|
+
|
|
+
|
|
+ touchwin(win);
|
|
+ refresh_all_windows(main_window);
|
|
+ while ((res = wgetch(win))) {
|
|
+ switch (res) {
|
|
+ case KEY_LEFT:
|
|
+ menu_driver(menu, REQ_LEFT_ITEM);
|
|
+ break;
|
|
+ case KEY_RIGHT:
|
|
+ menu_driver(menu, REQ_RIGHT_ITEM);
|
|
+ break;
|
|
+ case 10: /* ENTER */
|
|
+ case 27: /* ESCAPE */
|
|
+ case ' ':
|
|
+ case KEY_F(F_BACK):
|
|
+ case KEY_F(F_EXIT):
|
|
+ break;
|
|
+ }
|
|
+ touchwin(win);
|
|
+ refresh_all_windows(main_window);
|
|
+
|
|
+ if (res == 10 || res == ' ') {
|
|
+ res = item_index(current_item(menu));
|
|
+ break;
|
|
+ } else if (res == 27 || res == KEY_F(F_BACK) ||
|
|
+ res == KEY_F(F_EXIT)) {
|
|
+ res = KEY_EXIT;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ unpost_menu(menu);
|
|
+ free_menu(menu);
|
|
+ for (i = 0; i < btn_num; i++)
|
|
+ free_item(btns[i]);
|
|
+
|
|
+ delwin(win);
|
|
+ return res;
|
|
+}
|
|
+
|
|
+int dialog_inputbox(WINDOW *main_window,
|
|
+ const char *title, const char *prompt,
|
|
+ const char *init, char **resultp, int *result_len)
|
|
+{
|
|
+ int prompt_lines = 0;
|
|
+ int prompt_width = 0;
|
|
+ WINDOW *win;
|
|
+ WINDOW *prompt_win;
|
|
+ WINDOW *form_win;
|
|
+ PANEL *panel;
|
|
+ int i, x, y;
|
|
+ int res = -1;
|
|
+ int cursor_position = strlen(init);
|
|
+ int cursor_form_win;
|
|
+ char *result = *resultp;
|
|
+
|
|
+ if (strlen(init)+1 > *result_len) {
|
|
+ *result_len = strlen(init)+1;
|
|
+ *resultp = result = realloc(result, *result_len);
|
|
+ }
|
|
+
|
|
+ /* find the widest line of msg: */
|
|
+ prompt_lines = get_line_no(prompt);
|
|
+ for (i = 0; i < prompt_lines; i++) {
|
|
+ const char *line = get_line(prompt, i);
|
|
+ int len = get_line_length(line);
|
|
+ prompt_width = max(prompt_width, len);
|
|
+ }
|
|
+
|
|
+ if (title)
|
|
+ prompt_width = max(prompt_width, strlen(title));
|
|
+
|
|
+ /* place dialog in middle of screen */
|
|
+ y = (getmaxy(stdscr)-(prompt_lines+4))/2;
|
|
+ x = (getmaxx(stdscr)-(prompt_width+4))/2;
|
|
+
|
|
+ strncpy(result, init, *result_len);
|
|
+
|
|
+ /* create the windows */
|
|
+ win = newwin(prompt_lines+6, prompt_width+7, y, x);
|
|
+ prompt_win = derwin(win, prompt_lines+1, prompt_width, 2, 2);
|
|
+ form_win = derwin(win, 1, prompt_width, prompt_lines+3, 2);
|
|
+ keypad(form_win, TRUE);
|
|
+
|
|
+ (void) wattrset(form_win, attributes[INPUT_FIELD]);
|
|
+
|
|
+ (void) wattrset(win, attributes[INPUT_BOX]);
|
|
+ box(win, 0, 0);
|
|
+ (void) wattrset(win, attributes[INPUT_HEADING]);
|
|
+ if (title)
|
|
+ mvwprintw(win, 0, 3, "%s", title);
|
|
+
|
|
+ /* print message */
|
|
+ (void) wattrset(prompt_win, attributes[INPUT_TEXT]);
|
|
+ fill_window(prompt_win, prompt);
|
|
+
|
|
+ mvwprintw(form_win, 0, 0, "%*s", prompt_width, " ");
|
|
+ cursor_form_win = min(cursor_position, prompt_width-1);
|
|
+ mvwprintw(form_win, 0, 0, "%s",
|
|
+ result + cursor_position-cursor_form_win);
|
|
+
|
|
+ /* create panels */
|
|
+ panel = new_panel(win);
|
|
+
|
|
+ /* show the cursor */
|
|
+ curs_set(1);
|
|
+
|
|
+ touchwin(win);
|
|
+ refresh_all_windows(main_window);
|
|
+ while ((res = wgetch(form_win))) {
|
|
+ int len = strlen(result);
|
|
+ switch (res) {
|
|
+ case 10: /* ENTER */
|
|
+ case 27: /* ESCAPE */
|
|
+ case KEY_F(F_HELP):
|
|
+ case KEY_F(F_EXIT):
|
|
+ case KEY_F(F_BACK):
|
|
+ break;
|
|
+ case 127:
|
|
+ case KEY_BACKSPACE:
|
|
+ if (cursor_position > 0) {
|
|
+ memmove(&result[cursor_position-1],
|
|
+ &result[cursor_position],
|
|
+ len-cursor_position+1);
|
|
+ cursor_position--;
|
|
+ cursor_form_win--;
|
|
+ len--;
|
|
+ }
|
|
+ break;
|
|
+ case KEY_DC:
|
|
+ if (cursor_position >= 0 && cursor_position < len) {
|
|
+ memmove(&result[cursor_position],
|
|
+ &result[cursor_position+1],
|
|
+ len-cursor_position+1);
|
|
+ len--;
|
|
+ }
|
|
+ break;
|
|
+ case KEY_UP:
|
|
+ case KEY_RIGHT:
|
|
+ if (cursor_position < len) {
|
|
+ cursor_position++;
|
|
+ cursor_form_win++;
|
|
+ }
|
|
+ break;
|
|
+ case KEY_DOWN:
|
|
+ case KEY_LEFT:
|
|
+ if (cursor_position > 0) {
|
|
+ cursor_position--;
|
|
+ cursor_form_win--;
|
|
+ }
|
|
+ break;
|
|
+ case KEY_HOME:
|
|
+ cursor_position = 0;
|
|
+ cursor_form_win = 0;
|
|
+ break;
|
|
+ case KEY_END:
|
|
+ cursor_position = len;
|
|
+ cursor_form_win = min(cursor_position, prompt_width-1);
|
|
+ break;
|
|
+ default:
|
|
+ if ((isgraph(res) || isspace(res))) {
|
|
+ /* one for new char, one for '\0' */
|
|
+ if (len+2 > *result_len) {
|
|
+ *result_len = len+2;
|
|
+ *resultp = result = realloc(result,
|
|
+ *result_len);
|
|
+ }
|
|
+ /* insert the char at the proper position */
|
|
+ memmove(&result[cursor_position+1],
|
|
+ &result[cursor_position],
|
|
+ len-cursor_position+1);
|
|
+ result[cursor_position] = res;
|
|
+ cursor_position++;
|
|
+ cursor_form_win++;
|
|
+ len++;
|
|
+ } else {
|
|
+ mvprintw(0, 0, "unknown key: %d\n", res);
|
|
+ }
|
|
+ break;
|
|
+ }
|
|
+ if (cursor_form_win < 0)
|
|
+ cursor_form_win = 0;
|
|
+ else if (cursor_form_win > prompt_width-1)
|
|
+ cursor_form_win = prompt_width-1;
|
|
+
|
|
+ wmove(form_win, 0, 0);
|
|
+ wclrtoeol(form_win);
|
|
+ mvwprintw(form_win, 0, 0, "%*s", prompt_width, " ");
|
|
+ mvwprintw(form_win, 0, 0, "%s",
|
|
+ result + cursor_position-cursor_form_win);
|
|
+ wmove(form_win, 0, cursor_form_win);
|
|
+ touchwin(win);
|
|
+ refresh_all_windows(main_window);
|
|
+
|
|
+ if (res == 10) {
|
|
+ res = 0;
|
|
+ break;
|
|
+ } else if (res == 27 || res == KEY_F(F_BACK) ||
|
|
+ res == KEY_F(F_EXIT)) {
|
|
+ res = KEY_EXIT;
|
|
+ break;
|
|
+ } else if (res == KEY_F(F_HELP)) {
|
|
+ res = 1;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /* hide the cursor */
|
|
+ curs_set(0);
|
|
+ del_panel(panel);
|
|
+ delwin(prompt_win);
|
|
+ delwin(form_win);
|
|
+ delwin(win);
|
|
+ return res;
|
|
+}
|
|
+
|
|
+/* refresh all windows in the correct order */
|
|
+void refresh_all_windows(WINDOW *main_window)
|
|
+{
|
|
+ update_panels();
|
|
+ touchwin(main_window);
|
|
+ refresh();
|
|
+}
|
|
+
|
|
+/* layman's scrollable window... */
|
|
+void show_scroll_win(WINDOW *main_window,
|
|
+ const char *title,
|
|
+ const char *text)
|
|
+{
|
|
+ int res;
|
|
+ int total_lines = get_line_no(text);
|
|
+ int x, y, lines, columns;
|
|
+ int start_x = 0, start_y = 0;
|
|
+ int text_lines = 0, text_cols = 0;
|
|
+ int total_cols = 0;
|
|
+ int win_cols = 0;
|
|
+ int win_lines = 0;
|
|
+ int i = 0;
|
|
+ WINDOW *win;
|
|
+ WINDOW *pad;
|
|
+ PANEL *panel;
|
|
+
|
|
+ getmaxyx(stdscr, lines, columns);
|
|
+
|
|
+ /* find the widest line of msg: */
|
|
+ total_lines = get_line_no(text);
|
|
+ for (i = 0; i < total_lines; i++) {
|
|
+ const char *line = get_line(text, i);
|
|
+ int len = get_line_length(line);
|
|
+ total_cols = max(total_cols, len+2);
|
|
+ }
|
|
+
|
|
+ /* create the pad */
|
|
+ pad = newpad(total_lines+10, total_cols+10);
|
|
+ (void) wattrset(pad, attributes[SCROLLWIN_TEXT]);
|
|
+ fill_window(pad, text);
|
|
+
|
|
+ win_lines = min(total_lines+4, lines-2);
|
|
+ win_cols = min(total_cols+2, columns-2);
|
|
+ text_lines = max(win_lines-4, 0);
|
|
+ text_cols = max(win_cols-2, 0);
|
|
+
|
|
+ /* place window in middle of screen */
|
|
+ y = (lines-win_lines)/2;
|
|
+ x = (columns-win_cols)/2;
|
|
+
|
|
+ win = newwin(win_lines, win_cols, y, x);
|
|
+ keypad(win, TRUE);
|
|
+ /* show the help in the help window, and show the help panel */
|
|
+ (void) wattrset(win, attributes[SCROLLWIN_BOX]);
|
|
+ box(win, 0, 0);
|
|
+ (void) wattrset(win, attributes[SCROLLWIN_HEADING]);
|
|
+ mvwprintw(win, 0, 3, " %s ", title);
|
|
+ panel = new_panel(win);
|
|
+
|
|
+ /* handle scrolling */
|
|
+ do {
|
|
+
|
|
+ copywin(pad, win, start_y, start_x, 2, 2, text_lines,
|
|
+ text_cols, 0);
|
|
+ print_in_middle(win,
|
|
+ text_lines+2,
|
|
+ 0,
|
|
+ text_cols,
|
|
+ "<OK>",
|
|
+ attributes[DIALOG_MENU_FORE]);
|
|
+ wrefresh(win);
|
|
+
|
|
+ res = wgetch(win);
|
|
+ switch (res) {
|
|
+ case KEY_NPAGE:
|
|
+ case ' ':
|
|
+ case 'd':
|
|
+ start_y += text_lines-2;
|
|
+ break;
|
|
+ case KEY_PPAGE:
|
|
+ case 'u':
|
|
+ start_y -= text_lines+2;
|
|
+ break;
|
|
+ case KEY_HOME:
|
|
+ start_y = 0;
|
|
+ break;
|
|
+ case KEY_END:
|
|
+ start_y = total_lines-text_lines;
|
|
+ break;
|
|
+ case KEY_DOWN:
|
|
+ case 'j':
|
|
+ start_y++;
|
|
+ break;
|
|
+ case KEY_UP:
|
|
+ case 'k':
|
|
+ start_y--;
|
|
+ break;
|
|
+ case KEY_LEFT:
|
|
+ case 'h':
|
|
+ start_x--;
|
|
+ break;
|
|
+ case KEY_RIGHT:
|
|
+ case 'l':
|
|
+ start_x++;
|
|
+ break;
|
|
+ }
|
|
+ if (res == 10 || res == 27 || res == 'q' ||
|
|
+ res == KEY_F(F_HELP) || res == KEY_F(F_BACK) ||
|
|
+ res == KEY_F(F_EXIT))
|
|
+ break;
|
|
+ if (start_y < 0)
|
|
+ start_y = 0;
|
|
+ if (start_y >= total_lines-text_lines)
|
|
+ start_y = total_lines-text_lines;
|
|
+ if (start_x < 0)
|
|
+ start_x = 0;
|
|
+ if (start_x >= total_cols-text_cols)
|
|
+ start_x = total_cols-text_cols;
|
|
+ } while (res);
|
|
+
|
|
+ del_panel(panel);
|
|
+ delwin(win);
|
|
+ refresh_all_windows(main_window);
|
|
+}
|
|
diff --git a/scripts/kconfig/nconf.h b/scripts/kconfig/nconf.h
|
|
new file mode 100644
|
|
index 0000000..0d52617
|
|
--- /dev/null
|
|
+++ b/scripts/kconfig/nconf.h
|
|
@@ -0,0 +1,96 @@
|
|
+/*
|
|
+ * Copyright (C) 2008 Nir Tzachar <nir.tzachar@gmail.com?
|
|
+ * Released under the terms of the GNU GPL v2.0.
|
|
+ *
|
|
+ * Derived from menuconfig.
|
|
+ *
|
|
+ */
|
|
+
|
|
+#include <ctype.h>
|
|
+#include <errno.h>
|
|
+#include <fcntl.h>
|
|
+#include <limits.h>
|
|
+#include <stdarg.h>
|
|
+#include <stdlib.h>
|
|
+#include <string.h>
|
|
+#include <unistd.h>
|
|
+#include <locale.h>
|
|
+#include <curses.h>
|
|
+#include <menu.h>
|
|
+#include <panel.h>
|
|
+#include <form.h>
|
|
+
|
|
+#include <stdio.h>
|
|
+#include <time.h>
|
|
+#include <sys/time.h>
|
|
+
|
|
+#include "ncurses.h"
|
|
+
|
|
+#define max(a, b) ({\
|
|
+ typeof(a) _a = a;\
|
|
+ typeof(b) _b = b;\
|
|
+ _a > _b ? _a : _b; })
|
|
+
|
|
+#define min(a, b) ({\
|
|
+ typeof(a) _a = a;\
|
|
+ typeof(b) _b = b;\
|
|
+ _a < _b ? _a : _b; })
|
|
+
|
|
+typedef enum {
|
|
+ NORMAL = 1,
|
|
+ MAIN_HEADING,
|
|
+ MAIN_MENU_BOX,
|
|
+ MAIN_MENU_FORE,
|
|
+ MAIN_MENU_BACK,
|
|
+ MAIN_MENU_GREY,
|
|
+ MAIN_MENU_HEADING,
|
|
+ SCROLLWIN_TEXT,
|
|
+ SCROLLWIN_HEADING,
|
|
+ SCROLLWIN_BOX,
|
|
+ DIALOG_TEXT,
|
|
+ DIALOG_MENU_FORE,
|
|
+ DIALOG_MENU_BACK,
|
|
+ DIALOG_BOX,
|
|
+ INPUT_BOX,
|
|
+ INPUT_HEADING,
|
|
+ INPUT_TEXT,
|
|
+ INPUT_FIELD,
|
|
+ FUNCTION_TEXT,
|
|
+ FUNCTION_HIGHLIGHT,
|
|
+ ATTR_MAX
|
|
+} attributes_t;
|
|
+extern attributes_t attributes[];
|
|
+
|
|
+typedef enum {
|
|
+ F_HELP = 1,
|
|
+ F_SYMBOL = 2,
|
|
+ F_INSTS = 3,
|
|
+ F_CONF = 4,
|
|
+ F_BACK = 5,
|
|
+ F_SAVE = 6,
|
|
+ F_LOAD = 7,
|
|
+ F_SEARCH = 8,
|
|
+ F_EXIT = 9,
|
|
+} function_key;
|
|
+
|
|
+void set_colors(void);
|
|
+
|
|
+/* this changes the windows attributes !!! */
|
|
+void print_in_middle(WINDOW *win,
|
|
+ int starty,
|
|
+ int startx,
|
|
+ int width,
|
|
+ const char *string,
|
|
+ chtype color);
|
|
+int get_line_length(const char *line);
|
|
+int get_line_no(const char *text);
|
|
+const char *get_line(const char *text, int line_no);
|
|
+void fill_window(WINDOW *win, const char *text);
|
|
+int btn_dialog(WINDOW *main_window, const char *msg, int btn_num, ...);
|
|
+int dialog_inputbox(WINDOW *main_window,
|
|
+ const char *title, const char *prompt,
|
|
+ const char *init, char **resultp, int *result_len);
|
|
+void refresh_all_windows(WINDOW *main_window);
|
|
+void show_scroll_win(WINDOW *main_window,
|
|
+ const char *title,
|
|
+ const char *text);
|
|
diff --git a/scripts/kconfig/qconf.cc b/scripts/kconfig/qconf.cc
|
|
new file mode 100644
|
|
index 0000000..9d3b04b
|
|
--- /dev/null
|
|
+++ b/scripts/kconfig/qconf.cc
|
|
@@ -0,0 +1,1795 @@
|
|
+/*
|
|
+ * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
|
|
+ * Released under the terms of the GNU GPL v2.0.
|
|
+ */
|
|
+
|
|
+#include <qglobal.h>
|
|
+
|
|
+#if QT_VERSION < 0x040000
|
|
+#include <stddef.h>
|
|
+#include <qmainwindow.h>
|
|
+#include <qvbox.h>
|
|
+#include <qvaluelist.h>
|
|
+#include <qtextbrowser.h>
|
|
+#include <qaction.h>
|
|
+#include <qheader.h>
|
|
+#include <qfiledialog.h>
|
|
+#include <qdragobject.h>
|
|
+#include <qpopupmenu.h>
|
|
+#else
|
|
+#include <q3mainwindow.h>
|
|
+#include <q3vbox.h>
|
|
+#include <q3valuelist.h>
|
|
+#include <q3textbrowser.h>
|
|
+#include <q3action.h>
|
|
+#include <q3header.h>
|
|
+#include <q3filedialog.h>
|
|
+#include <q3dragobject.h>
|
|
+#include <q3popupmenu.h>
|
|
+#endif
|
|
+
|
|
+#include <qapplication.h>
|
|
+#include <qdesktopwidget.h>
|
|
+#include <qtoolbar.h>
|
|
+#include <qlayout.h>
|
|
+#include <qsplitter.h>
|
|
+#include <qlineedit.h>
|
|
+#include <qlabel.h>
|
|
+#include <qpushbutton.h>
|
|
+#include <qmenubar.h>
|
|
+#include <qmessagebox.h>
|
|
+#include <qregexp.h>
|
|
+#include <qevent.h>
|
|
+
|
|
+#include <stdlib.h>
|
|
+
|
|
+#include "lkc.h"
|
|
+#include "qconf.h"
|
|
+
|
|
+#include "qconf.moc"
|
|
+#include "images.c"
|
|
+
|
|
+#ifdef _
|
|
+# undef _
|
|
+# define _ qgettext
|
|
+#endif
|
|
+
|
|
+static QApplication *configApp;
|
|
+static ConfigSettings *configSettings;
|
|
+
|
|
+Q3Action *ConfigMainWindow::saveAction;
|
|
+
|
|
+static inline QString qgettext(const char* str)
|
|
+{
|
|
+ return QString::fromLocal8Bit(gettext(str));
|
|
+}
|
|
+
|
|
+static inline QString qgettext(const QString& str)
|
|
+{
|
|
+ return QString::fromLocal8Bit(gettext(str.latin1()));
|
|
+}
|
|
+
|
|
+ConfigSettings::ConfigSettings()
|
|
+ : QSettings("kernel.org", "qconf")
|
|
+{
|
|
+}
|
|
+
|
|
+/**
|
|
+ * Reads a list of integer values from the application settings.
|
|
+ */
|
|
+Q3ValueList<int> ConfigSettings::readSizes(const QString& key, bool *ok)
|
|
+{
|
|
+ Q3ValueList<int> result;
|
|
+ QStringList entryList = readListEntry(key, ok);
|
|
+ QStringList::Iterator it;
|
|
+
|
|
+ for (it = entryList.begin(); it != entryList.end(); ++it)
|
|
+ result.push_back((*it).toInt());
|
|
+
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * Writes a list of integer values to the application settings.
|
|
+ */
|
|
+bool ConfigSettings::writeSizes(const QString& key, const Q3ValueList<int>& value)
|
|
+{
|
|
+ QStringList stringList;
|
|
+ Q3ValueList<int>::ConstIterator it;
|
|
+
|
|
+ for (it = value.begin(); it != value.end(); ++it)
|
|
+ stringList.push_back(QString::number(*it));
|
|
+ return writeEntry(key, stringList);
|
|
+}
|
|
+
|
|
+
|
|
+/*
|
|
+ * set the new data
|
|
+ * TODO check the value
|
|
+ */
|
|
+void ConfigItem::okRename(int col)
|
|
+{
|
|
+ Parent::okRename(col);
|
|
+ sym_set_string_value(menu->sym, text(dataColIdx).latin1());
|
|
+ listView()->updateList(this);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * update the displayed of a menu entry
|
|
+ */
|
|
+void ConfigItem::updateMenu(void)
|
|
+{
|
|
+ ConfigList* list;
|
|
+ struct symbol* sym;
|
|
+ struct property *prop;
|
|
+ QString prompt;
|
|
+ int type;
|
|
+ tristate expr;
|
|
+
|
|
+ list = listView();
|
|
+ if (goParent) {
|
|
+ setPixmap(promptColIdx, list->menuBackPix);
|
|
+ prompt = "..";
|
|
+ goto set_prompt;
|
|
+ }
|
|
+
|
|
+ sym = menu->sym;
|
|
+ prop = menu->prompt;
|
|
+ prompt = _(menu_get_prompt(menu));
|
|
+
|
|
+ if (prop) switch (prop->type) {
|
|
+ case P_MENU:
|
|
+ if (list->mode == singleMode || list->mode == symbolMode) {
|
|
+ /* a menuconfig entry is displayed differently
|
|
+ * depending whether it's at the view root or a child.
|
|
+ */
|
|
+ if (sym && list->rootEntry == menu)
|
|
+ break;
|
|
+ setPixmap(promptColIdx, list->menuPix);
|
|
+ } else {
|
|
+ if (sym)
|
|
+ break;
|
|
+ setPixmap(promptColIdx, 0);
|
|
+ }
|
|
+ goto set_prompt;
|
|
+ case P_COMMENT:
|
|
+ setPixmap(promptColIdx, 0);
|
|
+ goto set_prompt;
|
|
+ default:
|
|
+ ;
|
|
+ }
|
|
+ if (!sym)
|
|
+ goto set_prompt;
|
|
+
|
|
+ setText(nameColIdx, QString::fromLocal8Bit(sym->name));
|
|
+
|
|
+ type = sym_get_type(sym);
|
|
+ switch (type) {
|
|
+ case S_BOOLEAN:
|
|
+ case S_TRISTATE:
|
|
+ char ch;
|
|
+
|
|
+ if (!sym_is_changable(sym) && list->optMode == normalOpt) {
|
|
+ setPixmap(promptColIdx, 0);
|
|
+ setText(noColIdx, QString::null);
|
|
+ setText(modColIdx, QString::null);
|
|
+ setText(yesColIdx, QString::null);
|
|
+ break;
|
|
+ }
|
|
+ expr = sym_get_tristate_value(sym);
|
|
+ switch (expr) {
|
|
+ case yes:
|
|
+ if (sym_is_choice_value(sym) && type == S_BOOLEAN)
|
|
+ setPixmap(promptColIdx, list->choiceYesPix);
|
|
+ else
|
|
+ setPixmap(promptColIdx, list->symbolYesPix);
|
|
+ setText(yesColIdx, "Y");
|
|
+ ch = 'Y';
|
|
+ break;
|
|
+ case mod:
|
|
+ setPixmap(promptColIdx, list->symbolModPix);
|
|
+ setText(modColIdx, "M");
|
|
+ ch = 'M';
|
|
+ break;
|
|
+ default:
|
|
+ if (sym_is_choice_value(sym) && type == S_BOOLEAN)
|
|
+ setPixmap(promptColIdx, list->choiceNoPix);
|
|
+ else
|
|
+ setPixmap(promptColIdx, list->symbolNoPix);
|
|
+ setText(noColIdx, "N");
|
|
+ ch = 'N';
|
|
+ break;
|
|
+ }
|
|
+ if (expr != no)
|
|
+ setText(noColIdx, sym_tristate_within_range(sym, no) ? "_" : 0);
|
|
+ if (expr != mod)
|
|
+ setText(modColIdx, sym_tristate_within_range(sym, mod) ? "_" : 0);
|
|
+ if (expr != yes)
|
|
+ setText(yesColIdx, sym_tristate_within_range(sym, yes) ? "_" : 0);
|
|
+
|
|
+ setText(dataColIdx, QChar(ch));
|
|
+ break;
|
|
+ case S_INT:
|
|
+ case S_HEX:
|
|
+ case S_STRING:
|
|
+ const char* data;
|
|
+
|
|
+ data = sym_get_string_value(sym);
|
|
+
|
|
+ int i = list->mapIdx(dataColIdx);
|
|
+ if (i >= 0)
|
|
+ setRenameEnabled(i, TRUE);
|
|
+ setText(dataColIdx, data);
|
|
+ if (type == S_STRING)
|
|
+ prompt = QString("%1: %2").arg(prompt).arg(data);
|
|
+ else
|
|
+ prompt = QString("(%2) %1").arg(prompt).arg(data);
|
|
+ break;
|
|
+ }
|
|
+ if (!sym_has_value(sym) && visible)
|
|
+ prompt += _(" (NEW)");
|
|
+set_prompt:
|
|
+ setText(promptColIdx, prompt);
|
|
+}
|
|
+
|
|
+void ConfigItem::testUpdateMenu(bool v)
|
|
+{
|
|
+ ConfigItem* i;
|
|
+
|
|
+ visible = v;
|
|
+ if (!menu)
|
|
+ return;
|
|
+
|
|
+ sym_calc_value(menu->sym);
|
|
+ if (menu->flags & MENU_CHANGED) {
|
|
+ /* the menu entry changed, so update all list items */
|
|
+ menu->flags &= ~MENU_CHANGED;
|
|
+ for (i = (ConfigItem*)menu->data; i; i = i->nextItem)
|
|
+ i->updateMenu();
|
|
+ } else if (listView()->updateAll)
|
|
+ updateMenu();
|
|
+}
|
|
+
|
|
+void ConfigItem::paintCell(QPainter* p, const QColorGroup& cg, int column, int width, int align)
|
|
+{
|
|
+ ConfigList* list = listView();
|
|
+
|
|
+ if (visible) {
|
|
+ if (isSelected() && !list->hasFocus() && list->mode == menuMode)
|
|
+ Parent::paintCell(p, list->inactivedColorGroup, column, width, align);
|
|
+ else
|
|
+ Parent::paintCell(p, cg, column, width, align);
|
|
+ } else
|
|
+ Parent::paintCell(p, list->disabledColorGroup, column, width, align);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * construct a menu entry
|
|
+ */
|
|
+void ConfigItem::init(void)
|
|
+{
|
|
+ if (menu) {
|
|
+ ConfigList* list = listView();
|
|
+ nextItem = (ConfigItem*)menu->data;
|
|
+ menu->data = this;
|
|
+
|
|
+ if (list->mode != fullMode)
|
|
+ setOpen(TRUE);
|
|
+ sym_calc_value(menu->sym);
|
|
+ }
|
|
+ updateMenu();
|
|
+}
|
|
+
|
|
+/*
|
|
+ * destruct a menu entry
|
|
+ */
|
|
+ConfigItem::~ConfigItem(void)
|
|
+{
|
|
+ if (menu) {
|
|
+ ConfigItem** ip = (ConfigItem**)&menu->data;
|
|
+ for (; *ip; ip = &(*ip)->nextItem) {
|
|
+ if (*ip == this) {
|
|
+ *ip = nextItem;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+ConfigLineEdit::ConfigLineEdit(ConfigView* parent)
|
|
+ : Parent(parent)
|
|
+{
|
|
+ connect(this, SIGNAL(lostFocus()), SLOT(hide()));
|
|
+}
|
|
+
|
|
+void ConfigLineEdit::show(ConfigItem* i)
|
|
+{
|
|
+ item = i;
|
|
+ if (sym_get_string_value(item->menu->sym))
|
|
+ setText(QString::fromLocal8Bit(sym_get_string_value(item->menu->sym)));
|
|
+ else
|
|
+ setText(QString::null);
|
|
+ Parent::show();
|
|
+ setFocus();
|
|
+}
|
|
+
|
|
+void ConfigLineEdit::keyPressEvent(QKeyEvent* e)
|
|
+{
|
|
+ switch (e->key()) {
|
|
+ case Qt::Key_Escape:
|
|
+ break;
|
|
+ case Qt::Key_Return:
|
|
+ case Qt::Key_Enter:
|
|
+ sym_set_string_value(item->menu->sym, text().latin1());
|
|
+ parent()->updateList(item);
|
|
+ break;
|
|
+ default:
|
|
+ Parent::keyPressEvent(e);
|
|
+ return;
|
|
+ }
|
|
+ e->accept();
|
|
+ parent()->list->setFocus();
|
|
+ hide();
|
|
+}
|
|
+
|
|
+ConfigList::ConfigList(ConfigView* p, const char *name)
|
|
+ : Parent(p, name),
|
|
+ updateAll(false),
|
|
+ symbolYesPix(xpm_symbol_yes), symbolModPix(xpm_symbol_mod), symbolNoPix(xpm_symbol_no),
|
|
+ choiceYesPix(xpm_choice_yes), choiceNoPix(xpm_choice_no),
|
|
+ menuPix(xpm_menu), menuInvPix(xpm_menu_inv), menuBackPix(xpm_menuback), voidPix(xpm_void),
|
|
+ showName(false), showRange(false), showData(false), optMode(normalOpt),
|
|
+ rootEntry(0), headerPopup(0)
|
|
+{
|
|
+ int i;
|
|
+
|
|
+ setSorting(-1);
|
|
+ setRootIsDecorated(TRUE);
|
|
+ disabledColorGroup = palette().active();
|
|
+ disabledColorGroup.setColor(QColorGroup::Text, palette().disabled().text());
|
|
+ inactivedColorGroup = palette().active();
|
|
+ inactivedColorGroup.setColor(QColorGroup::Highlight, palette().disabled().highlight());
|
|
+
|
|
+ connect(this, SIGNAL(selectionChanged(void)),
|
|
+ SLOT(updateSelection(void)));
|
|
+
|
|
+ if (name) {
|
|
+ configSettings->beginGroup(name);
|
|
+ showName = configSettings->readBoolEntry("/showName", false);
|
|
+ showRange = configSettings->readBoolEntry("/showRange", false);
|
|
+ showData = configSettings->readBoolEntry("/showData", false);
|
|
+ optMode = (enum optionMode)configSettings->readNumEntry("/optionMode", false);
|
|
+ configSettings->endGroup();
|
|
+ connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
|
|
+ }
|
|
+
|
|
+ for (i = 0; i < colNr; i++)
|
|
+ colMap[i] = colRevMap[i] = -1;
|
|
+ addColumn(promptColIdx, _("Option"));
|
|
+
|
|
+ reinit();
|
|
+}
|
|
+
|
|
+bool ConfigList::menuSkip(struct menu *menu)
|
|
+{
|
|
+ if (optMode == normalOpt && menu_is_visible(menu))
|
|
+ return false;
|
|
+ if (optMode == promptOpt && menu_has_prompt(menu))
|
|
+ return false;
|
|
+ if (optMode == allOpt)
|
|
+ return false;
|
|
+ return true;
|
|
+}
|
|
+
|
|
+void ConfigList::reinit(void)
|
|
+{
|
|
+ removeColumn(dataColIdx);
|
|
+ removeColumn(yesColIdx);
|
|
+ removeColumn(modColIdx);
|
|
+ removeColumn(noColIdx);
|
|
+ removeColumn(nameColIdx);
|
|
+
|
|
+ if (showName)
|
|
+ addColumn(nameColIdx, _("Name"));
|
|
+ if (showRange) {
|
|
+ addColumn(noColIdx, "N");
|
|
+ addColumn(modColIdx, "M");
|
|
+ addColumn(yesColIdx, "Y");
|
|
+ }
|
|
+ if (showData)
|
|
+ addColumn(dataColIdx, _("Value"));
|
|
+
|
|
+ updateListAll();
|
|
+}
|
|
+
|
|
+void ConfigList::saveSettings(void)
|
|
+{
|
|
+ if (name()) {
|
|
+ configSettings->beginGroup(name());
|
|
+ configSettings->writeEntry("/showName", showName);
|
|
+ configSettings->writeEntry("/showRange", showRange);
|
|
+ configSettings->writeEntry("/showData", showData);
|
|
+ configSettings->writeEntry("/optionMode", (int)optMode);
|
|
+ configSettings->endGroup();
|
|
+ }
|
|
+}
|
|
+
|
|
+ConfigItem* ConfigList::findConfigItem(struct menu *menu)
|
|
+{
|
|
+ ConfigItem* item = (ConfigItem*)menu->data;
|
|
+
|
|
+ for (; item; item = item->nextItem) {
|
|
+ if (this == item->listView())
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ return item;
|
|
+}
|
|
+
|
|
+void ConfigList::updateSelection(void)
|
|
+{
|
|
+ struct menu *menu;
|
|
+ enum prop_type type;
|
|
+
|
|
+ ConfigItem* item = (ConfigItem*)selectedItem();
|
|
+ if (!item)
|
|
+ return;
|
|
+
|
|
+ menu = item->menu;
|
|
+ emit menuChanged(menu);
|
|
+ if (!menu)
|
|
+ return;
|
|
+ type = menu->prompt ? menu->prompt->type : P_UNKNOWN;
|
|
+ if (mode == menuMode && type == P_MENU)
|
|
+ emit menuSelected(menu);
|
|
+}
|
|
+
|
|
+void ConfigList::updateList(ConfigItem* item)
|
|
+{
|
|
+ ConfigItem* last = 0;
|
|
+
|
|
+ if (!rootEntry) {
|
|
+ if (mode != listMode)
|
|
+ goto update;
|
|
+ Q3ListViewItemIterator it(this);
|
|
+ ConfigItem* item;
|
|
+
|
|
+ for (; it.current(); ++it) {
|
|
+ item = (ConfigItem*)it.current();
|
|
+ if (!item->menu)
|
|
+ continue;
|
|
+ item->testUpdateMenu(menu_is_visible(item->menu));
|
|
+ }
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ if (rootEntry != &rootmenu && (mode == singleMode ||
|
|
+ (mode == symbolMode && rootEntry->parent != &rootmenu))) {
|
|
+ item = firstChild();
|
|
+ if (!item)
|
|
+ item = new ConfigItem(this, 0, true);
|
|
+ last = item;
|
|
+ }
|
|
+ if ((mode == singleMode || (mode == symbolMode && !(rootEntry->flags & MENU_ROOT))) &&
|
|
+ rootEntry->sym && rootEntry->prompt) {
|
|
+ item = last ? last->nextSibling() : firstChild();
|
|
+ if (!item)
|
|
+ item = new ConfigItem(this, last, rootEntry, true);
|
|
+ else
|
|
+ item->testUpdateMenu(true);
|
|
+
|
|
+ updateMenuList(item, rootEntry);
|
|
+ triggerUpdate();
|
|
+ return;
|
|
+ }
|
|
+update:
|
|
+ updateMenuList(this, rootEntry);
|
|
+ triggerUpdate();
|
|
+}
|
|
+
|
|
+void ConfigList::setValue(ConfigItem* item, tristate val)
|
|
+{
|
|
+ struct symbol* sym;
|
|
+ int type;
|
|
+ tristate oldval;
|
|
+
|
|
+ sym = item->menu ? item->menu->sym : 0;
|
|
+ if (!sym)
|
|
+ return;
|
|
+
|
|
+ type = sym_get_type(sym);
|
|
+ switch (type) {
|
|
+ case S_BOOLEAN:
|
|
+ case S_TRISTATE:
|
|
+ oldval = sym_get_tristate_value(sym);
|
|
+
|
|
+ if (!sym_set_tristate_value(sym, val))
|
|
+ return;
|
|
+ if (oldval == no && item->menu->list)
|
|
+ item->setOpen(TRUE);
|
|
+ parent()->updateList(item);
|
|
+ break;
|
|
+ }
|
|
+}
|
|
+
|
|
+void ConfigList::changeValue(ConfigItem* item)
|
|
+{
|
|
+ struct symbol* sym;
|
|
+ struct menu* menu;
|
|
+ int type, oldexpr, newexpr;
|
|
+
|
|
+ menu = item->menu;
|
|
+ if (!menu)
|
|
+ return;
|
|
+ sym = menu->sym;
|
|
+ if (!sym) {
|
|
+ if (item->menu->list)
|
|
+ item->setOpen(!item->isOpen());
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ type = sym_get_type(sym);
|
|
+ switch (type) {
|
|
+ case S_BOOLEAN:
|
|
+ case S_TRISTATE:
|
|
+ oldexpr = sym_get_tristate_value(sym);
|
|
+ newexpr = sym_toggle_tristate_value(sym);
|
|
+ if (item->menu->list) {
|
|
+ if (oldexpr == newexpr)
|
|
+ item->setOpen(!item->isOpen());
|
|
+ else if (oldexpr == no)
|
|
+ item->setOpen(TRUE);
|
|
+ }
|
|
+ if (oldexpr != newexpr)
|
|
+ parent()->updateList(item);
|
|
+ break;
|
|
+ case S_INT:
|
|
+ case S_HEX:
|
|
+ case S_STRING:
|
|
+ if (colMap[dataColIdx] >= 0)
|
|
+ item->startRename(colMap[dataColIdx]);
|
|
+ else
|
|
+ parent()->lineEdit->show(item);
|
|
+ break;
|
|
+ }
|
|
+}
|
|
+
|
|
+void ConfigList::setRootMenu(struct menu *menu)
|
|
+{
|
|
+ enum prop_type type;
|
|
+
|
|
+ if (rootEntry == menu)
|
|
+ return;
|
|
+ type = menu && menu->prompt ? menu->prompt->type : P_UNKNOWN;
|
|
+ if (type != P_MENU)
|
|
+ return;
|
|
+ updateMenuList(this, 0);
|
|
+ rootEntry = menu;
|
|
+ updateListAll();
|
|
+ setSelected(currentItem(), hasFocus());
|
|
+ ensureItemVisible(currentItem());
|
|
+}
|
|
+
|
|
+void ConfigList::setParentMenu(void)
|
|
+{
|
|
+ ConfigItem* item;
|
|
+ struct menu *oldroot;
|
|
+
|
|
+ oldroot = rootEntry;
|
|
+ if (rootEntry == &rootmenu)
|
|
+ return;
|
|
+ setRootMenu(menu_get_parent_menu(rootEntry->parent));
|
|
+
|
|
+ Q3ListViewItemIterator it(this);
|
|
+ for (; (item = (ConfigItem*)it.current()); it++) {
|
|
+ if (item->menu == oldroot) {
|
|
+ setCurrentItem(item);
|
|
+ ensureItemVisible(item);
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+/*
|
|
+ * update all the children of a menu entry
|
|
+ * removes/adds the entries from the parent widget as necessary
|
|
+ *
|
|
+ * parent: either the menu list widget or a menu entry widget
|
|
+ * menu: entry to be updated
|
|
+ */
|
|
+template <class P>
|
|
+void ConfigList::updateMenuList(P* parent, struct menu* menu)
|
|
+{
|
|
+ struct menu* child;
|
|
+ ConfigItem* item;
|
|
+ ConfigItem* last;
|
|
+ bool visible;
|
|
+ enum prop_type type;
|
|
+
|
|
+ if (!menu) {
|
|
+ while ((item = parent->firstChild()))
|
|
+ delete item;
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ last = parent->firstChild();
|
|
+ if (last && !last->goParent)
|
|
+ last = 0;
|
|
+ for (child = menu->list; child; child = child->next) {
|
|
+ item = last ? last->nextSibling() : parent->firstChild();
|
|
+ type = child->prompt ? child->prompt->type : P_UNKNOWN;
|
|
+
|
|
+ switch (mode) {
|
|
+ case menuMode:
|
|
+ if (!(child->flags & MENU_ROOT))
|
|
+ goto hide;
|
|
+ break;
|
|
+ case symbolMode:
|
|
+ if (child->flags & MENU_ROOT)
|
|
+ goto hide;
|
|
+ break;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ visible = menu_is_visible(child);
|
|
+ if (!menuSkip(child)) {
|
|
+ if (!child->sym && !child->list && !child->prompt)
|
|
+ continue;
|
|
+ if (!item || item->menu != child)
|
|
+ item = new ConfigItem(parent, last, child, visible);
|
|
+ else
|
|
+ item->testUpdateMenu(visible);
|
|
+
|
|
+ if (mode == fullMode || mode == menuMode || type != P_MENU)
|
|
+ updateMenuList(item, child);
|
|
+ else
|
|
+ updateMenuList(item, 0);
|
|
+ last = item;
|
|
+ continue;
|
|
+ }
|
|
+ hide:
|
|
+ if (item && item->menu == child) {
|
|
+ last = parent->firstChild();
|
|
+ if (last == item)
|
|
+ last = 0;
|
|
+ else while (last->nextSibling() != item)
|
|
+ last = last->nextSibling();
|
|
+ delete item;
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+void ConfigList::keyPressEvent(QKeyEvent* ev)
|
|
+{
|
|
+ Q3ListViewItem* i = currentItem();
|
|
+ ConfigItem* item;
|
|
+ struct menu *menu;
|
|
+ enum prop_type type;
|
|
+
|
|
+ if (ev->key() == Qt::Key_Escape && mode != fullMode && mode != listMode) {
|
|
+ emit parentSelected();
|
|
+ ev->accept();
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ if (!i) {
|
|
+ Parent::keyPressEvent(ev);
|
|
+ return;
|
|
+ }
|
|
+ item = (ConfigItem*)i;
|
|
+
|
|
+ switch (ev->key()) {
|
|
+ case Qt::Key_Return:
|
|
+ case Qt::Key_Enter:
|
|
+ if (item->goParent) {
|
|
+ emit parentSelected();
|
|
+ break;
|
|
+ }
|
|
+ menu = item->menu;
|
|
+ if (!menu)
|
|
+ break;
|
|
+ type = menu->prompt ? menu->prompt->type : P_UNKNOWN;
|
|
+ if (type == P_MENU && rootEntry != menu &&
|
|
+ mode != fullMode && mode != menuMode) {
|
|
+ emit menuSelected(menu);
|
|
+ break;
|
|
+ }
|
|
+ case Qt::Key_Space:
|
|
+ changeValue(item);
|
|
+ break;
|
|
+ case Qt::Key_N:
|
|
+ setValue(item, no);
|
|
+ break;
|
|
+ case Qt::Key_M:
|
|
+ setValue(item, mod);
|
|
+ break;
|
|
+ case Qt::Key_Y:
|
|
+ setValue(item, yes);
|
|
+ break;
|
|
+ default:
|
|
+ Parent::keyPressEvent(ev);
|
|
+ return;
|
|
+ }
|
|
+ ev->accept();
|
|
+}
|
|
+
|
|
+void ConfigList::contentsMousePressEvent(QMouseEvent* e)
|
|
+{
|
|
+ //QPoint p(contentsToViewport(e->pos()));
|
|
+ //printf("contentsMousePressEvent: %d,%d\n", p.x(), p.y());
|
|
+ Parent::contentsMousePressEvent(e);
|
|
+}
|
|
+
|
|
+void ConfigList::contentsMouseReleaseEvent(QMouseEvent* e)
|
|
+{
|
|
+ QPoint p(contentsToViewport(e->pos()));
|
|
+ ConfigItem* item = (ConfigItem*)itemAt(p);
|
|
+ struct menu *menu;
|
|
+ enum prop_type ptype;
|
|
+ const QPixmap* pm;
|
|
+ int idx, x;
|
|
+
|
|
+ if (!item)
|
|
+ goto skip;
|
|
+
|
|
+ menu = item->menu;
|
|
+ x = header()->offset() + p.x();
|
|
+ idx = colRevMap[header()->sectionAt(x)];
|
|
+ switch (idx) {
|
|
+ case promptColIdx:
|
|
+ pm = item->pixmap(promptColIdx);
|
|
+ if (pm) {
|
|
+ int off = header()->sectionPos(0) + itemMargin() +
|
|
+ treeStepSize() * (item->depth() + (rootIsDecorated() ? 1 : 0));
|
|
+ if (x >= off && x < off + pm->width()) {
|
|
+ if (item->goParent) {
|
|
+ emit parentSelected();
|
|
+ break;
|
|
+ } else if (!menu)
|
|
+ break;
|
|
+ ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
|
|
+ if (ptype == P_MENU && rootEntry != menu &&
|
|
+ mode != fullMode && mode != menuMode)
|
|
+ emit menuSelected(menu);
|
|
+ else
|
|
+ changeValue(item);
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+ case noColIdx:
|
|
+ setValue(item, no);
|
|
+ break;
|
|
+ case modColIdx:
|
|
+ setValue(item, mod);
|
|
+ break;
|
|
+ case yesColIdx:
|
|
+ setValue(item, yes);
|
|
+ break;
|
|
+ case dataColIdx:
|
|
+ changeValue(item);
|
|
+ break;
|
|
+ }
|
|
+
|
|
+skip:
|
|
+ //printf("contentsMouseReleaseEvent: %d,%d\n", p.x(), p.y());
|
|
+ Parent::contentsMouseReleaseEvent(e);
|
|
+}
|
|
+
|
|
+void ConfigList::contentsMouseMoveEvent(QMouseEvent* e)
|
|
+{
|
|
+ //QPoint p(contentsToViewport(e->pos()));
|
|
+ //printf("contentsMouseMoveEvent: %d,%d\n", p.x(), p.y());
|
|
+ Parent::contentsMouseMoveEvent(e);
|
|
+}
|
|
+
|
|
+void ConfigList::contentsMouseDoubleClickEvent(QMouseEvent* e)
|
|
+{
|
|
+ QPoint p(contentsToViewport(e->pos()));
|
|
+ ConfigItem* item = (ConfigItem*)itemAt(p);
|
|
+ struct menu *menu;
|
|
+ enum prop_type ptype;
|
|
+
|
|
+ if (!item)
|
|
+ goto skip;
|
|
+ if (item->goParent) {
|
|
+ emit parentSelected();
|
|
+ goto skip;
|
|
+ }
|
|
+ menu = item->menu;
|
|
+ if (!menu)
|
|
+ goto skip;
|
|
+ ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
|
|
+ if (ptype == P_MENU && (mode == singleMode || mode == symbolMode))
|
|
+ emit menuSelected(menu);
|
|
+ else if (menu->sym)
|
|
+ changeValue(item);
|
|
+
|
|
+skip:
|
|
+ //printf("contentsMouseDoubleClickEvent: %d,%d\n", p.x(), p.y());
|
|
+ Parent::contentsMouseDoubleClickEvent(e);
|
|
+}
|
|
+
|
|
+void ConfigList::focusInEvent(QFocusEvent *e)
|
|
+{
|
|
+ struct menu *menu = NULL;
|
|
+
|
|
+ Parent::focusInEvent(e);
|
|
+
|
|
+ ConfigItem* item = (ConfigItem *)currentItem();
|
|
+ if (item) {
|
|
+ setSelected(item, TRUE);
|
|
+ menu = item->menu;
|
|
+ }
|
|
+ emit gotFocus(menu);
|
|
+}
|
|
+
|
|
+void ConfigList::contextMenuEvent(QContextMenuEvent *e)
|
|
+{
|
|
+ if (e->y() <= header()->geometry().bottom()) {
|
|
+ if (!headerPopup) {
|
|
+ Q3Action *action;
|
|
+
|
|
+ headerPopup = new Q3PopupMenu(this);
|
|
+ action = new Q3Action(NULL, _("Show Name"), 0, this);
|
|
+ action->setToggleAction(TRUE);
|
|
+ connect(action, SIGNAL(toggled(bool)),
|
|
+ parent(), SLOT(setShowName(bool)));
|
|
+ connect(parent(), SIGNAL(showNameChanged(bool)),
|
|
+ action, SLOT(setOn(bool)));
|
|
+ action->setOn(showName);
|
|
+ action->addTo(headerPopup);
|
|
+ action = new Q3Action(NULL, _("Show Range"), 0, this);
|
|
+ action->setToggleAction(TRUE);
|
|
+ connect(action, SIGNAL(toggled(bool)),
|
|
+ parent(), SLOT(setShowRange(bool)));
|
|
+ connect(parent(), SIGNAL(showRangeChanged(bool)),
|
|
+ action, SLOT(setOn(bool)));
|
|
+ action->setOn(showRange);
|
|
+ action->addTo(headerPopup);
|
|
+ action = new Q3Action(NULL, _("Show Data"), 0, this);
|
|
+ action->setToggleAction(TRUE);
|
|
+ connect(action, SIGNAL(toggled(bool)),
|
|
+ parent(), SLOT(setShowData(bool)));
|
|
+ connect(parent(), SIGNAL(showDataChanged(bool)),
|
|
+ action, SLOT(setOn(bool)));
|
|
+ action->setOn(showData);
|
|
+ action->addTo(headerPopup);
|
|
+ }
|
|
+ headerPopup->exec(e->globalPos());
|
|
+ e->accept();
|
|
+ } else
|
|
+ e->ignore();
|
|
+}
|
|
+
|
|
+ConfigView*ConfigView::viewList;
|
|
+QAction *ConfigView::showNormalAction;
|
|
+QAction *ConfigView::showAllAction;
|
|
+QAction *ConfigView::showPromptAction;
|
|
+
|
|
+ConfigView::ConfigView(QWidget* parent, const char *name)
|
|
+ : Parent(parent, name)
|
|
+{
|
|
+ list = new ConfigList(this, name);
|
|
+ lineEdit = new ConfigLineEdit(this);
|
|
+ lineEdit->hide();
|
|
+
|
|
+ this->nextView = viewList;
|
|
+ viewList = this;
|
|
+}
|
|
+
|
|
+ConfigView::~ConfigView(void)
|
|
+{
|
|
+ ConfigView** vp;
|
|
+
|
|
+ for (vp = &viewList; *vp; vp = &(*vp)->nextView) {
|
|
+ if (*vp == this) {
|
|
+ *vp = nextView;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+void ConfigView::setOptionMode(QAction *act)
|
|
+{
|
|
+ if (act == showNormalAction)
|
|
+ list->optMode = normalOpt;
|
|
+ else if (act == showAllAction)
|
|
+ list->optMode = allOpt;
|
|
+ else
|
|
+ list->optMode = promptOpt;
|
|
+
|
|
+ list->updateListAll();
|
|
+}
|
|
+
|
|
+void ConfigView::setShowName(bool b)
|
|
+{
|
|
+ if (list->showName != b) {
|
|
+ list->showName = b;
|
|
+ list->reinit();
|
|
+ emit showNameChanged(b);
|
|
+ }
|
|
+}
|
|
+
|
|
+void ConfigView::setShowRange(bool b)
|
|
+{
|
|
+ if (list->showRange != b) {
|
|
+ list->showRange = b;
|
|
+ list->reinit();
|
|
+ emit showRangeChanged(b);
|
|
+ }
|
|
+}
|
|
+
|
|
+void ConfigView::setShowData(bool b)
|
|
+{
|
|
+ if (list->showData != b) {
|
|
+ list->showData = b;
|
|
+ list->reinit();
|
|
+ emit showDataChanged(b);
|
|
+ }
|
|
+}
|
|
+
|
|
+void ConfigList::setAllOpen(bool open)
|
|
+{
|
|
+ Q3ListViewItemIterator it(this);
|
|
+
|
|
+ for (; it.current(); it++)
|
|
+ it.current()->setOpen(open);
|
|
+}
|
|
+
|
|
+void ConfigView::updateList(ConfigItem* item)
|
|
+{
|
|
+ ConfigView* v;
|
|
+
|
|
+ for (v = viewList; v; v = v->nextView)
|
|
+ v->list->updateList(item);
|
|
+}
|
|
+
|
|
+void ConfigView::updateListAll(void)
|
|
+{
|
|
+ ConfigView* v;
|
|
+
|
|
+ for (v = viewList; v; v = v->nextView)
|
|
+ v->list->updateListAll();
|
|
+}
|
|
+
|
|
+ConfigInfoView::ConfigInfoView(QWidget* parent, const char *name)
|
|
+ : Parent(parent, name), sym(0), _menu(0)
|
|
+{
|
|
+ if (name) {
|
|
+ configSettings->beginGroup(name);
|
|
+ _showDebug = configSettings->readBoolEntry("/showDebug", false);
|
|
+ configSettings->endGroup();
|
|
+ connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
|
|
+ }
|
|
+}
|
|
+
|
|
+void ConfigInfoView::saveSettings(void)
|
|
+{
|
|
+ if (name()) {
|
|
+ configSettings->beginGroup(name());
|
|
+ configSettings->writeEntry("/showDebug", showDebug());
|
|
+ configSettings->endGroup();
|
|
+ }
|
|
+}
|
|
+
|
|
+void ConfigInfoView::setShowDebug(bool b)
|
|
+{
|
|
+ if (_showDebug != b) {
|
|
+ _showDebug = b;
|
|
+ if (_menu)
|
|
+ menuInfo();
|
|
+ else if (sym)
|
|
+ symbolInfo();
|
|
+ emit showDebugChanged(b);
|
|
+ }
|
|
+}
|
|
+
|
|
+void ConfigInfoView::setInfo(struct menu *m)
|
|
+{
|
|
+ if (_menu == m)
|
|
+ return;
|
|
+ _menu = m;
|
|
+ sym = NULL;
|
|
+ if (!_menu)
|
|
+ clear();
|
|
+ else
|
|
+ menuInfo();
|
|
+}
|
|
+
|
|
+void ConfigInfoView::symbolInfo(void)
|
|
+{
|
|
+ QString str;
|
|
+
|
|
+ str += "<big>Symbol: <b>";
|
|
+ str += print_filter(sym->name);
|
|
+ str += "</b></big><br><br>value: ";
|
|
+ str += print_filter(sym_get_string_value(sym));
|
|
+ str += "<br>visibility: ";
|
|
+ str += sym->visible == yes ? "y" : sym->visible == mod ? "m" : "n";
|
|
+ str += "<br>";
|
|
+ str += debug_info(sym);
|
|
+
|
|
+ setText(str);
|
|
+}
|
|
+
|
|
+void ConfigInfoView::menuInfo(void)
|
|
+{
|
|
+ struct symbol* sym;
|
|
+ QString head, debug, help;
|
|
+
|
|
+ sym = _menu->sym;
|
|
+ if (sym) {
|
|
+ if (_menu->prompt) {
|
|
+ head += "<big><b>";
|
|
+ head += print_filter(_(_menu->prompt->text));
|
|
+ head += "</b></big>";
|
|
+ if (sym->name) {
|
|
+ head += " (";
|
|
+ if (showDebug())
|
|
+ head += QString().sprintf("<a href=\"s%p\">", sym);
|
|
+ head += print_filter(sym->name);
|
|
+ if (showDebug())
|
|
+ head += "</a>";
|
|
+ head += ")";
|
|
+ }
|
|
+ } else if (sym->name) {
|
|
+ head += "<big><b>";
|
|
+ if (showDebug())
|
|
+ head += QString().sprintf("<a href=\"s%p\">", sym);
|
|
+ head += print_filter(sym->name);
|
|
+ if (showDebug())
|
|
+ head += "</a>";
|
|
+ head += "</b></big>";
|
|
+ }
|
|
+ head += "<br><br>";
|
|
+
|
|
+ if (showDebug())
|
|
+ debug = debug_info(sym);
|
|
+
|
|
+ struct gstr help_gstr = str_new();
|
|
+ menu_get_ext_help(_menu, &help_gstr);
|
|
+ help = print_filter(str_get(&help_gstr));
|
|
+ str_free(&help_gstr);
|
|
+ } else if (_menu->prompt) {
|
|
+ head += "<big><b>";
|
|
+ head += print_filter(_(_menu->prompt->text));
|
|
+ head += "</b></big><br><br>";
|
|
+ if (showDebug()) {
|
|
+ if (_menu->prompt->visible.expr) {
|
|
+ debug += " dep: ";
|
|
+ expr_print(_menu->prompt->visible.expr, expr_print_help, &debug, E_NONE);
|
|
+ debug += "<br><br>";
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ if (showDebug())
|
|
+ debug += QString().sprintf("defined at %s:%d<br><br>", _menu->file->name, _menu->lineno);
|
|
+
|
|
+ setText(head + debug + help);
|
|
+}
|
|
+
|
|
+QString ConfigInfoView::debug_info(struct symbol *sym)
|
|
+{
|
|
+ QString debug;
|
|
+
|
|
+ debug += "type: ";
|
|
+ debug += print_filter(sym_type_name(sym->type));
|
|
+ if (sym_is_choice(sym))
|
|
+ debug += " (choice)";
|
|
+ debug += "<br>";
|
|
+ if (sym->rev_dep.expr) {
|
|
+ debug += "reverse dep: ";
|
|
+ expr_print(sym->rev_dep.expr, expr_print_help, &debug, E_NONE);
|
|
+ debug += "<br>";
|
|
+ }
|
|
+ for (struct property *prop = sym->prop; prop; prop = prop->next) {
|
|
+ switch (prop->type) {
|
|
+ case P_PROMPT:
|
|
+ case P_MENU:
|
|
+ debug += QString().sprintf("prompt: <a href=\"m%p\">", prop->menu);
|
|
+ debug += print_filter(_(prop->text));
|
|
+ debug += "</a><br>";
|
|
+ break;
|
|
+ case P_DEFAULT:
|
|
+ case P_SELECT:
|
|
+ case P_RANGE:
|
|
+ case P_ENV:
|
|
+ debug += prop_get_type_name(prop->type);
|
|
+ debug += ": ";
|
|
+ expr_print(prop->expr, expr_print_help, &debug, E_NONE);
|
|
+ debug += "<br>";
|
|
+ break;
|
|
+ case P_CHOICE:
|
|
+ if (sym_is_choice(sym)) {
|
|
+ debug += "choice: ";
|
|
+ expr_print(prop->expr, expr_print_help, &debug, E_NONE);
|
|
+ debug += "<br>";
|
|
+ }
|
|
+ break;
|
|
+ default:
|
|
+ debug += "unknown property: ";
|
|
+ debug += prop_get_type_name(prop->type);
|
|
+ debug += "<br>";
|
|
+ }
|
|
+ if (prop->visible.expr) {
|
|
+ debug += " dep: ";
|
|
+ expr_print(prop->visible.expr, expr_print_help, &debug, E_NONE);
|
|
+ debug += "<br>";
|
|
+ }
|
|
+ }
|
|
+ debug += "<br>";
|
|
+
|
|
+ return debug;
|
|
+}
|
|
+
|
|
+QString ConfigInfoView::print_filter(const QString &str)
|
|
+{
|
|
+ QRegExp re("[<>&\"\\n]");
|
|
+ QString res = str;
|
|
+ for (int i = 0; (i = res.find(re, i)) >= 0;) {
|
|
+ switch (res[i].latin1()) {
|
|
+ case '<':
|
|
+ res.replace(i, 1, "<");
|
|
+ i += 4;
|
|
+ break;
|
|
+ case '>':
|
|
+ res.replace(i, 1, ">");
|
|
+ i += 4;
|
|
+ break;
|
|
+ case '&':
|
|
+ res.replace(i, 1, "&");
|
|
+ i += 5;
|
|
+ break;
|
|
+ case '"':
|
|
+ res.replace(i, 1, """);
|
|
+ i += 6;
|
|
+ break;
|
|
+ case '\n':
|
|
+ res.replace(i, 1, "<br>");
|
|
+ i += 4;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ return res;
|
|
+}
|
|
+
|
|
+void ConfigInfoView::expr_print_help(void *data, struct symbol *sym, const char *str)
|
|
+{
|
|
+ QString* text = reinterpret_cast<QString*>(data);
|
|
+ QString str2 = print_filter(str);
|
|
+
|
|
+ if (sym && sym->name && !(sym->flags & SYMBOL_CONST)) {
|
|
+ *text += QString().sprintf("<a href=\"s%p\">", sym);
|
|
+ *text += str2;
|
|
+ *text += "</a>";
|
|
+ } else
|
|
+ *text += str2;
|
|
+}
|
|
+
|
|
+Q3PopupMenu* ConfigInfoView::createPopupMenu(const QPoint& pos)
|
|
+{
|
|
+ Q3PopupMenu* popup = Parent::createPopupMenu(pos);
|
|
+ Q3Action* action = new Q3Action(NULL, _("Show Debug Info"), 0, popup);
|
|
+ action->setToggleAction(TRUE);
|
|
+ connect(action, SIGNAL(toggled(bool)), SLOT(setShowDebug(bool)));
|
|
+ connect(this, SIGNAL(showDebugChanged(bool)), action, SLOT(setOn(bool)));
|
|
+ action->setOn(showDebug());
|
|
+ popup->insertSeparator();
|
|
+ action->addTo(popup);
|
|
+ return popup;
|
|
+}
|
|
+
|
|
+void ConfigInfoView::contentsContextMenuEvent(QContextMenuEvent *e)
|
|
+{
|
|
+ Parent::contentsContextMenuEvent(e);
|
|
+}
|
|
+
|
|
+ConfigSearchWindow::ConfigSearchWindow(ConfigMainWindow* parent, const char *name)
|
|
+ : Parent(parent, name), result(NULL)
|
|
+{
|
|
+ setCaption("Search Config");
|
|
+
|
|
+ QVBoxLayout* layout1 = new QVBoxLayout(this, 11, 6);
|
|
+ QHBoxLayout* layout2 = new QHBoxLayout(0, 0, 6);
|
|
+ layout2->addWidget(new QLabel(_("Find:"), this));
|
|
+ editField = new QLineEdit(this);
|
|
+ connect(editField, SIGNAL(returnPressed()), SLOT(search()));
|
|
+ layout2->addWidget(editField);
|
|
+ searchButton = new QPushButton(_("Search"), this);
|
|
+ searchButton->setAutoDefault(FALSE);
|
|
+ connect(searchButton, SIGNAL(clicked()), SLOT(search()));
|
|
+ layout2->addWidget(searchButton);
|
|
+ layout1->addLayout(layout2);
|
|
+
|
|
+ split = new QSplitter(this);
|
|
+ split->setOrientation(Qt::Vertical);
|
|
+ list = new ConfigView(split, name);
|
|
+ list->list->mode = listMode;
|
|
+ info = new ConfigInfoView(split, name);
|
|
+ connect(list->list, SIGNAL(menuChanged(struct menu *)),
|
|
+ info, SLOT(setInfo(struct menu *)));
|
|
+ connect(list->list, SIGNAL(menuChanged(struct menu *)),
|
|
+ parent, SLOT(setMenuLink(struct menu *)));
|
|
+
|
|
+ layout1->addWidget(split);
|
|
+
|
|
+ if (name) {
|
|
+ int x, y, width, height;
|
|
+ bool ok;
|
|
+
|
|
+ configSettings->beginGroup(name);
|
|
+ width = configSettings->readNumEntry("/window width", parent->width() / 2);
|
|
+ height = configSettings->readNumEntry("/window height", parent->height() / 2);
|
|
+ resize(width, height);
|
|
+ x = configSettings->readNumEntry("/window x", 0, &ok);
|
|
+ if (ok)
|
|
+ y = configSettings->readNumEntry("/window y", 0, &ok);
|
|
+ if (ok)
|
|
+ move(x, y);
|
|
+ Q3ValueList<int> sizes = configSettings->readSizes("/split", &ok);
|
|
+ if (ok)
|
|
+ split->setSizes(sizes);
|
|
+ configSettings->endGroup();
|
|
+ connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
|
|
+ }
|
|
+}
|
|
+
|
|
+void ConfigSearchWindow::saveSettings(void)
|
|
+{
|
|
+ if (name()) {
|
|
+ configSettings->beginGroup(name());
|
|
+ configSettings->writeEntry("/window x", pos().x());
|
|
+ configSettings->writeEntry("/window y", pos().y());
|
|
+ configSettings->writeEntry("/window width", size().width());
|
|
+ configSettings->writeEntry("/window height", size().height());
|
|
+ configSettings->writeSizes("/split", split->sizes());
|
|
+ configSettings->endGroup();
|
|
+ }
|
|
+}
|
|
+
|
|
+void ConfigSearchWindow::search(void)
|
|
+{
|
|
+ struct symbol **p;
|
|
+ struct property *prop;
|
|
+ ConfigItem *lastItem = NULL;
|
|
+
|
|
+ free(result);
|
|
+ list->list->clear();
|
|
+ info->clear();
|
|
+
|
|
+ result = sym_re_search(editField->text().latin1());
|
|
+ if (!result)
|
|
+ return;
|
|
+ for (p = result; *p; p++) {
|
|
+ for_all_prompts((*p), prop)
|
|
+ lastItem = new ConfigItem(list->list, lastItem, prop->menu,
|
|
+ menu_is_visible(prop->menu));
|
|
+ }
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Construct the complete config widget
|
|
+ */
|
|
+ConfigMainWindow::ConfigMainWindow(void)
|
|
+ : searchWindow(0)
|
|
+{
|
|
+ QMenuBar* menu;
|
|
+ bool ok;
|
|
+ int x, y, width, height;
|
|
+ char title[256];
|
|
+
|
|
+ QDesktopWidget *d = configApp->desktop();
|
|
+ snprintf(title, sizeof(title), "%s%s",
|
|
+ rootmenu.prompt->text,
|
|
+#if QT_VERSION < 0x040000
|
|
+ " (Qt3)"
|
|
+#else
|
|
+ ""
|
|
+#endif
|
|
+ );
|
|
+ setCaption(title);
|
|
+
|
|
+ width = configSettings->readNumEntry("/window width", d->width() - 64);
|
|
+ height = configSettings->readNumEntry("/window height", d->height() - 64);
|
|
+ resize(width, height);
|
|
+ x = configSettings->readNumEntry("/window x", 0, &ok);
|
|
+ if (ok)
|
|
+ y = configSettings->readNumEntry("/window y", 0, &ok);
|
|
+ if (ok)
|
|
+ move(x, y);
|
|
+
|
|
+ split1 = new QSplitter(this);
|
|
+ split1->setOrientation(Qt::Horizontal);
|
|
+ setCentralWidget(split1);
|
|
+
|
|
+ menuView = new ConfigView(split1, "menu");
|
|
+ menuList = menuView->list;
|
|
+
|
|
+ split2 = new QSplitter(split1);
|
|
+ split2->setOrientation(Qt::Vertical);
|
|
+
|
|
+ // create config tree
|
|
+ configView = new ConfigView(split2, "config");
|
|
+ configList = configView->list;
|
|
+
|
|
+ helpText = new ConfigInfoView(split2, "help");
|
|
+ helpText->setTextFormat(Qt::RichText);
|
|
+
|
|
+ setTabOrder(configList, helpText);
|
|
+ configList->setFocus();
|
|
+
|
|
+ menu = menuBar();
|
|
+ toolBar = new Q3ToolBar("Tools", this);
|
|
+
|
|
+ backAction = new Q3Action("Back", QPixmap(xpm_back), _("Back"), 0, this);
|
|
+ connect(backAction, SIGNAL(activated()), SLOT(goBack()));
|
|
+ backAction->setEnabled(FALSE);
|
|
+ Q3Action *quitAction = new Q3Action("Quit", _("&Quit"), Qt::CTRL + Qt::Key_Q, this);
|
|
+ connect(quitAction, SIGNAL(activated()), SLOT(close()));
|
|
+ Q3Action *loadAction = new Q3Action("Load", QPixmap(xpm_load), _("&Load"), Qt::CTRL + Qt::Key_L, this);
|
|
+ connect(loadAction, SIGNAL(activated()), SLOT(loadConfig()));
|
|
+ saveAction = new Q3Action("Save", QPixmap(xpm_save), _("&Save"), Qt::CTRL + Qt::Key_S, this);
|
|
+ connect(saveAction, SIGNAL(activated()), SLOT(saveConfig()));
|
|
+ conf_set_changed_callback(conf_changed);
|
|
+ // Set saveAction's initial state
|
|
+ conf_changed();
|
|
+ Q3Action *saveAsAction = new Q3Action("Save As...", _("Save &As..."), 0, this);
|
|
+ connect(saveAsAction, SIGNAL(activated()), SLOT(saveConfigAs()));
|
|
+ Q3Action *searchAction = new Q3Action("Find", _("&Find"), Qt::CTRL + Qt::Key_F, this);
|
|
+ connect(searchAction, SIGNAL(activated()), SLOT(searchConfig()));
|
|
+ Q3Action *singleViewAction = new Q3Action("Single View", QPixmap(xpm_single_view), _("Single View"), 0, this);
|
|
+ connect(singleViewAction, SIGNAL(activated()), SLOT(showSingleView()));
|
|
+ Q3Action *splitViewAction = new Q3Action("Split View", QPixmap(xpm_split_view), _("Split View"), 0, this);
|
|
+ connect(splitViewAction, SIGNAL(activated()), SLOT(showSplitView()));
|
|
+ Q3Action *fullViewAction = new Q3Action("Full View", QPixmap(xpm_tree_view), _("Full View"), 0, this);
|
|
+ connect(fullViewAction, SIGNAL(activated()), SLOT(showFullView()));
|
|
+
|
|
+ Q3Action *showNameAction = new Q3Action(NULL, _("Show Name"), 0, this);
|
|
+ showNameAction->setToggleAction(TRUE);
|
|
+ connect(showNameAction, SIGNAL(toggled(bool)), configView, SLOT(setShowName(bool)));
|
|
+ connect(configView, SIGNAL(showNameChanged(bool)), showNameAction, SLOT(setOn(bool)));
|
|
+ showNameAction->setOn(configView->showName());
|
|
+ Q3Action *showRangeAction = new Q3Action(NULL, _("Show Range"), 0, this);
|
|
+ showRangeAction->setToggleAction(TRUE);
|
|
+ connect(showRangeAction, SIGNAL(toggled(bool)), configView, SLOT(setShowRange(bool)));
|
|
+ connect(configView, SIGNAL(showRangeChanged(bool)), showRangeAction, SLOT(setOn(bool)));
|
|
+ showRangeAction->setOn(configList->showRange);
|
|
+ Q3Action *showDataAction = new Q3Action(NULL, _("Show Data"), 0, this);
|
|
+ showDataAction->setToggleAction(TRUE);
|
|
+ connect(showDataAction, SIGNAL(toggled(bool)), configView, SLOT(setShowData(bool)));
|
|
+ connect(configView, SIGNAL(showDataChanged(bool)), showDataAction, SLOT(setOn(bool)));
|
|
+ showDataAction->setOn(configList->showData);
|
|
+
|
|
+ QActionGroup *optGroup = new QActionGroup(this);
|
|
+ optGroup->setExclusive(TRUE);
|
|
+ connect(optGroup, SIGNAL(selected(QAction *)), configView,
|
|
+ SLOT(setOptionMode(QAction *)));
|
|
+ connect(optGroup, SIGNAL(selected(QAction *)), menuView,
|
|
+ SLOT(setOptionMode(QAction *)));
|
|
+
|
|
+#if QT_VERSION >= 0x040000
|
|
+ configView->showNormalAction = new QAction(_("Show Normal Options"), optGroup);
|
|
+ configView->showAllAction = new QAction(_("Show All Options"), optGroup);
|
|
+ configView->showPromptAction = new QAction(_("Show Prompt Options"), optGroup);
|
|
+#else
|
|
+ configView->showNormalAction = new QAction(_("Show Normal Options"), 0, optGroup);
|
|
+ configView->showAllAction = new QAction(_("Show All Options"), 0, optGroup);
|
|
+ configView->showPromptAction = new QAction(_("Show Prompt Options"), 0, optGroup);
|
|
+#endif
|
|
+ configView->showNormalAction->setToggleAction(TRUE);
|
|
+ configView->showNormalAction->setOn(configList->optMode == normalOpt);
|
|
+ configView->showAllAction->setToggleAction(TRUE);
|
|
+ configView->showAllAction->setOn(configList->optMode == allOpt);
|
|
+ configView->showPromptAction->setToggleAction(TRUE);
|
|
+ configView->showPromptAction->setOn(configList->optMode == promptOpt);
|
|
+
|
|
+ Q3Action *showDebugAction = new Q3Action(NULL, _("Show Debug Info"), 0, this);
|
|
+ showDebugAction->setToggleAction(TRUE);
|
|
+ connect(showDebugAction, SIGNAL(toggled(bool)), helpText, SLOT(setShowDebug(bool)));
|
|
+ connect(helpText, SIGNAL(showDebugChanged(bool)), showDebugAction, SLOT(setOn(bool)));
|
|
+ showDebugAction->setOn(helpText->showDebug());
|
|
+
|
|
+ Q3Action *showIntroAction = new Q3Action(NULL, _("Introduction"), 0, this);
|
|
+ connect(showIntroAction, SIGNAL(activated()), SLOT(showIntro()));
|
|
+ Q3Action *showAboutAction = new Q3Action(NULL, _("About"), 0, this);
|
|
+ connect(showAboutAction, SIGNAL(activated()), SLOT(showAbout()));
|
|
+
|
|
+ // init tool bar
|
|
+ backAction->addTo(toolBar);
|
|
+ toolBar->addSeparator();
|
|
+ loadAction->addTo(toolBar);
|
|
+ saveAction->addTo(toolBar);
|
|
+ toolBar->addSeparator();
|
|
+ singleViewAction->addTo(toolBar);
|
|
+ splitViewAction->addTo(toolBar);
|
|
+ fullViewAction->addTo(toolBar);
|
|
+
|
|
+ // create config menu
|
|
+ Q3PopupMenu* config = new Q3PopupMenu(this);
|
|
+ menu->insertItem(_("&File"), config);
|
|
+ loadAction->addTo(config);
|
|
+ saveAction->addTo(config);
|
|
+ saveAsAction->addTo(config);
|
|
+ config->insertSeparator();
|
|
+ quitAction->addTo(config);
|
|
+
|
|
+ // create edit menu
|
|
+ Q3PopupMenu* editMenu = new Q3PopupMenu(this);
|
|
+ menu->insertItem(_("&Edit"), editMenu);
|
|
+ searchAction->addTo(editMenu);
|
|
+
|
|
+ // create options menu
|
|
+ Q3PopupMenu* optionMenu = new Q3PopupMenu(this);
|
|
+ menu->insertItem(_("&Option"), optionMenu);
|
|
+ showNameAction->addTo(optionMenu);
|
|
+ showRangeAction->addTo(optionMenu);
|
|
+ showDataAction->addTo(optionMenu);
|
|
+ optionMenu->insertSeparator();
|
|
+ optGroup->addTo(optionMenu);
|
|
+ optionMenu->insertSeparator();
|
|
+
|
|
+ // create help menu
|
|
+ Q3PopupMenu* helpMenu = new Q3PopupMenu(this);
|
|
+ menu->insertSeparator();
|
|
+ menu->insertItem(_("&Help"), helpMenu);
|
|
+ showIntroAction->addTo(helpMenu);
|
|
+ showAboutAction->addTo(helpMenu);
|
|
+
|
|
+ connect(configList, SIGNAL(menuChanged(struct menu *)),
|
|
+ helpText, SLOT(setInfo(struct menu *)));
|
|
+ connect(configList, SIGNAL(menuSelected(struct menu *)),
|
|
+ SLOT(changeMenu(struct menu *)));
|
|
+ connect(configList, SIGNAL(parentSelected()),
|
|
+ SLOT(goBack()));
|
|
+ connect(menuList, SIGNAL(menuChanged(struct menu *)),
|
|
+ helpText, SLOT(setInfo(struct menu *)));
|
|
+ connect(menuList, SIGNAL(menuSelected(struct menu *)),
|
|
+ SLOT(changeMenu(struct menu *)));
|
|
+
|
|
+ connect(configList, SIGNAL(gotFocus(struct menu *)),
|
|
+ helpText, SLOT(setInfo(struct menu *)));
|
|
+ connect(menuList, SIGNAL(gotFocus(struct menu *)),
|
|
+ helpText, SLOT(setInfo(struct menu *)));
|
|
+ connect(menuList, SIGNAL(gotFocus(struct menu *)),
|
|
+ SLOT(listFocusChanged(void)));
|
|
+ connect(helpText, SIGNAL(menuSelected(struct menu *)),
|
|
+ SLOT(setMenuLink(struct menu *)));
|
|
+
|
|
+ QString listMode = configSettings->readEntry("/listMode", "symbol");
|
|
+ if (listMode == "single")
|
|
+ showSingleView();
|
|
+ else if (listMode == "full")
|
|
+ showFullView();
|
|
+ else /*if (listMode == "split")*/
|
|
+ showSplitView();
|
|
+
|
|
+ // UI setup done, restore splitter positions
|
|
+ Q3ValueList<int> sizes = configSettings->readSizes("/split1", &ok);
|
|
+ if (ok)
|
|
+ split1->setSizes(sizes);
|
|
+
|
|
+ sizes = configSettings->readSizes("/split2", &ok);
|
|
+ if (ok)
|
|
+ split2->setSizes(sizes);
|
|
+}
|
|
+
|
|
+void ConfigMainWindow::loadConfig(void)
|
|
+{
|
|
+ QString s = Q3FileDialog::getOpenFileName(conf_get_configname(), NULL, this);
|
|
+ if (s.isNull())
|
|
+ return;
|
|
+ if (conf_read(QFile::encodeName(s)))
|
|
+ QMessageBox::information(this, "qconf", _("Unable to load configuration!"));
|
|
+ ConfigView::updateListAll();
|
|
+}
|
|
+
|
|
+bool ConfigMainWindow::saveConfig(void)
|
|
+{
|
|
+ if (conf_write(NULL)) {
|
|
+ QMessageBox::information(this, "qconf", _("Unable to save configuration!"));
|
|
+ return false;
|
|
+ }
|
|
+ return true;
|
|
+}
|
|
+
|
|
+void ConfigMainWindow::saveConfigAs(void)
|
|
+{
|
|
+ QString s = Q3FileDialog::getSaveFileName(conf_get_configname(), NULL, this);
|
|
+ if (s.isNull())
|
|
+ return;
|
|
+ saveConfig();
|
|
+}
|
|
+
|
|
+void ConfigMainWindow::searchConfig(void)
|
|
+{
|
|
+ if (!searchWindow)
|
|
+ searchWindow = new ConfigSearchWindow(this, "search");
|
|
+ searchWindow->show();
|
|
+}
|
|
+
|
|
+void ConfigMainWindow::changeMenu(struct menu *menu)
|
|
+{
|
|
+ configList->setRootMenu(menu);
|
|
+ if (configList->rootEntry->parent == &rootmenu)
|
|
+ backAction->setEnabled(FALSE);
|
|
+ else
|
|
+ backAction->setEnabled(TRUE);
|
|
+}
|
|
+
|
|
+void ConfigMainWindow::setMenuLink(struct menu *menu)
|
|
+{
|
|
+ struct menu *parent;
|
|
+ ConfigList* list = NULL;
|
|
+ ConfigItem* item;
|
|
+
|
|
+ if (configList->menuSkip(menu))
|
|
+ return;
|
|
+
|
|
+ switch (configList->mode) {
|
|
+ case singleMode:
|
|
+ list = configList;
|
|
+ parent = menu_get_parent_menu(menu);
|
|
+ if (!parent)
|
|
+ return;
|
|
+ list->setRootMenu(parent);
|
|
+ break;
|
|
+ case symbolMode:
|
|
+ if (menu->flags & MENU_ROOT) {
|
|
+ configList->setRootMenu(menu);
|
|
+ configList->clearSelection();
|
|
+ list = menuList;
|
|
+ } else {
|
|
+ list = configList;
|
|
+ parent = menu_get_parent_menu(menu->parent);
|
|
+ if (!parent)
|
|
+ return;
|
|
+ item = menuList->findConfigItem(parent);
|
|
+ if (item) {
|
|
+ menuList->setSelected(item, TRUE);
|
|
+ menuList->ensureItemVisible(item);
|
|
+ }
|
|
+ list->setRootMenu(parent);
|
|
+ }
|
|
+ break;
|
|
+ case fullMode:
|
|
+ list = configList;
|
|
+ break;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if (list) {
|
|
+ item = list->findConfigItem(menu);
|
|
+ if (item) {
|
|
+ list->setSelected(item, TRUE);
|
|
+ list->ensureItemVisible(item);
|
|
+ list->setFocus();
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+void ConfigMainWindow::listFocusChanged(void)
|
|
+{
|
|
+ if (menuList->mode == menuMode)
|
|
+ configList->clearSelection();
|
|
+}
|
|
+
|
|
+void ConfigMainWindow::goBack(void)
|
|
+{
|
|
+ ConfigItem* item;
|
|
+
|
|
+ configList->setParentMenu();
|
|
+ if (configList->rootEntry == &rootmenu)
|
|
+ backAction->setEnabled(FALSE);
|
|
+ item = (ConfigItem*)menuList->selectedItem();
|
|
+ while (item) {
|
|
+ if (item->menu == configList->rootEntry) {
|
|
+ menuList->setSelected(item, TRUE);
|
|
+ break;
|
|
+ }
|
|
+ item = (ConfigItem*)item->parent();
|
|
+ }
|
|
+}
|
|
+
|
|
+void ConfigMainWindow::showSingleView(void)
|
|
+{
|
|
+ menuView->hide();
|
|
+ menuList->setRootMenu(0);
|
|
+ configList->mode = singleMode;
|
|
+ if (configList->rootEntry == &rootmenu)
|
|
+ configList->updateListAll();
|
|
+ else
|
|
+ configList->setRootMenu(&rootmenu);
|
|
+ configList->setAllOpen(TRUE);
|
|
+ configList->setFocus();
|
|
+}
|
|
+
|
|
+void ConfigMainWindow::showSplitView(void)
|
|
+{
|
|
+ configList->mode = symbolMode;
|
|
+ if (configList->rootEntry == &rootmenu)
|
|
+ configList->updateListAll();
|
|
+ else
|
|
+ configList->setRootMenu(&rootmenu);
|
|
+ configList->setAllOpen(TRUE);
|
|
+ configApp->processEvents();
|
|
+ menuList->mode = menuMode;
|
|
+ menuList->setRootMenu(&rootmenu);
|
|
+ menuList->setAllOpen(TRUE);
|
|
+ menuView->show();
|
|
+ menuList->setFocus();
|
|
+}
|
|
+
|
|
+void ConfigMainWindow::showFullView(void)
|
|
+{
|
|
+ menuView->hide();
|
|
+ menuList->setRootMenu(0);
|
|
+ configList->mode = fullMode;
|
|
+ if (configList->rootEntry == &rootmenu)
|
|
+ configList->updateListAll();
|
|
+ else
|
|
+ configList->setRootMenu(&rootmenu);
|
|
+ configList->setAllOpen(FALSE);
|
|
+ configList->setFocus();
|
|
+}
|
|
+
|
|
+/*
|
|
+ * ask for saving configuration before quitting
|
|
+ * TODO ask only when something changed
|
|
+ */
|
|
+void ConfigMainWindow::closeEvent(QCloseEvent* e)
|
|
+{
|
|
+ if (!conf_get_changed()) {
|
|
+ e->accept();
|
|
+ return;
|
|
+ }
|
|
+ QMessageBox mb("qconf", _("Save configuration?"), QMessageBox::Warning,
|
|
+ QMessageBox::Yes | QMessageBox::Default, QMessageBox::No, QMessageBox::Cancel | QMessageBox::Escape);
|
|
+ mb.setButtonText(QMessageBox::Yes, _("&Save Changes"));
|
|
+ mb.setButtonText(QMessageBox::No, _("&Discard Changes"));
|
|
+ mb.setButtonText(QMessageBox::Cancel, _("Cancel Exit"));
|
|
+ switch (mb.exec()) {
|
|
+ case QMessageBox::Yes:
|
|
+ if (saveConfig())
|
|
+ e->accept();
|
|
+ else
|
|
+ e->ignore();
|
|
+ break;
|
|
+ case QMessageBox::No:
|
|
+ e->accept();
|
|
+ break;
|
|
+ case QMessageBox::Cancel:
|
|
+ e->ignore();
|
|
+ break;
|
|
+ }
|
|
+}
|
|
+
|
|
+void ConfigMainWindow::showIntro(void)
|
|
+{
|
|
+ static const QString str = _("Welcome to the qconf graphical configuration tool.\n\n"
|
|
+ "For each option, a blank box indicates the feature is disabled, a check\n"
|
|
+ "indicates it is enabled, and a dot indicates that it is to be compiled\n"
|
|
+ "as a module. Clicking on the box will cycle through the three states.\n\n"
|
|
+ "If you do not see an option (e.g., a device driver) that you believe\n"
|
|
+ "should be present, try turning on Show All Options under the Options menu.\n"
|
|
+ "Although there is no cross reference yet to help you figure out what other\n"
|
|
+ "options must be enabled to support the option you are interested in, you can\n"
|
|
+ "still view the help of a grayed-out option.\n\n"
|
|
+ "Toggling Show Debug Info under the Options menu will show the dependencies,\n"
|
|
+ "which you can then match by examining other options.\n\n");
|
|
+
|
|
+ QMessageBox::information(this, "qconf", str);
|
|
+}
|
|
+
|
|
+void ConfigMainWindow::showAbout(void)
|
|
+{
|
|
+ static const QString str = _("qconf is Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>.\n\n"
|
|
+ "Bug reports and feature request can also be entered at http://bugzilla.kernel.org/\n");
|
|
+
|
|
+ QMessageBox::information(this, "qconf", str);
|
|
+}
|
|
+
|
|
+void ConfigMainWindow::saveSettings(void)
|
|
+{
|
|
+ configSettings->writeEntry("/window x", pos().x());
|
|
+ configSettings->writeEntry("/window y", pos().y());
|
|
+ configSettings->writeEntry("/window width", size().width());
|
|
+ configSettings->writeEntry("/window height", size().height());
|
|
+
|
|
+ QString entry;
|
|
+ switch(configList->mode) {
|
|
+ case singleMode :
|
|
+ entry = "single";
|
|
+ break;
|
|
+
|
|
+ case symbolMode :
|
|
+ entry = "split";
|
|
+ break;
|
|
+
|
|
+ case fullMode :
|
|
+ entry = "full";
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ configSettings->writeEntry("/listMode", entry);
|
|
+
|
|
+ configSettings->writeSizes("/split1", split1->sizes());
|
|
+ configSettings->writeSizes("/split2", split2->sizes());
|
|
+}
|
|
+
|
|
+void ConfigMainWindow::conf_changed(void)
|
|
+{
|
|
+ if (saveAction)
|
|
+ saveAction->setEnabled(conf_get_changed());
|
|
+}
|
|
+
|
|
+void fixup_rootmenu(struct menu *menu)
|
|
+{
|
|
+ struct menu *child;
|
|
+ static int menu_cnt = 0;
|
|
+
|
|
+ menu->flags |= MENU_ROOT;
|
|
+ for (child = menu->list; child; child = child->next) {
|
|
+ if (child->prompt && child->prompt->type == P_MENU) {
|
|
+ menu_cnt++;
|
|
+ fixup_rootmenu(child);
|
|
+ menu_cnt--;
|
|
+ } else if (!menu_cnt)
|
|
+ fixup_rootmenu(child);
|
|
+ }
|
|
+}
|
|
+
|
|
+static const char *progname;
|
|
+
|
|
+static void usage(void)
|
|
+{
|
|
+ printf(_("%s <config>\n"), progname);
|
|
+ exit(0);
|
|
+}
|
|
+
|
|
+int main(int ac, char** av)
|
|
+{
|
|
+ ConfigMainWindow* v;
|
|
+ const char *name;
|
|
+
|
|
+ bindtextdomain(PACKAGE, LOCALEDIR);
|
|
+ textdomain(PACKAGE);
|
|
+
|
|
+ progname = av[0];
|
|
+ configApp = new QApplication(ac, av);
|
|
+ if (ac > 1 && av[1][0] == '-') {
|
|
+ switch (av[1][1]) {
|
|
+ case 'h':
|
|
+ case '?':
|
|
+ usage();
|
|
+ }
|
|
+ name = av[2];
|
|
+ } else
|
|
+ name = av[1];
|
|
+ if (!name)
|
|
+ usage();
|
|
+
|
|
+ conf_parse(name);
|
|
+ fixup_rootmenu(&rootmenu);
|
|
+ conf_read(NULL);
|
|
+ //zconfdump(stdout);
|
|
+
|
|
+ configSettings = new ConfigSettings();
|
|
+ configSettings->beginGroup("/kconfig/qconf");
|
|
+ v = new ConfigMainWindow();
|
|
+
|
|
+ //zconfdump(stdout);
|
|
+ configApp->setMainWidget(v);
|
|
+ configApp->connect(configApp, SIGNAL(lastWindowClosed()), SLOT(quit()));
|
|
+ configApp->connect(configApp, SIGNAL(aboutToQuit()), v, SLOT(saveSettings()));
|
|
+ v->show();
|
|
+ configApp->exec();
|
|
+
|
|
+ configSettings->endGroup();
|
|
+ delete configSettings;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
diff --git a/scripts/kconfig/qconf.h b/scripts/kconfig/qconf.h
|
|
new file mode 100644
|
|
index 0000000..bde0c6b
|
|
--- /dev/null
|
|
+++ b/scripts/kconfig/qconf.h
|
|
@@ -0,0 +1,338 @@
|
|
+/*
|
|
+ * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
|
|
+ * Released under the terms of the GNU GPL v2.0.
|
|
+ */
|
|
+
|
|
+#if QT_VERSION < 0x040000
|
|
+#include <qlistview.h>
|
|
+#else
|
|
+#include <q3listview.h>
|
|
+#endif
|
|
+#include <qsettings.h>
|
|
+
|
|
+#if QT_VERSION < 0x040000
|
|
+#define Q3ValueList QValueList
|
|
+#define Q3PopupMenu QPopupMenu
|
|
+#define Q3ListView QListView
|
|
+#define Q3ListViewItem QListViewItem
|
|
+#define Q3VBox QVBox
|
|
+#define Q3TextBrowser QTextBrowser
|
|
+#define Q3MainWindow QMainWindow
|
|
+#define Q3Action QAction
|
|
+#define Q3ToolBar QToolBar
|
|
+#define Q3ListViewItemIterator QListViewItemIterator
|
|
+#define Q3FileDialog QFileDialog
|
|
+#endif
|
|
+
|
|
+class ConfigView;
|
|
+class ConfigList;
|
|
+class ConfigItem;
|
|
+class ConfigLineEdit;
|
|
+class ConfigMainWindow;
|
|
+
|
|
+class ConfigSettings : public QSettings {
|
|
+public:
|
|
+ ConfigSettings();
|
|
+ Q3ValueList<int> readSizes(const QString& key, bool *ok);
|
|
+ bool writeSizes(const QString& key, const Q3ValueList<int>& value);
|
|
+};
|
|
+
|
|
+enum colIdx {
|
|
+ promptColIdx, nameColIdx, noColIdx, modColIdx, yesColIdx, dataColIdx, colNr
|
|
+};
|
|
+enum listMode {
|
|
+ singleMode, menuMode, symbolMode, fullMode, listMode
|
|
+};
|
|
+enum optionMode {
|
|
+ normalOpt = 0, allOpt, promptOpt
|
|
+};
|
|
+
|
|
+class ConfigList : public Q3ListView {
|
|
+ Q_OBJECT
|
|
+ typedef class Q3ListView Parent;
|
|
+public:
|
|
+ ConfigList(ConfigView* p, const char *name = 0);
|
|
+ void reinit(void);
|
|
+ ConfigView* parent(void) const
|
|
+ {
|
|
+ return (ConfigView*)Parent::parent();
|
|
+ }
|
|
+ ConfigItem* findConfigItem(struct menu *);
|
|
+
|
|
+protected:
|
|
+ void keyPressEvent(QKeyEvent *e);
|
|
+ void contentsMousePressEvent(QMouseEvent *e);
|
|
+ void contentsMouseReleaseEvent(QMouseEvent *e);
|
|
+ void contentsMouseMoveEvent(QMouseEvent *e);
|
|
+ void contentsMouseDoubleClickEvent(QMouseEvent *e);
|
|
+ void focusInEvent(QFocusEvent *e);
|
|
+ void contextMenuEvent(QContextMenuEvent *e);
|
|
+
|
|
+public slots:
|
|
+ void setRootMenu(struct menu *menu);
|
|
+
|
|
+ void updateList(ConfigItem *item);
|
|
+ void setValue(ConfigItem* item, tristate val);
|
|
+ void changeValue(ConfigItem* item);
|
|
+ void updateSelection(void);
|
|
+ void saveSettings(void);
|
|
+signals:
|
|
+ void menuChanged(struct menu *menu);
|
|
+ void menuSelected(struct menu *menu);
|
|
+ void parentSelected(void);
|
|
+ void gotFocus(struct menu *);
|
|
+
|
|
+public:
|
|
+ void updateListAll(void)
|
|
+ {
|
|
+ updateAll = true;
|
|
+ updateList(NULL);
|
|
+ updateAll = false;
|
|
+ }
|
|
+ ConfigList* listView()
|
|
+ {
|
|
+ return this;
|
|
+ }
|
|
+ ConfigItem* firstChild() const
|
|
+ {
|
|
+ return (ConfigItem *)Parent::firstChild();
|
|
+ }
|
|
+ int mapIdx(colIdx idx)
|
|
+ {
|
|
+ return colMap[idx];
|
|
+ }
|
|
+ void addColumn(colIdx idx, const QString& label)
|
|
+ {
|
|
+ colMap[idx] = Parent::addColumn(label);
|
|
+ colRevMap[colMap[idx]] = idx;
|
|
+ }
|
|
+ void removeColumn(colIdx idx)
|
|
+ {
|
|
+ int col = colMap[idx];
|
|
+ if (col >= 0) {
|
|
+ Parent::removeColumn(col);
|
|
+ colRevMap[col] = colMap[idx] = -1;
|
|
+ }
|
|
+ }
|
|
+ void setAllOpen(bool open);
|
|
+ void setParentMenu(void);
|
|
+
|
|
+ bool menuSkip(struct menu *);
|
|
+
|
|
+ template <class P>
|
|
+ void updateMenuList(P*, struct menu*);
|
|
+
|
|
+ bool updateAll;
|
|
+
|
|
+ QPixmap symbolYesPix, symbolModPix, symbolNoPix;
|
|
+ QPixmap choiceYesPix, choiceNoPix;
|
|
+ QPixmap menuPix, menuInvPix, menuBackPix, voidPix;
|
|
+
|
|
+ bool showName, showRange, showData;
|
|
+ enum listMode mode;
|
|
+ enum optionMode optMode;
|
|
+ struct menu *rootEntry;
|
|
+ QColorGroup disabledColorGroup;
|
|
+ QColorGroup inactivedColorGroup;
|
|
+ Q3PopupMenu* headerPopup;
|
|
+
|
|
+private:
|
|
+ int colMap[colNr];
|
|
+ int colRevMap[colNr];
|
|
+};
|
|
+
|
|
+class ConfigItem : public Q3ListViewItem {
|
|
+ typedef class Q3ListViewItem Parent;
|
|
+public:
|
|
+ ConfigItem(Q3ListView *parent, ConfigItem *after, struct menu *m, bool v)
|
|
+ : Parent(parent, after), menu(m), visible(v), goParent(false)
|
|
+ {
|
|
+ init();
|
|
+ }
|
|
+ ConfigItem(ConfigItem *parent, ConfigItem *after, struct menu *m, bool v)
|
|
+ : Parent(parent, after), menu(m), visible(v), goParent(false)
|
|
+ {
|
|
+ init();
|
|
+ }
|
|
+ ConfigItem(Q3ListView *parent, ConfigItem *after, bool v)
|
|
+ : Parent(parent, after), menu(0), visible(v), goParent(true)
|
|
+ {
|
|
+ init();
|
|
+ }
|
|
+ ~ConfigItem(void);
|
|
+ void init(void);
|
|
+ void okRename(int col);
|
|
+ void updateMenu(void);
|
|
+ void testUpdateMenu(bool v);
|
|
+ ConfigList* listView() const
|
|
+ {
|
|
+ return (ConfigList*)Parent::listView();
|
|
+ }
|
|
+ ConfigItem* firstChild() const
|
|
+ {
|
|
+ return (ConfigItem *)Parent::firstChild();
|
|
+ }
|
|
+ ConfigItem* nextSibling() const
|
|
+ {
|
|
+ return (ConfigItem *)Parent::nextSibling();
|
|
+ }
|
|
+ void setText(colIdx idx, const QString& text)
|
|
+ {
|
|
+ Parent::setText(listView()->mapIdx(idx), text);
|
|
+ }
|
|
+ QString text(colIdx idx) const
|
|
+ {
|
|
+ return Parent::text(listView()->mapIdx(idx));
|
|
+ }
|
|
+ void setPixmap(colIdx idx, const QPixmap& pm)
|
|
+ {
|
|
+ Parent::setPixmap(listView()->mapIdx(idx), pm);
|
|
+ }
|
|
+ const QPixmap* pixmap(colIdx idx) const
|
|
+ {
|
|
+ return Parent::pixmap(listView()->mapIdx(idx));
|
|
+ }
|
|
+ void paintCell(QPainter* p, const QColorGroup& cg, int column, int width, int align);
|
|
+
|
|
+ ConfigItem* nextItem;
|
|
+ struct menu *menu;
|
|
+ bool visible;
|
|
+ bool goParent;
|
|
+};
|
|
+
|
|
+class ConfigLineEdit : public QLineEdit {
|
|
+ Q_OBJECT
|
|
+ typedef class QLineEdit Parent;
|
|
+public:
|
|
+ ConfigLineEdit(ConfigView* parent);
|
|
+ ConfigView* parent(void) const
|
|
+ {
|
|
+ return (ConfigView*)Parent::parent();
|
|
+ }
|
|
+ void show(ConfigItem *i);
|
|
+ void keyPressEvent(QKeyEvent *e);
|
|
+
|
|
+public:
|
|
+ ConfigItem *item;
|
|
+};
|
|
+
|
|
+class ConfigView : public Q3VBox {
|
|
+ Q_OBJECT
|
|
+ typedef class Q3VBox Parent;
|
|
+public:
|
|
+ ConfigView(QWidget* parent, const char *name = 0);
|
|
+ ~ConfigView(void);
|
|
+ static void updateList(ConfigItem* item);
|
|
+ static void updateListAll(void);
|
|
+
|
|
+ bool showName(void) const { return list->showName; }
|
|
+ bool showRange(void) const { return list->showRange; }
|
|
+ bool showData(void) const { return list->showData; }
|
|
+public slots:
|
|
+ void setShowName(bool);
|
|
+ void setShowRange(bool);
|
|
+ void setShowData(bool);
|
|
+ void setOptionMode(QAction *);
|
|
+signals:
|
|
+ void showNameChanged(bool);
|
|
+ void showRangeChanged(bool);
|
|
+ void showDataChanged(bool);
|
|
+public:
|
|
+ ConfigList* list;
|
|
+ ConfigLineEdit* lineEdit;
|
|
+
|
|
+ static ConfigView* viewList;
|
|
+ ConfigView* nextView;
|
|
+
|
|
+ static QAction *showNormalAction;
|
|
+ static QAction *showAllAction;
|
|
+ static QAction *showPromptAction;
|
|
+};
|
|
+
|
|
+class ConfigInfoView : public Q3TextBrowser {
|
|
+ Q_OBJECT
|
|
+ typedef class Q3TextBrowser Parent;
|
|
+public:
|
|
+ ConfigInfoView(QWidget* parent, const char *name = 0);
|
|
+ bool showDebug(void) const { return _showDebug; }
|
|
+
|
|
+public slots:
|
|
+ void setInfo(struct menu *menu);
|
|
+ void saveSettings(void);
|
|
+ void setShowDebug(bool);
|
|
+
|
|
+signals:
|
|
+ void showDebugChanged(bool);
|
|
+ void menuSelected(struct menu *);
|
|
+
|
|
+protected:
|
|
+ void symbolInfo(void);
|
|
+ void menuInfo(void);
|
|
+ QString debug_info(struct symbol *sym);
|
|
+ static QString print_filter(const QString &str);
|
|
+ static void expr_print_help(void *data, struct symbol *sym, const char *str);
|
|
+ Q3PopupMenu* createPopupMenu(const QPoint& pos);
|
|
+ void contentsContextMenuEvent(QContextMenuEvent *e);
|
|
+
|
|
+ struct symbol *sym;
|
|
+ struct menu *_menu;
|
|
+ bool _showDebug;
|
|
+};
|
|
+
|
|
+class ConfigSearchWindow : public QDialog {
|
|
+ Q_OBJECT
|
|
+ typedef class QDialog Parent;
|
|
+public:
|
|
+ ConfigSearchWindow(ConfigMainWindow* parent, const char *name = 0);
|
|
+
|
|
+public slots:
|
|
+ void saveSettings(void);
|
|
+ void search(void);
|
|
+
|
|
+protected:
|
|
+ QLineEdit* editField;
|
|
+ QPushButton* searchButton;
|
|
+ QSplitter* split;
|
|
+ ConfigView* list;
|
|
+ ConfigInfoView* info;
|
|
+
|
|
+ struct symbol **result;
|
|
+};
|
|
+
|
|
+class ConfigMainWindow : public Q3MainWindow {
|
|
+ Q_OBJECT
|
|
+
|
|
+ static Q3Action *saveAction;
|
|
+ static void conf_changed(void);
|
|
+public:
|
|
+ ConfigMainWindow(void);
|
|
+public slots:
|
|
+ void changeMenu(struct menu *);
|
|
+ void setMenuLink(struct menu *);
|
|
+ void listFocusChanged(void);
|
|
+ void goBack(void);
|
|
+ void loadConfig(void);
|
|
+ bool saveConfig(void);
|
|
+ void saveConfigAs(void);
|
|
+ void searchConfig(void);
|
|
+ void showSingleView(void);
|
|
+ void showSplitView(void);
|
|
+ void showFullView(void);
|
|
+ void showIntro(void);
|
|
+ void showAbout(void);
|
|
+ void saveSettings(void);
|
|
+
|
|
+protected:
|
|
+ void closeEvent(QCloseEvent *e);
|
|
+
|
|
+ ConfigSearchWindow *searchWindow;
|
|
+ ConfigView *menuView;
|
|
+ ConfigList *menuList;
|
|
+ ConfigView *configView;
|
|
+ ConfigList *configList;
|
|
+ ConfigInfoView *helpText;
|
|
+ Q3ToolBar *toolBar;
|
|
+ Q3Action *backAction;
|
|
+ QSplitter* split1;
|
|
+ QSplitter* split2;
|
|
+};
|
|
diff --git a/scripts/kconfig/streamline_config.pl b/scripts/kconfig/streamline_config.pl
|
|
new file mode 100755
|
|
index 0000000..9cb8522
|
|
--- /dev/null
|
|
+++ b/scripts/kconfig/streamline_config.pl
|
|
@@ -0,0 +1,647 @@
|
|
+#!/usr/bin/perl -w
|
|
+#
|
|
+# Copyright 2005-2009 - Steven Rostedt
|
|
+# Licensed under the terms of the GNU GPL License version 2
|
|
+#
|
|
+# It's simple enough to figure out how this works.
|
|
+# If not, then you can ask me at stripconfig@goodmis.org
|
|
+#
|
|
+# What it does?
|
|
+#
|
|
+# If you have installed a Linux kernel from a distribution
|
|
+# that turns on way too many modules than you need, and
|
|
+# you only want the modules you use, then this program
|
|
+# is perfect for you.
|
|
+#
|
|
+# It gives you the ability to turn off all the modules that are
|
|
+# not loaded on your system.
|
|
+#
|
|
+# Howto:
|
|
+#
|
|
+# 1. Boot up the kernel that you want to stream line the config on.
|
|
+# 2. Change directory to the directory holding the source of the
|
|
+# kernel that you just booted.
|
|
+# 3. Copy the configuraton file to this directory as .config
|
|
+# 4. Have all your devices that you need modules for connected and
|
|
+# operational (make sure that their corresponding modules are loaded)
|
|
+# 5. Run this script redirecting the output to some other file
|
|
+# like config_strip.
|
|
+# 6. Back up your old config (if you want too).
|
|
+# 7. copy the config_strip file to .config
|
|
+# 8. Run "make oldconfig"
|
|
+#
|
|
+# Now your kernel is ready to be built with only the modules that
|
|
+# are loaded.
|
|
+#
|
|
+# Here's what I did with my Debian distribution.
|
|
+#
|
|
+# cd /usr/src/linux-2.6.10
|
|
+# cp /boot/config-2.6.10-1-686-smp .config
|
|
+# ~/bin/streamline_config > config_strip
|
|
+# mv .config config_sav
|
|
+# mv config_strip .config
|
|
+# make oldconfig
|
|
+#
|
|
+use strict;
|
|
+use Getopt::Long;
|
|
+
|
|
+# set the environment variable LOCALMODCONFIG_DEBUG to get
|
|
+# debug output.
|
|
+my $debugprint = 0;
|
|
+$debugprint = 1 if (defined($ENV{LOCALMODCONFIG_DEBUG}));
|
|
+
|
|
+sub dprint {
|
|
+ return if (!$debugprint);
|
|
+ print STDERR @_;
|
|
+}
|
|
+
|
|
+my $config = ".config";
|
|
+
|
|
+my $uname = `uname -r`;
|
|
+chomp $uname;
|
|
+
|
|
+my @searchconfigs = (
|
|
+ {
|
|
+ "file" => ".config",
|
|
+ "exec" => "cat",
|
|
+ },
|
|
+ {
|
|
+ "file" => "/proc/config.gz",
|
|
+ "exec" => "zcat",
|
|
+ },
|
|
+ {
|
|
+ "file" => "/boot/config-$uname",
|
|
+ "exec" => "cat",
|
|
+ },
|
|
+ {
|
|
+ "file" => "/boot/vmlinuz-$uname",
|
|
+ "exec" => "scripts/extract-ikconfig",
|
|
+ "test" => "scripts/extract-ikconfig",
|
|
+ },
|
|
+ {
|
|
+ "file" => "vmlinux",
|
|
+ "exec" => "scripts/extract-ikconfig",
|
|
+ "test" => "scripts/extract-ikconfig",
|
|
+ },
|
|
+ {
|
|
+ "file" => "/lib/modules/$uname/kernel/kernel/configs.ko",
|
|
+ "exec" => "scripts/extract-ikconfig",
|
|
+ "test" => "scripts/extract-ikconfig",
|
|
+ },
|
|
+ {
|
|
+ "file" => "kernel/configs.ko",
|
|
+ "exec" => "scripts/extract-ikconfig",
|
|
+ "test" => "scripts/extract-ikconfig",
|
|
+ },
|
|
+ {
|
|
+ "file" => "kernel/configs.o",
|
|
+ "exec" => "scripts/extract-ikconfig",
|
|
+ "test" => "scripts/extract-ikconfig",
|
|
+ },
|
|
+);
|
|
+
|
|
+sub read_config {
|
|
+ foreach my $conf (@searchconfigs) {
|
|
+ my $file = $conf->{"file"};
|
|
+
|
|
+ next if ( ! -f "$file");
|
|
+
|
|
+ if (defined($conf->{"test"})) {
|
|
+ `$conf->{"test"} $conf->{"file"} 2>/dev/null`;
|
|
+ next if ($?);
|
|
+ }
|
|
+
|
|
+ my $exec = $conf->{"exec"};
|
|
+
|
|
+ print STDERR "using config: '$file'\n";
|
|
+
|
|
+ open(my $infile, '-|', "$exec $file") || die "Failed to run $exec $file";
|
|
+ my @x = <$infile>;
|
|
+ close $infile;
|
|
+ return @x;
|
|
+ }
|
|
+ die "No config file found";
|
|
+}
|
|
+
|
|
+my @config_file = read_config;
|
|
+
|
|
+# Parse options
|
|
+my $localmodconfig = 0;
|
|
+my $localyesconfig = 0;
|
|
+
|
|
+GetOptions("localmodconfig" => \$localmodconfig,
|
|
+ "localyesconfig" => \$localyesconfig);
|
|
+
|
|
+# Get the build source and top level Kconfig file (passed in)
|
|
+my $ksource = ($ARGV[0] ? $ARGV[0] : '.');
|
|
+my $kconfig = $ARGV[1];
|
|
+my $lsmod_file = $ENV{'LSMOD'};
|
|
+
|
|
+my @makefiles = `find $ksource -name Makefile 2>/dev/null`;
|
|
+chomp @makefiles;
|
|
+
|
|
+my %depends;
|
|
+my %selects;
|
|
+my %prompts;
|
|
+my %objects;
|
|
+my $var;
|
|
+my $iflevel = 0;
|
|
+my @ifdeps;
|
|
+
|
|
+# prevent recursion
|
|
+my %read_kconfigs;
|
|
+
|
|
+sub read_kconfig {
|
|
+ my ($kconfig) = @_;
|
|
+
|
|
+ my $state = "NONE";
|
|
+ my $config;
|
|
+
|
|
+ my $cont = 0;
|
|
+ my $line;
|
|
+
|
|
+ my $source = "$ksource/$kconfig";
|
|
+ my $last_source = "";
|
|
+
|
|
+ # Check for any environment variables used
|
|
+ while ($source =~ /\$(\w+)/ && $last_source ne $source) {
|
|
+ my $env = $1;
|
|
+ $last_source = $source;
|
|
+ $source =~ s/\$$env/$ENV{$env}/;
|
|
+ }
|
|
+
|
|
+ open(my $kinfile, '<', $source) || die "Can't open $kconfig";
|
|
+ while (<$kinfile>) {
|
|
+ chomp;
|
|
+
|
|
+ # Make sure that lines ending with \ continue
|
|
+ if ($cont) {
|
|
+ $_ = $line . " " . $_;
|
|
+ }
|
|
+
|
|
+ if (s/\\$//) {
|
|
+ $cont = 1;
|
|
+ $line = $_;
|
|
+ next;
|
|
+ }
|
|
+
|
|
+ $cont = 0;
|
|
+
|
|
+ # collect any Kconfig sources
|
|
+ if (/^source\s*"(.*)"/) {
|
|
+ my $kconfig = $1;
|
|
+ # prevent reading twice.
|
|
+ if (!defined($read_kconfigs{$kconfig})) {
|
|
+ $read_kconfigs{$kconfig} = 1;
|
|
+ read_kconfig($kconfig);
|
|
+ }
|
|
+ next;
|
|
+ }
|
|
+
|
|
+ # configs found
|
|
+ if (/^\s*(menu)?config\s+(\S+)\s*$/) {
|
|
+ $state = "NEW";
|
|
+ $config = $2;
|
|
+
|
|
+ # Add depends for 'if' nesting
|
|
+ for (my $i = 0; $i < $iflevel; $i++) {
|
|
+ if ($i) {
|
|
+ $depends{$config} .= " " . $ifdeps[$i];
|
|
+ } else {
|
|
+ $depends{$config} = $ifdeps[$i];
|
|
+ }
|
|
+ $state = "DEP";
|
|
+ }
|
|
+
|
|
+ # collect the depends for the config
|
|
+ } elsif ($state eq "NEW" && /^\s*depends\s+on\s+(.*)$/) {
|
|
+ $state = "DEP";
|
|
+ $depends{$config} = $1;
|
|
+ } elsif ($state eq "DEP" && /^\s*depends\s+on\s+(.*)$/) {
|
|
+ $depends{$config} .= " " . $1;
|
|
+ } elsif ($state eq "DEP" && /^\s*def(_(bool|tristate)|ault)\s+(\S.*)$/) {
|
|
+ my $dep = $3;
|
|
+ if ($dep !~ /^\s*(y|m|n)\s*$/) {
|
|
+ $dep =~ s/.*\sif\s+//;
|
|
+ $depends{$config} .= " " . $dep;
|
|
+ dprint "Added default depends $dep to $config\n";
|
|
+ }
|
|
+
|
|
+ # Get the configs that select this config
|
|
+ } elsif ($state ne "NONE" && /^\s*select\s+(\S+)/) {
|
|
+ my $conf = $1;
|
|
+ if (defined($selects{$conf})) {
|
|
+ $selects{$conf} .= " " . $config;
|
|
+ } else {
|
|
+ $selects{$conf} = $config;
|
|
+ }
|
|
+
|
|
+ # configs without prompts must be selected
|
|
+ } elsif ($state ne "NONE" && /^\s*tristate\s\S/) {
|
|
+ # note if the config has a prompt
|
|
+ $prompts{$config} = 1;
|
|
+
|
|
+ # Check for if statements
|
|
+ } elsif (/^if\s+(.*\S)\s*$/) {
|
|
+ my $deps = $1;
|
|
+ # remove beginning and ending non text
|
|
+ $deps =~ s/^[^a-zA-Z0-9_]*//;
|
|
+ $deps =~ s/[^a-zA-Z0-9_]*$//;
|
|
+
|
|
+ my @deps = split /[^a-zA-Z0-9_]+/, $deps;
|
|
+
|
|
+ $ifdeps[$iflevel++] = join ':', @deps;
|
|
+
|
|
+ } elsif (/^endif/) {
|
|
+
|
|
+ $iflevel-- if ($iflevel);
|
|
+
|
|
+ # stop on "help"
|
|
+ } elsif (/^\s*help\s*$/) {
|
|
+ $state = "NONE";
|
|
+ }
|
|
+ }
|
|
+ close($kinfile);
|
|
+}
|
|
+
|
|
+if ($kconfig) {
|
|
+ read_kconfig($kconfig);
|
|
+}
|
|
+
|
|
+# Makefiles can use variables to define their dependencies
|
|
+sub convert_vars {
|
|
+ my ($line, %vars) = @_;
|
|
+
|
|
+ my $process = "";
|
|
+
|
|
+ while ($line =~ s/^(.*?)(\$\((.*?)\))//) {
|
|
+ my $start = $1;
|
|
+ my $variable = $2;
|
|
+ my $var = $3;
|
|
+
|
|
+ if (defined($vars{$var})) {
|
|
+ $process .= $start . $vars{$var};
|
|
+ } else {
|
|
+ $process .= $start . $variable;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ $process .= $line;
|
|
+
|
|
+ return $process;
|
|
+}
|
|
+
|
|
+# Read all Makefiles to map the configs to the objects
|
|
+foreach my $makefile (@makefiles) {
|
|
+
|
|
+ my $line = "";
|
|
+ my %make_vars;
|
|
+
|
|
+ open(my $infile, '<', $makefile) || die "Can't open $makefile";
|
|
+ while (<$infile>) {
|
|
+ # if this line ends with a backslash, continue
|
|
+ chomp;
|
|
+ if (/^(.*)\\$/) {
|
|
+ $line .= $1;
|
|
+ next;
|
|
+ }
|
|
+
|
|
+ $line .= $_;
|
|
+ $_ = $line;
|
|
+ $line = "";
|
|
+
|
|
+ my $objs;
|
|
+
|
|
+ # Convert variables in a line (could define configs)
|
|
+ $_ = convert_vars($_, %make_vars);
|
|
+
|
|
+ # collect objects after obj-$(CONFIG_FOO_BAR)
|
|
+ if (/obj-\$\((CONFIG_[^\)]*)\)\s*[+:]?=\s*(.*)/) {
|
|
+ $var = $1;
|
|
+ $objs = $2;
|
|
+
|
|
+ # check if variables are set
|
|
+ } elsif (/^\s*(\S+)\s*[:]?=\s*(.*\S)/) {
|
|
+ $make_vars{$1} = $2;
|
|
+ }
|
|
+ if (defined($objs)) {
|
|
+ foreach my $obj (split /\s+/,$objs) {
|
|
+ $obj =~ s/-/_/g;
|
|
+ if ($obj =~ /(.*)\.o$/) {
|
|
+ # Objects may be enabled by more than one config.
|
|
+ # Store configs in an array.
|
|
+ my @arr;
|
|
+
|
|
+ if (defined($objects{$1})) {
|
|
+ @arr = @{$objects{$1}};
|
|
+ }
|
|
+
|
|
+ $arr[$#arr+1] = $var;
|
|
+
|
|
+ # The objects have a hash mapping to a reference
|
|
+ # of an array of configs.
|
|
+ $objects{$1} = \@arr;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ close($infile);
|
|
+}
|
|
+
|
|
+my %modules;
|
|
+my $linfile;
|
|
+
|
|
+if (defined($lsmod_file)) {
|
|
+ if ( ! -f $lsmod_file) {
|
|
+ if ( -f $ENV{'objtree'}."/".$lsmod_file) {
|
|
+ $lsmod_file = $ENV{'objtree'}."/".$lsmod_file;
|
|
+ } else {
|
|
+ die "$lsmod_file not found";
|
|
+ }
|
|
+ }
|
|
+
|
|
+ my $otype = ( -x $lsmod_file) ? '-|' : '<';
|
|
+ open($linfile, $otype, $lsmod_file);
|
|
+
|
|
+} else {
|
|
+
|
|
+ # see what modules are loaded on this system
|
|
+ my $lsmod;
|
|
+
|
|
+ foreach my $dir ( ("/sbin", "/bin", "/usr/sbin", "/usr/bin") ) {
|
|
+ if ( -x "$dir/lsmod" ) {
|
|
+ $lsmod = "$dir/lsmod";
|
|
+ last;
|
|
+ }
|
|
+}
|
|
+ if (!defined($lsmod)) {
|
|
+ # try just the path
|
|
+ $lsmod = "lsmod";
|
|
+ }
|
|
+
|
|
+ open($linfile, '-|', $lsmod) || die "Can not call lsmod with $lsmod";
|
|
+}
|
|
+
|
|
+while (<$linfile>) {
|
|
+ next if (/^Module/); # Skip the first line.
|
|
+ if (/^(\S+)/) {
|
|
+ $modules{$1} = 1;
|
|
+ }
|
|
+}
|
|
+close ($linfile);
|
|
+
|
|
+# add to the configs hash all configs that are needed to enable
|
|
+# a loaded module. This is a direct obj-${CONFIG_FOO} += bar.o
|
|
+# where we know we need bar.o so we add FOO to the list.
|
|
+my %configs;
|
|
+foreach my $module (keys(%modules)) {
|
|
+ if (defined($objects{$module})) {
|
|
+ my @arr = @{$objects{$module}};
|
|
+ foreach my $conf (@arr) {
|
|
+ $configs{$conf} = $module;
|
|
+ dprint "$conf added by direct ($module)\n";
|
|
+ if ($debugprint) {
|
|
+ my $c=$conf;
|
|
+ $c =~ s/^CONFIG_//;
|
|
+ if (defined($depends{$c})) {
|
|
+ dprint " deps = $depends{$c}\n";
|
|
+ } else {
|
|
+ dprint " no deps\n";
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ } else {
|
|
+ # Most likely, someone has a custom (binary?) module loaded.
|
|
+ print STDERR "$module config not found!!\n";
|
|
+ }
|
|
+}
|
|
+
|
|
+# Read the current config, and see what is enabled. We want to
|
|
+# ignore configs that we would not enable anyway.
|
|
+
|
|
+my %orig_configs;
|
|
+my $valid = "A-Za-z_0-9";
|
|
+
|
|
+foreach my $line (@config_file) {
|
|
+ $_ = $line;
|
|
+
|
|
+ if (/(CONFIG_[$valid]*)=(m|y)/) {
|
|
+ $orig_configs{$1} = $2;
|
|
+ }
|
|
+}
|
|
+
|
|
+my $repeat = 1;
|
|
+
|
|
+my $depconfig;
|
|
+
|
|
+#
|
|
+# Note, we do not care about operands (like: &&, ||, !) we want to add any
|
|
+# config that is in the depend list of another config. This script does
|
|
+# not enable configs that are not already enabled. If we come across a
|
|
+# config A that depends on !B, we can still add B to the list of depends
|
|
+# to keep on. If A was on in the original config, B would not have been
|
|
+# and B would not be turned on by this script.
|
|
+#
|
|
+sub parse_config_depends
|
|
+{
|
|
+ my ($p) = @_;
|
|
+
|
|
+ while ($p =~ /[$valid]/) {
|
|
+
|
|
+ if ($p =~ /^[^$valid]*([$valid]+)/) {
|
|
+ my $conf = "CONFIG_" . $1;
|
|
+
|
|
+ $p =~ s/^[^$valid]*[$valid]+//;
|
|
+
|
|
+ # We only need to process if the depend config is a module
|
|
+ if (!defined($orig_configs{$conf}) || !$orig_configs{conf} eq "m") {
|
|
+ next;
|
|
+ }
|
|
+
|
|
+ if (!defined($configs{$conf})) {
|
|
+ # We must make sure that this config has its
|
|
+ # dependencies met.
|
|
+ $repeat = 1; # do again
|
|
+ dprint "$conf selected by depend $depconfig\n";
|
|
+ $configs{$conf} = 1;
|
|
+ }
|
|
+ } else {
|
|
+ die "this should never happen";
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+# Select is treated a bit differently than depends. We call this
|
|
+# when a config has no prompt and requires another config to be
|
|
+# selected. We use to just select all configs that selected this
|
|
+# config, but found that that can balloon into enabling hundreds
|
|
+# of configs that we do not care about.
|
|
+#
|
|
+# The idea is we look at all the configs that select it. If one
|
|
+# is already in our list of configs to enable, then there's nothing
|
|
+# else to do. If there isn't, we pick the first config that was
|
|
+# enabled in the orignal config and use that.
|
|
+sub parse_config_selects
|
|
+{
|
|
+ my ($config, $p) = @_;
|
|
+
|
|
+ my $next_config;
|
|
+
|
|
+ while ($p =~ /[$valid]/) {
|
|
+
|
|
+ if ($p =~ /^[^$valid]*([$valid]+)/) {
|
|
+ my $conf = "CONFIG_" . $1;
|
|
+
|
|
+ $p =~ s/^[^$valid]*[$valid]+//;
|
|
+
|
|
+ # Make sure that this config exists in the current .config file
|
|
+ if (!defined($orig_configs{$conf})) {
|
|
+ dprint "$conf not set for $config select\n";
|
|
+ next;
|
|
+ }
|
|
+
|
|
+ # Check if something other than a module selects this config
|
|
+ if (defined($orig_configs{$conf}) && $orig_configs{$conf} ne "m") {
|
|
+ dprint "$conf (non module) selects config, we are good\n";
|
|
+ # we are good with this
|
|
+ return;
|
|
+ }
|
|
+ if (defined($configs{$conf})) {
|
|
+ dprint "$conf selects $config so we are good\n";
|
|
+ # A set config selects this config, we are good
|
|
+ return;
|
|
+ }
|
|
+ # Set this config to be selected
|
|
+ if (!defined($next_config)) {
|
|
+ $next_config = $conf;
|
|
+ }
|
|
+ } else {
|
|
+ die "this should never happen";
|
|
+ }
|
|
+ }
|
|
+
|
|
+ # If no possible config selected this, then something happened.
|
|
+ if (!defined($next_config)) {
|
|
+ print STDERR "WARNING: $config is required, but nothing in the\n";
|
|
+ print STDERR " current config selects it.\n";
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ # If we are here, then we found no config that is set and
|
|
+ # selects this config. Repeat.
|
|
+ $repeat = 1;
|
|
+ # Make this config need to be selected
|
|
+ $configs{$next_config} = 1;
|
|
+ dprint "$next_config selected by select $config\n";
|
|
+}
|
|
+
|
|
+my %process_selects;
|
|
+
|
|
+# loop through all configs, select their dependencies.
|
|
+sub loop_depend {
|
|
+ $repeat = 1;
|
|
+
|
|
+ while ($repeat) {
|
|
+ $repeat = 0;
|
|
+
|
|
+ forloop:
|
|
+ foreach my $config (keys %configs) {
|
|
+
|
|
+ # If this config is not a module, we do not need to process it
|
|
+ if (defined($orig_configs{$config}) && $orig_configs{$config} ne "m") {
|
|
+ next forloop;
|
|
+ }
|
|
+
|
|
+ $config =~ s/^CONFIG_//;
|
|
+ $depconfig = $config;
|
|
+
|
|
+ if (defined($depends{$config})) {
|
|
+ # This config has dependencies. Make sure they are also included
|
|
+ parse_config_depends $depends{$config};
|
|
+ }
|
|
+
|
|
+ # If the config has no prompt, then we need to check if a config
|
|
+ # that is enabled selected it. Or if we need to enable one.
|
|
+ if (!defined($prompts{$config}) && defined($selects{$config})) {
|
|
+ $process_selects{$config} = 1;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+sub loop_select {
|
|
+
|
|
+ foreach my $config (keys %process_selects) {
|
|
+ $config =~ s/^CONFIG_//;
|
|
+
|
|
+ dprint "Process select $config\n";
|
|
+
|
|
+ # config has no prompt and must be selected.
|
|
+ parse_config_selects $config, $selects{$config};
|
|
+ }
|
|
+}
|
|
+
|
|
+while ($repeat) {
|
|
+ # Get the first set of configs and their dependencies.
|
|
+ loop_depend;
|
|
+
|
|
+ $repeat = 0;
|
|
+
|
|
+ # Now we need to see if we have to check selects;
|
|
+ loop_select;
|
|
+}
|
|
+
|
|
+my %setconfigs;
|
|
+
|
|
+# Finally, read the .config file and turn off any module enabled that
|
|
+# we could not find a reason to keep enabled.
|
|
+foreach my $line (@config_file) {
|
|
+ $_ = $line;
|
|
+
|
|
+ if (/CONFIG_IKCONFIG/) {
|
|
+ if (/# CONFIG_IKCONFIG is not set/) {
|
|
+ # enable IKCONFIG at least as a module
|
|
+ print "CONFIG_IKCONFIG=m\n";
|
|
+ # don't ask about PROC
|
|
+ print "# CONFIG_IKCONFIG_PROC is not set\n";
|
|
+ } else {
|
|
+ print;
|
|
+ }
|
|
+ next;
|
|
+ }
|
|
+
|
|
+ if (/^(CONFIG.*)=(m|y)/) {
|
|
+ if (defined($configs{$1})) {
|
|
+ if ($localyesconfig) {
|
|
+ $setconfigs{$1} = 'y';
|
|
+ print "$1=y\n";
|
|
+ next;
|
|
+ } else {
|
|
+ $setconfigs{$1} = $2;
|
|
+ }
|
|
+ } elsif ($2 eq "m") {
|
|
+ print "# $1 is not set\n";
|
|
+ next;
|
|
+ }
|
|
+ }
|
|
+ print;
|
|
+}
|
|
+
|
|
+# Integrity check, make sure all modules that we want enabled do
|
|
+# indeed have their configs set.
|
|
+loop:
|
|
+foreach my $module (keys(%modules)) {
|
|
+ if (defined($objects{$module})) {
|
|
+ my @arr = @{$objects{$module}};
|
|
+ foreach my $conf (@arr) {
|
|
+ if (defined($setconfigs{$conf})) {
|
|
+ next loop;
|
|
+ }
|
|
+ }
|
|
+ print STDERR "module $module did not have configs";
|
|
+ foreach my $conf (@arr) {
|
|
+ print STDERR " " , $conf;
|
|
+ }
|
|
+ print STDERR "\n";
|
|
+ }
|
|
+}
|
|
diff --git a/scripts/kconfig/zconf.gperf b/scripts/kconfig/zconf.gperf
|
|
new file mode 100644
|
|
index 0000000..b6ac02d
|
|
--- /dev/null
|
|
+++ b/scripts/kconfig/zconf.gperf
|
|
@@ -0,0 +1,48 @@
|
|
+%language=ANSI-C
|
|
+%define hash-function-name kconf_id_hash
|
|
+%define lookup-function-name kconf_id_lookup
|
|
+%define string-pool-name kconf_id_strings
|
|
+%compare-strncmp
|
|
+%enum
|
|
+%pic
|
|
+%struct-type
|
|
+
|
|
+struct kconf_id;
|
|
+
|
|
+static const struct kconf_id *kconf_id_lookup(register const char *str, register unsigned int len);
|
|
+
|
|
+%%
|
|
+mainmenu, T_MAINMENU, TF_COMMAND
|
|
+menu, T_MENU, TF_COMMAND
|
|
+endmenu, T_ENDMENU, TF_COMMAND
|
|
+source, T_SOURCE, TF_COMMAND
|
|
+choice, T_CHOICE, TF_COMMAND
|
|
+endchoice, T_ENDCHOICE, TF_COMMAND
|
|
+comment, T_COMMENT, TF_COMMAND
|
|
+config, T_CONFIG, TF_COMMAND
|
|
+menuconfig, T_MENUCONFIG, TF_COMMAND
|
|
+help, T_HELP, TF_COMMAND
|
|
+if, T_IF, TF_COMMAND|TF_PARAM
|
|
+endif, T_ENDIF, TF_COMMAND
|
|
+depends, T_DEPENDS, TF_COMMAND
|
|
+optional, T_OPTIONAL, TF_COMMAND
|
|
+default, T_DEFAULT, TF_COMMAND, S_UNKNOWN
|
|
+prompt, T_PROMPT, TF_COMMAND
|
|
+tristate, T_TYPE, TF_COMMAND, S_TRISTATE
|
|
+def_tristate, T_DEFAULT, TF_COMMAND, S_TRISTATE
|
|
+bool, T_TYPE, TF_COMMAND, S_BOOLEAN
|
|
+boolean, T_TYPE, TF_COMMAND, S_BOOLEAN
|
|
+def_bool, T_DEFAULT, TF_COMMAND, S_BOOLEAN
|
|
+int, T_TYPE, TF_COMMAND, S_INT
|
|
+hex, T_TYPE, TF_COMMAND, S_HEX
|
|
+string, T_TYPE, TF_COMMAND, S_STRING
|
|
+select, T_SELECT, TF_COMMAND
|
|
+range, T_RANGE, TF_COMMAND
|
|
+visible, T_VISIBLE, TF_COMMAND
|
|
+option, T_OPTION, TF_COMMAND
|
|
+on, T_ON, TF_PARAM
|
|
+modules, T_OPT_MODULES, TF_OPTION
|
|
+defconfig_list, T_OPT_DEFCONFIG_LIST,TF_OPTION
|
|
+env, T_OPT_ENV, TF_OPTION
|
|
+allnoconfig_y, T_OPT_ALLNOCONFIG_Y,TF_OPTION
|
|
+%%
|
|
diff --git a/scripts/kconfig/zconf.l b/scripts/kconfig/zconf.l
|
|
new file mode 100644
|
|
index 0000000..6c62d93
|
|
--- /dev/null
|
|
+++ b/scripts/kconfig/zconf.l
|
|
@@ -0,0 +1,363 @@
|
|
+%option nostdinit noyywrap never-interactive full ecs
|
|
+%option 8bit nodefault perf-report perf-report
|
|
+%option noinput
|
|
+%x COMMAND HELP STRING PARAM
|
|
+%{
|
|
+/*
|
|
+ * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
|
|
+ * Released under the terms of the GNU GPL v2.0.
|
|
+ */
|
|
+
|
|
+#include <limits.h>
|
|
+#include <stdio.h>
|
|
+#include <stdlib.h>
|
|
+#include <string.h>
|
|
+#include <unistd.h>
|
|
+
|
|
+#include "lkc.h"
|
|
+
|
|
+#define START_STRSIZE 16
|
|
+
|
|
+static struct {
|
|
+ struct file *file;
|
|
+ int lineno;
|
|
+} current_pos;
|
|
+
|
|
+static char *text;
|
|
+static int text_size, text_asize;
|
|
+
|
|
+struct buffer {
|
|
+ struct buffer *parent;
|
|
+ YY_BUFFER_STATE state;
|
|
+};
|
|
+
|
|
+struct buffer *current_buf;
|
|
+
|
|
+static int last_ts, first_ts;
|
|
+
|
|
+static void zconf_endhelp(void);
|
|
+static void zconf_endfile(void);
|
|
+
|
|
+static void new_string(void)
|
|
+{
|
|
+ text = xmalloc(START_STRSIZE);
|
|
+ text_asize = START_STRSIZE;
|
|
+ text_size = 0;
|
|
+ *text = 0;
|
|
+}
|
|
+
|
|
+static void append_string(const char *str, int size)
|
|
+{
|
|
+ int new_size = text_size + size + 1;
|
|
+ if (new_size > text_asize) {
|
|
+ new_size += START_STRSIZE - 1;
|
|
+ new_size &= -START_STRSIZE;
|
|
+ text = realloc(text, new_size);
|
|
+ text_asize = new_size;
|
|
+ }
|
|
+ memcpy(text + text_size, str, size);
|
|
+ text_size += size;
|
|
+ text[text_size] = 0;
|
|
+}
|
|
+
|
|
+static void alloc_string(const char *str, int size)
|
|
+{
|
|
+ text = xmalloc(size + 1);
|
|
+ memcpy(text, str, size);
|
|
+ text[size] = 0;
|
|
+}
|
|
+%}
|
|
+
|
|
+n [A-Za-z0-9_]
|
|
+
|
|
+%%
|
|
+ int str = 0;
|
|
+ int ts, i;
|
|
+
|
|
+[ \t]*#.*\n |
|
|
+[ \t]*\n {
|
|
+ current_file->lineno++;
|
|
+ return T_EOL;
|
|
+}
|
|
+[ \t]*#.*
|
|
+
|
|
+
|
|
+[ \t]+ {
|
|
+ BEGIN(COMMAND);
|
|
+}
|
|
+
|
|
+. {
|
|
+ unput(yytext[0]);
|
|
+ BEGIN(COMMAND);
|
|
+}
|
|
+
|
|
+
|
|
+<COMMAND>{
|
|
+ {n}+ {
|
|
+ const struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
|
|
+ BEGIN(PARAM);
|
|
+ current_pos.file = current_file;
|
|
+ current_pos.lineno = current_file->lineno;
|
|
+ if (id && id->flags & TF_COMMAND) {
|
|
+ zconflval.id = id;
|
|
+ return id->token;
|
|
+ }
|
|
+ alloc_string(yytext, yyleng);
|
|
+ zconflval.string = text;
|
|
+ return T_WORD;
|
|
+ }
|
|
+ .
|
|
+ \n {
|
|
+ BEGIN(INITIAL);
|
|
+ current_file->lineno++;
|
|
+ return T_EOL;
|
|
+ }
|
|
+}
|
|
+
|
|
+<PARAM>{
|
|
+ "&&" return T_AND;
|
|
+ "||" return T_OR;
|
|
+ "(" return T_OPEN_PAREN;
|
|
+ ")" return T_CLOSE_PAREN;
|
|
+ "!" return T_NOT;
|
|
+ "=" return T_EQUAL;
|
|
+ "!=" return T_UNEQUAL;
|
|
+ \"|\' {
|
|
+ str = yytext[0];
|
|
+ new_string();
|
|
+ BEGIN(STRING);
|
|
+ }
|
|
+ \n BEGIN(INITIAL); current_file->lineno++; return T_EOL;
|
|
+ --- /* ignore */
|
|
+ ({n}|[-/.])+ {
|
|
+ const struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
|
|
+ if (id && id->flags & TF_PARAM) {
|
|
+ zconflval.id = id;
|
|
+ return id->token;
|
|
+ }
|
|
+ alloc_string(yytext, yyleng);
|
|
+ zconflval.string = text;
|
|
+ return T_WORD;
|
|
+ }
|
|
+ #.* /* comment */
|
|
+ \\\n current_file->lineno++;
|
|
+ .
|
|
+ <<EOF>> {
|
|
+ BEGIN(INITIAL);
|
|
+ }
|
|
+}
|
|
+
|
|
+<STRING>{
|
|
+ [^'"\\\n]+/\n {
|
|
+ append_string(yytext, yyleng);
|
|
+ zconflval.string = text;
|
|
+ return T_WORD_QUOTE;
|
|
+ }
|
|
+ [^'"\\\n]+ {
|
|
+ append_string(yytext, yyleng);
|
|
+ }
|
|
+ \\.?/\n {
|
|
+ append_string(yytext + 1, yyleng - 1);
|
|
+ zconflval.string = text;
|
|
+ return T_WORD_QUOTE;
|
|
+ }
|
|
+ \\.? {
|
|
+ append_string(yytext + 1, yyleng - 1);
|
|
+ }
|
|
+ \'|\" {
|
|
+ if (str == yytext[0]) {
|
|
+ BEGIN(PARAM);
|
|
+ zconflval.string = text;
|
|
+ return T_WORD_QUOTE;
|
|
+ } else
|
|
+ append_string(yytext, 1);
|
|
+ }
|
|
+ \n {
|
|
+ printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno());
|
|
+ current_file->lineno++;
|
|
+ BEGIN(INITIAL);
|
|
+ return T_EOL;
|
|
+ }
|
|
+ <<EOF>> {
|
|
+ BEGIN(INITIAL);
|
|
+ }
|
|
+}
|
|
+
|
|
+<HELP>{
|
|
+ [ \t]+ {
|
|
+ ts = 0;
|
|
+ for (i = 0; i < yyleng; i++) {
|
|
+ if (yytext[i] == '\t')
|
|
+ ts = (ts & ~7) + 8;
|
|
+ else
|
|
+ ts++;
|
|
+ }
|
|
+ last_ts = ts;
|
|
+ if (first_ts) {
|
|
+ if (ts < first_ts) {
|
|
+ zconf_endhelp();
|
|
+ return T_HELPTEXT;
|
|
+ }
|
|
+ ts -= first_ts;
|
|
+ while (ts > 8) {
|
|
+ append_string(" ", 8);
|
|
+ ts -= 8;
|
|
+ }
|
|
+ append_string(" ", ts);
|
|
+ }
|
|
+ }
|
|
+ [ \t]*\n/[^ \t\n] {
|
|
+ current_file->lineno++;
|
|
+ zconf_endhelp();
|
|
+ return T_HELPTEXT;
|
|
+ }
|
|
+ [ \t]*\n {
|
|
+ current_file->lineno++;
|
|
+ append_string("\n", 1);
|
|
+ }
|
|
+ [^ \t\n].* {
|
|
+ while (yyleng) {
|
|
+ if ((yytext[yyleng-1] != ' ') && (yytext[yyleng-1] != '\t'))
|
|
+ break;
|
|
+ yyleng--;
|
|
+ }
|
|
+ append_string(yytext, yyleng);
|
|
+ if (!first_ts)
|
|
+ first_ts = last_ts;
|
|
+ }
|
|
+ <<EOF>> {
|
|
+ zconf_endhelp();
|
|
+ return T_HELPTEXT;
|
|
+ }
|
|
+}
|
|
+
|
|
+<<EOF>> {
|
|
+ if (current_file) {
|
|
+ zconf_endfile();
|
|
+ return T_EOL;
|
|
+ }
|
|
+ fclose(yyin);
|
|
+ yyterminate();
|
|
+}
|
|
+
|
|
+%%
|
|
+void zconf_starthelp(void)
|
|
+{
|
|
+ new_string();
|
|
+ last_ts = first_ts = 0;
|
|
+ BEGIN(HELP);
|
|
+}
|
|
+
|
|
+static void zconf_endhelp(void)
|
|
+{
|
|
+ zconflval.string = text;
|
|
+ BEGIN(INITIAL);
|
|
+}
|
|
+
|
|
+
|
|
+/*
|
|
+ * Try to open specified file with following names:
|
|
+ * ./name
|
|
+ * $(srctree)/name
|
|
+ * The latter is used when srctree is separate from objtree
|
|
+ * when compiling the kernel.
|
|
+ * Return NULL if file is not found.
|
|
+ */
|
|
+FILE *zconf_fopen(const char *name)
|
|
+{
|
|
+ char *env, fullname[PATH_MAX+1];
|
|
+ FILE *f;
|
|
+
|
|
+ f = fopen(name, "r");
|
|
+ if (!f && name != NULL && name[0] != '/') {
|
|
+ env = getenv(SRCTREE);
|
|
+ if (env) {
|
|
+ sprintf(fullname, "%s/%s", env, name);
|
|
+ f = fopen(fullname, "r");
|
|
+ }
|
|
+ }
|
|
+ return f;
|
|
+}
|
|
+
|
|
+void zconf_initscan(const char *name)
|
|
+{
|
|
+ yyin = zconf_fopen(name);
|
|
+ if (!yyin) {
|
|
+ printf("can't find file %s\n", name);
|
|
+ exit(1);
|
|
+ }
|
|
+
|
|
+ current_buf = xmalloc(sizeof(*current_buf));
|
|
+ memset(current_buf, 0, sizeof(*current_buf));
|
|
+
|
|
+ current_file = file_lookup(name);
|
|
+ current_file->lineno = 1;
|
|
+}
|
|
+
|
|
+void zconf_nextfile(const char *name)
|
|
+{
|
|
+ struct file *iter;
|
|
+ struct file *file = file_lookup(name);
|
|
+ struct buffer *buf = xmalloc(sizeof(*buf));
|
|
+ memset(buf, 0, sizeof(*buf));
|
|
+
|
|
+ current_buf->state = YY_CURRENT_BUFFER;
|
|
+ yyin = zconf_fopen(file->name);
|
|
+ if (!yyin) {
|
|
+ printf("%s:%d: can't open file \"%s\"\n",
|
|
+ zconf_curname(), zconf_lineno(), file->name);
|
|
+ exit(1);
|
|
+ }
|
|
+ yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
|
|
+ buf->parent = current_buf;
|
|
+ current_buf = buf;
|
|
+
|
|
+ for (iter = current_file->parent; iter; iter = iter->parent ) {
|
|
+ if (!strcmp(current_file->name,iter->name) ) {
|
|
+ printf("%s:%d: recursive inclusion detected. "
|
|
+ "Inclusion path:\n current file : '%s'\n",
|
|
+ zconf_curname(), zconf_lineno(),
|
|
+ zconf_curname());
|
|
+ iter = current_file->parent;
|
|
+ while (iter && \
|
|
+ strcmp(iter->name,current_file->name)) {
|
|
+ printf(" included from: '%s:%d'\n",
|
|
+ iter->name, iter->lineno-1);
|
|
+ iter = iter->parent;
|
|
+ }
|
|
+ if (iter)
|
|
+ printf(" included from: '%s:%d'\n",
|
|
+ iter->name, iter->lineno+1);
|
|
+ exit(1);
|
|
+ }
|
|
+ }
|
|
+ file->lineno = 1;
|
|
+ file->parent = current_file;
|
|
+ current_file = file;
|
|
+}
|
|
+
|
|
+static void zconf_endfile(void)
|
|
+{
|
|
+ struct buffer *parent;
|
|
+
|
|
+ current_file = current_file->parent;
|
|
+
|
|
+ parent = current_buf->parent;
|
|
+ if (parent) {
|
|
+ fclose(yyin);
|
|
+ yy_delete_buffer(YY_CURRENT_BUFFER);
|
|
+ yy_switch_to_buffer(parent->state);
|
|
+ }
|
|
+ free(current_buf);
|
|
+ current_buf = parent;
|
|
+}
|
|
+
|
|
+int zconf_lineno(void)
|
|
+{
|
|
+ return current_pos.lineno;
|
|
+}
|
|
+
|
|
+const char *zconf_curname(void)
|
|
+{
|
|
+ return current_pos.file ? current_pos.file->name : "<none>";
|
|
+}
|
|
diff --git a/scripts/kconfig/zconf.y b/scripts/kconfig/zconf.y
|
|
new file mode 100644
|
|
index 0000000..0f683cf
|
|
--- /dev/null
|
|
+++ b/scripts/kconfig/zconf.y
|
|
@@ -0,0 +1,733 @@
|
|
+%{
|
|
+/*
|
|
+ * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
|
|
+ * Released under the terms of the GNU GPL v2.0.
|
|
+ */
|
|
+
|
|
+#include <ctype.h>
|
|
+#include <stdarg.h>
|
|
+#include <stdio.h>
|
|
+#include <stdlib.h>
|
|
+#include <string.h>
|
|
+#include <stdbool.h>
|
|
+
|
|
+#include "lkc.h"
|
|
+
|
|
+#define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt)
|
|
+
|
|
+#define PRINTD 0x0001
|
|
+#define DEBUG_PARSE 0x0002
|
|
+
|
|
+int cdebug = PRINTD;
|
|
+
|
|
+extern int zconflex(void);
|
|
+static void zconfprint(const char *err, ...);
|
|
+static void zconf_error(const char *err, ...);
|
|
+static void zconferror(const char *err);
|
|
+static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken);
|
|
+
|
|
+struct symbol *symbol_hash[SYMBOL_HASHSIZE];
|
|
+
|
|
+static struct menu *current_menu, *current_entry;
|
|
+
|
|
+%}
|
|
+%expect 30
|
|
+
|
|
+%union
|
|
+{
|
|
+ char *string;
|
|
+ struct file *file;
|
|
+ struct symbol *symbol;
|
|
+ struct expr *expr;
|
|
+ struct menu *menu;
|
|
+ const struct kconf_id *id;
|
|
+}
|
|
+
|
|
+%token <id>T_MAINMENU
|
|
+%token <id>T_MENU
|
|
+%token <id>T_ENDMENU
|
|
+%token <id>T_SOURCE
|
|
+%token <id>T_CHOICE
|
|
+%token <id>T_ENDCHOICE
|
|
+%token <id>T_COMMENT
|
|
+%token <id>T_CONFIG
|
|
+%token <id>T_MENUCONFIG
|
|
+%token <id>T_HELP
|
|
+%token <string> T_HELPTEXT
|
|
+%token <id>T_IF
|
|
+%token <id>T_ENDIF
|
|
+%token <id>T_DEPENDS
|
|
+%token <id>T_OPTIONAL
|
|
+%token <id>T_PROMPT
|
|
+%token <id>T_TYPE
|
|
+%token <id>T_DEFAULT
|
|
+%token <id>T_SELECT
|
|
+%token <id>T_RANGE
|
|
+%token <id>T_VISIBLE
|
|
+%token <id>T_OPTION
|
|
+%token <id>T_ON
|
|
+%token <string> T_WORD
|
|
+%token <string> T_WORD_QUOTE
|
|
+%token T_UNEQUAL
|
|
+%token T_CLOSE_PAREN
|
|
+%token T_OPEN_PAREN
|
|
+%token T_EOL
|
|
+
|
|
+%left T_OR
|
|
+%left T_AND
|
|
+%left T_EQUAL T_UNEQUAL
|
|
+%nonassoc T_NOT
|
|
+
|
|
+%type <string> prompt
|
|
+%type <symbol> symbol
|
|
+%type <expr> expr
|
|
+%type <expr> if_expr
|
|
+%type <id> end
|
|
+%type <id> option_name
|
|
+%type <menu> if_entry menu_entry choice_entry
|
|
+%type <string> symbol_option_arg word_opt
|
|
+
|
|
+%destructor {
|
|
+ fprintf(stderr, "%s:%d: missing end statement for this entry\n",
|
|
+ $$->file->name, $$->lineno);
|
|
+ if (current_menu == $$)
|
|
+ menu_end_menu();
|
|
+} if_entry menu_entry choice_entry
|
|
+
|
|
+%{
|
|
+/* Include zconf.hash.c here so it can see the token constants. */
|
|
+#include "zconf.hash.c"
|
|
+%}
|
|
+
|
|
+%%
|
|
+input: nl start | start;
|
|
+
|
|
+start: mainmenu_stmt stmt_list | stmt_list;
|
|
+
|
|
+stmt_list:
|
|
+ /* empty */
|
|
+ | stmt_list common_stmt
|
|
+ | stmt_list choice_stmt
|
|
+ | stmt_list menu_stmt
|
|
+ | stmt_list end { zconf_error("unexpected end statement"); }
|
|
+ | stmt_list T_WORD error T_EOL { zconf_error("unknown statement \"%s\"", $2); }
|
|
+ | stmt_list option_name error T_EOL
|
|
+{
|
|
+ zconf_error("unexpected option \"%s\"", kconf_id_strings + $2->name);
|
|
+}
|
|
+ | stmt_list error T_EOL { zconf_error("invalid statement"); }
|
|
+;
|
|
+
|
|
+option_name:
|
|
+ T_DEPENDS | T_PROMPT | T_TYPE | T_SELECT | T_OPTIONAL | T_RANGE | T_DEFAULT | T_VISIBLE
|
|
+;
|
|
+
|
|
+common_stmt:
|
|
+ T_EOL
|
|
+ | if_stmt
|
|
+ | comment_stmt
|
|
+ | config_stmt
|
|
+ | menuconfig_stmt
|
|
+ | source_stmt
|
|
+;
|
|
+
|
|
+option_error:
|
|
+ T_WORD error T_EOL { zconf_error("unknown option \"%s\"", $1); }
|
|
+ | error T_EOL { zconf_error("invalid option"); }
|
|
+;
|
|
+
|
|
+
|
|
+/* config/menuconfig entry */
|
|
+
|
|
+config_entry_start: T_CONFIG T_WORD T_EOL
|
|
+{
|
|
+ struct symbol *sym = sym_lookup($2, 0);
|
|
+ sym->flags |= SYMBOL_OPTIONAL;
|
|
+ menu_add_entry(sym);
|
|
+ printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), $2);
|
|
+};
|
|
+
|
|
+config_stmt: config_entry_start config_option_list
|
|
+{
|
|
+ menu_end_entry();
|
|
+ printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
|
|
+};
|
|
+
|
|
+menuconfig_entry_start: T_MENUCONFIG T_WORD T_EOL
|
|
+{
|
|
+ struct symbol *sym = sym_lookup($2, 0);
|
|
+ sym->flags |= SYMBOL_OPTIONAL;
|
|
+ menu_add_entry(sym);
|
|
+ printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), $2);
|
|
+};
|
|
+
|
|
+menuconfig_stmt: menuconfig_entry_start config_option_list
|
|
+{
|
|
+ if (current_entry->prompt)
|
|
+ current_entry->prompt->type = P_MENU;
|
|
+ else
|
|
+ zconfprint("warning: menuconfig statement without prompt");
|
|
+ menu_end_entry();
|
|
+ printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
|
|
+};
|
|
+
|
|
+config_option_list:
|
|
+ /* empty */
|
|
+ | config_option_list config_option
|
|
+ | config_option_list symbol_option
|
|
+ | config_option_list depends
|
|
+ | config_option_list help
|
|
+ | config_option_list option_error
|
|
+ | config_option_list T_EOL
|
|
+;
|
|
+
|
|
+config_option: T_TYPE prompt_stmt_opt T_EOL
|
|
+{
|
|
+ menu_set_type($1->stype);
|
|
+ printd(DEBUG_PARSE, "%s:%d:type(%u)\n",
|
|
+ zconf_curname(), zconf_lineno(),
|
|
+ $1->stype);
|
|
+};
|
|
+
|
|
+config_option: T_PROMPT prompt if_expr T_EOL
|
|
+{
|
|
+ menu_add_prompt(P_PROMPT, $2, $3);
|
|
+ printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
|
|
+};
|
|
+
|
|
+config_option: T_DEFAULT expr if_expr T_EOL
|
|
+{
|
|
+ menu_add_expr(P_DEFAULT, $2, $3);
|
|
+ if ($1->stype != S_UNKNOWN)
|
|
+ menu_set_type($1->stype);
|
|
+ printd(DEBUG_PARSE, "%s:%d:default(%u)\n",
|
|
+ zconf_curname(), zconf_lineno(),
|
|
+ $1->stype);
|
|
+};
|
|
+
|
|
+config_option: T_SELECT T_WORD if_expr T_EOL
|
|
+{
|
|
+ menu_add_symbol(P_SELECT, sym_lookup($2, 0), $3);
|
|
+ printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno());
|
|
+};
|
|
+
|
|
+config_option: T_RANGE symbol symbol if_expr T_EOL
|
|
+{
|
|
+ menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,$2, $3), $4);
|
|
+ printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno());
|
|
+};
|
|
+
|
|
+symbol_option: T_OPTION symbol_option_list T_EOL
|
|
+;
|
|
+
|
|
+symbol_option_list:
|
|
+ /* empty */
|
|
+ | symbol_option_list T_WORD symbol_option_arg
|
|
+{
|
|
+ const struct kconf_id *id = kconf_id_lookup($2, strlen($2));
|
|
+ if (id && id->flags & TF_OPTION)
|
|
+ menu_add_option(id->token, $3);
|
|
+ else
|
|
+ zconfprint("warning: ignoring unknown option %s", $2);
|
|
+ free($2);
|
|
+};
|
|
+
|
|
+symbol_option_arg:
|
|
+ /* empty */ { $$ = NULL; }
|
|
+ | T_EQUAL prompt { $$ = $2; }
|
|
+;
|
|
+
|
|
+/* choice entry */
|
|
+
|
|
+choice: T_CHOICE word_opt T_EOL
|
|
+{
|
|
+ struct symbol *sym = sym_lookup($2, SYMBOL_CHOICE);
|
|
+ sym->flags |= SYMBOL_AUTO;
|
|
+ menu_add_entry(sym);
|
|
+ menu_add_expr(P_CHOICE, NULL, NULL);
|
|
+ printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno());
|
|
+};
|
|
+
|
|
+choice_entry: choice choice_option_list
|
|
+{
|
|
+ $$ = menu_add_menu();
|
|
+};
|
|
+
|
|
+choice_end: end
|
|
+{
|
|
+ if (zconf_endtoken($1, T_CHOICE, T_ENDCHOICE)) {
|
|
+ menu_end_menu();
|
|
+ printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno());
|
|
+ }
|
|
+};
|
|
+
|
|
+choice_stmt: choice_entry choice_block choice_end
|
|
+;
|
|
+
|
|
+choice_option_list:
|
|
+ /* empty */
|
|
+ | choice_option_list choice_option
|
|
+ | choice_option_list depends
|
|
+ | choice_option_list help
|
|
+ | choice_option_list T_EOL
|
|
+ | choice_option_list option_error
|
|
+;
|
|
+
|
|
+choice_option: T_PROMPT prompt if_expr T_EOL
|
|
+{
|
|
+ menu_add_prompt(P_PROMPT, $2, $3);
|
|
+ printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
|
|
+};
|
|
+
|
|
+choice_option: T_TYPE prompt_stmt_opt T_EOL
|
|
+{
|
|
+ if ($1->stype == S_BOOLEAN || $1->stype == S_TRISTATE) {
|
|
+ menu_set_type($1->stype);
|
|
+ printd(DEBUG_PARSE, "%s:%d:type(%u)\n",
|
|
+ zconf_curname(), zconf_lineno(),
|
|
+ $1->stype);
|
|
+ } else
|
|
+ YYERROR;
|
|
+};
|
|
+
|
|
+choice_option: T_OPTIONAL T_EOL
|
|
+{
|
|
+ current_entry->sym->flags |= SYMBOL_OPTIONAL;
|
|
+ printd(DEBUG_PARSE, "%s:%d:optional\n", zconf_curname(), zconf_lineno());
|
|
+};
|
|
+
|
|
+choice_option: T_DEFAULT T_WORD if_expr T_EOL
|
|
+{
|
|
+ if ($1->stype == S_UNKNOWN) {
|
|
+ menu_add_symbol(P_DEFAULT, sym_lookup($2, 0), $3);
|
|
+ printd(DEBUG_PARSE, "%s:%d:default\n",
|
|
+ zconf_curname(), zconf_lineno());
|
|
+ } else
|
|
+ YYERROR;
|
|
+};
|
|
+
|
|
+choice_block:
|
|
+ /* empty */
|
|
+ | choice_block common_stmt
|
|
+;
|
|
+
|
|
+/* if entry */
|
|
+
|
|
+if_entry: T_IF expr nl
|
|
+{
|
|
+ printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno());
|
|
+ menu_add_entry(NULL);
|
|
+ menu_add_dep($2);
|
|
+ $$ = menu_add_menu();
|
|
+};
|
|
+
|
|
+if_end: end
|
|
+{
|
|
+ if (zconf_endtoken($1, T_IF, T_ENDIF)) {
|
|
+ menu_end_menu();
|
|
+ printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno());
|
|
+ }
|
|
+};
|
|
+
|
|
+if_stmt: if_entry if_block if_end
|
|
+;
|
|
+
|
|
+if_block:
|
|
+ /* empty */
|
|
+ | if_block common_stmt
|
|
+ | if_block menu_stmt
|
|
+ | if_block choice_stmt
|
|
+;
|
|
+
|
|
+/* mainmenu entry */
|
|
+
|
|
+mainmenu_stmt: T_MAINMENU prompt nl
|
|
+{
|
|
+ menu_add_prompt(P_MENU, $2, NULL);
|
|
+};
|
|
+
|
|
+/* menu entry */
|
|
+
|
|
+menu: T_MENU prompt T_EOL
|
|
+{
|
|
+ menu_add_entry(NULL);
|
|
+ menu_add_prompt(P_MENU, $2, NULL);
|
|
+ printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno());
|
|
+};
|
|
+
|
|
+menu_entry: menu visibility_list depends_list
|
|
+{
|
|
+ $$ = menu_add_menu();
|
|
+};
|
|
+
|
|
+menu_end: end
|
|
+{
|
|
+ if (zconf_endtoken($1, T_MENU, T_ENDMENU)) {
|
|
+ menu_end_menu();
|
|
+ printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno());
|
|
+ }
|
|
+};
|
|
+
|
|
+menu_stmt: menu_entry menu_block menu_end
|
|
+;
|
|
+
|
|
+menu_block:
|
|
+ /* empty */
|
|
+ | menu_block common_stmt
|
|
+ | menu_block menu_stmt
|
|
+ | menu_block choice_stmt
|
|
+;
|
|
+
|
|
+source_stmt: T_SOURCE prompt T_EOL
|
|
+{
|
|
+ printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), $2);
|
|
+ zconf_nextfile($2);
|
|
+};
|
|
+
|
|
+/* comment entry */
|
|
+
|
|
+comment: T_COMMENT prompt T_EOL
|
|
+{
|
|
+ menu_add_entry(NULL);
|
|
+ menu_add_prompt(P_COMMENT, $2, NULL);
|
|
+ printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno());
|
|
+};
|
|
+
|
|
+comment_stmt: comment depends_list
|
|
+{
|
|
+ menu_end_entry();
|
|
+};
|
|
+
|
|
+/* help option */
|
|
+
|
|
+help_start: T_HELP T_EOL
|
|
+{
|
|
+ printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno());
|
|
+ zconf_starthelp();
|
|
+};
|
|
+
|
|
+help: help_start T_HELPTEXT
|
|
+{
|
|
+ current_entry->help = $2;
|
|
+};
|
|
+
|
|
+/* depends option */
|
|
+
|
|
+depends_list:
|
|
+ /* empty */
|
|
+ | depends_list depends
|
|
+ | depends_list T_EOL
|
|
+ | depends_list option_error
|
|
+;
|
|
+
|
|
+depends: T_DEPENDS T_ON expr T_EOL
|
|
+{
|
|
+ menu_add_dep($3);
|
|
+ printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno());
|
|
+};
|
|
+
|
|
+/* visibility option */
|
|
+
|
|
+visibility_list:
|
|
+ /* empty */
|
|
+ | visibility_list visible
|
|
+ | visibility_list T_EOL
|
|
+;
|
|
+
|
|
+visible: T_VISIBLE if_expr
|
|
+{
|
|
+ menu_add_visibility($2);
|
|
+};
|
|
+
|
|
+/* prompt statement */
|
|
+
|
|
+prompt_stmt_opt:
|
|
+ /* empty */
|
|
+ | prompt if_expr
|
|
+{
|
|
+ menu_add_prompt(P_PROMPT, $1, $2);
|
|
+};
|
|
+
|
|
+prompt: T_WORD
|
|
+ | T_WORD_QUOTE
|
|
+;
|
|
+
|
|
+end: T_ENDMENU T_EOL { $$ = $1; }
|
|
+ | T_ENDCHOICE T_EOL { $$ = $1; }
|
|
+ | T_ENDIF T_EOL { $$ = $1; }
|
|
+;
|
|
+
|
|
+nl:
|
|
+ T_EOL
|
|
+ | nl T_EOL
|
|
+;
|
|
+
|
|
+if_expr: /* empty */ { $$ = NULL; }
|
|
+ | T_IF expr { $$ = $2; }
|
|
+;
|
|
+
|
|
+expr: symbol { $$ = expr_alloc_symbol($1); }
|
|
+ | symbol T_EQUAL symbol { $$ = expr_alloc_comp(E_EQUAL, $1, $3); }
|
|
+ | symbol T_UNEQUAL symbol { $$ = expr_alloc_comp(E_UNEQUAL, $1, $3); }
|
|
+ | T_OPEN_PAREN expr T_CLOSE_PAREN { $$ = $2; }
|
|
+ | T_NOT expr { $$ = expr_alloc_one(E_NOT, $2); }
|
|
+ | expr T_OR expr { $$ = expr_alloc_two(E_OR, $1, $3); }
|
|
+ | expr T_AND expr { $$ = expr_alloc_two(E_AND, $1, $3); }
|
|
+;
|
|
+
|
|
+symbol: T_WORD { $$ = sym_lookup($1, 0); free($1); }
|
|
+ | T_WORD_QUOTE { $$ = sym_lookup($1, SYMBOL_CONST); free($1); }
|
|
+;
|
|
+
|
|
+word_opt: /* empty */ { $$ = NULL; }
|
|
+ | T_WORD
|
|
+
|
|
+%%
|
|
+
|
|
+void conf_parse(const char *name)
|
|
+{
|
|
+ struct symbol *sym;
|
|
+ int i;
|
|
+
|
|
+ zconf_initscan(name);
|
|
+
|
|
+ sym_init();
|
|
+ _menu_init();
|
|
+ rootmenu.prompt = menu_add_prompt(P_MENU, "Linux Kernel Configuration", NULL);
|
|
+
|
|
+ if (getenv("ZCONF_DEBUG"))
|
|
+ zconfdebug = 1;
|
|
+ zconfparse();
|
|
+ if (zconfnerrs)
|
|
+ exit(1);
|
|
+ if (!modules_sym)
|
|
+ modules_sym = sym_find( "n" );
|
|
+
|
|
+ rootmenu.prompt->text = _(rootmenu.prompt->text);
|
|
+ rootmenu.prompt->text = sym_expand_string_value(rootmenu.prompt->text);
|
|
+
|
|
+ menu_finalize(&rootmenu);
|
|
+ for_all_symbols(i, sym) {
|
|
+ if (sym_check_deps(sym))
|
|
+ zconfnerrs++;
|
|
+ }
|
|
+ if (zconfnerrs)
|
|
+ exit(1);
|
|
+ sym_set_change_count(1);
|
|
+}
|
|
+
|
|
+static const char *zconf_tokenname(int token)
|
|
+{
|
|
+ switch (token) {
|
|
+ case T_MENU: return "menu";
|
|
+ case T_ENDMENU: return "endmenu";
|
|
+ case T_CHOICE: return "choice";
|
|
+ case T_ENDCHOICE: return "endchoice";
|
|
+ case T_IF: return "if";
|
|
+ case T_ENDIF: return "endif";
|
|
+ case T_DEPENDS: return "depends";
|
|
+ case T_VISIBLE: return "visible";
|
|
+ }
|
|
+ return "<token>";
|
|
+}
|
|
+
|
|
+static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken)
|
|
+{
|
|
+ if (id->token != endtoken) {
|
|
+ zconf_error("unexpected '%s' within %s block",
|
|
+ kconf_id_strings + id->name, zconf_tokenname(starttoken));
|
|
+ zconfnerrs++;
|
|
+ return false;
|
|
+ }
|
|
+ if (current_menu->file != current_file) {
|
|
+ zconf_error("'%s' in different file than '%s'",
|
|
+ kconf_id_strings + id->name, zconf_tokenname(starttoken));
|
|
+ fprintf(stderr, "%s:%d: location of the '%s'\n",
|
|
+ current_menu->file->name, current_menu->lineno,
|
|
+ zconf_tokenname(starttoken));
|
|
+ zconfnerrs++;
|
|
+ return false;
|
|
+ }
|
|
+ return true;
|
|
+}
|
|
+
|
|
+static void zconfprint(const char *err, ...)
|
|
+{
|
|
+ va_list ap;
|
|
+
|
|
+ fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno());
|
|
+ va_start(ap, err);
|
|
+ vfprintf(stderr, err, ap);
|
|
+ va_end(ap);
|
|
+ fprintf(stderr, "\n");
|
|
+}
|
|
+
|
|
+static void zconf_error(const char *err, ...)
|
|
+{
|
|
+ va_list ap;
|
|
+
|
|
+ zconfnerrs++;
|
|
+ fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno());
|
|
+ va_start(ap, err);
|
|
+ vfprintf(stderr, err, ap);
|
|
+ va_end(ap);
|
|
+ fprintf(stderr, "\n");
|
|
+}
|
|
+
|
|
+static void zconferror(const char *err)
|
|
+{
|
|
+ fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err);
|
|
+}
|
|
+
|
|
+static void print_quoted_string(FILE *out, const char *str)
|
|
+{
|
|
+ const char *p;
|
|
+ int len;
|
|
+
|
|
+ putc('"', out);
|
|
+ while ((p = strchr(str, '"'))) {
|
|
+ len = p - str;
|
|
+ if (len)
|
|
+ fprintf(out, "%.*s", len, str);
|
|
+ fputs("\\\"", out);
|
|
+ str = p + 1;
|
|
+ }
|
|
+ fputs(str, out);
|
|
+ putc('"', out);
|
|
+}
|
|
+
|
|
+static void print_symbol(FILE *out, struct menu *menu)
|
|
+{
|
|
+ struct symbol *sym = menu->sym;
|
|
+ struct property *prop;
|
|
+
|
|
+ if (sym_is_choice(sym))
|
|
+ fprintf(out, "\nchoice\n");
|
|
+ else
|
|
+ fprintf(out, "\nconfig %s\n", sym->name);
|
|
+ switch (sym->type) {
|
|
+ case S_BOOLEAN:
|
|
+ fputs(" boolean\n", out);
|
|
+ break;
|
|
+ case S_TRISTATE:
|
|
+ fputs(" tristate\n", out);
|
|
+ break;
|
|
+ case S_STRING:
|
|
+ fputs(" string\n", out);
|
|
+ break;
|
|
+ case S_INT:
|
|
+ fputs(" integer\n", out);
|
|
+ break;
|
|
+ case S_HEX:
|
|
+ fputs(" hex\n", out);
|
|
+ break;
|
|
+ default:
|
|
+ fputs(" ???\n", out);
|
|
+ break;
|
|
+ }
|
|
+ for (prop = sym->prop; prop; prop = prop->next) {
|
|
+ if (prop->menu != menu)
|
|
+ continue;
|
|
+ switch (prop->type) {
|
|
+ case P_PROMPT:
|
|
+ fputs(" prompt ", out);
|
|
+ print_quoted_string(out, prop->text);
|
|
+ if (!expr_is_yes(prop->visible.expr)) {
|
|
+ fputs(" if ", out);
|
|
+ expr_fprint(prop->visible.expr, out);
|
|
+ }
|
|
+ fputc('\n', out);
|
|
+ break;
|
|
+ case P_DEFAULT:
|
|
+ fputs( " default ", out);
|
|
+ expr_fprint(prop->expr, out);
|
|
+ if (!expr_is_yes(prop->visible.expr)) {
|
|
+ fputs(" if ", out);
|
|
+ expr_fprint(prop->visible.expr, out);
|
|
+ }
|
|
+ fputc('\n', out);
|
|
+ break;
|
|
+ case P_CHOICE:
|
|
+ fputs(" #choice value\n", out);
|
|
+ break;
|
|
+ case P_SELECT:
|
|
+ fputs( " select ", out);
|
|
+ expr_fprint(prop->expr, out);
|
|
+ fputc('\n', out);
|
|
+ break;
|
|
+ case P_RANGE:
|
|
+ fputs( " range ", out);
|
|
+ expr_fprint(prop->expr, out);
|
|
+ fputc('\n', out);
|
|
+ break;
|
|
+ case P_MENU:
|
|
+ fputs( " menu ", out);
|
|
+ print_quoted_string(out, prop->text);
|
|
+ fputc('\n', out);
|
|
+ break;
|
|
+ default:
|
|
+ fprintf(out, " unknown prop %d!\n", prop->type);
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ if (menu->help) {
|
|
+ int len = strlen(menu->help);
|
|
+ while (menu->help[--len] == '\n')
|
|
+ menu->help[len] = 0;
|
|
+ fprintf(out, " help\n%s\n", menu->help);
|
|
+ }
|
|
+}
|
|
+
|
|
+void zconfdump(FILE *out)
|
|
+{
|
|
+ struct property *prop;
|
|
+ struct symbol *sym;
|
|
+ struct menu *menu;
|
|
+
|
|
+ menu = rootmenu.list;
|
|
+ while (menu) {
|
|
+ if ((sym = menu->sym))
|
|
+ print_symbol(out, menu);
|
|
+ else if ((prop = menu->prompt)) {
|
|
+ switch (prop->type) {
|
|
+ case P_COMMENT:
|
|
+ fputs("\ncomment ", out);
|
|
+ print_quoted_string(out, prop->text);
|
|
+ fputs("\n", out);
|
|
+ break;
|
|
+ case P_MENU:
|
|
+ fputs("\nmenu ", out);
|
|
+ print_quoted_string(out, prop->text);
|
|
+ fputs("\n", out);
|
|
+ break;
|
|
+ default:
|
|
+ ;
|
|
+ }
|
|
+ if (!expr_is_yes(prop->visible.expr)) {
|
|
+ fputs(" depends ", out);
|
|
+ expr_fprint(prop->visible.expr, out);
|
|
+ fputc('\n', out);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (menu->list)
|
|
+ menu = menu->list;
|
|
+ else if (menu->next)
|
|
+ menu = menu->next;
|
|
+ else while ((menu = menu->parent)) {
|
|
+ if (menu->prompt && menu->prompt->type == P_MENU)
|
|
+ fputs("\nendmenu\n", out);
|
|
+ if (menu->next) {
|
|
+ menu = menu->next;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+#include "zconf.lex.c"
|
|
+#include "util.c"
|
|
+#include "confdata.c"
|
|
+#include "expr.c"
|
|
+#include "symbol.c"
|
|
+#include "menu.c"
|
|
--
|
|
2.51.0
|
|
|