From 4f4b00f8dd2fee76efe3d068d4fdfdb714d1d39f Mon Sep 17 00:00:00 2001 From: =?utf8?q?Rapha=C3=ABl=20Droz?= Date: Sun, 20 Jan 2013 17:20:44 +0100 Subject: [PATCH] miscellaneous fixes & doc: i18n, custom format and vcard * converted HOWTO.translating_abook to UTF-8, added a couple of lines about quickly installing and testing new translations and updated URL of some po-related softwares. * fixed a trivial error with custom format strncpy() initialization * vcard builtin import: removed variables unused since e3aa1d4 * vcard export: set a "PREF" EMAIL field attribute (not [yet] used by vcard import though) * vcard libvformat import: - fixed segfault on 64bits arch where a va_list's NULL sentinel value must be properly casted [sizeof(int) != sizeof(char *)] - now really import multivalued fields (better use of libvformat): VFGP_FIND instead of VFGP_GET + vf_get_next_property() - use of abook_list instead of strconcat for multivalued fields (groups and emails) - no more duplicated phone numbers if one or more *PHONE/FAX is provided while no HOMEPHONE is available --- abook.c | 4 +- doc/HOWTO.translating_abook | 14 ++-- filter.c | 12 ++-- vcard.c | 133 +++++++++++++++--------------------- 4 files changed, 71 insertions(+), 92 deletions(-) diff --git a/abook.c b/abook.c index 05ec429..1651267 100644 --- a/abook.c +++ b/abook.c @@ -390,8 +390,8 @@ parse_command_line(int argc, char **argv) selected_item_filter = select_output_item_filter(outformat); break; case OPT_OUTFORMAT_STR: - strncpy(custom_format, optarg, FORMAT_STRING_LEN - 1); - custom_format[FORMAT_STRING_LEN] = 0; + strncpy(custom_format, optarg, FORMAT_STRING_LEN); + custom_format[FORMAT_STRING_LEN - 1] = 0; break; case OPT_INFILE: set_convert_var(infile); diff --git a/doc/HOWTO.translating_abook b/doc/HOWTO.translating_abook index 2dfec7d..0c303a7 100644 --- a/doc/HOWTO.translating_abook +++ b/doc/HOWTO.translating_abook @@ -193,7 +193,7 @@ A few notes: contributors can contact you if they want to join you in the translation team, or have remarks/typo fixes to give about the translations. You can either just give your name/nick, or add an email - address, f ex "Last-Translator: Cédric Duval \n". + address, f ex "Last-Translator: Cédric Duval \n". * Comments Adding comments (lines begining with the '#' character) can be a good @@ -207,6 +207,12 @@ A few notes: (standard length is 80 characters). Don't translate blindly, try to look where your string will be displayed to adapt your translation. +* Testing translations + To give a look at the live translations without really installing abook + you can install abook and its mo files in a subdirectory: + ./configure --prefix $(pwd)/fakeinstall/usr ; make install + Then, eg: LANGUAGE=sv ./fakeinstall/usr/bin/abook + * A few useful tools The po-file format is very simple, and the file can be edited with a standard text editor. @@ -214,8 +220,8 @@ A few notes: But if you prefer, there are few specialized tools you may find convenient for translating: * poEdit (http://www.poedit.org/) - * KBabel (http://i18n.kde.org/tools/kbabel/) - * GTranslator (http://gtranslator.sourceforge.net/) + * Lokalize (http://userbase.kde.org/Lokalize/) + * GTranslator (http://projects.gnome.org/gtranslator/) * Emacs po mode * Vim po mode (http://vim.sourceforge.net/scripts/script.php?script_id=695 @@ -229,6 +235,6 @@ And finally I hope you'll have fun contributing to a more internationalized world. :) If you have any more questions, don't hesitate to contact me -(Cédric Duval ) or the abook development +(Cédric Duval ) or the abook development mailing list (http://lists.sourceforge.net/lists/listinfo/abook-devel). diff --git a/filter.c b/filter.c index 613a827..20c8973 100644 --- a/filter.c +++ b/filter.c @@ -1645,10 +1645,7 @@ vcard_parse_email(list_item item, char *line) static void vcard_parse_address(list_item item, char *line) { - int i; - int k; char *value; - char *address_field; value = vcard_get_line_element(line, VCARD_VALUE); if(!value) @@ -2000,7 +1997,7 @@ vcard_export_database(FILE *out, struct db_enumerator e) void vcard_export_item(FILE *out, int item) { - int j; + int j, email_no; char *name, *tmp; abook_list *emails, *em; fprintf(out, "BEGIN:VCARD\r\nFN:%s\r\n", @@ -2048,9 +2045,10 @@ vcard_export_item(FILE *out, int item) tmp = db_email_get(item); if(*tmp) { emails = csv_to_abook_list(tmp); - - for(em = emails; em; em = em->next) - fprintf(out, "EMAIL;INTERNET:%s\r\n", em->data); + fprintf(out, "EMAIL;PREF;INTERNET:%s\r\n", emails->data); + email_no = 1; + for(em = emails->next; em; em = em->next, email_no++ ) + fprintf(out, "EMAIL;%d;INTERNET:%s\r\n", email_no, em->data); abook_list_free(&emails); } diff --git a/vcard.c b/vcard.c index 0ff5642..060de88 100644 --- a/vcard.c +++ b/vcard.c @@ -16,6 +16,8 @@ #include #include "database.h" +#include "options.h" // bool +#include "misc.h" // abook_list_to_csv #include "xmalloc.h" #include "vcard.h" @@ -32,51 +34,50 @@ int vcard_parse_file_libvformat(char *filename) { // property number (used for multivalued properties) int props = 0; // temporary values - char *propval; - char multival[MAX_FIELD_LEN] = { 0 }; - size_t available = MAX_FIELD_LEN; + abook_list *multivalues = NULL; + char *propval = 0; + bool phone_found; do { list_item item = item_create(); + phone_found = false; + /* Note: libvformat use va_args, we *must* cast the last + NULL argument to (char*) for arch where + sizeof(int) != sizeof(char *) */ // fullname [ or struct-name [ or name ] ] - if (vf_get_property(&prop, vfobj, VFGP_FIND, NULL, "FN", NULL)) + if (vf_get_property(&prop, vfobj, VFGP_FIND, NULL, "FN", (char*)0)) if ((propval = vf_get_prop_value_string(prop, 0))) item_fput(item, NAME, xstrdup(propval)); - if (!propval && vf_get_property(&prop, vfobj, VFGP_FIND, NULL, "N", "*", NULL)) { - // TODO: GIVENNAME , FAMILYNAME + if (!propval && vf_get_property(&prop, vfobj, VFGP_FIND, NULL, "N", (char*)0)) { + // TODO: GIVENNAME, FAMILYNAME propval = vf_get_prop_value_string(prop, 0); if(propval) item_fput(item, NAME, xstrdup(propval)); } - if (!propval && vf_get_property(&prop, vfobj, VFGP_FIND, NULL, "NAME", NULL)) { + if (!propval && vf_get_property(&prop, vfobj, VFGP_FIND, NULL, "NAME", (char*)0)) { propval = vf_get_prop_value_string(prop, 0); if(propval) item_fput(item, NAME, xstrdup(propval)); } - // email(s) - // TODO: use our strconcat() ? - if (vf_get_property(&prop, vfobj, VFGP_FIND, NULL, "EMAIL", NULL)) { - props = 0; - available = MAX_FIELD_LEN; - while (available > 0 && props < 5) { - propval = vf_get_prop_value_string(prop, props++); - if(!propval) continue; - if (available > 0 && *multival != 0) - strncat(multival, ",", available--); - strncat(multival, propval, available); - available -= strlen(propval); - } - if (available < MAX_FIELD_LEN) - item_fput(item, EMAIL, xstrdup(multival)); + // email(s). (TODO: EMAIL;PREF: should be abook's first) + if (vf_get_property(&prop, vfobj, VFGP_FIND, NULL, "EMAIL", (char*)0)) { + do { + props = 0; + while ((propval = vf_get_prop_value_string(prop, props++))) { + abook_list_append(&multivalues, propval); + } + } while (vf_get_next_property(&prop)); + item_fput(item, EMAIL, abook_list_to_csv(multivalues)); + abook_list_free(&multivalues); } // format for ADR: // PO Box, Extended Addr, Street, Locality, Region, Postal Code, Country - if (vf_get_property(&prop, vfobj, VFGP_FIND, NULL, "ADR", NULL)) { + if (vf_get_property(&prop, vfobj, VFGP_FIND, NULL, "ADR", (char*)0)) { props = 0; // PO Box: abook ignores vf_get_prop_value_string(prop, props++); @@ -101,91 +102,65 @@ int vcard_parse_file_libvformat(char *filename) { if(propval) item_fput(item, COUNTRY, xstrdup(propval)); } - - /* - // city: not in libvformat - if (vf_get_property(&prop, vfobj, VFGP_FIND, NULL, "ADR", "CITY", NULL)) { - propval = vf_get_prop_value_string(prop, 0); - item_fput(item, CITY, xstrdup(propval)); - } - // state - // zip - // country - if (vf_get_property(&prop, vfobj, VFGP_FIND, NULL, "C", NULL)) { - propval = vf_get_prop_value_string(prop, 0); - item_fput(item, COUNTRY, xstrdup(propval)); + // phone numbers + // home + if (vf_get_property(&prop, vfobj, VFGP_FIND, NULL, "TEL", "HOME", (char*)0) && (propval = vf_get_prop_value_string(prop, 0))) { + item_fput(item, PHONE, xstrdup(propval)); phone_found = true; } - */ - - // phone - // check for HOME - if (vf_get_property(&prop, vfobj, VFGP_FIND, NULL, "TEL", "HOME")) { - propval = vf_get_prop_value_string(prop, 0); - item_fput(item, PHONE, xstrdup(propval)); - } - // or grab a more generic one otherwise - else if(vf_get_property(&prop, vfobj, VFGP_FIND, NULL, "TEL", NULL)) { - propval = vf_get_prop_value_string(prop, 0); - item_fput(item, PHONE, xstrdup(propval)); - } - // workphone - if (vf_get_property(&prop, vfobj, VFGP_FIND, NULL, "TEL", "WORK", NULL)) { - propval = vf_get_prop_value_string(prop, 0); - item_fput(item, WORKPHONE, xstrdup(propval)); + if (vf_get_property(&prop, vfobj, VFGP_FIND, NULL, "TEL", "WORK", (char*)0) && (propval = vf_get_prop_value_string(prop, 0))) { + item_fput(item, WORKPHONE, xstrdup(propval)); phone_found = true; } // fax - if (vf_get_property(&prop, vfobj, VFGP_FIND, NULL, "TEL", "FAX", NULL)) { - propval = vf_get_prop_value_string(prop, 0); - item_fput(item, FAX, xstrdup(propval)); + if (vf_get_property(&prop, vfobj, VFGP_FIND, NULL, "TEL", "FAX", (char*)0) && (propval = vf_get_prop_value_string(prop, 0))) { + item_fput(item, FAX, xstrdup(propval)); phone_found = true; } // cellphone - if (vf_get_property(&prop, vfobj, VFGP_FIND, NULL, "TEL", "CELL", NULL)) { - propval = vf_get_prop_value_string(prop, 0); - item_fput(item, MOBILEPHONE, xstrdup(propval)); + if (vf_get_property(&prop, vfobj, VFGP_FIND, NULL, "TEL", "CELL", (char*)0) && (propval = vf_get_prop_value_string(prop, 0))) { + item_fput(item, MOBILEPHONE, xstrdup(propval)); phone_found = true; + } + + // or grab any other one as default + if(! phone_found && vf_get_property(&prop, vfobj, VFGP_FIND, NULL, "TEL", (char*)0) && (propval = vf_get_prop_value_string(prop, 0))) { + item_fput(item, PHONE, xstrdup(propval)); } // nick - if (vf_get_property(&prop, vfobj, VFGP_FIND, NULL, "NICKNAME", NULL)) { - propval = vf_get_prop_value_string(prop, 0); - item_fput(item, NICK, xstrdup(propval)); + if (vf_get_property(&prop, vfobj, VFGP_FIND, NULL, "NICKNAME", (char*)0)) { + propval = vf_get_prop_value_string(prop, 0); + item_fput(item, NICK, xstrdup(propval)); } // url - if (vf_get_property(&prop, vfobj, VFGP_FIND, NULL, "URL", NULL)) { + if (vf_get_property(&prop, vfobj, VFGP_FIND, NULL, "URL", (char*)0)) { propval = vf_get_prop_value_string(prop, 0); item_fput(item, URL, xstrdup(propval)); } // notes - if (vf_get_property(&prop, vfobj, VFGP_FIND, NULL, "NOTE", NULL)) { + if (vf_get_property(&prop, vfobj, VFGP_FIND, NULL, "NOTE", (char*)0)) { propval = vf_get_prop_value_string(prop, 0); item_fput(item, NOTES, xstrdup(propval)); } // anniversary - if (vf_get_property(&prop, vfobj, VFGP_FIND, NULL, "BDAY", NULL)) { + if (vf_get_property(&prop, vfobj, VFGP_FIND, NULL, "BDAY", (char*)0)) { propval = vf_get_prop_value_string(prop, 0); item_fput(item, ANNIVERSARY, xstrdup(propval)); } // (mutt) groups - if (vf_get_property(&prop, vfobj, VFGP_FIND, NULL, "CATEGORIES", NULL)) { - props = 0; - available = MAX_FIELD_LEN; - *multival = 0; - while (available > 0 && props < 5) { - propval = vf_get_prop_value_string(prop, props++); - if(!propval) continue; - if (available > 0 && *multival != 0) - strncat(multival, ",", available--); - strncat(multival, propval, available); - available -= strlen(propval); - } - if (available < MAX_FIELD_LEN) - item_fput(item, GROUPS, xstrdup(multival)); + if (vf_get_property(&prop, vfobj, VFGP_FIND, NULL, "CATEGORIES", (char*)0)) { + do { + props = 0; + while ((propval = vf_get_prop_value_string(prop, props++))) { + abook_list_append(&multivalues, propval); + } + } while (vf_get_next_property(&prop)); + item_fput(item, GROUPS, abook_list_to_csv(multivalues)); + abook_list_free(&multivalues); } add_item2database(item); -- 2.39.2