Hi, 

[ Just lurking on d-i for a while, to get up to speed on the design
before contributing].

Why do you use DEBCONF_LANG rather than LANG or LC_ALL ?

Similarly, in some parts of the installer, there is a need to find the
Country. Shouldn't that be found from LC_ALL as well?

Regards,
Alastair McKinstry


On Sat, 2002-11-09 at 03:05, Denis Barbier wrote:
> Here is an improved patch, it has been tested and looks fine.
> Currently language choice is performed by a DEBCONF_LANG environment
> variable.
> In src/modules/db/textdb/textdb.c, the textdb_template_get_real needs
> more work.
> 
> Denis
> ----
> 

> Index: debian/changelog
> ===================================================================
> RCS file: /cvs/debian-boot/debian-installer/tools/cdebconf/debian/changelog,v
> retrieving revision 1.40
> diff -u -r1.40 changelog
> --- debian/changelog  6 Nov 2002 10:11:37 -0000       1.40
> +++ debian/changelog  9 Nov 2002 01:21:18 -0000
> @@ -29,6 +29,13 @@
>      - fix confmodule.c and commands.c to not use fixed-size
>        buffers. (closes: #167312)
>    * Denis Barbier:
> +    - change internal template structure in src/template.h in order
> +      to help managing localized fields, and fix doc/modules.txt
> +      accordingly
> +    - define accessors to get and set template values, should be used
> +      everywhere instead of direct access to structure members
> +    - partially handle localized fields, only UTF-8 templates files
> +      are considered
>      - convert to po-debconf, set Build-Depends: debhelper (>= 4.1.13)
>        to ensure that generated templates are right, and set output encoding
>        to UTF-8.
> Index: doc/modules.txt
> ===================================================================
> RCS file: /cvs/debian-boot/debian-installer/tools/cdebconf/doc/modules.txt,v
> retrieving revision 1.7
> diff -u -r1.7 modules.txt
> --- doc/modules.txt   1 Jul 2002 06:58:37 -0000       1.7
> +++ doc/modules.txt   9 Nov 2002 01:21:18 -0000
> @@ -36,20 +36,37 @@
>  A template has the following publically accessible fields:
>  
>  - char *tag: the template's tag
> -- char *type: the template's type XXX can be one of ...
> -- char *defaultval: the template's default value, as a string
> -- char *choices: if the template's type is choices based, here the choices
> -                 are listed in a single string, seperated by commas XXX right?
> -- char *description: a description of the template XXX must be under ... chars?
> -- char *extended_description: a longer description 
> -- struct language_description *localized descriptions - has following fields:
> -  - struct language_description *next: NULL or another localized description
> -  - char *language: ISO tag for language XXX right?
> -  - char *choices, char *description, char *extended_description: as above,
> -    only in specified language
> -  
> +- char *type: the template's type, can be one of select, multiselect,
> +              string, boolean, note, text and password
> +- struct template_l10n_fields *fields - has following fields:
> +  - struct template_l10n_fields *next: NULL or another localized field
> +                                       structure
> +  - char *language: ISO code for language (ll or ll_LL)
> +  - char *defaultval: the template's default value, as a string
> +  - char *choices: if the template's type is choices based, here the choices
> +                   are listed in a single string, seperated by commas
> +  - char *description: a description of the template XXX must be under ... chars?
> +  - char *extended_description: a longer description 
> +
> +The first template_l10n_fields structure must always be in English, and
> +its ISO code is set to C.
> +
>  XXX not covering "next", I assume it is private
>  XXX not covering memory management or deletion
> +
> +Publically accessible methods:
> +
> +const char *lget(struct template *, const char *lang, const char *field):
> +   Return a string value for given field in a language, or NULL if not found
> +
> +void lset(struct template *, const char *lang, const char *field, const char 
>*value):
> +   Save string value at field for a given language
> +
> +const char *get(struct template *, const char *field):
> +   Return a string value for given field in English
> +
> +void set(struct template *, const char *field, const char *value):
> +   Save string value at English field
>  
>  question API
>  ~~~~~~~~~~~~
> Index: src/commands.c
> ===================================================================
> RCS file: /cvs/debian-boot/debian-installer/tools/cdebconf/src/commands.c,v
> retrieving revision 1.24
> diff -u -r1.24 commands.c
> --- src/commands.c    5 Nov 2002 02:55:13 -0000       1.24
> +++ src/commands.c    9 Nov 2002 01:21:18 -0000
> @@ -614,14 +614,14 @@
>               if (strcmp(field, "value") == 0)
>                       snprintf(out, outsize, "%u %s", CMDSTATUS_SUCCESS, q->value);
>               else if (strcmp(field, "description") == 0)
> -                     snprintf(out, outsize, "%u %s", CMDSTATUS_SUCCESS, 
>question_description(q));
> +                     snprintf(out, outsize, "%u %s", CMDSTATUS_SUCCESS, 
>question_get_translated_field(q, field));
>               else if (strcmp(field, "extended_description") == 0)
>                       /* NOTE: this probably is wrong, because the extended
>                        * description is likely multiline
>                        */
> -                     snprintf(out, outsize, "%u %s", CMDSTATUS_SUCCESS, 
>question_extended_description(q));
> +                     snprintf(out, outsize, "%u %s", CMDSTATUS_SUCCESS, 
>question_get_translated_field(q, field));
>               else if (strcmp(field, "choices") == 0)
> -                     snprintf(out, outsize, "%u %s", CMDSTATUS_SUCCESS, 
>question_choices(q));
> +                     snprintf(out, outsize, "%u %s", CMDSTATUS_SUCCESS, 
>question_get_translated_field(q, field));
>               else
>                       snprintf(out, outsize, "%u %s does not exist", 
>CMDSTATUS_BADPARAM, field);
>       }
> Index: src/question.c
> ===================================================================
> RCS file: /cvs/debian-boot/debian-installer/tools/cdebconf/src/question.c,v
> retrieving revision 1.12
> diff -u -r1.12 question.c
> --- src/question.c    7 Aug 2002 16:34:01 -0000       1.12
> +++ src/question.c    9 Nov 2002 01:21:18 -0000
> @@ -43,6 +43,8 @@
>  #include "configuration.h"
>  #include "database.h"
>  
> +static char cur_lang[6] = {0};
> +
>  struct question *question_new(const char *tag)
>  {
>       struct question *q;
> @@ -228,126 +230,44 @@
>       return DC_OK;
>  }
>  
> -/*
> - * Function: getlanguage
> - * Input: none
> - * Output: const char* (size == 3) the language code of the currently 
> - *         selected language
> - * Description: find the currently selected language
> - * Assumptions: config_new and database_new succeeds, 
> - *              debian-installer/language exists
> - */
> -
> -const char *getlanguage()
> -{
> -#if 0   /* FIXME */
> -    static struct database *db = NULL;
> -    static struct configuration *config = NULL;
> -     static char language[3];
> -     /* We need to directly access the configuration, since I couldn't
> -        get debconfclient to work from in here. */
> -     struct question *q2 = NULL;
> -        memset(language,'\0',3);
> -
> -     if (! config) /* Then db isn't set either.. */
> -     {
> -             config = config_new();
> -                if (config == 0) 
> -                        DIE("Error initializing configuration item (%s %d)", 
>__FILE__,__LINE__);
> -             if (config->read(config, DEBCONFCONFIG) == 0)
> -                     DIE("Error reading configuration information");
> -             if ((db = database_new(config)) == 0)
> -                     DIE("Cannot initialize DebConf database");
> -             db->load(db);
> -     }
> -     q2 = db->question_get(db, "debian-installer/language");
> -        if (q2 != NULL) {
> -                if (q2->value != NULL)
> -                        snprintf(language,3,"%.2s",q2->value);
> -                question_deref(q2);
> -        }
> -     return language;
> -#else
> -    return "";
> -#endif
> -}
> -
> -const char *question_description(struct question *q)
> -{
> -     static char buf[4096] = {0};
> -     struct language_description *langdesc;
> -
> -     langdesc = q->template->localized_descriptions;
> -     while (langdesc)
> -     {
> -             if (strcmp(langdesc->language,getlanguage()) == 0) 
> -             {
> -                     question_expand_vars(q, langdesc->description, buf, 
>sizeof(buf));
> -                     return buf;
> -             }
> -             langdesc = langdesc->next;
> -     }
> -     question_expand_vars(q, q->template->description, buf, sizeof(buf));
> -     return buf;
> -}
> -
> -const char *question_extended_description(struct question *q)
> -{
> -     static char buf[4096] = {0};
> -     question_expand_vars(q, q->template->extended_description, buf, sizeof(buf));
> -     return buf;
> -}
> -
> -const char *question_extended_description_translated(struct question *q)
> +const char *getlanguage(void)
>  {
> -     static char buf[4096] = {0};
> -     struct language_description *langdesc;
> -
> -     langdesc = q->template->localized_descriptions;
> -     while (langdesc)
> +     if (cur_lang[0] == 0)
>       {
> -             if (strcmp(langdesc->language,getlanguage()) == 0 && 
>langdesc->description != NULL)
> -             {
> -                     question_expand_vars(q, langdesc->extended_description, buf, 
>sizeof(buf));
> -                     return buf;
> -             }
> -             langdesc = langdesc->next;
> +             if (getenv("DEBCONF_LANG")) 
> +                     strncpy(cur_lang, getenv("DEBCONF_LANG"), 5);
> +             else
> +                     strcpy(cur_lang, "C");
>       }
> -     question_expand_vars(q, q->template->extended_description, buf, sizeof(buf));
> -     return buf;
> +     return cur_lang;
>  }
>  
> -const char *question_choices_translated(struct question *q)
> +const char *question_get_field(struct question *q, const char *field)
>  {
>       static char buf[4096] = {0};
> -     struct language_description *langdesc;
> -
> -     langdesc = q->template->localized_descriptions;
> -     while (langdesc)
> -     {
> -             if (strcmp(langdesc->language,getlanguage()) == 0 && langdesc->choices 
>!= NULL)
> -             {
> -                     question_expand_vars(q, langdesc->choices, buf, sizeof(buf));
> -                     return buf;
> -             }
> -             langdesc = langdesc->next;
> -     }
> -     question_expand_vars(q, q->template->choices, buf, sizeof(buf));
> +     if (strcmp(field, "default") == 0) {
> +             if (q->value != 0 && *q->value != 0)
> +                     return q->value;
> +             else
> +                     return q->template->get(q->template, field);
> +     }
> +     question_expand_vars(q,
> +             q->template->get(q->template, field),
> +             buf, sizeof(buf));
>       return buf;
>  }
>  
> -const char *question_choices(struct question *q)
> +const char *question_get_translated_field(struct question *q, const char *field)
>  {
>       static char buf[4096] = {0};
> -     question_expand_vars(q, q->template->choices, buf, sizeof(buf));
> +     if (strcmp(field, "default") == 0) {
> +             if (q->value != 0 && *q->value != 0)
> +                     return q->value;
> +             else
> +                     return q->template->lget(q->template, getlanguage(), field);
> +     }
> +     question_expand_vars(q,
> +             q->template->lget(q->template, getlanguage(), field),
> +             buf, sizeof(buf));
>       return buf;
>  }
> -
> -const char *question_defaultval(struct question *q)
> -{
> -     if (q->value != 0 && *q->value != 0)
> -             return q->value;
> -     else
> -             return q->template->defaultval;
> -}
> -
> Index: src/question.h
> ===================================================================
> RCS file: /cvs/debian-boot/debian-installer/tools/cdebconf/src/question.h,v
> retrieving revision 1.9
> diff -u -r1.9 question.h
> --- src/question.h    12 Aug 2002 13:38:34 -0000      1.9
> +++ src/question.h    9 Nov 2002 01:21:18 -0000
> @@ -45,10 +45,7 @@
>       const char *value);
>  void question_owner_add(struct question *q, const char *owner);
>  void question_owner_delete(struct question *q, const char *owner);
> -const char *question_description(struct question *q);
> -const char *question_extended_description(struct question *q);
> -const char *question_choices_translated(struct question *q);
> -const char *question_choices(struct question *q);
> -const char *question_defaultval(struct question *q);
> +const char *question_get_field(struct question *q, const char *field);
> +const char *question_get_translated_field(struct question *q, const char *field);
>  
>  #endif
> Index: src/template.c
> ===================================================================
> RCS file: /cvs/debian-boot/debian-installer/tools/cdebconf/src/template.c,v
> retrieving revision 1.8
> diff -u -r1.8 template.c
> --- src/template.c    1 Jul 2002 06:58:37 -0000       1.8
> +++ src/template.c    9 Nov 2002 01:21:19 -0000
> @@ -42,11 +42,31 @@
>  
>  #include <stdio.h>
>  
> +static const char *template_lget(struct template *t, const char *lang,
> +                const char *field);
> +static const char *template_get(struct template *t, const char *field);
> +static void template_lset(struct template *t, const char *lang,
> +                const char *field, const char *value);
> +static void template_set(struct template *t, const char *field,
> +                const char *value);
> +static const char *template_next_lang(struct template *t, const char *l);
> +
> +const char *template_fields_list[] = {
> +        "tag",
> +        "type",
> +        "default",
> +        "choices",
> +        "description",
> +        "extended_description",
> +        NULL
> +};
> +
>  /*
>   * Function: template_new
>   * Input: a tag, describing which template this is.  Can be null.
>   * Output: a blank template struct.  Tag is strdup-ed, so the original
>             string may change without harm.
> +           The fields structure is also allocated to store English fields
>   * Description: allocate a new, empty struct template.
>   * Assumptions: NEW succeeds
>   * Todo: 
> @@ -54,22 +74,40 @@
>  
>  struct template *template_new(const char *tag)
>  {
> +     struct template_l10n_fields *f = NEW(struct template_l10n_fields);
>       struct template *t = NEW(struct template);
> +     memset(f, 0, sizeof(struct template_l10n_fields));
> +     f->language = STRDUP("C");
>       memset(t, 0, sizeof(struct template));
>       t->ref = 1;
>       t->tag = STRDUP(tag);
> +     t->get = template_get;
> +     t->set = template_set;
> +     t->lget = template_lget;
> +     t->lset = template_lset;
> +     t->next_lang = template_next_lang;
> +     t->fields = f;
>       return t;
>  }
>  
>  void template_delete(struct template *t)
>  {
> +     struct template_l10n_fields *p, *q;
> +
>       DELETE(t->tag);
>       DELETE(t->type);
> -     DELETE(t->defaultval);
> -     DELETE(t->choices);
> -     DELETE(t->description);
> -     DELETE(t->extended_description);
> +     p = t->fields;
>       DELETE(t);
> +     while (p != NULL)
> +     {
> +             q = p->next;
> +             DELETE(p->defaultval);
> +             DELETE(p->choices);
> +             DELETE(p->description);
> +             DELETE(p->extended_description);
> +             DELETE(p);
> +             p = q;
> +     }
>  }
>  
>  void template_ref(struct template *t)
> @@ -89,23 +127,251 @@
>   * Output: a copy of the template passed as input
>   * Description: duplicate a template
>   * Assumptions: template_new succeeds, STRDUP succeeds.
> - * Todo: Handle localization
>   */
>  
>  struct template *template_dup(struct template *t)
>  {
>          struct template *ret = template_new(t->tag);
> +        struct template_l10n_fields *from, *to;
> +
>          ret->type = STRDUP(t->type);
> -        ret->defaultval = STRDUP(t->defaultval);
> -        ret->choices = STRDUP(t->choices);
> -        ret->description = STRDUP(t->description);
> -        ret->extended_description = STRDUP(t->extended_description);
> +        if (t->fields == NULL)
> +                return ret;
> +
> +        ret->fields = NEW(struct template_l10n_fields);
> +
> +        from = t->fields;
> +        to = ret->fields;
> +        /*  Iterate over available languages  */
> +        while (1)
> +        {
> +                to->defaultval = STRDUP(from->defaultval);
> +                to->choices = STRDUP(from->choices);
> +                to->description = STRDUP(from->description);
> +                to->extended_description = STRDUP(from->extended_description);
> +
> +                if (from->next == NULL)
> +                {
> +                        to->next = NULL;
> +                        break;
> +                }
> +                to->next = NEW(struct template_l10n_fields);
> +                from = from->next;
> +                to = to->next;
> +        }
> +        return ret;
> +}
> +
> +static const char *template_field_get(struct template_l10n_fields *p,
> +                const char *field)
> +{
> +    if (strcasecmp(field, "default") == 0)
> +        return p->defaultval;
> +    else if (strcasecmp(field, "choices") == 0)
> +        return p->choices;
> +    else if (strcasecmp(field, "description") == 0)
> +        return p->description;
> +    else if (strcasecmp(field, "extended_description") == 0)
> +        return p->extended_description;
> +    return NULL;
> +}
> +
> +static void template_field_set(struct template_l10n_fields *p,
> +                const char *field, const char *value)
> +{
> +    if (strcasecmp(field, "default") == 0)
> +    {
> +        DELETE(p->defaultval);
> +        p->defaultval = STRDUP(value);
> +    }
> +    else if (strcasecmp(field, "choices") == 0)
> +    {
> +        DELETE(p->choices);
> +        p->choices = STRDUP(value);
> +    }
> +    else if (strcasecmp(field, "description") == 0)
> +    {
> +        DELETE(p->description);
> +        p->description = STRDUP(value);
> +    }
> +    else if (strcasecmp(field, "extended_description") == 0)
> +    {
> +        DELETE(p->extended_description);
> +        p->extended_description = STRDUP(value);
> +    }
> +}
> +
> +/*
> + * Function: template_get
> + * Input: a template
> + * Input: a language name
> + * Input: a field name
> + * Output: the value of the given field in the given language, field
> + *         name may be any of type, default, choices, description and
> + *         extended_description
> + * Description: get field value
> + * Assumptions: 
> + */
> +
> +static const char *template_lget(struct template *t, const char *lang,
> +                const char *field)
> +{
> +    struct template_l10n_fields *p;
> +    const char *ret = NULL, *altret = NULL;
> +
> +    if (strcmp(lang, "C") == 0 && strcasecmp(field, "tag") == 0)
> +        return t->tag;
> +    else if (strcmp(lang, "C") == 0 && strcasecmp(field, "type") == 0)
> +        return t->type;
> +
> +    p = t->fields;
> +    while (p != NULL)
> +    {
> +        /*  Exact match  */
> +        if (strcmp(p->language, lang) == 0)
> +            return template_field_get(p, field);
> +
> +        /*  Language is xx_XX and a xx field is found  */
> +        if (strlen(p->language) == 2 && strncmp(lang, p->language, 2) == 0)
> +            altret = template_field_get(p, field);
> +
> +        p = p->next;
> +    }
> +    if (altret != NULL)
> +        return altret;
> +    if (ret)
>          return ret;
> +    /*  Default value  */
> +    return template_field_get(t->fields, field);
> +}
> +
> +static const char *template_get(struct template *t, const char *field)
> +{
> +    char *orig_field;
> +    char *lang;
> +    char *p;
> +    const char *ret = NULL;
> +
> +    p = strchr(field, '-');
> +    if (p == NULL)
> +        return template_lget(t, "C", field);
> +
> +    orig_field = strdup(field);
> +    lang = strchr(orig_field, '-');
> +    *lang = 0;
> +    lang++;
> +    if (strstr(lang, ".UTF-8") == lang + 2)
> +    {
> +        *(lang+2) = 0;
> +        ret = template_lget(t, lang, orig_field);
> +    }
> +    else if (strstr(lang, ".UTF-8") == lang + 5)
> +    {
> +        *(lang+5) = 0;
> +        ret = template_lget(t, lang, orig_field);
> +    }
> +#ifndef NODEBUG
> +    else
> +        fprintf(stderr, "Unknown localized field:\n%s\n", p);
> +#endif
> +    free(orig_field);
> +    return ret;
> +}
> +
> +static void template_lset(struct template *t, const char *lang,
> +                const char *field, const char *value)
> +{
> +    struct template_l10n_fields *p, *last;
> +
> +    if (strcmp(lang, "C") == 0 && strcasecmp(field, "tag") == 0)
> +    {
> +        t->tag = STRDUP(value);
> +        return;
> +    }
> +    else if (strcmp(lang, "C") == 0 && strcasecmp(field, "type") == 0)
> +    {
> +        t->type = STRDUP(value);
> +        return;
> +    }
> +
> +    p = t->fields;
> +    last = p;
> +    while (p != NULL)
> +    {
> +        if (strcmp(p->language, lang) == 0)
> +        {
> +            template_field_set(p, field, value);
> +            return;
> +        }
> +        last = p;
> +        p = p->next;
> +    }
> +    p = NEW(struct template_l10n_fields);
> +    memset(p, 0, sizeof(struct template_l10n_fields));
> +    p->language = STRDUP(lang);
> +    last->next = p;
> +    template_field_set(p, field, value);
> +}
> +
> +static void template_set(struct template *t, const char *field,
> +                const char *value)
> +{
> +    char *orig_field;
> +    char *lang;
> +    char *p;
> +
> +    p = strchr(field, '-');
> +    if (p == NULL)
> +        template_lset(t, "C", field, value);
> +    else
> +    {
> +        orig_field = strdup(field);
> +        lang = strchr(orig_field, '-');
> +        *lang = 0;
> +        lang++;
> +        if (strstr(lang, ".UTF-8") == lang + 2)
> +        {
> +            *(lang+2) = 0;
> +            template_lset(t, lang, orig_field, value);
> +        }
> +        else if (strstr(lang, ".UTF-8") == lang + 5)
> +        {
> +            *(lang+5) = 0;
> +            template_lset(t, lang, orig_field, value);
> +        }
> +#ifndef NODEBUG
> +        else
> +            fprintf(stderr, "Unknown localized field:\n%s\n", p);
> +#endif
> +        free(orig_field);
> +    }
> +}
> +
> +static const char *template_next_lang(struct template *t, const char *lang)
> +{
> +    struct template_l10n_fields *p;
> +
> +    if (lang == NULL)
> +        return NULL;
> +
> +    p = t->fields;
> +    while (p != NULL)
> +    {
> +        if (strcmp(p->language, lang) == 0)
> +        {
> +            if (p->next == NULL)
> +                return NULL;
> +            return p->next->language;
> +        }
> +        p = p->next;
> +    }
> +    return NULL;
>  }
>  
>  struct template *template_load(const char *filename)
>  {
>       char buf[2048], extdesc[8192];
> +     char lang[6];
>       char *p, *bufp;
>       FILE *fp;
>       struct template *tlist = NULL, *t = 0;
> @@ -130,55 +396,36 @@
>                       t = template_new(p+10);
>               }
>               else if (strstr(p, "Type: ") == p && t != 0)
> -                     t->type = strdup(p+6);
> +                     template_set(t, "type", p+6);
>               else if (strstr(p, "Default: ") == p && t != 0)
> -                     t->defaultval = strdup(p+9);
> +                     template_set(t, "default", p+9);
>               else if (strstr(p, "Choices: ") == p && t != 0)
> -                     t->choices = strdup(p+9);
> +                     template_set(t, "choices", p+9);
>               else if (strstr(p, "Choices-") == p && t != 0) 
>               {
> -                     struct language_description *langdesc = malloc(sizeof(struct 
>language_description));
> -                     struct language_description *lng_tmp = 0;
> -                     memset(langdesc,0,sizeof(struct language_description));
> -                     /* We assume that the language codes are
> -                        always 2 characters long, */
> -
> -                     langdesc->language = malloc(3);
> -                     snprintf(langdesc->language,3,"%.2s",p+8);
> -                     
> -                     langdesc->choices = strdup(p+11);
> -
> -                     if (t->localized_descriptions == NULL) 
> +                     if (strstr(p, ".UTF-8: ") == p + 10)
> +                     {
> +                             strncpy(lang, p+8, 2);
> +                             lang[2] = 0;
> +                             template_lset(t, lang, "choices", p+18);
> +                     }
> +                     else if (strstr(p, ".UTF-8: ") == p + 13)
>                       {
> -                             t->localized_descriptions = langdesc;
> +                             strncpy(lang, p+8, 5);
> +                             lang[5] = 0;
> +                             template_lset(t, lang, "choices", p+21);
>                       }
>                       else
>                       {
> -                             lng_tmp = t->localized_descriptions;
> -                             while (lng_tmp != NULL)
> -                             {
> -                                     if 
>(strcmp(lng_tmp->language,langdesc->language) == 0)
> -                                     {
> -                                             if (lng_tmp->choices)
> -                                                     free(lng_tmp->choices);
> -                                             lng_tmp->choices = langdesc->choices;
> -                                             free(langdesc->language);
> -                                             free(langdesc);
> -                                             langdesc = NULL;
> -                                             break;
> -                                     }
> -                                     lng_tmp = lng_tmp->next;
> -                             }
> -                             if (langdesc != NULL) 
> -                             {
> -                                     langdesc->next = t->localized_descriptions;
> -                                     t->localized_descriptions = langdesc;
> -                             }
> +#ifndef NODEBUG
> +                             fprintf(stderr, "Unknown localized field:\n%s\n", p);
> +#endif
> +                                continue;
>                       }
>               }
>               else if (strstr(p, "Description: ") == p && t != 0)
>               {
> -                     t->description = strdup(p+13);
> +                     template_set(t, "description", p+13);
>                       extdesc[0] = 0;
>                       i = fgetc(fp);
>                       /* Don't use fgets unless you _need_ to, a
> @@ -219,22 +466,31 @@
>                                                       *bufp = ' ';
>                                       }
>                                       
> -                             t->extended_description = strdup(extdesc);
> +                             template_set(t, "extended_description", extdesc);
>                       }
>               }
>               else if (strstr(p, "Description-") == p && t != 0)
>               {
> -                     struct language_description *langdesc = malloc(sizeof(struct 
>language_description));
> -                     struct language_description *lng_tmp = 0;
> -                     memset(langdesc,0,sizeof(struct language_description));
> -
> -                     /* We assume that the language codes are
> -                        always 2 characters long, */
> -
> -                     langdesc->language = malloc(3);
> -                     snprintf(langdesc->language,3,"%.2s",p+12);
> -                     langdesc->description = strdup(p+16);
> -
> +                     if (strstr(p, ".UTF-8: ") == p + 14)
> +                     {
> +                             strncpy(lang, p+12, 2);
> +                             lang[2] = 0;
> +                             template_lset(t, lang, "description", p+22);
> +                     }
> +                     else if (strstr(p, ".UTF-8: ") == p + 17)
> +                     {
> +                             strncpy(lang, p+12, 5);
> +                             lang[5] = 0;
> +                             template_lset(t, lang, "description", p+25);
> +                     }
> +                     else
> +                     {
> +#ifndef NODEBUG
> +                             fprintf(stderr, "Unknown localized field:\n%s\n", p);
> +#endif
> +                                /*  Skip extended description  */
> +                                lang[0] = 0;
> +                     }
>                       extdesc[0] = 0;
>                       i = fgetc(fp);
>                       /* Don't use fgets unless you _need_ to, a
> @@ -273,37 +529,8 @@
>                                                       *bufp = ' ';
>                                       }
>                               
> -                             langdesc->extended_description = strdup(extdesc);
> -                     }
> -                     if (t->localized_descriptions == NULL) 
> -                     {
> -                             t->localized_descriptions = langdesc;
> -                     }
> -                     else
> -                     {
> -                             lng_tmp = t->localized_descriptions;
> -                             while (lng_tmp != NULL)
> -                             {
> -                                     if 
>(strcmp(lng_tmp->language,langdesc->language) == 0)
> -                                     {
> -                                             if (lng_tmp->description != NULL)
> -                                                     free(lng_tmp->description);
> -                                             if (lng_tmp->extended_description != 
>NULL)
> -                                                     
>free(lng_tmp->extended_description);
> -                                             lng_tmp->description = 
>langdesc->description;
> -                                             lng_tmp->extended_description = 
>langdesc->extended_description;
> -                                             free(langdesc->language);
> -                                             free(langdesc);
> -                                             langdesc = NULL;
> -                                             break;
> -                                     }
> -                                     lng_tmp = lng_tmp->next;
> -                             }
> -                             if (langdesc != NULL) 
> -                             {
> -                                     langdesc->next = t->localized_descriptions;
> -                                     t->localized_descriptions = langdesc;
> -                             }
> +                             if (lang[0] != 0)
> +                                     template_lset(t, lang, "extended_description", 
>extdesc);
>                       }
>               }
>       }
> Index: src/template.h
> ===================================================================
> RCS file: /cvs/debian-boot/debian-installer/tools/cdebconf/src/template.h,v
> retrieving revision 1.3
> diff -u -r1.3 template.h
> --- src/template.h    12 Aug 2002 13:38:34 -0000      1.3
> +++ src/template.h    9 Nov 2002 01:21:19 -0000
> @@ -1,13 +1,14 @@
>  #ifndef _TEMPLATE_H_
>  #define _TEMPLATE_H_
>  
> -struct language_description 
> +struct template_l10n_fields
>  {
>       char *language;
> +     char *defaultval;
> +     char *choices;
>       char *description;
>       char *extended_description;
> -     char *choices;
> -     struct language_description *next;
> +     struct template_l10n_fields *next;
>  };
>  
>  struct template
> @@ -15,13 +16,17 @@
>       char *tag;
>       unsigned int ref;
>       char *type;
> -     char *defaultval;
> -     char *choices;
> -     char *description;
> -     char *extended_description;
> -     struct language_description *localized_descriptions;
> +     struct template_l10n_fields *fields;
>       struct template *next;
> +     const char *(*lget)(struct template *, const char *l, const char *f);
> +     const char *(*get)(struct template *, const char *f);
> +        void (*lset)(struct template *, const char *l, const char *f,
> +                        const char *v);
> +        void (*set)(struct template *, const char *f, const char *v);
> +     const char *(*next_lang)(struct template *, const char *l);
>  };
> +
> +extern const char *template_fields_list[];
>  
>  struct template *template_new(const char *tag);
>  void template_delete(struct template *t);
> Index: src/modules/db/rfc822db/rfc822db.c
> ===================================================================
> RCS file: 
>/cvs/debian-boot/debian-installer/tools/cdebconf/src/modules/db/rfc822db/rfc822db.c,v
> retrieving revision 1.9
> diff -u -r1.9 rfc822db.c
> --- src/modules/db/rfc822db/rfc822db.c        3 Nov 2002 14:58:19 -0000       1.9
> +++ src/modules/db/rfc822db/rfc822db.c        9 Nov 2002 01:21:19 -0000
> @@ -239,7 +239,6 @@
>   * Output: DC_OK/DC_NOTOK
>   * Description: parse a template db file and put it into the cache
>   * Assumptions: the file is in valid rfc822 format
> - * TODO: handle localized templates
>   */
>  static int rfc822db_template_load(struct template_db *db)
>  {
> @@ -262,8 +261,7 @@
>      {
>          struct template *tmp;
>          const char *name;
> -        char tbuf[1024];
> -        memset(&tbuf,0,1024);
> +        struct rfc822_header *h;
>  
>          name = rfc822db_header_lookup(header, "name");
>          if (name == NULL)
> @@ -274,13 +272,10 @@
>          }
>  
>          tmp = template_new(name);
> +        for (h = header; h != NULL; h = h->next)
> +            if (strcmp(h->header, "Name") != 0)
> +                tmp->set(tmp, h->header, h->value);
>  
> -        tmp->type = rfc822db_header_lookup(header, "type");
> -        tmp->defaultval = rfc822db_header_lookup(header, "default");
> -        tmp->choices = rfc822db_header_lookup(header, "choices");
> -        tmp->description = rfc822db_header_lookup(header, "description");
> -        tmp->extended_description = rfc822db_header_lookup(header, 
>"extended_description");
> -/*  struct language_description *localized_descriptions; */
>          tmp->next = NULL;
>          tsearch(tmp, &dbdata->root, nodetemplatecomp);
>      }
> @@ -292,52 +287,54 @@
>  
>  void rfc822db_template_dump(const void *node, const VISIT which, const int depth)
>  {
> -  struct language_description *langdesc;
> -  const struct template *t = (*(struct template **) node);
> -  switch (which) {
> -  case preorder:
> -    break;
> -  case endorder:
> -    break;
> -  case postorder: 
> -  case leaf:
> -        INFO(INFO_VERBOSE, "dumping template %s\n", (t)->tag);
> -        
> -        fprintf(outf, "Name: %s\n", escapestr((t)->tag));
> -        fprintf(outf, "Type: %s\n", escapestr((t)->type));
> -        if ((t)->defaultval != NULL)
> -            fprintf(outf, "Default: %s\n", escapestr((t)->defaultval));
> -        if ((t)->choices != NULL)
> -            fprintf(outf, "Choices: %s\n", escapestr((t)->choices));
> -        if ((t)->description != NULL)
> -            fprintf(outf, "Description: %s\n", escapestr((t)->description));
> -        if ((t)->extended_description != NULL)
> -            fprintf(outf, "Extended_description: %s\n", 
>escapestr((t)->extended_description));
> -        
> -        langdesc = (t)->localized_descriptions;
> -        while (langdesc) 
> +    const char *p, *lang;
> +    const char **field;
> +    const struct template *t = (*(struct template **) node);
> +
> +    switch (which) {
> +    case preorder:
> +        break;
> +    case endorder:
> +        break;
> +    case postorder: 
> +    case leaf:
> +        p = t->get((struct template *) t, "tag");
> +        INFO(INFO_VERBOSE, "dumping template %s\n", p);
> +
> +        for (field = template_fields_list; *field != NULL; field++)
>          {
> -            if (langdesc->description != NULL) 
> -                fprintf(outf, "Description-%s: %s\n", 
> -                    langdesc->language, 
> -                    escapestr(langdesc->description));
> -            
> -            if (langdesc->extended_description != NULL)
> -                fprintf(outf, "Extended_description-%s: %s\n", 
> -                    langdesc->language, 
> -                    escapestr(langdesc->extended_description));
> -            
> -            if (langdesc->choices != NULL) 
> -                fprintf(outf, "Choices-%s: %s\n", 
> -                    langdesc->language, 
> -                    escapestr(langdesc->choices));
> -            
> -            langdesc = langdesc->next;
> +            p = t->get((struct template *) t, *field);
> +            if (p != NULL)
> +            {
> +                if (strcmp(*field, "tag") == 0)
> +                    fprintf(outf, "Name: %s\n", escapestr(p));
> +                            else
> +                    fprintf(outf, "%c%s: %s\n",
> +                        toupper((*field)[0]),
> +                        (*field)+1, escapestr(p));
> +            }
> +        }
> +    
> +        lang = t->next_lang((struct template *) t, "C");
> +        while (lang) 
> +        {
> +            for (field = template_fields_list; *field != NULL; field++)
> +            {
> +                p = t->lget((struct template *) t, lang, *field);
> +                if (p != NULL)
> +                {
> +                    if (strcmp(*field, "tag") != 0)
> +                        fprintf(outf, "%c%s-%s.UTF-8: %s\n",
> +                            toupper((*field)[0]), (*field)+1,
> +                            lang, escapestr(p));
> +                }
> +            }
> +            lang = t->next_lang((struct template *) t, lang);
>          }
>          fprintf(outf, "\n");
> -  }
> -  
> +    }
>  }
> +  
>  static int rfc822db_template_save(struct template_db *db)
>  {
>      struct template_db_cache *dbdata = db->data;
> @@ -596,7 +593,7 @@
>      struct question *q, q2;
>  
>      memset(&q2, 0, sizeof (struct question));
> -    q2.tag = ltag;
> +    q2.tag = (char *) ltag;
>      q = tfind(&q2, &dbdata->root, nodequestioncomp);
>      if (q != NULL)
>      {
> Index: src/modules/db/textdb/textdb.c
> ===================================================================
> RCS file: 
>/cvs/debian-boot/debian-installer/tools/cdebconf/src/modules/db/textdb/textdb.c,v
> retrieving revision 1.5
> diff -u -r1.5 textdb.c
> --- src/modules/db/textdb/textdb.c    30 Jul 2002 05:55:27 -0000      1.5
> +++ src/modules/db/textdb/textdb.c    9 Nov 2002 01:21:19 -0000
> @@ -135,38 +135,35 @@
>  {
>       FILE *outf;
>       char *filename;
> -     struct language_description *langdesc;
> +     const char *p, *lang;
> +     const char **field;
>  
> -     if (t->tag == NULL) return DC_NOTOK;
> -     filename = template_filename(db, t->tag);
> +     if (t->get(t, "tag") == NULL) return DC_NOTOK;
> +     filename = template_filename(db, t->get(t, "tag"));
>       
>       if ((outf = fopen(filename, "w")) == NULL)
>               return DC_NOTOK;
>  
>       fprintf(outf, "template {\n");
>  
> -     fprintf(outf, "\ttag \"%s\";\n", escapestr(t->tag));
> -     fprintf(outf, "\ttype \"%s\";\n", escapestr(t->type));
> -     if (t->defaultval != NULL)
> -             fprintf(outf, "\tdefault \"%s\";\n", escapestr(t->defaultval));
> -     if (t->choices != NULL)
> -             fprintf(outf, "\tchoices \"%s\";\n", escapestr(t->choices));
> -     if (t->description != NULL)
> -             fprintf(outf, "\tdescription \"%s\";\n", escapestr(t->description));
> -     if (t->extended_description != NULL)
> -             fprintf(outf, "\textended_description \"%s\";\n", 
>escapestr(t->extended_description));
> -
> -     langdesc = t->localized_descriptions;
> -     while (langdesc) 
> +     for (field = template_fields_list; *field != NULL; field++)
>       {
> -             if (langdesc->description != NULL) 
> -                     fprintf(outf, "\tdescription-%s \"%s\";\n", 
>langdesc->language, escapestr(langdesc->description));
> -             if (langdesc->extended_description != NULL)
> -                     fprintf(outf, "\textended_description-%s \"%s\";\n", 
>langdesc->language, escapestr(langdesc->extended_description));
> -             if (langdesc->choices != NULL) 
> -                     fprintf(outf, "\tchoices-%s \"%s\";\n", langdesc->language, 
>escapestr(langdesc->choices));
> +             p = t->get(t, *field);
> +             if (p != NULL)
> +                     fprintf(outf, "\t%s \"%s\";\n", *field, escapestr(p));
> +     }
>  
> -             langdesc = langdesc->next;
> +     lang = t->next_lang(t, "C");
> +     while (lang) 
> +     {
> +             for (field = template_fields_list; *field != NULL; field++)
> +             {
> +                     p = t->lget(t, lang, *field);
> +                     if (p != NULL)
> +                             fprintf(outf, "\t%s-%s \"%s\";\n", *field,
> +                                                lang, escapestr(p));
> +             }
> +             lang = t->next_lang(t, lang);
>       }
>  
>       fprintf(outf, "};\n");
> @@ -204,16 +201,17 @@
>       }
>       else
>       {
> -             t->type = STRDUP(unescapestr(rec->get(rec, "template::type", 
>"string")));
> -             t->defaultval = STRDUP(unescapestr(rec->get(rec, "template::default", 
>0)));
> -             t->choices = STRDUP(unescapestr(rec->get(rec, "template::choices", 
>0)));
> -             t->description = STRDUP(unescapestr(rec->get(rec, 
>"template::description", 0)));
> -             t->extended_description = STRDUP(unescapestr(rec->get(rec, 
>"template::extended_description", 0)));
> +             t->set(t, "type", STRDUP(unescapestr(rec->get(rec, "template::type", 
>"string"))));
> +             t->set(t, "default", STRDUP(unescapestr(rec->get(rec, 
>"template::default", 0))));
> +             t->set(t, "choices", STRDUP(unescapestr(rec->get(rec, 
>"template::choices", 0))));
> +             t->set(t, "description", STRDUP(unescapestr(rec->get(rec, 
>"template::description", 0))));
> +             t->set(t, "extended_description", STRDUP(unescapestr(rec->get(rec, 
>"template::extended_description", 0))));
>  
>               /* We can't ask for all the localized descriptions so we need to
>                * brute-force this.
>                * This is stupid and ugly and should be fixed, FIXME
>                */
> +#if 0
>               for (a = 'a'; a <= 'z'; a++)
>                       for (b = 'a'; b <= 'z'; b++)
>                       {
> @@ -239,6 +237,7 @@
>                                       t->localized_descriptions = langdesc;
>                               }
>                       }
> +#endif
>       }
>               
>  
> Index: src/modules/frontend/bogl/bogl.c
> ===================================================================
> RCS file: 
>/cvs/debian-boot/debian-installer/tools/cdebconf/src/modules/frontend/bogl/bogl.c,v
> retrieving revision 1.4
> diff -u -r1.4 bogl.c
> --- src/modules/frontend/bogl/bogl.c  2 Jul 2002 06:53:47 -0000       1.4
> +++ src/modules/frontend/bogl/bogl.c  9 Nov 2002 01:21:19 -0000
> @@ -58,12 +58,12 @@
>  static void drawdesctop(struct frontend *ui, struct question *q)
>  {
>       bowl_title(ui->title);
> -     bowl_new_text(question_description(q));
> +     bowl_new_text(question_get_translated_field(q, "description"));
>  }
>  
>  static void drawdescbot(struct frontend *ui, struct question *q)
>  {
> -     bowl_new_text(question_extended_description(q));
> +     bowl_new_text(question_get_translated_field(q, "extended_description"));
>  }
>  
>  /* boolean requires a new widget, the radio button :( */
> @@ -71,7 +71,7 @@
>  int bogl_handler_boolean(struct frontend *ui, struct question *q)
>  {
>       /* Should just make bowl_new_checkbox be properly const-qualified. */
> -     char *desc = strdup(question_description(q));
> +     char *desc = strdup(question_get_translated_field(q, "description"));
>       int ret;
>       
>  #if 0
> @@ -120,40 +120,50 @@
>  
>  int bogl_handler_multiselect(struct frontend *ui, struct question *q)
>  {
> -     int nchoices, ndefs, ret, i, j;
> +     char **choices, **choices_translated, **defaults, *selected;
> +     int i, j, count, dcount, ret;
>       const char *p;
> -     char **choices, **defaults, *selected;
> -     
> -     nchoices = 1;
> -     for(p = question_choices(q); *p; p++)
> -             if(*p == ',')
> -                     nchoices++;
> -     choices = malloc(sizeof(char *) * nchoices);
> -     nchoices = strchoicesplit(question_choices(q), choices, nchoices);
> -     selected = malloc(sizeof(char) * nchoices);
> -     memset(selected, ' ', nchoices);
>  
> -     ndefs = 1;
> -     for(p = question_defaultval(q); *p; p++)
> +     count = 0;
> +     p = question_get_field(q, "choices");
> +     if (*p)
> +     {
> +             count++;
> +             for(; *p; p++)
> +                     if(*p == ',')
> +                             count++;
> +     }
> +
> +     if (count <= 0) return DC_NOTOK;
> +
> +     choices = malloc(sizeof(char *) * count);
> +     strchoicesplit(question_get_field(q, "choices"), choices, count);
> +     choices_translated = malloc(sizeof(char *) * count);
> +     strchoicesplit(question_get_field(q, "choices"), choices_translated, count);
> +     selected = malloc(sizeof(char) * count);
> +     memset(selected, ' ', count);
> +
> +     dcount = 1;
> +     for(p = question_get_field(q, "default"); *p; p++)
>               if(*p == ',')
> -                     ndefs++;
> -     defaults = malloc(sizeof(char *) * ndefs);
> -     ndefs = strchoicesplit(question_defaultval(q), defaults, ndefs);
> -     for(i = 0; i < ndefs; i++)
> +                     dcount++;
> +     defaults = malloc(sizeof(char *) * dcount);
> +     dcount = strchoicesplit(question_get_field(q, "default"), defaults, dcount);
> +     for(j = 0; j < dcount; j++)
>       {
> -             for(j = 0; j < nchoices; j++)
> -                     if(strcmp(choices[j], defaults[i]) == 0)
> +             for(i = 0; i < count; i++)
> +                     if(strcmp(choices[i], defaults[j]) == 0)
>                       {
> -                             selected[j] = '*';
> +                             selected[i] = '*';
>                               break;
>                       }
> -             free(defaults[i]);
> +             free(defaults[j]);
>       }
>       free(defaults);
>  
>       bowl_flush();
>       drawdesctop(ui, q);
> -     bowl_new_checkbox(choices, selected, nchoices, (nchoices > 15) ? 15 : 
>nchoices);
> +     bowl_new_checkbox(choices, selected, count, (count > 15) ? 15 : count);
>       drawnavbuttons(ui, q);
>       drawdescbot(ui, q);
>       
> @@ -163,19 +173,19 @@
>       if(ret == DC_OK)
>       {
>               /* Be safe - allow for commas and spaces. */
> -             char *answer = malloc(strlen(question_choices(q)) + 1 + nchoices);
> +             char *answer = malloc(strlen(question_get_translated_field(q, 
>"choices")) + 1 + count);
>               answer[0] = 0;
> -             for(i = 0; i < nchoices; i++)
> +             for(i = 0; i < count; i++)
>                       if (selected[i] == '*')
>                       {
>                               if(answer[0] != 0)
>                                       strcat(answer, ", ");
> -                             strcat(answer, choices[i]);
> +                             strcat(answer, choices_translated[i]);
>                       }
>               question_setvalue(q, answer);
>       }
>  
> -     for(i = 0; i < nchoices; i++)
> +     for(i = 0; i < count; i++)
>               free(choices[i]);
>       free(choices);
>  
> @@ -189,7 +199,7 @@
>  
>       bowl_flush();
>       drawdesctop(ui, q);
> -     bowl_new_input(&s, question_defaultval(q));
> +     bowl_new_input(&s, question_get_field(q, "default"));
>       drawnavbuttons(ui, q);
>       drawdescbot(ui, q);
>       bowl_layout();
> Index: src/modules/frontend/ncurses/ncurses.c
> ===================================================================
> RCS file: 
>/cvs/debian-boot/debian-installer/tools/cdebconf/src/modules/frontend/ncurses/ncurses.c,v
> retrieving revision 1.9
> diff -u -r1.9 ncurses.c
> --- src/modules/frontend/ncurses/ncurses.c    9 Jul 2002 05:25:04 -0000       1.9
> +++ src/modules/frontend/ncurses/ncurses.c    9 Nov 2002 01:21:19 -0000
> @@ -223,8 +223,8 @@
>       WINDOW *descwin = UIDATA(ui)->descwin;
>  
>       drawframe(ui, WIN_QUERY, ui->title);
> -     wrapprint(qrywin, question_description(q), 0, COLS-2);
> -     wrapprint(descwin, question_extended_description(q), 0, COLS-2);
> +     wrapprint(qrywin, question_get_translated_field(q, "description"), 0, COLS-2);
> +     wrapprint(descwin, question_get_translated_field(q, "extended_description"), 
>0, COLS-2);
>       wclrtobot(qrywin);
>       wclrtobot(descwin);
>       wrefresh(stdscr);
> @@ -237,12 +237,17 @@
>       char *value = "true";
>       int ret = 0, ans, pos = 2;
>       int ybut = UIDATA(ui)->qrylines - 6;
> +     char *dft;
>       WINDOW *win = UIDATA(ui)->qrywin;
>  
>       if (q->value != 0 && *q->value != 0)
>               value = q->value;
> -     else if (q->template->defaultval != 0 && *q->template->defaultval != 0)
> -             value = q->template->defaultval;
> +     else
> +     {
> +             dft = (char *) q->template->get(q->template, "default");
> +             if (dft != 0 && *dft != 0)
> +                     value = dft;
> +     }
>  
>       ans = (strcmp(value, "true") == 0);
>  
> @@ -351,29 +356,33 @@
>  
>  static int nchandler_select(struct frontend *ui, struct question *q)
>  {
> -     char *value = NULL;
>       char *choices[100] = {0};
> -     int i, count, ret = 0, val = 0, pos = 2, xpos, ypos;
> +     char *choices_translated[100] = {0};
> +     char *defaults[100] = {0};
> +     const char *defval = question_get_field(q, "default");
> +
> +     int i, count, dcount, ret = 0, def = -1, pos = 2, xpos, ypos;
>       int top, bottom, longest;
>       WINDOW *win = UIDATA(ui)->qrywin;
>  
>       /* Parse out all the choices */
> -     count = strchoicesplit((char *)question_choices(q), choices, DIM(choices));
> +     count = strchoicesplit(question_get_field(q, "choices"), choices, 
>DIM(choices));
>       if (count <= 0) return DC_NOTOK;
>  
> +     strchoicesplit(question_get_translated_field(q, "choices"), 
>choices_translated, DIM(choices_translated));
> +     dcount = strchoicesplit(question_get_field(q, "default"), defaults, 
>DIM(defaults));
> +
>       /* See what the currently selected value should be -- either a
>        * previously selected value, or the default for the question
>        */
> -     if ((q->value != 0 && *q->value != 0 && (value = q->value)) ||
> -         (q->template->defaultval != 0 && *q->template->defaultval != 0 && 
> -             (value = q->template->defaultval)))
> +     if (defval != NULL)
>       {
>               for (i = 0; i < count; i++)
> -                     if (strcmp(choices[i], value) == 0)
> -                             val = i;
> +                     if (strcmp(choices[i], defval) == 0)
> +                             def = i + 1;
>       }
>  
> -     longest = longestlen(choices, count);
> +     longest = longestlen(choices_translated, count);
>       top = 0; bottom = MIN(count, UIDATA(ui)->qrylines-5);
>       xpos = (COLS-longest)/2-1;
>  
> @@ -382,11 +391,11 @@
>               ypos = 2;
>               for (i = top; i < bottom; i++)
>               {
> -                     if (pos == 2 && i == val) 
> +                     if (pos == 2 && i == def) 
>                               wstandout(win); 
>                       else 
>                               wstandend(win);
> -                     mvwprintw(win, ypos++, xpos, " %-*s ", longest, choices[i]);
> +                     mvwprintw(win, ypos++, xpos, " %-*s ", longest, 
>choices_translated[i]);
>               }
>               wstandend(win);
>  
> @@ -398,17 +407,17 @@
>               {
>               case KEY_LEFT:
>               case KEY_UP:
> -                     val--;
> -                     if (val < 0) val = count-1;
> +                     def--;
> +                     if (def < 0) def = count-1;
>  
> -                     /* check val against top/bottom */
> +                     /* check def against top/bottom */
>                       break;
>               case KEY_RIGHT:
>               case KEY_DOWN:
> -                     val++;
> -                     if (val >= count) val = 0;
> +                     def++;
> +                     if (def >= count) def = 0;
>  
> -                     /* check val against top/bottom */
> +                     /* check def against top/bottom */
>                       break;
>               case 9: /* TAB */
>                       pos++;
> @@ -432,7 +441,7 @@
>               }
>       }
>       if (ret == DC_OK)
> -             question_setvalue(q, choices[val]);
> +             question_setvalue(q, choices[def]);
>       return ret;
>  }
>  
> Index: src/modules/frontend/slang/slang.c
> ===================================================================
> RCS file: 
>/cvs/debian-boot/debian-installer/tools/cdebconf/src/modules/frontend/slang/slang.c,v
> retrieving revision 1.11
> diff -u -r1.11 slang.c
> --- src/modules/frontend/slang/slang.c        9 Jul 2002 05:25:04 -0000       1.11
> +++ src/modules/frontend/slang/slang.c        9 Nov 2002 01:21:20 -0000
> @@ -197,8 +197,8 @@
>       slang_drawwin(&uid->qrywin);
>       slang_drawwin(&uid->descwin);
>       /* Draw in the descriptions */
> -     slang_wrapprint(&uid->qrywin, question_description(q), 0);
> -     slang_wrapprint(&uid->descwin, question_extended_description(q),
> +     slang_wrapprint(&uid->qrywin, question_get_translated_field(q, "description"), 
>0);
> +     slang_wrapprint(&uid->descwin, question_get_translated_field(q, 
>"extended_description"),
>               uid->descstart);
>  
>       /* caller should call slang_flush() ! */
> @@ -319,7 +319,7 @@
>       const char *value = "true";
>       int ret = 0, ans, pos = 2;
>  
> -     value = question_defaultval(q);
> +     value = question_get_field(q, "default");
>  
>       ans = (strcmp(value, "true") == 0);
>  
> @@ -373,6 +373,7 @@
>  static int slang_getselect(struct frontend *ui, struct question *q, int multi)
>  {
>       char *choices[100] = {0};
> +     char *choices_translated[100] = {0};
>       char *defaults[100] = {0};
>       char selected[100] = {0};
>       char answer[1024] = {0};
> @@ -382,8 +383,9 @@
>       struct slwindow *win = &uid->qrywin;
>  
>       /* Parse out all the choices */
> -     count = strchoicesplit(question_choices(q), choices, DIM(choices));
> -     dcount = strchoicesplit(question_defaultval(q), defaults, DIM(defaults));
> +     count = strchoicesplit(question_get_field(q, "choices"), choices, 
>DIM(choices));
> +     strchoicesplit(question_get_translated_field(q, "choices"), 
>choices_translated, DIM(choices_translated));
> +     dcount = strchoicesplit(question_get_field(q, "default"), defaults, 
>DIM(defaults));
>       INFO(INFO_VERBOSE, "Parsed out %d choices, %d defaults\n", count, dcount);
>       if (count <= 0) return DC_NOTOK;
>  
> @@ -391,11 +393,9 @@
>        * previously selected value, or the default for the question
>        */
>       for (j = 0; j < dcount; j++)
> -     {
>               for (i = 0; i < count; i++)
>                       if (strcmp(choices[i], defaults[j]) == 0)
>                               selected[i] = 1;
> -     }
>  
>       longest = strlongest(choices, count);
>       top = 0;
> @@ -414,10 +414,10 @@
>                       slang_printf(ypos++, xpos, ((pos == 2 && i == val) ?
>                               win->selectedcolor : win->drawcolor),
>                               "(%c) %-*s ", (selected[i] ? '*' : ' '), 
> -                             longest, choices[i]);
> +                             longest, choices_translated[i]);
>  
>                       INFO(INFO_VERBOSE, "(%c) %-*s\n", (selected[i] ? '*' : 
> -                             ' '), longest, choices[i]);
> +                             ' '), longest, choices_translated[i]);
>               }
>  
>               slang_navbuttons(ui, q, pos);
> @@ -454,7 +454,7 @@
>                       case 0: ret = DC_GOBACK; break;
>                       case 1: ret = DC_OK; break;
>                       default: 
> -                             if (multi == 0)
> +                             if (multi == 1)
>                               {
>                                       memset(selected, 0, sizeof(selected));
>                                       selected[val] = 1;
> @@ -477,10 +477,12 @@
>                       strvacat(answer, sizeof(answer), choices[i], NULL);
>               }
>               free(choices[i]);
> +             free(choices_translated[i]);
>       }
>       for (i = 0; i < dcount; i++)
>               free(defaults[i]);
>       question_setvalue(q, answer);
> +
>       return DC_OK;
>  }
>  
> @@ -505,7 +507,7 @@
>       int cursor;
>       char *tmp;
>  
> -     STRCPY(value, question_defaultval(q));
> +     STRCPY(value, question_get_field(q, "default"));
>       cursor = strlen(value);
>  
>       /* TODO: scrolling */
> Index: src/modules/frontend/text/text.c
> ===================================================================
> RCS file: 
>/cvs/debian-boot/debian-installer/tools/cdebconf/src/modules/frontend/text/text.c,v
> retrieving revision 1.15
> diff -u -r1.15 text.c
> --- src/modules/frontend/text/text.c  5 Nov 2002 03:01:51 -0000       1.15
> +++ src/modules/frontend/text/text.c  9 Nov 2002 01:21:20 -0000
> @@ -119,8 +119,8 @@
>   */
>  static void texthandler_displaydesc(struct frontend *obj, struct question *q) 
>  {
> -     wrap_print(question_description(q));
> -     wrap_print(question_extended_description(q));
> +     wrap_print(question_get_translated_field(q, "description"));
> +     wrap_print(question_get_translated_field(q, "extended_description"));
>  }
>  
>  /*
> @@ -138,7 +138,7 @@
>       int def = -1;
>       const char *defval;
>  
> -     defval = question_defaultval(q);
> +     defval = question_get_field(q, "default");
>       if (defval)
>       {
>               if (strcmp(defval, "true") == 0)
> @@ -180,25 +180,28 @@
>  static int texthandler_multiselect(struct frontend *obj, struct question *q)
>  {
>       char *choices[100] = {0};
> +     char *choices_translated[100] = {0};
>       char *defaults[100] = {0};
>       char selected[100] = {0};
> -     char answer[1024];
> +     char answer[1024] = {0};
>       int i, j, count, dcount, choice;
>  
> -     count = strchoicesplit(question_choices(q), choices, DIM(choices));
> -     dcount = strchoicesplit(question_defaultval(q), defaults, DIM(defaults));
> +     count = strchoicesplit(question_get_field(q, "choices"), choices, 
>DIM(choices));
> +     if (count <= 0) return DC_NOTOK;
> +
> +     strchoicesplit(question_get_translated_field(q, "choices"), 
>choices_translated, DIM(choices_translated));
> +     dcount = strchoicesplit(question_get_field(q, "default"), defaults, 
>DIM(defaults));
>  
> -     if (dcount > 0)
> +     for (j = 0; j < dcount; j++)
>               for (i = 0; i < count; i++)
> -                     for (j = 0; j < dcount; j++)
> -                             if (strcmp(choices[i], defaults[j]) == 0)
> -                                     selected[i] = 1;
> +                     if (strcmp(choices[i], defaults[j]) == 0)
> +                             selected[i] = 1;
>  
>       while(1)
>       {
>               for (i = 0; i < count; i++)
>               {
> -                     printf("%3d. %s%s\n", i+1, choices[i], 
> +                     printf("%3d. %s%s\n", i+1, choices_translated[i], 
>                               (selected[i] ? _(" (selected)") : ""));
>                       
>               }
> @@ -217,7 +220,6 @@
>               }
>       }
>  
> -     answer[0] = 0;
>       for (i = 0; i < count; i++)
>       {
>               if (selected[i])
> @@ -227,6 +229,7 @@
>                       strvacat(answer, sizeof(answer), choices[i], NULL);
>               }
>               free(choices[i]);
> +             free(choices_translated[i]);
>       }
>       for (i = 0; i < dcount; i++)
>               free(defaults[i]);
> @@ -301,34 +304,33 @@
>       char *choices_translated[100] = {0};
>       char answer[10];
>       int i, count, choice = 1, def = -1;
> -     const char *defval = question_defaultval(q);
> +     const char *defval = question_get_field(q, "default");
> +
> +     count = strchoicesplit(question_get_field(q, "choices"), choices, 
>DIM(choices));
> +     if (count <= 0) return DC_NOTOK;
>  
> -     count = strchoicesplit(question_choices(q), choices, DIM(choices));
> -     strchoicesplit(question_choices_translated(q), choices_translated, 
>DIM(choices_translated));
> +     strchoicesplit(question_get_translated_field(q, "choices"), 
>choices_translated, DIM(choices_translated));
>          /* fprintf(stderr,"In texthandler_select, count is: %d\n", count);*/
> -     if (count > 1)
> +     if (defval != NULL)
>       {
> -             if (defval != NULL)
> -             {
> -                     for (i = 0; i < count; i++)
> -                             if (strcmp(choices[i], defval) == 0)
> -                                     def = i + 1;
> -             }
> -
> -             do
> -             {
> -                     for (i = 0; i < count; i++)
> -                             printf("%3d. %s%s\n", i+1, choices_translated[i],
> -                                     (def == i + 1 ? _(" (default)") : ""));
> -
> -                     printf(_("Prompt: 1 - %d> "), count);
> -                     fgets(answer, sizeof(answer), stdin);
> -                     if (answer[0] == '\n')
> -                             choice = def;
> -                     else
> -                             choice = atoi(answer);
> -             } while (choice <= 0 || choice > count);
> +             for (i = 0; i < count; i++)
> +                     if (strcmp(choices[i], defval) == 0)
> +                             def = i + 1;
>       }
> +
> +     do
> +     {
> +             for (i = 0; i < count; i++)
> +                     printf("%3d. %s%s\n", i+1, choices_translated[i],
> +                             (def == i + 1 ? _(" (default)") : ""));
> +
> +             printf(_("Prompt: 1 - %d> "), count);
> +             fgets(answer, sizeof(answer), stdin);
> +             if (answer[0] == '\n')
> +                     choice = def;
> +             else
> +                     choice = atoi(answer);
> +     } while (choice <= 0 || choice > count);
>       /*      fprintf(stderr,"In %s, line: %d\n\tanswer: %s, choice[choice]: %s\n",
>               __FILE__,__LINE__,answer, choices[choice - 1]);*/
>       question_setvalue(q, choices[choice - 1]);
> @@ -352,7 +354,7 @@
>  static int texthandler_string(struct frontend *obj, struct question *q)
>  {
>       char buf[1024] = {0};
> -     const char *defval = question_defaultval(q);
> +     const char *defval = question_get_field(q, "default");
>       if (defval)
>               printf(_("[default = %s]"), defval);
>       printf("> "); fflush(stdout);
-- 
Alastair McKinstry <[EMAIL PROTECTED]>
GPG Key fingerprint = 9E64 E714 8E08 81F9 F3DC  1020 FA8E 3790 9051 38F4

He that would make his own liberty secure must guard even his enemy from
oppression; for if he violates this duty he establishes a precedent that
will reach to himself.

- --Thomas Paine

Attachment: signature.asc
Description: This is a digitally signed message part

Reply via email to