1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
4 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU Lesser General Public
8 * License as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this program; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
20 * Author: Chris Toshok (toshok@ximian.com)
31 #include <glib/gi18n-lib.h>
32 #include "e-contact.h"
34 #include "e-name-western.h"
37 #include "libedataserver/e-data-server-util.h"
39 #define LOCALEDIR e_util_get_localedir ()
44 G_DEFINE_TYPE (EContact, e_contact, E_TYPE_VCARD)
46 struct _EContactPrivate {
47 gchar *cached_strings [E_CONTACT_FIELD_LAST];
50 #define E_CONTACT_FIELD_TYPE_STRING 0x00000001 /* used for simple single valued attributes */
51 /*E_CONTACT_FIELD_TYPE_FLOAT*/
52 #define E_CONTACT_FIELD_TYPE_LIST 0x00000002 /* used for multivalued single attributes - the elements are of type gchar * */
53 #define E_CONTACT_FIELD_TYPE_MULTI 0x00000004 /* used for multivalued attributes - the elements are of type EVCardAttribute */
54 #define E_CONTACT_FIELD_TYPE_GETSET 0x00000008 /* used for attributes that need custom handling for getting/setting */
55 #define E_CONTACT_FIELD_TYPE_STRUCT 0x00000010 /* used for structured types (N and ADR properties, in particular) */
56 #define E_CONTACT_FIELD_TYPE_BOOLEAN 0x00000020 /* used for boolean types (WANTS_HTML) */
58 #define E_CONTACT_FIELD_TYPE_SYNTHETIC 0x10000000 /* used when there isn't a corresponding vcard field (such as email_1) */
59 #define E_CONTACT_FIELD_TYPE_LIST_ELEM 0x20000000 /* used when a synthetic attribute is a numbered list element */
60 #define E_CONTACT_FIELD_TYPE_MULTI_ELEM 0x40000000 /* used when we're looking for the nth attribute where more than 1 can be present in the vcard */
61 #define E_CONTACT_FIELD_TYPE_ATTR_TYPE 0x80000000 /* used when a synthetic attribute is flagged with a TYPE= that we'll be looking for */
66 EContactField field_id;
67 const gchar *vcard_field_name;
68 const gchar *field_name; /* non translated */
69 const gchar *pretty_name; /* translated */
74 const gchar *attr_type1;
75 const gchar *attr_type2;
77 gpointer (*struct_getter)(EContact *contact, EVCardAttribute *attribute);
78 void (*struct_setter)(EContact *contact, EVCardAttribute *attribute, gpointer data);
80 GType (*boxed_type_getter) (void);
83 static gpointer photo_getter (EContact *contact, EVCardAttribute *attr);
84 static void photo_setter (EContact *contact, EVCardAttribute *attr, gpointer data);
85 static gpointer geo_getter (EContact *contact, EVCardAttribute *attr);
86 static void geo_setter (EContact *contact, EVCardAttribute *attr, gpointer data);
87 static gpointer fn_getter (EContact *contact, EVCardAttribute *attr);
88 static void fn_setter (EContact *contact, EVCardAttribute *attr, gpointer data);
89 static gpointer n_getter (EContact *contact, EVCardAttribute *attr);
90 static void n_setter (EContact *contact, EVCardAttribute *attr, gpointer data);
91 static gpointer adr_getter (EContact *contact, EVCardAttribute *attr);
92 static void adr_setter (EContact *contact, EVCardAttribute *attr, gpointer data);
93 static gpointer date_getter (EContact *contact, EVCardAttribute *attr);
94 static void date_setter (EContact *contact, EVCardAttribute *attr, gpointer data);
95 static gpointer cert_getter (EContact *contact, EVCardAttribute *attr);
96 static void cert_setter (EContact *contact, EVCardAttribute *attr, gpointer data);
98 #define STRING_FIELD(id,vc,n,pn,ro) { E_CONTACT_FIELD_TYPE_STRING, (id), (vc), (n), (pn), (ro) }
99 #define BOOLEAN_FIELD(id,vc,n,pn,ro) { E_CONTACT_FIELD_TYPE_BOOLEAN, (id), (vc), (n), (pn), (ro) }
100 #define LIST_FIELD(id,vc,n,pn,ro) { E_CONTACT_FIELD_TYPE_LIST, (id), (vc), (n), (pn), (ro) }
101 #define MULTI_LIST_FIELD(id,vc,n,pn,ro) { E_CONTACT_FIELD_TYPE_MULTI, (id), (vc), (n), (pn), (ro) }
102 #define GETSET_FIELD(id,vc,n,pn,ro,get,set) { E_CONTACT_FIELD_TYPE_STRING | E_CONTACT_FIELD_TYPE_GETSET, (id), (vc), (n), (pn), (ro), -1, NULL, NULL, (get), (set) }
103 #define STRUCT_FIELD(id,vc,n,pn,ro,get,set,ty) { E_CONTACT_FIELD_TYPE_STRUCT | E_CONTACT_FIELD_TYPE_GETSET, (id), (vc), (n), (pn), (ro), -1, NULL, NULL, (get), (set), (ty) }
104 #define SYNTH_STR_FIELD(id,n,pn,ro) { E_CONTACT_FIELD_TYPE_STRING | E_CONTACT_FIELD_TYPE_SYNTHETIC, (id), NULL, (n), (pn), (ro) }
105 #define LIST_ELEM_STR_FIELD(id,vc,n,pn,ro,nm) { E_CONTACT_FIELD_TYPE_LIST_ELEM | E_CONTACT_FIELD_TYPE_SYNTHETIC | E_CONTACT_FIELD_TYPE_STRING, (id), (vc), (n), (pn), (ro), (nm) }
106 #define MULTI_ELEM_STR_FIELD(id,vc,n,pn,ro,nm) { E_CONTACT_FIELD_TYPE_MULTI_ELEM | E_CONTACT_FIELD_TYPE_SYNTHETIC | E_CONTACT_FIELD_TYPE_STRING, (id), (vc), (n), (pn), (ro), (nm) }
107 #define ATTR_TYPE_STR_FIELD(id,vc,n,pn,ro,at1,nth) { E_CONTACT_FIELD_TYPE_ATTR_TYPE | E_CONTACT_FIELD_TYPE_SYNTHETIC | E_CONTACT_FIELD_TYPE_STRING, (id), (vc), (n), (pn), (ro), (nth), (at1), NULL }
108 #define ATTR_TYPE_GETSET_FIELD(id,vc,n,pn,ro,at1,nth,get,set) { E_CONTACT_FIELD_TYPE_ATTR_TYPE | E_CONTACT_FIELD_TYPE_GETSET, (id), (vc), (n), (pn), (ro), (nth), (at1), NULL, (get), (set) }
109 #define ATTR2_TYPE_STR_FIELD(id,vc,n,pn,ro,at1,at2,nth) { E_CONTACT_FIELD_TYPE_ATTR_TYPE | E_CONTACT_FIELD_TYPE_SYNTHETIC | E_CONTACT_FIELD_TYPE_STRING, (id), (vc), (n), (pn), (ro), (nth), (at1), (at2) }
110 #define ATTR_TYPE_STRUCT_FIELD(id,vc,n,pn,ro,at,get,set,ty) { E_CONTACT_FIELD_TYPE_ATTR_TYPE | E_CONTACT_FIELD_TYPE_SYNTHETIC | E_CONTACT_FIELD_TYPE_GETSET | E_CONTACT_FIELD_TYPE_STRUCT, (id), (vc), (n), (pn), (ro), 0, (at), NULL, (get), (set), (ty) }
112 /* This *must* be kept in the same order as the EContactField enum */
113 static const EContactFieldInfo field_info[] = {
114 {0,}, /* Dummy row as EContactField starts from 1 */
115 STRING_FIELD (E_CONTACT_UID, EVC_UID, "id", N_("Unique ID"), FALSE),
116 STRING_FIELD (E_CONTACT_FILE_AS, EVC_X_FILE_AS, "file_as", N_("File Under"), FALSE),
117 /* URI of the book to which the contact belongs to */
118 STRING_FIELD (E_CONTACT_BOOK_URI, EVC_X_BOOK_URI, "book_uri", N_("Book URI"), FALSE),
121 /* FN isn't really a structured field - we use a getter/setter
122 so we can set the N property (since evo 1.4 works fine with
123 vcards that don't even have a N attribute. *sigh*) */
124 GETSET_FIELD (E_CONTACT_FULL_NAME, EVC_FN, "full_name", N_("Full Name"), FALSE, fn_getter, fn_setter),
125 LIST_ELEM_STR_FIELD (E_CONTACT_GIVEN_NAME, EVC_N, "given_name", N_("Given Name"), FALSE, 1),
126 LIST_ELEM_STR_FIELD (E_CONTACT_FAMILY_NAME, EVC_N, "family_name", N_("Family Name"), FALSE, 0),
127 STRING_FIELD (E_CONTACT_NICKNAME, EVC_NICKNAME, "nickname", N_("Nickname"), FALSE),
130 MULTI_ELEM_STR_FIELD (E_CONTACT_EMAIL_1, EVC_EMAIL, "email_1", N_("Email 1"), FALSE, 0),
131 MULTI_ELEM_STR_FIELD (E_CONTACT_EMAIL_2, EVC_EMAIL, "email_2", N_("Email 2"), FALSE, 1),
132 MULTI_ELEM_STR_FIELD (E_CONTACT_EMAIL_3, EVC_EMAIL, "email_3", N_("Email 3"), FALSE, 2),
133 MULTI_ELEM_STR_FIELD (E_CONTACT_EMAIL_4, EVC_EMAIL, "email_4", N_("Email 4"), FALSE, 3),
135 STRING_FIELD (E_CONTACT_MAILER, EVC_MAILER, "mailer", N_("Mailer"), FALSE),
138 ATTR_TYPE_STR_FIELD (E_CONTACT_ADDRESS_LABEL_HOME, EVC_LABEL, "address_label_home", N_("Home Address Label"), FALSE, "HOME", 0),
139 ATTR_TYPE_STR_FIELD (E_CONTACT_ADDRESS_LABEL_WORK, EVC_LABEL, "address_label_work", N_("Work Address Label"), FALSE, "WORK", 0),
140 ATTR_TYPE_STR_FIELD (E_CONTACT_ADDRESS_LABEL_OTHER, EVC_LABEL, "address_label_other", N_("Other Address Label"), FALSE, "OTHER", 0),
143 ATTR_TYPE_STR_FIELD (E_CONTACT_PHONE_ASSISTANT, EVC_TEL, "assistant_phone", N_("Assistant Phone"), FALSE, EVC_X_ASSISTANT, 0),
144 ATTR2_TYPE_STR_FIELD (E_CONTACT_PHONE_BUSINESS, EVC_TEL, "business_phone", N_("Business Phone"), FALSE, "WORK", "VOICE", 0),
145 ATTR2_TYPE_STR_FIELD (E_CONTACT_PHONE_BUSINESS_2, EVC_TEL, "business_phone_2", N_("Business Phone 2"), FALSE, "WORK", "VOICE", 1),
146 ATTR2_TYPE_STR_FIELD (E_CONTACT_PHONE_BUSINESS_FAX, EVC_TEL, "business_fax", N_("Business Fax"), FALSE, "WORK", "FAX", 0),
147 ATTR_TYPE_STR_FIELD (E_CONTACT_PHONE_CALLBACK, EVC_TEL, "callback_phone", N_("Callback Phone"), FALSE, EVC_X_CALLBACK, 0),
148 ATTR_TYPE_STR_FIELD (E_CONTACT_PHONE_CAR, EVC_TEL, "car_phone", N_("Car Phone"), FALSE, "CAR", 0),
149 ATTR_TYPE_STR_FIELD (E_CONTACT_PHONE_COMPANY, EVC_TEL, "company_phone", N_("Company Phone"), FALSE, EVC_X_COMPANY, 0),
150 ATTR2_TYPE_STR_FIELD (E_CONTACT_PHONE_HOME, EVC_TEL, "home_phone", N_("Home Phone"), FALSE, "HOME", "VOICE", 0),
151 ATTR2_TYPE_STR_FIELD (E_CONTACT_PHONE_HOME_2, EVC_TEL, "home_phone_2", N_("Home Phone 2"), FALSE, "HOME", "VOICE", 1),
152 ATTR2_TYPE_STR_FIELD (E_CONTACT_PHONE_HOME_FAX, EVC_TEL, "home_fax", N_("Home Fax"), FALSE, "HOME", "FAX", 0),
153 ATTR_TYPE_STR_FIELD (E_CONTACT_PHONE_ISDN, EVC_TEL, "isdn_phone", N_("ISDN"), FALSE, "ISDN", 0),
154 ATTR_TYPE_STR_FIELD (E_CONTACT_PHONE_MOBILE, EVC_TEL, "mobile_phone", N_("Mobile Phone"), FALSE, "CELL", 0),
155 ATTR_TYPE_STR_FIELD (E_CONTACT_PHONE_OTHER, EVC_TEL, "other_phone", N_("Other Phone"), FALSE, "VOICE", 0),
156 ATTR_TYPE_STR_FIELD (E_CONTACT_PHONE_OTHER_FAX, EVC_TEL, "other_fax", N_("Other Fax"), FALSE, "FAX", 0),
157 ATTR_TYPE_STR_FIELD (E_CONTACT_PHONE_PAGER, EVC_TEL, "pager", N_("Pager"), FALSE, "PAGER", 0),
158 ATTR_TYPE_STR_FIELD (E_CONTACT_PHONE_PRIMARY, EVC_TEL, "primary_phone", N_("Primary Phone"), FALSE, "PREF", 0),
159 ATTR_TYPE_STR_FIELD (E_CONTACT_PHONE_RADIO, EVC_TEL, "radio", N_("Radio"), FALSE, EVC_X_RADIO, 0),
160 ATTR_TYPE_STR_FIELD (E_CONTACT_PHONE_TELEX, EVC_TEL, "telex", N_("Telex"), FALSE, EVC_X_TELEX, 0),
161 /* To translators: TTY is Teletypewriter */
162 ATTR_TYPE_STR_FIELD (E_CONTACT_PHONE_TTYTDD, EVC_TEL, "tty", N_("TTY"), FALSE, EVC_X_TTYTDD, 0),
164 /* Organizational fields */
165 LIST_ELEM_STR_FIELD (E_CONTACT_ORG, EVC_ORG, "org", N_("Organization"), FALSE, 0),
166 LIST_ELEM_STR_FIELD (E_CONTACT_ORG_UNIT, EVC_ORG, "org_unit", N_("Organizational Unit"), FALSE, 1),
167 LIST_ELEM_STR_FIELD (E_CONTACT_OFFICE, EVC_ORG, "office", N_("Office"), FALSE, 2),
168 STRING_FIELD (E_CONTACT_TITLE, EVC_TITLE, "title", N_("Title"), FALSE),
169 STRING_FIELD (E_CONTACT_ROLE, EVC_ROLE, "role", N_("Role"), FALSE),
170 STRING_FIELD (E_CONTACT_MANAGER, EVC_X_MANAGER, "manager", N_("Manager"), FALSE),
171 STRING_FIELD (E_CONTACT_ASSISTANT, EVC_X_ASSISTANT, "assistant", N_("Assistant"), FALSE),
174 STRING_FIELD (E_CONTACT_HOMEPAGE_URL, EVC_URL, "homepage_url", N_("Homepage URL"), FALSE),
175 STRING_FIELD (E_CONTACT_BLOG_URL, EVC_X_BLOG_URL, "blog_url", N_("Weblog URL"), FALSE),
177 /* Contact categories */
178 SYNTH_STR_FIELD (E_CONTACT_CATEGORIES, "categories", N_("Categories"), FALSE),
180 /* Collaboration fields */
181 STRING_FIELD (E_CONTACT_CALENDAR_URI, EVC_CALURI, "caluri", N_("Calendar URI"), FALSE),
182 STRING_FIELD (E_CONTACT_FREEBUSY_URL, EVC_FBURL, "fburl", N_("Free/Busy URL"), FALSE),
183 STRING_FIELD (E_CONTACT_ICS_CALENDAR, EVC_ICSCALENDAR, "icscalendar", N_("ICS Calendar"), FALSE),
184 STRING_FIELD (E_CONTACT_VIDEO_URL, EVC_X_VIDEO_URL, "video_url", N_("Video Conferencing URL"), FALSE),
187 STRING_FIELD (E_CONTACT_SPOUSE, EVC_X_SPOUSE, "spouse", N_("Spouse's Name"), FALSE),
188 STRING_FIELD (E_CONTACT_NOTE, EVC_NOTE, "note", N_("Note"), FALSE),
190 /* Instant messaging fields */
191 ATTR_TYPE_STR_FIELD (E_CONTACT_IM_AIM_HOME_1, EVC_X_AIM, "im_aim_home_1", N_("AIM Home Screen Name 1"), FALSE, "HOME", 0),
192 ATTR_TYPE_STR_FIELD (E_CONTACT_IM_AIM_HOME_2, EVC_X_AIM, "im_aim_home_2", N_("AIM Home Screen Name 2"), FALSE, "HOME", 1),
193 ATTR_TYPE_STR_FIELD (E_CONTACT_IM_AIM_HOME_3, EVC_X_AIM, "im_aim_home_3", N_("AIM Home Screen Name 3"), FALSE, "HOME", 2),
194 ATTR_TYPE_STR_FIELD (E_CONTACT_IM_AIM_WORK_1, EVC_X_AIM, "im_aim_work_1", N_("AIM Work Screen Name 1"), FALSE, "WORK", 0),
195 ATTR_TYPE_STR_FIELD (E_CONTACT_IM_AIM_WORK_2, EVC_X_AIM, "im_aim_work_2", N_("AIM Work Screen Name 2"), FALSE, "WORK", 1),
196 ATTR_TYPE_STR_FIELD (E_CONTACT_IM_AIM_WORK_3, EVC_X_AIM, "im_aim_work_3", N_("AIM Work Screen Name 3"), FALSE, "WORK", 2),
197 ATTR_TYPE_STR_FIELD (E_CONTACT_IM_GROUPWISE_HOME_1, EVC_X_GROUPWISE, "im_groupwise_home_1", N_("GroupWise Home Screen Name 1"), FALSE, "HOME", 0),
198 ATTR_TYPE_STR_FIELD (E_CONTACT_IM_GROUPWISE_HOME_2, EVC_X_GROUPWISE, "im_groupwise_home_2", N_("GroupWise Home Screen Name 2"), FALSE, "HOME", 1),
199 ATTR_TYPE_STR_FIELD (E_CONTACT_IM_GROUPWISE_HOME_3, EVC_X_GROUPWISE, "im_groupwise_home_3", N_("GroupWise Home Screen Name 3"), FALSE, "HOME", 2),
200 ATTR_TYPE_STR_FIELD (E_CONTACT_IM_GROUPWISE_WORK_1, EVC_X_GROUPWISE, "im_groupwise_work_1", N_("GroupWise Work Screen Name 1"), FALSE, "WORK", 0),
201 ATTR_TYPE_STR_FIELD (E_CONTACT_IM_GROUPWISE_WORK_2, EVC_X_GROUPWISE, "im_groupwise_work_2", N_("GroupWise Work Screen Name 2"), FALSE, "WORK", 1),
202 ATTR_TYPE_STR_FIELD (E_CONTACT_IM_GROUPWISE_WORK_3, EVC_X_GROUPWISE, "im_groupwise_work_3", N_("GroupWise Work Screen Name 3"), FALSE, "WORK", 2),
203 ATTR_TYPE_STR_FIELD (E_CONTACT_IM_JABBER_HOME_1, EVC_X_JABBER, "im_jabber_home_1", N_("Jabber Home ID 1"), FALSE, "HOME", 0),
204 ATTR_TYPE_STR_FIELD (E_CONTACT_IM_JABBER_HOME_2, EVC_X_JABBER, "im_jabber_home_2", N_("Jabber Home ID 2"), FALSE, "HOME", 1),
205 ATTR_TYPE_STR_FIELD (E_CONTACT_IM_JABBER_HOME_3, EVC_X_JABBER, "im_jabber_home_3", N_("Jabber Home ID 3"), FALSE, "HOME", 2),
206 ATTR_TYPE_STR_FIELD (E_CONTACT_IM_JABBER_WORK_1, EVC_X_JABBER, "im_jabber_work_1", N_("Jabber Work ID 1"), FALSE, "WORK", 0),
207 ATTR_TYPE_STR_FIELD (E_CONTACT_IM_JABBER_WORK_2, EVC_X_JABBER, "im_jabber_work_3", N_("Jabber Work ID 2"), FALSE, "WORK", 1),
208 ATTR_TYPE_STR_FIELD (E_CONTACT_IM_JABBER_WORK_3, EVC_X_JABBER, "im_jabber_work_2", N_("Jabber Work ID 3"), FALSE, "WORK", 2),
209 ATTR_TYPE_STR_FIELD (E_CONTACT_IM_YAHOO_HOME_1, EVC_X_YAHOO, "im_yahoo_home_1", N_("Yahoo! Home Screen Name 1"), FALSE, "HOME", 0),
210 ATTR_TYPE_STR_FIELD (E_CONTACT_IM_YAHOO_HOME_2, EVC_X_YAHOO, "im_yahoo_home_2", N_("Yahoo! Home Screen Name 2"), FALSE, "HOME", 1),
211 ATTR_TYPE_STR_FIELD (E_CONTACT_IM_YAHOO_HOME_3, EVC_X_YAHOO, "im_yahoo_home_3", N_("Yahoo! Home Screen Name 3"), FALSE, "HOME", 2),
212 ATTR_TYPE_STR_FIELD (E_CONTACT_IM_YAHOO_WORK_1, EVC_X_YAHOO, "im_yahoo_work_1", N_("Yahoo! Work Screen Name 1"), FALSE, "WORK", 0),
213 ATTR_TYPE_STR_FIELD (E_CONTACT_IM_YAHOO_WORK_2, EVC_X_YAHOO, "im_yahoo_work_2", N_("Yahoo! Work Screen Name 2"), FALSE, "WORK", 1),
214 ATTR_TYPE_STR_FIELD (E_CONTACT_IM_YAHOO_WORK_3, EVC_X_YAHOO, "im_yahoo_work_3", N_("Yahoo! Work Screen Name 3"), FALSE, "WORK", 2),
215 ATTR_TYPE_STR_FIELD (E_CONTACT_IM_MSN_HOME_1, EVC_X_MSN, "im_msn_home_1", N_("MSN Home Screen Name 1"), FALSE, "HOME", 0),
216 ATTR_TYPE_STR_FIELD (E_CONTACT_IM_MSN_HOME_2, EVC_X_MSN, "im_msn_home_2", N_("MSN Home Screen Name 2"), FALSE, "HOME", 1),
217 ATTR_TYPE_STR_FIELD (E_CONTACT_IM_MSN_HOME_3, EVC_X_MSN, "im_msn_home_3", N_("MSN Home Screen Name 3"), FALSE, "HOME", 2),
218 ATTR_TYPE_STR_FIELD (E_CONTACT_IM_MSN_WORK_1, EVC_X_MSN, "im_msn_work_1", N_("MSN Work Screen Name 1"), FALSE, "WORK", 0),
219 ATTR_TYPE_STR_FIELD (E_CONTACT_IM_MSN_WORK_2, EVC_X_MSN, "im_msn_work_2", N_("MSN Work Screen Name 2"), FALSE, "WORK", 1),
220 ATTR_TYPE_STR_FIELD (E_CONTACT_IM_MSN_WORK_3, EVC_X_MSN, "im_msn_work_3", N_("MSN Work Screen Name 3"), FALSE, "WORK", 2),
221 ATTR_TYPE_STR_FIELD (E_CONTACT_IM_ICQ_HOME_1, EVC_X_ICQ, "im_icq_home_1", N_("ICQ Home ID 1"), FALSE, "HOME", 0),
222 ATTR_TYPE_STR_FIELD (E_CONTACT_IM_ICQ_HOME_2, EVC_X_ICQ, "im_icq_home_2", N_("ICQ Home ID 2"), FALSE, "HOME", 1),
223 ATTR_TYPE_STR_FIELD (E_CONTACT_IM_ICQ_HOME_3, EVC_X_ICQ, "im_icq_home_3", N_("ICQ Home ID 3"), FALSE, "HOME", 2),
224 ATTR_TYPE_STR_FIELD (E_CONTACT_IM_ICQ_WORK_1, EVC_X_ICQ, "im_icq_work_1", N_("ICQ Work ID 1"), FALSE, "WORK", 0),
225 ATTR_TYPE_STR_FIELD (E_CONTACT_IM_ICQ_WORK_2, EVC_X_ICQ, "im_icq_work_2", N_("ICQ Work ID 2"), FALSE, "WORK", 1),
226 ATTR_TYPE_STR_FIELD (E_CONTACT_IM_ICQ_WORK_3, EVC_X_ICQ, "im_icq_work_3", N_("ICQ Work ID 3"), FALSE, "WORK", 2),
228 /* Last modified time */
229 STRING_FIELD (E_CONTACT_REV, EVC_REV, "Rev", N_("Last Revision"), FALSE),
230 SYNTH_STR_FIELD (E_CONTACT_NAME_OR_ORG, "name_or_org", N_("Name or Org"), TRUE),
233 MULTI_LIST_FIELD (E_CONTACT_ADDRESS, EVC_ADR, "address", N_("Address List"), FALSE),
234 ATTR_TYPE_STRUCT_FIELD (E_CONTACT_ADDRESS_HOME, EVC_ADR, "address_home", N_("Home Address"), FALSE, "HOME", adr_getter, adr_setter, e_contact_address_get_type),
235 ATTR_TYPE_STRUCT_FIELD (E_CONTACT_ADDRESS_WORK, EVC_ADR, "address_work", N_("Work Address"), FALSE, "WORK", adr_getter, adr_setter, e_contact_address_get_type),
236 ATTR_TYPE_STRUCT_FIELD (E_CONTACT_ADDRESS_OTHER, EVC_ADR, "address_other", N_("Other Address"), FALSE, "OTHER", adr_getter, adr_setter, e_contact_address_get_type),
238 /* Contact categories */
239 LIST_FIELD (E_CONTACT_CATEGORY_LIST, EVC_CATEGORIES, "category_list", N_("Category List"), FALSE),
242 STRUCT_FIELD (E_CONTACT_PHOTO, EVC_PHOTO, "photo", N_("Photo"), FALSE, photo_getter, photo_setter, e_contact_photo_get_type),
243 STRUCT_FIELD (E_CONTACT_LOGO, EVC_LOGO, "logo", N_("Logo"), FALSE, photo_getter, photo_setter, e_contact_photo_get_type),
245 STRUCT_FIELD (E_CONTACT_NAME, EVC_N, "name", N_("Name"), FALSE, n_getter, n_setter, e_contact_name_get_type),
246 MULTI_LIST_FIELD (E_CONTACT_EMAIL, EVC_EMAIL, "email", N_("Email List"), FALSE),
248 /* Instant messaging fields */
249 MULTI_LIST_FIELD (E_CONTACT_IM_AIM, EVC_X_AIM, "im_aim", N_("AIM Screen Name List"), FALSE),
250 MULTI_LIST_FIELD (E_CONTACT_IM_GROUPWISE, EVC_X_GROUPWISE, "im_groupwise", N_("GroupWise ID List"), FALSE),
251 MULTI_LIST_FIELD (E_CONTACT_IM_JABBER, EVC_X_JABBER, "im_jabber", N_("Jabber ID List"), FALSE),
252 MULTI_LIST_FIELD (E_CONTACT_IM_YAHOO, EVC_X_YAHOO, "im_yahoo", N_("Yahoo! Screen Name List"), FALSE),
253 MULTI_LIST_FIELD (E_CONTACT_IM_MSN, EVC_X_MSN, "im_msn", N_("MSN Screen Name List"), FALSE),
254 MULTI_LIST_FIELD (E_CONTACT_IM_ICQ, EVC_X_ICQ, "im_icq", N_("ICQ ID List"), FALSE),
256 BOOLEAN_FIELD (E_CONTACT_WANTS_HTML, EVC_X_WANTS_HTML, "wants_html", N_("Wants HTML Mail"), FALSE),
258 BOOLEAN_FIELD (E_CONTACT_IS_LIST, EVC_X_LIST, "list", N_("List"), FALSE),
259 BOOLEAN_FIELD (E_CONTACT_LIST_SHOW_ADDRESSES, EVC_X_LIST_SHOW_ADDRESSES, "list_show_addresses", N_("List Show Addresses"), FALSE),
261 STRUCT_FIELD (E_CONTACT_BIRTH_DATE, EVC_BDAY, "birth_date", N_("Birth Date"), FALSE, date_getter, date_setter, e_contact_date_get_type),
262 STRUCT_FIELD (E_CONTACT_ANNIVERSARY, EVC_X_ANNIVERSARY, "anniversary", N_("Anniversary"), FALSE, date_getter, date_setter, e_contact_date_get_type),
264 /* Security fields */
265 ATTR_TYPE_STRUCT_FIELD (E_CONTACT_X509_CERT, EVC_KEY, "x509Cert", N_("X.509 Certificate"), FALSE, "X509", cert_getter, cert_setter, e_contact_cert_get_type),
267 ATTR_TYPE_STR_FIELD (E_CONTACT_IM_GADUGADU_HOME_1, EVC_X_GADUGADU, "im_gadugadu_home_1", N_("Gadu-Gadu Home ID 1"), FALSE, "HOME", 0),
268 ATTR_TYPE_STR_FIELD (E_CONTACT_IM_GADUGADU_HOME_2, EVC_X_GADUGADU, "im_gadugadu_home_2", N_("Gadu-Gadu Home ID 2"), FALSE, "HOME", 1),
269 ATTR_TYPE_STR_FIELD (E_CONTACT_IM_GADUGADU_HOME_3, EVC_X_GADUGADU, "im_gadugadu_home_3", N_("Gadu-Gadu Home ID 3"), FALSE, "HOME", 2),
270 ATTR_TYPE_STR_FIELD (E_CONTACT_IM_GADUGADU_WORK_1, EVC_X_GADUGADU, "im_gadugadu_work_1", N_("Gadu-Gadu Work ID 1"), FALSE, "WORK", 0),
271 ATTR_TYPE_STR_FIELD (E_CONTACT_IM_GADUGADU_WORK_2, EVC_X_GADUGADU, "im_gadugadu_work_2", N_("Gadu-Gadu Work ID 2"), FALSE, "WORK", 1),
272 ATTR_TYPE_STR_FIELD (E_CONTACT_IM_GADUGADU_WORK_3, EVC_X_GADUGADU, "im_gadugadu_work_3", N_("Gadu-Gadu Work ID 3"), FALSE, "WORK", 2),
273 MULTI_LIST_FIELD (E_CONTACT_IM_GADUGADU, EVC_X_GADUGADU, "im_gadugadu", N_("Gadu-Gadu ID List"), FALSE),
275 /* Geo information */
276 STRUCT_FIELD (E_CONTACT_GEO, EVC_GEO, "geo", N_("Geographic Information"), FALSE, geo_getter, geo_setter, e_contact_geo_get_type),
278 MULTI_LIST_FIELD (E_CONTACT_TEL, EVC_TEL, "phone", N_("Telephone"), FALSE),
280 ATTR_TYPE_STR_FIELD (E_CONTACT_IM_SKYPE_HOME_1, EVC_X_SKYPE, "im_skype_home_1", N_("Skype Home Name 1"), FALSE, "HOME", 0),
281 ATTR_TYPE_STR_FIELD (E_CONTACT_IM_SKYPE_HOME_2, EVC_X_SKYPE, "im_skype_home_2", N_("Skype Home Name 2"), FALSE, "HOME", 1),
282 ATTR_TYPE_STR_FIELD (E_CONTACT_IM_SKYPE_HOME_3, EVC_X_SKYPE, "im_skype_home_3", N_("Skype Home Name 3"), FALSE, "HOME", 2),
283 ATTR_TYPE_STR_FIELD (E_CONTACT_IM_SKYPE_WORK_1, EVC_X_SKYPE, "im_skype_work_1", N_("Skype Work Name 1"), FALSE, "WORK", 0),
284 ATTR_TYPE_STR_FIELD (E_CONTACT_IM_SKYPE_WORK_2, EVC_X_SKYPE, "im_skype_work_2", N_("Skype Work Name 2"), FALSE, "WORK", 1),
285 ATTR_TYPE_STR_FIELD (E_CONTACT_IM_SKYPE_WORK_3, EVC_X_SKYPE, "im_skype_work_3", N_("Skype Work Name 3"), FALSE, "WORK", 2),
286 MULTI_LIST_FIELD (E_CONTACT_IM_SKYPE, EVC_X_SKYPE, "im_skype", N_("Skype Name List"), FALSE),
288 MULTI_LIST_FIELD (E_CONTACT_SIP, EVC_X_SIP, "sip", N_("SIP address"), FALSE),
291 #undef LIST_ELEM_STR_FIELD
293 #undef SYNTH_STR_FIELD
297 static GObjectClass *parent_class;
299 static void e_contact_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
300 static void e_contact_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
303 e_contact_finalize (GObject *object)
305 EContact *ec = E_CONTACT (object);
308 for (i = E_CONTACT_FIELD_FIRST; i < E_CONTACT_FIELD_LAST; i++) {
309 g_free (ec->priv->cached_strings[i]);
317 G_OBJECT_CLASS (parent_class)->finalize (object);
321 e_contact_class_init (EContactClass *klass)
323 GObjectClass *object_class;
326 object_class = G_OBJECT_CLASS(klass);
328 parent_class = g_type_class_ref (E_TYPE_VCARD);
330 object_class->finalize = e_contact_finalize;
331 object_class->set_property = e_contact_set_property;
332 object_class->get_property = e_contact_get_property;
334 for (i = E_CONTACT_FIELD_FIRST; i < E_CONTACT_FIELD_LAST; i++) {
335 GParamSpec *pspec = NULL;
337 /* Verify the table is correctly ordered */
338 g_assert (i == field_info[i].field_id);
340 if (field_info[i].t & E_CONTACT_FIELD_TYPE_STRING)
341 pspec = g_param_spec_string (field_info[i].field_name,
342 _(field_info[i].pretty_name),
343 field_info[i].pretty_name,
345 (field_info[i].read_only ? G_PARAM_READABLE : G_PARAM_READWRITE)
346 | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB);
347 else if (field_info[i].t & E_CONTACT_FIELD_TYPE_BOOLEAN)
348 pspec = g_param_spec_boolean (field_info[i].field_name,
349 _(field_info[i].pretty_name),
350 field_info[i].pretty_name,
352 (field_info[i].read_only ? G_PARAM_READABLE : G_PARAM_READWRITE)
353 | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB);
354 else if (field_info[i].t & E_CONTACT_FIELD_TYPE_STRUCT)
355 pspec = g_param_spec_boxed (field_info[i].field_name,
356 _(field_info[i].pretty_name),
357 field_info[i].pretty_name,
358 field_info[i].boxed_type_getter(),
359 (field_info[i].read_only ? G_PARAM_READABLE : G_PARAM_READWRITE)
360 | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB);
362 pspec = g_param_spec_pointer (field_info[i].field_name,
363 _(field_info[i].pretty_name),
364 field_info[i].pretty_name,
365 (field_info[i].read_only ? G_PARAM_READABLE : G_PARAM_READWRITE)
366 | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB);
368 g_object_class_install_property (object_class, field_info[i].field_id,
374 e_contact_init (EContact *ec)
376 ec->priv = g_new0 (EContactPrivate, 1);
379 static EVCardAttribute*
380 e_contact_get_first_attr (EContact *contact, const gchar *attr_name)
384 attrs = e_vcard_get_attributes (E_VCARD (contact));
386 for (l = attrs; l; l = l->next) {
387 EVCardAttribute *attr = l->data;
390 name = e_vcard_attribute_get_name (attr);
392 if (!g_ascii_strcasecmp (name, attr_name))
402 geo_getter (EContact *contact, EVCardAttribute *attr)
405 GList *p = e_vcard_attribute_get_values (attr);
406 EContactGeo *geo = g_new0 (EContactGeo, 1);
408 geo->latitude = (p && p->data ? g_ascii_strtod (p->data, NULL) : 0); if (p) p = p->next;
409 geo->longitude = (p && p->data ? g_ascii_strtod (p->data, NULL) : 0);
418 geo_setter (EContact *contact, EVCardAttribute *attr, gpointer data)
420 EContactGeo *geo = data;
421 gchar buf[G_ASCII_DTOSTR_BUF_SIZE];
423 e_vcard_attribute_add_value
424 (attr, g_ascii_dtostr (buf, sizeof (buf), geo->latitude));
426 e_vcard_attribute_add_value
427 (attr, g_ascii_dtostr (buf, sizeof (buf), geo->longitude));
431 photo_getter (EContact *contact, EVCardAttribute *attr)
438 values = e_vcard_attribute_get_param (attr, EVC_ENCODING);
439 if (values && (g_ascii_strcasecmp (values->data, "b") == 0 ||
440 /* second for photo vCard 2.1 support */
441 g_ascii_strcasecmp (values->data, "base64") == 0)) {
442 values = e_vcard_attribute_get_values_decoded (attr);
443 if (values && values->data) {
444 GString *s = values->data;
445 EContactPhoto *photo;
450 photo = g_new0 (EContactPhoto, 1);
451 photo->type = E_CONTACT_PHOTO_TYPE_INLINED;
452 photo->data.inlined.length = s->len;
453 photo->data.inlined.data = g_malloc (photo->data.inlined.length);
454 memcpy (photo->data.inlined.data, s->str, photo->data.inlined.length);
456 values = e_vcard_attribute_get_param (attr, EVC_TYPE);
457 if (values && values->data)
458 photo->data.inlined.mime_type = g_strdup_printf("image/%s", (gchar *)values->data);
463 values = e_vcard_attribute_get_param (attr, EVC_VALUE);
464 if (values && g_ascii_strcasecmp (values->data, "uri") == 0) {
465 EContactPhoto *photo;
466 photo = g_new0 (EContactPhoto, 1);
467 photo->type = E_CONTACT_PHOTO_TYPE_URI;
468 photo->data.uri = e_vcard_attribute_get_value (attr);
475 photo_setter (EContact *contact, EVCardAttribute *attr, gpointer data)
477 EContactPhoto *photo = data;
478 const gchar *image_type, *p;
480 switch (photo->type) {
481 case E_CONTACT_PHOTO_TYPE_INLINED:
482 g_return_if_fail (photo->data.inlined.length > 0);
484 e_vcard_attribute_add_param_with_value (attr,
485 e_vcard_attribute_param_new (EVC_ENCODING),
487 if (photo->data.inlined.mime_type && (p = strchr (photo->data.inlined.mime_type, '/'))) {
490 image_type = "X-EVOLUTION-UNKNOWN";
492 e_vcard_attribute_add_param_with_value (attr,
493 e_vcard_attribute_param_new (EVC_TYPE),
496 e_vcard_attribute_add_value_decoded (attr, (gchar *)photo->data.inlined.data, photo->data.inlined.length);
498 case E_CONTACT_PHOTO_TYPE_URI:
499 e_vcard_attribute_add_param_with_value (attr,
500 e_vcard_attribute_param_new (EVC_VALUE),
502 e_vcard_attribute_add_value (attr, photo->data.uri);
505 g_warning ("Unknown EContactPhotoType %d", photo->type);
512 fn_getter (EContact *contact, EVCardAttribute *attr)
515 GList *p = e_vcard_attribute_get_values (attr);
517 return p && p->data ? p->data : (gpointer) "";
524 fn_setter (EContact *contact, EVCardAttribute *attr, gpointer data)
526 gchar *name_str = data;
528 e_vcard_attribute_add_value (attr, name_str);
530 attr = e_contact_get_first_attr (contact, EVC_N);
532 EContactName *name = e_contact_name_from_string ((gchar *)data);
534 attr = e_vcard_attribute_new (NULL, EVC_N);
535 e_vcard_append_attribute (E_VCARD (contact), attr);
537 /* call the setter directly */
538 n_setter (contact, attr, name);
540 e_contact_name_free (name);
547 n_getter (EContact *contact, EVCardAttribute *attr)
549 EContactName *name = g_new0 (EContactName, 1);
550 EVCardAttribute *new_attr;
554 GList *p = e_vcard_attribute_get_values (attr);
556 name->family = g_strdup (p && p->data ? p->data : ""); if (p) p = p->next;
557 name->given = g_strdup (p && p->data ? p->data : ""); if (p) p = p->next;
558 name->additional = g_strdup (p && p->data ? p->data : ""); if (p) p = p->next;
559 name->prefixes = g_strdup (p && p->data ? p->data : ""); if (p) p = p->next;
560 name->suffixes = g_strdup (p && p->data ? p->data : "");
563 new_attr = e_contact_get_first_attr (contact, EVC_FN);
565 new_attr = e_vcard_attribute_new (NULL, EVC_FN);
566 e_vcard_append_attribute (E_VCARD (contact), new_attr);
567 name_str = e_contact_name_to_string (name);
568 e_vcard_attribute_add_value (new_attr, name_str);
576 n_setter (EContact *contact, EVCardAttribute *attr, gpointer data)
578 EContactName *name = data;
580 e_vcard_attribute_add_value (attr, name->family ? name->family : "");
581 e_vcard_attribute_add_value (attr, name->given ? name->given : "");
582 e_vcard_attribute_add_value (attr, name->additional ? name->additional : "");
583 e_vcard_attribute_add_value (attr, name->prefixes ? name->prefixes : "");
584 e_vcard_attribute_add_value (attr, name->suffixes ? name->suffixes : "");
586 /* now find the attribute for FileAs. if it's not present, fill it in */
587 attr = e_contact_get_first_attr (contact, EVC_X_FILE_AS);
589 gchar *strings[3], **stringptr;
591 attr = e_vcard_attribute_new (NULL, EVC_X_FILE_AS);
592 e_vcard_append_attribute (E_VCARD (contact), attr);
595 if (name->family && *name->family)
596 *(stringptr++) = name->family;
597 if (name->given && *name->given)
598 *(stringptr++) = name->given;
600 string = g_strjoinv(", ", strings);
602 e_vcard_attribute_add_value (attr, string);
611 adr_getter (EContact *contact, EVCardAttribute *attr)
614 GList *p = e_vcard_attribute_get_values (attr);
615 EContactAddress *addr = g_new0 (EContactAddress, 1);
617 addr->address_format = g_strdup ("");
618 addr->po = g_strdup (p && p->data ? p->data : ""); if (p) p = p->next;
619 addr->ext = g_strdup (p && p->data ? p->data : ""); if (p) p = p->next;
620 addr->street = g_strdup (p && p->data ? p->data : ""); if (p) p = p->next;
621 addr->locality = g_strdup (p && p->data ? p->data : ""); if (p) p = p->next;
622 addr->region = g_strdup (p && p->data ? p->data : ""); if (p) p = p->next;
623 addr->code = g_strdup (p && p->data ? p->data : ""); if (p) p = p->next;
624 addr->country = g_strdup (p && p->data ? p->data : ""); if (p) p = p->next;
633 adr_setter (EContact *contact, EVCardAttribute *attr, gpointer data)
635 EContactAddress *addr = data;
637 e_vcard_attribute_add_value (attr, addr->po);
638 e_vcard_attribute_add_value (attr, addr->ext);
639 e_vcard_attribute_add_value (attr, addr->street);
640 e_vcard_attribute_add_value (attr, addr->locality);
641 e_vcard_attribute_add_value (attr, addr->region);
642 e_vcard_attribute_add_value (attr, addr->code);
643 e_vcard_attribute_add_value (attr, addr->country);
649 date_getter (EContact *contact, EVCardAttribute *attr)
652 GList *p = e_vcard_attribute_get_values (attr);
655 if (p && p->data && ((gchar *) p->data) [0])
656 date = e_contact_date_from_string ((gchar *) p->data);
667 date_setter (EContact *contact, EVCardAttribute *attr, gpointer data)
669 EContactDate *date = data;
672 str = e_contact_date_to_string (date);
674 e_vcard_attribute_add_value (attr, str);
681 cert_getter (EContact *contact, EVCardAttribute *attr)
684 /* the certificate is stored in this vcard. just
686 GList *values = e_vcard_attribute_get_values_decoded (attr);
688 if (values && values->data) {
689 GString *s = values->data;
690 EContactCert *cert = g_new0 (EContactCert, 1);
692 cert->length = s->len;
693 cert->data = g_malloc (cert->length);
694 memcpy (cert->data, s->str, cert->length);
700 /* XXX if we stored a fingerprint in the cert we could look it
701 up via NSS, but that would require the additional NSS dep
702 here, and we'd have more than one process opening the
703 certdb, which is bad. *sigh* */
709 cert_setter (EContact *contact, EVCardAttribute *attr, gpointer data)
711 EContactCert *cert = data;
713 e_vcard_attribute_add_param_with_value (attr,
714 e_vcard_attribute_param_new (EVC_ENCODING),
717 e_vcard_attribute_add_value_decoded (attr, cert->data, cert->length);
722 /* Set_arg handler for the contact */
724 e_contact_set_property (GObject *object,
729 EContact *contact = E_CONTACT (object);
730 const EContactFieldInfo *info = NULL;
732 if (prop_id < 1 || prop_id >= E_CONTACT_FIELD_LAST) {
733 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
737 info = &field_info[prop_id];
739 if (info->t & E_CONTACT_FIELD_TYPE_MULTI) {
740 GList *new_values = g_value_get_pointer (value);
743 /* first we remove all attributes of the type we're
744 adding, then add new ones based on the values that
746 e_vcard_remove_attributes (E_VCARD (contact), NULL, info->vcard_field_name);
748 for (l = new_values; l; l = l->next)
749 e_vcard_append_attribute_with_value (E_VCARD (contact),
750 e_vcard_attribute_new (NULL, info->vcard_field_name),
753 else if (info->t & E_CONTACT_FIELD_TYPE_SYNTHETIC) {
754 if (info->t & E_CONTACT_FIELD_TYPE_MULTI_ELEM) {
755 /* XXX this is kinda broken - we don't insert
756 insert padding elements if, e.g. the user
757 sets email 3 when email 1 and 2 don't
758 exist. But, if we *did* pad the lists we'd
759 end up with empty items in the vcard. I
760 dunno which is worse. */
761 EVCardAttribute *attr = NULL;
762 gboolean found = FALSE;
763 gint num_left = info->list_elem;
764 GList *attrs = e_vcard_get_attributes (E_VCARD (contact));
768 for (l = attrs; l; l = l->next) {
772 name = e_vcard_attribute_get_name (attr);
774 if (!g_ascii_strcasecmp (name, info->vcard_field_name)) {
775 if (num_left-- == 0) {
782 sval = g_value_get_string (value);
785 /* we found it, overwrite it */
786 e_vcard_attribute_remove_values (attr);
789 /* we didn't find it - add a new attribute */
790 attr = e_vcard_attribute_new (NULL, info->vcard_field_name);
791 if (!g_ascii_strcasecmp (info->vcard_field_name, "EMAIL") &&
794 /* Add default type */
795 e_vcard_attribute_add_param_with_value ( attr,
796 e_vcard_attribute_param_new (EVC_TYPE),
799 e_vcard_append_attribute (E_VCARD (contact), attr);
802 e_vcard_attribute_add_value (attr, sval);
806 e_vcard_remove_attribute (E_VCARD (contact), attr);
809 else if (info->t & E_CONTACT_FIELD_TYPE_ATTR_TYPE) {
810 /* XXX this is kinda broken - we don't insert
811 insert padding elements if, e.g. the user
812 sets email 3 when email 1 and 2 don't
813 exist. But, if we *did* pad the lists we'd
814 end up with empty items in the vcard. I
815 dunno which is worse. */
816 EVCardAttribute *attr = NULL;
817 gboolean found = FALSE;
818 gint num_left = info->list_elem;
819 GList *attrs = e_vcard_get_attributes (E_VCARD (contact));
822 for (l = attrs; l && !found; l = l->next) {
824 gboolean found_needed1, found_needed2;
826 found_needed1 = (info->attr_type1 == NULL);
827 found_needed2 = (info->attr_type2 == NULL);
830 name = e_vcard_attribute_get_name (attr);
832 if (!g_ascii_strcasecmp (name, info->vcard_field_name)) {
835 for (params = e_vcard_attribute_get_params (attr); params; params = params->next) {
836 EVCardAttributeParam *param = params->data;
837 const gchar *param_name = e_vcard_attribute_param_get_name (param);
839 if (!g_ascii_strcasecmp (param_name, EVC_TYPE)) {
840 gboolean matches = FALSE;
841 GList *values = e_vcard_attribute_param_get_values (param);
843 while (values && values->data) {
844 if (!found_needed1 && !g_ascii_strcasecmp ((gchar *)values->data, info->attr_type1)) {
845 found_needed1 = TRUE;
848 else if (!found_needed2 && !g_ascii_strcasecmp ((gchar *)values->data, info->attr_type2)) {
849 found_needed2 = TRUE;
856 values = values->next;
860 /* this is to enforce that we find an attribute
861 with *only* the TYPE='s we need. This may seem like
862 an odd restriction but it's the only way at present to
863 implement the Other Fax and Other Phone attributes. */
865 found_needed2 = FALSE;
870 if (found_needed1 && found_needed2) {
871 if (num_left-- == 0) {
881 /* we found it, overwrite it */
882 e_vcard_attribute_remove_values (attr);
885 /* we didn't find it - add a new attribute */
886 attr = e_vcard_attribute_new (NULL, info->vcard_field_name);
887 e_vcard_append_attribute (E_VCARD (contact), attr);
888 if (info->attr_type1)
889 e_vcard_attribute_add_param_with_value (attr, e_vcard_attribute_param_new (EVC_TYPE),
891 if (info->attr_type2)
892 e_vcard_attribute_add_param_with_value (attr, e_vcard_attribute_param_new (EVC_TYPE),
896 if (info->t & E_CONTACT_FIELD_TYPE_STRUCT || info->t & E_CONTACT_FIELD_TYPE_GETSET) {
897 gpointer data = info->t & E_CONTACT_FIELD_TYPE_STRUCT ? g_value_get_boxed (value) : (gchar *)g_value_get_string (value);
899 if ((info->t & E_CONTACT_FIELD_TYPE_STRUCT && data)
900 || (data && *(gchar *)data))
901 info->struct_setter (contact, attr, data);
903 e_vcard_remove_attribute (E_VCARD (contact), attr);
906 const gchar *sval = g_value_get_string (value);
909 e_vcard_attribute_add_value (attr, sval);
911 e_vcard_remove_attribute (E_VCARD (contact), attr);
914 else if (info->t & E_CONTACT_FIELD_TYPE_LIST_ELEM) {
915 EVCardAttribute *attr = e_contact_get_first_attr (contact, info->vcard_field_name);
918 const gchar *sval = g_value_get_string (value);
924 d(printf ("adding new %s\n", info->vcard_field_name));
926 attr = e_vcard_attribute_new (NULL, info->vcard_field_name);
927 e_vcard_append_attribute (E_VCARD (contact), attr);
930 values = e_vcard_attribute_get_values (attr);
931 p = g_list_nth (values, info->list_elem);
935 p->data = g_strdup (g_value_get_string (value));
938 /* there weren't enough elements in the list, pad it */
939 gint count = info->list_elem - g_list_length (values);
942 e_vcard_attribute_add_value (attr, "");
944 e_vcard_attribute_add_value (attr, g_value_get_string (value));
948 switch (info->field_id) {
949 case E_CONTACT_CATEGORIES: {
950 EVCardAttribute *attr = e_contact_get_first_attr (contact, EVC_CATEGORIES);
955 e_vcard_attribute_remove_values (attr);
957 /* we didn't find it - add a new attribute */
958 attr = e_vcard_attribute_new (NULL, EVC_CATEGORIES);
959 e_vcard_append_attribute (E_VCARD (contact), attr);
962 str = g_value_get_string (value);
964 split = g_strsplit (str, ",", 0);
966 for (s = split; *s; s++) {
967 e_vcard_attribute_add_value (attr, g_strstrip (*s));
971 e_vcard_attribute_add_value (attr, str);
974 d(printf ("removing %s\n", info->vcard_field_name));
976 e_vcard_remove_attribute (E_VCARD (contact), attr);
981 g_warning ("unhandled synthetic field 0x%02x", info->field_id);
986 else if (info->t & E_CONTACT_FIELD_TYPE_STRUCT || info->t & E_CONTACT_FIELD_TYPE_GETSET) {
987 EVCardAttribute *attr = e_contact_get_first_attr (contact, info->vcard_field_name);
988 gpointer data = info->t & E_CONTACT_FIELD_TYPE_STRUCT ? g_value_get_boxed (value) : (gchar *)g_value_get_string (value);
991 if ((info->t & E_CONTACT_FIELD_TYPE_STRUCT && data)
992 || (data && *(gchar *)data)) {
993 d(printf ("overwriting existing %s\n", info->vcard_field_name));
994 /* remove all existing values and parameters.
995 the setter will add the correct ones */
996 e_vcard_attribute_remove_values (attr);
997 e_vcard_attribute_remove_params (attr);
999 info->struct_setter (contact, attr, data);
1002 d(printf ("removing %s\n", info->vcard_field_name));
1004 e_vcard_remove_attribute (E_VCARD (contact), attr);
1007 else if ((info->t & E_CONTACT_FIELD_TYPE_STRUCT && data)
1008 || (data && *(gchar *)data)) {
1009 d(printf ("adding new %s\n", info->vcard_field_name));
1010 attr = e_vcard_attribute_new (NULL, info->vcard_field_name);
1012 e_vcard_append_attribute (E_VCARD (contact), attr);
1014 info->struct_setter (contact, attr, data);
1017 else if (info->t & E_CONTACT_FIELD_TYPE_BOOLEAN) {
1018 EVCardAttribute *attr;
1020 /* first we search for an attribute we can overwrite */
1021 attr = e_contact_get_first_attr (contact, info->vcard_field_name);
1023 d(printf ("setting %s to `%s'\n", info->vcard_field_name, g_value_get_string (value)));
1024 e_vcard_attribute_remove_values (attr);
1025 e_vcard_attribute_add_value (attr, g_value_get_boolean (value) ? "TRUE" : "FALSE");
1028 /* and if we don't find one we create a new attribute */
1029 e_vcard_append_attribute_with_value (E_VCARD (contact),
1030 e_vcard_attribute_new (NULL, info->vcard_field_name),
1031 g_value_get_boolean (value) ? "TRUE" : "FALSE");
1034 else if (info->t & E_CONTACT_FIELD_TYPE_STRING) {
1035 EVCardAttribute *attr;
1036 const gchar *sval = g_value_get_string (value);
1038 /* first we search for an attribute we can overwrite */
1039 attr = e_contact_get_first_attr (contact, info->vcard_field_name);
1041 d(printf ("setting %s to `%s'\n", info->vcard_field_name, sval));
1042 e_vcard_attribute_remove_values (attr);
1044 e_vcard_attribute_add_value (attr, sval);
1047 d(printf ("removing %s\n", info->vcard_field_name));
1049 e_vcard_remove_attribute (E_VCARD (contact), attr);
1054 /* and if we don't find one we create a new attribute */
1055 e_vcard_append_attribute_with_value (E_VCARD (contact),
1056 e_vcard_attribute_new (NULL, info->vcard_field_name),
1057 g_value_get_string (value));
1060 else if (info->t & E_CONTACT_FIELD_TYPE_LIST) {
1061 EVCardAttribute *attr;
1064 values = g_value_get_pointer (value);
1066 attr = e_contact_get_first_attr (contact, info->vcard_field_name);
1069 e_vcard_attribute_remove_values (attr);
1072 e_vcard_remove_attribute (E_VCARD (contact), attr);
1075 attr = e_vcard_attribute_new (NULL, info->vcard_field_name);
1076 e_vcard_append_attribute (E_VCARD (contact), attr);
1079 for (l = values; l != NULL; l = l->next)
1080 e_vcard_attribute_add_value (attr, l->data);
1083 g_warning ("unhandled attribute `%s'", info->vcard_field_name);
1087 static EVCardAttribute *
1088 e_contact_find_attribute_with_types (EContact *contact, const gchar *attr_name, const gchar *type_needed1, const gchar *type_needed2, gint nth)
1091 gboolean found_needed1, found_needed2;
1093 attrs = e_vcard_get_attributes (E_VCARD (contact));
1095 for (l = attrs; l; l = l->next) {
1096 EVCardAttribute *attr = l->data;
1099 found_needed1 = (type_needed1 == NULL);
1100 found_needed2 = (type_needed2 == NULL);
1102 name = e_vcard_attribute_get_name (attr);
1104 if (!g_ascii_strcasecmp (name, attr_name)) {
1107 for (params = e_vcard_attribute_get_params (attr); params; params = params->next) {
1108 EVCardAttributeParam *param = params->data;
1109 const gchar *param_name = e_vcard_attribute_param_get_name (param);
1111 if (!g_ascii_strcasecmp (param_name, EVC_TYPE)) {
1112 gboolean matches = FALSE;
1113 GList *values = e_vcard_attribute_param_get_values (param);
1115 while (values && values->data) {
1116 if (!found_needed1 && !g_ascii_strcasecmp ((gchar *)values->data, type_needed1)) {
1117 found_needed1 = TRUE;
1120 else if (!found_needed2 && !g_ascii_strcasecmp ((gchar *)values->data, type_needed2)) {
1121 found_needed2 = TRUE;
1127 values = values->next;
1131 /* this is to enforce that we find an attribute
1132 with *only* the TYPE='s we need. This may seem like
1133 an odd restriction but it's the only way at present to
1134 implement the Other Fax and Other Phone attributes. */
1136 found_needed2 = FALSE;
1141 if (found_needed1 && found_needed2) {
1155 e_contact_get_property (GObject *object,
1160 const EContactFieldInfo *info = NULL;
1163 if (prop_id < 1 || prop_id >= E_CONTACT_FIELD_LAST) {
1164 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1165 g_value_reset (value);
1169 info = &field_info[prop_id];
1170 data = e_contact_get (E_CONTACT (object), prop_id);
1172 if (info->t & E_CONTACT_FIELD_TYPE_BOOLEAN) {
1173 g_value_set_boolean (value, data != NULL);
1174 } else if (info->t & E_CONTACT_FIELD_TYPE_LIST) {
1175 g_value_set_pointer (value, data);
1176 } else if (info->t & E_CONTACT_FIELD_TYPE_STRUCT) {
1177 g_value_take_boxed (value, data);
1178 } else if (info->t & E_CONTACT_FIELD_TYPE_GETSET) {
1179 if (info->t & E_CONTACT_FIELD_TYPE_STRUCT) {
1180 g_value_set_boxed (value, data);
1182 g_value_set_string (value, data);
1184 } else if (info->t & E_CONTACT_FIELD_TYPE_STRING) {
1185 g_value_set_string (value, data);
1187 g_value_set_pointer (value, data);
1196 * Creates a new, blank #EContact.
1198 * Returns: A new #EContact.
1201 e_contact_new (void)
1203 return e_contact_new_from_vcard ("");
1207 * e_contact_new_from_vcard:
1208 * @vcard: a string representing a vcard
1210 * Creates a new #EContact based on a vcard.
1212 * Returns: A new #EContact.
1215 e_contact_new_from_vcard (const gchar *vcard)
1218 const gchar *file_as;
1220 g_return_val_if_fail (vcard != NULL, NULL);
1222 contact = g_object_new (E_TYPE_CONTACT, NULL);
1223 e_vcard_construct (E_VCARD (contact), vcard);
1225 /* Generate a FILE_AS field if needed */
1227 file_as = e_contact_get_const (contact, E_CONTACT_FILE_AS);
1228 if (!file_as || !*file_as) {
1231 gchar *file_as_new = NULL;
1233 gchar **strings_p = strings;
1235 name = e_contact_get (contact, E_CONTACT_NAME);
1236 org = e_contact_get_const (contact, E_CONTACT_ORG);
1239 if (name->family && *name->family)
1240 *(strings_p++) = name->family;
1241 if (name->given && *name->given)
1242 *(strings_p++) = name->given;
1244 if (strings_p != strings) {
1246 file_as_new = g_strjoinv (", ", strings);
1249 e_contact_name_free (name);
1252 if (!file_as_new && org && *org)
1253 file_as_new = g_strdup (org);
1256 e_contact_set (contact, E_CONTACT_FILE_AS, file_as_new);
1257 g_free (file_as_new);
1265 * e_contact_duplicate:
1266 * @contact: an #EContact
1268 * Creates a copy of @contact.
1270 * Returns: A new #EContact identical to @contact.
1273 e_contact_duplicate (EContact *contact)
1278 g_return_val_if_fail (E_IS_CONTACT (contact), NULL);
1280 vcard = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
1281 c = e_contact_new_from_vcard (vcard);
1288 * e_contact_field_name:
1289 * @field_id: an #EContactField
1291 * Gets the string representation of @field_id.
1293 * Returns: The string representation of @field_id, or %NULL if it doesn't exist.
1296 e_contact_field_name (EContactField field_id)
1298 g_return_val_if_fail (field_id >= 1 && field_id <= E_CONTACT_FIELD_LAST, "");
1300 return field_info[field_id].field_name;
1304 * e_contact_pretty_name:
1305 * @field_id: an #EContactField
1307 * Gets a human-readable, translated string representation
1310 * Returns: The human-readable representation of @field_id, or %NULL if it doesn't exist.
1313 e_contact_pretty_name (EContactField field_id)
1315 g_return_val_if_fail (field_id >= 1 && field_id <= E_CONTACT_FIELD_LAST, "");
1318 bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
1319 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
1322 return _(field_info[field_id].pretty_name);
1326 * e_contact_vcard_attribute:
1327 * @field_id: an #EContactField
1329 * Gets the vcard attribute corresponding to @field_id, as a string.
1331 * Returns: The vcard attribute corresponding to @field_id, or %NULL if it doesn't exist.
1334 e_contact_vcard_attribute (EContactField field_id)
1336 g_return_val_if_fail (field_id >= 1 && field_id <= E_CONTACT_FIELD_LAST, "");
1338 return field_info[field_id].vcard_field_name;
1342 * e_contact_field_id:
1343 * @field_name: a string representing a contact field
1345 * Gets the #EContactField corresponding to the @field_name.
1347 * Returns: An #EContactField corresponding to @field_name, or %0 if it doesn't exist.
1350 e_contact_field_id (const gchar *field_name)
1353 for (i = E_CONTACT_FIELD_FIRST; i < E_CONTACT_FIELD_LAST; i ++) {
1354 if (!g_ascii_strcasecmp (field_info[i].field_name, field_name))
1355 return field_info[i].field_id;
1358 g_warning ("unknown field name `%s'", field_name);
1363 * e_contact_field_id_from_vcard:
1364 * @vcard_field: a string representing a vCard field
1366 * Gets the #EContactField corresponding to the @vcard_field.
1368 * Returns: An #EContactField corresponding to @vcard_field, or %0 if it doesn't exist.
1373 e_contact_field_id_from_vcard (const gchar *vcard_field)
1377 for (i = E_CONTACT_FIELD_FIRST; i < E_CONTACT_FIELD_LAST; i ++) {
1378 if (field_info[i].vcard_field_name == NULL)
1380 if (field_info[i].t & E_CONTACT_FIELD_TYPE_SYNTHETIC)
1382 if (!strcmp (field_info[i].vcard_field_name, vcard_field))
1383 return field_info[i].field_id;
1386 g_warning ("unknown vCard field `%s'", vcard_field);
1392 * @contact: an #EContact
1393 * @field_id: an #EContactField
1395 * Gets the value of @contact's field specified by @field_id.
1397 * Returns: Depends on the field's type, owned by the caller.
1400 e_contact_get (EContact *contact, EContactField field_id)
1402 const EContactFieldInfo *info = NULL;
1404 g_return_val_if_fail (contact && E_IS_CONTACT (contact), NULL);
1405 g_return_val_if_fail (field_id >= 1 && field_id <= E_CONTACT_FIELD_LAST, NULL);
1407 info = &field_info[field_id];
1409 if (info->t & E_CONTACT_FIELD_TYPE_BOOLEAN) {
1410 EVCardAttribute *attr = e_contact_get_first_attr (contact, info->vcard_field_name);
1411 gboolean rv = FALSE;
1414 GList *v = e_vcard_attribute_get_values (attr);
1415 rv = v && v->data && !g_ascii_strcasecmp ((gchar *)v->data, "true");
1416 return rv ? (gpointer) "1" : NULL;
1419 else if (info->t & E_CONTACT_FIELD_TYPE_LIST) {
1420 EVCardAttribute *attr = e_contact_get_first_attr (contact, info->vcard_field_name);
1423 GList *list = g_list_copy (e_vcard_attribute_get_values (attr));
1425 for (l = list; l; l = l->next)
1426 l->data = l->data ? g_strstrip (g_strdup (l->data)) : NULL;
1430 else if (info->t & E_CONTACT_FIELD_TYPE_LIST_ELEM) {
1431 if (info->t & E_CONTACT_FIELD_TYPE_STRING) {
1432 EVCardAttribute *attr = e_contact_get_first_attr (contact, info->vcard_field_name);
1437 v = e_vcard_attribute_get_values (attr);
1438 v = g_list_nth (v, info->list_elem);
1440 return v ? g_strstrip (g_strdup (v->data)) : NULL;
1444 else if (info->t & E_CONTACT_FIELD_TYPE_MULTI_ELEM) {
1445 if (info->t & E_CONTACT_FIELD_TYPE_STRING) {
1447 gint num_left = info->list_elem;
1449 attrs = e_vcard_get_attributes (E_VCARD (contact));
1451 for (l = attrs; l; l = l->next) {
1452 EVCardAttribute *attr = l->data;
1455 name = e_vcard_attribute_get_name (attr);
1457 if (!g_ascii_strcasecmp (name, info->vcard_field_name)) {
1458 if (num_left-- == 0) {
1459 GList *v = e_vcard_attribute_get_values (attr);
1461 return v ? g_strstrip (g_strdup (v->data)) : NULL;
1467 else if (info->t & E_CONTACT_FIELD_TYPE_ATTR_TYPE) {
1468 EVCardAttribute *attr = e_contact_find_attribute_with_types (contact, info->vcard_field_name, info->attr_type1, info->attr_type2, info->list_elem);
1470 if (info->t & E_CONTACT_FIELD_TYPE_STRING) {
1472 GList *p = e_vcard_attribute_get_values (attr);
1473 return g_strstrip (g_strdup (p->data));
1480 return info->struct_getter (contact, attr);
1484 else if (info->t & E_CONTACT_FIELD_TYPE_STRUCT) {
1485 EVCardAttribute *attr = e_contact_get_first_attr (contact, info->vcard_field_name);
1487 return info->struct_getter (contact, attr);
1489 else if (info->t & E_CONTACT_FIELD_TYPE_GETSET) {
1490 EVCardAttribute *attr = e_contact_get_first_attr (contact, info->vcard_field_name);
1494 rv = info->struct_getter (contact, attr);
1496 if (info->t & E_CONTACT_FIELD_TYPE_STRUCT)
1497 return (gpointer)info->boxed_type_getter();
1501 return g_strstrip (g_strdup (rv));
1503 else if (info->t & E_CONTACT_FIELD_TYPE_SYNTHETIC) {
1504 switch (info->field_id) {
1505 case E_CONTACT_NAME_OR_ORG: {
1508 str = e_contact_get_const (contact, E_CONTACT_FILE_AS);
1510 str = e_contact_get_const (contact, E_CONTACT_FULL_NAME);
1512 str = e_contact_get_const (contact, E_CONTACT_ORG);
1514 gboolean is_list = GPOINTER_TO_INT (e_contact_get (contact, E_CONTACT_IS_LIST));
1517 str = _("Unnamed List");
1519 str = e_contact_get_const (contact, E_CONTACT_EMAIL_1);
1522 return str ? g_strstrip (g_strdup (str)) : NULL;
1524 case E_CONTACT_CATEGORIES: {
1525 EVCardAttribute *attr = e_contact_get_first_attr (contact, EVC_CATEGORIES);
1529 GString *str = g_string_new ("");
1530 GList *v = e_vcard_attribute_get_values (attr);
1532 g_string_append (str, (gchar *)v->data);
1535 g_string_append (str, ", ");
1538 rv = g_string_free (str, FALSE);
1543 g_warning ("unhandled synthetic field 0x%02x", info->field_id);
1549 GList *rv = NULL; /* used for multi attribute lists */
1551 attrs = e_vcard_get_attributes (E_VCARD (contact));
1553 for (l = attrs; l; l = l->next) {
1554 EVCardAttribute *attr = l->data;
1557 name = e_vcard_attribute_get_name (attr);
1559 if (!g_ascii_strcasecmp (name, info->vcard_field_name)) {
1561 v = e_vcard_attribute_get_values (attr);
1563 if (info->t & E_CONTACT_FIELD_TYPE_STRING) {
1564 return v ? g_strstrip (g_strdup (v->data)) : NULL;
1567 rv = g_list_append (rv, v ? g_strstrip (g_strdup (v->data)) : NULL);
1577 * e_contact_get_const:
1578 * @contact: an #EContact
1579 * @field_id: an #EContactField
1581 * Gets the value of @contact's field specified by @field_id, caching
1582 * the result so it can be freed later.
1584 * Returns: Depends on the field's type, owned by the #EContact.
1587 e_contact_get_const (EContact *contact, EContactField field_id)
1589 gpointer value = NULL;
1591 g_return_val_if_fail (E_IS_CONTACT (contact), NULL);
1592 g_return_val_if_fail (field_info [field_id].t & E_CONTACT_FIELD_TYPE_STRING, NULL);
1594 value = contact->priv->cached_strings[field_id];
1597 value = e_contact_get (contact, field_id);
1599 contact->priv->cached_strings[field_id] = value;
1607 * @contact: an #EContact
1608 * @field_id: an #EContactField
1609 * @value: a value whose type depends on the @field_id
1611 * Sets the value of @contact's field specified by @field_id to @value.
1614 e_contact_set (EContact *contact, EContactField field_id, gconstpointer value)
1616 d(printf ("e_contact_set (%p, %d, %p)\n", contact, field_id, value));
1618 g_return_if_fail (contact && E_IS_CONTACT (contact));
1619 g_return_if_fail (field_id >= 1 && field_id <= E_CONTACT_FIELD_LAST);
1621 /* set the cached slot to NULL so we'll re-get the new string
1622 if e_contact_get_const is called again */
1623 contact->priv->cached_strings[field_id] = NULL;
1625 g_object_set (contact,
1626 e_contact_field_name (field_id), value,
1631 * e_contact_get_attributes:
1632 * @contact: an #EContact
1633 * @field_id: an #EContactField
1635 * Gets a list of the vcard attributes for @contact's @field_id.
1637 * Returns: A #GList of pointers to #EVCardAttribute, owned by the caller.
1640 e_contact_get_attributes (EContact *contact, EContactField field_id)
1644 const EContactFieldInfo *info = NULL;
1646 g_return_val_if_fail (contact && E_IS_CONTACT (contact), NULL);
1647 g_return_val_if_fail (field_id >= 1 && field_id <= E_CONTACT_FIELD_LAST, NULL);
1649 info = &field_info[field_id];
1651 attrs = e_vcard_get_attributes (E_VCARD (contact));
1653 for (a = attrs; a; a = a->next) {
1654 EVCardAttribute *attr = a->data;
1657 name = e_vcard_attribute_get_name (attr);
1659 if (!g_ascii_strcasecmp (name, info->vcard_field_name)) {
1660 l = g_list_prepend (l, e_vcard_attribute_copy (attr));
1664 return g_list_reverse(l);
1668 * e_contact_set_attributes:
1669 * @contact: an #EContact
1670 * @field_id: an #EContactField
1671 * @attributes: a #GList of pointers to #EVCardAttribute
1673 * Sets the vcard attributes for @contact's @field_id.
1674 * Attributes are added to the contact in the same order as they are in @attributes.
1677 e_contact_set_attributes (EContact *contact, EContactField field_id, GList *attributes)
1679 const EContactFieldInfo *info = NULL;
1682 g_return_if_fail (contact && E_IS_CONTACT (contact));
1683 g_return_if_fail (field_id >= 1 && field_id <= E_CONTACT_FIELD_LAST);
1685 info = &field_info[field_id];
1687 e_vcard_remove_attributes (E_VCARD (contact), NULL, info->vcard_field_name);
1689 for (l = attributes; l; l = l->next)
1690 e_vcard_append_attribute (E_VCARD (contact),
1691 e_vcard_attribute_copy ((EVCardAttribute*)l->data));
1695 * e_contact_name_new:
1697 * Creates a new #EContactName struct.
1699 * Returns: A new #EContactName struct.
1702 e_contact_name_new (void)
1704 return g_new0 (EContactName, 1);
1708 * e_contact_name_to_string:
1709 * @name: an #EContactName
1711 * Generates a string representation of @name.
1713 * Returns: The string representation of @name.
1716 e_contact_name_to_string(const EContactName *name)
1718 gchar *strings[6], **stringptr = strings;
1720 g_return_val_if_fail (name != NULL, NULL);
1722 if (name->prefixes && *name->prefixes)
1723 *(stringptr++) = name->prefixes;
1724 if (name->given && *name->given)
1725 *(stringptr++) = name->given;
1726 if (name->additional && *name->additional)
1727 *(stringptr++) = name->additional;
1728 if (name->family && *name->family)
1729 *(stringptr++) = name->family;
1730 if (name->suffixes && *name->suffixes)
1731 *(stringptr++) = name->suffixes;
1733 return g_strjoinv(" ", strings);
1737 * e_contact_name_from_string:
1738 * @name_str: a string representing a contact's full name
1740 * Creates a new #EContactName based on the parsed @name_str.
1742 * Returns: A new #EContactName struct.
1745 e_contact_name_from_string (const gchar *name_str)
1747 EContactName *name = e_contact_name_new();
1748 ENameWestern *western;
1750 g_return_val_if_fail (name_str != NULL, NULL);
1752 western = e_name_western_parse (name_str ? name_str : "");
1754 name->prefixes = g_strdup (western->prefix);
1755 name->given = g_strdup (western->first );
1756 name->additional = g_strdup (western->middle);
1757 name->family = g_strdup (western->last );
1758 name->suffixes = g_strdup (western->suffix);
1760 e_name_western_free(western);
1766 * e_contact_name_copy:
1767 * @n: an #EContactName
1769 * Creates a copy of @n.
1771 * Returns: A new #EContactName identical to @n.
1774 e_contact_name_copy (EContactName *n)
1778 g_return_val_if_fail (n != NULL, NULL);
1780 name = e_contact_name_new();
1782 name->prefixes = g_strdup (n->prefixes);
1783 name->given = g_strdup (n->given);
1784 name->additional = g_strdup (n->additional);
1785 name->family = g_strdup (n->family);
1786 name->suffixes = g_strdup (n->suffixes);
1792 * e_contact_name_free:
1793 * @name: an #EContactName
1795 * Frees @name and its contents.
1798 e_contact_name_free (EContactName *name)
1803 g_free (name->family);
1804 g_free (name->given);
1805 g_free (name->additional);
1806 g_free (name->prefixes);
1807 g_free (name->suffixes);
1812 #define E_CONTACT_DEFINE_BOXED_TYPE(_tp,_nm) \
1814 _tp ## _get_type (void) \
1816 static volatile gsize type_id__volatile = 0; \
1818 if (g_once_init_enter (&type_id__volatile)) { \
1821 type_id = g_boxed_type_register_static (_nm, \
1822 (GBoxedCopyFunc) _tp ## _copy, \
1823 (GBoxedFreeFunc) _tp ## _free); \
1825 g_once_init_leave (&type_id__volatile, type_id);\
1828 return type_id__volatile; \
1831 E_CONTACT_DEFINE_BOXED_TYPE (e_contact_name, "EContactName")
1834 * e_contact_date_from_string:
1835 * @str: a date string in the format YYYY-MM-DD or YYYYMMDD
1837 * Creates a new #EContactDate based on @str.
1839 * Returns: A new #EContactDate struct.
1842 e_contact_date_from_string (const gchar *str)
1848 g_return_val_if_fail (str != NULL, NULL);
1850 date = e_contact_date_new();
1851 /* ignore time part */
1852 if ((t = strchr (str, 'T')) != NULL)
1855 length = strlen(str);
1857 if (length == 10 ) {
1858 date->year = str[0] * 1000 + str[1] * 100 + str[2] * 10 + str[3] - '0' * 1111;
1859 date->month = str[5] * 10 + str[6] - '0' * 11;
1860 date->day = str[8] * 10 + str[9] - '0' * 11;
1861 } else if (length == 8) {
1862 date->year = str[0] * 1000 + str[1] * 100 + str[2] * 10 + str[3] - '0' * 1111;
1863 date->month = str[4] * 10 + str[5] - '0' * 11;
1864 date->day = str[6] * 10 + str[7] - '0' * 11;
1871 * e_contact_date_to_string:
1872 * @dt: an #EContactDate
1874 * Generates a date string in the format YYYY-MM-DD based
1875 * on the values of @dt.
1877 * Returns: A date string, owned by the caller.
1880 e_contact_date_to_string (EContactDate *dt)
1883 return g_strdup_printf ("%04d-%02d-%02d",
1884 CLAMP(dt->year, 1000, 9999),
1885 CLAMP(dt->month, 1, 12),
1886 CLAMP(dt->day, 1, 31));
1892 * e_contact_date_equal:
1893 * @dt1: an #EContactDate
1894 * @dt2: an #EContactDate
1896 * Checks if @dt1 and @dt2 are the same date.
1898 * Returns: %TRUE if @dt1 and @dt2 are equal, %FALSE otherwise.
1901 e_contact_date_equal (EContactDate *dt1, EContactDate *dt2)
1904 return (dt1->year == dt2->year &&
1905 dt1->month == dt2->month &&
1906 dt1->day == dt2->day);
1908 return (!!dt1 == !!dt2);
1912 * e_contact_date_copy:
1913 * @dt: an #EContactDate
1915 * Creates a copy of @dt.
1917 * Returns: A new #EContactDate struct identical to @dt.
1919 static EContactDate *
1920 e_contact_date_copy (EContactDate *dt)
1922 EContactDate *dt2 = e_contact_date_new ();
1923 dt2->year = dt->year;
1924 dt2->month = dt->month;
1931 * e_contact_date_free:
1932 * @date: an #EContactDate
1934 * Frees the @date struct and its contents.
1937 e_contact_date_free (EContactDate *date)
1942 E_CONTACT_DEFINE_BOXED_TYPE (e_contact_date, "EContactDate")
1945 * e_contact_date_new:
1947 * Creates a new #EContactDate struct.
1949 * Returns: A new #EContactDate struct.
1952 e_contact_date_new (void)
1954 return g_new0 (EContactDate, 1);
1958 * e_contact_photo_free:
1959 * @photo: an #EContactPhoto struct
1961 * Frees the @photo struct and its contents.
1964 e_contact_photo_free (EContactPhoto *photo)
1969 switch (photo->type) {
1970 case E_CONTACT_PHOTO_TYPE_INLINED:
1971 g_free (photo->data.inlined.mime_type);
1972 g_free (photo->data.inlined.data);
1974 case E_CONTACT_PHOTO_TYPE_URI:
1975 g_free (photo->data.uri);
1978 g_warning ("Unknown EContactPhotoType %d", photo->type);
1986 * e_contact_photo_copy:
1987 * @photo: an #EContactPhoto
1989 * Creates a copy of @photo.
1991 * Returns: A new #EContactPhoto struct identical to @photo.
1993 static EContactPhoto *
1994 e_contact_photo_copy (EContactPhoto *photo)
1996 EContactPhoto *photo2 = g_new0 (EContactPhoto, 1);
1997 switch (photo->type) {
1998 case E_CONTACT_PHOTO_TYPE_INLINED:
1999 photo2->type = E_CONTACT_PHOTO_TYPE_INLINED;
2000 photo2->data.inlined.mime_type = g_strdup (photo->data.inlined.mime_type);
2001 photo2->data.inlined.length = photo->data.inlined.length;
2002 photo2->data.inlined.data = g_malloc (photo2->data.inlined.length);
2003 memcpy (photo2->data.inlined.data, photo->data.inlined.data, photo->data.inlined.length);
2005 case E_CONTACT_PHOTO_TYPE_URI:
2006 photo2->type = E_CONTACT_PHOTO_TYPE_URI;
2007 photo2->data.uri = g_strdup (photo->data.uri);
2010 g_warning ("Unknown EContactPhotoType %d", photo->type);
2016 E_CONTACT_DEFINE_BOXED_TYPE (e_contact_photo, "EContactPhoto")
2019 * e_contact_geo_free:
2020 * @geo: an #EContactGeo
2022 * Frees the @geo struct and its contents.
2027 e_contact_geo_free (EContactGeo *geo)
2032 static EContactGeo *
2033 e_contact_geo_copy (EContactGeo *geo)
2035 EContactGeo *geo2 = g_new0 (EContactGeo, 1);
2036 geo2->latitude = geo->latitude;
2037 geo2->longitude = geo->longitude;
2042 E_CONTACT_DEFINE_BOXED_TYPE (e_contact_geo, "EContactGeo")
2045 * e_contact_address_free:
2046 * @address: an #EContactAddress
2048 * Frees the @address struct and its contents.
2051 e_contact_address_free (EContactAddress *address)
2056 g_free (address->address_format);
2057 g_free (address->po);
2058 g_free (address->ext);
2059 g_free (address->street);
2060 g_free (address->locality);
2061 g_free (address->region);
2062 g_free (address->code);
2063 g_free (address->country);
2068 static EContactAddress *
2069 e_contact_address_copy (EContactAddress *address)
2071 EContactAddress *address2 = g_new0 (EContactAddress, 1);
2073 address2->address_format = g_strdup (address->address_format);
2074 address2->po = g_strdup (address->po);
2075 address2->ext = g_strdup (address->ext);
2076 address2->street = g_strdup (address->street);
2077 address2->locality = g_strdup (address->locality);
2078 address2->region = g_strdup (address->region);
2079 address2->code = g_strdup (address->code);
2080 address2->country = g_strdup (address->country);
2085 E_CONTACT_DEFINE_BOXED_TYPE (e_contact_address, "EContactAddress")
2088 * e_contact_cert_free:
2089 * @cert: an #EContactCert
2091 * Frees the @cert struct and its contents.
2094 e_contact_cert_free (EContactCert *cert)
2099 g_free (cert->data);
2103 static EContactCert *
2104 e_contact_cert_copy (EContactCert *cert)
2106 EContactCert *cert2 = g_new0 (EContactCert, 1);
2107 cert2->length = cert->length;
2108 cert2->data = g_malloc (cert2->length);
2109 memcpy (cert2->data, cert->data, cert->length);
2114 E_CONTACT_DEFINE_BOXED_TYPE (e_contact_cert, "EContactCert")