Statistics
| Revision:

root / src / addressbook.c @ 1

History | View | Annotate | Download (103 KB)

1
/*
2
 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3
 * Copyright (C) 1999-2002 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 <gdk/gdkkeysyms.h>
28
#include <gtk/gtkwindow.h>
29
#include <gtk/gtksignal.h>
30
#include <gtk/gtkvbox.h>
31
#include <gtk/gtkscrolledwindow.h>
32
#include <gtk/gtkhpaned.h>
33
#include <gtk/gtkhbox.h>
34
#include <gtk/gtklabel.h>
35
#include <gtk/gtkentry.h>
36
#include <gtk/gtkctree.h>
37
#include <gtk/gtkclist.h>
38
#include <gtk/gtktable.h>
39
#include <gtk/gtkhbbox.h>
40
#include <gtk/gtkbutton.h>
41
#include <gtk/gtkmenu.h>
42
#include <gtk/gtkmenuitem.h>
43
#include <gtk/gtkitemfactory.h>
44
#include <string.h>
45
#include <setjmp.h>
46

    
47
#include "intl.h"
48
#include "main.h"
49
#include "addressbook.h"
50
#include "manage_window.h"
51
#include "prefs_common.h"
52
#include "alertpanel.h"
53
#include "inputdialog.h"
54
#include "menu.h"
55
#include "stock_pixmap.h"
56
#include "xml.h"
57
#include "prefs.h"
58
#include "procmime.h"
59
#include "utils.h"
60
#include "gtkutils.h"
61
#include "codeconv.h"
62
#include "about.h"
63
#include "addr_compl.h"
64

    
65
#include "mgutils.h"
66
#include "addressitem.h"
67
#include "addritem.h"
68
#include "addrcache.h"
69
#include "addrbook.h"
70
#include "addrindex.h"
71
#include "addressadd.h"
72
#include "vcard.h"
73
#include "editvcard.h"
74
#include "editgroup.h"
75
#include "editaddress.h"
76
#include "editbook.h"
77
#include "ldif.h"
78
#include "importldif.h"
79

    
80
#ifdef USE_JPILOT
81
#include "jpilot.h"
82
#include "editjpilot.h"
83
#endif
84

    
85
#ifdef USE_LDAP
86
#include <pthread.h>
87
#include "syldap.h"
88
#include "editldap.h"
89

    
90
#define ADDRESSBOOK_LDAP_BUSYMSG "Busy"
91
#endif
92

    
93
typedef enum
94
{
95
        COL_NAME        = 0,
96
        COL_ADDRESS        = 1,
97
        COL_REMARKS        = 2
98
} AddressBookColumnPos;
99

    
100
#define N_COLS        3
101
#define COL_NAME_WIDTH                164
102
#define COL_ADDRESS_WIDTH        156
103

    
104
#define COL_FOLDER_WIDTH        170
105
#define ADDRESSBOOK_WIDTH        640
106
#define ADDRESSBOOK_HEIGHT        360
107

    
108
#define ADDRESSBOOK_MSGBUF_SIZE 2048
109

    
110
static GdkPixmap *folderxpm;
111
static GdkBitmap *folderxpmmask;
112
static GdkPixmap *folderopenxpm;
113
static GdkBitmap *folderopenxpmmask;
114
static GdkPixmap *groupxpm;
115
static GdkBitmap *groupxpmmask;
116
static GdkPixmap *interfacexpm;
117
static GdkBitmap *interfacexpmmask;
118
static GdkPixmap *bookxpm;
119
static GdkBitmap *bookxpmmask;
120
static GdkPixmap *addressxpm;
121
static GdkBitmap *addressxpmmask;
122
static GdkPixmap *vcardxpm;
123
static GdkBitmap *vcardxpmmask;
124
static GdkPixmap *jpilotxpm;
125
static GdkBitmap *jpilotxpmmask;
126
static GdkPixmap *categoryxpm;
127
static GdkBitmap *categoryxpmmask;
128
static GdkPixmap *ldapxpm;
129
static GdkBitmap *ldapxpmmask;
130

    
131
/* Message buffer */
132
static gchar addressbook_msgbuf[ ADDRESSBOOK_MSGBUF_SIZE ];
133

    
134
/* Address list selection */
135
static GList *_addressListSelection_ = NULL;
136

    
137
/* Address index file and interfaces */
138
static AddressIndex *_addressIndex_ = NULL;
139
static GList *_addressInterfaceList_ = NULL;
140
static GList *_addressIFaceSelection_ = NULL;
141
#define ADDRESSBOOK_IFACE_SELECTION "1/y,3/y,4/y,2/n"
142

    
143
static AddressBook_win addrbook;
144

    
145
static GHashTable *_addressBookTypeHash_ = NULL;
146
static GList *_addressBookTypeList_ = NULL;
147

    
148
static void addressbook_create                        (void);
149
static gint addressbook_close                        (void);
150
static void addressbook_button_set_sensitive        (void);
151

    
152
/* callback functions */
153
static void addressbook_del_clicked                (GtkButton        *button,
154
                                                 gpointer         data);
155
static void addressbook_reg_clicked                (GtkButton        *button,
156
                                                 gpointer         data);
157
static void addressbook_to_clicked                (GtkButton        *button,
158
                                                 gpointer         data);
159
static void addressbook_lup_clicked                (GtkButton        *button,
160
                                                 gpointer        data);
161

    
162
static void addressbook_tree_selected                (GtkCTree        *ctree,
163
                                                 GtkCTreeNode        *node,
164
                                                 gint                 column,
165
                                                 gpointer         data);
166
static void addressbook_list_selected                (GtkCList        *clist,
167
                                                 gint                 row,
168
                                                 gint                 column,
169
                                                 GdkEvent        *event,
170
                                                 gpointer         data);
171
static void addressbook_list_row_selected        (GtkCTree        *clist,
172
                                                 GtkCTreeNode        *node,
173
                                                 gint                 column,
174
                                                 gpointer         data);
175
static void addressbook_list_row_unselected        (GtkCTree        *clist,
176
                                                 GtkCTreeNode        *node,
177
                                                 gint                 column,
178
                                                 gpointer         data);
179
static void addressbook_person_expand_node        (GtkCTree        *ctree,
180
                                                 GList                *node,
181
                                                 gpointer        *data );
182
static void addressbook_person_collapse_node        (GtkCTree        *ctree,
183
                                                 GList                *node,
184
                                                 gpointer        *data );
185
static void addressbook_entry_gotfocus                (GtkWidget        *widget);
186

    
187
#if 0
188
static void addressbook_entry_changed                (GtkWidget        *widget);
189
#endif
190

    
191
static gboolean addressbook_list_button_pressed        (GtkWidget        *widget,
192
                                                 GdkEventButton        *event,
193
                                                 gpointer         data);
194
static gboolean addressbook_list_button_released(GtkWidget        *widget,
195
                                                 GdkEventButton        *event,
196
                                                 gpointer         data);
197
static gboolean addressbook_tree_button_pressed        (GtkWidget        *ctree,
198
                                                 GdkEventButton        *event,
199
                                                 gpointer         data);
200
static gboolean addressbook_tree_button_released(GtkWidget        *ctree,
201
                                                 GdkEventButton        *event,
202
                                                 gpointer         data);
203
static void addressbook_popup_close                (GtkMenuShell        *menu_shell,
204
                                                 gpointer         data);
205

    
206
static void addressbook_new_folder_cb                (gpointer         data,
207
                                                 guint                 action,
208
                                                 GtkWidget        *widget);
209
static void addressbook_new_group_cb                (gpointer         data,
210
                                                 guint                 action,
211
                                                 GtkWidget        *widget);
212
static void addressbook_treenode_edit_cb        (gpointer         data,
213
                                                 guint                 action,
214
                                                 GtkWidget        *widget);
215
static void addressbook_treenode_delete_cb        (gpointer         data,
216
                                                 guint                 action,
217
                                                 GtkWidget        *widget);
218

    
219
static void addressbook_change_node_name        (GtkCTreeNode        *node,
220
                                                 const gchar        *name);
221

    
222
static void addressbook_new_address_cb                (gpointer         data,
223
                                                 guint                 action,
224
                                                 GtkWidget        *widget);
225
static void addressbook_edit_address_cb                (gpointer         data,
226
                                                 guint                 action,
227
                                                 GtkWidget        *widget);
228
static void addressbook_delete_address_cb        (gpointer         data,
229
                                                 guint                 action,
230
                                                 GtkWidget        *widget);
231

    
232
static void close_cb                                (gpointer         data,
233
                                                 guint                 action,
234
                                                 GtkWidget        *widget);
235
static void addressbook_file_save_cb                (gpointer         data,
236
                                                 guint                 action,
237
                                                 GtkWidget        *widget);
238

    
239
/* Data source edit stuff */
240
static void addressbook_new_book_cb                (gpointer         data,
241
                                                        guint                 action,
242
                                                 GtkWidget        *widget);
243
static void addressbook_new_vcard_cb                (gpointer         data,
244
                                                        guint                 action,
245
                                                 GtkWidget        *widget);
246

    
247
#ifdef USE_JPILOT
248
static void addressbook_new_jpilot_cb                (gpointer         data,
249
                                                        guint                 action,
250
                                                 GtkWidget        *widget);
251
#endif
252

    
253
#ifdef USE_LDAP
254
static void addressbook_new_ldap_cb                (gpointer         data,
255
                                                        guint                 action,
256
                                                 GtkWidget        *widget);
257
#endif
258

    
259
static void addressbook_set_clist                (AddressObject        *obj);
260

    
261
static void addressbook_load_tree                (void);
262
void addressbook_read_file                        (void);
263

    
264
static GtkCTreeNode *addressbook_add_object        (GtkCTreeNode        *node,
265
                                                 AddressObject        *obj);
266
static AddressDataSource *addressbook_find_datasource
267
                                                (GtkCTreeNode        *node );
268

    
269
static AddressBookFile *addressbook_get_book_file();
270

    
271
static GtkCTreeNode *addressbook_node_add_folder
272
                                                (GtkCTreeNode        *node,
273
                                                AddressDataSource *ds,
274
                                                ItemFolder        *itemFolder,
275
                                                AddressObjectType otype);
276
static GtkCTreeNode *addressbook_node_add_group (GtkCTreeNode        *node,
277
                                                AddressDataSource *ds,
278
                                                ItemGroup        *itemGroup);
279
/* static GtkCTreeNode *addressbook_node_add_category */
280
/*                                                (GtkCTreeNode        *node, */
281
/*                                                 AddressDataSource *ds, */
282
/*                                                 ItemFolder        *itemFolder); */
283
static void addressbook_tree_remove_children        (GtkCTree        *ctree,
284
                                                GtkCTreeNode        *parent);
285
static void addressbook_move_nodes_up                (GtkCTree        *ctree,
286
                                                GtkCTreeNode        *node);
287
static GtkCTreeNode *addressbook_find_group_node (GtkCTreeNode        *parent,
288
                                                ItemGroup        *group);
289

    
290
/* static void addressbook_delete_object        (AddressObject        *obj); */
291

    
292
static gboolean key_pressed                        (GtkWidget        *widget,
293
                                                 GdkEventKey        *event,
294
                                                 gpointer         data);
295
static gint addressbook_list_compare_func        (GtkCList        *clist,
296
                                                 gconstpointer         ptr1,
297
                                                 gconstpointer         ptr2);
298
/* static gint addressbook_obj_name_compare        (gconstpointer         a, */
299
/*                                                 gconstpointer         b); */
300

    
301
/* static void addressbook_book_show_message        (AddressBookFile *book); */
302
/* static void addressbook_vcard_show_message        (VCardFile *vcf); */
303
#ifdef USE_JPILOT
304
/* static void addressbook_jpilot_show_message        (JPilotFile *jpf); */
305
#endif
306
#ifdef USE_LDAP
307
static void addressbook_ldap_show_message        (SyldapServer *server);
308
#endif
309

    
310
/* LUT's and IF stuff */
311
static void addressbook_free_adapter                (GtkCTreeNode        *node);
312
static void addressbook_free_child_adapters        (GtkCTreeNode        *node);
313
AddressTypeControlItem *addrbookctl_lookup        (gint                 ot);
314
AddressTypeControlItem *addrbookctl_lookup_iface(AddressIfType         ifType);
315

    
316
void addrbookctl_build_map                        (GtkWidget        *window);
317
void addrbookctl_build_iflist                        (void);
318
AdapterInterface *addrbookctl_find_interface        (AddressIfType         ifType);
319
void addrbookctl_build_ifselect                        (void);
320

    
321
static void addrbookctl_free_interface                (AdapterInterface *adapter);
322
static void addrbookctl_free_datasource                (AdapterDSource          *adapter);
323
static void addrbookctl_free_folder                (AdapterFolder          *adapter);
324
static void addrbookctl_free_group                (AdapterGroup          *adapter);
325

    
326
static void addressbook_list_select_clear        (void);
327
static void addressbook_list_select_add                (AddressObject *obj);
328
static void addressbook_list_select_remove        (AddressObject *obj);
329

    
330
static void addressbook_import_ldif_cb                (void);
331

    
332
static GtkItemFactoryEntry addressbook_entries[] =
333
{
334
        {N_("/_File"),                        NULL,                NULL, 0, "<Branch>"},
335
        {N_("/_File/New _Book"),        "<alt>B",        addressbook_new_book_cb,        0, NULL},
336
        {N_("/_File/New _vCard"),        "<alt>D",        addressbook_new_vcard_cb,       0, NULL},
337
#ifdef USE_JPILOT
338
        {N_("/_File/New _JPilot"),        "<alt>J",        addressbook_new_jpilot_cb,      0, NULL},
339
#endif
340
#ifdef USE_LDAP
341
        {N_("/_File/New _Server"),        "<alt>S",        addressbook_new_ldap_cb,        0, NULL},
342
#endif
343
        {N_("/_File/---"),                NULL,                NULL, 0, "<Separator>"},
344
        {N_("/_File/_Edit"),                NULL,                addressbook_treenode_edit_cb,   0, NULL},
345
        {N_("/_File/_Delete"),                NULL,                addressbook_treenode_delete_cb, 0, NULL},
346
        {N_("/_File/---"),                NULL,                NULL, 0, "<Separator>"},
347
        {N_("/_File/_Save"),                "<alt>S",        addressbook_file_save_cb,       0, NULL},
348
        {N_("/_File/_Close"),                "<alt>W",        close_cb, 0, NULL},
349
        {N_("/_Address"),                NULL,                NULL, 0, "<Branch>"},
350
        {N_("/_Address/New _Address"),        "<alt>N",        addressbook_new_address_cb,     0, NULL},
351
        {N_("/_Address/New _Group"),        "<alt>G",        addressbook_new_group_cb,       0, NULL},
352
        {N_("/_Address/New _Folder"),        "<alt>R",        addressbook_new_folder_cb,      0, NULL},
353
        {N_("/_Address/---"),                NULL,                NULL, 0, "<Separator>"},
354
        {N_("/_Address/_Edit"),                "<alt>Return",        addressbook_edit_address_cb,    0, NULL},
355
        {N_("/_Address/_Delete"),        NULL,                addressbook_delete_address_cb,  0, NULL},
356
        {N_("/_Tools"),                        NULL,                NULL, 0, "<Branch>"},
357
        {N_("/_Tools/Import _LDIF file"), NULL,                addressbook_import_ldif_cb,        0, NULL},
358
        {N_("/_Help"),                        NULL,                NULL, 0, "<LastBranch>"},
359
        {N_("/_Help/_About"),                NULL,                about_show, 0, NULL}
360
};
361

    
362
/* New options to be added. */
363
/*
364
        {N_("/_Edit"),                        NULL,                NULL, 0, "<Branch>"},
365
        {N_("/_Edit/C_ut"),                "<ctl>X",        NULL,                                0, NULL},
366
        {N_("/_Edit/_Copy"),                "<ctl>C",        NULL,                           0, NULL},
367
        {N_("/_Edit/_Paste"),                "<ctl>V",        NULL,                           0, NULL},
368
        {N_("/_Tools"),                        NULL,                NULL, 0, "<Branch>"},
369
        {N_("/_Tools/Import _Mozilla"),        NULL,           NULL,                                0, NULL},
370
        {N_("/_Tools/Import _vCard"),        NULL,           NULL,                                0, NULL},
371
        {N_("/_Tools/---"),                NULL,                NULL, 0, "<Separator>"},
372
        {N_("/_Tools/Export _LDIF file"), NULL,                NULL,                                0, NULL},
373
        {N_("/_Tools/Export v_Card"),        NULL,           NULL,                                0, NULL},
374
*/
375

    
376
static GtkItemFactoryEntry addressbook_tree_popup_entries[] =
377
{
378
        {N_("/New _Address"),        NULL, addressbook_new_address_cb, 0, NULL},
379
        {N_("/New _Group"),        NULL, addressbook_new_group_cb,   0, NULL},
380
        {N_("/New _Folder"),        NULL, addressbook_new_folder_cb,  0, NULL},
381
        {N_("/---"),                NULL, NULL, 0, "<Separator>"},
382
        {N_("/_Edit"),                NULL, addressbook_treenode_edit_cb,   0, NULL},
383
        {N_("/_Delete"),        NULL, addressbook_treenode_delete_cb, 0, NULL}
384
};
385

    
386
static GtkItemFactoryEntry addressbook_list_popup_entries[] =
387
{
388
        {N_("/New _Address"),        NULL, addressbook_new_address_cb,  0, NULL},
389
        {N_("/New _Group"),        NULL, addressbook_new_group_cb,    0, NULL},
390
        {N_("/New _Folder"),        NULL, addressbook_new_folder_cb,   0, NULL},
391
        {N_("/---"),                NULL, NULL, 0, "<Separator>"},
392
        {N_("/_Edit"),                NULL, addressbook_edit_address_cb,   0, NULL},
393
        {N_("/_Delete"),        NULL, addressbook_delete_address_cb, 0, NULL}
394
};
395

    
396
void addressbook_open(Compose *target)
397
{
398
        if (!addrbook.window) {
399
                addressbook_read_file();
400
                addressbook_create();
401
                addressbook_load_tree();
402
                gtk_ctree_select(GTK_CTREE(addrbook.ctree),
403
                                 GTK_CTREE_NODE(GTK_CLIST(addrbook.ctree)->row_list));
404
        } else
405
                gtk_widget_hide(addrbook.window);
406

    
407
        gtk_widget_show_all(addrbook.window);
408

    
409
        addressbook_set_target_compose(target);
410
}
411

    
412
void addressbook_set_target_compose(Compose *target)
413
{
414
        addrbook.target_compose = target;
415

    
416
        addressbook_button_set_sensitive();
417
}
418

    
419
Compose *addressbook_get_target_compose(void)
420
{
421
        return addrbook.target_compose;
422
}
423

    
424
void addressbook_refresh(void)
425
{
426
        if (addrbook.window) {
427
                if (addrbook.treeSelected) {
428
                        gtk_ctree_select(GTK_CTREE(addrbook.ctree),
429
                                         addrbook.treeSelected);
430
                }
431
        }
432
        addressbook_export_to_file();
433
}
434

    
435
/*
436
* Create the address book widgets. The address book contains two CTree widgets: the
437
* address index tree on the left and the address list on the right.
438
*
439
* The address index tree displays a hierarchy of interfaces and groups. Each node in
440
* this tree is linked to an address Adapter. Adapters have been created for interfaces,
441
* data sources and folder objects.
442
*
443
* The address list displays group, person and email objects. These items are linked
444
* directly to ItemGroup, ItemPerson and ItemEMail objects inside the address book data
445
* sources.
446
*
447
* In the tradition of MVC architecture, the data stores have been separated from the
448
* GUI components. The addrindex.c file provides the interface to all data stores.
449
*/
450
static void addressbook_create(void)
451
{
452
        GtkWidget *window;
453
        GtkWidget *vbox;
454
        GtkWidget *menubar;
455
        GtkWidget *vbox2;
456
        GtkWidget *ctree_swin;
457
        GtkWidget *ctree;
458
        GtkWidget *clist_vbox;
459
        GtkWidget *clist_swin;
460
        GtkWidget *clist;
461
        GtkWidget *paned;
462
        GtkWidget *hbox;
463
        GtkWidget *label;
464
        GtkWidget *entry;
465
        GtkWidget *statusbar;
466
        GtkWidget *hbbox;
467
        GtkWidget *hsbox;
468
        GtkWidget *del_btn;
469
        GtkWidget *reg_btn;
470
        GtkWidget *lup_btn;
471
        GtkWidget *to_btn;
472
        GtkWidget *cc_btn;
473
        GtkWidget *bcc_btn;
474
        GtkWidget *tree_popup;
475
        GtkWidget *list_popup;
476
        GtkItemFactory *tree_factory;
477
        GtkItemFactory *list_factory;
478
        GtkItemFactory *menu_factory;
479
        gint n_entries;
480
        GList *nodeIf;
481

    
482
        gchar *titles[N_COLS];
483
        gchar *text;
484
        gint i;
485

    
486
        debug_print("Creating addressbook window...\n");
487

    
488
        titles[COL_NAME]    = _("Name");
489
        titles[COL_ADDRESS] = _("E-Mail address");
490
        titles[COL_REMARKS] = _("Remarks");
491

    
492
        window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
493
        gtk_window_set_title(GTK_WINDOW(window), _("Address book"));
494
        gtk_widget_set_size_request
495
                (window, ADDRESSBOOK_WIDTH, ADDRESSBOOK_HEIGHT);
496
        gtk_window_set_policy(GTK_WINDOW(window), TRUE, TRUE, TRUE);
497
        gtk_window_set_wmclass(GTK_WINDOW(window), "addressbook", "Sylpheed");
498
        gtk_widget_realize(window);
499

    
500
        g_signal_connect(G_OBJECT(window), "delete_event",
501
                         G_CALLBACK(addressbook_close), NULL);
502
        g_signal_connect(G_OBJECT(window), "key_press_event",
503
                         G_CALLBACK(key_pressed), NULL);
504
        MANAGE_WINDOW_SIGNALS_CONNECT(window);
505

    
506
        vbox = gtk_vbox_new(FALSE, 0);
507
        gtk_container_add(GTK_CONTAINER(window), vbox);
508

    
509
        n_entries = sizeof(addressbook_entries) /
510
                sizeof(addressbook_entries[0]);
511
        menubar = menubar_create(window, addressbook_entries, n_entries,
512
                                 "<AddressBook>", NULL);
513
        gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, TRUE, 0);
514
        menu_factory = gtk_item_factory_from_widget(menubar);
515

    
516
        vbox2 = gtk_vbox_new(FALSE, 4);
517
        gtk_container_set_border_width(GTK_CONTAINER(vbox2), BORDER_WIDTH);
518
        gtk_box_pack_start(GTK_BOX(vbox), vbox2, TRUE, TRUE, 0);
519

    
520
        ctree_swin = gtk_scrolled_window_new(NULL, NULL);
521
        gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(ctree_swin),
522
                                       GTK_POLICY_AUTOMATIC,
523
                                       GTK_POLICY_ALWAYS);
524
        gtk_widget_set_size_request(ctree_swin, COL_FOLDER_WIDTH + 40, -1);
525

    
526
        /* Address index */
527
        ctree = gtk_ctree_new(1, 0);
528
        gtk_container_add(GTK_CONTAINER(ctree_swin), ctree);
529
        gtk_clist_set_selection_mode(GTK_CLIST(ctree), GTK_SELECTION_BROWSE);
530
        gtk_clist_set_column_width(GTK_CLIST(ctree), 0, COL_FOLDER_WIDTH);
531
        gtk_ctree_set_line_style(GTK_CTREE(ctree), GTK_CTREE_LINES_DOTTED);
532
        gtk_ctree_set_expander_style(GTK_CTREE(ctree),
533
                                     GTK_CTREE_EXPANDER_SQUARE);
534
        gtk_ctree_set_indent(GTK_CTREE(ctree), CTREE_INDENT);
535
        gtk_clist_set_compare_func(GTK_CLIST(ctree),
536
                                   addressbook_list_compare_func);
537

    
538
        g_signal_connect(G_OBJECT(ctree), "tree_select_row",
539
                         G_CALLBACK(addressbook_tree_selected), NULL);
540
        g_signal_connect(G_OBJECT(ctree), "button_press_event",
541
                         G_CALLBACK(addressbook_tree_button_pressed),
542
                         NULL);
543
        g_signal_connect(G_OBJECT(ctree), "button_release_event",
544
                         G_CALLBACK(addressbook_tree_button_released),
545
                         NULL);
546

    
547
        clist_vbox = gtk_vbox_new(FALSE, 4);
548

    
549
        clist_swin = gtk_scrolled_window_new(NULL, NULL);
550
        gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(clist_swin),
551
                                       GTK_POLICY_AUTOMATIC,
552
                                       GTK_POLICY_ALWAYS);
553
        gtk_box_pack_start(GTK_BOX(clist_vbox), clist_swin, TRUE, TRUE, 0);
554

    
555
        /* Address list */
556
        clist = gtk_ctree_new_with_titles(N_COLS, 0, titles);
557
        gtk_container_add(GTK_CONTAINER(clist_swin), clist);
558
        gtk_clist_set_selection_mode(GTK_CLIST(clist), GTK_SELECTION_EXTENDED);
559
        gtk_ctree_set_line_style(GTK_CTREE(clist), GTK_CTREE_LINES_NONE);
560
        gtk_ctree_set_expander_style(GTK_CTREE(clist), GTK_CTREE_EXPANDER_SQUARE);
561
        gtk_ctree_set_indent(GTK_CTREE(clist), CTREE_INDENT);
562
        gtk_clist_set_column_width(GTK_CLIST(clist), COL_NAME,
563
                                   COL_NAME_WIDTH);
564
        gtk_clist_set_column_width(GTK_CLIST(clist), COL_ADDRESS,
565
                                   COL_ADDRESS_WIDTH);
566
        gtk_clist_set_compare_func(GTK_CLIST(clist),
567
                                   addressbook_list_compare_func);
568

    
569
        for (i = 0; i < N_COLS; i++)
570
                GTK_WIDGET_UNSET_FLAGS(GTK_CLIST(clist)->column[i].button,
571
                                       GTK_CAN_FOCUS);
572

    
573
        g_signal_connect(G_OBJECT(clist), "tree_select_row",
574
                         G_CALLBACK(addressbook_list_row_selected), NULL);
575
        g_signal_connect(G_OBJECT(clist), "tree_unselect_row",
576
                         G_CALLBACK(addressbook_list_row_unselected), NULL);
577
        g_signal_connect(G_OBJECT(clist), "button_press_event",
578
                         G_CALLBACK(addressbook_list_button_pressed),
579
                         NULL);
580
        g_signal_connect(G_OBJECT(clist), "button_release_event",
581
                         G_CALLBACK(addressbook_list_button_released),
582
                         NULL);
583
        g_signal_connect(G_OBJECT(clist), "select_row",
584
                         G_CALLBACK(addressbook_list_selected), NULL);
585
        g_signal_connect(G_OBJECT(clist), "tree_expand",
586
                         G_CALLBACK(addressbook_person_expand_node), NULL);
587
        g_signal_connect(G_OBJECT(clist), "tree_collapse",
588
                         G_CALLBACK(addressbook_person_collapse_node), NULL);
589

    
590
        hbox = gtk_hbox_new(FALSE, 4);
591
        gtk_box_pack_start(GTK_BOX(clist_vbox), hbox, FALSE, FALSE, 0);
592

    
593
        label = gtk_label_new(_("Name:"));
594
        gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
595

    
596
        entry = gtk_entry_new();
597
        gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0);
598

    
599
        address_completion_register_entry(GTK_ENTRY(entry));
600
        g_signal_connect(G_OBJECT(entry), "focus_in_event",
601
                         G_CALLBACK(addressbook_entry_gotfocus), NULL);
602

    
603
#if 0
604
        g_signal_connect(G_OBJECT(entry), "changed",
605
                         G_CALLBACK(addressbook_entry_changed), NULL);
606
#endif
607

    
608
        paned = gtk_hpaned_new();
609
        gtk_box_pack_start(GTK_BOX(vbox2), paned, TRUE, TRUE, 0);
610
        gtk_paned_add1(GTK_PANED(paned), ctree_swin);
611
        gtk_paned_add2(GTK_PANED(paned), clist_vbox);
612

    
613
        /* Status bar */
614
        hsbox = gtk_hbox_new(FALSE, 0);
615
        gtk_box_pack_end(GTK_BOX(vbox), hsbox, FALSE, FALSE, BORDER_WIDTH);
616
        statusbar = gtk_statusbar_new();
617
        gtk_box_pack_start(GTK_BOX(hsbox), statusbar, TRUE, TRUE, BORDER_WIDTH);
618

    
619
        /* Button panel */
620
        hbbox = gtk_hbutton_box_new();
621
        gtk_button_box_set_layout(GTK_BUTTON_BOX(hbbox), GTK_BUTTONBOX_END);
622
        gtk_box_set_spacing(GTK_BOX(hbbox), 2);
623
        gtk_box_pack_end(GTK_BOX(vbox), hbbox, FALSE, FALSE, 0);
624

    
625
        del_btn = gtk_button_new_with_label(_("Delete"));
626
        GTK_WIDGET_SET_FLAGS(del_btn, GTK_CAN_DEFAULT);
627
        gtk_box_pack_start(GTK_BOX(hbbox), del_btn, TRUE, TRUE, 0);
628
        reg_btn = gtk_button_new_with_label(_("Add"));
629
        GTK_WIDGET_SET_FLAGS(reg_btn, GTK_CAN_DEFAULT);
630
        gtk_box_pack_start(GTK_BOX(hbbox), reg_btn, TRUE, TRUE, 0);
631
        lup_btn = gtk_button_new_with_label(_("Lookup"));
632
        GTK_WIDGET_SET_FLAGS(lup_btn, GTK_CAN_DEFAULT);
633
        gtk_box_pack_start(GTK_BOX(hbbox), lup_btn, TRUE, TRUE, 0);
634

    
635
        g_signal_connect(G_OBJECT(del_btn), "clicked",
636
                         G_CALLBACK(addressbook_del_clicked), NULL);
637
        g_signal_connect(G_OBJECT(reg_btn), "clicked",
638
                         G_CALLBACK(addressbook_reg_clicked), NULL);
639
        g_signal_connect(G_OBJECT(lup_btn), "clicked",
640
                         G_CALLBACK(addressbook_lup_clicked), NULL);
641

    
642
        to_btn = gtk_button_new_with_label
643
                (prefs_common.trans_hdr ? _("To:") : "To:");
644
        GTK_WIDGET_SET_FLAGS(to_btn, GTK_CAN_DEFAULT);
645
        gtk_box_pack_start(GTK_BOX(hbbox), to_btn, TRUE, TRUE, 0);
646
        cc_btn = gtk_button_new_with_label
647
                (prefs_common.trans_hdr ? _("Cc:") : "Cc:");
648
        GTK_WIDGET_SET_FLAGS(cc_btn, GTK_CAN_DEFAULT);
649
        gtk_box_pack_start(GTK_BOX(hbbox), cc_btn, TRUE, TRUE, 0);
650
        bcc_btn = gtk_button_new_with_label
651
                (prefs_common.trans_hdr ? _("Bcc:") : "Bcc:");
652
        GTK_WIDGET_SET_FLAGS(bcc_btn, GTK_CAN_DEFAULT);
653
        gtk_box_pack_start(GTK_BOX(hbbox), bcc_btn, TRUE, TRUE, 0);
654

    
655
        g_signal_connect(G_OBJECT(to_btn), "clicked",
656
                         G_CALLBACK(addressbook_to_clicked),
657
                         GINT_TO_POINTER(COMPOSE_ENTRY_TO));
658
        g_signal_connect(G_OBJECT(cc_btn), "clicked",
659
                         G_CALLBACK(addressbook_to_clicked),
660
                         GINT_TO_POINTER(COMPOSE_ENTRY_CC));
661
        g_signal_connect(G_OBJECT(bcc_btn), "clicked",
662
                         G_CALLBACK(addressbook_to_clicked),
663
                         GINT_TO_POINTER(COMPOSE_ENTRY_BCC));
664

    
665
        /* Build icons for interface */
666
        stock_pixmap_gdk( window, STOCK_PIXMAP_INTERFACE,
667
                          &interfacexpm, &interfacexpmmask );
668

    
669
        /* Build control tables */
670
        addrbookctl_build_map(window);
671
        addrbookctl_build_iflist();
672
        addrbookctl_build_ifselect();
673

    
674
        /* Add each interface into the tree as a root level folder */
675
        nodeIf = _addressInterfaceList_;
676
        while( nodeIf ) {
677
                AdapterInterface *adapter = nodeIf->data;
678
                AddressInterface *iface = adapter->interface;
679
                nodeIf = g_list_next(nodeIf);
680

    
681
                if(iface->useInterface) {
682
                        AddressTypeControlItem *atci = adapter->atci;
683
                        text = atci->displayName;
684
                        adapter->treeNode =
685
                                gtk_ctree_insert_node( GTK_CTREE(ctree),
686
                                        NULL, NULL, &text, FOLDER_SPACING,
687
                                        interfacexpm, interfacexpmmask,
688
                                        interfacexpm, interfacexpmmask,
689
                                        FALSE, FALSE );
690
                        menu_set_sensitive( menu_factory, atci->menuCommand, adapter->haveLibrary );
691
                        gtk_ctree_node_set_row_data( GTK_CTREE(ctree), adapter->treeNode, adapter );
692
                }
693
        }
694

    
695
        /* Popup menu */
696
        n_entries = sizeof(addressbook_tree_popup_entries) /
697
                sizeof(addressbook_tree_popup_entries[0]);
698
        tree_popup = menu_create_items(addressbook_tree_popup_entries,
699
                                       n_entries,
700
                                       "<AddressBookTree>", &tree_factory,
701
                                       NULL);
702
        g_signal_connect(G_OBJECT(tree_popup), "selection_done",
703
                         G_CALLBACK(addressbook_popup_close), NULL);
704
        n_entries = sizeof(addressbook_list_popup_entries) /
705
                sizeof(addressbook_list_popup_entries[0]);
706
        list_popup = menu_create_items(addressbook_list_popup_entries,
707
                                       n_entries,
708
                                       "<AddressBookList>", &list_factory,
709
                                       NULL);
710

    
711
        addrbook.window  = window;
712
        addrbook.menubar = menubar;
713
        addrbook.ctree   = ctree;
714
        addrbook.clist   = clist;
715
        addrbook.entry   = entry;
716
        addrbook.statusbar = statusbar;
717
        addrbook.status_cid = gtk_statusbar_get_context_id( GTK_STATUSBAR(statusbar), "Addressbook Window" );
718

    
719
        addrbook.del_btn = del_btn;
720
        addrbook.reg_btn = reg_btn;
721
        addrbook.lup_btn = lup_btn;
722
        addrbook.to_btn  = to_btn;
723
        addrbook.cc_btn  = cc_btn;
724
        addrbook.bcc_btn = bcc_btn;
725

    
726
        addrbook.tree_popup   = tree_popup;
727
        addrbook.list_popup   = list_popup;
728
        addrbook.tree_factory = tree_factory;
729
        addrbook.list_factory = list_factory;
730
        addrbook.menu_factory = menu_factory;
731

    
732
        addrbook.listSelected = NULL;
733
        address_completion_start(window);
734
        gtk_widget_show_all(window);
735

    
736
}
737

    
738
static gint addressbook_close(void)
739
{
740
        gtk_widget_hide(addrbook.window);
741
        addressbook_export_to_file();
742
        return TRUE;
743
}
744

    
745
static void addressbook_status_show( gchar *msg ) {
746
        if( addrbook.statusbar != NULL ) {
747
                gtk_statusbar_pop( GTK_STATUSBAR(addrbook.statusbar), addrbook.status_cid );
748
                if( msg ) {
749
                        gtk_statusbar_push( GTK_STATUSBAR(addrbook.statusbar), addrbook.status_cid, msg );
750
                }
751
        }
752
}
753

    
754
static void addressbook_ds_show_message( AddressDataSource *ds ) {
755
        gint retVal;
756
        gchar *name;
757
        *addressbook_msgbuf = '\0';
758
        if( ds ) {
759
                name = addrindex_ds_get_name( ds );
760
                retVal = addrindex_ds_get_status_code( ds );
761
                if( retVal == MGU_SUCCESS ) {
762
                        if( ds ) {
763
                                sprintf( addressbook_msgbuf, "%s", name );
764
                        }
765
                }
766
                else {
767
                        if( ds == NULL ) {
768
                                sprintf( addressbook_msgbuf, "%s", mgu_error2string( retVal ) );
769
                        }
770
                        else {
771
                                sprintf( addressbook_msgbuf, "%s: %s", name, mgu_error2string( retVal ) );
772
                        }
773
                }
774
        }
775
        addressbook_status_show( addressbook_msgbuf );
776
}
777

    
778
static void addressbook_button_set_sensitive(void)
779
{
780
        gboolean to_sens  = FALSE;
781
        gboolean cc_sens  = FALSE;
782
        gboolean bcc_sens = FALSE;
783

    
784
        if (!addrbook.window) return;
785

    
786
        if (addrbook.target_compose) {
787
                to_sens = TRUE;
788
                cc_sens = TRUE;
789
                if (addrbook.target_compose->use_bcc)
790
                        bcc_sens = TRUE;
791
        }
792

    
793
        gtk_widget_set_sensitive(addrbook.to_btn, to_sens);
794
        gtk_widget_set_sensitive(addrbook.cc_btn, cc_sens);
795
        gtk_widget_set_sensitive(addrbook.bcc_btn, bcc_sens);
796
}
797

    
798
/*
799
* Delete one or more objects from address list.
800
*/
801
static void addressbook_del_clicked(GtkButton *button, gpointer data)
802
{
803
        GtkCTree *clist = GTK_CTREE(addrbook.clist);
804
        GtkCTree *ctree = GTK_CTREE(addrbook.ctree);
805
        AddressObject *pobj, *obj;
806
        AdapterDSource *ads = NULL;
807
        GtkCTreeNode *nodeList;
808
        gboolean procFlag;
809
        AlertValue aval;
810
        AddressBookFile *abf = NULL;
811
        AddressDataSource *ds = NULL;
812

    
813
        pobj = gtk_ctree_node_get_row_data(ctree, addrbook.opened );
814
        g_return_if_fail(pobj != NULL);
815

    
816
        nodeList = addrbook.listSelected;
817
        obj = gtk_ctree_node_get_row_data( clist, nodeList );
818
        if( obj == NULL) return;
819
        ds = addressbook_find_datasource( addrbook.treeSelected );
820
        if( ds == NULL ) return;
821

    
822
        procFlag = FALSE;
823
        if( pobj->type == ADDR_DATASOURCE ) {
824
                ads = ADAPTER_DSOURCE(pobj);
825
                if( ads->subType == ADDR_BOOK ) procFlag = TRUE;
826
        }
827
        else if( pobj->type == ADDR_ITEM_FOLDER ) {
828
                procFlag = TRUE;
829
        }
830
        else if( pobj->type == ADDR_ITEM_GROUP ) {
831
                procFlag = TRUE;
832
        }
833
        if( ! procFlag ) return;
834
        abf = ds->rawDataSource;
835
        if( abf == NULL ) return;
836

    
837
        /* Confirm deletion */
838
        aval = alertpanel( _("Delete address(es)"),
839
                        _("Really delete the address(es)?"),
840
                        _("Yes"), _("No"), NULL );
841
        if( aval != G_ALERTDEFAULT ) return;
842

    
843
        /* Process deletions */
844
        if( pobj->type == ADDR_DATASOURCE || pobj->type == ADDR_ITEM_FOLDER ) {
845
                /* Items inside folders */
846
                GList *node;
847
                node = _addressListSelection_;
848
                while( node ) {
849
                        AddrItemObject *aio = node->data;
850
                        node = g_list_next( node );
851
                        if( aio->type == ADDR_ITEM_GROUP ) {
852
                                ItemGroup *item = ( ItemGroup * ) aio;
853
                                GtkCTreeNode *nd = NULL;
854

    
855
                                nd = addressbook_find_group_node( addrbook.opened, item );
856
                                item = addrbook_remove_group( abf, item );
857
                                if( item ) {
858
                                        addritem_free_item_group( item );
859
                                        item = NULL;
860
                                }
861
                                /* Remove group from parent node */
862
                                gtk_ctree_remove_node( ctree, nd );
863
                        }
864
                        else if( aio->type == ADDR_ITEM_PERSON ) {
865
                                ItemPerson *item = ( ItemPerson * ) aio;
866
                                item = addrbook_remove_person( abf, item );
867
                                if( item ) {
868
                                        addritem_free_item_person( item );
869
                                        item = NULL;
870
                                }
871
                        }
872
                        else if( aio->type == ADDR_ITEM_EMAIL ) {
873
                                ItemEMail *item = ( ItemEMail * ) aio;
874
                                ItemPerson *person = ( ItemPerson * ) ADDRITEM_PARENT(item);
875
                                item = addrbook_person_remove_email( abf, person, item );
876
                                if( item ) {
877
                                        addritem_free_item_email( item );
878
                                        item = NULL;
879
                                }
880
                        }
881
                }
882
                addressbook_list_select_clear();
883
                gtk_ctree_select( ctree, addrbook.opened);
884
                return;
885
        }
886
        else if( pobj->type == ADDR_ITEM_GROUP ) {
887
                /* Items inside groups */
888
                GList *node;
889
                node = _addressListSelection_;
890
                while( node ) {
891
                        AddrItemObject *aio = node->data;
892
                        node = g_list_next( node );
893
                        if( aio->type == ADDR_ITEM_EMAIL ) {
894
                                ItemEMail *item = ( ItemEMail * ) aio;
895
                                ItemPerson *person = ( ItemPerson * ) ADDRITEM_PARENT(item);
896
                                item = addrbook_person_remove_email( abf, person, item );
897
                                if( item ) {
898
                                        addritem_print_item_email( item, stdout );
899
                                        addritem_free_item_email( item );
900
                                        item = NULL;
901
                                }
902
                        }
903
                }
904
                addressbook_list_select_clear();
905
                gtk_ctree_select( ctree, addrbook.opened);
906
                return;
907
        }
908

    
909
        gtk_ctree_node_set_row_data( clist, nodeList, NULL );
910
        gtk_ctree_remove_node( clist, nodeList );
911
        addressbook_list_select_remove( obj );
912

    
913
}
914

    
915
static void addressbook_reg_clicked(GtkButton *button, gpointer data)
916
{
917
        addressbook_new_address_cb( NULL, 0, NULL );
918
}
919

    
920
gchar *addressbook_format_address( AddressObject * obj ) {
921
        gchar *buf = NULL;
922
        gchar *name = NULL;
923
        gchar *address = NULL;
924

    
925
        if( obj->type == ADDR_ITEM_EMAIL ) {
926
                ItemPerson *person = NULL;
927
                ItemEMail *email = ( ItemEMail * ) obj;
928

    
929
                person = ( ItemPerson * ) ADDRITEM_PARENT(email);
930
                if( email->address ) {
931
                        if( ADDRITEM_NAME(email) ) {
932
                                name = ADDRITEM_NAME(email);
933
                                if( *name == '\0' ) {
934
                                        name = ADDRITEM_NAME(person);
935
                                }
936
                        }
937
                        else if( ADDRITEM_NAME(person) ) {
938
                                name = ADDRITEM_NAME(person);
939
                        }
940
                        else {
941
                                buf = g_strdup( email->address );
942
                        }
943
                        address = email->address;
944
                }
945
        }
946
        else if( obj->type == ADDR_ITEM_PERSON ) {
947
                ItemPerson *person = ( ItemPerson * ) obj;
948
                GList *node = person->listEMail;
949

    
950
                name = ADDRITEM_NAME(person);
951
                if( node ) {
952
                        ItemEMail *email = ( ItemEMail * ) node->data;
953
                        address = email->address;
954
                }
955
        }
956
        if( address ) {
957
                if( name && name[0] != '\0' ) {
958
                        if( name[0] != '"' && strpbrk( name, ",.[]<>" ) != NULL )
959
                                buf = g_strdup_printf( "\"%s\" <%s>", name, address );
960
                        else
961
                                buf = g_strdup_printf( "%s <%s>", name, address );
962
                }
963
                else {
964
                        buf = g_strdup( address );
965
                }
966
        }
967

    
968
        return buf;
969
}
970

    
971
static void addressbook_to_clicked(GtkButton *button, gpointer data)
972
{
973
        GList *node = _addressListSelection_;
974
        if (!addrbook.target_compose) return;
975
        while( node ) {
976
                AddressObject *obj = node->data;
977
                Compose *compose = addrbook.target_compose;
978
                node = g_list_next( node );
979
                if( obj->type == ADDR_ITEM_PERSON || obj->type == ADDR_ITEM_EMAIL ) {
980
                        gchar *addr = addressbook_format_address( obj );
981
                        compose_entry_append( compose, addr, (ComposeEntryType) data );
982
                        g_free( addr );
983
                        addr = NULL;
984
                }
985
                else if( obj->type == ADDR_ITEM_GROUP ) {
986
                        ItemGroup *group = ( ItemGroup * ) obj;
987
                        GList *nodeMail = group->listEMail;
988
                        while( nodeMail ) {
989
                                ItemEMail *email = nodeMail->data;
990
                                gchar *addr = addressbook_format_address( ( AddressObject * ) email );
991
                                compose_entry_append( compose, addr, (ComposeEntryType) data );
992
                                g_free( addr );
993
                                nodeMail = g_list_next( nodeMail );
994
                        }
995
                }
996
        }
997
}
998

    
999
static void addressbook_menubar_set_sensitive( gboolean sensitive ) {
1000
        menu_set_sensitive( addrbook.menu_factory, "/File/New Book",    sensitive );
1001
        menu_set_sensitive( addrbook.menu_factory, "/File/New vCard",  sensitive );
1002
#ifdef USE_JPILOT
1003
        menu_set_sensitive( addrbook.menu_factory, "/File/New JPilot", sensitive );
1004
#endif
1005
#ifdef USE_LDAP
1006
        menu_set_sensitive( addrbook.menu_factory, "/File/New Server",  sensitive );
1007
#endif
1008
        menu_set_sensitive( addrbook.menu_factory, "/File/Edit",        sensitive );
1009
        menu_set_sensitive( addrbook.menu_factory, "/File/Delete",      sensitive );
1010

    
1011
        menu_set_sensitive( addrbook.menu_factory, "/Address/New Address", sensitive );
1012
        menu_set_sensitive( addrbook.menu_factory, "/Address/New Group",   sensitive );
1013
        menu_set_sensitive( addrbook.menu_factory, "/Address/New Folder",  sensitive );
1014
        gtk_widget_set_sensitive( addrbook.reg_btn, sensitive );
1015
        gtk_widget_set_sensitive( addrbook.del_btn, sensitive );
1016
}
1017

    
1018
static void addressbook_menuitem_set_sensitive( AddressObject *obj, GtkCTreeNode *node ) {
1019
        gboolean canEdit = FALSE;
1020
        gboolean canAdd = FALSE;
1021
        gboolean canEditTr = TRUE;
1022
        gboolean editAddress = FALSE;
1023
        AddressTypeControlItem *atci = NULL;
1024
        AddressDataSource *ds = NULL;
1025
        AddressInterface *iface = NULL;
1026

    
1027
        if( obj == NULL ) return;
1028
        if( obj->type == ADDR_INTERFACE ) {
1029
                AdapterInterface *adapter = ADAPTER_INTERFACE(obj);
1030
                iface = adapter->interface;
1031
                if( iface ) {
1032
                        if( iface->haveLibrary ) {
1033
                                /* Enable appropriate File / New command */
1034
                                atci = adapter->atci;
1035
                                menu_set_sensitive( addrbook.menu_factory, atci->menuCommand, TRUE );
1036
                        }
1037
                }
1038
                canEditTr = FALSE;
1039
        }
1040
        else if( obj->type == ADDR_DATASOURCE ) {
1041
                AdapterDSource *ads = ADAPTER_DSOURCE(obj);
1042
                ds = ads->dataSource;
1043
                iface = ds->interface;
1044
                if( ! iface->readOnly ) {
1045
                        canAdd = canEdit = editAddress = TRUE;
1046
                }
1047
                if( ! iface->haveLibrary ) {
1048
                        canAdd = canEdit = editAddress = FALSE;
1049
                }
1050
        }
1051
        else if( obj->type == ADDR_ITEM_FOLDER ) {
1052
                ds = addressbook_find_datasource( addrbook.treeSelected );
1053
                if( ds ) {
1054
                        iface = ds->interface;
1055
                        if( ! iface->readOnly ) {
1056
                                canAdd = editAddress = TRUE;
1057
                        }
1058
                }
1059
        }
1060
        else if( obj->type == ADDR_ITEM_GROUP ) {
1061
                ds = addressbook_find_datasource( addrbook.treeSelected );
1062
                if( ds ) {
1063
                        iface = ds->interface;
1064
                        if( ! iface->readOnly ) {
1065
                                editAddress = TRUE;
1066
                        }
1067
                }
1068
        }
1069

    
1070
        if( addrbook.listSelected == NULL ) canEdit = FALSE;
1071

    
1072
        /* Enable add */
1073
        menu_set_sensitive( addrbook.menu_factory, "/Address/New Address", editAddress );
1074
        menu_set_sensitive( addrbook.menu_factory, "/Address/New Group",   canAdd );
1075
        menu_set_sensitive( addrbook.menu_factory, "/Address/New Folder",  canAdd );
1076
        gtk_widget_set_sensitive( addrbook.reg_btn, editAddress );
1077

    
1078
        /* Enable edit */
1079
        menu_set_sensitive( addrbook.menu_factory, "/Address/Edit",   canEdit );
1080
        menu_set_sensitive( addrbook.menu_factory, "/Address/Delete", canEdit );
1081
        gtk_widget_set_sensitive( addrbook.del_btn, canEdit );
1082

    
1083
        menu_set_sensitive( addrbook.menu_factory, "/File/Edit",      canEditTr );
1084
        menu_set_sensitive( addrbook.menu_factory, "/File/Delete",    canEditTr );
1085
}
1086

    
1087
static void addressbook_tree_selected(GtkCTree *ctree, GtkCTreeNode *node,
1088
                                      gint column, gpointer data)
1089
{
1090
        AddressObject *obj = NULL;
1091
        AdapterDSource *ads = NULL;
1092
        AddressDataSource *ds = NULL;
1093
        ItemFolder *rootFolder = NULL;
1094

    
1095
        addrbook.treeSelected = node;
1096
        addrbook.listSelected = NULL;
1097
        addressbook_status_show( "" );
1098
        if( addrbook.entry != NULL ) gtk_entry_set_text(GTK_ENTRY(addrbook.entry), "");
1099

    
1100
        if( addrbook.clist ) gtk_clist_clear( GTK_CLIST(addrbook.clist) );
1101
        if( node ) obj = gtk_ctree_node_get_row_data( ctree, node );
1102
        if( obj == NULL ) return;
1103

    
1104
        addrbook.opened = node;
1105

    
1106
        if( obj->type == ADDR_DATASOURCE ) {
1107
                /* Read from file */
1108
                static gboolean tVal = TRUE;
1109

    
1110
                ads = ADAPTER_DSOURCE(obj);
1111
                if( ads == NULL ) return;
1112
                ds = ads->dataSource;
1113
                if( ds == NULL ) return;                
1114

    
1115
                if( addrindex_ds_get_modify_flag( ds ) ) {
1116
                        addrindex_ds_read_data( ds );
1117
                }
1118

    
1119
                if( ! addrindex_ds_get_read_flag( ds ) ) {
1120
                        addrindex_ds_read_data( ds );
1121
                }
1122
                addressbook_ds_show_message( ds );
1123

    
1124
                if( ! addrindex_ds_get_access_flag( ds ) ) {
1125
                        /* Remove existing folders and groups */
1126
                        gtk_clist_freeze( GTK_CLIST(ctree) );
1127
                        addressbook_tree_remove_children( ctree, node );
1128
                        gtk_clist_thaw( GTK_CLIST(ctree) );
1129

    
1130
                        /* Load folders into the tree */
1131
                        rootFolder = addrindex_ds_get_root_folder( ds );
1132
                        if( ds->type == ADDR_IF_JPILOT ) {
1133
                                addressbook_node_add_folder( node, ds, rootFolder, ADDR_CATEGORY );
1134
                        }
1135
                        else {
1136
                                addressbook_node_add_folder( node, ds, rootFolder, ADDR_ITEM_FOLDER );
1137
                        }
1138
                        addrindex_ds_set_access_flag( ds, &tVal );
1139
                        gtk_ctree_expand( ctree, node );
1140
                }
1141
        }
1142

    
1143
        /* Update address list */
1144
        addressbook_set_clist( obj );
1145

    
1146
        /* Setup main menu selections */
1147
        addressbook_menubar_set_sensitive( FALSE );
1148
        addressbook_menuitem_set_sensitive( obj, node );
1149

    
1150
        addressbook_list_select_clear();
1151

    
1152
}
1153

    
1154
static void addressbook_list_selected(GtkCList *clist, gint row, gint column,
1155
                                      GdkEvent *event, gpointer data)
1156
{
1157
        if (event && event->type == GDK_2BUTTON_PRESS) {
1158
                /* Handle double click */
1159
                if (prefs_common.add_address_by_click &&
1160
                    addrbook.target_compose)
1161
                        addressbook_to_clicked(NULL, GINT_TO_POINTER(COMPOSE_ENTRY_TO));
1162
                else
1163
                        addressbook_edit_address_cb(NULL, 0, NULL);
1164
        }
1165
}
1166

    
1167
#if 0
1168
static void addressbook_list_select_show() {
1169
        GList *node = _addressListSelection_;
1170
        gchar *addr = NULL;
1171
        printf( "show selection...>>>\n" );
1172
        while( node != NULL ) {
1173
                AddressObject *obj = ( AddressObject * ) node->data;
1174
                if( obj ) {
1175
                        printf( "- %d : '%s'\n", obj->type, obj->name );
1176
                        if( obj->type == ADDR_ITEM_GROUP ) {
1177
                                ItemGroup *group = ( ItemGroup * ) obj;
1178
                                GList *node = group->listEMail;
1179
                                while( node ) {
1180
                                        ItemEMail *email = node->data;
1181
                                        addr = addressbook_format_address( ( AddressObject * ) email );
1182
                                        if( addr ) {
1183
                                                printf( "\tgrp >%s<\n", addr );
1184
                                                g_free( addr );
1185
                                        }
1186
                                        node = g_list_next( node );
1187
                                }
1188
                        }
1189
                        else {
1190
                                addr = addressbook_format_address( obj );
1191
                                if( addr ) {
1192
                                        printf( "\t>%s<\n", addr );
1193
                                        g_free( addr );
1194
                                }
1195
                        }
1196
                }
1197
                else {
1198
                        printf( "- NULL" );
1199
                }
1200
                node = g_list_next( node );
1201
        }
1202
        printf( "show selection...<<<\n" );
1203
}
1204
#endif
1205

    
1206
static void addressbook_list_select_clear() {
1207
        if( _addressListSelection_ ) {
1208
                g_list_free( _addressListSelection_ );
1209
        }
1210
        _addressListSelection_ = NULL;
1211
}
1212

    
1213
static void addressbook_list_select_add( AddressObject *obj ) {
1214
        if( obj ) {
1215
                if(     obj->type == ADDR_ITEM_PERSON ||
1216
                        obj->type == ADDR_ITEM_EMAIL ||
1217
                        obj->type == ADDR_ITEM_GROUP ) {
1218
                        if( ! g_list_find( _addressListSelection_, obj ) ) {
1219
                                _addressListSelection_ = g_list_append( _addressListSelection_, obj );
1220
                        }
1221
                }
1222
        }
1223
        /* addressbook_list_select_show(); */
1224
}
1225

    
1226
static void addressbook_list_select_remove( AddressObject *obj ) {
1227
        if( obj == NULL ) return;
1228
        if( _addressListSelection_ ) {
1229
                _addressListSelection_ = g_list_remove(        _addressListSelection_, obj );
1230
        }
1231
        /* addressbook_list_select_show(); */
1232
}
1233

    
1234
static void addressbook_list_row_selected( GtkCTree *clist, GtkCTreeNode *node, gint column, gpointer data ) {
1235
        GtkEntry *entry = GTK_ENTRY(addrbook.entry);
1236
        AddressObject *obj = NULL;
1237
        AddressObject *pobj = NULL;
1238
        AdapterDSource *ads = NULL;
1239
        AddressInterface *iface = NULL;
1240
        AddressDataSource *ds = NULL;
1241
        gboolean canEdit = FALSE;
1242
        gboolean canDelete = FALSE;
1243

    
1244
        gtk_entry_set_text( entry, "" );
1245
        addrbook.listSelected = node;
1246
        obj = gtk_ctree_node_get_row_data( clist, node );
1247
        if( obj != NULL ) {
1248
                /* printf( "list select: %d : '%s'\n", obj->type, obj->name ); */
1249
                addressbook_list_select_add( obj );
1250
        }
1251

    
1252
        pobj = gtk_ctree_node_get_row_data( GTK_CTREE(addrbook.ctree), addrbook.treeSelected );
1253
        if( pobj == NULL ) return;
1254

    
1255
        menu_set_insensitive_all( GTK_MENU_SHELL(addrbook.list_popup) );
1256

    
1257
        if( pobj->type == ADDR_DATASOURCE ) {
1258
                ads = ADAPTER_DSOURCE(pobj);
1259
                ds = ads->dataSource;
1260
                iface = ds->interface;
1261
                if( ! iface->readOnly ) {
1262
                        canEdit = TRUE;
1263
                        menu_set_sensitive( addrbook.list_factory, "/New Address", TRUE );
1264
                        menu_set_sensitive( addrbook.list_factory, "/New Folder", TRUE );
1265
                        menu_set_sensitive( addrbook.list_factory, "/New Group", TRUE );
1266
                        gtk_widget_set_sensitive( addrbook.reg_btn, TRUE );
1267
                }
1268
        }
1269
        else if( pobj->type != ADDR_INTERFACE ) {
1270
                ds = addressbook_find_datasource( addrbook.treeSelected );
1271
                iface = ds->interface;
1272
                if( ! iface->readOnly ) {
1273
                        if( pobj->type == ADDR_ITEM_FOLDER || pobj->type == ADDR_ITEM_GROUP ) {
1274
                                canEdit = TRUE;
1275
                                menu_set_sensitive( addrbook.list_factory, "/New Address", TRUE );
1276
                                gtk_widget_set_sensitive( addrbook.reg_btn, TRUE );
1277
                        }
1278
                        if( pobj->type == ADDR_ITEM_FOLDER ) {
1279
                                canEdit = TRUE;
1280
                                menu_set_sensitive( addrbook.list_factory, "/New Folder", TRUE );
1281
                                menu_set_sensitive( addrbook.list_factory, "/New Group", TRUE );
1282
                        }
1283
                }
1284
        }
1285
        if( obj == NULL ) canEdit = FALSE;
1286
        canDelete = canEdit;
1287
        if( GTK_CLIST(clist)->selection && GTK_CLIST(clist)->selection->next ) canEdit = FALSE;
1288

    
1289
        menu_set_sensitive( addrbook.list_factory, "/Edit",   canEdit );
1290
        menu_set_sensitive( addrbook.list_factory, "/Delete", canDelete );
1291

    
1292
        menu_set_sensitive( addrbook.menu_factory, "/Address/Edit",   canEdit );
1293
        menu_set_sensitive( addrbook.menu_factory, "/Address/Delete", canDelete );
1294

    
1295
        gtk_widget_set_sensitive( addrbook.del_btn, canDelete );
1296

    
1297
}
1298

    
1299
static void addressbook_list_row_unselected( GtkCTree *ctree, GtkCTreeNode *node, gint column, gpointer data ) {
1300
        AddressObject *obj;
1301

    
1302
        obj = gtk_ctree_node_get_row_data( ctree, node );
1303
        if( obj != NULL ) {
1304
                /* g_print( "list unselect: %d : '%s'\n", obj->type, obj->name ); */
1305
                addressbook_list_select_remove( obj );
1306
        }
1307
}
1308

    
1309
static void addressbook_entry_gotfocus( GtkWidget *widget ) {
1310
        gtk_editable_select_region( GTK_EDITABLE(addrbook.entry), 0, -1 );
1311
}
1312

    
1313
static gboolean addressbook_list_button_pressed(GtkWidget *widget,
1314
                                                GdkEventButton *event,
1315
                                                gpointer data)
1316
{
1317
        if( ! event ) return FALSE;
1318
        if( event->button == 3 ) {
1319
                gtk_menu_popup( GTK_MENU(addrbook.list_popup), NULL, NULL, NULL, NULL,
1320
                       event->button, event->time );
1321
        }
1322
        return FALSE;
1323
}
1324

    
1325
static gboolean addressbook_list_button_released(GtkWidget *widget,
1326
                                                 GdkEventButton *event,
1327
                                                 gpointer data)
1328
{
1329
        return FALSE;
1330
}
1331

    
1332
static gboolean addressbook_tree_button_pressed(GtkWidget *ctree,
1333
                                                GdkEventButton *event,
1334
                                                gpointer data)
1335
{
1336
        GtkCList *clist = GTK_CLIST(ctree);
1337
        gint row, column;
1338
        AddressObject *obj = NULL;
1339
        /* GtkCTreeNode *node; */
1340
        AdapterDSource *ads = NULL;
1341
        AddressInterface *iface = NULL;
1342
        AddressDataSource *ds = NULL;
1343
        /* AddressTypeControlItem *atci = NULL; */
1344
        gboolean canEdit = FALSE;
1345

    
1346
        if( ! event ) return FALSE;
1347
        addressbook_menubar_set_sensitive( FALSE );
1348
/* */
1349
        if( gtk_clist_get_selection_info( clist, event->x, event->y, &row, &column ) ) {
1350
                gtk_clist_select_row( clist, row, column );
1351
                gtkut_clist_set_focus_row(clist, row);
1352
                obj = gtk_clist_get_row_data( clist, row );
1353
        }
1354
/* */
1355
        menu_set_insensitive_all(GTK_MENU_SHELL(addrbook.tree_popup));
1356

    
1357
        if( obj == NULL ) return FALSE;
1358
        if (obj->type == ADDR_DATASOURCE) {
1359
                ads = ADAPTER_DSOURCE(obj);
1360
                ds = ads->dataSource;
1361
                iface = ds->interface;
1362
                canEdit = TRUE;
1363
                if( ! iface->readOnly ) {
1364
                        menu_set_sensitive( addrbook.tree_factory, "/New Address", TRUE );
1365
                        menu_set_sensitive( addrbook.tree_factory, "/New Folder", TRUE );
1366
                        menu_set_sensitive( addrbook.tree_factory, "/New Group", TRUE );
1367
                        gtk_widget_set_sensitive( addrbook.reg_btn, TRUE );
1368
                }
1369
        }
1370
        else if (obj->type == ADDR_ITEM_FOLDER) {
1371
                ds = addressbook_find_datasource( addrbook.treeSelected );
1372
                iface = ds->interface;
1373
                if( ! iface->readOnly ) {
1374
                        canEdit = TRUE;
1375
                        menu_set_sensitive( addrbook.tree_factory, "/New Address", TRUE );
1376
                        menu_set_sensitive( addrbook.tree_factory, "/New Folder", TRUE );
1377
                        menu_set_sensitive( addrbook.tree_factory, "/New Group", TRUE );
1378
                        gtk_widget_set_sensitive( addrbook.reg_btn, TRUE );
1379
                }
1380
        }
1381
        else if (obj->type == ADDR_ITEM_GROUP) {
1382
                ds = addressbook_find_datasource( addrbook.treeSelected );
1383
                iface = ds->interface;
1384
                if( ! iface->readOnly ) {
1385
                        canEdit = TRUE;
1386
                        menu_set_sensitive( addrbook.tree_factory, "/New Address", TRUE );
1387
                        gtk_widget_set_sensitive( addrbook.reg_btn, TRUE );
1388
                }
1389
        }
1390

    
1391
        /* Enable edit */
1392
        menu_set_sensitive( addrbook.tree_factory, "/Edit",   canEdit );
1393
        menu_set_sensitive( addrbook.tree_factory, "/Delete", canEdit );
1394
        menu_set_sensitive( addrbook.menu_factory, "/File/Edit",   canEdit );
1395
        menu_set_sensitive( addrbook.menu_factory, "/File/Delete", canEdit );
1396

    
1397
        if( event->button == 3 ) {
1398
                gtk_menu_popup(GTK_MENU(addrbook.tree_popup), NULL, NULL, NULL, NULL,
1399
                               event->button, event->time);
1400
        }
1401

    
1402
        return FALSE;
1403
}
1404

    
1405
static gboolean addressbook_tree_button_released(GtkWidget *ctree,
1406
                                                 GdkEventButton *event,
1407
                                                 gpointer data)
1408
{
1409
        gtk_ctree_select(GTK_CTREE(addrbook.ctree), addrbook.opened);
1410
        gtkut_ctree_set_focus_row(GTK_CTREE(addrbook.ctree), addrbook.opened);
1411
        return FALSE;
1412
}
1413

    
1414
static void addressbook_popup_close(GtkMenuShell *menu_shell, gpointer data)
1415
{
1416
        if (!addrbook.opened) return;
1417

    
1418
        gtk_ctree_select(GTK_CTREE(addrbook.ctree), addrbook.opened);
1419
        gtkut_ctree_set_focus_row(GTK_CTREE(addrbook.ctree),
1420
                                  addrbook.opened);
1421
}
1422

    
1423
static void addressbook_new_folder_cb(gpointer data, guint action,
1424
                                      GtkWidget *widget)
1425
{
1426
        GtkCTree *ctree = GTK_CTREE(addrbook.ctree);
1427
        AddressObject *obj = NULL;
1428
        AddressDataSource *ds = NULL;
1429
        AddressBookFile *abf = NULL;
1430
        ItemFolder *parentFolder = NULL;
1431
        ItemFolder *folder = NULL;
1432

    
1433
        if( ! addrbook.treeSelected ) return;
1434
        obj = gtk_ctree_node_get_row_data( ctree, addrbook.treeSelected );
1435
        if( obj == NULL ) return;
1436
        ds = addressbook_find_datasource( addrbook.treeSelected );
1437
        if( ds == NULL ) return;
1438

    
1439
        if( obj->type == ADDR_DATASOURCE ) {
1440
                if( ADAPTER_DSOURCE(obj)->subType != ADDR_BOOK ) return;
1441
        }
1442
        else if( obj->type == ADDR_ITEM_FOLDER ) {
1443
                parentFolder = ADAPTER_FOLDER(obj)->itemFolder;
1444
        }
1445
        else {
1446
                return;
1447
        }
1448

    
1449
        abf = ds->rawDataSource;
1450
        if( abf == NULL ) return;
1451
        folder = addressbook_edit_folder( abf, parentFolder, NULL );
1452
        if( folder ) {
1453
                GtkCTreeNode *nn;
1454
                nn = addressbook_node_add_folder( addrbook.treeSelected, ds, folder, ADDR_ITEM_FOLDER );
1455
                gtk_ctree_expand( ctree, addrbook.treeSelected );
1456
                if( addrbook.treeSelected == addrbook.opened ) addressbook_set_clist(obj);
1457
        }
1458

    
1459
}
1460

    
1461
static void addressbook_new_group_cb(gpointer data, guint action,
1462
                                     GtkWidget *widget)
1463
{
1464
        GtkCTree *ctree = GTK_CTREE(addrbook.ctree);
1465
        AddressObject *obj = NULL;
1466
        AddressDataSource *ds = NULL;
1467
        AddressBookFile *abf = NULL;
1468
        ItemFolder *parentFolder = NULL;
1469
        ItemGroup *group = NULL;
1470

    
1471
        if( ! addrbook.treeSelected ) return;
1472
        obj = gtk_ctree_node_get_row_data(ctree, addrbook.treeSelected);
1473
        if( obj == NULL ) return;
1474
        ds = addressbook_find_datasource( addrbook.treeSelected );
1475
        if( ds == NULL ) return;
1476

    
1477
        if( obj->type == ADDR_DATASOURCE ) {
1478
                if( ADAPTER_DSOURCE(obj)->subType != ADDR_BOOK ) return;
1479
        }
1480
        else if( obj->type == ADDR_ITEM_FOLDER ) {
1481
                parentFolder = ADAPTER_FOLDER(obj)->itemFolder;
1482
        }
1483
        else {
1484
                return;
1485
        }
1486

    
1487
        abf = ds->rawDataSource;
1488
        if( abf == NULL ) return;
1489
        group = addressbook_edit_group( abf, parentFolder, NULL );
1490
        if( group ) {
1491
                GtkCTreeNode *nn;
1492
                nn = addressbook_node_add_group( addrbook.treeSelected, ds, group );
1493
                gtk_ctree_expand( ctree, addrbook.treeSelected );
1494
                if( addrbook.treeSelected == addrbook.opened ) addressbook_set_clist(obj);
1495
        }
1496

    
1497
}
1498

    
1499
static void addressbook_change_node_name(GtkCTreeNode *node, const gchar *name)
1500
{
1501
        GtkCTree *ctree = GTK_CTREE(addrbook.ctree);
1502
        gchar *text[1];
1503
        guint8 spacing;
1504
        GdkPixmap *pix_cl, *pix_op;
1505
        GdkBitmap *mask_cl, *mask_op;
1506
        gboolean is_leaf, expanded;
1507

    
1508
        gtk_ctree_get_node_info(ctree, node, text, &spacing,
1509
                                &pix_cl, &mask_cl, &pix_op, &mask_op,
1510
                                &is_leaf, &expanded);
1511
        gtk_ctree_set_node_info(ctree, node, name, spacing,
1512
                                pix_cl, mask_cl, pix_op, mask_op,
1513
                                is_leaf, expanded);
1514
}
1515

    
1516
/*
1517
* Edit data source.
1518
* Enter: obj   Address object to edit.
1519
*        node  Node in tree.
1520
* Return: New name of data source.
1521
*/
1522
static gchar *addressbook_edit_datasource( AddressObject *obj, GtkCTreeNode *node ) {
1523
        gchar *newName = NULL;
1524
        AddressDataSource *ds = NULL;
1525
        AddressInterface *iface = NULL;
1526
        AdapterDSource *ads = NULL;
1527

    
1528
        ds = addressbook_find_datasource( node );
1529
        if( ds == NULL ) return NULL;
1530
        iface = ds->interface;
1531
        if( ! iface->haveLibrary ) return NULL;
1532

    
1533
        /* Read data from data source */
1534
        if( ! addrindex_ds_get_read_flag( ds ) ) {
1535
                addrindex_ds_read_data( ds );
1536
        }
1537

    
1538
        /* Handle edit */
1539
        ads = ADAPTER_DSOURCE(obj);
1540
        if( ads->subType == ADDR_BOOK ) {
1541
                if( addressbook_edit_book( _addressIndex_, ads ) == NULL ) return NULL;
1542
        }
1543
        else if( ads->subType == ADDR_VCARD ) {
1544
                       if( addressbook_edit_vcard( _addressIndex_, ads ) == NULL ) return NULL;
1545
        }
1546
#ifdef USE_JPILOT
1547
        else if( ads->subType == ADDR_JPILOT ) {
1548
                if( addressbook_edit_jpilot( _addressIndex_, ads ) == NULL ) return NULL;
1549
        }
1550
#endif
1551
#ifdef USE_LDAP
1552
        else if( ads->subType == ADDR_LDAP ) {
1553
                if( addressbook_edit_ldap( _addressIndex_, ads ) == NULL ) return NULL;
1554
        }
1555
#endif
1556
        else {
1557
                return NULL;
1558
        }
1559
        newName = obj->name;
1560
        return newName;
1561
}
1562

    
1563
/*
1564
* Edit an object that is in the address tree area.
1565
*/
1566
static void addressbook_treenode_edit_cb(gpointer data, guint action,
1567
                                       GtkWidget *widget)
1568
{
1569
        GtkCTree *ctree = GTK_CTREE(addrbook.ctree);
1570
        AddressObject *obj;
1571
        AddressDataSource *ds = NULL;
1572
        AddressBookFile *abf = NULL;
1573
        GtkCTreeNode *node = NULL, *parentNode = NULL;
1574
        gchar *name = NULL;
1575

    
1576
        if( ! addrbook.treeSelected ) return;
1577
        node = addrbook.treeSelected;
1578
        if( GTK_CTREE_ROW(node)->level == 1 ) return;
1579
        obj = gtk_ctree_node_get_row_data( ctree, node );
1580
        if( obj == NULL ) return;
1581
        parentNode = GTK_CTREE_ROW(node)->parent;
1582

    
1583
        ds = addressbook_find_datasource( node );
1584
        if( ds == NULL ) return;
1585

    
1586
        if( obj->type == ADDR_DATASOURCE ) {
1587
                name = addressbook_edit_datasource( obj, node );
1588
                if( name == NULL ) return;
1589
        }
1590
        else {
1591
                abf = ds->rawDataSource;
1592
                if( abf == NULL ) return;
1593
                if( obj->type == ADDR_ITEM_FOLDER ) {
1594
                        AdapterFolder *adapter = ADAPTER_FOLDER(obj);
1595
                        ItemFolder *item = adapter->itemFolder;
1596
                        ItemFolder *parentFolder = NULL;
1597
                        parentFolder = ( ItemFolder * ) ADDRITEM_PARENT(item);
1598
                        if( addressbook_edit_folder( abf, parentFolder, item ) == NULL ) return;
1599
                        name = ADDRITEM_NAME(item);
1600
                }
1601
                else if( obj->type == ADDR_ITEM_GROUP ) {
1602
                        AdapterGroup *adapter = ADAPTER_GROUP(obj);
1603
                        ItemGroup *item = adapter->itemGroup;
1604
                        ItemFolder *parentFolder = NULL;
1605
                        parentFolder = ( ItemFolder * ) ADDRITEM_PARENT(item);
1606
                        if( addressbook_edit_group( abf, parentFolder, item ) == NULL ) return;
1607
                        name = ADDRITEM_NAME(item);
1608
                }
1609
        }
1610
        if( name && parentNode ) {
1611
                /* Update node in tree view */
1612
                addressbook_change_node_name( node, name );
1613
                gtk_ctree_sort_node(ctree, parentNode);
1614
                gtk_ctree_expand( ctree, node );
1615
                gtk_ctree_select( ctree, node );
1616
        }
1617
}
1618

    
1619
/*
1620
* Delete an item from the tree widget.
1621
*/
1622
static void addressbook_treenode_delete_cb(gpointer data, guint action,
1623
                                         GtkWidget *widget)
1624
{
1625
        GtkCTree *ctree = GTK_CTREE(addrbook.ctree);
1626
        GtkCTreeNode *node = NULL;
1627
        AddressObject *obj;
1628
        gchar *message;
1629
        AlertValue aval;
1630
        AddressBookFile *abf = NULL;
1631
        AdapterDSource *ads = NULL;
1632
        AddressInterface *iface = NULL;
1633
        AddressDataSource *ds = NULL;
1634
        gboolean remFlag = FALSE;
1635

    
1636
        if( ! addrbook.treeSelected ) return;
1637
        node = addrbook.treeSelected;
1638
        if( GTK_CTREE_ROW(node)->level == 1 ) return;
1639

    
1640
        obj = gtk_ctree_node_get_row_data( ctree, node );
1641
        g_return_if_fail(obj != NULL);
1642

    
1643
        if( obj->type == ADDR_DATASOURCE ) {
1644
                ads = ADAPTER_DSOURCE(obj);
1645
                if( ads == NULL ) return;
1646
                ds = ads->dataSource;
1647
                if( ds == NULL ) return;
1648
        }
1649
        else {
1650
                /* Must be folder or something else */
1651
                ds = addressbook_find_datasource( node );
1652
                if( ds == NULL ) return;
1653

    
1654
                /* Only allow deletion from non-readOnly data sources */
1655
                iface = ds->interface;
1656
                if( iface->readOnly ) return;
1657
        }
1658

    
1659
        /* Confirm deletion */
1660
        if( obj->type == ADDR_ITEM_FOLDER ) {
1661
                message = g_strdup_printf( _(
1662
                                "Do you want to delete the folder AND all addresses in `%s' ? \n" \
1663
                                "If deleting the folder only, addresses will be moved into parent folder." ),
1664
                                obj->name );
1665
                aval = alertpanel( _("Delete"), message, _("Folder only"), _("Folder and Addresses"), _("Cancel") );
1666
                g_free(message);
1667
                if( aval == G_ALERTOTHER ) return;
1668
        }
1669
        else {
1670
                message = g_strdup_printf(_("Really delete `%s' ?"), obj->name);
1671
                aval = alertpanel(_("Delete"), message, _("Yes"), _("No"), NULL);
1672
                g_free(message);
1673
                if (aval != G_ALERTDEFAULT) return;
1674
        }
1675

    
1676
        /* Proceed with deletion */
1677
        if( obj->type == ADDR_DATASOURCE ) {
1678
                /* Remove data source. */
1679
                if( addrindex_index_remove_datasource( _addressIndex_, ds ) ) {
1680
                        addressbook_free_child_adapters( node );
1681
                        remFlag = TRUE;
1682
                }
1683
        }
1684
        else {
1685
                abf = addressbook_get_book_file();
1686
                if( abf == NULL ) return;
1687
        }
1688

    
1689
        if( obj->type == ADDR_ITEM_FOLDER ) {
1690
                AdapterFolder *adapter = ADAPTER_FOLDER(obj);
1691
                ItemFolder *item = adapter->itemFolder;
1692
                if( aval == G_ALERTDEFAULT ) {
1693
                        /* Remove folder only */
1694
                        item = addrbook_remove_folder( abf, item );
1695
                        if( item ) {
1696
                                addritem_free_item_folder( item );
1697
                                addressbook_move_nodes_up( ctree, node );
1698
                                remFlag = TRUE;
1699
                        }
1700
                }
1701
                else if( aval == G_ALERTALTERNATE ) {
1702
                        /* Remove folder and addresses */
1703
                        item = addrbook_remove_folder_delete( abf, item );
1704
                        if( item ) {
1705
                                addritem_free_item_folder( item );
1706
                                addressbook_free_child_adapters( node );
1707
                                remFlag = TRUE;
1708
                        }
1709
                }
1710
        }
1711
        else if( obj->type == ADDR_ITEM_GROUP ) {
1712
                AdapterGroup *adapter = ADAPTER_GROUP(obj);
1713
                ItemGroup *item = adapter->itemGroup;
1714

    
1715
                item = addrbook_remove_group( abf, item );
1716
                if( item ) {
1717
                        addritem_free_item_group( item );
1718
                        remFlag = TRUE;
1719
                }
1720
        }
1721

    
1722
        if( remFlag ) {
1723
                /* Free up adapter and remove node. */
1724
                addressbook_free_adapter( node );
1725
                gtk_ctree_remove_node(ctree, node );
1726
        }
1727
}
1728

    
1729
static void addressbook_new_address_cb( gpointer data, guint action, GtkWidget *widget ) {
1730
        AddressObject *pobj = NULL;
1731
        AddressDataSource *ds = NULL;
1732
        AddressBookFile *abf = NULL;
1733

    
1734
        pobj = gtk_ctree_node_get_row_data(GTK_CTREE(addrbook.ctree), addrbook.treeSelected);
1735
        if( pobj == NULL ) return;
1736
        ds = addressbook_find_datasource( GTK_CTREE_NODE(addrbook.treeSelected) );
1737
        if( ds == NULL ) return;
1738

    
1739
        abf = ds->rawDataSource;
1740
        if( abf == NULL ) return;
1741

    
1742
        if( pobj->type == ADDR_DATASOURCE ) {
1743
                if( ADAPTER_DSOURCE(pobj)->subType == ADDR_BOOK ) {
1744
                        /* New address */
1745
                        ItemPerson *person = addressbook_edit_person( abf, NULL, NULL, FALSE );
1746
                        if( person ) {
1747
                                if( addrbook.treeSelected == addrbook.opened ) {
1748
                                        gtk_ctree_select( GTK_CTREE(addrbook.ctree), addrbook.opened );
1749
                                }
1750
                        }
1751
                }
1752
        }
1753
        else if( pobj->type == ADDR_ITEM_FOLDER ) {
1754
                /* New address */
1755
                ItemFolder *folder = ADAPTER_FOLDER(pobj)->itemFolder;
1756
                ItemPerson *person = addressbook_edit_person( abf, folder, NULL, FALSE );
1757
                if( person ) {
1758
                        if (addrbook.treeSelected == addrbook.opened) {
1759
                                gtk_ctree_select( GTK_CTREE(addrbook.ctree), addrbook.opened );
1760
                        }
1761
                }
1762
        }
1763
        else if( pobj->type == ADDR_ITEM_GROUP ) {
1764
                /* New address in group */
1765
                ItemGroup *group = ADAPTER_GROUP(pobj)->itemGroup;
1766
                if( addressbook_edit_group( abf, NULL, group ) == NULL ) return;
1767
                if (addrbook.treeSelected == addrbook.opened) {
1768
                        /* Change node name in tree. */
1769
                        addressbook_change_node_name( addrbook.treeSelected, ADDRITEM_NAME(group) );
1770
                        gtk_ctree_select( GTK_CTREE(addrbook.ctree), addrbook.opened );
1771
                }
1772
        }
1773
}
1774

    
1775
/*
1776
* Search for specified group in address index tree.
1777
*/
1778
static GtkCTreeNode *addressbook_find_group_node( GtkCTreeNode *parent, ItemGroup *group ) {
1779
        GtkCTreeNode *node = NULL;
1780
        GtkCTreeRow *currRow;
1781

    
1782
        currRow = GTK_CTREE_ROW( parent );
1783
        if( currRow ) {
1784
                node = currRow->children;
1785
                while( node ) {
1786
                        AddressObject *obj = gtk_ctree_node_get_row_data( GTK_CTREE(addrbook.ctree), node );
1787
                        if( obj->type == ADDR_ITEM_GROUP ) {
1788
                                ItemGroup *g = ADAPTER_GROUP(obj)->itemGroup;
1789
                                if( g == group ) return node;
1790
                        }
1791
                        currRow = GTK_CTREE_ROW(node);
1792
                        node = currRow->sibling;
1793
                }
1794
        }
1795
        return NULL;
1796
}
1797

    
1798
static AddressBookFile *addressbook_get_book_file() {
1799
        AddressBookFile *abf = NULL;
1800
        AddressDataSource *ds = NULL;
1801

    
1802
        ds = addressbook_find_datasource( addrbook.treeSelected );
1803
        if( ds == NULL ) return NULL;
1804
        if( ds->type == ADDR_IF_BOOK ) abf = ds->rawDataSource;
1805
        return abf;
1806
}
1807

    
1808
static void addressbook_tree_remove_children( GtkCTree *ctree, GtkCTreeNode *parent ) {
1809
        GtkCTreeNode *node;
1810
        GtkCTreeRow *row;
1811

    
1812
        /* Remove existing folders and groups */
1813
        row = GTK_CTREE_ROW( parent );
1814
        if( row ) {
1815
                while( (node = row->children) ) {
1816
                        gtk_ctree_remove_node( ctree, node );
1817
                }
1818
        }
1819
}
1820

    
1821
static void addressbook_move_nodes_up( GtkCTree *ctree, GtkCTreeNode *node ) {
1822
        GtkCTreeNode *parent, *child;
1823
        GtkCTreeRow *currRow;
1824
        currRow = GTK_CTREE_ROW( node );
1825
        if( currRow ) {
1826
                parent = currRow->parent;
1827
                while( (child = currRow->children) ) {
1828
                        gtk_ctree_move( ctree, child, parent, node );
1829
                }
1830
                gtk_ctree_sort_node( ctree, parent );
1831
        }
1832
}
1833

    
1834
static void addressbook_edit_address_cb( gpointer data, guint action, GtkWidget *widget ) {
1835
        GtkCTree *clist = GTK_CTREE(addrbook.clist);
1836
        GtkCTree *ctree;
1837
        AddressObject *obj = NULL, *pobj = NULL;
1838
        AddressDataSource *ds = NULL;
1839
        GtkCTreeNode *node = NULL, *parentNode = NULL;
1840
        gchar *name = NULL;
1841
        AddressBookFile *abf = NULL;
1842

    
1843
        if( addrbook.listSelected == NULL ) return;
1844
        obj = gtk_ctree_node_get_row_data( clist, addrbook.listSelected );
1845
        g_return_if_fail(obj != NULL);
1846

    
1847
               ctree = GTK_CTREE( addrbook.ctree );
1848
        pobj = gtk_ctree_node_get_row_data( ctree, addrbook.treeSelected );
1849
        node = gtk_ctree_find_by_row_data( ctree, addrbook.treeSelected, obj );
1850

    
1851
        ds = addressbook_find_datasource( GTK_CTREE_NODE(addrbook.treeSelected) );
1852
        if( ds == NULL ) return;
1853

    
1854
        abf = addressbook_get_book_file();
1855
        if( abf == NULL ) return;
1856
        if( obj->type == ADDR_ITEM_EMAIL ) {
1857
                ItemEMail *email = ( ItemEMail * ) obj;
1858
                ItemPerson *person;
1859
                if( email == NULL ) return;
1860
                if( pobj && pobj->type == ADDR_ITEM_GROUP ) {
1861
                        /* Edit parent group */
1862
                        AdapterGroup *adapter = ADAPTER_GROUP(pobj);
1863
                        ItemGroup *itemGrp = adapter->itemGroup;
1864
                        if( addressbook_edit_group( abf, NULL, itemGrp ) == NULL ) return;
1865
                        name = ADDRITEM_NAME(itemGrp);
1866
                        node = addrbook.treeSelected;
1867
                        parentNode = GTK_CTREE_ROW(node)->parent;
1868
                }
1869
                else {
1870
                        /* Edit person - email page */
1871
                        person = ( ItemPerson * ) ADDRITEM_PARENT(email);
1872
                        if( addressbook_edit_person( abf, NULL, person, TRUE ) == NULL ) return;
1873
                        gtk_ctree_select( ctree, addrbook.opened );
1874
                        invalidate_address_completion();
1875
                        return;
1876
                }
1877
        }
1878
        else if( obj->type == ADDR_ITEM_PERSON ) {
1879
                /* Edit person - basic page */
1880
                ItemPerson *person = ( ItemPerson * ) obj;
1881
                if( addressbook_edit_person( abf, NULL, person, FALSE ) == NULL ) return;
1882
                gtk_ctree_select( ctree, addrbook.opened );
1883
                invalidate_address_completion();
1884
                return;
1885
        }
1886
        else if( obj->type == ADDR_ITEM_GROUP ) {
1887
                ItemGroup *itemGrp = ( ItemGroup * ) obj;
1888
                if( addressbook_edit_group( abf, NULL, itemGrp ) == NULL ) return;
1889
                parentNode = addrbook.treeSelected;
1890
                node = addressbook_find_group_node( parentNode, itemGrp );
1891
                name = ADDRITEM_NAME(itemGrp);
1892
        }
1893
        else {
1894
                return;
1895
        }
1896

    
1897
        /* Update tree node with node name */
1898
        if( node == NULL ) return;
1899
        addressbook_change_node_name( node, name );
1900
        gtk_ctree_sort_node( ctree, parentNode );
1901
        gtk_ctree_select( ctree, addrbook.opened );
1902
}
1903

    
1904
static void addressbook_delete_address_cb(gpointer data, guint action,
1905
                                          GtkWidget *widget)
1906
{
1907
        addressbook_del_clicked(NULL, NULL);
1908
}
1909

    
1910
static void close_cb(gpointer data, guint action, GtkWidget *widget)
1911
{
1912
        addressbook_close();
1913
}
1914

    
1915
static void addressbook_file_save_cb( gpointer data, guint action, GtkWidget *widget ) {
1916
        addressbook_export_to_file();
1917
}
1918

    
1919
static void addressbook_person_expand_node( GtkCTree *ctree, GList *node, gpointer *data ) {
1920
        if( node ) {
1921
                ItemPerson *person = gtk_ctree_node_get_row_data( ctree, GTK_CTREE_NODE(node) );
1922
                if( person ) addritem_person_set_opened( person, TRUE );
1923
        }
1924
}
1925

    
1926
static void addressbook_person_collapse_node( GtkCTree *ctree, GList *node, gpointer *data ) {
1927
        if( node ) {
1928
                ItemPerson *person = gtk_ctree_node_get_row_data( ctree, GTK_CTREE_NODE(node) );
1929
                if( person ) addritem_person_set_opened( person, FALSE );
1930
        }
1931
}
1932

    
1933
static gchar *addressbook_format_item_clist( ItemPerson *person, ItemEMail *email ) {
1934
        gchar *str = NULL;
1935
        gchar *eMailAlias = ADDRITEM_NAME(email);
1936
        if( eMailAlias && *eMailAlias != '\0' ) {
1937
                if( person ) {
1938
                        str = g_strdup_printf( "%s - %s", ADDRITEM_NAME(person), eMailAlias );
1939
                }
1940
                else {
1941
                        str = g_strdup( eMailAlias );
1942
                }
1943
        }
1944
        return str;
1945
}
1946

    
1947
static void addressbook_load_group( GtkCTree *clist, ItemGroup *itemGroup ) {
1948
        GList *items = itemGroup->listEMail;
1949
        AddressTypeControlItem *atci = addrbookctl_lookup( ADDR_ITEM_EMAIL );
1950
        for( ; items != NULL; items = g_list_next( items ) ) {
1951
                GtkCTreeNode *nodeEMail = NULL;
1952
                gchar *text[N_COLS];
1953
                ItemEMail *email = items->data;
1954
                ItemPerson *person;
1955
                gchar *str = NULL;
1956

    
1957
                if( ! email ) continue;
1958

    
1959
                person = ( ItemPerson * ) ADDRITEM_PARENT(email);
1960
                str = addressbook_format_item_clist( person, email );
1961
                if( str ) {
1962
                        text[COL_NAME] = str;
1963
                }
1964
                else {
1965
                        text[COL_NAME] = ADDRITEM_NAME(person);
1966
                }
1967
                text[COL_ADDRESS] = email->address;
1968
                text[COL_REMARKS] = email->remarks;
1969
                nodeEMail = gtk_ctree_insert_node(
1970
                                clist, NULL, NULL,
1971
                                text, FOLDER_SPACING,
1972
                                atci->iconXpm, atci->maskXpm,
1973
                                atci->iconXpmOpen, atci->maskXpmOpen,
1974
                                FALSE, FALSE );
1975
                gtk_ctree_node_set_row_data( clist, nodeEMail, email );
1976
                g_free( str );
1977
                str = NULL;
1978
        }
1979
}
1980

    
1981
static void addressbook_folder_load_person( GtkCTree *clist, ItemFolder *itemFolder ) {
1982
        GList *items;
1983
        AddressTypeControlItem *atci = addrbookctl_lookup( ADDR_ITEM_PERSON );
1984
        AddressTypeControlItem *atciMail = addrbookctl_lookup( ADDR_ITEM_EMAIL );
1985

    
1986
        if( atci == NULL ) return;
1987
        if( atciMail == NULL ) return;
1988

    
1989
        /* Load email addresses */
1990
        items = addritem_folder_get_person_list( itemFolder );
1991
        for( ; items != NULL; items = g_list_next( items ) ) {
1992
                GtkCTreeNode *nodePerson = NULL;
1993
                GtkCTreeNode *nodeEMail = NULL;
1994
                gchar *text[N_COLS];
1995
                gboolean flgFirst = TRUE, haveAddr = FALSE;
1996
                /* gint row; */
1997
                ItemPerson *person;
1998
                GList *node;
1999

    
2000
                person = ( ItemPerson * ) items->data;
2001
                if( person == NULL ) continue;
2002

    
2003
                text[COL_NAME] = NULL;
2004
                node = person->listEMail;
2005
                while( node ) {
2006
                        ItemEMail *email = node->data;
2007
                        gchar *eMailAddr = NULL;
2008
                        node = g_list_next( node );
2009

    
2010
                        text[COL_ADDRESS] = email->address;
2011
                        text[COL_REMARKS] = email->remarks;
2012
                        eMailAddr = ADDRITEM_NAME(email);
2013
                        if( eMailAddr && *eMailAddr == '\0' ) eMailAddr = NULL;
2014
                        if( flgFirst ) {
2015
                                /* First email belongs with person */
2016
                                gchar *str = addressbook_format_item_clist( person, email );
2017
                                if( str ) {
2018
                                        text[COL_NAME] = str;
2019
                                }
2020
                                else {
2021
                                        text[COL_NAME] = ADDRITEM_NAME(person);
2022
                                }
2023
                                nodePerson = gtk_ctree_insert_node(
2024
                                                clist, NULL, NULL,
2025
                                                text, FOLDER_SPACING,
2026
                                                atci->iconXpm, atci->maskXpm,
2027
                                                atci->iconXpmOpen, atci->maskXpmOpen,
2028
                                                FALSE, person->isOpened );
2029
                                g_free( str );
2030
                                str = NULL;
2031
                                gtk_ctree_node_set_row_data(clist, nodePerson, person );
2032
                        }
2033
                        else {
2034
                                /* Subsequent email is a child node of person */
2035
                                text[COL_NAME] = ADDRITEM_NAME(email);
2036
                                nodeEMail = gtk_ctree_insert_node(
2037
                                                clist, nodePerson, NULL,
2038
                                                text, FOLDER_SPACING,
2039
                                                atciMail->iconXpm, atciMail->maskXpm,
2040
                                                atciMail->iconXpmOpen, atciMail->maskXpmOpen,
2041
                                                FALSE, TRUE );
2042
                                gtk_ctree_node_set_row_data(clist, nodeEMail, email );
2043
                        }
2044
                        flgFirst = FALSE;
2045
                        haveAddr = TRUE;
2046
                }
2047
                if( ! haveAddr ) {
2048
                        /* Have name without EMail */
2049
                        text[COL_NAME] = ADDRITEM_NAME(person);
2050
                        text[COL_ADDRESS] = NULL;
2051
                        text[COL_REMARKS] = NULL;
2052
                        nodePerson = gtk_ctree_insert_node(
2053
                                        clist, NULL, NULL,
2054
                                        text, FOLDER_SPACING,
2055
                                        atci->iconXpm, atci->maskXpm,
2056
                                        atci->iconXpmOpen, atci->maskXpmOpen,
2057
                                        FALSE, person->isOpened );
2058
                        gtk_ctree_node_set_row_data(clist, nodePerson, person );
2059
                }
2060
        }
2061
        gtk_ctree_sort_node(GTK_CTREE(clist), NULL);
2062

    
2063
        /* Free up the list */
2064
        mgu_clear_list( items );
2065
        g_list_free( items );
2066
}
2067

    
2068
static void addressbook_folder_load_group( GtkCTree *clist, ItemFolder *itemFolder ) {
2069
        GList *items;
2070
        AddressTypeControlItem *atci =  addrbookctl_lookup( ADDR_ITEM_GROUP );
2071

    
2072
        /* Load any groups */
2073
        if( ! atci ) return;
2074
        items = addritem_folder_get_group_list( itemFolder );
2075
        for( ; items != NULL; items = g_list_next( items ) ) {
2076
                GtkCTreeNode *nodeGroup = NULL;
2077
                gchar *text[N_COLS];
2078
                ItemGroup *group = items->data;
2079
                if( group == NULL ) continue;
2080
                text[COL_NAME] = ADDRITEM_NAME(group);
2081
                text[COL_ADDRESS] = NULL;
2082
                text[COL_REMARKS] = NULL;
2083
                nodeGroup = gtk_ctree_insert_node(clist, NULL, NULL,
2084
                                      text, FOLDER_SPACING,
2085
                                      atci->iconXpm, atci->maskXpm,
2086
                                      atci->iconXpmOpen, atci->maskXpmOpen,
2087
                                      FALSE, FALSE);
2088
                gtk_ctree_node_set_row_data(clist, nodeGroup, group );
2089
        }
2090
        gtk_ctree_sort_node(clist, NULL);
2091

    
2092
        /* Free up the list */
2093
        mgu_clear_list( items );
2094
        g_list_free( items );
2095
}
2096

    
2097
#if 0
2098
/*
2099
 * Load data sources into list.
2100
 */
2101
static void addressbook_node_load_datasource( GtkCTree *clist, AddressObject *obj ) {
2102
        AdapterInterface *adapter;
2103
        AddressInterface *iface;
2104
        AddressTypeControlItem *atci = NULL;
2105
        /* AddressDataSource *ds; */
2106
        GtkCTreeNode *newNode, *node;
2107
        GtkCTreeRow *row;
2108
        GtkCell *cell = NULL;
2109
        gchar *text[N_COLS];
2110

2111
        adapter = ADAPTER_INTERFACE(obj);
2112
        if( adapter == NULL ) return;
2113
        iface = adapter->interface;
2114
        atci = adapter->atci;
2115
        if( atci == NULL ) return;
2116

2117
        /* Create nodes in list copying values for data sources in tree */
2118
        row = GTK_CTREE_ROW( adapter->treeNode );
2119
        if( row ) {
2120
                node = row->children;
2121
                while( node ) {
2122
                        gpointer data = gtk_ctree_node_get_row_data( clist, node );
2123
                        row = GTK_CTREE_ROW( node );
2124
                        cell = ( ( GtkCListRow * )row )->cell;
2125
                        text[COL_NAME] = cell->u.text;
2126
                        text[COL_ADDRESS] = NULL;
2127
                        text[COL_REMARKS] = NULL;
2128
                        newNode = gtk_ctree_insert_node( clist, NULL, NULL,
2129
                                      text, FOLDER_SPACING,
2130
                                      atci->iconXpm, atci->maskXpm,
2131
                                      atci->iconXpmOpen, atci->maskXpmOpen,
2132
                                      FALSE, FALSE);
2133
                        gtk_ctree_node_set_row_data( clist, newNode, data );
2134
                        node = row->sibling;
2135

2136
                }
2137
        }
2138
        gtk_ctree_sort_node( clist, NULL );
2139
}
2140
#endif
2141

    
2142
static AddressDataSource *addressbook_find_datasource( GtkCTreeNode *node ) {
2143
        AddressDataSource *ds = NULL;
2144
        AddressObject *ao;
2145

    
2146
        g_return_val_if_fail(addrbook.ctree != NULL, NULL);
2147

    
2148
        while( node ) {
2149
                if( GTK_CTREE_ROW(node)->level < 2 ) return NULL;
2150
                ao = gtk_ctree_node_get_row_data( GTK_CTREE(addrbook.ctree), node );
2151
                if( ao ) {
2152
/*                        printf( "ao->type = %d\n", ao->type ); */
2153
                        if( ao->type == ADDR_DATASOURCE ) {
2154
                                AdapterDSource *ads = ADAPTER_DSOURCE(ao);
2155
/*                                printf( "found it\n" ); */
2156
                                ds = ads->dataSource;
2157
                                break;
2158
                        }
2159
                }
2160
                node = GTK_CTREE_ROW(node)->parent;
2161
        }
2162
        return ds;
2163
}
2164

    
2165
/*
2166
* Load address list widget with children of specified object.
2167
* Enter: obj        Parent object to be loaded.
2168
*/
2169
static void addressbook_set_clist( AddressObject *obj ) {
2170
        GtkCTree *ctreelist = GTK_CTREE(addrbook.clist);
2171
        GtkCList *clist = GTK_CLIST(addrbook.clist);
2172
        AddressDataSource *ds = NULL;
2173
        AdapterDSource *ads = NULL;
2174

    
2175
        if( obj == NULL ) {
2176
                gtk_clist_clear(clist);
2177
                return;
2178
        }
2179

    
2180
        if( obj->type == ADDR_INTERFACE ) {
2181
                /* printf( "set_clist: loading datasource...\n" ); */
2182
                /* addressbook_node_load_datasource( clist, obj ); */
2183
                return;
2184
        }
2185

    
2186
        gtk_clist_freeze(clist);
2187
        gtk_clist_clear(clist);
2188

    
2189
        if( obj->type == ADDR_DATASOURCE ) {
2190
                ads = ADAPTER_DSOURCE(obj);
2191
                ds = ADAPTER_DSOURCE(obj)->dataSource;
2192
                if( ds ) {
2193
                        /* Load root folder */
2194
                        ItemFolder *rootFolder = NULL;
2195
                        rootFolder = addrindex_ds_get_root_folder( ds );
2196
                        addressbook_folder_load_person( ctreelist, addrindex_ds_get_root_folder( ds ) );
2197
                        addressbook_folder_load_group( ctreelist, addrindex_ds_get_root_folder( ds ) );
2198
                }
2199
        }
2200
        else {
2201
                if( obj->type == ADDR_ITEM_GROUP ) {
2202
                        /* Load groups */
2203
                        ItemGroup *itemGroup = ADAPTER_GROUP(obj)->itemGroup;
2204
                        addressbook_load_group( ctreelist, itemGroup );
2205
                }
2206
                else if( obj->type == ADDR_ITEM_FOLDER ) {
2207
                        /* Load folders */
2208
                        ItemFolder *itemFolder = ADAPTER_FOLDER(obj)->itemFolder;
2209
                        addressbook_folder_load_person( ctreelist, itemFolder );
2210
                        addressbook_folder_load_group( ctreelist, itemFolder );
2211
                }
2212
        }
2213

    
2214
        gtk_clist_sort(clist);
2215
        gtk_clist_thaw(clist);
2216
}
2217

    
2218
/*
2219
* Free adaptor for specified node.
2220
*/
2221
static void addressbook_free_adapter( GtkCTreeNode *node ) {
2222
        AddressObject *ao;
2223

    
2224
        g_return_if_fail(addrbook.ctree != NULL);
2225

    
2226
        if( node ) {
2227
                if( GTK_CTREE_ROW(node)->level < 2 ) return;
2228
                ao = gtk_ctree_node_get_row_data( GTK_CTREE(addrbook.ctree), node );
2229
                if( ao == NULL ) return;
2230
                if( ao->type == ADDR_INTERFACE ) {
2231
                        AdapterInterface *ai = ADAPTER_INTERFACE(ao);
2232
                        addrbookctl_free_interface( ai );
2233
                }
2234
                else if( ao->type == ADDR_DATASOURCE ) {
2235
                        AdapterDSource *ads = ADAPTER_DSOURCE(ao);
2236
                        addrbookctl_free_datasource( ads );
2237
                }
2238
                else if( ao->type == ADDR_ITEM_FOLDER ) {
2239
                        AdapterFolder *af = ADAPTER_FOLDER(ao);
2240
                        addrbookctl_free_folder( af );
2241
                }
2242
                else if( ao->type == ADDR_ITEM_GROUP ) {
2243
                        AdapterGroup *ag = ADAPTER_GROUP(ao);
2244
                        addrbookctl_free_group( ag );
2245
                }
2246
                gtk_ctree_node_set_row_data( GTK_CTREE(addrbook.ctree), node, NULL );
2247
        }
2248
}
2249

    
2250
/*
2251
* Free all children adapters.
2252
*/
2253
static void addressbook_free_child_adapters( GtkCTreeNode *node ) {
2254
        GtkCTreeNode *parent, *child;
2255
        GtkCTreeRow *currRow;
2256

    
2257
        if( node == NULL ) return;
2258
        currRow = GTK_CTREE_ROW( node );
2259
        if( currRow ) {
2260
                parent = currRow->parent;
2261
                child = currRow->children;
2262
                while( child ) {
2263
                        addressbook_free_child_adapters( child );
2264
                        addressbook_free_adapter( child );
2265
                        currRow = GTK_CTREE_ROW( child );
2266
                        child = currRow->sibling;
2267
                }
2268
        }
2269
}
2270

    
2271
AdapterDSource *addressbook_create_ds_adapter( AddressDataSource *ds,
2272
                                AddressObjectType otype, gchar *name )
2273
{
2274
        AdapterDSource *adapter = g_new0( AdapterDSource, 1 );
2275
        ADDRESS_OBJECT(adapter)->type = ADDR_DATASOURCE;
2276
        ADDRESS_OBJECT_NAME(adapter) = g_strdup( name );
2277
        adapter->dataSource = ds;
2278
        adapter->subType = otype;
2279
        return adapter;
2280
}
2281

    
2282
void addressbook_ads_set_name( AdapterDSource *adapter, gchar *value ) {
2283
        ADDRESS_OBJECT_NAME(adapter) = mgu_replace_string( ADDRESS_OBJECT_NAME(adapter), value );
2284
}
2285

    
2286
/*
2287
 * Load tree from address index with the initial data.
2288
 */
2289
static void addressbook_load_tree( void ) {
2290
        GtkCTree *ctree = GTK_CTREE( addrbook.ctree );
2291
        GList *nodeIf, *nodeDS;
2292
        AdapterInterface *adapter;
2293
        AddressInterface *iface;
2294
        AddressTypeControlItem *atci;
2295
        AddressDataSource *ds;
2296
        AdapterDSource *ads;
2297
        GtkCTreeNode *node, *newNode;
2298
        gchar *name;
2299

    
2300
        nodeIf = _addressInterfaceList_;
2301
        while( nodeIf ) {
2302
                adapter = nodeIf->data;
2303
                node = adapter->treeNode;
2304
                iface = adapter->interface;
2305
                atci = adapter->atci;
2306
                if( iface ) {
2307
                        if( iface->useInterface ) {
2308
                                /* Load data sources below interface node */
2309
                                nodeDS = iface->listSource;
2310
                                while( nodeDS ) {
2311
                                        ds = nodeDS->data;
2312
                                        newNode = NULL;
2313
                                        name = addrindex_ds_get_name( ds );
2314
                                        ads = addressbook_create_ds_adapter( ds, atci->objectType, name );
2315
                                        newNode = addressbook_add_object( node, ADDRESS_OBJECT(ads) );
2316
                                        nodeDS = g_list_next( nodeDS );
2317
                                }
2318
                                gtk_ctree_expand( ctree, node );
2319
                        }
2320
                }
2321
                nodeIf = g_list_next( nodeIf );
2322
        }
2323
}
2324

    
2325
/*
2326
 * Convert the old address book to new format.
2327
 */
2328
static gboolean addressbook_convert( AddressIndex *addrIndex ) {
2329
        gboolean retVal = FALSE;
2330
        gboolean errFlag = TRUE;
2331
        gchar *msg = NULL;
2332

    
2333
        /* Read old address book, performing conversion */
2334
        debug_print( "Reading and converting old address book...\n" );
2335
        addrindex_set_file_name( addrIndex, ADDRESSBOOK_OLD_FILE );
2336
        addrindex_read_data( addrIndex );
2337
        if( addrIndex->retVal == MGU_NO_FILE ) {
2338
                /* We do not have a file - new user */
2339
                debug_print( "New user... create new books...\n" );
2340
                addrindex_create_new_books( addrIndex );
2341
                if( addrIndex->retVal == MGU_SUCCESS ) {
2342
                        /* Save index file */
2343
                        addrindex_set_file_name( addrIndex, ADDRESSBOOK_INDEX_FILE );
2344
                        addrindex_save_data( addrIndex );
2345
                        if( addrIndex->retVal == MGU_SUCCESS ) {
2346
                                retVal = TRUE;
2347
                                errFlag = FALSE;
2348
                        }
2349
                        else {
2350
                                msg = _( "New user, could not save index file." );
2351
                        }
2352
                }
2353
                else {
2354
                        msg = _( "New user, could not save address book files." );
2355
                }
2356
        }
2357
        else {
2358
                /* We have an old file */
2359
                if( addrIndex->wasConverted ) {
2360
                        /* Converted successfully - save address index */
2361
                        addrindex_set_file_name( addrIndex, ADDRESSBOOK_INDEX_FILE );
2362
                        addrindex_save_data( addrIndex );
2363
                        if( addrIndex->retVal == MGU_SUCCESS ) {
2364
                                msg = _( "Old address book converted successfully." );
2365
                                retVal = TRUE;
2366
                                errFlag = FALSE;
2367
                        }
2368
                        else {
2369
                                msg = _("Old address book converted,\n"
2370
                                        "could not save new address index file" );
2371
                        }
2372
                }
2373
                else {
2374
                        /* File conversion failed - just create new books */
2375
                        debug_print( "File conversion failed... just create new books...\n" );
2376
                        addrindex_create_new_books( addrIndex );
2377
                        if( addrIndex->retVal == MGU_SUCCESS ) {
2378
                                /* Save index */
2379
                                addrindex_set_file_name( addrIndex, ADDRESSBOOK_INDEX_FILE );
2380
                                addrindex_save_data( addrIndex );
2381
                                if( addrIndex->retVal == MGU_SUCCESS ) {
2382
                                        msg = _("Could not convert address book,\n"
2383
                                                "but created empty new address book files." );
2384
                                        retVal = TRUE;
2385
                                        errFlag = FALSE;
2386
                                }
2387
                                else {
2388
                                        msg = _("Could not convert address book,\n"
2389
                                                "could not create new address book files." );
2390
                                }
2391
                        }
2392
                        else {
2393
                                msg = _("Could not convert address book\n"
2394
                                        "and could not create new address book files." );
2395
                        }
2396
                }
2397
        }
2398
        if( errFlag ) {
2399
                debug_print( "Error\n%s\n", msg );
2400
                alertpanel( _( "Addressbook conversion error" ), msg, _( "Close" ), NULL, NULL );
2401
        }
2402
        else if( msg ) {
2403
                debug_print( "Warning\n%s\n", msg );
2404
                alertpanel( _( "Addressbook conversion" ), msg, _( "Close" ), NULL, NULL );
2405
        }
2406

    
2407
        return retVal;
2408
}
2409

    
2410
void addressbook_read_file( void ) {
2411
        AddressIndex *addrIndex = NULL;
2412

    
2413
        debug_print( "Reading address index...\n" );
2414
        if( _addressIndex_ ) {
2415
                debug_print( "address book already read!!!\n" );
2416
                return;
2417
        }
2418

    
2419
        addrIndex = addrindex_create_index();
2420

    
2421
        /* Use new address book index. */
2422
        addrindex_set_file_path( addrIndex, get_rc_dir() );
2423
        addrindex_set_file_name( addrIndex, ADDRESSBOOK_INDEX_FILE );
2424
        addrindex_read_data( addrIndex );
2425
        if( addrIndex->retVal == MGU_NO_FILE ) {
2426
                /* Conversion required */
2427
                debug_print( "Converting...\n" );
2428
                if( addressbook_convert( addrIndex ) ) {
2429
                        _addressIndex_ = addrIndex;
2430
                }
2431
        }
2432
        else if( addrIndex->retVal == MGU_SUCCESS ) {
2433
                _addressIndex_ = addrIndex;
2434
        }
2435
        else {
2436
                /* Error reading address book */
2437
                debug_print( "Could not read address index.\n" );
2438
                addrindex_print_index( addrIndex, stdout );
2439
                alertpanel( _( "Addressbook Error" ),
2440
                            _( "Could not read address index" ),
2441
                            _( "Close" ), NULL, NULL );
2442
        }
2443
        debug_print( "done.\n" );
2444
}
2445

    
2446
#if 0
2447
void addressbook_read_file_old( void ) {
2448
        AddressIndex *addrIndex = NULL;
2449
        gboolean errFlag = TRUE;
2450
        gchar *msg = NULL;
2451

2452
        if( _addressIndex_ ) {
2453
                debug_print( "address book already read!!!\n" );
2454
                return;
2455
        }
2456

2457
        addrIndex = addrindex_create_index();
2458

2459
        /* Use use new address book. */
2460
        /* addrindex_set_file_path( addrIndex, "/home/match/tmp/empty-dir" ); */
2461
        addrindex_set_file_path( addrIndex, get_rc_dir() );
2462
        addrindex_set_file_name( addrIndex, ADDRESSBOOK_INDEX_FILE );
2463

2464
        debug_print( "Reading address index...\n" );
2465
        addrindex_read_data( addrIndex );
2466
        if( addrIndex->retVal == MGU_NO_FILE ) {
2467
                /* Read old address book, performing conversion */
2468
                debug_print( "Reading and converting old address book...\n" );
2469
                addrindex_set_file_name( addrIndex, ADDRESSBOOK_OLD_FILE );
2470
                addrindex_read_data( addrIndex );
2471
                if( addrIndex->retVal == MGU_NO_FILE ) {
2472
                        /* We do not have a file - new user */
2473
                        debug_print( "New user... create new books...\n" );
2474
                        addrindex_create_new_books( addrIndex );
2475
                        if( addrIndex->retVal == MGU_SUCCESS ) {
2476
                                /* Save index file */
2477
                                addrindex_set_file_name( addrIndex, ADDRESSBOOK_INDEX_FILE );
2478
                                addrindex_save_data( addrIndex );
2479
                                if( addrIndex->retVal == MGU_SUCCESS ) {
2480
                                        errFlag = FALSE;
2481
                                }
2482
                                else {
2483
                                        msg = g_strdup( _( "New user, could not save index file." ) );
2484
                                }
2485
                        }
2486
                        else {
2487
                                msg = g_strdup( _( "New user, could not save address book files." ) );
2488
                        }
2489
                }
2490
                else {
2491
                        /* We have an old file */
2492
                        if( addrIndex->wasConverted ) {
2493
                                /* Converted successfully - save address index */
2494
                                addrindex_set_file_name( addrIndex, ADDRESSBOOK_INDEX_FILE );
2495
                                addrindex_save_data( addrIndex );
2496
                                if( addrIndex->retVal == MGU_SUCCESS ) {
2497
                                        msg = g_strdup( _( "Old address book converted successfully." ) );
2498
                                        errFlag = FALSE;
2499
                                }
2500
                                else {
2501
                                        msg = g_strdup( _(
2502
                                                "Old address book converted, " \
2503
                                                "could not save new address index file" ) );
2504
                                }
2505
                        }
2506
                        else {
2507
                                /* File conversion failed - just create new books */
2508
                                debug_print( "File conversion failed... just create new books...\n" );
2509
                                addrindex_create_new_books( addrIndex );
2510
                                if( addrIndex->retVal == MGU_SUCCESS ) {
2511
                                        /* Save index */
2512
                                        addrindex_set_file_name( addrIndex, ADDRESSBOOK_INDEX_FILE );
2513
                                        addrindex_save_data( addrIndex );
2514
                                        if( addrIndex->retVal == MGU_SUCCESS ) {
2515
                                                msg = g_strdup( _(
2516
                                                        "Could not convert address book, " \
2517
                                                        "but created empty new address book files." ) );
2518
                                                errFlag = FALSE;
2519
                                        }
2520
                                        else {
2521
                                                msg = g_strdup( _(
2522
                                                        "Could not convert address book, " \
2523
                                                        "could not create new address book files." ) );
2524
                                        }
2525
                                }
2526
                                else {
2527
                                        msg = g_strdup( _(
2528
                                                "Could not convert address book " \
2529
                                                "and could not create new address book files." ) );
2530
                                }
2531
                        }
2532
                }
2533
        }
2534
        else if( addrIndex->retVal == MGU_SUCCESS ) {
2535
                errFlag = FALSE;
2536
        }
2537
        else {
2538
                debug_print( "Could not read address index.\n" );
2539
                addrindex_print_index( addrIndex, stdout );
2540
                msg = g_strdup( _( "Could not read address index" ) );
2541
        }
2542
        _addressIndex_ = addrIndex;
2543

2544
        if( errFlag ) {
2545
                debug_print( "Error\n%s\n", msg );
2546
                alertpanel( _( "Addressbook Conversion Error" ), msg,
2547
                            _( "Close" ), NULL, NULL );
2548
        }
2549
        else {
2550
                if( msg ) {
2551
                        debug_print( "Warning\n%s\n", msg );
2552
                        alertpanel( _( "Addressbook Conversion" ), msg,
2553
                                    _( "Close" ), NULL, NULL );
2554
                }
2555
        }
2556
        if( msg ) g_free( msg );
2557
        debug_print( "done.\n" );
2558
}
2559
#endif
2560

    
2561
/*
2562
* Add object into the address index tree widget.
2563
* Enter: node        Parent node.
2564
*        obj        Object to add.
2565
* Return: Node that was added, or NULL if object not added.
2566
*/
2567
static GtkCTreeNode *addressbook_add_object(GtkCTreeNode *node,
2568
                                            AddressObject *obj)
2569
{
2570
        GtkCTree *ctree = GTK_CTREE(addrbook.ctree);
2571
        GtkCTreeNode *added;
2572
        AddressObject *pobj;
2573
        AddressObjectType otype;
2574
        AddressTypeControlItem *atci = NULL;
2575

    
2576
        g_return_val_if_fail(node != NULL, NULL);
2577
        g_return_val_if_fail(obj  != NULL, NULL);
2578

    
2579
        pobj = gtk_ctree_node_get_row_data(ctree, node);
2580
        g_return_val_if_fail(pobj != NULL, NULL);
2581

    
2582
        /* Determine object type to be displayed */
2583
        if( obj->type == ADDR_DATASOURCE ) {
2584
                otype = ADAPTER_DSOURCE(obj)->subType;
2585
        }
2586
        else {
2587
                otype = obj->type;
2588
        }
2589

    
2590
        /* Handle any special conditions. */
2591
        added = node;
2592
        atci = addrbookctl_lookup( otype );
2593
        if( atci ) {
2594
                if( atci->showInTree ) {
2595
                        /* Add object to tree */
2596
                        gchar **name;
2597
                        name = &obj->name;
2598
                        added = gtk_ctree_insert_node( ctree, node, NULL, name, FOLDER_SPACING,
2599
                                atci->iconXpm, atci->maskXpm, atci->iconXpmOpen, atci->maskXpmOpen,
2600
                                atci->treeLeaf, atci->treeExpand );
2601
                        gtk_ctree_node_set_row_data(ctree, added, obj);
2602
                }
2603
        }
2604

    
2605
        gtk_ctree_sort_node(ctree, node);
2606

    
2607
        return added;
2608
}
2609

    
2610
/*
2611
* Add group into the address index tree.
2612
* Enter: node           Parent node.
2613
*        ds        Data source.
2614
*        itemGroup Group to add.
2615
* Return: Inserted node.
2616
*/
2617
static GtkCTreeNode *addressbook_node_add_group( GtkCTreeNode *node, AddressDataSource *ds, ItemGroup *itemGroup ) {
2618
        GtkCTree *ctree = GTK_CTREE(addrbook.ctree);
2619
        GtkCTreeNode *newNode;
2620
        AdapterGroup *adapter;
2621
        AddressTypeControlItem *atci = NULL;
2622
        gchar **name;
2623

    
2624
        if( ds == NULL ) return NULL;
2625
        if( node == NULL || itemGroup == NULL ) return NULL;
2626

    
2627
        name = &itemGroup->obj.name;
2628

    
2629
        atci = addrbookctl_lookup( ADDR_ITEM_GROUP );
2630

    
2631
        adapter = g_new0( AdapterGroup, 1 );
2632
        ADDRESS_OBJECT_TYPE(adapter) = ADDR_ITEM_GROUP;
2633
        ADDRESS_OBJECT_NAME(adapter) = g_strdup( ADDRITEM_NAME(itemGroup) );
2634
        adapter->itemGroup = itemGroup;
2635

    
2636
        newNode = gtk_ctree_insert_node( ctree, node, NULL, name, FOLDER_SPACING,
2637
                        atci->iconXpm, atci->maskXpm, atci->iconXpm, atci->maskXpm,
2638
                        atci->treeLeaf, atci->treeExpand );
2639
        gtk_ctree_node_set_row_data( ctree, newNode, adapter );
2640
        gtk_ctree_sort_node( ctree, node );
2641
        return newNode;
2642
}
2643

    
2644
/*
2645
* Add folder into the address index tree.
2646
* Enter: node            Parent node.
2647
*        ds         Data source.
2648
*        itemFolder Folder to add.
2649
*        otype      Object type to display.
2650
* Return: Inserted node.
2651
*/
2652
static GtkCTreeNode *addressbook_node_add_folder(
2653
                GtkCTreeNode *node, AddressDataSource *ds, ItemFolder *itemFolder, AddressObjectType otype )
2654
{
2655
        GtkCTree *ctree = GTK_CTREE(addrbook.ctree);
2656
        GtkCTreeNode *newNode = NULL;
2657
        AdapterFolder *adapter;
2658
        AddressTypeControlItem *atci = NULL;
2659
        GList *listItems = NULL;
2660
        gchar **name;
2661
        ItemFolder *rootFolder;
2662

    
2663
        if( ds == NULL ) return NULL;
2664
        if( node == NULL || itemFolder == NULL ) return NULL;
2665

    
2666
        /* Determine object type */
2667
        atci = addrbookctl_lookup( otype );
2668
        if( atci == NULL ) return NULL;
2669

    
2670
        rootFolder = addrindex_ds_get_root_folder( ds );
2671
        if( itemFolder == rootFolder ) {
2672
                newNode = node;
2673
        }
2674
        else {
2675
                name = &itemFolder->obj.name;
2676

    
2677
                adapter = g_new0( AdapterFolder, 1 );
2678
                ADDRESS_OBJECT_TYPE(adapter) = ADDR_ITEM_FOLDER;
2679
                ADDRESS_OBJECT_NAME(adapter) = g_strdup( ADDRITEM_NAME(itemFolder) );
2680
                adapter->itemFolder = itemFolder;
2681

    
2682
                newNode = gtk_ctree_insert_node( ctree, node, NULL, name, FOLDER_SPACING,
2683
                                atci->iconXpm, atci->maskXpm, atci->iconXpm, atci->maskXpm,
2684
                                atci->treeLeaf, atci->treeExpand );
2685
                gtk_ctree_node_set_row_data( ctree, newNode, adapter );
2686
        }
2687

    
2688
        listItems = itemFolder->listFolder;
2689
        while( listItems ) {
2690
                ItemFolder *item = listItems->data;
2691
                addressbook_node_add_folder( newNode, ds, item, otype );
2692
                listItems = g_list_next( listItems );
2693
        }
2694
        listItems = itemFolder->listGroup;
2695
        while( listItems ) {
2696
                ItemGroup *item = listItems->data;
2697
                addressbook_node_add_group( newNode, ds, item );
2698
                listItems = g_list_next( listItems );
2699
        }
2700
        gtk_ctree_sort_node( ctree, node );
2701
        return newNode;
2702
}
2703

    
2704
#if 0
2705
static void addressbook_delete_object(AddressObject *obj) {
2706
        AdapterDSource *ads = NULL;
2707
        AddressDataSource *ds = NULL;
2708
        if (!obj) return;
2709

2710
        /* Remove data source. */
2711
        /* printf( "Delete obj type : %d\n", obj->type ); */
2712

2713
        ads = ADAPTER_DSOURCE(obj);
2714
        if( ads == NULL ) return;
2715
        ds = ads->dataSource;
2716
        if( ds == NULL ) return;
2717

2718
        /* Remove data source */
2719
        if( addrindex_index_remove_datasource( _addressIndex_, ds ) ) {
2720
                addrindex_free_datasource( _addressIndex_, ds );
2721
        }
2722
        /* Free up Adapter object */
2723
        g_free( ADAPTER_DSOURCE(obj) );
2724
}
2725
#endif
2726

    
2727
void addressbook_export_to_file( void ) {
2728
        if( _addressIndex_ ) {
2729
                /* Save all new address book data */
2730
                debug_print( "Saving address books...\n" );
2731
                addrindex_save_all_books( _addressIndex_ );
2732

    
2733
                debug_print( "Exporting addressbook to file...\n" );
2734
                addrindex_save_data( _addressIndex_ );
2735
                if( _addressIndex_->retVal != MGU_SUCCESS ) {
2736
                        addrindex_print_index( _addressIndex_, stdout );
2737
                }
2738

    
2739
                /* Notify address completion of new data */
2740
                invalidate_address_completion();
2741
        }
2742
}
2743

    
2744
static gboolean key_pressed(GtkWidget *widget, GdkEventKey *event,
2745
                            gpointer data)
2746
{
2747
        if (event && event->keyval == GDK_Escape)
2748
                addressbook_close();
2749
        return FALSE;
2750
}
2751

    
2752
/*
2753
* Comparsion using names of AddressItem objects.
2754
*/
2755
/*
2756
static gint addressbook_list_compare_func(GtkCList *clist,
2757
                                          gconstpointer ptr1,
2758
                                          gconstpointer ptr2)
2759
{
2760
        AddressObject *obj1 = ((GtkCListRow *)ptr1)->data;
2761
        AddressObject *obj2 = ((GtkCListRow *)ptr2)->data;
2762
        gchar *name1 = NULL, *name2 = NULL;
2763
        if( obj1 ) name1 = obj1->name;
2764
        if( obj2 ) name2 = obj2->name;
2765
        if( ! name1 ) return ( name2 != NULL );
2766
        if( ! name2 ) return -1;
2767
        return strcasecmp(name1, name2);
2768
}
2769
*/
2770

    
2771
/*
2772
* Comparison using cell contents (text in first column).
2773
*/
2774
static gint addressbook_list_compare_func( GtkCList *clist, gconstpointer ptr1, gconstpointer ptr2 ) {
2775
        GtkCell *cell1 = ((GtkCListRow *)ptr1)->cell;
2776
        GtkCell *cell2 = ((GtkCListRow *)ptr2)->cell;
2777
        gchar *name1 = NULL, *name2 = NULL;
2778
        if( cell1 ) name1 = cell1->u.text;
2779
        if( cell2 ) name2 = cell2->u.text;
2780
        if( ! name1 ) return ( name2 != NULL );
2781
        if( ! name2 ) return -1;
2782
        return strcasecmp( name1, name2 );
2783
}
2784

    
2785
/* static */ 
2786
gint addressbook_obj_name_compare(gconstpointer a, gconstpointer b)
2787
{
2788
        const AddressObject *obj = a;
2789
        const gchar *name = b;
2790
        AddressTypeControlItem *atci = NULL;
2791

    
2792
        if (!obj || !name) return -1;
2793

    
2794
        atci = addrbookctl_lookup( obj->type );
2795
        if( ! atci ) return -1;
2796
        if( ! obj->name ) return -1;
2797
        return strcasecmp(obj->name, name);
2798
}
2799

    
2800
#if 0
2801
static void addressbook_book_show_message( AddressBookFile *abf ) {
2802
        *addressbook_msgbuf = '\0';
2803
        if( abf ) {
2804
                if( abf->retVal == MGU_SUCCESS ) {
2805
                        sprintf( addressbook_msgbuf, "%s", abf->name );
2806
                }
2807
                else {
2808
                        sprintf( addressbook_msgbuf, "%s: %s", abf->name, mgu_error2string( abf->retVal ) );
2809
                }
2810
        }
2811
        addressbook_status_show( addressbook_msgbuf );
2812
}
2813
#endif
2814

    
2815
static void addressbook_new_book_cb( gpointer data, guint action, GtkWidget *widget ) {
2816
        AdapterDSource *ads;
2817
        AdapterInterface *adapter;
2818

    
2819
        adapter = addrbookctl_find_interface( ADDR_IF_BOOK );
2820
        if( adapter == NULL ) return;
2821
        if( addrbook.treeSelected == NULL ) return;
2822
        if( addrbook.treeSelected != adapter->treeNode ) return;
2823
        ads = addressbook_edit_book( _addressIndex_, NULL );
2824
        if( ads ) {
2825
                addressbook_add_object( addrbook.treeSelected, ADDRESS_OBJECT(ads) );
2826
                if( addrbook.treeSelected == addrbook.opened ) {
2827
                        gtk_ctree_select( GTK_CTREE(addrbook.ctree), addrbook.opened );
2828
                }
2829
        }
2830
}
2831

    
2832
static void addressbook_new_vcard_cb( gpointer data, guint action, GtkWidget *widget ) {
2833
        AdapterDSource *ads;
2834
        AdapterInterface *adapter;
2835

    
2836
        adapter = addrbookctl_find_interface( ADDR_IF_VCARD );
2837
        if( adapter == NULL ) return;
2838
        if( addrbook.treeSelected != adapter->treeNode ) return;
2839
        ads = addressbook_edit_vcard( _addressIndex_, NULL );
2840
        if( ads ) {
2841
                addressbook_add_object( addrbook.treeSelected, ADDRESS_OBJECT(ads) );
2842
                if( addrbook.treeSelected == addrbook.opened ) {
2843
                        gtk_ctree_select( GTK_CTREE(addrbook.ctree), addrbook.opened );
2844
                }
2845
        }
2846
}
2847

    
2848
#if 0
2849
static void addressbook_vcard_show_message( VCardFile *vcf ) {
2850
        *addressbook_msgbuf = '\0';
2851
        if( vcf ) {
2852
                if( vcf->retVal == MGU_SUCCESS ) {
2853
                        sprintf( addressbook_msgbuf, "%s", vcf->name );
2854
                }
2855
                else {
2856
                        sprintf( addressbook_msgbuf, "%s: %s", vcf->name, mgu_error2string( vcf->retVal ) );
2857
                }
2858
        }
2859
        addressbook_status_show( addressbook_msgbuf );
2860
}
2861
#endif
2862

    
2863
#ifdef USE_JPILOT
2864
static void addressbook_new_jpilot_cb( gpointer data, guint action, GtkWidget *widget ) {
2865
        AdapterDSource *ads;
2866
        AdapterInterface *adapter;
2867
        AddressInterface *iface;
2868

    
2869
        adapter = addrbookctl_find_interface( ADDR_IF_JPILOT );
2870
        if( adapter == NULL ) return;
2871
        if( addrbook.treeSelected != adapter->treeNode ) return;
2872
        iface = adapter->interface;
2873
        if( ! iface->haveLibrary ) return;
2874
        ads = addressbook_edit_jpilot( _addressIndex_, NULL );
2875
        if( ads ) {
2876
                addressbook_add_object( addrbook.treeSelected, ADDRESS_OBJECT(ads) );
2877
                if( addrbook.treeSelected == addrbook.opened ) {
2878
                        gtk_ctree_select( GTK_CTREE(addrbook.ctree), addrbook.opened );
2879
                }
2880
        }
2881
}
2882

    
2883
#if 0
2884
static void addressbook_jpilot_show_message( JPilotFile *jpf ) {
2885
        *addressbook_msgbuf = '\0';
2886
        if( jpf ) {
2887
                if( jpf->retVal == MGU_SUCCESS ) {
2888
                        sprintf( addressbook_msgbuf, "%s", jpf->name );
2889
                }
2890
                else {
2891
                        sprintf( addressbook_msgbuf, "%s: %s", jpf->name, mgu_error2string( jpf->retVal ) );
2892
                }
2893
        }
2894
        addressbook_status_show( addressbook_msgbuf );
2895
}
2896
#endif
2897
#endif /* USE_JPILOT */
2898

    
2899
#ifdef USE_LDAP
2900
static void addressbook_new_ldap_cb( gpointer data, guint action, GtkWidget *widget ) {
2901
        AdapterDSource *ads;
2902
        AdapterInterface *adapter;
2903
        AddressInterface *iface;
2904

    
2905
        adapter = addrbookctl_find_interface( ADDR_IF_LDAP );
2906
        if( adapter == NULL ) return;
2907
        if( addrbook.treeSelected != adapter->treeNode ) return;
2908
        iface = adapter->interface;
2909
        if( ! iface->haveLibrary ) return;
2910
        ads = addressbook_edit_ldap( _addressIndex_, NULL );
2911
        if( ads ) {
2912
                addressbook_add_object( addrbook.treeSelected, ADDRESS_OBJECT(ads) );
2913
                if( addrbook.treeSelected == addrbook.opened ) {
2914
                        gtk_ctree_select( GTK_CTREE(addrbook.ctree), addrbook.opened );
2915
                }
2916
        }
2917
}
2918

    
2919
static void addressbook_ldap_show_message( SyldapServer *svr ) {
2920
        *addressbook_msgbuf = '\0';
2921
        if( svr ) {
2922
                if( svr->busyFlag ) {
2923
                        sprintf( addressbook_msgbuf, "%s: %s", svr->name, ADDRESSBOOK_LDAP_BUSYMSG );
2924
                }
2925
                else {
2926
                        if( svr->retVal == MGU_SUCCESS ) {
2927
                                sprintf( addressbook_msgbuf, "%s", svr->name );
2928
                        }
2929
                        else {
2930
                                sprintf( addressbook_msgbuf, "%s: %s", svr->name, mgu_error2string( svr->retVal ) );
2931
                        }
2932
                }
2933
        }
2934
        addressbook_status_show( addressbook_msgbuf );
2935
}
2936

    
2937
static void ldapsearch_callback( SyldapServer *sls ) {
2938
        GtkCTree *ctree = GTK_CTREE(addrbook.ctree);
2939
        AddressObject *obj;
2940
        AdapterDSource *ads = NULL;
2941
        AddressDataSource *ds = NULL;
2942
        AddressInterface *iface = NULL;
2943

    
2944
        if( sls == NULL ) return;
2945
        if( ! addrbook.treeSelected ) return;
2946
        if( GTK_CTREE_ROW( addrbook.treeSelected )->level == 1 ) return;
2947

    
2948
        obj = gtk_ctree_node_get_row_data( ctree, addrbook.treeSelected );
2949
        if( obj == NULL ) return;
2950
        if( obj->type == ADDR_DATASOURCE ) {
2951
                ads = ADAPTER_DSOURCE(obj);
2952
                if( ads->subType == ADDR_LDAP ) {
2953
                        SyldapServer *server;
2954

    
2955
                        ds = ads->dataSource;
2956
                        if( ds == NULL ) return;
2957
                        iface = ds->interface;
2958
                        if( ! iface->haveLibrary ) return;
2959
                        server = ds->rawDataSource;
2960
                        if( server == sls ) {
2961
                                /* Read from cache */
2962
                                gtk_widget_show_all(addrbook.window);
2963
                                addressbook_set_clist( obj );
2964
                                addressbook_ldap_show_message( sls );
2965
                                gtk_widget_show_all(addrbook.window);
2966
                                gtk_entry_set_text( GTK_ENTRY(addrbook.entry), "" );
2967
                        }
2968
                }
2969
        }
2970
}
2971
#endif
2972

    
2973
/*
2974
 * Lookup button handler.
2975
 */
2976
static void addressbook_lup_clicked( GtkButton *button, gpointer data ) {
2977
        GtkCTree *ctree = GTK_CTREE(addrbook.ctree);
2978
        AddressObject *obj;
2979
        AdapterDSource *ads = NULL;
2980
#ifdef USE_LDAP
2981
        AddressDataSource *ds = NULL;
2982
        AddressInterface *iface = NULL;
2983
#endif /* USE_LDAP */
2984
        gchar *sLookup;
2985

    
2986
        if( ! addrbook.treeSelected ) return;
2987
        if( GTK_CTREE_ROW( addrbook.treeSelected )->level == 1 ) return;
2988

    
2989
        obj = gtk_ctree_node_get_row_data( ctree, addrbook.treeSelected );
2990
        if( obj == NULL ) return;
2991

    
2992
        sLookup = gtk_editable_get_chars( GTK_EDITABLE(addrbook.entry), 0, -1 );
2993
        g_strchomp( sLookup );
2994

    
2995
        if( obj->type == ADDR_DATASOURCE ) {
2996
                ads = ADAPTER_DSOURCE(obj);
2997
#ifdef USE_LDAP
2998
                if( ads->subType == ADDR_LDAP ) {
2999
                        SyldapServer *server;
3000

    
3001
                        ds = ads->dataSource;
3002
                        if( ds == NULL ) return;
3003
                        iface = ds->interface;
3004
                        if( ! iface->haveLibrary ) return;
3005
                        server = ds->rawDataSource;
3006
                        if( server ) {
3007
                                syldap_cancel_read( server );
3008
                                if( *sLookup == '\0' || strlen( sLookup ) < 1 ) return;
3009
                                syldap_set_search_value( server, sLookup );
3010
                                syldap_set_callback( server, ldapsearch_callback );
3011
                                syldap_read_data_th( server );
3012
                                addressbook_ldap_show_message( server );
3013
                        }
3014
                }
3015
#endif /* USE_LDAP */
3016
        }
3017

    
3018
        g_free( sLookup );
3019
}
3020

    
3021
/* **********************************************************************
3022
* Build lookup tables.
3023
* ***********************************************************************
3024
*/
3025

    
3026
/*
3027
* Build table that controls the rendering of object types.
3028
*/
3029
void addrbookctl_build_map( GtkWidget *window ) {
3030
        AddressTypeControlItem *atci;
3031

    
3032
        /* Build icons */
3033
        stock_pixmap_gdk(window, STOCK_PIXMAP_DIR_CLOSE, &folderxpm, &folderxpmmask);
3034
        stock_pixmap_gdk(window, STOCK_PIXMAP_DIR_OPEN, &folderopenxpm, &folderopenxpmmask);
3035
        stock_pixmap_gdk(window, STOCK_PIXMAP_GROUP, &groupxpm, &groupxpmmask);
3036
        stock_pixmap_gdk(window, STOCK_PIXMAP_VCARD, &vcardxpm, &vcardxpmmask);
3037
        stock_pixmap_gdk(window, STOCK_PIXMAP_BOOK, &bookxpm, &bookxpmmask);
3038
        stock_pixmap_gdk(window, STOCK_PIXMAP_ADDRESS, &addressxpm, &addressxpmmask);
3039
        stock_pixmap_gdk(window, STOCK_PIXMAP_JPILOT, &jpilotxpm, &jpilotxpmmask);
3040
        stock_pixmap_gdk(window, STOCK_PIXMAP_CATEGORY, &categoryxpm, &categoryxpmmask);
3041
        stock_pixmap_gdk(window, STOCK_PIXMAP_LDAP, &ldapxpm, &ldapxpmmask);
3042

    
3043
        _addressBookTypeHash_ = g_hash_table_new( g_int_hash, g_int_equal );
3044
        _addressBookTypeList_ = NULL;
3045

    
3046
        /* Interface */
3047
        atci = g_new0( AddressTypeControlItem, 1 );
3048
        atci->objectType = ADDR_INTERFACE;
3049
        atci->interfaceType = ADDR_IF_NONE;
3050
        atci->showInTree = TRUE;
3051
        atci->treeExpand = TRUE;
3052
        atci->treeLeaf = FALSE;
3053
        atci->displayName = _( "Interface" );
3054
        atci->iconXpm = folderxpm;
3055
        atci->maskXpm = folderxpmmask;
3056
        atci->iconXpmOpen = folderopenxpm;
3057
        atci->maskXpmOpen = folderopenxpmmask;
3058
        atci->menuCommand = NULL;
3059
        g_hash_table_insert( _addressBookTypeHash_, &atci->objectType, atci );
3060
        _addressBookTypeList_ = g_list_append( _addressBookTypeList_, atci );
3061

    
3062
        /* Address book */
3063
        atci = g_new0( AddressTypeControlItem, 1 );
3064
        atci->objectType = ADDR_BOOK;
3065
        atci->interfaceType = ADDR_IF_BOOK;
3066
        atci->showInTree = TRUE;
3067
        atci->treeExpand = TRUE;
3068
        atci->treeLeaf = FALSE;
3069
        atci->displayName = _( "Address Book" );
3070
        atci->iconXpm = bookxpm;
3071
        atci->maskXpm = bookxpmmask;
3072
        atci->iconXpmOpen = bookxpm;
3073
        atci->maskXpmOpen = bookxpmmask;
3074
        atci->menuCommand = "/File/New Book";
3075
        g_hash_table_insert( _addressBookTypeHash_, &atci->objectType, atci );
3076
        _addressBookTypeList_ = g_list_append( _addressBookTypeList_, atci );
3077

    
3078
        /* Item person */
3079
        atci = g_new0( AddressTypeControlItem, 1 );
3080
        atci->objectType = ADDR_ITEM_PERSON;
3081
        atci->interfaceType = ADDR_IF_NONE;
3082
        atci->showInTree = FALSE;
3083
        atci->treeExpand = FALSE;
3084
        atci->treeLeaf = FALSE;
3085
        atci->displayName = _( "Person" );
3086
        atci->iconXpm = NULL;
3087
        atci->maskXpm = NULL;
3088
        atci->iconXpmOpen = NULL;
3089
        atci->maskXpmOpen = NULL;
3090
        atci->menuCommand = NULL;
3091
        g_hash_table_insert( _addressBookTypeHash_, &atci->objectType, atci );
3092
        _addressBookTypeList_ = g_list_append( _addressBookTypeList_, atci );
3093

    
3094
        /* Item email */
3095
        atci = g_new0( AddressTypeControlItem, 1 );
3096
        atci->objectType = ADDR_ITEM_EMAIL;
3097
        atci->interfaceType = ADDR_IF_NONE;
3098
        atci->showInTree = FALSE;
3099
        atci->treeExpand = FALSE;
3100
        atci->treeLeaf = TRUE;
3101
        atci->displayName = _( "EMail Address" );
3102
        atci->iconXpm = addressxpm;
3103
        atci->maskXpm = addressxpmmask;
3104
        atci->iconXpmOpen = addressxpm;
3105
        atci->maskXpmOpen = addressxpmmask;
3106
        atci->menuCommand = NULL;
3107
        g_hash_table_insert( _addressBookTypeHash_, &atci->objectType, atci );
3108
        _addressBookTypeList_ = g_list_append( _addressBookTypeList_, atci );
3109

    
3110
        /* Item group */
3111
        atci = g_new0( AddressTypeControlItem, 1 );
3112
        atci->objectType = ADDR_ITEM_GROUP;
3113
        atci->interfaceType = ADDR_IF_BOOK;
3114
        atci->showInTree = TRUE;
3115
        atci->treeExpand = FALSE;
3116
        atci->treeLeaf = FALSE;
3117
        atci->displayName = _( "Group" );
3118
        atci->iconXpm = groupxpm;
3119
        atci->maskXpm = groupxpmmask;
3120
        atci->iconXpmOpen = groupxpm;
3121
        atci->maskXpmOpen = groupxpmmask;
3122
        atci->menuCommand = NULL;
3123
        g_hash_table_insert( _addressBookTypeHash_, &atci->objectType, atci );
3124
        _addressBookTypeList_ = g_list_append( _addressBookTypeList_, atci );
3125

    
3126
        /* Item folder */
3127
        atci = g_new0( AddressTypeControlItem, 1 );
3128
        atci->objectType = ADDR_ITEM_FOLDER;
3129
        atci->interfaceType = ADDR_IF_BOOK;
3130
        atci->showInTree = TRUE;
3131
        atci->treeExpand = FALSE;
3132
        atci->treeLeaf = FALSE;
3133
        atci->displayName = _( "Folder" );
3134
        atci->iconXpm = folderxpm;
3135
        atci->maskXpm = folderxpmmask;
3136
        atci->iconXpmOpen = folderopenxpm;
3137
        atci->maskXpmOpen = folderopenxpmmask;
3138
        atci->menuCommand = NULL;
3139
        g_hash_table_insert( _addressBookTypeHash_, &atci->objectType, atci );
3140
        _addressBookTypeList_ = g_list_append( _addressBookTypeList_, atci );
3141

    
3142
        /* vCard */
3143
        atci = g_new0( AddressTypeControlItem, 1 );
3144
        atci->objectType = ADDR_VCARD;
3145
        atci->interfaceType = ADDR_IF_VCARD;
3146
        atci->showInTree = TRUE;
3147
        atci->treeExpand = TRUE;
3148
        atci->treeLeaf = TRUE;
3149
        atci->displayName = _( "vCard" );
3150
        atci->iconXpm = vcardxpm;
3151
        atci->maskXpm = vcardxpmmask;
3152
        atci->iconXpmOpen = vcardxpm;
3153
        atci->maskXpmOpen = vcardxpmmask;
3154
        atci->menuCommand = "/File/New vCard";
3155
        g_hash_table_insert( _addressBookTypeHash_, &atci->objectType, atci );
3156
        _addressBookTypeList_ = g_list_append( _addressBookTypeList_, atci );
3157

    
3158
        /* JPilot */
3159
        atci = g_new0( AddressTypeControlItem, 1 );
3160
        atci->objectType = ADDR_JPILOT;
3161
        atci->interfaceType = ADDR_IF_JPILOT;
3162
        atci->showInTree = TRUE;
3163
        atci->treeExpand = TRUE;
3164
        atci->treeLeaf = FALSE;
3165
        atci->displayName = _( "JPilot" );
3166
        atci->iconXpm = jpilotxpm;
3167
        atci->maskXpm = jpilotxpmmask;
3168
        atci->iconXpmOpen = jpilotxpm;
3169
        atci->maskXpmOpen = jpilotxpmmask;
3170
        atci->menuCommand = "/File/New JPilot";
3171
        g_hash_table_insert( _addressBookTypeHash_, &atci->objectType, atci );
3172
        _addressBookTypeList_ = g_list_append( _addressBookTypeList_, atci );
3173

    
3174
        /* Category */
3175
        atci = g_new0( AddressTypeControlItem, 1 );
3176
        atci->objectType = ADDR_CATEGORY;
3177
        atci->interfaceType = ADDR_IF_JPILOT;
3178
        atci->showInTree = TRUE;
3179
        atci->treeExpand = TRUE;
3180
        atci->treeLeaf = TRUE;
3181
        atci->displayName = _( "JPilot" );
3182
        atci->iconXpm = categoryxpm;
3183
        atci->maskXpm = categoryxpmmask;
3184
        atci->iconXpmOpen = categoryxpm;
3185
        atci->maskXpmOpen = categoryxpmmask;
3186
        atci->menuCommand = NULL;
3187
        g_hash_table_insert( _addressBookTypeHash_, &atci->objectType, atci );
3188
        _addressBookTypeList_ = g_list_append( _addressBookTypeList_, atci );
3189

    
3190
        /* LDAP Server */
3191
        atci = g_new0( AddressTypeControlItem, 1 );
3192
        atci->objectType = ADDR_LDAP;
3193
        atci->interfaceType = ADDR_IF_LDAP;
3194
        atci->showInTree = TRUE;
3195
        atci->treeExpand = TRUE;
3196
        atci->treeLeaf = TRUE;
3197
        atci->displayName = _( "LDAP Server" );
3198
        atci->iconXpm = ldapxpm;
3199
        atci->maskXpm = ldapxpmmask;
3200
        atci->iconXpmOpen = ldapxpm;
3201
        atci->maskXpmOpen = ldapxpmmask;
3202
        atci->menuCommand = "/File/New Server";
3203
        g_hash_table_insert( _addressBookTypeHash_, &atci->objectType, atci );
3204
        _addressBookTypeList_ = g_list_append( _addressBookTypeList_, atci );
3205

    
3206
}
3207

    
3208
/*
3209
* Search for specified object type.
3210
*/
3211
AddressTypeControlItem *addrbookctl_lookup( gint ot ) {
3212
        gint objType = ot;
3213
        return ( AddressTypeControlItem * ) g_hash_table_lookup( _addressBookTypeHash_, &objType );
3214
}
3215

    
3216
/*
3217
* Search for specified interface type.
3218
*/
3219
AddressTypeControlItem *addrbookctl_lookup_iface( AddressIfType ifType ) {
3220
        GList *node = _addressBookTypeList_;
3221
        while( node ) {
3222
                AddressTypeControlItem *atci = node->data;
3223
                if( atci->interfaceType == ifType ) return atci;
3224
                node = g_list_next( node );
3225
        }
3226
        return NULL;
3227
}
3228

    
3229
static void addrbookctl_free_address( AddressObject *obj ) {
3230
        g_free( obj->name );
3231
        obj->type = ADDR_NONE;
3232
        obj->name = NULL;
3233
}
3234

    
3235
static void addrbookctl_free_interface( AdapterInterface *adapter ) {
3236
        addrbookctl_free_address( ADDRESS_OBJECT(adapter) );
3237
        adapter->interface = NULL;
3238
        adapter->interfaceType = ADDR_IF_NONE;
3239
        adapter->atci = NULL;
3240
        adapter->enabled = FALSE;
3241
        adapter->haveLibrary = FALSE;
3242
        adapter->treeNode = NULL;
3243
        g_free( adapter );
3244
}
3245

    
3246
static void addrbookctl_free_datasource( AdapterDSource *adapter ) {
3247
        addrbookctl_free_address( ADDRESS_OBJECT(adapter) );
3248
        adapter->dataSource = NULL;
3249
        adapter->subType = ADDR_NONE;
3250
        g_free( adapter );
3251
}
3252

    
3253
static void addrbookctl_free_folder( AdapterFolder *adapter ) {
3254
        addrbookctl_free_address( ADDRESS_OBJECT(adapter) );
3255
        adapter->itemFolder = NULL;
3256
        g_free( adapter );
3257
}
3258

    
3259
static void addrbookctl_free_group( AdapterGroup *adapter ) {
3260
        addrbookctl_free_address( ADDRESS_OBJECT(adapter) );
3261
        adapter->itemGroup = NULL;
3262
        g_free( adapter );
3263
}
3264

    
3265
/*
3266
 * Build GUI interface list.
3267
 */
3268
void addrbookctl_build_iflist() {
3269
        AddressTypeControlItem *atci;
3270
        AdapterInterface *adapter;
3271
        GList *list = NULL;
3272

    
3273
        if( _addressIndex_ == NULL ) {
3274
                _addressIndex_ = addrindex_create_index();
3275
        }
3276
        _addressInterfaceList_ = NULL;
3277
        list = addrindex_get_interface_list( _addressIndex_ );
3278
        while( list ) {
3279
                AddressInterface *interface = list->data;
3280
                atci = addrbookctl_lookup_iface( interface->type );
3281
                if( atci ) {
3282
                        adapter = g_new0( AdapterInterface, 1 );
3283
                        adapter->interfaceType = interface->type;
3284
                        adapter->atci = atci;
3285
                        adapter->interface = interface;
3286
                        adapter->treeNode = NULL;
3287
                        adapter->enabled = TRUE;
3288
                        adapter->haveLibrary = interface->haveLibrary;
3289
                        ADDRESS_OBJECT(adapter)->type = ADDR_INTERFACE;
3290
                        ADDRESS_OBJECT_NAME(adapter) = g_strdup( atci->displayName );
3291
                        _addressInterfaceList_ = g_list_append( _addressInterfaceList_, adapter );
3292
                }
3293
                list = g_list_next( list );
3294
        }
3295
}
3296

    
3297
void addrbookctl_free_selection( GList *list ) {
3298
        GList *node = list;
3299
        while( node ) {
3300
                AdapterInterface *adapter = node->data;
3301
                adapter = NULL;
3302
                node = g_list_next( node );
3303
        }
3304
        g_list_free( list );
3305
}
3306

    
3307
/*
3308
* Find GUI interface type specified interface type.
3309
* Return: Interface item, or NULL if not found.
3310
*/
3311
AdapterInterface *addrbookctl_find_interface( AddressIfType ifType ) {
3312
        GList *node = _addressInterfaceList_;
3313
        while( node ) {
3314
                AdapterInterface *adapter = node->data;
3315
                if( adapter->interfaceType == ifType ) return adapter;
3316
                node = g_list_next( node );
3317
        }
3318
        return NULL;
3319
}
3320

    
3321
/*
3322
* Build interface list selection.
3323
*/
3324
void addrbookctl_build_ifselect() {
3325
        GList *newList = NULL;
3326
        gchar *selectStr;
3327
        gchar **splitStr;
3328
        gint ifType;
3329
        gint i;
3330
        gchar *endptr = NULL;
3331
        gboolean enabled;
3332
        AdapterInterface *adapter;
3333
        /* GList *node; */
3334

    
3335
        selectStr = g_strdup( ADDRESSBOOK_IFACE_SELECTION );
3336

    
3337
        /* Parse string */
3338
        splitStr = g_strsplit( selectStr, ",", -1 );
3339
        for( i = 0; i < ADDRESSBOOK_MAX_IFACE; i++ ) {
3340
                if( splitStr[i] ) {
3341
                        /* printf( "%d : %s\n", i, splitStr[i] ); */
3342
                        ifType = strtol( splitStr[i], &endptr, 10 );
3343
                        enabled = TRUE;
3344
                        if( *endptr ) {
3345
                                if( strcmp( endptr, "/n" ) == 0 ) {
3346
                                        enabled = FALSE;
3347
                                }
3348
                        }
3349
                        /* printf( "\t%d : %s\n", ifType, enabled ? "yes" : "no" ); */
3350
                        adapter = addrbookctl_find_interface( ifType );
3351
                        if( adapter ) {
3352
                                newList = g_list_append( newList, adapter );
3353
                        }
3354
                }
3355
                else {
3356
                        break;
3357
                }
3358
        }
3359
        /* printf( "i=%d\n", i ); */
3360
        g_strfreev( splitStr );
3361
        g_free( selectStr );
3362

    
3363
        /* Replace existing list */
3364
        mgu_clear_list( _addressIFaceSelection_ );
3365
        g_list_free( _addressIFaceSelection_ );
3366
        _addressIFaceSelection_ = newList;
3367
        newList = NULL;
3368

    
3369
}
3370

    
3371
/* **********************************************************************
3372
* Add sender to address book.
3373
* ***********************************************************************
3374
*/
3375

    
3376
/*
3377
 * This function is used by the Add sender to address book function.
3378
 */
3379
gboolean addressbook_add_contact( const gchar *name, const gchar *address, const gchar *remarks ) {
3380
        debug_print( "addressbook_add_contact: name/address: %s - %s\n", name, address );
3381
        if( addressadd_selection( _addressIndex_, name, address, remarks ) ) {
3382
                debug_print( "addressbook_add_contact - added\n" );
3383
                addressbook_refresh();
3384
        }
3385
        return TRUE;
3386
}
3387

    
3388
/* **********************************************************************
3389
* Address completion support.
3390
* ***********************************************************************
3391
*/
3392

    
3393
/*
3394
* This function is used by the address completion function to load
3395
* addresses.
3396
* Enter: callBackFunc Function to be called when an address is
3397
*                     to be loaded.
3398
* Return: TRUE if data loaded, FALSE if address index not loaded.
3399
*/
3400
gboolean addressbook_load_completion( gint (*callBackFunc) ( const gchar *, const gchar * ) ) {
3401
        /* AddressInterface *interface; */
3402
        AddressDataSource *ds;
3403
        GList *nodeIf, *nodeDS;
3404
        GList *listP, *nodeP;
3405
        GList *nodeM;
3406
        gchar *sName, *sAddress, *sAlias, *sFriendly;
3407

    
3408
        debug_print( "addressbook_load_completion\n" );
3409

    
3410
        if( _addressIndex_ == NULL ) return FALSE;
3411

    
3412
        nodeIf = addrindex_get_interface_list( _addressIndex_ );
3413
        while( nodeIf ) {
3414
                AddressInterface *interface = nodeIf->data;
3415
                nodeDS = interface->listSource;
3416
                while( nodeDS ) {
3417
                        ds = nodeDS->data;
3418

    
3419
                        /* Read address book */
3420
                        if( ! addrindex_ds_get_read_flag( ds ) ) {
3421
                                addrindex_ds_read_data( ds );
3422
                        }
3423

    
3424
                        /* Get all persons */
3425
                        listP = addrindex_ds_get_all_persons( ds );
3426
                        nodeP = listP;
3427
                        while( nodeP ) {
3428
                                ItemPerson *person = nodeP->data;
3429
                                nodeM = person->listEMail;
3430

    
3431
                                /* Figure out name to use */
3432
                                sName = person->nickName;
3433
                                if( sName == NULL || *sName == '\0' ) {
3434
                                        sName = ADDRITEM_NAME(person);
3435
                                }
3436

    
3437
                                /* Process each E-Mail address */
3438
                                while( nodeM ) {
3439
                                        ItemEMail *email = nodeM->data;
3440
                                        /* Have mail */
3441
                                        sFriendly = sName;
3442
                                        sAddress = email->address;
3443
                                        if( sAddress || *sAddress != '\0' ) {
3444
                                                sAlias = ADDRITEM_NAME(email);
3445
                                                if( sAlias && *sAlias != '\0' ) {
3446
                                                        sFriendly = sAlias;
3447
                                                }
3448
                                                ( callBackFunc ) ( sFriendly, sAddress );
3449
                                        }
3450

    
3451
                                        nodeM = g_list_next( nodeM );
3452
                                }
3453
                                nodeP = g_list_next( nodeP );
3454
                        }
3455
                        /* Free up the list */
3456
                        g_list_free( listP );
3457

    
3458
                        nodeDS = g_list_next( nodeDS );
3459
                }
3460
                nodeIf = g_list_next( nodeIf );
3461
        }
3462
        debug_print( "addressbook_load_completion... done\n" );
3463

    
3464
        return TRUE;
3465
}
3466

    
3467
/* **********************************************************************
3468
* Address Import.
3469
* ***********************************************************************
3470
*/
3471

    
3472
/*
3473
* Import LDIF file.
3474
*/
3475
static void addressbook_import_ldif_cb() {
3476
        AddressDataSource *ds = NULL;
3477
        AdapterDSource *ads = NULL;
3478
        AddressBookFile *abf = NULL;
3479
        AdapterInterface *adapter;
3480
        GtkCTreeNode *newNode;
3481

    
3482
        adapter = addrbookctl_find_interface( ADDR_IF_BOOK );
3483
        if ( !adapter || !adapter->treeNode ) return;
3484

    
3485
        abf = addressbook_imp_ldif( _addressIndex_ );
3486
        if ( !abf ) return;
3487

    
3488
        ds = addrindex_index_add_datasource( _addressIndex_, ADDR_IF_BOOK, abf );
3489
        ads = addressbook_create_ds_adapter( ds, ADDR_BOOK, NULL );
3490
        addressbook_ads_set_name( ads, abf->name );
3491
        newNode = addressbook_add_object( adapter->treeNode, ADDRESS_OBJECT(ads) );
3492
        if ( newNode ) {
3493
                gtk_ctree_select( GTK_CTREE(addrbook.ctree), newNode );
3494
                addrbook.treeSelected = newNode;
3495
        }
3496

    
3497
        /* Notify address completion */
3498
        invalidate_address_completion();
3499
}
3500

    
3501
/*
3502
* End of Source.
3503
*/