Index: e-vcard.c
===================================================================
--- e-vcard.c	(revision 156)
+++ e-vcard.c	(working copy)
@@ -133,13 +133,18 @@
 	GString *str = g_string_new ("");
 	char *p = buf;
 	char *next, *next2;
+	char *start;
+	int len;
 
 	/* we're pretty liberal with line folding here.  We handle
 	   lines folded with \r\n<WS>... and \n\r<WS>... and
 	   \n<WS>... We also turn single \r's and \n's not followed by
 	   WS into \r\n's. */
+	start = p; len = 0;
 	while (*p) {
-		if (*p == '\r' || *p == '\n') {
+		if G_UNLIKELY (*p == '\r' || *p == '\n') {
+			g_string_insert_len (str, -1, start, len);
+
 			next = g_utf8_next_char (p);
 			if (*next == '\n' || *next == '\r') {
 				next2 = g_utf8_next_char (next);
@@ -147,7 +152,7 @@
 					p = g_utf8_next_char (next2);
 				}
 				else {
-					str = g_string_append (str, CRLF);
+					g_string_append (str, CRLF);
 					p = g_utf8_next_char (next);
 				}
 			}
@@ -155,15 +160,19 @@
 				p = g_utf8_next_char (next);
 			}
 			else {
-				str = g_string_append (str, CRLF);
+				g_string_append (str, CRLF);
 				p = g_utf8_next_char (p);
 			}
+			len = 0;
+			start = p;
 		}
 		else {
-			str = g_string_append_unichar (str, g_utf8_get_char (p));
+			len++;
 			p = g_utf8_next_char (p);
 		}
 	}
+	if (p != start)
+		g_string_insert_len (str, -1, start, len);
 
 	g_free (buf);
 
@@ -244,12 +253,12 @@
 				c = (((a>='a'?a-'a'+10:a-'0')&0x0f) << 4)
 					| ((b>='a'?b-'a'+10:b-'0')&0x0f);
 				
-				str = g_string_append_unichar (str, c);
+				g_string_insert_unichar (str, -1, c);
 			}
 			else 
 				{
-					str = g_string_append_c (str, a);
-					str = g_string_append_c (str, b);
+					g_string_append_c (str, a);
+					g_string_append_c (str, b);
 				}
 			
 			lp++;
@@ -259,19 +268,19 @@
 			   the characters */
 			lp = g_utf8_next_char(lp);
 			if (*lp == '\0') {
-				str = g_string_append_c (str, '\\');
+				g_string_append_c (str, '\\');
 				break;
 			}
 			switch (*lp) {
-			case 'n': str = g_string_append_c (str, '\n'); break;
-			case 'r': str = g_string_append_c (str, '\r'); break;
-			case ';': str = g_string_append_c (str, ';'); break;
-			case ',': str = g_string_append_c (str, ','); break;
-			case '\\': str = g_string_append_c (str, '\\'); break;
+			case 'n': g_string_append_c (str, '\n'); break;
+			case 'r': g_string_append_c (str, '\r'); break;
+			case ';': g_string_append_c (str, ';'); break;
+			case ',': g_string_append_c (str, ','); break;
+			case '\\': g_string_append_c (str, '\\'); break;
 			default:
 				g_warning ("invalid escape, passing it through");
-				str = g_string_append_c (str, '\\');
-				str = g_string_append_unichar (str, g_utf8_get_char(lp));
+				g_string_append_c (str, '\\');
+				g_string_insert_unichar (str, -1, g_utf8_get_char(lp));
 				break;
 			}
 			lp = g_utf8_next_char(lp);
@@ -283,7 +292,7 @@
 			lp = g_utf8_next_char(lp);
 		}
 		else {
-			str = g_string_append_unichar (str, g_utf8_get_char (lp));
+			g_string_insert_unichar (str, -1, g_utf8_get_char (lp));
 			lp = g_utf8_next_char(lp);
 		}
 	}
@@ -314,7 +323,7 @@
 			lp = g_utf8_next_char (lp);
 		}
 		else if (in_quote || g_unichar_isalnum (g_utf8_get_char (lp)) || *lp == '-' || *lp == '_') {
-			str = g_string_append_unichar (str, g_utf8_get_char (lp));
+			g_string_insert_unichar (str, -1, g_utf8_get_char (lp));
 			lp = g_utf8_next_char (lp);
 		}
 		/* accumulate until we hit the '=' or ';'.  If we hit
@@ -494,7 +503,7 @@
 			}
 		}
 		else if (g_unichar_isalnum (g_utf8_get_char (lp)) || *lp == '-' || *lp == '_') {
-			str = g_string_append_unichar (str, g_utf8_get_char (lp));
+			g_string_insert_unichar (str, -1, g_utf8_get_char (lp));
 		}
 		else {
 			g_warning ("invalid character found in attribute group/name");
@@ -617,24 +626,24 @@
 	for (p = s; p && *p; p++) {
 		switch (*p) {
 		case '\n':
-			str = g_string_append (str, "\\n");
+			g_string_append (str, "\\n");
 			break;
 		case '\r':
 			if (*(p+1) == '\n')
 				p++;
-			str = g_string_append (str, "\\n");
+			g_string_append (str, "\\n");
 			break;
 		case ';':
-			str = g_string_append (str, "\\;");
+			g_string_append (str, "\\;");
 			break;
 		case ',':
-			str = g_string_append (str, "\\,");
+			g_string_append (str, "\\,");
 			break;
 		case '\\':
-			str = g_string_append (str, "\\\\");
+			g_string_append (str, "\\\\");
 			break;
 		default:
-			str = g_string_append_c (str, *p);
+			g_string_append_c (str, *p);
 			break;
 		}
 	}
@@ -665,19 +674,19 @@
 		if (*p == '\\') {
 			p++;
 			if (*p == '\0') {
-				str = g_string_append_c (str, '\\');
+				g_string_append_c (str, '\\');
 				break;
 			}
 			switch (*p) {
-			case 'n':  str = g_string_append_c (str, '\n'); break;
-			case 'r':  str = g_string_append_c (str, '\r'); break;
-			case ';':  str = g_string_append_c (str, ';'); break;
-			case ',':  str = g_string_append_c (str, ','); break;
-			case '\\': str = g_string_append_c (str, '\\'); break;
+			case 'n':  g_string_append_c (str, '\n'); break;
+			case 'r':  g_string_append_c (str, '\r'); break;
+			case ';':  g_string_append_c (str, ';'); break;
+			case ',':  g_string_append_c (str, ','); break;
+			case '\\': g_string_append_c (str, '\\'); break;
 			default:
 				g_warning ("invalid escape, passing it through");
-				str = g_string_append_c (str, '\\');
-				str = g_string_append_unichar (str, g_utf8_get_char(p));
+				g_string_append_c (str, '\\');
+				g_string_append_unichar (str, g_utf8_get_char(p));
 				break;
 			}
 		}
@@ -745,13 +754,14 @@
 	GList *l;
 	GList *v;
 
-	GString *str = g_string_new ("");
+	GString *str;
 
-	str = g_string_append (str, "BEGIN:VCARD" CRLF);
+	str = g_string_new ("BEGIN:VCARD" CRLF);
+
 	/* we hardcode the version (since we're outputting to a
 	   specific version) and ignore any version attributes the
 	   vcard might contain */
-	str = g_string_append (str, "VERSION:3.0" CRLF);
+	g_string_append (str, "VERSION:3.0" CRLF);
 
 	for (l = evc->priv->attributes; l; l = l->next) {
 		GList *p;
@@ -771,10 +781,10 @@
 		 */
 
 		if (attr->group) {
-			attr_str = g_string_append (attr_str, attr->group);
-			attr_str = g_string_append_c (attr_str, '.');
+			g_string_append (attr_str, attr->group);
+			g_string_append_c (attr_str, '.');
 		}
-		attr_str = g_string_append (attr_str, attr->name);
+		g_string_append (attr_str, attr->name);
 
 		/* handle the parameters */
 		for (p = attr->params; p; p = p->next) {
@@ -782,10 +792,10 @@
 			/* 5.8.2:
 			 * param        = param-name "=" param-value *("," param-value)
 			 */
-			attr_str = g_string_append_c (attr_str, ';');
-			attr_str = g_string_append (attr_str, param->name);
+			g_string_append_c (attr_str, ';');
+			g_string_append (attr_str, param->name);
 			if (param->values) {
-				attr_str = g_string_append_c (attr_str, '=');
+				g_string_append_c (attr_str, '=');
 				for (v = param->values; v; v = v->next) {
 					char *value = v->data;
 					char *p = value;
@@ -798,17 +808,17 @@
 						p = g_utf8_next_char (p);
 					}
 					if (quotes)
-						attr_str = g_string_append_c (attr_str, '"');
-					attr_str = g_string_append (attr_str, value);
+						g_string_append_c (attr_str, '"');
+					g_string_append (attr_str, value);
 					if (quotes)
-						attr_str = g_string_append_c (attr_str, '"');
+						g_string_append_c (attr_str, '"');
 					if (v->next)
-						attr_str = g_string_append_c (attr_str, ',');
+						g_string_append_c (attr_str, ',');
 				}
 			}
 		}
 
-		attr_str = g_string_append_c (attr_str, ':');
+		g_string_append_c (attr_str, ':');
 
 		for (v = attr->values; v; v = v->next) {
 			char *value = v->data;
@@ -816,15 +826,15 @@
 
 			escaped_value = e_vcard_escape_string (value);
 
-			attr_str = g_string_append (attr_str, escaped_value);
+			g_string_append (attr_str, escaped_value);
 			if (v->next) {
 				/* XXX toshok - i hate you, rfc 2426.
 				   why doesn't CATEGORIES use a ; like
 				   a normal list attribute? */
 				if (!strcmp (attr->name, "CATEGORIES"))
-					attr_str = g_string_append_c (attr_str, ',');
+					g_string_append_c (attr_str, ',');
 				else
-					attr_str = g_string_append_c (attr_str, ';');
+					g_string_append_c (attr_str, ';');
 			}
 
 			g_free (escaped_value);
@@ -843,19 +853,19 @@
 				l += 75;
 				p = g_utf8_offset_to_pointer (attr_str->str, l);
 			
-				attr_str = g_string_insert_len (attr_str, (p - attr_str->str), CRLF " ", sizeof (CRLF " ") - 1);
+				g_string_insert_len (attr_str, (p - attr_str->str), CRLF " ", sizeof (CRLF " ") - 1);
 			}
 			else
 				break;
 		} while (l < g_utf8_strlen (attr_str->str, -1));
 
-		attr_str = g_string_append (attr_str, CRLF);
+		g_string_append (attr_str, CRLF);
 
-		str = g_string_append (str, attr_str->str);
+		g_string_append (str, attr_str->str);
 		g_string_free (attr_str, TRUE);
 	}
 
-	str = g_string_append (str, "END:VCARD");
+	g_string_append (str, "END:VCARD");
 
 	return g_string_free (str, FALSE);
 }
