1 /*@ S-nail - a mail user agent derived from Berkeley Mail.
2 *@ Header display, search, etc., related user commands.
4 * Copyright (c) 2000-2004 Gunnar Ritter, Freiburg i. Br., Germany.
5 * Copyright (c) 2012 - 2018 Steffen (Daode) Nurpmeso <steffen@sdaoden.eu>.
6 * SPDX-License-Identifier: BSD-3-Clause
9 * Copyright (c) 1980, 1993
10 * The Regents of the University of California. All rights reserved.
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 #define n_FILE cmd_head
39 #ifndef HAVE_AMALGAMATION
45 /* Print out the header of a specific message.
46 * time_current must be up-to-date when this is called.
47 * a_chead__hprf: handle *headline*
48 * a_chead__subject: -1 if Subject: yet seen, otherwise n_alloc()d Subject:
49 * a_chead__putindent: print out the indenting in threaded display
50 * a_chead__putuc: print out a Unicode character or a substitute for it, return
51 * 0 on error or wcwidth() (or 1) on success */
52 static void a_chead_print_head(size_t yetprinted
, size_t msgno
, FILE *f
,
53 bool_t threaded
, bool_t subject_thread_compress
);
55 static void a_chead__hprf(size_t yetprinted
, char const *fmt
, size_t msgno
,
56 FILE *f
, bool_t threaded
, bool_t subject_thread_compress
,
57 char const *attrlist
);
58 static char *a_chead__subject(struct message
*mp
, bool_t threaded
,
59 bool_t subject_thread_compress
, size_t yetprinted
);
60 static int a_chead__putindent(FILE *fp
, struct message
*mp
, int maxwidth
);
61 static size_t a_chead__putuc(int u
, int c
, FILE *fp
);
62 static int a_chead__dispc(struct message
*mp
, char const *a
);
64 /* Shared `z' implementation */
65 static int a_chead_scroll(char const *arg
, bool_t onlynew
);
67 /* Shared `headers' implementation */
68 static int _headers(int msgspec
);
71 a_chead_print_head(size_t yetprinted
, size_t msgno
, FILE *f
, bool_t threaded
,
72 bool_t subject_thread_compress
){
74 char attrlist
[attrlen
+1], *cp
;
78 if((cp
= ok_vlook(attrlist
)) != NULL
){
79 if(strlen(cp
) == attrlen
){
80 memcpy(attrlist
, cp
, attrlen
+1);
83 n_err(_("*attrlist* is not of the correct length, using built-in\n"));
86 if(ok_blook(bsdcompat
) || ok_blook(bsdflags
)){
87 char const bsdattr
[attrlen
+1] = "NU *HMFAT+-$~";
89 memcpy(attrlist
, bsdattr
, sizeof bsdattr
);
90 }else if(ok_blook(SYSV3
)){
91 char const bsdattr
[attrlen
+1] = "NU *HMFAT+-$~";
93 memcpy(attrlist
, bsdattr
, sizeof bsdattr
);
94 n_OBSOLETE(_("*SYSV3*: please use *bsdcompat* or *bsdflags*, "
95 "or set *attrlist*"));
97 char const pattr
[attrlen
+1] = "NUROSPMFAT+-$~";
99 memcpy(attrlist
, pattr
, sizeof pattr
);
103 if((fmt
= ok_vlook(headline
)) == NULL
){
104 fmt
= ((ok_blook(bsdcompat
) || ok_blook(bsdheadline
))
105 ? "%>%a%m %-20f %16d %4l/%-5o %i%-S"
106 : "%>%a%m %-18f %-16d %4l/%-5o %i%-s");
109 a_chead__hprf(yetprinted
, fmt
, msgno
, f
, threaded
, subject_thread_compress
,
115 a_chead__hprf(size_t yetprinted
, char const *fmt
, size_t msgno
, FILE *f
,
116 bool_t threaded
, bool_t subject_thread_compress
, char const *attrlist
)
118 char buf
[16], cbuf
[8], *cp
, *subjline
;
119 char const *date
, *name
, *fp
, *color_tag
;
120 int i
, n
, s
, wleft
, subjlen
;
122 n_COLOUR( struct n_colour_pen
*cpen_new COMMA
*cpen_cur COMMA
*cpen_bas
; )
128 _LOOP_MASK
= (1<<4) - 1,
129 _SFMT
= 1<<4, /* It is 'S' */
130 /* For the simple byte-based counts in wleft and n we sometimes need
131 * adjustments to compensate for additional bytes of UTF-8 sequences */
132 _PUTCB_UTF8_SHIFT
= 5,
133 _PUTCB_UTF8_MASK
= 3<<5
138 if ((mp
= message
+ msgno
- 1) == dot
)
142 date
= n_header_textual_date_info(mp
, &color_tag
);
146 n_header_textual_sender_info(mp
, &cp
, NULL
, NULL
, NULL
, &isto
);
154 /* Detect the width of the non-format characters in *headline*;
155 * like that we can simply use putc() in the next loop, since we have
156 * already calculated their column widths (TODO it's sick) */
157 wleft
= subjlen
= n_scrnwidth
;
159 for (fp
= fmt
; *fp
!= '\0'; ++fp
) {
165 if (digitchar(*fp
)) {
168 n
= 10*n
+ *fp
- '0';
169 while (++fp
, digitchar(*fp
));
179 if (n_mb_cur_max
> 1) {
181 if ((s
= mbtowc(&wc
, fp
, n_mb_cur_max
)) == -1)
183 else if ((n
= wcwidth(wc
)) == -1)
195 /* Walk *headline*, producing output TODO not (really) MB safe */
197 if(n_COLOUR_IS_ACTIVE()){
199 color_tag
= n_COLOUR_TAG_SUM_DOT
;
200 cpen_bas
= n_colour_pen_create(n_COLOUR_ID_SUM_HEADER
, color_tag
);
201 n_colour_pen_put(cpen_new
= cpen_cur
= cpen_bas
);
203 cpen_new
= cpen_bas
= cpen_cur
= NULL
;
206 for (fp
= fmt
; *fp
!= '\0'; ++fp
) {
209 if ((c
= *fp
& 0xFF) != '%') {
211 if(n_COLOUR_IS_ACTIVE() && (cpen_new
= cpen_bas
) != cpen_cur
)
212 n_colour_pen_put(cpen_cur
= cpen_new
);
221 if ((c
= *++fp
) == '-') {
226 if (digitchar(*fp
)) {
228 n
= 10*n
+ *fp
- '0';
229 while (++fp
, digitchar(*fp
));
232 if ((c
= *fp
& 0xFF) == '\0')
242 if (flags
& _ISDOT
) {
244 if(n_COLOUR_IS_ACTIVE())
245 cpen_new
= n_colour_pen_create(n_COLOUR_ID_SUM_DOTMARK
,
248 if((n_psonce
& n_PSO_UNICODE
) && !ok_blook(headline_plain
)){
250 /* 25B8;BLACK RIGHT-POINTING SMALL TRIANGLE */
251 cbuf
[1] = (char)0x96, cbuf
[2] = (char)0xB8;
253 /* 25C2;BLACK LEFT-POINTING SMALL TRIANGLE */
254 cbuf
[1] = (char)0x97, cbuf
[2] = (char)0x82;
257 flags
|= 2 << _PUTCB_UTF8_SHIFT
;
266 if (UICMP(32, n_ABS(n
), >, wleft
))
267 n
= (n
< 0) ? -wleft
: wleft
;
268 snprintf(buf
, sizeof buf
, "%u.%02u",
269 (mp
->m_spamscore
>> 8), (mp
->m_spamscore
& 0xFF));
270 n
= fprintf(f
, "%*s", n
, buf
);
271 wleft
= (n
>= 0) ? wleft
- n
: 0;
278 c
= a_chead__dispc(mp
, attrlist
);
281 if(n_COLOUR_IS_ACTIVE()){
282 if(cpen_new
== cpen_cur
)
284 if(cpen_new
!= cpen_cur
)
285 n_colour_pen_put(cpen_cur
= cpen_new
);
288 if (UICMP(32, n_ABS(n
), >, wleft
))
289 n
= (n
< 0) ? -wleft
: wleft
;
291 n
= fprintf(f
, "%*s", n
, cbuf
);
294 if ((n
= (flags
& _PUTCB_UTF8_MASK
)) != 0) {
295 n
>>= _PUTCB_UTF8_SHIFT
;
299 wleft
= 0; /* TODO I/O error.. ? break? */
302 if(n_COLOUR_IS_ACTIVE() && (cpen_new
= cpen_bas
) != cpen_cur
)
303 n_colour_pen_put(cpen_cur
= cpen_new
);
309 if (UICMP(32, n_ABS(n
), >, wleft
))
310 n
= (n
< 0) ? -wleft
: wleft
;
311 n
= fprintf(f
, "%*.*s", n
, n_ABS(n
), date
);
312 wleft
= (n
>= 0) ? wleft
- n
: 0;
317 if (UICMP(32, n_ABS(n
), >, wleft
))
318 n
= (n
< 0) ? -wleft
: wleft
;
319 n
= fprintf(f
, "%*u", n
, (threaded
== 1 ? mp
->m_level
: 0));
320 wleft
= (n
>= 0) ? wleft
- n
: 0;
331 n
= (n
< 0) ? -wleft
: wleft
;
333 if (flags
& _ISTO
) /* XXX tr()! */
335 n
= fprintf(f
, "%s%s", ((flags
& _ISTO
) ? "To " : n_empty
),
336 colalign(name
, i
, n
, &wleft
));
339 else if (flags
& _ISTO
)
345 if(n_COLOUR_IS_ACTIVE()){
346 cpen_new
= n_colour_pen_create(n_COLOUR_ID_SUM_THREAD
,
348 if(cpen_new
!= cpen_cur
)
349 n_colour_pen_put(cpen_cur
= cpen_new
);
352 n
= a_chead__putindent(f
, mp
, n_MIN(wleft
, (int)n_scrnwidth
- 60));
353 wleft
= (n
>= 0) ? wleft
- n
: 0;
355 if(n_COLOUR_IS_ACTIVE() && (cpen_new
= cpen_bas
) != cpen_cur
)
356 n_colour_pen_put(cpen_cur
= cpen_new
);
363 if (UICMP(32, n_ABS(n
), >, wleft
))
364 n
= (n
< 0) ? -wleft
: wleft
;
366 n
= fprintf(f
, "%*ld", n
, mp
->m_xlines
);
367 wleft
= (n
>= 0) ? wleft
- n
: 0;
379 for (i
= msgCount
; i
> 999; i
/= 10)
382 if (UICMP(32, n_ABS(n
), >, wleft
))
383 n
= (n
< 0) ? -wleft
: wleft
;
384 n
= fprintf(f
, "%*lu", n
, (ul_i
)msgno
);
385 wleft
= (n
>= 0) ? wleft
- n
: 0;
390 if (UICMP(32, n_ABS(n
), >, wleft
))
391 n
= (n
< 0) ? -wleft
: wleft
;
392 n
= fprintf(f
, "%*lu", n
, (ul_i
)mp
->m_xsize
);
393 wleft
= (n
>= 0) ? wleft
- n
: 0;
405 if (UICMP(32, n_ABS(n
), >, subjlen
))
406 n
= (n
< 0) ? -subjlen
: subjlen
;
408 n
-= (n
< 0) ? -2 : 2;
411 if (subjline
== NULL
)
412 subjline
= a_chead__subject(mp
, (threaded
&& (flags
& _IFMT
)),
413 subject_thread_compress
, yetprinted
);
414 if (subjline
== (char*)-1) {
415 n
= fprintf(f
, "%*s", n
, n_empty
);
416 wleft
= (n
>= 0) ? wleft
- n
: 0;
418 n
= fprintf(f
, ((flags
& _SFMT
) ? "\"%s\"" : "%s"),
419 colalign(subjline
, n_ABS(n
), n
, &wleft
));
424 case 'T': /* Message recipient flags */
425 switch(is_mlist_mp(mp
, MLIST_OTHER
)){
426 case MLIST_OTHER
: c
= ' '; break;
427 case MLIST_KNOWN
: c
= 'l'; break;
428 case MLIST_SUBSCRIBED
: c
= 'L'; break;
435 for (i
= msgCount
; i
> 999; i
/= 10)
438 if (UICMP(32, n_ABS(n
), >, wleft
))
439 n
= (n
< 0) ? -wleft
: wleft
;
440 n
= fprintf(f
, "%*lu",
441 n
, (threaded
? (ul_i
)mp
->m_threadpos
: (ul_i
)msgno
));
442 wleft
= (n
>= 0) ? wleft
- n
: 0;
448 if (UICMP(32, n_ABS(n
), >, wleft
))
449 n
= (n
< 0) ? -wleft
: wleft
;
450 n
= fprintf(f
, "%*" PRIu64
, n
, mp
->m_uid
);
451 wleft
= (n
>= 0) ? wleft
- n
: 0;
458 if (n_poption
& n_PO_D_V
)
459 n_err(_("Unknown *headline* format: %%%c\n"), c
);
468 n_COLOUR( n_colour_reset(); )
471 if (subjline
!= NULL
&& subjline
!= (char*)-1)
477 a_chead__subject(struct message
*mp
, bool_t threaded
,
478 bool_t subject_thread_compress
, size_t yetprinted
)
486 if ((ms
= hfield1("subject", mp
)) == NULL
)
489 in
.l
= strlen(in
.s
= ms
);
490 mime_fromhdr(&in
, &out
, TD_ICONV
| TD_ISPR
);
493 if (!threaded
|| !subject_thread_compress
|| mp
->m_level
== 0)
496 /* In a display thread - check whether this message uses the same
497 * Subject: as it's parent or elder neighbour, suppress printing it if
498 * this is the case. To extend this a bit, ignore any leading Re: or
499 * Fwd: plus follow-up WS. Ignore invisible messages along the way */
500 ms
= n_UNCONST(subject_re_trim(n_UNCONST(ms
)));
502 for (; (mp
= prev_in_thread(mp
)) != NULL
&& yetprinted
-- > 0;) {
505 if (visible(mp
) && (os
= hfield1("subject", mp
)) != NULL
) {
509 in
.l
= strlen(in
.s
= os
);
510 mime_fromhdr(&in
, &oout
, TD_ICONV
| TD_ISPR
);
511 x
= asccasecmp(ms
, subject_re_trim(oout
.s
));
527 a_chead__putindent(FILE *fp
, struct message
*mp
, int maxwidth
)/* XXX magics */
530 int *us
, indlvl
, indw
, i
, important
= MNEW
| MFLAGGED
;
534 if (mp
->m_level
== 0 || maxwidth
== 0) {
539 cs
= n_lofi_alloc(mp
->m_level
);
540 us
= n_lofi_alloc(mp
->m_level
* sizeof *us
);
543 if (mp
->m_younger
&& UICMP(32, i
+ 1, ==, mp
->m_younger
->m_level
)) {
544 if (mp
->m_parent
&& mp
->m_parent
->m_flag
& important
)
545 us
[i
] = mp
->m_flag
& important
? 0x2523 : 0x2520;
547 us
[i
] = mp
->m_flag
& important
? 0x251D : 0x251C;
550 if (mp
->m_parent
&& mp
->m_parent
->m_flag
& important
)
551 us
[i
] = mp
->m_flag
& important
? 0x2517 : 0x2516;
553 us
[i
] = mp
->m_flag
& important
? 0x2515 : 0x2514;
558 for (i
= mp
->m_level
- 2; i
>= 0; --i
) {
560 if (UICMP(32, i
, >, mq
->m_level
- 1)) {
565 if (mq
->m_parent
&& (mq
->m_parent
->m_flag
& important
))
578 for (indlvl
= indw
= 0; (ui8_t
)indlvl
< mp
->m_level
&& indw
< maxwidth
;
580 if (indw
< maxwidth
- 1)
581 indw
+= (int)a_chead__putuc(us
[indlvl
], cs
[indlvl
] & 0xFF, fp
);
583 indw
+= (int)a_chead__putuc(0x21B8, '^', fp
);
585 indw
+= a_chead__putuc(0x25B8, '>', fp
);
595 a_chead__putuc(int u
, int c
, FILE *fp
){
600 #ifdef HAVE_NATCH_CHAR
601 if((n_psonce
& n_PSO_UNICODE
) && (u
& ~(wchar_t)0177) &&
602 !ok_blook(headline_plain
)){
603 char mbb
[MB_LEN_MAX
];
606 if((n
= wctomb(mbb
, u
)) > 0){
608 for(i
= 0; i
< n
; ++i
)
609 if(putc(mbb
[i
] & 0377, fp
) == EOF
){
614 rv
= (putc('\0', fp
) != EOF
);
619 rv
= (putc(c
, fp
) != EOF
);
625 a_chead__dispc(struct message
*mp
, char const *a
)
630 if ((mp
->m_flag
& (MREAD
| MNEW
)) == MREAD
)
632 if ((mp
->m_flag
& (MREAD
| MNEW
)) == (MREAD
| MNEW
))
634 if (mp
->m_flag
& MANSWERED
)
636 if (mp
->m_flag
& MDRAFTED
)
638 if ((mp
->m_flag
& (MREAD
| MNEW
)) == MNEW
)
640 if (!(mp
->m_flag
& (MREAD
| MNEW
)))
642 if (mp
->m_flag
& MSPAM
)
644 if (mp
->m_flag
& MSPAMUNSURE
)
646 if (mp
->m_flag
& MSAVED
)
648 if (mp
->m_flag
& MPRESERVE
)
650 if (mp
->m_flag
& (MBOX
| MBOXED
))
652 if (mp
->m_flag
& MFLAGGED
)
654 if (mb
.mb_threaded
== 1) { /* TODO bad, and m_collapsed is weird */
655 /* TODO So this does not work because of weird thread handling and
656 * TODO intermixing view and controller except when run via -L from
657 * TODO command line; in general these flags should go and we need
658 * TODO specific *headline* formats which always work and indicate
659 * TODO whether a message is in a thread, the head of a subthread etc. */
660 if (mp
->m_collapsed
> 0)
662 else if (mp
->m_collapsed
< 0)
670 a_chead_scroll(char const *arg
, bool_t onlynew
){
673 int msgspec
, size
, maxs
;
676 /* TODO scroll problem: we do not know whether + and $ have already reached
677 * TODO the last screen in threaded mode */
678 msgspec
= onlynew
? -1 : 0;
679 size
= (int)/*TODO*/n_screensize();
680 if((maxs
= msgCount
/ size
) > 0 && msgCount
% size
== 0)
711 case '1': case '2': case '3': case '4': case '5':
712 case '6': case '7': case '8': case '9': case '0':
715 if((n_idec_siz_cp(&l
, arg
, 0, NULL
716 ) & (n_IDEC_STATE_EMASK
| n_IDEC_STATE_CONSUMED
)
717 ) != n_IDEC_STATE_CONSUMED
)
719 if(l
> maxs
- (isabs
? 0 : _screen
))
721 _screen
= isabs
? (int)l
: _screen
+ l
;
727 fprintf(n_stdout
, _("On last screenful of messages\n"));
735 if((n_idec_siz_cp(&l
, ++arg
, 0, NULL
736 ) & (n_IDEC_STATE_EMASK
| n_IDEC_STATE_CONSUMED
)
737 ) != n_IDEC_STATE_CONSUMED
)
746 fprintf(n_stdout
, _("On first screenful of messages\n"));
753 n_err(_("Unrecognized scrolling command: %s\n"), arg
);
758 size
= _headers(msgspec
);
765 _headers(int msgspec
) /* TODO rework v15 */
767 bool_t needdot
, showlast
;
768 int g
, k
, mesg
, size
;
769 struct message
*lastmq
, *mp
, *mq
;
771 ui32_t
volatile flag
;
775 time_current_update(&time_current
, FAL0
);
777 fl
= MNEW
| MFLAGGED
;
782 size
= (int)/*TODO*/n_screensize();
785 #if 0 /* FIXME original code path */
798 needdot
= (msgspec
<= 0) ? TRU1
: (dot
!= &message
[msgspec
- 1]);
799 showlast
= ok_blook(showlast
);
801 if (mb
.mb_threaded
== 0) {
804 for (mp
= message
; PTRCMP(mp
, <, message
+ msgCount
); ++mp
)
808 if (mp
->m_flag
& fl
) {
812 if ((msgspec
> 0 && PTRCMP(mp
, ==, message
+ msgspec
- 1)) ||
813 (msgspec
== 0 && g
== k
) ||
814 (msgspec
== -2 && g
== k
+ size
&& lastmq
) ||
815 (msgspec
< 0 && g
>= k
&& (mp
->m_flag
& fl
) != 0))
819 if (lastmq
&& (msgspec
== -2 ||
820 (msgspec
== -1 && PTRCMP(mp
, ==, message
+ msgCount
)))) {
827 mesg
= (int)PTR2SIZE(mp
- message
);
829 if (mb
.mb_type
== MB_IMAP
)
830 imap_getheaders(mesg
+ 1, mesg
+ size
);
832 n_COLOUR( n_colour_env_create(n_COLOUR_CTX_SUM
, n_stdout
, FAL0
); )
834 for(lastmq
= NULL
, mq
= &message
[msgCount
]; mp
< mq
; lastmq
= mp
, ++mp
){
838 if (UICMP(32, flag
, >=, size
))
842 if(UICMP(32, flag
, ==, size
- 1) || &mp
[1] == mq
)
851 a_chead_print_head(0, mesg
, n_stdout
, FAL0
, FAL0
);
854 if(needdot
&& ok_blook(showlast
)) /* xxx will not show */
857 n_COLOUR( n_colour_env_gut(); )
858 } else { /* threaded */
861 for (mp
= threadroot
; mp
; mp
= next_in_thread(mp
)){
862 /* TODO thread handling needs rewrite, m_collapsed must go */
864 (mp
->m_collapsed
<= 0 ||
865 PTRCMP(mp
, ==, message
+ msgspec
- 1))) {
868 if (mp
->m_flag
& fl
) {
872 if ((msgspec
> 0 && PTRCMP(mp
, ==, message
+ msgspec
- 1)) ||
873 (msgspec
== 0 && g
== k
) ||
874 (msgspec
== -2 && g
== k
+ size
&& lastmq
) ||
875 (msgspec
< 0 && g
>= k
&& (mp
->m_flag
& fl
) != 0))
880 if (lastmq
&& (msgspec
== -2 ||
881 (msgspec
== -1 && PTRCMP(mp
, ==, message
+ msgCount
)))) {
888 n_COLOUR( n_colour_env_create(n_COLOUR_CTX_SUM
, n_stdout
, FAL0
); )
890 for(lastmq
= NULL
; mp
!= NULL
; lastmq
= mp
, mp
= mq
){
891 mq
= next_in_thread(mp
);
893 (mp
->m_collapsed
<= 0 ||
894 PTRCMP(mp
, ==, message
+ msgspec
- 1))) {
895 if (UICMP(32, flag
, >=, size
))
899 if(UICMP(32, flag
, ==, size
- 1) || mq
== NULL
)
907 a_chead_print_head(flag
, PTR2SIZE(mp
- message
+ 1), n_stdout
,
908 mb
.mb_threaded
, TRU1
);
913 if(needdot
&& ok_blook(showlast
)) /* xxx will not show */
916 n_COLOUR( n_colour_env_gut(); )
920 fprintf(n_stdout
, _("No more mail.\n"));
921 if (n_pstate
& (n_PS_ROBOT
| n_PS_HOOK_MASK
))
934 rv
= print_header_group((int*)v
);
940 print_header_group(int *vector
)
945 assert(vector
!= NULL
&& vector
!= (void*)-1);
946 rv
= _headers(vector
[0]);
957 rv
= a_chead_scroll(*(char const**)v
, FAL0
);
968 rv
= a_chead_scroll(*(char const**)v
, TRU1
);
980 if (*(args
= v
) == '\0' || args
[1] != '\0') {
982 n_err(_("Synopsis: dotmove: up <-> or down <+> by one message\n"));
984 } else switch (args
[0]) {
988 fprintf(n_stdout
, _("At EOF\n"));
990 } else if (n_getmsglist(n_UNCONST(/*TODO*/args
), msgvec
, 0, NULL
) > 0) {
991 setdot(message
+ msgvec
[0] - 1);
993 rv
= c_headers(msgvec
);
1007 int *msgvec
, *ip
, n
;
1009 FILE * volatile obuf
;
1012 if(*(msgvec
= vp
) == 0)
1015 time_current_update(&time_current
, FAL0
);
1019 if (n_psonce
& n_PSO_INTERACTIVE
) {
1020 if ((cp
= ok_vlook(crt
)) != NULL
) {
1023 for (n
= 0, ip
= msgvec
; *ip
!= 0; ++ip
)
1027 ib
= n_screensize();
1029 n_idec_uiz_cp(&ib
, cp
, 0, NULL
);
1030 if (UICMP(z
, n
, >, ib
) && (obuf
= n_pager_open()) == NULL
)
1035 /* Update dot before display so that the dotmark etc. are correct */
1036 for (ip
= msgvec
; ip
[1] != 0; ++ip
)
1038 setdot(&message
[(ok_blook(showlast
) ? *ip
: *msgvec
) - 1]);
1040 n_COLOUR( n_colour_env_create(n_COLOUR_CTX_SUM
, obuf
, obuf
!= n_stdout
); )
1042 for (n
= 0, ip
= msgvec
; *ip
!= 0; ++ip
) { /* TODO join into _print_head() */
1043 a_chead_print_head((size_t)n
++, (size_t)*ip
, obuf
, mb
.mb_threaded
, FAL0
);
1047 n_COLOUR( n_colour_env_gut(); )
1049 if (obuf
!= n_stdout
)
1050 n_pager_close(obuf
);
1057 print_headers(int const *msgvec
, bool_t only_marked
,
1058 bool_t subject_thread_compress
)
1063 time_current_update(&time_current
, FAL0
);
1065 n_COLOUR( n_colour_env_create(n_COLOUR_CTX_SUM
, n_stdout
, FAL0
); )
1067 for(printed
= 0; *msgvec
!= 0; ++msgvec
) {
1068 struct message
*mp
= message
+ *msgvec
- 1;
1070 if (!(mp
->m_flag
& MMARK
))
1072 } else if (!visible(mp
))
1074 a_chead_print_head(printed
++, *msgvec
, n_stdout
, mb
.mb_threaded
,
1075 subject_thread_compress
);
1079 n_COLOUR( n_colour_env_gut(); )