[PATCH] Integrate convert_body2printable() into expand_ctrl_chars()

Michael Bienia <[email protected]>
Newsgroups gmane.network.tin.devel
Message-ID <[email protected]>
Hello,

the attached patch integrates convert_body2printable() into
expand_ctrl_chars().

I've also removed the addition of \n to the end of the string from
expand_ctrl_chars() to see what breaks. But so far everything seems to
be okay.

The asserts within the wide-char case in expand_ctrl_chars() are there
to catch remaining bugs with wide chars. They should be removed before
the next stable release and replaced with fall-back code if necessary.

Michael
patch-20060530.diff (text/plain, 8.2 KB)
 include/proto.h |    1 
 src/charset.c   |   42 --------------------
 src/cook.c      |  113 +++++++++++++++++++++++++++++++++++++++-----------------
 src/help.c      |    4 -
 4 files changed, 81 insertions(+), 79 deletions(-)
diff -Nurp tin-1.9.1/include/proto.h tin-1.9.1.patched/include/proto.h
--- tin-1.9.1/include/proto.h	2006-02-15 19:44:37.000000000 +0100
+++ tin-1.9.1.patched/include/proto.h	2006-05-27 17:54:41.435700561 +0200
@@ -85,7 +85,6 @@ extern void write_attributes_file(const 
 
 /* charset.c */
 extern char *convert_to_printable(char *buf);
-extern char *convert_body2printable(char* buf);
 extern t_bool is_art_tex_encoded(FILE *fp);
 extern void convert_iso2asc(char *iso, char **asc_buffer, int *max_line_len, int t);
 extern void convert_tex2iso(char *from, char *to);
diff -Nurp tin-1.9.1/src/charset.c tin-1.9.1.patched/src/charset.c
--- tin-1.9.1/src/charset.c	2006-02-22 01:31:06.000000000 +0100
+++ tin-1.9.1.patched/src/charset.c	2006-05-27 17:54:24.548642913 +0200
@@ -427,45 +427,3 @@ wconvert_to_printable(
 	return wbuf;
 }
 #endif /* MULTIBYTE_ABLE && !NO_LOCALE */
-
-
-/*
- * Same as convert_to_printable() but allows Backspace (ASCII 8), TAB (ASCII
- * 9), and FormFeed (ASCII 12) according to son of RFC 1036 section 4.4;
- * LineFeed (ASCII 10) and CarriageReturn (ASCII 13) are allowed, too.
- *
- * NOTES: don't make wc a wint_t as libutf8 (at least version 0.8)
- *        sometimes fails to propper convert (wchar_t) 0 to (wint_t) 0
- *        and thus loop termination fails.
- */
-char *
-convert_body2printable(
-	char *buf)
-{
-#if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
-	char *buffer;
-	wchar_t *wc, *wbuffer;
-	size_t len = strlen(buf) + 1;
-
-	if ((wbuffer = char2wchar_t(buf)) != NULL) {
-		for (wc = wbuffer; *wc; wc++) {
-			if (!(iswprint((wint_t) *wc) || *wc == (wchar_t) 8 || *wc == (wchar_t) 9 || *wc == (wchar_t) 10 || *wc == (wchar_t) 12 || *wc == (wchar_t) 13 || (IS_LOCAL_CHARSET("Big5") && *wc == (wchar_t) 27)))
-				*wc = (wchar_t) '?';
-		}
-		if ((buffer = wchar_t2char(wbuffer)) != NULL) {
-			strncpy(buf, buffer, len);
-			buf[len - 1] = '\0';
-			free(buffer);
-		}
-		free(wbuffer);
-	}
-#else
-	unsigned char *c;
-
-	for (c = (unsigned char *) buf; *c; c++) {
-		if (!(my_isprint(*c) || *c == 8 || *c == 9 || *c == 10 || *c == 12 || *c == 13 || (IS_LOCAL_CHARSET("Big5") && *c == 27)))
-			*c = '?';
-	}
-#endif /* MULTIBYTE_ABLE && !NO_LOCALE */
-	return buf;
-}
diff -Nurp tin-1.9.1/src/cook.c tin-1.9.1.patched/src/cook.c
--- tin-1.9.1/src/cook.c	2006-03-11 13:35:26.000000000 +0100
+++ tin-1.9.1.patched/src/cook.c	2006-05-30 15:55:34.544114362 +0200
@@ -59,6 +59,9 @@ static t_bool header_wanted(const char *
 static t_part *new_uue(t_part **part, char *name);
 static void process_text_body_part(t_bool wrap_lines, FILE *in, t_part *part, int hide_uue, int tabs);
 static void put_cooked(size_t buf_len, t_bool wrap_lines, int flags, const char *fmt, ...);
+#if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
+	static t_bool wexpand_ctrl_chars(wchar_t **wline, size_t *length, size_t lcook_width);
+#endif /* MULTIBYTE_ABLE && !NO_LOCALE */
 #ifdef DEBUG_ART
 	static void dump_cooked(void);
 #endif /* DEBUG_ART */
@@ -82,60 +85,109 @@ expand_ctrl_chars(
 	int *length,
 	size_t lcook_width)
 {
+	t_bool ctrl_L = FALSE;
+#if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
+	wchar_t *wline = char2wchar_t(*line);
+	size_t wlen;
+
+	/* 
+	 * remove the assert() before release
+	 * it should help us find problems with wide-char strings
+	 * in the development branch
+	 */
+	assert (wline != NULL);
+	wlen = wcslen(wline);
+	ctrl_L = wexpand_ctrl_chars(&wline, &wlen, lcook_width);
+	free(*line);
+	*line = wchar_t2char(wline);
+	free(wline);
+	assert (line != NULL);
+	*length = strlen(*line);
+#else
 	int curr_len = LEN;
 	int i = 0, j;
 	char *buf = my_malloc(curr_len);
 	char *c;
-	t_bool ctrl_L = FALSE, resize = FALSE;
 
 	c = *line;
 	while (*c) {
-		if (resize) {
+		if (i > curr_len - 3) {
 			curr_len <<= 1;
 			buf = my_realloc(buf, curr_len);
-			resize = FALSE;
 		}
-		if (*c == '\t') { /* expand tabs */
+		if (*c == '\t') { 		/* expand tabs */
 /*			j = ((i + lcook_width) / lcook_width) * lcook_width; */
 			j = i + lcook_width - (i % lcook_width);
-			if (j > curr_len - 2) {
-				resize = TRUE;
-				continue;
-			}
 			for (; i < j; i++)
 				buf[i] = ' ';
+		} else if (((*c) & 0xFF) < ' ' && *c != '\n' && (!IS_LOCAL_CHARSET("Big5") || *c != 27)) {	/* literal ctrl chars */
+			buf[i++] = '^';
+			buf[i++] = ((*c) & 0xFF) + '@';
+			if (*c == '\f')		/* ^L detected */
+				ctrl_L = TRUE;
 		} else {
-			if (((*c) & 0xFF) < ' ' && *c != '\n' && (!IS_LOCAL_CHARSET("Big5") || *c != 27)) {	/* literal ctrl chars */
-				if (i > curr_len - 4) {
-					resize = TRUE;
-					continue;
-				}
-				buf[i++] = '^';
-				buf[i++] = ((*c) & 0xFF) + '@';
-				if (*c == '\f')	/* ^L detected */
-					ctrl_L = TRUE;
-			} else {
-				if (i > curr_len - 3) {
-					resize = TRUE;
-					continue;
-				}
+			if (!my_isprint(*c) && *c != '\n')
+				buf[i++] = '?';
+			else
 				buf[i++] = *c;
-			}
 		}
 		c++;
 	}
-	/* put_cooked() requires a newline at the end of the line */
-	if (buf[i - 1] != '\n')
-		buf[i++] = '\n';	/* Force last char of string to be \n */
 	buf[i] = '\0';
 	*length = i + 1;
 	*line = my_realloc(*line, *length);
 	strcpy(*line, buf);
 	free(buf);
+#endif /* MULTIBYTE_ABLE && !NO_LOCALE */
 	return ctrl_L;
 }
 
 
+#if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
+static t_bool
+wexpand_ctrl_chars(
+	wchar_t **wline,
+	size_t *length,
+	size_t lcook_width)
+{
+	size_t cur_len = LEN, i = 0, j;
+	wchar_t *wbuf = my_malloc(cur_len * sizeof(wchar_t));
+	wchar_t *wc;
+	t_bool ctrl_L = FALSE;
+
+	wc = *wline;
+	while (*wc) {
+		if (i > cur_len - 3) {
+			cur_len <<= 1;
+			wbuf = my_realloc(wbuf, cur_len * sizeof(wchar_t));
+		}
+		if (*wc == '\t') {		/* expand_tabs */
+			j = i + lcook_width - (i % lcook_width);
+			for (; i < j; i++)
+				wbuf[i] = ' ';
+		} else if (*wc  < ' ' && *wc != '\n' && (!IS_LOCAL_CHARSET("Big5") || *wc != 27)) {	/* literal ctrl chars */
+			wbuf[i++] = '^';
+			wbuf[i++] = *wc + '@';
+			if (*wc == '\f')	/* ^L detected */
+				ctrl_L = TRUE;
+		} else {
+			if (!iswprint((wint_t) *wc) && *wc != '\n')
+				wbuf[i++] = '?';
+			else
+				wbuf[i++] = *wc;
+		}
+		wc++;
+	}
+	wbuf[i] = '\0';
+	*length = i + 1;
+	*wline = my_realloc(*wline, *length * sizeof(wchar_t));
+	wcscpy(*wline, wbuf);
+	free(wbuf);
+	return ctrl_L;
+}
+#endif /* MULTIBYTE_ABLE && !NO_LOCALE */
+
+
 /*
  * Output text to the cooked stream. Wrap lines as necessary.
  * Update the line count and the array of line offsets
@@ -552,13 +604,6 @@ process_text_body_part(
 		if (MATCH_REGEX(news_regex, line, len))
 			flags |= C_NEWS;
 
-		/*
-		 * Basically, c_b2p() does: if (!(my_isprint(*c) || *c==8 || *c==9 || *c==12))
-		 * It is only used here
-		 * How about if !isprint() && !isctrl() - expand_ctrl_chars is done at display time.
-		 * TODO: integrate into expand_ctrl_chars
-		 */
-		convert_body2printable(line);
 		if (expand_ctrl_chars(&line, &max_line_len, tabs))
 			flags |= C_CTRLL;				/* Line contains form-feed */
 		put_cooked(max_line_len, wrap_lines && (!IS_LOCAL_CHARSET("Big5")), flags, "%s", line);
@@ -692,7 +737,7 @@ cook_article(
 
 		if (header_wanted(line)) {	/* Put cooked data */
 			int i = LEN;
-			char *l = my_strdup(convert_body2printable(rfc1522_decode(line)));	/* FIXME: don't decode addr-part of From:/Cc:/ etc.pp. */
+			char *l = my_strdup(rfc1522_decode(line));	/* FIXME: don't decode addr-part of From:/Cc:/ etc.pp. */
 
 			header_put = TRUE;
 			expand_ctrl_chars(&l, &i, tabs);
diff -Nurp tin-1.9.1/src/help.c tin-1.9.1.patched/src/help.c
--- tin-1.9.1/src/help.c	2006-02-15 19:44:37.000000000 +0100
+++ tin-1.9.1.patched/src/help.c	2006-05-30 16:06:00.308753894 +0200
@@ -469,7 +469,7 @@ make_help_page(
 				snprintf(buf, LEN, "%s", _(helppage->helptext));
 			buf[LEN - 1] = '\0';
 			expand_ctrl_chars(&buf, &length, 8);
-			fprintf(fp, "%s", buf);
+			fprintf(fp, "%s\n", buf);
 		} else {
 			for (i = 0; i < keys.used; i++) {
 				if (keys.list[i].function == helppage->func && keys.list[i].key) {
@@ -478,7 +478,7 @@ make_help_page(
 					buf[LEN - 1] = '\0';
 					expand_ctrl_chars(&buf, &length, 8);
 					if (strcmp(last, buf)) {
-						fprintf(fp, "%s", buf);
+						fprintf(fp, "%s\n", buf);
 						strncpy(last, buf, LEN);
 					}
 				}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.