2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 1999,2000 Hiroyuki Yamamoto
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.
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.
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.
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>
49 #include "addressbook.h"
50 #include "manage_window.h"
51 #include "prefs_common.h"
52 #include "alertpanel.h"
53 #include "inputdialog.h"
62 #include "addr_compl.h"
64 #include "addressitem.h"
66 #include "editvcard.h"
70 #include "editjpilot.h"
78 // Interval to check for LDAP search results
79 // #define ADDRESSBOOK_LDAP_TIMER_INTERVAL 100
80 #define ADDRESSBOOK_LDAP_BUSYMSG "Busy"
84 #include "pixmaps/dir-close.xpm"
85 #include "pixmaps/dir-open.xpm"
86 #include "pixmaps/group.xpm"
87 #include "pixmaps/vcard.xpm"
89 #include "pixmaps/jpilot.xpm"
90 #include "pixmaps/category.xpm"
93 #include "pixmaps/ldap.xpm"
96 // XML tag names for top level folders
97 #define ADDRESS_TAG_COMMON "common_address"
98 #define ADDRESS_TAG_PERSONAL "personal_address"
99 #define ADDRESS_TAG_VCARD "vcard_list"
101 #define ADDRESS_TAG_JPILOT "jpilot_list"
104 #define ADDRESS_TAG_LDAP "ldap_list"
112 } AddressBookColumnPos
;
115 #define COL_NAME_WIDTH 144
116 #define COL_ADDRESS_WIDTH 156
118 #define COL_FOLDER_WIDTH 170
119 #define ADDRESSBOOK_WIDTH 640
120 #define ADDRESSBOOK_HEIGHT 360
122 #define ADDRESSBOOK_MSGBUF_SIZE 2048
124 static GdkPixmap
*folderxpm
;
125 static GdkBitmap
*folderxpmmask
;
126 static GdkPixmap
*folderopenxpm
;
127 static GdkBitmap
*folderopenxpmmask
;
128 static GdkPixmap
*groupxpm
;
129 static GdkBitmap
*groupxpmmask
;
130 static GdkPixmap
*vcardxpm
;
131 static GdkBitmap
*vcardxpmmask
;
133 static GdkPixmap
*jpilotxpm
;
134 static GdkBitmap
*jpilotxpmmask
;
135 static GdkPixmap
*categoryxpm
;
136 static GdkBitmap
*categoryxpmmask
;
139 static GdkPixmap
*ldapxpm
;
140 static GdkBitmap
*ldapxpmmask
;
143 // Pilot library indicator (set at run-time)
144 static _have_pilot_library_
;
146 // LDAP library indicator (set at run-time)
147 static _have_ldap_library_
;
150 static gchar addressbook_msgbuf
[ ADDRESSBOOK_MSGBUF_SIZE
];
152 static AddressBook addrbook
;
154 static struct _AddressEdit
157 GtkWidget
*name_entry
;
158 GtkWidget
*addr_entry
;
159 GtkWidget
*rem_entry
;
161 GtkWidget
*cancel_btn
;
164 static void addressbook_create (gboolean show
);
165 static gint
addressbook_close (void);
166 static void addressbook_button_set_sensitive (void);
168 /* callback functions */
169 static void addressbook_del_clicked (GtkButton
*button
,
171 static void addressbook_reg_clicked (GtkButton
*button
,
173 static void addressbook_to_clicked (GtkButton
*button
,
175 static void addressbook_lup_clicked (GtkButton
*button
,
178 static void addressbook_tree_selected (GtkCTree
*ctree
,
182 static void addressbook_list_selected (GtkCList
*clist
,
187 static void addressbook_entry_gotfocus (GtkWidget
*widget
);
190 static void addressbook_entry_changed (GtkWidget
*widget
);
193 static void addressbook_list_button_pressed (GtkWidget
*widget
,
194 GdkEventButton
*event
,
196 static void addressbook_list_button_released (GtkWidget
*widget
,
197 GdkEventButton
*event
,
199 static void addressbook_tree_button_pressed (GtkWidget
*ctree
,
200 GdkEventButton
*event
,
202 static void addressbook_tree_button_released (GtkWidget
*ctree
,
203 GdkEventButton
*event
,
205 static void addressbook_popup_close (GtkMenuShell
*menu_shell
,
208 static void addressbook_new_folder_cb (gpointer data
,
211 static void addressbook_new_group_cb (gpointer data
,
214 static void addressbook_edit_folder_cb (gpointer data
,
217 static void addressbook_delete_folder_cb (gpointer data
,
221 static void addressbook_change_node_name (GtkCTreeNode
*node
,
223 static void addressbook_edit_group (GtkCTreeNode
*group_node
);
225 static void addressbook_edit_address_create (gboolean
*cancelled
);
226 static void edit_address_ok (GtkWidget
*widget
,
227 gboolean
*cancelled
);
228 static void edit_address_cancel (GtkWidget
*widget
,
229 gboolean
*cancelled
);
230 static gint
edit_address_delete_event (GtkWidget
*widget
,
232 gboolean
*cancelled
);
233 static void edit_address_key_pressed (GtkWidget
*widget
,
235 gboolean
*cancelled
);
236 static AddressItem
*addressbook_edit_address (AddressItem
*item
);
238 static void addressbook_new_address_cb (gpointer data
,
241 static void addressbook_edit_address_cb (gpointer data
,
244 static void addressbook_delete_address_cb (gpointer data
,
248 static void close_cb (gpointer data
,
253 static void addressbook_new_vcard_cb ( gpointer data
,
259 static void addressbook_new_jpilot_cb ( gpointer data
,
266 static void addressbook_new_ldap_cb ( gpointer data
,
271 static AddressItem
*addressbook_parse_address (const gchar
*str
);
272 static void addressbook_append_to_compose_entry (AddressItem
*item
,
273 ComposeEntryType type
);
275 static void addressbook_set_clist (AddressObject
*obj
);
277 static void addressbook_read_file (void);
278 static void addressbook_get_tree (XMLFile
*file
,
280 const gchar
*folder_tag
);
281 static void addressbook_add_objs (XMLFile
*file
,
284 static GtkCTreeNode
*addressbook_add_object (GtkCTreeNode
*node
,
286 static void addressbook_delete_object (AddressObject
*obj
);
287 static AddressObject
*addressbook_find_object_by_name
291 static AddressItem
*addressbook_parse_item (XMLFile
*file
);
292 static void addressbook_xml_recursive_write (GtkCTreeNode
*node
,
294 static void addressbook_node_write_begin (GtkCTreeNode
*node
,
296 static void addressbook_node_write_end (GtkCTreeNode
*node
,
298 static void addressbook_write_items (FILE *fp
,
301 static void tab_indent_out (FILE *fp
,
304 static void key_pressed (GtkWidget
*widget
,
307 static gint
addressbook_list_compare_func (GtkCList
*clist
,
310 static gint
addressbook_obj_name_compare (gconstpointer a
,
313 static AddressVCard
*addressbook_parse_vcard ( XMLFile
*file
);
314 static void addressbook_write_vcard ( FILE *fp
,
317 static void addressbook_vcard_show_message ( VCardFile
*vcf
);
320 static AddressJPilot
*addressbook_parse_jpilot ( XMLFile
*file
);
321 static void addressbook_write_jpilot ( FILE *fp
,
322 AddressJPilot
*jpilot
,
324 static void addressbook_jpilot_show_message ( JPilotFile
*jpf
);
327 static AddressLDAP
*addressbook_parse_ldap ( XMLFile
*file
);
328 static void addressbook_write_ldap ( FILE *fp
,
331 static void addressbook_ldap_show_message ( SyldapServer
*server
);
334 static GtkItemFactoryEntry addressbook_entries
[] =
336 {N_("/_File"), NULL
, NULL
, 0, "<Branch>"},
337 {N_("/_File/New _Address"), "<alt>N", addressbook_new_address_cb
, 0, NULL
},
338 {N_("/_File/New _Group"), "<alt>G", addressbook_new_group_cb
, 0, NULL
},
339 {N_("/_File/New _Folder"), "<alt>R", addressbook_new_folder_cb
, 0, NULL
},
340 {N_("/_File/New _V-Card"), "<alt>D", addressbook_new_vcard_cb
, 0, NULL
},
342 {N_("/_File/New _J-Pilot"), "<alt>J", addressbook_new_jpilot_cb
, 0, NULL
},
345 {N_("/_File/New _Server"), "<alt>S", addressbook_new_ldap_cb
, 0, NULL
},
347 {N_("/_File/---"), NULL
, NULL
, 0, "<Separator>"},
348 {N_("/_File/_Edit"), "<alt>Return", addressbook_edit_address_cb
, 0, NULL
},
349 {N_("/_File/_Delete"), NULL
, addressbook_delete_address_cb
, 0, NULL
},
350 {N_("/_File/---"), NULL
, NULL
, 0, "<Separator>"},
351 {N_("/_File/_Close"), "<alt>W", close_cb
, 0, NULL
},
352 {N_("/_Help"), NULL
, NULL
, 0, "<LastBranch>"},
353 {N_("/_Help/_About"), NULL
, about_show
, 0, NULL
}
356 static GtkItemFactoryEntry addressbook_tree_popup_entries
[] =
358 {N_("/New _Address"), NULL
, addressbook_new_address_cb
, 0, NULL
},
359 {N_("/New _Group"), NULL
, addressbook_new_group_cb
, 0, NULL
},
360 {N_("/New _Folder"), NULL
, addressbook_new_folder_cb
, 0, NULL
},
361 {N_("/New _V-Card"), NULL
, addressbook_new_vcard_cb
, 0, NULL
},
363 {N_("/New _J-Pilot"), NULL
, addressbook_new_jpilot_cb
, 0, NULL
},
366 {N_("/New _Server"), NULL
, addressbook_new_ldap_cb
, 0, NULL
},
368 {N_("/---"), NULL
, NULL
, 0, "<Separator>"},
369 {N_("/_Edit"), NULL
, addressbook_edit_folder_cb
, 0, NULL
},
370 {N_("/_Delete"), NULL
, addressbook_delete_folder_cb
, 0, NULL
}
373 static GtkItemFactoryEntry addressbook_list_popup_entries
[] =
375 {N_("/New _Address"), NULL
, addressbook_new_address_cb
, 0, NULL
},
376 {N_("/New _Group"), NULL
, addressbook_new_group_cb
, 0, NULL
},
377 {N_("/New _Folder"), NULL
, addressbook_new_folder_cb
, 0, NULL
},
378 {N_("/---"), NULL
, NULL
, 0, "<Separator>"},
379 {N_("/_Edit"), NULL
, addressbook_edit_address_cb
, 0, NULL
},
380 {N_("/_Delete"), NULL
, addressbook_delete_address_cb
, 0, NULL
}
383 void addressbook_open(Compose
*target
)
385 if (!addrbook
.window
) {
386 addressbook_create(TRUE
);
387 addressbook_read_file();
388 addrbook
.open_folder
= TRUE
;
389 gtk_ctree_select(GTK_CTREE(addrbook
.ctree
),
390 GTK_CTREE_NODE(GTK_CLIST(addrbook
.ctree
)->row_list
));
392 gtk_widget_hide(addrbook
.window
);
394 gtk_widget_show_all(addrbook
.window
);
396 addressbook_set_target_compose(target
);
399 void addressbook_set_target_compose(Compose
*target
)
401 addrbook
.target_compose
= target
;
403 addressbook_button_set_sensitive();
406 Compose
*addressbook_get_target_compose(void)
408 return addrbook
.target_compose
;
411 static void addressbook_create(gboolean show
)
417 GtkWidget
*ctree_swin
;
419 GtkWidget
*clist_vbox
;
420 GtkWidget
*clist_swin
;
426 GtkWidget
*statusbar
;
436 GtkWidget
*tree_popup
;
437 GtkWidget
*list_popup
;
438 GtkItemFactory
*tree_factory
;
439 GtkItemFactory
*list_factory
;
440 GtkItemFactory
*menu_factory
;
443 gchar
*titles
[N_COLS
] = {_("Name"), _("E-Mail address"), _("Remarks")};
447 debug_print("Creating addressbook window...\n");
449 // Global flag if we have library installed (at run-time)
450 _have_pilot_library_
= FALSE
;
451 _have_ldap_library_
= FALSE
;
453 window
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
454 gtk_window_set_title(GTK_WINDOW(window
), _("Address book"));
455 gtk_widget_set_usize(window
, ADDRESSBOOK_WIDTH
, ADDRESSBOOK_HEIGHT
);
456 //gtk_container_set_border_width(GTK_CONTAINER(window), BORDER_WIDTH);
457 gtk_window_set_policy(GTK_WINDOW(window
), TRUE
, TRUE
, TRUE
);
458 gtk_widget_realize(window
);
460 gtk_signal_connect(GTK_OBJECT(window
), "delete_event",
461 GTK_SIGNAL_FUNC(addressbook_close
), NULL
);
462 gtk_signal_connect(GTK_OBJECT(window
), "key_press_event",
463 GTK_SIGNAL_FUNC(key_pressed
), NULL
);
464 gtk_signal_connect(GTK_OBJECT(window
), "focus_in_event",
465 GTK_SIGNAL_FUNC(manage_window_focus_in
), NULL
);
466 gtk_signal_connect(GTK_OBJECT(window
), "focus_out_event",
467 GTK_SIGNAL_FUNC(manage_window_focus_out
), NULL
);
469 vbox
= gtk_vbox_new(FALSE
, 0);
470 gtk_container_add(GTK_CONTAINER(window
), vbox
);
472 n_entries
= sizeof(addressbook_entries
) /
473 sizeof(addressbook_entries
[0]);
474 menubar
= menubar_create(window
, addressbook_entries
, n_entries
,
475 "<AddressBook>", NULL
);
476 gtk_box_pack_start(GTK_BOX(vbox
), menubar
, FALSE
, TRUE
, 0);
477 menu_factory
= gtk_item_factory_from_widget(menubar
);
479 vbox2
= gtk_vbox_new(FALSE
, 4);
480 gtk_container_set_border_width(GTK_CONTAINER(vbox2
), BORDER_WIDTH
);
481 gtk_box_pack_start(GTK_BOX(vbox
), vbox2
, TRUE
, TRUE
, 0);
483 ctree_swin
= gtk_scrolled_window_new(NULL
, NULL
);
484 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(ctree_swin
),
485 GTK_POLICY_AUTOMATIC
,
487 gtk_widget_set_usize(ctree_swin
, COL_FOLDER_WIDTH
+ 40, -1);
489 ctree
= gtk_ctree_new(1, 0);
490 gtk_container_add(GTK_CONTAINER(ctree_swin
), ctree
);
491 gtk_clist_set_selection_mode(GTK_CLIST(ctree
), GTK_SELECTION_BROWSE
);
492 gtk_clist_set_column_width(GTK_CLIST(ctree
), 0, COL_FOLDER_WIDTH
);
493 gtk_ctree_set_line_style(GTK_CTREE(ctree
), GTK_CTREE_LINES_DOTTED
);
494 gtk_ctree_set_expander_style(GTK_CTREE(ctree
),
495 GTK_CTREE_EXPANDER_SQUARE
);
496 gtk_ctree_set_indent(GTK_CTREE(ctree
), CTREE_INDENT
);
497 gtk_clist_set_compare_func(GTK_CLIST(ctree
),
498 addressbook_list_compare_func
);
500 gtk_signal_connect(GTK_OBJECT(ctree
), "tree_select_row",
501 GTK_SIGNAL_FUNC(addressbook_tree_selected
), NULL
);
502 gtk_signal_connect(GTK_OBJECT(ctree
), "button_press_event",
503 GTK_SIGNAL_FUNC(addressbook_tree_button_pressed
),
505 gtk_signal_connect(GTK_OBJECT(ctree
), "button_release_event",
506 GTK_SIGNAL_FUNC(addressbook_tree_button_released
),
509 clist_vbox
= gtk_vbox_new(FALSE
, 4);
511 clist_swin
= gtk_scrolled_window_new(NULL
, NULL
);
512 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(clist_swin
),
513 GTK_POLICY_AUTOMATIC
,
515 gtk_box_pack_start(GTK_BOX(clist_vbox
), clist_swin
, TRUE
, TRUE
, 0);
517 clist
= gtk_clist_new_with_titles(N_COLS
, titles
);
518 gtk_container_add(GTK_CONTAINER(clist_swin
), clist
);
519 gtk_clist_set_selection_mode(GTK_CLIST(clist
), GTK_SELECTION_EXTENDED
);
520 gtk_clist_set_column_width(GTK_CLIST(clist
), COL_NAME
,
522 gtk_clist_set_column_width(GTK_CLIST(clist
), COL_ADDRESS
,
524 gtk_clist_set_compare_func(GTK_CLIST(clist
),
525 addressbook_list_compare_func
);
527 for (i
= 0; i
< N_COLS
; i
++)
528 GTK_WIDGET_UNSET_FLAGS(GTK_CLIST(clist
)->column
[i
].button
,
531 gtk_signal_connect(GTK_OBJECT(clist
), "select_row",
532 GTK_SIGNAL_FUNC(addressbook_list_selected
), NULL
);
533 gtk_signal_connect(GTK_OBJECT(clist
), "button_press_event",
534 GTK_SIGNAL_FUNC(addressbook_list_button_pressed
),
536 gtk_signal_connect(GTK_OBJECT(clist
), "button_release_event",
537 GTK_SIGNAL_FUNC(addressbook_list_button_released
),
540 hbox
= gtk_hbox_new(FALSE
, 4);
541 gtk_box_pack_start(GTK_BOX(clist_vbox
), hbox
, FALSE
, FALSE
, 0);
543 label
= gtk_label_new(_("Name:"));
544 gtk_box_pack_start(GTK_BOX(hbox
), label
, FALSE
, FALSE
, 0);
546 entry
= gtk_entry_new();
547 gtk_box_pack_start(GTK_BOX(hbox
), entry
, TRUE
, TRUE
, 0);
549 address_completion_register_entry(GTK_ENTRY(entry
));
550 gtk_signal_connect(GTK_OBJECT(entry
), "focus_in_event",
551 GTK_SIGNAL_FUNC(addressbook_entry_gotfocus
), NULL
);
554 gtk_signal_connect(GTK_OBJECT(entry
), "changed",
555 GTK_SIGNAL_FUNC(addressbook_entry_changed
), NULL
);
558 paned
= gtk_hpaned_new();
559 gtk_box_pack_start(GTK_BOX(vbox2
), paned
, TRUE
, TRUE
, 0);
560 gtk_paned_add1(GTK_PANED(paned
), ctree_swin
);
561 gtk_paned_add2(GTK_PANED(paned
), clist_vbox
);
564 hsbox
= gtk_hbox_new(FALSE
, 0);
565 gtk_box_pack_end(GTK_BOX(vbox
), hsbox
, FALSE
, FALSE
, BORDER_WIDTH
);
566 statusbar
= gtk_statusbar_new();
567 gtk_box_pack_start(GTK_BOX(hsbox
), statusbar
, TRUE
, TRUE
, BORDER_WIDTH
);
570 hbbox
= gtk_hbutton_box_new();
571 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbbox
), GTK_BUTTONBOX_END
);
572 gtk_button_box_set_spacing(GTK_BUTTON_BOX(hbbox
), 2);
573 gtk_box_pack_end(GTK_BOX(vbox
), hbbox
, FALSE
, FALSE
, 0);
575 del_btn
= gtk_button_new_with_label(_("Delete"));
576 GTK_WIDGET_SET_FLAGS(del_btn
, GTK_CAN_DEFAULT
);
577 gtk_box_pack_start(GTK_BOX(hbbox
), del_btn
, TRUE
, TRUE
, 0);
578 reg_btn
= gtk_button_new_with_label(_("Add"));
579 GTK_WIDGET_SET_FLAGS(reg_btn
, GTK_CAN_DEFAULT
);
580 gtk_box_pack_start(GTK_BOX(hbbox
), reg_btn
, TRUE
, TRUE
, 0);
581 lup_btn
= gtk_button_new_with_label(_("Lookup"));
582 GTK_WIDGET_SET_FLAGS(lup_btn
, GTK_CAN_DEFAULT
);
583 gtk_box_pack_start(GTK_BOX(hbbox
), lup_btn
, TRUE
, TRUE
, 0);
585 gtk_signal_connect(GTK_OBJECT(del_btn
), "clicked",
586 GTK_SIGNAL_FUNC(addressbook_del_clicked
), NULL
);
587 gtk_signal_connect(GTK_OBJECT(reg_btn
), "clicked",
588 GTK_SIGNAL_FUNC(addressbook_reg_clicked
), NULL
);
589 gtk_signal_connect(GTK_OBJECT(lup_btn
), "clicked",
590 GTK_SIGNAL_FUNC(addressbook_lup_clicked
), NULL
);
592 to_btn
= gtk_button_new_with_label
593 (prefs_common
.trans_hdr
? _("To:") : "To:");
594 GTK_WIDGET_SET_FLAGS(to_btn
, GTK_CAN_DEFAULT
);
595 gtk_box_pack_start(GTK_BOX(hbbox
), to_btn
, TRUE
, TRUE
, 0);
596 cc_btn
= gtk_button_new_with_label
597 (prefs_common
.trans_hdr
? _("Cc:") : "Cc:");
598 GTK_WIDGET_SET_FLAGS(cc_btn
, GTK_CAN_DEFAULT
);
599 gtk_box_pack_start(GTK_BOX(hbbox
), cc_btn
, TRUE
, TRUE
, 0);
600 bcc_btn
= gtk_button_new_with_label
601 (prefs_common
.trans_hdr
? _("Bcc:") : "Bcc:");
602 GTK_WIDGET_SET_FLAGS(bcc_btn
, GTK_CAN_DEFAULT
);
603 gtk_box_pack_start(GTK_BOX(hbbox
), bcc_btn
, TRUE
, TRUE
, 0);
605 gtk_signal_connect(GTK_OBJECT(to_btn
), "clicked",
606 GTK_SIGNAL_FUNC(addressbook_to_clicked
),
607 GINT_TO_POINTER(COMPOSE_TO
));
608 gtk_signal_connect(GTK_OBJECT(cc_btn
), "clicked",
609 GTK_SIGNAL_FUNC(addressbook_to_clicked
),
610 GINT_TO_POINTER(COMPOSE_CC
));
611 gtk_signal_connect(GTK_OBJECT(bcc_btn
), "clicked",
612 GTK_SIGNAL_FUNC(addressbook_to_clicked
),
613 GINT_TO_POINTER(COMPOSE_BCC
));
615 PIXMAP_CREATE(window
, folderxpm
, folderxpmmask
, DIRECTORY_CLOSE_XPM
);
616 PIXMAP_CREATE(window
, folderopenxpm
, folderopenxpmmask
,
618 PIXMAP_CREATE(window
, groupxpm
, groupxpmmask
, group_xpm
);
619 PIXMAP_CREATE(window
, vcardxpm
, vcardxpmmask
, vcard_xpm
);
621 PIXMAP_CREATE(window
, jpilotxpm
, jpilotxpmmask
, jpilot_xpm
);
622 PIXMAP_CREATE(window
, categoryxpm
, categoryxpmmask
, category_xpm
);
625 PIXMAP_CREATE(window
, ldapxpm
, ldapxpmmask
, ldap_xpm
);
628 text
= _("Common address");
630 gtk_ctree_insert_node(GTK_CTREE(ctree
),
631 NULL
, NULL
, &text
, FOLDER_SPACING
,
632 folderxpm
, folderxpmmask
,
633 folderopenxpm
, folderopenxpmmask
,
635 text
= _("Personal address");
637 gtk_ctree_insert_node(GTK_CTREE(ctree
),
638 NULL
, NULL
, &text
, FOLDER_SPACING
,
639 folderxpm
, folderxpmmask
,
640 folderopenxpm
, folderopenxpmmask
,
645 gtk_ctree_insert_node(GTK_CTREE(ctree
),
646 NULL
, NULL
, &text
, FOLDER_SPACING
,
647 folderxpm
, folderxpmmask
,
648 folderopenxpm
, folderopenxpmmask
,
654 gtk_ctree_insert_node(GTK_CTREE(ctree
),
655 NULL
, NULL
, &text
, FOLDER_SPACING
,
656 folderxpm
, folderxpmmask
,
657 folderopenxpm
, folderopenxpmmask
,
659 if( jpilot_test_pilot_lib() ) {
660 _have_pilot_library_
= TRUE
;
661 menu_set_sensitive( menu_factory
, "/File/New J-Pilot", TRUE
);
664 menu_set_sensitive( menu_factory
, "/File/New J-Pilot", FALSE
);
669 text
= _("Directory");
671 gtk_ctree_insert_node(GTK_CTREE(ctree
),
672 NULL
, NULL
, &text
, FOLDER_SPACING
,
673 folderxpm
, folderxpmmask
,
674 folderopenxpm
, folderopenxpmmask
,
676 if( syldap_test_ldap_lib() ) {
677 _have_ldap_library_
= TRUE
;
678 menu_set_sensitive( menu_factory
, "/File/New Server", TRUE
);
681 menu_set_sensitive( menu_factory
, "/File/New Server", FALSE
);
686 n_entries
= sizeof(addressbook_tree_popup_entries
) /
687 sizeof(addressbook_tree_popup_entries
[0]);
688 tree_popup
= menu_create_items(addressbook_tree_popup_entries
,
690 "<AddressBookTree>", &tree_factory
,
692 gtk_signal_connect(GTK_OBJECT(tree_popup
), "selection_done",
693 GTK_SIGNAL_FUNC(addressbook_popup_close
), NULL
);
694 n_entries
= sizeof(addressbook_list_popup_entries
) /
695 sizeof(addressbook_list_popup_entries
[0]);
696 list_popup
= menu_create_items(addressbook_list_popup_entries
,
698 "<AddressBookList>", &list_factory
,
701 addrbook
.window
= window
;
702 addrbook
.menubar
= menubar
;
703 addrbook
.ctree
= ctree
;
704 addrbook
.clist
= clist
;
705 addrbook
.entry
= entry
;
706 addrbook
.statusbar
= statusbar
;
707 addrbook
.status_cid
= gtk_statusbar_get_context_id( GTK_STATUSBAR(statusbar
), "Addressbook Window" );
709 addrbook
.del_btn
= del_btn
;
710 addrbook
.reg_btn
= reg_btn
;
711 addrbook
.lup_btn
= lup_btn
;
712 addrbook
.to_btn
= to_btn
;
713 addrbook
.cc_btn
= cc_btn
;
714 addrbook
.bcc_btn
= bcc_btn
;
716 addrbook
.tree_popup
= tree_popup
;
717 addrbook
.list_popup
= list_popup
;
718 addrbook
.tree_factory
= tree_factory
;
719 addrbook
.list_factory
= list_factory
;
720 addrbook
.menu_factory
= menu_factory
;
722 address_completion_start(window
);
725 gtk_widget_show_all(window
);
728 static gint
addressbook_close(void)
730 gtk_widget_hide(addrbook
.window
);
731 addressbook_export_to_file();
732 /* tell addr_compl that there's a new addressbook file */
733 invalidate_address_completion();
737 static void addressbook_status_show( gchar
*msg
) {
738 if( addrbook
.statusbar
!= NULL
) {
739 gtk_statusbar_pop( GTK_STATUSBAR(addrbook
.statusbar
), addrbook
.status_cid
);
741 gtk_statusbar_push( GTK_STATUSBAR(addrbook
.statusbar
), addrbook
.status_cid
, msg
);
746 static void addressbook_button_set_sensitive(void)
748 gboolean to_sens
= FALSE
;
749 gboolean cc_sens
= FALSE
;
750 gboolean bcc_sens
= FALSE
;
752 if (!addrbook
.window
) return;
754 if (addrbook
.target_compose
) {
757 if (addrbook
.target_compose
->use_bcc
)
761 gtk_widget_set_sensitive(addrbook
.to_btn
, to_sens
);
762 gtk_widget_set_sensitive(addrbook
.cc_btn
, cc_sens
);
763 gtk_widget_set_sensitive(addrbook
.bcc_btn
, bcc_sens
);
766 static void addressbook_del_clicked(GtkButton
*button
, gpointer data
)
768 GtkCList
*clist
= GTK_CLIST(addrbook
.clist
);
769 GtkCTree
*ctree
= GTK_CTREE(addrbook
.ctree
);
770 AddressObject
*pobj
, *obj
;
775 if (!clist
->selection
) {
776 addressbook_delete_folder_cb(NULL
, 0, NULL
);
780 pobj
= gtk_ctree_node_get_row_data(ctree
, addrbook
.opened
);
781 g_return_if_fail(pobj
!= NULL
);
783 if (alertpanel(_("Delete address(es)"),
784 _("Really delete the address(es)?"),
785 _("Yes"), _("No"), NULL
) != G_ALERTDEFAULT
)
788 for (cur
= clist
->selection
; cur
!= NULL
; cur
= next
) {
790 row
= GPOINTER_TO_INT(cur
->data
);
793 obj
= gtk_clist_get_row_data(clist
, row
);
796 if (pobj
->type
== ADDR_GROUP
) {
797 AddressGroup
*group
= ADDRESS_GROUP(pobj
);
798 group
->items
= g_list_remove(group
->items
, obj
);
799 } else if (pobj
->type
== ADDR_FOLDER
) {
800 AddressFolder
*folder
= ADDRESS_FOLDER(pobj
);
802 folder
->items
= g_list_remove(folder
->items
, obj
);
803 if (obj
->type
== ADDR_GROUP
) {
806 else if (obj
->type
== ADDR_VCARD
) {
809 else if (obj
->type
== ADDR_JPILOT
) {
812 else if (obj
->type
== ADDR_LDAP
) {
818 node
= gtk_ctree_find_by_row_data
819 (ctree
, addrbook
.opened
, obj
);
820 if (node
) gtk_ctree_remove_node(ctree
, node
);
825 addressbook_delete_object(obj
);
827 gtk_clist_remove(clist
, row
);
831 static void addressbook_reg_clicked(GtkButton
*button
, gpointer data
)
833 GtkCTree
*ctree
= GTK_CTREE(addrbook
.ctree
);
834 GtkEntry
*entry
= GTK_ENTRY(addrbook
.entry
);
839 if (*gtk_entry_get_text(entry
) == '\0') {
840 addressbook_new_address_cb(NULL
, 0, NULL
);
843 if (!addrbook
.opened
) return;
845 obj
= gtk_ctree_node_get_row_data(ctree
, addrbook
.opened
);
848 g_return_if_fail(obj
->type
== ADDR_GROUP
|| obj
->type
== ADDR_FOLDER
);
850 str
= gtk_editable_get_chars(GTK_EDITABLE(entry
), 0, -1);
852 item
= addressbook_parse_address(str
);
855 if (addressbook_find_object_by_name
856 (addrbook
.opened
, item
->name
) != NULL
) {
857 addressbook_delete_object(ADDRESS_OBJECT(item
));
859 } else if (addressbook_edit_address(item
) == NULL
) {
860 addressbook_delete_object(ADDRESS_OBJECT(item
));
866 item
= addressbook_edit_address(NULL
);
870 if (addressbook_find_object_by_name(addrbook
.opened
, item
->name
)) {
871 addressbook_delete_object(ADDRESS_OBJECT(item
));
875 addressbook_add_object(addrbook
.opened
, ADDRESS_OBJECT(item
));
876 addrbook
.open_folder
= TRUE
;
877 gtk_ctree_select(GTK_CTREE(addrbook
.ctree
), addrbook
.opened
);
880 static AddressItem
*addressbook_parse_address(const gchar
*str
)
883 gchar
*address
= NULL
;
888 Xalloca(buf
, strlen(str
) + 1, return NULL
);
892 if (*buf
== '\0') return NULL
;
894 if ((start
= strchr(buf
, '<'))) {
899 name
= g_strdup(buf
);
902 if ((end
= strchr(start
, '>'))) {
906 address
= g_strdup(start
);
909 name
= g_strdup(buf
);
911 if (!name
&& !address
) return NULL
;
913 item
= mgu_create_address();
914 ADDRESS_OBJECT_TYPE(item
) = ADDR_ITEM
;
916 item
->address
= address
;
917 item
->remarks
= NULL
;
922 static void addressbook_to_clicked(GtkButton
*button
, gpointer data
)
924 GtkCList
*clist
= GTK_CLIST(addrbook
.clist
);
927 if (!addrbook
.target_compose
) return;
929 for (cur
= clist
->selection
; cur
!= NULL
; cur
= cur
->next
) {
932 obj
= gtk_clist_get_row_data(clist
,
933 GPOINTER_TO_INT(cur
->data
));
936 if (obj
->type
== ADDR_ITEM
) {
937 addressbook_append_to_compose_entry
938 (ADDRESS_ITEM(obj
), (ComposeEntryType
)data
);
939 } else if (obj
->type
== ADDR_GROUP
) {
943 group
= ADDRESS_GROUP(obj
);
944 for (cur_item
= group
->items
; cur_item
!= NULL
;
945 cur_item
= cur_item
->next
) {
946 if (ADDRESS_OBJECT(cur_item
->data
)->type
949 addressbook_append_to_compose_entry
950 (ADDRESS_ITEM(cur_item
->data
),
951 (ComposeEntryType
)data
);
957 static void addressbook_append_to_compose_entry(AddressItem
*item
,
958 ComposeEntryType type
)
960 Compose
*compose
= addrbook
.target_compose
;
962 if (item
->name
&& item
->address
) {
965 buf
= g_strdup_printf
966 ("%s <%s>", item
->name
, item
->address
);
967 compose_entry_append(compose
, buf
, type
);
969 } else if (item
->address
)
970 compose_entry_append(compose
, item
->address
, type
);
973 static void addressbook_menubar_set_sensitive( gboolean sensitive
) {
974 menu_set_sensitive( addrbook
.menu_factory
, "/File/New Address", sensitive
);
975 menu_set_sensitive( addrbook
.menu_factory
, "/File/New Group", sensitive
);
976 menu_set_sensitive( addrbook
.menu_factory
, "/File/New Folder", sensitive
);
977 menu_set_sensitive( addrbook
.menu_factory
, "/File/New V-Card", sensitive
);
979 menu_set_sensitive( addrbook
.menu_factory
, "/File/New J-Pilot", sensitive
);
982 menu_set_sensitive( addrbook
.menu_factory
, "/File/New Server", sensitive
);
984 gtk_widget_set_sensitive( addrbook
.reg_btn
, sensitive
);
985 gtk_widget_set_sensitive( addrbook
.del_btn
, sensitive
);
988 static void addressbook_menuitem_set_sensitive( AddressObject
*obj
, GtkCTreeNode
*node
) {
989 gboolean canEdit
= TRUE
;
990 if( obj
->type
== ADDR_FOLDER
) {
991 if( node
== addrbook
.common
) {
994 if( node
== addrbook
.personal
) {
997 if( node
== addrbook
.vcard
) {
999 menu_set_sensitive( addrbook
.menu_factory
, "/File/New V-Card", TRUE
);
1002 else if( node
== addrbook
.jpilot
) {
1004 if( _have_pilot_library_
) {
1005 menu_set_sensitive( addrbook
.menu_factory
, "/File/New J-Pilot", TRUE
);
1010 else if( node
== addrbook
.ldap
) {
1012 if( _have_ldap_library_
) {
1013 menu_set_sensitive( addrbook
.menu_factory
, "/File/New Server", TRUE
);
1018 menu_set_sensitive( addrbook
.menu_factory
, "/File/New Address", TRUE
);
1019 menu_set_sensitive( addrbook
.menu_factory
, "/File/New Group", TRUE
);
1020 menu_set_sensitive( addrbook
.menu_factory
, "/File/New Folder", TRUE
);
1021 gtk_widget_set_sensitive( addrbook
.reg_btn
, TRUE
);
1022 gtk_widget_set_sensitive( addrbook
.del_btn
, TRUE
);
1025 else if( obj
->type
== ADDR_GROUP
) {
1026 menu_set_sensitive( addrbook
.menu_factory
, "/File/New Address", TRUE
);
1027 gtk_widget_set_sensitive( addrbook
.reg_btn
, TRUE
);
1028 gtk_widget_set_sensitive( addrbook
.del_btn
, TRUE
);
1031 else if( obj
->type
== ADDR_JPILOT
) {
1032 if( ! _have_pilot_library_
) canEdit
= FALSE
;
1034 else if( obj
->type
== ADDR_CATEGORY
) {
1039 else if( obj
->type
== ADDR_LDAP
) {
1040 if( ! _have_ldap_library_
) canEdit
= FALSE
;
1043 menu_set_sensitive( addrbook
.menu_factory
, "/File/Edit", canEdit
);
1044 menu_set_sensitive( addrbook
.menu_factory
, "/File/Delete", canEdit
);
1047 static void addressbook_tree_selected(GtkCTree
*ctree
, GtkCTreeNode
*node
,
1048 gint column
, gpointer data
)
1052 addrbook
.selected
= node
;
1053 addrbook
.open_folder
= FALSE
;
1054 addressbook_status_show( "" );
1055 if( addrbook
.entry
!= NULL
) {
1056 gtk_entry_set_text(GTK_ENTRY(addrbook
.entry
), "");
1059 obj
= gtk_ctree_node_get_row_data(ctree
, node
);
1060 if( obj
== NULL
) return;
1062 addrbook
.opened
= node
;
1064 if( obj
->type
== ADDR_GROUP
|| obj
->type
== ADDR_FOLDER
||
1065 obj
->type
== ADDR_VCARD
|| obj
->type
== ADDR_JPILOT
||
1066 obj
->type
== ADDR_CATEGORY
|| obj
->type
== ADDR_LDAP
) {
1067 addressbook_set_clist(obj
);
1070 if( obj
->type
== ADDR_VCARD
) {
1073 vcf
= ADDRESS_VCARD(obj
)->cardFile
;
1074 vcard_read_data( vcf
);
1075 addressbook_vcard_show_message( vcf
);
1076 ADDRESS_VCARD(obj
)->items
= vcard_get_address_list( vcf
);
1077 addressbook_set_clist( obj
);
1080 else if( obj
->type
== ADDR_JPILOT
) {
1081 if( _have_pilot_library_
) {
1084 GList
*catList
, *catNode
;
1085 AddressCategory
*acat
;
1086 GtkCTreeNode
*childNode
, *nextNode
;
1087 GtkCTreeRow
*currRow
;
1089 jpf
= ADDRESS_JPILOT(obj
)->pilotFile
;
1090 addressbook_jpilot_show_message( jpf
);
1091 if( jpilot_get_modified( jpf
) ) {
1092 jpilot_read_data( jpf
);
1093 catList
= jpilot_get_category_items( jpf
);
1095 // Remove existing categories
1096 currRow
= GTK_CTREE_ROW( node
);
1098 while( nextNode
= currRow
->children
) {
1099 gtk_ctree_remove_node( ctree
, nextNode
);
1103 // Load new categories into the tree.
1106 AddressItem
*item
= catNode
->data
;
1107 acat
= g_new(AddressCategory
, 1);
1108 ADDRESS_OBJECT_TYPE(acat
) = ADDR_CATEGORY
;
1109 acat
->name
= g_strdup( item
->name
);
1111 acat
->pilotFile
= jpf
;
1112 acat
->category
= item
;
1113 catNode
= g_list_next( catNode
);
1114 addressbook_add_object(node
, ADDRESS_OBJECT(acat
));
1117 ADDRESS_JPILOT(obj
)->items
= catList
;
1119 addressbook_set_clist( obj
);
1122 else if( obj
->type
== ADDR_CATEGORY
) {
1123 if( _have_pilot_library_
) {
1127 jpf
= ADDRESS_JPILOT(obj
)->pilotFile
;
1128 if( jpilot_get_modified( jpf
) ) {
1129 // Force parent to be reloaded
1130 gtk_ctree_select( GTK_CTREE(addrbook
.ctree
), GTK_CTREE_ROW(node
)->parent
);
1131 gtk_ctree_expand( GTK_CTREE(addrbook
.ctree
), GTK_CTREE_ROW(node
)->parent
);
1134 AddressItem
*item
= NULL
;
1135 AddressCategory
*acat
= ADDRESS_CATEGORY(obj
);
1136 if( acat
) item
= acat
->category
;
1138 ADDRESS_CATEGORY(obj
)->items
=
1139 jpilot_get_address_list_cat( jpf
, item
->categoryID
);
1141 addressbook_set_clist( obj
);
1147 else if( obj
->type
== ADDR_LDAP
) {
1148 if( _have_ldap_library_
) {
1150 SyldapServer
*server
;
1151 server
= ADDRESS_LDAP(obj
)->ldapServer
;
1152 addressbook_ldap_show_message( server
);
1153 if( ! server
->busyFlag
) {
1154 ADDRESS_LDAP(obj
)->items
= syldap_get_address_list( server
);
1155 addressbook_set_clist( obj
);
1161 // Setup main menu selections
1162 addressbook_menubar_set_sensitive( FALSE
);
1163 addressbook_menuitem_set_sensitive( obj
, node
);
1166 static void addressbook_list_selected(GtkCList
*clist
, gint row
, gint column
,
1167 GdkEvent
*event
, gpointer data
)
1169 GtkEntry
*entry
= GTK_ENTRY(addrbook
.entry
);
1173 if (event
&& event
->type
== GDK_2BUTTON_PRESS
) {
1174 if (prefs_common
.add_address_by_click
&&
1175 addrbook
.target_compose
)
1176 addressbook_to_clicked(NULL
, NULL
);
1178 addressbook_edit_address_cb(NULL
, 0, NULL
);
1183 gtk_signal_handler_block_by_func
1185 GTK_SIGNAL_FUNC(addressbook_entry_changed
), NULL
);
1188 gtk_entry_set_text(entry
, "");
1190 for (cur
= clist
->selection
; cur
!= NULL
; cur
= cur
->next
) {
1191 obj
= gtk_clist_get_row_data(clist
,
1192 GPOINTER_TO_INT(cur
->data
));
1193 g_return_if_fail(obj
!= NULL
);
1195 if (obj
->type
== ADDR_ITEM
) {
1198 item
= ADDRESS_ITEM(obj
);
1199 if (item
->name
&& item
->address
) {
1202 buf
= g_strdup_printf
1203 ("%s <%s>", item
->name
, item
->address
);
1204 if (*gtk_entry_get_text(entry
) != '\0')
1205 gtk_entry_append_text(entry
, ", ");
1206 gtk_entry_append_text(entry
, buf
);
1208 } else if (item
->address
) {
1209 if (*gtk_entry_get_text(entry
) != '\0')
1210 gtk_entry_append_text(entry
, ", ");
1211 gtk_entry_append_text(entry
, item
->address
);
1217 gtk_signal_handler_unblock_by_func
1219 GTK_SIGNAL_FUNC(addressbook_entry_changed
), NULL
);
1224 static void addressbook_entry_changed(GtkWidget
*widget
)
1226 GtkCList
*clist
= GTK_CLIST(addrbook
.clist
);
1227 GtkEntry
*entry
= GTK_ENTRY(addrbook
.entry
);
1232 //if (clist->selection && clist->selection->next) return;
1234 str
= gtk_entry_get_text(entry
);
1236 gtk_clist_unselect_all(clist
);
1241 for (row
= 0; row
< clist
->rows
; row
++) {
1245 obj
= ADDRESS_OBJECT(gtk_clist_get_row_data(clist
, row
));
1247 if (obj
->type
== ADDR_ITEM
)
1248 name
= ADDRESS_ITEM(obj
)->name
;
1249 else if (obj
->type
== ADDR_GROUP
)
1250 name
= ADDRESS_GROUP(obj
)->name
;
1254 if (name
&& !strncasecmp(name
, str
, len
)) {
1255 gtk_clist_unselect_all(clist
);
1256 gtk_clist_select_row(clist
, row
, -1);
1261 gtk_clist_unselect_all(clist
);
1265 static void addressbook_entry_gotfocus( GtkWidget
*widget
) {
1266 gtk_editable_select_region( GTK_EDITABLE(addrbook
.entry
), 0, -1 );
1269 static void addressbook_list_button_pressed(GtkWidget
*widget
,
1270 GdkEventButton
*event
,
1273 GtkCList
*clist
= GTK_CLIST(widget
);
1276 AddressObject
*obj
, *pobj
;
1280 obj
= gtk_ctree_node_get_row_data(GTK_CTREE(addrbook
.ctree
),
1282 g_return_if_fail(obj
!= NULL
);
1284 pobj
= gtk_ctree_node_get_row_data(GTK_CTREE(addrbook
.ctree
), addrbook
.selected
);
1286 if( pobj
->type
== ADDR_VCARD
||
1287 pobj
->type
== ADDR_JPILOT
||
1288 pobj
->type
== ADDR_CATEGORY
||
1289 pobj
->type
== ADDR_LDAP
) {
1290 menu_set_sensitive(addrbook
.menu_factory
, "/File/Edit", FALSE
);
1291 menu_set_sensitive(addrbook
.menu_factory
, "/File/Delete", FALSE
);
1295 if (event
->button
!= 3) return;
1296 menu_set_insensitive_all(GTK_MENU_SHELL(addrbook
.list_popup
));
1298 if (gtk_clist_get_selection_info
1299 (clist
, event
->x
, event
->y
, &row
, &column
)) {
1300 GtkCListRow
*clist_row
;
1302 clist_row
= g_list_nth(clist
->row_list
, row
)->data
;
1303 if (clist_row
->state
!= GTK_STATE_SELECTED
) {
1304 gtk_clist_unselect_all(clist
);
1305 gtk_clist_select_row(clist
, row
, column
);
1307 gtkut_clist_set_focus_row(clist
, row
);
1309 if( obj
->type
!= ADDR_VCARD
&&
1310 obj
->type
!= ADDR_JPILOT
&&
1311 obj
->type
!= ADDR_CATEGORY
&&
1312 obj
->type
!= ADDR_LDAP
) {
1313 menu_set_sensitive(addrbook
.list_factory
, "/Edit", TRUE
);
1314 menu_set_sensitive(addrbook
.list_factory
, "/Delete", TRUE
);
1318 if( !( addrbook
.opened
== addrbook
.vcard
||
1319 addrbook
.opened
== addrbook
.jpilot
||
1320 addrbook
.opened
== addrbook
.ldap
) ) {
1322 if( obj
->type
== ADDR_FOLDER
|| obj
->type
== ADDR_GROUP
) {
1323 menu_set_sensitive(addrbook
.list_factory
, "/New Address", TRUE
);
1324 gtk_widget_set_sensitive( addrbook
.reg_btn
, TRUE
);
1325 gtk_widget_set_sensitive( addrbook
.del_btn
, TRUE
);
1327 if (obj
->type
== ADDR_FOLDER
) {
1328 menu_set_sensitive(addrbook
.list_factory
, "/New Folder", TRUE
);
1329 menu_set_sensitive(addrbook
.list_factory
, "/New Group", TRUE
);
1332 gtk_menu_popup(GTK_MENU(addrbook
.list_popup
), NULL
, NULL
, NULL
, NULL
,
1333 event
->button
, event
->time
);
1336 static void addressbook_list_button_released(GtkWidget
*widget
,
1337 GdkEventButton
*event
,
1342 static void addressbook_tree_button_pressed(GtkWidget
*ctree
,
1343 GdkEventButton
*event
,
1346 GtkCList
*clist
= GTK_CLIST(ctree
);
1352 if (event
->button
== 1) {
1353 addrbook
.open_folder
= TRUE
;
1356 if (event
->button
!= 3) return;
1358 if (!gtk_clist_get_selection_info
1359 (clist
, event
->x
, event
->y
, &row
, &column
)) return;
1360 gtk_clist_select_row(clist
, row
, column
);
1362 obj
= gtk_clist_get_row_data(clist
, row
);
1363 g_return_if_fail(obj
!= NULL
);
1365 menu_set_insensitive_all(GTK_MENU_SHELL(addrbook
.tree_popup
));
1367 if (obj
->type
== ADDR_FOLDER
) {
1368 node
= gtk_ctree_node_nth(GTK_CTREE(ctree
), row
);
1369 if( node
== addrbook
.vcard
) {
1370 menu_set_sensitive(addrbook
.tree_factory
, "/New V-Card", TRUE
);
1373 else if( node
== addrbook
.jpilot
) {
1374 if( _have_pilot_library_
) {
1375 menu_set_sensitive(addrbook
.tree_factory
, "/New J-Pilot", TRUE
);
1380 else if( node
== addrbook
.ldap
) {
1381 if( _have_ldap_library_
) {
1382 menu_set_sensitive(addrbook
.tree_factory
, "/New Server", TRUE
);
1387 menu_set_sensitive(addrbook
.tree_factory
, "/New Address", TRUE
);
1388 menu_set_sensitive(addrbook
.tree_factory
, "/New Folder", TRUE
);
1389 menu_set_sensitive(addrbook
.tree_factory
, "/New Group", TRUE
);
1390 if (node
&& GTK_CTREE_ROW(node
)->level
>= 2) {
1391 menu_set_sensitive(addrbook
.tree_factory
, "/Edit", TRUE
);
1392 menu_set_sensitive(addrbook
.tree_factory
, "/Delete", TRUE
);
1394 gtk_widget_set_sensitive( addrbook
.reg_btn
, TRUE
);
1395 gtk_widget_set_sensitive( addrbook
.del_btn
, TRUE
);
1398 else if (obj
->type
== ADDR_GROUP
) {
1399 menu_set_sensitive(addrbook
.tree_factory
, "/New Address", TRUE
);
1400 menu_set_sensitive(addrbook
.tree_factory
, "/Edit", TRUE
);
1401 menu_set_sensitive(addrbook
.tree_factory
, "/Delete", TRUE
);
1402 gtk_widget_set_sensitive( addrbook
.reg_btn
, TRUE
);
1403 gtk_widget_set_sensitive( addrbook
.del_btn
, TRUE
);
1405 else if (obj
->type
== ADDR_VCARD
) {
1406 menu_set_sensitive(addrbook
.tree_factory
, "/Edit", TRUE
);
1407 menu_set_sensitive(addrbook
.tree_factory
, "/Delete", TRUE
);
1410 else if (obj
->type
== ADDR_JPILOT
) {
1411 if( _have_pilot_library_
) {
1412 menu_set_sensitive(addrbook
.tree_factory
, "/Edit", TRUE
);
1413 menu_set_sensitive(addrbook
.tree_factory
, "/Delete", TRUE
);
1416 else if (obj
->type
== ADDR_CATEGORY
) {
1417 if( _have_pilot_library_
) {
1418 menu_set_sensitive(addrbook
.tree_factory
, "/Edit", FALSE
);
1419 menu_set_sensitive(addrbook
.tree_factory
, "/Delete", FALSE
);
1424 else if (obj
->type
== ADDR_LDAP
) {
1425 if( _have_ldap_library_
) {
1426 menu_set_sensitive(addrbook
.tree_factory
, "/Edit", TRUE
);
1427 menu_set_sensitive(addrbook
.tree_factory
, "/Delete", TRUE
);
1434 gtk_menu_popup(GTK_MENU(addrbook
.tree_popup
), NULL
, NULL
, NULL
, NULL
,
1435 event
->button
, event
->time
);
1438 static void addressbook_tree_button_released(GtkWidget
*ctree
,
1439 GdkEventButton
*event
,
1442 gtk_ctree_select(GTK_CTREE(addrbook
.ctree
), addrbook
.opened
);
1443 gtkut_ctree_set_focus_row(GTK_CTREE(addrbook
.ctree
), addrbook
.opened
);
1446 static void addressbook_popup_close(GtkMenuShell
*menu_shell
, gpointer data
)
1448 if (!addrbook
.opened
) return;
1450 gtk_ctree_select(GTK_CTREE(addrbook
.ctree
), addrbook
.opened
);
1451 gtkut_ctree_set_focus_row(GTK_CTREE(addrbook
.ctree
),
1455 static void addressbook_new_folder_cb(gpointer data
, guint action
,
1458 GtkCTree
*ctree
= GTK_CTREE(addrbook
.ctree
);
1460 AddressFolder
*folder
;
1463 if (!addrbook
.selected
) return;
1465 obj
= gtk_ctree_node_get_row_data(ctree
, addrbook
.selected
);
1466 g_return_if_fail(obj
!= NULL
);
1467 if (obj
->type
!= ADDR_FOLDER
) return;
1469 new_folder
= input_dialog(_("New folder"),
1470 _("Input the name of new folder:"),
1472 if (!new_folder
) return;
1473 g_strstrip(new_folder
);
1474 if (*new_folder
== '\0') {
1479 if (gtk_ctree_find_by_row_data_custom(ctree
, addrbook
.selected
,
1481 addressbook_obj_name_compare
)) {
1482 alertpanel_error(_("The name already exists."));
1487 folder
= g_new(AddressFolder
, 1);
1488 ADDRESS_OBJECT_TYPE(folder
) = ADDR_FOLDER
;
1489 folder
->name
= g_strdup(new_folder
);
1490 folder
->items
= NULL
;
1492 addressbook_add_object(addrbook
.selected
, ADDRESS_OBJECT(folder
));
1496 if (addrbook
.selected
== addrbook
.opened
)
1497 addressbook_set_clist(obj
);
1500 static void addressbook_new_group_cb(gpointer data
, guint action
,
1503 GtkCTree
*ctree
= GTK_CTREE(addrbook
.ctree
);
1505 AddressGroup
*group
;
1508 if (!addrbook
.selected
) return;
1510 obj
= gtk_ctree_node_get_row_data(ctree
, addrbook
.selected
);
1511 g_return_if_fail(obj
!= NULL
);
1512 if (obj
->type
!= ADDR_FOLDER
) return;
1514 new_group
= input_dialog(_("New group"),
1515 _("Input the name of new group:"),
1517 if (!new_group
) return;
1518 g_strstrip(new_group
);
1519 if (*new_group
== '\0') {
1524 if (gtk_ctree_find_by_row_data_custom(ctree
, addrbook
.selected
,
1526 addressbook_obj_name_compare
)) {
1527 alertpanel_error(_("The name already exists."));
1532 group
= g_new(AddressGroup
, 1);
1533 ADDRESS_OBJECT_TYPE(group
) = ADDR_GROUP
;
1534 group
->name
= g_strdup(new_group
);
1535 group
->items
= NULL
;
1537 addressbook_add_object(addrbook
.selected
, ADDRESS_OBJECT(group
));
1541 if (addrbook
.selected
== addrbook
.opened
)
1542 addressbook_set_clist(obj
);
1545 static void addressbook_change_node_name(GtkCTreeNode
*node
, const gchar
*name
)
1547 GtkCTree
*ctree
= GTK_CTREE(addrbook
.ctree
);
1550 GdkPixmap
*pix_cl
, *pix_op
;
1551 GdkBitmap
*mask_cl
, *mask_op
;
1552 gboolean is_leaf
, expanded
;
1554 gtk_ctree_get_node_info(ctree
, node
, text
, &spacing
,
1555 &pix_cl
, &mask_cl
, &pix_op
, &mask_op
,
1556 &is_leaf
, &expanded
);
1557 gtk_ctree_set_node_info(ctree
, node
, name
, spacing
,
1558 pix_cl
, mask_cl
, pix_op
, mask_op
,
1562 static void addressbook_edit_group(GtkCTreeNode
*group_node
)
1564 GtkCTree
*ctree
= GTK_CTREE(addrbook
.ctree
);
1565 GtkCList
*clist
= GTK_CLIST(addrbook
.clist
);
1567 AddressGroup
*group
;
1571 if (!group_node
&& clist
->selection
) {
1572 obj
= gtk_clist_get_row_data(clist
,
1573 GPOINTER_TO_INT(clist
->selection
->data
));
1574 g_return_if_fail(obj
!= NULL
);
1575 if (obj
->type
!= ADDR_GROUP
) return;
1576 node
= gtk_ctree_find_by_row_data
1577 (ctree
, addrbook
.selected
, obj
);
1583 node
= addrbook
.selected
;
1584 obj
= gtk_ctree_node_get_row_data(ctree
, node
);
1585 g_return_if_fail(obj
!= NULL
);
1586 if (obj
->type
!= ADDR_GROUP
) return;
1589 group
= ADDRESS_GROUP(obj
);
1591 new_name
= input_dialog(_("Edit group"),
1592 _("Input the new name of group:"),
1594 if (!new_name
) return;
1595 g_strstrip(new_name
);
1596 if (*new_name
== '\0') {
1601 if (gtk_ctree_find_by_row_data_custom(ctree
, addrbook
.selected
,
1603 addressbook_obj_name_compare
)) {
1604 alertpanel_error(_("The name already exists."));
1609 g_free(group
->name
);
1610 group
->name
= g_strdup(new_name
);
1612 addressbook_change_node_name(node
, new_name
);
1613 gtk_ctree_sort_node(ctree
, GTK_CTREE_ROW(node
)->parent
);
1617 addrbook
.open_folder
= TRUE
;
1618 gtk_ctree_select(ctree
, addrbook
.opened
);
1621 static void addressbook_edit_folder_cb(gpointer data
, guint action
,
1624 GtkCTree
*ctree
= GTK_CTREE(addrbook
.ctree
);
1626 AddressFolder
*folder
;
1627 gchar
*new_name
= NULL
;
1628 GtkCTreeNode
*node
= NULL
, *parentNode
= NULL
;
1630 if (!addrbook
.selected
) return;
1631 if (GTK_CTREE_ROW(addrbook
.selected
)->level
== 1) return;
1633 obj
= gtk_ctree_node_get_row_data(ctree
, addrbook
.selected
);
1634 g_return_if_fail(obj
!= NULL
);
1635 g_return_if_fail(obj
->type
== ADDR_FOLDER
|| obj
->type
== ADDR_GROUP
||
1636 obj
->type
== ADDR_VCARD
|| obj
->type
== ADDR_JPILOT
||
1637 obj
->type
== ADDR_CATEGORY
|| obj
->type
== ADDR_LDAP
);
1639 if (obj
->type
== ADDR_GROUP
) {
1640 addressbook_edit_group(addrbook
.selected
);
1644 if( obj
->type
== ADDR_VCARD
) {
1645 AddressVCard
*vcard
= ADDRESS_VCARD(obj
);
1646 if( addressbook_edit_vcard( vcard
) == NULL
) return;
1647 new_name
= vcard
->name
;
1648 parentNode
= addrbook
.vcard
;
1651 else if( obj
->type
== ADDR_JPILOT
) {
1652 AddressJPilot
*jpilot
= ADDRESS_JPILOT(obj
);
1653 if( ! _have_pilot_library_
) return;
1654 if( addressbook_edit_jpilot( jpilot
) == NULL
) return;
1655 new_name
= jpilot
->name
;
1656 parentNode
= addrbook
.jpilot
;
1660 else if( obj
->type
== ADDR_LDAP
) {
1661 AddressLDAP
*ldapi
= ADDRESS_LDAP(obj
);
1662 if( ! _have_ldap_library_
) return;
1663 if( addressbook_edit_ldap( ldapi
) == NULL
) return;
1664 new_name
= ldapi
->name
;
1665 parentNode
= addrbook
.ldap
;
1669 if( new_name
&& parentNode
) {
1670 // Update node in tree view
1671 node
= gtk_ctree_find_by_row_data( ctree
, addrbook
.selected
, obj
);
1672 if( ! node
) return;
1673 addressbook_change_node_name( node
, new_name
);
1674 gtk_ctree_sort_node(ctree
, parentNode
);
1675 addrbook
.open_folder
= TRUE
;
1676 gtk_ctree_select( GTK_CTREE(addrbook
.ctree
), node
);
1680 folder
= ADDRESS_FOLDER(obj
);
1681 new_name
= input_dialog(_("Edit folder"),
1682 _("Input the new name of folder:"),
1685 if (!new_name
) return;
1686 g_strstrip(new_name
);
1687 if (*new_name
== '\0') {
1692 if (gtk_ctree_find_by_row_data_custom(ctree
, addrbook
.selected
,
1694 addressbook_obj_name_compare
)) {
1695 alertpanel_error(_("The name already exists."));
1700 g_free(folder
->name
);
1701 folder
->name
= g_strdup(new_name
);
1703 addressbook_change_node_name(addrbook
.selected
, new_name
);
1704 gtk_ctree_sort_node(ctree
, GTK_CTREE_ROW(addrbook
.selected
)->parent
);
1709 static void addressbook_delete_folder_cb(gpointer data
, guint action
,
1712 GtkCTree
*ctree
= GTK_CTREE(addrbook
.ctree
);
1713 AddressObject
*obj
, *pobj
;
1718 if (!addrbook
.selected
) return;
1719 if (GTK_CTREE_ROW(addrbook
.selected
)->level
== 1) return;
1721 obj
= gtk_ctree_node_get_row_data(ctree
, addrbook
.selected
);
1722 g_return_if_fail(obj
!= NULL
);
1724 if (obj
->type
== ADDR_GROUP
)
1725 name
= ADDRESS_GROUP(obj
)->name
;
1726 else if (obj
->type
== ADDR_FOLDER
)
1727 name
= ADDRESS_FOLDER(obj
)->name
;
1728 else if (obj
->type
== ADDR_VCARD
)
1729 name
= ADDRESS_VCARD(obj
)->name
;
1731 else if (obj
->type
== ADDR_JPILOT
) {
1732 if( ! _have_pilot_library_
) return;
1733 name
= ADDRESS_JPILOT(obj
)->name
;
1737 else if (obj
->type
== ADDR_LDAP
) {
1738 if( ! _have_ldap_library_
) return;
1739 name
= ADDRESS_LDAP(obj
)->name
;
1745 message
= g_strdup_printf(_("Really delete `%s' ?"), name
);
1746 aval
= alertpanel(_("Delete"), message
, _("Yes"), _("No"), NULL
);
1748 if (aval
!= G_ALERTDEFAULT
) return;
1750 pobj
= gtk_ctree_node_get_row_data
1751 (ctree
, GTK_CTREE_ROW(addrbook
.selected
)->parent
);
1753 g_return_if_fail(pobj
->type
== ADDR_FOLDER
);
1754 ADDRESS_FOLDER(pobj
)->items
=
1755 g_list_remove(ADDRESS_FOLDER(pobj
)->items
, obj
);
1757 addressbook_delete_object(obj
);
1758 addrbook
.open_folder
= TRUE
;
1759 gtk_ctree_remove_node(ctree
, addrbook
.selected
);
1760 addrbook
.open_folder
= FALSE
;
1763 #define SET_LABEL_AND_ENTRY(str, entry, top) \
1765 label = gtk_label_new(str); \
1766 gtk_table_attach(GTK_TABLE(table), label, 0, 1, top, (top + 1), \
1767 GTK_FILL, 0, 0, 0); \
1768 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); \
1770 entry = gtk_entry_new(); \
1771 gtk_table_attach(GTK_TABLE(table), entry, 1, 2, top, (top + 1), \
1772 GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0); \
1775 static void addressbook_edit_address_create(gboolean
*cancelled
)
1781 GtkWidget
*name_entry
;
1782 GtkWidget
*addr_entry
;
1783 GtkWidget
*rem_entry
;
1786 GtkWidget
*cancel_btn
;
1788 debug_print("Creating edit_address window...\n");
1790 window
= gtk_window_new(GTK_WINDOW_DIALOG
);
1791 gtk_widget_set_usize(window
, 400, -1);
1792 gtk_container_set_border_width(GTK_CONTAINER(window
), 8);
1793 gtk_window_set_title(GTK_WINDOW(window
), _("Edit address"));
1794 gtk_window_set_position(GTK_WINDOW(window
), GTK_WIN_POS_CENTER
);
1795 gtk_window_set_modal(GTK_WINDOW(window
), TRUE
);
1796 gtk_signal_connect(GTK_OBJECT(window
), "delete_event",
1797 GTK_SIGNAL_FUNC(edit_address_delete_event
),
1799 gtk_signal_connect(GTK_OBJECT(window
), "key_press_event",
1800 GTK_SIGNAL_FUNC(edit_address_key_pressed
),
1803 vbox
= gtk_vbox_new(FALSE
, 8);
1804 gtk_container_add(GTK_CONTAINER(window
), vbox
);
1806 table
= gtk_table_new(3, 2, FALSE
);
1807 gtk_box_pack_start(GTK_BOX(vbox
), table
, FALSE
, FALSE
, 0);
1808 gtk_table_set_row_spacings(GTK_TABLE(table
), 8);
1809 gtk_table_set_col_spacings(GTK_TABLE(table
), 8);
1811 SET_LABEL_AND_ENTRY(_("Name"), name_entry
, 0);
1812 SET_LABEL_AND_ENTRY(_("Address"), addr_entry
, 1);
1813 SET_LABEL_AND_ENTRY(_("Remarks"), rem_entry
, 2);
1815 gtkut_button_set_create(&hbbox
, &ok_btn
, _("OK"),
1816 &cancel_btn
, _("Cancel"), NULL
, NULL
);
1817 gtk_box_pack_end(GTK_BOX(vbox
), hbbox
, FALSE
, FALSE
, 0);
1818 gtk_widget_grab_default(ok_btn
);
1820 gtk_signal_connect(GTK_OBJECT(ok_btn
), "clicked",
1821 GTK_SIGNAL_FUNC(edit_address_ok
), cancelled
);
1822 gtk_signal_connect(GTK_OBJECT(cancel_btn
), "clicked",
1823 GTK_SIGNAL_FUNC(edit_address_cancel
), cancelled
);
1825 gtk_widget_show_all(vbox
);
1827 addredit
.window
= window
;
1828 addredit
.name_entry
= name_entry
;
1829 addredit
.addr_entry
= addr_entry
;
1830 addredit
.rem_entry
= rem_entry
;
1831 addredit
.ok_btn
= ok_btn
;
1832 addredit
.cancel_btn
= cancel_btn
;
1835 static void edit_address_ok(GtkWidget
*widget
, gboolean
*cancelled
)
1841 static void edit_address_cancel(GtkWidget
*widget
, gboolean
*cancelled
)
1847 static gint
edit_address_delete_event(GtkWidget
*widget
, GdkEventAny
*event
,
1848 gboolean
*cancelled
)
1856 static void edit_address_key_pressed(GtkWidget
*widget
, GdkEventKey
*event
,
1857 gboolean
*cancelled
)
1859 if (event
&& event
->keyval
== GDK_Escape
) {
1865 static AddressItem
*addressbook_edit_address(AddressItem
*item
)
1867 static gboolean cancelled
;
1870 if (!addredit
.window
)
1871 addressbook_edit_address_create(&cancelled
);
1872 gtk_widget_grab_focus(addredit
.ok_btn
);
1873 gtk_widget_grab_focus(addredit
.name_entry
);
1874 gtk_widget_show(addredit
.window
);
1875 manage_window_set_transient(GTK_WINDOW(addredit
.window
));
1877 gtk_entry_set_text(GTK_ENTRY(addredit
.name_entry
), "");
1878 gtk_entry_set_text(GTK_ENTRY(addredit
.addr_entry
), "");
1879 gtk_entry_set_text(GTK_ENTRY(addredit
.rem_entry
), "");
1883 gtk_entry_set_text(GTK_ENTRY(addredit
.name_entry
),
1886 gtk_entry_set_text(GTK_ENTRY(addredit
.addr_entry
),
1889 gtk_entry_set_text(GTK_ENTRY(addredit
.rem_entry
),
1894 gtk_widget_hide(addredit
.window
);
1895 if (cancelled
== TRUE
) return NULL
;
1897 str
= gtk_entry_get_text(GTK_ENTRY(addredit
.name_entry
));
1898 if (*str
== '\0') return NULL
;
1901 item
= mgu_create_address();
1902 ADDRESS_OBJECT_TYPE(item
) = ADDR_ITEM
;
1906 item
->name
= g_strdup(str
);
1908 str
= gtk_entry_get_text(GTK_ENTRY(addredit
.addr_entry
));
1909 g_free(item
->address
);
1911 item
->address
= NULL
;
1913 item
->address
= g_strdup(str
);
1915 str
= gtk_entry_get_text(GTK_ENTRY(addredit
.rem_entry
));
1916 g_free(item
->remarks
);
1918 item
->remarks
= NULL
;
1920 item
->remarks
= g_strdup(str
);
1925 static void addressbook_new_address_cb(gpointer data
, guint action
,
1930 item
= addressbook_edit_address(NULL
);
1933 addressbook_add_object(addrbook
.selected
,
1934 ADDRESS_OBJECT(item
));
1935 if (addrbook
.selected
== addrbook
.opened
) {
1936 addrbook
.open_folder
= TRUE
;
1937 gtk_ctree_select(GTK_CTREE(addrbook
.ctree
),
1943 static void addressbook_edit_address_cb(gpointer data
, guint action
,
1946 GtkCList
*clist
= GTK_CLIST(addrbook
.clist
);
1948 AddressObject
*obj
, *pobj
;
1949 GtkCTreeNode
*node
= NULL
, *parentNode
= NULL
;
1952 if (!clist
->selection
) {
1953 addressbook_edit_folder_cb(NULL
, 0, NULL
);
1957 obj
= gtk_clist_get_row_data(clist
, GPOINTER_TO_INT(clist
->selection
->data
));
1958 g_return_if_fail(obj
!= NULL
);
1960 pobj
= gtk_ctree_node_get_row_data(GTK_CTREE(addrbook
.ctree
), addrbook
.selected
);
1962 if (obj
->type
== ADDR_ITEM
) {
1963 AddressItem
*item
= ADDRESS_ITEM(obj
);
1966 // Prevent edit of readonly items
1967 if( pobj
->type
== ADDR_VCARD
||
1968 pobj
->type
== ADDR_JPILOT
||
1969 pobj
->type
== ADDR_CATEGORY
||
1970 pobj
->type
== ADDR_LDAP
) return;
1973 if (addressbook_edit_address(item
) == NULL
) return;
1975 addrbook
.open_folder
= TRUE
;
1976 gtk_ctree_select(GTK_CTREE(addrbook
.ctree
), addrbook
.opened
);
1979 else if (obj
->type
== ADDR_GROUP
) {
1980 addressbook_edit_group(NULL
);
1983 else if( obj
->type
== ADDR_VCARD
) {
1984 AddressVCard
*vcard
= ADDRESS_VCARD(obj
);
1985 if( addressbook_edit_vcard( vcard
) == NULL
) return;
1986 nodeName
= vcard
->name
;
1987 parentNode
= addrbook
.vcard
;
1990 else if( obj
->type
== ADDR_JPILOT
) {
1991 AddressJPilot
*jpilot
= ADDRESS_JPILOT(obj
);
1992 if( addressbook_edit_jpilot( jpilot
) == NULL
) return;
1993 nodeName
= jpilot
->name
;
1994 parentNode
= addrbook
.jpilot
;
1998 else if( obj
->type
== ADDR_LDAP
) {
1999 AddressLDAP
*ldapi
= ADDRESS_LDAP(obj
);
2000 if( addressbook_edit_ldap( ldapi
) == NULL
) return;
2001 nodeName
= ldapi
->name
;
2002 parentNode
= addrbook
.ldap
;
2009 // Update tree node with node name
2010 ctree
= GTK_CTREE( addrbook
.ctree
);
2011 node
= gtk_ctree_find_by_row_data( ctree
, addrbook
.selected
, obj
);
2012 if( ! node
) return;
2013 addressbook_change_node_name( node
, nodeName
);
2014 gtk_ctree_sort_node(ctree
, parentNode
);
2015 addrbook
.open_folder
= TRUE
;
2016 gtk_ctree_select( ctree
, addrbook
.opened
);
2019 static void addressbook_delete_address_cb(gpointer data
, guint action
,
2022 addressbook_del_clicked(NULL
, NULL
);
2025 static void close_cb(gpointer data
, guint action
, GtkWidget
*widget
)
2027 addressbook_close();
2030 static void addressbook_set_clist(AddressObject
*obj
)
2032 GtkCList
*clist
= GTK_CLIST(addrbook
.clist
);
2034 gchar
*text
[N_COLS
];
2037 gtk_clist_clear(clist
);
2041 gtk_clist_freeze(clist
);
2042 gtk_clist_clear(clist
);
2044 if (obj
->type
== ADDR_GROUP
)
2045 items
= ADDRESS_GROUP(obj
)->items
;
2046 else if (obj
->type
== ADDR_FOLDER
) {
2047 items
= ADDRESS_FOLDER(obj
)->items
;
2049 else if (obj
->type
== ADDR_VCARD
) {
2050 items
= ADDRESS_VCARD(obj
)->items
;
2053 else if (obj
->type
== ADDR_JPILOT
) {
2054 items
= ADDRESS_JPILOT(obj
)->items
;
2056 else if (obj
->type
== ADDR_CATEGORY
) {
2057 items
= ADDRESS_CATEGORY(obj
)->items
;
2061 else if (obj
->type
== ADDR_LDAP
) {
2062 items
= ADDRESS_LDAP(obj
)->items
;
2066 gtk_clist_thaw(clist
);
2070 for (; items
!= NULL
; items
= items
->next
) {
2071 AddressObject
*iobj
;
2073 iobj
= ADDRESS_OBJECT(items
->data
);
2074 if( iobj
== NULL
) continue;
2076 if (iobj
->type
== ADDR_GROUP
) {
2077 AddressGroup
*group
;
2079 group
= ADDRESS_GROUP(iobj
);
2080 text
[COL_NAME
] = group
->name
;
2081 text
[COL_ADDRESS
] = NULL
;
2082 text
[COL_REMARKS
] = NULL
;
2083 row
= gtk_clist_append(clist
, text
);
2084 gtk_clist_set_pixtext(clist
, row
, COL_NAME
,
2086 groupxpm
, groupxpmmask
);
2087 gtk_clist_set_row_data(clist
, row
, iobj
);
2088 } if (iobj
->type
== ADDR_VCARD
) {
2089 AddressVCard
*vcard
;
2091 vcard
= ADDRESS_VCARD(iobj
);
2092 text
[COL_NAME
] = vcard
->name
;
2093 text
[COL_ADDRESS
] = NULL
;
2094 text
[COL_REMARKS
] = NULL
;
2095 row
= gtk_clist_append(clist
, text
);
2096 gtk_clist_set_pixtext(clist
, row
, COL_NAME
,
2098 vcardxpm
, vcardxpmmask
);
2099 gtk_clist_set_row_data(clist
, row
, iobj
);
2101 } if (iobj
->type
== ADDR_JPILOT
) {
2102 AddressJPilot
*jpilot
;
2104 jpilot
= ADDRESS_JPILOT(iobj
);
2105 text
[COL_NAME
] = jpilot
->name
;
2106 text
[COL_ADDRESS
] = NULL
;
2107 text
[COL_REMARKS
] = NULL
;
2108 row
= gtk_clist_append(clist
, text
);
2109 gtk_clist_set_pixtext(clist
, row
, COL_NAME
,
2111 jpilotxpm
, jpilotxpmmask
);
2112 gtk_clist_set_row_data(clist
, row
, iobj
);
2113 } if (iobj
->type
== ADDR_CATEGORY
) {
2114 AddressCategory
*category
;
2116 category
= ADDRESS_CATEGORY(iobj
);
2117 text
[COL_NAME
] = category
->name
;
2118 text
[COL_ADDRESS
] = NULL
;
2119 text
[COL_REMARKS
] = NULL
;
2120 row
= gtk_clist_append(clist
, text
);
2121 gtk_clist_set_pixtext(clist
, row
, COL_NAME
,
2123 categoryxpm
, categoryxpmmask
);
2124 gtk_clist_set_row_data(clist
, row
, iobj
);
2127 } if (iobj
->type
== ADDR_LDAP
) {
2130 ldapi
= ADDRESS_LDAP(iobj
);
2131 text
[COL_NAME
] = ldapi
->name
;
2132 text
[COL_ADDRESS
] = NULL
;
2133 text
[COL_REMARKS
] = NULL
;
2134 row
= gtk_clist_append(clist
, text
);
2135 gtk_clist_set_pixtext(clist
, row
, COL_NAME
,
2137 ldapxpm
, ldapxpmmask
);
2138 gtk_clist_set_row_data(clist
, row
, iobj
);
2140 } else if (iobj
->type
== ADDR_ITEM
) {
2143 item
= ADDRESS_ITEM(iobj
);
2144 text
[COL_NAME
] = item
->name
;
2145 text
[COL_ADDRESS
] = item
->address
;
2146 text
[COL_REMARKS
] = item
->remarks
;
2147 row
= gtk_clist_append(clist
, text
);
2148 gtk_clist_set_row_data(clist
, row
, iobj
);
2152 gtk_clist_sort(clist
);
2153 gtk_clist_thaw(clist
);
2156 static void addressbook_read_file(void)
2161 debug_print(_("Reading addressbook file..."));
2163 path
= g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S
, ADDRESS_BOOK
, NULL
);
2164 if ((file
= xml_open_file(path
)) == NULL
) {
2165 debug_print(_("%s doesn't exist.\n"), path
);
2167 addressbook_get_tree(NULL
, addrbook
.common
, ADDRESS_TAG_COMMON
);
2168 addressbook_get_tree(NULL
, addrbook
.personal
, ADDRESS_TAG_PERSONAL
);
2169 addressbook_get_tree(NULL
, addrbook
.vcard
, ADDRESS_TAG_VCARD
);
2171 addressbook_get_tree(NULL
, addrbook
.jpilot
, ADDRESS_TAG_JPILOT
);
2174 addressbook_get_tree(NULL
, addrbook
.ldap
, ADDRESS_TAG_LDAP
);
2182 if (xml_parse_next_tag(file
) < 0 ||
2183 xml_compare_tag(file
, "addressbook") == FALSE
) {
2184 g_warning("Invalid addressbook data\n");
2185 xml_close_file(file
);
2189 addressbook_get_tree(file
, addrbook
.common
, ADDRESS_TAG_COMMON
);
2190 addressbook_get_tree(file
, addrbook
.personal
, ADDRESS_TAG_PERSONAL
);
2191 addressbook_get_tree(file
, addrbook
.vcard
, ADDRESS_TAG_VCARD
);
2193 addressbook_get_tree(file
, addrbook
.jpilot
, ADDRESS_TAG_JPILOT
);
2196 addressbook_get_tree(file
, addrbook
.ldap
, ADDRESS_TAG_LDAP
);
2199 xml_close_file(file
);
2201 debug_print(_("done.\n"));
2204 static void addressbook_get_tree(XMLFile
*file
, GtkCTreeNode
*node
,
2205 const gchar
*folder_tag
)
2207 AddressFolder
*folder
;
2209 g_return_if_fail(node
!= NULL
);
2211 folder
= g_new(AddressFolder
, 1);
2212 ADDRESS_OBJECT(folder
)->type
= ADDR_FOLDER
;
2213 folder
->name
= g_strdup(folder_tag
);
2214 folder
->items
= NULL
;
2215 gtk_ctree_node_set_row_data(GTK_CTREE(addrbook
.ctree
), node
, folder
);
2218 if (xml_parse_next_tag(file
) < 0 ||
2219 xml_compare_tag(file
, folder_tag
) == FALSE
) {
2220 g_warning("Invalid addressbook data\n");
2225 if (file
) addressbook_add_objs(file
, node
);
2228 static void addressbook_add_objs(XMLFile
*file
, GtkCTreeNode
*node
)
2232 GtkCTreeNode
*new_node
;
2235 prev_level
= file
->level
;
2236 if (xml_parse_next_tag(file
) < 0) return;
2237 if (file
->level
< prev_level
) return;
2239 if (xml_compare_tag(file
, "group")) {
2240 AddressGroup
*group
;
2242 group
= g_new(AddressGroup
, 1);
2243 ADDRESS_OBJECT_TYPE(group
) = ADDR_GROUP
;
2244 attr
= xml_get_current_tag_attr(file
);
2246 group
->name
= g_strdup(((XMLAttr
*)attr
->data
)->value
);
2249 group
->items
= NULL
;
2251 new_node
= addressbook_add_object
2252 (node
, ADDRESS_OBJECT(group
));
2254 addressbook_add_objs(file
, new_node
);
2255 } else if (xml_compare_tag(file
, "folder")) {
2256 AddressFolder
*folder
;
2258 folder
= g_new(AddressFolder
, 1);
2259 ADDRESS_OBJECT_TYPE(folder
) = ADDR_FOLDER
;
2260 attr
= xml_get_current_tag_attr(file
);
2262 folder
->name
= g_strdup(((XMLAttr
*)attr
->data
)->value
);
2264 folder
->name
= NULL
;
2265 folder
->items
= NULL
;
2267 new_node
= addressbook_add_object
2268 (node
, ADDRESS_OBJECT(folder
));
2270 addressbook_add_objs(file
, new_node
);
2272 else if( xml_compare_tag( file
, "vcard" ) ) {
2273 AddressVCard
*vcard
;
2274 vcard
= addressbook_parse_vcard( file
);
2275 if( ! vcard
) return;
2276 new_node
= addressbook_add_object
2277 (node
, ADDRESS_OBJECT(vcard
));
2280 else if( xml_compare_tag( file
, "jpilot" ) ) {
2281 AddressJPilot
*jpilot
;
2282 jpilot
= addressbook_parse_jpilot( file
);
2283 if( ! jpilot
) return;
2284 new_node
= addressbook_add_object
2285 (node
, ADDRESS_OBJECT(jpilot
));
2289 else if( xml_compare_tag( file
, "server" ) ) {
2291 ldapi
= addressbook_parse_ldap( file
);
2292 if( ! ldapi
) return;
2293 new_node
= addressbook_add_object
2294 (node
, ADDRESS_OBJECT(ldapi
));
2297 else if (xml_compare_tag(file
, "item")) {
2300 item
= addressbook_parse_item(file
);
2302 new_node
= addressbook_add_object
2303 (node
, ADDRESS_OBJECT(item
));
2305 g_warning("Invalid tag\n");
2311 static GtkCTreeNode
*addressbook_add_object(GtkCTreeNode
*node
,
2314 GtkCTree
*ctree
= GTK_CTREE(addrbook
.ctree
);
2315 GtkCTreeNode
*added
;
2316 AddressObject
*pobj
;
2318 g_return_val_if_fail(node
!= NULL
, NULL
);
2319 g_return_val_if_fail(obj
!= NULL
, NULL
);
2321 pobj
= gtk_ctree_node_get_row_data(ctree
, node
);
2322 g_return_val_if_fail(pobj
!= NULL
, NULL
);
2324 if (pobj
->type
== ADDR_ITEM
) {
2325 g_warning("Parent object mustn't be an item.\n");
2328 if (pobj
->type
== ADDR_FOLDER
&&
2329 (obj
->type
== ADDR_GROUP
|| obj
->type
== ADDR_FOLDER
))
2330 gtk_ctree_expand(ctree
, node
);
2332 if (pobj
->type
== ADDR_FOLDER
&& obj
->type
== ADDR_VCARD
)
2333 gtk_ctree_expand(ctree
, node
);
2335 if (pobj
->type
== ADDR_FOLDER
&& obj
->type
== ADDR_JPILOT
)
2336 gtk_ctree_expand(ctree
, node
);
2338 if (pobj
->type
== ADDR_FOLDER
&& obj
->type
== ADDR_LDAP
)
2339 gtk_ctree_expand(ctree
, node
);
2341 if (obj
->type
== ADDR_GROUP
) {
2342 AddressGroup
*group
= ADDRESS_GROUP(obj
);
2344 if (pobj
->type
!= ADDR_FOLDER
) {
2345 g_warning("Group can't be added in another group.\n");
2349 added
= gtk_ctree_insert_node(ctree
, node
, NULL
,
2350 &group
->name
, FOLDER_SPACING
,
2351 groupxpm
, groupxpmmask
,
2352 groupxpm
, groupxpmmask
,
2354 gtk_ctree_node_set_row_data(ctree
, added
, obj
);
2355 } else if (obj
->type
== ADDR_FOLDER
) {
2356 AddressFolder
*folder
= ADDRESS_FOLDER(obj
);
2358 if (pobj
->type
!= ADDR_FOLDER
) {
2359 g_warning("Group can't contain folder.\n");
2363 added
= gtk_ctree_insert_node(ctree
, node
, NULL
,
2364 &folder
->name
, FOLDER_SPACING
,
2365 folderxpm
, folderxpmmask
,
2366 folderopenxpm
, folderopenxpmmask
,
2368 gtk_ctree_node_set_row_data(ctree
, added
, obj
);
2371 else if (obj
->type
== ADDR_VCARD
) {
2372 AddressVCard
*vcard
= ADDRESS_VCARD(obj
);
2373 added
= gtk_ctree_insert_node(ctree
, node
, NULL
,
2374 &vcard
->name
, FOLDER_SPACING
,
2375 vcardxpm
, vcardxpmmask
,
2376 vcardxpm
, vcardxpmmask
,
2378 gtk_ctree_node_set_row_data(ctree
, added
, obj
);
2381 else if (obj
->type
== ADDR_JPILOT
) {
2382 AddressJPilot
*jpilot
= ADDRESS_JPILOT(obj
);
2383 added
= gtk_ctree_insert_node(ctree
, node
, NULL
,
2384 &jpilot
->name
, FOLDER_SPACING
,
2385 jpilotxpm
, jpilotxpmmask
,
2386 jpilotxpm
, jpilotxpmmask
,
2388 gtk_ctree_node_set_row_data(ctree
, added
, obj
);
2390 else if (obj
->type
== ADDR_CATEGORY
) {
2391 AddressCategory
*category
= ADDRESS_CATEGORY(obj
);
2392 added
= gtk_ctree_insert_node(ctree
, node
, NULL
,
2393 &category
->name
, FOLDER_SPACING
,
2394 categoryxpm
, categoryxpmmask
,
2395 categoryxpm
, categoryxpmmask
,
2397 gtk_ctree_node_set_row_data(ctree
, added
, obj
);
2401 else if (obj
->type
== ADDR_LDAP
) {
2402 AddressLDAP
*server
= ADDRESS_LDAP(obj
);
2403 added
= gtk_ctree_insert_node(ctree
, node
, NULL
,
2404 &server
->name
, FOLDER_SPACING
,
2405 ldapxpm
, ldapxpmmask
,
2406 ldapxpm
, ldapxpmmask
,
2408 gtk_ctree_node_set_row_data(ctree
, added
, obj
);
2415 if (obj
->type
== ADDR_GROUP
|| obj
->type
== ADDR_ITEM
) {
2416 if (pobj
->type
== ADDR_GROUP
) {
2417 AddressGroup
*group
= ADDRESS_GROUP(pobj
);
2419 group
->items
= g_list_append(group
->items
, obj
);
2420 } else if (pobj
->type
== ADDR_FOLDER
) {
2421 AddressFolder
*folder
= ADDRESS_FOLDER(pobj
);
2423 folder
->items
= g_list_append(folder
->items
, obj
);
2427 if (pobj
->type
== ADDR_FOLDER
) {
2428 if (obj
->type
== ADDR_VCARD
|| obj
->type
== ADDR_JPILOT
|| obj
->type
== ADDR_LDAP
) {
2429 AddressFolder
*folder
= ADDRESS_FOLDER(pobj
);
2430 folder
->items
= g_list_append(folder
->items
, obj
);
2434 gtk_ctree_sort_node(ctree
, node
);
2439 static void addressbook_delete_object(AddressObject
*obj
)
2443 if (obj
->type
== ADDR_ITEM
) {
2444 AddressItem
*item
= ADDRESS_ITEM(obj
);
2446 mgu_free_address( item
);
2447 } else if (obj
->type
== ADDR_GROUP
) {
2448 AddressGroup
*group
= ADDRESS_GROUP(obj
);
2450 g_free(group
->name
);
2451 while (group
->items
!= NULL
) {
2452 addressbook_delete_object
2453 (ADDRESS_OBJECT(group
->items
->data
));
2454 group
->items
= g_list_remove(group
->items
,
2455 group
->items
->data
);
2458 } else if (obj
->type
== ADDR_FOLDER
) {
2459 AddressFolder
*folder
= ADDRESS_FOLDER(obj
);
2461 g_free(folder
->name
);
2462 while (folder
->items
!= NULL
) {
2463 addressbook_delete_object
2464 (ADDRESS_OBJECT(folder
->items
->data
));
2465 folder
->items
= g_list_remove(folder
->items
,
2466 folder
->items
->data
);
2470 else if( obj
->type
== ADDR_VCARD
) {
2471 AddressVCard
*vcard
= ADDRESS_VCARD(obj
);
2472 g_free( vcard
->name
);
2473 vcard_free( vcard
->cardFile
);
2474 vcard
->cardFile
= NULL
;
2475 vcard
->items
= NULL
;
2479 else if( obj
->type
== ADDR_JPILOT
) {
2480 AddressJPilot
*jpilot
= ADDRESS_JPILOT(obj
);
2481 g_free( jpilot
->name
);
2482 jpilot_free( jpilot
->pilotFile
);
2483 jpilot
->pilotFile
= NULL
;
2484 jpilot
->items
= NULL
;
2489 else if( obj
->type
== ADDR_LDAP
) {
2490 AddressLDAP
*ldapi
= ADDRESS_LDAP(obj
);
2491 g_free( ldapi
->name
);
2492 syldap_free( ldapi
->ldapServer
);
2493 ldapi
->ldapServer
= NULL
;
2494 ldapi
->items
= NULL
;
2500 static AddressObject
*addressbook_find_object_by_name(GtkCTreeNode
*node
,
2503 GtkCTree
*ctree
= GTK_CTREE(addrbook
.ctree
);
2507 g_return_val_if_fail(node
!= NULL
, NULL
);
2509 obj
= gtk_ctree_node_get_row_data(ctree
, node
);
2510 g_return_val_if_fail(obj
!= NULL
, NULL
);
2512 if (obj
->type
== ADDR_GROUP
) {
2513 AddressGroup
*group
= ADDRESS_GROUP(obj
);
2515 found
= g_list_find_custom(group
->items
, (gpointer
)name
,
2516 addressbook_obj_name_compare
);
2517 if (found
) return ADDRESS_OBJECT(found
->data
);
2518 } else if (obj
->type
== ADDR_FOLDER
) {
2519 AddressFolder
*folder
= ADDRESS_FOLDER(obj
);
2521 found
= g_list_find_custom(folder
->items
, (gpointer
)name
,
2522 addressbook_obj_name_compare
);
2523 if (found
) return ADDRESS_OBJECT(found
->data
);
2524 } else if (obj
->type
== ADDR_ITEM
) {
2525 if (!addressbook_obj_name_compare(obj
, name
)) return obj
;
2531 static AddressItem
*addressbook_parse_item(XMLFile
*file
)
2537 item
= mgu_create_address();
2538 ADDRESS_OBJECT(item
)->type
= ADDR_ITEM
;
2540 level
= file
->level
;
2542 while (xml_parse_next_tag(file
) == 0) {
2543 if (file
->level
< level
) return item
;
2544 if (file
->level
== level
) break;
2546 element
= xml_get_element(file
);
2548 if (xml_compare_tag(file
, "name")) {
2549 item
->name
= element
;
2550 } else if (xml_compare_tag(file
, "address")) {
2551 item
->address
= element
;
2552 } else if (xml_compare_tag(file
, "remarks")) {
2553 item
->remarks
= element
;
2556 if (xml_parse_next_tag(file
) < 0) break;
2557 if (file
->level
!= level
) break;
2560 g_warning("addressbook_parse_item(): Parse error\n");
2561 mgu_free_address( item
);
2564 void addressbook_export_to_file(void)
2569 if (!addrbook
.ctree
) return;
2571 debug_print(_("Exporting addressbook to file..."));
2573 path
= g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S
, ADDRESS_BOOK
, NULL
);
2574 if ((pfile
= prefs_write_open(path
)) == NULL
) {
2580 fprintf(pfile
->fp
, "<?xml version=\"1.0\" encoding=\"%s\"?>\n",
2581 conv_get_current_charset_str());
2582 fputs("<addressbook>\n\n", pfile
->fp
);
2584 addressbook_xml_recursive_write(NULL
, pfile
->fp
);
2586 fputs("</addressbook>\n", pfile
->fp
);
2588 if (prefs_write_close(pfile
) < 0) {
2589 g_warning(_("failed to write addressbook data.\n"));
2593 debug_print(_("done.\n"));
2596 /* Most part of this function was taken from gtk_ctree_pre_recursive() and
2597 gtk_ctree_post_recursive(). */
2598 static void addressbook_xml_recursive_write(GtkCTreeNode
*node
, FILE *fp
)
2604 work
= GTK_CTREE_ROW(node
)->children
;
2605 addressbook_node_write_begin(node
, fp
);
2607 work
= GTK_CTREE_NODE(GTK_CLIST(addrbook
.ctree
)->row_list
);
2610 tmp
= GTK_CTREE_ROW(work
)->sibling
;
2611 addressbook_xml_recursive_write(work
, fp
);
2616 addressbook_node_write_end(node
, fp
);
2619 static void addressbook_node_write_begin(GtkCTreeNode
*node
, FILE *fp
)
2623 obj
= gtk_ctree_node_get_row_data(GTK_CTREE(addrbook
.ctree
), node
);
2624 g_return_if_fail(obj
!= NULL
);
2626 if (obj
->type
== ADDR_FOLDER
) {
2627 AddressFolder
*folder
= ADDRESS_FOLDER(obj
);
2629 if (GTK_CTREE_ROW(node
)->level
== 1) {
2630 fprintf(fp
, "<%s>\n", folder
->name
);
2632 tab_indent_out(fp
, GTK_CTREE_ROW(node
)->level
- 1);
2633 fputs("<folder name=\"", fp
);
2634 xml_file_put_escape_str(fp
, folder
->name
);
2637 } else if (obj
->type
== ADDR_GROUP
) {
2638 AddressGroup
*group
= ADDRESS_GROUP(obj
);
2640 tab_indent_out(fp
, GTK_CTREE_ROW(node
)->level
- 1);
2641 fputs("<group name=\"", fp
);
2642 xml_file_put_escape_str(fp
, group
->name
);
2647 static void addressbook_node_write_end(GtkCTreeNode
*node
, FILE *fp
)
2651 obj
= gtk_ctree_node_get_row_data(GTK_CTREE(addrbook
.ctree
), node
);
2652 g_return_if_fail(obj
!= NULL
);
2654 if (obj
->type
== ADDR_FOLDER
) {
2655 AddressFolder
*folder
= ADDRESS_FOLDER(obj
);
2657 addressbook_write_items(fp
, folder
->items
,
2658 GTK_CTREE_ROW(node
)->level
);
2660 if (GTK_CTREE_ROW(node
)->level
== 1) {
2661 fprintf(fp
, "</%s>\n\n", folder
->name
);
2663 tab_indent_out(fp
, GTK_CTREE_ROW(node
)->level
- 1);
2664 fputs("</folder>\n", fp
);
2666 } else if (obj
->type
== ADDR_GROUP
) {
2667 AddressGroup
*group
= ADDRESS_GROUP(obj
);
2669 addressbook_write_items(fp
, group
->items
,
2670 GTK_CTREE_ROW(node
)->level
);
2672 tab_indent_out(fp
, GTK_CTREE_ROW(node
)->level
- 1);
2673 fputs("</group>\n", fp
);
2675 else if (obj
->type
== ADDR_VCARD
) {
2676 AddressVCard
*vcard
= ADDRESS_VCARD(obj
);
2677 addressbook_write_vcard( fp
, vcard
, GTK_CTREE_ROW(node
)->level
);
2680 else if (obj
->type
== ADDR_JPILOT
) {
2681 AddressJPilot
*jpilot
= ADDRESS_JPILOT(obj
);
2682 addressbook_write_jpilot( fp
, jpilot
, GTK_CTREE_ROW(node
)->level
);
2686 else if (obj
->type
== ADDR_LDAP
) {
2687 AddressLDAP
*ldap
= ADDRESS_LDAP(obj
);
2688 addressbook_write_ldap( fp
, ldap
, GTK_CTREE_ROW(node
)->level
);
2693 static void addressbook_write_items(FILE *fp
, GList
*items
, guint level
)
2697 for (; items
!= NULL
; items
= items
->next
) {
2698 if (ADDRESS_OBJECT_TYPE(items
->data
) == ADDR_ITEM
) {
2699 item
= ADDRESS_ITEM(items
->data
);
2701 tab_indent_out(fp
, level
);
2702 fputs("<item>\n", fp
);
2704 tab_indent_out(fp
, level
+ 1);
2705 fputs("<name>", fp
);
2706 xml_file_put_escape_str(fp
, item
->name
);
2707 fputs("</name>\n", fp
);
2709 tab_indent_out(fp
, level
+ 1);
2710 fputs("<address>", fp
);
2711 xml_file_put_escape_str(fp
, item
->address
);
2712 fputs("</address>\n", fp
);
2714 tab_indent_out(fp
, level
+ 1);
2715 fputs("<remarks>", fp
);
2716 xml_file_put_escape_str(fp
, item
->remarks
);
2717 fputs("</remarks>\n", fp
);
2719 tab_indent_out(fp
, level
);
2720 fputs("</item>\n", fp
);
2725 static void tab_indent_out(FILE *fp
, guint level
)
2729 for (i
= 0; i
< level
; i
++)
2733 static void key_pressed(GtkWidget
*widget
, GdkEventKey
*event
, gpointer data
)
2735 if (event
&& event
->keyval
== GDK_Escape
)
2736 addressbook_close();
2739 static gint
addressbook_list_compare_func(GtkCList
*clist
,
2743 AddressObject
*obj1
= ((GtkCListRow
*)ptr1
)->data
;
2744 AddressObject
*obj2
= ((GtkCListRow
*)ptr2
)->data
;
2745 gchar
*name1
, *name2
;
2748 if (obj1
->type
== ADDR_ITEM
)
2749 name1
= ADDRESS_ITEM(obj1
)->name
;
2750 else if (obj1
->type
== ADDR_GROUP
)
2751 name1
= ADDRESS_GROUP(obj1
)->name
;
2752 else if (obj1
->type
== ADDR_FOLDER
)
2753 name1
= ADDRESS_FOLDER(obj1
)->name
;
2754 else if (obj1
->type
== ADDR_VCARD
)
2755 name1
= ADDRESS_VCARD(obj1
)->name
;
2757 else if (obj1
->type
== ADDR_JPILOT
)
2758 name1
= ADDRESS_JPILOT(obj1
)->name
;
2759 else if (obj1
->type
== ADDR_CATEGORY
)
2760 name1
= ADDRESS_CATEGORY(obj1
)->name
;
2763 else if (obj1
->type
== ADDR_LDAP
)
2764 name1
= ADDRESS_LDAP(obj1
)->name
;
2772 if (obj2
->type
== ADDR_ITEM
)
2773 name2
= ADDRESS_ITEM(obj2
)->name
;
2774 else if (obj2
->type
== ADDR_GROUP
)
2775 name2
= ADDRESS_GROUP(obj2
)->name
;
2776 else if (obj2
->type
== ADDR_FOLDER
)
2777 name2
= ADDRESS_FOLDER(obj2
)->name
;
2778 else if (obj2
->type
== ADDR_VCARD
)
2779 name2
= ADDRESS_VCARD(obj2
)->name
;
2781 else if (obj2
->type
== ADDR_JPILOT
)
2782 name2
= ADDRESS_JPILOT(obj2
)->name
;
2783 else if (obj2
->type
== ADDR_CATEGORY
)
2784 name2
= ADDRESS_CATEGORY(obj2
)->name
;
2787 else if (obj2
->type
== ADDR_LDAP
)
2788 name2
= ADDRESS_LDAP(obj2
)->name
;
2796 return (name2
!= NULL
);
2800 return strcasecmp(name1
, name2
);
2803 static gint
addressbook_obj_name_compare(gconstpointer a
, gconstpointer b
)
2805 const AddressObject
*obj
= a
;
2806 const gchar
*name
= b
;
2808 if (!obj
|| !name
) return -1;
2810 if (obj
->type
== ADDR_GROUP
) {
2811 AddressGroup
*group
= ADDRESS_GROUP(obj
);
2815 return strcasecmp(group
->name
, name
);
2816 } else if (obj
->type
== ADDR_FOLDER
) {
2817 AddressFolder
*folder
= ADDRESS_FOLDER(obj
);
2821 return strcasecmp(folder
->name
, name
);
2823 else if (obj
->type
== ADDR_VCARD
) {
2824 AddressVCard
*vcard
= ADDRESS_VCARD(obj
);
2828 return strcasecmp(vcard
->name
, name
);
2831 else if (obj
->type
== ADDR_JPILOT
) {
2832 AddressJPilot
*jpilot
= ADDRESS_JPILOT(obj
);
2836 return strcasecmp(jpilot
->name
, name
);
2838 else if (obj
->type
== ADDR_CATEGORY
) {
2839 AddressCategory
*category
= ADDRESS_CATEGORY(obj
);
2840 if (!category
->name
)
2843 return strcasecmp(category
->name
, name
);
2847 else if (obj
->type
== ADDR_LDAP
) {
2848 AddressLDAP
*server
= ADDRESS_LDAP(obj
);
2852 return strcasecmp(server
->name
, name
);
2855 else if (obj
->type
== ADDR_ITEM
) {
2856 AddressItem
*item
= ADDRESS_ITEM(obj
);
2860 return strcasecmp(item
->name
, name
);
2865 static AddressVCard
*addressbook_parse_vcard(XMLFile
*file
) {
2866 AddressVCard
*item
= NULL
;
2869 gchar
*name
, *value
;
2871 vcf
= vcard_create();
2872 attr
= xml_get_current_tag_attr( file
);
2874 name
= ((XMLAttr
*)attr
->data
)->name
;
2875 value
= ((XMLAttr
*)attr
->data
)->value
;
2876 if( strcmp( name
, "name" ) == 0 ) {
2877 vcard_set_name( vcf
, value
);
2879 else if( strcmp( name
, "file" ) == 0) {
2880 vcard_set_file( vcf
, value
);
2882 attr
= g_list_next( attr
);
2886 if( xml_parse_next_tag( file
) >= 0 ) {
2887 if( vcard_validate( vcf
) ) {
2888 item
= g_new( AddressVCard
, 1 );
2889 ADDRESS_OBJECT(item
)->type
= ADDR_VCARD
;
2890 item
->name
= g_strdup( vcf
->name
);
2891 item
->cardFile
= vcf
;
2897 // Must be an invalid tag or data.
2898 g_warning( "addressbook_parse_vcard(): Parse error\n");
2905 static void addressbook_write_vcard( FILE *fp
, AddressVCard
*vcard
, guint level
) {
2906 VCardFile
*cardFile
= vcard
->cardFile
;
2908 tab_indent_out(fp
, 1);
2909 fputs("<vcard ", fp
);
2910 fputs("name=\"", fp
);
2911 xml_file_put_escape_str(fp
, cardFile
->name
);
2913 fputs(" file=\"", fp
);
2914 xml_file_put_escape_str(fp
, cardFile
->path
);
2921 static AddressJPilot
*addressbook_parse_jpilot(XMLFile
*file
) {
2922 AddressJPilot
*item
= NULL
;
2925 gchar
*name
, *value
;
2927 jpf
= jpilot_create();
2928 attr
= xml_get_current_tag_attr( file
);
2930 name
= ((XMLAttr
*)attr
->data
)->name
;
2931 value
= ((XMLAttr
*)attr
->data
)->value
;
2932 if( strcmp( name
, "name" ) == 0 ) {
2933 jpilot_set_name( jpf
, value
);
2935 else if( strcmp( name
, "file" ) == 0 ) {
2936 jpilot_set_file( jpf
, value
);
2938 else if( strcmp( name
, "custom-1" ) == 0 ) {
2939 jpilot_add_custom_label( jpf
, value
);
2941 else if( strcmp( name
, "custom-2" ) == 0 ) {
2942 jpilot_add_custom_label( jpf
, value
);
2944 else if( strcmp( name
, "custom-3" ) == 0 ) {
2945 jpilot_add_custom_label( jpf
, value
);
2947 else if( strcmp( name
, "custom-4" ) == 0 ) {
2948 jpilot_add_custom_label( jpf
, value
);
2950 attr
= g_list_next( attr
);
2954 if( xml_parse_next_tag( file
) >= 0 ) {
2955 if( jpilot_validate( jpf
) ) {
2956 item
= g_new( AddressJPilot
, 1 );
2957 ADDRESS_OBJECT(item
)->type
= ADDR_JPILOT
;
2958 item
->name
= g_strdup( jpf
->name
);
2959 item
->pilotFile
= jpf
;
2965 // Must be an invalid tag or data.
2966 g_warning( "addressbook_parse_jpilot(): Parse error\n");
2973 static void addressbook_write_jpilot( FILE *fp
, AddressJPilot
*jpilot
, guint level
) {
2974 JPilotFile
*pilotFile
= jpilot
->pilotFile
;
2978 GList
*customLbl
= jpilot_get_custom_labels( pilotFile
);
2979 tab_indent_out(fp
, 1);
2980 fputs("<jpilot ", fp
);
2981 fputs("name=\"", fp
);
2982 xml_file_put_escape_str(fp
, pilotFile
->name
);
2983 fputs("\" file=\"", fp
);
2984 xml_file_put_escape_str(fp
, pilotFile
->path
);
2990 fprintf( fp
, "custom-%d=\"", ind
);
2991 xml_file_put_escape_str( fp
, node
->data
);
2994 node
= g_list_next( node
);
3001 static void addressbook_new_vcard_cb( gpointer data
, guint action
, GtkWidget
*widget
) {
3002 AddressVCard
*vcard
;
3004 if( addrbook
.selected
!= addrbook
.vcard
) return;
3005 vcard
= addressbook_edit_vcard( NULL
);
3007 addressbook_add_object( addrbook
.selected
, ADDRESS_OBJECT(vcard
) );
3008 if( addrbook
.selected
== addrbook
.opened
) {
3009 addrbook
.open_folder
= TRUE
;
3010 gtk_ctree_select( GTK_CTREE(addrbook
.ctree
), addrbook
.opened
);
3015 static void addressbook_vcard_show_message( VCardFile
*vcf
) {
3016 *addressbook_msgbuf
= '\0';
3018 if( vcf
->retVal
== MGU_SUCCESS
) {
3019 sprintf( addressbook_msgbuf
, "%s", vcf
->name
);
3022 sprintf( addressbook_msgbuf
, "%s: %s", vcf
->name
, mgu_error2string( vcf
->retVal
) );
3025 addressbook_status_show( addressbook_msgbuf
);
3029 static void addressbook_new_jpilot_cb( gpointer data
, guint action
, GtkWidget
*widget
) {
3030 AddressJPilot
*jpilot
;
3032 if( addrbook
.selected
!= addrbook
.jpilot
) return;
3033 if( ! _have_pilot_library_
) return;
3034 jpilot
= addressbook_edit_jpilot( NULL
);
3036 addressbook_add_object( addrbook
.selected
, ADDRESS_OBJECT(jpilot
) );
3037 if( addrbook
.selected
== addrbook
.opened
) {
3038 addrbook
.open_folder
= TRUE
;
3039 gtk_ctree_select( GTK_CTREE(addrbook
.ctree
), addrbook
.opened
);
3044 static void addressbook_jpilot_show_message( JPilotFile
*jpf
) {
3045 *addressbook_msgbuf
= '\0';
3047 if( jpf
->retVal
== MGU_SUCCESS
) {
3048 sprintf( addressbook_msgbuf
, "%s", jpf
->name
);
3051 sprintf( addressbook_msgbuf
, "%s: %s", jpf
->name
, mgu_error2string( jpf
->retVal
) );
3054 addressbook_status_show( addressbook_msgbuf
);
3060 static void addressbook_new_ldap_cb( gpointer data
, guint action
, GtkWidget
*widget
) {
3063 if( addrbook
.selected
!= addrbook
.ldap
) return;
3064 if( ! _have_ldap_library_
) return;
3065 ldapi
= addressbook_edit_ldap( NULL
);
3067 addressbook_add_object( addrbook
.selected
, ADDRESS_OBJECT(ldapi
) );
3068 if( addrbook
.selected
== addrbook
.opened
) {
3069 addrbook
.open_folder
= TRUE
;
3070 gtk_ctree_select( GTK_CTREE(addrbook
.ctree
), addrbook
.opened
);
3075 static AddressLDAP
*addressbook_parse_ldap(XMLFile
*file
) {
3076 AddressLDAP
*item
= NULL
;
3077 SyldapServer
*server
;
3079 gchar
*name
, *value
;
3082 server
= syldap_create();
3083 attr
= xml_get_current_tag_attr( file
);
3085 name
= ((XMLAttr
*)attr
->data
)->name
;
3086 value
= ((XMLAttr
*)attr
->data
)->value
;
3087 ivalue
= atoi( value
);
3088 if( strcmp( name
, "name" ) == 0 ) {
3089 syldap_set_name( server
, value
);
3091 else if( strcmp( name
, "host" ) == 0 ) {
3092 syldap_set_host( server
, value
);
3094 else if( strcmp( name
, "port" ) == 0 ) {
3095 syldap_set_port( server
, ivalue
);
3097 else if( strcmp( name
, "base-dn" ) == 0 ) {
3098 syldap_set_base_dn( server
, value
);
3100 else if( strcmp( name
, "bind-dn" ) == 0 ) {
3101 syldap_set_bind_dn( server
, value
);
3103 else if( strcmp( name
, "bind-pass" ) == 0 ) {
3104 syldap_set_bind_password( server
, value
);
3106 else if( strcmp( name
, "criteria" ) == 0 ) {
3107 syldap_set_search_criteria( server
, value
);
3109 else if( strcmp( name
, "max-entry" ) == 0 ) {
3110 syldap_set_max_entries( server
, ivalue
);
3112 else if( strcmp( name
, "timeout" ) == 0 ) {
3113 syldap_set_timeout( server
, ivalue
);
3115 attr
= g_list_next( attr
);
3119 if( xml_parse_next_tag( file
) >= 0 ) {
3120 item
= g_new( AddressLDAP
, 1 );
3121 ADDRESS_OBJECT(item
)->type
= ADDR_LDAP
;
3122 item
->name
= g_strdup( server
->name
);
3123 item
->ldapServer
= server
;
3128 // Must be an invalid tag or data.
3129 g_warning( "addressbook_parse_ldap(): Parse error\n");
3130 syldap_free( server
);
3136 static void addressbook_write_ldap( FILE *fp
, AddressLDAP
*ldapi
, guint level
) {
3137 SyldapServer
*server
= ldapi
->ldapServer
;
3139 tab_indent_out(fp
, 1);
3140 fputs("<server ", fp
);
3141 fputs("name=\"", fp
);
3142 xml_file_put_escape_str(fp
, server
->name
);
3143 fputs("\" host=\"", fp
);
3144 xml_file_put_escape_str(fp
, server
->hostName
);
3145 fprintf( fp
, "\" port=\"%d", server
->port
);
3146 fputs("\" base-dn=\"", fp
);
3147 xml_file_put_escape_str(fp
, server
->baseDN
);
3148 fputs("\" bind-dn=\"", fp
);
3149 xml_file_put_escape_str(fp
, server
->bindDN
);
3150 fputs("\" bind-pass=\"", fp
);
3151 xml_file_put_escape_str(fp
, server
->bindPass
);
3152 fputs("\" criteria=\"", fp
);
3153 xml_file_put_escape_str(fp
, server
->searchCriteria
);
3154 fprintf( fp
, "\" max-entry=\"%d", server
->maxEntries
);
3155 fprintf( fp
, "\" timeout=\"%d", server
->timeOut
);
3156 fputs("\" />\n", fp
);
3160 static void addressbook_ldap_show_message( SyldapServer
*svr
) {
3161 *addressbook_msgbuf
= '\0';
3163 if( svr
->busyFlag
) {
3164 sprintf( addressbook_msgbuf
, "%s: %s", svr
->name
, ADDRESSBOOK_LDAP_BUSYMSG
);
3167 if( svr
->retVal
== MGU_SUCCESS
) {
3168 sprintf( addressbook_msgbuf
, "%s", svr
->name
);
3171 sprintf( addressbook_msgbuf
, "%s: %s", svr
->name
, mgu_error2string( svr
->retVal
) );
3175 addressbook_status_show( addressbook_msgbuf
);
3178 static gint
ldapsearch_callback( SyldapServer
*sls
) {
3179 GtkCTree
*ctree
= GTK_CTREE(addrbook
.ctree
);
3182 if( sls
== NULL
) return;
3183 if( ! addrbook
.selected
) return;
3184 if( GTK_CTREE_ROW( addrbook
.selected
)->level
== 1 ) return;
3186 obj
= gtk_ctree_node_get_row_data( ctree
, addrbook
.selected
);
3187 if( obj
== NULL
) return;
3188 if( obj
->type
== ADDR_LDAP
) {
3189 AddressLDAP
*ldapi
= ADDRESS_LDAP(obj
);
3190 SyldapServer
*server
= ldapi
->ldapServer
;
3191 if( server
== sls
) {
3192 if( ! _have_ldap_library_
) return;
3194 gtk_widget_show_all(addrbook
.window
);
3195 ADDRESS_LDAP(obj
)->items
= syldap_get_address_list( sls
);
3196 addressbook_set_clist( obj
);
3197 addressbook_ldap_show_message( sls
);
3198 gtk_widget_show_all(addrbook
.window
);
3205 * Lookup button handler.
3207 static void addressbook_lup_clicked( GtkButton
*button
, gpointer data
) {
3208 GtkCTree
*ctree
= GTK_CTREE(addrbook
.ctree
);
3213 SyldapServer
*server
;
3216 sLookup
= gtk_editable_get_chars( GTK_EDITABLE(addrbook
.entry
), 0, -1 );
3217 g_strchomp( sLookup
);
3219 if( ! addrbook
.selected
) return;
3220 if( GTK_CTREE_ROW( addrbook
.selected
)->level
== 1 ) return;
3222 obj
= gtk_ctree_node_get_row_data( ctree
, addrbook
.selected
);
3223 if( obj
== NULL
) return;
3226 if( obj
->type
== ADDR_LDAP
) {
3227 ldapi
= ADDRESS_LDAP(obj
);
3228 server
= ldapi
->ldapServer
;
3230 if( ! _have_ldap_library_
) return;
3231 syldap_cancel_read( server
);
3232 if( *sLookup
== '\0' || strlen( sLookup
) < 1 ) return;
3233 syldap_set_search_value( server
, sLookup
);
3234 syldap_set_callback( server
, ldapsearch_callback
);
3235 syldap_read_data_th( server
);
3236 addressbook_ldap_show_message( server
);
3246 gboolean init
; /* if FALSE should init jump buffer */
3247 GtkCTreeNode
*node_found
; /* match (can be used to backtrack folders) */
3248 AddressObject
*addr_found
; /* match */
3249 int level
; /* current recursion level (0 is root level) */
3250 jmp_buf jumper
; /* jump buffer */
3254 FindObject ancestor
;
3255 const gchar
*groupname
;
3259 FindObject ancestor
;
3261 const gchar
*address
;
3265 FindObject ancestor
;
3269 typedef gboolean (*ADDRESSBOOK_TRAVERSE_FUNC
)(AddressObject
*node
, gpointer data
);
3273 static gboolean
traverse_find_group_by_name(AddressObject
*ao
, FindGroup
*find
)
3275 AddressFolder
*folder
;
3276 AddressGroup
*group
;
3278 /* a group or folder: both are groups */
3279 if (ADDRESS_OBJECT_TYPE(ao
) == ADDR_GROUP
) {
3280 group
= ADDRESS_GROUP(ao
);
3281 if (0 == g_strcasecmp(group
->name
, find
->groupname
)) {
3285 else if (ADDRESS_OBJECT_TYPE(ao
) == ADDR_FOLDER
) {
3286 folder
= ADDRESS_FOLDER(ao
);
3287 if (0 == g_strcasecmp(folder
->name
, find
->groupname
)) {
3294 static gboolean
traverse_find_name_email(AddressObject
*ao
, FindAddress
*find
)
3297 if (ADDRESS_OBJECT_TYPE(ao
) == ADDR_ITEM
) {
3298 gboolean nmatch
= FALSE
, amatch
= FALSE
;
3299 item
= ADDRESS_ITEM(ao
);
3301 * o only match at the first characters in item strings
3302 * o match either name or address */
3303 if (find
->name
&& item
->name
) {
3304 nmatch
= item
->name
== strcasestr(item
->name
, find
->name
);
3306 if (find
->address
&& item
->address
) {
3307 amatch
= item
->address
== strcasestr(item
->address
, find
->address
);
3309 return nmatch
|| amatch
;
3314 static gboolean
traverse_find_all_groups(AddressObject
*ao
, FindAllGroups
*find
)
3316 /* NOTE: added strings come from the address book. should perhaps
3317 * strdup() them, especially if the address book is invalidated */
3318 if (ADDRESS_OBJECT_TYPE(ao
) == ADDR_FOLDER
) {
3319 AddressFolder
*folder
= ADDRESS_FOLDER(ao
);
3320 find
->grouplist
= g_list_insert_sorted(find
->grouplist
, (gpointer
) folder
->name
, (GCompareFunc
) g_strcasecmp
);
3322 else if (ADDRESS_OBJECT_TYPE(ao
) == ADDR_GROUP
) {
3323 AddressGroup
*group
= ADDRESS_GROUP(ao
);
3324 find
->grouplist
= g_list_insert_sorted(find
->grouplist
, (gpointer
) group
->name
, (GCompareFunc
) g_strcasecmp
);
3329 /* addressbook_traverse() - traverses all address objects stored in the address book.
3330 * for some reason gtkctree's recursive tree functions don't allow a premature return,
3331 * which is what we need if we need to enumerate the tree and check for a condition
3332 * and then skipping other nodes. */
3333 static AddressObject
*addressbook_traverse(GtkCTreeNode
*node
, ADDRESSBOOK_TRAVERSE_FUNC func
, FindObject
*data
, int level
)
3335 GtkCTreeNode
*current
, *tmp
;
3338 if (data
->init
== FALSE
) {
3339 /* initialize non-local exit */
3342 /* HANDLE NON-LOCAL EXIT */
3343 if (setjmp(data
->jumper
)) {
3344 return data
->addr_found
;
3348 /* actual recursive code */
3350 current
= GTK_CTREE_NODE(GTK_CLIST(addrbook
.ctree
)->row_list
);
3357 tmp
= GTK_CTREE_ROW(current
)->sibling
;
3358 ao
= (AddressObject
*) gtk_ctree_node_get_row_data(GTK_CTREE(addrbook
.ctree
), current
);
3362 next
= (ADDRESS_OBJECT_TYPE(ao
) == ADDR_FOLDER
) ?
3363 g_list_first(((ADDRESS_FOLDER(ao
))->items
)) :
3364 (ADDRESS_OBJECT_TYPE(ao
) == ADDR_GROUP
) ?
3365 g_list_first(((ADDRESS_GROUP(ao
))->items
)) : NULL
;
3368 /* NOTE: first iteration of the root calls callback for the tree
3369 * node, other iterations call callback for the address book items */
3370 if (func(ao
, data
)) {
3372 data
->node_found
= current
;
3373 data
->addr_found
= ao
;
3374 longjmp(data
->jumper
, 1);
3376 /* ctree node only stores folders and groups. now descend into
3377 * address object data, searching for address items. */
3378 for ( ; next
&& ADDRESS_OBJECT_TYPE((next
->data
)) != ADDR_ITEM
3379 ; next
= g_list_next(next
))
3381 ao
= next
? (AddressObject
*) next
->data
: NULL
;
3382 next
= next
? g_list_next(next
) : NULL
;
3385 /* check the children (if level permits) */
3386 if (level
== -1 || data
->level
< level
) {
3387 current
= GTK_CTREE_ROW(current
)->children
;
3390 addressbook_traverse(current
, func
, data
, level
);
3394 /* check the siblings */
3400 static GtkCTreeNode
*addressbook_get_group_node(const gchar
*name
)
3402 FindGroup fg
= { { FALSE
, NULL
, NULL
}, NULL
};
3403 fg
.groupname
= name
;
3404 addressbook_traverse(NULL
, (void *)traverse_find_group_by_name
, (FindObject
*)&fg
, -1);
3405 return fg
.ancestor
.node_found
;
3408 static void addressbook_free_item(AddressItem
*item
)
3411 if (item
->name
) g_free(item
->name
);
3412 if (item
->address
) g_free(item
->address
);
3413 if (item
->remarks
) g_free(item
->remarks
);
3418 static AddressItem
*addressbook_alloc_item(const gchar
*name
, const gchar
*address
, const gchar
*remarks
)
3420 AddressItem
*item
= g_new0(AddressItem
, 1);
3423 item
->obj
.type
= ADDR_ITEM
;
3424 if (item
->name
= g_strdup(name
))
3425 if (item
->address
= g_strdup(address
)) {
3427 item
->remarks
= g_strdup(remarks
);
3432 addressbook_free_item(item
);
3438 /* public provisional API */
3440 /* addressbook_access() - should be called before using any of the following apis. it
3441 * reloads the address book. */
3442 void addressbook_access(void)
3444 log_message("accessing address book\n");
3445 if (!addrbook
.window
) {
3446 addressbook_create(FALSE
);
3447 addressbook_read_file();
3448 addrbook
.open_folder
= TRUE
;
3449 gtk_ctree_select(GTK_CTREE(addrbook
.ctree
), GTK_CTREE_NODE(GTK_CLIST(addrbook
.ctree
)->row_list
));
3453 /* addressbook_unaccess() - should only be called after changing the address book's
3455 void addressbook_unaccess(void)
3457 log_message("unaccessing address book\n");
3458 addressbook_export_to_file();
3459 invalidate_address_completion();
3462 const gchar
*addressbook_get_personal_folder_name(void)
3464 return _("Personal addresses"); /* human readable */
3467 const gchar
*addressbook_get_common_folder_name(void)
3469 return _("Common addresses"); /* human readable */
3472 /* addressbook_find_group_by_name() - finds a group (folder or group) by
3474 AddressObject
*addressbook_find_group_by_name(const gchar
*name
)
3476 FindGroup fg
= { { FALSE
, NULL
, NULL
} };
3479 /* initialize obj members */
3480 fg
.groupname
= name
;
3481 ao
= addressbook_traverse(NULL
,
3482 (ADDRESSBOOK_TRAVERSE_FUNC
)traverse_find_group_by_name
,
3483 (FindObject
*)&fg
, -1);
3487 /* addressbook_find_contact() - finds an address item by either name or address
3488 * or both. the comparison is done on the first few characters of the strings */
3489 AddressObject
*addressbook_find_contact(const gchar
*name
, const gchar
*address
)
3491 FindAddress fa
= { { FALSE
, NULL
, NULL
} };
3495 fa
.address
= address
;
3496 ao
= addressbook_traverse(NULL
, (ADDRESSBOOK_TRAVERSE_FUNC
)traverse_find_name_email
,
3497 (FindObject
*)&fa
, -1);
3501 /* addressbook_get_group_list() - returns a list of strings with group names (both
3502 * groups and folders). free the list using g_list_free(). note that another
3503 * call may invalidate the returned list */
3504 GList
*addressbook_get_group_list(void)
3506 FindAllGroups fag
= { { FALSE
, NULL
, NULL
}, NULL
};
3507 addressbook_traverse(NULL
, (ADDRESSBOOK_TRAVERSE_FUNC
)traverse_find_all_groups
,
3508 (FindObject
*)&fag
, -1);
3509 return fag
.grouplist
;
3512 /* addressbook_add_contact() - adds a contact to the address book. returns 1
3513 * if succesful else error */
3514 gint
addressbook_add_contact(const gchar
*group
, const gchar
*name
, const gchar
*address
,
3515 const gchar
*remarks
)
3519 FindAddress fa
= { { FALSE
, NULL
, NULL
} };
3521 /* a healthy mix of hiro's and my code */
3522 if (name
== NULL
|| strlen(name
) == 0
3523 || address
== NULL
|| strlen(address
) == 0
3524 || group
== NULL
|| strlen(group
) == 0) {
3527 node
= addressbook_get_group_node(group
);
3532 /* check if it's already in this group */
3534 fa
.address
= address
;
3536 if (addressbook_traverse(node
, (gpointer
)traverse_find_name_email
, (gpointer
)&fa
, 0)) {
3537 log_message("address <%s> already in %s\n", address
, group
);
3541 item
= addressbook_alloc_item(name
, address
, remarks
);
3546 if (!addressbook_add_object(node
, (AddressObject
*)item
)) {
3547 addressbook_free_item(item
);
3551 /* make sure it's updated if selected */
3552 log_message("updating addressbook widgets\n");
3553 addrbook
.open_folder
= TRUE
;
3554 gtk_ctree_select(GTK_CTREE(addrbook
.ctree
), addrbook
.opened
);
3556 /* not saved yet. only after unaccessing the address book */
3560 static void group_object_data_destroy(gchar
*group
)
3575 static void addressbook_destroy_contact(ContactInfo
*ci
)
3577 g_return_if_fail(ci
!= NULL
);
3578 if (ci
->name
) g_free(ci
->name
);
3579 if (ci
->address
) g_free(ci
->address
);
3580 if (ci
->remarks
) g_free(ci
->remarks
);
3584 static ContactInfo
*addressbook_new_contact(const gchar
*name
, const gchar
*address
, const gchar
*remarks
)
3586 ContactInfo
*ci
= g_new0(ContactInfo
, 1);
3588 g_return_val_if_fail(ci
!= NULL
, NULL
);
3589 g_return_val_if_fail(address
!= NULL
, NULL
); /* address should be valid */
3590 ci
->name
= name
? g_strdup(name
) : NULL
;
3591 ci
->address
= g_strdup(address
);
3592 ci
->remarks
= remarks
? g_strdup(remarks
) : NULL
;
3593 if (NULL
== ci
->address
) {
3594 addressbook_destroy_contact(ci
);
3600 static void addressbook_group_menu_selected(GtkMenuItem
*menuitem
,
3603 const gchar
*group_name
= (const gchar
*) gtk_object_get_data(GTK_OBJECT(menuitem
),
3607 g_warning("%s(%d) - invalid group name\n", __FILE__
, __LINE__
);
3610 g_return_if_fail(group_name
!= NULL
);
3612 g_message("selected group %s from menu\n", group_name
);
3613 g_message("selected %s <%s>\n", data
->name
? data
->name
: data
->address
, data
->address
);
3615 addressbook_access();
3616 addressbook_add_contact(group_name
, data
->name
? data
->name
: data
->address
,
3617 data
->address
, data
->remarks
? data
->remarks
: data
->address
);
3618 addressbook_unaccess();
3623 /* addressbook_add_contact_by_meny() - launches menu with group items. submenu may be
3624 * the menu item in the parent menu, or NULL for a normal right-click context menu */
3625 gboolean
addressbook_add_submenu(GtkWidget
*submenu
,
3627 const gchar
*address
,
3628 const gchar
*remarks
)
3630 GtkWidget
*menu
, *menuitem
;
3631 GList
*groups
, *tmp
;
3634 ci
= addressbook_new_contact(name
, address
, remarks
);
3635 g_return_val_if_fail(ci
!= NULL
, FALSE
);
3637 addressbook_access();
3638 groups
= addressbook_get_group_list();
3639 g_return_val_if_fail(groups
!= NULL
, (addressbook_destroy_contact(ci
), FALSE
));
3641 menu
= gtk_menu_new();
3642 g_return_val_if_fail(menu
!= NULL
, (g_list_free(groups
), addressbook_destroy_contact(ci
), FALSE
));
3644 /* add groups to menu */
3645 for (tmp
= g_list_first(groups
); tmp
!= NULL
; tmp
= g_list_next(tmp
)) {
3646 const gchar
*display_name
;
3647 gchar
*original_name
= (gchar
*) tmp
->data
;
3648 gboolean addItem
= TRUE
;
3650 if (!g_strcasecmp(original_name
, ADDRESS_TAG_PERSONAL
)) {
3651 display_name
= addressbook_get_personal_folder_name();
3653 else if (!g_strcasecmp(original_name
, ADDRESS_TAG_COMMON
)) {
3654 display_name
= addressbook_get_common_folder_name();
3656 else if( ! g_strcasecmp( original_name
, ADDRESS_TAG_VCARD
) ) {
3660 else if( ! g_strcasecmp( original_name
, ADDRESS_TAG_JPILOT
) ) {
3665 else if( ! g_strcasecmp( original_name
, ADDRESS_TAG_LDAP
) ) {
3670 display_name
= original_name
;
3674 original_name
= g_strdup(original_name
);
3675 menuitem
= gtk_menu_item_new_with_label(display_name
);
3676 /* register the duplicated string pointer as object data,
3677 * so we get the opportunity to free it */
3678 gtk_object_set_data_full(GTK_OBJECT(menuitem
), "group_name",
3680 (GtkDestroyNotify
) group_object_data_destroy
);
3681 gtk_signal_connect(GTK_OBJECT(menuitem
), "activate",
3682 GTK_SIGNAL_FUNC(addressbook_group_menu_selected
),
3684 gtk_menu_append(GTK_MENU(menu
), menuitem
);
3685 gtk_widget_show(menuitem
);
3689 gtk_widget_show(menu
);
3692 gtk_menu_item_set_submenu(GTK_MENU_ITEM(submenu
), menu
);
3693 gtk_widget_set_sensitive(GTK_WIDGET(submenu
), TRUE
);
3696 gtk_widget_grab_focus(GTK_WIDGET(menu
));
3697 gtk_menu_popup(GTK_MENU(menu
), NULL
, NULL
, NULL
, NULL
, 1, GDK_CURRENT_TIME
);
3700 if (groups
) g_list_free(groups
);