Correct the use of pthread_create() in several places.
[claws.git] / src / editaddress.c
1 /*
2  * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
3  * Copyright (C) 1999-2016 Hiroyuki Yamamoto and the Claws Mail team
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 3 of the License, or
8  * (at your option) any later version.
9  *
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
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 #ifdef HAVE_CONFIG_H
20 #  include "config.h"
21 #include "claws-features.h"
22 #endif
23
24 #include "defs.h"
25
26 #include <glib.h>
27 #include <glib/gi18n.h>
28 #include <gdk/gdkkeysyms.h>
29 #include <gtk/gtk.h>
30
31 #include "alertpanel.h"
32 #include "stock_pixmap.h"
33 #include "mgutils.h"
34 #include "addressbook.h"
35 #include "addressitem.h"
36 #include "addritem.h"
37 #include "addrbook.h"
38 #include "manage_window.h"
39 #include "gtkutils.h"
40 #include "filesel.h"
41 #include "codeconv.h"
42 #include "editaddress.h"
43 #include "editaddress_other_attributes_ldap.h"
44 #include "prefs_common.h"
45 #include "menu.h"
46 #include "combobox.h"
47
48 /* transient data */
49 static struct _PersonEdit_dlg personeditdlg;
50 static AddressBookFile *current_abf = NULL;
51 static ItemPerson *current_person = NULL;
52 static ItemFolder *current_parent_folder = NULL;
53 static EditAddressPostUpdateCallback edit_person_close_post_update_cb = NULL;
54
55 typedef enum {
56         EMAIL_COL_EMAIL   = 0,
57         EMAIL_COL_ALIAS   = 1,
58         EMAIL_COL_REMARKS = 2
59 } PersonEditEMailColumnPos;
60
61 typedef enum {
62         ATTRIB_COL_NAME    = 0,
63         ATTRIB_COL_VALUE   = 1
64 } PersonEditAttribColumnPos;
65
66 #define EDITPERSON_WIDTH      520
67 #define EDITPERSON_HEIGHT     320
68
69 #ifndef GENERIC_UMPC
70 # define EMAIL_N_COLS          3
71 # define EMAIL_COL_WIDTH_EMAIL 180
72 # define EMAIL_COL_WIDTH_ALIAS 80
73 #else
74 # define EMAIL_N_COLS          1
75 # define EMAIL_COL_WIDTH_EMAIL 130
76 # define EMAIL_COL_WIDTH_ALIAS 130
77 #endif
78
79 #ifndef GENERIC_UMPC
80 # define ATTRIB_N_COLS          2
81 # define ATTRIB_COL_WIDTH_NAME  240
82 # define ATTRIB_COL_WIDTH_VALUE 0
83 #else
84 # define ATTRIB_N_COLS          2
85 # define ATTRIB_COL_WIDTH_NAME  120
86 # define ATTRIB_COL_WIDTH_VALUE 120
87 #endif
88
89 #define PAGE_BASIC             0
90 #define PAGE_EMAIL             1
91 #define PAGE_ATTRIBUTES        2
92
93 static gboolean addressbook_edit_person_close( gboolean cancelled );
94 static GList *edit_person_build_email_list();
95 static GList *edit_person_build_attrib_list();
96
97 static gchar* edit_person_get_common_name_from_widgets(void)
98 {
99         gchar *cn = NULL; /* cn must be freed by caller */
100
101 #ifndef GENERIC_UMPC
102         {
103                 cn = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_name), 0, -1 );
104                 if ( cn == NULL || *cn == '\0' ) {
105                         gchar *first = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_first), 0, -1 );
106                         gchar *last = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_last), 0, -1 );
107                         cn = g_strdup_printf("%s%s%s", first?first:"", (first && last && *first && *last)?" ":"", last?last:"");
108                         g_free(first);
109                         g_free(last);
110                 }
111                 if ( cn == NULL || *cn == '\0' ) {
112                         g_free(cn);
113                         cn = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_nick), 0, -1 );;
114                 }
115         }
116 #else
117         {
118                 gchar *first = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_first), 0, -1 );
119                 gchar *last = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_last), 0, -1 );
120                 cn = g_strdup_printf("%s%s%s", first?first:"", (first && last && *first && *last)?" ":"", last?last:"");
121                 g_free(first);
122                 g_free(last);
123         }
124 #endif
125         if ( cn != NULL )
126                 g_strstrip(cn);
127         return cn;
128 }
129
130 static void edit_person_status_show( gchar *msg ) {
131         if( personeditdlg.statusbar != NULL ) {
132                 gtk_statusbar_pop( GTK_STATUSBAR(personeditdlg.statusbar), personeditdlg.status_cid );
133                 if( msg ) {
134                         gtk_statusbar_push( GTK_STATUSBAR(personeditdlg.statusbar), personeditdlg.status_cid, msg );
135                 }
136         }
137 }
138
139 static void edit_person_cancel(GtkWidget *widget, gboolean *cancelled) {
140         *cancelled = TRUE;
141         if (prefs_common.addressbook_use_editaddress_dialog)
142                 gtk_main_quit();
143         else
144                 addressbook_edit_person_close( *cancelled );
145 }
146
147 static void edit_person_ok(GtkWidget *widget, gboolean *cancelled) {
148         GList *listEMail = edit_person_build_email_list();
149         GList *listAttrib = edit_person_build_attrib_list();
150         gchar *cn = edit_person_get_common_name_from_widgets();
151
152         if( (cn == NULL || *cn == '\0') && listEMail == NULL && listAttrib == NULL ) {
153                 gint val;
154
155                 val = alertpanel( _("Add New Person"),
156 #ifndef GENERIC_UMPC
157                                 _("Adding a new person requires at least one of the\n"
158                                   "following values to be set:\n"
159                                   " - Display Name\n"
160                                   " - First Name\n"
161                                   " - Last Name\n"
162                                   " - Nickname\n"
163                                   " - any email address\n"
164                                   " - any additional attribute\n\n"
165                                   "Click OK to keep editing this contact.\n"
166                                   "Click Cancel to close without saving."),
167 #else
168                                 _("Adding a new person requires at least one of the\n"
169                                   "following values to be set:\n"
170                                   " - First Name\n"
171                                   " - Last Name\n"
172                                   " - any email address\n"
173                                   " - any additional attribute\n\n"
174                                   "Click OK to keep editing this contact.\n"
175                                   "Click Cancel to close without saving."),
176 #endif
177                                 GTK_STOCK_CANCEL, "+"GTK_STOCK_OK, NULL );
178                 if( val == G_ALERTDEFAULT ) {
179                         edit_person_cancel(widget, cancelled);
180                 }
181                 g_free( cn );
182                 return;
183         }
184         g_free( cn );
185
186         *cancelled = FALSE;
187         if (prefs_common.addressbook_use_editaddress_dialog)
188                 gtk_main_quit();
189         else
190                 addressbook_edit_person_close( *cancelled );
191 }
192
193 static gint edit_person_delete_event(GtkWidget *widget, GdkEventAny *event, gboolean *cancelled) {
194         *cancelled = TRUE;
195         if (prefs_common.addressbook_use_editaddress_dialog)
196                 gtk_main_quit();
197         else
198                 addressbook_edit_person_close( *cancelled );
199         return TRUE;
200 }
201
202 static gboolean edit_person_key_pressed(GtkWidget *widget, GdkEventKey *event, gboolean *cancelled) {
203         if (prefs_common.addressbook_use_editaddress_dialog) {
204         if (event && event->keyval == GDK_KEY_Escape) {
205                 *cancelled = TRUE;
206                 gtk_main_quit();
207         }
208         }
209         return FALSE;
210 }
211
212 static gchar *_title_new_ = NULL;
213 static gchar *_title_edit_ = NULL;
214
215 static void edit_person_set_widgets_title( gchar *text )
216 {
217         gchar *label = NULL;
218
219         cm_return_if_fail( text != NULL );
220
221         gtk_label_set_text(GTK_LABEL(personeditdlg.title), "");
222         label = g_markup_printf_escaped("<b>%s</b>", text);
223         gtk_label_set_markup(GTK_LABEL(personeditdlg.title), label);
224         g_free(label);
225 }
226
227 static void edit_person_set_window_title( gint pageNum ) {
228         gchar *sTitle;
229
230         if( _title_new_ == NULL ) {
231                 _title_new_ = g_strdup( _("Add New Person") );
232                 _title_edit_ = g_strdup( _("Edit Person Details") );
233         }
234
235         if( pageNum == PAGE_BASIC ) {
236                 if( personeditdlg.editNew ) {
237                         if (prefs_common.addressbook_use_editaddress_dialog)
238                                 gtk_window_set_title( GTK_WINDOW(personeditdlg.container), _title_new_ );
239                         else
240                                 edit_person_set_widgets_title( _title_new_ );
241                 }
242                 else {
243                         if (prefs_common.addressbook_use_editaddress_dialog)
244                                 gtk_window_set_title( GTK_WINDOW(personeditdlg.container), _title_edit_ );
245                         else
246                                 edit_person_set_widgets_title( _title_edit_ );
247                 }
248         }
249         else {
250                 if( personeditdlg.entry_name == NULL ) {
251                         sTitle = g_strdup( _title_edit_ );
252                 }
253                 else {
254                         gchar *name;
255                         name = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_name), 0, -1 );
256                         g_strstrip(name);
257                         if ( *name != '\0' )
258                                 sTitle = g_strdup_printf( "%s - %s", _title_edit_, name );
259                         else
260                                 sTitle = g_strdup( _title_edit_ );
261                         g_free( name );
262                 }
263                 if (prefs_common.addressbook_use_editaddress_dialog)
264                         gtk_window_set_title( GTK_WINDOW(personeditdlg.container), sTitle );
265                 else
266                         edit_person_set_widgets_title( sTitle );
267                 g_free( sTitle );
268         }
269 }
270
271 static void edit_person_email_clear( gpointer data ) {
272         gtk_entry_set_text( GTK_ENTRY(personeditdlg.entry_email), "" );
273         gtk_entry_set_text( GTK_ENTRY(personeditdlg.entry_alias), "" );
274         gtk_entry_set_text( GTK_ENTRY(personeditdlg.entry_remarks), "" );
275 }
276
277 static void edit_person_attrib_clear( gpointer data ) {
278         if (!personeditdlg.ldap) {
279                 gtk_entry_set_text( GTK_ENTRY(gtk_bin_get_child(GTK_BIN((personeditdlg.entry_atname)))), "" );
280                 gtk_entry_set_text( GTK_ENTRY(personeditdlg.entry_atvalue), "" );
281         }
282 }
283
284 static void edit_person_switch_page( GtkNotebook *notebook, gpointer page,
285                                         gint pageNum, gpointer user_data)
286 {
287         edit_person_set_window_title( pageNum );
288         edit_person_status_show( "" );
289 }
290
291 /*
292 * Load clist with a copy of person's email addresses.
293 */
294 static void edit_person_load_email( ItemPerson *person ) {
295         GList *node = person->listEMail;
296         GtkCMCList *clist = GTK_CMCLIST(personeditdlg.clist_email);
297         gchar *text[ EMAIL_N_COLS ];
298         while( node ) {
299                 ItemEMail *emorig = ( ItemEMail * ) node->data;
300                 ItemEMail *email = addritem_copyfull_item_email( emorig );
301                 gint row;
302                 text[ EMAIL_COL_EMAIL   ] = email->address;
303 #ifndef GENERIC_UMPC
304                 text[ EMAIL_COL_ALIAS   ] = email->obj.name;
305                 text[ EMAIL_COL_REMARKS ] = email->remarks;
306 #endif
307                 row = gtk_cmclist_append( clist, text );
308                 gtk_cmclist_set_row_data( clist, row, email );
309                 node = g_list_next( node );
310         }
311 }
312
313 static void edit_person_email_list_selected( GtkCMCList *clist, gint row, gint column, GdkEvent *event, gpointer data ) {
314         ItemEMail *email = gtk_cmclist_get_row_data( clist, row );
315         if( email ) {
316                 if( email->address )
317                         gtk_entry_set_text( GTK_ENTRY(personeditdlg.entry_email), email->address );
318                 if( ADDRITEM_NAME(email) )
319                         gtk_entry_set_text( GTK_ENTRY(personeditdlg.entry_alias), ADDRITEM_NAME(email) );
320                 if( email->remarks )
321                         gtk_entry_set_text( GTK_ENTRY(personeditdlg.entry_remarks), email->remarks );
322                 if (!personeditdlg.read_only) {
323                         gtk_widget_set_sensitive(personeditdlg.email_del, TRUE);
324                         gtk_widget_set_sensitive(personeditdlg.email_up, row > 0);
325                         gtk_widget_set_sensitive(personeditdlg.email_down, gtk_cmclist_get_row_data(clist, row + 1) != NULL);
326                 }
327         } else {
328                 gtk_widget_set_sensitive(personeditdlg.email_del, FALSE);
329                 gtk_widget_set_sensitive(personeditdlg.email_up, FALSE);
330                 gtk_widget_set_sensitive(personeditdlg.email_down, FALSE);
331         }
332         personeditdlg.rowIndEMail = row;
333         edit_person_status_show( NULL );
334 }
335
336 static void edit_person_email_move( gint dir ) {
337         GtkCMCList *clist = GTK_CMCLIST(personeditdlg.clist_email);
338         gint row = personeditdlg.rowIndEMail + dir;
339         ItemEMail *email = gtk_cmclist_get_row_data( clist, row );
340         if( email ) {
341                 gtk_cmclist_row_move( clist, personeditdlg.rowIndEMail, row );
342                 personeditdlg.rowIndEMail = row;
343                 if (!personeditdlg.read_only) {
344                         gtk_widget_set_sensitive(personeditdlg.email_up, row > 0);
345                         gtk_widget_set_sensitive(personeditdlg.email_down, gtk_cmclist_get_row_data(clist, row + 1) != NULL);
346                 }
347         } else {
348                 gtk_widget_set_sensitive(personeditdlg.email_up, FALSE);
349                 gtk_widget_set_sensitive(personeditdlg.email_down, FALSE);
350         }
351         edit_person_email_clear( NULL );
352         edit_person_status_show( NULL );
353 }
354
355 static void edit_person_email_move_up( gpointer data ) {
356         edit_person_email_move( -1 );
357 }
358
359 static void edit_person_email_move_down( gpointer data ) {
360         edit_person_email_move( +1 );
361 }
362
363 static void edit_person_email_delete( gpointer data ) {
364         GtkCMCList *clist = GTK_CMCLIST(personeditdlg.clist_email);
365         gint row = personeditdlg.rowIndEMail;
366         ItemEMail *email = gtk_cmclist_get_row_data( clist, row );
367         edit_person_email_clear( NULL );
368         if( email ) {
369                 /* Remove list entry */
370                 gtk_cmclist_remove( clist, row );
371                 addritem_free_item_email( email );
372                 email = NULL;
373         }
374
375         /* Position hilite bar */
376         email = gtk_cmclist_get_row_data( clist, row );
377         if( ! email ) {
378                 personeditdlg.rowIndEMail = -1 + row;
379         }
380         if (!personeditdlg.read_only) {
381                 gtk_widget_set_sensitive(personeditdlg.email_del, gtk_cmclist_get_row_data(clist, 0) != NULL);
382                 gtk_widget_set_sensitive(personeditdlg.email_up, gtk_cmclist_get_row_data(clist, personeditdlg.rowIndEMail + 1) != NULL);
383                 gtk_widget_set_sensitive(personeditdlg.email_down, gtk_cmclist_get_row_data(clist, personeditdlg.rowIndEMail - 1) != NULL);
384         }
385         edit_person_status_show( NULL );
386 }
387
388 static ItemEMail *edit_person_email_edit( gboolean *error, ItemEMail *email ) {
389         ItemEMail *retVal = NULL;
390         gchar *sEmail, *sAlias, *sRemarks, *sEmail_;
391
392         *error = TRUE;
393         sEmail_ = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_email), 0, -1 );
394         sAlias = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_alias), 0, -1 );
395         sRemarks = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_remarks), 0, -1 );
396         sEmail = mgu_email_check_empty( sEmail_ );
397         g_free( sEmail_ );
398
399         if( sEmail ) {
400                 if( email == NULL ) {
401                         email = addritem_create_item_email();
402                 }
403                 addritem_email_set_address( email, sEmail );
404                 addritem_email_set_alias( email, sAlias );
405                 addritem_email_set_remarks( email, sRemarks );
406                 retVal = email;
407                 *error = FALSE;
408         }
409         else {
410                 edit_person_status_show( _( "An Email address must be supplied." ) );
411         }
412
413         g_free( sEmail );
414         g_free( sAlias );
415         g_free( sRemarks );
416
417         return retVal;
418 }
419
420 static void edit_person_email_modify( gpointer data ) {
421         gboolean errFlg = FALSE;
422         GtkCMCList *clist = GTK_CMCLIST(personeditdlg.clist_email);
423         gint row = personeditdlg.rowIndEMail;
424         ItemEMail *email = gtk_cmclist_get_row_data( clist, row );
425         if( email ) {
426                 edit_person_email_edit( &errFlg, email );
427                 if( ! errFlg ) {
428                         gtk_cmclist_set_text( clist, row, EMAIL_COL_EMAIL, email->address );
429                         gtk_cmclist_set_text( clist, row, EMAIL_COL_ALIAS, email->obj.name );
430                         gtk_cmclist_set_text( clist, row, EMAIL_COL_REMARKS, email->remarks );
431                         edit_person_email_clear( NULL );
432                 }
433         }
434 }
435
436 static void edit_person_email_add( gpointer data ) {
437         GtkCMCList *clist = GTK_CMCLIST(personeditdlg.clist_email);
438         gboolean errFlg = FALSE;
439         ItemEMail *email = NULL;
440         gint row = personeditdlg.rowIndEMail;
441         if( gtk_cmclist_get_row_data( clist, row ) == NULL ) row = 0;
442
443         email = edit_person_email_edit( &errFlg, NULL );
444         if( ! errFlg ) {
445                 gchar *text[ EMAIL_N_COLS ];
446                 text[ EMAIL_COL_EMAIL   ] = email->address;
447 #ifndef GENERIC_UMPC
448                 text[ EMAIL_COL_ALIAS   ] = email->obj.name;
449                 text[ EMAIL_COL_REMARKS ] = email->remarks;
450 #endif
451                 row = gtk_cmclist_insert( clist, 1 + row, text );
452                 gtk_cmclist_set_row_data( clist, row, email );
453                 gtk_cmclist_select_row( clist, row, 0 );
454                 edit_person_email_clear( NULL );
455         }
456 }
457
458 /*
459 * Comparison using cell contents (text in first column). Used for sort
460 * address index widget.
461 */
462 static gint edit_person_attrib_compare_func(
463         GtkCMCList *clist, gconstpointer ptr1, gconstpointer ptr2 )
464 {
465         GtkCMCell *cell1 = ((GtkCMCListRow *)ptr1)->cell;
466         GtkCMCell *cell2 = ((GtkCMCListRow *)ptr2)->cell;
467         gchar *name1 = NULL, *name2 = NULL;
468
469         if( cell1 ) name1 = cell1->u.text;
470         if( cell2 ) name2 = cell2->u.text;
471         if( ! name1 ) return ( name2 != NULL );
472         if( ! name2 ) return -1;
473         return g_utf8_collate( name1, name2 );
474 }
475
476 static gboolean list_find_attribute(const gchar *attr)
477 {
478         GtkCMCList *clist = GTK_CMCLIST(personeditdlg.clist_attrib);
479         UserAttribute *attrib;
480         gint row = 0;
481         while( (attrib = gtk_cmclist_get_row_data( clist, row )) ) {
482                 if (!g_ascii_strcasecmp(attrib->name, attr)) {
483                         gtk_cmclist_select_row(clist, row, 0);
484                         return TRUE;
485                 }
486                 row++;
487         }
488         return FALSE;
489 }
490
491 static gboolean list_find_email(const gchar *addr)
492 {
493         GtkCMCList *clist = GTK_CMCLIST(personeditdlg.clist_email);
494         ItemEMail *email;
495         gint row = 0;
496         while( (email = gtk_cmclist_get_row_data( clist, row )) ) {
497                 if (!g_ascii_strcasecmp(email->address, addr)) {
498                         gtk_cmclist_select_row(clist, row, 0);
499                         return TRUE;
500                 }
501                 row++;
502         }
503         return FALSE;
504 }
505
506 /*
507 * Load clist with a copy of person's email addresses.
508 */
509 static void edit_person_load_attrib( ItemPerson *person ) {
510         GList *node = person->listAttrib;
511         GtkCMCList *clist = GTK_CMCLIST(personeditdlg.clist_attrib);
512         gchar *text[ ATTRIB_N_COLS ];
513         while( node ) {
514                 UserAttribute *atorig = ( UserAttribute * ) node->data;
515                 UserAttribute *attrib = addritem_copy_attribute( atorig );
516                 gint row;
517                 debug_print("name: %s value: %s\n", attrib->name, attrib->value);
518                 text[ ATTRIB_COL_NAME  ] = attrib->name;
519                 text[ ATTRIB_COL_VALUE ] = attrib->value;
520
521                 row = gtk_cmclist_append( clist, text );
522                 gtk_cmclist_set_row_data( clist, row, attrib );
523                 node = g_list_next( node );
524         }
525 }
526
527 static void edit_person_attrib_list_selected( GtkCMCList *clist, gint row, gint column, GdkEvent *event, gpointer data ) {
528         UserAttribute *attrib = gtk_cmclist_get_row_data( clist, row );
529         if( attrib && !personeditdlg.read_only && !personeditdlg.ldap ) {
530                 gtk_entry_set_text( GTK_ENTRY(gtk_bin_get_child(GTK_BIN((personeditdlg.entry_atname))) ), attrib->name );
531                 gtk_entry_set_text( GTK_ENTRY(personeditdlg.entry_atvalue), attrib->value );
532                 gtk_widget_set_sensitive(personeditdlg.attrib_del, TRUE);
533         } else {
534                 gtk_widget_set_sensitive(personeditdlg.attrib_del, FALSE);
535         }
536         personeditdlg.rowIndAttrib = row;
537         edit_person_status_show( NULL );
538 }
539
540 static void edit_person_attrib_delete( gpointer data ) {
541         GtkCMCList *clist = GTK_CMCLIST(personeditdlg.clist_attrib);
542         gint row = personeditdlg.rowIndAttrib;
543         UserAttribute *attrib = gtk_cmclist_get_row_data( clist, row );
544         edit_person_attrib_clear( NULL );
545         if( attrib ) {
546                 /* Remove list entry */
547                 gtk_cmclist_remove( clist, row );
548                 addritem_free_attribute( attrib );
549                 attrib = NULL;
550         }
551
552         /* Position hilite bar */
553         attrib = gtk_cmclist_get_row_data( clist, row );
554         if( ! attrib ) {
555                 personeditdlg.rowIndAttrib = -1 + row;
556         } 
557         
558         if (!personeditdlg.read_only && !personeditdlg.ldap)
559                 gtk_widget_set_sensitive(personeditdlg.attrib_del, gtk_cmclist_get_row_data(clist, 0) != NULL);
560         
561         edit_person_status_show( NULL );
562 }
563
564 static UserAttribute *edit_person_attrib_edit( gboolean *error, UserAttribute *attrib ) {
565         UserAttribute *retVal = NULL;
566         gchar *sName, *sValue, *sName_, *sValue_;
567
568         *error = TRUE;
569         sName_ = gtk_editable_get_chars( GTK_EDITABLE(gtk_bin_get_child(GTK_BIN((personeditdlg.entry_atname)))), 0, -1 );
570         sValue_ = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_atvalue), 0, -1 );
571         sName = mgu_email_check_empty( sName_ );
572         sValue = mgu_email_check_empty( sValue_ );
573         g_free( sName_ );
574         g_free( sValue_ );
575
576         if( sName && sValue ) {
577                 if( attrib == NULL ) {
578                         attrib = addritem_create_attribute();
579                 }
580                 addritem_attrib_set_name( attrib, sName );
581                 addritem_attrib_set_value( attrib, sValue );
582                 retVal = attrib;
583                 *error = FALSE;
584         }
585         else {
586                 edit_person_status_show( _( "A Name and Value must be supplied." ) );
587         }
588
589         g_free( sName );
590         g_free( sValue );
591
592         return retVal;
593 }
594
595 static void edit_person_attrib_modify( gpointer data ) {
596         gboolean errFlg = FALSE;
597         GtkCMCList *clist = GTK_CMCLIST(personeditdlg.clist_attrib);
598         gint row = personeditdlg.rowIndAttrib;
599         UserAttribute *attrib = gtk_cmclist_get_row_data( clist, row );
600         if( attrib ) {
601                 edit_person_attrib_edit( &errFlg, attrib );
602                 if( ! errFlg ) {
603                         gtk_cmclist_set_text( clist, row, ATTRIB_COL_NAME, attrib->name );
604                         gtk_cmclist_set_text( clist, row, ATTRIB_COL_VALUE, attrib->value );
605                         edit_person_attrib_clear( NULL );
606                 }
607         }
608 }
609
610 static void edit_person_attrib_add( gpointer data ) {
611         GtkCMCList *clist = GTK_CMCLIST(personeditdlg.clist_attrib);
612         gboolean errFlg = FALSE;
613         UserAttribute *attrib = NULL;
614         gint row = personeditdlg.rowIndAttrib;
615         if( gtk_cmclist_get_row_data( clist, row ) == NULL ) row = 0;
616
617         attrib = edit_person_attrib_edit( &errFlg, NULL );
618         if( ! errFlg ) {
619                 gchar *text[ ATTRIB_N_COLS ];
620                 text[ ATTRIB_COL_NAME  ] = attrib->name;
621                 text[ ATTRIB_COL_VALUE ] = attrib->value;
622
623                 row = gtk_cmclist_insert( clist, 1 + row, text );
624                 gtk_cmclist_set_row_data( clist, row, attrib );
625                 gtk_cmclist_select_row( clist, row, 0 );
626                 edit_person_attrib_clear( NULL );
627         }
628 }
629
630 /*!
631  *\brief        Save Gtk object size to prefs dataset
632  */
633 static void edit_person_size_allocate_cb(GtkWidget *widget,
634                                          GtkAllocation *allocation)
635 {
636         cm_return_if_fail(allocation != NULL);
637
638         prefs_common.addressbookeditpersonwin_width = allocation->width;
639         prefs_common.addressbookeditpersonwin_height = allocation->height;
640 }
641
642 /* build edit person widgets, return a pointer to the main container of the widgetset (a vbox) */
643 static GtkWidget* addressbook_edit_person_widgets_create( GtkWidget* container, gboolean *cancelled )
644 {
645         GtkWidget *vbox;
646         GtkWidget *vnbox;
647         GtkWidget *notebook;
648         GtkWidget *hbbox;
649         GtkWidget *ok_btn;
650         GtkWidget *cancel_btn;
651
652         vbox = gtk_vbox_new(FALSE, 4);
653          gtk_container_set_border_width(GTK_CONTAINER(vbox), BORDER_WIDTH); 
654         gtk_widget_show(vbox);
655         gtk_container_add(GTK_CONTAINER(container), vbox);
656
657         vnbox = gtk_vbox_new(FALSE, 4);
658         gtk_container_set_border_width(GTK_CONTAINER(vnbox), 4);
659         gtk_widget_show(vnbox);
660         gtk_box_pack_start(GTK_BOX(vbox), vnbox, TRUE, TRUE, 0);
661
662         /* Notebook */
663         notebook = gtk_notebook_new();
664         gtk_widget_show(notebook);
665         gtk_box_pack_start(GTK_BOX(vnbox), notebook, TRUE, TRUE, 0);
666         gtk_container_set_border_width(GTK_CONTAINER(notebook), 6);
667
668         /* Button panel */
669         if (prefs_common.addressbook_use_editaddress_dialog)
670         gtkut_stock_button_set_create(&hbbox, &cancel_btn, GTK_STOCK_CANCEL,
671                                       &ok_btn, GTK_STOCK_OK,
672                                       NULL, NULL);
673         else
674                 gtkut_stock_with_text_button_set_create(&hbbox,
675                                           &cancel_btn, GTK_STOCK_CANCEL, _("Discard"),
676                                       &ok_btn, GTK_STOCK_OK, _("Apply"),
677                                       NULL, NULL, NULL);
678         gtk_box_pack_end(GTK_BOX(vnbox), hbbox, FALSE, FALSE, 0);
679         gtk_widget_grab_default(ok_btn);
680
681         g_signal_connect(G_OBJECT(ok_btn), "clicked",
682                          G_CALLBACK(edit_person_ok), cancelled);
683         g_signal_connect(G_OBJECT(cancel_btn), "clicked",
684                          G_CALLBACK(edit_person_cancel), cancelled);
685         g_signal_connect(G_OBJECT(notebook), "switch_page",
686                          G_CALLBACK(edit_person_switch_page), NULL );
687
688         gtk_widget_show_all(vbox);
689
690         personeditdlg.notebook   = notebook;
691         personeditdlg.ok_btn     = ok_btn;
692         personeditdlg.cancel_btn = cancel_btn;
693
694         return vbox;
695 }
696
697 static void addressbook_edit_person_dialog_create( gboolean *cancelled ) {
698         GtkWidget *window;
699         GtkWidget *hsbox;
700         GtkWidget *vbox;
701         GtkWidget *statusbar;
702         static GdkGeometry geometry;
703
704         window = gtkut_window_new(GTK_WINDOW_TOPLEVEL, "editaddress");
705         /* gtk_container_set_border_width(GTK_CONTAINER(window), 0); */
706         gtk_window_set_title(GTK_WINDOW(window), _("Edit Person Data"));
707         gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
708         gtk_window_set_modal(GTK_WINDOW(window), TRUE); 
709         g_signal_connect(G_OBJECT(window), "delete_event",
710                          G_CALLBACK(edit_person_delete_event),
711                          cancelled);
712         g_signal_connect(G_OBJECT(window), "size_allocate",
713                          G_CALLBACK(edit_person_size_allocate_cb),
714                         cancelled);
715         g_signal_connect(G_OBJECT(window), "key_press_event",
716                          G_CALLBACK(edit_person_key_pressed),
717                          cancelled);
718
719         vbox = addressbook_edit_person_widgets_create(window, cancelled);
720
721         /* Status line */
722         hsbox = gtk_hbox_new(FALSE, 0);
723         gtk_box_pack_end(GTK_BOX(vbox), hsbox, FALSE, FALSE, BORDER_WIDTH);
724         statusbar = gtk_statusbar_new();
725         gtk_box_pack_start(GTK_BOX(hsbox), statusbar, TRUE, TRUE, BORDER_WIDTH);
726
727         if (!geometry.min_height) {
728                 geometry.min_width = EDITPERSON_WIDTH;
729                 geometry.min_height = EDITPERSON_HEIGHT;
730         }
731
732         gtk_window_set_geometry_hints(GTK_WINDOW(window), NULL, &geometry,
733                                       GDK_HINT_MIN_SIZE);
734         gtk_widget_set_size_request(window, prefs_common.addressbookeditpersonwin_width,
735                                     prefs_common.addressbookeditpersonwin_height);
736
737         personeditdlg.container  = window;
738         personeditdlg.statusbar  = statusbar;
739         personeditdlg.status_cid = gtk_statusbar_get_context_id( GTK_STATUSBAR(statusbar), "Edit Person Dialog" );
740
741 }
742
743 /* parent must be a box */
744 static void addressbook_edit_person_widgetset_create( GtkWidget *parent, gboolean *cancelled )
745 {
746         GtkWidget *vbox;
747         GtkWidget *label;
748
749         if ( parent == NULL )
750                 g_warning("addressbook_edit_person_widgetset_create: parent is NULL");
751
752         vbox = gtk_vbox_new(FALSE, 0);
753         gtk_box_pack_end(GTK_BOX(parent), vbox, TRUE, TRUE, 0);
754
755         label = gtk_label_new(_("Edit Person Data"));
756         gtk_label_set_justify( GTK_LABEL(label), GTK_JUSTIFY_CENTER);
757         gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
758
759         addressbook_edit_person_widgets_create(vbox, cancelled);
760
761         gtk_widget_set_size_request(vbox, EDITPERSON_WIDTH, EDITPERSON_HEIGHT);
762
763         personeditdlg.container = vbox;
764         personeditdlg.title = label;
765         personeditdlg.statusbar  = NULL;
766         personeditdlg.status_cid = 0;
767 }
768
769 void addressbook_edit_person_widgetset_hide( void )
770 {
771         if ( personeditdlg.container )
772                 gtk_widget_hide( personeditdlg.container );
773 }
774
775 static void addressbook_edit_person_set_picture(void)
776 {
777         GError *error = NULL;
778         gchar *filename;
779         int width, height, scalewidth, scaleheight;
780
781         if (personeditdlg.ldap)
782                 return;
783
784         if ( (filename = filesel_select_file_open(_("Choose a picture"), NULL)) ) {
785                 GdkPixbuf *pixbuf = NULL;
786                 gdk_pixbuf_get_file_info(filename, &width, &height);
787
788                 if ( width > 128 || height > 128 ) {
789                         if (width > height) {
790                                 scaleheight = (height * 128) / width;
791                                 scalewidth = 128;
792                         }
793                         else {
794                                 scalewidth = (width * 128) / height;
795                                 scaleheight = 128;
796                         }
797                         pixbuf = gdk_pixbuf_new_from_file_at_scale(filename, 
798                                         scalewidth, scaleheight, TRUE, &error);
799                 } else {
800                         pixbuf = gdk_pixbuf_new_from_file(filename, &error);
801                 }
802                 if (error) {
803                         alertpanel_error(_("Failed to import image: \n%s"),
804                                         error->message);
805                         g_error_free(error);
806                         error = NULL;
807                         /* keep the previous picture if any */
808                         g_free(filename);
809                         if (pixbuf)
810                                 g_object_unref(pixbuf);
811                         return;
812                 }
813                 personeditdlg.picture_set = TRUE;
814                 cm_menu_set_sensitive("EditAddressPopup/UnsetPicture", personeditdlg.picture_set);
815                 g_free(filename);
816                 gtk_image_set_from_pixbuf(GTK_IMAGE(personeditdlg.image), pixbuf);
817                 g_object_unref(pixbuf);
818         }
819 }       
820
821 static void addressbook_edit_person_clear_picture(void)
822 {
823         GdkPixbuf *pixbuf;
824
825         stock_pixbuf_gdk(STOCK_PIXMAP_ANONYMOUS, &pixbuf);
826         personeditdlg.picture_set = FALSE;
827         cm_menu_set_sensitive("EditAddressPopup/UnsetPicture", personeditdlg.picture_set);
828         gtk_image_set_from_pixbuf(GTK_IMAGE(personeditdlg.image), pixbuf);
829 }
830
831 static void addressbook_edit_person_set_picture_menu_cb (GtkAction *action, gpointer data)
832 {
833         addressbook_edit_person_set_picture();
834 }
835
836 static void addressbook_edit_person_unset_picture_menu_cb (GtkAction *action, gpointer data)
837 {
838         addressbook_edit_person_clear_picture();
839 }
840
841 static GtkWidget *editaddr_popup_menu = NULL;
842 static GtkActionEntry editaddr_popup_entries[] =
843 {
844         {"EditAddressPopup",                    NULL, "EditAddressPopup" },
845         {"EditAddressPopup/SetPicture",         NULL, N_("_Set picture"), NULL, NULL, G_CALLBACK(addressbook_edit_person_set_picture_menu_cb) },
846         {"EditAddressPopup/UnsetPicture",       NULL, N_("_Unset picture"), NULL, NULL, G_CALLBACK(addressbook_edit_person_unset_picture_menu_cb) },
847 };
848
849 static void addressbook_edit_person_set_picture_cb(GtkWidget *widget, 
850                 GdkEventButton *event, gpointer data)
851 {       
852         if (event->button == 1) {
853                 addressbook_edit_person_set_picture();
854         } else {
855                 gtk_menu_popup(GTK_MENU(editaddr_popup_menu), 
856                                NULL, NULL, NULL, NULL, 
857                                event->button, event->time);
858         }
859 }
860
861 static gboolean addressbook_edit_person_picture_popup_menu(GtkWidget *widget, gpointer data)
862 {
863         GdkEventButton event;
864         
865         event.button = 3;
866         event.time = gtk_get_current_event_time();
867         
868         addressbook_edit_person_set_picture_cb(NULL, &event, data);
869
870         return TRUE;
871 }
872
873 static void addressbook_edit_person_page_basic( gint pageNum, gchar *pageLbl ) {
874         GtkWidget *vbox;
875         GtkWidget *hbox;
876         GtkWidget *table;
877         GtkWidget *label;
878         GtkWidget *ebox_picture;
879         GtkWidget *frame_picture;
880         GtkWidget *entry_name;
881         GtkWidget *entry_fn;
882         GtkWidget *entry_ln;
883         GtkWidget *entry_nn;
884         const gchar *locale;
885         gint top = 0;
886
887         vbox = gtk_vbox_new( FALSE, 20 );
888         hbox = gtk_hbox_new( FALSE, 8 );
889
890         gtk_widget_show( vbox );        
891
892         if (!editaddr_popup_menu) {
893                 cm_menu_create_action_group("EditAddressPopup", editaddr_popup_entries,
894                         G_N_ELEMENTS(editaddr_popup_entries), (gpointer)NULL);
895                 MENUITEM_ADDUI("/Menus", "EditAddressPopup", "EditAddressPopup", GTK_UI_MANAGER_MENU)
896                 MENUITEM_ADDUI("/Menus/EditAddressPopup", "SetPicture", "EditAddressPopup/SetPicture", GTK_UI_MANAGER_MENUITEM)
897                 MENUITEM_ADDUI("/Menus/EditAddressPopup", "UnsetPicture", "EditAddressPopup/UnsetPicture", GTK_UI_MANAGER_MENUITEM)
898
899                 editaddr_popup_menu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(
900                         gtk_ui_manager_get_widget(gtkut_ui_manager(), "/Menus/EditAddressPopup")) );
901         }
902         /* User's picture */
903         ebox_picture = gtk_event_box_new();
904         frame_picture = gtk_frame_new(_("Photo"));
905         
906         /* Room for a photo */
907         personeditdlg.image = gtk_image_new();
908         addressbook_edit_person_clear_picture();
909
910         gtk_container_add(GTK_CONTAINER(ebox_picture), personeditdlg.image);
911         gtk_container_add(GTK_CONTAINER(frame_picture), ebox_picture);  
912         gtk_container_add(GTK_CONTAINER( personeditdlg.notebook ), hbox );
913         gtk_container_set_border_width( GTK_CONTAINER (vbox), BORDER_WIDTH );
914         gtk_container_set_border_width( GTK_CONTAINER (hbox), BORDER_WIDTH );
915
916         label = gtk_label_new_with_mnemonic( pageLbl );
917         gtk_widget_show( label );
918         
919         gtk_box_pack_start(GTK_BOX(hbox), frame_picture, TRUE, TRUE, 0);
920         
921         gtk_notebook_set_tab_label(
922                 GTK_NOTEBOOK( personeditdlg.notebook ),
923                 gtk_notebook_get_nth_page( GTK_NOTEBOOK( personeditdlg.notebook ), pageNum ), label );
924         
925         g_signal_connect(G_OBJECT(ebox_picture), "popup-menu",
926                          G_CALLBACK(addressbook_edit_person_picture_popup_menu), NULL);
927         g_signal_connect(G_OBJECT(ebox_picture), "button_press_event", 
928                         G_CALLBACK(addressbook_edit_person_set_picture_cb), NULL);
929
930         table = gtk_table_new( 3, 3, FALSE);
931
932 #define ATTACH_ROW(text, entry) \
933 { \
934         label = gtk_label_new(text); \
935         gtk_table_attach(GTK_TABLE(table), label, 0, 1, top, (top + 1), \
936                          GTK_FILL, 0, 0, 0); \
937         gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); \
938  \
939         entry = gtk_entry_new(); \
940         gtk_table_attach(GTK_TABLE(table), entry, 1, 2, top, (top + 1), \
941                          GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0); \
942         top++; \
943 }
944
945 #define ATTACH_HIDDEN_ROW(text, entry) \
946 { \
947         entry = gtk_entry_new(); \
948 }
949
950 #ifndef GENERIC_UMPC
951         ATTACH_ROW(_("Display Name"), entry_name);
952 #else
953         ATTACH_HIDDEN_ROW(_("Display Name"), entry_name);
954 #endif
955         locale = conv_get_current_locale();
956         if (locale &&
957             (!g_ascii_strncasecmp(locale, "hu", 2) ||
958              !g_ascii_strncasecmp(locale, "ja", 2) ||
959              !g_ascii_strncasecmp(locale, "ko", 2) ||
960              !g_ascii_strncasecmp(locale, "vi", 2) ||
961              !g_ascii_strncasecmp(locale, "zh", 2))) {
962                 ATTACH_ROW(_("Last Name"), entry_ln);
963                 ATTACH_ROW(_("First Name"), entry_fn);
964         } else {
965                 ATTACH_ROW(_("First Name"), entry_fn);
966                 ATTACH_ROW(_("Last Name"), entry_ln);
967         }
968 #ifndef GENERIC_UMPC
969         ATTACH_ROW(_("Nickname"), entry_nn);
970 #else
971         ATTACH_HIDDEN_ROW(_("Nickname"), entry_nn);
972 #endif
973
974 #undef ATTACH_ROW
975 #undef ATTACH_HIDDEN_ROW
976         gtk_box_pack_start(GTK_BOX(vbox), table, TRUE, TRUE, 0);
977         gtk_box_pack_end(GTK_BOX(hbox), vbox, TRUE, TRUE, 0);
978         gtk_container_set_border_width( GTK_CONTAINER(table), 8 );
979         gtk_table_set_row_spacings(GTK_TABLE(table), 15);
980         gtk_table_set_col_spacings(GTK_TABLE(table), 8);
981
982         gtk_widget_show_all(vbox);
983         personeditdlg.entry_name  = entry_name;
984         personeditdlg.entry_first = entry_fn;
985         personeditdlg.entry_last  = entry_ln;
986         personeditdlg.entry_nick  = entry_nn;
987 }
988
989 static gboolean email_adding = FALSE, email_saving = FALSE;
990
991 static void edit_person_entry_email_changed (GtkWidget *entry, gpointer data)
992 {
993         gboolean non_empty = gtk_cmclist_get_row_data(GTK_CMCLIST(personeditdlg.clist_email), 0) != NULL;
994
995         if (personeditdlg.read_only)
996                 return;
997
998         if (gtk_entry_get_text(GTK_ENTRY(personeditdlg.entry_email)) == NULL
999         ||  strlen(gtk_entry_get_text(GTK_ENTRY(personeditdlg.entry_email))) == 0) {
1000                 gtk_widget_set_sensitive(personeditdlg.email_add,FALSE);
1001                 gtk_widget_set_sensitive(personeditdlg.email_mod,FALSE);
1002                 email_adding = FALSE;
1003                 email_saving = FALSE;
1004         } else if (list_find_email(gtk_entry_get_text(GTK_ENTRY(personeditdlg.entry_email)))) {
1005                 gtk_widget_set_sensitive(personeditdlg.email_add,FALSE);
1006                 gtk_widget_set_sensitive(personeditdlg.email_mod,non_empty);
1007                 email_adding = FALSE;
1008                 email_saving = non_empty;
1009         } else {
1010                 gtk_widget_set_sensitive(personeditdlg.email_add,TRUE);
1011                 gtk_widget_set_sensitive(personeditdlg.email_mod,non_empty);
1012                 email_adding = TRUE;
1013                 email_saving = non_empty;
1014         }
1015 }
1016
1017 static gboolean edit_person_entry_email_pressed(GtkWidget *widget, GdkEventKey *event, gpointer data)
1018 {
1019         if (event && event->keyval == GDK_KEY_Return) {
1020                 if (email_saving)
1021                         edit_person_email_modify(NULL);         
1022                 else if (email_adding)
1023                         edit_person_email_add(NULL);
1024         }
1025         return FALSE;
1026 }
1027
1028
1029 static void addressbook_edit_person_page_email( gint pageNum, gchar *pageLbl ) {
1030         GtkWidget *vbox;
1031         GtkWidget *hbox;
1032         GtkWidget *vboxl;
1033         GtkWidget *vboxb;
1034         GtkWidget *vbuttonbox;
1035         GtkWidget *buttonUp;
1036         GtkWidget *buttonDown;
1037         GtkWidget *buttonDel;
1038         GtkWidget *buttonMod;
1039         GtkWidget *buttonAdd;
1040
1041         GtkWidget *table;
1042         GtkWidget *label;
1043         GtkWidget *clist_swin;
1044         GtkWidget *clist;
1045         GtkWidget *entry_email;
1046         GtkWidget *entry_alias;
1047         GtkWidget *entry_remarks;
1048         gint top;
1049
1050         gchar *titles[ EMAIL_N_COLS ];
1051         gint i;
1052
1053         titles[ EMAIL_COL_EMAIL   ] = _("Email Address");
1054 #ifndef GENERIC_UMPC
1055         titles[ EMAIL_COL_ALIAS   ] = _("Alias");
1056         titles[ EMAIL_COL_REMARKS ] = _("Remarks");
1057 #endif
1058         vbox = gtk_vbox_new( FALSE, 8 );
1059         gtk_widget_show( vbox );
1060         gtk_container_add( GTK_CONTAINER( personeditdlg.notebook ), vbox );
1061         gtk_container_set_border_width( GTK_CONTAINER (vbox), BORDER_WIDTH );
1062
1063         label = gtk_label_new_with_mnemonic( pageLbl );
1064         gtk_widget_show( label );
1065         gtk_notebook_set_tab_label(
1066                 GTK_NOTEBOOK( personeditdlg.notebook ),
1067                 gtk_notebook_get_nth_page( GTK_NOTEBOOK( personeditdlg.notebook ), pageNum ), label );
1068
1069         /* Split into two areas */
1070         hbox = gtk_hbox_new( FALSE, 0 );
1071         gtk_container_add( GTK_CONTAINER( vbox ), hbox );
1072
1073         /* Address list */
1074         vboxl = gtk_vbox_new( FALSE, 4 );
1075         gtk_container_add( GTK_CONTAINER( hbox ), vboxl );
1076         gtk_container_set_border_width( GTK_CONTAINER(vboxl), 4 );
1077
1078         clist_swin = gtk_scrolled_window_new( NULL, NULL );
1079         gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(clist_swin),
1080                                        GTK_POLICY_AUTOMATIC,
1081                                        GTK_POLICY_AUTOMATIC);
1082
1083         clist = gtk_cmclist_new_with_titles( EMAIL_N_COLS, titles );
1084
1085         gtk_container_add( GTK_CONTAINER(clist_swin), clist );
1086         gtk_cmclist_set_selection_mode( GTK_CMCLIST(clist), GTK_SELECTION_BROWSE );
1087         gtk_cmclist_set_column_width( GTK_CMCLIST(clist), EMAIL_COL_EMAIL, EMAIL_COL_WIDTH_EMAIL );
1088         gtk_cmclist_set_column_width( GTK_CMCLIST(clist), EMAIL_COL_ALIAS, EMAIL_COL_WIDTH_ALIAS );
1089
1090         for( i = 0; i < EMAIL_N_COLS; i++ )
1091                 gtkut_widget_set_can_focus(GTK_CMCLIST(clist)->column[i].button, FALSE);
1092
1093         /* Data entry area */
1094         table = gtk_table_new( 4, 2, FALSE);
1095
1096 #ifndef GENERIC_UMPC
1097         gtk_container_add( GTK_CONTAINER(vboxl), clist_swin );
1098         gtk_box_pack_start(GTK_BOX(vboxl), table, FALSE, FALSE, 0);
1099 #else
1100         gtk_box_pack_start(GTK_BOX(vboxl), table, FALSE, FALSE, 0);
1101         gtk_container_add( GTK_CONTAINER(vboxl), clist_swin );
1102         gtk_cmclist_column_titles_hide(GTK_CMCLIST(clist));
1103 #endif
1104         gtk_container_set_border_width( GTK_CONTAINER(table), 4 );
1105         gtk_table_set_row_spacings(GTK_TABLE(table), 4);
1106         gtk_table_set_col_spacings(GTK_TABLE(table), 4);
1107
1108         entry_email = gtk_entry_new();
1109         entry_alias = gtk_entry_new();
1110         entry_remarks = gtk_entry_new();
1111
1112         /* First row */
1113         top = 0;
1114         label = gtk_label_new(_("Email Address"));
1115         gtk_table_attach(GTK_TABLE(table), label, 0, 1, top, (top + 1), GTK_FILL, 0, 0, 0);
1116         gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
1117
1118         gtk_table_attach(GTK_TABLE(table), entry_email, 1, 2, top, (top + 1), GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
1119
1120 #ifndef GENERIC_UMPC
1121         /* Next row */
1122         ++top;
1123         label = gtk_label_new(_("Alias"));
1124         gtk_table_attach(GTK_TABLE(table), label, 0, 1, top, (top + 1), GTK_FILL, 0, 0, 0);
1125         gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
1126
1127         gtk_table_attach(GTK_TABLE(table), entry_alias, 1, 2, top, (top + 1), GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
1128
1129         /* Next row */
1130         ++top;
1131         label = gtk_label_new(_("Remarks"));
1132         gtk_table_attach(GTK_TABLE(table), label, 0, 1, top, (top + 1), GTK_FILL, 0, 0, 0);
1133         gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
1134
1135         gtk_table_attach(GTK_TABLE(table), entry_remarks, 1, 2, top, (top + 1), GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
1136 #endif
1137
1138         /* Button box */
1139         vboxb = gtk_vbox_new( FALSE, 4 );
1140         gtk_box_pack_start(GTK_BOX(hbox), vboxb, FALSE, FALSE, 2);
1141
1142         vbuttonbox = gtk_vbutton_box_new();
1143         gtk_button_box_set_layout( GTK_BUTTON_BOX(vbuttonbox), GTK_BUTTONBOX_START );
1144         gtk_box_set_spacing( GTK_BOX(vbuttonbox), 8 );
1145         gtk_container_set_border_width( GTK_CONTAINER(vbuttonbox), 4 );
1146         gtk_container_add( GTK_CONTAINER(vboxb), vbuttonbox );
1147
1148         /* Buttons */
1149         buttonUp = gtk_button_new_from_stock(GTK_STOCK_GO_UP);
1150         buttonDown = gtk_button_new_from_stock(GTK_STOCK_GO_DOWN);
1151         buttonDel = gtk_button_new_from_stock(GTK_STOCK_DELETE);
1152         buttonMod = gtk_button_new_from_stock(GTK_STOCK_SAVE);
1153         buttonAdd = gtk_button_new_from_stock(GTK_STOCK_ADD);
1154         
1155
1156 #ifndef GENERIC_UMPC
1157         gtk_container_add( GTK_CONTAINER(vbuttonbox), buttonUp );
1158
1159         gtk_container_add( GTK_CONTAINER(vbuttonbox), buttonDown );
1160 #endif
1161         gtk_container_add( GTK_CONTAINER(vbuttonbox), buttonDel );
1162
1163         gtk_container_add( GTK_CONTAINER(vbuttonbox), buttonMod );
1164
1165         gtk_container_add( GTK_CONTAINER(vbuttonbox), buttonAdd );
1166
1167         gtk_widget_show_all(vbox);
1168
1169         /* Event handlers */
1170         g_signal_connect( G_OBJECT(clist), "select_row",
1171                           G_CALLBACK( edit_person_email_list_selected), NULL );
1172         g_signal_connect( G_OBJECT(buttonUp), "clicked",
1173                           G_CALLBACK( edit_person_email_move_up ), NULL );
1174         g_signal_connect( G_OBJECT(buttonDown), "clicked",
1175                           G_CALLBACK( edit_person_email_move_down ), NULL );
1176         g_signal_connect( G_OBJECT(buttonDel), "clicked",
1177                           G_CALLBACK( edit_person_email_delete ), NULL );
1178         g_signal_connect( G_OBJECT(buttonMod), "clicked",
1179                           G_CALLBACK( edit_person_email_modify ), NULL );
1180         g_signal_connect( G_OBJECT(buttonAdd), "clicked",
1181                           G_CALLBACK( edit_person_email_add ), NULL );
1182         g_signal_connect(G_OBJECT(entry_email), "changed",
1183                          G_CALLBACK(edit_person_entry_email_changed), NULL);
1184         g_signal_connect(G_OBJECT(entry_email), "key_press_event",
1185                          G_CALLBACK(edit_person_entry_email_pressed), NULL);
1186         g_signal_connect(G_OBJECT(entry_alias), "key_press_event",
1187                          G_CALLBACK(edit_person_entry_email_pressed), NULL);
1188         g_signal_connect(G_OBJECT(entry_remarks), "key_press_event",
1189                          G_CALLBACK(edit_person_entry_email_pressed), NULL);
1190
1191         personeditdlg.clist_email   = clist;
1192         personeditdlg.entry_email   = entry_email;
1193         personeditdlg.entry_alias   = entry_alias;
1194         personeditdlg.entry_remarks = entry_remarks;
1195         personeditdlg.email_up = buttonUp;
1196         personeditdlg.email_down = buttonDown;
1197         personeditdlg.email_del = buttonDel;
1198         personeditdlg.email_mod = buttonMod;
1199         personeditdlg.email_add = buttonAdd;
1200 }
1201
1202 static gboolean attrib_adding = FALSE, attrib_saving = FALSE;
1203
1204 static void edit_person_entry_att_changed (GtkWidget *entry, gpointer data)
1205 {
1206         gboolean non_empty = gtk_cmclist_get_row_data(GTK_CMCLIST(personeditdlg.clist_attrib), 0) != NULL;
1207         const gchar *atname;
1208
1209         if (personeditdlg.read_only || personeditdlg.ldap)
1210                 return;
1211
1212         atname = gtk_entry_get_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN((personeditdlg.entry_atname)))));
1213         if ( atname == NULL
1214         ||  strlen(atname) == 0) {
1215                 gtk_widget_set_sensitive(personeditdlg.attrib_add,FALSE);
1216                 gtk_widget_set_sensitive(personeditdlg.attrib_mod,FALSE);
1217                 attrib_adding = FALSE;
1218                 attrib_saving = FALSE;
1219         } else if (list_find_attribute(atname)) {
1220                 gtk_widget_set_sensitive(personeditdlg.attrib_add,FALSE);
1221                 gtk_widget_set_sensitive(personeditdlg.attrib_mod,non_empty);
1222                 attrib_adding = FALSE;
1223                 attrib_saving = non_empty;
1224         } else {
1225                 gtk_widget_set_sensitive(personeditdlg.attrib_add,TRUE);
1226                 gtk_widget_set_sensitive(personeditdlg.attrib_mod,non_empty);
1227                 attrib_adding = TRUE;
1228                 attrib_saving = non_empty;
1229         }
1230 }
1231
1232 static gboolean edit_person_entry_att_pressed(GtkWidget *widget, GdkEventKey *event, gpointer data)
1233 {
1234         if (event && event->keyval == GDK_KEY_Return) {
1235                 if (attrib_saving)
1236                         edit_person_attrib_modify(NULL);
1237                 else if (attrib_adding)
1238                         edit_person_attrib_add(NULL);
1239         }
1240         return FALSE;
1241 }
1242
1243 static void addressbook_edit_person_page_attrib( gint pageNum, gchar *pageLbl ) {
1244         GtkWidget *vbox;
1245         GtkWidget *hbox;
1246         GtkWidget *vboxl;
1247         GtkWidget *vboxb;
1248         GtkWidget *vbuttonbox;
1249         GtkWidget *buttonDel;
1250         GtkWidget *buttonMod;
1251         GtkWidget *buttonAdd;
1252
1253         GtkWidget *table;
1254         GtkWidget *label;
1255         GtkWidget *clist_swin;
1256         GtkWidget *clist;
1257         GtkWidget *entry_name;
1258         GtkWidget *entry_value;
1259         gint top;
1260
1261         gchar *titles[ ATTRIB_N_COLS ];
1262         gint i;
1263
1264         titles[ ATTRIB_COL_NAME  ] = _("Name");
1265         titles[ ATTRIB_COL_VALUE ] = _("Value");
1266
1267         vbox = gtk_vbox_new( FALSE, 8 );
1268         gtk_widget_show( vbox );
1269         gtk_container_add( GTK_CONTAINER( personeditdlg.notebook ), vbox );
1270         gtk_container_set_border_width( GTK_CONTAINER (vbox), BORDER_WIDTH );
1271
1272         label = gtk_label_new_with_mnemonic( pageLbl );
1273         gtk_widget_show( label );
1274         gtk_notebook_set_tab_label(
1275                 GTK_NOTEBOOK( personeditdlg.notebook ),
1276                 gtk_notebook_get_nth_page( GTK_NOTEBOOK( personeditdlg.notebook ), pageNum ), label );
1277
1278         /* Split into two areas */
1279         hbox = gtk_hbox_new( FALSE, 0 );
1280         gtk_container_add( GTK_CONTAINER( vbox ), hbox );
1281
1282         /* Attribute list */
1283         vboxl = gtk_vbox_new( FALSE, 4 );
1284         gtk_container_add( GTK_CONTAINER( hbox ), vboxl );
1285         gtk_container_set_border_width( GTK_CONTAINER(vboxl), 4 );
1286
1287         clist_swin = gtk_scrolled_window_new( NULL, NULL );
1288         gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(clist_swin),
1289                                        GTK_POLICY_AUTOMATIC,
1290                                        GTK_POLICY_AUTOMATIC);
1291
1292         clist = gtk_cmclist_new_with_titles( ATTRIB_N_COLS, titles );
1293         gtk_container_add( GTK_CONTAINER(clist_swin), clist );
1294         gtk_cmclist_set_selection_mode( GTK_CMCLIST(clist), GTK_SELECTION_BROWSE );
1295         gtk_cmclist_set_compare_func( GTK_CMCLIST(clist), edit_person_attrib_compare_func );
1296         gtk_cmclist_set_auto_sort( GTK_CMCLIST(clist), TRUE );
1297         gtk_cmclist_set_column_width( GTK_CMCLIST(clist), ATTRIB_COL_NAME, ATTRIB_COL_WIDTH_NAME );
1298         gtk_cmclist_set_column_width( GTK_CMCLIST(clist), ATTRIB_COL_VALUE, ATTRIB_COL_WIDTH_VALUE );
1299
1300         for( i = 0; i < ATTRIB_N_COLS; i++ )
1301                 gtkut_widget_set_can_focus(GTK_CMCLIST(clist)->column[i].button, FALSE);
1302
1303         /* Data entry area */
1304 #ifndef GENERIC_UMPC
1305         table = gtk_table_new( 4, 2, FALSE);
1306         gtk_container_add( GTK_CONTAINER(vboxl), clist_swin );
1307         gtk_box_pack_start(GTK_BOX(vboxl), table, FALSE, FALSE, 0);
1308 #else
1309         table = gtk_table_new( 2, 4, FALSE);
1310         gtk_box_pack_start(GTK_BOX(vboxl), table, FALSE, FALSE, 0);
1311         gtk_container_add( GTK_CONTAINER(vboxl), clist_swin );
1312         gtk_cmclist_column_titles_hide(GTK_CMCLIST(clist));
1313 #endif
1314         gtk_container_set_border_width( GTK_CONTAINER(table), 4 );
1315         gtk_table_set_row_spacings(GTK_TABLE(table), 4);
1316         gtk_table_set_col_spacings(GTK_TABLE(table), 4);
1317
1318         /* First row */
1319         top = 0;
1320 #ifndef GENERIC_UMPC
1321         label = gtk_label_new(_("Name"));
1322         gtk_table_attach(GTK_TABLE(table), label, 0, 1, top, (top + 1), GTK_FILL, 0, 0, 0);
1323         gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
1324
1325 #if !GTK_CHECK_VERSION(2, 24, 0)
1326         entry_name = gtk_combo_box_entry_new_text ();
1327 #else
1328         entry_name = gtk_combo_box_text_new_with_entry ();
1329 #endif
1330         gtk_table_attach(GTK_TABLE(table), entry_name, 1, 2, top, (top + 1), GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
1331
1332         /* Next row */
1333         ++top;
1334         label = gtk_label_new(_("Value"));
1335         gtk_table_attach(GTK_TABLE(table), label, 0, 1, top, (top + 1), GTK_FILL, 0, 0, 0);
1336         gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
1337
1338         entry_value = gtk_entry_new();
1339         gtk_table_attach(GTK_TABLE(table), entry_value, 1, 2, top, (top + 1), GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
1340 #else
1341         label = gtk_label_new(_("Name"));
1342         gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, GTK_FILL, 0, 0, 0);
1343         gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
1344
1345 #if !GTK_CHECK_VERSION(2, 24, 0)
1346         entry_name = gtk_combo_box_entry_new_text ();
1347 #else
1348         entry_name = gtk_combo_box_text_new_with_entry ();
1349 #endif
1350         gtk_table_attach(GTK_TABLE(table), entry_name, 1, 2, 0, 1, GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
1351
1352         /* Next row */
1353         ++top;
1354         label = gtk_label_new(_("Value"));
1355         gtk_table_attach(GTK_TABLE(table), label, 2, 3, 0, 1, GTK_FILL, 0, 0, 0);
1356         gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
1357
1358         entry_value = gtk_entry_new();
1359         gtk_table_attach(GTK_TABLE(table), entry_value, 3, 4, 0, 1, GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
1360 #endif
1361         gtk_combo_box_set_active(GTK_COMBO_BOX(entry_name), -1);
1362         if (prefs_common.addressbook_custom_attributes)
1363 #if !GTK_CHECK_VERSION(2, 24, 0)
1364                 combobox_set_popdown_strings(GTK_COMBO_BOX(entry_name),
1365                                 prefs_common.addressbook_custom_attributes);
1366 #else
1367                 combobox_set_popdown_strings(GTK_COMBO_BOX_TEXT(entry_name),
1368                                 prefs_common.addressbook_custom_attributes);            
1369 #endif
1370         /* Button box */
1371         vboxb = gtk_vbox_new( FALSE, 4 );
1372         gtk_box_pack_start(GTK_BOX(hbox), vboxb, FALSE, FALSE, 2);
1373
1374         vbuttonbox = gtk_vbutton_box_new();
1375         gtk_button_box_set_layout( GTK_BUTTON_BOX(vbuttonbox), GTK_BUTTONBOX_START );
1376         gtk_box_set_spacing( GTK_BOX(vbuttonbox), 8 );
1377         gtk_container_set_border_width( GTK_CONTAINER(vbuttonbox), 4 );
1378         gtk_container_add( GTK_CONTAINER(vboxb), vbuttonbox );
1379
1380         /* Buttons */
1381         buttonDel = gtk_button_new_from_stock(GTK_STOCK_DELETE);
1382         gtk_container_add( GTK_CONTAINER(vbuttonbox), buttonDel );
1383
1384         buttonMod = gtk_button_new_from_stock(GTK_STOCK_SAVE);
1385         gtk_container_add( GTK_CONTAINER(vbuttonbox), buttonMod );
1386
1387         buttonAdd = gtk_button_new_from_stock(GTK_STOCK_ADD);
1388         gtk_container_add( GTK_CONTAINER(vbuttonbox), buttonAdd );
1389         
1390         gtk_widget_set_sensitive(buttonDel,FALSE);
1391         gtk_widget_set_sensitive(buttonMod,FALSE);
1392         gtk_widget_set_sensitive(buttonAdd,FALSE);
1393
1394         gtk_widget_show_all(vbox);
1395
1396         /* Event handlers */
1397         g_signal_connect( G_OBJECT(clist), "select_row",
1398                           G_CALLBACK( edit_person_attrib_list_selected), NULL );
1399         g_signal_connect( G_OBJECT(buttonDel), "clicked",
1400                           G_CALLBACK( edit_person_attrib_delete ), NULL );
1401         g_signal_connect( G_OBJECT(buttonMod), "clicked",
1402                           G_CALLBACK( edit_person_attrib_modify ), NULL );
1403         g_signal_connect( G_OBJECT(buttonAdd), "clicked",
1404                           G_CALLBACK( edit_person_attrib_add ), NULL );
1405         g_signal_connect(G_OBJECT(entry_name), "changed",
1406                          G_CALLBACK(edit_person_entry_att_changed), NULL);
1407         g_signal_connect(G_OBJECT(entry_name), "key_press_event",
1408                          G_CALLBACK(edit_person_entry_att_pressed), NULL);
1409         g_signal_connect(G_OBJECT(entry_value), "key_press_event",
1410                          G_CALLBACK(edit_person_entry_att_pressed), NULL);
1411
1412         personeditdlg.clist_attrib  = clist;
1413         personeditdlg.entry_atname  = entry_name;
1414         personeditdlg.entry_atvalue = entry_value;
1415         personeditdlg.attrib_add = buttonAdd;
1416         personeditdlg.attrib_del = buttonDel;
1417         personeditdlg.attrib_mod = buttonMod;
1418 }
1419
1420 static void addressbook_edit_person_create( GtkWidget *parent, gboolean *cancelled ) {
1421         if (prefs_common.addressbook_use_editaddress_dialog)
1422                 addressbook_edit_person_dialog_create( cancelled );
1423         else
1424                 addressbook_edit_person_widgetset_create( parent, cancelled );
1425         addressbook_edit_person_page_basic( PAGE_BASIC, _( "_User Data" ) );
1426         addressbook_edit_person_page_email( PAGE_EMAIL, _( "_Email Addresses" ) );
1427 #ifdef USE_LDAP
1428         if (personeditdlg.ldap)
1429                 addressbook_edit_person_page_attrib_ldap(&personeditdlg, PAGE_ATTRIBUTES, _("O_ther Attributes"));
1430         else
1431 #endif
1432                 addressbook_edit_person_page_attrib( PAGE_ATTRIBUTES, _( "O_ther Attributes" ) );
1433         gtk_widget_show_all( personeditdlg.container );
1434 }
1435
1436 /*
1437 * Return list of email items.
1438 */
1439 static GList *edit_person_build_email_list() {
1440         GtkCMCList *clist = GTK_CMCLIST(personeditdlg.clist_email);
1441         GList *listEMail = NULL;
1442         ItemEMail *email;
1443         gint row = 0;
1444         while( (email = gtk_cmclist_get_row_data( clist, row )) ) {
1445                 listEMail = g_list_append( listEMail, email );
1446                 row++;
1447         }
1448         return listEMail;
1449 }
1450
1451 /*
1452 * Return list of attributes.
1453 */
1454 static GList *edit_person_build_attrib_list() {
1455         GtkCMCList *clist = GTK_CMCLIST(personeditdlg.clist_attrib);
1456         GList *listAttrib = NULL;
1457         UserAttribute *attrib;
1458         gint row = 0;
1459         while( (attrib = gtk_cmclist_get_row_data( clist, row )) ) {
1460                 listAttrib = g_list_append( listAttrib, attrib );
1461                 row++;
1462         }
1463         return listAttrib;
1464 }
1465
1466 static void update_sensitivity(void)
1467 {
1468         gtk_widget_set_sensitive(personeditdlg.entry_name,    !personeditdlg.read_only);
1469         gtk_widget_set_sensitive(personeditdlg.entry_first,   !personeditdlg.read_only);
1470         gtk_widget_set_sensitive(personeditdlg.entry_last,    !personeditdlg.read_only);
1471         gtk_widget_set_sensitive(personeditdlg.entry_nick,    !personeditdlg.read_only && !personeditdlg.ldap);
1472         gtk_widget_set_sensitive(personeditdlg.entry_email,   !personeditdlg.read_only);
1473         gtk_widget_set_sensitive(personeditdlg.entry_alias,   !personeditdlg.read_only && !personeditdlg.ldap);
1474         gtk_widget_set_sensitive(personeditdlg.entry_remarks, !personeditdlg.read_only && !personeditdlg.ldap);
1475         gtk_widget_set_sensitive(personeditdlg.email_up,      !personeditdlg.read_only);
1476         gtk_widget_set_sensitive(personeditdlg.email_down,    !personeditdlg.read_only);
1477         gtk_widget_set_sensitive(personeditdlg.email_del,     !personeditdlg.read_only);
1478         gtk_widget_set_sensitive(personeditdlg.email_mod,     !personeditdlg.read_only);
1479         gtk_widget_set_sensitive(personeditdlg.email_add,     !personeditdlg.read_only);
1480         gtk_widget_set_sensitive(personeditdlg.entry_atname,  !personeditdlg.read_only);
1481         gtk_widget_set_sensitive(personeditdlg.entry_atvalue, !personeditdlg.read_only);
1482         gtk_widget_set_sensitive(personeditdlg.attrib_add,    !personeditdlg.read_only);
1483         gtk_widget_set_sensitive(personeditdlg.attrib_del,    !personeditdlg.read_only);
1484         gtk_widget_set_sensitive(personeditdlg.attrib_mod,    !personeditdlg.read_only);
1485 }
1486
1487 static void addressbook_edit_person_flush_transient( void )
1488 {
1489         ItemPerson *person = current_person;
1490         EditAddressPostUpdateCallback callback = edit_person_close_post_update_cb;
1491
1492         /* reset transient data */
1493         current_abf = NULL;
1494         current_person = NULL;
1495         current_parent_folder = NULL;
1496         edit_person_close_post_update_cb = NULL;
1497
1498         /* post action to perform on addressbook side */
1499         if (callback)
1500                 callback( person );
1501 }
1502
1503 void addressbook_edit_person_invalidate( AddressBookFile *abf, ItemFolder *parent_folder,
1504                                                                                  ItemPerson *person )
1505 {
1506         if (current_abf == NULL &&
1507                 current_person == NULL &&
1508                 current_parent_folder == NULL)
1509                 /* edit address form is already hidden */
1510                 return;
1511
1512         /* unconditional invalidation or invalidating the currently edited item */
1513         if ( ( abf == NULL && person == NULL && parent_folder == NULL )
1514                 || (current_abf == abf ||
1515                         current_person == person ||
1516                         current_parent_folder == parent_folder))
1517                 addressbook_edit_person_close( TRUE );
1518 }
1519
1520 static gboolean addressbook_edit_person_close( gboolean cancelled )
1521 {
1522         GList *listEMail = NULL;
1523         GList *listAttrib = NULL;
1524         GError *error = NULL;
1525
1526         listEMail = edit_person_build_email_list();
1527         listAttrib = edit_person_build_attrib_list();
1528         if( cancelled ) {
1529                 addritem_free_list_email( listEMail );
1530                 addritem_free_list_attribute( listAttrib );
1531                 gtk_cmclist_clear( GTK_CMCLIST(personeditdlg.clist_email) );
1532                 gtk_cmclist_clear( GTK_CMCLIST(personeditdlg.clist_attrib) );
1533
1534                 if (!prefs_common.addressbook_use_editaddress_dialog)
1535                         gtk_widget_hide( personeditdlg.container );
1536
1537                 /* no callback, as we're discarding the form */
1538                 edit_person_close_post_update_cb = NULL;
1539                 addressbook_edit_person_flush_transient();
1540                 current_person = NULL;
1541
1542                 /* set focus to the address list (this is done by the post_update_cb usually) */
1543                 addressbook_address_list_set_focus();
1544                 return FALSE;
1545         }
1546
1547         if( current_person && current_abf ) {
1548                 /* Update email/attribute list for existing current_person */
1549                 addrbook_update_address_list( current_abf, current_person, listEMail );
1550                 addrbook_update_attrib_list( current_abf, current_person, listAttrib );
1551         }
1552         else {
1553                 /* Create new current_person and email/attribute list */
1554                 if( ! cancelled && current_abf ) {
1555                         current_person = addrbook_add_address_list( current_abf, current_parent_folder, listEMail );
1556                         addrbook_add_attrib_list( current_abf, current_person, listAttrib );
1557                 }
1558         }
1559         listEMail = NULL;
1560         listAttrib = NULL;
1561
1562         if(!cancelled && current_person != NULL) {
1563                 /* Set current_person stuff */          
1564
1565                 gchar *name;
1566                 gchar *cn = edit_person_get_common_name_from_widgets();
1567
1568                 addritem_person_set_common_name( current_person, cn );
1569                 g_free( cn );
1570
1571                 if (personeditdlg.picture_set) { 
1572                         GdkPixbuf * pixbuf = gtk_image_get_pixbuf(GTK_IMAGE(personeditdlg.image));
1573
1574                         if (!current_person->picture)
1575                                 name = g_strconcat( get_rc_dir(), G_DIR_SEPARATOR_S, ADDRBOOK_DIR, G_DIR_SEPARATOR_S, 
1576                                                 ADDRITEM_ID(current_person), ".png", NULL );
1577                         else 
1578                                 name = g_strconcat( get_rc_dir(), G_DIR_SEPARATOR_S, ADDRBOOK_DIR, G_DIR_SEPARATOR_S, 
1579                                                 current_person->picture, ".png", NULL );
1580
1581                         gdk_pixbuf_save(pixbuf, name, "png", &error, NULL);
1582                         if (error) {
1583                                 alertpanel_error(_("Failed to save image: \n%s"),
1584                                                 error->message);
1585                                 g_error_free(error);
1586                         } else {
1587                                 debug_print("saved picture to %s\n", name);
1588                         }
1589                         if (!current_person->picture)
1590                                 addritem_person_set_picture( current_person, ADDRITEM_ID(current_person) ) ;
1591                         g_free( name );
1592                 } else {
1593                         if (!current_person->picture)
1594                                 name = g_strconcat( get_rc_dir(), G_DIR_SEPARATOR_S, ADDRBOOK_DIR, G_DIR_SEPARATOR_S, 
1595                                                 ADDRITEM_ID(current_person), ".png", NULL );
1596                         else 
1597                                 name = g_strconcat( get_rc_dir(), G_DIR_SEPARATOR_S, ADDRBOOK_DIR, G_DIR_SEPARATOR_S, 
1598                                                 current_person->picture, ".png", NULL );
1599                         claws_unlink(name);
1600                         g_free(name);
1601                 }
1602                 name = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_first), 0, -1 );
1603                 addritem_person_set_first_name( current_person, name );
1604                 g_free( name );
1605                 name = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_last), 0, -1 );
1606                 addritem_person_set_last_name( current_person, name );
1607                 g_free( name );
1608                 name = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_nick), 0, -1 );
1609                 addritem_person_set_nick_name( current_person, name );
1610                 g_free( name );
1611         }
1612
1613         gtk_cmclist_clear( GTK_CMCLIST(personeditdlg.clist_email) );
1614         gtk_cmclist_clear( GTK_CMCLIST(personeditdlg.clist_attrib) );
1615
1616         if (!prefs_common.addressbook_use_editaddress_dialog)
1617                 gtk_widget_hide( personeditdlg.container );
1618
1619         addressbook_edit_person_flush_transient();
1620
1621         return TRUE;
1622 }
1623  
1624 /*
1625 * Edit person.
1626 * Enter: abf    Address book.
1627 *        parent Parent folder for person (or NULL if adding to root folder). Argument is
1628 *               only required for new objects).
1629 *        person Person to edit, or NULL for a new person object.
1630 *        pgMail If TRUE, E-Mail page will be activated.
1631 * Return: Edited object, or NULL if cancelled.*/
1632 ItemPerson *addressbook_edit_person( AddressBookFile *abf, ItemFolder *parent_folder, ItemPerson *person,
1633                                                                          gboolean pgMail, GtkWidget *parent_container,
1634                                                                          void (*post_update_cb) (ItemPerson *person),
1635                                                                          gboolean get_focus) {
1636         static gboolean cancelled;
1637         GError *error = NULL;
1638         GdkPixbuf *pixbuf = NULL;
1639         /* set transient data */
1640         current_abf = abf;
1641         current_person = person;
1642         current_parent_folder = parent_folder;
1643         edit_person_close_post_update_cb = post_update_cb;
1644         personeditdlg.ldap = (abf && abf->type == ADBOOKTYPE_LDAP)? TRUE : FALSE;
1645
1646         if( personeditdlg.container ) {
1647                 gtk_widget_destroy(personeditdlg.container);
1648                 personeditdlg.container = NULL;
1649         }
1650         addressbook_edit_person_create(parent_container, &cancelled);
1651
1652         /* typically, get focus when dialog mode is enabled, or when editing a new address */
1653         if( get_focus ) {
1654                 gtk_widget_grab_focus(personeditdlg.ok_btn);
1655                 gtk_widget_grab_focus(personeditdlg.entry_name);
1656         }
1657         
1658         personeditdlg.read_only = (current_abf == NULL);
1659         update_sensitivity();
1660
1661         gtk_widget_show(personeditdlg.container);
1662         if (prefs_common.addressbook_use_editaddress_dialog)
1663                 manage_window_set_transient(GTK_WINDOW(personeditdlg.container));
1664         else
1665                 if (get_focus)
1666                         addressbook_address_list_disable_some_actions();
1667
1668         /* Clear all fields */
1669         personeditdlg.rowIndEMail = -1;
1670         personeditdlg.rowIndAttrib = -1;
1671         edit_person_status_show( "" );
1672         gtk_cmclist_clear( GTK_CMCLIST(personeditdlg.clist_email) );
1673         gtk_cmclist_clear( GTK_CMCLIST(personeditdlg.clist_attrib) );
1674         gtk_entry_set_text(GTK_ENTRY(personeditdlg.entry_name), "" );
1675         gtk_entry_set_text(GTK_ENTRY(personeditdlg.entry_first), "" );
1676         gtk_entry_set_text(GTK_ENTRY(personeditdlg.entry_last), "" );
1677         gtk_entry_set_text(GTK_ENTRY(personeditdlg.entry_nick), "" );
1678
1679         personeditdlg.editNew = FALSE;
1680         if( current_person ) {
1681                 gchar *filename = NULL;
1682
1683                 if( ADDRITEM_NAME(current_person) )
1684                         gtk_entry_set_text(GTK_ENTRY(personeditdlg.entry_name), ADDRITEM_NAME(person) );
1685
1686                 cm_menu_set_sensitive("EditAddressPopup/SetPicture", !personeditdlg.ldap);
1687                 cm_menu_set_sensitive("EditAddressPopup/UnsetPicture", !personeditdlg.ldap);
1688                 if( current_person->picture ) { 
1689                         filename = g_strconcat( get_rc_dir(), G_DIR_SEPARATOR_S, ADDRBOOK_DIR, G_DIR_SEPARATOR_S, 
1690                                                         current_person->picture, ".png", NULL );
1691                         if (is_file_exist(filename)) {
1692                                 pixbuf = gdk_pixbuf_new_from_file(filename, &error);
1693                                 if (error) {
1694                                         debug_print("Failed to import image: %s\n",
1695                                                         error->message);
1696                                         g_error_free(error);
1697                                         goto no_img;
1698                                 }
1699                                 personeditdlg.picture_set = TRUE;
1700                                 cm_menu_set_sensitive("EditAddressPopup/UnsetPicture", !personeditdlg.ldap && personeditdlg.picture_set);
1701                         } else {
1702                                 goto no_img;
1703                         }
1704                         gtk_image_set_from_pixbuf(GTK_IMAGE(personeditdlg.image), pixbuf);
1705                 } else {
1706 no_img:
1707                         addressbook_edit_person_clear_picture();
1708                 }
1709                 
1710                 g_free(filename);
1711                 if (pixbuf) {
1712                         g_object_unref(pixbuf);
1713                         pixbuf = NULL;
1714                 }
1715
1716                 if( current_person->firstName )
1717                         gtk_entry_set_text(GTK_ENTRY(personeditdlg.entry_first), current_person->firstName );
1718                 if( current_person->lastName )
1719                         gtk_entry_set_text(GTK_ENTRY(personeditdlg.entry_last), current_person->lastName );
1720                 if( current_person->nickName )
1721                         gtk_entry_set_text(GTK_ENTRY(personeditdlg.entry_nick), current_person->nickName );
1722                 edit_person_load_email( current_person );
1723                 edit_person_load_attrib( current_person );
1724                 gtk_entry_set_text(GTK_ENTRY(personeditdlg.entry_atvalue), "");
1725         }
1726         else {
1727                 personeditdlg.editNew = TRUE;
1728         }
1729
1730         /* Select appropriate start page */
1731         if( pgMail ) {
1732                 gtk_notebook_set_current_page( GTK_NOTEBOOK(personeditdlg.notebook), PAGE_EMAIL );
1733         }
1734         else {
1735                 gtk_notebook_set_current_page( GTK_NOTEBOOK(personeditdlg.notebook), PAGE_BASIC );
1736         }
1737
1738         gtk_cmclist_select_row( GTK_CMCLIST(personeditdlg.clist_email), 0, 0 );
1739         gtk_cmclist_select_row( GTK_CMCLIST(personeditdlg.clist_attrib), 0, 0 );
1740         edit_person_email_clear( NULL );
1741         if (current_person)
1742                 edit_person_email_list_selected(GTK_CMCLIST(personeditdlg.clist_email), 0, 0, NULL, NULL);
1743
1744         edit_person_attrib_clear( NULL );
1745
1746         if (prefs_common.addressbook_use_editaddress_dialog) {
1747                 gtk_main();
1748                 gtk_widget_hide( personeditdlg.container );
1749
1750                 if (!addressbook_edit_person_close( cancelled )) {
1751                         return NULL;
1752                 }
1753         }
1754         
1755         return person;
1756 }
1757
1758 void addressbook_edit_reload_attr_list( void )
1759 {
1760         if (personeditdlg.entry_atname) {
1761 #if !GTK_CHECK_VERSION(2, 24, 0)
1762                 combobox_unset_popdown_strings(GTK_COMBO_BOX(personeditdlg.entry_atname));
1763 #else           
1764                 combobox_unset_popdown_strings(GTK_COMBO_BOX_TEXT(personeditdlg.entry_atname));
1765 #endif
1766                 if (prefs_common.addressbook_custom_attributes)
1767 #if !GTK_CHECK_VERSION(2, 24, 0)
1768                         combobox_set_popdown_strings(GTK_COMBO_BOX(personeditdlg.entry_atname),
1769                                         prefs_common.addressbook_custom_attributes);
1770 #else           
1771                         combobox_set_popdown_strings(GTK_COMBO_BOX_TEXT(personeditdlg.entry_atname),
1772                                         prefs_common.addressbook_custom_attributes);
1773 #endif
1774         }
1775 }
1776
1777 /*
1778 * End of Source.
1779 */
1780