kconfig/menuconfig: lxdialog is now built-in

lxdialog was previously called as an external program causing screen
to flicker when used. With this patch lxdialog is now built-in.
It is loosly based om previous work by:  Petr Baudis <pasky@ucw.cz>

Following is a list of changes:
o Moved build of dialog routings to kconfig Makefile
o menubox + checklist uses a new item list to hold all menu items
o in util.c implmented helper function to deal with item list
o menubox now uses parameters to save scroll state (avoids temp file)
o textbox now get text to be displayed as parameter and not a file
o make sure to properly delete subwin's before main windows
o killed unused files: lxdialog.c msgbox.c
o modified return value for ESC to match direct calling
o in a few places the code has been adjusted to 80 char wide
o in textbox a small refactoring was made to make code remotely readable
o in mconf removed all unused stuff (functions/variables)

Following is a list of know short comings:
a) pressing ESC twice will be interpreted as two ESC presses
b) resize does not work. menuconfig needs to be restarted to be adjusted

Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
Cette révision appartient à :
Sam Ravnborg
2006-07-27 22:10:27 +02:00
révisé par Sam Ravnborg
Parent 350b5b7638
révision 2982de6993
12 fichiers modifiés avec 503 ajouts et 1020 suppressions

Voir le fichier

@@ -24,6 +24,7 @@
#define LKC_DIRECT_LINK
#include "lkc.h"
#include "lxdialog/dialog.h"
static char menu_backtitle[128];
static const char mconf_readme[] = N_(
@@ -270,16 +271,12 @@ search_help[] = N_(
" USB$ => find all CONFIG_ symbols ending with USB\n"
"\n");
static char buf[4096], *bufptr = buf;
static char input_buf[4096];
static char filename[PATH_MAX+1] = ".config";
static char *args[1024], **argptr = args;
static int indent;
static struct termios ios_org;
static int rows = 0, cols = 0;
static struct menu *current_menu;
static int child_count;
static int do_resize;
static int single_menu_mode;
static void conf(struct menu *menu);
@@ -290,12 +287,6 @@ static void conf_save(void);
static void show_textbox(const char *title, const char *text, int r, int c);
static void show_helptext(const char *title, const char *text);
static void show_help(struct menu *menu);
static void show_file(const char *filename, const char *title, int r, int c);
static void cprint_init(void);
static int cprint1(const char *fmt, ...);
static void cprint_done(void);
static int cprint(const char *fmt, ...);
static void init_wsize(void)
{
@@ -332,54 +323,6 @@ static void init_wsize(void)
cols -= 5;
}
static void cprint_init(void)
{
bufptr = buf;
argptr = args;
memset(args, 0, sizeof(args));
indent = 0;
child_count = 0;
cprint("./scripts/kconfig/lxdialog/lxdialog");
cprint("--backtitle");
cprint(menu_backtitle);
}
static int cprint1(const char *fmt, ...)
{
va_list ap;
int res;
if (!*argptr)
*argptr = bufptr;
va_start(ap, fmt);
res = vsprintf(bufptr, fmt, ap);
va_end(ap);
bufptr += res;
return res;
}
static void cprint_done(void)
{
*bufptr++ = 0;
argptr++;
}
static int cprint(const char *fmt, ...)
{
va_list ap;
int res;
*argptr++ = bufptr;
va_start(ap, fmt);
res = vsprintf(bufptr, fmt, ap);
va_end(ap);
bufptr += res;
*bufptr++ = 0;
return res;
}
static void get_prompt_str(struct gstr *r, struct property *prop)
{
int i, j;
@@ -452,108 +395,17 @@ static struct gstr get_relations_str(struct symbol **sym_arr)
return res;
}
pid_t pid;
static void winch_handler(int sig)
{
if (!do_resize) {
kill(pid, SIGINT);
do_resize = 1;
}
}
static int exec_conf(void)
{
int pipefd[2], stat, size;
struct sigaction sa;
sigset_t sset, osset;
sigemptyset(&sset);
sigaddset(&sset, SIGINT);
sigprocmask(SIG_BLOCK, &sset, &osset);
signal(SIGINT, SIG_DFL);
sa.sa_handler = winch_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
sigaction(SIGWINCH, &sa, NULL);
*argptr++ = NULL;
pipe(pipefd);
pid = fork();
if (pid == 0) {
sigprocmask(SIG_SETMASK, &osset, NULL);
dup2(pipefd[1], 2);
close(pipefd[0]);
close(pipefd[1]);
execv(args[0], args);
_exit(EXIT_FAILURE);
}
close(pipefd[1]);
bufptr = input_buf;
while (1) {
size = input_buf + sizeof(input_buf) - bufptr;
size = read(pipefd[0], bufptr, size);
if (size <= 0) {
if (size < 0) {
if (errno == EINTR || errno == EAGAIN)
continue;
perror("read");
}
break;
}
bufptr += size;
}
*bufptr++ = 0;
close(pipefd[0]);
waitpid(pid, &stat, 0);
if (do_resize) {
init_wsize();
do_resize = 0;
sigprocmask(SIG_SETMASK, &osset, NULL);
return -1;
}
if (WIFSIGNALED(stat)) {
printf("\finterrupted(%d)\n", WTERMSIG(stat));
exit(1);
}
#if 0
printf("\fexit state: %d\nexit data: '%s'\n", WEXITSTATUS(stat), input_buf);
sleep(1);
#endif
sigpending(&sset);
if (sigismember(&sset, SIGINT)) {
printf("\finterrupted\n");
exit(1);
}
sigprocmask(SIG_SETMASK, &osset, NULL);
return WEXITSTATUS(stat);
}
static void search_conf(void)
{
struct symbol **sym_arr;
int stat;
struct gstr res;
int dres;
again:
cprint_init();
cprint("--title");
cprint(_("Search Configuration Parameter"));
cprint("--inputbox");
cprint(_("Enter CONFIG_ (sub)string to search for (omit CONFIG_)"));
cprint("10");
cprint("75");
cprint("");
stat = exec_conf();
if (stat < 0)
goto again;
switch (stat) {
reset_dialog();
dres = dialog_inputbox(_("Search Configuration Parameter"),
_("Enter CONFIG_ (sub)string to search for (omit CONFIG_)"),
10, 75, "");
switch (dres) {
case 0:
break;
case 1:
@@ -563,7 +415,7 @@ again:
return;
}
sym_arr = sym_re_search(input_buf);
sym_arr = sym_re_search(dialog_input_result);
res = get_relations_str(sym_arr);
free(sym_arr);
show_textbox(_("Search Results"), str_get(&res), 0, 0);
@@ -590,24 +442,24 @@ static void build_conf(struct menu *menu)
switch (prop->type) {
case P_MENU:
child_count++;
cprint("m%p", menu);
if (single_menu_mode) {
cprint1("%s%*c%s",
menu->data ? "-->" : "++>",
indent + 1, ' ', prompt);
item_make("%s%*c%s",
menu->data ? "-->" : "++>",
indent + 1, ' ', prompt);
} else
cprint1(" %*c%s --->", indent + 1, ' ', prompt);
item_make(" %*c%s --->", indent + 1, ' ', prompt);
cprint_done();
item_set_tag('m');
item_set_data(menu);
if (single_menu_mode && menu->data)
goto conf_childs;
return;
default:
if (prompt) {
child_count++;
cprint(":%p", menu);
cprint("---%*c%s", indent + 1, ' ', prompt);
item_make("---%*c%s", indent + 1, ' ', prompt);
item_set_tag(':');
item_set_data(menu);
}
}
} else
@@ -628,10 +480,9 @@ static void build_conf(struct menu *menu)
val = sym_get_tristate_value(sym);
if (sym_is_changable(sym)) {
cprint("t%p", menu);
switch (type) {
case S_BOOLEAN:
cprint1("[%c]", val == no ? ' ' : '*');
item_make("[%c]", val == no ? ' ' : '*');
break;
case S_TRISTATE:
switch (val) {
@@ -639,84 +490,87 @@ static void build_conf(struct menu *menu)
case mod: ch = 'M'; break;
default: ch = ' '; break;
}
cprint1("<%c>", ch);
item_make("<%c>", ch);
break;
}
item_set_tag('t');
item_set_data(menu);
} else {
cprint("%c%p", def_menu ? 't' : ':', menu);
cprint1(" ");
item_make(" ");
item_set_tag(def_menu ? 't' : ':');
item_set_data(menu);
}
cprint1("%*c%s", indent + 1, ' ', menu_get_prompt(menu));
item_add_str("%*c%s", indent + 1, ' ', menu_get_prompt(menu));
if (val == yes) {
if (def_menu) {
cprint1(" (%s)", menu_get_prompt(def_menu));
cprint1(" --->");
cprint_done();
item_add_str(" (%s)", menu_get_prompt(def_menu));
item_add_str(" --->");
if (def_menu->list) {
indent += 2;
build_conf(def_menu);
indent -= 2;
}
} else
cprint_done();
}
return;
}
cprint_done();
} else {
if (menu == current_menu) {
cprint(":%p", menu);
cprint("---%*c%s", indent + 1, ' ', menu_get_prompt(menu));
item_make("---%*c%s", indent + 1, ' ', menu_get_prompt(menu));
item_set_tag(':');
item_set_data(menu);
goto conf_childs;
}
child_count++;
val = sym_get_tristate_value(sym);
if (sym_is_choice_value(sym) && val == yes) {
cprint(":%p", menu);
cprint1(" ");
item_make(" ");
item_set_tag(':');
item_set_data(menu);
} else {
switch (type) {
case S_BOOLEAN:
cprint("t%p", menu);
if (sym_is_changable(sym))
cprint1("[%c]", val == no ? ' ' : '*');
item_make("[%c]", val == no ? ' ' : '*');
else
cprint1("---");
item_make("---");
item_set_tag('t');
item_set_data(menu);
break;
case S_TRISTATE:
cprint("t%p", menu);
switch (val) {
case yes: ch = '*'; break;
case mod: ch = 'M'; break;
default: ch = ' '; break;
}
if (sym_is_changable(sym))
cprint1("<%c>", ch);
item_make("<%c>", ch);
else
cprint1("---");
item_make("---");
item_set_tag('t');
item_set_data(menu);
break;
default:
cprint("s%p", menu);
tmp = cprint1("(%s)", sym_get_string_value(sym));
tmp = 2 + strlen(sym_get_string_value(sym)); /* () = 2 */
item_make("(%s)", sym_get_string_value(sym));
tmp = indent - tmp + 4;
if (tmp < 0)
tmp = 0;
cprint1("%*c%s%s", tmp, ' ', menu_get_prompt(menu),
(sym_has_value(sym) || !sym_is_changable(sym)) ?
"" : " (NEW)");
cprint_done();
item_add_str("%*c%s%s", tmp, ' ', menu_get_prompt(menu),
(sym_has_value(sym) || !sym_is_changable(sym)) ?
"" : " (NEW)");
item_set_tag('s');
item_set_data(menu);
goto conf_childs;
}
}
cprint1("%*c%s%s", indent + 1, ' ', menu_get_prompt(menu),
(sym_has_value(sym) || !sym_is_changable(sym)) ?
"" : " (NEW)");
item_add_str("%*c%s%s", indent + 1, ' ', menu_get_prompt(menu),
(sym_has_value(sym) || !sym_is_changable(sym)) ?
"" : " (NEW)");
if (menu->prompt->type == P_MENU) {
cprint1(" --->");
cprint_done();
item_add_str(" --->");
return;
}
cprint_done();
}
conf_childs:
@@ -731,59 +585,43 @@ static void conf(struct menu *menu)
struct menu *submenu;
const char *prompt = menu_get_prompt(menu);
struct symbol *sym;
char active_entry[40];
int stat, type, i;
struct menu *active_menu = NULL;
int res;
int s_scroll = 0;
unlink("lxdialog.scrltmp");
active_entry[0] = 0;
while (1) {
cprint_init();
cprint("--title");
cprint("%s", prompt ? prompt : _("Main Menu"));
cprint("--menu");
cprint(_(menu_instructions));
cprint("%d", rows);
cprint("%d", cols);
cprint("%d", rows - 10);
cprint("%s", active_entry);
item_reset();
current_menu = menu;
build_conf(menu);
if (!child_count)
break;
if (menu == &rootmenu) {
cprint(":");
cprint("--- ");
cprint("L");
cprint(_(" Load an Alternate Configuration File"));
cprint("S");
cprint(_(" Save Configuration to an Alternate File"));
item_make("--- ");
item_set_tag(':');
item_make(_(" Load an Alternate Configuration File"));
item_set_tag('L');
item_make(_(" Save an Alternate Configuration File"));
item_set_tag('S');
}
stat = exec_conf();
if (stat < 0)
continue;
if (stat == 1 || stat == 255)
reset_dialog();
res = dialog_menu(prompt ? prompt : _("Main Menu"),
_(menu_instructions),
rows, cols, rows - 10,
active_menu, &s_scroll);
if (res == 1 || res == 255)
break;
type = input_buf[0];
if (!type)
if (!item_activate_selected())
continue;
if (!item_tag())
continue;
for (i = 0; input_buf[i] && !isspace(input_buf[i]); i++)
;
if (i >= sizeof(active_entry))
i = sizeof(active_entry) - 1;
input_buf[i] = 0;
strcpy(active_entry, input_buf);
submenu = item_data();
active_menu = item_data();
sym = submenu->sym;
sym = NULL;
submenu = NULL;
if (sscanf(input_buf + 1, "%p", &submenu) == 1)
sym = submenu->sym;
switch (stat) {
switch (res) {
case 0:
switch (type) {
switch (item_tag()) {
case 'm':
if (single_menu_mode)
submenu->data = (void *) (long) !submenu->data;
@@ -814,7 +652,7 @@ static void conf(struct menu *menu)
show_helptext("README", _(mconf_readme));
break;
case 3:
if (type == 't') {
if (item_is_tag('t')) {
if (sym_set_tristate_value(sym, yes))
break;
if (sym_set_tristate_value(sym, mod))
@@ -822,17 +660,17 @@ static void conf(struct menu *menu)
}
break;
case 4:
if (type == 't')
if (item_is_tag('t'))
sym_set_tristate_value(sym, no);
break;
case 5:
if (type == 't')
if (item_is_tag('t'))
sym_set_tristate_value(sym, mod);
break;
case 6:
if (type == 't')
if (item_is_tag('t'))
sym_toggle_tristate_value(sym);
else if (type == 'm')
else if (item_is_tag('m'))
conf(submenu);
break;
case 7:
@@ -844,13 +682,8 @@ static void conf(struct menu *menu)
static void show_textbox(const char *title, const char *text, int r, int c)
{
int fd;
fd = creat(".help.tmp", 0777);
write(fd, text, strlen(text));
close(fd);
show_file(".help.tmp", title, r, c);
unlink(".help.tmp");
reset_dialog();
dialog_textbox(title, text, r ? r : rows, c ? c : cols);
}
static void show_helptext(const char *title, const char *text)
@@ -878,62 +711,44 @@ static void show_help(struct menu *menu)
str_free(&help);
}
static void show_file(const char *filename, const char *title, int r, int c)
{
do {
cprint_init();
if (title) {
cprint("--title");
cprint("%s", title);
}
cprint("--textbox");
cprint("%s", filename);
cprint("%d", r ? r : rows);
cprint("%d", c ? c : cols);
} while (exec_conf() < 0);
}
static void conf_choice(struct menu *menu)
{
const char *prompt = menu_get_prompt(menu);
struct menu *child;
struct symbol *active;
int stat;
active = sym_get_choice_value(menu->sym);
while (1) {
cprint_init();
cprint("--title");
cprint("%s", prompt ? prompt : _("Main Menu"));
cprint("--radiolist");
cprint(_(radiolist_instructions));
cprint("15");
cprint("70");
cprint("6");
int res;
int selected;
item_reset();
current_menu = menu;
for (child = menu->list; child; child = child->next) {
if (!menu_is_visible(child))
continue;
cprint("%p", child);
cprint("%s", menu_get_prompt(child));
item_make("%s", menu_get_prompt(child));
item_set_data(child);
if (child->sym == active)
item_set_selected(1);
if (child->sym == sym_get_choice_value(menu->sym))
cprint("ON");
else if (child->sym == active)
cprint("SELECTED");
else
cprint("OFF");
item_set_tag('X');
}
stat = exec_conf();
switch (stat) {
reset_dialog();
res = dialog_checklist(prompt ? prompt : _("Main Menu"),
_(radiolist_instructions),
15, 70, 6);
selected = item_activate_selected();
switch (res) {
case 0:
if (sscanf(input_buf, "%p", &child) != 1)
break;
sym_set_tristate_value(child->sym, yes);
if (selected) {
child = item_data();
sym_set_tristate_value(child->sym, yes);
}
return;
case 1:
if (sscanf(input_buf, "%p", &child) == 1) {
if (selected) {
child = item_data();
show_help(child);
active = child->sym;
} else
@@ -948,33 +763,31 @@ static void conf_choice(struct menu *menu)
static void conf_string(struct menu *menu)
{
const char *prompt = menu_get_prompt(menu);
int stat;
while (1) {
cprint_init();
cprint("--title");
cprint("%s", prompt ? prompt : _("Main Menu"));
cprint("--inputbox");
int res;
char *heading;
switch (sym_get_type(menu->sym)) {
case S_INT:
cprint(_(inputbox_instructions_int));
heading = _(inputbox_instructions_int);
break;
case S_HEX:
cprint(_(inputbox_instructions_hex));
heading = _(inputbox_instructions_hex);
break;
case S_STRING:
cprint(_(inputbox_instructions_string));
heading = _(inputbox_instructions_string);
break;
default:
/* panic? */;
heading = "Internal mconf error!";
}
cprint("10");
cprint("75");
cprint("%s", sym_get_string_value(menu->sym));
stat = exec_conf();
switch (stat) {
reset_dialog();
res = dialog_inputbox(prompt ? prompt : _("Main Menu"),
heading, 10, 75,
sym_get_string_value(menu->sym));
switch (res) {
case 0:
if (sym_set_string_value(menu->sym, input_buf))
if (sym_set_string_value(menu->sym, dialog_input_result))
return;
show_textbox(NULL, _("You have made an invalid entry."), 5, 43);
break;
@@ -989,21 +802,17 @@ static void conf_string(struct menu *menu)
static void conf_load(void)
{
int stat;
while (1) {
cprint_init();
cprint("--inputbox");
cprint(load_config_text);
cprint("11");
cprint("55");
cprint("%s", filename);
stat = exec_conf();
switch(stat) {
int res;
reset_dialog();
res = dialog_inputbox(NULL, load_config_text,
11, 55, filename);
switch(res) {
case 0:
if (!input_buf[0])
if (!dialog_input_result[0])
return;
if (!conf_read(input_buf))
if (!conf_read(dialog_input_result))
return;
show_textbox(NULL, _("File does not exist!"), 5, 38);
break;
@@ -1018,21 +827,16 @@ static void conf_load(void)
static void conf_save(void)
{
int stat;
while (1) {
cprint_init();
cprint("--inputbox");
cprint(save_config_text);
cprint("11");
cprint("55");
cprint("%s", filename);
stat = exec_conf();
switch(stat) {
int res;
reset_dialog();
res = dialog_inputbox(NULL, save_config_text,
11, 55, filename);
switch(res) {
case 0:
if (!input_buf[0])
if (!dialog_input_result[0])
return;
if (!conf_write(input_buf))
if (!conf_write(dialog_input_result))
return;
show_textbox(NULL, _("Can't create file! Probably a nonexistent directory."), 5, 60);
break;
@@ -1048,15 +852,13 @@ static void conf_save(void)
static void conf_cleanup(void)
{
tcsetattr(1, TCSAFLUSH, &ios_org);
unlink(".help.tmp");
unlink("lxdialog.scrltmp");
}
int main(int ac, char **av)
{
struct symbol *sym;
char *mode;
int stat;
int res;
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
@@ -1079,18 +881,16 @@ int main(int ac, char **av)
tcgetattr(1, &ios_org);
atexit(conf_cleanup);
init_wsize();
reset_dialog();
init_dialog(menu_backtitle);
conf(&rootmenu);
do {
cprint_init();
cprint("--yesno");
cprint(_("Do you wish to save your new kernel configuration?"));
cprint("5");
cprint("60");
stat = exec_conf();
} while (stat < 0);
if (stat == 0) {
reset_dialog();
res = dialog_yesno(NULL,
_("Do you wish to save your "
"new kernel configuration?"),
5, 60);
end_dialog();
if (res == 0) {
if (conf_write(NULL)) {
fprintf(stderr, _("\n\n"
"Error during writing of the kernel configuration.\n"