Changeset 36361


Ignore:
Timestamp:
2013-04-18T14:05:16+02:00 (5 years ago)
Author:
nbd
Message:

build: add new menuconfig code based on linux 3.9

Location:
trunk
Files:
1 added
6 deleted
27 edited
1 moved

Legend:

Unmodified
Added
Removed
  • trunk/include/toplevel.mk

    r36082 r36361  
    9090defconfig: scripts/config/conf prepare-tmpinfo FORCE 
    9191        touch .config 
    92         $< -D .config Config.in 
     92        $< --defconfig .config Config.in 
     93 
     94confdefault-y=allyes 
     95confdefault-m=allmod 
     96confdefault-n=allno 
     97confdefault:=$(confdefault-$(CONFDEFAULT)) 
    9398 
    9499oldconfig: scripts/config/conf prepare-tmpinfo FORCE 
    95         $< -$(if $(CONFDEFAULT),$(CONFDEFAULT),o) Config.in 
     100        $< --$(if $(confdefault),$(confdefault),old)config Config.in 
    96101 
    97102menuconfig: scripts/config/mconf prepare-tmpinfo FORCE 
     
    148153        @( \ 
    149154                cp .config tmp/.config; \ 
    150                 ./scripts/config/conf -D tmp/.config -w tmp/.config Config.in > /dev/null 2>&1; \ 
     155                ./scripts/config/conf --defconfig tmp/.config -w tmp/.config Config.in > /dev/null 2>&1; \ 
    151156                if ./scripts/kconfig.pl '>' .config tmp/.config | grep -q CONFIG; then \ 
    152157                        printf "$(_R)WARNING: your configuration is out of sync. Please run make menuconfig, oldconfig or defconfig!$(_N)\n" >&2; \ 
  • trunk/scripts/config/Makefile

    r9300 r36361  
    1414# 
    1515# FreeBSD 
    16 export CFLAGS+=-DKBUILD_NO_NLS 
     16 
     17check_lxdialog = $(shell $(SHELL) $(CURDIR)/lxdialog/check-lxdialog.sh -$(1)) 
     18export CFLAGS += -DKBUILD_NO_NLS -I. $(call check_lxdialog,ccflags) 
    1719 
    1820conf-objs       := conf.o zconf.tab.o 
    1921mconf-objs      := mconf.o zconf.tab.o 
     22lxdialog-objs := \ 
     23        lxdialog/checklist.o lxdialog/util.o lxdialog/inputbox.o \ 
     24        lxdialog/textbox.o lxdialog/yesno.o lxdialog/menubox.o 
    2025 
    21 clean-files     := lkc_defs.h qconf.moc .tmp_qtcheck \ 
    22                    .tmp_gtkcheck zconf.tab.c lex.zconf.c zconf.hash.c 
     26clean-files     := zconf.tab.c lex.zconf.c zconf.hash.c 
    2327 
    24 all: conf mconf lxdialog/lxdialog 
    25  
    26 lxdialog/lxdialog: 
    27         $(MAKE) -C lxdialog 
     28all: conf mconf 
    2829 
    2930conf: $(conf-objs) 
    30 mconf: $(mconf-objs)  
     31mconf: $(mconf-objs) $(lxdialog-objs) 
     32        $(CC) -o $@ $^ $(call check_lxdialog,ldflags $(CC)) 
    3133 
    3234clean: 
    33         rm -f *.o $(clean-files) conf mconf 
    34         $(MAKE) -C lxdialog clean 
     35        rm -f *.o lxdialog/*.o $(clean-files) conf mconf 
    3536 
    36 zconf.tab.o: lex.zconf.c zconf.hash.c confdata.c 
     37zconf.tab.o: zconf.lex.c zconf.hash.c confdata.c 
    3738 
    3839kconfig_load.o: lkc_defs.h 
    3940 
    40 lkc_defs.h: $(src)/lkc_proto.h 
    41         sed < $< > $@ 's/P(\([^,]*\),.*/#define \1 (\*\1_p)/' 
    42  
    4341zconf.tab.c: zconf.y 
    44 lex.zconf.c: zconf.l 
     42zconf.lex.c: zconf.l 
    4543zconf.hash.c: zconf.gperf 
    4644 
     
    4846        cp $@_shipped $@ || bison -l -b $* -p $(notdir $*) $< 
    4947 
    50 lex.%.c: %.l 
     48%.lex.c: %.l 
    5149        cp $@_shipped $@ || flex -L -P$(notdir $*) -o$@ $< 
    5250 
  • trunk/scripts/config/README

    r6502 r36361  
    1 These files were taken from the Linux 2.6.16.7 Kernel 
     1These files were taken from the Linux 3.9 Kernel 
    22Configuration System and modified for the OpenWrt Buildroot. 
  • trunk/scripts/config/conf.c

    r25230 r36361  
    44 */ 
    55 
     6#include <locale.h> 
    67#include <ctype.h> 
     8#include <stdio.h> 
    79#include <stdlib.h> 
    810#include <string.h> 
     11#include <time.h> 
    912#include <unistd.h> 
    10 #include <time.h> 
     13#include <getopt.h> 
    1114#include <sys/stat.h> 
    12  
    13 #define LKC_DIRECT_LINK 
     15#include <sys/time.h> 
     16 
    1417#include "lkc.h" 
    1518 
    1619static void conf(struct menu *menu); 
    1720static void check_conf(struct menu *menu); 
    18  
    19 enum { 
    20         ask_all, 
    21         ask_new, 
    22         ask_silent, 
    23         set_default, 
    24         set_yes, 
    25         set_mod, 
    26         set_no, 
    27         set_random 
    28 } input_mode = ask_all; 
    29 char *defconfig_file; 
     21static void xfgets(char *str, int size, FILE *in); 
     22 
     23enum input_mode { 
     24        oldaskconfig, 
     25        silentoldconfig, 
     26        oldconfig, 
     27        allnoconfig, 
     28        allyesconfig, 
     29        allmodconfig, 
     30        alldefconfig, 
     31        randconfig, 
     32        defconfig, 
     33        savedefconfig, 
     34        listnewconfig, 
     35        olddefconfig, 
     36} input_mode = oldaskconfig; 
    3037 
    3138static int indent = 1; 
     39static int tty_stdio; 
    3240static int valid_stdin = 1; 
     41static int sync_kconfig; 
    3342static int conf_cnt; 
    3443static char line[128]; 
    3544static struct menu *rootEntry; 
    3645 
    37 static char nohelp_text[] = N_("Sorry, no help available for this option yet.\n"); 
     46static void print_help(struct menu *menu) 
     47{ 
     48        struct gstr help = str_new(); 
     49 
     50        menu_get_ext_help(menu, &help); 
     51 
     52        printf("\n%s\n", str_get(&help)); 
     53        str_free(&help); 
     54} 
    3855 
    3956static void strip(char *str) 
     
    5673static void check_stdin(void) 
    5774{ 
    58         if (!valid_stdin && input_mode == ask_silent) { 
     75        if (!valid_stdin) { 
    5976                printf(_("aborted!\n\n")); 
    6077                printf(_("Console input/output is redirected. ")); 
     
    6481} 
    6582 
    66 static char *fgets_check_stream(char *s, int size, FILE *stream) 
    67 { 
    68         char *ret = fgets(s, size, stream); 
    69  
    70         if (ret == NULL && feof(stream)) { 
    71                 printf(_("aborted!\n\n")); 
    72                 printf(_("Console input is closed. ")); 
    73                 printf(_("Run 'make oldconfig' to update configuration.\n\n")); 
    74                 exit(1); 
    75         } 
    76  
    77         return ret; 
    78 } 
    79  
    80 static void conf_askvalue(struct symbol *sym, const char *def) 
     83static int conf_askvalue(struct symbol *sym, const char *def) 
    8184{ 
    8285        enum symbol_type type = sym_get_type(sym); 
    83         tristate val; 
    8486 
    8587        if (!sym_has_value(sym)) 
    86                 printf("(NEW) "); 
     88                printf(_("(NEW) ")); 
    8789 
    8890        line[0] = '\n'; 
     
    9395                line[0] = '\n'; 
    9496                line[1] = 0; 
    95                 return; 
     97                return 0; 
    9698        } 
    9799 
    98100        switch (input_mode) { 
    99         case set_no: 
    100         case set_mod: 
    101         case set_yes: 
    102         case set_random: 
     101        case oldconfig: 
     102        case silentoldconfig: 
    103103                if (sym_has_value(sym)) { 
    104104                        printf("%s\n", def); 
    105                         return; 
    106                 } 
    107                 break; 
    108         case ask_new: 
    109         case ask_silent: 
    110                 if (sym_has_value(sym)) { 
    111                         printf("%s\n", def); 
    112                         return; 
     105                        return 0; 
    113106                } 
    114107                check_stdin(); 
    115         case ask_all: 
     108                /* fall through */ 
     109        case oldaskconfig: 
    116110                fflush(stdout); 
    117                 fgets_check_stream(line, 128, stdin); 
    118                 return; 
    119         case set_default: 
    120                 printf("%s\n", def); 
    121                 return; 
     111                xfgets(line, 128, stdin); 
     112                if (!tty_stdio) 
     113                        printf("\n"); 
     114                return 1; 
    122115        default: 
    123116                break; 
     
    129122        case S_STRING: 
    130123                printf("%s\n", def); 
    131                 return; 
     124                return 1; 
    132125        default: 
    133126                ; 
    134127        } 
    135         switch (input_mode) { 
    136         case set_yes: 
    137                 if (sym_tristate_within_range(sym, yes)) { 
    138                         line[0] = 'y'; 
    139                         line[1] = '\n'; 
    140                         line[2] = 0; 
    141                         break; 
    142                 } 
    143         case set_mod: 
    144                 if (type == S_TRISTATE) { 
    145                         if (sym_tristate_within_range(sym, mod)) { 
    146                                 line[0] = 'm'; 
    147                                 line[1] = '\n'; 
    148                                 line[2] = 0; 
    149                                 break; 
    150                         } 
    151                 } else { 
    152                         if (sym_tristate_within_range(sym, yes)) { 
    153                                 line[0] = 'y'; 
    154                                 line[1] = '\n'; 
    155                                 line[2] = 0; 
    156                                 break; 
    157                         } 
    158                 } 
    159         case set_no: 
    160                 if (sym_tristate_within_range(sym, no)) { 
    161                         line[0] = 'n'; 
    162                         line[1] = '\n'; 
    163                         line[2] = 0; 
    164                         break; 
    165                 } 
    166         case set_random: 
    167                 do { 
    168                         val = (tristate)(random() % 3); 
    169                 } while (!sym_tristate_within_range(sym, val)); 
    170                 switch (val) { 
    171                 case no: line[0] = 'n'; break; 
    172                 case mod: line[0] = 'm'; break; 
    173                 case yes: line[0] = 'y'; break; 
    174                 } 
    175                 line[1] = '\n'; 
    176                 line[2] = 0; 
    177                 break; 
    178         default: 
    179                 break; 
    180         } 
    181128        printf("%s", line); 
    182 } 
    183  
    184 int conf_string(struct menu *menu) 
     129        return 1; 
     130} 
     131 
     132static int conf_string(struct menu *menu) 
    185133{ 
    186134        struct symbol *sym = menu->sym; 
    187         const char *def, *help; 
     135        const char *def; 
    188136 
    189137        while (1) { 
    190                 printf("%*s%s ", indent - 1, "", menu->prompt->text); 
     138                printf("%*s%s ", indent - 1, "", _(menu->prompt->text)); 
    191139                printf("(%s) ", sym->name); 
    192140                def = sym_get_string_value(sym); 
    193141                if (sym_get_string_value(sym)) 
    194142                        printf("[%s] ", def); 
    195                 conf_askvalue(sym, def); 
     143                if (!conf_askvalue(sym, def)) 
     144                        return 0; 
    196145                switch (line[0]) { 
    197146                case '\n': 
     
    200149                        /* print help */ 
    201150                        if (line[1] == '\n') { 
    202                                 help = nohelp_text; 
    203                                 if (menu->sym->help) 
    204                                         help = menu->sym->help; 
    205                                 printf("\n%s\n", menu->sym->help); 
     151                                print_help(menu); 
    206152                                def = NULL; 
    207153                                break; 
    208154                        } 
     155                        /* fall through */ 
    209156                default: 
    210157                        line[strlen(line)-1] = 0; 
     
    219166{ 
    220167        struct symbol *sym = menu->sym; 
    221         int type; 
    222168        tristate oldval, newval; 
    223         const char *help; 
    224169 
    225170        while (1) { 
    226                 printf("%*s%s ", indent - 1, "", menu->prompt->text); 
     171                printf("%*s%s ", indent - 1, "", _(menu->prompt->text)); 
    227172                if (sym->name) 
    228173                        printf("(%s) ", sym->name); 
    229                 type = sym_get_type(sym); 
    230174                putchar('['); 
    231175                oldval = sym_get_tristate_value(sym); 
     
    247191                if (oldval != yes && sym_tristate_within_range(sym, yes)) 
    248192                        printf("/y"); 
    249                 if (sym->help) 
     193                if (menu_has_help(menu)) 
    250194                        printf("/?"); 
    251195                printf("] "); 
    252                 conf_askvalue(sym, sym_get_string_value(sym)); 
     196                if (!conf_askvalue(sym, sym_get_string_value(sym))) 
     197                        return 0; 
    253198                strip(line); 
    254199 
     
    283228                        return 0; 
    284229help: 
    285                 help = nohelp_text; 
    286                 if (sym->help) 
    287                         help = sym->help; 
    288                 printf("\n%s\n", help); 
     230                print_help(menu); 
    289231        } 
    290232} 
     
    294236        struct symbol *sym, *def_sym; 
    295237        struct menu *child; 
    296         int type; 
    297238        bool is_new; 
    298239 
    299240        sym = menu->sym; 
    300         type = sym_get_type(sym); 
    301241        is_new = !sym_has_value(sym); 
    302242        if (sym_is_changable(sym)) { 
     
    316256                        return 1; 
    317257                case mod: 
    318                         printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu)); 
     258                        printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu))); 
    319259                        return 0; 
    320260                case yes: 
     
    326266                int cnt, def; 
    327267 
    328                 printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu)); 
     268                printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu))); 
    329269                def_sym = sym_get_choice_value(sym); 
    330270                cnt = def = 0; 
    331                 line[0] = '0'; 
    332                 line[1] = 0; 
     271                line[0] = 0; 
    333272                for (child = menu->list; child; child = child->next) { 
    334273                        if (!menu_is_visible(child)) 
    335274                                continue; 
    336275                        if (!child->sym) { 
    337                                 printf("%*c %s\n", indent, '*', menu_get_prompt(child)); 
     276                                printf("%*c %s\n", indent, '*', _(menu_get_prompt(child))); 
    338277                                continue; 
    339278                        } 
     
    344283                        } else 
    345284                                printf("%*c", indent, ' '); 
    346                         printf(" %d. %s", cnt, menu_get_prompt(child)); 
     285                        printf(" %d. %s", cnt, _(menu_get_prompt(child))); 
    347286                        if (child->sym->name) 
    348287                                printf(" (%s)", child->sym->name); 
    349288                        if (!sym_has_value(child->sym)) 
    350                                 printf(" (NEW)"); 
     289                                printf(_(" (NEW)")); 
    351290                        printf("\n"); 
    352291                } 
    353                 printf("%*schoice", indent - 1, ""); 
     292                printf(_("%*schoice"), indent - 1, ""); 
    354293                if (cnt == 1) { 
    355294                        printf("[1]: 1\n"); 
     
    357296                } 
    358297                printf("[1-%d", cnt); 
    359                 if (sym->help) 
     298                if (menu_has_help(menu)) 
    360299                        printf("?"); 
    361300                printf("]: "); 
    362301                switch (input_mode) { 
    363                 case ask_new: 
    364                 case ask_silent: 
     302                case oldconfig: 
     303                case silentoldconfig: 
    365304                        if (!is_new) { 
    366305                                cnt = def; 
     
    369308                        } 
    370309                        check_stdin(); 
    371                 case ask_all: 
     310                        /* fall through */ 
     311                case oldaskconfig: 
    372312                        fflush(stdout); 
    373                         fgets_check_stream(line, 128, stdin); 
     313                        xfgets(line, 128, stdin); 
    374314                        strip(line); 
    375315                        if (line[0] == '?') { 
    376                                 printf("\n%s\n", menu->sym->help ? 
    377                                         menu->sym->help : nohelp_text); 
     316                                print_help(menu); 
    378317                                continue; 
    379318                        } 
     
    385324                                continue; 
    386325                        break; 
    387                 case set_random: 
    388                         def = (random() % cnt) + 1; 
    389                 case set_default: 
    390                 case set_yes: 
    391                 case set_mod: 
    392                 case set_no: 
    393                         cnt = def; 
    394                         printf("%d\n", cnt); 
     326                default: 
    395327                        break; 
    396328                } 
     
    405337                if (!child) 
    406338                        continue; 
    407                 if (line[strlen(line) - 1] == '?') { 
    408                         printf("\n%s\n", child->sym->help ? 
    409                                 child->sym->help : nohelp_text); 
     339                if (line[0] && line[strlen(line) - 1] == '?') { 
     340                        print_help(child); 
    410341                        continue; 
    411342                } 
    412343                sym_set_choice_value(sym, child->sym); 
    413                 if (child->list) { 
     344                for (child = child->list; child; child = child->next) { 
    414345                        indent += 2; 
    415                         conf(child->list); 
     346                        conf(child); 
    416347                        indent -= 2; 
    417348                } 
     
    436367                switch (prop->type) { 
    437368                case P_MENU: 
    438                         if (input_mode == ask_silent && rootEntry != menu) { 
     369                        if ((input_mode == silentoldconfig || 
     370                             input_mode == listnewconfig || 
     371                             input_mode == olddefconfig) && 
     372                            rootEntry != menu) { 
    439373                                check_conf(menu); 
    440374                                return; 
    441375                        } 
     376                        /* fall through */ 
    442377                case P_COMMENT: 
    443378                        prompt = menu_get_prompt(menu); 
     
    445380                                printf("%*c\n%*c %s\n%*c\n", 
    446381                                        indent, '*', 
    447                                         indent, '*', prompt, 
     382                                        indent, '*', _(prompt), 
    448383                                        indent, '*'); 
    449384                default: 
     
    494429                if (sym_is_changable(sym) || 
    495430                    (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) { 
    496                         if (!conf_cnt++) 
    497                                 printf(_("*\n* Restart config...\n*\n")); 
    498                         rootEntry = menu_get_parent_menu(menu); 
    499                         conf(rootEntry); 
     431                        if (input_mode == listnewconfig) { 
     432                                if (sym->name && !sym_is_choice_value(sym)) { 
     433                                        printf("%s%s\n", CONFIG_, sym->name); 
     434                                } 
     435                        } else if (input_mode != olddefconfig) { 
     436                                if (!conf_cnt++) 
     437                                        printf(_("*\n* Restart config...\n*\n")); 
     438                                rootEntry = menu_get_parent_menu(menu); 
     439                                conf(rootEntry); 
     440                        } 
    500441                } 
    501442        } 
     
    505446} 
    506447 
     448static struct option long_opts[] = { 
     449        {"oldaskconfig",    no_argument,       NULL, oldaskconfig}, 
     450        {"oldconfig",       no_argument,       NULL, oldconfig}, 
     451        {"silentoldconfig", no_argument,       NULL, silentoldconfig}, 
     452        {"defconfig",       optional_argument, NULL, defconfig}, 
     453        {"savedefconfig",   required_argument, NULL, savedefconfig}, 
     454        {"allnoconfig",     no_argument,       NULL, allnoconfig}, 
     455        {"allyesconfig",    no_argument,       NULL, allyesconfig}, 
     456        {"allmodconfig",    no_argument,       NULL, allmodconfig}, 
     457        {"alldefconfig",    no_argument,       NULL, alldefconfig}, 
     458        {"randconfig",      no_argument,       NULL, randconfig}, 
     459        {"listnewconfig",   no_argument,       NULL, listnewconfig}, 
     460        {"olddefconfig",    no_argument,       NULL, olddefconfig}, 
     461        /* 
     462         * oldnoconfig is an alias of olddefconfig, because people already 
     463         * are dependent on its behavior(sets new symbols to their default 
     464         * value but not 'n') with the counter-intuitive name. 
     465         */ 
     466        {"oldnoconfig",     no_argument,       NULL, olddefconfig}, 
     467        {NULL, 0, NULL, 0} 
     468}; 
     469 
     470static void conf_usage(const char *progname) 
     471{ 
     472 
     473        printf("Usage: %s [option] <kconfig-file>\n", progname); 
     474        printf("[option] is _one_ of the following:\n"); 
     475        printf("  --listnewconfig         List new options\n"); 
     476        printf("  --oldaskconfig          Start a new configuration using a line-oriented program\n"); 
     477        printf("  --oldconfig             Update a configuration using a provided .config as base\n"); 
     478        printf("  --silentoldconfig       Same as oldconfig, but quietly, additionally update deps\n"); 
     479        printf("  --olddefconfig          Same as silentoldconfig but sets new symbols to their default value\n"); 
     480        printf("  --oldnoconfig           An alias of olddefconfig\n"); 
     481        printf("  --defconfig <file>      New config with default defined in <file>\n"); 
     482        printf("  --savedefconfig <file>  Save the minimal current configuration to <file>\n"); 
     483        printf("  --allnoconfig           New config where all options are answered with no\n"); 
     484        printf("  --allyesconfig          New config where all options are answered with yes\n"); 
     485        printf("  --allmodconfig          New config where all options are answered with mod\n"); 
     486        printf("  --alldefconfig          New config with all symbols set to default\n"); 
     487        printf("  --randconfig            New config with random answer to all options\n"); 
     488} 
     489 
    507490int main(int ac, char **av) 
    508491{ 
    509         int i = 1; 
    510         const char *name; 
    511         char *output = NULL; 
     492        const char *progname = av[0]; 
     493        int opt; 
     494        const char *name, *defconfig_file = NULL /* gcc uninit */; 
    512495        struct stat tmpstat; 
    513  
    514         while (ac > i && av[i][0] == '-') { 
    515                 switch (av[i++][1]) { 
    516                 case 'o': 
    517                         input_mode = ask_new; 
    518                         break; 
    519                 case 's': 
    520                         input_mode = ask_silent; 
    521                         valid_stdin = isatty(0) && isatty(1) && isatty(2); 
    522                         break; 
    523                 case 'd': 
    524                         input_mode = set_default; 
    525                         break; 
    526                 case 'D': 
    527                         input_mode = set_default; 
    528                         defconfig_file = av[i++]; 
    529                         if (!defconfig_file) { 
    530                                 printf(_("%s: No default config file specified\n"), 
    531                                         av[0]); 
    532                                 exit(1); 
    533                         } 
     496        const char *input_file = NULL, *output_file = NULL; 
     497 
     498        setlocale(LC_ALL, ""); 
     499        bindtextdomain(PACKAGE, LOCALEDIR); 
     500        textdomain(PACKAGE); 
     501 
     502        tty_stdio = isatty(0) && isatty(1) && isatty(2); 
     503 
     504        while ((opt = getopt_long(ac, av, "r:w:", long_opts, NULL)) != -1) { 
     505                input_mode = (enum input_mode)opt; 
     506                switch (opt) { 
     507                case silentoldconfig: 
     508                        sync_kconfig = 1; 
     509                        break; 
     510                case defconfig: 
     511                case savedefconfig: 
     512                        defconfig_file = optarg; 
     513                        break; 
     514                case randconfig: 
     515                { 
     516                        struct timeval now; 
     517                        unsigned int seed; 
     518 
     519                        /* 
     520                         * Use microseconds derived seed, 
     521                         * compensate for systems where it may be zero 
     522                         */ 
     523                        gettimeofday(&now, NULL); 
     524 
     525                        seed = (unsigned int)((now.tv_sec + 1) * (now.tv_usec + 1)); 
     526                        srand(seed); 
     527                        break; 
     528                } 
     529                case oldaskconfig: 
     530                case oldconfig: 
     531                case allnoconfig: 
     532                case allyesconfig: 
     533                case allmodconfig: 
     534                case alldefconfig: 
     535                case listnewconfig: 
     536                case olddefconfig: 
     537                        break; 
     538                case 'r': 
     539                        input_file = optarg; 
    534540                        break; 
    535541                case 'w': 
    536                         output = av[i++]; 
    537                         break; 
    538                 case 'n': 
    539                         input_mode = set_no; 
    540                         break; 
    541                 case 'm': 
    542                         input_mode = set_mod; 
    543                         break; 
    544                 case 'y': 
    545                         input_mode = set_yes; 
    546                         break; 
    547                 case 'r': 
    548                         input_mode = set_random; 
    549                         srandom(time(NULL)); 
    550                         break; 
    551                 case 'h': 
     542                        output_file = optarg; 
     543                        break; 
    552544                case '?': 
    553                         printf("%s [-o|-s] config\n", av[0]); 
    554                         exit(0); 
    555                 } 
    556         } 
    557         name = av[i]; 
    558         if (!name) { 
     545                        conf_usage(progname); 
     546                        exit(1); 
     547                        break; 
     548                } 
     549        } 
     550        if (ac == optind) { 
    559551                printf(_("%s: Kconfig file missing\n"), av[0]); 
    560         } 
     552                conf_usage(progname); 
     553                exit(1); 
     554        } 
     555        name = av[optind]; 
    561556        conf_parse(name); 
    562557        //zconfdump(stdout); 
     558        if (sync_kconfig) { 
     559                name = conf_get_configname(); 
     560                if (stat(name, &tmpstat)) { 
     561                        fprintf(stderr, _("***\n" 
     562                                "*** Configuration file \"%s\" not found!\n" 
     563                                "***\n" 
     564                                "*** Please run some configurator (e.g. \"make oldconfig\" or\n" 
     565                                "*** \"make menuconfig\" or \"make xconfig\").\n" 
     566                                "***\n"), name); 
     567                        exit(1); 
     568                } 
     569        } 
     570 
    563571        switch (input_mode) { 
    564         case set_default: 
     572        case defconfig: 
    565573                if (!defconfig_file) 
    566574                        defconfig_file = conf_get_default_confname(); 
    567575                if (conf_read(defconfig_file)) { 
    568                         printf("***\n" 
     576                        printf(_("***\n" 
    569577                                "*** Can't find default configuration \"%s\"!\n" 
    570                                 "***\n", defconfig_file); 
     578                                "***\n"), defconfig_file); 
    571579                        exit(1); 
    572580                } 
    573581                break; 
    574         case ask_silent: 
    575                 if (stat(".config", &tmpstat)) { 
    576                         printf(_("***\n" 
    577                                 "*** You have not yet configured your build!\n" 
    578                                 "***\n" 
    579                                 "*** Please run some configurator (e.g. \"make oldconfig\" or\n" 
    580                                 "*** \"make menuconfig\" or \"make xconfig\").\n" 
    581                                 "***\n")); 
    582                         exit(1); 
    583                 } 
    584         case ask_all: 
    585         case ask_new: 
    586         case set_no: 
    587         case set_mod: 
    588         case set_yes: 
    589         case set_random: 
    590                 conf_read(NULL); 
     582        case savedefconfig: 
     583        case silentoldconfig: 
     584        case oldaskconfig: 
     585        case oldconfig: 
     586        case listnewconfig: 
     587        case olddefconfig: 
     588        case allnoconfig: 
     589        case allyesconfig: 
     590        case allmodconfig: 
     591        case alldefconfig: 
     592        case randconfig: 
     593                conf_read(input_file); 
    591594                break; 
    592595        default: 
     
    594597        } 
    595598 
    596         if (input_mode != ask_silent) { 
     599        if (sync_kconfig) { 
     600                if (conf_get_changed()) { 
     601                        name = getenv("KCONFIG_NOSILENTUPDATE"); 
     602                        if (name && *name) { 
     603                                fprintf(stderr, 
     604                                        _("\n*** The configuration requires explicit update.\n\n")); 
     605                                return 1; 
     606                        } 
     607                } 
     608                valid_stdin = tty_stdio; 
     609        } 
     610 
     611        switch (input_mode) { 
     612        case allnoconfig: 
     613                conf_set_all_new_symbols(def_no); 
     614                break; 
     615        case allyesconfig: 
     616                conf_set_all_new_symbols(def_yes); 
     617                break; 
     618        case allmodconfig: 
     619                conf_set_all_new_symbols(def_mod); 
     620                break; 
     621        case alldefconfig: 
     622                conf_set_all_new_symbols(def_default); 
     623                break; 
     624        case randconfig: 
     625                conf_set_all_new_symbols(def_random); 
     626                break; 
     627        case defconfig: 
     628                conf_set_all_new_symbols(def_default); 
     629                break; 
     630        case savedefconfig: 
     631                break; 
     632        case oldaskconfig: 
    597633                rootEntry = &rootmenu; 
    598634                conf(&rootmenu); 
    599                 if (input_mode == ask_all) { 
    600                         input_mode = ask_silent; 
    601                         valid_stdin = 1; 
    602                 } 
    603         } 
    604         do { 
    605                 conf_cnt = 0; 
    606                 check_conf(&rootmenu); 
    607         } while (conf_cnt); 
    608         if (conf_write(output)) { 
    609                 fprintf(stderr, _("\n*** Error during writing of the build configuration.\n\n")); 
    610                 return 1; 
     635                input_mode = silentoldconfig; 
     636                /* fall through */ 
     637        case oldconfig: 
     638        case listnewconfig: 
     639        case olddefconfig: 
     640        case silentoldconfig: 
     641                /* Update until a loop caused no more changes */ 
     642                do { 
     643                        conf_cnt = 0; 
     644                        check_conf(&rootmenu); 
     645                } while (conf_cnt && 
     646                         (input_mode != listnewconfig && 
     647                          input_mode != olddefconfig)); 
     648                break; 
     649        } 
     650 
     651        if (sync_kconfig) { 
     652                /* silentoldconfig is used during the build so we shall update autoconf. 
     653                 * All other commands are only used to generate a config. 
     654                 */ 
     655                if ((output_file || conf_get_changed()) && 
     656                    conf_write(output_file)) { 
     657                        fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n")); 
     658                        exit(1); 
     659                } 
     660                if (conf_write_autoconf()) { 
     661                        fprintf(stderr, _("\n*** Error during update of the configuration.\n\n")); 
     662                        return 1; 
     663                } 
     664        } else if (input_mode == savedefconfig) { 
     665                if (conf_write_defconfig(defconfig_file)) { 
     666                        fprintf(stderr, _("n*** Error while saving defconfig to: %s\n\n"), 
     667                                defconfig_file); 
     668                        return 1; 
     669                } 
     670        } else if (input_mode != listnewconfig) { 
     671                if (conf_write(output_file)) { 
     672                        fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n")); 
     673                        exit(1); 
     674                } 
    611675        } 
    612676        return 0; 
    613677} 
     678 
     679/* 
     680 * Helper function to facilitate fgets() by Jean Sacren. 
     681 */ 
     682void xfgets(char *str, int size, FILE *in) 
     683{ 
     684        if (fgets(str, size, in) == NULL) 
     685                fprintf(stderr, "\nError in reading or end of file.\n"); 
     686} 
  • trunk/scripts/config/confdata.c

    r13008 r36361  
    66#include <sys/stat.h> 
    77#include <ctype.h> 
     8#include <errno.h> 
     9#include <fcntl.h> 
     10#include <stdarg.h> 
    811#include <stdio.h> 
    912#include <stdlib.h> 
     
    1215#include <unistd.h> 
    1316 
    14 #define LKC_DIRECT_LINK 
    1517#include "lkc.h" 
    16  
    17 #define LOCAL_BUILD_SETTINGS "/.openwrt/defconfig" 
    1818 
    1919static void conf_warning(const char *fmt, ...) 
    2020        __attribute__ ((format (printf, 1, 2))); 
    2121 
     22static void conf_message(const char *fmt, ...) 
     23        __attribute__ ((format (printf, 1, 2))); 
     24 
    2225static const char *conf_filename; 
    2326static int conf_lineno, conf_warnings, conf_unsaved; 
    2427 
    25 const char conf_def_filename[] = ".config"; 
    26  
    27 const char conf_defname[] = "scripts/config/defconfig"; 
    28  
    29 const char *conf_confnames[] = { 
    30         ".config", 
    31         conf_defname, 
    32         NULL, 
    33 }; 
     28const char conf_defname[] = "arch/$ARCH/defconfig"; 
    3429 
    3530static void conf_warning(const char *fmt, ...) 
     
    4237        va_end(ap); 
    4338        conf_warnings++; 
     39} 
     40 
     41static void conf_default_message_callback(const char *fmt, va_list ap) 
     42{ 
     43        printf("#\n# "); 
     44        vprintf(fmt, ap); 
     45        printf("\n#\n"); 
     46} 
     47 
     48static void (*conf_message_callback) (const char *fmt, va_list ap) = 
     49        conf_default_message_callback; 
     50void conf_set_message_callback(void (*fn) (const char *fmt, va_list ap)) 
     51{ 
     52        conf_message_callback = fn; 
     53} 
     54 
     55static void conf_message(const char *fmt, ...) 
     56{ 
     57        va_list ap; 
     58 
     59        va_start(ap, fmt); 
     60        if (conf_message_callback) 
     61                conf_message_callback(fmt, ap); 
     62} 
     63 
     64const char *conf_get_configname(void) 
     65{ 
     66        char *name = getenv("KCONFIG_CONFIG"); 
     67 
     68        return name ? name : ".config"; 
     69} 
     70 
     71const char *conf_get_autoconfig_name(void) 
     72{ 
     73        char *name = getenv("KCONFIG_AUTOCONFIG"); 
     74 
     75        return name ? name : "include/config/auto.conf"; 
    4476} 
    4577 
     
    86118} 
    87119 
    88 void conf_reset(void) 
     120static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p) 
     121{ 
     122        char *p2; 
     123 
     124        switch (sym->type) { 
     125        case S_TRISTATE: 
     126                if (p[0] == 'm') { 
     127                        sym->def[def].tri = mod; 
     128                        sym->flags |= def_flags; 
     129                        break; 
     130                } 
     131                /* fall through */ 
     132        case S_BOOLEAN: 
     133                if (p[0] == 'y') { 
     134                        sym->def[def].tri = yes; 
     135                        sym->flags |= def_flags; 
     136                        break; 
     137                } 
     138                if (p[0] == 'n') { 
     139                        sym->def[def].tri = no; 
     140                        sym->flags |= def_flags; 
     141                        break; 
     142                } 
     143                conf_warning("symbol value '%s' invalid for %s", p, sym->name); 
     144                return 1; 
     145        case S_OTHER: 
     146                if (*p != '"') { 
     147                        for (p2 = p; *p2 && !isspace(*p2); p2++) 
     148                                ; 
     149                        sym->type = S_STRING; 
     150                        goto done; 
     151                } 
     152                /* fall through */ 
     153        case S_STRING: 
     154                if (*p++ != '"') 
     155                        break; 
     156                for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) { 
     157                        if (*p2 == '"') { 
     158                                *p2 = 0; 
     159                                break; 
     160                        } 
     161                        memmove(p2, p2 + 1, strlen(p2)); 
     162                } 
     163                if (!p2) { 
     164                        conf_warning("invalid string found"); 
     165                        return 1; 
     166                } 
     167                /* fall through */ 
     168        case S_INT: 
     169        case S_HEX: 
     170        done: 
     171                if (sym_string_valid(sym, p)) { 
     172                        sym->def[def].val = strdup(p); 
     173                        sym->flags |= def_flags; 
     174                } else { 
     175                        conf_warning("symbol value '%s' invalid for %s", p, sym->name); 
     176                        return 1; 
     177                } 
     178                break; 
     179        default: 
     180                ; 
     181        } 
     182        return 0; 
     183} 
     184 
     185#define LINE_GROWTH 16 
     186static int add_byte(int c, char **lineptr, size_t slen, size_t *n) 
     187{ 
     188        char *nline; 
     189        size_t new_size = slen + 1; 
     190        if (new_size > *n) { 
     191                new_size += LINE_GROWTH - 1; 
     192                new_size *= 2; 
     193                nline = realloc(*lineptr, new_size); 
     194                if (!nline) 
     195                        return -1; 
     196 
     197                *lineptr = nline; 
     198                *n = new_size; 
     199        } 
     200 
     201        (*lineptr)[slen] = c; 
     202 
     203        return 0; 
     204} 
     205 
     206static ssize_t compat_getline(char **lineptr, size_t *n, FILE *stream) 
     207{ 
     208        char *line = *lineptr; 
     209        size_t slen = 0; 
     210 
     211        for (;;) { 
     212                int c = getc(stream); 
     213 
     214                switch (c) { 
     215                case '\n': 
     216                        if (add_byte(c, &line, slen, n) < 0) 
     217                                goto e_out; 
     218                        slen++; 
     219                        /* fall through */ 
     220                case EOF: 
     221                        if (add_byte('\0', &line, slen, n) < 0) 
     222                                goto e_out; 
     223                        *lineptr = line; 
     224                        if (slen == 0) 
     225                                return -1; 
     226                        return slen; 
     227                default: 
     228                        if (add_byte(c, &line, slen, n) < 0) 
     229                                goto e_out; 
     230                        slen++; 
     231                } 
     232        } 
     233 
     234e_out: 
     235        line[slen-1] = '\0'; 
     236        *lineptr = line; 
     237        return -1; 
     238} 
     239 
     240void conf_reset(int def) 
    89241{ 
    90242        struct symbol *sym; 
    91         int i; 
    92  
     243        int i, def_flags; 
     244 
     245        def_flags = SYMBOL_DEF << def; 
    93246        for_all_symbols(i, sym) { 
    94                 sym->flags |= SYMBOL_NEW | SYMBOL_CHANGED; 
     247                sym->flags |= SYMBOL_CHANGED; 
     248                sym->flags &= ~(def_flags|SYMBOL_VALID); 
    95249                if (sym_is_choice(sym)) 
    96                         sym->flags &= ~SYMBOL_NEW; 
    97                 sym->flags &= ~SYMBOL_VALID; 
     250                        sym->flags |= def_flags; 
    98251                switch (sym->type) { 
    99252                case S_INT: 
    100253                case S_HEX: 
    101254                case S_STRING: 
    102                         if (sym->user.val) 
    103                                 free(sym->user.val); 
     255                        if (sym->def[def].val) 
     256                                free(sym->def[def].val); 
     257                        /* fall through */ 
    104258                default: 
    105                         sym->user.val = NULL; 
    106                         sym->user.tri = no; 
    107                 } 
    108         } 
    109         conf_read_simple(NULL, 0); 
    110 } 
    111  
    112 int conf_read_file(FILE *in, struct symbol *sym){ 
    113         char line[1024]; 
     259                        sym->def[def].val = NULL; 
     260                        sym->def[def].tri = no; 
     261                } 
     262        } 
     263} 
     264 
     265int conf_read_simple(const char *name, int def) 
     266{ 
     267        FILE *in = NULL; 
     268        char   *line = NULL; 
     269        size_t  line_asize = 0; 
    114270        char *p, *p2; 
    115  
    116         while (fgets(line, sizeof(line), in)) { 
     271        struct symbol *sym; 
     272        int def_flags; 
     273 
     274        if (name) { 
     275                in = zconf_fopen(name); 
     276        } else { 
     277                struct property *prop; 
     278 
     279                name = conf_get_configname(); 
     280                in = zconf_fopen(name); 
     281                if (in) 
     282                        goto load; 
     283                sym_add_change_count(1); 
     284                if (!sym_defconfig_list) { 
     285                        if (modules_sym) 
     286                                sym_calc_value(modules_sym); 
     287                        return 1; 
     288                } 
     289 
     290                for_all_defaults(sym_defconfig_list, prop) { 
     291                        if (expr_calc_value(prop->visible.expr) == no || 
     292                            prop->expr->type != E_SYMBOL) 
     293                                continue; 
     294                        name = conf_expand_value(prop->expr->left.sym->name); 
     295                        in = zconf_fopen(name); 
     296                        if (in) { 
     297                                conf_message(_("using defaults found in %s"), 
     298                                         name); 
     299                                goto load; 
     300                        } 
     301                } 
     302        } 
     303        if (!in) 
     304                return 1; 
     305 
     306load: 
     307        conf_filename = name; 
     308        conf_lineno = 0; 
     309        conf_warnings = 0; 
     310        conf_unsaved = 0; 
     311 
     312        def_flags = SYMBOL_DEF << def; 
     313        conf_reset(def); 
     314 
     315        while (compat_getline(&line, &line_asize, in) != -1) { 
    117316                conf_lineno++; 
    118317                sym = NULL; 
    119                 switch (line[0]) { 
    120                 case '#': 
    121                         if (memcmp(line + 2, "CONFIG_", 7)) 
     318                if (line[0] == '#') { 
     319                        if (memcmp(line + 2, CONFIG_, strlen(CONFIG_))) 
    122320                                continue; 
    123                         p = strchr(line + 9, ' '); 
     321                        p = strchr(line + 2 + strlen(CONFIG_), ' '); 
    124322                        if (!p) 
    125323                                continue; 
     
    127325                        if (strncmp(p, "is not set", 10)) 
    128326                                continue; 
    129                         sym = sym_find(line + 9); 
    130                         if (!sym) { 
    131                                 //conf_warning("trying to assign nonexistent symbol %s", line + 9); 
    132                                 break; 
    133                         } /*else if (!(sym->flags & SYMBOL_NEW)) { 
    134                                 //conf_warning("trying to reassign symbol %s", sym->name); 
    135                                 break; 
    136                         }*/ 
     327                        if (def == S_DEF_USER) { 
     328                                sym = sym_find(line + 2 + strlen(CONFIG_)); 
     329                                if (!sym) { 
     330                                        sym_add_change_count(1); 
     331                                        goto setsym; 
     332                                } 
     333                        } else { 
     334                                sym = sym_lookup(line + 2 + strlen(CONFIG_), 0); 
     335                                if (sym->type == S_UNKNOWN) 
     336                                        sym->type = S_BOOLEAN; 
     337                        } 
    137338                        switch (sym->type) { 
    138339                        case S_BOOLEAN: 
    139340                        case S_TRISTATE: 
    140                                 sym->user.tri = no; 
    141                                 sym->flags &= ~SYMBOL_NEW; 
     341                                sym->def[def].tri = no; 
     342                                sym->flags |= def_flags; 
    142343                                break; 
    143344                        default: 
    144345                                ; 
    145346                        } 
    146                         break; 
    147                 case 'C': 
    148                         if (memcmp(line, "CONFIG_", 7)) { 
    149                                 conf_warning("unexpected data"); 
    150                                 continue; 
    151                         } 
    152                         p = strchr(line + 7, '='); 
     347                } else if (memcmp(line, CONFIG_, strlen(CONFIG_)) == 0) { 
     348                        p = strchr(line + strlen(CONFIG_), '='); 
    153349                        if (!p) 
    154350                                continue; 
    155351                        *p++ = 0; 
    156352                        p2 = strchr(p, '\n'); 
    157                         if (p2) 
    158                                 *p2 = 0; 
    159                         sym = sym_find(line + 7); 
    160                         if (!sym) { 
    161                                 //conf_warning("trying to assign nonexistent symbol %s", line + 7); 
    162                                 break; 
    163                         } /*else if (!(sym->flags & SYMBOL_NEW)) { 
    164                                 conf_warning("trying to reassign symbol %s", sym->name); 
    165                                 break; 
    166                         }*/ 
    167                         switch (sym->type) { 
    168                         case S_TRISTATE: 
    169                                 if (p[0] == 'm') { 
    170                                         sym->user.tri = mod; 
    171                                         sym->flags &= ~SYMBOL_NEW; 
    172                                         break; 
     353                        if (p2) { 
     354                                *p2-- = 0; 
     355                                if (*p2 == '\r') 
     356                                        *p2 = 0; 
     357                        } 
     358                        if (def == S_DEF_USER) { 
     359                                sym = sym_find(line + strlen(CONFIG_)); 
     360                                if (!sym) { 
     361                                        sym_add_change_count(1); 
     362                                        goto setsym; 
    173363                                } 
    174                         case S_BOOLEAN: 
    175                                 if (p[0] == 'y') { 
    176                                         sym->user.tri = yes; 
    177                                         sym->flags &= ~SYMBOL_NEW; 
    178                                         break; 
    179                                 } 
    180                                 if (p[0] == 'n') { 
    181                                         sym->user.tri = no; 
    182                                         sym->flags &= ~SYMBOL_NEW; 
    183                                         break; 
    184                                 } 
    185                                 conf_warning("symbol value '%s' invalid for %s", p, sym->name); 
    186                                 break; 
    187                         case S_STRING: 
    188                                 if (*p++ != '"') 
    189                                         break; 
    190                                 for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) { 
    191                                         if (*p2 == '"') { 
    192                                                 *p2 = 0; 
    193                                                 break; 
    194                                         } 
    195                                         memmove(p2, p2 + 1, strlen(p2)); 
    196                                 } 
    197                                 if (!p2) { 
    198                                         conf_warning("invalid string found"); 
    199                                         continue; 
    200                                 } 
    201                         case S_INT: 
    202                         case S_HEX: 
    203                                 if (sym_string_valid(sym, p)) { 
    204                                         sym->user.val = strdup(p); 
    205                                         sym->flags &= ~SYMBOL_NEW; 
    206                                 } else { 
    207                                         conf_warning("symbol value '%s' invalid for %s", p, sym->name); 
    208                                         continue; 
    209                                 } 
    210                                 break; 
    211                         default: 
    212                                 ; 
    213                         } 
    214                         break; 
    215                 case '\n': 
    216                         break; 
    217                 default: 
    218                         conf_warning("unexpected data"); 
     364                        } else { 
     365                                sym = sym_lookup(line + strlen(CONFIG_), 0); 
     366                                if (sym->type == S_UNKNOWN) 
     367                                        sym->type = S_OTHER; 
     368                        } 
     369                        if (conf_set_sym_val(sym, def, def_flags, p)) 
     370                                continue; 
     371                } else { 
     372                        if (line[0] != '\r' && line[0] != '\n') 
     373                                conf_warning("unexpected data"); 
    219374                        continue; 
    220375                } 
     376setsym: 
    221377                if (sym && sym_is_choice_value(sym)) { 
    222378                        struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym)); 
    223                         switch (sym->user.tri) { 
     379                        switch (sym->def[def].tri) { 
    224380                        case no: 
    225381                                break; 
    226382                        case mod: 
    227                                 if (cs->user.tri == yes) { 
     383                                if (cs->def[def].tri == yes) { 
    228384                                        conf_warning("%s creates inconsistent choice state", sym->name); 
    229                                         cs->flags |= SYMBOL_NEW; 
     385                                        cs->flags &= ~def_flags; 
    230386                                } 
    231387                                break; 
    232388                        case yes: 
    233                                 cs->user.val = sym; 
    234                                 break; 
    235                         } 
    236                         cs->user.tri = E_OR(cs->user.tri, sym->user.tri); 
    237                 } 
    238         } 
     389                                if (cs->def[def].tri != no) 
     390                                        conf_warning("override: %s changes choice state", sym->name); 
     391                                cs->def[def].val = sym; 
     392                                break; 
     393                        } 
     394                        cs->def[def].tri = EXPR_OR(cs->def[def].tri, sym->def[def].tri); 
     395                } 
     396        } 
     397        free(line); 
    239398        fclose(in); 
    240399 
     400        if (modules_sym) 
     401                sym_calc_value(modules_sym); 
    241402        return 0; 
    242403} 
    243404 
    244 int conf_read_simple(const char *name, int load_config) 
    245 { 
    246         FILE *in = NULL; 
    247         FILE *defaults = NULL; 
     405int conf_read(const char *name) 
     406{ 
    248407        struct symbol *sym; 
    249408        int i; 
    250         char *home_dir = getenv("HOME"); 
    251         char *default_config_path = NULL; 
    252          
    253         if(home_dir){ 
    254                         default_config_path = malloc(strlen(home_dir) + sizeof(LOCAL_BUILD_SETTINGS) + 1); 
    255                         sprintf(default_config_path, "%s%s", home_dir, LOCAL_BUILD_SETTINGS); 
    256                         defaults = zconf_fopen(default_config_path); 
    257                         if(defaults) 
    258                                         printf("# using buildsystem predefines from %s\n", default_config_path); 
    259                         free(default_config_path); 
    260         } 
    261          
    262         if(load_config){ 
    263                 if (name) { 
    264                         in = zconf_fopen(name); 
    265                 } else { 
    266                         const char **names = conf_confnames; 
    267                         while ((name = *names++)) { 
    268                                 name = conf_expand_value(name); 
    269                                 in = zconf_fopen(name); 
    270                                 if (in) { 
    271                                         printf(_("#\n" 
    272                                                  "# using defaults found in %s\n" 
    273                                                  "#\n"), name); 
    274                                         break; 
    275                                 } 
    276                         } 
    277                 } 
    278         } 
    279  
    280         if (!in && !defaults) 
    281                 return 1; 
    282  
    283         conf_filename = name; 
    284         conf_lineno = 0; 
    285         conf_warnings = 0; 
    286         conf_unsaved = 0; 
    287          
    288         for_all_symbols(i, sym) { 
    289                 sym->flags |= SYMBOL_NEW | SYMBOL_CHANGED; 
    290                 if (sym_is_choice(sym)) 
    291                         sym->flags &= ~SYMBOL_NEW; 
    292                 sym->flags &= ~SYMBOL_VALID; 
    293                 switch (sym->type) { 
    294                 case S_INT: 
    295                 case S_HEX: 
    296                 case S_STRING: 
    297                         if (sym->user.val) 
    298                                 free(sym->user.val); 
    299                 default: 
    300                         sym->user.val = NULL; 
    301                         sym->user.tri = no; 
    302                 } 
    303         } 
    304  
    305         if(defaults) 
    306                 conf_read_file(defaults, sym); 
    307          
    308         if(in) 
    309                 conf_read_file(in, sym); 
    310          
    311         if (modules_sym) 
    312                 sym_calc_value(modules_sym); 
    313  
    314         return 0;        
    315 } 
    316  
    317 int conf_read(const char *name) 
    318 { 
    319         struct symbol *sym; 
    320         struct property *prop; 
    321         struct expr *e; 
    322         int i; 
    323  
    324         if (conf_read_simple(name, 1)) 
     409 
     410        sym_set_change_count(0); 
     411 
     412        if (conf_read_simple(name, S_DEF_USER)) 
    325413                return 1; 
    326414 
     
    328416                sym_calc_value(sym); 
    329417                if (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO)) 
    330                         goto sym_ok; 
     418                        continue; 
    331419                if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) { 
    332420                        /* check that calculated value agrees with saved value */ 
     
    334422                        case S_BOOLEAN: 
    335423                        case S_TRISTATE: 
    336                                 if (sym->user.tri != sym_get_tristate_value(sym)) 
     424                                if (sym->def[S_DEF_USER].tri != sym_get_tristate_value(sym)) 
    337425                                        break; 
    338426                                if (!sym_is_choice(sym)) 
    339                                         goto sym_ok; 
     427                                        continue; 
     428                                /* fall through */ 
    340429                        default: 
    341                                 if (!strcmp(sym->curr.val, sym->user.val)) 
    342                                         goto sym_ok; 
     430                                if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val)) 
     431                                        continue; 
    343432                                break; 
    344433                        } 
    345434                } else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE)) 
    346435                        /* no previous value and not saved */ 
    347                         goto sym_ok; 
     436                        continue; 
    348437                conf_unsaved++; 
    349438                /* maybe print value in verbose mode... */ 
    350         sym_ok: 
     439        } 
     440 
     441        for_all_symbols(i, sym) { 
    351442                if (sym_has_value(sym) && !sym_is_choice_value(sym)) { 
    352                         if (sym->visible == no) 
    353                                 sym->flags |= SYMBOL_NEW; 
     443                        /* Reset values of generates values, so they'll appear 
     444                         * as new, if they should become visible, but that 
     445                         * doesn't quite work if the Kconfig and the saved 
     446                         * configuration disagree. 
     447                         */ 
     448                        if (sym->visible == no && !conf_unsaved) 
     449                                sym->flags &= ~SYMBOL_DEF_USER; 
    354450                        switch (sym->type) { 
    355451                        case S_STRING: 
    356452                        case S_INT: 
    357453                        case S_HEX: 
    358                                 if (!sym_string_within_range(sym, sym->user.val)) { 
    359                                         sym->flags |= SYMBOL_NEW; 
    360                                         sym->flags &= ~SYMBOL_VALID; 
     454                                /* Reset a string value if it's out of range */ 
     455                                if (sym_string_within_range(sym, sym->def[S_DEF_USER].val)) 
     456                                        break; 
     457                                sym->flags &= ~(SYMBOL_VALID|SYMBOL_DEF_USER); 
     458                                conf_unsaved++; 
     459                                break; 
     460                        default: 
     461                                break; 
     462                        } 
     463                } 
     464        } 
     465 
     466        sym_add_change_count(conf_warnings || conf_unsaved); 
     467 
     468        return 0; 
     469} 
     470 
     471/* 
     472 * Kconfig configuration printer 
     473 * 
     474 * This printer is used when generating the resulting configuration after 
     475 * kconfig invocation and `defconfig' files. Unset symbol might be omitted by 
     476 * passing a non-NULL argument to the printer. 
     477 * 
     478 */ 
     479static void 
     480kconfig_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) 
     481{ 
     482 
     483        switch (sym->type) { 
     484        case S_BOOLEAN: 
     485        case S_TRISTATE: 
     486                if (*value == 'n') { 
     487                        bool skip_unset = (arg != NULL); 
     488 
     489                        if (!skip_unset) 
     490                                fprintf(fp, "# %s%s is not set\n", 
     491                                    CONFIG_, sym->name); 
     492                        return; 
     493                } 
     494                break; 
     495        default: 
     496                break; 
     497        } 
     498 
     499        fprintf(fp, "%s%s=%s\n", CONFIG_, sym->name, value); 
     500} 
     501 
     502static void 
     503kconfig_print_comment(FILE *fp, const char *value, void *arg) 
     504{ 
     505        const char *p = value; 
     506        size_t l; 
     507 
     508        for (;;) { 
     509                l = strcspn(p, "\n"); 
     510                fprintf(fp, "#"); 
     511                if (l) { 
     512                        fprintf(fp, " "); 
     513                        xfwrite(p, l, 1, fp); 
     514                        p += l; 
     515                } 
     516                fprintf(fp, "\n"); 
     517                if (*p++ == '\0') 
     518                        break; 
     519        } 
     520} 
     521 
     522static struct conf_printer kconfig_printer_cb = 
     523{ 
     524        .print_symbol = kconfig_print_symbol, 
     525        .print_comment = kconfig_print_comment, 
     526}; 
     527 
     528/* 
     529 * Header printer 
     530 * 
     531 * This printer is used when generating the `include/generated/autoconf.h' file. 
     532 */ 
     533static void 
     534header_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) 
     535{ 
     536 
     537        switch (sym->type) { 
     538        case S_BOOLEAN: 
     539        case S_TRISTATE: { 
     540                const char *suffix = ""; 
     541 
     542                switch (*value) { 
     543                case 'n': 
     544                        break; 
     545                case 'm': 
     546                        suffix = "_MODULE"; 
     547                        /* fall through */ 
     548                default: 
     549                        fprintf(fp, "#define %s%s%s 1\n", 
     550                            CONFIG_, sym->name, suffix); 
     551                } 
     552                break; 
     553        } 
     554        case S_HEX: { 
     555                const char *prefix = ""; 
     556 
     557                if (value[0] != '0' || (value[1] != 'x' && value[1] != 'X')) 
     558                        prefix = "0x"; 
     559                fprintf(fp, "#define %s%s %s%s\n", 
     560                    CONFIG_, sym->name, prefix, value); 
     561                break; 
     562        } 
     563        case S_STRING: 
     564        case S_INT: 
     565                fprintf(fp, "#define %s%s %s\n", 
     566                    CONFIG_, sym->name, value); 
     567                break; 
     568        default: 
     569                break; 
     570        } 
     571 
     572} 
     573 
     574static void 
     575header_print_comment(FILE *fp, const char *value, void *arg) 
     576{ 
     577        const char *p = value; 
     578        size_t l; 
     579 
     580        fprintf(fp, "/*\n"); 
     581        for (;;) { 
     582                l = strcspn(p, "\n"); 
     583                fprintf(fp, " *"); 
     584                if (l) { 
     585                        fprintf(fp, " "); 
     586                        xfwrite(p, l, 1, fp); 
     587                        p += l; 
     588                } 
     589                fprintf(fp, "\n"); 
     590                if (*p++ == '\0') 
     591                        break; 
     592        } 
     593        fprintf(fp, " */\n"); 
     594} 
     595 
     596static struct conf_printer header_printer_cb = 
     597{ 
     598        .print_symbol = header_print_symbol, 
     599        .print_comment = header_print_comment, 
     600}; 
     601 
     602/* 
     603 * Tristate printer 
     604 * 
     605 * This printer is used when generating the `include/config/tristate.conf' file. 
     606 */ 
     607static void 
     608tristate_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) 
     609{ 
     610 
     611        if (sym->type == S_TRISTATE && *value != 'n') 
     612                fprintf(fp, "%s%s=%c\n", CONFIG_, sym->name, (char)toupper(*value)); 
     613} 
     614 
     615static struct conf_printer tristate_printer_cb = 
     616{ 
     617        .print_symbol = tristate_print_symbol, 
     618        .print_comment = kconfig_print_comment, 
     619}; 
     620 
     621static void conf_write_symbol(FILE *fp, struct symbol *sym, 
     622                              struct conf_printer *printer, void *printer_arg) 
     623{ 
     624        const char *str; 
     625 
     626        switch (sym->type) { 
     627        case S_OTHER: 
     628        case S_UNKNOWN: 
     629                break; 
     630        case S_STRING: 
     631                str = sym_get_string_value(sym); 
     632                str = sym_escape_string_value(str); 
     633                printer->print_symbol(fp, sym, str, printer_arg); 
     634                free((void *)str); 
     635                break; 
     636        default: 
     637                str = sym_get_string_value(sym); 
     638                printer->print_symbol(fp, sym, str, printer_arg); 
     639        } 
     640} 
     641 
     642static void 
     643conf_write_heading(FILE *fp, struct conf_printer *printer, void *printer_arg) 
     644{ 
     645        char buf[256]; 
     646 
     647        snprintf(buf, sizeof(buf), 
     648            "\n" 
     649            "Automatically generated file; DO NOT EDIT.\n" 
     650            "%s\n", 
     651            rootmenu.prompt->text); 
     652 
     653        printer->print_comment(fp, buf, printer_arg); 
     654} 
     655 
     656/* 
     657 * Write out a minimal config. 
     658 * All values that has default values are skipped as this is redundant. 
     659 */ 
     660int conf_write_defconfig(const char *filename) 
     661{ 
     662        struct symbol *sym; 
     663        struct menu *menu; 
     664        FILE *out; 
     665 
     666        out = fopen(filename, "w"); 
     667        if (!out) 
     668                return 1; 
     669 
     670        sym_clear_all_valid(); 
     671 
     672        /* Traverse all menus to find all relevant symbols */ 
     673        menu = rootmenu.list; 
     674 
     675        while (menu != NULL) 
     676        { 
     677                sym = menu->sym; 
     678                if (sym == NULL) { 
     679                        if (!menu_is_visible(menu)) 
     680                                goto next_menu; 
     681                } else if (!sym_is_choice(sym)) { 
     682                        sym_calc_value(sym); 
     683                        if (!(sym->flags & SYMBOL_WRITE)) 
     684                                goto next_menu; 
     685                        sym->flags &= ~SYMBOL_WRITE; 
     686                        /* If we cannot change the symbol - skip */ 
     687                        if (!sym_is_changable(sym)) 
     688                                goto next_menu; 
     689                        /* If symbol equals to default value - skip */ 
     690                        if (strcmp(sym_get_string_value(sym), sym_get_string_default(sym)) == 0) 
     691                                goto next_menu; 
     692 
     693                        /* 
     694                         * If symbol is a choice value and equals to the 
     695                         * default for a choice - skip. 
     696                         * But only if value is bool and equal to "y" and 
     697                         * choice is not "optional". 
     698                         * (If choice is "optional" then all values can be "n") 
     699                         */ 
     700                        if (sym_is_choice_value(sym)) { 
     701                                struct symbol *cs; 
     702                                struct symbol *ds; 
     703 
     704                                cs = prop_get_symbol(sym_get_choice_prop(sym)); 
     705                                ds = sym_choice_default(cs); 
     706                                if (!sym_is_optional(cs) && sym == ds) { 
     707                                        if ((sym->type == S_BOOLEAN) && 
     708                                            sym_get_tristate_value(sym) == yes) 
     709                                                goto next_menu; 
    361710                                } 
    362                         default: 
    363                                 break; 
    364                         } 
    365                 } 
    366                 if (!sym_is_choice(sym)) 
    367                         continue; 
    368                 prop = sym_get_choice_prop(sym); 
    369                 for (e = prop->expr; e; e = e->left.expr) 
    370                         if (e->right.sym->visible != no) 
    371                                 sym->flags |= e->right.sym->flags & SYMBOL_NEW; 
    372         } 
    373  
    374         sym_change_count = conf_warnings && conf_unsaved; 
    375  
     711                        } 
     712                        conf_write_symbol(out, sym, &kconfig_printer_cb, NULL); 
     713                } 
     714next_menu: 
     715                if (menu->list != NULL) { 
     716                        menu = menu->list; 
     717                } 
     718                else if (menu->next != NULL) { 
     719                        menu = menu->next; 
     720                } else { 
     721                        while ((menu = menu->parent)) { 
     722                                if (menu->next != NULL) { 
     723                                        menu = menu->next; 
     724                                        break; 
     725                                } 
     726                        } 
     727                } 
     728        } 
     729        fclose(out); 
    376730        return 0; 
    377731} 
     
    383737        struct menu *menu; 
    384738        const char *basename; 
    385         char dirname[128], tmpname[128], newname[128]; 
    386         int type, l; 
    387739        const char *str; 
    388         time_t now; 
    389         int use_timestamp = 1; 
     740        char dirname[PATH_MAX+1], tmpname[PATH_MAX+1], newname[PATH_MAX+1]; 
    390741        char *env; 
    391742 
     
    398749                        strcpy(dirname, name); 
    399750                        strcat(dirname, "/"); 
    400                         basename = conf_def_filename; 
     751                        basename = conf_get_configname(); 
    401752                } else if ((slash = strrchr(name, '/'))) { 
    402753                        int size = slash - name + 1; 
     
    406757                                basename = slash + 1; 
    407758                        else 
    408                                 basename = conf_def_filename; 
     759                                basename = conf_get_configname(); 
    409760                } else 
    410761                        basename = name; 
    411762        } else 
    412                 basename = conf_def_filename; 
    413  
    414         sprintf(newname, "%s.tmpconfig.%d", dirname, (int)getpid()); 
    415         out = fopen(newname, "w"); 
     763                basename = conf_get_configname(); 
     764 
     765        sprintf(newname, "%s%s", dirname, basename); 
     766        env = getenv("KCONFIG_OVERWRITECONFIG"); 
     767        if (!env || !*env) { 
     768                sprintf(tmpname, "%s.tmpconfig.%d", dirname, (int)getpid()); 
     769                out = fopen(tmpname, "w"); 
     770        } else { 
     771                *tmpname = 0; 
     772                out = fopen(newname, "w"); 
     773        } 
    416774        if (!out) 
    417775                return 1; 
    418         sym = sym_lookup("OPENWRTVERSION", 0); 
    419         sym_calc_value(sym); 
    420         time(&now); 
    421         env = getenv("KCONFIG_NOTIMESTAMP"); 
    422         if (env && *env) 
    423                 use_timestamp = 0; 
    424  
    425         fprintf(out, _("#\n" 
    426                        "# Automatically generated make config: don't edit\n" 
    427                        "# OpenWrt version: %s\n" 
    428                        "%s%s" 
    429                        "#\n"), 
    430                      sym_get_string_value(sym), 
    431                      use_timestamp ? "# " : "", 
    432                      use_timestamp ? ctime(&now) : ""); 
    433  
    434         if (!sym_change_count) 
     776 
     777        conf_write_heading(out, &kconfig_printer_cb, NULL); 
     778 
     779        if (!conf_get_changed()) 
    435780                sym_clear_all_valid(); 
    436781 
     
    451796                                goto next; 
    452797                        sym->flags &= ~SYMBOL_WRITE; 
    453                         type = sym->type; 
    454                         if (type == S_TRISTATE) { 
    455                                 sym_calc_value(modules_sym); 
    456 /* tristate always enabled */ 
    457 #if 0 
    458                                 if (modules_sym->curr.tri == no) 
    459                                         type = S_BOOLEAN; 
    460 #endif 
    461                         } 
    462                         switch (type) { 
    463                         case S_BOOLEAN: 
    464                         case S_TRISTATE: 
    465                                 switch (sym_get_tristate_value(sym)) { 
    466                                 case no: 
    467                                         fprintf(out, "# CONFIG_%s is not set\n", sym->name); 
    468                                         break; 
    469                                 case mod: 
    470                                         fprintf(out, "CONFIG_%s=m\n", sym->name); 
    471                                         break; 
    472                                 case yes: 
    473                                         fprintf(out, "CONFIG_%s=y\n", sym->name); 
    474                                         break; 
    475                                 } 
    476                                 break; 
    477                         case S_STRING: 
    478                                 // fix me 
    479                                 str = sym_get_string_value(sym); 
    480                                 fprintf(out, "CONFIG_%s=\"", sym->name); 
    481                                 do { 
    482                                         l = strcspn(str, "\"\\"); 
    483                                         if (l) { 
    484                                                 fwrite(str, l, 1, out); 
    485                                         } 
    486                                         str += l; 
    487                                         while (*str == '\\' || *str == '"') { 
    488                                                 fprintf(out, "\\%c", *str); 
    489                                                 str++; 
    490                                         } 
    491                                 } while (*str); 
    492                                 fputs("\"\n", out); 
    493                                 break; 
    494                         case S_HEX: 
    495                                 str = sym_get_string_value(sym); 
    496                                 if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) { 
    497                                         fprintf(out, "CONFIG_%s=%s\n", sym->name, str); 
    498                                         break; 
    499                                 } 
    500                         case S_INT: 
    501                                 str = sym_get_string_value(sym); 
    502                                 fprintf(out, "CONFIG_%s=%s\n", sym->name, str); 
    503                                 break; 
    504                         } 
    505                 } 
    506  
    507         next: 
     798 
     799                        conf_write_symbol(out, sym, &kconfig_printer_cb, NULL); 
     800                } 
     801 
     802next: 
    508803                if (menu->list) { 
    509804                        menu = menu->list; 
     
    520815        } 
    521816        fclose(out); 
    522         if (!name || basename != conf_def_filename) { 
    523                 if (!name) 
    524                         name = conf_def_filename; 
    525                 sprintf(tmpname, "%s.old", name); 
    526                 rename(name, tmpname); 
    527         } 
    528         sprintf(tmpname, "%s%s", dirname, basename); 
    529         if (rename(newname, tmpname)) 
    530                 return 1; 
    531  
    532         sym_change_count = 0; 
     817 
     818        if (*tmpname) { 
     819                strcat(dirname, basename); 
     820                strcat(dirname, ".old"); 
     821                rename(newname, dirname); 
     822                if (rename(tmpname, newname)) 
     823                        return 1; 
     824        } 
     825 
     826        conf_message(_("configuration written to %s"), newname); 
     827 
     828        sym_set_change_count(0); 
    533829 
    534830        return 0; 
    535831} 
     832 
     833static int conf_split_config(void) 
     834{ 
     835        const char *name; 
     836        char path[PATH_MAX+1]; 
     837        char *s, *d, c; 
     838        struct symbol *sym; 
     839        struct stat sb; 
     840        int res, i, fd; 
     841 
     842        name = conf_get_autoconfig_name(); 
     843        conf_read_simple(name, S_DEF_AUTO); 
     844 
     845        if (chdir("include/config")) 
     846                return 1; 
     847 
     848        res = 0; 
     849        for_all_symbols(i, sym) { 
     850                sym_calc_value(sym); 
     851                if ((sym->flags & SYMBOL_AUTO) || !sym->name) 
     852                        continue; 
     853                if (sym->flags & SYMBOL_WRITE) { 
     854                        if (sym->flags & SYMBOL_DEF_AUTO) { 
     855                                /* 
     856                                 * symbol has old and new value, 
     857                                 * so compare them... 
     858                                 */ 
     859                                switch (sym->type) { 
     860                                case S_BOOLEAN: 
     861                                case S_TRISTATE: 
     862                                        if (sym_get_tristate_value(sym) == 
     863                                            sym->def[S_DEF_AUTO].tri) 
     864                                                continue; 
     865                                        break; 
     866                                case S_STRING: 
     867                                case S_HEX: 
     868                                case S_INT: 
     869                                        if (!strcmp(sym_get_string_value(sym), 
     870                                                    sym->def[S_DEF_AUTO].val)) 
     871                                                continue; 
     872                                        break; 
     873                                default: 
     874                                        break; 
     875                                } 
     876                        } else { 
     877                                /* 
     878                                 * If there is no old value, only 'no' (unset) 
     879                                 * is allowed as new value. 
     880                                 */ 
     881                                switch (sym->type) { 
     882                                case S_BOOLEAN: 
     883                                case S_TRISTATE: 
     884                                        if (sym_get_tristate_value(sym) == no) 
     885                                                continue; 
     886                                        break; 
     887                                default: 
     888                                        break; 
     889                                } 
     890                        } 
     891                } else if (!(sym->flags & SYMBOL_DEF_AUTO)) 
     892                        /* There is neither an old nor a new value. */ 
     893                        continue; 
     894                /* else 
     895                 *      There is an old value, but no new value ('no' (unset) 
     896                 *      isn't saved in auto.conf, so the old value is always 
     897                 *      different from 'no'). 
     898                 */ 
     899 
     900                /* Replace all '_' and append ".h" */ 
     901                s = sym->name; 
     902                d = path; 
     903                while ((c = *s++)) { 
     904                        c = tolower(c); 
     905                        *d++ = (c == '_') ? '/' : c; 
     906                } 
     907                strcpy(d, ".h"); 
     908 
     909                /* Assume directory path already exists. */ 
     910                fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); 
     911                if (fd == -1) { 
     912                        if (errno != ENOENT) { 
     913                                res = 1; 
     914                                break; 
     915                        } 
     916                        /* 
     917                         * Create directory components, 
     918                         * unless they exist already. 
     919                         */ 
     920                        d = path; 
     921                        while ((d = strchr(d, '/'))) { 
     922                                *d = 0; 
     923                                if (stat(path, &sb) && mkdir(path, 0755)) { 
     924                                        res = 1; 
     925                                        goto out; 
     926                                } 
     927                                *d++ = '/'; 
     928                        } 
     929                        /* Try it again. */ 
     930                        fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); 
     931                        if (fd == -1) { 
     932                                res = 1; 
     933                                break; 
     934                        } 
     935                } 
     936                close(fd); 
     937        } 
     938out: 
     939        if (chdir("../..")) 
     940                return 1; 
     941 
     942        return res; 
     943} 
     944 
     945int conf_write_autoconf(void) 
     946{ 
     947        struct symbol *sym; 
     948        const char *name; 
     949        FILE *out, *tristate, *out_h; 
     950        int i; 
     951 
     952        sym_clear_all_valid(); 
     953 
     954        file_write_dep("include/config/auto.conf.cmd"); 
     955 
     956        if (conf_split_config()) 
     957                return 1; 
     958 
     959        out = fopen(".tmpconfig", "w"); 
     960        if (!out) 
     961                return 1; 
     962 
     963        tristate = fopen(".tmpconfig_tristate", "w"); 
     964        if (!tristate) { 
     965                fclose(out); 
     966                return 1; 
     967        } 
     968 
     969        out_h = fopen(".tmpconfig.h", "w"); 
     970        if (!out_h) { 
     971                fclose(out); 
     972                fclose(tristate); 
     973                return 1; 
     974        } 
     975 
     976        conf_write_heading(out, &kconfig_printer_cb, NULL); 
     977 
     978        conf_write_heading(tristate, &tristate_printer_cb, NULL); 
     979 
     980        conf_write_heading(out_h, &header_printer_cb, NULL); 
     981 
     982        for_all_symbols(i, sym) { 
     983                sym_calc_value(sym); 
     984                if (!(sym->flags & SYMBOL_WRITE) || !sym->name) 
     985                        continue; 
     986 
     987                /* write symbol to auto.conf, tristate and header files */ 
     988                conf_write_symbol(out, sym, &kconfig_printer_cb, (void *)1); 
     989 
     990                conf_write_symbol(tristate, sym, &tristate_printer_cb, (void *)1); 
     991 
     992                conf_write_symbol(out_h, sym, &header_printer_cb, NULL); 
     993        } 
     994        fclose(out); 
     995        fclose(tristate); 
     996        fclose(out_h); 
     997 
     998        name = getenv("KCONFIG_AUTOHEADER"); 
     999        if (!name) 
     1000                name = "include/generated/autoconf.h"; 
     1001        if (rename(".tmpconfig.h", name)) 
     1002                return 1; 
     1003        name = getenv("KCONFIG_TRISTATE"); 
     1004        if (!name) 
     1005                name = "include/config/tristate.conf"; 
     1006        if (rename(".tmpconfig_tristate", name)) 
     1007                return 1; 
     1008        name = conf_get_autoconfig_name(); 
     1009        /* 
     1010         * This must be the last step, kbuild has a dependency on auto.conf 
     1011         * and this marks the successful completion of the previous steps. 
     1012         */ 
     1013        if (rename(".tmpconfig", name)) 
     1014                return 1; 
     1015 
     1016        return 0; 
     1017} 
     1018 
     1019static int sym_change_count; 
     1020static void (*conf_changed_callback)(void); 
     1021 
     1022void sym_set_change_count(int count) 
     1023{ 
     1024        int _sym_change_count = sym_change_count; 
     1025        sym_change_count = count; 
     1026        if (conf_changed_callback && 
     1027            (bool)_sym_change_count != (bool)count) 
     1028                conf_changed_callback(); 
     1029} 
     1030 
     1031void sym_add_change_count(int count) 
     1032{ 
     1033        sym_set_change_count(count + sym_change_count); 
     1034} 
     1035 
     1036bool conf_get_changed(void) 
     1037{ 
     1038        return sym_change_count; 
     1039} 
     1040 
     1041void conf_set_changed_callback(void (*fn)(void)) 
     1042{ 
     1043        conf_changed_callback = fn; 
     1044} 
     1045 
     1046static void randomize_choice_values(struct symbol *csym) 
     1047{ 
     1048        struct property *prop; 
     1049        struct symbol *sym; 
     1050        struct expr *e; 
     1051        int cnt, def; 
     1052 
     1053        /* 
     1054         * If choice is mod then we may have more items selected 
     1055         * and if no then no-one. 
     1056         * In both cases stop. 
     1057         */ 
     1058        if (csym->curr.tri != yes) 
     1059                return; 
     1060 
     1061        prop = sym_get_choice_prop(csym); 
     1062 
     1063        /* count entries in choice block */ 
     1064        cnt = 0; 
     1065        expr_list_for_each_sym(prop->expr, e, sym) 
     1066                cnt++; 
     1067 
     1068        /* 
     1069         * find a random value and set it to yes, 
     1070         * set the rest to no so we have only one set 
     1071         */ 
     1072        def = (rand() % cnt); 
     1073 
     1074        cnt = 0; 
     1075        expr_list_for_each_sym(prop->expr, e, sym) { 
     1076                if (def == cnt++) { 
     1077                        sym->def[S_DEF_USER].tri = yes; 
     1078                        csym->def[S_DEF_USER].val = sym; 
     1079                } 
     1080                else { 
     1081                        sym->def[S_DEF_USER].tri = no; 
     1082                } 
     1083        } 
     1084        csym->flags |= SYMBOL_DEF_USER; 
     1085        /* clear VALID to get value calculated */ 
     1086        csym->flags &= ~(SYMBOL_VALID); 
     1087} 
     1088 
     1089static void set_all_choice_values(struct symbol *csym) 
     1090{ 
     1091        struct property *prop; 
     1092        struct symbol *sym; 
     1093        struct expr *e; 
     1094 
     1095        prop = sym_get_choice_prop(csym); 
     1096 
     1097        /* 
     1098         * Set all non-assinged choice values to no 
     1099         */ 
     1100        expr_list_for_each_sym(prop->expr, e, sym) { 
     1101                if (!sym_has_value(sym)) 
     1102                        sym->def[S_DEF_USER].tri = no; 
     1103        } 
     1104        csym->flags |= SYMBOL_DEF_USER; 
     1105        /* clear VALID to get value calculated */ 
     1106        csym->flags &= ~(SYMBOL_VALID); 
     1107} 
     1108 
     1109void conf_set_all_new_symbols(enum conf_def_mode mode) 
     1110{ 
     1111        struct symbol *sym, *csym; 
     1112        int i, cnt; 
     1113 
     1114        for_all_symbols(i, sym) { 
     1115                if (sym_has_value(sym)) 
     1116                        continue; 
     1117                switch (sym_get_type(sym)) { 
     1118                case S_BOOLEAN: 
     1119                case S_TRISTATE: 
     1120                        switch (mode) { 
     1121                        case def_yes: 
     1122                                sym->def[S_DEF_USER].tri = yes; 
     1123                                break; 
     1124                        case def_mod: 
     1125                                sym->def[S_DEF_USER].tri = mod; 
     1126                                break; 
     1127                        case def_no: 
     1128                                sym->def[S_DEF_USER].tri = no; 
     1129                                break; 
     1130                        case def_random: 
     1131                                cnt = sym_get_type(sym) == S_TRISTATE ? 3 : 2; 
     1132                                sym->def[S_DEF_USER].tri = (tristate)(rand() % cnt); 
     1133                                break; 
     1134                        default: 
     1135                                continue; 
     1136                        } 
     1137                        if (!(sym_is_choice(sym) && mode == def_random)) 
     1138                                sym->flags |= SYMBOL_DEF_USER; 
     1139                        break; 
     1140                default: 
     1141                        break; 
     1142                } 
     1143 
     1144        } 
     1145 
     1146        sym_clear_all_valid(); 
     1147 
     1148        /* 
     1149         * We have different type of choice blocks. 
     1150         * If curr.tri equals to mod then we can select several 
     1151         * choice symbols in one block. 
     1152         * In this case we do nothing. 
     1153         * If curr.tri equals yes then only one symbol can be 
     1154         * selected in a choice block and we set it to yes, 
     1155         * and the rest to no. 
     1156         */ 
     1157        for_all_symbols(i, csym) { 
     1158                if (sym_has_value(csym) || !sym_is_choice(csym)) 
     1159                        continue; 
     1160 
     1161                sym_calc_value(csym); 
     1162                if (mode == def_random) 
     1163                        randomize_choice_values(csym); 
     1164                else 
     1165                        set_all_choice_values(csym); 
     1166        } 
     1167} 
  • trunk/scripts/config/expr.c

    r28658 r36361  
    88#include <string.h> 
    99 
    10 #define LKC_DIRECT_LINK 
    1110#include "lkc.h" 
    1211 
     
    1514struct expr *expr_alloc_symbol(struct symbol *sym) 
    1615{ 
    17         struct expr *e = malloc(sizeof(*e)); 
    18         memset(e, 0, sizeof(*e)); 
     16        struct expr *e = xcalloc(1, sizeof(*e)); 
    1917        e->type = E_SYMBOL; 
    2018        e->left.sym = sym; 
     
    2422struct expr *expr_alloc_one(enum expr_type type, struct expr *ce) 
    2523{ 
    26         struct expr *e = malloc(sizeof(*e)); 
    27         memset(e, 0, sizeof(*e)); 
     24        struct expr *e = xcalloc(1, sizeof(*e)); 
    2825        e->type = type; 
    2926        e->left.expr = ce; 
     
    3330struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2) 
    3431{ 
    35         struct expr *e = malloc(sizeof(*e)); 
    36         memset(e, 0, sizeof(*e)); 
     32        struct expr *e = xcalloc(1, sizeof(*e)); 
    3733        e->type = type; 
    3834        e->left.expr = e1; 
     
    4339struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2) 
    4440{ 
    45         struct expr *e = malloc(sizeof(*e)); 
    46         memset(e, 0, sizeof(*e)); 
     41        struct expr *e = xcalloc(1, sizeof(*e)); 
    4742        e->type = type; 
    4843        e->left.sym = s1; 
     
    6560} 
    6661 
    67 struct expr *expr_copy(struct expr *org) 
     62struct expr *expr_copy(const struct expr *org) 
    6863{ 
    6964        struct expr *e; 
     
    7267                return NULL; 
    7368 
    74         e = malloc(sizeof(*org)); 
     69        e = xmalloc(sizeof(*org)); 
    7570        memcpy(e, org, sizeof(*org)); 
    7671        switch (org->type) { 
     
    8883        case E_AND: 
    8984        case E_OR: 
    90         case E_CHOICE: 
     85        case E_LIST: 
    9186                e->left.expr = expr_copy(org->left.expr); 
    9287                e->right.expr = expr_copy(org->right.expr); 
     
    218213                trans_count = old_count; 
    219214                return res; 
    220         case E_CHOICE: 
     215        case E_LIST: 
    221216        case E_RANGE: 
    222217        case E_NONE: 
     
    649644        case E_UNEQUAL: 
    650645        case E_SYMBOL: 
    651         case E_CHOICE: 
     646        case E_LIST: 
    652647                break; 
    653648        default: 
     
    933928        case E_SYMBOL: 
    934929                return expr_alloc_comp(type, e->left.sym, sym); 
    935         case E_CHOICE: 
     930        case E_LIST: 
    936931        case E_RANGE: 
    937932        case E_NONE: 
     
    956951                val1 = expr_calc_value(e->left.expr); 
    957952                val2 = expr_calc_value(e->right.expr); 
    958                 return E_AND(val1, val2); 
     953                return EXPR_AND(val1, val2); 
    959954        case E_OR: 
    960955                val1 = expr_calc_value(e->left.expr); 
    961956                val2 = expr_calc_value(e->right.expr); 
    962                 return E_OR(val1, val2); 
     957                return EXPR_OR(val1, val2); 
    963958        case E_NOT: 
    964959                val1 = expr_calc_value(e->left.expr); 
    965                 return E_NOT(val1); 
     960                return EXPR_NOT(val1); 
    966961        case E_EQUAL: 
    967962                sym_calc_value(e->left.sym); 
     
    1001996                        return 1; 
    1002997        case E_OR: 
    1003                 if (t2 == E_CHOICE) 
     998                if (t2 == E_LIST) 
    1004999                        return 1; 
    1005         case E_CHOICE: 
     1000        case E_LIST: 
    10061001                if (t2 == 0) 
    10071002                        return 1; 
     
    10121007        return 0; 
    10131008#endif 
     1009} 
     1010 
     1011static inline struct expr * 
     1012expr_get_leftmost_symbol(const struct expr *e) 
     1013{ 
     1014 
     1015        if (e == NULL) 
     1016                return NULL; 
     1017 
     1018        while (e->type != E_SYMBOL) 
     1019                e = e->left.expr; 
     1020 
     1021        return expr_copy(e); 
     1022} 
     1023 
     1024/* 
     1025 * Given expression `e1' and `e2', returns the leaf of the longest 
     1026 * sub-expression of `e1' not containing 'e2. 
     1027 */ 
     1028struct expr *expr_simplify_unmet_dep(struct expr *e1, struct expr *e2) 
     1029{ 
     1030        struct expr *ret; 
     1031 
     1032        switch (e1->type) { 
     1033        case E_OR: 
     1034                return expr_alloc_and( 
     1035                    expr_simplify_unmet_dep(e1->left.expr, e2), 
     1036                    expr_simplify_unmet_dep(e1->right.expr, e2)); 
     1037        case E_AND: { 
     1038                struct expr *e; 
     1039                e = expr_alloc_and(expr_copy(e1), expr_copy(e2)); 
     1040                e = expr_eliminate_dups(e); 
     1041                ret = (!expr_eq(e, e1)) ? e1 : NULL; 
     1042                expr_free(e); 
     1043                break; 
     1044                } 
     1045        default: 
     1046                ret = e1; 
     1047                break; 
     1048        } 
     1049 
     1050        return expr_get_leftmost_symbol(ret); 
    10141051} 
    10151052 
     
    10601097                expr_print(e->right.expr, fn, data, E_AND); 
    10611098                break; 
    1062         case E_CHOICE: 
     1099        case E_LIST: 
    10631100                fn(data, e->right.sym, e->right.sym->name); 
    10641101                if (e->left.expr) { 
    10651102                        fn(data, NULL, " ^ "); 
    1066                         expr_print(e->left.expr, fn, data, E_CHOICE); 
     1103                        expr_print(e->left.expr, fn, data, E_LIST); 
    10671104                } 
    10681105                break; 
     
    10881125static void expr_print_file_helper(void *data, struct symbol *sym, const char *str) 
    10891126{ 
    1090         fwrite(str, strlen(str), 1, data); 
     1127        xfwrite(str, strlen(str), 1, data); 
    10911128} 
    10921129 
  • trunk/scripts/config/expr.h

    r28658 r36361  
    1111#endif 
    1212 
     13#include <assert.h> 
    1314#include <stdio.h> 
     15#include "list.h" 
    1416#ifndef __cplusplus 
    1517#include <stdbool.h> 
     
    1921        struct file *next; 
    2022        struct file *parent; 
    21         char *name; 
     23        const char *name; 
    2224        int lineno; 
    23         int flags; 
    24 }; 
    25  
    26 #define FILE_BUSY               0x0001 
    27 #define FILE_SCANNED            0x0002 
    28 #define FILE_PRINTED            0x0004 
     25}; 
    2926 
    3027typedef enum tristate { 
     
    3330 
    3431enum expr_type { 
    35         E_NONE, E_OR, E_AND, E_NOT, E_EQUAL, E_UNEQUAL, E_CHOICE, E_SYMBOL, E_RANGE 
     32        E_NONE, E_OR, E_AND, E_NOT, E_EQUAL, E_UNEQUAL, E_LIST, E_SYMBOL, E_RANGE 
    3633}; 
    3734 
     
    4643}; 
    4744 
    48 #define E_OR(dep1, dep2)        (((dep1)>(dep2))?(dep1):(dep2)) 
    49 #define E_AND(dep1, dep2)       (((dep1)<(dep2))?(dep1):(dep2)) 
    50 #define E_NOT(dep)              (2-(dep)) 
     45#define EXPR_OR(dep1, dep2)     (((dep1)>(dep2))?(dep1):(dep2)) 
     46#define EXPR_AND(dep1, dep2)    (((dep1)<(dep2))?(dep1):(dep2)) 
     47#define EXPR_NOT(dep)           (2-(dep)) 
     48 
     49#define expr_list_for_each_sym(l, e, s) \ 
     50        for (e = (l); e && (s = e->right.sym); e = e->left.expr) 
    5151 
    5252struct expr_value { 
     
    6464}; 
    6565 
     66/* enum values are used as index to symbol.def[] */ 
     67enum { 
     68        S_DEF_USER,             /* main user value */ 
     69        S_DEF_AUTO,             /* values read from auto.conf */ 
     70        S_DEF_DEF3,             /* Reserved for UI usage */ 
     71        S_DEF_DEF4,             /* Reserved for UI usage */ 
     72        S_DEF_COUNT 
     73}; 
     74 
    6675struct symbol { 
    6776        struct symbol *next; 
    6877        char *name; 
    69         char *help; 
    7078        enum symbol_type type; 
    71         struct symbol_value curr, user; 
     79        struct symbol_value curr; 
     80        struct symbol_value def[S_DEF_COUNT]; 
    7281        tristate visible; 
    7382        int flags; 
    7483        struct property *prop; 
    75         struct expr *dep, *dep2; 
     84        struct expr_value dir_dep; 
    7685        struct expr_value rev_dep; 
    77         struct expr_value rev_dep_inv; 
    7886}; 
    7987 
    8088#define for_all_symbols(i, sym) for (i = 0; i < SYMBOL_HASHSIZE; i++) for (sym = symbol_hash[i]; sym; sym = sym->next) if (sym->type != S_OTHER) 
    8189 
    82 #define SYMBOL_YES              0x0001 
    83 #define SYMBOL_MOD              0x0002 
    84 #define SYMBOL_NO               0x0004 
    85 #define SYMBOL_CONST            0x0007 
    86 #define SYMBOL_CHECK            0x0008 
    87 #define SYMBOL_CHOICE           0x0010 
    88 #define SYMBOL_CHOICEVAL        0x0020 
    89 #define SYMBOL_PRINTED          0x0040 
    90 #define SYMBOL_VALID            0x0080 
    91 #define SYMBOL_OPTIONAL         0x0100 
    92 #define SYMBOL_WRITE            0x0200 
    93 #define SYMBOL_CHANGED          0x0400 
    94 #define SYMBOL_NEW              0x0800 
    95 #define SYMBOL_AUTO             0x1000 
    96 #define SYMBOL_CHECKED          0x2000 
    97 #define SYMBOL_WARNED           0x8000 
     90#define SYMBOL_CONST      0x0001  /* symbol is const */ 
     91#define SYMBOL_CHECK      0x0008  /* used during dependency checking */ 
     92#define SYMBOL_CHOICE     0x0010  /* start of a choice block (null name) */ 
     93#define SYMBOL_CHOICEVAL  0x0020  /* used as a value in a choice block */ 
     94#define SYMBOL_VALID      0x0080  /* set when symbol.curr is calculated */ 
     95#define SYMBOL_OPTIONAL   0x0100  /* choice is optional - values can be 'n' */ 
     96#define SYMBOL_WRITE      0x0200  /* ? */ 
     97#define SYMBOL_CHANGED    0x0400  /* ? */ 
     98#define SYMBOL_AUTO       0x1000  /* value from environment variable */ 
     99#define SYMBOL_CHECKED    0x2000  /* used during dependency checking */ 
     100#define SYMBOL_WARNED     0x8000  /* warning has been issued */ 
     101 
     102/* Set when symbol.def[] is used */ 
     103#define SYMBOL_DEF        0x10000  /* First bit of SYMBOL_DEF */ 
     104#define SYMBOL_DEF_USER   0x10000  /* symbol.def[S_DEF_USER] is valid */ 
     105#define SYMBOL_DEF_AUTO   0x20000  /* symbol.def[S_DEF_AUTO] is valid */ 
     106#define SYMBOL_DEF3       0x40000  /* symbol.def[S_DEF_3] is valid */ 
     107#define SYMBOL_DEF4       0x80000  /* symbol.def[S_DEF_4] is valid */ 
    98108 
    99109#define SYMBOL_MAXLENGTH        256 
    100 #define SYMBOL_HASHSIZE         257 
    101  
     110#define SYMBOL_HASHSIZE         9973 
     111 
     112/* A property represent the config options that can be associated 
     113 * with a config "symbol". 
     114 * Sample: 
     115 * config FOO 
     116 *         default y 
     117 *         prompt "foo prompt" 
     118 *         select BAR 
     119 * config BAZ 
     120 *         int "BAZ Value" 
     121 *         range 1..255 
     122 */ 
    102123enum prop_type { 
    103         P_UNKNOWN, P_PROMPT, P_COMMENT, P_MENU, P_DEFAULT, P_CHOICE, P_DESELECT, P_SELECT, P_RANGE, P_RESET 
     124        P_UNKNOWN, 
     125        P_PROMPT,   /* prompt "foo prompt" or "BAZ Value" */ 
     126        P_COMMENT,  /* text associated with a comment */ 
     127        P_MENU,     /* prompt associated with a menuconfig option */ 
     128        P_DEFAULT,  /* default y */ 
     129        P_CHOICE,   /* choice value */ 
     130        P_SELECT,   /* select BAR */ 
     131        P_RANGE,    /* range 7..100 (for a symbol) */ 
     132        P_ENV,      /* value from environment variable */ 
     133        P_SYMBOL,   /* where a symbol is defined */ 
     134        P_RESET,        /* reset to defaults condition */ 
    104135}; 
    105136 
    106137struct property { 
    107         struct property *next; 
    108         struct symbol *sym; 
    109         enum prop_type type; 
    110         const char *text; 
     138        struct property *next;     /* next property - null if last */ 
     139        struct symbol *sym;        /* the symbol for which the property is associated */ 
     140        enum prop_type type;       /* type of property */ 
     141        const char *text;          /* the prompt value - P_PROMPT, P_MENU, P_COMMENT */ 
    111142        struct expr_value visible; 
    112         struct expr *expr; 
    113         struct menu *menu; 
    114         struct file *file; 
    115         int lineno; 
     143        struct expr *expr;         /* the optional conditional part of the property */ 
     144        struct menu *menu;         /* the menu the property are associated with 
     145                                    * valid for: P_SELECT, P_RANGE, P_CHOICE, 
     146                                    * P_PROMPT, P_DEFAULT, P_MENU, P_COMMENT */ 
     147        struct file *file;         /* what file was this property defined */ 
     148        int lineno;                /* what lineno was this property defined */ 
    116149}; 
    117150 
     
    131164        struct symbol *sym; 
    132165        struct property *prompt; 
     166        struct expr *visibility; 
    133167        struct expr *dep; 
    134168        unsigned int flags; 
    135         //char *help; 
     169        char *help; 
    136170        struct file *file; 
    137171        int lineno; 
     
    142176#define MENU_ROOT               0x0002 
    143177 
    144 #ifndef SWIG 
     178struct jump_key { 
     179        struct list_head entries; 
     180        size_t offset; 
     181        struct menu *target; 
     182        int index; 
     183}; 
     184 
     185#define JUMP_NB                 9 
    145186 
    146187extern struct file *file_list; 
     
    150191extern struct symbol symbol_yes, symbol_no, symbol_mod; 
    151192extern struct symbol *modules_sym; 
     193extern struct symbol *sym_defconfig_list; 
    152194extern int cdebug; 
    153195struct expr *expr_alloc_symbol(struct symbol *sym); 
     
    157199struct expr *expr_alloc_and(struct expr *e1, struct expr *e2); 
    158200struct expr *expr_alloc_or(struct expr *e1, struct expr *e2); 
    159 struct expr *expr_copy(struct expr *org); 
     201struct expr *expr_copy(const struct expr *org); 
    160202void expr_free(struct expr *e); 
    161203int expr_eq(struct expr *e1, struct expr *e2); 
     
    172214void expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2); 
    173215struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym); 
     216struct expr *expr_simplify_unmet_dep(struct expr *e1, struct expr *e2); 
    174217 
    175218void expr_fprint(struct expr *e, FILE *out); 
     
    186229        return e && (e->type == E_SYMBOL && e->left.sym == &symbol_no); 
    187230} 
    188 #endif 
    189231 
    190232#ifdef __cplusplus 
  • trunk/scripts/config/lkc.h

    r28658 r36361  
    1212# include <libintl.h> 
    1313#else 
    14 # define gettext(Msgid) ((const char *) (Msgid)) 
    15 # define textdomain(Domainname) ((const char *) (Domainname)) 
    16 # define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname)) 
     14static inline const char *gettext(const char *txt) { return txt; } 
     15static inline void textdomain(const char *domainname) {} 
     16static inline void bindtextdomain(const char *name, const char *dir) {} 
     17static inline char *bind_textdomain_codeset(const char *dn, char *c) { return c; } 
    1718#endif 
    1819 
     
    2122#endif 
    2223 
    23 #ifdef LKC_DIRECT_LINK 
    2424#define P(name,type,arg)        extern type name arg 
    25 #else 
    26 #include "lkc_defs.h" 
    27 #define P(name,type,arg)        extern type (*name ## _p) arg 
    28 #endif 
    2925#include "lkc_proto.h" 
    3026#undef P 
     
    3228#define SRCTREE "srctree" 
    3329 
     30#ifndef PACKAGE 
    3431#define PACKAGE "linux" 
     32#endif 
     33 
    3534#define LOCALEDIR "/usr/share/locale" 
    3635 
     
    3837#define N_(text) (text) 
    3938 
     39#ifndef CONFIG_ 
     40#define CONFIG_ "CONFIG_" 
     41#endif 
     42static inline const char *CONFIG_prefix(void) 
     43{ 
     44        return getenv( "CONFIG_" ) ?: CONFIG_; 
     45} 
     46#undef CONFIG_ 
     47#define CONFIG_ CONFIG_prefix() 
    4048 
    4149#define TF_COMMAND      0x0001 
    4250#define TF_PARAM        0x0002 
     51#define TF_OPTION       0x0004 
     52 
     53enum conf_def_mode { 
     54        def_default, 
     55        def_yes, 
     56        def_mod, 
     57        def_no, 
     58        def_random 
     59}; 
     60 
     61#define T_OPT_MODULES           1 
     62#define T_OPT_DEFCONFIG_LIST    2 
     63#define T_OPT_ENV               3 
    4364 
    4465struct kconf_id { 
     
    4970}; 
    5071 
     72extern int zconfdebug; 
     73 
    5174int zconfparse(void); 
    5275void zconfdump(FILE *out); 
    53  
    54 extern int zconfdebug; 
    5576void zconf_starthelp(void); 
    5677FILE *zconf_fopen(const char *name); 
     
    5879void zconf_nextfile(const char *name); 
    5980int zconf_lineno(void); 
    60 char *zconf_curname(void); 
     81const char *zconf_curname(void); 
    6182 
    6283/* confdata.c */ 
    63 extern const char conf_def_filename[]; 
     84const char *conf_get_configname(void); 
     85const char *conf_get_autoconfig_name(void); 
     86char *conf_get_default_confname(void); 
     87void sym_set_change_count(int count); 
     88void sym_add_change_count(int count); 
     89void conf_set_all_new_symbols(enum conf_def_mode mode); 
    6490 
    65 char *conf_get_default_confname(void); 
     91struct conf_printer { 
     92        void (*print_symbol)(FILE *, struct symbol *, const char *, void *); 
     93        void (*print_comment)(FILE *, const char *, void *); 
     94}; 
    6695 
    67 /* kconfig_load.c */ 
    68 void kconfig_load(void); 
     96/* confdata.c and expr.c */ 
     97static inline void xfwrite(const void *str, size_t len, size_t count, FILE *out) 
     98{ 
     99        assert(len != 0); 
     100 
     101        if (fwrite(str, len, count, out) != count) 
     102                fprintf(stderr, "Error in writing or end of file.\n"); 
     103} 
    69104 
    70105/* menu.c */ 
    71 void menu_init(void); 
     106void _menu_init(void); 
     107void menu_warn(struct menu *menu, const char *fmt, ...); 
    72108struct menu *menu_add_menu(void); 
    73109void menu_end_menu(void); 
     
    75111void menu_end_entry(void); 
    76112void menu_add_dep(struct expr *dep); 
     113void menu_add_visibility(struct expr *dep); 
    77114struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep); 
    78115struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep); 
    79116void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep); 
    80117void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep); 
     118void menu_add_option(int token, char *arg); 
    81119void menu_finalize(struct menu *parent); 
    82120void menu_set_type(int type); 
     
    85123struct file *file_lookup(const char *name); 
    86124int file_write_dep(const char *name); 
     125void *xmalloc(size_t size); 
     126void *xcalloc(size_t nmemb, size_t size); 
    87127 
    88128struct gstr { 
     
    90130        char  *s; 
    91131        /* 
    92          * when max_width is not zero long lines in string s (if any) get 
    93          * wrapped not to exceed the max_width value 
    94          */ 
     132        * when max_width is not zero long lines in string s (if any) get 
     133        * wrapped not to exceed the max_width value 
     134        */ 
    95135        int max_width; 
    96136}; 
     
    103143 
    104144/* symbol.c */ 
     145extern struct expr *sym_env_list; 
     146 
    105147void sym_init(void); 
    106148void sym_clear_all_valid(void); 
     149void sym_set_all_changed(void); 
    107150void sym_set_changed(struct symbol *sym); 
     151struct symbol *sym_choice_default(struct symbol *sym); 
     152const char *sym_get_string_default(struct symbol *sym); 
    108153struct symbol *sym_check_deps(struct symbol *sym); 
    109154struct property *prop_alloc(enum prop_type type, struct symbol *sym); 
    110155struct symbol *prop_get_symbol(struct property *prop); 
     156struct property *sym_get_env_prop(struct symbol *sym); 
    111157 
    112158static inline tristate sym_get_tristate_value(struct symbol *sym) 
     
    143189static inline bool sym_has_value(struct symbol *sym) 
    144190{ 
    145         return sym->flags & SYMBOL_NEW ? false : true; 
     191        return sym->flags & SYMBOL_DEF_USER ? true : false; 
    146192} 
    147193 
  • trunk/scripts/config/lkc_proto.h

    r28658 r36361  
     1#include <stdarg.h> 
    12 
    23/* confdata.c */ 
    34P(conf_parse,void,(const char *name)); 
    45P(conf_read,int,(const char *name)); 
    5 P(conf_reset,void,(void)); 
    6 P(conf_read_simple,int,(const char *name, int load_config)); 
     6P(conf_read_simple,int,(const char *name, int)); 
     7P(conf_reset,void,(int)); 
     8P(conf_write_defconfig,int,(const char *name)); 
    79P(conf_write,int,(const char *name)); 
     10P(conf_write_autoconf,int,(void)); 
     11P(conf_get_changed,bool,(void)); 
     12P(conf_set_changed_callback, void,(void (*fn)(void))); 
     13P(conf_set_message_callback, void,(void (*fn)(const char *fmt, va_list ap))); 
    814 
    915/* menu.c */ 
    1016P(rootmenu,struct menu,); 
    1117 
    12 P(menu_is_visible,bool,(struct menu *menu)); 
     18P(menu_is_visible, bool, (struct menu *menu)); 
     19P(menu_has_prompt, bool, (struct menu *menu)); 
    1320P(menu_get_prompt,const char *,(struct menu *menu)); 
    1421P(menu_get_root_menu,struct menu *,(struct menu *menu)); 
    1522P(menu_get_parent_menu,struct menu *,(struct menu *menu)); 
     23P(menu_has_help,bool,(struct menu *menu)); 
     24P(menu_get_help,const char *,(struct menu *menu)); 
     25P(get_symbol_str, void, (struct gstr *r, struct symbol *sym, struct list_head 
     26                         *head)); 
     27P(get_relations_str, struct gstr, (struct symbol **sym_arr, struct list_head 
     28                                   *head)); 
     29P(menu_get_ext_help,void,(struct menu *menu, struct gstr *help)); 
    1630 
    1731/* symbol.c */ 
    1832P(symbol_hash,struct symbol *,[SYMBOL_HASHSIZE]); 
    19 P(sym_change_count,int,); 
    2033 
    21 P(sym_lookup,struct symbol *,(const char *name, int isconst)); 
     34P(sym_lookup,struct symbol *,(const char *name, int flags)); 
    2235P(sym_find,struct symbol *,(const char *name)); 
     36P(sym_expand_string_value,const char *,(const char *in)); 
     37P(sym_escape_string_value, const char *,(const char *in)); 
    2338P(sym_re_search,struct symbol **,(const char *pattern)); 
    2439P(sym_type_name,const char *,(enum symbol_type type)); 
  • trunk/scripts/config/lxdialog/check-lxdialog.sh

    r6502 r36361  
    1 #!/usr/bin/env bash 
     1#!/bin/sh 
    22# Check ncurses compatibility 
    33 
     
    55ldflags() 
    66{ 
    7         for ext in so dylib; do 
    8                 for dir in "" /usr/local/lib /opt/local/lib; do 
    9                         $cc ${dir:+-L$dir} -print-file-name=libncursesw.$ext | grep -q / 
     7        for ext in so a dll.a dylib ; do 
     8                for lib in ncursesw ncurses curses ; do 
     9                        $cc -print-file-name=lib${lib}.${ext} | grep -q / 
    1010                        if [ $? -eq 0 ]; then 
    11                                 echo $dir '-lncursesw' 
    12                                 exit 
    13                         fi 
    14                         $cc ${dir:+-L$dir} -print-file-name=libncurses.$ext | grep -q / 
    15                         if [ $? -eq 0 ]; then 
    16                                 echo $dir '-lncurses' 
    17                                 exit  
    18                         fi 
    19                         $cc ${dir:+-L$dir} -print-file-name=libcurses.$ext | grep -q / 
    20                         if [ $? -eq 0 ]; then 
    21                                 echo $dir '-lcurses' 
     11                                echo "-l${lib}" 
    2212                                exit 
    2313                        fi 
     
    3020ccflags() 
    3121{ 
    32         if [ -f /usr/include/ncurses/ncurses.h ]; then 
     22        if [ -f /usr/include/ncursesw/curses.h ]; then 
     23                echo '-I/usr/include/ncursesw -DCURSES_LOC="<ncursesw/curses.h>"' 
     24                echo ' -DNCURSES_WIDECHAR=1' 
     25        elif [ -f /usr/include/ncurses/ncurses.h ]; then 
    3326                echo '-I/usr/include/ncurses -DCURSES_LOC="<ncurses.h>"' 
    3427        elif [ -f /usr/include/ncurses/curses.h ]; then 
    3528                echo '-I/usr/include/ncurses -DCURSES_LOC="<ncurses/curses.h>"' 
    36         elif [ -f /opt/local/include/ncurses/ncurses.h ]; then 
    37                 echo '-I/opt/local/include -I/opt/local/include/ncurses -DCURSES_LOC="<ncurses/ncurses.h>"' 
    3829        elif [ -f /usr/include/ncurses.h ]; then 
    3930                echo '-DCURSES_LOC="<ncurses.h>"' 
     
    4940# Check if we can link to ncurses 
    5041check() { 
    51         echo "main() {}" | $cc -xc - -o $tmp 2> /dev/null 
     42        $cc -x c - -o $tmp 2>/dev/null <<'EOF' 
     43#include CURSES_LOC 
     44main() {} 
     45EOF 
    5246        if [ $? != 0 ]; then 
    53                 echo " *** Unable to find the ncurses libraries."          1>&2 
    54                 echo " *** make menuconfig require the ncurses libraries"  1>&2 
    55                 echo " *** "                                               1>&2 
    56                 echo " *** Install ncurses (ncurses-devel) and try again"  1>&2 
    57                 echo " *** "                                               1>&2 
    58                 exit 1 
     47            echo " *** Unable to find the ncurses libraries or the"       1>&2 
     48            echo " *** required header files."                            1>&2 
     49            echo " *** 'make menuconfig' requires the ncurses libraries." 1>&2 
     50            echo " *** "                                                  1>&2 
     51            echo " *** Install ncurses (ncurses-devel) and try again."    1>&2 
     52            echo " *** "                                                  1>&2 
     53            exit 1 
    5954        fi 
    6055} 
    6156 
    6257usage() { 
    63         printf "Usage: $0 [-check compiler options|-header|-library]\n" 
     58        printf "Usage: $0 [-check compiler options|-ccflags|-ldflags compiler options]\n" 
    6459} 
    6560 
  • trunk/scripts/config/lxdialog/checklist.c

    r6502 r36361  
    2929 * Print list item 
    3030 */ 
    31 static void print_item(WINDOW * win, const char *item, int status, int choice, 
    32                        int selected) 
     31static void print_item(WINDOW * win, int choice, int selected) 
    3332{ 
    3433        int i; 
     34        char *list_item = malloc(list_width + 1); 
     35 
     36        strncpy(list_item, item_str(), list_width - item_x); 
     37        list_item[list_width - item_x] = '\0'; 
    3538 
    3639        /* Clear 'residue' of last item */ 
    37         wattrset(win, menubox_attr); 
     40        wattrset(win, dlg.menubox.atr); 
    3841        wmove(win, choice, 0); 
    3942        for (i = 0; i < list_width; i++) 
     
    4144 
    4245        wmove(win, choice, check_x); 
    43         wattrset(win, selected ? check_selected_attr : check_attr); 
    44         wprintw(win, "(%c)", status ? 'X' : ' '); 
    45  
    46         wattrset(win, selected ? tag_selected_attr : tag_attr); 
    47         mvwaddch(win, choice, item_x, item[0]); 
    48         wattrset(win, selected ? item_selected_attr : item_attr); 
    49         waddstr(win, (char *)item + 1); 
     46        wattrset(win, selected ? dlg.check_selected.atr 
     47                 : dlg.check.atr); 
     48        if (!item_is_tag(':')) 
     49                wprintw(win, "(%c)", item_is_tag('X') ? 'X' : ' '); 
     50 
     51        wattrset(win, selected ? dlg.tag_selected.atr : dlg.tag.atr); 
     52        mvwaddch(win, choice, item_x, list_item[0]); 
     53        wattrset(win, selected ? dlg.item_selected.atr : dlg.item.atr); 
     54        waddstr(win, list_item + 1); 
    5055        if (selected) { 
    5156                wmove(win, choice, check_x + 1); 
    5257                wrefresh(win); 
    5358        } 
     59        free(list_item); 
    5460} 
    5561 
     
    6369 
    6470        if (scroll > 0) { 
    65                 wattrset(win, uarrow_attr); 
     71                wattrset(win, dlg.uarrow.atr); 
    6672                waddch(win, ACS_UARROW); 
    6773                waddstr(win, "(-)"); 
    6874        } else { 
    69                 wattrset(win, menubox_attr); 
     75                wattrset(win, dlg.menubox.atr); 
    7076                waddch(win, ACS_HLINE); 
    7177                waddch(win, ACS_HLINE); 
     
    7884 
    7985        if ((height < item_no) && (scroll + choice < item_no - 1)) { 
    80                 wattrset(win, darrow_attr); 
     86                wattrset(win, dlg.darrow.atr); 
    8187                waddch(win, ACS_DARROW); 
    8288                waddstr(win, "(+)"); 
    8389        } else { 
    84                 wattrset(win, menubox_border_attr); 
     90                wattrset(win, dlg.menubox_border.atr); 
    8591                waddch(win, ACS_HLINE); 
    8692                waddch(win, ACS_HLINE); 
     
    98104        int y = height - 2; 
    99105 
    100         print_button(dialog, "Select", y, x, selected == 0); 
    101         print_button(dialog, " Help ", y, x + 14, selected == 1); 
     106        print_button(dialog, gettext("Select"), y, x, selected == 0); 
     107        print_button(dialog, gettext(" Help "), y, x + 14, selected == 1); 
    102108 
    103109        wmove(dialog, y, x + 1 + 14 * selected); 
     
    110116 */ 
    111117int dialog_checklist(const char *title, const char *prompt, int height, 
    112                      int width, int list_height, int item_no, 
    113                      const char *const *items) 
     118                     int width, int list_height) 
    114119{ 
    115120        int i, x, y, box_x, box_y; 
    116         int key = 0, button = 0, choice = 0, scroll = 0, max_choice, *status; 
     121        int key = 0, button = 0, choice = 0, scroll = 0, max_choice; 
    117122        WINDOW *dialog, *list; 
    118123 
    119         /* Allocate space for storing item on/off status */ 
    120         if ((status = malloc(sizeof(int) * item_no)) == NULL) { 
    121                 endwin(); 
    122                 fprintf(stderr, 
    123                         "\nCan't allocate memory in dialog_checklist().\n"); 
    124                 exit(-1); 
    125         } 
    126  
    127         /* Initializes status */ 
    128         for (i = 0; i < item_no; i++) { 
    129                 status[i] = !strcasecmp(items[i * 3 + 2], "on"); 
    130                 if ((!choice && status[i]) 
    131                     || !strcasecmp(items[i * 3 + 2], "selected")) 
    132                         choice = i + 1; 
    133         } 
    134         if (choice) 
    135                 choice--; 
    136  
    137         max_choice = MIN(list_height, item_no); 
     124        /* which item to highlight */ 
     125        item_foreach() { 
     126                if (item_is_tag('X')) 
     127                        choice = item_n(); 
     128                if (item_is_selected()) { 
     129                        choice = item_n(); 
     130                        break; 
     131                } 
     132        } 
     133 
     134do_resize: 
     135        if (getmaxy(stdscr) < (height + 6)) 
     136                return -ERRDISPLAYTOOSMALL; 
     137        if (getmaxx(stdscr) < (width + 6)) 
     138                return -ERRDISPLAYTOOSMALL; 
     139 
     140        max_choice = MIN(list_height, item_count()); 
    138141 
    139142        /* center dialog box on screen */ 
     
    146149        keypad(dialog, TRUE); 
    147150 
    148         draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr); 
    149         wattrset(dialog, border_attr); 
     151        draw_box(dialog, 0, 0, height, width, 
     152                 dlg.dialog.atr, dlg.border.atr); 
     153        wattrset(dialog, dlg.border.atr); 
    150154        mvwaddch(dialog, height - 3, 0, ACS_LTEE); 
    151155        for (i = 0; i < width - 2; i++) 
    152156                waddch(dialog, ACS_HLINE); 
    153         wattrset(dialog, dialog_attr); 
     157        wattrset(dialog, dlg.dialog.atr); 
    154158        waddch(dialog, ACS_RTEE); 
    155159 
    156160        print_title(dialog, title, width); 
    157161 
    158         wattrset(dialog, dialog_attr); 
     162        wattrset(dialog, dlg.dialog.atr); 
    159163        print_autowrap(dialog, prompt, width - 2, 1, 3); 
    160164 
     
    171175        /* draw a box around the list items */ 
    172176        draw_box(dialog, box_y, box_x, list_height + 2, list_width + 2, 
    173                  menubox_border_attr, menubox_attr); 
     177                 dlg.menubox_border.atr, dlg.menubox.atr); 
    174178 
    175179        /* Find length of longest item in order to center checklist */ 
    176180        check_x = 0; 
    177         for (i = 0; i < item_no; i++) 
    178                 check_x = MAX(check_x, +strlen(items[i * 3 + 1]) + 4); 
     181        item_foreach() 
     182                check_x = MAX(check_x, strlen(item_str()) + 4); 
     183        check_x = MIN(check_x, list_width); 
    179184 
    180185        check_x = (list_width - check_x) / 2; 
     
    188193        /* Print the list */ 
    189194        for (i = 0; i < max_choice; i++) { 
    190                 print_item(list, items[(scroll + i) * 3 + 1], 
    191                            status[i + scroll], i, i == choice); 
    192         } 
    193  
    194         print_arrows(dialog, choice, item_no, scroll, 
     195                item_set(scroll + i); 
     196                print_item(list, i, i == choice); 
     197        } 
     198 
     199        print_arrows(dialog, choice, item_count(), scroll, 
    195200                     box_y, box_x + check_x + 5, list_height); 
    196201 
    197202        print_buttons(dialog, height, width, 0); 
    198203 
     204        wnoutrefresh(dialog); 
    199205        wnoutrefresh(list); 
    200         wnoutrefresh(dialog); 
    201206        doupdate(); 
    202207 
    203         while (key != ESC) { 
     208        while (key != KEY_ESC) { 
    204209                key = wgetch(dialog); 
    205210 
    206                 for (i = 0; i < max_choice; i++) 
    207                         if (toupper(key) == 
    208                             toupper(items[(scroll + i) * 3 + 1][0])) 
     211                for (i = 0; i < max_choice; i++) { 
     212                        item_set(i + scroll); 
     213                        if (toupper(key) == toupper(item_str()[0])) 
    209214                                break; 
     215                } 
    210216 
    211217                if (i < max_choice || key == KEY_UP || key == KEY_DOWN || 
     
    218224                                        if (list_height > 1) { 
    219225                                                /* De-highlight current first item */ 
    220                                                 print_item(list, items[scroll * 3 + 1], 
    221                                                            status[scroll], 0, FALSE); 
     226                                                item_set(scroll); 
     227                                                print_item(list, 0, FALSE); 
    222228                                                scrollok(list, TRUE); 
    223229                                                wscrl(list, -1); 
     
    225231                                        } 
    226232                                        scroll--; 
    227                                         print_item(list, items[scroll * 3 + 1], status[scroll], 0, TRUE); 
    228                                         wnoutrefresh(list); 
    229  
    230                                         print_arrows(dialog, choice, item_no, 
     233                                        item_set(scroll); 
     234                                        print_item(list, 0, TRUE); 
     235                                        print_arrows(dialog, choice, item_count(), 
    231236                                                     scroll, box_y, box_x + check_x + 5, list_height); 
    232237 
    233                                         wrefresh(dialog); 
     238                                        wnoutrefresh(dialog); 
     239                                        wrefresh(list); 
    234240 
    235241                                        continue;       /* wait for another key press */ 
     
    238244                        } else if (key == KEY_DOWN || key == '+') { 
    239245                                if (choice == max_choice - 1) { 
    240                                         if (scroll + choice >= item_no - 1) 
     246                                        if (scroll + choice >= item_count() - 1) 
    241247                                                continue; 
    242248                                        /* Scroll list up */ 
    243249                                        if (list_height > 1) { 
    244250                                                /* De-highlight current last item before scrolling up */ 
    245                                                 print_item(list, items[(scroll + max_choice - 1) * 3 + 1], 
    246                                                            status[scroll + max_choice - 1], 
    247                                                            max_choice - 1, FALSE); 
     251                                                item_set(scroll + max_choice - 1); 
     252                                                print_item(list, 
     253                                                            max_choice - 1, 
     254                                                            FALSE); 
    248255                                                scrollok(list, TRUE); 
    249256                                                wscrl(list, 1); 
     
    251258                                        } 
    252259                                        scroll++; 
    253                                         print_item(list, items[(scroll + max_choice - 1) * 3 + 1], 
    254                                                    status[scroll + max_choice - 1], max_choice - 1, TRUE); 
    255                                         wnoutrefresh(list); 
    256  
    257                                         print_arrows(dialog, choice, item_no, 
     260                                        item_set(scroll + max_choice - 1); 
     261                                        print_item(list, max_choice - 1, TRUE); 
     262 
     263                                        print_arrows(dialog, choice, item_count(), 
    258264                                                     scroll, box_y, box_x + check_x + 5, list_height); 
    259265 
    260                                         wrefresh(dialog); 
     266                                        wnoutrefresh(dialog); 
     267                                        wrefresh(list); 
    261268 
    262269                                        continue;       /* wait for another key press */ 
     
    266273                        if (i != choice) { 
    267274                                /* De-highlight current item */ 
    268                                 print_item(list, items[(scroll + choice) * 3 + 1], 
    269                                            status[scroll + choice], choice, FALSE); 
     275                                item_set(scroll + choice); 
     276                                print_item(list, choice, FALSE); 
    270277                                /* Highlight new item */ 
    271278                                choice = i; 
    272                                 print_item(list, items[(scroll + choice) * 3 + 1], 
    273                                            status[scroll + choice], choice, TRUE); 
    274                                 wnoutrefresh(list); 
    275                                 wrefresh(dialog); 
     279                                item_set(scroll + choice); 
     280                                print_item(list, choice, TRUE); 
     281                                wnoutrefresh(dialog); 
     282                                wrefresh(list); 
    276283                        } 
    277284                        continue;       /* wait for another key press */ 
     
    281288                case 'h': 
    282289                case '?': 
    283                         fprintf(stderr, "%s", items[(scroll + choice) * 3]); 
     290                        button = 1; 
     291                        /* fall-through */ 
     292                case 'S': 
     293                case 's': 
     294                case ' ': 
     295                case '\n': 
     296                        item_foreach() 
     297                                item_set_selected(0); 
     298                        item_set(scroll + choice); 
     299                        item_set_selected(1); 
     300                        delwin(list); 
    284301                        delwin(dialog); 
    285                         free(status); 
    286                         return 1; 
     302                        return button; 
    287303                case TAB: 
    288304                case KEY_LEFT: 
     
    294310                        wrefresh(dialog); 
    295311                        break; 
    296                 case 'S': 
    297                 case 's': 
    298                 case ' ': 
    299                 case '\n': 
    300                         if (!button) { 
    301                                 if (!status[scroll + choice]) { 
    302                                         for (i = 0; i < item_no; i++) 
    303                                                 status[i] = 0; 
    304                                         status[scroll + choice] = 1; 
    305                                         for (i = 0; i < max_choice; i++) 
    306                                                 print_item(list, items[(scroll + i) * 3 + 1], 
    307                                                            status[scroll + i], i, i == choice); 
    308                                 } 
    309                                 wnoutrefresh(list); 
    310                                 wrefresh(dialog); 
    311  
    312                                 for (i = 0; i < item_no; i++) 
    313                                         if (status[i]) 
    314                                                 fprintf(stderr, "%s", items[i * 3]); 
    315                         } else 
    316                                 fprintf(stderr, "%s", items[(scroll + choice) * 3]); 
    317                         delwin(dialog); 
    318                         free(status); 
    319                         return button; 
    320312                case 'X': 
    321313                case 'x': 
    322                         key = ESC; 
    323                 case ESC: 
     314                        key = KEY_ESC; 
    324315                        break; 
     316                case KEY_ESC: 
     317                        key = on_key_esc(dialog); 
     318                        break; 
     319                case KEY_RESIZE: 
     320                        delwin(list); 
     321                        delwin(dialog); 
     322                        on_key_resize(); 
     323                        goto do_resize; 
    325324                } 
    326325 
     
    328327                doupdate(); 
    329328        } 
    330  
     329        delwin(list); 
    331330        delwin(dialog); 
    332         free(status); 
    333         return -1;              /* ESC pressed */ 
     331        return key;             /* ESC pressed */ 
    334332} 
  • trunk/scripts/config/lxdialog/dialog.h

    r6502 r36361  
    2525#include <stdlib.h> 
    2626#include <string.h> 
     27#include <stdbool.h> 
     28 
     29#ifndef KBUILD_NO_NLS 
     30# include <libintl.h> 
     31#else 
     32# define gettext(Msgid) ((const char *) (Msgid)) 
     33#endif 
    2734 
    2835#ifdef __sun__ 
     
    4956#define TR(params) _tracef params 
    5057 
    51 #define ESC 27 
     58#define KEY_ESC 27 
    5259#define TAB 9 
    5360#define MAX_LEN 2048 
     
    8794#endif 
    8895 
    89 /* 
    90  * Attribute names 
    91  */ 
    92 #define screen_attr                   attributes[0] 
    93 #define shadow_attr                   attributes[1] 
    94 #define dialog_attr                   attributes[2] 
    95 #define title_attr                    attributes[3] 
    96 #define border_attr                   attributes[4] 
    97 #define button_active_attr            attributes[5] 
    98 #define button_inactive_attr          attributes[6] 
    99 #define button_key_active_attr        attributes[7] 
    100 #define button_key_inactive_attr      attributes[8] 
    101 #define button_label_active_attr      attributes[9] 
    102 #define button_label_inactive_attr    attributes[10] 
    103 #define inputbox_attr                 attributes[11] 
    104 #define inputbox_border_attr          attributes[12] 
    105 #define searchbox_attr                attributes[13] 
    106 #define searchbox_title_attr          attributes[14] 
    107 #define searchbox_border_attr         attributes[15] 
    108 #define position_indicator_attr       attributes[16] 
    109 #define menubox_attr                  attributes[17] 
    110 #define menubox_border_attr           attributes[18] 
    111 #define item_attr                     attributes[19] 
    112 #define item_selected_attr            attributes[20] 
    113 #define tag_attr                      attributes[21] 
    114 #define tag_selected_attr             attributes[22] 
    115 #define tag_key_attr                  attributes[23] 
    116 #define tag_key_selected_attr         attributes[24] 
    117 #define check_attr                    attributes[25] 
    118 #define check_selected_attr           attributes[26] 
    119 #define uarrow_attr                   attributes[27] 
    120 #define darrow_attr                   attributes[28] 
    121  
    122 /* number of attributes */ 
    123 #define ATTRIBUTE_COUNT               29 
     96/* error return codes */ 
     97#define ERRDISPLAYTOOSMALL (KEY_MAX + 1) 
     98 
     99/* 
     100 *   Color definitions 
     101 */ 
     102struct dialog_color { 
     103        chtype atr;     /* Color attribute */ 
     104        int fg;         /* foreground */ 
     105        int bg;         /* background */ 
     106        int hl;         /* highlight this item */ 
     107}; 
     108 
     109struct dialog_info { 
     110        const char *backtitle; 
     111        struct dialog_color screen; 
     112        struct dialog_color shadow; 
     113        struct dialog_color dialog; 
     114        struct dialog_color title; 
     115        struct dialog_color border; 
     116        struct dialog_color button_active; 
     117        struct dialog_color button_inactive; 
     118        struct dialog_color button_key_active; 
     119        struct dialog_color button_key_inactive; 
     120        struct dialog_color button_label_active; 
     121        struct dialog_color button_label_inactive; 
     122        struct dialog_color inputbox; 
     123        struct dialog_color inputbox_border; 
     124        struct dialog_color searchbox; 
     125        struct dialog_color searchbox_title; 
     126        struct dialog_color searchbox_border; 
     127        struct dialog_color position_indicator; 
     128        struct dialog_color menubox; 
     129        struct dialog_color menubox_border; 
     130        struct dialog_color item; 
     131        struct dialog_color item_selected; 
     132        struct dialog_color tag; 
     133        struct dialog_color tag_selected; 
     134        struct dialog_color tag_key; 
     135        struct dialog_color tag_key_selected; 
     136        struct dialog_color check; 
     137        struct dialog_color check_selected; 
     138        struct dialog_color uarrow; 
     139        struct dialog_color darrow; 
     140}; 
    124141 
    125142/* 
    126143 * Global variables 
    127144 */ 
    128 extern bool use_colors; 
    129 extern bool use_shadow; 
    130  
    131 extern chtype attributes[]; 
    132  
    133 extern const char *backtitle; 
     145extern struct dialog_info dlg; 
     146extern char dialog_input_result[]; 
     147extern int saved_x, saved_y;            /* Needed in signal handler in mconf.c */ 
    134148 
    135149/* 
    136150 * Function prototypes 
    137151 */ 
    138 extern void create_rc(const char *filename); 
    139 extern int parse_rc(void); 
    140  
    141 void init_dialog(void); 
    142 void end_dialog(void); 
     152 
     153/* item list as used by checklist and menubox */ 
     154void item_reset(void); 
     155void item_make(const char *fmt, ...); 
     156void item_add_str(const char *fmt, ...); 
     157void item_set_tag(char tag); 
     158void item_set_data(void *p); 
     159void item_set_selected(int val); 
     160int item_activate_selected(void); 
     161void *item_data(void); 
     162char item_tag(void); 
     163 
     164/* item list manipulation for lxdialog use */ 
     165#define MAXITEMSTR 200 
     166struct dialog_item { 
     167        char str[MAXITEMSTR];   /* promtp displayed */ 
     168        char tag; 
     169        void *data;     /* pointer to menu item - used by menubox+checklist */ 
     170        int selected;   /* Set to 1 by dialog_*() function if selected. */ 
     171}; 
     172 
     173/* list of lialog_items */ 
     174struct dialog_list { 
     175        struct dialog_item node; 
     176        struct dialog_list *next; 
     177}; 
     178 
     179extern struct dialog_list *item_cur; 
     180extern struct dialog_list item_nil; 
     181extern struct dialog_list *item_head; 
     182 
     183int item_count(void); 
     184void item_set(int n); 
     185int item_n(void); 
     186const char *item_str(void); 
     187int item_is_selected(void); 
     188int item_is_tag(char tag); 
     189#define item_foreach() \ 
     190        for (item_cur = item_head ? item_head: item_cur; \ 
     191             item_cur && (item_cur != &item_nil); item_cur = item_cur->next) 
     192 
     193/* generic key handlers */ 
     194int on_key_esc(WINDOW *win); 
     195int on_key_resize(void); 
     196 
     197int init_dialog(const char *backtitle); 
     198void set_dialog_backtitle(const char *backtitle); 
     199void end_dialog(int x, int y); 
    143200void attr_clear(WINDOW * win, int height, int width, chtype attr); 
    144201void dialog_clear(void); 
    145 void color_setup(void); 
    146202void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x); 
    147203void print_button(WINDOW * win, const char *label, int y, int x, int selected); 
     
    155211int dialog_msgbox(const char *title, const char *prompt, int height, 
    156212                  int width, int pause); 
    157 int dialog_textbox(const char *title, const char *file, int height, int width); 
    158 int dialog_menu(const char *title, const char *prompt, int height, int width, 
    159                 int menu_height, const char *choice, int item_no, 
    160                 const char *const *items); 
     213 
     214 
     215typedef void (*update_text_fn)(char *buf, size_t start, size_t end, void 
     216                               *_data); 
     217int dialog_textbox(const char *title, char *tbuf, int initial_height, 
     218                   int initial_width, int *keys, int *_vscroll, int *_hscroll, 
     219                   update_text_fn update_text, void *data); 
     220int dialog_menu(const char *title, const char *prompt, 
     221                const void *selected, int *s_scroll); 
    161222int dialog_checklist(const char *title, const char *prompt, int height, 
    162                      int width, int list_height, int item_no, 
    163                      const char *const *items); 
    164 extern char dialog_input_result[]; 
     223                     int width, int list_height); 
    165224int dialog_inputbox(const char *title, const char *prompt, int height, 
    166225                    int width, const char *init); 
  • trunk/scripts/config/lxdialog/inputbox.c

    r6502 r36361  
    3232        int y = height - 2; 
    3333 
    34         print_button(dialog, "  Ok  ", y, x, selected == 0); 
    35         print_button(dialog, " Help ", y, x + 14, selected == 1); 
     34        print_button(dialog, gettext("  Ok  "), y, x, selected == 0); 
     35        print_button(dialog, gettext(" Help "), y, x + 14, selected == 1); 
    3636 
    3737        wmove(dialog, y, x + 1 + 14 * selected); 
     
    4646{ 
    4747        int i, x, y, box_y, box_x, box_width; 
    48         int input_x = 0, scroll = 0, key = 0, button = -1; 
     48        int input_x = 0, key = 0, button = -1; 
     49        int show_x, len, pos; 
    4950        char *instr = dialog_input_result; 
    5051        WINDOW *dialog; 
     52 
     53        if (!init) 
     54                instr[0] = '\0'; 
     55        else 
     56                strcpy(instr, init); 
     57 
     58do_resize: 
     59        if (getmaxy(stdscr) <= (height - 2)) 
     60                return -ERRDISPLAYTOOSMALL; 
     61        if (getmaxx(stdscr) <= (width - 2)) 
     62                return -ERRDISPLAYTOOSMALL; 
    5163 
    5264        /* center dialog box on screen */ 
     
    5971        keypad(dialog, TRUE); 
    6072 
    61         draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr); 
    62         wattrset(dialog, border_attr); 
     73        draw_box(dialog, 0, 0, height, width, 
     74                 dlg.dialog.atr, dlg.border.atr); 
     75        wattrset(dialog, dlg.border.atr); 
    6376        mvwaddch(dialog, height - 3, 0, ACS_LTEE); 
    6477        for (i = 0; i < width - 2; i++) 
    6578                waddch(dialog, ACS_HLINE); 
    66         wattrset(dialog, dialog_attr); 
     79        wattrset(dialog, dlg.dialog.atr); 
    6780        waddch(dialog, ACS_RTEE); 
    6881 
    6982        print_title(dialog, title, width); 
    7083 
    71         wattrset(dialog, dialog_attr); 
     84        wattrset(dialog, dlg.dialog.atr); 
    7285        print_autowrap(dialog, prompt, width - 2, 1, 3); 
    7386 
     
    7790        box_y = y + 2; 
    7891        box_x = (width - box_width) / 2; 
    79         draw_box(dialog, y + 1, box_x - 1, 3, box_width + 2, border_attr, dialog_attr); 
     92        draw_box(dialog, y + 1, box_x - 1, 3, box_width + 2, 
     93                 dlg.dialog.atr, dlg.border.atr); 
    8094 
    8195        print_buttons(dialog, height, width, 0); 
     
    8397        /* Set up the initial value */ 
    8498        wmove(dialog, box_y, box_x); 
    85         wattrset(dialog, inputbox_attr); 
    86  
    87         if (!init) 
    88                 instr[0] = '\0'; 
    89         else 
    90                 strcpy(instr, init); 
    91  
    92         input_x = strlen(instr); 
    93  
    94         if (input_x >= box_width) { 
    95                 scroll = input_x - box_width + 1; 
     99        wattrset(dialog, dlg.inputbox.atr); 
     100 
     101        len = strlen(instr); 
     102        pos = len; 
     103 
     104        if (len >= box_width) { 
     105                show_x = len - box_width + 1; 
    96106                input_x = box_width - 1; 
    97107                for (i = 0; i < box_width - 1; i++) 
    98                         waddch(dialog, instr[scroll + i]); 
     108                        waddch(dialog, instr[show_x + i]); 
    99109        } else { 
     110                show_x = 0; 
     111                input_x = len; 
    100112                waddstr(dialog, instr); 
    101113        } 
     
    105117        wrefresh(dialog); 
    106118 
    107         while (key != ESC) { 
     119        while (key != KEY_ESC) { 
    108120                key = wgetch(dialog); 
    109121 
     
    114126                        case KEY_DOWN: 
    115127                                break; 
    116                         case KEY_LEFT: 
    117                                 continue; 
    118                         case KEY_RIGHT: 
    119                                 continue; 
    120128                        case KEY_BACKSPACE: 
    121129                        case 127: 
    122                                 if (input_x || scroll) { 
    123                                         wattrset(dialog, inputbox_attr); 
    124                                         if (!input_x) { 
    125                                                 scroll = scroll < box_width - 1 ? 0 : scroll - (box_width - 1); 
    126                                                 wmove(dialog, box_y, box_x); 
    127                                                 for (i = 0; i < box_width; i++) 
    128                                                         waddch(dialog, 
    129                                                                instr[scroll + input_x + i] ? 
    130                                                                instr[scroll + input_x + i] : ' '); 
    131                                                 input_x = strlen(instr) - scroll; 
     130                                if (pos) { 
     131                                        wattrset(dialog, dlg.inputbox.atr); 
     132                                        if (input_x == 0) { 
     133                                                show_x--; 
    132134                                        } else 
    133135                                                input_x--; 
    134                                         instr[scroll + input_x] = '\0'; 
    135                                         mvwaddch(dialog, box_y, input_x + box_x, ' '); 
     136 
     137                                        if (pos < len) { 
     138                                                for (i = pos - 1; i < len; i++) { 
     139                                                        instr[i] = instr[i+1]; 
     140                                                } 
     141                                        } 
     142 
     143                                        pos--; 
     144                                        len--; 
     145                                        instr[len] = '\0'; 
     146                                        wmove(dialog, box_y, box_x); 
     147                                        for (i = 0; i < box_width; i++) { 
     148                                                if (!instr[show_x + i]) { 
     149                                                        waddch(dialog, ' '); 
     150                                                        break; 
     151                                                } 
     152                                                waddch(dialog, instr[show_x + i]); 
     153                                        } 
    136154                                        wmove(dialog, box_y, input_x + box_x); 
    137155                                        wrefresh(dialog); 
    138156                                } 
    139157                                continue; 
     158                        case KEY_LEFT: 
     159                                if (pos > 0) { 
     160                                        if (input_x > 0) { 
     161                                                wmove(dialog, box_y, --input_x + box_x); 
     162                                        } else if (input_x == 0) { 
     163                                                show_x--; 
     164                                                wmove(dialog, box_y, box_x); 
     165                                                for (i = 0; i < box_width; i++) { 
     166                                                        if (!instr[show_x + i]) { 
     167                                                                waddch(dialog, ' '); 
     168                                                                break; 
     169                                                        } 
     170                                                        waddch(dialog, instr[show_x + i]); 
     171                                                } 
     172                                                wmove(dialog, box_y, box_x); 
     173                                        } 
     174                                        pos--; 
     175                                } 
     176                                continue; 
     177                        case KEY_RIGHT: 
     178                                if (pos < len) { 
     179                                        if (input_x < box_width - 1) { 
     180                                                wmove(dialog, box_y, ++input_x + box_x); 
     181                                        } else if (input_x == box_width - 1) { 
     182                                                show_x++; 
     183                                                wmove(dialog, box_y, box_x); 
     184                                                for (i = 0; i < box_width; i++) { 
     185                                                        if (!instr[show_x + i]) { 
     186                                                                waddch(dialog, ' '); 
     187                                                                break; 
     188                                                        } 
     189                                                        waddch(dialog, instr[show_x + i]); 
     190                                                } 
     191                                                wmove(dialog, box_y, input_x + box_x); 
     192                                        } 
     193                                        pos++; 
     194                                } 
     195                                continue; 
    140196                        default: 
    141197                                if (key < 0x100 && isprint(key)) { 
    142                                         if (scroll + input_x < MAX_LEN) { 
    143                                                 wattrset(dialog, inputbox_attr); 
    144                                                 instr[scroll + input_x] = key; 
    145                                                 instr[scroll + input_x + 1] = '\0'; 
     198                                        if (len < MAX_LEN) { 
     199                                                wattrset(dialog, dlg.inputbox.atr); 
     200                                                if (pos < len) { 
     201                                                        for (i = len; i > pos; i--) 
     202                                                                instr[i] = instr[i-1]; 
     203                                                        instr[pos] = key; 
     204                                                } else { 
     205                                                        instr[len] = key; 
     206                                                } 
     207                                                pos++; 
     208                                                len++; 
     209                                                instr[len] = '\0'; 
     210 
    146211                                                if (input_x == box_width - 1) { 
    147                                                         scroll++; 
    148                                                         wmove(dialog, box_y, box_x); 
    149                                                         for (i = 0; i < box_width - 1; i++) 
    150                                                                 waddch(dialog, instr [scroll + i]); 
     212                                                        show_x++; 
    151213                                                } else { 
    152                                                         wmove(dialog, box_y, input_x++ + box_x); 
    153                                                         waddch(dialog, key); 
    154                                                 } 
     214                                                        input_x++; 
     215                                                } 
     216 
     217                                                wmove(dialog, box_y, box_x); 
     218                                                for (i = 0; i < box_width; i++) { 
     219                                                        if (!instr[show_x + i]) { 
     220                                                                waddch(dialog, ' '); 
     221                                                                break; 
     222                                                        } 
     223                                                        waddch(dialog, instr[show_x + i]); 
     224                                                } 
     225                                                wmove(dialog, box_y, input_x + box_x); 
    155226                                                wrefresh(dialog); 
    156227                                        } else 
     
    173244                        switch (button) { 
    174245                        case -1: 
    175                                 button = 1;     /* Indicates "Cancel" button is selected */ 
     246                                button = 1;     /* Indicates "Help" button is selected */ 
    176247                                print_buttons(dialog, height, width, 1); 
    177248                                break; 
     
    197268                                break; 
    198269                        case 0: 
    199                                 button = 1;     /* Indicates "Cancel" button is selected */ 
     270                                button = 1;     /* Indicates "Help" button is selected */ 
    200271                                print_buttons(dialog, height, width, 1); 
    201272                                break; 
     
    214285                case 'X': 
    215286                case 'x': 
    216                         key = ESC; 
    217                 case ESC: 
     287                        key = KEY_ESC; 
    218288                        break; 
     289                case KEY_ESC: 
     290                        key = on_key_esc(dialog); 
     291                        break; 
     292                case KEY_RESIZE: 
     293                        delwin(dialog); 
     294                        on_key_resize(); 
     295                        goto do_resize; 
    219296                } 
    220297        } 
    221298 
    222299        delwin(dialog); 
    223         return -1;              /* ESC pressed */ 
     300        return KEY_ESC;         /* ESC pressed */ 
    224301} 
  • trunk/scripts/config/lxdialog/menubox.c

    r6502 r36361  
    2727 *    *)  A bugfix for the Page-Down problem 
    2828 * 
    29  *    *)  Formerly when I used Page Down and Page Up, the cursor would be set  
     29 *    *)  Formerly when I used Page Down and Page Up, the cursor would be set 
    3030 *        to the first position in the menu box.  Now lxdialog is a bit 
    3131 *        smarter and works more like other menu systems (just have a look at 
     
    5959#include "dialog.h" 
    6060 
    61 #define ITEM_IDENT 1   /* Indent of menu entries. Fixed for all menus */ 
    62 static int menu_width; 
     61static int menu_width, item_x; 
    6362 
    6463/* 
    6564 * Print menu item 
    6665 */ 
    67 static void do_print_item(WINDOW * win, const char *item, int choice, 
     66static void do_print_item(WINDOW * win, const char *item, int line_y, 
    6867                          int selected, int hotkey) 
    6968{ 
     
    7170        char *menu_item = malloc(menu_width + 1); 
    7271 
    73         strncpy(menu_item, item, menu_width - ITEM_IDENT); 
    74         menu_item[menu_width] = 0; 
     72        strncpy(menu_item, item, menu_width - item_x); 
     73        menu_item[menu_width - item_x] = '\0'; 
    7574        j = first_alpha(menu_item, "YyNnMmHh"); 
    7675 
    7776        /* Clear 'residue' of last item */ 
    78         wattrset(win, menubox_attr); 
    79         wmove(win, choice, 0); 
     77        wattrset(win, dlg.menubox.atr); 
     78        wmove(win, line_y, 0); 
    8079#if OLD_NCURSES 
    8180        { 
     
    8786        wclrtoeol(win); 
    8887#endif 
    89         wattrset(win, selected ? item_selected_attr : item_attr); 
    90         mvwaddstr(win, choice, ITEM_IDENT, menu_item); 
     88        wattrset(win, selected ? dlg.item_selected.atr : dlg.item.atr); 
     89        mvwaddstr(win, line_y, item_x, menu_item); 
    9190        if (hotkey) { 
    92                 wattrset(win, selected ? tag_key_selected_attr : tag_key_attr); 
    93                 mvwaddch(win, choice, ITEM_IDENT + j, menu_item[j]); 
     91                wattrset(win, selected ? dlg.tag_key_selected.atr 
     92                         : dlg.tag_key.atr); 
     93                mvwaddch(win, line_y, item_x + j, menu_item[j]); 
    9494        } 
    9595        if (selected) { 
    96                 wmove(win, choice, ITEM_IDENT + 1); 
     96                wmove(win, line_y, item_x + 1); 
    9797        } 
    9898        free(menu_item); 
     
    100100} 
    101101 
    102 #define print_item(index, choice, selected) \ 
    103 do {\ 
    104         int hotkey = (items[(index) * 2][0] != ':'); \ 
    105         do_print_item(menu, items[(index) * 2 + 1], choice, selected, hotkey); \ 
     102#define print_item(index, choice, selected)                             \ 
     103do {                                                                    \ 
     104        item_set(index);                                                \ 
     105        do_print_item(menu, item_str(), choice, selected, !item_is_tag(':')); \ 
    106106} while (0) 
    107107 
     
    119119 
    120120        if (scroll > 0) { 
    121                 wattrset(win, uarrow_attr); 
     121                wattrset(win, dlg.uarrow.atr); 
    122122                waddch(win, ACS_UARROW); 
    123123                waddstr(win, "(-)"); 
    124124        } else { 
    125                 wattrset(win, menubox_attr); 
     125                wattrset(win, dlg.menubox.atr); 
    126126                waddch(win, ACS_HLINE); 
    127127                waddch(win, ACS_HLINE); 
     
    135135 
    136136        if ((height < item_no) && (scroll + height < item_no)) { 
    137                 wattrset(win, darrow_attr); 
     137                wattrset(win, dlg.darrow.atr); 
    138138                waddch(win, ACS_DARROW); 
    139139                waddstr(win, "(+)"); 
    140140        } else { 
    141                 wattrset(win, menubox_border_attr); 
     141                wattrset(win, dlg.menubox_border.atr); 
    142142                waddch(win, ACS_HLINE); 
    143143                waddch(win, ACS_HLINE); 
     
    155155static void print_buttons(WINDOW * win, int height, int width, int selected) 
    156156{ 
    157         int x = width / 2 - 16; 
     157        int x = width / 2 - 28; 
    158158        int y = height - 2; 
    159159 
    160         print_button(win, "Select", y, x, selected == 0); 
    161         print_button(win, " Exit ", y, x + 12, selected == 1); 
    162         print_button(win, " Help ", y, x + 24, selected == 2); 
     160        print_button(win, gettext("Select"), y, x, selected == 0); 
     161        print_button(win, gettext(" Exit "), y, x + 12, selected == 1); 
     162        print_button(win, gettext(" Help "), y, x + 24, selected == 2); 
     163        print_button(win, gettext(" Save "), y, x + 36, selected == 3); 
     164        print_button(win, gettext(" Load "), y, x + 48, selected == 4); 
    163165 
    164166        wmove(win, y, x + 1 + 12 * selected); 
     
    180182 * Display a menu for choosing among a number of options 
    181183 */ 
    182 int dialog_menu(const char *title, const char *prompt, int height, int width, 
    183                 int menu_height, const char *current, int item_no, 
    184                 const char *const *items) 
     184int dialog_menu(const char *title, const char *prompt, 
     185                const void *selected, int *s_scroll) 
    185186{ 
    186187        int i, j, x, y, box_x, box_y; 
     188        int height, width, menu_height; 
    187189        int key = 0, button = 0, scroll = 0, choice = 0; 
    188190        int first_item =  0, max_choice; 
    189191        WINDOW *dialog, *menu; 
    190         FILE *f; 
    191  
    192         max_choice = MIN(menu_height, item_no); 
     192 
     193do_resize: 
     194        height = getmaxy(stdscr); 
     195        width = getmaxx(stdscr); 
     196        if (height < 15 || width < 65) 
     197                return -ERRDISPLAYTOOSMALL; 
     198 
     199        height -= 4; 
     200        width  -= 5; 
     201        menu_height = height - 10; 
     202 
     203        max_choice = MIN(menu_height, item_count()); 
    193204 
    194205        /* center dialog box on screen */ 
     
    201212        keypad(dialog, TRUE); 
    202213 
    203         draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr); 
    204         wattrset(dialog, border_attr); 
     214        draw_box(dialog, 0, 0, height, width, 
     215                 dlg.dialog.atr, dlg.border.atr); 
     216        wattrset(dialog, dlg.border.atr); 
    205217        mvwaddch(dialog, height - 3, 0, ACS_LTEE); 
    206218        for (i = 0; i < width - 2; i++) 
    207219                waddch(dialog, ACS_HLINE); 
    208         wattrset(dialog, dialog_attr); 
    209         wbkgdset(dialog, dialog_attr & A_COLOR); 
     220        wattrset(dialog, dlg.dialog.atr); 
     221        wbkgdset(dialog, dlg.dialog.atr & A_COLOR); 
    210222        waddch(dialog, ACS_RTEE); 
    211223 
    212224        print_title(dialog, title, width); 
    213225 
    214         wattrset(dialog, dialog_attr); 
     226        wattrset(dialog, dlg.dialog.atr); 
    215227        print_autowrap(dialog, prompt, width - 2, 1, 3); 
    216228 
     
    226238        /* draw a box around the menu items */ 
    227239        draw_box(dialog, box_y, box_x, menu_height + 2, menu_width + 2, 
    228                  menubox_border_attr, menubox_attr); 
     240                 dlg.menubox_border.atr, dlg.menubox.atr); 
     241 
     242        if (menu_width >= 80) 
     243                item_x = (menu_width - 70) / 2; 
     244        else 
     245                item_x = 4; 
    229246 
    230247        /* Set choice to default item */ 
    231         for (i = 0; i < item_no; i++) 
    232                 if (strcmp(current, items[i * 2]) == 0) 
    233                         choice = i; 
    234  
    235         /* get the scroll info from the temp file */ 
    236         if ((f = fopen("lxdialog.scrltmp", "r")) != NULL) { 
    237                 if ((fscanf(f, "%d\n", &scroll) == 1) && (scroll <= choice) && 
    238                     (scroll + max_choice > choice) && (scroll >= 0) && 
    239                     (scroll + max_choice <= item_no)) { 
    240                         first_item = scroll; 
    241                         choice = choice - scroll; 
    242                         fclose(f); 
    243                 } else { 
    244                         scroll = 0; 
    245                         remove("lxdialog.scrltmp"); 
    246                         fclose(f); 
    247                         f = NULL; 
    248                 } 
    249         } 
    250         if ((choice >= max_choice) || (f == NULL && choice >= max_choice / 2)) { 
    251                 if (choice >= item_no - max_choice / 2) 
    252                         scroll = first_item = item_no - max_choice; 
     248        item_foreach() 
     249                if (selected && (selected == item_data())) 
     250                        choice = item_n(); 
     251        /* get the saved scroll info */ 
     252        scroll = *s_scroll; 
     253        if ((scroll <= choice) && (scroll + max_choice > choice) && 
     254           (scroll >= 0) && (scroll + max_choice <= item_count())) { 
     255                first_item = scroll; 
     256                choice = choice - scroll; 
     257        } else { 
     258                scroll = 0; 
     259        } 
     260        if ((choice >= max_choice)) { 
     261                if (choice >= item_count() - max_choice / 2) 
     262                        scroll = first_item = item_count() - max_choice; 
    253263                else 
    254264                        scroll = first_item = choice - max_choice / 2; 
     
    263273        wnoutrefresh(menu); 
    264274 
    265         print_arrows(dialog, item_no, scroll, 
    266                      box_y, box_x + ITEM_IDENT + 1, menu_height); 
     275        print_arrows(dialog, item_count(), scroll, 
     276                     box_y, box_x + item_x + 1, menu_height); 
    267277 
    268278        print_buttons(dialog, height, width, 0); 
    269         wmove(menu, choice, ITEM_IDENT + 1); 
     279        wmove(menu, choice, item_x + 1); 
    270280        wrefresh(menu); 
    271281 
    272         while (key != ESC) { 
     282        while (key != KEY_ESC) { 
    273283                key = wgetch(menu); 
    274284 
     
    280290                else { 
    281291                        for (i = choice + 1; i < max_choice; i++) { 
    282                                 j = first_alpha(items[(scroll + i) * 2 + 1], "YyNnMmHh"); 
    283                                 if (key == tolower(items[(scroll + i) * 2 + 1][j])) 
     292                                item_set(scroll + i); 
     293                                j = first_alpha(item_str(), "YyNnMmHh"); 
     294                                if (key == tolower(item_str()[j])) 
    284295                                        break; 
    285296                        } 
    286297                        if (i == max_choice) 
    287298                                for (i = 0; i < max_choice; i++) { 
    288                                         j = first_alpha(items [(scroll + i) * 2 + 1], "YyNnMmHh"); 
    289                                         if (key == tolower(items[(scroll + i) * 2 + 1][j])) 
     299                                        item_set(scroll + i); 
     300                                        j = first_alpha(item_str(), "YyNnMmHh"); 
     301                                        if (key == tolower(item_str()[j])) 
    290302                                                break; 
    291303                                } 
     
    312324 
    313325                                if ((choice > max_choice - 3) && 
    314                                     (scroll + max_choice < item_no)) { 
     326                                    (scroll + max_choice < item_count())) { 
    315327                                        /* Scroll menu up */ 
    316328                                        do_scroll(menu, &scroll, 1); 
     
    335347                        } else if (key == KEY_NPAGE) { 
    336348                                for (i = 0; (i < max_choice); i++) { 
    337                                         if (scroll + max_choice < item_no) { 
     349                                        if (scroll + max_choice < item_count()) { 
    338350                                                do_scroll(menu, &scroll, 1); 
    339351                                                print_item(scroll+max_choice-1, 
     
    349361                        print_item(scroll + choice, choice, TRUE); 
    350362 
    351                         print_arrows(dialog, item_no, scroll, 
    352                                      box_y, box_x + ITEM_IDENT + 1, menu_height); 
     363                        print_arrows(dialog, item_count(), scroll, 
     364                                     box_y, box_x + item_x + 1, menu_height); 
    353365 
    354366                        wnoutrefresh(dialog); 
     
    363375                case KEY_RIGHT: 
    364376                        button = ((key == KEY_LEFT ? --button : ++button) < 0) 
    365                             ? 2 : (button > 2 ? 0 : button); 
     377                            ? 4 : (button > 4 ? 0 : button); 
    366378 
    367379                        print_buttons(dialog, height, width, button); 
     
    374386                case 'm': 
    375387                case '/': 
     388                case 'h': 
     389                case '?': 
     390                case 'z': 
     391                case '\n': 
    376392                        /* save scroll info */ 
    377                         if ((f = fopen("lxdialog.scrltmp", "w")) != NULL) { 
    378                                 fprintf(f, "%d\n", scroll); 
    379                                 fclose(f); 
    380                         } 
     393                        *s_scroll = scroll; 
     394                        delwin(menu); 
    381395                        delwin(dialog); 
    382                         fprintf(stderr, "%s\n", items[(scroll + choice) * 2]); 
     396                        item_set(scroll + choice); 
     397                        item_set_selected(1); 
    383398                        switch (key) { 
     399                        case 'h': 
     400                        case '?': 
     401                                return 2; 
    384402                        case 's': 
    385                                 return 3; 
    386403                        case 'y': 
    387                                 return 3; 
     404                                return 5; 
    388405                        case 'n': 
    389                                 return 4; 
     406                                return 6; 
    390407                        case 'm': 
    391                                 return 5; 
     408                                return 7; 
    392409                        case ' ': 
    393                                 return 6; 
     410                                return 8; 
    394411                        case '/': 
    395                                 return 7; 
     412                                return 9; 
     413                        case 'z': 
     414                                return 10; 
     415                        case '\n': 
     416                                return button; 
    396417                        } 
    397418                        return 0; 
    398                 case 'h': 
    399                 case '?': 
    400                         button = 2; 
    401                 case '\n': 
    402                         delwin(dialog); 
    403                         if (button == 2) 
    404                                 fprintf(stderr, "%s \"%s\"\n", 
    405                                         items[(scroll + choice) * 2], 
    406                                         items[(scroll + choice) * 2 + 1] + 
    407                                         first_alpha(items [(scroll + choice) * 2 + 1], "")); 
    408                         else 
    409                                 fprintf(stderr, "%s\n", 
    410                                         items[(scroll + choice) * 2]); 
    411  
    412                         remove("lxdialog.scrltmp"); 
    413                         return button; 
    414419                case 'e': 
    415420                case 'x': 
    416                         key = ESC; 
    417                 case ESC: 
     421                        key = KEY_ESC; 
    418422                        break; 
     423                case KEY_ESC: 
     424                        key = on_key_esc(menu); 
     425                        break; 
     426                case KEY_RESIZE: 
     427                        on_key_resize(); 
     428                        delwin(menu); 
     429                        delwin(dialog); 
     430                        goto do_resize; 
    419431                } 
    420432        } 
    421  
     433        delwin(menu); 
    422434        delwin(dialog); 
    423         remove("lxdialog.scrltmp"); 
    424         return -1;              /* ESC pressed */ 
     435        return key;             /* ESC pressed */ 
    425436} 
  • trunk/scripts/config/lxdialog/textbox.c

    r6502 r36361  
    2323 
    2424static void back_lines(int n); 
    25 static void print_page(WINDOW * win, int height, int width); 
    26 static void print_line(WINDOW * win, int row, int width); 
     25static void print_page(WINDOW *win, int height, int width, update_text_fn 
     26                       update_text, void *data); 
     27static void print_line(WINDOW *win, int row, int width); 
    2728static char *get_line(void); 
    28 static void print_position(WINDOW * win, int height, int width); 
    29  
    30 static int hscroll, fd, file_size, bytes_read; 
    31 static int begin_reached = 1, end_reached, page_length; 
    32 static char *buf, *page; 
     29static void print_position(WINDOW * win); 
     30 
     31static int hscroll; 
     32static int begin_reached, end_reached, page_length; 
     33static char *buf; 
     34static char *page; 
     35 
     36/* 
     37 * refresh window content 
     38 */ 
     39static void refresh_text_box(WINDOW *dialog, WINDOW *box, int boxh, int boxw, 
     40                             int cur_y, int cur_x, update_text_fn update_text, 
     41                             void *data) 
     42{ 
     43        print_page(box, boxh, boxw, update_text, data); 
     44        print_position(dialog); 
     45        wmove(dialog, cur_y, cur_x);    /* Restore cursor position */ 
     46        wrefresh(dialog); 
     47} 
     48 
    3349 
    3450/* 
    3551 * Display text from a file in a dialog box. 
    36  */ 
    37 int dialog_textbox(const char *title, const char *file, int height, int width) 
    38 { 
    39         int i, x, y, cur_x, cur_y, fpos, key = 0; 
    40         int passed_end; 
    41         char search_term[MAX_LEN + 1]; 
    42         WINDOW *dialog, *text; 
    43  
    44         search_term[0] = '\0';  /* no search term entered yet */ 
    45  
    46         /* Open input file for reading */ 
    47         if ((fd = open(file, O_RDONLY)) == -1) { 
    48                 endwin(); 
    49                 fprintf(stderr, "\nCan't open input file in dialog_textbox().\n"); 
    50                 exit(-1); 
    51         } 
    52         /* Get file size. Actually, 'file_size' is the real file size - 1, 
    53            since it's only the last byte offset from the beginning */ 
    54         if ((file_size = lseek(fd, 0, SEEK_END)) == -1) { 
    55                 endwin(); 
    56                 fprintf(stderr, "\nError getting file size in dialog_textbox().\n"); 
    57                 exit(-1); 
    58         } 
    59         /* Restore file pointer to beginning of file after getting file size */ 
    60         if (lseek(fd, 0, SEEK_SET) == -1) { 
    61                 endwin(); 
    62                 fprintf(stderr, "\nError moving file pointer in dialog_textbox().\n"); 
    63                 exit(-1); 
    64         } 
    65         /* Allocate space for read buffer */ 
    66         if ((buf = malloc(BUF_SIZE + 1)) == NULL) { 
    67                 endwin(); 
    68                 fprintf(stderr, "\nCan't allocate memory in dialog_textbox().\n"); 
    69                 exit(-1); 
    70         } 
    71         if ((bytes_read = read(fd, buf, BUF_SIZE)) == -1) { 
    72                 endwin(); 
    73                 fprintf(stderr, "\nError reading file in dialog_textbox().\n"); 
    74                 exit(-1); 
    75         } 
    76         buf[bytes_read] = '\0'; /* mark end of valid data */ 
    77         page = buf;             /* page is pointer to start of page to be displayed */ 
     52 * 
     53 * keys is a null-terminated array 
     54 * update_text() may not add or remove any '\n' or '\0' in tbuf 
     55 */ 
     56int dialog_textbox(const char *title, char *tbuf, int initial_height, 
     57                   int initial_width, int *keys, int *_vscroll, int *_hscroll, 
     58                   update_text_fn update_text, void *data) 
     59{ 
     60        int i, x, y, cur_x, cur_y, key = 0; 
     61        int height, width, boxh, boxw; 
     62        WINDOW *dialog, *box; 
     63        bool done = false; 
     64 
     65        begin_reached = 1; 
     66        end_reached = 0; 
     67        page_length = 0; 
     68        hscroll = 0; 
     69        buf = tbuf; 
     70        page = buf;     /* page is pointer to start of page to be displayed */ 
     71 
     72        if (_vscroll && *_vscroll) { 
     73                begin_reached = 0; 
     74 
     75                for (i = 0; i < *_vscroll; i++) 
     76                        get_line(); 
     77        } 
     78        if (_hscroll) 
     79                hscroll = *_hscroll; 
     80 
     81do_resize: 
     82        getmaxyx(stdscr, height, width); 
     83        if (height < 8 || width < 8) 
     84                return -ERRDISPLAYTOOSMALL; 
     85        if (initial_height != 0) 
     86                height = initial_height; 
     87        else 
     88                if (height > 4) 
     89                        height -= 4; 
     90                else 
     91                        height = 0; 
     92        if (initial_width != 0) 
     93                width = initial_width; 
     94        else 
     95                if (width > 5) 
     96                        width -= 5; 
     97                else 
     98                        width = 0; 
    7899 
    79100        /* center dialog box on screen */ 
     
    86107        keypad(dialog, TRUE); 
    87108 
    88         /* Create window for text region, used for scrolling text */ 
    89         text = subwin(dialog, height - 4, width - 2, y + 1, x + 1); 
    90         wattrset(text, dialog_attr); 
    91         wbkgdset(text, dialog_attr & A_COLOR); 
    92  
    93         keypad(text, TRUE); 
     109        /* Create window for box region, used for scrolling text */ 
     110        boxh = height - 4; 
     111        boxw = width - 2; 
     112        box = subwin(dialog, boxh, boxw, y + 1, x + 1); 
     113        wattrset(box, dlg.dialog.atr); 
     114        wbkgdset(box, dlg.dialog.atr & A_COLOR); 
     115 
     116        keypad(box, TRUE); 
    94117 
    95118        /* register the new window, along with its borders */ 
    96         draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr); 
    97  
    98         wattrset(dialog, border_attr); 
     119        draw_box(dialog, 0, 0, height, width, 
     120                 dlg.dialog.atr, dlg.border.atr); 
     121 
     122        wattrset(dialog, dlg.border.atr); 
    99123        mvwaddch(dialog, height - 3, 0, ACS_LTEE); 
    100124        for (i = 0; i < width - 2; i++) 
    101125                waddch(dialog, ACS_HLINE); 
    102         wattrset(dialog, dialog_attr); 
    103         wbkgdset(dialog, dialog_attr & A_COLOR); 
     126        wattrset(dialog, dlg.dialog.atr); 
     127        wbkgdset(dialog, dlg.dialog.atr & A_COLOR); 
    104128        waddch(dialog, ACS_RTEE); 
    105129 
    106130        print_title(dialog, title, width); 
    107131 
    108         print_button(dialog, " Exit ", height - 2, width / 2 - 4, TRUE); 
     132        print_button(dialog, gettext(" Exit "), height - 2, width / 2 - 4, TRUE); 
    109133        wnoutrefresh(dialog); 
    110134        getyx(dialog, cur_y, cur_x);    /* Save cursor position */ 
    111135 
    112136        /* Print first page of text */ 
    113         attr_clear(text, height - 4, width - 2, dialog_attr); 
    114         print_page(text, height - 4, width - 2); 
    115         print_position(dialog, height, width); 
    116         wmove(dialog, cur_y, cur_x);    /* Restore cursor position */ 
    117         wrefresh(dialog); 
    118  
    119         while ((key != ESC) && (key != '\n')) { 
     137        attr_clear(box, boxh, boxw, dlg.dialog.atr); 
     138        refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x, update_text, 
     139                         data); 
     140 
     141        while (!done) { 
    120142                key = wgetch(dialog); 
    121143                switch (key) { 
     
    124146                case 'X': 
    125147                case 'x': 
    126                         delwin(dialog); 
    127                         free(buf); 
    128                         close(fd); 
    129                         return 0; 
     148                case 'q': 
     149                case '\n': 
     150                        done = true; 
     151                        break; 
    130152                case 'g':       /* First page */ 
    131153                case KEY_HOME: 
    132154                        if (!begin_reached) { 
    133155                                begin_reached = 1; 
    134                                 /* First page not in buffer? */ 
    135                                 if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) { 
    136                                         endwin(); 
    137                                         fprintf(stderr, "\nError moving file pointer in dialog_textbox().\n"); 
    138                                         exit(-1); 
    139                                 } 
    140                                 if (fpos > bytes_read) {        /* Yes, we have to read it in */ 
    141                                         if (lseek(fd, 0, SEEK_SET) == -1) { 
    142                                                 endwin(); 
    143                                                 fprintf(stderr, "\nError moving file pointer in " 
    144                                                                 "dialog_textbox().\n"); 
    145                                                 exit(-1); 
    146                                         } 
    147                                         if ((bytes_read = 
    148                                              read(fd, buf, BUF_SIZE)) == -1) { 
    149                                                 endwin(); 
    150                                                 fprintf(stderr, "\nError reading file in dialog_textbox().\n"); 
    151                                                 exit(-1); 
    152                                         } 
    153                                         buf[bytes_read] = '\0'; 
    154                                 } 
    155156                                page = buf; 
    156                                 print_page(text, height - 4, width - 2); 
    157                                 print_position(dialog, height, width); 
    158                                 wmove(dialog, cur_y, cur_x);    /* Restore cursor position */ 
    159                                 wrefresh(dialog); 
     157                                refresh_text_box(dialog, box, boxh, boxw, 
     158                                                 cur_y, cur_x, update_text, 
     159                                                 data); 
    160160                        } 
    161161                        break; 
     
    164164 
    165165                        end_reached = 1; 
    166                         /* Last page not in buffer? */ 
    167                         if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) { 
    168                                 endwin(); 
    169                                 fprintf(stderr, "\nError moving file pointer in dialog_textbox().\n"); 
    170                                 exit(-1); 
    171                         } 
    172                         if (fpos < file_size) { /* Yes, we have to read it in */ 
    173                                 if (lseek(fd, -BUF_SIZE, SEEK_END) == -1) { 
    174                                         endwin(); 
    175                                         fprintf(stderr, "\nError moving file pointer in dialog_textbox().\n"); 
    176                                         exit(-1); 
    177                                 } 
    178                                 if ((bytes_read = 
    179                                      read(fd, buf, BUF_SIZE)) == -1) { 
    180                                         endwin(); 
    181                                         fprintf(stderr, "\nError reading file in dialog_textbox().\n"); 
    182                                         exit(-1); 
    183                                 } 
    184                                 buf[bytes_read] = '\0'; 
    185                         } 
    186                         page = buf + bytes_read; 
    187                         back_lines(height - 4); 
    188                         print_page(text, height - 4, width - 2); 
    189                         print_position(dialog, height, width); 
    190                         wmove(dialog, cur_y, cur_x);    /* Restore cursor position */ 
    191                         wrefresh(dialog); 
     166                        /* point to last char in buf */ 
     167                        page = buf + strlen(buf); 
     168                        back_lines(boxh); 
     169                        refresh_text_box(dialog, box, boxh, boxw, cur_y, 
     170                                         cur_x, update_text, data); 
    192171                        break; 
    193172                case 'K':       /* Previous line */ 
    194173                case 'k': 
    195174                case KEY_UP: 
    196                         if (!begin_reached) { 
    197                                 back_lines(page_length + 1); 
    198  
    199                                 /* We don't call print_page() here but use scrolling to ensure 
    200                                    faster screen update. However, 'end_reached' and 
    201                                    'page_length' should still be updated, and 'page' should 
    202                                    point to start of next page. This is done by calling 
    203                                    get_line() in the following 'for' loop. */ 
    204                                 scrollok(text, TRUE); 
    205                                 wscrl(text, -1);        /* Scroll text region down one line */ 
    206                                 scrollok(text, FALSE); 
    207                                 page_length = 0; 
    208                                 passed_end = 0; 
    209                                 for (i = 0; i < height - 4; i++) { 
    210                                         if (!i) { 
    211                                                 /* print first line of page */ 
    212                                                 print_line(text, 0, width - 2); 
    213                                                 wnoutrefresh(text); 
    214                                         } else 
    215                                                 /* Called to update 'end_reached' and 'page' */ 
    216                                                 get_line(); 
    217                                         if (!passed_end) 
    218                                                 page_length++; 
    219                                         if (end_reached && !passed_end) 
    220                                                 passed_end = 1; 
    221                                 } 
    222  
    223                                 print_position(dialog, height, width); 
    224                                 wmove(dialog, cur_y, cur_x);    /* Restore cursor position */ 
    225                                 wrefresh(dialog); 
    226                         } 
     175                        if (begin_reached) 
     176                                break; 
     177 
     178                        back_lines(page_length + 1); 
     179                        refresh_text_box(dialog, box, boxh, boxw, cur_y, 
     180                                         cur_x, update_text, data); 
    227181                        break; 
    228182                case 'B':       /* Previous page */ 
    229183                case 'b': 
     184                case 'u': 
    230185                case KEY_PPAGE: 
    231186                        if (begin_reached) 
    232187                                break; 
    233                         back_lines(page_length + height - 4); 
    234                         print_page(text, height - 4, width - 2); 
    235                         print_position(dialog, height, width); 
    236                         wmove(dialog, cur_y, cur_x); 
    237                         wrefresh(dialog); 
     188                        back_lines(page_length + boxh); 
     189                        refresh_text_box(dialog, box, boxh, boxw, cur_y, 
     190                                         cur_x, update_text, data); 
    238191                        break; 
    239192                case 'J':       /* Next line */ 
    240193                case 'j': 
    241194                case KEY_DOWN: 
    242                         if (!end_reached) { 
    243                                 begin_reached = 0; 
    244                                 scrollok(text, TRUE); 
    245                                 scroll(text);   /* Scroll text region up one line */ 
    246                                 scrollok(text, FALSE); 
    247                                 print_line(text, height - 5, width - 2); 
    248                                 wnoutrefresh(text); 
    249                                 print_position(dialog, height, width); 
    250                                 wmove(dialog, cur_y, cur_x);    /* Restore cursor position */ 
    251                                 wrefresh(dialog); 
    252                         } 
     195                        if (end_reached) 
     196                                break; 
     197 
     198                        back_lines(page_length - 1); 
     199                        refresh_text_box(dialog, box, boxh, boxw, cur_y, 
     200                                         cur_x, update_text, data); 
    253201                        break; 
    254202                case KEY_NPAGE: /* Next page */ 
    255203                case ' ': 
     204                case 'd': 
    256205                        if (end_reached) 
    257206                                break; 
    258207 
    259208                        begin_reached = 0; 
    260                         print_page(text, height - 4, width - 2); 
    261                         print_position(dialog, height, width); 
    262                         wmove(dialog, cur_y, cur_x); 
    263                         wrefresh(dialog); 
     209                        refresh_text_box(dialog, box, boxh, boxw, cur_y, 
     210                                         cur_x, update_text, data); 
    264211                        break; 
    265212                case '0':       /* Beginning of line */ 
     
    276223                        /* Reprint current page to scroll horizontally */ 
    277224                        back_lines(page_length); 
    278                         print_page(text, height - 4, width - 2); 
    279                         wmove(dialog, cur_y, cur_x); 
    280                         wrefresh(dialog); 
     225                        refresh_text_box(dialog, box, boxh, boxw, cur_y, 
     226                                         cur_x, update_text, data); 
    281227                        break; 
    282228                case 'L':       /* Scroll right */ 
     
    288234                        /* Reprint current page to scroll horizontally */ 
    289235                        back_lines(page_length); 
    290                         print_page(text, height - 4, width - 2); 
    291                         wmove(dialog, cur_y, cur_x); 
    292                         wrefresh(dialog); 
    293                         break; 
    294                 case ESC: 
    295                         break; 
     236                        refresh_text_box(dialog, box, boxh, boxw, cur_y, 
     237                                         cur_x, update_text, data); 
     238                        break; 
     239                case KEY_ESC: 
     240                        if (on_key_esc(dialog) == KEY_ESC) 
     241                                done = true; 
     242                        break; 
     243                case KEY_RESIZE: 
     244                        back_lines(height); 
     245                        delwin(box); 
     246                        delwin(dialog); 
     247                        on_key_resize(); 
     248                        goto do_resize; 
     249                default: 
     250                        for (i = 0; keys[i]; i++) { 
     251                                if (key == keys[i]) { 
     252                                        done = true; 
     253                                        break; 
     254                                } 
     255                        } 
    296256                } 
    297257        } 
    298  
     258        delwin(box); 
    299259        delwin(dialog); 
    300         free(buf); 
    301         close(fd); 
    302         return -1;              /* ESC pressed */ 
    303 } 
    304  
    305 /* 
    306  * Go back 'n' lines in text file. Called by dialog_textbox(). 
     260        if (_vscroll) { 
     261                const char *s; 
     262 
     263                s = buf; 
     264                *_vscroll = 0; 
     265                back_lines(page_length); 
     266                while (s < page && (s = strchr(s, '\n'))) { 
     267                        (*_vscroll)++; 
     268                        s++; 
     269                } 
     270        } 
     271        if (_hscroll) 
     272                *_hscroll = hscroll; 
     273        return key; 
     274} 
     275 
     276/* 
     277 * Go back 'n' lines in text. Called by dialog_textbox(). 
    307278 * 'page' will be updated to point to the desired line in 'buf'. 
    308279 */ 
    309280static void back_lines(int n) 
    310281{ 
    311         int i, fpos; 
     282        int i; 
    312283 
    313284        begin_reached = 0; 
    314         /* We have to distinguish between end_reached and !end_reached 
    315            since at end of file, the line is not ended by a '\n'. 
    316            The code inside 'if' basically does a '--page' to move one 
    317            character backward so as to skip '\n' of the previous line */ 
    318         if (!end_reached) { 
    319                 /* Either beginning of buffer or beginning of file reached? */ 
     285        /* Go back 'n' lines */ 
     286        for (i = 0; i < n; i++) { 
     287                if (*page == '\0') { 
     288                        if (end_reached) { 
     289                                end_reached = 0; 
     290                                continue; 
     291                        } 
     292                } 
    320293                if (page == buf) { 
    321                         if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) { 
    322                                 endwin(); 
    323                                 fprintf(stderr, "\nError moving file pointer in " 
    324                                                 "back_lines().\n"); 
    325                                 exit(-1); 
    326                         } 
    327                         if (fpos > bytes_read) {        /* Not beginning of file yet */ 
    328                                 /* We've reached beginning of buffer, but not beginning of 
    329                                    file yet, so read previous part of file into buffer. 
    330                                    Note that we only move backward for BUF_SIZE/2 bytes, 
    331                                    but not BUF_SIZE bytes to avoid re-reading again in 
    332                                    print_page() later */ 
    333                                 /* Really possible to move backward BUF_SIZE/2 bytes? */ 
    334                                 if (fpos < BUF_SIZE / 2 + bytes_read) { 
    335                                         /* No, move less then */ 
    336                                         if (lseek(fd, 0, SEEK_SET) == -1) { 
    337                                                 endwin(); 
    338                                                 fprintf(stderr, "\nError moving file pointer in " 
    339                                                                 "back_lines().\n"); 
    340                                                 exit(-1); 
    341                                         } 
    342                                         page = buf + fpos - bytes_read; 
    343                                 } else {        /* Move backward BUF_SIZE/2 bytes */ 
    344                                         if (lseek (fd, -(BUF_SIZE / 2 + bytes_read), SEEK_CUR) == -1) { 
    345                                                 endwin(); 
    346                                                 fprintf(stderr, "\nError moving file pointer " 
    347                                                                 "in back_lines().\n"); 
    348                                                 exit(-1); 
    349                                         } 
    350                                         page = buf + BUF_SIZE / 2; 
    351                                 } 
    352                                 if ((bytes_read = 
    353                                      read(fd, buf, BUF_SIZE)) == -1) { 
    354                                         endwin(); 
    355                                         fprintf(stderr, "\nError reading file in back_lines().\n"); 
    356                                         exit(-1); 
    357                                 } 
    358                                 buf[bytes_read] = '\0'; 
    359                         } else {        /* Beginning of file reached */ 
     294                        begin_reached = 1; 
     295                        return; 
     296                } 
     297                page--; 
     298                do { 
     299                        if (page == buf) { 
    360300                                begin_reached = 1; 
    361301                                return; 
    362302                        } 
    363                 } 
    364                 if (*(--page) != '\n') {        /* '--page' here */ 
    365                         /* Something's wrong... */ 
    366                         endwin(); 
    367                         fprintf(stderr, "\nInternal error in back_lines().\n"); 
    368                         exit(-1); 
    369                 } 
    370         } 
    371         /* Go back 'n' lines */ 
    372         for (i = 0; i < n; i++) 
    373                 do { 
    374                         if (page == buf) { 
    375                                 if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) { 
    376                                         endwin(); 
    377                                         fprintf(stderr, "\nError moving file pointer in back_lines().\n"); 
    378                                         exit(-1); 
    379                                 } 
    380                                 if (fpos > bytes_read) { 
    381                                         /* Really possible to move backward BUF_SIZE/2 bytes? */ 
    382                                         if (fpos < BUF_SIZE / 2 + bytes_read) { 
    383                                                 /* No, move less then */ 
    384                                                 if (lseek(fd, 0, SEEK_SET) == -1) { 
    385                                                         endwin(); 
    386                                                         fprintf(stderr, "\nError moving file pointer " 
    387                                                                         "in back_lines().\n"); 
    388                                                         exit(-1); 
    389                                                 } 
    390                                                 page = buf + fpos - bytes_read; 
    391                                         } else {        /* Move backward BUF_SIZE/2 bytes */ 
    392                                                 if (lseek (fd, -(BUF_SIZE / 2 + bytes_read), SEEK_CUR) == -1) { 
    393                                                         endwin(); 
    394                                                         fprintf(stderr, "\nError moving file pointer" 
    395                                                                         " in back_lines().\n"); 
    396                                                         exit(-1); 
    397                                                 } 
    398                                                 page = buf + BUF_SIZE / 2; 
    399                                         } 
    400                                         if ((bytes_read = 
    401                                              read(fd, buf, BUF_SIZE)) == -1) { 
    402                                                 endwin(); 
    403                                                 fprintf(stderr, "\nError reading file in " 
    404                                                                 "back_lines().\n"); 
    405                                                 exit(-1); 
    406                                         } 
    407                                         buf[bytes_read] = '\0'; 
    408                                 } else {        /* Beginning of file reached */ 
    409                                         begin_reached = 1; 
    410                                         return; 
    411                                 } 
    412                         } 
    413                 } while (*(--page) != '\n'); 
    414         page++; 
    415 } 
    416  
    417 /* 
    418  * Print a new page of text. Called by dialog_textbox(). 
    419  */ 
    420 static void print_page(WINDOW * win, int height, int width) 
     303                        page--; 
     304                } while (*page != '\n'); 
     305                page++; 
     306        } 
     307} 
     308 
     309/* 
     310 * Print a new page of text. 
     311 */ 
     312static void print_page(WINDOW *win, int height, int width, update_text_fn 
     313                       update_text, void *data) 
    421314{ 
    422315        int i, passed_end = 0; 
     316 
     317        if (update_text) { 
     318                char *end; 
     319 
     320                for (i = 0; i < height; i++) 
     321                        get_line(); 
     322                end = page; 
     323                back_lines(height); 
     324                update_text(buf, page - buf, end - buf, data); 
     325        } 
    423326 
    424327        page_length = 0; 
     
    434337 
    435338/* 
    436  * Print a new line of text. Called by dialog_textbox() and print_page().