2005-12-05 [colin] 1.9.100cvs67
[claws.git] / src / editaddress.c
1 /*
2  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3  * Copyright (C) 1999-2003 Hiroyuki Yamamoto
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 2 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, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #  include "config.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/gtkwindow.h>
30 #include <gtk/gtksignal.h>
31 #include <gtk/gtklabel.h>
32 #include <gtk/gtkvbox.h>
33 #include <gtk/gtkentry.h>
34 #include <gtk/gtktable.h>
35
36 #include "mgutils.h"
37 #include "addressbook.h"
38 #include "addressitem.h"
39 #include "addritem.h"
40 #include "addrbook.h"
41 #include "manage_window.h"
42 #include "gtkutils.h"
43 #include "codeconv.h"
44
45 #include "prefs_common.h"
46
47 static struct _PersonEdit_dlg {
48         GtkWidget *window;
49         GtkWidget *notebook;
50         GtkWidget *ok_btn;
51         GtkWidget *cancel_btn;
52         GtkWidget *statusbar;
53         gint status_cid;
54
55         /* User data tab */
56         GtkWidget *entry_name;
57         GtkWidget *entry_first;
58         GtkWidget *entry_last;
59         GtkWidget *entry_nick;
60
61         /* EMail data tab */
62         GtkWidget *entry_email;
63         GtkWidget *entry_alias;
64         GtkWidget *entry_remarks;
65         GtkWidget *clist_email;
66         GtkWidget *email_up;
67         GtkWidget *email_down;
68         GtkWidget *email_del;
69         GtkWidget *email_mod;
70         GtkWidget *email_add;
71
72         /* Attribute data tab */
73         GtkWidget *entry_atname;
74         GtkWidget *entry_atvalue;
75         GtkWidget *clist_attrib;
76         GtkWidget *attrib_add;
77         GtkWidget *attrib_del;
78         GtkWidget *attrib_mod;
79
80         gint rowIndEMail;
81         gint rowIndAttrib;
82         gboolean editNew;
83         gboolean read_only;
84
85 } personeditdlg;
86
87 typedef enum {
88         EMAIL_COL_EMAIL   = 0,
89         EMAIL_COL_ALIAS   = 1,
90         EMAIL_COL_REMARKS = 2
91 } PersonEditEMailColumnPos;
92
93 typedef enum {
94         ATTRIB_COL_NAME    = 0,
95         ATTRIB_COL_VALUE   = 1
96 } PersonEditAttribColumnPos;
97
98 #define EDITPERSON_WIDTH      520
99 #define EDITPERSON_HEIGHT     340
100
101 #define EMAIL_N_COLS          3
102 #define EMAIL_COL_WIDTH_EMAIL 180
103 #define EMAIL_COL_WIDTH_ALIAS 80
104
105 #define ATTRIB_N_COLS          2
106 #define ATTRIB_COL_WIDTH_NAME  120
107 #define ATTRIB_COL_WIDTH_VALUE 180
108
109 #define PAGE_BASIC             0
110 #define PAGE_EMAIL             1
111 #define PAGE_ATTRIBUTES        2
112
113 static void edit_person_status_show( gchar *msg ) {
114         if( personeditdlg.statusbar != NULL ) {
115                 gtk_statusbar_pop( GTK_STATUSBAR(personeditdlg.statusbar), personeditdlg.status_cid );
116                 if( msg ) {
117                         gtk_statusbar_push( GTK_STATUSBAR(personeditdlg.statusbar), personeditdlg.status_cid, msg );
118                 }
119         }
120 }
121
122 static void edit_person_ok(GtkWidget *widget, gboolean *cancelled) {
123         *cancelled = FALSE;
124         gtk_main_quit();
125 }
126
127 static void edit_person_cancel(GtkWidget *widget, gboolean *cancelled) {
128         *cancelled = TRUE;
129         gtk_main_quit();
130 }
131
132 static gint edit_person_delete_event(GtkWidget *widget, GdkEventAny *event, gboolean *cancelled) {
133         *cancelled = TRUE;
134         gtk_main_quit();
135         return TRUE;
136 }
137
138 static gboolean edit_person_key_pressed(GtkWidget *widget, GdkEventKey *event, gboolean *cancelled) {
139         if (event && event->keyval == GDK_Escape) {
140                 *cancelled = TRUE;
141                 gtk_main_quit();
142         }
143         return FALSE;
144 }
145
146 static gchar *_title_new_ = NULL;
147 static gchar *_title_edit_ = NULL;
148
149 static void edit_person_set_window_title( gint pageNum ) {
150         gchar *sTitle;
151
152         if( _title_new_ == NULL ) {
153                 _title_new_ = g_strdup( _("Add New Person") );
154                 _title_edit_ = g_strdup( _("Edit Person Details") );
155         }
156
157         if( pageNum == PAGE_BASIC ) {
158                 if( personeditdlg.editNew ) {
159                         gtk_window_set_title( GTK_WINDOW(personeditdlg.window), _title_new_ );
160                 }
161                 else {
162                         gtk_window_set_title( GTK_WINDOW(personeditdlg.window), _title_edit_ );
163                 }
164         }
165         else {
166                 if( personeditdlg.entry_name == NULL ) {
167                         sTitle = g_strdup( _title_edit_ );
168                 }
169                 else {
170                         gchar *name;
171                         name = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_name), 0, -1 );
172                         sTitle = g_strdup_printf( "%s - %s", _title_edit_, name );
173                         g_free( name );
174                 }
175                 gtk_window_set_title( GTK_WINDOW(personeditdlg.window), sTitle );
176                 g_free( sTitle );
177         }
178 }
179
180 static void edit_person_email_clear( gpointer data ) {
181         gtk_entry_set_text( GTK_ENTRY(personeditdlg.entry_email), "" );
182         gtk_entry_set_text( GTK_ENTRY(personeditdlg.entry_alias), "" );
183         gtk_entry_set_text( GTK_ENTRY(personeditdlg.entry_remarks), "" );
184 }
185
186 static void edit_person_attrib_clear( gpointer data ) {
187         gtk_entry_set_text( GTK_ENTRY(personeditdlg.entry_atname), "" );
188         gtk_entry_set_text( GTK_ENTRY(personeditdlg.entry_atvalue), "" );
189 }
190
191 static void edit_person_switch_page( GtkNotebook *notebook, GtkNotebookPage *page,
192                                         gint pageNum, gpointer user_data)
193 {
194         edit_person_set_window_title( pageNum );
195         edit_person_status_show( "" );
196 }
197
198 /*
199 * Load clist with a copy of person's email addresses.
200 */
201 static void edit_person_load_email( ItemPerson *person ) {
202         GList *node = person->listEMail;
203         GtkCList *clist = GTK_CLIST(personeditdlg.clist_email);
204         gchar *text[ EMAIL_N_COLS ];
205         while( node ) {
206                 ItemEMail *emorig = ( ItemEMail * ) node->data;
207                 ItemEMail *email = addritem_copyfull_item_email( emorig );
208                 gint row;
209                 text[ EMAIL_COL_EMAIL   ] = email->address;
210                 text[ EMAIL_COL_ALIAS   ] = email->obj.name;
211                 text[ EMAIL_COL_REMARKS ] = email->remarks;
212
213                 row = gtk_clist_append( clist, text );
214                 gtk_clist_set_row_data( clist, row, email );
215                 node = g_list_next( node );
216         }
217 }
218
219 static void edit_person_email_list_selected( GtkCList *clist, gint row, gint column, GdkEvent *event, gpointer data ) {
220         ItemEMail *email = gtk_clist_get_row_data( clist, row );
221         if( email ) {
222                 if( email->address )
223                         gtk_entry_set_text( GTK_ENTRY(personeditdlg.entry_email), email->address );
224                 if( ADDRITEM_NAME(email) )
225                         gtk_entry_set_text( GTK_ENTRY(personeditdlg.entry_alias), ADDRITEM_NAME(email) );
226                 if( email->remarks )
227                         gtk_entry_set_text( GTK_ENTRY(personeditdlg.entry_remarks), email->remarks );
228                 if (!personeditdlg.read_only) {
229                         gtk_widget_set_sensitive(personeditdlg.email_del, TRUE);
230                         gtk_widget_set_sensitive(personeditdlg.email_up, row > 0);
231                         gtk_widget_set_sensitive(personeditdlg.email_down, gtk_clist_get_row_data(clist, row + 1) != NULL);
232                 }
233         } else {
234                 gtk_widget_set_sensitive(personeditdlg.email_del, FALSE);
235                 gtk_widget_set_sensitive(personeditdlg.email_up, FALSE);
236                 gtk_widget_set_sensitive(personeditdlg.email_down, FALSE);
237         }
238         personeditdlg.rowIndEMail = row;
239         edit_person_status_show( NULL );
240 }
241
242 static void edit_person_email_move( gint dir ) {
243         GtkCList *clist = GTK_CLIST(personeditdlg.clist_email);
244         gint row = personeditdlg.rowIndEMail + dir;
245         ItemEMail *email = gtk_clist_get_row_data( clist, row );
246         if( email ) {
247                 gtk_clist_row_move( clist, personeditdlg.rowIndEMail, row );
248                 personeditdlg.rowIndEMail = row;
249                 if (!personeditdlg.read_only) {
250                         gtk_widget_set_sensitive(personeditdlg.email_up, row > 0);
251                         gtk_widget_set_sensitive(personeditdlg.email_down, gtk_clist_get_row_data(clist, row + 1) != NULL);
252                 }
253         } else {
254                 gtk_widget_set_sensitive(personeditdlg.email_up, FALSE);
255                 gtk_widget_set_sensitive(personeditdlg.email_down, FALSE);
256         }
257         edit_person_email_clear( NULL );
258         edit_person_status_show( NULL );
259 }
260
261 static void edit_person_email_move_up( gpointer data ) {
262         edit_person_email_move( -1 );
263 }
264
265 static void edit_person_email_move_down( gpointer data ) {
266         edit_person_email_move( +1 );
267 }
268
269 static void edit_person_email_delete( gpointer data ) {
270         GtkCList *clist = GTK_CLIST(personeditdlg.clist_email);
271         gint row = personeditdlg.rowIndEMail;
272         ItemEMail *email = gtk_clist_get_row_data( clist, row );
273         edit_person_email_clear( NULL );
274         if( email ) {
275                 /* Remove list entry */
276                 gtk_clist_remove( clist, row );
277                 addritem_free_item_email( email );
278                 email = NULL;
279         }
280
281         /* Position hilite bar */
282         email = gtk_clist_get_row_data( clist, row );
283         if( ! email ) {
284                 personeditdlg.rowIndEMail = -1 + row;
285         }
286         if (!personeditdlg.read_only) {
287                 gtk_widget_set_sensitive(personeditdlg.email_del, gtk_clist_get_row_data(clist, 0) != NULL);
288                 gtk_widget_set_sensitive(personeditdlg.email_up, gtk_clist_get_row_data(clist, personeditdlg.rowIndEMail + 1) != NULL);
289                 gtk_widget_set_sensitive(personeditdlg.email_down, gtk_clist_get_row_data(clist, personeditdlg.rowIndEMail - 1) != NULL);
290         }
291         edit_person_status_show( NULL );
292 }
293
294 static ItemEMail *edit_person_email_edit( gboolean *error, ItemEMail *email ) {
295         ItemEMail *retVal = NULL;
296         gchar *sEmail, *sAlias, *sRemarks, *sEmail_;
297
298         *error = TRUE;
299         sEmail_ = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_email), 0, -1 );
300         sAlias = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_alias), 0, -1 );
301         sRemarks = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_remarks), 0, -1 );
302         sEmail = mgu_email_check_empty( sEmail_ );
303         g_free( sEmail_ );
304
305         if( sEmail ) {
306                 if( email == NULL ) {
307                         email = addritem_create_item_email();
308                 }
309                 addritem_email_set_address( email, sEmail );
310                 addritem_email_set_alias( email, sAlias );
311                 addritem_email_set_remarks( email, sRemarks );
312                 retVal = email;
313                 *error = FALSE;
314         }
315         else {
316                 edit_person_status_show( _( "An E-Mail address must be supplied." ) );
317         }
318
319         g_free( sEmail );
320         g_free( sAlias );
321         g_free( sRemarks );
322
323         return retVal;
324 }
325
326 static void edit_person_email_modify( gpointer data ) {
327         gboolean errFlg = FALSE;
328         GtkCList *clist = GTK_CLIST(personeditdlg.clist_email);
329         gint row = personeditdlg.rowIndEMail;
330         ItemEMail *email = gtk_clist_get_row_data( clist, row );
331         if( email ) {
332                 edit_person_email_edit( &errFlg, email );
333                 if( ! errFlg ) {
334                         gtk_clist_set_text( clist, row, EMAIL_COL_EMAIL, email->address );
335                         gtk_clist_set_text( clist, row, EMAIL_COL_ALIAS, email->obj.name );
336                         gtk_clist_set_text( clist, row, EMAIL_COL_REMARKS, email->remarks );
337                         edit_person_email_clear( NULL );
338                 }
339         }
340 }
341
342 static void edit_person_email_add( gpointer data ) {
343         GtkCList *clist = GTK_CLIST(personeditdlg.clist_email);
344         gboolean errFlg = FALSE;
345         ItemEMail *email = NULL;
346         gint row = personeditdlg.rowIndEMail;
347         if( gtk_clist_get_row_data( clist, row ) == NULL ) row = 0;
348
349         email = edit_person_email_edit( &errFlg, NULL );
350         if( ! errFlg ) {
351                 gchar *text[ EMAIL_N_COLS ];
352                 text[ EMAIL_COL_EMAIL   ] = email->address;
353                 text[ EMAIL_COL_ALIAS   ] = email->obj.name;
354                 text[ EMAIL_COL_REMARKS ] = email->remarks;
355
356                 row = gtk_clist_insert( clist, 1 + row, text );
357                 gtk_clist_set_row_data( clist, row, email );
358                 gtk_clist_select_row( clist, row, 0 );
359                 edit_person_email_clear( NULL );
360         }
361 }
362
363 /*
364 * Comparison using cell contents (text in first column). Used for sort
365 * address index widget.
366 */
367 static gint edit_person_attrib_compare_func(
368         GtkCList *clist, gconstpointer ptr1, gconstpointer ptr2 )
369 {
370         GtkCell *cell1 = ((GtkCListRow *)ptr1)->cell;
371         GtkCell *cell2 = ((GtkCListRow *)ptr2)->cell;
372         gchar *name1 = NULL, *name2 = NULL;
373
374         if( cell1 ) name1 = cell1->u.text;
375         if( cell2 ) name2 = cell2->u.text;
376         if( ! name1 ) return ( name2 != NULL );
377         if( ! name2 ) return -1;
378         return g_utf8_collate( name1, name2 );
379 }
380
381 static gboolean list_find_attribute(const gchar *attr)
382 {
383         GtkCList *clist = GTK_CLIST(personeditdlg.clist_attrib);
384         UserAttribute *attrib;
385         gint row = 0;
386         while( (attrib = gtk_clist_get_row_data( clist, row )) ) {
387                 if (!g_ascii_strcasecmp(attrib->name, attr)) {
388                         gtk_clist_select_row(clist, row, 0);
389                         return TRUE;
390                 }
391                 row++;
392         }
393         return FALSE;
394 }
395
396 static gboolean list_find_email(const gchar *addr)
397 {
398         GtkCList *clist = GTK_CLIST(personeditdlg.clist_email);
399         ItemEMail *email;
400         gint row = 0;
401         while( (email = gtk_clist_get_row_data( clist, row )) ) {
402                 if (!g_ascii_strcasecmp(email->address, addr)) {
403                         gtk_clist_select_row(clist, row, 0);
404                         return TRUE;
405                 }
406                 row++;
407         }
408         return FALSE;
409 }
410
411 /*
412 * Load clist with a copy of person's email addresses.
413 */
414 static void edit_person_load_attrib( ItemPerson *person ) {
415         GList *node = person->listAttrib;
416         GtkCList *clist = GTK_CLIST(personeditdlg.clist_attrib);
417         gchar *text[ ATTRIB_N_COLS ];
418         while( node ) {
419                 UserAttribute *atorig = ( UserAttribute * ) node->data;
420                 UserAttribute *attrib = addritem_copy_attribute( atorig );
421                 gint row;
422                 text[ ATTRIB_COL_NAME  ] = attrib->name;
423                 text[ ATTRIB_COL_VALUE ] = attrib->value;
424
425                 row = gtk_clist_append( clist, text );
426                 gtk_clist_set_row_data( clist, row, attrib );
427                 node = g_list_next( node );
428         }
429 }
430
431 static void edit_person_attrib_list_selected( GtkCList *clist, gint row, gint column, GdkEvent *event, gpointer data ) {
432         UserAttribute *attrib = gtk_clist_get_row_data( clist, row );
433         if( attrib && !personeditdlg.read_only) {
434                 gtk_entry_set_text( GTK_ENTRY(personeditdlg.entry_atname), attrib->name );
435                 gtk_entry_set_text( GTK_ENTRY(personeditdlg.entry_atvalue), attrib->value );
436                 gtk_widget_set_sensitive(personeditdlg.attrib_del, TRUE);
437         } else {
438                 gtk_widget_set_sensitive(personeditdlg.attrib_del, FALSE);
439         }
440         personeditdlg.rowIndAttrib = row;
441         edit_person_status_show( NULL );
442 }
443
444 static void edit_person_attrib_delete( gpointer data ) {
445         GtkCList *clist = GTK_CLIST(personeditdlg.clist_attrib);
446         gint row = personeditdlg.rowIndAttrib;
447         UserAttribute *attrib = gtk_clist_get_row_data( clist, row );
448         edit_person_attrib_clear( NULL );
449         if( attrib ) {
450                 /* Remove list entry */
451                 gtk_clist_remove( clist, row );
452                 addritem_free_attribute( attrib );
453                 attrib = NULL;
454         }
455
456         /* Position hilite bar */
457         attrib = gtk_clist_get_row_data( clist, row );
458         if( ! attrib ) {
459                 personeditdlg.rowIndAttrib = -1 + row;
460         } 
461         
462         if (!personeditdlg.read_only)
463                 gtk_widget_set_sensitive(personeditdlg.attrib_del, gtk_clist_get_row_data(clist, 0) != NULL);
464         
465         edit_person_status_show( NULL );
466 }
467
468 static UserAttribute *edit_person_attrib_edit( gboolean *error, UserAttribute *attrib ) {
469         UserAttribute *retVal = NULL;
470         gchar *sName, *sValue, *sName_, *sValue_;
471
472         *error = TRUE;
473         sName_ = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_atname), 0, -1 );
474         sValue_ = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_atvalue), 0, -1 );
475         sName = mgu_email_check_empty( sName_ );
476         sValue = mgu_email_check_empty( sValue_ );
477         g_free( sName_ );
478         g_free( sValue_ );
479
480         if( sName && sValue ) {
481                 if( attrib == NULL ) {
482                         attrib = addritem_create_attribute();
483                 }
484                 addritem_attrib_set_name( attrib, sName );
485                 addritem_attrib_set_value( attrib, sValue );
486                 retVal = attrib;
487                 *error = FALSE;
488         }
489         else {
490                 edit_person_status_show( _( "A Name and Value must be supplied." ) );
491         }
492
493         g_free( sName );
494         g_free( sValue );
495
496         return retVal;
497 }
498
499 static void edit_person_attrib_modify( gpointer data ) {
500         gboolean errFlg = FALSE;
501         GtkCList *clist = GTK_CLIST(personeditdlg.clist_attrib);
502         gint row = personeditdlg.rowIndAttrib;
503         UserAttribute *attrib = gtk_clist_get_row_data( clist, row );
504         if( attrib ) {
505                 edit_person_attrib_edit( &errFlg, attrib );
506                 if( ! errFlg ) {
507                         gtk_clist_set_text( clist, row, ATTRIB_COL_NAME, attrib->name );
508                         gtk_clist_set_text( clist, row, ATTRIB_COL_VALUE, attrib->value );
509                         edit_person_attrib_clear( NULL );
510                 }
511         }
512 }
513
514 static void edit_person_attrib_add( gpointer data ) {
515         GtkCList *clist = GTK_CLIST(personeditdlg.clist_attrib);
516         gboolean errFlg = FALSE;
517         UserAttribute *attrib = NULL;
518         gint row = personeditdlg.rowIndAttrib;
519         if( gtk_clist_get_row_data( clist, row ) == NULL ) row = 0;
520
521         attrib = edit_person_attrib_edit( &errFlg, NULL );
522         if( ! errFlg ) {
523                 gchar *text[ EMAIL_N_COLS ];
524                 text[ ATTRIB_COL_NAME  ] = attrib->name;
525                 text[ ATTRIB_COL_VALUE ] = attrib->value;
526
527                 row = gtk_clist_insert( clist, 1 + row, text );
528                 gtk_clist_set_row_data( clist, row, attrib );
529                 gtk_clist_select_row( clist, row, 0 );
530                 edit_person_attrib_clear( NULL );
531         }
532 }
533
534 /*!
535  *\brief        Save Gtk object size to prefs dataset
536  */
537 static void edit_person_size_allocate_cb(GtkWidget *widget,
538                                          GtkAllocation *allocation)
539 {
540         g_return_if_fail(allocation != NULL);
541
542         prefs_common.addressbookeditpersonwin_width = allocation->width;
543         prefs_common.addressbookeditpersonwin_height = allocation->height;
544 }
545
546 static void addressbook_edit_person_dialog_create( gboolean *cancelled ) {
547         GtkWidget *window;
548         GtkWidget *vbox;
549         GtkWidget *vnbox;
550         GtkWidget *notebook;
551         GtkWidget *hbbox;
552         GtkWidget *ok_btn;
553         GtkWidget *cancel_btn;
554         GtkWidget *hsbox;
555         GtkWidget *statusbar;
556         static GdkGeometry geometry;
557
558         window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
559         /* gtk_container_set_border_width(GTK_CONTAINER(window), 0); */
560         gtk_window_set_title(GTK_WINDOW(window), _("Edit Person Data"));
561         gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
562         gtk_window_set_modal(GTK_WINDOW(window), TRUE); 
563         g_signal_connect(G_OBJECT(window), "delete_event",
564                          G_CALLBACK(edit_person_delete_event),
565                          cancelled);
566         g_signal_connect(G_OBJECT(window), "size_allocate",
567                          G_CALLBACK(edit_person_size_allocate_cb),
568                         cancelled);
569         g_signal_connect(G_OBJECT(window), "key_press_event",
570                          G_CALLBACK(edit_person_key_pressed),
571                          cancelled);
572
573         vbox = gtk_vbox_new(FALSE, 4);
574         /* gtk_container_set_border_width(GTK_CONTAINER(vbox), BORDER_WIDTH); */
575         gtk_widget_show(vbox);
576         gtk_container_add(GTK_CONTAINER(window), vbox);
577
578         vnbox = gtk_vbox_new(FALSE, 4);
579         gtk_container_set_border_width(GTK_CONTAINER(vnbox), 4);
580         gtk_widget_show(vnbox);
581         gtk_box_pack_start(GTK_BOX(vbox), vnbox, TRUE, TRUE, 0);
582
583         /* Notebook */
584         notebook = gtk_notebook_new();
585         gtk_widget_show(notebook);
586         gtk_box_pack_start(GTK_BOX(vnbox), notebook, TRUE, TRUE, 0);
587         gtk_container_set_border_width(GTK_CONTAINER(notebook), 6);
588
589         /* Status line */
590         hsbox = gtk_hbox_new(FALSE, 0);
591         gtk_box_pack_end(GTK_BOX(vbox), hsbox, FALSE, FALSE, BORDER_WIDTH);
592         statusbar = gtk_statusbar_new();
593         gtk_box_pack_start(GTK_BOX(hsbox), statusbar, TRUE, TRUE, BORDER_WIDTH);
594
595         /* Button panel */
596         gtkut_stock_button_set_create(&hbbox, &ok_btn, GTK_STOCK_OK,
597                                       &cancel_btn, GTK_STOCK_CANCEL,
598                                       NULL, NULL);
599         gtk_box_pack_end(GTK_BOX(vnbox), hbbox, FALSE, FALSE, 0);
600         gtk_widget_grab_default(ok_btn);
601
602         g_signal_connect(G_OBJECT(ok_btn), "clicked",
603                          G_CALLBACK(edit_person_ok), cancelled);
604         g_signal_connect(G_OBJECT(cancel_btn), "clicked",
605                          G_CALLBACK(edit_person_cancel), cancelled);
606         g_signal_connect(G_OBJECT(notebook), "switch_page",
607                          G_CALLBACK(edit_person_switch_page), NULL );
608
609         gtk_widget_show_all(vbox);
610
611         if (!geometry.min_height) {
612                 geometry.min_width = EDITPERSON_WIDTH;
613                 geometry.min_height = EDITPERSON_HEIGHT;
614         }
615
616         gtk_window_set_geometry_hints(GTK_WINDOW(window), NULL, &geometry,
617                                       GDK_HINT_MIN_SIZE);
618         gtk_widget_set_size_request(window, prefs_common.addressbookeditpersonwin_width,
619                                     prefs_common.addressbookeditpersonwin_height);
620
621         personeditdlg.window     = window;
622         personeditdlg.notebook   = notebook;
623         personeditdlg.ok_btn     = ok_btn;
624         personeditdlg.cancel_btn = cancel_btn;
625         personeditdlg.statusbar  = statusbar;
626         personeditdlg.status_cid = gtk_statusbar_get_context_id( GTK_STATUSBAR(statusbar), "Edit Person Dialog" );
627
628 }
629
630 static void addressbook_edit_person_page_basic( gint pageNum, gchar *pageLbl ) {
631         GtkWidget *vbox;
632         GtkWidget *table;
633         GtkWidget *label;
634         GtkWidget *entry_name;
635         GtkWidget *entry_fn;
636         GtkWidget *entry_ln;
637         GtkWidget *entry_nn;
638         const gchar *locale;
639         gint top = 0;
640
641         vbox = gtk_vbox_new( FALSE, 8 );
642         gtk_widget_show( vbox );
643         gtk_container_add( GTK_CONTAINER( personeditdlg.notebook ), vbox );
644         gtk_container_set_border_width( GTK_CONTAINER (vbox), BORDER_WIDTH );
645
646         label = gtk_label_new( pageLbl );
647         gtk_widget_show( label );
648         gtk_notebook_set_tab_label(
649                 GTK_NOTEBOOK( personeditdlg.notebook ),
650                 gtk_notebook_get_nth_page( GTK_NOTEBOOK( personeditdlg.notebook ), pageNum ), label );
651
652         table = gtk_table_new( 4, 3, FALSE);
653         gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0);
654         gtk_container_set_border_width( GTK_CONTAINER(table), 8 );
655         gtk_table_set_row_spacings(GTK_TABLE(table), 8);
656         gtk_table_set_col_spacings(GTK_TABLE(table), 8);
657
658 #define ATTACH_ROW(text, entry) \
659 { \
660         label = gtk_label_new(text); \
661         gtk_table_attach(GTK_TABLE(table), label, 0, 1, top, (top + 1), \
662                          GTK_FILL, 0, 0, 0); \
663         gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); \
664  \
665         entry = gtk_entry_new(); \
666         gtk_table_attach(GTK_TABLE(table), entry, 1, 2, top, (top + 1), \
667                          GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0); \
668         top++; \
669 }
670
671         ATTACH_ROW(_("Display Name"), entry_name);
672         locale = conv_get_current_locale();
673         if (locale &&
674             (!g_ascii_strncasecmp(locale, "ja", 2) ||
675              !g_ascii_strncasecmp(locale, "ko", 2) ||
676              !g_ascii_strncasecmp(locale, "zh", 2))) {
677                 ATTACH_ROW(_("Last Name"), entry_ln);
678                 ATTACH_ROW(_("First Name"), entry_fn);
679         } else {
680                 ATTACH_ROW(_("First Name"), entry_fn);
681                 ATTACH_ROW(_("Last Name"), entry_ln);
682         }
683         ATTACH_ROW(_("Nickname"), entry_nn);
684
685 #undef ATTACH_ROW
686
687         gtk_widget_show_all(vbox);
688
689         personeditdlg.entry_name  = entry_name;
690         personeditdlg.entry_first = entry_fn;
691         personeditdlg.entry_last  = entry_ln;
692         personeditdlg.entry_nick  = entry_nn;
693 }
694
695 static gboolean email_adding = FALSE, email_saving = FALSE;
696
697 static void edit_person_entry_email_changed (GtkWidget *entry, gpointer data)
698 {
699         gboolean non_empty = gtk_clist_get_row_data(GTK_CLIST(personeditdlg.clist_email), 0) != NULL;
700
701         if (personeditdlg.read_only)
702                 return;
703
704         if (gtk_entry_get_text(GTK_ENTRY(personeditdlg.entry_email)) == NULL
705         ||  strlen(gtk_entry_get_text(GTK_ENTRY(personeditdlg.entry_email))) == 0) {
706                 gtk_widget_set_sensitive(personeditdlg.email_add,FALSE);
707                 gtk_widget_set_sensitive(personeditdlg.email_mod,FALSE);
708                 email_adding = FALSE;
709                 email_saving = FALSE;
710         } else if (list_find_email(gtk_entry_get_text(GTK_ENTRY(personeditdlg.entry_email)))) {
711                 gtk_widget_set_sensitive(personeditdlg.email_add,FALSE);
712                 gtk_widget_set_sensitive(personeditdlg.email_mod,non_empty);
713                 email_adding = FALSE;
714                 email_saving = non_empty;
715         } else {
716                 gtk_widget_set_sensitive(personeditdlg.email_add,TRUE);
717                 gtk_widget_set_sensitive(personeditdlg.email_mod,non_empty);
718                 email_adding = TRUE;
719                 email_saving = non_empty;
720         }
721 }
722
723 static gboolean edit_person_entry_email_pressed(GtkWidget *widget, GdkEventKey *event, gpointer data)
724 {
725         if (event && event->keyval == GDK_Return) {
726                 if (email_saving)
727                         edit_person_email_modify(NULL);         
728                 else if (email_adding)
729                         edit_person_email_add(NULL);
730         }
731         return FALSE;
732 }
733
734
735 static void addressbook_edit_person_page_email( gint pageNum, gchar *pageLbl ) {
736         GtkWidget *vbox;
737         GtkWidget *hbox;
738         GtkWidget *vboxl;
739         GtkWidget *vboxb;
740         GtkWidget *vbuttonbox;
741         GtkWidget *buttonUp;
742         GtkWidget *buttonDown;
743         GtkWidget *buttonDel;
744         GtkWidget *buttonMod;
745         GtkWidget *buttonAdd;
746
747         GtkWidget *table;
748         GtkWidget *label;
749         GtkWidget *clist_swin;
750         GtkWidget *clist;
751         GtkWidget *entry_email;
752         GtkWidget *entry_alias;
753         GtkWidget *entry_remarks;
754         gint top;
755
756         gchar *titles[ EMAIL_N_COLS ];
757         gint i;
758
759         titles[ EMAIL_COL_EMAIL   ] = _("E-Mail Address");
760         titles[ EMAIL_COL_ALIAS   ] = _("Alias");
761         titles[ EMAIL_COL_REMARKS ] = _("Remarks");
762
763         vbox = gtk_vbox_new( FALSE, 8 );
764         gtk_widget_show( vbox );
765         gtk_container_add( GTK_CONTAINER( personeditdlg.notebook ), vbox );
766         gtk_container_set_border_width( GTK_CONTAINER (vbox), BORDER_WIDTH );
767
768         label = gtk_label_new( pageLbl );
769         gtk_widget_show( label );
770         gtk_notebook_set_tab_label(
771                 GTK_NOTEBOOK( personeditdlg.notebook ),
772                 gtk_notebook_get_nth_page( GTK_NOTEBOOK( personeditdlg.notebook ), pageNum ), label );
773
774         /* Split into two areas */
775         hbox = gtk_hbox_new( FALSE, 0 );
776         gtk_container_add( GTK_CONTAINER( vbox ), hbox );
777
778         /* Address list */
779         vboxl = gtk_vbox_new( FALSE, 4 );
780         gtk_container_add( GTK_CONTAINER( hbox ), vboxl );
781         gtk_container_set_border_width( GTK_CONTAINER(vboxl), 4 );
782
783         clist_swin = gtk_scrolled_window_new( NULL, NULL );
784         gtk_container_add( GTK_CONTAINER(vboxl), clist_swin );
785         gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(clist_swin),
786                                        GTK_POLICY_AUTOMATIC,
787                                        GTK_POLICY_AUTOMATIC);
788
789         clist = gtk_clist_new_with_titles( EMAIL_N_COLS, titles );
790         gtk_container_add( GTK_CONTAINER(clist_swin), clist );
791         gtk_clist_set_selection_mode( GTK_CLIST(clist), GTK_SELECTION_BROWSE );
792         gtk_clist_set_column_width( GTK_CLIST(clist), EMAIL_COL_EMAIL, EMAIL_COL_WIDTH_EMAIL );
793         gtk_clist_set_column_width( GTK_CLIST(clist), EMAIL_COL_ALIAS, EMAIL_COL_WIDTH_ALIAS );
794
795         for( i = 0; i < EMAIL_N_COLS; i++ )
796                 GTK_WIDGET_UNSET_FLAGS(GTK_CLIST(clist)->column[i].button, GTK_CAN_FOCUS);
797
798         /* Data entry area */
799         table = gtk_table_new( 4, 2, FALSE);
800         gtk_box_pack_start(GTK_BOX(vboxl), table, FALSE, FALSE, 0);
801         gtk_container_set_border_width( GTK_CONTAINER(table), 4 );
802         gtk_table_set_row_spacings(GTK_TABLE(table), 4);
803         gtk_table_set_col_spacings(GTK_TABLE(table), 4);
804
805         /* First row */
806         top = 0;
807         label = gtk_label_new(_("E-Mail Address"));
808         gtk_table_attach(GTK_TABLE(table), label, 0, 1, top, (top + 1), GTK_FILL, 0, 0, 0);
809         gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
810
811         entry_email = gtk_entry_new();
812         gtk_table_attach(GTK_TABLE(table), entry_email, 1, 2, top, (top + 1), GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
813
814         /* Next row */
815         ++top;
816         label = gtk_label_new(_("Alias"));
817         gtk_table_attach(GTK_TABLE(table), label, 0, 1, top, (top + 1), GTK_FILL, 0, 0, 0);
818         gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
819
820         entry_alias = gtk_entry_new();
821         gtk_table_attach(GTK_TABLE(table), entry_alias, 1, 2, top, (top + 1), GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
822
823         /* Next row */
824         ++top;
825         label = gtk_label_new(_("Remarks"));
826         gtk_table_attach(GTK_TABLE(table), label, 0, 1, top, (top + 1), GTK_FILL, 0, 0, 0);
827         gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
828
829         entry_remarks = gtk_entry_new();
830         gtk_table_attach(GTK_TABLE(table), entry_remarks, 1, 2, top, (top + 1), GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
831
832         /* Button box */
833         vboxb = gtk_vbox_new( FALSE, 4 );
834         gtk_box_pack_start(GTK_BOX(hbox), vboxb, FALSE, FALSE, 2);
835
836         vbuttonbox = gtk_vbutton_box_new();
837         gtk_button_box_set_layout( GTK_BUTTON_BOX(vbuttonbox), GTK_BUTTONBOX_START );
838         gtk_box_set_spacing( GTK_BOX(vbuttonbox), 8 );
839         gtk_container_set_border_width( GTK_CONTAINER(vbuttonbox), 4 );
840         gtk_container_add( GTK_CONTAINER(vboxb), vbuttonbox );
841
842         /* Buttons */
843         buttonUp = gtk_button_new_from_stock(GTK_STOCK_GO_UP);
844         gtk_container_add( GTK_CONTAINER(vbuttonbox), buttonUp );
845
846         buttonDown = gtk_button_new_from_stock(GTK_STOCK_GO_DOWN);
847         gtk_container_add( GTK_CONTAINER(vbuttonbox), buttonDown );
848
849         buttonDel = gtk_button_new_from_stock(GTK_STOCK_DELETE);
850         gtk_container_add( GTK_CONTAINER(vbuttonbox), buttonDel );
851
852         buttonMod = gtk_button_new_from_stock(GTK_STOCK_SAVE);
853         gtk_container_add( GTK_CONTAINER(vbuttonbox), buttonMod );
854
855         buttonAdd = gtk_button_new_from_stock(GTK_STOCK_ADD);
856         gtk_container_add( GTK_CONTAINER(vbuttonbox), buttonAdd );
857
858         gtk_widget_show_all(vbox);
859
860         /* Event handlers */
861         g_signal_connect( G_OBJECT(clist), "select_row",
862                           G_CALLBACK( edit_person_email_list_selected), NULL );
863         g_signal_connect( G_OBJECT(buttonUp), "clicked",
864                           G_CALLBACK( edit_person_email_move_up ), NULL );
865         g_signal_connect( G_OBJECT(buttonDown), "clicked",
866                           G_CALLBACK( edit_person_email_move_down ), NULL );
867         g_signal_connect( G_OBJECT(buttonDel), "clicked",
868                           G_CALLBACK( edit_person_email_delete ), NULL );
869         g_signal_connect( G_OBJECT(buttonMod), "clicked",
870                           G_CALLBACK( edit_person_email_modify ), NULL );
871         g_signal_connect( G_OBJECT(buttonAdd), "clicked",
872                           G_CALLBACK( edit_person_email_add ), NULL );
873         g_signal_connect(G_OBJECT(entry_email), "changed",
874                          G_CALLBACK(edit_person_entry_email_changed), NULL);
875         g_signal_connect(G_OBJECT(entry_email), "key_press_event",
876                          G_CALLBACK(edit_person_entry_email_pressed), NULL);
877         g_signal_connect(G_OBJECT(entry_alias), "key_press_event",
878                          G_CALLBACK(edit_person_entry_email_pressed), NULL);
879         g_signal_connect(G_OBJECT(entry_remarks), "key_press_event",
880                          G_CALLBACK(edit_person_entry_email_pressed), NULL);
881
882         personeditdlg.clist_email   = clist;
883         personeditdlg.entry_email   = entry_email;
884         personeditdlg.entry_alias   = entry_alias;
885         personeditdlg.entry_remarks = entry_remarks;
886         personeditdlg.email_up = buttonUp;
887         personeditdlg.email_down = buttonDown;
888         personeditdlg.email_del = buttonDel;
889         personeditdlg.email_mod = buttonMod;
890         personeditdlg.email_add = buttonAdd;
891 }
892
893 static gboolean attrib_adding = FALSE, attrib_saving = FALSE;
894
895 static void edit_person_entry_att_changed (GtkWidget *entry, gpointer data)
896 {
897         gboolean non_empty = gtk_clist_get_row_data(GTK_CLIST(personeditdlg.clist_attrib), 0) != NULL;
898
899         if (personeditdlg.read_only)
900                 return;
901
902         if (gtk_entry_get_text(GTK_ENTRY(personeditdlg.entry_atname)) == NULL
903         ||  strlen(gtk_entry_get_text(GTK_ENTRY(personeditdlg.entry_atname))) == 0) {
904                 gtk_widget_set_sensitive(personeditdlg.attrib_add,FALSE);
905                 gtk_widget_set_sensitive(personeditdlg.attrib_mod,FALSE);
906                 attrib_adding = FALSE;
907                 attrib_saving = FALSE;
908         } else if (list_find_attribute(gtk_entry_get_text(GTK_ENTRY(personeditdlg.entry_atname)))) {
909                 gtk_widget_set_sensitive(personeditdlg.attrib_add,FALSE);
910                 gtk_widget_set_sensitive(personeditdlg.attrib_mod,non_empty);
911                 attrib_adding = FALSE;
912                 attrib_saving = non_empty;
913         } else {
914                 gtk_widget_set_sensitive(personeditdlg.attrib_add,TRUE);
915                 gtk_widget_set_sensitive(personeditdlg.attrib_mod,non_empty);
916                 attrib_adding = TRUE;
917                 attrib_saving = non_empty;
918         }
919 }
920
921 static gboolean edit_person_entry_att_pressed(GtkWidget *widget, GdkEventKey *event, gpointer data)
922 {
923         if (event && event->keyval == GDK_Return) {
924                 if (attrib_saving)
925                         edit_person_attrib_modify(NULL);
926                 else if (attrib_adding)
927                         edit_person_attrib_add(NULL);
928         }
929         return FALSE;
930 }
931
932 static void addressbook_edit_person_page_attrib( gint pageNum, gchar *pageLbl ) {
933         GtkWidget *vbox;
934         GtkWidget *hbox;
935         GtkWidget *vboxl;
936         GtkWidget *vboxb;
937         GtkWidget *vbuttonbox;
938         GtkWidget *buttonDel;
939         GtkWidget *buttonMod;
940         GtkWidget *buttonAdd;
941
942         GtkWidget *table;
943         GtkWidget *label;
944         GtkWidget *clist_swin;
945         GtkWidget *clist;
946         GtkWidget *entry_name;
947         GtkWidget *entry_value;
948         gint top;
949
950         gchar *titles[ ATTRIB_N_COLS ];
951         gint i;
952
953         titles[ ATTRIB_COL_NAME  ] = _("Name");
954         titles[ ATTRIB_COL_VALUE ] = _("Value");
955
956         vbox = gtk_vbox_new( FALSE, 8 );
957         gtk_widget_show( vbox );
958         gtk_container_add( GTK_CONTAINER( personeditdlg.notebook ), vbox );
959         gtk_container_set_border_width( GTK_CONTAINER (vbox), BORDER_WIDTH );
960
961         label = gtk_label_new( pageLbl );
962         gtk_widget_show( label );
963         gtk_notebook_set_tab_label(
964                 GTK_NOTEBOOK( personeditdlg.notebook ),
965                 gtk_notebook_get_nth_page( GTK_NOTEBOOK( personeditdlg.notebook ), pageNum ), label );
966
967         /* Split into two areas */
968         hbox = gtk_hbox_new( FALSE, 0 );
969         gtk_container_add( GTK_CONTAINER( vbox ), hbox );
970
971         /* Attribute list */
972         vboxl = gtk_vbox_new( FALSE, 4 );
973         gtk_container_add( GTK_CONTAINER( hbox ), vboxl );
974         gtk_container_set_border_width( GTK_CONTAINER(vboxl), 4 );
975
976         clist_swin = gtk_scrolled_window_new( NULL, NULL );
977         gtk_container_add( GTK_CONTAINER(vboxl), clist_swin );
978         gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(clist_swin),
979                                        GTK_POLICY_AUTOMATIC,
980                                        GTK_POLICY_AUTOMATIC);
981
982         clist = gtk_clist_new_with_titles( ATTRIB_N_COLS, titles );
983         gtk_container_add( GTK_CONTAINER(clist_swin), clist );
984         gtk_clist_set_selection_mode( GTK_CLIST(clist), GTK_SELECTION_BROWSE );
985         gtk_clist_set_column_width( GTK_CLIST(clist), ATTRIB_COL_NAME, ATTRIB_COL_WIDTH_NAME );
986         gtk_clist_set_column_width( GTK_CLIST(clist), ATTRIB_COL_VALUE, ATTRIB_COL_WIDTH_VALUE );
987         gtk_clist_set_compare_func( GTK_CLIST(clist), edit_person_attrib_compare_func );
988         gtk_clist_set_auto_sort( GTK_CLIST(clist), TRUE );
989
990         for( i = 0; i < ATTRIB_N_COLS; i++ )
991                 GTK_WIDGET_UNSET_FLAGS(GTK_CLIST(clist)->column[i].button, GTK_CAN_FOCUS);
992
993         /* Data entry area */
994         table = gtk_table_new( 4, 2, FALSE);
995         gtk_box_pack_start(GTK_BOX(vboxl), table, FALSE, FALSE, 0);
996         gtk_container_set_border_width( GTK_CONTAINER(table), 4 );
997         gtk_table_set_row_spacings(GTK_TABLE(table), 4);
998         gtk_table_set_col_spacings(GTK_TABLE(table), 4);
999
1000         /* First row */
1001         top = 0;
1002         label = gtk_label_new(_("Name"));
1003         gtk_table_attach(GTK_TABLE(table), label, 0, 1, top, (top + 1), GTK_FILL, 0, 0, 0);
1004         gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
1005
1006         entry_name = gtk_entry_new();
1007         gtk_table_attach(GTK_TABLE(table), entry_name, 1, 2, top, (top + 1), GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
1008
1009         /* Next row */
1010         ++top;
1011         label = gtk_label_new(_("Value"));
1012         gtk_table_attach(GTK_TABLE(table), label, 0, 1, top, (top + 1), GTK_FILL, 0, 0, 0);
1013         gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
1014
1015         entry_value = gtk_entry_new();
1016         gtk_table_attach(GTK_TABLE(table), entry_value, 1, 2, top, (top + 1), GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
1017
1018         /* Button box */
1019         vboxb = gtk_vbox_new( FALSE, 4 );
1020         gtk_box_pack_start(GTK_BOX(hbox), vboxb, FALSE, FALSE, 2);
1021
1022         vbuttonbox = gtk_vbutton_box_new();
1023         gtk_button_box_set_layout( GTK_BUTTON_BOX(vbuttonbox), GTK_BUTTONBOX_START );
1024         gtk_box_set_spacing( GTK_BOX(vbuttonbox), 8 );
1025         gtk_container_set_border_width( GTK_CONTAINER(vbuttonbox), 4 );
1026         gtk_container_add( GTK_CONTAINER(vboxb), vbuttonbox );
1027
1028         /* Buttons */
1029         buttonDel = gtk_button_new_from_stock(GTK_STOCK_DELETE);
1030         gtk_container_add( GTK_CONTAINER(vbuttonbox), buttonDel );
1031
1032         buttonMod = gtk_button_new_from_stock(GTK_STOCK_SAVE);
1033         gtk_container_add( GTK_CONTAINER(vbuttonbox), buttonMod );
1034
1035         buttonAdd = gtk_button_new_from_stock(GTK_STOCK_ADD);
1036         gtk_container_add( GTK_CONTAINER(vbuttonbox), buttonAdd );
1037         
1038         gtk_widget_set_sensitive(buttonDel,FALSE);
1039         gtk_widget_set_sensitive(buttonMod,FALSE);
1040         gtk_widget_set_sensitive(buttonAdd,FALSE);
1041
1042         gtk_widget_show_all(vbox);
1043
1044         /* Event handlers */
1045         g_signal_connect( G_OBJECT(clist), "select_row",
1046                           G_CALLBACK( edit_person_attrib_list_selected), NULL );
1047         g_signal_connect( G_OBJECT(buttonDel), "clicked",
1048                           G_CALLBACK( edit_person_attrib_delete ), NULL );
1049         g_signal_connect( G_OBJECT(buttonMod), "clicked",
1050                           G_CALLBACK( edit_person_attrib_modify ), NULL );
1051         g_signal_connect( G_OBJECT(buttonAdd), "clicked",
1052                           G_CALLBACK( edit_person_attrib_add ), NULL );
1053         g_signal_connect(G_OBJECT(entry_name), "changed",
1054                          G_CALLBACK(edit_person_entry_att_changed), NULL);
1055         g_signal_connect(G_OBJECT(entry_name), "key_press_event",
1056                          G_CALLBACK(edit_person_entry_att_pressed), NULL);
1057         g_signal_connect(G_OBJECT(entry_value), "key_press_event",
1058                          G_CALLBACK(edit_person_entry_att_pressed), NULL);
1059
1060         personeditdlg.clist_attrib  = clist;
1061         personeditdlg.entry_atname  = entry_name;
1062         personeditdlg.entry_atvalue = entry_value;
1063         personeditdlg.attrib_add = buttonAdd;
1064         personeditdlg.attrib_del = buttonDel;
1065         personeditdlg.attrib_mod = buttonMod;
1066 }
1067
1068 static void addressbook_edit_person_create( gboolean *cancelled ) {
1069         addressbook_edit_person_dialog_create( cancelled );
1070         addressbook_edit_person_page_basic( PAGE_BASIC, _( "User Data" ) );
1071         addressbook_edit_person_page_email( PAGE_EMAIL, _( "E-Mail Addresses" ) );
1072         addressbook_edit_person_page_attrib( PAGE_ATTRIBUTES, _( "Other Attributes" ) );
1073         gtk_widget_show_all( personeditdlg.window );
1074 }
1075
1076 /*
1077 * Return list of email items.
1078 */
1079 static GList *edit_person_build_email_list() {
1080         GtkCList *clist = GTK_CLIST(personeditdlg.clist_email);
1081         GList *listEMail = NULL;
1082         ItemEMail *email;
1083         gint row = 0;
1084         while( (email = gtk_clist_get_row_data( clist, row )) ) {
1085                 listEMail = g_list_append( listEMail, email );
1086                 row++;
1087         }
1088         return listEMail;
1089 }
1090
1091 /*
1092 * Return list of attributes.
1093 */
1094 static GList *edit_person_build_attrib_list() {
1095         GtkCList *clist = GTK_CLIST(personeditdlg.clist_attrib);
1096         GList *listAttrib = NULL;
1097         UserAttribute *attrib;
1098         gint row = 0;
1099         while( (attrib = gtk_clist_get_row_data( clist, row )) ) {
1100                 listAttrib = g_list_append( listAttrib, attrib );
1101                 row++;
1102         }
1103         return listAttrib;
1104 }
1105
1106 static void update_sensitivity(void)
1107 {
1108         gtk_widget_set_sensitive(personeditdlg.entry_name,    !personeditdlg.read_only);
1109         gtk_widget_set_sensitive(personeditdlg.entry_first,   !personeditdlg.read_only);
1110         gtk_widget_set_sensitive(personeditdlg.entry_last,    !personeditdlg.read_only);
1111         gtk_widget_set_sensitive(personeditdlg.entry_nick,    !personeditdlg.read_only);
1112         gtk_widget_set_sensitive(personeditdlg.entry_email,   !personeditdlg.read_only);
1113         gtk_widget_set_sensitive(personeditdlg.entry_alias,   !personeditdlg.read_only);
1114         gtk_widget_set_sensitive(personeditdlg.entry_remarks, !personeditdlg.read_only);
1115         gtk_widget_set_sensitive(personeditdlg.email_up,      !personeditdlg.read_only);
1116         gtk_widget_set_sensitive(personeditdlg.email_down,    !personeditdlg.read_only);
1117         gtk_widget_set_sensitive(personeditdlg.email_del,     !personeditdlg.read_only);
1118         gtk_widget_set_sensitive(personeditdlg.email_mod,     !personeditdlg.read_only);
1119         gtk_widget_set_sensitive(personeditdlg.email_add,     !personeditdlg.read_only);
1120         gtk_widget_set_sensitive(personeditdlg.entry_atname,  !personeditdlg.read_only);
1121         gtk_widget_set_sensitive(personeditdlg.entry_atvalue, !personeditdlg.read_only);
1122         gtk_widget_set_sensitive(personeditdlg.attrib_add,    !personeditdlg.read_only);
1123         gtk_widget_set_sensitive(personeditdlg.attrib_del,    !personeditdlg.read_only);
1124         gtk_widget_set_sensitive(personeditdlg.attrib_mod,    !personeditdlg.read_only);
1125 }
1126
1127 /*
1128 * Edit person.
1129 * Enter: abf    Address book.
1130 *        parent Parent folder for person (or NULL if adding to root folder). Argument is
1131 *               only required for new objects).
1132 *        person Person to edit, or NULL for a new person object.
1133 *        pgMail If TRUE, E-Mail page will be activated.
1134 * Return: Edited object, or NULL if cancelled.
1135 */
1136 ItemPerson *addressbook_edit_person( AddressBookFile *abf, ItemFolder *parent, ItemPerson *person, gboolean pgMail ) {
1137         static gboolean cancelled;
1138         GList *listEMail = NULL;
1139         GList *listAttrib = NULL;
1140         gchar *cn = NULL;
1141
1142         if (!personeditdlg.window)
1143                 addressbook_edit_person_create(&cancelled);
1144         gtk_widget_grab_focus(personeditdlg.ok_btn);
1145         gtk_widget_grab_focus(personeditdlg.entry_name);
1146         
1147         personeditdlg.read_only = (abf == NULL);
1148         update_sensitivity();
1149
1150         gtk_widget_show(personeditdlg.window);
1151         manage_window_set_transient(GTK_WINDOW(personeditdlg.window));
1152
1153         /* Clear all fields */
1154         personeditdlg.rowIndEMail = -1;
1155         personeditdlg.rowIndAttrib = -1;
1156         edit_person_status_show( "" );
1157         gtk_clist_clear( GTK_CLIST(personeditdlg.clist_email) );
1158         gtk_clist_clear( GTK_CLIST(personeditdlg.clist_attrib) );
1159         gtk_entry_set_text(GTK_ENTRY(personeditdlg.entry_name), "" );
1160         gtk_entry_set_text(GTK_ENTRY(personeditdlg.entry_first), "" );
1161         gtk_entry_set_text(GTK_ENTRY(personeditdlg.entry_last), "" );
1162         gtk_entry_set_text(GTK_ENTRY(personeditdlg.entry_nick), "" );
1163
1164         personeditdlg.editNew = FALSE;
1165         if( person ) {
1166                 if( ADDRITEM_NAME(person) )
1167                         gtk_entry_set_text(GTK_ENTRY(personeditdlg.entry_name), ADDRITEM_NAME(person) );
1168                 if( person->firstName )
1169                         gtk_entry_set_text(GTK_ENTRY(personeditdlg.entry_first), person->firstName );
1170                 if( person->lastName )
1171                         gtk_entry_set_text(GTK_ENTRY(personeditdlg.entry_last), person->lastName );
1172                 if( person->nickName )
1173                         gtk_entry_set_text(GTK_ENTRY(personeditdlg.entry_nick), person->nickName );
1174                 edit_person_load_email( person );
1175                 edit_person_load_attrib( person );
1176         }
1177         else {
1178                 personeditdlg.editNew = TRUE;
1179         }
1180
1181         /* Select appropriate start page */
1182         if( pgMail ) {
1183                 gtk_notebook_set_current_page( GTK_NOTEBOOK(personeditdlg.notebook), PAGE_EMAIL );
1184         }
1185         else {
1186                 gtk_notebook_set_current_page( GTK_NOTEBOOK(personeditdlg.notebook), PAGE_BASIC );
1187         }
1188
1189         gtk_clist_select_row( GTK_CLIST(personeditdlg.clist_email), 0, 0 );
1190         gtk_clist_select_row( GTK_CLIST(personeditdlg.clist_attrib), 0, 0 );
1191         edit_person_email_clear( NULL );
1192         if (person)
1193                 edit_person_email_list_selected(GTK_CLIST(personeditdlg.clist_email), 0, 0, NULL, NULL);
1194
1195         edit_person_attrib_clear( NULL );
1196
1197         gtk_main();
1198         gtk_widget_hide( personeditdlg.window );
1199
1200         listEMail = edit_person_build_email_list();
1201         listAttrib = edit_person_build_attrib_list();
1202         if( cancelled ) {
1203                 addritem_free_list_email( listEMail );
1204                 addritem_free_list_attribute( listAttrib );
1205                 gtk_clist_clear( GTK_CLIST(personeditdlg.clist_email) );
1206                 gtk_clist_clear( GTK_CLIST(personeditdlg.clist_attrib) );
1207                 return NULL;
1208         }
1209
1210         cn = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_name), 0, -1 );
1211         if( person && abf ) {
1212                 /* Update email/attribute list for existing person */
1213                 addrbook_update_address_list( abf, person, listEMail );
1214                 addrbook_update_attrib_list( abf, person, listAttrib );
1215         }
1216         else {
1217                 /* Create new person and email/attribute list */
1218                 if( cn == NULL || *cn == '\0' ) {
1219                         /* Wasting our time */
1220                         if( listEMail == NULL && listAttrib == NULL ) cancelled = TRUE;
1221                 }
1222                 if( ! cancelled && abf ) {
1223                         person = addrbook_add_address_list( abf, parent, listEMail );
1224                         addrbook_add_attrib_list( abf, person, listAttrib );
1225                 }
1226         }
1227         listEMail = NULL;
1228         listAttrib = NULL;
1229
1230         if( ! cancelled ) {
1231                 /* Set person stuff */
1232                 gchar *name;
1233                 addritem_person_set_common_name( person, cn );
1234                 name = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_first), 0, -1 );
1235                 addritem_person_set_first_name( person, name );
1236                 g_free( name );
1237                 name = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_last), 0, -1 );
1238                 addritem_person_set_last_name( person, name );
1239                 g_free( name );
1240                 name = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_nick), 0, -1 );
1241                 addritem_person_set_nick_name( person, name );
1242                 g_free( name );
1243         }
1244         g_free( cn );
1245
1246         gtk_clist_clear( GTK_CLIST(personeditdlg.clist_email) );
1247         gtk_clist_clear( GTK_CLIST(personeditdlg.clist_attrib) );
1248
1249         return person;
1250 }
1251
1252 /*
1253 * End of Source.
1254 */
1255