[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

[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: