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

[d-i][patch] cdebconf and localized fields



I am going to hack cdebconf in order to support UTF-8 encoded localized
templates files.  As I am new to cdebconf, I prefer posting an early
patch, which is not tested, breaks modules (the template structure is
altered), etc.  But at least there is a clean interface with localized
fields, and fixing the rest of the code should not be that hard.
Is it the way to go, or is this patch fully wrong?

Denis
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	10 Oct 2002 23:04:02 -0000
@@ -36,20 +36,36 @@
 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
+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 *template_get(struct template *, const char *lang, const char *field):
+   Return a string value for given field in a language,
+   or NULL if not found
+void template_set(struct template *, const char *lang, const char *field, const char *value):
+   Save string value at field for a given language
+
+const char *template_getC(struct template *, const char *field):
+   Return a string value for given field in English
+void template_setC(struct template *, const char *field, const char *value):
+   Save string value at English field
 
 question API
 ~~~~~~~~~~~~
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	10 Oct 2002 23:04:02 -0000
@@ -268,78 +268,34 @@
         }
 	return language;
 #else
-    return "";
+    return "C";
 #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));
+	question_expand_vars(q,
+		template_get(q->template, getlanguage(), "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)
-{
-	static char buf[4096] = {0};
-	struct language_description *langdesc;
-
-	langdesc = q->template->localized_descriptions;
-	while (langdesc)
-	{
-		if (strcmp(langdesc->language,getlanguage()) == 0 && langdesc->description != NULL)
-		{
-			question_expand_vars(q, langdesc->extended_description, buf, sizeof(buf));
-			return buf;
-		}
-		langdesc = langdesc->next;
-	}
-	question_expand_vars(q, q->template->extended_description, buf, sizeof(buf));
-	return buf;
-}
-
-const char *question_choices_translated(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 && 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));
+	question_expand_vars(q,
+		template_get(q->template, getlanguage(), "extended_description"),
+		buf, sizeof(buf));
 	return buf;
 }
 
 const char *question_choices(struct question *q)
 {
 	static char buf[4096] = {0};
-	question_expand_vars(q, q->template->choices, buf, sizeof(buf));
+	question_expand_vars(q,
+		template_get(q->template, getlanguage(), "choices"),
+		buf, sizeof(buf));
 	return buf;
 }
 
@@ -348,6 +304,6 @@
 	if (q->value != 0 && *q->value != 0)
 		return q->value;
 	else
-		return q->template->defaultval;
+		return template_get(q->template, getlanguage(), "default");
 }
 
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	10 Oct 2002 23:04:02 -0000
@@ -47,6 +47,7 @@
  * 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 +55,35 @@
 
 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->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 +103,163 @@
  * 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 (strcmp(field, "default") == 0)
+        return p->defaultval;
+    else if (strcmp(field, "choices") == 0)
+        return p->choices;
+    else if (strcmp(field, "description") == 0)
+        return p->description;
+    else if (strcmp(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 (strcmp(field, "default") == 0)
+    {
+        DELETE(p->defaultval);
+        p->defaultval = STRDUP(value);
+    }
+    else if (strcmp(field, "choices") == 0)
+    {
+        DELETE(p->choices);
+        p->choices = STRDUP(value);
+    }
+    else if (strcmp(field, "description") == 0)
+    {
+        DELETE(p->description);
+        p->description = STRDUP(value);
+    }
+    else if (strcmp(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: 
+ */
+
+const char *template_get(struct template *t, const char *lang,
+                const char *field)
+{
+    struct template_l10n_fields *p;
+    const char *ret = NULL, *altret = NULL;
+
+    if (strcmp(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 and a xx_XX field is found  */
+        if (strlen(lang) == 2 && strncmp(p->language, lang, 2) == 0)
+            altret = template_field_get(p, field);
+
+        p = p->next;
+    }
+    if (altret != NULL)
+        return altret;
+    return ret;
+}
+
+const char *template_getC(struct template *t, const char *field)
+{
+    return template_get(t, "C", field);
+}
+
+void template_set(struct template *t, const char *lang,
+                const char *field, const char *value)
+{
+    struct template_l10n_fields *p, *last;
+
+    if (strcmp(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);
+}
+
+void template_setC(struct template *t, const char *field, const char *value)
+{
+    template_set(t, "C", field, value);
+}
+
 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 +284,35 @@
 			t = template_new(p+10);
 		}
 		else if (strstr(p, "Type: ") == p && t != 0)
-			t->type = strdup(p+6);
+			template_setC(t, "type", p+6);
 		else if (strstr(p, "Default: ") == p && t != 0)
-			t->defaultval = strdup(p+9);
+			template_setC(t, "default", p+9);
 		else if (strstr(p, "Choices: ") == p && t != 0)
-			t->choices = strdup(p+9);
+			template_setC(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_set(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_set(t, lang, "choices", p+21);
 			}
+#if DEBUG
 			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;
-				}
+				fprintf(stderr, "Unknown localized fields:\n%s\n", p);
 			}
+#endif
 		}
 		else if (strstr(p, "Description: ") == p && t != 0)
 		{
-			t->description = strdup(p+13);
+			template_setC(t, "description", p+13);
 			extdesc[0] = 0;
 			i = fgetc(fp);
 			/* Don't use fgets unless you _need_ to, a
@@ -219,22 +353,29 @@
 							*bufp = ' ';
 					}
 					
-				t->extended_description = strdup(extdesc);
+				template_setC(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_set(t, lang, "description", p+22);
+			}
+			else if (strstr(p, ".UTF-8: ") == p + 17)
+			{
+				strncpy(lang, p+12, 5);
+				lang[5] = 0;
+				template_set(t, lang, "description", p+25);
+			}
+#if DEBUG
+			else
+			{
+				fprintf(stderr, "Unknown localized fields:\n%s\n", p);
+			}
+#endif
 			extdesc[0] = 0;
 			i = fgetc(fp);
 			/* Don't use fgets unless you _need_ to, a
@@ -273,37 +414,7 @@
 							*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;
-				}
+				template_set(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	10 Oct 2002 23:04:02 -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,11 +16,7 @@
 	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;
 };
 
@@ -28,6 +25,10 @@
 void template_ref(struct template *t);
 void template_deref(struct template *t);
 struct template *template_dup(struct template *t);
+const char *template_get(struct template *t, const char *l, const char *f);
+const char *template_getC(struct template *t, const char *f);
+void template_set(struct template *t, const char *lang, const char *field, const char *value);
+void template_setC(struct template *t, const char *field, const char *value);
 
 struct template *template_load(const char *filename);
 

Reply to: