1 #if !defined(lint) && !defined(DOS)
2 static char rcsid
[] = "$Id: takeaddr.c 1012 2008-03-26 00:44:22Z hubert@u.washington.edu $";
6 * ========================================================================
7 * Copyright 2006-2008 University of Washington
8 * Copyright 2013-2020 Eduardo Chappa
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
14 * http://www.apache.org/licenses/LICENSE-2.0
16 * ========================================================================
19 /*======================================================================
21 Mostly support for Take Address command.
30 #include "confscroll.h"
39 #include "../pith/state.h"
40 #include "../pith/msgno.h"
41 #include "../pith/adrbklib.h"
42 #include "../pith/bldaddr.h"
43 #include "../pith/bitmap.h"
44 #include "../pith/util.h"
45 #include "../pith/addrstring.h"
46 #include "../pith/remote.h"
47 #include "../pith/newmail.h"
48 #include "../pith/list.h"
49 #include "../pith/abdlc.h"
50 #include "../pith/ablookup.h"
51 #include "../pith/stream.h"
52 #include "../pith/mailcmd.h"
53 #include "../pith/busy.h"
56 typedef struct takeaddress_screen
{
62 static TA_SCREEN_S
*ta_screen
;
63 static char *fakedomain
= "@";
65 static ESCKEY_S save_or_export
[] = {
66 {'s', 's', "S", N_("Save")},
67 {'e', 'e', "E", N_("Export")},
71 /* internal prototypes */
72 int edit_nickname(AdrBk
*, AddrScrn_Disp
*, int, char *, char *, HelpType
, int, int);
73 void add_abook_entry(TA_S
*, char *, char *, char *, char *, int, TA_STATE_S
**, char *);
74 void take_to_addrbooks_frontend(char **, char *, char *, char *, char *,
75 char *, int, TA_STATE_S
**, char *);
76 void take_to_addrbooks(char **, char *, char *, char *, char *,
77 char *, int, TA_STATE_S
**, char *);
78 PerAddrBook
*use_this_addrbook(int, char *);
79 PerAddrBook
*check_for_addrbook(char *);
80 int takeaddr_screen(struct pine
*, TA_S
*, int, ScreenMode
, TA_STATE_S
**, char *);
81 void takeaddr_bypass(struct pine
*, TA_S
*, TA_STATE_S
**);
82 int ta_do_take(TA_S
*, int, int, TA_STATE_S
**, char *);
83 TA_S
*whereis_taline(TA_S
*);
84 int ta_take_marked_addrs(int, TA_S
*, int, TA_STATE_S
**, char *);
85 int ta_take_single_addr(TA_S
*, int, TA_STATE_S
**, char *);
86 int update_takeaddr_screen(struct pine
*, TA_S
*, TA_SCREEN_S
*, Pos
*);
87 void takeaddr_screen_redrawer_list(void);
88 void takeaddr_screen_redrawer_single(void);
89 int attached_addr_handler(TA_S
*, int);
90 int take_without_edit(TA_S
*, int, int, TA_STATE_S
**, char *);
91 void export_vcard_att(struct pine
*, int, long, ATTACH_S
*);
92 int take_export_tool(struct pine
*, int, CONF_S
**, unsigned);
95 int ta_scroll_up(long);
96 int ta_scroll_down(long);
97 int ta_scroll_to_pos(long);
98 int ta_scroll_callback(int, long);
103 * Edit a nickname field.
105 * Args: abook -- the addressbook handle
106 * dl -- display list line (NULL if new entry)
107 * command_line -- line to prompt on
108 * orig -- nickname to edit
111 * return_existing -- changes the behavior when a user types in a nickname
112 * which already exists in this abook. If not set, it
113 * will just keep looping until the user changes; if set,
114 * it will return -8 to the caller and orig will be set
115 * to the matching nickname.
117 * Returns: -10 to cancel
119 * -7 only case of nickname changed (only happens if dl set)
120 * -8 existing nickname chosen (only happens if return_existing set)
121 * 0 new value copied into orig
124 edit_nickname(AdrBk
*abook
, AddrScrn_Disp
*dl
, int command_line
, char *orig
,
125 char *prompt
, HelpType this_help
, int return_existing
, int takeaddr
)
127 char edit_buf
[MAX_NICKNAME
+ 1];
129 int i
, flags
, lastrc
, rc
;
130 AdrBk_Entry
*check
, *passed_in_ae
;
132 SAVE_STATE_S state
; /* For saving state of addrbooks temporarily */
135 ekey
[i
= 0].ch
= ctrl('T');
138 ekey
[i
++].label
= N_("To AddrBk");
140 if(F_ON(F_ENABLE_TAB_COMPLETE
,ps_global
)){
141 ekey
[i
].ch
= ctrl('I');
143 ekey
[i
].name
= "TAB";
144 ekey
[i
++].label
= N_("Complete");
149 strncpy(edit_buf
, orig
, sizeof(edit_buf
)-1);
150 edit_buf
[sizeof(edit_buf
)-1] = '\0';
152 passed_in_ae
= adrbk_get_ae(abook
, (a_c_arg_t
) dl
->elnum
);
154 passed_in_ae
= (AdrBk_Entry
*)NULL
;
161 q_status_message(SM_ORDER
, 3, 4, error
);
162 fs_give((void **)&error
);
165 /* display a message because adrbk_lookup_by_nick returned positive */
168 strncpy(orig
, edit_buf
, sizeof(edit_buf
)-1);
169 orig
[sizeof(edit_buf
)-1] = '\0';
171 (void)adrbk_get_ae(abook
, (a_c_arg_t
) dl
->elnum
);
175 q_status_message1(SM_ORDER
, 0, 4,
176 _("Already an entry with nickname \"%s\""), edit_buf
);
181 help
= (help
== NO_HELP
? this_help
: NO_HELP
);
183 flags
= OE_APPEND_CURRENT
;
184 rc
= optionally_enter(edit_buf
, command_line
, 0, sizeof(edit_buf
),
185 prompt
, ekey
, help
, &flags
);
190 if(rc
== 2){ /* ^T */
191 void (*redraw
) (void) = ps_global
->redrawer
;
192 char *returned_nickname
;
194 push_titlebar_state();
197 returned_nickname
= addr_book_takeaddr();
199 returned_nickname
= addr_book_selnick();
201 restore_state(&state
);
202 if(returned_nickname
){
203 strncpy(edit_buf
, returned_nickname
, sizeof(edit_buf
)-1);
204 edit_buf
[sizeof(edit_buf
)-1] = '\0';
205 fs_give((void **)&returned_nickname
);
209 pop_titlebar_state();
211 if((ps_global
->redrawer
= redraw
) != NULL
) /* reset old value, and test */
212 (*ps_global
->redrawer
)();
214 else if(rc
== 11){ /* TAB */
216 char *new_nickname
= NULL
;
219 ambiguity
= abook_nickname_complete(edit_buf
, &new_nickname
,
220 (lastrc
==rc
&& !(flags
& OE_USER_MODIFIED
)), 0);
223 strncpy(edit_buf
, new_nickname
, sizeof(edit_buf
));
224 edit_buf
[sizeof(edit_buf
)-1] = '\0';
227 fs_give((void **) &new_nickname
);
239 nickname_check(edit_buf
, &error
) ||
241 adrbk_lookup_by_nick(abook
, edit_buf
, (adrbk_cntr_t
*)NULL
)) &&
242 check
!= passed_in_ae
));
246 (void)adrbk_get_ae(abook
, (a_c_arg_t
) dl
->elnum
);
251 /* only the case of nickname changed */
252 if(passed_in_ae
&& check
== passed_in_ae
&& strcmp(edit_buf
, orig
)){
253 (void)adrbk_get_ae(abook
, (a_c_arg_t
) dl
->elnum
);
254 strncpy(orig
, edit_buf
, sizeof(edit_buf
)-1);
255 orig
[sizeof(edit_buf
)-1] = '\0';
260 (void)adrbk_get_ae(abook
, (a_c_arg_t
) dl
->elnum
);
262 if(strcmp(edit_buf
, orig
) == 0) /* no change */
265 strncpy(orig
, edit_buf
, sizeof(edit_buf
)-1);
266 orig
[sizeof(edit_buf
)-1] = '\0';
272 * Add an entry to address book.
273 * It is for capturing addresses off incoming mail.
274 * This is a front end for take_to_addrbooks.
275 * It is also used for replacing an existing entry and for adding a single
276 * new address to an existing list.
278 * The reason this is here is so that when Taking a single address, we can
279 * rearrange the fullname to be Last, First instead of First Last.
281 * Args: ta_entry -- the entry from the take screen
282 * command_line -- line to prompt on
284 * Result: item is added to one of the address books,
285 * an error message is queued if appropriate.
288 add_abook_entry(TA_S
*ta_entry
, char *nick
, char *fullname
, char *fcc
,
289 char *comment
, int command_line
, TA_STATE_S
**tas
, char *cmd
)
292 char new_fullname
[6*MAX_FULLNAME
+ 1], new_address
[6*MAX_ADDRESS
+ 1];
295 dprint((5, "-- add_abook_entry --\n"));
297 /*-- rearrange full name (Last, First) ---*/
298 new_fullname
[0] = '\0';
299 addr
= ta_entry
->addr
;
300 if(!fullname
&& addr
->personal
!= NULL
){
301 if(F_ON(F_DISABLE_TAKE_LASTFIRST
, ps_global
)){
302 strncpy(new_fullname
, addr
->personal
, sizeof(new_fullname
)-1);
303 new_fullname
[sizeof(new_fullname
)-1] = '\0';
306 char old_fullname
[6*MAX_FULLNAME
+ 1];
308 snprintf(old_fullname
, sizeof(old_fullname
), "%s", addr
->personal
);
309 old_fullname
[sizeof(old_fullname
)-1] = '\0';
310 switch_to_last_comma_first(old_fullname
, new_fullname
, sizeof(new_fullname
));
314 /* initial value for new address */
315 new_address
[0] = '\0';
316 if(addr
->mailbox
&& addr
->mailbox
[0]){
317 char *scratch
, *p
, *t
, *u
;
323 scratch
= (char *) fs_get(es
);
325 rbuf
.f
= dummy_soutr
;
329 rbuf
.end
= scratch
+es
-1;
330 rfc822_output_address_list(&rbuf
, addr
, 0L, NULL
);
332 if((p
= srchstr(scratch
, "@" RAWFIELD
)) != NULL
){
334 if(*t
== '&'){ /* find "leading" token */
335 *t
++ = ' '; /* replace token */
336 *p
= '\0'; /* tie off string */
337 u
= (char *)rfc822_base64((unsigned char *)t
,
338 (unsigned long)strlen(t
), &l
);
339 *p
= '@'; /* restore 'p' */
340 rplstr(p
, es
-(p
-scratch
), 12, ""); /* clear special token */
341 rplstr(t
, es
-(t
-scratch
), strlen(t
), u
); /* Null u is handled */
343 fs_give((void **)&u
);
345 else if(t
== scratch
)
349 strncpy(new_address
, scratch
, sizeof(new_address
)-1);
350 new_address
[sizeof(new_address
)-1] = '\0';
353 fs_give((void **)&scratch
);
356 if(ta_entry
->frwrded
){
360 for(i
= 0, a
= addr
; a
; i
++, a
= a
->next
)
361 ;/* just counting for alloc below */
363 /* catch special case where empty addr was set in vcard_to_ta */
364 if(i
== 1 && !addr
->host
&& !addr
->mailbox
&& !addr
->personal
)
367 new_list
= (char **) fs_get((i
+1) * sizeof(char *));
368 for(j
= 0, a
= addr
; i
&& a
; j
++, a
= a
->next
){
376 bufp
= (char *) fs_get(len
* sizeof(char));
377 new_list
[j
] = cpystr(addr_string(a
, bufp
, len
));
379 fs_give((void **) &bufp
);
387 j
= (ta_entry
->strvalue
&& ta_entry
->strvalue
[0]) ? 2 : 1;
389 new_list
= (char **) fs_get(j
* sizeof(char *));
392 new_list
[i
++] = cpystr(ta_entry
->strvalue
);
397 take_to_addrbooks_frontend(new_list
, nick
,
398 fullname
? fullname
: new_fullname
,
399 new_address
, fcc
, comment
, command_line
,
401 free_list_array(&new_list
);
406 take_to_addrbooks_frontend(char **new_entries
, char *nick
, char *fullname
,
407 char *addr
, char *fcc
, char *comment
, int cmdline
,
408 TA_STATE_S
**tas
, char *cmd
)
410 jmp_buf save_jmp_buf
;
411 int *save_nesting_level
;
413 dprint((5, "-- take_to_addrbooks_frontend --\n"));
415 if(ps_global
->remote_abook_validity
> 0 &&
416 adrbk_check_and_fix_all(ab_nesting_level
== 0, 0, 0))
417 ps_global
->mangled_footer
= 1;
419 save_nesting_level
= cpyint(ab_nesting_level
);
420 memcpy(save_jmp_buf
, addrbook_changed_unexpectedly
, sizeof(jmp_buf));
421 if(setjmp(addrbook_changed_unexpectedly
)){
422 q_status_message(SM_ORDER
, 5, 10, _("Resetting address book..."));
424 "RESETTING address book... take_to_addrbooks_frontend!\n"));
426 ab_nesting_level
= *save_nesting_level
;
430 take_to_addrbooks(new_entries
, nick
, fullname
, addr
, fcc
, comment
, cmdline
,
432 memcpy(addrbook_changed_unexpectedly
, save_jmp_buf
, sizeof(jmp_buf));
434 if(save_nesting_level
)
435 fs_give((void **)&save_nesting_level
);
440 * Add to address book, called from take screen.
441 * It is also used for adding to an existing list or replacing an existing
444 * Args: new_entries -- a list of addresses to add to a list or to form
446 * nick -- if adding new entry, suggest this for nickname
447 * fullname -- if adding new entry, use this for fullname
448 * addr -- if only one new_entry, this is its addr
449 * fcc -- if adding new entry, use this for fcc
450 * comment -- if adding new entry, use this for comment
451 * command_line -- line to prompt on
453 * Result: item is added to one of the address books,
454 * an error message is queued if appropriate.
457 take_to_addrbooks(char **new_entries
, char *nick
, char *fullname
, char *addr
,
458 char *fcc
, char *comment
, int command_line
, TA_STATE_S
**tas
, char *cmd
)
460 char new_nickname
[6*MAX_NICKNAME
+ 1], exist_nick
[6*MAX_NICKNAME
+ 1];
461 char prompt
[200], **p
;
462 int rc
, listadd
= 0, ans
, i
;
466 AdrBk_Entry
*abe
= (AdrBk_Entry
*)NULL
, *abe_copy
;
467 adrbk_cntr_t entry_num
= NO_NEXT
;
468 size_t tot_size
, new_size
, old_size
;
471 char *simple_a
= NULL
;
475 dprint((5, "-- take_to_addrbooks --\n"));
480 pab
= setup_for_addrbook_add(&state
, command_line
, cmd
);
482 /* check we got it opened ok */
483 if(pab
== NULL
|| pab
->address_book
== NULL
)
484 goto take_to_addrbooks_cancel
;
486 adrbk_check_validity(pab
->address_book
, 1L);
487 if(pab
->address_book
->flags
& FILE_OUTOFDATE
||
488 (pab
->address_book
->rd
&&
489 pab
->address_book
->rd
->flags
& REM_OUTOFDATE
)){
490 q_status_message3(SM_ORDER
, 0, 4,
491 "Address book%s%s has changed: %stry again",
492 (as
.n_addrbk
> 1 && pab
->abnick
) ? " " : "",
493 (as
.n_addrbk
> 1 && pab
->abnick
) ? pab
->abnick
: "",
494 (ps_global
->remote_abook_validity
== -1) ? "resynchronize and " : "");
496 restore_state(&((*tas
)->state
));
500 restore_state(&state
);
505 abook
= pab
->address_book
;
506 new_nickname
[0] = '\0';
507 exist_nick
[0] = '\0';
512 /* rfc822_parse_adrlist feels free to destroy input so send copy */
513 tmp_a_string
= cpystr(addr
);
514 rfc822_parse_adrlist(&a
, tmp_a_string
, fakedomain
);
516 fs_give((void **)&tmp_a_string
);
519 simple_a
= simple_addr_string(a
, tmp_20k_buf
, SIZEOF_20KBUF
);
520 mail_free_address(&a
);
523 if(simple_a
&& *simple_a
)
524 abe
= adrbk_lookup_by_addr(abook
, simple_a
, NULL
);
527 snprintf(prompt
, sizeof(prompt
), _("Warning: address exists with %s%s, continue "),
528 (abe
->nickname
&& abe
->nickname
[0]) ? "nickname "
529 : (abe
->fullname
&& abe
->fullname
[0]) ? "fullname "
531 (abe
->nickname
&& abe
->nickname
[0]) ? abe
->nickname
532 : (abe
->fullname
&& abe
->fullname
[0]) ? abe
->fullname
534 prompt
[sizeof(prompt
)-1] = '\0';
535 switch(want_to(prompt
, 'y', 'x', NO_HELP
, WT_NORM
)){
537 if(abe
->nickname
&& abe
->nickname
[0]){
538 strncpy(new_nickname
, abe
->nickname
, sizeof(new_nickname
));
539 new_nickname
[sizeof(new_nickname
)-1] = '\0';
540 strncpy(exist_nick
, new_nickname
, sizeof(exist_nick
));
541 exist_nick
[sizeof(exist_nick
)-1] = '\0';
547 goto take_to_addrbooks_cancel
;
557 /*----- nickname ------*/
558 snprintf(prompt
, sizeof(prompt
),
559 _("Enter new or existing nickname (one word and easy to remember): "));
560 prompt
[sizeof(prompt
)-1] = '\0';
561 if(!new_nickname
[0] && nick
){
562 strncpy(new_nickname
, nick
, sizeof(new_nickname
));
563 new_nickname
[sizeof(new_nickname
)-1] = '\0';
566 rc
= edit_nickname(abook
, (AddrScrn_Disp
*)NULL
, command_line
,
567 new_nickname
, prompt
, h_oe_takenick
, 1, 1);
568 if(rc
== -8){ /* this means an existing nickname was entered */
569 abe
= adrbk_lookup_by_nick(abook
, new_nickname
, &entry_num
);
570 if(!abe
){ /* this shouldn't happen */
571 q_status_message1(SM_ORDER
, 0, 4,
572 _("Already an entry %s in address book!"), new_nickname
);
573 goto take_to_addrbooks_cancel
;
578 if(abe
->tag
== Single
&& !strcmp(new_nickname
, exist_nick
)){
579 static ESCKEY_S choices
[] = {
580 {'r', 'r', "R", N_("Replace")},
581 {'n', 'n', "N", N_("No")},
582 {-1, 0, NULL
, NULL
}};
584 snprintf(prompt
, sizeof(prompt
), _("Entry %s (%s) exists, replace ? "),
586 (abe
->fullname
&& abe
->fullname
[0])
587 ? (char *)rfc1522_decode_to_utf8((unsigned char *)tmp_20k_buf
,
588 SIZEOF_20KBUF
, abe
->fullname
)
590 prompt
[sizeof(prompt
)-1] = '\0';
591 ans
= radio_buttons(prompt
,
600 static ESCKEY_S choices
[] = {
601 {'r', 'r', "R", N_("Replace")},
602 {'a', 'a', "A", N_("Add")},
603 {'n', 'n', "N", N_("No")},
604 {-1, 0, NULL
, NULL
}};
606 snprintf(prompt
, sizeof(prompt
),
607 _("%s %s (%s) exists, replace or add addresses to it ? "),
608 abe
->tag
== List
? "List" : "Entry",
610 (abe
->fullname
&& abe
->fullname
[0])
611 ? (char *)rfc1522_decode_to_utf8((unsigned char *)tmp_20k_buf
,
612 SIZEOF_20KBUF
, abe
->fullname
)
614 prompt
[sizeof(prompt
)-1] = '\0';
616 ans
= radio_buttons(prompt
,
621 h_oe_take_replace_or_add
,
639 goto take_to_addrbooks_cancel
;
642 else if(rc
!= 0 && rc
!= -9) /* -9 means a null nickname */
643 goto take_to_addrbooks_cancel
;
645 if((long)abook
->count
> MAX_ADRBK_SIZE
||
646 (old_tag
== NotSet
&& (long)abook
->count
>= MAX_ADRBK_SIZE
)){
647 q_status_message(SM_ORDER
, 3, 5,
648 _("Address book is at maximum size, cancelled."));
649 dprint((2, "Addrbook at Max size, TakeAddr cancelled\n"));
650 goto take_to_addrbooks_cancel
;
654 /* count up size of existing list */
655 if(abe
->tag
== List
){
656 for(p
= abe
->addr
.list
; p
!= NULL
&& *p
!= NULL
; p
++)
659 old_size
= p
- abe
->addr
.list
;
661 /* or size of existing single address */
662 else if(abe
->addr
.addr
&& abe
->addr
.addr
[0])
667 else /* don't care about old size, they will be tossed in edit_entry */
670 /* make up an abe to pass to edit_entry */
671 abe_copy
= adrbk_newentry();
672 abe_copy
->nickname
= cpystr(new_nickname
);
673 abe_copy
->tag
= List
;
674 abe_copy
->addr
.list
= NULL
;
677 abe_copy
->fullname
= cpystr((abe
->fullname
&& abe
->fullname
[0])
678 ? abe
->fullname
: "");
679 abe_copy
->fcc
= cpystr((abe
->fcc
&& abe
->fcc
[0]) ? abe
->fcc
: "");
680 abe_copy
->extra
= cpystr((abe
->extra
&&abe
->extra
[0]) ? abe
->extra
: "");
684 * use passed in info if available
686 abe_copy
->fullname
= cpystr((fullname
&& fullname
[0])
688 : (abe
&& abe
->fullname
)
691 abe_copy
->fcc
= cpystr((fcc
&& fcc
[0])
696 abe_copy
->extra
= cpystr((comment
&& comment
[0])
698 : (abe
&& abe
->extra
)
703 /* get rid of duplicates */
705 if(abe
->tag
== List
){
708 ADDRESS
*newadr
, *oldadr
;
710 for(q
= new_entries
; q
!= NULL
&& *q
!= NULL
;){
712 tmp_a_string
= cpystr(*q
);
714 rfc822_parse_adrlist(&newadr
, tmp_a_string
, fakedomain
);
715 fs_give((void **) &tmp_a_string
);
717 elim_dup
= (newadr
== NULL
);
718 for(p
= abe
->addr
.list
;
719 !elim_dup
&& p
!= NULL
&& *p
!= NULL
;
721 tmp_a_string
= cpystr(*p
);
723 rfc822_parse_adrlist(&oldadr
, tmp_a_string
, fakedomain
);
724 fs_give((void **) &tmp_a_string
);
726 if(address_is_same(newadr
, oldadr
))
730 mail_free_address(&oldadr
);
733 /* slide the addresses down one to eliminate newadr */
738 for(r
= q
; r
!= NULL
&& *r
!= NULL
; r
++)
742 fs_give((void **) &f
);
748 mail_free_address(&newadr
);
753 ADDRESS
*newadr
, *oldadr
;
755 tmp_a_string
= cpystr(abe
->addr
.addr
? abe
->addr
.addr
: "");
757 rfc822_parse_adrlist(&oldadr
, tmp_a_string
, fakedomain
);
758 fs_give((void **) &tmp_a_string
);
760 for(q
= new_entries
; q
!= NULL
&& *q
!= NULL
;){
762 tmp_a_string
= cpystr(*q
);
764 rfc822_parse_adrlist(&newadr
, tmp_a_string
, fakedomain
);
765 fs_give((void **) &tmp_a_string
);
767 /* slide the addresses down one to eliminate newadr */
768 if(address_is_same(newadr
, oldadr
)){
772 for(r
= q
; r
!= NULL
&& *r
!= NULL
; r
++)
776 fs_give((void **) &f
);
782 mail_free_address(&newadr
);
786 mail_free_address(&oldadr
);
789 if(!new_entries
|| !*new_entries
){
790 q_status_message1(SM_ORDER
, 0, 4,
791 _("All of the addresses are already included in \"%s\""),
795 restore_state(&((*tas
)->state
));
799 restore_state(&state
);
805 /* count up size of new list */
806 for(p
= new_entries
; p
!= NULL
&& *p
!= NULL
; p
++)
809 new_size
= p
- new_entries
;
810 tot_size
= old_size
+ new_size
;
811 abe_copy
->addr
.list
= (char **) fs_get((tot_size
+1) * sizeof(char *));
812 memset((void *) abe_copy
->addr
.list
, 0, (tot_size
+1) * sizeof(char *));
814 if(abe
->tag
== List
){
815 for(i
= 0; i
< old_size
; i
++)
816 abe_copy
->addr
.list
[i
] = cpystr(abe
->addr
.list
[i
]);
819 abe_copy
->addr
.list
[0] = cpystr(abe
->addr
.addr
);
822 /* add new addresses to list */
823 if(tot_size
== 1 && addr
)
824 abe_copy
->addr
.list
[0] = cpystr(addr
);
826 for(i
= 0; i
< new_size
; i
++)
827 abe_copy
->addr
.list
[old_size
+ i
] = cpystr(new_entries
[i
]);
829 abe_copy
->addr
.list
[tot_size
] = NULL
;
831 if(F_ON(F_DISABLE_TAKE_FULLNAMES
, ps_global
)){
832 for(i
= 0; abe_copy
->addr
.list
[i
]; i
++){
835 tmp_a_string
= cpystr(abe_copy
->addr
.list
[i
]);
836 rfc822_parse_adrlist(&a
, tmp_a_string
, fakedomain
);
838 fs_give((void **) &tmp_a_string
);
841 simple_a
= simple_addr_string(a
, tmp_20k_buf
, SIZEOF_20KBUF
);
842 mail_free_address(&a
);
845 /* replace the old addr string with one with no full name */
846 if(simple_a
&& *simple_a
){
847 if(abe_copy
->addr
.list
[i
])
848 fs_give((void **) &abe_copy
->addr
.list
[i
]);
850 abe_copy
->addr
.list
[i
] = cpystr(simple_a
);
855 edit_entry(abook
, abe_copy
, (a_c_arg_t
) entry_num
, old_tag
, 0, NULL
, cmd
);
860 restore_state(&((*tas
)->state
));
864 restore_state(&state
);
868 take_to_addrbooks_cancel
:
869 q_status_message(SM_INFO
, 0, 2, _("Address book addition cancelled"));
871 restore_state(&((*tas
)->state
));
875 restore_state(&state
);
880 * Prep addrbook for TakeAddr add operation.
882 * Arg: savep -- Address of a pointer to save addrbook state in.
883 * stp -- Address of a pointer to save addrbook state in.
885 * Returns: a PerAddrBook pointer, or NULL.
888 setup_for_addrbook_add(SAVE_STATE_S
*state
, int command_line
, char *cmd
)
891 int save_rem_abook_valid
= 0;
896 if(as
.n_addrbk
== 0){
897 q_status_message(SM_ORDER
, 3, 4, _("No address book configured!"));
901 pab
= use_this_addrbook(command_line
, cmd
);
906 if((pab
->type
& REMOTE_VIA_IMAP
) && ps_global
->remote_abook_validity
== -1){
907 save_rem_abook_valid
= -1;
908 ps_global
->remote_abook_validity
= 0;
911 /* initialize addrbook so we can add to it */
912 init_abook(pab
, Open
);
914 if(save_rem_abook_valid
)
915 ps_global
->remote_abook_validity
= save_rem_abook_valid
;
917 if(pab
->ostatus
!= Open
){
918 q_status_message(SM_ORDER
, 3, 4, _("Can't open address book!"));
922 if(pab
->access
!= ReadWrite
){
923 if(pab
->access
== ReadOnly
)
924 q_status_message(SM_ORDER
, 0, 4, _("AddressBook is Read Only"));
925 else if(pab
->access
== NoAccess
)
926 q_status_message(SM_ORDER
, 3, 4,
927 _("AddressBook not accessible, permission denied"));
937 * Interact with user to figure out which address book they want to add a
938 * new entry (TakeAddr) to.
940 * Args: command_line -- just the line to prompt on
942 * Results: returns a pab pointing to the selected addrbook, or NULL.
945 use_this_addrbook(int command_line
, char *cmd
)
949 PerAddrBook
*pab
, *the_only_pab
;
950 #define MAX_ABOOK 2000
951 int i
, abook_num
, count_read_write
;
952 char addrbook
[MAX_ABOOK
+ 1],
953 prompt
[MAX_ABOOK
+ 81];
954 static ESCKEY_S ekey
[] = {
956 {ctrl('P'), 10, "^P", N_("Prev AddrBook")},
957 {ctrl('N'), 11, "^N", N_("Next AddrBook")},
958 {KEY_UP
, 10, "", ""},
959 {KEY_DOWN
, 11, "", ""},
960 {-1, 0, NULL
, NULL
}};
962 dprint((9, "- use_this_addrbook -\n"));
964 /* check for only one ReadWrite addrbook */
965 count_read_write
= 0;
966 for(i
= 0; i
< as
.n_addrbk
; i
++){
969 * NoExists is counted, too, so the user can add to an empty
970 * addrbook the first time.
972 if(pab
->access
== ReadWrite
||
973 pab
->access
== NoExists
||
974 pab
->access
== MaybeRorW
){
976 the_only_pab
= &as
.adrbks
[i
];
980 /* only one usable addrbook, use it */
981 if(count_read_write
== 1)
982 return(the_only_pab
);
984 /* no addrbook to write to */
985 if(count_read_write
== 0){
986 q_status_message2(SM_ORDER
| SM_DING
, 3, 4,
987 "No %sAddressbook to %s to!",
988 (as
.n_addrbk
> 0) ? "writable " : "", cmd
);
992 /* start with the first addrbook */
994 pab
= &as
.adrbks
[abook_num
];
995 strncpy(addrbook
, pab
->abnick
, sizeof(addrbook
)-1);
996 addrbook
[sizeof(addrbook
)-1] = '\0';
997 snprintf(prompt
, sizeof(prompt
), "%c%s to which addrbook : %s",
998 islower((unsigned char)(*cmd
)) ? toupper((unsigned char)*cmd
) : *cmd
,
1000 (pab
->access
== ReadOnly
|| pab
->access
== NoAccess
) ?
1001 "[ReadOnly] " : "");
1002 prompt
[sizeof(prompt
)-1] = '\0';
1004 ps_global
->mangled_footer
= 1;
1009 q_status_message1(SM_ORDER
, 3, 4, _("No addressbook \"%s\""),
1013 help
= (help
== NO_HELP
? h_oe_chooseabook
: NO_HELP
);
1015 flags
= OE_APPEND_CURRENT
;
1016 rc
= optionally_enter(addrbook
, command_line
, 0, sizeof(addrbook
),
1017 prompt
, ekey
, help
, &flags
);
1019 if(rc
== 1){ /* ^C */
1022 snprintf(capcmd
, sizeof(capcmd
),
1024 islower((unsigned char)(*cmd
)) ? toupper((unsigned char)*cmd
)
1027 capcmd
[sizeof(capcmd
)-1] = '\0';
1028 cmd_cancelled(capcmd
);
1032 if(rc
== 10){ /* Previous addrbook */
1034 abook_num
= as
.n_addrbk
- 1;
1036 pab
= &as
.adrbks
[abook_num
];
1037 strncpy(addrbook
, pab
->abnick
, sizeof(addrbook
)-1);
1038 addrbook
[sizeof(addrbook
)-1] = '\0';
1039 snprintf(prompt
, sizeof(prompt
), "%s to which addrbook : %s", cmd
,
1040 (pab
->access
== ReadOnly
|| pab
->access
== NoAccess
) ?
1041 "[ReadOnly] " : "");
1042 prompt
[sizeof(prompt
)-1] = '\0';
1044 else if(rc
== 11){ /* Next addrbook */
1045 if(++abook_num
> as
.n_addrbk
- 1)
1048 pab
= &as
.adrbks
[abook_num
];
1049 strncpy(addrbook
, pab
->abnick
, sizeof(addrbook
)-1);
1050 addrbook
[sizeof(addrbook
)-1] = '\0';
1051 snprintf(prompt
, sizeof(prompt
), "%s to which addrbook : %s", cmd
,
1052 (pab
->access
== ReadOnly
|| pab
->access
== NoAccess
) ?
1053 "[ReadOnly] " : "");
1054 prompt
[sizeof(prompt
)-1] = '\0';
1057 }while(rc
== 2 || rc
== 3 || rc
== 4 || rc
== 10 || rc
== 11 || rc
== 12 ||
1058 !(pab
= check_for_addrbook(addrbook
)));
1060 ps_global
->mangled_footer
= 1;
1070 * Return a pab pointer to the addrbook which corresponds to the argument.
1072 * Args: addrbook -- the string representing the addrbook.
1074 * Results: returns a PerAddrBook pointer for the referenced addrbook, NULL
1075 * if none. First the nicknames are checked and then the filenames.
1076 * This must be one of the existing addrbooks.
1079 check_for_addrbook(char *addrbook
)
1082 register PerAddrBook
*pab
;
1084 for(i
= 0; i
< as
.n_addrbk
; i
++){
1085 pab
= &as
.adrbks
[i
];
1086 if(strcmp(pab
->abnick
, addrbook
) == 0)
1093 for(i
= 0; i
< as
.n_addrbk
; i
++){
1094 pab
= &as
.adrbks
[i
];
1095 if(strcmp(pab
->filename
, addrbook
) == 0)
1107 * Screen for selecting which addresses to Take to address book.
1109 * Args: ps -- Pine state
1110 * ta_list -- Screen is formed from this list of addresses
1111 * how_many_selected -- how many checked initially in ListMode
1112 * mode -- which mode to start in
1114 * Result: an address book may be updated
1115 * Returns -- 0 normally
1116 * 1 if it returns before redrawing screen
1119 takeaddr_screen(struct pine
*ps
, TA_S
*ta_list
, int how_many_selected
,
1120 ScreenMode mode
, TA_STATE_S
**tas
, char *command
)
1123 int cmd
, dline
, give_warn_message
, command_line
;
1125 directly_to_take
= 0,
1128 TA_S
*current
= NULL
,
1133 struct key_menu
*km
;
1135 dprint((2, "- takeaddr_screen -\n"));
1137 command_line
= -FOOTER_ROWS(ps
); /* third line from the bottom */
1139 screen
.current
= screen
.top_line
= NULL
;
1142 if(ta_list
== NULL
){
1143 /* TRANSLATORS: something like
1144 No addresses to save, cancelled */
1145 q_status_message1(SM_INFO
, 0, 2, "No addresses to %s, cancelled",
1150 current
= first_sel_taline(ta_list
);
1151 ps
->mangled_screen
= 1;
1152 ta_screen
= &screen
;
1154 if(is_talist_of_one(current
)){
1156 screen
.mode
= SingleMode
;
1158 else if(screen
.mode
== ListMode
)
1159 q_status_message(SM_INFO
, 0, 1,
1160 _("List mode: Use \"X\" to mark addresses to be included in list"));
1162 q_status_message(SM_INFO
, 0, 1,
1163 _("Single mode: Use \"P\" or \"N\" to select desired address"));
1170 ps
->mangled_body
= 1;
1174 if(screen
.mode
== ListMode
)
1175 ps
->redrawer
= takeaddr_screen_redrawer_list
;
1177 ps
->redrawer
= takeaddr_screen_redrawer_single
;
1179 if(ps
->mangled_screen
){
1180 ps
->mangled_header
= 1;
1181 ps
->mangled_footer
= 1;
1182 ps
->mangled_body
= 1;
1183 ps
->mangled_screen
= 0;
1186 /*----------- Check for new mail -----------*/
1187 if(new_mail(0, NM_TIMING(ch
), NM_STATUS_MSG
| NM_DEFER_SORT
) >= 0)
1188 ps
->mangled_header
= 1;
1191 mswin_beginupdate();
1193 if(ps
->mangled_header
){
1196 snprintf(tbuf
, sizeof(tbuf
), "TAKE ADDRESS SCREEN (%s Mode)",
1197 (screen
.mode
== ListMode
) ? "List"
1199 tbuf
[sizeof(tbuf
)-1] = '\0';
1200 set_titlebar(tbuf
, ps
->mail_stream
, ps
->context_current
,
1201 ps
->cur_folder
, ps
->msgmap
, 1, FolderName
, 0, 0,
1203 ps
->mangled_header
= 0;
1206 dline
= update_takeaddr_screen(ps
, current
, &screen
, &cursor_pos
);
1207 if(F_OFF(F_SHOW_CURSOR
, ps
)){
1208 cursor_pos
.row
= ps
->ttyo
->screen_rows
- FOOTER_ROWS(ps
);
1212 /*---- This displays new mail notification, or errors ---*/
1214 FOOTER_ROWS(ps_global
) = 3;
1215 mark_status_unknown();
1218 display_message(ch
);
1220 FOOTER_ROWS(ps_global
) = 1;
1221 mark_status_unknown();
1224 /*---- Redraw footer ----*/
1225 if(ps
->mangled_footer
){
1229 FOOTER_ROWS(ps
) = 3;
1234 ps
->mangled_footer
= 0;
1236 km
= (screen
.mode
== ListMode
) ? &ta_keymenu_lm
: &ta_keymenu_sm
;
1238 menu_clear_binding(km
, KEY_LEFT
);
1239 menu_clear_binding(km
, KEY_RIGHT
);
1240 if(F_ON(F_ARROW_NAV
, ps_global
)){
1243 if((cmd
= menu_clear_binding(km
, '<')) != MC_UNKNOWN
){
1244 menu_add_binding(km
, '<', cmd
);
1245 menu_add_binding(km
, KEY_LEFT
, cmd
);
1248 if((cmd
= menu_clear_binding(km
, '>')) != MC_UNKNOWN
){
1249 menu_add_binding(km
, '>', cmd
);
1250 menu_add_binding(km
, KEY_RIGHT
, cmd
);
1254 draw_keymenu(km
, bitmap
, ps
->ttyo
->screen_cols
,
1255 1 - FOOTER_ROWS(ps_global
), 0, FirstMenu
);
1258 FOOTER_ROWS(ps
) = 1;
1259 mark_keymenu_dirty();
1266 /*------ Read the command from the keyboard ----*/
1267 MoveCursor(cursor_pos
.row
, cursor_pos
.col
);
1269 if(directly_to_take
){ /* bypass this screen */
1271 blank_keymenu(ps_global
->ttyo
->screen_rows
- 2, 0);
1275 mouse_in_content(KEY_MOUSE
, -1, -1, 0, 0);
1276 register_mfunc(mouse_in_content
, HEADER_ROWS(ps_global
), 0,
1277 ps_global
->ttyo
->screen_rows
- (FOOTER_ROWS(ps
)+1),
1278 ps_global
->ttyo
->screen_cols
);
1282 mswin_setscrollcallback(ta_scroll_callback
);
1284 ch
= READ_COMMAND(&utf8str
);
1286 clear_mfunc(mouse_in_content
);
1290 mswin_setscrollcallback(NULL
);
1292 cmd
= menu_command(ch
, km
);
1293 if (ta_screen
->current
)
1294 current
= ta_screen
->current
;
1312 case MC_HELP
: /* help! */
1313 if(FOOTER_ROWS(ps_global
) == 1 && km_popped
== 0){
1315 ps_global
->mangled_footer
= 1;
1319 helper(h_takeaddr_screen
, _("HELP FOR TAKE ADDRESS SCREEN"),
1321 ps
->mangled_screen
= 1;
1324 case MC_EXIT
: /* exit takeaddr screen */
1325 q_status_message(SM_INFO
, 0, 2, _("Address book addition cancelled"));
1331 if(ta_do_take(current
, how_many_selected
, command_line
, tas
,
1335 directly_to_take
= 0;
1339 case MC_CHARDOWN
: /* next list element */
1340 if((ctmp
= next_sel_taline(current
)) != NULL
)
1343 q_status_message(SM_INFO
, 0, 1, _("Already on last line."));
1347 case MC_CHARUP
: /* previous list element */
1348 if((ctmp
= pre_sel_taline(current
)) != NULL
)
1351 q_status_message(SM_INFO
, 0, 1, _("Already on first line."));
1355 case MC_PAGEDN
: /* page forward */
1356 give_warn_message
= 1;
1357 while(dline
++ < ps
->ttyo
->screen_rows
- FOOTER_ROWS(ps
)){
1358 if((ctmp
= next_sel_taline(current
)) != NULL
){
1360 give_warn_message
= 0;
1366 if(give_warn_message
)
1367 q_status_message(SM_INFO
, 0, 1, _("Already on last page."));
1371 case MC_PAGEUP
: /* page backward */
1372 /* move to top of screen */
1373 give_warn_message
= 1;
1374 while(dline
-- > HEADER_ROWS(ps_global
)){
1375 if((ctmp
= pre_sel_taline(current
)) != NULL
){
1377 give_warn_message
= 0;
1383 /* page back one screenful */
1384 while(++dline
< ps
->ttyo
->screen_rows
- FOOTER_ROWS(ps
)){
1385 if((ctmp
= pre_sel_taline(current
)) != NULL
){
1387 give_warn_message
= 0;
1393 if(give_warn_message
)
1394 q_status_message(SM_INFO
, 0, 1, _("Already on first page."));
1398 case MC_WHEREIS
: /* whereis */
1399 if((ctmp
= whereis_taline(current
)) != NULL
)
1402 ps
->mangled_footer
= 1;
1414 mouse_get_last(NULL
, &mp
);
1415 mp
.row
-= HEADER_ROWS(ps_global
);
1416 ctmp
= screen
.top_line
;
1418 if(screen
.mode
== SingleMode
){
1419 if(ta_do_take(current
, how_many_selected
, command_line
,
1423 directly_to_take
= 0;
1426 current
->checked
= !current
->checked
; /* flip it */
1427 how_many_selected
+= (current
->checked
? 1 : -1);
1431 while(mp
.row
&& ctmp
!= NULL
){
1433 do ctmp
= ctmp
->next
;
1434 while(ctmp
!= NULL
&& ctmp
->skip_it
&& !ctmp
->print
);
1437 if(ctmp
!= NULL
&& !ctmp
->skip_it
)
1447 ps
->mangled_screen
= 1;
1450 case MC_CHOICE
: /* [UN]select this addr */
1451 current
->checked
= !current
->checked
; /* flip it */
1452 how_many_selected
+= (current
->checked
? 1 : -1);
1455 case MC_SELALL
: /* select all */
1456 how_many_selected
= ta_mark_all(first_sel_taline(current
));
1457 ps
->mangled_body
= 1;
1460 case MC_UNSELALL
: /* unselect all */
1461 how_many_selected
= ta_unmark_all(first_sel_taline(current
));
1462 ps
->mangled_body
= 1;
1465 case MC_LISTMODE
: /* switch to SingleMode */
1466 if(screen
.mode
== ListMode
){
1467 screen
.mode
= SingleMode
;
1468 q_status_message(SM_INFO
, 0, 1,
1469 _("Single mode: Use \"P\" or \"N\" to select desired address"));
1472 screen
.mode
= ListMode
;
1473 q_status_message(SM_INFO
, 0, 1,
1474 _("List mode: Use \"X\" to mark addresses to be included in list"));
1476 if(how_many_selected
<= 1){
1478 ta_unmark_all(first_sel_taline(current
));
1479 current
->checked
= 1;
1480 how_many_selected
++;
1484 ps
->mangled_screen
= 1;
1488 case MC_NONE
: /* simple timeout */
1492 /* Unbound (or not dealt with) keystroke */
1499 bogus_command(ch
, F_ON(F_USE_FK
, ps
) ? "F1" : "?");
1503 bogus_utf8_command(utf8str
, F_ON(F_USE_FK
, ps
) ? "F1" : "?");
1508 ps
->mangled_screen
= 1;
1515 * Do what takeaddr_screen does except bypass the takeaddr_screen and
1516 * go directly to do_take.
1519 takeaddr_bypass(struct pine
*ps
, TA_S
*current
, TA_STATE_S
**tasp
)
1521 TA_SCREEN_S screen
; /* We have to fake out ta_do_take because */
1522 /* we're bypassing takeaddr_screen. */
1523 ta_screen
= &screen
;
1524 ta_screen
->mode
= SingleMode
;
1525 current
= first_sel_taline(current
);
1526 (void) ta_do_take(current
, 1, -FOOTER_ROWS(ps_global
), tasp
, _("save"));
1527 ps
->mangled_screen
= 1;
1535 ta_do_take(TA_S
*current
, int how_many_selected
, int command_line
,
1536 TA_STATE_S
**tas
, char *cmd
)
1538 return((ta_screen
->mode
== ListMode
)
1539 ? ta_take_marked_addrs(how_many_selected
,
1540 first_sel_taline(current
),
1541 command_line
, tas
, cmd
)
1542 : ta_take_single_addr(current
, command_line
, tas
, cmd
));
1547 * WhereIs for TakeAddr screen.
1549 * Returns the line match is found in or NULL.
1552 whereis_taline(TA_S
*current
)
1555 int rc
, found
= 0, wrapped
= 0, flags
;
1556 char *result
= NULL
, buf
[MAX_SEARCH
+1], tmp
[MAX_SEARCH
+20];
1557 static char last
[MAX_SEARCH
+1];
1559 static ESCKEY_S ekey
[] = {
1561 {ctrl('Y'), 10, "^Y", N_("Top")},
1562 {ctrl('V'), 11, "^V", N_("Bottom")},
1563 {-1, 0, NULL
, NULL
}};
1568 /*--- get string ---*/
1570 snprintf(tmp
, sizeof(tmp
), _("Word to find %s%.*s%s: "),
1571 (last
[0]) ? "[" : "",
1572 MAX_SEARCH
, (last
[0]) ? last
: "", /* MAX_SEARCH == sizeof(tmp) - 20 */
1573 (last
[0]) ? "]" : "");
1574 tmp
[sizeof(tmp
)-1] = '\0';
1576 flags
= OE_APPEND_CURRENT
| OE_KEEP_TRAILING_SPACE
;
1578 rc
= optionally_enter(buf
,-FOOTER_ROWS(ps_global
),0,sizeof(buf
),
1579 tmp
,ekey
,help
,&flags
);
1581 help
= help
== NO_HELP
? h_config_whereis
: NO_HELP
;
1582 else if(rc
== 0 || rc
== 1 || rc
== 10 || rc
== 11 || !buf
[0]){
1583 if(rc
== 0 && !buf
[0] && last
[0]){
1584 strncpy(buf
, last
, sizeof(buf
)-1);
1585 buf
[sizeof(buf
)-1] = '\0';
1592 if(rc
== 0 && buf
[0]){
1594 while((p
= next_taline(p
)) != NULL
)
1595 if(srchstr((char *)rfc1522_decode_to_utf8((unsigned char *)tmp_20k_buf
,
1596 SIZEOF_20KBUF
, p
->strvalue
),
1603 p
= first_taline(current
);
1606 if(srchstr((char *)rfc1522_decode_to_utf8((unsigned char *)tmp_20k_buf
,
1607 SIZEOF_20KBUF
, p
->strvalue
),
1618 current
= first_sel_taline(current
);
1619 result
= _("Searched to top");
1622 current
= last_sel_taline(current
);
1623 result
= _("Searched to bottom");
1627 result
= _("WhereIs cancelled");
1632 result
= wrapped
? _("Search wrapped to beginning") : _("Word found");
1633 strncpy(last
, buf
, sizeof(last
)-1);
1634 last
[sizeof(last
)-1] = '\0';
1637 q_status_message(SM_ORDER
,0,3,result
? result
: _("Word not found"));
1643 * Call the addrbook functions which add the checked addresses.
1645 * Args: how_many_selected -- how many addresses are checked
1646 * f_line -- the first ta line
1648 * Returns: 1 -- we're done, caller should return
1649 * 0 -- we're not done
1652 ta_take_marked_addrs(int how_many_selected
, TA_S
*f_line
, int command_line
,
1653 TA_STATE_S
**tas
, char *cmd
)
1658 if(how_many_selected
== 0){
1659 q_status_message(SM_ORDER
, 0, 4,
1660 _("No addresses marked for taking. Use ExitTake to leave TakeAddr screen"));
1664 if(how_many_selected
== 1){
1665 for(p
= f_line
; p
; p
= next_sel_taline(p
))
1666 if(p
->checked
&& !p
->skip_it
)
1671 (p
->nickname
&& p
->nickname
[0]) ? p
->nickname
: NULL
,
1672 (p
->fullname
&& p
->fullname
[0]) ? p
->fullname
: NULL
,
1673 (p
->fcc
&& p
->fcc
[0]) ? p
->fcc
: NULL
,
1674 (p
->comment
&& p
->comment
[0]) ? p
->comment
: NULL
,
1675 command_line
, tas
, cmd
);
1678 new_list
= list_of_checked(f_line
);
1679 for(p
= f_line
; p
; p
= next_sel_taline(p
))
1680 if(p
->checked
&& !p
->skip_it
)
1683 take_to_addrbooks_frontend(new_list
, p
? p
->nickname
: NULL
,
1684 p
? p
->fullname
: NULL
, NULL
, p
? p
->fcc
: NULL
,
1685 p
? p
->comment
: NULL
, command_line
, tas
, cmd
);
1686 free_list_array(&new_list
);
1694 ta_take_single_addr(TA_S
*cur
, int command_line
, TA_STATE_S
**tas
, char *cmd
)
1696 add_abook_entry(cur
,
1697 (cur
->nickname
&& cur
->nickname
[0]) ? cur
->nickname
: NULL
,
1698 (cur
->fullname
&& cur
->fullname
[0]) ? cur
->fullname
: NULL
,
1699 (cur
->fcc
&& cur
->fcc
[0]) ? cur
->fcc
: NULL
,
1700 (cur
->comment
&& cur
->comment
[0]) ? cur
->comment
: NULL
,
1701 command_line
, tas
, cmd
);
1708 * Manage display of the Take Address screen.
1710 * Args: ps -- pine state
1711 * current -- the current TA line
1712 * screen -- the TA screen
1713 * cursor_pos -- return good cursor position here
1716 update_takeaddr_screen(struct pine
*ps
, TA_S
*current
, TA_SCREEN_S
*screen
, Pos
*cursor_pos
)
1722 char buf1
[6*MAX_SCREEN_COLS
+ 30];
1723 char buf2
[6*MAX_SCREEN_COLS
+ 30];
1725 int screen_width
= ps
->ttyo
->screen_cols
;
1728 cpos
.row
= HEADER_ROWS(ps
); /* default return value */
1730 /* calculate top line of display */
1734 if (ta_screen
->top_line
){
1735 for(dline
= 0, ctmp
= ta_screen
->top_line
;
1736 ctmp
&& ctmp
!= current
; ctmp
= next_taline(ctmp
))
1739 if (ctmp
&& (dline
< ps
->ttyo
->screen_rows
- HEADER_ROWS(ps
)
1741 top_line
= ta_screen
->top_line
;
1746 ctmp
= top_line
= first_taline(current
);
1748 if(((dline
++) % (ps
->ttyo
->screen_rows
- HEADER_ROWS(ps
)
1749 - FOOTER_ROWS(ps
))) == 0)
1751 while(ctmp
!= current
&& (ctmp
= next_taline(ctmp
)));
1756 * Figure out how far down the top line is from the top and how many
1757 * total lines there are. Dumb to loop every time thru, but
1758 * there aren't that many lines, and it's cheaper than rewriting things
1759 * to maintain a line count in each structure...
1761 for(dline
= 0, ctmp
= pre_taline(top_line
); ctmp
; ctmp
= pre_taline(ctmp
))
1764 scroll_setpos(dline
);
1766 for(ctmp
= next_taline(top_line
); ctmp
; ctmp
= next_taline(ctmp
))
1769 scroll_setrange(ps
->ttyo
->screen_rows
- FOOTER_ROWS(ps
) - HEADER_ROWS(ps
),
1774 /* mangled body or new page, force redraw */
1775 if(ps
->mangled_body
|| screen
->top_line
!= top_line
)
1776 screen
->current
= NULL
;
1778 /* find width of longest line for nicer formatting */
1780 for(ctmp
= first_taline(top_line
); ctmp
; ctmp
= next_taline(ctmp
)){
1786 && longest
< (width
= utf8_width((char *)rfc1522_decode_to_utf8((unsigned char *)tmp_20k_buf
,
1787 SIZEOF_20KBUF
, ctmp
->strvalue
))))
1791 #define LENGTH_OF_THAT_STRING 5 /* "[X] " */
1792 longest
= MIN(longest
, ps
->ttyo
->screen_cols
);
1794 /* loop thru painting what's needed */
1795 for(dline
= 0, ctmp
= top_line
;
1796 dline
< ps
->ttyo
->screen_rows
- FOOTER_ROWS(ps
) - HEADER_ROWS(ps
);
1797 dline
++, ctmp
= next_taline(ctmp
)){
1800 * only fall thru painting if something needs painting...
1802 if(!ctmp
|| !screen
->current
|| ctmp
== screen
->current
||
1803 ctmp
== top_line
|| ctmp
== current
){
1804 ClearLine(dline
+ HEADER_ROWS(ps
));
1805 if(!ctmp
|| !ctmp
->strvalue
)
1810 if(ctmp
== current
){
1811 cpos
.row
= dline
+ HEADER_ROWS(ps
); /* col set below */
1818 j
= LENGTH_OF_THAT_STRING
;
1821 * Copy the value to a temp buffer expanding tabs, and
1822 * making sure not to write beyond screen right...
1824 q
= (char *) rfc1522_decode_to_utf8((unsigned char *)tmp_20k_buf
,
1825 SIZEOF_20KBUF
, ctmp
->strvalue
);
1827 for(i
= 0; q
[i
] && j
< ps
->ttyo
->screen_cols
&& p
-buf1
< sizeof(buf1
); i
++){
1828 if(q
[i
] == ctrl('I')){
1831 while(j
< ps
->ttyo
->screen_cols
&& ((++j
)&0x07) && p
-buf1
< sizeof(buf1
));
1840 if(p
-buf1
< sizeof(buf1
))
1843 if(utf8_width(buf1
) < longest
){
1844 (void) utf8_pad_to_width(buf2
, buf1
, sizeof(buf2
), longest
, 1);
1845 /* it's expected to be in buf1 below */
1846 strncpy(buf1
, buf2
, sizeof(buf1
));
1847 buf1
[sizeof(buf1
)-1] = '\0';
1850 /* mark lines which have check marks */
1851 if(ctmp
== current
){
1852 if(screen
->mode
== ListMode
){
1853 snprintf(buf2
, sizeof(buf2
), "[%c] %s", ctmp
->checked
? 'X' : SPACE
, buf1
);
1854 buf2
[sizeof(buf2
)-1] = '\0';
1855 cpos
.col
= 1; /* position on the X */
1858 snprintf(buf2
, sizeof(buf2
), " %s", buf1
);
1859 buf2
[sizeof(buf2
)-1] = '\0';
1860 cpos
.col
= 5; /* 5 spaces before text */
1865 int width
, actual_width
;
1869 * In buf2 make ------string--------
1870 * which reaches all the way across the screen. String will
1871 * already have a leading and trailing space.
1873 width
= utf8_width(buf1
);
1875 if(width
> screen_width
){
1876 actual_width
= utf8_truncate(buf1
, screen_width
);
1877 /* it might be 1 less */
1878 if(actual_width
< screen_width
&& (len
=strlen(buf1
))+1 < sizeof(buf1
)){
1884 snprintf(buf2
, sizeof(buf2
), "%s%s",
1885 repeat_char((screen_width
-width
)/2, '-'), buf1
);
1886 buf2
[sizeof(buf2
)-1] = '\0';
1888 width
= utf8_width(buf2
);
1889 snprintf(buf2
+len
, sizeof(buf2
)-len
, "%s",
1890 repeat_char(screen_width
-width
, '-'));
1891 buf2
[sizeof(buf2
)-1] = '\0';
1895 if(screen
->mode
== ListMode
) /* 6*MAX_SCREEN_COLS + 24 = sizeof(buf2)-6 */
1896 snprintf(buf2
, sizeof(buf2
), "[%c] %.*s", ctmp
->checked
? 'X' : SPACE
,
1897 6*MAX_SCREEN_COLS
+ 24, buf1
);
1899 snprintf(buf2
, sizeof(buf2
), " %.*s", 6*MAX_SCREEN_COLS
+24, buf1
);
1901 buf2
[sizeof(buf2
)-1] = '\0';
1905 PutLine0(dline
+ HEADER_ROWS(ps
), 0, buf2
);
1911 ps
->mangled_body
= 0;
1912 screen
->top_line
= top_line
;
1913 screen
->current
= current
;
1922 takeaddr_screen_redrawer_list(void)
1924 ps_global
->mangled_body
= 1;
1925 (void)update_takeaddr_screen(ps_global
, ta_screen
->current
, ta_screen
,
1931 takeaddr_screen_redrawer_single(void)
1933 ps_global
->mangled_body
= 1;
1934 (void)update_takeaddr_screen(ps_global
, ta_screen
->current
, ta_screen
,
1939 /* jpf work in progress
1940 * Execute command to take addresses out of message and put in the address book
1942 * Args: ps -- pine state
1943 * msgmap -- the MessageMap
1944 * agg -- this is aggregate operation if set
1946 * Result: The entry is added to an address book.
1949 cmd_take_addr(struct pine
*ps
, MSGNO_S
*msgmap
, int agg
)
1951 TA_S
*ta_list
= NULL
;
1952 int how_many_selected
= 0, rtype
;
1954 /* Ask user what kind of Take they want to do */
1955 if(!agg
&& F_ON(F_ENABLE_ROLE_TAKE
, ps
)){
1956 rtype
= rule_setup_type(ps
,
1958 ((mn_get_total(msgmap
) > 0)
1959 ? (F_ON(F_ENABLE_TAKE_EXPORT
, ps
)
1960 ? (RS_INCADDR
| RS_INCEXP
)
1965 else if(F_ON(F_ENABLE_TAKE_EXPORT
, ps
) && mn_get_total(msgmap
) > 0)
1966 rtype
= rule_setup_type(ps
, RS_INCADDR
| RS_INCEXP
, "Take to : ");
1970 if(rtype
== 'x' || rtype
== 'Z'){
1972 cmd_cancelled(NULL
);
1973 else if(rtype
== 'Z')
1974 q_status_message(SM_ORDER
| SM_DING
, 3, 5,
1975 "Try turning on color with the Setup/Kolor command.");
1979 ps
->mangled_footer
= 1;
1985 LINES_TO_TAKE
*lines_to_take
= NULL
;
1987 rtype
= set_up_takeaddr('e', ps
, msgmap
, &ta_list
, &how_many_selected
,
1988 agg
? TA_AGG
: 0, NULL
);
1991 if(convert_ta_to_lines(ta_list
, &lines_to_take
)){
1992 while(lines_to_take
&& lines_to_take
->prev
)
1993 lines_to_take
= lines_to_take
->prev
;
1995 take_to_export(ps
, lines_to_take
);
1997 free_ltlines(&lines_to_take
);
2000 q_status_message(SM_ORDER
, 3, 4, _("Can't find anything to export"));
2013 role_take(ps
, msgmap
, rtype
);
2017 rtype
= set_up_takeaddr('a', ps
, msgmap
, &ta_list
, &how_many_selected
,
2018 agg
? TA_AGG
: 0, attached_addr_handler
);
2020 (void) takeaddr_screen(ps
, ta_list
, how_many_selected
,
2021 agg
? ListMode
: SingleMode
,
2032 free_talines(&ta_list
);
2033 env_for_pico_callback
= NULL
;
2034 body_for_pico_callback
= NULL
;
2036 return(rtype
>= 0 ? 1 : 0);
2041 attached_addr_handler(TA_S
*current
, int added
)
2044 int command_line
= -FOOTER_ROWS(ps_global
);
2046 snprintf(prompt
, sizeof(prompt
),
2047 "Take %d entries from attachment to addrbook all at once ",
2049 switch(want_to(prompt
, 'n', 'x', NO_HELP
, WT_NORM
)){
2051 if(take_without_edit(current
, added
, command_line
, NULL
, "take") >= 0)
2052 return(0); /* all taken care of */
2054 return(-1); /* problem */
2057 cmd_cancelled("Take");
2058 return(-1); /* problem */
2061 return(1); /* proceed */
2067 take_without_edit(TA_S
*ta_list
, int num_in_list
, int command_line
, TA_STATE_S
**tas
, char *cmd
)
2069 #define OURTMPBUFLEN 200
2070 PerAddrBook
*pab_dst
;
2071 SAVE_STATE_S state
; /* For saving state of addrbooks temporarily */
2072 int rc
, total_to_copy
;
2073 int how_many_dups
= 0, how_many_to_copy
= 0, skip_dups
= 0;
2075 int err
= 0, need_write
= 0, we_cancel
= 0;
2076 adrbk_cntr_t new_entry_num
;
2077 char warn
[2][MAX_NICKNAME
+1];
2078 char tmp
[OURTMPBUFLEN
];
2080 SWOOP_S
*swoop_list
= NULL
, *sw
;
2082 dprint((2, "\n - take_without_edit(%d) - \n",
2085 /* move to beginning of the list */
2087 while(ta_list
->prev
)
2088 ta_list
= ta_list
->prev
;
2090 pab_dst
= setup_for_addrbook_add(&state
, command_line
, cmd
);
2094 swoop_list
= (SWOOP_S
*)fs_get((num_in_list
+1) * sizeof(SWOOP_S
));
2095 memset((void *)swoop_list
, 0, (num_in_list
+1) * sizeof(SWOOP_S
));
2099 * Look through all the vcards for those with nicknames already
2100 * existing in the destination abook (dups) and build a list of
2101 * entries to be acted on.
2103 for(current
= ta_list
; current
; current
= current
->next
){
2104 adrbk_cntr_t dst_enum
;
2106 if(current
->skip_it
)
2109 /* check to see if this nickname already exists in the dest abook */
2110 if(current
->nickname
&& current
->nickname
[0]){
2113 current
->checked
= 0;
2114 abe
= adrbk_lookup_by_nick(pab_dst
->address_book
,
2115 current
->nickname
, &dst_enum
);
2117 * This nickname already exists.
2121 sw
->dst_enum
= dst_enum
;
2122 if(how_many_dups
< 2){
2123 strncpy(warn
[how_many_dups
], current
->nickname
, MAX_NICKNAME
);
2124 warn
[how_many_dups
][MAX_NICKNAME
] = '\0';
2137 * If there are some nicknames which already exist in the selected
2138 * abook, ask user what to do.
2140 if(how_many_dups
> 0){
2141 if(how_many_dups
== 1){
2142 if(how_many_to_copy
== 1 && num_in_list
== 1){
2143 ret
= 'T'; /* use Take */
2145 (*tas
)->state
= state
;
2146 (*tas
)->pab
= pab_dst
;
2152 snprintf(tmp
, sizeof(tmp
),
2153 "Entry with nickname \"%.*s\" already exists, replace ",
2154 OURTMPBUFLEN
-50, warn
[0]);
2157 else if(how_many_dups
== 2)
2158 snprintf(tmp
, sizeof(tmp
),
2159 "Nicknames \"%.*s\" and \"%.*s\" already exist, replace ",
2160 (OURTMPBUFLEN
-50)/2, warn
[0], (OURTMPBUFLEN
-50)/2, warn
[1]);
2162 snprintf(tmp
, sizeof(tmp
), "%d of the nicknames already exist, replace ",
2165 switch(want_to(tmp
, 'n', 'x', h_ab_copy_dups
, WT_NORM
)){
2180 * Because the deletes happen immediately we have to delete from high
2181 * entry number towards lower entry numbers so that we are deleting
2182 * the correct entries. In order to do that we'll sort the swoop_list
2183 * to give us a safe order.
2185 if(!skip_dups
&& how_many_dups
> 1)
2186 qsort((qsort_t
*)swoop_list
, (size_t)num_in_list
, sizeof(*swoop_list
),
2189 we_cancel
= busy_cue("Saving addrbook entries", NULL
, 0);
2190 total_to_copy
= how_many_to_copy
- (skip_dups
? how_many_dups
: 0);
2193 * Add the list of entries to the destination abook.
2195 for(sw
= swoop_list
; sw
&& sw
->ta
; sw
++){
2197 char abuf
[MAX_ADDRESS
+ 1];
2200 if(skip_dups
&& sw
->dup
)
2204 * Delete existing dups and replace them.
2208 /* delete the existing entry */
2210 if(adrbk_delete(pab_dst
->address_book
,
2211 (a_c_arg_t
)sw
->dst_enum
, 1, 0, 0, 0) == 0){
2215 q_status_message2(SM_ORDER
| SM_DING
, 3, 5,
2216 "Error replacing entry in %.200s: %.200s",
2218 error_description(errno
));
2225 * We need to count the number of addresses in this entry in order
2226 * to tell the adrbk routines if it is a List or a Single, and in
2227 * order to pass the right stuff to be added.
2229 count_of_addrs
= count_addrs(sw
->ta
->addr
);
2230 tag
= (count_of_addrs
> 1) ? List
: Single
;
2232 if(sw
->ta
->addr
->mailbox
&& sw
->ta
->addr
->mailbox
[0]){
2233 char *scratch
, *p
, *t
, *u
;
2238 es
= est_size(sw
->ta
->addr
);
2239 scratch
= (char *) fs_get(es
* sizeof(char));
2241 rbuf
.f
= dummy_soutr
;
2245 rbuf
.end
= scratch
+es
-1;
2246 rfc822_output_address_list(&rbuf
, sw
->ta
->addr
, 0L, NULL
);
2248 if((p
= srchstr(scratch
, "@" RAWFIELD
)) != NULL
){
2250 if(*t
== '&'){ /* find "leading" token */
2251 *t
++ = ' '; /* replace token */
2252 *p
= '\0'; /* tie off string */
2253 u
= (char *)rfc822_base64((unsigned char *)t
,
2254 (unsigned long)strlen(t
), &l
);
2255 *p
= '@'; /* restore 'p' */
2256 rplstr(p
, es
-(p
-scratch
), 12, ""); /* clear special token */
2257 rplstr(t
, es
-(t
-scratch
), strlen(t
), u
); /* Null u is handled */
2259 fs_give((void **)&u
);
2261 else if(t
== scratch
)
2265 strncpy(abuf
, scratch
, sizeof(abuf
)-1);
2266 abuf
[sizeof(abuf
)-1] = '\0';
2269 fs_give((void **)&scratch
);
2277 * Now we have a clean slate to work with.
2279 if(total_to_copy
<= 1)
2280 rc
= adrbk_add(pab_dst
->address_book
,
2284 tag
== Single
? abuf
: NULL
,
2294 rc
= adrbk_append(pab_dst
->address_book
,
2297 tag
== Single
? abuf
: NULL
,
2307 * If the entry we copied is a list, we also have to add
2308 * the list members to the copy.
2310 if(rc
== 0 && tag
== List
){
2311 int i
, save_sort_rule
;
2312 ADDRESS
*a
, *save_next
;
2315 list
= (char **)fs_get((count_of_addrs
+ 1) * sizeof(char *));
2316 memset((void *)list
, 0, (count_of_addrs
+1) * sizeof(char *));
2318 for(a
= sw
->ta
->addr
; a
; a
= a
->next
){
2319 save_next
= a
->next
;
2322 if(a
->mailbox
&& a
->mailbox
[0]){
2323 char *scratch
, *p
, *t
, *u
;
2329 scratch
= (char *) fs_get(es
* sizeof(char));
2331 rbuf
.f
= dummy_soutr
;
2335 rbuf
.end
= scratch
+es
-1;
2336 rfc822_output_address_list(&rbuf
, a
, 0L, NULL
);
2338 if((p
= srchstr(scratch
, "@" RAWFIELD
)) != NULL
){
2340 if(*t
== '&'){ /* find "leading" token */
2341 *t
++ = ' '; /* replace token */
2342 *p
= '\0'; /* tie off string */
2343 u
= (char *)rfc822_base64((unsigned char *)t
,
2344 (unsigned long)strlen(t
), &l
);
2345 *p
= '@'; /* restore 'p' */
2346 rplstr(p
, es
-(p
-scratch
), 12, ""); /* clear special token */
2347 rplstr(t
, es
-(t
-scratch
), strlen(t
), u
); /* Null u is handled */
2349 fs_give((void **)&u
);
2351 else if(t
== scratch
)
2355 strncpy(abuf
, scratch
, sizeof(abuf
)-1);
2356 abuf
[sizeof(abuf
)-1] = '\0';
2359 fs_give((void **)&scratch
);
2364 list
[i
++] = cpystr(abuf
);
2365 a
->next
= save_next
;
2369 * We want it to copy the list in the exact order
2370 * without sorting it.
2372 save_sort_rule
= pab_dst
->address_book
->sort_rule
;
2373 pab_dst
->address_book
->sort_rule
= AB_SORT_RULE_NONE
;
2375 rc
= adrbk_nlistadd(pab_dst
->address_book
,
2376 (a_c_arg_t
)new_entry_num
, NULL
, NULL
,
2379 pab_dst
->address_book
->sort_rule
= save_sort_rule
;
2380 free_list_array(&list
);
2384 q_status_message1(SM_ORDER
| SM_DING
, 3, 5,
2385 "Error saving: %.200s",
2386 error_description(errno
));
2393 int sort_happened
= 0;
2395 if(adrbk_write(pab_dst
->address_book
, 0, NULL
, &sort_happened
, 0, 1)){
2401 ps_global
->mangled_screen
= 1;
2409 restore_state(&state
);
2412 fs_give((void **)&swoop_list
);
2414 ps_global
->mangled_footer
= 1;
2417 #define CAPCMDLEN 50
2418 char capcmd
[CAPCMDLEN
];
2421 snprintf(capcmd
, sizeof(capcmd
),
2423 islower((unsigned char)(*cmd
)) ? toupper((unsigned char)*cmd
)
2425 CAPCMDLEN
-2, cmd
+1);
2427 q_status_message1(SM_ORDER
| SM_DING
, 3, 4,
2428 "%.200s only partially completed", capcmd
);
2430 cmd_cancelled(capcmd
);
2432 else if(ret
!= 'T' && total_to_copy
> 0){
2435 snprintf(tmp
, sizeof(tmp
), "Saved %d %s to \"%.*s\"",
2437 (total_to_copy
> 1) ? "entries" : "entry",
2438 OURTMPBUFLEN
-30, pab_dst
->abnick
);
2439 q_status_message(SM_ORDER
, 4, 4, tmp
);
2447 * Special case interface to allow a more interactive Save in the case where
2448 * the user seems to be wanting to save an exact copy of an existing entry.
2449 * For example, they might be trying to save a copy of a list with the intention
2450 * of changing it a little bit. The regular save doesn't allow this, since no
2451 * editing takes place, but this version plops them into the address book
2455 take_this_one_entry(struct pine
*ps
, TA_STATE_S
**tasp
, AdrBk
*abook
, long int cur_line
)
2459 char *fcc
= NULL
, *comment
= NULL
, *fullname
= NULL
,
2462 int how_many_selected
;
2463 TA_S
*current
= NULL
;
2465 dl
= dlist(cur_line
);
2468 q_status_message(SM_ORDER
, 0, 4, _("Nothing to save, cancelled"));
2472 if(dl
->type
== ListHead
|| dl
->type
== Simple
){
2473 fcc
= (abe
->fcc
&& abe
->fcc
[0]) ? abe
->fcc
: NULL
;
2474 comment
= (abe
->extra
&& abe
->extra
[0]) ? abe
->extra
: NULL
;
2475 fullname
= (abe
->fullname
&& abe
->fullname
[0]) ? abe
->fullname
: NULL
;
2476 nickname
= (abe
->nickname
&& abe
->nickname
[0]) ? abe
->nickname
: NULL
;
2479 addr
= abe_to_address(abe
, dl
, abook
, &how_many_selected
);
2481 addr
= mail_newaddr();
2482 addr
->host
= cpystr("");
2483 addr
->mailbox
= cpystr("");
2490 * Special case. When user is saving an entry with a runtime
2491 * ldap lookup address, they may be doing it because the lookup
2492 * has become stale. Give them a way to get the old address out
2493 * of the lookup entry so they can save that, instead.
2495 if(!addr
->personal
&& !strncmp(addr
->mailbox
, RUN_LDAP
, LEN_RL
)){
2496 LDAP_SERV_S
*info
= NULL
;
2498 static ESCKEY_S backup_or_ldap
[] = {
2499 {'b', 'b', "B", N_("Backup")},
2500 {'l', 'l', "L", N_("LDAP")},
2501 {-1, 0, NULL
, NULL
}};
2503 info
= break_up_ldap_server(addr
->mailbox
+ LEN_RL
);
2504 if(info
&& info
->mail
&& *info
->mail
)
2505 i
= radio_buttons(_("Copy backup address or retain LDAP search criteria ? "),
2506 -FOOTER_ROWS(ps_global
), backup_or_ldap
,
2508 h_ab_backup_or_ldap
, RB_NORM
);
2513 rfc822_parse_adrlist(&a
, info
->mail
, fakedomain
);
2517 fs_give((void **)&addr
->mailbox
);
2519 fs_give((void **)&addr
->host
);
2521 addr
->mailbox
= a
->mailbox
;
2523 addr
->host
= a
->host
;
2525 mail_free_address(&a
);
2530 free_ldap_server_info(&info
);
2532 #endif /* ENABLE_LDAP */
2533 current
= fill_in_ta(¤t
, addr
, 0, (char *)NULL
);
2538 * The empty string for the last argument is significant. Fill_in_ta
2539 * copies the whole adrlist into a single TA if there is a print
2542 if(dl
->type
== ListHead
)
2543 current
= fill_in_ta(¤t
, addr
, 1, "");
2545 current
= fill_in_ta(¤t
, addr
, 0, (char *)NULL
);
2551 "default case in take_this_one_entry, shouldn't happen\n"));
2555 if(current
->strvalue
&& !strcmp(current
->strvalue
, "@")){
2556 fs_give((void **)¤t
->strvalue
);
2557 if(fullname
&& fullname
[0])
2558 current
->strvalue
= cpystr(fullname
);
2559 else if(nickname
&& nickname
[0])
2560 current
->strvalue
= cpystr(nickname
);
2562 current
->strvalue
= cpystr("?");
2564 convert_possibly_encoded_str_to_utf8(¤t
->strvalue
);
2568 mail_free_address(&addr
);
2571 current
= first_sel_taline(current
);
2572 if(fullname
&& *fullname
){
2573 current
->fullname
= cpystr(fullname
);
2574 convert_possibly_encoded_str_to_utf8(¤t
->fullname
);
2578 current
->fcc
= cpystr(fcc
);
2579 convert_possibly_encoded_str_to_utf8(¤t
->fcc
);
2582 if(comment
&& *comment
){
2583 current
->comment
= cpystr(comment
);
2584 convert_possibly_encoded_str_to_utf8(¤t
->comment
);
2587 if(nickname
&& *nickname
){
2588 current
->nickname
= cpystr(nickname
);
2589 convert_possibly_encoded_str_to_utf8(¤t
->nickname
);
2592 takeaddr_bypass(ps
, current
, tasp
);
2595 q_status_message(SM_ORDER
, 0, 4, _("Nothing to save, cancelled"));
2597 free_talines(¤t
);
2602 * Execute command to save addresses out of vcard attachment.
2605 save_vcard_att(struct pine
*ps
, int qline
, long int msgno
, ATTACH_S
*a
)
2607 int how_many_selected
, j
;
2608 TA_S
*current
= NULL
;
2609 TA_STATE_S tas
, *tasp
;
2612 dprint((2, "\n - saving vcard attachment - \n"));
2614 j
= radio_buttons(_("Save to address book or Export to filesystem ? "),
2615 qline
, save_or_export
, 's', 'x',
2616 h_ab_save_exp
, RB_NORM
|RB_SEQ_SENSITIVE
);
2620 q_status_message(SM_INFO
, 0, 2, _("Address book save cancelled"));
2624 export_vcard_att(ps
, qline
, msgno
, a
);
2631 q_status_message(SM_ORDER
, 3, 3, "can't happen in save_vcard_att");
2635 dprint((2, "\n - saving attachment into address book - \n"));
2636 ps
->mangled_footer
= 1;
2638 how_many_selected
= process_vcard_atts(ps
->mail_stream
, msgno
, NULL
,
2639 a
->body
, a
->number
, ¤t
);
2640 if(how_many_selected
> 0){
2643 if(how_many_selected
== 1){
2644 takeaddr_bypass(ps
, current
, NULL
);
2646 else if(take_without_edit(current
, how_many_selected
, qline
,
2647 &tasp
, "save") == 'T'){
2651 how_many_selected
-=
2652 eliminate_dups_but_not_us(first_sel_taline(current
));
2654 (void)takeaddr_screen(ps
, current
, how_many_selected
, SingleMode
,
2658 * If takeaddr_screen or its children didn't do this for us,
2662 restore_state(&(tas
.state
));
2665 else if(how_many_selected
== 0)
2666 q_status_message(SM_ORDER
, 0, 3,
2667 _("Save cancelled: no entries in attachment"));
2669 free_talines(¤t
);
2674 * Execute command to export vcard attachment.
2677 export_vcard_att(struct pine
*ps
, int qline
, long int msgno
, ATTACH_S
*a
)
2679 int how_many_selected
, i
;
2681 STORE_S
*srcstore
= NULL
;
2683 static ESCKEY_S vcard_or_addresses
[] = {
2684 {'a', 'a', "A", N_("Address List")},
2685 {'v', 'v', "V", N_("VCard")},
2686 {-1, 0, NULL
, NULL
}};
2689 q_status_message(SM_ORDER
, 0, 3,
2690 "Alpine demo can't export addresses to files");
2694 dprint((2, "\n - exporting vcard attachment - \n"));
2696 i
= radio_buttons(_("Export list of addresses or vCard text ? "),
2697 qline
, vcard_or_addresses
, 'a', 'x',
2698 h_ab_export_vcard
, RB_NORM
|RB_SEQ_SENSITIVE
);
2702 q_status_message(SM_INFO
, 0, 2, _("Address book export cancelled"));
2709 write_attachment(qline
, msgno
, a
, "EXPORT");
2713 q_status_message(SM_ORDER
, 3, 3, _("can't happen in export_vcard_att"));
2717 ps
->mangled_footer
= 1;
2719 how_many_selected
= process_vcard_atts(ps
->mail_stream
, msgno
, NULL
,
2720 a
->body
, a
->number
, ¤t
);
2722 * Run through all of the list and run through
2723 * the addresses in each ta->addr, writing them into a storage object.
2724 * Then export to filesystem.
2727 if(how_many_selected
> 0 &&
2728 (srcstore
= so_get(srctype
, NULL
, EDIT_ACCESS
)) != NULL
){
2732 for(current
= first_taline(current
);
2734 current
= next_taline(current
)){
2736 for(aa
= current
->addr
; aa
; aa
= aa
->next
){
2739 so_puts(srcstore
, addr_list_string(aa
, NULL
, 0));
2741 so_puts(srcstore
, "\n");
2747 simple_export(ps
, so_text(srcstore
), srctype
, "addresses", NULL
);
2749 q_status_message(SM_ORDER
, 0, 3, _("No addresses to export"));
2754 if(how_many_selected
== 0)
2755 q_status_message(SM_ORDER
, 0, 3, _("Nothing to export"));
2757 q_status_message(SM_ORDER
,0,2, _("Error allocating space"));
2763 take_to_export(struct pine
*ps
, LINES_TO_TAKE
*lines_to_take
)
2765 CONF_S
*ctmp
= NULL
, *first_line
= NULL
;
2766 OPT_SCREEN_S screen
;
2768 char *help_title
= _("HELP FOR TAKE EXPORT SCREEN");
2770 ScreenMode listmode
= SingleMode
;
2772 for(li
= lines_to_take
; li
; li
= li
->next
){
2774 new_confline(&ctmp
);
2775 ctmp
->flags
|= CF_STARTITEM
;
2776 if(li
->flags
& LT_NOSELECT
)
2777 ctmp
->flags
|= CF_NOSELECT
;
2778 else if(!first_line
)
2781 p
= li
->printval
? li
->printval
: "";
2783 if(ctmp
->flags
& CF_NOSELECT
)
2784 ctmp
->value
= cpystr(p
);
2788 /* 5 is for "[X] " */
2790 ctmp
->value
= (char *)fs_get((l
+1) * sizeof(char));
2791 snprintf(ctmp
->value
, l
+1, " %s", p
);
2792 ctmp
->value
[l
] = '\0';
2795 /* this points to data, it doesn't have its own copy */
2796 ctmp
->d
.t
.exportval
= li
->exportval
? li
->exportval
: NULL
;
2797 ctmp
->d
.t
.selected
= 0;
2798 ctmp
->d
.t
.listmode
= &listmode
;
2800 ctmp
->tool
= take_export_tool
;
2801 ctmp
->help_title
= help_title
;
2802 ctmp
->help
= h_takeexport_screen
;
2803 ctmp
->keymenu
= &take_export_keymenu_sm
;
2807 q_status_message(SM_ORDER
, 3, 3, _("No lines to export"));
2809 memset(&screen
, 0, sizeof(screen
));
2810 conf_scroll_screen(ps
, &screen
, first_line
, _("Take Export"), NULL
, 0, NULL
);
2816 take_export_tool(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
)
2820 int some_selected
= 0, something_to_export
= 0;
2822 STORE_S
*srcstore
= NULL
;
2828 if((srcstore
= so_get(srctype
, NULL
, EDIT_ACCESS
)) != NULL
){
2829 if(*(*cl
)->d
.t
.listmode
== SingleMode
){
2831 if((*cl
)->d
.t
.exportval
&& (*cl
)->d
.t
.exportval
[0]){
2832 so_puts(srcstore
, (*cl
)->d
.t
.exportval
);
2833 so_puts(srcstore
, "\n");
2834 something_to_export
++;
2835 prompt_msg
= "selection";
2839 /* go to first line */
2840 for(ctmp
= *cl
; prev_confline(ctmp
); ctmp
= prev_confline(ctmp
))
2843 for(; ctmp
; ctmp
= next_confline(ctmp
))
2844 if(!(ctmp
->flags
& CF_NOSELECT
) && ctmp
->d
.t
.selected
){
2846 if(ctmp
->d
.t
.exportval
&& ctmp
->d
.t
.exportval
[0]){
2847 so_puts(srcstore
, ctmp
->d
.t
.exportval
);
2848 so_puts(srcstore
, "\n");
2849 something_to_export
++;
2850 prompt_msg
= "selections";
2857 q_status_message(SM_ORDER
, 0, 3, _("Error allocating space"));
2858 else if(something_to_export
)
2859 simple_export(ps
, so_text(srcstore
), srctype
, prompt_msg
, NULL
);
2860 else if(!some_selected
&& *(*cl
)->d
.t
.listmode
== ListMode
)
2861 q_status_message(SM_ORDER
, 0, 3, _("Use \"X\" to mark selections"));
2863 q_status_message(SM_ORDER
, 0, 3, _("Nothing to export"));
2871 if(*(*cl
)->d
.t
.listmode
== SingleMode
){
2873 * UnHide the checkboxes
2876 *(*cl
)->d
.t
.listmode
= ListMode
;
2878 /* go to first line */
2879 for(ctmp
= *cl
; prev_confline(ctmp
); ctmp
= prev_confline(ctmp
))
2882 for(; ctmp
; ctmp
= next_confline(ctmp
))
2883 if(!(ctmp
->flags
& CF_NOSELECT
) && ctmp
->value
){
2884 ctmp
->value
[0] = '[';
2885 ctmp
->value
[1] = ctmp
->d
.t
.selected
? 'X' : SPACE
;
2886 ctmp
->value
[2] = ']';
2887 ctmp
->keymenu
= &take_export_keymenu_lm
;
2892 * Hide the checkboxes
2895 *(*cl
)->d
.t
.listmode
= SingleMode
;
2897 /* go to first line */
2898 for(ctmp
= *cl
; prev_confline(ctmp
); ctmp
= prev_confline(ctmp
))
2901 for(; ctmp
; ctmp
= next_confline(ctmp
))
2902 if(!(ctmp
->flags
& CF_NOSELECT
) && ctmp
->value
){
2903 ctmp
->value
[0] = ctmp
->value
[1] = ctmp
->value
[2] = SPACE
;
2904 ctmp
->keymenu
= &take_export_keymenu_sm
;
2908 ps
->mangled_body
= ps
->mangled_footer
= 1;
2912 if((*cl
)->value
[1] == 'X'){
2913 (*cl
)->d
.t
.selected
= 0;
2914 (*cl
)->value
[1] = SPACE
;
2917 (*cl
)->d
.t
.selected
= 1;
2918 (*cl
)->value
[1] = 'X';
2921 ps
->mangled_body
= 1;
2925 /* go to first line */
2926 for(ctmp
= *cl
; prev_confline(ctmp
); ctmp
= prev_confline(ctmp
))
2929 for(; ctmp
; ctmp
= next_confline(ctmp
)){
2930 if(!(ctmp
->flags
& CF_NOSELECT
) && ctmp
->value
){
2931 ctmp
->d
.t
.selected
= 1;
2933 ctmp
->value
[1] = 'X';
2937 ps
->mangled_body
= 1;
2941 /* go to first line */
2942 for(ctmp
= *cl
; prev_confline(ctmp
); ctmp
= prev_confline(ctmp
))
2945 for(; ctmp
; ctmp
= next_confline(ctmp
)){
2946 if(!(ctmp
->flags
& CF_NOSELECT
) && ctmp
->value
){
2947 ctmp
->d
.t
.selected
= 0;
2949 ctmp
->value
[1] = SPACE
;
2953 ps
->mangled_body
= 1;
2957 retval
= simple_exit_cmd(flags
);
2970 * Save an LDAP directory entry somewhere
2972 * Args: ps -- pine struct
2973 * e -- the entry to save
2974 * save -- If this is set, then bypass the question about whether
2975 * to save or export and just do the save.
2978 save_ldap_entry(struct pine
*ps
, LDAP_CHOOSE_S
*e
, int save
)
2980 char *fullname
= NULL
,
2985 struct berval
**cn
= NULL
,
2997 dprint((2, "\n - save_ldap_entry - \n"));
3003 for(a
= ldap_first_attribute(e
->ld
, e
->selected_entry
, &ber
);
3005 a
= ldap_next_attribute(e
->ld
, e
->selected_entry
, ber
)){
3007 dprint((9, " %s", a
? a
: "?"));
3008 if(strcmp(a
, e
->info_used
->cnattr
) == 0){
3010 cn
= ldap_get_values_len(e
->ld
, e
->selected_entry
, a
);
3012 else if(strcmp(a
, e
->info_used
->mailattr
) == 0){
3014 mail
= ldap_get_values_len(e
->ld
, e
->selected_entry
, a
);
3016 else if(strcmp(a
, "electronicmail") == 0){
3018 elecmail
= ldap_get_values_len(e
->ld
, e
->selected_entry
, a
);
3020 else if(strcmp(a
, "comment") == 0){
3022 note
= ldap_get_values_len(e
->ld
, e
->selected_entry
, a
);
3024 else if(strcmp(a
, e
->info_used
->snattr
) == 0){
3026 sn
= ldap_get_values_len(e
->ld
, e
->selected_entry
, a
);
3028 else if(strcmp(a
, e
->info_used
->gnattr
) == 0){
3030 givenname
= ldap_get_values_len(e
->ld
, e
->selected_entry
, a
);
3032 else if(strcmp(a
, "telephonenumber") == 0){
3034 telephone
= ldap_get_values_len(e
->ld
, e
->selected_entry
, a
);
3036 else if(strcmp(a
, "title") == 0){
3038 title
= ldap_get_values_len(e
->ld
, e
->selected_entry
, a
);
3043 j
= radio_buttons(_("Save to address book or Export to filesystem ? "),
3044 -FOOTER_ROWS(ps
), save_or_export
, 's', 'x',
3045 h_ab_save_exp
, RB_NORM
);
3049 q_status_message(SM_INFO
, 0, 2, _("Address book save cancelled"));
3061 q_status_message(SM_ORDER
, 3, 3,
3062 "can't happen in save_ldap_ent");
3069 if(ALPINE_LDAP_can_use(elecmail
) && !mail
)
3072 ldap_value_free_len(elecmail
);
3077 if(save
){ /* save into the address book */
3083 int how_many_selected
= 0;
3086 if(ALPINE_LDAP_can_use(cn
))
3087 fullname
= cpystr(cn
[0]->bv_val
);
3088 if(ALPINE_LDAP_can_use(sn
))
3089 last
= cpystr(sn
[0]->bv_val
);
3090 if(ALPINE_LDAP_can_use(givenname
))
3091 first
= cpystr(givenname
[0]->bv_val
);
3093 if(ALPINE_LDAP_can_use(note
))
3098 for(len
= 0, num
= 0; ALPINE_LDAP_usable(cm
, num
); num
++)
3099 len
+= strlen(cm
[num
]->bv_val
) + 2;
3102 comment
= (char *)fs_get(len
* sizeof(char));
3105 while(ALPINE_LDAP_usable(cm
, num
)){
3106 sstrncpy(&d
, cm
[num
]->bv_val
, len
-(d
-comment
));
3108 if(ALPINE_LDAP_usable(cm
, num
))
3109 sstrncpy(&d
, "; ", len
-(d
-comment
));
3112 comment
[len
-1] = '\0';
3115 for(len
= 0, num
= 0; ALPINE_LDAP_usable(mail
, num
); num
++)
3116 len
+= strlen(mail
[num
]->bv_val
) + 2;
3118 /* paste the email addresses together */
3120 address
= (char *)fs_get(len
* sizeof(char));
3123 while(ALPINE_LDAP_usable(mail
, num
)){
3124 sstrncpy(&d
, mail
[num
]->bv_val
, len
-(d
-address
));
3126 if(ALPINE_LDAP_usable(mail
, num
))
3127 sstrncpy(&d
, ", ", len
-(d
-address
));
3130 address
[len
-1] = '\0';
3135 rfc822_parse_adrlist(&addr
, address
, fakedomain
);
3137 if(addr
&& fullname
&& !(first
&& last
)){
3139 fs_give((void **)&addr
->personal
);
3141 addr
->personal
= cpystr(fullname
);
3144 if(addr
&& e
->serv
&& *e
->serv
){ /* save by reference */
3145 char *dn
, *edn
= NULL
;
3147 dn
= ldap_get_dn(e
->ld
, e
->selected_entry
);
3149 edn
= add_backslash_escapes(dn
);
3150 our_ldap_dn_memfree(dn
);
3153 if(e
->serv
&& *e
->serv
&& edn
&& *edn
){
3154 char buf
[MAILTMPLEN
+1];
3155 char *backup_mail
= NULL
;
3157 how_many_selected
++;
3159 if(addr
&& addr
->mailbox
&& addr
->host
){
3160 strncpy(buf
, addr
->mailbox
, sizeof(buf
)-2),
3161 buf
[sizeof(buf
)-2] = '\0';
3162 strncat(buf
, "@", sizeof(buf
)-1-strlen(buf
));
3163 strncat(buf
, addr
->host
, sizeof(buf
)-1-strlen(buf
));
3164 buf
[sizeof(buf
)-1] = '\0';
3165 backup_mail
= cpystr(buf
);
3169 * We only need one addr which we will use to hold the
3170 * pointer to the query.
3173 mail_free_address(&addr
->next
);
3176 fs_give((void **)&addr
->mailbox
);
3178 fs_give((void **)&addr
->host
);
3180 fs_give((void **)&addr
->personal
);
3182 snprintf(buf
, sizeof(buf
),
3183 "%s%s /base=%s/scope=base/cust=(objectclass=*)%s%s",
3187 backup_mail
? "/mail=" : "",
3188 backup_mail
? backup_mail
: "");
3189 buf
[sizeof(buf
)-1] = '\0';
3192 fs_give((void **)&backup_mail
);
3195 * Put the search parameters in mailbox and put @ in
3196 * host so that expand_address accepts it as an unqualified
3197 * address and doesn't try to add localdomain.
3199 addr
->mailbox
= cpystr(buf
);
3200 addr
->host
= cpystr("@");
3204 fs_give((void **)&edn
);
3206 else{ /* save by value */
3207 how_many_selected
++;
3209 addr
= mail_newaddr();
3212 if(how_many_selected
> 0){
3213 TA_S
*current
= NULL
;
3216 * The empty string for the last argument is significant.
3217 * Fill_in_ta copies the whole adrlist into a single TA if
3218 * there is a print string.
3220 current
= fill_in_ta(¤t
, addr
, 1, "");
3221 current
= first_sel_taline(current
);
3223 if(first
&& last
&& current
){
3227 l
= strlen(last
) + 2 + strlen(first
);
3228 p
= (char *)fs_get((l
+1) * sizeof(char));
3229 snprintf(p
, l
, "%s, %s", last
, first
);
3231 current
->fullname
= p
;
3232 convert_possibly_encoded_str_to_utf8(¤t
->fullname
);
3235 if(comment
&& current
){
3236 current
->comment
= cpystr(comment
);
3237 convert_possibly_encoded_str_to_utf8(¤t
->comment
);
3241 * We don't want the personal name to make it into the address
3242 * field in an LDAP: query sort of address, so move it
3245 if(e
->serv
&& *e
->serv
&& current
&& fullname
){
3246 if(current
->fullname
)
3247 fs_give((void **)¤t
->fullname
);
3249 current
->fullname
= fullname
;
3251 convert_possibly_encoded_str_to_utf8(¤t
->fullname
);
3254 mail_free_address(&addr
);
3257 takeaddr_bypass(ps
, current
, NULL
);
3259 q_status_message(SM_ORDER
, 0, 4, "Nothing to save");
3261 free_talines(¤t
);
3264 q_status_message(SM_ORDER
, 0, 4, "Nothing to save");
3267 else if(export
){ /* export to filesystem */
3268 STORE_S
*srcstore
= NULL
;
3270 static ESCKEY_S text_or_vcard
[] = {
3271 {'t', 't', "T", N_("Text")},
3272 {'a', 'a', "A", N_("Addresses")},
3273 {'v', 'v', "V", N_("VCard")},
3274 {-1, 0, NULL
, NULL
}};
3277 _("Export text of entry, address, or VCard format ? "),
3278 -FOOTER_ROWS(ps
), text_or_vcard
, 't', 'x',
3279 h_ldap_text_or_vcard
, RB_NORM
);
3283 q_status_message(SM_INFO
, 0, 2, _("Address book export cancelled"));
3288 if(!(srcstore
= prep_ldap_for_viewing(ps
, e
, srctype
, NULL
)))
3289 q_status_message(SM_ORDER
, 0, 2, _("Error allocating space"));
3291 (void)simple_export(ps_global
, so_text(srcstore
), srctype
,
3299 if(ALPINE_LDAP_can_use(mail
)){
3302 if(!(srcstore
= so_get(srctype
, NULL
, EDIT_ACCESS
)))
3303 q_status_message(SM_ORDER
,0,2, _("Error allocating space"));
3305 for(num
= 0; ALPINE_LDAP_usable(mail
, num
); num
++){
3306 so_puts(srcstore
, mail
[num
]->bv_val
);
3307 so_puts(srcstore
, "\n");
3310 (void)simple_export(ps_global
, so_text(srcstore
),
3311 srctype
, "addresses", NULL
);
3320 if(!(srcstore
= so_get(srctype
, NULL
, EDIT_ACCESS
)))
3321 q_status_message(SM_ORDER
,0,2, _("Error allocating space"));
3324 VCARD_INFO_S
*vinfo
;
3326 vinfo
= (VCARD_INFO_S
*)fs_get(sizeof(VCARD_INFO_S
));
3327 memset((void *)vinfo
, 0, sizeof(VCARD_INFO_S
));
3329 if(ALPINE_LDAP_can_use(cn
))
3330 vinfo
->fullname
= berval_to_array(cn
);
3332 if(ALPINE_LDAP_can_use(note
))
3333 vinfo
->note
= berval_to_array(note
);
3335 if(ALPINE_LDAP_can_use(title
))
3336 vinfo
->title
= berval_to_array(title
);
3338 if(ALPINE_LDAP_can_use(telephone
))
3339 vinfo
->tel
= berval_to_array(telephone
);
3341 if(ALPINE_LDAP_can_use(mail
))
3342 vinfo
->email
= berval_to_array(mail
);
3344 if(ALPINE_LDAP_can_use(sn
))
3345 vinfo
->last
= cpystr(sn
[0]->bv_val
);
3347 if(ALPINE_LDAP_can_use(givenname
))
3348 vinfo
->first
= cpystr(givenname
[0]->bv_val
);
3350 gf_set_so_writec(&pc
, srcstore
);
3352 write_single_vcard_entry(ps_global
, pc
, vinfo
);
3354 free_vcard_info(&vinfo
);
3356 (void)simple_export(ps_global
, so_text(srcstore
),
3357 srctype
, "vcard text", NULL
);
3364 q_status_message(SM_ORDER
, 3, 3, "can't happen in text_or_vcard");
3370 ldap_value_free_len(cn
);
3372 ldap_value_free_len(mail
);
3374 ldap_value_free_len(elecmail
);
3376 ldap_value_free_len(note
);
3378 ldap_value_free_len(sn
);
3380 ldap_value_free_len(givenname
);
3382 ldap_value_free_len(telephone
);
3384 ldap_value_free_len(title
);
3386 fs_give((void **)&fullname
);
3388 fs_give((void **)&address
);
3390 fs_give((void **)&first
);
3392 fs_give((void **)&last
);
3394 fs_give((void **)&comment
);
3396 #endif /* ENABLE_LDAP */
3406 return(ta_scroll_down(-count
));
3411 while(i
&& ta_screen
->top_line
->next
){
3412 if(ta_screen
->top_line
== ta_screen
->current
){
3413 if(next_sel
= next_sel_taline(ta_screen
->current
)){
3414 ta_screen
->current
= next_sel
;
3415 ta_screen
->top_line
= next_taline(ta_screen
->top_line
);
3421 ta_screen
->top_line
= next_taline(ta_screen
->top_line
);
3430 ta_scroll_down(count
)
3434 return(ta_scroll_up(-count
));
3437 long page_size
= ps_global
->ttyo
->screen_rows
-
3438 FOOTER_ROWS(ps_global
) - HEADER_ROWS(ps_global
);
3440 TA_S
*first
= first_taline(ta_screen
->top_line
);
3444 for(ctmp
= ta_screen
->top_line
;
3445 ctmp
!= ta_screen
->current
; ctmp
= next_taline(ctmp
))
3447 while(i
&& ta_screen
->top_line
!= first
){
3448 ta_screen
->top_line
= pre_taline(ta_screen
->top_line
);
3451 if(dline
>= page_size
){
3452 ctmp
= pre_sel_taline(ta_screen
->current
);
3455 ta_screen
->top_line
= next_taline(ta_screen
->top_line
);
3458 for(; ctmp
!= ta_screen
->current
;
3459 ta_screen
->current
= pre_taline(ta_screen
->current
))
3468 int ta_scroll_to_pos(line
)
3474 for(dline
= 0, ctmp
= first_taline(ta_screen
->top_line
);
3475 ctmp
!= ta_screen
->top_line
; ctmp
= next_taline(ctmp
))
3481 return(ta_scroll_up(line
- dline
));
3485 ta_scroll_callback (cmd
, scroll_pos
)
3490 long page_size
= ps_global
->ttyo
->screen_rows
- HEADER_ROWS(ps_global
)
3491 - FOOTER_ROWS(ps_global
);
3494 case MSWIN_KEY_SCROLLUPLINE
:
3495 paint
= ta_scroll_down (scroll_pos
);
3498 case MSWIN_KEY_SCROLLDOWNLINE
:
3499 paint
= ta_scroll_up (scroll_pos
);
3502 case MSWIN_KEY_SCROLLUPPAGE
:
3503 paint
= ta_scroll_down (page_size
);
3506 case MSWIN_KEY_SCROLLDOWNPAGE
:
3507 paint
= ta_scroll_up (page_size
);
3510 case MSWIN_KEY_SCROLLTO
:
3511 paint
= ta_scroll_to_pos (scroll_pos
);
3516 update_takeaddr_screen(ps_global
, ta_screen
->current
, ta_screen
, (Pos
*)NULL
);
3521 #endif /* _WINDOWS */