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