[cdebconf] RFC: sorting translated choices fields
Hi,
I did not commit this patch because it introduces a new template
field, and would like to ask first if someone objects.
When a template contains a
Listorder: lexicographic
line, select and multiselect translated choices are sorted. This
patch only implements the text frontend, will do others when it is
seconded.
Denis
Index: src/strutl.c
===================================================================
RCS file: /cvs/debian-boot/debian-installer/tools/cdebconf/src/strutl.c,v
retrieving revision 1.22
diff -u -w -r1.22 strutl.c
--- src/strutl.c 4 Sep 2003 08:50:18 -0000 1.22
+++ src/strutl.c 12 Oct 2003 14:47:01 -0000
@@ -10,6 +10,7 @@
#ifdef HAVE_LIBTEXTWRAP
#include <textwrap.h>
#endif
+#include <assert.h>
int strcountcmp(const char *s1, const char *e1, const char *s2, const char *e2)
{
@@ -216,6 +217,88 @@
s = e;
if (*s == ',') s++;
+ }
+ return argc;
+}
+
+static int mystrcmp(const void *p1, const void *p2)
+{
+ return strcmp(*((char **) p1), *((char **) p2));
+}
+
+int strchoicesplit2(const char *inbuf, char **argv, int *tindex, size_t maxnarg)
+{
+ int argc = 0, i;
+ const char *s = inbuf, *e, *c;
+ char *p;
+
+ if (inbuf == 0) return 0;
+
+ INFO(INFO_VERBOSE, "Splitting [%s]\n", inbuf);
+ while (*s != 0 && argc < maxnarg)
+ {
+ /* skip initial spaces */
+ while (isspace(*s)) s++;
+
+ /* find end */
+ e = s;
+ while (*e != 0)
+ {
+ if (*e == '\\' && *(e+1) == ',')
+ e += 2;
+ else if (*e == ',')
+ break;
+ else
+ e++;
+ }
+
+ argv[argc] = malloc(e-s+1+10);
+ for (c = s, i = 0; c < e; c++, i++)
+ {
+ if (*c == '\\' && c < (e-1) && *(c+1) == ',')
+ {
+ argv[argc][i] = ',';
+ c++;
+ }
+ else
+ argv[argc][i] = *c;
+ }
+ argv[argc][i] = 0;
+ p = &argv[argc][i-1];
+ /* strip off trailing spaces */
+ while (p > argv[argc] && *p == ' ') *p-- = 0;
+
+ /* append string index */
+ if (tindex != NULL)
+ {
+ p++;
+ *p++ = ':';
+ snprintf(p, 10, "%d", argc);
+ }
+
+ argc++;
+ s = e;
+ if (*s == ',') s++;
+ }
+ if (tindex != NULL)
+ {
+ qsort(argv, argc, sizeof(char *), mystrcmp);
+ /*
+ * In each string stored in argv, ":IND" has been appended,
+ * where IND was the position before sorting.
+ * This loop removes this extra markup to restore original
+ * strings, and put this information into an array of integers:
+ * original index -> ret[index in translated strings]
+ */
+ i = 0;
+ while (i < argc)
+ {
+ p = strrchr(argv[i], ':');
+ assert(p);
+ *p = 0;
+ tindex[i] = strtol(p+1, NULL, 10);
+ i++;
+ }
}
return argc;
}
Index: src/strutl.h
===================================================================
RCS file: /cvs/debian-boot/debian-installer/tools/cdebconf/src/strutl.h,v
retrieving revision 1.12
diff -u -w -r1.12 strutl.h
--- src/strutl.h 24 Feb 2003 20:17:53 -0000 1.12
+++ src/strutl.h 12 Oct 2003 14:47:01 -0000
@@ -40,6 +40,7 @@
int strparsecword(char **inbuf, char *outbuf, size_t maxlen);
int strparsequoteword(char **inbuf, char *outbuf, size_t maxlen);
int strchoicesplit(const char *inbuf, char **argv, size_t maxnarg);
+int strchoicesplit2(const char *inbuf, char **argv, int *tindex, size_t maxnarg);
int strcmdsplit(char *inbuf, char **argv, size_t maxnarg);
void strunescape(const char *inbuf, char *outbuf, const size_t maxlen, const int quote);
void strescape(const char *inbuf, char *outbuf, const size_t maxlen, const int quote);
Index: src/template.c
===================================================================
RCS file: /cvs/debian-boot/debian-installer/tools/cdebconf/src/template.c,v
retrieving revision 1.26
diff -u -w -r1.26 template.c
--- src/template.c 8 Oct 2003 22:03:51 -0000 1.26
+++ src/template.c 12 Oct 2003 14:47:01 -0000
@@ -18,6 +18,7 @@
const char *template_fields_list[] = {
"tag",
"type",
+ "listorder",
"default",
"choices",
"description",
@@ -116,6 +117,7 @@
DELETE(t->tag);
DELETE(t->type);
+ DELETE(t->listorder);
p = t->fields;
DELETE(t);
while (p != NULL)
@@ -155,6 +157,7 @@
struct template_l10n_fields *from, *to;
ret->type = STRDUP(t->type);
+ ret->listorder = STRDUP(t->listorder);
if (t->fields == NULL)
return ret;
@@ -248,6 +251,8 @@
return t->tag;
else if (strcasecmp(field, "type") == 0)
return t->type;
+ else if (strcasecmp(field, "listorder") == 0)
+ return t->listorder;
/* If field is Foo-xx.UTF-8 then call template_lget(t, "xx", "Foo") */
if (strchr(field, '-') != NULL)
@@ -351,6 +356,11 @@
t->type = STRDUP(value);
return;
}
+ else if (strcasecmp(field, "listorder") == 0)
+ {
+ t->listorder = STRDUP(value);
+ return;
+ }
/* If field is Foo-xx.UTF-8 then call template_lget(t, "xx", "Foo") */
if (strchr(field, '-') != NULL)
@@ -500,6 +510,8 @@
t = template_new(p+10);
else if (strstr(p, "Type: ") == p && t != 0)
template_lset(t, NULL, "type", p+6);
+ else if (strstr(p, "Listorder: ") == p && t != 0)
+ template_lset(t, NULL, "listorder", p+11);
else if (strstr(p, "Default: ") == p && t != 0)
template_lset(t, NULL, "default", p+9);
else if (strstr(p, "Default-") == p && t != 0)
Index: src/template.h
===================================================================
RCS file: /cvs/debian-boot/debian-installer/tools/cdebconf/src/template.h,v
retrieving revision 1.8
diff -u -w -r1.8 template.h
--- src/template.h 18 Aug 2003 13:24:18 -0000 1.8
+++ src/template.h 12 Oct 2003 14:47:01 -0000
@@ -20,6 +20,7 @@
char *tag;
unsigned int ref;
char *type;
+ char *listorder;
struct template_l10n_fields *fields;
struct template *next;
char *(*lget)(struct template *, const char *l, const char *f);
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.45
diff -u -w -r1.45 text.c
--- src/modules/frontend/text/text.c 8 Oct 2003 21:40:19 -0000 1.45
+++ src/modules/frontend/text/text.c 12 Oct 2003 14:47:02 -0000
@@ -60,6 +60,7 @@
#define q_get_description(q) question_get_field((q), "", "description")
#define q_get_choices(q) question_get_field((q), "", "choices")
#define q_get_choices_vals(q) question_get_field((q), NULL, "choices")
+#define q_get_listorder(q) question_get_field((q), NULL, "listorder")
#define MAKE_UPPER(C) do { if (islower((int) C)) { C = (char) toupper((int) C); } } while(0)
/*
@@ -250,6 +251,7 @@
char answer[4096] = {0};
int i, j, line, count = 0, dcount, choice;
const char *p;
+ int *tindex = NULL;
p = q_get_choices_vals(q);
if (*p)
@@ -264,23 +266,31 @@
choices = malloc(sizeof(char *) * count);
count = strchoicesplit(q_get_choices_vals(q), choices, count);
choices_translated = malloc(sizeof(char *) * count);
- if (strchoicesplit(q_get_choices(q), choices_translated, count) != count)
+ if (strcmp(q_get_listorder(q), "lexicographic") == 0)
+ tindex = malloc(sizeof(int *) * count);
+ if (strchoicesplit2(q_get_choices(q), choices_translated, tindex, count) != count)
return DC_NOTOK;
+ if (tindex == NULL)
+ {
+ tindex = malloc(sizeof(int *) * count);
+ for (i=0; i<count; i++)
+ tindex[i] = i;
+ }
defaults = malloc(sizeof(char *) * count);
dcount = strchoicesplit(question_getvalue(q, ""), defaults, count);
selected = calloc(1, sizeof(char) * count);
for (j = 0; j < dcount; j++)
for (i = 0; i < count; i++) {
- if (strcmp(choices[i], defaults[j]) == 0)
- selected[i] = 1;
+ if (strcmp(choices[tindex[i]], defaults[j]) == 0)
+ selected[tindex[i]] = 1;
}
i = 0;
while (1) {
for (line = 0; i < count && line < getheight()-1; i++, line++)
- if (selected[i])
+ if (selected[tindex[i]])
/* A selected item in a Multiselect question */
printf(get_text(obj, "debconf/multiselect-selected", "%3d. %s (selected)"), i+1, choices_translated[i]);
else
@@ -309,14 +319,14 @@
if (answer[0] == *(get_text(obj,"debconf/begin-key", "B")))
{ i = 0; continue; }
- choice = atoi(answer);
+ choice = atoi(answer) - 1;
- if (choice > 0 && choice <= count) {
- if (selected[choice-1] == 0)
- selected[choice-1] = 1;
+ if (choice >= 0 && choice < count) {
+ if (selected[tindex[choice]] == 0)
+ selected[tindex[choice]] = 1;
else
- selected[choice-1] = 0;
- i = choice-getheight()+1 > 0 ? choice-getheight()+1 : 0;
+ selected[tindex[choice]] = 0;
+ i = choice-getheight()+2 > 0 ? choice-getheight()+2 : 0;
}
}
@@ -332,6 +342,7 @@
free(choices[i]);
free(choices_translated[i]);
}
+ free(tindex);
free(choices);
free(choices_translated);
free(selected);
@@ -422,6 +433,7 @@
int i, line, count = 0, choice = 1, def = -1;
const char *defval = question_getvalue(q, "");
const char *p;
+ int *tindex = NULL;
p = q_get_choices_vals(q);
if (*p)
@@ -436,8 +448,16 @@
choices = malloc(sizeof(char *) * count);
count = strchoicesplit(q_get_choices_vals(q), choices, count);
choices_translated = malloc(sizeof(char *) * count);
- if (strchoicesplit(q_get_choices(q), choices_translated, count) != count)
+ if (strcmp(q_get_listorder(q), "lexicographic") == 0)
+ tindex = malloc(sizeof(int *) * count);
+ if (strchoicesplit2(q_get_choices(q), choices_translated, tindex, count) != count)
return DC_NOTOK;
+ if (tindex == NULL)
+ {
+ tindex = malloc(sizeof(int *) * count);
+ for (i=0; i<count; i++)
+ tindex[i] = i;
+ }
if (count == 1)
defval = choices[0];
@@ -446,15 +466,15 @@
if (defval != NULL)
{
for (i = 0; i < count; i++)
- if (strcmp(choices[i], defval) == 0)
- def = i + 1;
+ if (strcmp(choices[tindex[i]], defval) == 0)
+ def = i;
}
i = 0;
do {
for (line = 0; i < count && line < getheight()-1; i++, line++) {
- if (def == i + 1)
+ if (def == i)
/* A selected item in a Select question */
printf(get_text(obj, "debconf/select-default", "%3d. %s (default)"), i+1, choices_translated[i]);
else
@@ -463,9 +483,9 @@
}
if (i == count) {
- if (def > 0 && choices_translated[def-1]) {
+ if (def >= 0 && choices_translated[def]) {
printf(get_text(obj, "debconf/prompt-num-with-default", "Prompt: 1 - %d, default=%s> "),
- count, choices_translated[def-1]);
+ count, choices_translated[def]);
} else {
printf(get_text(obj, "debconf/prompt-num", "Prompt: 1 - %d> "), count);
}
@@ -482,16 +502,17 @@
#endif
choice = def;
else
- choice = atoi(answer);
- } while (choice <= 0 || choice > count);
+ choice = atoi(answer) - 1;
+ } 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]);
+ question_setvalue(q, choices[tindex[choice]]);
for (i = 0; i < count; i++)
{
free(choices[i]);
free(choices_translated[i]);
}
+ free(tindex);
free(choices);
free(choices_translated);
Reply to: