summaryrefslogtreecommitdiff
path: root/scripts/kconfig
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/kconfig')
-rw-r--r--scripts/kconfig/Makefile4
-rw-r--r--scripts/kconfig/conf.c7
-rw-r--r--scripts/kconfig/confdata.c27
-rw-r--r--scripts/kconfig/expr.h12
-rwxr-xr-xscripts/kconfig/gconf-cfg.sh11
-rw-r--r--scripts/kconfig/gconf.c1687
-rw-r--r--scripts/kconfig/gconf.ui (renamed from scripts/kconfig/gconf.glade)361
-rw-r--r--scripts/kconfig/lexer.l1
-rw-r--r--scripts/kconfig/lkc.h4
-rw-r--r--scripts/kconfig/lkc_proto.h1
-rw-r--r--scripts/kconfig/lxdialog/inputbox.c6
-rw-r--r--scripts/kconfig/lxdialog/menubox.c2
-rw-r--r--scripts/kconfig/lxdialog/util.c3
-rw-r--r--scripts/kconfig/mconf.c3
-rw-r--r--scripts/kconfig/menu.c99
-rwxr-xr-xscripts/kconfig/merge_config.sh4
-rw-r--r--scripts/kconfig/nconf.c7
-rw-r--r--scripts/kconfig/nconf.gui.c18
-rw-r--r--scripts/kconfig/parser.y87
-rw-r--r--scripts/kconfig/qconf.cc261
-rw-r--r--scripts/kconfig/qconf.h20
-rwxr-xr-xscripts/kconfig/streamline_config.pl18
-rw-r--r--scripts/kconfig/symbol.c55
-rw-r--r--scripts/kconfig/tests/conftest.py17
-rw-r--r--scripts/kconfig/tests/err_transitional/Kconfig52
-rw-r--r--scripts/kconfig/tests/err_transitional/__init__.py14
-rw-r--r--scripts/kconfig/tests/err_transitional/expected_stderr7
-rw-r--r--scripts/kconfig/tests/transitional/Kconfig132
-rw-r--r--scripts/kconfig/tests/transitional/__init__.py25
-rw-r--r--scripts/kconfig/tests/transitional/expected_config15
-rw-r--r--scripts/kconfig/tests/transitional/expected_stdout1
-rw-r--r--scripts/kconfig/tests/transitional/initial_config20
32 files changed, 1585 insertions, 1396 deletions
diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile
index a0a0be38cbdc..fb50bd4f4103 100644
--- a/scripts/kconfig/Makefile
+++ b/scripts/kconfig/Makefile
@@ -105,9 +105,11 @@ configfiles = $(wildcard $(srctree)/kernel/configs/$(1) $(srctree)/arch/$(SRCARC
all-config-fragments = $(call configfiles,*.config)
config-fragments = $(call configfiles,$@)
+cmd_merge_fragments = $(srctree)/scripts/kconfig/merge_config.sh -m $(KCONFIG_CONFIG) $(config-fragments)
+
%.config: $(obj)/conf
$(if $(config-fragments),, $(error $@ fragment does not exists on this architecture))
- $(Q)$(CONFIG_SHELL) $(srctree)/scripts/kconfig/merge_config.sh -m $(KCONFIG_CONFIG) $(config-fragments)
+ $(call cmd,merge_fragments)
$(Q)$(MAKE) -f $(srctree)/Makefile olddefconfig
PHONY += tinyconfig
diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c
index 3d7d454c54da..a7b44cd8ae14 100644
--- a/scripts/kconfig/conf.c
+++ b/scripts/kconfig/conf.c
@@ -594,7 +594,7 @@ static void check_conf(struct menu *menu)
default:
if (!conf_cnt++)
printf("*\n* Restart config...\n*\n");
- rootEntry = menu_get_parent_menu(menu);
+ rootEntry = menu_get_menu_or_parent_menu(menu);
conf(rootEntry);
break;
}
@@ -628,7 +628,7 @@ static const struct option long_opts[] = {
static void conf_usage(const char *progname)
{
- printf("Usage: %s [options] <kconfig-file>\n", progname);
+ printf("Usage: %s [options] kconfig_file\n", progname);
printf("\n");
printf("Generic options:\n");
printf(" -h, --help Print this message and exit.\n");
@@ -653,6 +653,9 @@ static void conf_usage(const char *progname)
printf(" --mod2yesconfig Change answers from mod to yes if possible\n");
printf(" --mod2noconfig Change answers from mod to no if possible\n");
printf(" (If none of the above is given, --oldaskconfig is the default)\n");
+ printf("\n");
+ printf("Arguments:\n");
+ printf(" kconfig_file Top-level Kconfig file.\n");
}
int main(int ac, char **av)
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
index 4286d5e7f95d..9599a0408862 100644
--- a/scripts/kconfig/confdata.c
+++ b/scripts/kconfig/confdata.c
@@ -77,7 +77,7 @@ static bool is_same(const char *file1, const char *file2)
if (map2 == MAP_FAILED)
goto close2;
- if (bcmp(map1, map2, st1.st_size))
+ if (memcmp(map1, map2, st1.st_size))
goto close2;
ret = true;
@@ -360,10 +360,12 @@ int conf_read_simple(const char *name, int def)
*p = '\0';
- in = zconf_fopen(env);
+ name = env;
+
+ in = zconf_fopen(name);
if (in) {
conf_message("using defaults found in %s",
- env);
+ name);
goto load;
}
@@ -383,7 +385,7 @@ load:
def_flags = SYMBOL_DEF << def;
for_all_symbols(sym) {
- sym->flags &= ~(def_flags|SYMBOL_VALID);
+ sym->flags &= ~def_flags;
switch (sym->type) {
case S_INT:
case S_HEX:
@@ -396,7 +398,11 @@ load:
}
}
- expr_invalidate_all();
+ if (def == S_DEF_USER) {
+ for_all_symbols(sym)
+ sym->flags &= ~SYMBOL_VALID;
+ expr_invalidate_all();
+ }
while (getline_stripped(&line, &line_asize, in) != -1) {
struct menu *choice;
@@ -462,6 +468,9 @@ load:
if (conf_set_sym_val(sym, def, def_flags, val))
continue;
+ if (def != S_DEF_USER)
+ continue;
+
/*
* If this is a choice member, give it the highest priority.
* If conflicting CONFIG options are given from an input file,
@@ -965,10 +974,8 @@ static int conf_touch_deps(void)
depfile_path[depfile_prefix_len] = 0;
conf_read_simple(name, S_DEF_AUTO);
- sym_calc_value(modules_sym);
for_all_symbols(sym) {
- sym_calc_value(sym);
if (sym_is_choice(sym))
continue;
if (sym->flags & SYMBOL_WRITE) {
@@ -1082,12 +1089,12 @@ int conf_write_autoconf(int overwrite)
if (ret)
return -1;
- if (conf_touch_deps())
- return 1;
-
for_all_symbols(sym)
sym_calc_value(sym);
+ if (conf_touch_deps())
+ return 1;
+
ret = __conf_write_autoconf(conf_get_autoheader_name(),
print_symbol_for_c,
&comment_style_c);
diff --git a/scripts/kconfig/expr.h b/scripts/kconfig/expr.h
index 21578dcd4292..5f900d18dae0 100644
--- a/scripts/kconfig/expr.h
+++ b/scripts/kconfig/expr.h
@@ -145,6 +145,7 @@ struct symbol {
#define SYMBOL_CONST 0x0001 /* symbol is const */
#define SYMBOL_CHECK 0x0008 /* used during dependency checking */
#define SYMBOL_VALID 0x0080 /* set when symbol.curr is calculated */
+#define SYMBOL_TRANS 0x0100 /* symbol is transitional only (not visible)*/
#define SYMBOL_WRITE 0x0200 /* write symbol to file (KCONFIG_CONFIG) */
#define SYMBOL_WRITTEN 0x0800 /* track info to avoid double-write to .config */
#define SYMBOL_CHECKED 0x2000 /* used during dependency checking */
@@ -205,15 +206,26 @@ struct property {
for (st = sym->prop; st; st = st->next) \
if (st->text)
+enum menu_type {
+ M_CHOICE, // "choice"
+ M_COMMENT, // "comment"
+ M_IF, // "if"
+ M_MENU, // "mainmenu", "menu", "menuconfig"
+ M_NORMAL, // others, i.e., "config"
+};
+
/*
* Represents a node in the menu tree, as seen in e.g. menuconfig (though used
* for all front ends). Each symbol, menu, etc. defined in the Kconfig files
* gets a node. A symbol defined in multiple locations gets one node at each
* location.
*
+ * @type: type of the menu entry
* @choice_members: list of choice members with priority.
*/
struct menu {
+ enum menu_type type;
+
/* The next menu node at the same level */
struct menu *next;
diff --git a/scripts/kconfig/gconf-cfg.sh b/scripts/kconfig/gconf-cfg.sh
index fc954c0538fa..856c692f480c 100755
--- a/scripts/kconfig/gconf-cfg.sh
+++ b/scripts/kconfig/gconf-cfg.sh
@@ -6,7 +6,7 @@ set -eu
cflags=$1
libs=$2
-PKG="gtk+-2.0 gmodule-2.0 libglade-2.0"
+PKG=gtk+-3.0
if [ -z "$(command -v ${HOSTPKG_CONFIG})" ]; then
echo >&2 "*"
@@ -18,18 +18,11 @@ fi
if ! ${HOSTPKG_CONFIG} --exists $PKG; then
echo >&2 "*"
echo >&2 "* Unable to find the GTK+ installation. Please make sure that"
- echo >&2 "* the GTK+ 2.0 development package is correctly installed."
+ echo >&2 "* the GTK 3 development package is correctly installed."
echo >&2 "* You need $PKG"
echo >&2 "*"
exit 1
fi
-if ! ${HOSTPKG_CONFIG} --atleast-version=2.0.0 gtk+-2.0; then
- echo >&2 "*"
- echo >&2 "* GTK+ is present but version >= 2.0.0 is required."
- echo >&2 "*"
- exit 1
-fi
-
${HOSTPKG_CONFIG} --cflags ${PKG} > ${cflags}
${HOSTPKG_CONFIG} --libs ${PKG} > ${libs}
diff --git a/scripts/kconfig/gconf.c b/scripts/kconfig/gconf.c
index c0f46f189060..8b164ccfa008 100644
--- a/scripts/kconfig/gconf.c
+++ b/scripts/kconfig/gconf.c
@@ -7,10 +7,7 @@
#include "lkc.h"
#include "images.h"
-#include <glade/glade.h>
#include <gtk/gtk.h>
-#include <glib.h>
-#include <gdk/gdkkeysyms.h>
#include <stdio.h>
#include <string.h>
@@ -18,7 +15,7 @@
#include <unistd.h>
#include <time.h>
-enum {
+enum view_mode {
SINGLE_VIEW, SPLIT_VIEW, FULL_VIEW
};
@@ -30,29 +27,24 @@ 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;
+static GtkWidget *main_wnd;
+static GtkWidget *tree1_w; // left frame
+static GtkWidget *tree2_w; // right frame
+static GtkWidget *text_w;
+static GtkWidget *hpaned;
+static GtkWidget *vpaned;
+static GtkWidget *back_btn, *save_btn, *single_btn, *split_btn, *full_btn;
+static GtkWidget *save_menu_item;
-GtkTextTag *tag1, *tag2;
-GdkColor color;
+static GtkTextTag *tag1, *tag2;
-GtkTreeStore *tree1, *tree2, *tree;
-GtkTreeModel *model1, *model2;
-static GtkTreeIter *parents[256];
-static gint indent;
+static GtkTreeStore *tree1, *tree2;
+static GdkPixbuf *pix_menu;
-static struct menu *current; // current node for SINGLE view
-static struct menu *browsed; // browsed node for SPLIT view
+static struct menu *browsed; // browsed menu for SINGLE/SPLIT view
+static struct menu *selected; // selected entry
enum {
COL_OPTION, COL_NAME, COL_NO, COL_MOD, COL_YES, COL_VALUE,
@@ -61,28 +53,8 @@ enum {
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 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);
-}
+static void display_tree(GtkTreeStore *store, struct menu *menu);
+static void recreate_tree(void);
static void conf_changed(bool dirty)
{
@@ -90,465 +62,373 @@ static void conf_changed(bool dirty)
gtk_widget_set_sensitive(save_menu_item, dirty);
}
-/* Main Window Initialization */
-static void init_main_window(const gchar *glade_file)
+/* Utility Functions */
+
+static void text_insert_msg(const char *title, const char *msg)
{
- GladeXML *xml;
- GtkWidget *widget;
- GtkTextBuffer *txtbuf;
- GtkStyle *style;
+ GtkTextBuffer *buffer;
+ GtkTextIter start, end;
- xml = glade_xml_new(glade_file, "window1", NULL);
- if (!xml)
- g_error("GUI loading failed !\n");
- glade_xml_signal_autoconnect(xml);
+ 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);
- 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");
+ 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);
+}
- back_btn = glade_xml_get_widget(xml, "button1");
- gtk_widget_set_sensitive(back_btn, FALSE);
+static void text_insert_help(struct menu *menu)
+{
+ struct gstr help = str_new();
- widget = glade_xml_get_widget(xml, "show_name1");
- gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
- show_name);
+ menu_get_ext_help(menu, &help);
+ text_insert_msg(menu_get_prompt(menu), str_get(&help));
+ str_free(&help);
+}
- widget = glade_xml_get_widget(xml, "show_range1");
- gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
- show_range);
+static void _select_menu(GtkTreeView *view, GtkTreeModel *model,
+ GtkTreeIter *parent, struct menu *match)
+{
+ GtkTreeIter iter;
+ gboolean valid;
- widget = glade_xml_get_widget(xml, "show_data1");
- gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
- show_value);
+ valid = gtk_tree_model_iter_children(model, &iter, parent);
+ while (valid) {
+ struct menu *menu;
- save_btn = glade_xml_get_widget(xml, "button3");
- save_menu_item = glade_xml_get_widget(xml, "save1");
- conf_set_changed_callback(conf_changed);
+ gtk_tree_model_get(model, &iter, COL_MENU, &menu, -1);
- style = gtk_widget_get_style(main_wnd);
- widget = glade_xml_get_widget(xml, "toolbar1");
+ if (menu == match) {
+ GtkTreeSelection *selection;
+ GtkTreePath *path;
- 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);
+ /*
+ * Expand parents to reflect the selection, and
+ * scroll down to it.
+ */
+ path = gtk_tree_model_get_path(model, &iter);
+ gtk_tree_view_expand_to_path(view, path);
+ gtk_tree_view_scroll_to_cell(view, path, NULL, TRUE,
+ 0.5, 0.0);
+ gtk_tree_path_free(path);
- 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);
+ selection = gtk_tree_view_get_selection(view);
+ gtk_tree_selection_select_iter(selection, &iter);
- gtk_window_set_title(GTK_WINDOW(main_wnd), rootmenu.prompt->text);
+ text_insert_help(menu);
+ }
+
+ _select_menu(view, model, &iter, match);
- gtk_widget_show(main_wnd);
+ valid = gtk_tree_model_iter_next(model, &iter);
+ }
}
-static void init_tree_model(void)
+static void select_menu(GtkTreeView *view, struct menu *match)
{
- 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);
+ _select_menu(view, gtk_tree_view_get_model(view), NULL, match);
}
-static void init_left_tree(void)
+static void _update_row_visibility(GtkTreeView *view)
{
- 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);
+ GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER(gtk_tree_view_get_model(view));
- sel = gtk_tree_view_get_selection(view);
- gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
- gtk_widget_realize(tree1_w);
+ gtk_tree_model_filter_refilter(filter);
}
-static void renderer_edited(GtkCellRendererText * cell,
- const gchar * path_string,
- const gchar * new_text, gpointer user_data);
+static void update_row_visibility(void)
+{
+ if (view_mode == SPLIT_VIEW)
+ _update_row_visibility(GTK_TREE_VIEW(tree1_w));
+ _update_row_visibility(GTK_TREE_VIEW(tree2_w));
+}
-static void init_right_tree(void)
+static void set_node(GtkTreeStore *tree, GtkTreeIter *node, struct menu *menu)
{
- GtkTreeView *view = GTK_TREE_VIEW(tree2_w);
- GtkCellRenderer *renderer;
- GtkTreeSelection *sel;
- GtkTreeViewColumn *column;
- gint i;
+ struct symbol *sym = menu->sym;
+ tristate val;
+ gchar *option;
+ const gchar *_no = "";
+ const gchar *_mod = "";
+ const gchar *_yes = "";
+ const gchar *value = "";
+ GdkRGBA color;
+ gboolean editable = FALSE;
+ gboolean btnvis = FALSE;
+
+ option = g_strdup_printf("%s %s %s %s",
+ menu->type == M_COMMENT ? "***" : "",
+ menu_get_prompt(menu),
+ menu->type == M_COMMENT ? "***" : "",
+ sym && !sym_has_value(sym) ? "(NEW)" : "");
+
+ gdk_rgba_parse(&color, menu_is_visible(menu) ? "Black" : "DarkGray");
- gtk_tree_view_set_model(view, model2);
- gtk_tree_view_set_headers_visible(view, TRUE);
- gtk_tree_view_set_rules_hint(view, TRUE);
+ if (!sym)
+ goto set;
- column = gtk_tree_view_column_new();
- gtk_tree_view_append_column(view, column);
- gtk_tree_view_column_set_title(column, "Options");
+ sym_calc_value(sym);
- 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);
+ if (menu->type == M_CHOICE) { // parse children to get a final value
+ struct symbol *def_sym = sym_calc_choice(menu);
+ struct menu *def_menu = 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);
+ for (struct menu *child = menu->list; child; child = child->next) {
+ if (menu_is_visible(child) && child->sym == def_sym)
+ def_menu = child;
}
- }
- sel = gtk_tree_view_get_selection(view);
- gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
-}
+ if (def_menu)
+ value = menu_get_prompt(def_menu);
+ goto set;
+ }
-/* Utility Functions */
+ switch (sym_get_type(sym)) {
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ btnvis = TRUE;
-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();
+ val = sym_get_tristate_value(sym);
+ switch (val) {
+ case no:
+ _no = "N";
+ value = "N";
+ break;
+ case mod:
+ _mod = "M";
+ value = "M";
+ break;
+ case yes:
+ _yes = "Y";
+ value = "Y";
+ break;
+ }
- menu_get_ext_help(menu, &help);
+ if (val != no && sym_tristate_within_range(sym, no))
+ _no = "_";
+ if (val != mod && sym_tristate_within_range(sym, mod))
+ _mod = "_";
+ if (val != yes && sym_tristate_within_range(sym, yes))
+ _yes = "_";
+ break;
+ default:
+ value = sym_get_string_value(sym);
+ editable = TRUE;
+ break;
+ }
- 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);
+set:
+ gtk_tree_store_set(tree, node,
+ COL_OPTION, option,
+ COL_NAME, sym ? sym->name : "",
+ COL_NO, _no,
+ COL_MOD, _mod,
+ COL_YES, _yes,
+ COL_VALUE, value,
+ COL_MENU, (gpointer) menu,
+ COL_COLOR, &color,
+ COL_EDIT, editable,
+ COL_PIXBUF, pix_menu,
+ COL_PIXVIS, view_mode == SINGLE_VIEW && menu->type == M_MENU,
+ COL_BTNVIS, btnvis,
+ COL_BTNACT, _yes[0] == 'Y',
+ COL_BTNINC, _mod[0] == 'M',
+ COL_BTNRAD, sym && sym_is_choice_value(sym),
+ -1);
- 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);
+ g_free(option);
}
-
-static void text_insert_msg(const char *title, const char *message)
+static void _update_tree(GtkTreeStore *store, GtkTreeIter *parent)
{
- GtkTextBuffer *buffer;
- GtkTextIter start, end;
- const char *msg = message;
+ GtkTreeModel *model = GTK_TREE_MODEL(store);
+ GtkTreeIter iter;
+ gboolean valid;
- 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);
+ valid = gtk_tree_model_iter_children(model, &iter, parent);
+ while (valid) {
+ struct menu *menu;
- 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);
-}
+ gtk_tree_model_get(model, &iter, COL_MENU, &menu, -1);
+ if (menu)
+ set_node(store, &iter, menu);
-/* Main Windows Callbacks */
+ _update_tree(store, &iter);
-void on_save_activate(GtkMenuItem * menuitem, gpointer user_data);
-gboolean on_window1_delete_event(GtkWidget * widget, GdkEvent * event,
- gpointer user_data)
+ valid = gtk_tree_model_iter_next(model, &iter);
+ }
+}
+
+static void update_tree(GtkTreeStore *store)
{
- GtkWidget *dialog, *label;
- gint result;
+ _update_tree(store, NULL);
+ update_row_visibility();
+}
- if (!conf_get_changed())
- return FALSE;
+static void update_trees(void)
+{
+ if (view_mode == SPLIT_VIEW)
+ update_tree(tree1);
+ update_tree(tree2);
+}
- 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);
+static void set_view_mode(enum view_mode mode)
+{
+ view_mode = mode;
- label = gtk_label_new("\nSave configuration ?\n");
- gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label);
- gtk_widget_show(label);
+ if (mode == SPLIT_VIEW) { // two panes
+ gint w;
- 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;
+ gtk_widget_show(tree1_w);
+ gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, NULL);
+ gtk_paned_set_position(GTK_PANED(hpaned), w / 2);
+ } else {
+ gtk_widget_hide(tree1_w);
+ gtk_paned_set_position(GTK_PANED(hpaned), 0);
}
- return FALSE;
-}
+ gtk_widget_set_sensitive(single_btn, TRUE);
+ gtk_widget_set_sensitive(split_btn, TRUE);
+ gtk_widget_set_sensitive(full_btn, TRUE);
+ switch (mode) {
+ case SINGLE_VIEW:
+ if (selected)
+ browsed = menu_get_parent_menu(selected) ?: &rootmenu;
+ else
+ browsed = &rootmenu;
+ recreate_tree();
+ text_insert_msg("", "");
+ select_menu(GTK_TREE_VIEW(tree2_w), selected);
+ gtk_widget_set_sensitive(single_btn, FALSE);
+ break;
+ case SPLIT_VIEW:
+ browsed = selected;
+ while (browsed && !(browsed->flags & MENU_ROOT))
+ browsed = browsed->parent;
+ gtk_tree_store_clear(tree1);
+ display_tree(tree1, &rootmenu);
+ gtk_tree_view_expand_all(GTK_TREE_VIEW(tree1_w));
+ gtk_tree_store_clear(tree2);
+ if (browsed)
+ display_tree(tree2, browsed);
+ text_insert_msg("", "");
+ select_menu(GTK_TREE_VIEW(tree1_w), browsed);
+ select_menu(GTK_TREE_VIEW(tree2_w), selected);
+ gtk_widget_set_sensitive(split_btn, FALSE);
+ break;
+ case FULL_VIEW:
+ gtk_tree_store_clear(tree2);
+ display_tree(tree2, &rootmenu);
+ text_insert_msg("", "");
+ select_menu(GTK_TREE_VIEW(tree2_w), selected);
+ gtk_widget_set_sensitive(full_btn, FALSE);
+ break;
+ }
-void on_window1_destroy(GtkObject * object, gpointer user_data)
-{
- gtk_main_quit();
+ gtk_widget_set_sensitive(back_btn,
+ mode == SINGLE_VIEW && browsed != &rootmenu);
}
+/* Menu & Toolbar Callbacks */
-void
-on_window1_size_request(GtkWidget * widget,
- GtkRequisition * requisition, gpointer user_data)
+static void on_load1_activate(GtkMenuItem *menuitem, 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);
-}
+ GtkWidget *dialog;
+ GtkFileChooser *chooser;
+ gint res;
+ dialog = gtk_file_chooser_dialog_new("Load file...",
+ GTK_WINDOW(user_data),
+ GTK_FILE_CHOOSER_ACTION_OPEN,
+ "_Cancel", GTK_RESPONSE_CANCEL,
+ "_Open", GTK_RESPONSE_ACCEPT,
+ NULL);
-/* Menu & Toolbar Callbacks */
+ chooser = GTK_FILE_CHOOSER(dialog);
+ gtk_file_chooser_set_filename(chooser, conf_get_configname());
+ res = gtk_dialog_run(GTK_DIALOG(dialog));
+ if (res == GTK_RESPONSE_ACCEPT) {
+ char *filename;
-static void
-load_filename(GtkFileSelection * file_selector, gpointer user_data)
-{
- const gchar *fn;
+ filename = gtk_file_chooser_get_filename(chooser);
- fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION
- (user_data));
+ if (conf_read(filename))
+ text_insert_msg("Error",
+ "Unable to load configuration!");
+ else
+ update_trees();
- if (conf_read(fn))
- text_insert_msg("Error", "Unable to load configuration !");
- else
- display_tree_part();
-}
+ g_free(filename);
+ }
-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);
+ gtk_widget_destroy(GTK_WIDGET(dialog));
}
-
-void on_save_activate(GtkMenuItem * menuitem, gpointer user_data)
+static void on_save_activate(GtkMenuItem *menuitem, gpointer user_data)
{
if (conf_write(NULL))
text_insert_msg("Error", "Unable to save configuration !");
conf_write_autoconf(0);
}
-
-static void
-store_filename(GtkFileSelection * file_selector, gpointer user_data)
+static void on_save_as1_activate(GtkMenuItem *menuitem, gpointer user_data)
{
- const gchar *fn;
+ GtkWidget *dialog;
+ GtkFileChooser *chooser;
+ gint res;
- fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION
- (user_data));
+ dialog = gtk_file_chooser_dialog_new("Save file as...",
+ GTK_WINDOW(user_data),
+ GTK_FILE_CHOOSER_ACTION_SAVE,
+ "_Cancel", GTK_RESPONSE_CANCEL,
+ "_Save", GTK_RESPONSE_ACCEPT,
+ NULL);
- if (conf_write(fn))
- text_insert_msg("Error", "Unable to save configuration !");
+ chooser = GTK_FILE_CHOOSER(dialog);
+ gtk_file_chooser_set_filename(chooser, conf_get_configname());
- gtk_widget_destroy(GTK_WIDGET(user_data));
-}
+ res = gtk_dialog_run(GTK_DIALOG(dialog));
+ if (res == GTK_RESPONSE_ACCEPT) {
+ char *filename;
-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);
-}
+ filename = gtk_file_chooser_get_filename(chooser);
+ if (conf_write(filename))
+ text_insert_msg("Error",
+ "Unable to save configuration !");
-void on_quit1_activate(GtkMenuItem * menuitem, gpointer user_data)
-{
- if (!on_window1_delete_event(NULL, NULL, NULL))
- gtk_widget_destroy(GTK_WIDGET(main_wnd));
-}
+ g_free(filename);
+ }
+ gtk_widget_destroy(dialog);
+}
-void on_show_name1_activate(GtkMenuItem * menuitem, gpointer user_data)
+static void on_show_name1_activate(GtkMenuItem *menuitem, gpointer user_data)
{
GtkTreeViewColumn *col;
- show_name = GTK_CHECK_MENU_ITEM(menuitem)->active;
+ show_name = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem));
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)
+static void on_show_range1_activate(GtkMenuItem *menuitem, gpointer user_data)
{
GtkTreeViewColumn *col;
- show_range = GTK_CHECK_MENU_ITEM(menuitem)->active;
+ show_range = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem));
col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NO);
if (col)
gtk_tree_view_column_set_visible(col, show_range);
@@ -561,46 +441,38 @@ void on_show_range1_activate(GtkMenuItem * menuitem, gpointer user_data)
}
-
-void on_show_data1_activate(GtkMenuItem * menuitem, gpointer user_data)
+static void on_show_data1_activate(GtkMenuItem *menuitem, gpointer user_data)
{
GtkTreeViewColumn *col;
- show_value = GTK_CHECK_MENU_ITEM(menuitem)->active;
+ show_value = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem));
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)
+static 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 */
+ update_row_visibility();
}
-
-void
-on_set_option_mode2_activate(GtkMenuItem *menuitem, gpointer user_data)
+static 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 */
+ update_row_visibility();
}
-
-void
-on_set_option_mode3_activate(GtkMenuItem *menuitem, gpointer user_data)
+static 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 */
+ update_row_visibility();
}
-
-void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data)
+static void on_introduction1_activate(GtkMenuItem *menuitem, gpointer user_data)
{
GtkWidget *dialog;
const gchar *intro_text =
@@ -621,14 +493,11 @@ void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data)
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);
+ gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_destroy(dialog);
}
-
-void on_about1_activate(GtkMenuItem * menuitem, gpointer user_data)
+static void on_about1_activate(GtkMenuItem *menuitem, gpointer user_data)
{
GtkWidget *dialog;
const gchar *about_text =
@@ -638,15 +507,16 @@ void on_about1_activate(GtkMenuItem * menuitem, gpointer user_data)
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);
+ GTK_BUTTONS_CLOSE, "%s\nGTK version: %d.%d.%d",
+ about_text,
+ gtk_get_major_version(),
+ gtk_get_minor_version(),
+ gtk_get_micro_version());
+ gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_destroy(dialog);
}
-
-void on_license1_activate(GtkMenuItem * menuitem, gpointer user_data)
+static void on_license1_activate(GtkMenuItem *menuitem, gpointer user_data)
{
GtkWidget *dialog;
const gchar *license_text =
@@ -658,81 +528,127 @@ void on_license1_activate(GtkMenuItem * menuitem, gpointer user_data)
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);
+ gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_destroy(dialog);
}
-
-void on_back_clicked(GtkButton * button, gpointer user_data)
+/* toolbar handlers */
+static void on_back_clicked(GtkButton *button, gpointer user_data)
{
- enum prop_type ptype;
+ browsed = menu_get_parent_menu(browsed) ?: &rootmenu;
- current = current->parent;
- ptype = current->prompt ? current->prompt->type : P_UNKNOWN;
- if (ptype != P_MENU)
- current = current->parent;
- display_tree_part();
+ recreate_tree();
- if (current == &rootmenu)
+ if (browsed == &rootmenu)
gtk_widget_set_sensitive(back_btn, FALSE);
}
-
-void on_load_clicked(GtkButton * button, gpointer user_data)
+static void on_load_clicked(GtkButton *button, gpointer user_data)
{
on_load1_activate(NULL, user_data);
}
-
-void on_single_clicked(GtkButton * button, gpointer user_data)
+static void on_save_clicked(GtkButton *button, gpointer user_data)
{
- view_mode = SINGLE_VIEW;
- gtk_widget_hide(tree1_w);
- current = &rootmenu;
- display_tree_part();
+ on_save_activate(NULL, user_data);
}
+static void on_single_clicked(GtkButton *button, gpointer user_data)
+{
+ set_view_mode(SINGLE_VIEW);
+}
-void on_split_clicked(GtkButton * button, gpointer user_data)
+static 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();
+ set_view_mode(SPLIT_VIEW);
+}
- /* Disable back btn, like in full mode. */
- gtk_widget_set_sensitive(back_btn, FALSE);
+static void on_full_clicked(GtkButton *button, gpointer user_data)
+{
+ set_view_mode(FULL_VIEW);
}
+static void on_collapse_clicked(GtkButton *button, gpointer user_data)
+{
+ gtk_tree_view_collapse_all(GTK_TREE_VIEW(tree2_w));
+}
-void on_full_clicked(GtkButton * button, gpointer user_data)
+static void on_expand_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);
+ gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w));
}
+/* Main Windows Callbacks */
-void on_collapse_clicked(GtkButton * button, gpointer user_data)
+static void on_window1_destroy(GtkWidget *widget, gpointer user_data)
{
- gtk_tree_view_collapse_all(GTK_TREE_VIEW(tree2_w));
+ gtk_main_quit();
}
+static gboolean on_window1_configure(GtkWidget *self,
+ GdkEventConfigure *event,
+ gpointer user_data)
+{
+ gtk_paned_set_position(GTK_PANED(vpaned), 2 * event->height / 3);
+ return FALSE;
+}
-void on_expand_clicked(GtkButton * button, gpointer user_data)
+static gboolean on_window1_delete_event(GtkWidget *widget, GdkEvent *event,
+ gpointer user_data)
{
- gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w));
+ GtkWidget *dialog, *label, *content_area;
+ gint result;
+ gint ret = FALSE;
+
+ 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),
+ "_OK",
+ GTK_RESPONSE_YES,
+ "_No",
+ GTK_RESPONSE_NO,
+ "_Cancel",
+ GTK_RESPONSE_CANCEL, NULL);
+ gtk_dialog_set_default_response(GTK_DIALOG(dialog),
+ GTK_RESPONSE_CANCEL);
+
+ label = gtk_label_new("\nSave configuration ?\n");
+ content_area = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+ gtk_container_add(GTK_CONTAINER(content_area), label);
+ gtk_widget_show(label);
+
+ result = gtk_dialog_run(GTK_DIALOG(dialog));
+ switch (result) {
+ case GTK_RESPONSE_YES:
+ on_save_activate(NULL, NULL);
+ break;
+ case GTK_RESPONSE_NO:
+ break;
+ case GTK_RESPONSE_CANCEL:
+ case GTK_RESPONSE_DELETE_EVENT:
+ default:
+ ret = TRUE;
+ break;
+ }
+
+ gtk_widget_destroy(dialog);
+
+ if (!ret)
+ g_object_unref(pix_menu);
+
+ return ret;
}
+static void on_quit1_activate(GtkMenuItem *menuitem, gpointer user_data)
+{
+ if (!on_window1_delete_event(NULL, NULL, NULL))
+ gtk_widget_destroy(GTK_WIDGET(main_wnd));
+}
/* CTree Callbacks */
@@ -741,25 +657,28 @@ static void renderer_edited(GtkCellRendererText * cell,
const gchar * path_string,
const gchar * new_text, gpointer user_data)
{
+ GtkTreeView *view = GTK_TREE_VIEW(user_data);
+ GtkTreeModel *model = gtk_tree_view_get_model(view);
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;
+ if (!gtk_tree_model_get_iter(model, &iter, path))
+ goto free;
- gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
+ gtk_tree_model_get(model, &iter, COL_MENU, &menu, -1);
sym = menu->sym;
- gtk_tree_model_get(model2, &iter, COL_VALUE, &old_def, -1);
+ gtk_tree_model_get(model, &iter, COL_VALUE, &old_def, -1);
new_def = new_text;
sym_set_string_value(sym, new_def);
- update_tree(&rootmenu, NULL);
+ update_trees();
+free:
gtk_tree_path_free(path);
}
@@ -787,14 +706,7 @@ static void change_sym_value(struct menu *menu, gint col)
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
+ update_trees();
break;
case S_INT:
case S_HEX:
@@ -810,14 +722,7 @@ static void toggle_sym_value(struct menu *menu)
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
+ update_trees();
}
static gint column2index(GtkTreeViewColumn * column)
@@ -837,43 +742,39 @@ static gint column2index(GtkTreeViewColumn * column)
/* User click: update choice (full) or goes down (single) */
-gboolean
-on_treeview2_button_press_event(GtkWidget * widget,
- GdkEventButton * event, gpointer user_data)
+static gboolean on_treeview2_button_press_event(GtkWidget *widget,
+ GdkEventButton *event,
+ gpointer user_data)
{
GtkTreeView *view = GTK_TREE_VIEW(widget);
+ GtkTreeModel *model = gtk_tree_view_get_model(view);
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
+ gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, NULL, NULL);
if (path == NULL)
return FALSE;
- if (!gtk_tree_model_get_iter(model2, &iter, path))
+ if (!gtk_tree_model_get_iter(model, &iter, path))
return FALSE;
- gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);
+ gtk_tree_model_get(model, &iter, COL_MENU, &menu, -1);
+
+ selected = menu;
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) {
+ if (ptype == P_MENU && view_mode == SINGLE_VIEW && col == COL_OPTION) {
// goes down into menu
- current = menu;
- display_tree_part();
+ browsed = menu;
+ recreate_tree();
gtk_widget_set_sensitive(back_btn, TRUE);
} else if (col == COL_OPTION) {
toggle_sym_value(menu);
@@ -894,35 +795,31 @@ on_treeview2_button_press_event(GtkWidget * widget,
}
/* Key pressed: update choice */
-gboolean
-on_treeview2_key_press_event(GtkWidget * widget,
- GdkEventKey * event, gpointer user_data)
+static gboolean on_treeview2_key_press_event(GtkWidget *widget,
+ GdkEventKey *event,
+ gpointer user_data)
{
GtkTreeView *view = GTK_TREE_VIEW(widget);
+ GtkTreeModel *model = gtk_tree_view_get_model(view);
GtkTreePath *path;
- GtkTreeViewColumn *column;
GtkTreeIter iter;
struct menu *menu;
gint col;
- gtk_tree_view_get_cursor(view, &path, &column);
+ gtk_tree_view_get_cursor(view, &path, NULL);
if (path == NULL)
return FALSE;
- if (event->keyval == GDK_space) {
+ if (event->keyval == GDK_KEY_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);
+ gtk_tree_model_get_iter(model, &iter, path);
+ gtk_tree_model_get(model, &iter, COL_MENU, &menu, -1);
if (!strcasecmp(event->string, "n"))
col = COL_NO;
@@ -939,448 +836,449 @@ on_treeview2_key_press_event(GtkWidget * widget,
/* Row selection changed: update help */
-void
-on_treeview2_cursor_changed(GtkTreeView * treeview, gpointer user_data)
+static void on_treeview2_cursor_changed(GtkTreeView *treeview,
+ gpointer user_data)
{
+ GtkTreeModel *model = gtk_tree_view_get_model(treeview);
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);
+ if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
+ gtk_tree_model_get(model, &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)
+static gboolean on_treeview1_button_press_event(GtkWidget *widget,
+ GdkEventButton *event,
+ gpointer user_data)
{
GtkTreeView *view = GTK_TREE_VIEW(widget);
+ GtkTreeModel *model = gtk_tree_view_get_model(view);
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);
+ gtk_tree_view_get_path_at_pos(view, tx, ty, &path, NULL, NULL, NULL);
if (path == NULL)
return FALSE;
- gtk_tree_model_get_iter(model1, &iter, path);
- gtk_tree_model_get(model1, &iter, COL_MENU, &menu, -1);
+ gtk_tree_model_get_iter(model, &iter, path);
+ gtk_tree_model_get(model, &iter, COL_MENU, &menu, -1);
- if (event->type == GDK_2BUTTON_PRESS) {
+ if (event->type == GDK_2BUTTON_PRESS)
toggle_sym_value(menu);
- current = menu;
- display_tree_part();
- } else {
+
+ selected = menu;
+
+ if (menu->type == M_MENU) {
browsed = menu;
- display_tree_part();
+ recreate_tree();
}
- 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)
+/* Display the whole tree (single/split/full view) */
+static void _display_tree(GtkTreeStore *tree, struct menu *menu,
+ GtkTreeIter *parent)
{
- 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));
-
- ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
-
- row[COL_OPTION] =
- g_strdup_printf("%s %s %s %s",
- ptype == P_COMMENT ? "***" : "",
- menu_get_prompt(menu),
- ptype == P_COMMENT ? "***" : "",
- 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");
-
- 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);
- menu->flags &= ~MENU_CHANGED;
-
- if (sym_is_choice(sym)) { // parse childs for getting final value
- struct menu *child;
- struct symbol *def_sym = sym_calc_choice(menu);
- struct menu *def_menu = NULL;
+ struct menu *child;
+ GtkTreeIter iter;
- for (child = menu->list; child; child = child->next) {
- if (menu_is_visible(child)
- && child->sym == def_sym)
- def_menu = child;
- }
+ for (child = menu->list; child; child = child->next) {
+ /*
+ * REVISIT:
+ * menu_finalize() creates empty "if" entries.
+ * Do not confuse gtk_tree_model_get(), which would otherwise
+ * return "if" menu entry.
+ */
+ if (child->type == M_IF)
+ continue;
- if (def_menu)
- row[COL_VALUE] =
- g_strdup(menu_get_prompt(def_menu));
+ if ((view_mode == SPLIT_VIEW)
+ && !(child->flags & MENU_ROOT) && (tree == tree1))
+ continue;
- row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
- return row;
- }
- if (sym_is_choice_value(sym))
- row[COL_BTNRAD] = GINT_TO_POINTER(TRUE);
+ if ((view_mode == SPLIT_VIEW) && (child->flags & MENU_ROOT)
+ && (tree == tree2))
+ continue;
- stype = sym_get_type(sym);
- switch (stype) {
- case S_BOOLEAN:
- 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;
- }
+ gtk_tree_store_append(tree, &iter, parent);
+ set_node(tree, &iter, child);
- 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;
+ if (view_mode != SINGLE_VIEW || child->type != M_MENU)
+ _display_tree(tree, child, &iter);
}
+}
- return row;
+static void display_tree(GtkTreeStore *store, struct menu *menu)
+{
+ _display_tree(store, menu, NULL);
}
+/* Recreate the tree store starting at 'browsed' node */
+static void recreate_tree(void)
+{
+ gtk_tree_store_clear(tree2);
+ display_tree(tree2, browsed);
+ gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w));
+}
-/* Set the node content with a row of strings */
-static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row)
+static void fixup_rootmenu(struct menu *menu)
{
- GdkColor color;
- gboolean success;
- GdkPixbuf *pix;
+ struct menu *child;
+ static int menu_cnt = 0;
- pix = gdk_pixbuf_new_from_xpm_data((const char **)
- row[COL_PIXBUF]);
+ 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);
+ }
+}
- gdk_color_parse(row[COL_COLOR], &color);
- gdk_colormap_alloc_colors(gdk_colormap_get_system(), &color, 1,
- FALSE, FALSE, &success);
+/* Main Window Initialization */
+static void replace_button_icon(GtkWidget *widget, const char * const xpm[])
+{
+ GdkPixbuf *pixbuf;
+ GtkWidget *image;
- 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);
+ pixbuf = gdk_pixbuf_new_from_xpm_data((const char **)xpm);
+ image = gtk_image_new_from_pixbuf(pixbuf);
+ g_object_unref(pixbuf);
- g_object_unref(pix);
+ gtk_widget_show(image);
+ gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(widget), image);
}
-
-/* Add a node to the tree */
-static void place_node(struct menu *menu, char **row)
+static void init_main_window(const gchar *glade_file)
{
- GtkTreeIter *parent = parents[indent - 1];
- GtkTreeIter *node = parents[indent];
+ GtkBuilder *builder;
+ GtkWidget *widget;
+ GtkTextBuffer *txtbuf;
- gtk_tree_store_append(tree, node, parent);
- set_node(node, menu, row);
-}
+ builder = gtk_builder_new_from_file(glade_file);
+ if (!builder)
+ g_error("GUI loading failed !\n");
+ main_wnd = GTK_WIDGET(gtk_builder_get_object(builder, "window1"));
+ g_signal_connect(main_wnd, "destroy",
+ G_CALLBACK(on_window1_destroy), NULL);
+ g_signal_connect(main_wnd, "configure-event",
+ G_CALLBACK(on_window1_configure), NULL);
+ g_signal_connect(main_wnd, "delete-event",
+ G_CALLBACK(on_window1_delete_event), NULL);
+
+ hpaned = GTK_WIDGET(gtk_builder_get_object(builder, "hpaned1"));
+ vpaned = GTK_WIDGET(gtk_builder_get_object(builder, "vpaned1"));
+ tree1_w = GTK_WIDGET(gtk_builder_get_object(builder, "treeview1"));
+ g_signal_connect(tree1_w, "cursor-changed",
+ G_CALLBACK(on_treeview2_cursor_changed), NULL);
+ g_signal_connect(tree1_w, "button-press-event",
+ G_CALLBACK(on_treeview1_button_press_event), NULL);
+ g_signal_connect(tree1_w, "key-press-event",
+ G_CALLBACK(on_treeview2_key_press_event), NULL);
+
+ tree2_w = GTK_WIDGET(gtk_builder_get_object(builder, "treeview2"));
+ g_signal_connect(tree2_w, "cursor-changed",
+ G_CALLBACK(on_treeview2_cursor_changed), NULL);
+ g_signal_connect(tree2_w, "button-press-event",
+ G_CALLBACK(on_treeview2_button_press_event), NULL);
+ g_signal_connect(tree2_w, "key-press-event",
+ G_CALLBACK(on_treeview2_key_press_event), NULL);
+
+ text_w = GTK_WIDGET(gtk_builder_get_object(builder, "textview3"));
+
+ /* menubar */
+ widget = GTK_WIDGET(gtk_builder_get_object(builder, "load1"));
+ g_signal_connect(widget, "activate",
+ G_CALLBACK(on_load1_activate), NULL);
+
+ save_menu_item = GTK_WIDGET(gtk_builder_get_object(builder, "save1"));
+ g_signal_connect(save_menu_item, "activate",
+ G_CALLBACK(on_save_activate), NULL);
+
+ widget = GTK_WIDGET(gtk_builder_get_object(builder, "save_as1"));
+ g_signal_connect(widget, "activate",
+ G_CALLBACK(on_save_as1_activate), NULL);
+
+ widget = GTK_WIDGET(gtk_builder_get_object(builder, "quit1"));
+ g_signal_connect(widget, "activate",
+ G_CALLBACK(on_quit1_activate), NULL);
+
+ widget = GTK_WIDGET(gtk_builder_get_object(builder, "show_name1"));
+ g_signal_connect(widget, "activate",
+ G_CALLBACK(on_show_name1_activate), NULL);
+ gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
+ show_name);
-/* Find a node in the GTK+ tree */
-static GtkTreeIter found;
+ widget = GTK_WIDGET(gtk_builder_get_object(builder, "show_range1"));
+ g_signal_connect(widget, "activate",
+ G_CALLBACK(on_show_range1_activate), NULL);
+ gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
+ show_range);
-/*
- * Find a menu in the GtkTree starting at parent.
- */
-static GtkTreeIter *gtktree_iter_find_node(GtkTreeIter *parent,
- struct menu *tofind)
-{
- GtkTreeIter iter;
- GtkTreeIter *child = &iter;
- gboolean valid;
- GtkTreeIter *ret;
+ widget = GTK_WIDGET(gtk_builder_get_object(builder, "show_data1"));
+ g_signal_connect(widget, "activate",
+ G_CALLBACK(on_show_data1_activate), NULL);
+ gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
+ show_value);
- valid = gtk_tree_model_iter_children(model2, child, parent);
- while (valid) {
- struct menu *menu;
+ widget = GTK_WIDGET(gtk_builder_get_object(builder, "set_option_mode1"));
+ g_signal_connect(widget, "activate",
+ G_CALLBACK(on_set_option_mode1_activate), NULL);
- gtk_tree_model_get(model2, child, 6, &menu, -1);
+ widget = GTK_WIDGET(gtk_builder_get_object(builder, "set_option_mode2"));
+ g_signal_connect(widget, "activate",
+ G_CALLBACK(on_set_option_mode2_activate), NULL);
- if (menu == tofind) {
- memcpy(&found, child, sizeof(GtkTreeIter));
- return &found;
- }
+ widget = GTK_WIDGET(gtk_builder_get_object(builder, "set_option_mode3"));
+ g_signal_connect(widget, "activate",
+ G_CALLBACK(on_set_option_mode3_activate), NULL);
- ret = gtktree_iter_find_node(child, tofind);
- if (ret)
- return ret;
+ widget = GTK_WIDGET(gtk_builder_get_object(builder, "introduction1"));
+ g_signal_connect(widget, "activate",
+ G_CALLBACK(on_introduction1_activate), NULL);
- valid = gtk_tree_model_iter_next(model2, child);
- }
+ widget = GTK_WIDGET(gtk_builder_get_object(builder, "about1"));
+ g_signal_connect(widget, "activate",
+ G_CALLBACK(on_about1_activate), NULL);
- return NULL;
-}
+ widget = GTK_WIDGET(gtk_builder_get_object(builder, "license1"));
+ g_signal_connect(widget, "activate",
+ G_CALLBACK(on_license1_activate), NULL);
+ /* toolbar */
+ back_btn = GTK_WIDGET(gtk_builder_get_object(builder, "button1"));
+ g_signal_connect(back_btn, "clicked",
+ G_CALLBACK(on_back_clicked), NULL);
+ gtk_widget_set_sensitive(back_btn, FALSE);
-/*
- * 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;
+ widget = GTK_WIDGET(gtk_builder_get_object(builder, "button2"));
+ g_signal_connect(widget, "clicked",
+ G_CALLBACK(on_load_clicked), NULL);
- if (src == &rootmenu)
- indent = 1;
+ save_btn = GTK_WIDGET(gtk_builder_get_object(builder, "button3"));
+ g_signal_connect(save_btn, "clicked",
+ G_CALLBACK(on_save_clicked), NULL);
- valid = gtk_tree_model_iter_children(model2, child2, dst);
- for (child1 = src->list; child1; child1 = child1->next) {
+ single_btn = GTK_WIDGET(gtk_builder_get_object(builder, "button4"));
+ g_signal_connect(single_btn, "clicked",
+ G_CALLBACK(on_single_clicked), NULL);
+ replace_button_icon(single_btn, xpm_single_view);
- sym = child1->sym;
+ split_btn = GTK_WIDGET(gtk_builder_get_object(builder, "button5"));
+ g_signal_connect(split_btn, "clicked",
+ G_CALLBACK(on_split_clicked), NULL);
+ replace_button_icon(split_btn, xpm_split_view);
- reparse:
- menu1 = child1;
- if (valid)
- gtk_tree_model_get(model2, child2, COL_MENU,
- &menu2, -1);
- else
- menu2 = NULL; // force adding of a first child
-
- 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;
- }
+ full_btn = GTK_WIDGET(gtk_builder_get_object(builder, "button6"));
+ g_signal_connect(full_btn, "clicked",
+ G_CALLBACK(on_full_clicked), NULL);
+ replace_button_icon(full_btn, xpm_tree_view);
- 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 && (child1->flags & MENU_CHANGED)) {
- set_node(child2, menu1, fill_row(menu1));
- }
+ widget = GTK_WIDGET(gtk_builder_get_object(builder, "button7"));
+ g_signal_connect(widget, "clicked",
+ G_CALLBACK(on_collapse_clicked), NULL);
- indent++;
- update_tree(child1, child2);
- indent--;
+ widget = GTK_WIDGET(gtk_builder_get_object(builder, "button8"));
+ g_signal_connect(widget, "clicked",
+ G_CALLBACK(on_expand_clicked), NULL);
- valid = gtk_tree_model_iter_next(model2, child2);
- }
-}
+ 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);
-/* Display the whole tree (single/split/full view) */
-static void display_tree(struct menu *menu)
+ gtk_widget_show_all(main_wnd);
+
+ g_object_unref(builder);
+
+ conf_set_changed_callback(conf_changed);
+}
+
+static gboolean visible_func(GtkTreeModel *model, GtkTreeIter *iter,
+ gpointer data)
{
- struct property *prop;
- struct menu *child;
- enum prop_type ptype;
+ struct menu *menu;
- if (menu == &rootmenu) {
- indent = 1;
- current = &rootmenu;
- }
+ gtk_tree_model_get(model, iter, COL_MENU, &menu, -1);
- for (child = menu->list; child; child = child->next) {
- prop = child->prompt;
- ptype = prop ? prop->type : P_UNKNOWN;
+ if (!menu)
+ return FALSE;
- menu->flags &= ~MENU_CHANGED;
+ return menu_is_visible(menu) || opt_mode == OPT_ALL ||
+ (opt_mode == OPT_PROMPT && menu_has_prompt(menu));
+}
- if ((view_mode == SPLIT_VIEW)
- && !(child->flags & MENU_ROOT) && (tree == tree1))
- continue;
+static void init_left_tree(void)
+{
+ GtkTreeView *view = GTK_TREE_VIEW(tree1_w);
+ GtkCellRenderer *renderer;
+ GtkTreeSelection *sel;
+ GtkTreeViewColumn *column;
+ GtkTreeModel *filter;
- if ((view_mode == SPLIT_VIEW) && (child->flags & MENU_ROOT)
- && (tree == tree2))
- continue;
+ 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_RGBA,
+ G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF,
+ G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
+ G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
+ G_TYPE_BOOLEAN);
- 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));
+ filter = gtk_tree_model_filter_new(GTK_TREE_MODEL(tree1), NULL);
- 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))*/
+ gtk_tree_model_filter_set_visible_func(GTK_TREE_MODEL_FILTER(filter),
+ visible_func, NULL, NULL);
+ gtk_tree_view_set_model(view, filter);
- /* 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);
- }
+ column = gtk_tree_view_column_new();
+ gtk_tree_view_append_column(view, column);
+ gtk_tree_view_column_set_title(column, "Options");
- if (((view_mode == SINGLE_VIEW) && (menu->flags & MENU_ROOT))
- || (view_mode == FULL_VIEW)
- || (view_mode == SPLIT_VIEW)) {
- indent++;
- display_tree(child);
- indent--;
- }
- }
-}
+ 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-rgba",
+ COL_COLOR, NULL);
-/* 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);
- else if (view_mode == FULL_VIEW)
- display_tree(&rootmenu);
- gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w));
+ sel = gtk_tree_view_get_selection(view);
+ gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
}
-/* Display the list in the left frame (split view) */
-static void display_list(void)
+static void init_right_tree(void)
{
- if (tree1)
- gtk_tree_store_clear(tree1);
+ GtkTreeView *view = GTK_TREE_VIEW(tree2_w);
+ GtkCellRenderer *renderer;
+ GtkTreeSelection *sel;
+ GtkTreeViewColumn *column;
+ GtkTreeModel *filter;
+ gint i;
- tree = tree1;
- display_tree(&rootmenu);
- gtk_tree_view_expand_all(GTK_TREE_VIEW(tree1_w));
- tree = tree2;
-}
+ 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_RGBA,
+ G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF,
+ G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
+ G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
+ G_TYPE_BOOLEAN);
-static void fixup_rootmenu(struct menu *menu)
-{
- struct menu *child;
- static int menu_cnt = 0;
+ filter = gtk_tree_model_filter_new(GTK_TREE_MODEL(tree2), NULL);
- 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);
+ gtk_tree_model_filter_set_visible_func(GTK_TREE_MODEL_FILTER(filter),
+ visible_func, NULL, NULL);
+ gtk_tree_view_set_model(view, filter);
+
+ 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-rgba",
+ COL_COLOR, NULL);
+
+ renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_insert_column_with_attributes(view, -1,
+ "Name", renderer,
+ "text", COL_NAME,
+ "foreground-rgba",
+ COL_COLOR, NULL);
+ renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_insert_column_with_attributes(view, -1,
+ "N", renderer,
+ "text", COL_NO,
+ "foreground-rgba",
+ COL_COLOR, NULL);
+ renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_insert_column_with_attributes(view, -1,
+ "M", renderer,
+ "text", COL_MOD,
+ "foreground-rgba",
+ COL_COLOR, NULL);
+ renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_insert_column_with_attributes(view, -1,
+ "Y", renderer,
+ "text", COL_YES,
+ "foreground-rgba",
+ 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-rgba",
+ COL_COLOR, NULL);
+ g_signal_connect(G_OBJECT(renderer), "edited",
+ G_CALLBACK(renderer_edited), tree2_w);
+
+ pix_menu = gdk_pixbuf_new_from_xpm_data((const char **)xpm_menu);
+
+ 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);
+}
/* Main */
int main(int ac, char *av[])
@@ -1390,18 +1288,16 @@ int main(int ac, char *av[])
gchar *glade_file;
/* GTK stuffs */
- gtk_set_locale();
gtk_init(&ac, &av);
- glade_init();
/* Determine GUI path */
env = getenv(SRCTREE);
if (env)
- glade_file = g_strconcat(env, "/scripts/kconfig/gconf.glade", NULL);
+ glade_file = g_strconcat(env, "/scripts/kconfig/gconf.ui", NULL);
else if (av[0][0] == '/')
- glade_file = g_strconcat(av[0], ".glade", NULL);
+ glade_file = g_strconcat(av[0], ".ui", NULL);
else
- glade_file = g_strconcat(g_get_current_dir(), "/", av[0], ".glade", NULL);
+ glade_file = g_strconcat(g_get_current_dir(), "/", av[0], ".ui", NULL);
/* Conf stuffs */
if (ac > 1 && av[1][0] == '-') {
@@ -1426,23 +1322,12 @@ int main(int ac, char *av[])
/* Load the interface and connect signals */
init_main_window(glade_file);
- init_tree_model();
init_left_tree();
init_right_tree();
conf_read(NULL);
- switch (view_mode) {
- case SINGLE_VIEW:
- display_tree_part();
- break;
- case SPLIT_VIEW:
- display_list();
- break;
- case FULL_VIEW:
- display_tree(&rootmenu);
- break;
- }
+ set_view_mode(view_mode);
gtk_main();
diff --git a/scripts/kconfig/gconf.glade b/scripts/kconfig/gconf.ui
index aa483cb32755..ab4431255fa7 100644
--- a/scripts/kconfig/gconf.glade
+++ b/scripts/kconfig/gconf.ui
@@ -1,8 +1,8 @@
<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
-<glade-interface>
+<interface>
-<widget class="GtkWindow" id="window1">
+<object 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>
@@ -17,295 +17,196 @@
<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">
+ <object class="GtkBox" id="vbox1">
+ <property name="orientation">vertical</property>
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child>
- <widget class="GtkMenuBar" id="menubar1">
+ <object class="GtkMenuBar" id="menubar1">
<property name="visible">True</property>
<child>
- <widget class="GtkMenuItem" id="file1">
+ <object 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 type="submenu">
+ <object class="GtkMenu" id="file1_menu">
<child>
- <widget class="GtkImageMenuItem" id="load1">
+ <object class="GtkMenuItem" id="load1">
<property name="visible">True</property>
- <property name="tooltip" translatable="yes">Load a config file</property>
+ <property name="tooltip-text" 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>
+ </object>
</child>
<child>
- <widget class="GtkImageMenuItem" id="save1">
+ <object class="GtkMenuItem" id="save1">
<property name="visible">True</property>
- <property name="tooltip" translatable="yes">Save the config in .config</property>
+ <property name="tooltip-text" 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>
+ </object>
</child>
<child>
- <widget class="GtkImageMenuItem" id="save_as1">
+ <object class="GtkMenuItem" id="save_as1">
<property name="visible">True</property>
- <property name="tooltip" translatable="yes">Save the config in a file</property>
+ <property name="tooltip-text" 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>
+ </object>
</child>
<child>
- <widget class="GtkSeparatorMenuItem" id="separator1">
+ <object class="GtkSeparatorMenuItem" id="separator1">
<property name="visible">True</property>
- </widget>
+ </object>
</child>
<child>
- <widget class="GtkImageMenuItem" id="quit1">
+ <object class="GtkMenuItem" 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>
+ </object>
</child>
- </widget>
+ </object>
</child>
- </widget>
+ </object>
</child>
<child>
- <widget class="GtkMenuItem" id="options1">
+ <object 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 type="submenu">
+ <object class="GtkMenu" id="options1_menu">
<child>
- <widget class="GtkCheckMenuItem" id="show_name1">
+ <object class="GtkCheckMenuItem" id="show_name1">
<property name="visible">True</property>
- <property name="tooltip" translatable="yes">Show name</property>
+ <property name="tooltip-text" 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>
+ </object>
</child>
<child>
- <widget class="GtkCheckMenuItem" id="show_range1">
+ <object class="GtkCheckMenuItem" id="show_range1">
<property name="visible">True</property>
- <property name="tooltip" translatable="yes">Show range (Y/M/N)</property>
+ <property name="tooltip-text" 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>
+ </object>
</child>
<child>
- <widget class="GtkCheckMenuItem" id="show_data1">
+ <object class="GtkCheckMenuItem" id="show_data1">
<property name="visible">True</property>
- <property name="tooltip" translatable="yes">Show value of the option</property>
+ <property name="tooltip-text" 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>
+ </object>
</child>
<child>
- <widget class="GtkSeparatorMenuItem" id="separator2">
+ <object class="GtkSeparatorMenuItem" id="separator2">
<property name="visible">True</property>
- </widget>
+ </object>
</child>
<child>
- <widget class="GtkRadioMenuItem" id="set_option_mode1">
+ <object class="GtkRadioMenuItem" id="set_option_mode1">
<property name="visible">True</property>
- <property name="tooltip" translatable="yes">Show normal options</property>
+ <property name="tooltip-text" 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>
+ </object>
</child>
<child>
- <widget class="GtkRadioMenuItem" id="set_option_mode2">
+ <object class="GtkRadioMenuItem" id="set_option_mode2">
<property name="visible">True</property>
- <property name="tooltip" translatable="yes">Show all options</property>
+ <property name="tooltip-text" 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>
+ </object>
</child>
<child>
- <widget class="GtkRadioMenuItem" id="set_option_mode3">
+ <object class="GtkRadioMenuItem" id="set_option_mode3">
<property name="visible">True</property>
- <property name="tooltip" translatable="yes">Show all options with prompts</property>
+ <property name="tooltip-text" 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>
+ </object>
</child>
- </widget>
+ </object>
</child>
- </widget>
+ </object>
</child>
<child>
- <widget class="GtkMenuItem" id="help1">
+ <object 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 type="submenu">
+ <object class="GtkMenu" id="help1_menu">
<child>
- <widget class="GtkImageMenuItem" id="introduction1">
+ <object class="GtkMenuItem" 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>
+ </object>
</child>
<child>
- <widget class="GtkImageMenuItem" id="about1">
+ <object class="GtkMenuItem" 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>
+ </object>
</child>
<child>
- <widget class="GtkImageMenuItem" id="license1">
+ <object class="GtkMenuItem" 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>
+ </object>
</child>
- </widget>
+ </object>
</child>
- </widget>
+ </object>
</child>
- </widget>
+ </object>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
@@ -314,32 +215,23 @@
</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">
+ <object 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">
+ <object class="GtkToolButton" id="button1">
<property name="visible">True</property>
- <property name="tooltip" translatable="yes">Goes up of one level (single view)</property>
+ <property name="tooltip-text" translatable="yes">Goes up 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>
+ </object>
<packing>
<property name="expand">False</property>
<property name="homogeneous">True</property>
@@ -347,18 +239,18 @@
</child>
<child>
- <widget class="GtkToolItem" id="toolitem1">
+ <object 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">
+ <object class="GtkVSeparator" id="vseparator1">
<property name="visible">True</property>
- </widget>
+ </object>
</child>
- </widget>
+ </object>
<packing>
<property name="expand">False</property>
<property name="homogeneous">False</property>
@@ -366,17 +258,16 @@
</child>
<child>
- <widget class="GtkToolButton" id="button2">
+ <object class="GtkToolButton" id="button2">
<property name="visible">True</property>
- <property name="tooltip" translatable="yes">Load a config file</property>
+ <property name="tooltip-text" 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>
+ </object>
<packing>
<property name="expand">False</property>
<property name="homogeneous">True</property>
@@ -384,17 +275,16 @@
</child>
<child>
- <widget class="GtkToolButton" id="button3">
+ <object class="GtkToolButton" id="button3">
<property name="visible">True</property>
- <property name="tooltip" translatable="yes">Save a config file</property>
+ <property name="tooltip-text" 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>
+ </object>
<packing>
<property name="expand">False</property>
<property name="homogeneous">True</property>
@@ -402,18 +292,18 @@
</child>
<child>
- <widget class="GtkToolItem" id="toolitem2">
+ <object 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">
+ <object class="GtkVSeparator" id="vseparator2">
<property name="visible">True</property>
- </widget>
+ </object>
</child>
- </widget>
+ </object>
<packing>
<property name="expand">False</property>
<property name="homogeneous">False</property>
@@ -421,17 +311,16 @@
</child>
<child>
- <widget class="GtkToolButton" id="button4">
+ <object class="GtkToolButton" id="button4">
<property name="visible">True</property>
- <property name="tooltip" translatable="yes">Single view</property>
+ <property name="tooltip-text" 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>
+ </object>
<packing>
<property name="expand">False</property>
<property name="homogeneous">True</property>
@@ -439,17 +328,16 @@
</child>
<child>
- <widget class="GtkToolButton" id="button5">
+ <object class="GtkToolButton" id="button5">
<property name="visible">True</property>
- <property name="tooltip" translatable="yes">Split view</property>
+ <property name="tooltip-text" 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>
+ </object>
<packing>
<property name="expand">False</property>
<property name="homogeneous">True</property>
@@ -457,17 +345,16 @@
</child>
<child>
- <widget class="GtkToolButton" id="button6">
+ <object class="GtkToolButton" id="button6">
<property name="visible">True</property>
- <property name="tooltip" translatable="yes">Full view</property>
+ <property name="tooltip-text" 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>
+ </object>
<packing>
<property name="expand">False</property>
<property name="homogeneous">True</property>
@@ -475,18 +362,18 @@
</child>
<child>
- <widget class="GtkToolItem" id="toolitem3">
+ <object 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">
+ <object class="GtkVSeparator" id="vseparator3">
<property name="visible">True</property>
- </widget>
+ </object>
</child>
- </widget>
+ </object>
<packing>
<property name="expand">False</property>
<property name="homogeneous">False</property>
@@ -494,17 +381,16 @@
</child>
<child>
- <widget class="GtkToolButton" id="button7">
+ <object 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="tooltip-text" 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>
+ </object>
<packing>
<property name="expand">False</property>
<property name="homogeneous">True</property>
@@ -512,25 +398,22 @@
</child>
<child>
- <widget class="GtkToolButton" id="button8">
+ <object 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="tooltip-text" 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>
+ </object>
<packing>
<property name="expand">False</property>
<property name="homogeneous">True</property>
</packing>
</child>
- </widget>
- </child>
- </widget>
+ </object>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
@@ -539,14 +422,13 @@
</child>
<child>
- <widget class="GtkHPaned" id="hpaned1">
+ <object class="GtkPaned" 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">
+ <object 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>
@@ -554,19 +436,16 @@
<property name="window_placement">GTK_CORNER_TOP_LEFT</property>
<child>
- <widget class="GtkTreeView" id="treeview1">
+ <object 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>
+ </object>
</child>
- </widget>
+ </object>
<packing>
<property name="shrink">True</property>
<property name="resize">False</property>
@@ -574,13 +453,13 @@
</child>
<child>
- <widget class="GtkVPaned" id="vpaned1">
+ <object class="GtkPaned" id="vpaned1">
+ <property name="orientation">vertical</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
- <property name="position">0</property>
<child>
- <widget class="GtkScrolledWindow" id="scrolledwindow2">
+ <object 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>
@@ -588,7 +467,7 @@
<property name="window_placement">GTK_CORNER_TOP_LEFT</property>
<child>
- <widget class="GtkTreeView" id="treeview2">
+ <object class="GtkTreeView" id="treeview2">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="has_focus">True</property>
@@ -596,12 +475,9 @@
<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>
+ </object>
</child>
- </widget>
+ </object>
<packing>
<property name="shrink">True</property>
<property name="resize">False</property>
@@ -609,7 +485,7 @@
</child>
<child>
- <widget class="GtkScrolledWindow" id="scrolledwindow3">
+ <object 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>
@@ -617,7 +493,7 @@
<property name="window_placement">GTK_CORNER_TOP_LEFT</property>
<child>
- <widget class="GtkTextView" id="textview3">
+ <object class="GtkTextView" id="textview3">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="editable">False</property>
@@ -632,30 +508,29 @@
<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>
+ </object>
</child>
- </widget>
+ </object>
<packing>
<property name="shrink">True</property>
<property name="resize">True</property>
</packing>
</child>
- </widget>
+ </object>
<packing>
<property name="shrink">True</property>
<property name="resize">True</property>
</packing>
</child>
- </widget>
+ </object>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
- </widget>
+ </object>
</child>
-</widget>
+</object>
-</glade-interface>
+</interface>
diff --git a/scripts/kconfig/lexer.l b/scripts/kconfig/lexer.l
index 9c2cdfc33c6f..6d2c92c6095d 100644
--- a/scripts/kconfig/lexer.l
+++ b/scripts/kconfig/lexer.l
@@ -126,6 +126,7 @@ n [A-Za-z0-9_-]
"select" return T_SELECT;
"source" return T_SOURCE;
"string" return T_STRING;
+"transitional" return T_TRANSITIONAL;
"tristate" return T_TRISTATE;
"visible" return T_VISIBLE;
"||" return T_OR;
diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h
index b8ebc3094a23..56548efc14d7 100644
--- a/scripts/kconfig/lkc.h
+++ b/scripts/kconfig/lkc.h
@@ -81,7 +81,7 @@ void _menu_init(void);
void menu_warn(const struct menu *menu, const char *fmt, ...);
struct menu *menu_add_menu(void);
void menu_end_menu(void);
-void menu_add_entry(struct symbol *sym);
+void menu_add_entry(struct symbol *sym, enum menu_type type);
void menu_add_dep(struct expr *dep);
void menu_add_visibility(struct expr *dep);
struct property *menu_add_prompt(enum prop_type type, const char *prompt,
@@ -98,9 +98,11 @@ bool menu_is_visible(struct menu *menu);
bool menu_has_prompt(const struct menu *menu);
const char *menu_get_prompt(const struct menu *menu);
struct menu *menu_get_parent_menu(struct menu *menu);
+struct menu *menu_get_menu_or_parent_menu(struct menu *menu);
int get_jump_key_char(void);
struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head);
void menu_get_ext_help(struct menu *menu, struct gstr *help);
+void menu_dump(void);
/* symbol.c */
void sym_clear_all_valid(void);
diff --git a/scripts/kconfig/lkc_proto.h b/scripts/kconfig/lkc_proto.h
index 63519cd24bc7..8914b4e8f2a8 100644
--- a/scripts/kconfig/lkc_proto.h
+++ b/scripts/kconfig/lkc_proto.h
@@ -34,6 +34,7 @@ bool sym_string_valid(struct symbol *sym, const char *newval);
bool sym_string_within_range(struct symbol *sym, const char *str);
bool sym_set_string_value(struct symbol *sym, const char *newval);
bool sym_is_changeable(const struct symbol *sym);
+struct menu *sym_get_prompt_menu(const struct symbol *sym);
struct menu *sym_get_choice_menu(const struct symbol *sym);
const char * sym_get_string_value(struct symbol *sym);
diff --git a/scripts/kconfig/lxdialog/inputbox.c b/scripts/kconfig/lxdialog/inputbox.c
index 3c6e24b20f5b..5e4a131724f2 100644
--- a/scripts/kconfig/lxdialog/inputbox.c
+++ b/scripts/kconfig/lxdialog/inputbox.c
@@ -39,8 +39,10 @@ int dialog_inputbox(const char *title, const char *prompt, int height, int width
if (!init)
instr[0] = '\0';
- else
- strcpy(instr, init);
+ else {
+ strncpy(instr, init, sizeof(dialog_input_result) - 1);
+ instr[sizeof(dialog_input_result) - 1] = '\0';
+ }
do_resize:
if (getmaxy(stdscr) <= (height - INPUTBOX_HEIGHT_MIN))
diff --git a/scripts/kconfig/lxdialog/menubox.c b/scripts/kconfig/lxdialog/menubox.c
index 6e6244df0c56..d4c19b7beebb 100644
--- a/scripts/kconfig/lxdialog/menubox.c
+++ b/scripts/kconfig/lxdialog/menubox.c
@@ -264,7 +264,7 @@ do_resize:
if (key < 256 && isalpha(key))
key = tolower(key);
- if (strchr("ynmh", key))
+ if (strchr("ynmh ", key))
i = max_choice;
else {
for (i = choice + 1; i < max_choice; i++) {
diff --git a/scripts/kconfig/lxdialog/util.c b/scripts/kconfig/lxdialog/util.c
index 964139c87fcb..b34000beb294 100644
--- a/scripts/kconfig/lxdialog/util.c
+++ b/scripts/kconfig/lxdialog/util.c
@@ -345,8 +345,7 @@ void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x)
int prompt_len, room, wlen;
char tempstr[MAX_LEN + 1], *word, *sp, *sp2, *newline_separator = 0;
- strcpy(tempstr, prompt);
-
+ snprintf(tempstr, sizeof(tempstr), "%s", prompt);
prompt_len = strlen(tempstr);
if (prompt_len <= width - x * 2) { /* If prompt is short */
diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c
index 84ea9215c0a7..b8b7bba84a65 100644
--- a/scripts/kconfig/mconf.c
+++ b/scripts/kconfig/mconf.c
@@ -12,6 +12,7 @@
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
+#include <locale.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
@@ -931,6 +932,8 @@ int main(int ac, char **av)
signal(SIGINT, sig_handler);
+ setlocale(LC_ALL, "");
+
if (ac > 1 && strcmp(av[1], "-s") == 0) {
silent = 1;
/* Silence conf_read() until the real callback is set up */
diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
index 6587ac86d0d5..0f1a6513987c 100644
--- a/scripts/kconfig/menu.c
+++ b/scripts/kconfig/menu.c
@@ -15,7 +15,7 @@
static const char nohelp_text[] = "There is no help available for this option.";
-struct menu rootmenu;
+struct menu rootmenu = { .type = M_MENU };
static struct menu **last_entry_ptr;
/**
@@ -65,12 +65,13 @@ void _menu_init(void)
last_entry_ptr = &rootmenu.list;
}
-void menu_add_entry(struct symbol *sym)
+void menu_add_entry(struct symbol *sym, enum menu_type type)
{
struct menu *menu;
menu = xmalloc(sizeof(*menu));
memset(menu, 0, sizeof(*menu));
+ menu->type = type;
menu->sym = sym;
menu->parent = current_menu;
menu->filename = cur_filename;
@@ -574,8 +575,28 @@ const char *menu_get_prompt(const struct menu *menu)
return NULL;
}
+/**
+ * menu_get_parent_menu - return the parent menu or NULL
+ * @menu: pointer to the menu
+ * return: the parent menu, or NULL if there is no parent.
+ */
struct menu *menu_get_parent_menu(struct menu *menu)
{
+ for (menu = menu->parent; menu; menu = menu->parent)
+ if (menu->type == M_MENU)
+ return menu;
+
+ return NULL;
+}
+
+/**
+ * menu_get_menu_or_parent_menu - return the parent menu or the menu itself
+ * @menu: pointer to the menu
+ * return: the parent menu. If the given argument is already a menu, return
+ * itself.
+ */
+struct menu *menu_get_menu_or_parent_menu(struct menu *menu)
+{
enum prop_type type;
for (; menu != &rootmenu; menu = menu->parent) {
@@ -767,3 +788,77 @@ void menu_get_ext_help(struct menu *menu, struct gstr *help)
if (sym)
get_symbol_str(help, sym, NULL);
}
+
+/**
+ * menu_dump - dump all menu entries in a tree-like format
+ */
+void menu_dump(void)
+{
+ struct menu *menu = &rootmenu;
+ unsigned long long bits = 0;
+ int indent = 0;
+
+ while (menu) {
+
+ for (int i = indent - 1; i >= 0; i--) {
+ if (bits & (1ULL << i)) {
+ if (i > 0)
+ printf("| ");
+ else
+ printf("|-- ");
+ } else {
+ if (i > 0)
+ printf(" ");
+ else
+ printf("`-- ");
+ }
+ }
+
+ switch (menu->type) {
+ case M_CHOICE:
+ printf("choice \"%s\"\n", menu->prompt->text);
+ break;
+ case M_COMMENT:
+ printf("comment \"%s\"\n", menu->prompt->text);
+ break;
+ case M_IF:
+ printf("if\n");
+ break;
+ case M_MENU:
+ printf("menu \"%s\"", menu->prompt->text);
+ if (!menu->sym) {
+ printf("\n");
+ break;
+ }
+ printf(" + ");
+ /* fallthrough */
+ case M_NORMAL:
+ printf("symbol %s\n", menu->sym->name);
+ break;
+ }
+ if (menu->list) {
+ bits <<= 1;
+ menu = menu->list;
+ if (menu->next)
+ bits |= 1;
+ else
+ bits &= ~1;
+ indent++;
+ continue;
+ }
+
+ while (menu && !menu->next) {
+ menu = menu->parent;
+ bits >>= 1;
+ indent--;
+ }
+
+ if (menu) {
+ menu = menu->next;
+ if (menu->next)
+ bits |= 1;
+ else
+ bits &= ~1;
+ }
+ }
+}
diff --git a/scripts/kconfig/merge_config.sh b/scripts/kconfig/merge_config.sh
index 0b7952471c18..79c09b378be8 100755
--- a/scripts/kconfig/merge_config.sh
+++ b/scripts/kconfig/merge_config.sh
@@ -112,8 +112,8 @@ INITFILE=$1
shift;
if [ ! -r "$INITFILE" ]; then
- echo "The base file '$INITFILE' does not exist. Exit." >&2
- exit 1
+ echo "The base file '$INITFILE' does not exist. Creating one..." >&2
+ touch "$INITFILE"
fi
MERGE_LIST=$*
diff --git a/scripts/kconfig/nconf.c b/scripts/kconfig/nconf.c
index 063b4f7ccbdb..521700ed7152 100644
--- a/scripts/kconfig/nconf.c
+++ b/scripts/kconfig/nconf.c
@@ -7,6 +7,7 @@
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
+#include <locale.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
@@ -467,7 +468,7 @@ static void handle_f9(int *key, struct menu *current_item)
return;
}
-/* return != 0 to indicate the key was handles */
+/* return != 0 to indicate the key was handled */
static int process_special_keys(int *key, struct menu *menu)
{
int i;
@@ -593,6 +594,8 @@ static void item_add_str(const char *fmt, ...)
tmp_str,
sizeof(k_menu_items[index].str));
+ k_menu_items[index].str[sizeof(k_menu_items[index].str) - 1] = '\0';
+
free_item(curses_menu_items[index]);
curses_menu_items[index] = new_item(
k_menu_items[index].str,
@@ -1476,6 +1479,8 @@ int main(int ac, char **av)
int lines, columns;
char *mode;
+ setlocale(LC_ALL, "");
+
if (ac > 1 && strcmp(av[1], "-s") == 0) {
/* Silence conf_read() until the real callback is set up */
conf_set_message_callback(NULL);
diff --git a/scripts/kconfig/nconf.gui.c b/scripts/kconfig/nconf.gui.c
index 72b605efe549..2d097bc7ef1a 100644
--- a/scripts/kconfig/nconf.gui.c
+++ b/scripts/kconfig/nconf.gui.c
@@ -173,12 +173,10 @@ void fill_window(WINDOW *win, const char *text)
/* 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);
+ int len = min(get_line_length(line), x);
+
+ mvwprintw(win, i, 0, "%.*s", len, line);
}
}
@@ -277,6 +275,15 @@ int btn_dialog(WINDOW *main_window, const char *msg, int btn_num, ...)
case KEY_RIGHT:
menu_driver(menu, REQ_RIGHT_ITEM);
break;
+ case 9: /* TAB */
+ if (btn_num > 1) {
+ /* cycle through buttons */
+ if (item_index(current_item(menu)) == btn_num - 1)
+ menu_driver(menu, REQ_FIRST_ITEM);
+ else
+ menu_driver(menu, REQ_NEXT_ITEM);
+ }
+ break;
case 10: /* ENTER */
case 27: /* ESCAPE */
case ' ':
@@ -350,6 +357,7 @@ int dialog_inputbox(WINDOW *main_window,
x = (columns-win_cols)/2;
strncpy(result, init, *result_len);
+ result[*result_len - 1] = '\0';
/* create the windows */
win = newwin(win_lines, win_cols, y, x);
diff --git a/scripts/kconfig/parser.y b/scripts/kconfig/parser.y
index bc43fb67c7c4..49b79dde1725 100644
--- a/scripts/kconfig/parser.y
+++ b/scripts/kconfig/parser.y
@@ -24,7 +24,6 @@
int cdebug = PRINTD;
static void yyerror(const char *err);
-static void zconfprint(const char *err, ...);
static void zconf_error(const char *err, ...);
static bool zconf_endtoken(const char *tokenname,
const char *expected_tokenname);
@@ -76,6 +75,7 @@ struct menu *current_menu, *current_entry, *current_choice;
%token T_SELECT
%token T_SOURCE
%token T_STRING
+%token T_TRANSITIONAL
%token T_TRISTATE
%token T_VISIBLE
%token T_EOL
@@ -140,7 +140,7 @@ stmt_list_in_choice:
config_entry_start: T_CONFIG nonconst_symbol T_EOL
{
- menu_add_entry($2);
+ menu_add_entry($2, M_NORMAL);
printd(DEBUG_PARSE, "%s:%d:config %s\n", cur_filename, cur_lineno, $2->name);
};
@@ -174,7 +174,7 @@ config_stmt: config_entry_start config_option_list
menuconfig_entry_start: T_MENUCONFIG nonconst_symbol T_EOL
{
- menu_add_entry($2);
+ menu_add_entry($2, M_MENU);
printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", cur_filename, cur_lineno, $2->name);
};
@@ -183,7 +183,7 @@ 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");
+ zconf_error("menuconfig statement without prompt");
printd(DEBUG_PARSE, "%s:%d:endconfig\n", cur_filename, cur_lineno);
};
@@ -206,6 +206,12 @@ config_option: T_PROMPT T_WORD_QUOTE if_expr T_EOL
printd(DEBUG_PARSE, "%s:%d:prompt\n", cur_filename, cur_lineno);
};
+config_option: T_TRANSITIONAL T_EOL
+{
+ current_entry->sym->flags |= SYMBOL_TRANS;
+ printd(DEBUG_PARSE, "%s:%d:transitional\n", cur_filename, cur_lineno);
+};
+
config_option: default expr if_expr T_EOL
{
menu_add_expr(P_DEFAULT, $2, $3);
@@ -247,7 +253,7 @@ choice: T_CHOICE T_EOL
{
struct symbol *sym = sym_lookup(NULL, 0);
- menu_add_entry(sym);
+ menu_add_entry(sym, M_CHOICE);
menu_set_type(S_BOOLEAN);
INIT_LIST_HEAD(&current_entry->choice_members);
@@ -293,12 +299,6 @@ choice_option: T_PROMPT T_WORD_QUOTE if_expr T_EOL
printd(DEBUG_PARSE, "%s:%d:prompt\n", cur_filename, cur_lineno);
};
-choice_option: T_BOOL T_WORD_QUOTE if_expr T_EOL
-{
- menu_add_prompt(P_PROMPT, $2, $3);
- printd(DEBUG_PARSE, "%s:%d:bool\n", cur_filename, cur_lineno);
-};
-
choice_option: T_DEFAULT nonconst_symbol if_expr T_EOL
{
menu_add_symbol(P_DEFAULT, $2, $3);
@@ -322,7 +322,7 @@ default:
if_entry: T_IF expr T_EOL
{
printd(DEBUG_PARSE, "%s:%d:if\n", cur_filename, cur_lineno);
- menu_add_entry(NULL);
+ menu_add_entry(NULL, M_IF);
menu_add_dep($2);
$$ = menu_add_menu();
};
@@ -345,7 +345,7 @@ if_stmt_in_choice: if_entry stmt_list_in_choice if_end
menu: T_MENU T_WORD_QUOTE T_EOL
{
- menu_add_entry(NULL);
+ menu_add_entry(NULL, M_MENU);
menu_add_prompt(P_MENU, $2, NULL);
printd(DEBUG_PARSE, "%s:%d:menu\n", cur_filename, cur_lineno);
};
@@ -383,7 +383,7 @@ source_stmt: T_SOURCE T_WORD_QUOTE T_EOL
comment: T_COMMENT T_WORD_QUOTE T_EOL
{
- menu_add_entry(NULL);
+ menu_add_entry(NULL, M_COMMENT);
menu_add_prompt(P_COMMENT, $2, NULL);
printd(DEBUG_PARSE, "%s:%d:comment\n", cur_filename, cur_lineno);
};
@@ -408,14 +408,14 @@ help: help_start T_HELPTEXT
{
if (current_entry->help) {
free(current_entry->help);
- zconfprint("warning: '%s' defined with more than one help text -- only the last one will be used",
- current_entry->sym->name ?: "<choice>");
+ zconf_error("'%s' defined with more than one help text",
+ current_entry->sym->name ?: "<choice>");
}
/* Is the help text empty or all whitespace? */
if ($2[strspn($2, " \f\n\r\t\v")] == '\0')
- zconfprint("warning: '%s' defined with blank help text",
- current_entry->sym->name ?: "<choice>");
+ zconf_error("'%s' defined with blank help text",
+ current_entry->sym->name ?: "<choice>");
current_entry->help = $2;
};
@@ -490,6 +490,43 @@ assign_val:
%%
/**
+ * transitional_check_sanity - check transitional symbols have no other
+ * properties
+ *
+ * @menu: menu of the potentially transitional symbol
+ *
+ * Return: -1 if an error is found, 0 otherwise.
+ */
+static int transitional_check_sanity(const struct menu *menu)
+{
+ struct property *prop;
+
+ if (!menu->sym || !(menu->sym->flags & SYMBOL_TRANS))
+ return 0;
+
+ /* Check for depends and visible conditions. */
+ if ((menu->dep && !expr_is_yes(menu->dep)) ||
+ (menu->visibility && !expr_is_yes(menu->visibility))) {
+ fprintf(stderr, "%s:%d: error: %s",
+ menu->filename, menu->lineno,
+ "transitional symbols can only have help sections\n");
+ return -1;
+ }
+
+ /* Check for any property other than "help". */
+ for (prop = menu->sym->prop; prop; prop = prop->next) {
+ if (prop->type != P_COMMENT) {
+ fprintf(stderr, "%s:%d: error: %s",
+ prop->filename, prop->lineno,
+ "transitional symbols can only have help sections\n");
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/**
* choice_check_sanity - check sanity of a choice member
*
* @menu: menu of the choice member
@@ -565,6 +602,9 @@ void conf_parse(const char *name)
if (menu->sym && sym_check_deps(menu->sym))
yynerrs++;
+ if (transitional_check_sanity(menu))
+ yynerrs++;
+
if (menu->sym && sym_is_choice(menu->sym)) {
menu_for_each_sub_entry(child, menu)
if (child->sym && choice_check_sanity(child))
@@ -598,17 +638,6 @@ static bool zconf_endtoken(const char *tokenname,
return true;
}
-static void zconfprint(const char *err, ...)
-{
- va_list ap;
-
- fprintf(stderr, "%s:%d: ", cur_filename, cur_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;
diff --git a/scripts/kconfig/qconf.cc b/scripts/kconfig/qconf.cc
index e260cab1c2af..b84c9f2485d1 100644
--- a/scripts/kconfig/qconf.cc
+++ b/scripts/kconfig/qconf.cc
@@ -37,6 +37,12 @@ QAction *ConfigMainWindow::saveAction;
ConfigSettings::ConfigSettings()
: QSettings("kernel.org", "qconf")
{
+ beginGroup("/kconfig/qconf");
+}
+
+ConfigSettings::~ConfigSettings()
+{
+ endGroup();
}
/**
@@ -92,7 +98,6 @@ void ConfigItem::updateMenu(void)
{
ConfigList* list;
struct symbol* sym;
- struct property *prop;
QString prompt;
int type;
tristate expr;
@@ -105,12 +110,11 @@ void ConfigItem::updateMenu(void)
}
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) {
+ switch (menu->type) {
+ case M_MENU:
+ if (list->mode == singleMode) {
/* a menuconfig entry is displayed differently
* depending whether it's at the view root or a child.
*/
@@ -123,10 +127,16 @@ void ConfigItem::updateMenu(void)
setIcon(promptColIdx, QIcon());
}
goto set_prompt;
- case P_COMMENT:
+ case M_COMMENT:
setIcon(promptColIdx, QIcon());
prompt = "*** " + prompt + " ***";
goto set_prompt;
+ case M_CHOICE:
+ setIcon(promptColIdx, QIcon());
+ sym = sym_calc_choice(menu);
+ if (sym)
+ setText(dataColIdx, sym->name);
+ goto set_prompt;
default:
;
}
@@ -159,7 +169,7 @@ void ConfigItem::updateMenu(void)
ch = 'M';
break;
default:
- if (sym_is_choice_value(sym) && type == S_BOOLEAN)
+ if (sym_is_choice_value(sym))
setIcon(promptColIdx, choiceNoIcon);
else
setIcon(promptColIdx, symbolNoIcon);
@@ -175,21 +185,24 @@ void ConfigItem::updateMenu(void)
setText(dataColIdx, sym_get_string_value(sym));
break;
}
- if (!sym_has_value(sym) && visible)
+ if (!sym_has_value(sym))
prompt += " (NEW)";
set_prompt:
setText(promptColIdx, prompt);
}
-void ConfigItem::testUpdateMenu(bool v)
+void ConfigItem::testUpdateMenu(void)
{
ConfigItem* i;
- visible = v;
if (!menu)
return;
- sym_calc_value(menu->sym);
+ if (menu->type == M_CHOICE)
+ sym_calc_choice(menu);
+ else
+ sym_calc_value(menu->sym);
+
if (menu->flags & MENU_CHANGED) {
/* the menu entry changed, so update all list items */
menu->flags &= ~MENU_CHANGED;
@@ -307,7 +320,6 @@ ConfigList::ConfigList(QWidget *parent, const char *name)
{
setObjectName(name);
setSortingEnabled(false);
- setRootIsDecorated(true);
setVerticalScrollMode(ScrollPerPixel);
setHorizontalScrollMode(ScrollPerPixel);
@@ -430,27 +442,26 @@ void ConfigList::updateList()
item = (ConfigItem*)(*it);
if (!item->menu)
continue;
- item->testUpdateMenu(menu_is_visible(item->menu));
+ item->testUpdateMenu();
++it;
}
return;
}
- if (rootEntry != &rootmenu && (mode == singleMode ||
- (mode == symbolMode && rootEntry->parent != &rootmenu))) {
+ if (rootEntry != &rootmenu && mode == singleMode) {
item = (ConfigItem *)topLevelItem(0);
if (!item)
- item = new ConfigItem(this, 0, true);
+ item = new ConfigItem(this, 0);
last = item;
}
if ((mode == singleMode || (mode == symbolMode && !(rootEntry->flags & MENU_ROOT))) &&
rootEntry->sym && rootEntry->prompt) {
item = last ? last->nextSibling() : nullptr;
if (!item)
- item = new ConfigItem(this, last, rootEntry, true);
+ item = new ConfigItem(this, last, rootEntry);
else
- item->testUpdateMenu(true);
+ item->testUpdateMenu();
updateMenuList(item, rootEntry);
update();
@@ -481,7 +492,7 @@ void ConfigList::updateListAllForAll()
while (it.hasNext()) {
ConfigList *list = it.next();
- list->updateList();
+ list->updateListAll();
}
}
@@ -572,7 +583,7 @@ void ConfigList::setParentMenu(void)
oldroot = rootEntry;
if (rootEntry == &rootmenu)
return;
- setRootMenu(menu_get_parent_menu(rootEntry->parent));
+ setRootMenu(menu_get_menu_or_parent_menu(rootEntry->parent));
QTreeWidgetItemIterator it(this);
while (*it) {
@@ -599,7 +610,6 @@ void ConfigList::updateMenuList(ConfigItem *parent, struct menu* menu)
struct menu* child;
ConfigItem* item;
ConfigItem* last;
- bool visible;
enum prop_type type;
if (!menu) {
@@ -631,14 +641,13 @@ void ConfigList::updateMenuList(ConfigItem *parent, struct menu* menu)
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);
+ item = new ConfigItem(parent, last, child);
else
- item->testUpdateMenu(visible);
+ item->testUpdateMenu();
if (mode == fullMode || mode == menuMode || type != P_MENU)
updateMenuList(item, child);
@@ -664,7 +673,6 @@ void ConfigList::updateMenuList(struct menu *menu)
struct menu* child;
ConfigItem* item;
ConfigItem* last;
- bool visible;
enum prop_type type;
if (!menu) {
@@ -696,14 +704,13 @@ void ConfigList::updateMenuList(struct menu *menu)
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(this, last, child, visible);
+ item = new ConfigItem(this, last, child);
else
- item->testUpdateMenu(visible);
+ item->testUpdateMenu();
if (mode == fullMode || mode == menuMode || type != P_MENU)
updateMenuList(item, child);
@@ -731,7 +738,7 @@ void ConfigList::keyPressEvent(QKeyEvent* ev)
struct menu *menu;
enum prop_type type;
- if (ev->key() == Qt::Key_Escape && mode != fullMode && mode != listMode) {
+ if (ev->key() == Qt::Key_Escape && mode == singleMode) {
emit parentSelected();
ev->accept();
return;
@@ -781,13 +788,6 @@ void ConfigList::keyPressEvent(QKeyEvent* ev)
ev->accept();
}
-void ConfigList::mousePressEvent(QMouseEvent* e)
-{
- //QPoint p(contentsToViewport(e->pos()));
- //printf("contentsMousePressEvent: %d,%d\n", p.x(), p.y());
- Parent::mousePressEvent(e);
-}
-
void ConfigList::mouseReleaseEvent(QMouseEvent* e)
{
QPoint p = e->pos();
@@ -834,13 +834,6 @@ skip:
Parent::mouseReleaseEvent(e);
}
-void ConfigList::mouseMoveEvent(QMouseEvent* e)
-{
- //QPoint p(contentsToViewport(e->pos()));
- //printf("contentsMouseMoveEvent: %d,%d\n", p.x(), p.y());
- Parent::mouseMoveEvent(e);
-}
-
void ConfigList::mouseDoubleClickEvent(QMouseEvent* e)
{
QPoint p = e->pos();
@@ -1022,7 +1015,7 @@ void ConfigInfoView::menuInfo(void)
if (sym->name) {
stream << " (";
if (showDebug())
- stream << "<a href=\"s" << sym->name << "\">";
+ stream << "<a href=\"" << sym->name << "\">";
stream << print_filter(sym->name);
if (showDebug())
stream << "</a>";
@@ -1031,7 +1024,7 @@ void ConfigInfoView::menuInfo(void)
} else if (sym->name) {
stream << "<big><b>";
if (showDebug())
- stream << "<a href=\"s" << sym->name << "\">";
+ stream << "<a href=\"" << sym->name << "\">";
stream << print_filter(sym->name);
if (showDebug())
stream << "</a>";
@@ -1086,9 +1079,9 @@ QString ConfigInfoView::debug_info(struct symbol *sym)
switch (prop->type) {
case P_PROMPT:
case P_MENU:
- stream << "prompt: <a href=\"m" << sym->name << "\">";
+ stream << "prompt: ";
stream << print_filter(prop->text);
- stream << "</a><br>";
+ stream << "<br>";
break;
case P_DEFAULT:
case P_SELECT:
@@ -1122,28 +1115,19 @@ QString ConfigInfoView::print_filter(const QString &str)
{
QRegularExpression re("[<>&\"\\n]");
QString res = str;
+
+ QHash<QChar, QString> patterns;
+ patterns['<'] = "&lt;";
+ patterns['>'] = "&gt;";
+ patterns['&'] = "&amp;";
+ patterns['"'] = "&quot;";
+ patterns['\n'] = "<br>";
+
for (int i = 0; (i = res.indexOf(re, i)) >= 0;) {
- switch (res[i].toLatin1()) {
- case '<':
- res.replace(i, 1, "&lt;");
- i += 4;
- break;
- case '>':
- res.replace(i, 1, "&gt;");
- i += 4;
- break;
- case '&':
- res.replace(i, 1, "&amp;");
- i += 5;
- break;
- case '"':
- res.replace(i, 1, "&quot;");
- i += 6;
- break;
- case '\n':
- res.replace(i, 1, "<br>");
- i += 4;
- break;
+ const QString n = patterns.value(res[i], QString());
+ if (!n.isEmpty()) {
+ res.replace(i, 1, n);
+ i += n.length();
}
}
return res;
@@ -1154,7 +1138,7 @@ void ConfigInfoView::expr_print_help(void *data, struct symbol *sym, const char
QTextStream *stream = reinterpret_cast<QTextStream *>(data);
if (sym && sym->name && !(sym->flags & SYMBOL_CONST)) {
- *stream << "<a href=\"s" << sym->name << "\">";
+ *stream << "<a href=\"" << sym->name << "\">";
*stream << print_filter(str);
*stream << "</a>";
} else {
@@ -1164,39 +1148,11 @@ void ConfigInfoView::expr_print_help(void *data, struct symbol *sym, const char
void ConfigInfoView::clicked(const QUrl &url)
{
- QByteArray str = url.toEncoded();
- const std::size_t count = str.size();
- char *data = new char[count + 2]; // '$' + '\0'
- struct symbol **result;
- struct menu *m = NULL;
-
- if (count < 1) {
- delete[] data;
- return;
- }
+ struct menu *m;
- memcpy(data, str.constData(), count);
- data[count] = '\0';
-
- /* Seek for exact match */
- data[0] = '^';
- strcat(data, "$");
- result = sym_re_search(data);
- if (!result) {
- delete[] data;
- return;
- }
-
- sym = *result;
-
- /* Seek for the menu which holds the symbol */
- for (struct property *prop = sym->prop; prop; prop = prop->next) {
- if (prop->type != P_PROMPT && prop->type != P_MENU)
- continue;
- m = prop->menu;
- break;
- }
+ sym = sym_find(url.toEncoded().constData());
+ m = sym_get_prompt_menu(sym);
if (!m) {
/* Symbol is not visible as a menu */
symbolInfo();
@@ -1204,9 +1160,6 @@ void ConfigInfoView::clicked(const QUrl &url)
} else {
emit menuSelected(m);
}
-
- free(result);
- delete[] data;
}
void ConfigInfoView::contextMenuEvent(QContextMenuEvent *event)
@@ -1240,8 +1193,7 @@ ConfigSearchWindow::ConfigSearchWindow(ConfigMainWindow *parent)
layout2->addWidget(searchButton);
layout1->addLayout(layout2);
- split = new QSplitter(this);
- split->setOrientation(Qt::Vertical);
+ split = new QSplitter(Qt::Vertical, this);
list = new ConfigList(split, "search");
list->mode = listMode;
info = new ConfigInfoView(split, "search");
@@ -1300,8 +1252,7 @@ void ConfigSearchWindow::search(void)
return;
for (p = result; *p; p++) {
for_all_prompts((*p), prop)
- lastItem = new ConfigItem(list, lastItem, prop->menu,
- menu_is_visible(prop->menu));
+ lastItem = new ConfigItem(list, lastItem, prop->menu);
}
}
@@ -1341,61 +1292,56 @@ ConfigMainWindow::ConfigMainWindow(void)
ConfigItem::menubackIcon = QIcon(QPixmap(xpm_menuback));
QWidget *widget = new QWidget(this);
- QVBoxLayout *layout = new QVBoxLayout(widget);
setCentralWidget(widget);
- split1 = new QSplitter(widget);
- split1->setOrientation(Qt::Horizontal);
- split1->setChildrenCollapsible(false);
-
- menuList = new ConfigList(widget, "menu");
+ QVBoxLayout *layout = new QVBoxLayout(widget);
- split2 = new QSplitter(widget);
+ split2 = new QSplitter(Qt::Vertical, widget);
+ layout->addWidget(split2);
split2->setChildrenCollapsible(false);
- split2->setOrientation(Qt::Vertical);
- // create config tree
- configList = new ConfigList(widget, "config");
+ split1 = new QSplitter(Qt::Horizontal, split2);
+ split1->setChildrenCollapsible(false);
- helpText = new ConfigInfoView(widget, "help");
+ configList = new ConfigList(split1, "config");
- layout->addWidget(split2);
- split2->addWidget(split1);
- split1->addWidget(configList);
- split1->addWidget(menuList);
- split2->addWidget(helpText);
+ menuList = new ConfigList(split1, "menu");
+ helpText = new ConfigInfoView(split2, "help");
setTabOrder(configList, helpText);
+
configList->setFocus();
backAction = new QAction(QPixmap(xpm_back), "Back", this);
+ backAction->setShortcut(QKeySequence::Back);
connect(backAction, &QAction::triggered,
this, &ConfigMainWindow::goBack);
QAction *quitAction = new QAction("&Quit", this);
- quitAction->setShortcut(Qt::CTRL | Qt::Key_Q);
+ quitAction->setShortcut(QKeySequence::Quit);
connect(quitAction, &QAction::triggered,
this, &ConfigMainWindow::close);
- QAction *loadAction = new QAction(QPixmap(xpm_load), "&Load", this);
- loadAction->setShortcut(Qt::CTRL | Qt::Key_L);
+ QAction *loadAction = new QAction(QPixmap(xpm_load), "&Open", this);
+ loadAction->setShortcut(QKeySequence::Open);
connect(loadAction, &QAction::triggered,
this, &ConfigMainWindow::loadConfig);
saveAction = new QAction(QPixmap(xpm_save), "&Save", this);
- saveAction->setShortcut(Qt::CTRL | Qt::Key_S);
+ saveAction->setShortcut(QKeySequence::Save);
connect(saveAction, &QAction::triggered,
this, &ConfigMainWindow::saveConfig);
conf_set_changed_callback(conf_changed);
- configname = xstrdup(conf_get_configname());
+ configname = conf_get_configname();
QAction *saveAsAction = new QAction("Save &As...", this);
+ saveAsAction->setShortcut(QKeySequence::SaveAs);
connect(saveAsAction, &QAction::triggered,
this, &ConfigMainWindow::saveConfigAs);
QAction *searchAction = new QAction("&Find", this);
- searchAction->setShortcut(Qt::CTRL | Qt::Key_F);
+ searchAction->setShortcut(QKeySequence::Find);
connect(searchAction, &QAction::triggered,
this, &ConfigMainWindow::searchConfig);
singleViewAction = new QAction(QPixmap(xpm_single_view), "Single View", this);
@@ -1431,6 +1377,19 @@ ConfigMainWindow::ConfigMainWindow(void)
ConfigList::showPromptAction = new QAction("Show Prompt Options", optGroup);
ConfigList::showPromptAction->setCheckable(true);
+ switch (configList->optMode) {
+ case allOpt:
+ ConfigList::showAllAction->setChecked(true);
+ break;
+ case promptOpt:
+ ConfigList::showPromptAction->setChecked(true);
+ break;
+ case normalOpt:
+ default:
+ ConfigList::showNormalAction->setChecked(true);
+ break;
+ }
+
QAction *showDebugAction = new QAction("Show Debug Info", this);
showDebugAction->setCheckable(true);
connect(showDebugAction, &QAction::toggled,
@@ -1505,6 +1464,9 @@ ConfigMainWindow::ConfigMainWindow(void)
connect(helpText, &ConfigInfoView::menuSelected,
this, &ConfigMainWindow::setMenuLink);
+ connect(configApp, &QApplication::aboutToQuit,
+ this, &ConfigMainWindow::saveSettings);
+
conf_read(NULL);
QString listMode = configSettings->value("/listMode", "symbol").toString();
@@ -1528,28 +1490,22 @@ ConfigMainWindow::ConfigMainWindow(void)
void ConfigMainWindow::loadConfig(void)
{
QString str;
- QByteArray ba;
- const char *name;
- str = QFileDialog::getOpenFileName(this, "", configname);
- if (str.isNull())
+ str = QFileDialog::getOpenFileName(this, QString(), configname);
+ if (str.isEmpty())
return;
- ba = str.toLocal8Bit();
- name = ba.data();
-
- if (conf_read(name))
+ if (conf_read(str.toLocal8Bit().constData()))
QMessageBox::information(this, "qconf", "Unable to load configuration!");
- free(configname);
- configname = xstrdup(name);
+ configname = str;
ConfigList::updateListAllForAll();
}
bool ConfigMainWindow::saveConfig(void)
{
- if (conf_write(configname)) {
+ if (conf_write(configname.toLocal8Bit().constData())) {
QMessageBox::information(this, "qconf", "Unable to save configuration!");
return false;
}
@@ -1561,23 +1517,17 @@ bool ConfigMainWindow::saveConfig(void)
void ConfigMainWindow::saveConfigAs(void)
{
QString str;
- QByteArray ba;
- const char *name;
- str = QFileDialog::getSaveFileName(this, "", configname);
- if (str.isNull())
+ str = QFileDialog::getSaveFileName(this, QString(), configname);
+ if (str.isEmpty())
return;
- ba = str.toLocal8Bit();
- name = ba.data();
-
- if (conf_write(name)) {
+ if (conf_write(str.toLocal8Bit().constData())) {
QMessageBox::information(this, "qconf", "Unable to save configuration!");
}
conf_write_autoconf(0);
- free(configname);
- configname = xstrdup(name);
+ configname = str;
}
void ConfigMainWindow::searchConfig(void)
@@ -1609,7 +1559,7 @@ void ConfigMainWindow::setMenuLink(struct menu *menu)
switch (configList->mode) {
case singleMode:
list = configList;
- parent = menu_get_parent_menu(menu);
+ parent = menu_get_menu_or_parent_menu(menu);
if (!parent)
return;
list->setRootMenu(parent);
@@ -1620,7 +1570,7 @@ void ConfigMainWindow::setMenuLink(struct menu *menu)
configList->clearSelection();
list = configList;
} else {
- parent = menu_get_parent_menu(menu->parent);
+ parent = menu_get_menu_or_parent_menu(menu->parent);
if (!parent)
return;
@@ -1662,9 +1612,6 @@ void ConfigMainWindow::listFocusChanged(void)
void ConfigMainWindow::goBack(void)
{
- if (configList->rootEntry == &rootmenu)
- return;
-
configList->setParentMenu();
}
@@ -1901,17 +1848,13 @@ int main(int ac, char** av)
configApp = new QApplication(ac, av);
configSettings = new ConfigSettings();
- configSettings->beginGroup("/kconfig/qconf");
v = new ConfigMainWindow();
//zconfdump(stdout);
- configApp->connect(configApp, SIGNAL(lastWindowClosed()), SLOT(quit()));
- configApp->connect(configApp, SIGNAL(aboutToQuit()), v, SLOT(saveSettings()));
v->show();
configApp->exec();
- configSettings->endGroup();
delete configSettings;
delete v;
delete configApp;
diff --git a/scripts/kconfig/qconf.h b/scripts/kconfig/qconf.h
index 53373064d90a..ab4e51f12914 100644
--- a/scripts/kconfig/qconf.h
+++ b/scripts/kconfig/qconf.h
@@ -24,6 +24,7 @@ class ConfigMainWindow;
class ConfigSettings : public QSettings {
public:
ConfigSettings();
+ ~ConfigSettings(void);
QList<int> readSizes(const QString& key, bool *ok);
bool writeSizes(const QString& key, const QList<int>& value);
};
@@ -55,9 +56,7 @@ public:
protected:
void keyPressEvent(QKeyEvent *e);
- void mousePressEvent(QMouseEvent *e);
void mouseReleaseEvent(QMouseEvent *e);
- void mouseMoveEvent(QMouseEvent *e);
void mouseDoubleClickEvent(QMouseEvent *e);
void focusInEvent(QFocusEvent *e);
void contextMenuEvent(QContextMenuEvent *e);
@@ -116,25 +115,25 @@ public:
class ConfigItem : public QTreeWidgetItem {
typedef class QTreeWidgetItem Parent;
public:
- ConfigItem(ConfigList *parent, ConfigItem *after, struct menu *m, bool v)
- : Parent(parent, after), nextItem(0), menu(m), visible(v), goParent(false)
+ ConfigItem(ConfigList *parent, ConfigItem *after, struct menu *m)
+ : Parent(parent, after), nextItem(0), menu(m), goParent(false)
{
init();
}
- ConfigItem(ConfigItem *parent, ConfigItem *after, struct menu *m, bool v)
- : Parent(parent, after), nextItem(0), menu(m), visible(v), goParent(false)
+ ConfigItem(ConfigItem *parent, ConfigItem *after, struct menu *m)
+ : Parent(parent, after), nextItem(0), menu(m), goParent(false)
{
init();
}
- ConfigItem(ConfigList *parent, ConfigItem *after, bool v)
- : Parent(parent, after), nextItem(0), menu(0), visible(v), goParent(true)
+ ConfigItem(ConfigList *parent, ConfigItem *after)
+ : Parent(parent, after), nextItem(0), menu(0), goParent(true)
{
init();
}
~ConfigItem(void);
void init(void);
void updateMenu(void);
- void testUpdateMenu(bool v);
+ void testUpdateMenu(void);
ConfigList* listView() const
{
return (ConfigList*)Parent::treeWidget();
@@ -161,7 +160,6 @@ public:
ConfigItem* nextItem;
struct menu *menu;
- bool visible;
bool goParent;
static QIcon symbolYesIcon, symbolModIcon, symbolNoIcon;
@@ -237,7 +235,7 @@ protected:
class ConfigMainWindow : public QMainWindow {
Q_OBJECT
- char *configname;
+ QString configname;
static QAction *saveAction;
static void conf_changed(bool);
public:
diff --git a/scripts/kconfig/streamline_config.pl b/scripts/kconfig/streamline_config.pl
index d51cd7ac15d2..8e23faab5d22 100755
--- a/scripts/kconfig/streamline_config.pl
+++ b/scripts/kconfig/streamline_config.pl
@@ -144,6 +144,7 @@ my %selects;
my %prompts;
my %objects;
my %config2kfile;
+my %defaults;
my $var;
my $iflevel = 0;
my @ifdeps;
@@ -220,8 +221,9 @@ sub read_kconfig {
$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.*)$/) {
+ } elsif ($state ne "NONE" && /^\s*def(_(bool|tristate)|ault)\s+(\S.*)$/) {
my $dep = $3;
+ $defaults{$config} = 1;
if ($dep !~ /^\s*(y|m|n)\s*$/) {
$dep =~ s/.*\sif\s+//;
$depends{$config} .= " " . $dep;
@@ -503,7 +505,7 @@ sub parse_config_selects
# 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";
+ dprint "$conf (non module) selects $config, we are good\n";
# we are good with this
return;
}
@@ -523,8 +525,16 @@ sub parse_config_selects
# 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";
+
+ # Some config options have no prompt, and nothing selects them, but
+ # they stay turned on once the final checks for the configs
+ # are done. These configs have a default option, so turn off the
+ # warnings for configs with default options.
+ if (!defined($defaults{$config})) {
+ print STDERR "WARNING: $config is required, but nothing in the\n";
+ print STDERR " current config selects it.\n";
+ }
+
return;
}
diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c
index a3af93aaaf32..7e81b3676ee9 100644
--- a/scripts/kconfig/symbol.c
+++ b/scripts/kconfig/symbol.c
@@ -71,6 +71,24 @@ const char *sym_type_name(enum symbol_type type)
}
/**
+ * sym_get_prompt_menu - get the menu entry with a prompt
+ *
+ * @sym: a symbol pointer
+ *
+ * Return: the menu entry with a prompt.
+ */
+struct menu *sym_get_prompt_menu(const struct symbol *sym)
+{
+ struct menu *m;
+
+ list_for_each_entry(m, &sym->menus, link)
+ if (m->prompt)
+ return m;
+
+ return NULL;
+}
+
+/**
* sym_get_choice_menu - get the parent choice menu if present
*
* @sym: a symbol pointer
@@ -80,18 +98,12 @@ const char *sym_type_name(enum symbol_type type)
struct menu *sym_get_choice_menu(const struct symbol *sym)
{
struct menu *menu = NULL;
- struct menu *m;
/*
* Choice members must have a prompt. Find a menu entry with a prompt,
* and assume it resides inside a choice block.
*/
- list_for_each_entry(m, &sym->menus, link)
- if (m->prompt) {
- menu = m;
- break;
- }
-
+ menu = sym_get_prompt_menu(sym);
if (!menu)
return NULL;
@@ -183,6 +195,10 @@ static void sym_set_changed(struct symbol *sym)
list_for_each_entry(menu, &sym->menus, link)
menu->flags |= MENU_CHANGED;
+
+ menu = sym_get_choice_menu(sym);
+ if (menu)
+ menu->flags |= MENU_CHANGED;
}
static void sym_set_all_changed(void)
@@ -198,6 +214,11 @@ static void sym_calc_visibility(struct symbol *sym)
struct property *prop;
tristate tri;
+ if (sym->flags & SYMBOL_TRANS) {
+ sym->visible = yes;
+ return;
+ }
+
/* any prompt visible? */
tri = no;
for_all_prompts(sym, prop) {
@@ -376,6 +397,7 @@ static void sym_warn_unmet_dep(const struct symbol *sym)
" Selected by [m]:\n");
fputs(str_get(&gs), stderr);
+ str_free(&gs);
sym_warnings++;
}
@@ -389,7 +411,7 @@ bool sym_dep_errors(void)
void sym_calc_value(struct symbol *sym)
{
struct symbol_value newval, oldval;
- struct property *prop;
+ struct property *prop = NULL;
struct menu *choice_menu;
if (!sym)
@@ -498,6 +520,19 @@ void sym_calc_value(struct symbol *sym)
;
}
+ /*
+ * If the symbol lacks a user value but its value comes from a
+ * single transitional symbol with an existing user value, mark
+ * this symbol as having a user value to avoid prompting.
+ */
+ if (prop && !sym_has_value(sym)) {
+ struct symbol *ds = prop_get_symbol(prop);
+ if (ds && (ds->flags & SYMBOL_TRANS) && sym_has_value(ds)) {
+ sym->def[S_DEF_USER] = newval;
+ sym->flags |= SYMBOL_DEF_USER;
+ }
+ }
+
sym->curr = newval;
sym_validate_range(sym);
@@ -509,7 +544,7 @@ void sym_calc_value(struct symbol *sym)
}
}
- if (sym_is_choice(sym))
+ if (sym_is_choice(sym) || sym->flags & SYMBOL_TRANS)
sym->flags &= ~SYMBOL_WRITE;
}
@@ -866,7 +901,7 @@ const char *sym_get_string_value(struct symbol *sym)
default:
;
}
- return (const char *)sym->curr.val;
+ return sym->curr.val;
}
bool sym_is_changeable(const struct symbol *sym)
diff --git a/scripts/kconfig/tests/conftest.py b/scripts/kconfig/tests/conftest.py
index 2a2a7e2da060..d94b79e012c0 100644
--- a/scripts/kconfig/tests/conftest.py
+++ b/scripts/kconfig/tests/conftest.py
@@ -81,7 +81,22 @@ class Conf:
# For interactive modes such as oldaskconfig, oldconfig,
# send 'Enter' key until the program finishes.
if interactive:
- ps.stdin.write(b'\n')
+ try:
+ ps.stdin.write(b'\n')
+ ps.stdin.flush()
+ except (BrokenPipeError, OSError):
+ # Process has exited, stop sending input
+ break
+
+ # Close stdin gracefully
+ try:
+ ps.stdin.close()
+ except (BrokenPipeError, OSError):
+ # Ignore broken pipe on close
+ pass
+
+ # Wait for process to complete
+ ps.wait()
self.retcode = ps.returncode
self.stdout = ps.stdout.read().decode()
diff --git a/scripts/kconfig/tests/err_transitional/Kconfig b/scripts/kconfig/tests/err_transitional/Kconfig
new file mode 100644
index 000000000000..a75ed3b2fe5e
--- /dev/null
+++ b/scripts/kconfig/tests/err_transitional/Kconfig
@@ -0,0 +1,52 @@
+# SPDX-License-Identifier: GPL-2.0
+# Test that transitional symbols cannot have properties other than help
+
+config BAD_DEFAULT
+ bool
+ transitional
+ default y
+ help
+ This transitional symbol illegally has a default property.
+
+config BAD_PROMPT
+ bool
+ transitional
+ prompt "Bad prompt"
+ help
+ This transitional symbol illegally has a prompt.
+
+config BAD_SELECT
+ bool
+ transitional
+ select OTHER_SYMBOL
+ help
+ This transitional symbol illegally has a select.
+
+config BAD_IMPLY
+ bool
+ transitional
+ imply OTHER_SYMBOL
+ help
+ This transitional symbol illegally has an imply.
+
+config BAD_DEPENDS
+ bool
+ transitional
+ depends on OTHER_SYMBOL
+ help
+ This transitional symbol illegally has a depends.
+
+config BAD_RANGE
+ int
+ transitional
+ range 1 10
+ help
+ This transitional symbol illegally has a range.
+
+config BAD_NO_TYPE
+ transitional
+ help
+ This transitional symbol illegally has no type specified.
+
+config OTHER_SYMBOL
+ bool
diff --git a/scripts/kconfig/tests/err_transitional/__init__.py b/scripts/kconfig/tests/err_transitional/__init__.py
new file mode 100644
index 000000000000..7dffb5b0833f
--- /dev/null
+++ b/scripts/kconfig/tests/err_transitional/__init__.py
@@ -0,0 +1,14 @@
+# SPDX-License-Identifier: GPL-2.0
+"""
+Test that transitional symbols with invalid properties are rejected.
+
+Transitional symbols can only have help sections. Any other properties
+(default, select, depends, etc.) should cause a parser error.
+"""
+
+def test(conf):
+ # This should fail with exit code 1 due to invalid transitional symbol
+ assert conf.olddefconfig() == 1
+
+ # Check that the error message is about transitional symbols
+ assert conf.stderr_contains('expected_stderr')
diff --git a/scripts/kconfig/tests/err_transitional/expected_stderr b/scripts/kconfig/tests/err_transitional/expected_stderr
new file mode 100644
index 000000000000..b52db4f680f4
--- /dev/null
+++ b/scripts/kconfig/tests/err_transitional/expected_stderr
@@ -0,0 +1,7 @@
+Kconfig:46:warning: config symbol defined without type
+Kconfig:7: error: transitional symbols can only have help sections
+Kconfig:14: error: transitional symbols can only have help sections
+Kconfig:21: error: transitional symbols can only have help sections
+Kconfig:28: error: transitional symbols can only have help sections
+Kconfig:32: error: transitional symbols can only have help sections
+Kconfig:42: error: transitional symbols can only have help sections
diff --git a/scripts/kconfig/tests/transitional/Kconfig b/scripts/kconfig/tests/transitional/Kconfig
new file mode 100644
index 000000000000..faa4d396f828
--- /dev/null
+++ b/scripts/kconfig/tests/transitional/Kconfig
@@ -0,0 +1,132 @@
+# SPDX-License-Identifier: GPL-2.0
+# Test transitional symbols for config migration with all Kconfig types
+
+# Enable module support for tristate testing
+config MODULES
+ bool "Enable loadable module support"
+ modules
+ default y
+
+# Basic migration tests for all types
+config NEW_BOOL
+ bool "New bool option"
+ default OLD_BOOL
+
+config OLD_BOOL
+ bool
+ transitional
+
+config NEW_TRISTATE
+ tristate "New tristate option"
+ default OLD_TRISTATE
+
+config OLD_TRISTATE
+ tristate
+ transitional
+
+config NEW_STRING
+ string "New string option"
+ default OLD_STRING
+
+config OLD_STRING
+ string
+ transitional
+
+config NEW_HEX
+ hex "New hex option"
+ default OLD_HEX
+
+config OLD_HEX
+ hex
+ transitional
+
+config NEW_INT
+ int "New int option"
+ default OLD_INT
+
+config OLD_INT
+ int
+ transitional
+
+# Precedence tests for all types
+config NEW_BOOL_PRECEDENCE
+ bool "New bool option with precedence"
+ default OLD_BOOL_PRECEDENCE
+
+config OLD_BOOL_PRECEDENCE
+ bool
+ transitional
+
+config NEW_STRING_PRECEDENCE
+ string "New string option with precedence"
+ default OLD_STRING_PRECEDENCE
+
+config OLD_STRING_PRECEDENCE
+ string
+ transitional
+
+config NEW_TRISTATE_PRECEDENCE
+ tristate "New tristate option with precedence"
+ default OLD_TRISTATE_PRECEDENCE
+
+config OLD_TRISTATE_PRECEDENCE
+ tristate
+ transitional
+
+config NEW_HEX_PRECEDENCE
+ hex "New hex option with precedence"
+ default OLD_HEX_PRECEDENCE
+
+config OLD_HEX_PRECEDENCE
+ hex
+ transitional
+
+config NEW_INT_PRECEDENCE
+ int "New int option with precedence"
+ default OLD_INT_PRECEDENCE
+
+config OLD_INT_PRECEDENCE
+ int
+ transitional
+
+# Test that help sections are allowed for transitional symbols
+config OLD_WITH_HELP
+ bool
+ transitional
+ help
+ This transitional symbol has a help section to validate that help is allowed.
+
+# Test that we can set something to =n via transitional symbol
+config NEW_DISABLED
+ tristate "Check for setting to disabled"
+ default OLD_DISABLED
+
+config OLD_DISABLED
+ tristate
+ transitional
+
+# Test that a potential new value disappears if it lacks a prompt
+config NEW_DISABLED_UNSAVED
+ tristate
+ default OLD_DISABLED
+
+config OLD_DISABLED_UNSAVED
+ tristate
+ transitional
+
+# Test conditional default: transitional value should not prevent prompting
+# when default visibility makes the expression evaluate to 'no'
+config DEPENDENCY_TEST
+ bool "Dependency for testing"
+ default n
+
+config NEW_CONDITIONAL_DEFAULT
+ bool "New option with conditional default"
+ default OLD_CONDITIONAL_DEFAULT if DEPENDENCY_TEST
+
+config OLD_CONDITIONAL_DEFAULT
+ bool
+ transitional
+
+config REGULAR_OPTION
+ bool "Regular option"
diff --git a/scripts/kconfig/tests/transitional/__init__.py b/scripts/kconfig/tests/transitional/__init__.py
new file mode 100644
index 000000000000..b50ba2397548
--- /dev/null
+++ b/scripts/kconfig/tests/transitional/__init__.py
@@ -0,0 +1,25 @@
+# SPDX-License-Identifier: GPL-2.0
+"""
+Test transitional symbol migration functionality for all Kconfig types.
+
+This tests that:
+- OLD_* options in existing .config cause NEW_* options to be set
+- OLD_* options are not written to the new .config file
+- NEW_* options appear in the new .config file with correct values
+- NEW_* options with defaults from transitional symbols are not prompted
+- All Kconfig types work correctly: bool, tristate, string, hex, int
+- User-set NEW values take precedence over conflicting OLD transitional values
+"""
+
+def test(conf):
+ # Run olddefconfig to process the migration with the initial config
+ assert conf.olddefconfig(dot_config='initial_config') == 0
+
+ # Check that the configuration matches expected output
+ assert conf.config_contains('expected_config')
+
+ # Test oldconfig to ensure symbols with transitional defaults are not prompted
+ assert conf.oldconfig(dot_config='initial_config', in_keys='n\n') == 0
+
+ # Except for when conditional default evaluates to 'no'
+ assert conf.stdout_contains('expected_stdout')
diff --git a/scripts/kconfig/tests/transitional/expected_config b/scripts/kconfig/tests/transitional/expected_config
new file mode 100644
index 000000000000..e01f5f070a26
--- /dev/null
+++ b/scripts/kconfig/tests/transitional/expected_config
@@ -0,0 +1,15 @@
+CONFIG_MODULES=y
+CONFIG_NEW_BOOL=y
+CONFIG_NEW_TRISTATE=m
+CONFIG_NEW_STRING="test string"
+CONFIG_NEW_HEX=0x1234
+CONFIG_NEW_INT=42
+# CONFIG_NEW_BOOL_PRECEDENCE is not set
+CONFIG_NEW_STRING_PRECEDENCE="user value"
+CONFIG_NEW_TRISTATE_PRECEDENCE=y
+CONFIG_NEW_HEX_PRECEDENCE=0xABCD
+CONFIG_NEW_INT_PRECEDENCE=100
+# CONFIG_NEW_DISABLED is not set
+# CONFIG_DEPENDENCY_TEST is not set
+# CONFIG_NEW_CONDITIONAL_DEFAULT is not set
+# CONFIG_REGULAR_OPTION is not set
diff --git a/scripts/kconfig/tests/transitional/expected_stdout b/scripts/kconfig/tests/transitional/expected_stdout
new file mode 100644
index 000000000000..6f0b285d6469
--- /dev/null
+++ b/scripts/kconfig/tests/transitional/expected_stdout
@@ -0,0 +1 @@
+New option with conditional default (NEW_CONDITIONAL_DEFAULT) [N/y/?] (NEW) n
diff --git a/scripts/kconfig/tests/transitional/initial_config b/scripts/kconfig/tests/transitional/initial_config
new file mode 100644
index 000000000000..68b7da672426
--- /dev/null
+++ b/scripts/kconfig/tests/transitional/initial_config
@@ -0,0 +1,20 @@
+CONFIG_MODULES=y
+CONFIG_OLD_BOOL=y
+CONFIG_OLD_TRISTATE=m
+CONFIG_OLD_STRING="test string"
+CONFIG_OLD_HEX=0x1234
+CONFIG_OLD_INT=42
+# CONFIG_NEW_BOOL_PRECEDENCE is not set
+CONFIG_OLD_BOOL_PRECEDENCE=y
+CONFIG_NEW_STRING_PRECEDENCE="user value"
+CONFIG_OLD_STRING_PRECEDENCE="old value"
+CONFIG_NEW_TRISTATE_PRECEDENCE=y
+CONFIG_OLD_TRISTATE_PRECEDENCE=m
+CONFIG_NEW_HEX_PRECEDENCE=0xABCD
+CONFIG_OLD_HEX_PRECEDENCE=0x5678
+CONFIG_NEW_INT_PRECEDENCE=100
+CONFIG_OLD_INT_PRECEDENCE=200
+# CONFIG_OLD_DISABLED is not set
+# CONFIG_OLD_DISABLED_UNSAVED is not set
+# CONFIG_DEPENDENCY_TEST is not set
+CONFIG_OLD_CONDITIONAL_DEFAULT=y