Index: lib/Makefile.am
===================================================================
RCS file: /cvsroot/synce/rra/lib/Makefile.am,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -b -B -u -p -r1.18 -r1.19
--- lib/Makefile.am	17 Aug 2004 16:13:21 -0000	1.18
+++ lib/Makefile.am	22 Jul 2005 07:34:05 -0000	1.19
@@ -1,5 +1,5 @@
 ## useful flags
-AM_CFLAGS = -g -Wall -Wsign-compare -Wno-long-long -Werror -ansi @CFLAGS@ -I..
+AM_CFLAGS = -g -Wall -Wsign-compare -Wno-long-long -ansi @CFLAGS@ -I..
 ## @APPLE_CFLAGS@
 
 includedir = @includedir@/rra
Index: lib/common_handlers.c
===================================================================
RCS file: /cvsroot/synce/rra/lib/common_handlers.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -b -B -u -p -r1.9 -r1.10
--- lib/common_handlers.c	2 May 2004 11:16:17 -0000	1.9
+++ lib/common_handlers.c	6 Aug 2005 13:11:33 -0000	1.10
@@ -1,4 +1,4 @@
-/* $Id: common_handlers.c,v 1.9 2004/05/02 11:16:17 twogood Exp $ */
+/* $Id: common_handlers.c,v 1.10 2005/08/06 13:11:33 twogood Exp $ */
 #define _GNU_SOURCE 1
 #include "common_handlers.h"
 #include "parser.h"
@@ -203,7 +203,11 @@ bool on_mdir_line_description(Parser* p,
         strbuf_append_c(note, *q);
     }
 
-    success = parser_add_blob(p, ID_NOTES, note->buffer, note->length);
+    success = parser_add_blob(
+        p, 
+        ID_NOTES, 
+        (const uint8_t*)note->buffer, 
+        note->length);
 
     if (parser_utf8(p))
       free(source);
Index: lib/contact.c
===================================================================
RCS file: /cvsroot/synce/rra/lib/contact.c,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -b -B -u -p -r1.22 -r1.23
--- lib/contact.c	13 May 2005 11:35:28 -0000	1.22
+++ lib/contact.c	22 Jul 2005 07:30:56 -0000	1.23
@@ -1,4 +1,4 @@
-/* $Id: contact.c,v 1.22 2005/05/13 11:35:28 twogood Exp $ */
+/* $Id: contact.c,v 1.23 2005/07/22 07:30:56 twogood Exp $ */
 #define _GNU_SOURCE 1
 #include "contact.h"
 #include "contact_ids.h"
@@ -67,6 +67,52 @@ static void strbuf_append_escaped(StrBuf
 	}
 }/*}}}*/
 
+/* 
+   More or less the same as strbuf_append_escaped(), but specialized for comma separated lists
+*/
+static void strbuf_append_comma_separated(StrBuf* result, char* source, uint32_t flags)/*{{{*/
+{
+	char* p;
+
+	if (!source)
+		return;
+
+	for (p = source; *p; p++)
+	{
+		switch (*p)
+		{
+			case '\r': 				/* CR */
+				/* ignore */
+				break;		
+
+			case '\n':				/* LF */
+				strbuf_append_c(result, '\\');
+				strbuf_append_c(result, 'n');
+				break;
+	
+			case '\\':
+				strbuf_append_c(result, '\\');
+				strbuf_append_c(result, *p);
+				break;
+
+			case ',':
+				strbuf_append_c(result, ',');
+				while (*(p+1)==' ') /* skip blanks after comma */
+				  p++;
+				break;
+
+			case ';':
+				if (flags & RRA_CONTACT_VERSION_3_0)
+					strbuf_append_c(result, '\\');
+				/* fall through */
+
+			default:
+				strbuf_append_c(result, *p);
+				break;
+		}
+	}
+}/*}}}*/
+
 void strbuf_append_escaped_wstr(StrBuf* strbuf, WCHAR* wstr, uint32_t flags)/*{{{*/
 {
 	if (wstr)
@@ -83,6 +129,22 @@ void strbuf_append_escaped_wstr(StrBuf* 
 	}
 }/*}}}*/
 
+void strbuf_append_comma_separated_wstr(StrBuf* strbuf, WCHAR* wstr, uint32_t flags)/*{{{*/
+{
+	if (wstr)
+	{
+		char* str = NULL;
+	 
+		if (flags & RRA_CONTACT_UTF8)
+			str = wstr_to_utf8(wstr);
+		else
+			str = wstr_to_ascii(wstr);
+
+		strbuf_append_comma_separated(strbuf, str, flags);
+		wstr_free_string(str);
+	}
+}/*}}}*/
+
 /*
  * value should be a comma-separated list of types
  */
@@ -313,7 +375,7 @@ static bool rra_contact_to_vcard2(/*{{{*
 
 			case ID_CATEGORY:
 				strbuf_append(vcard, "CATEGORIES:");
-				strbuf_append_escaped_wstr(vcard, pFields[i].val.lpwstr, flags);
+				strbuf_append_comma_separated_wstr(vcard, pFields[i].val.lpwstr, flags);
 				strbuf_append_crlf(vcard);
 				break;
 
@@ -818,8 +880,10 @@ static bool parser_handle_field(/*{{{*/
 		Parser* parser,
 		char* name, 
 		char* type, 
-		char* value)
+		char* value,
+		int nth)
 {
+
 	bool success = false;
 
 #if VERBOSE
@@ -848,7 +912,7 @@ static bool parser_handle_field(/*{{{*/
 		}
 	}/*}}}*/
 
-	if (parser->level != 1)
+	if (parser->level != 1 && nth==0)
 	{
 		synce_error("Not within BEGIN:VCARD / END:VCARD");
 		goto exit;
@@ -931,11 +995,17 @@ static bool parser_handle_field(/*{{{*/
 		/* TODO: make type uppercase */
 		if (STR_IN_STR(type, "HOME"))
 		{
+			if (nth==1)
 			add_string(parser, fax ? ID_HOME_FAX : ID_HOME_TEL, type, value);
+			else
+				add_string(parser, ID_HOME2_TEL, type, value);
 		}
 		else if (STR_IN_STR(type, "WORK"))
 		{
+			if (nth==1)
 			add_string(parser, fax ? ID_WORK_FAX : ID_WORK_TEL, type, value);
+			else
+				add_string(parser, ID_WORK2_TEL, type, value);
 		}
 		else if (STR_IN_STR(type, "CELL"))
 		{
@@ -965,7 +1035,18 @@ static bool parser_handle_field(/*{{{*/
 					type, name);
 		}
 	
+		switch (nth)
+		{
+			case 1:
 		add_string(parser, ID_EMAIL, type, value);
+				break;
+			case 2:
+				add_string(parser, ID_EMAIL2, type, value);
+				break;
+			case 3:
+				add_string(parser, ID_EMAIL3, type, value);
+				break;
+		}
 	}/*}}}*/
 	else if (STR_EQUAL(name, "URL"))/*{{{*/
 	{
@@ -1064,6 +1145,89 @@ exit:
 }/*}}}*/
 
 /*
+ * all tel_work, tel_home and email must be considered before
+ * deciding which will get a slot, as there may be too many
+ */
+void enqueue_field(/*{{{*/
+		struct FieldStrings *fs,
+		int *count,
+		int max,
+		struct FieldStrings *data)
+{
+	int slot=-1;
+	int i;
+
+	/* if there are free slots, there is no problem */
+	if ((*count)<max)
+		slot=(*count);
+	else if (data->pref) 
+		/* so there is no free slot, but a(nother) preferred one is coming
+		   kick out a non-preferred one, if possible
+		*/
+		for (i=0; i<max; i++)
+			if (!fs[i].pref) {
+				slot=i;
+				break;
+			}
+	if (slot>=0) {
+		fs[slot].name  = data->name;
+		fs[slot].type  = data->type;
+		fs[slot].value = data->value;
+		fs[slot].pref  = data->pref;
+		(*count)++;
+	}
+}/*}}}*/
+
+/*
+ * process the queued fields.
+ */
+void process_queue(/*{{{*/
+	Parser *parser,
+	struct FieldStrings *fs,
+	int count)
+{
+	int i;
+	int j=1;
+	char *loc;
+	
+	/* Get the first preferred and make it the preferred one on the device */
+	for (i=0; i<count; i++) {
+		if (fs[i].pref || count==(i+1)) {
+			parser_handle_field(
+				parser,
+				fs[i].name,
+				fs[i].type,
+				fs[i].value,
+				1);
+			/* mark this as already processed */
+			fs[i].name=NULL;
+			break;
+		}
+	}
+	
+	/* Process all remaining */
+	for (i=0; i<count; i++) {
+		if (fs[i].name!=NULL) {
+
+			/* The remaining can't be preferred. Correct me, if I'm wrong! */
+			loc = strstr(fs[i].type, "TYPE=PREF;");
+			if (!loc)
+				loc = strstr(fs[i].type, ";TYPE=PREF");
+			if (loc)
+				memmove(loc, loc+10 ,strlen(fs[i].type)-(loc-fs[i].type-10));
+
+			parser_handle_field(
+				parser,
+				fs[i].name,
+				fs[i].type,
+				fs[i].value,
+				j+1);
+			j++;
+		}
+	}
+}/*}}}*/
+
+/*
  * Simple vCard parser
  */
 static bool rra_contact_from_vcard2(/*{{{*/
@@ -1085,6 +1249,14 @@ static bool rra_contact_from_vcard2(/*{{
 	const char* value = NULL;
 	const char* value_end = NULL;
 
+	struct FieldStrings *tel_work  = malloc( MAX_TEL_WORK * sizeof( struct FieldStrings ) ); 
+	struct FieldStrings *tel_home  = malloc( MAX_TEL_HOME * sizeof( struct FieldStrings ) ); 
+	struct FieldStrings *email     = malloc( MAX_EMAIL * sizeof( struct FieldStrings ) ); 
+	struct FieldStrings *tmp_field = malloc( 1 * sizeof( struct FieldStrings ) ); 
+	int count_tel_work = 0;
+	int count_tel_home = 0;
+	int count_email    = 0;
+
 	parser.vcard_version  = RRA_CONTACT_VERSION_UNKNOWN;
 	parser.level          = 0;
 	parser.fields         = fields;
@@ -1150,12 +1322,33 @@ static bool rra_contact_from_vcard2(/*{{
 				{
 					value_end = p;
 
+					/* We have to queue tel and email fields, as there may be more than one,
+					   and we have to find out, which one is the preferred.
+					   Unfortunately there may be none, or many preferred fields :(
+					*/
+
+					tmp_field->name  = strndup(name, name_end - name);
+					tmp_field->type  = type ? strndup(type, type_end - type) : strdup("");
+					tmp_field->value = strndup(value, value_end - value);
+					tmp_field->pref  = STR_IN_STR(tmp_field->type, "PREF");
+
+					if (STR_IN_STR(tmp_field->name, "TEL") && STR_IN_STR(tmp_field->type, "WORK")) {
+						enqueue_field(tel_work, &count_tel_work, MAX_TEL_WORK, tmp_field);
+					}
+					else if (STR_IN_STR(tmp_field->name, "TEL") && STR_IN_STR(tmp_field->type, "HOME")) {
+						enqueue_field(tel_home, &count_tel_home, MAX_TEL_HOME, tmp_field);
+					}
+					else if (STR_IN_STR(tmp_field->name, "EMAIL")) {
+						enqueue_field(email, &count_email, MAX_EMAIL, tmp_field);
+					}
+					else {
 					parser_handle_field(
 							&parser,
-							strndup(name, name_end - name),
-							type ? strndup(type, type_end - type) : strdup(""),
-							strndup(value, value_end - value));
-
+								tmp_field->name,
+								tmp_field->type,
+								tmp_field->value,
+								0);
+					}
 					state = VCARD_STATE_NEWLINE;
 				}
 				p++;
@@ -1167,6 +1360,10 @@ static bool rra_contact_from_vcard2(/*{{
 		}
 	}
 
+	process_queue(&parser, tel_work, count_tel_work);
+	process_queue(&parser, tel_home, count_tel_home);
+	process_queue(&parser, email, count_email);
+
 	*field_count = parser.field_index;
 
 	success = true;
Index: lib/contact.h
===================================================================
RCS file: /cvsroot/synce/rra/lib/contact.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -B -u -p -r1.1 -r1.2
--- lib/contact.h	8 Dec 2003 09:44:02 -0000	1.1
+++ lib/contact.h	22 Jul 2005 07:30:57 -0000	1.2
@@ -1,4 +1,4 @@
-/* $Id: contact.h,v 1.1 2003/12/08 09:44:02 twogood Exp $ */
+/* $Id: contact.h,v 1.2 2005/07/22 07:30:57 twogood Exp $ */
 #ifndef __contact_h__
 #define __contact_h__
 
@@ -41,6 +41,14 @@ bool rra_contact_from_vcard(
 		uint32_t flags);
 #endif /* SWIG */
 
+struct FieldStrings
+{
+	char* name;
+	char* type;
+	char* value;
+	bool pref;
+};
+
 #define rra_contact_free_vcard(p) if (p) free(p)
 #define rra_contact_free_data(p)  if (p) free(p)
 
Index: lib/contact_ids.h
===================================================================
RCS file: /cvsroot/synce/rra/lib/contact_ids.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -b -B -u -p -r1.4 -r1.5
--- lib/contact_ids.h	16 Feb 2005 14:36:12 -0000	1.4
+++ lib/contact_ids.h	22 Jul 2005 07:30:57 -0000	1.5
@@ -59,5 +59,9 @@
 #define ID_EMAIL2       0x4093
 #define ID_EMAIL3       0x40a3
 
+#define MAX_TEL_WORK 2
+#define MAX_TEL_HOME 2
+#define MAX_EMAIL 3
+
 #endif
 
Index: src/Makefile.am
===================================================================
RCS file: /cvsroot/synce/rra/src/Makefile.am,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -b -B -u -p -r1.18 -r1.19
--- src/Makefile.am	18 Apr 2004 20:13:44 -0000	1.18
+++ src/Makefile.am	22 Jul 2005 07:34:05 -0000	1.19
@@ -1,5 +1,5 @@
 ## useful flags
-AM_CFLAGS = -g -Wall -Wsign-compare -Wno-long-long -Werror -ansi @CFLAGS@ -I../lib
+AM_CFLAGS = -g -Wall -Wsign-compare -Wno-long-long -ansi @CFLAGS@ -I../lib
 LDADD = -L../lib ../lib/librra.la
 
 bin_PROGRAMS = synce-matchmaker
