2007-07-10 [colin] 2.10.0cvs13
[claws.git] / src / addrclip.c
1 /*
2  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3  * Copyright (C) 2002-2007 Match Grun and the Claws Mail team
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  */
19
20 /*
21  * Contains address clipboard objects and related functions. The address 
22  * clipboard is implemented as a linked list of AddrSelectItem objects. 
23  * The address clipboard offers two groups of functions:
24  *
25  * a) Cut, copy and paste of address item objects (ItemFolder, ItemGroup,
26  *    ItemPerson) into a folder. With this method, we can paste ItemPerson
27  *    objects but not unattached ItemEMail objects into a folder. ItemEMail 
28  *    objects are owned by an ItemPerson object. Any ItemEMail objects that 
29  *    appear in the clipboard are ignored. If an ItemPerson object is found, 
30  *    the ItemPerson *and* ItemEMail objects that it owns are pasted.
31  *
32  * b) Copy and paste of ItemEMail address objects only into (below) 
33  *    ItemPerson objects. All ItemEMail objects which are owned by
34  *    ItemPerson and referenced by ItemGroup objects are pasted. Any
35  *    ItemFolder objects in the clipboard, and any objects owned by
36  *    ItemFolder objects are ignored.
37  *
38  * Objects are inserted to the clipboard by copying (cloning) 
39  * AddrSelectItem objects from the address books selection list to the
40  * clipboard's internal selection list. The clipboard makes use of the
41  * object id's and address cache id's to access objects contained in
42  * the address cache. If the referenced object is not found, it is
43  * ignored. This eliminates the need to delete pointers in multiple
44  * linked lists when an address object is deleted.
45  * 
46  */
47
48 #include <stdio.h>
49 #include <glib.h>
50
51 #include "addrcache.h"
52 #include "addrbook.h"
53 #include "addrselect.h"
54 #include "addrindex.h"
55 #include "addrclip.h"
56
57 /*
58 * Create a clipboard.
59 */
60 AddressClipboard *addrclip_create( void ) {
61         AddressClipboard *clipBoard;
62
63         clipBoard = g_new0( AddressClipboard, 1 );
64         clipBoard->cutFlag = FALSE;
65         clipBoard->objectList = NULL;
66         return clipBoard;
67 }
68
69 /*
70 * Clear clipboard.
71 */
72 void addrclip_clear( AddressClipboard *clipBoard ) {
73         GList *node;
74         AddrSelectItem *item;
75
76         g_return_if_fail( clipBoard != NULL );
77         node = clipBoard->objectList;
78         while( node ) {
79                 item = node->data;
80                 addrselect_item_free( item );
81                 node->data = NULL;
82                 node = g_list_next( node );
83         }
84         g_list_free( clipBoard->objectList );
85         clipBoard->objectList = NULL;
86 }
87
88 /*
89 * Free up a clipboard.
90 */
91 void addrclip_free( AddressClipboard *clipBoard ) {
92         g_return_if_fail( clipBoard != NULL );
93
94         addrclip_clear( clipBoard );
95         clipBoard->cutFlag = FALSE;
96 }
97
98 /*
99 * Setup reference to address index.
100 */
101 void addrclip_set_index(
102         AddressClipboard *clipBoard, AddressIndex *addrIndex )
103 {
104         g_return_if_fail( clipBoard != NULL );
105         g_return_if_fail( addrIndex != NULL );
106         clipBoard->addressIndex = addrIndex;
107 }
108
109 /*
110 * Test whether clipboard is empty.
111 * Enter: clipBoard Clipboard.
112 * Return: TRUE if clipboard is empty.
113 */
114 gboolean addrclip_is_empty( AddressClipboard *clipBoard ) {
115         gboolean retVal = TRUE;
116
117         if( clipBoard ) {
118                 if( clipBoard->objectList ) retVal = FALSE;
119         }
120         return retVal;
121 }
122
123 /*
124 * Add a list of address selection objects to clipbard.
125 * Enter: clipBoard Clipboard.
126 *        addrList  List of address selection objects.
127 */
128 void addrclip_add( AddressClipboard *clipBoard, AddrSelectList *asl ) {
129         GList *node;
130
131         g_return_if_fail( clipBoard != NULL );
132         g_return_if_fail( asl != NULL );
133         node = asl->listSelect;
134         while( node ) {
135                 AddrSelectItem *item, *itemCopy;
136
137                 item = node->data;
138                 itemCopy = addrselect_item_copy( item );
139                 clipBoard->objectList =
140                         g_list_append( clipBoard->objectList, itemCopy );
141                 node = g_list_next( node );
142         }
143 }
144
145 /*
146 * Show clipboard contents.
147 * Enter: clipBoard Clipboard.
148 *        stream    Output stream.
149 */
150 void addrclip_list_show( AddressClipboard *clipBoard, FILE *stream ) {
151         GList *node;
152         AddrItemObject *aio;
153         AddressCache *cache;
154
155         g_return_if_fail( clipBoard != NULL );
156         node = clipBoard->objectList;
157         while( node != NULL ) {
158                 AddrSelectItem *item;
159
160                 item = node->data;
161                 addrselect_item_print( item, stream );
162
163                 cache = addrindex_get_cache( clipBoard->addressIndex, item->cacheID );
164                 aio = addrcache_get_object( cache, item->uid );
165                 if( aio ) {
166                         if( ADDRITEM_TYPE(aio) == ITEMTYPE_PERSON ) {
167                                 addritem_print_item_person( ( ItemPerson * ) aio, stream );
168                         }
169                         else if( ADDRITEM_TYPE(aio) == ITEMTYPE_EMAIL ) {
170                                 addritem_print_item_email( ( ItemEMail * ) aio, stream );
171                         }
172                         else if( ADDRITEM_TYPE(aio) == ITEMTYPE_GROUP ) {
173                                 addritem_print_item_group( ( ItemGroup * ) aio, stream );
174                         }
175                         else if( ADDRITEM_TYPE(aio) == ITEMTYPE_FOLDER ) {
176                                 addritem_print_item_folder( ( ItemFolder * ) aio, stream );
177                         }
178                 }
179                 node = g_list_next( node );
180         }
181 }
182
183 /* Pasted address pointers */
184 typedef struct _AddrClip_EMail_ AddrClip_EMail;
185 struct _AddrClip_EMail_ {
186         ItemEMail *original;
187         ItemEMail *copy;
188 };
189
190 /*
191  * Free up specified list of addresses.
192  */
193 static void addrclip_free_copy_list( GList *copyList ) {
194         GList *node;
195
196         node = copyList;
197         while( node ) {
198                 AddrClip_EMail *em = node->data;
199                 em->original = NULL;
200                 em->copy = NULL;
201                 g_free( em );
202                 em = NULL;
203                 node = g_list_next( node );
204         }
205 }
206
207 /*
208  * Paste person into cache.
209  * Enter: cache    Address cache to paste into.
210  *        folder   Folder to store
211  *        person   Person to paste.
212  *        copyLIst List of email addresses pasted.
213  * Return: Update list of email addresses pasted.
214  */
215 static GList *addrclip_cache_add_person(
216         AddressCache *cache, ItemFolder *folder, ItemPerson *person,
217         GList *copyList )
218 {
219         ItemPerson *newPerson;
220         ItemEMail *email;
221         ItemEMail *newEMail;
222         UserAttribute *attrib;
223         UserAttribute *newAttrib;
224         GList *node;
225         AddrClip_EMail *em;
226
227         /* Copy person */
228         newPerson = addritem_copy_item_person( person );
229         addrcache_id_person( cache, newPerson );
230         addrcache_folder_add_person( cache, folder, newPerson );
231
232         /* Copy email addresses */
233         node = person->listEMail;
234         while( node ) {
235                 email = node->data;
236                 newEMail = addritem_copy_item_email( email );
237                 addrcache_id_email( cache, newEMail );
238                 addrcache_person_add_email( cache, newPerson, newEMail );
239                 node = g_list_next( node );
240
241                 /* Take a copy of the original */
242                 em = g_new0( AddrClip_EMail, 1 );
243                 em->original = email;
244                 em->copy = newEMail;
245                 copyList = g_list_append( copyList, em );
246         }
247
248         /* Copy user attributes */
249         node = person->listAttrib;
250         while( node ) {
251                 attrib = node->data;
252                 newAttrib = addritem_copy_attribute( attrib );
253                 addrcache_id_attribute( cache, newAttrib );
254                 addritem_person_add_attribute( newPerson, newAttrib );
255                 node = g_list_next( node );
256         }
257
258         return copyList;
259 }
260
261 /*
262  * Search for new email record in copied email list.
263  * Enter: copyList  List of copied email address mappings.
264  *        emailOrig Original email item.
265  * Return: New email item corresponding to original item if pasted. Or NULL if
266  *         not found.
267  */
268 static ItemEMail *addrclip_find_copied_email(
269         GList *copyList, ItemEMail *emailOrig )
270 {
271         ItemEMail *emailCopy;
272         GList *node;
273         AddrClip_EMail *em;
274
275         emailCopy = NULL;
276         node = copyList;
277         while( node ) {
278                 em = node->data;
279                 if( em->original == emailOrig ) {
280                         emailCopy = em->copy;
281                         break;
282                 }
283                 node = g_list_next( node );
284         }
285         return emailCopy;
286 }
287
288 /*
289  * Paste group into cache.
290  * Enter: cache    Address cache to paste into.
291  *        folder   Folder to store
292  *        group    Group to paste.
293  *        copyList List of email addresses pasted.
294  * Return: Group added.
295  */
296 static ItemGroup *addrclip_cache_add_group(
297         AddressCache *cache, ItemFolder *folder, ItemGroup *group,
298         GList *copyList )
299 {
300         ItemGroup *newGroup;
301         ItemEMail *emailOrig, *emailCopy;
302         GList *node;
303
304         /* Copy group */
305         newGroup = addritem_copy_item_group( group );
306         addrcache_id_group( cache, newGroup );
307         addrcache_folder_add_group( cache, folder, newGroup );
308
309         /* Add references of copied addresses to group */
310         node = group->listEMail;
311         while( node ) {
312                 emailOrig = ( ItemEMail * ) node->data;
313                 emailCopy = addrclip_find_copied_email( copyList, emailOrig );
314                 if( emailCopy ) {
315                         addrcache_group_add_email( cache, newGroup, emailCopy );
316                 }
317                 node = g_list_next( node );
318         }
319         return newGroup;
320 }
321
322 /*
323  * Copy specified folder into cache. Note this functions uses pointers to
324  * folders to copy from. There should not be any deleted items referenced
325  * by these pointers!!!
326  * Enter: cache        Address cache to copy into.
327  *        targetFolder Target folder.
328  *        folder       Folder to copy.
329  * Return: Folder added.
330  */
331 static ItemFolder *addrclip_cache_copy_folder(
332         AddressCache *cache, ItemFolder *targetFolder, ItemFolder *folder )
333 {
334         ItemFolder *newFolder;
335         ItemGroup *newGroup;
336         GList *node;
337         GList *copyList;
338
339         /* Copy folder */
340         newFolder = addritem_copy_item_folder( folder );
341         addrcache_id_folder( cache, newFolder );
342         addrcache_folder_add_folder( cache, targetFolder, newFolder );
343
344         /* Copy people to new folder */
345         copyList = NULL;
346         node = folder->listPerson;
347         while( node ) {
348                 ItemPerson *item = node->data;
349                 node = g_list_next( node );
350                 copyList = addrclip_cache_add_person(
351                                 cache, newFolder, item, copyList );
352         }
353
354         /* Copy groups to new folder */
355         node = folder->listGroup;
356         while( node ) {
357                 ItemGroup *item = node->data;
358                 node = g_list_next( node );
359                 newGroup = addrclip_cache_add_group(
360                                 cache, newFolder, item, copyList );
361         }
362         g_list_free( copyList );
363
364         /* Copy folders to new folder (recursive) */
365         node = folder->listFolder;
366         while( node ) {
367                 ItemFolder *item = node->data;
368                 node = g_list_next( node );
369                 addrclip_cache_copy_folder( cache, newFolder, item );
370         }
371
372         return newFolder;
373 }
374
375 /*
376 * Paste item list into address book.
377 * Enter: cache     Target address cache.
378 *        folder    Target folder where data is pasted.
379 *        itemList  List of items to paste.
380 *        clipBoard Clipboard.
381 * Return: List of group or folder items added.
382 */
383 static GList *addrclip_cache_add_folder(
384         AddressCache *cache, ItemFolder *folder, GList *itemList,
385         AddressClipboard *clipBoard )
386 {
387         GList *folderGroup;
388         GList *node;
389         AddrSelectItem *item;
390         AddrItemObject *aio;
391         AddressCache *cacheFrom;
392         gboolean haveGroups;
393         GList *copyList;
394
395         folderGroup = NULL;
396         copyList = NULL;
397         haveGroups = FALSE;
398         node = itemList;
399         while( node ) {
400                 item = node->data;
401                 node = g_list_next( node );
402
403                 cacheFrom = addrindex_get_cache(
404                                 clipBoard->addressIndex, item->cacheID );
405                 if( cacheFrom == NULL ) continue;
406                 if( item->uid ) {
407                         aio = addrcache_get_object( cacheFrom, item->uid );
408                         if( aio ) {
409                                 if( ADDRITEM_TYPE(aio) == ITEMTYPE_PERSON ) {
410                                         ItemPerson *person;
411
412                                         person = ( ItemPerson * ) aio;
413                                         copyList = addrclip_cache_add_person(
414                                                 cache, folder, person, copyList );
415                                 }
416                                 /*
417                                 else if( ADDRITEM_TYPE(aio) == ITEMTYPE_EMAIL ) {
418                                 } 
419                                 */
420                                 else if( ADDRITEM_TYPE(aio) == ITEMTYPE_GROUP ) {
421                                         haveGroups = TRUE;      /* Process later */
422                                 }
423                                 else if( ADDRITEM_TYPE(aio) == ITEMTYPE_FOLDER ) {
424                                         ItemFolder *itemFolder, *newFolder;
425
426                                         itemFolder = ( ItemFolder * ) aio;
427                                         newFolder = addrclip_cache_copy_folder(
428                                                         cache, folder, itemFolder );
429                                         folderGroup =
430                                                 g_list_append( folderGroup, newFolder );
431                                 }
432                         }
433                 }
434                 else {
435                         if( item->objectType == ITEMTYPE_DATASOURCE ) {
436                                 /*
437                                 * Must be an address book - allow copy only if
438                                 * copying from a different cache.
439                                 */
440                                 if( cache != cacheFrom ) {
441                                         ItemFolder *itemFolder, *newFolder;
442
443                                         itemFolder = cacheFrom->rootFolder;
444                                         newFolder = addrclip_cache_copy_folder(
445                                                 cache, folder, itemFolder );
446                                         addritem_folder_set_name( newFolder,
447                                                 addrcache_get_name( cacheFrom ) );
448                                         folderGroup =
449                                                 g_list_append( folderGroup, newFolder );
450                                 }
451                         }
452                 }
453         }
454
455         /* Finally add any groups */
456         if( haveGroups ) {
457                 node = itemList;
458                 while( node ) {
459                         item = node->data;
460                         node = g_list_next( node );
461                         cacheFrom = addrindex_get_cache(
462                                         clipBoard->addressIndex, item->cacheID );
463                         if( cacheFrom == NULL ) continue;
464                         aio = addrcache_get_object( cacheFrom, item->uid );
465                         if( aio ) {
466                                 if( ADDRITEM_TYPE(aio) == ITEMTYPE_GROUP ) {
467                                         ItemGroup *group, *newGroup;
468
469                                         group = ( ItemGroup * ) aio;
470                                         newGroup = addrclip_cache_add_group(
471                                                 cache, folder, group, copyList );
472                                         folderGroup =
473                                                 g_list_append( folderGroup, newGroup );
474                                 }
475                         }
476                 }
477         }
478
479         /* Free up stuff */
480         addrclip_free_copy_list( copyList );
481         g_list_free( copyList );
482         copyList = NULL;
483
484         return folderGroup;
485 }
486
487 /*
488 * Move items in list into new folder
489 * Enter: cache        Target address cache.
490 *        targetFolder Target folder where data is pasted.
491 *        itemList     List of items to paste.
492 *        clipBoard    Clipboard.
493 * Return: List of group or folder items added.
494 */
495 static GList *addrclip_cache_move_items(
496         AddressCache *cache, ItemFolder *targetFolder, GList *itemList,
497         AddressClipboard *clipBoard )
498 {
499         GList *folderGroup;
500         GList *node;
501         AddrSelectItem *item;
502         AddrItemObject *aio;
503         AddressCache *cacheFrom;
504
505         folderGroup = NULL;
506         node = itemList;
507         while( node ) {
508                 item = node->data;
509                 node = g_list_next( node );
510                 cacheFrom = addrindex_get_cache(
511                                 clipBoard->addressIndex, item->cacheID );
512                 if( cacheFrom == NULL ) continue;
513                 aio = addrcache_get_object( cacheFrom, item->uid );
514                 if( aio ) {
515                         if( ADDRITEM_TYPE(aio) == ITEMTYPE_PERSON ) {
516                                 ItemPerson *person;
517
518                                 person = ( ItemPerson * ) aio;
519                                 addrcache_folder_move_person(
520                                         cache, person, targetFolder );
521                         }
522                         else if( ADDRITEM_TYPE(aio) == ITEMTYPE_GROUP ) {
523                                 ItemGroup *group;
524
525                                 group = ( ItemGroup * ) aio;
526                                 addrcache_folder_move_group(
527                                         cache, group, targetFolder );
528                                 folderGroup = g_list_append( folderGroup, group );
529                         }
530                         else if( ADDRITEM_TYPE(aio) == ITEMTYPE_FOLDER ) {
531                                 ItemFolder *folder;
532
533                                 folder = ( ItemFolder * ) aio;
534                                 addrcache_folder_move_folder(
535                                         cache, folder, targetFolder );
536                                 folderGroup =
537                                         g_list_append( folderGroup, folder );
538                         }
539                 }
540         }
541         return folderGroup;
542 }
543
544 /*
545 * Get address cache of first item in list. This assumes that all items in
546 * the clipboard are located in the same cache.
547 * Enter: clipBoard Clipboard.
548 * Return: List of group or folder items added.
549 */
550 static AddressCache *addrclip_list_get_cache( AddressClipboard *clipBoard ) {
551         AddressCache *cache;
552         GList *itemList;
553         AddrSelectItem *item;
554
555         cache = NULL;
556         itemList = clipBoard->objectList;
557         if( itemList ) {
558                 item = itemList->data;
559                 cache = addrindex_get_cache(
560                                 clipBoard->addressIndex, item->cacheID );
561         }
562         return cache;
563 }
564
565 /*
566 * Paste (copy) clipboard into address book.
567 * Enter: clipBoard Clipboard.
568 *        book      Target address book.
569 *        folder    Target folder where data is pasted, or null for root folder.
570 * Return: List of group or folder items added.
571 */
572 GList *addrclip_paste_copy(
573         AddressClipboard *clipBoard, AddressBookFile *book,
574         ItemFolder *folder )
575 {
576         AddressCache *cache;
577         GList *itemList;
578         GList *folderGroup;
579
580         g_return_val_if_fail( clipBoard != NULL, NULL );
581
582         cache = book->addressCache;
583         if( folder == NULL ) folder = cache->rootFolder;
584
585         folderGroup = NULL;
586         itemList = clipBoard->objectList;
587         folderGroup = addrclip_cache_add_folder(
588                         cache, folder, itemList, clipBoard );
589
590         return folderGroup;
591 }
592
593 /*
594 * Remove items that were cut from clipboard.
595 * Enter: clipBoard Clipboard.
596 */
597 void addrclip_delete_item( AddressClipboard *clipBoard ) {
598         AddrSelectItem *item;
599         AddrItemObject *aio;
600         AddressCache *cacheFrom;
601         GList *node;
602
603         /* If cutting within current cache, no deletion is necessary */
604         if( clipBoard->moveFlag ) return;
605
606         /* Remove groups */
607         node = clipBoard->objectList;
608         while( node ) {
609                 item = node->data;
610                 node = g_list_next( node );
611                 cacheFrom = addrindex_get_cache(
612                                 clipBoard->addressIndex, item->cacheID );
613                 if( cacheFrom == NULL ) continue;
614                 aio = addrcache_get_object( cacheFrom, item->uid );
615                 if( aio ) {
616                         if( ADDRITEM_TYPE(aio) == ITEMTYPE_GROUP ) {
617                                 ItemGroup *group;
618
619                                 group = ( ItemGroup * ) aio;
620                                 group = addrcache_remove_group( cacheFrom, group );
621                                 if( group ) {
622                                         addritem_free_item_group( group );
623                                 }
624                         }
625                 }
626         }
627
628         /* Remove persons and folders */
629         node = clipBoard->objectList;
630         while( node ) {
631                 item = node->data;
632                 node = g_list_next( node );
633
634                 cacheFrom = addrindex_get_cache(
635                                 clipBoard->addressIndex, item->cacheID );
636                 if( cacheFrom == NULL ) continue;
637
638                 aio = addrcache_get_object( cacheFrom, item->uid );
639                 if( aio ) {
640                         if( ADDRITEM_TYPE(aio) == ITEMTYPE_PERSON ) {
641                                 ItemPerson *person;
642
643                                 person = ( ItemPerson * ) aio;
644                                 person = addrcache_remove_person( cacheFrom, person );
645                                 if( person ) {
646                                         addritem_free_item_person( person );
647                                 }
648                         }
649                         else if( ADDRITEM_TYPE(aio) == ITEMTYPE_FOLDER ) {
650                                 ItemFolder *itemFolder;
651
652                                 itemFolder = ( ItemFolder * ) aio;
653                                 itemFolder = addrcache_remove_folder_delete(
654                                                 cacheFrom, itemFolder );
655                                 addritem_free_item_folder( itemFolder );
656                         }
657                 }
658         }
659 }
660
661 /*
662 * Paste (move) clipboard into address book.
663 * Enter: clipBoard Clipboard.
664 *        book      Target address book.
665 *        folder    Target folder where data is pasted, or null for root folder.
666 * Return: List of group or folder items added.
667 */
668 GList *addrclip_paste_cut(
669         AddressClipboard *clipBoard, AddressBookFile *book,
670         ItemFolder *folder )
671 {
672         AddressCache *cache, *cacheFrom;
673         GList *itemList;
674         GList *folderGroup;
675
676         g_return_val_if_fail( clipBoard != NULL, NULL );
677
678         cache = book->addressCache;
679         if( folder == NULL ) folder = cache->rootFolder;
680
681         folderGroup = NULL;
682         clipBoard->moveFlag = FALSE;
683         cacheFrom = addrclip_list_get_cache( clipBoard );
684         if( cacheFrom && cacheFrom == cache ) {
685                 /* Move items between folders in same book */
686                 itemList = clipBoard->objectList;
687                 folderGroup = addrclip_cache_move_items(
688                                 cache, folder, itemList, clipBoard );
689                 clipBoard->moveFlag = TRUE;
690         }
691         else {
692                 /* Move items across address books */
693                 itemList = clipBoard->objectList;
694                 folderGroup = addrclip_cache_add_folder(
695                                 cache, folder, itemList, clipBoard );
696         }
697
698         return folderGroup;
699 }
700
701 /*
702  * ============================================================================
703  * Paste address only.
704  * ============================================================================
705  */
706
707 /*
708  * Copy email addresses from specified list.
709  * Enter: cache      Address cache to paste into.
710  *        target     Person to receive email addresses.
711  *        listEMail  List of email addresses.
712  * Return: Number of addresses added.
713  */
714 static gint addrclip_person_add_email(
715         AddressCache *cache, ItemPerson *target, GList *listEMail )
716 {
717         gint cnt;
718         GList *node;
719
720         /* Copy email addresses */
721         cnt = 0;
722         node = listEMail;
723         while( node ) {
724                 ItemEMail *email, *newEMail;
725
726                 email = node->data;
727                 newEMail = addritem_copy_item_email( email );
728                 addrcache_id_email( cache, newEMail );
729                 addrcache_person_add_email( cache, target, newEMail );
730                 node = g_list_next( node );
731                 cnt++;
732         }
733         return cnt;
734 }
735
736 /*
737 * Paste (copy) E-Mail addresses from clipboard into specified person.
738 * Enter: aio     Address item to copy from.
739 *        cache   Target address cache.
740 *        person  Target person where data is pasted.
741 * Return: Number of EMail records added.
742 */
743 static gint addrclip_copy_email_to_person(
744         AddrItemObject *aio, AddressCache *cache, ItemPerson *person )
745 {
746         gint cnt;
747         GList *listEMail;
748
749         cnt = 0;
750
751         if( ADDRITEM_TYPE(aio) == ITEMTYPE_PERSON ) {
752                 ItemPerson *fromPerson;
753
754                 fromPerson = ( ItemPerson * ) aio;
755                 listEMail = fromPerson->listEMail;
756                 cnt += addrclip_person_add_email(
757                         cache, person, listEMail );
758         }
759         else if( ADDRITEM_TYPE(aio) == ITEMTYPE_EMAIL ) {
760                 ItemEMail *email, *newEMail;
761
762                 email = ( ItemEMail * ) aio;
763                 newEMail = addritem_copy_item_email( email );
764                 addrcache_id_email( cache, newEMail );
765                 addrcache_person_add_email( cache, person, newEMail );
766                 cnt++;
767         }
768         else if( ADDRITEM_TYPE(aio) == ITEMTYPE_GROUP ) {
769                 ItemGroup *group;
770
771                 group = ( ItemGroup * ) aio;
772                 listEMail = group->listEMail;
773                 cnt += addrclip_person_add_email(
774                         cache, person, listEMail );
775         }
776         else if( ADDRITEM_TYPE(aio) == ITEMTYPE_FOLDER ) {
777                 ItemFolder *folder;
778                 AddrItemObject *item;
779                 GList *node;
780
781                 folder = ( ItemFolder * ) aio;
782                 node = folder->listPerson;
783                 while( node ) {
784                         item = node->data;
785                         node = g_list_next( node );
786                         cnt += addrclip_copy_email_to_person( item, cache, person );
787                 }
788
789                 node = folder->listGroup;
790                 while( node ) {
791                         item = node->data;
792                         node = g_list_next( node );
793                         cnt += addrclip_copy_email_to_person( item, cache, person );
794                 }
795
796                 node = folder->listFolder;
797                 while( node ) {
798                         item = node->data;
799                         node = g_list_next( node );
800                         cnt += addrclip_copy_email_to_person( item, cache, person );
801                 }
802         }
803         return cnt;
804 }
805
806 /*
807 * End of Source.
808 */
809