2005-09-08 [colin] 1.9.14cvs9
[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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 static void addressbook_edit_person_dialog_create( gboolean *cancelled ) {
535         GtkWidget *window;
536         GtkWidget *vbox;
537         GtkWidget *vnbox;
538         GtkWidget *notebook;
539         GtkWidget *hbbox;
540         GtkWidget *ok_btn;
541         GtkWidget *cancel_btn;
542         GtkWidget *hsbox;
543         GtkWidget *statusbar;
544
545         window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
546         gtk_widget_set_size_request(window, EDITPERSON_WIDTH, EDITPERSON_HEIGHT );
547         /* gtk_container_set_border_width(GTK_CONTAINER(window), 0); */
548         gtk_window_set_title(GTK_WINDOW(window), _("Edit Person Data"));
549         gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
550         gtk_window_set_modal(GTK_WINDOW(window), TRUE); 
551         g_signal_connect(G_OBJECT(window), "delete_event",
552                          G_CALLBACK(edit_person_delete_event),
553                          cancelled);
554         g_signal_connect(G_OBJECT(window), "key_press_event",
555                          G_CALLBACK(edit_person_key_pressed),
556                          cancelled);
557
558         vbox = gtk_vbox_new(FALSE, 4);
559         /* gtk_container_set_border_width(GTK_CONTAINER(vbox), BORDER_WIDTH); */
560         gtk_widget_show(vbox);
561         gtk_container_add(GTK_CONTAINER(window), vbox);
562
563         vnbox = gtk_vbox_new(FALSE, 4);
564         gtk_container_set_border_width(GTK_CONTAINER(vnbox), 4);
565         gtk_widget_show(vnbox);
566         gtk_box_pack_start(GTK_BOX(vbox), vnbox, TRUE, TRUE, 0);
567
568         /* Notebook */
569         notebook = gtk_notebook_new();
570         gtk_widget_show(notebook);
571         gtk_box_pack_start(GTK_BOX(vnbox), notebook, TRUE, TRUE, 0);
572         gtk_container_set_border_width(GTK_CONTAINER(notebook), 6);
573
574         /* Status line */
575         hsbox = gtk_hbox_new(FALSE, 0);
576         gtk_box_pack_end(GTK_BOX(vbox), hsbox, FALSE, FALSE, BORDER_WIDTH);
577         statusbar = gtk_statusbar_new();
578         gtk_box_pack_start(GTK_BOX(hsbox), statusbar, TRUE, TRUE, BORDER_WIDTH);
579
580         /* Button panel */
581         gtkut_stock_button_set_create(&hbbox, &ok_btn, GTK_STOCK_OK,
582                                       &cancel_btn, GTK_STOCK_CANCEL,
583                                       NULL, NULL);
584         gtk_box_pack_end(GTK_BOX(vnbox), hbbox, FALSE, FALSE, 0);
585         gtk_widget_grab_default(ok_btn);
586
587         g_signal_connect(G_OBJECT(ok_btn), "clicked",
588                          G_CALLBACK(edit_person_ok), cancelled);
589         g_signal_connect(G_OBJECT(cancel_btn), "clicked",
590                          G_CALLBACK(edit_person_cancel), cancelled);
591         g_signal_connect(G_OBJECT(notebook), "switch_page",
592                          G_CALLBACK(edit_person_switch_page), NULL );
593
594         gtk_widget_show_all(vbox);
595
596         personeditdlg.window     = window;
597         personeditdlg.notebook   = notebook;
598         personeditdlg.ok_btn     = ok_btn;
599         personeditdlg.cancel_btn = cancel_btn;
600         personeditdlg.statusbar  = statusbar;
601         personeditdlg.status_cid = gtk_statusbar_get_context_id( GTK_STATUSBAR(statusbar), "Edit Person Dialog" );
602
603 }
604
605 static void addressbook_edit_person_page_basic( gint pageNum, gchar *pageLbl ) {
606         GtkWidget *vbox;
607         GtkWidget *table;
608         GtkWidget *label;
609         GtkWidget *entry_name;
610         GtkWidget *entry_fn;
611         GtkWidget *entry_ln;
612         GtkWidget *entry_nn;
613         const gchar *locale;
614         gint top = 0;
615
616         vbox = gtk_vbox_new( FALSE, 8 );
617         gtk_widget_show( vbox );
618         gtk_container_add( GTK_CONTAINER( personeditdlg.notebook ), vbox );
619         gtk_container_set_border_width( GTK_CONTAINER (vbox), BORDER_WIDTH );
620
621         label = gtk_label_new( pageLbl );
622         gtk_widget_show( label );
623         gtk_notebook_set_tab_label(
624                 GTK_NOTEBOOK( personeditdlg.notebook ),
625                 gtk_notebook_get_nth_page( GTK_NOTEBOOK( personeditdlg.notebook ), pageNum ), label );
626
627         table = gtk_table_new( 4, 3, FALSE);
628         gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0);
629         gtk_container_set_border_width( GTK_CONTAINER(table), 8 );
630         gtk_table_set_row_spacings(GTK_TABLE(table), 8);
631         gtk_table_set_col_spacings(GTK_TABLE(table), 8);
632
633 #define ATTACH_ROW(text, entry) \
634 { \
635         label = gtk_label_new(text); \
636         gtk_table_attach(GTK_TABLE(table), label, 0, 1, top, (top + 1), \
637                          GTK_FILL, 0, 0, 0); \
638         gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); \
639  \
640         entry = gtk_entry_new(); \
641         gtk_table_attach(GTK_TABLE(table), entry, 1, 2, top, (top + 1), \
642                          GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0); \
643         top++; \
644 }
645
646         ATTACH_ROW(_("Display Name"), entry_name);
647         locale = conv_get_current_locale();
648         if (locale &&
649             (!g_ascii_strncasecmp(locale, "ja", 2) ||
650              !g_ascii_strncasecmp(locale, "ko", 2) ||
651              !g_ascii_strncasecmp(locale, "zh", 2))) {
652                 ATTACH_ROW(_("Last Name"), entry_ln);
653                 ATTACH_ROW(_("First Name"), entry_fn);
654         } else {
655                 ATTACH_ROW(_("First Name"), entry_fn);
656                 ATTACH_ROW(_("Last Name"), entry_ln);
657         }
658         ATTACH_ROW(_("Nickname"), entry_nn);
659
660 #undef ATTACH_ROW
661
662         gtk_widget_show_all(vbox);
663
664         personeditdlg.entry_name  = entry_name;
665         personeditdlg.entry_first = entry_fn;
666         personeditdlg.entry_last  = entry_ln;
667         personeditdlg.entry_nick  = entry_nn;
668 }
669
670 static gboolean email_adding = FALSE, email_saving = FALSE;
671
672 static void edit_person_entry_email_changed (GtkWidget *entry, gpointer data)
673 {
674         gboolean non_empty = gtk_clist_get_row_data(GTK_CLIST(personeditdlg.clist_email), 0) != NULL;
675
676         if (personeditdlg.read_only)
677                 return;
678
679         if (gtk_entry_get_text(GTK_ENTRY(personeditdlg.entry_email)) == NULL
680         ||  strlen(gtk_entry_get_text(GTK_ENTRY(personeditdlg.entry_email))) == 0) {
681                 gtk_widget_set_sensitive(personeditdlg.email_add,FALSE);
682                 gtk_widget_set_sensitive(personeditdlg.email_mod,FALSE);
683                 email_adding = FALSE;
684                 email_saving = FALSE;
685         } else if (list_find_email(gtk_entry_get_text(GTK_ENTRY(personeditdlg.entry_email)))) {
686                 gtk_widget_set_sensitive(personeditdlg.email_add,FALSE);
687                 gtk_widget_set_sensitive(personeditdlg.email_mod,non_empty);
688                 email_adding = FALSE;
689                 email_saving = non_empty;
690         } else {
691                 gtk_widget_set_sensitive(personeditdlg.email_add,TRUE);
692                 gtk_widget_set_sensitive(personeditdlg.email_mod,non_empty);
693                 email_adding = TRUE;
694                 email_saving = non_empty;
695         }
696 }
697
698 static gboolean edit_person_entry_email_pressed(GtkWidget *widget, GdkEventKey *event, gpointer data)
699 {
700         if (event && event->keyval == GDK_Return) {
701                 if (email_saving)
702                         edit_person_email_modify(NULL);         
703                 else if (email_adding)
704                         edit_person_email_add(NULL);
705         }
706         return FALSE;
707 }
708
709
710 static void addressbook_edit_person_page_email( gint pageNum, gchar *pageLbl ) {
711         GtkWidget *vbox;
712         GtkWidget *hbox;
713         GtkWidget *vboxl;
714         GtkWidget *vboxb;
715         GtkWidget *vbuttonbox;
716         GtkWidget *buttonUp;
717         GtkWidget *buttonDown;
718         GtkWidget *buttonDel;
719         GtkWidget *buttonMod;
720         GtkWidget *buttonAdd;
721
722         GtkWidget *table;
723         GtkWidget *label;
724         GtkWidget *clist_swin;
725         GtkWidget *clist;
726         GtkWidget *entry_email;
727         GtkWidget *entry_alias;
728         GtkWidget *entry_remarks;
729         gint top;
730
731         gchar *titles[ EMAIL_N_COLS ];
732         gint i;
733
734         titles[ EMAIL_COL_EMAIL   ] = _("E-Mail Address");
735         titles[ EMAIL_COL_ALIAS   ] = _("Alias");
736         titles[ EMAIL_COL_REMARKS ] = _("Remarks");
737
738         vbox = gtk_vbox_new( FALSE, 8 );
739         gtk_widget_show( vbox );
740         gtk_container_add( GTK_CONTAINER( personeditdlg.notebook ), vbox );
741         gtk_container_set_border_width( GTK_CONTAINER (vbox), BORDER_WIDTH );
742
743         label = gtk_label_new( pageLbl );
744         gtk_widget_show( label );
745         gtk_notebook_set_tab_label(
746                 GTK_NOTEBOOK( personeditdlg.notebook ),
747                 gtk_notebook_get_nth_page( GTK_NOTEBOOK( personeditdlg.notebook ), pageNum ), label );
748
749         /* Split into two areas */
750         hbox = gtk_hbox_new( FALSE, 0 );
751         gtk_container_add( GTK_CONTAINER( vbox ), hbox );
752
753         /* Address list */
754         vboxl = gtk_vbox_new( FALSE, 4 );
755         gtk_container_add( GTK_CONTAINER( hbox ), vboxl );
756         gtk_container_set_border_width( GTK_CONTAINER(vboxl), 4 );
757
758         clist_swin = gtk_scrolled_window_new( NULL, NULL );
759         gtk_container_add( GTK_CONTAINER(vboxl), clist_swin );
760         gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(clist_swin),
761                                        GTK_POLICY_AUTOMATIC,
762                                        GTK_POLICY_AUTOMATIC);
763
764         clist = gtk_clist_new_with_titles( EMAIL_N_COLS, titles );
765         gtk_container_add( GTK_CONTAINER(clist_swin), clist );
766         gtk_clist_set_selection_mode( GTK_CLIST(clist), GTK_SELECTION_BROWSE );
767         gtk_clist_set_column_width( GTK_CLIST(clist), EMAIL_COL_EMAIL, EMAIL_COL_WIDTH_EMAIL );
768         gtk_clist_set_column_width( GTK_CLIST(clist), EMAIL_COL_ALIAS, EMAIL_COL_WIDTH_ALIAS );
769
770         for( i = 0; i < EMAIL_N_COLS; i++ )
771                 GTK_WIDGET_UNSET_FLAGS(GTK_CLIST(clist)->column[i].button, GTK_CAN_FOCUS);
772
773         /* Data entry area */
774         table = gtk_table_new( 4, 2, FALSE);
775         gtk_box_pack_start(GTK_BOX(vboxl), table, FALSE, FALSE, 0);
776         gtk_container_set_border_width( GTK_CONTAINER(table), 4 );
777         gtk_table_set_row_spacings(GTK_TABLE(table), 4);
778         gtk_table_set_col_spacings(GTK_TABLE(table), 4);
779
780         /* First row */
781         top = 0;
782         label = gtk_label_new(_("E-Mail Address"));
783         gtk_table_attach(GTK_TABLE(table), label, 0, 1, top, (top + 1), GTK_FILL, 0, 0, 0);
784         gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
785
786         entry_email = gtk_entry_new();
787         gtk_table_attach(GTK_TABLE(table), entry_email, 1, 2, top, (top + 1), GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
788
789         /* Next row */
790         ++top;
791         label = gtk_label_new(_("Alias"));
792         gtk_table_attach(GTK_TABLE(table), label, 0, 1, top, (top + 1), GTK_FILL, 0, 0, 0);
793         gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
794
795         entry_alias = gtk_entry_new();
796         gtk_table_attach(GTK_TABLE(table), entry_alias, 1, 2, top, (top + 1), GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
797
798         /* Next row */
799         ++top;
800         label = gtk_label_new(_("Remarks"));
801         gtk_table_attach(GTK_TABLE(table), label, 0, 1, top, (top + 1), GTK_FILL, 0, 0, 0);
802         gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
803
804         entry_remarks = gtk_entry_new();
805         gtk_table_attach(GTK_TABLE(table), entry_remarks, 1, 2, top, (top + 1), GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
806
807         /* Button box */
808         vboxb = gtk_vbox_new( FALSE, 4 );
809         gtk_box_pack_start(GTK_BOX(hbox), vboxb, FALSE, FALSE, 2);
810
811         vbuttonbox = gtk_vbutton_box_new();
812         gtk_button_box_set_layout( GTK_BUTTON_BOX(vbuttonbox), GTK_BUTTONBOX_START );
813         gtk_box_set_spacing( GTK_BOX(vbuttonbox), 8 );
814         gtk_container_set_border_width( GTK_CONTAINER(vbuttonbox), 4 );
815         gtk_container_add( GTK_CONTAINER(vboxb), vbuttonbox );
816
817         /* Buttons */
818         buttonUp = gtk_button_new_from_stock(GTK_STOCK_GO_UP);
819         gtk_container_add( GTK_CONTAINER(vbuttonbox), buttonUp );
820
821         buttonDown = gtk_button_new_from_stock(GTK_STOCK_GO_DOWN);
822         gtk_container_add( GTK_CONTAINER(vbuttonbox), buttonDown );
823
824         buttonDel = gtk_button_new_from_stock(GTK_STOCK_DELETE);
825         gtk_container_add( GTK_CONTAINER(vbuttonbox), buttonDel );
826
827         buttonMod = gtk_button_new_from_stock(GTK_STOCK_SAVE);
828         gtk_container_add( GTK_CONTAINER(vbuttonbox), buttonMod );
829
830         buttonAdd = gtk_button_new_from_stock(GTK_STOCK_ADD);
831         gtk_container_add( GTK_CONTAINER(vbuttonbox), buttonAdd );
832
833         gtk_widget_show_all(vbox);
834
835         /* Event handlers */
836         g_signal_connect( G_OBJECT(clist), "select_row",
837                           G_CALLBACK( edit_person_email_list_selected), NULL );
838         g_signal_connect( G_OBJECT(buttonUp), "clicked",
839                           G_CALLBACK( edit_person_email_move_up ), NULL );
840         g_signal_connect( G_OBJECT(buttonDown), "clicked",
841                           G_CALLBACK( edit_person_email_move_down ), NULL );
842         g_signal_connect( G_OBJECT(buttonDel), "clicked",
843                           G_CALLBACK( edit_person_email_delete ), NULL );
844         g_signal_connect( G_OBJECT(buttonMod), "clicked",
845                           G_CALLBACK( edit_person_email_modify ), NULL );
846         g_signal_connect( G_OBJECT(buttonAdd), "clicked",
847                           G_CALLBACK( edit_person_email_add ), NULL );
848         g_signal_connect(G_OBJECT(entry_email), "changed",
849                          G_CALLBACK(edit_person_entry_email_changed), NULL);
850         g_signal_connect(G_OBJECT(entry_email), "key_press_event",
851                          G_CALLBACK(edit_person_entry_email_pressed), NULL);
852         g_signal_connect(G_OBJECT(entry_alias), "key_press_event",
853                          G_CALLBACK(edit_person_entry_email_pressed), NULL);
854         g_signal_connect(G_OBJECT(entry_remarks), "key_press_event",
855                          G_CALLBACK(edit_person_entry_email_pressed), NULL);
856
857         personeditdlg.clist_email   = clist;
858         personeditdlg.entry_email   = entry_email;
859         personeditdlg.entry_alias   = entry_alias;
860         personeditdlg.entry_remarks = entry_remarks;
861         personeditdlg.email_up = buttonUp;
862         personeditdlg.email_down = buttonDown;
863         personeditdlg.email_del = buttonDel;
864         personeditdlg.email_mod = buttonMod;
865         personeditdlg.email_add = buttonAdd;
866 }
867
868 static gboolean attrib_adding = FALSE, attrib_saving = FALSE;
869
870 static void edit_person_entry_att_changed (GtkWidget *entry, gpointer data)
871 {
872         gboolean non_empty = gtk_clist_get_row_data(GTK_CLIST(personeditdlg.clist_attrib), 0) != NULL;
873
874         if (personeditdlg.read_only)
875                 return;
876
877         if (gtk_entry_get_text(GTK_ENTRY(personeditdlg.entry_atname)) == NULL
878         ||  strlen(gtk_entry_get_text(GTK_ENTRY(personeditdlg.entry_atname))) == 0) {
879                 gtk_widget_set_sensitive(personeditdlg.attrib_add,FALSE);
880                 gtk_widget_set_sensitive(personeditdlg.attrib_mod,FALSE);
881                 attrib_adding = FALSE;
882                 attrib_saving = FALSE;
883         } else if (list_find_attribute(gtk_entry_get_text(GTK_ENTRY(personeditdlg.entry_atname)))) {
884                 gtk_widget_set_sensitive(personeditdlg.attrib_add,FALSE);
885                 gtk_widget_set_sensitive(personeditdlg.attrib_mod,non_empty);
886                 attrib_adding = FALSE;
887                 attrib_saving = non_empty;
888         } else {
889                 gtk_widget_set_sensitive(personeditdlg.attrib_add,TRUE);
890                 gtk_widget_set_sensitive(personeditdlg.attrib_mod,non_empty);
891                 attrib_adding = TRUE;
892                 attrib_saving = non_empty;
893         }
894 }
895
896 static gboolean edit_person_entry_att_pressed(GtkWidget *widget, GdkEventKey *event, gpointer data)
897 {
898         if (event && event->keyval == GDK_Return) {
899                 if (attrib_saving)
900                         edit_person_attrib_modify(NULL);
901                 else if (attrib_adding)
902                         edit_person_attrib_add(NULL);
903         }
904         return FALSE;
905 }
906
907 static void addressbook_edit_person_page_attrib( gint pageNum, gchar *pageLbl ) {
908         GtkWidget *vbox;
909         GtkWidget *hbox;
910         GtkWidget *vboxl;
911         GtkWidget *vboxb;
912         GtkWidget *vbuttonbox;
913         GtkWidget *buttonDel;
914         GtkWidget *buttonMod;
915         GtkWidget *buttonAdd;
916
917         GtkWidget *table;
918         GtkWidget *label;
919         GtkWidget *clist_swin;
920         GtkWidget *clist;
921         GtkWidget *entry_name;
922         GtkWidget *entry_value;
923         gint top;
924
925         gchar *titles[ ATTRIB_N_COLS ];
926         gint i;
927
928         titles[ ATTRIB_COL_NAME  ] = _("Name");
929         titles[ ATTRIB_COL_VALUE ] = _("Value");
930
931         vbox = gtk_vbox_new( FALSE, 8 );
932         gtk_widget_show( vbox );
933         gtk_container_add( GTK_CONTAINER( personeditdlg.notebook ), vbox );
934         gtk_container_set_border_width( GTK_CONTAINER (vbox), BORDER_WIDTH );
935
936         label = gtk_label_new( pageLbl );
937         gtk_widget_show( label );
938         gtk_notebook_set_tab_label(
939                 GTK_NOTEBOOK( personeditdlg.notebook ),
940                 gtk_notebook_get_nth_page( GTK_NOTEBOOK( personeditdlg.notebook ), pageNum ), label );
941
942         /* Split into two areas */
943         hbox = gtk_hbox_new( FALSE, 0 );
944         gtk_container_add( GTK_CONTAINER( vbox ), hbox );
945
946         /* Attribute list */
947         vboxl = gtk_vbox_new( FALSE, 4 );
948         gtk_container_add( GTK_CONTAINER( hbox ), vboxl );
949         gtk_container_set_border_width( GTK_CONTAINER(vboxl), 4 );
950
951         clist_swin = gtk_scrolled_window_new( NULL, NULL );
952         gtk_container_add( GTK_CONTAINER(vboxl), clist_swin );
953         gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(clist_swin),
954                                        GTK_POLICY_AUTOMATIC,
955                                        GTK_POLICY_AUTOMATIC);
956
957         clist = gtk_clist_new_with_titles( ATTRIB_N_COLS, titles );
958         gtk_container_add( GTK_CONTAINER(clist_swin), clist );
959         gtk_clist_set_selection_mode( GTK_CLIST(clist), GTK_SELECTION_BROWSE );
960         gtk_clist_set_column_width( GTK_CLIST(clist), ATTRIB_COL_NAME, ATTRIB_COL_WIDTH_NAME );
961         gtk_clist_set_column_width( GTK_CLIST(clist), ATTRIB_COL_VALUE, ATTRIB_COL_WIDTH_VALUE );
962         gtk_clist_set_compare_func( GTK_CLIST(clist), edit_person_attrib_compare_func );
963         gtk_clist_set_auto_sort( GTK_CLIST(clist), TRUE );
964
965         for( i = 0; i < ATTRIB_N_COLS; i++ )
966                 GTK_WIDGET_UNSET_FLAGS(GTK_CLIST(clist)->column[i].button, GTK_CAN_FOCUS);
967
968         /* Data entry area */
969         table = gtk_table_new( 4, 2, FALSE);
970         gtk_box_pack_start(GTK_BOX(vboxl), table, FALSE, FALSE, 0);
971         gtk_container_set_border_width( GTK_CONTAINER(table), 4 );
972         gtk_table_set_row_spacings(GTK_TABLE(table), 4);
973         gtk_table_set_col_spacings(GTK_TABLE(table), 4);
974
975         /* First row */
976         top = 0;
977         label = gtk_label_new(_("Name"));
978         gtk_table_attach(GTK_TABLE(table), label, 0, 1, top, (top + 1), GTK_FILL, 0, 0, 0);
979         gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
980
981         entry_name = gtk_entry_new();
982         gtk_table_attach(GTK_TABLE(table), entry_name, 1, 2, top, (top + 1), GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
983
984         /* Next row */
985         ++top;
986         label = gtk_label_new(_("Value"));
987         gtk_table_attach(GTK_TABLE(table), label, 0, 1, top, (top + 1), GTK_FILL, 0, 0, 0);
988         gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
989
990         entry_value = gtk_entry_new();
991         gtk_table_attach(GTK_TABLE(table), entry_value, 1, 2, top, (top + 1), GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
992
993         /* Button box */
994         vboxb = gtk_vbox_new( FALSE, 4 );
995         gtk_box_pack_start(GTK_BOX(hbox), vboxb, FALSE, FALSE, 2);
996
997         vbuttonbox = gtk_vbutton_box_new();
998         gtk_button_box_set_layout( GTK_BUTTON_BOX(vbuttonbox), GTK_BUTTONBOX_START );
999         gtk_box_set_spacing( GTK_BOX(vbuttonbox), 8 );
1000         gtk_container_set_border_width( GTK_CONTAINER(vbuttonbox), 4 );
1001         gtk_container_add( GTK_CONTAINER(vboxb), vbuttonbox );
1002
1003         /* Buttons */
1004         buttonDel = gtk_button_new_from_stock(GTK_STOCK_DELETE);
1005         gtk_container_add( GTK_CONTAINER(vbuttonbox), buttonDel );
1006
1007         buttonMod = gtk_button_new_from_stock(GTK_STOCK_SAVE);
1008         gtk_container_add( GTK_CONTAINER(vbuttonbox), buttonMod );
1009
1010         buttonAdd = gtk_button_new_from_stock(GTK_STOCK_ADD);
1011         gtk_container_add( GTK_CONTAINER(vbuttonbox), buttonAdd );
1012         
1013         gtk_widget_set_sensitive(buttonDel,FALSE);
1014         gtk_widget_set_sensitive(buttonMod,FALSE);
1015         gtk_widget_set_sensitive(buttonAdd,FALSE);
1016
1017         gtk_widget_show_all(vbox);
1018
1019         /* Event handlers */
1020         g_signal_connect( G_OBJECT(clist), "select_row",
1021                           G_CALLBACK( edit_person_attrib_list_selected), NULL );
1022         g_signal_connect( G_OBJECT(buttonDel), "clicked",
1023                           G_CALLBACK( edit_person_attrib_delete ), NULL );
1024         g_signal_connect( G_OBJECT(buttonMod), "clicked",
1025                           G_CALLBACK( edit_person_attrib_modify ), NULL );
1026         g_signal_connect( G_OBJECT(buttonAdd), "clicked",
1027                           G_CALLBACK( edit_person_attrib_add ), NULL );
1028         g_signal_connect(G_OBJECT(entry_name), "changed",
1029                          G_CALLBACK(edit_person_entry_att_changed), NULL);
1030         g_signal_connect(G_OBJECT(entry_name), "key_press_event",
1031                          G_CALLBACK(edit_person_entry_att_pressed), NULL);
1032         g_signal_connect(G_OBJECT(entry_value), "key_press_event",
1033                          G_CALLBACK(edit_person_entry_att_pressed), NULL);
1034
1035         personeditdlg.clist_attrib  = clist;
1036         personeditdlg.entry_atname  = entry_name;
1037         personeditdlg.entry_atvalue = entry_value;
1038         personeditdlg.attrib_add = buttonAdd;
1039         personeditdlg.attrib_del = buttonDel;
1040         personeditdlg.attrib_mod = buttonMod;
1041 }
1042
1043 static void addressbook_edit_person_create( gboolean *cancelled ) {
1044         addressbook_edit_person_dialog_create( cancelled );
1045         addressbook_edit_person_page_basic( PAGE_BASIC, _( "User Data" ) );
1046         addressbook_edit_person_page_email( PAGE_EMAIL, _( "E-Mail Addresses" ) );
1047         addressbook_edit_person_page_attrib( PAGE_ATTRIBUTES, _( "Other Attributes" ) );
1048         gtk_widget_show_all( personeditdlg.window );
1049 }
1050
1051 /*
1052 * Return list of email items.
1053 */
1054 static GList *edit_person_build_email_list() {
1055         GtkCList *clist = GTK_CLIST(personeditdlg.clist_email);
1056         GList *listEMail = NULL;
1057         ItemEMail *email;
1058         gint row = 0;
1059         while( (email = gtk_clist_get_row_data( clist, row )) ) {
1060                 listEMail = g_list_append( listEMail, email );
1061                 row++;
1062         }
1063         return listEMail;
1064 }
1065
1066 /*
1067 * Return list of attributes.
1068 */
1069 static GList *edit_person_build_attrib_list() {
1070         GtkCList *clist = GTK_CLIST(personeditdlg.clist_attrib);
1071         GList *listAttrib = NULL;
1072         UserAttribute *attrib;
1073         gint row = 0;
1074         while( (attrib = gtk_clist_get_row_data( clist, row )) ) {
1075                 listAttrib = g_list_append( listAttrib, attrib );
1076                 row++;
1077         }
1078         return listAttrib;
1079 }
1080
1081 static void update_sensitivity(void)
1082 {
1083         gtk_widget_set_sensitive(personeditdlg.entry_name,    !personeditdlg.read_only);
1084         gtk_widget_set_sensitive(personeditdlg.entry_first,   !personeditdlg.read_only);
1085         gtk_widget_set_sensitive(personeditdlg.entry_last,    !personeditdlg.read_only);
1086         gtk_widget_set_sensitive(personeditdlg.entry_nick,    !personeditdlg.read_only);
1087         gtk_widget_set_sensitive(personeditdlg.entry_email,   !personeditdlg.read_only);
1088         gtk_widget_set_sensitive(personeditdlg.entry_alias,   !personeditdlg.read_only);
1089         gtk_widget_set_sensitive(personeditdlg.entry_remarks, !personeditdlg.read_only);
1090         gtk_widget_set_sensitive(personeditdlg.email_up,      !personeditdlg.read_only);
1091         gtk_widget_set_sensitive(personeditdlg.email_down,    !personeditdlg.read_only);
1092         gtk_widget_set_sensitive(personeditdlg.email_del,     !personeditdlg.read_only);
1093         gtk_widget_set_sensitive(personeditdlg.email_mod,     !personeditdlg.read_only);
1094         gtk_widget_set_sensitive(personeditdlg.email_add,     !personeditdlg.read_only);
1095         gtk_widget_set_sensitive(personeditdlg.entry_atname,  !personeditdlg.read_only);
1096         gtk_widget_set_sensitive(personeditdlg.entry_atvalue, !personeditdlg.read_only);
1097         gtk_widget_set_sensitive(personeditdlg.attrib_add,    !personeditdlg.read_only);
1098         gtk_widget_set_sensitive(personeditdlg.attrib_del,    !personeditdlg.read_only);
1099         gtk_widget_set_sensitive(personeditdlg.attrib_mod,    !personeditdlg.read_only);
1100 }
1101
1102 /*
1103 * Edit person.
1104 * Enter: abf    Address book.
1105 *        parent Parent folder for person (or NULL if adding to root folder). Argument is
1106 *               only required for new objects).
1107 *        person Person to edit, or NULL for a new person object.
1108 *        pgMail If TRUE, E-Mail page will be activated.
1109 * Return: Edited object, or NULL if cancelled.
1110 */
1111 ItemPerson *addressbook_edit_person( AddressBookFile *abf, ItemFolder *parent, ItemPerson *person, gboolean pgMail ) {
1112         static gboolean cancelled;
1113         GList *listEMail = NULL;
1114         GList *listAttrib = NULL;
1115         gchar *cn = NULL;
1116
1117         if (!personeditdlg.window)
1118                 addressbook_edit_person_create(&cancelled);
1119         gtk_widget_grab_focus(personeditdlg.ok_btn);
1120         gtk_widget_grab_focus(personeditdlg.entry_name);
1121         
1122         personeditdlg.read_only = (abf == NULL);
1123         update_sensitivity();
1124
1125         gtk_widget_show(personeditdlg.window);
1126         manage_window_set_transient(GTK_WINDOW(personeditdlg.window));
1127
1128         /* Clear all fields */
1129         personeditdlg.rowIndEMail = -1;
1130         personeditdlg.rowIndAttrib = -1;
1131         edit_person_status_show( "" );
1132         gtk_clist_clear( GTK_CLIST(personeditdlg.clist_email) );
1133         gtk_clist_clear( GTK_CLIST(personeditdlg.clist_attrib) );
1134         gtk_entry_set_text(GTK_ENTRY(personeditdlg.entry_name), "" );
1135         gtk_entry_set_text(GTK_ENTRY(personeditdlg.entry_first), "" );
1136         gtk_entry_set_text(GTK_ENTRY(personeditdlg.entry_last), "" );
1137         gtk_entry_set_text(GTK_ENTRY(personeditdlg.entry_nick), "" );
1138
1139         personeditdlg.editNew = FALSE;
1140         if( person ) {
1141                 if( ADDRITEM_NAME(person) )
1142                         gtk_entry_set_text(GTK_ENTRY(personeditdlg.entry_name), ADDRITEM_NAME(person) );
1143                 if( person->firstName )
1144                         gtk_entry_set_text(GTK_ENTRY(personeditdlg.entry_first), person->firstName );
1145                 if( person->lastName )
1146                         gtk_entry_set_text(GTK_ENTRY(personeditdlg.entry_last), person->lastName );
1147                 if( person->nickName )
1148                         gtk_entry_set_text(GTK_ENTRY(personeditdlg.entry_nick), person->nickName );
1149                 edit_person_load_email( person );
1150                 edit_person_load_attrib( person );
1151         }
1152         else {
1153                 personeditdlg.editNew = TRUE;
1154         }
1155
1156         /* Select appropriate start page */
1157         if( pgMail ) {
1158                 gtk_notebook_set_current_page( GTK_NOTEBOOK(personeditdlg.notebook), PAGE_EMAIL );
1159         }
1160         else {
1161                 gtk_notebook_set_current_page( GTK_NOTEBOOK(personeditdlg.notebook), PAGE_BASIC );
1162         }
1163
1164         gtk_clist_select_row( GTK_CLIST(personeditdlg.clist_email), 0, 0 );
1165         gtk_clist_select_row( GTK_CLIST(personeditdlg.clist_attrib), 0, 0 );
1166         edit_person_email_clear( NULL );
1167         if (person)
1168                 edit_person_email_list_selected(GTK_CLIST(personeditdlg.clist_email), 0, 0, NULL, NULL);
1169
1170         edit_person_attrib_clear( NULL );
1171
1172         gtk_main();
1173         gtk_widget_hide( personeditdlg.window );
1174
1175         listEMail = edit_person_build_email_list();
1176         listAttrib = edit_person_build_attrib_list();
1177         if( cancelled ) {
1178                 addritem_free_list_email( listEMail );
1179                 addritem_free_list_attribute( listAttrib );
1180                 gtk_clist_clear( GTK_CLIST(personeditdlg.clist_email) );
1181                 gtk_clist_clear( GTK_CLIST(personeditdlg.clist_attrib) );
1182                 return NULL;
1183         }
1184
1185         cn = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_name), 0, -1 );
1186         if( person && abf ) {
1187                 /* Update email/attribute list for existing person */
1188                 addrbook_update_address_list( abf, person, listEMail );
1189                 addrbook_update_attrib_list( abf, person, listAttrib );
1190         }
1191         else {
1192                 /* Create new person and email/attribute list */
1193                 if( cn == NULL || *cn == '\0' ) {
1194                         /* Wasting our time */
1195                         if( listEMail == NULL && listAttrib == NULL ) cancelled = TRUE;
1196                 }
1197                 if( ! cancelled && abf ) {
1198                         person = addrbook_add_address_list( abf, parent, listEMail );
1199                         addrbook_add_attrib_list( abf, person, listAttrib );
1200                 }
1201         }
1202         listEMail = NULL;
1203         listAttrib = NULL;
1204
1205         if( ! cancelled ) {
1206                 /* Set person stuff */
1207                 gchar *name;
1208                 addritem_person_set_common_name( person, cn );
1209                 name = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_first), 0, -1 );
1210                 addritem_person_set_first_name( person, name );
1211                 g_free( name );
1212                 name = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_last), 0, -1 );
1213                 addritem_person_set_last_name( person, name );
1214                 g_free( name );
1215                 name = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_nick), 0, -1 );
1216                 addritem_person_set_nick_name( person, name );
1217                 g_free( name );
1218         }
1219         g_free( cn );
1220
1221         gtk_clist_clear( GTK_CLIST(personeditdlg.clist_email) );
1222         gtk_clist_clear( GTK_CLIST(personeditdlg.clist_attrib) );
1223
1224         return person;
1225 }
1226
1227 /*
1228 * End of Source.
1229 */
1230