(Pseudo) Fix history (non gabbiness) by stripping PS_ARGLIST_MASK
[s-mailx.git] / cmd1.c
blobb6a154c6e95c5bc884cea03b4c4dd302e79615c3
1 /*@ S-nail - a mail user agent derived from Berkeley Mail.
2 *@ User commands.
4 * Copyright (c) 2000-2004 Gunnar Ritter, Freiburg i. Br., Germany.
5 * Copyright (c) 2012 - 2016 Steffen (Daode) Nurpmeso <steffen@sdaoden.eu>.
6 */
7 /*
8 * Copyright (c) 1980, 1993
9 * The Regents of the University of California. All rights reserved.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
35 #undef n_FILE
36 #define n_FILE cmd1
38 #ifndef HAVE_AMALGAMATION
39 # include "nail.h"
40 #endif
42 static int _screen;
44 /* Prepare and print "[Message: xy]:" intro */
45 static void _show_msg_overview(FILE *obuf, struct message *mp, int msg_no);
47 /* ... And place the extracted date in `date' */
48 static void _parse_from_(struct message *mp, char date[FROM_DATEBUF]);
50 /* Print out the header of a specific message
51 * __hprf: handle *headline*
52 * __subject: return -1 if Subject: yet seen, otherwise smalloc()d Subject:
53 * __putindent: print out the indenting in threaded display */
54 static void _print_head(size_t yetprinted, size_t msgno, FILE *f,
55 bool_t threaded);
56 static void __hprf(size_t yetprinted, char const *fmt, size_t msgno,
57 FILE *f, bool_t threaded, char const *attrlist);
58 static char * __subject(struct message *mp, bool_t threaded,
59 size_t yetprinted);
60 static int __putindent(FILE *fp, struct message *mp, int maxwidth);
62 static int _dispc(struct message *mp, char const *a);
64 /* Shared `z' implementation */
65 static int a_cmd_scroll(char const *arg, bool_t onlynew);
67 /* Shared `headers' implementation */
68 static int _headers(int msgspec);
70 /* Show the requested messages */
71 static int _type1(int *msgvec, bool_t doign, bool_t dopage, bool_t dopipe,
72 bool_t dodecode, char *cmd, ui64_t *tstats);
74 /* Pipe the requested messages */
75 static int _pipe1(char *str, int doign);
77 /* `top' / `Top' */
78 static int a_cmd_top(void *vp, struct ignoretab *itp);
80 static void
81 _show_msg_overview(FILE *obuf, struct message *mp, int msg_no)
83 char const *cpre = "", *csuf = "";
84 NYD_ENTER;
86 #ifdef HAVE_COLOUR
87 if (pstate & PS_COLOUR_ACTIVE) {
88 struct n_colour_pen *cpen;
90 if ((cpen = n_colour_pen_create(n_COLOUR_ID_VIEW_MSGINFO, NULL)) != NULL){
91 struct str const *sp;
93 if ((sp = n_colour_pen_to_str(cpen)) != NULL)
94 cpre = sp->s;
95 if ((sp = n_colour_reset_to_str()) != NULL)
96 csuf = sp->s;
99 #endif
100 fprintf(obuf, _("%s[-- Message %2d -- %lu lines, %lu bytes --]:%s\n"),
101 cpre, msg_no, (ul_i)mp->m_lines, (ul_i)mp->m_size, csuf);
102 NYD_LEAVE;
105 static void
106 _parse_from_(struct message *mp, char date[FROM_DATEBUF]) /* TODO line pool */
108 FILE *ibuf;
109 int hlen;
110 char *hline = NULL;
111 size_t hsize = 0;
112 NYD_ENTER;
114 if ((ibuf = setinput(&mb, mp, NEED_HEADER)) != NULL &&
115 (hlen = readline_restart(ibuf, &hline, &hsize, 0)) > 0)
116 extract_date_from_from_(hline, hlen, date);
117 if (hline != NULL)
118 free(hline);
119 NYD_LEAVE;
122 static void
123 _print_head(size_t yetprinted, size_t msgno, FILE *f, bool_t threaded)
125 enum {attrlen = 14};
126 char attrlist[attrlen +1], *cp;
127 char const *fmt;
128 NYD_ENTER;
130 if ((cp = ok_vlook(attrlist)) != NULL) {
131 if (strlen(cp) == attrlen) {
132 memcpy(attrlist, cp, attrlen +1);
133 goto jattrok;
135 n_err(_("*attrlist* is not of the correct length, using builtin\n"));
138 if (ok_blook(bsdcompat) || ok_blook(bsdflags)) {
139 char const bsdattr[attrlen +1] = "NU *HMFAT+-$~";
140 memcpy(attrlist, bsdattr, sizeof bsdattr);
141 } else if (ok_blook(SYSV3)) {
142 char const bsdattr[attrlen +1] = "NU *HMFAT+-$~";
143 memcpy(attrlist, bsdattr, sizeof bsdattr);
144 OBSOLETE(_("*SYSV3*: please use *bsdcompat* or *bsdflags*, "
145 "or set *attrlist*"));
146 } else {
147 char const pattr[attrlen +1] = "NUROSPMFAT+-$~";
148 memcpy(attrlist, pattr, sizeof pattr);
151 jattrok:
152 if ((fmt = ok_vlook(headline)) == NULL) {
153 fmt = ((ok_blook(bsdcompat) || ok_blook(bsdheadline))
154 ? "%>%a%m %-20f %16d %3l/%-5o %i%-S"
155 : "%>%a%m %-18f %16d %4l/%-5o %i%-s");
158 __hprf(yetprinted, fmt, msgno, f, threaded, attrlist);
159 NYD_LEAVE;
162 static void
163 __hprf(size_t yetprinted, char const *fmt, size_t msgno, FILE *f,
164 bool_t threaded, char const *attrlist)
166 char buf[16], datebuf[FROM_DATEBUF], cbuf[8], *cp, *subjline;
167 char const *datefmt, *date, *name, *fp n_COLOUR( COMMA *colo_tag );
168 int i, n, s, wleft, subjlen;
169 struct message *mp;
170 time_t datet;
171 n_COLOUR( struct n_colour_pen *cpen_new COMMA *cpen_cur COMMA *cpen_bas; )
172 enum {
173 _NONE = 0,
174 _ISDOT = 1<<0,
175 _ISADDR = 1<<1,
176 _ISTO = 1<<2,
177 _IFMT = 1<<3,
178 _LOOP_MASK = (1<<4) - 1,
179 _SFMT = 1<<4
180 } flags = _NONE;
181 NYD_ENTER;
182 UNUSED(buf);
184 if ((mp = message + msgno - 1) == dot)
185 flags = _ISDOT;
186 datet = mp->m_time;
187 date = NULL;
188 n_COLOUR( colo_tag = NULL; )
190 datefmt = ok_vlook(datefield);
191 jredo:
192 if (datefmt != NULL) {
193 fp = hfield1("date", mp);/* TODO use m_date field! */
194 if (fp == NULL) {
195 datefmt = NULL;
196 goto jredo;
198 datet = rfctime(fp);
199 date = fakedate(datet);
200 fp = ok_vlook(datefield_markout_older);
201 i = (*datefmt != '\0');
202 if (fp != NULL)
203 i |= (*fp != '\0') ? 2 | 4 : 2; /* XXX no magics */
205 /* May we strftime(3)? */
206 if (i & (1 | 4))
207 memcpy(&time_current.tc_local, localtime(&datet),
208 sizeof time_current.tc_local);
210 if ((i & 2) && (datet > time_current.tc_time + DATE_SECSDAY ||
211 #define _6M ((DATE_DAYSYEAR / 2) * DATE_SECSDAY)
212 (datet + _6M < time_current.tc_time))) {
213 #undef _6M
214 if ((datefmt = (i & 4) ? fp : NULL) == NULL) {
215 memset(datebuf, ' ', FROM_DATEBUF); /* xxx ur */
216 memcpy(datebuf + 4, date + 4, 7);
217 datebuf[4 + 7] = ' ';
218 memcpy(datebuf + 4 + 7 + 1, date + 20, 4);
219 datebuf[4 + 7 + 1 + 4] = '\0';
220 date = datebuf;
222 n_COLOUR( colo_tag = n_COLOUR_TAG_SUM_OLDER; )
223 } else if ((i & 1) == 0)
224 datefmt = NULL;
225 } else if (datet == (time_t)0 && !(mp->m_flag & MNOFROM)) {
226 /* TODO eliminate this path, query the FROM_ date in setptr(),
227 * TODO all other codepaths do so by themselves ALREADY ?????
228 * TODO assert(mp->m_time != 0);, then
229 * TODO ALSO changes behaviour of datefield_markout_older */
230 _parse_from_(mp, datebuf);
231 date = datebuf;
232 } else
233 date = fakedate(datet);
235 flags |= _ISADDR;
236 name = name1(mp, 0);
237 if (name != NULL && ok_blook(showto) && is_myname(skin(name))) {
238 if ((cp = hfield1("to", mp)) != NULL) {
239 name = cp;
240 flags |= _ISTO;
243 if (name == NULL) {
244 name = "";
245 flags &= ~_ISADDR;
247 if (flags & _ISADDR)
248 name = ok_blook(showname) ? realname(name) : prstr(skin(name));
250 subjline = NULL;
252 /* Detect the width of the non-format characters in *headline*;
253 * like that we can simply use putc() in the next loop, since we have
254 * already calculated their column widths (TODO it's sick) */
255 wleft = subjlen = scrnwidth;
257 for (fp = fmt; *fp != '\0'; ++fp) {
258 if (*fp == '%') {
259 if (*++fp == '-')
260 ++fp;
261 else if (*fp == '+')
262 ++fp;
263 if (digitchar(*fp)) {
264 n = 0;
266 n = 10*n + *fp - '0';
267 while (++fp, digitchar(*fp));
268 subjlen -= n;
270 if (*fp == 'i')
271 flags |= _IFMT;
273 if (*fp == '\0')
274 break;
275 } else {
276 #ifdef HAVE_WCWIDTH
277 if (mb_cur_max > 1) {
278 wchar_t wc;
279 if ((s = mbtowc(&wc, fp, mb_cur_max)) == -1)
280 n = s = 1;
281 else if ((n = wcwidth(wc)) == -1)
282 n = 1;
283 } else
284 #endif
285 n = s = 1;
286 subjlen -= n;
287 wleft -= n;
288 while (--s > 0)
289 ++fp;
293 /* Walk *headline*, producing output TODO not (really) MB safe */
294 #ifdef HAVE_COLOUR
295 if (flags & _ISDOT)
296 colo_tag = n_COLOUR_TAG_SUM_DOT;
297 cpen_bas = n_colour_pen_create(n_COLOUR_ID_SUM_HEADER, colo_tag);
298 n_colour_pen_put(cpen_new = cpen_cur = cpen_bas, f);
299 #endif
301 for (fp = fmt; *fp != '\0'; ++fp) {
302 char c;
304 if ((c = *fp & 0xFF) != '%') {
305 #ifdef HAVE_COLOUR
306 if ((cpen_new = cpen_bas) != cpen_cur)
307 n_colour_pen_put(cpen_cur = cpen_new, f);
308 #endif
309 putc(c, f);
310 continue;
313 flags &= _LOOP_MASK;
314 n = 0;
315 s = 1;
316 if ((c = *++fp) == '-') {
317 s = -1;
318 ++fp;
319 } else if (c == '+')
320 ++fp;
321 if (digitchar(*fp)) {
323 n = 10*n + *fp - '0';
324 while (++fp, digitchar(*fp));
327 if ((c = *fp & 0xFF) == '\0')
328 break;
329 n *= s;
331 cbuf[1] = '\0';
332 switch (c) {
333 case '%':
334 goto jputcb;
335 case '>':
336 case '<':
337 if (flags & _ISDOT) {
338 n_COLOUR( cpen_new = n_colour_pen_create(n_COLOUR_ID_SUM_DOTMARK,
339 colo_tag); );
340 if (options & OPT_UNICODE) {
341 if (c == '>')
342 /* 25B8;BLACK RIGHT-POINTING SMALL TRIANGLE: â–¸ */
343 cbuf[1] = (char)0x96, cbuf[2] = (char)0xB8;
344 else
345 /* 25C2;BLACK LEFT-POINTING SMALL TRIANGLE: â—‚ */
346 cbuf[1] = (char)0x97, cbuf[2] = (char)0x82;
347 c = (char)0xE2;
348 cbuf[3] = '\0';
350 } else
351 c = ' ';
352 goto jputcb;
353 case '$':
354 #ifdef HAVE_SPAM
355 if (n == 0)
356 n = 5;
357 if (UICMP(32, ABS(n), >, wleft))
358 n = (n < 0) ? -wleft : wleft;
359 snprintf(buf, sizeof buf, "%u.%02u",
360 (mp->m_spamscore >> 8), (mp->m_spamscore & 0xFF));
361 n = fprintf(f, "%*s", n, buf);
362 wleft = (n >= 0) ? wleft - n : 0;
363 break;
364 #else
365 c = '?';
366 goto jputcb;
367 #endif
368 case 'a':
369 c = _dispc(mp, attrlist);
370 jputcb:
371 #ifdef HAVE_COLOUR
372 if (cpen_new == cpen_cur)
373 cpen_new = cpen_bas;
374 if (cpen_new != cpen_cur)
375 n_colour_pen_put(cpen_cur = cpen_new, f);
376 #endif
377 if (UICMP(32, ABS(n), >, wleft))
378 n = (n < 0) ? -wleft : wleft;
379 cbuf[0] = c;
380 n = fprintf(f, "%*s", n, cbuf);
381 wleft = (n >= 0) ? wleft - n : 0;
382 #ifdef HAVE_COLOUR
383 if ((cpen_new = cpen_bas) != cpen_cur)
384 n_colour_pen_put(cpen_cur = cpen_new, f);
385 #endif
386 break;
387 case 'd':
388 if (datefmt != NULL) {
389 i = strftime(datebuf, sizeof datebuf, datefmt,
390 &time_current.tc_local);
391 if (i != 0)
392 date = datebuf;
393 else
394 n_err(_("Ignored date format, it excesses the target "
395 "buffer (%lu bytes)\n"), (ul_i)sizeof(datebuf));
396 datefmt = NULL;
398 if (n == 0)
399 n = 16;
400 if (UICMP(32, ABS(n), >, wleft))
401 n = (n < 0) ? -wleft : wleft;
402 n = fprintf(f, "%*.*s", n, n, date);
403 wleft = (n >= 0) ? wleft - n : 0;
404 break;
405 case 'e':
406 if (n == 0)
407 n = 2;
408 if (UICMP(32, ABS(n), >, wleft))
409 n = (n < 0) ? -wleft : wleft;
410 n = fprintf(f, "%*u", n, (threaded == 1 ? mp->m_level : 0));
411 wleft = (n >= 0) ? wleft - n : 0;
412 break;
413 case 'f':
414 if (n == 0) {
415 n = 18;
416 if (s < 0)
417 n = -n;
419 i = ABS(n);
420 if (i > wleft) {
421 i = wleft;
422 n = (n < 0) ? -wleft : wleft;
424 if (flags & _ISTO) /* XXX tr()! */
425 i -= 3;
426 n = fprintf(f, "%s%s", ((flags & _ISTO) ? "To " : ""),
427 colalign(name, i, n, &wleft));
428 if (n < 0)
429 wleft = 0;
430 else if (flags & _ISTO)
431 wleft -= 3;
432 break;
433 case 'i':
434 if (threaded) {
435 #ifdef HAVE_COLOUR
436 cpen_new = n_colour_pen_create(n_COLOUR_ID_SUM_THREAD, colo_tag);
437 if (cpen_new != cpen_cur)
438 n_colour_pen_put(cpen_cur = cpen_new, f);
439 #endif
440 n = __putindent(f, mp, MIN(wleft, scrnwidth - 60));
441 wleft = (n >= 0) ? wleft - n : 0;
442 #ifdef HAVE_COLOUR
443 if ((cpen_new = cpen_bas) != cpen_cur)
444 n_colour_pen_put(cpen_cur = cpen_new, f);
445 #endif
447 break;
448 case 'l':
449 if (n == 0)
450 n = 4;
451 if (UICMP(32, ABS(n), >, wleft))
452 n = (n < 0) ? -wleft : wleft;
453 if (mp->m_xlines) {
454 n = fprintf(f, "%*ld", n, mp->m_xlines);
455 wleft = (n >= 0) ? wleft - n : 0;
456 } else {
457 n = ABS(n);
458 wleft -= n;
459 while (n-- != 0)
460 putc(' ', f);
462 break;
463 case 'm':
464 if (n == 0) {
465 n = 3;
466 if (threaded)
467 for (i = msgCount; i > 999; i /= 10)
468 ++n;
470 if (UICMP(32, ABS(n), >, wleft))
471 n = (n < 0) ? -wleft : wleft;
472 n = fprintf(f, "%*lu", n, (ul_i)msgno);
473 wleft = (n >= 0) ? wleft - n : 0;
474 break;
475 case 'o':
476 if (n == 0)
477 n = -5;
478 if (UICMP(32, ABS(n), >, wleft))
479 n = (n < 0) ? -wleft : wleft;
480 n = fprintf(f, "%*lu", n, (ul_i)mp->m_xsize);
481 wleft = (n >= 0) ? wleft - n : 0;
482 break;
483 case 'S':
484 flags |= _SFMT;
485 /*FALLTHRU*/
486 case 's':
487 if (n == 0)
488 n = subjlen - 2;
489 if (n > 0 && s < 0)
490 n = -n;
491 if (subjlen > wleft)
492 subjlen = wleft;
493 if (UICMP(32, ABS(n), >, subjlen))
494 n = (n < 0) ? -subjlen : subjlen;
495 if (flags & _SFMT)
496 n -= (n < 0) ? -2 : 2;
497 if (n == 0)
498 break;
499 if (subjline == NULL)
500 subjline = __subject(mp, (threaded && (flags & _IFMT)), yetprinted);
501 if (subjline == (char*)-1) {
502 n = fprintf(f, "%*s", n, "");
503 wleft = (n >= 0) ? wleft - n : 0;
504 } else {
505 n = fprintf(f, ((flags & _SFMT) ? "\"%s\"" : "%s"),
506 colalign(subjline, ABS(n), n, &wleft));
507 if (n < 0)
508 wleft = 0;
510 break;
511 case 'T': { /* Message recipient flags */
512 /* We never can reuse "name" since it's the full name */
513 struct name const *np = lextract(hfield1("to", mp), GTO | GSKIN);
514 c = ' ';
515 i = 0;
516 j_A_redo:
517 for (; np != NULL; np = np->n_flink) {
518 switch (is_mlist(np->n_name, FAL0)) {
519 case MLIST_SUBSCRIBED: c = 'S'; goto jputcb;
520 case MLIST_KNOWN: c = 'L'; goto jputcb;
521 case MLIST_OTHER:
522 default: break;
525 if (i != 0)
526 goto jputcb;
527 ++i;
528 np = lextract(hfield1("cc", mp), GCC | GSKIN);
529 goto j_A_redo;
531 case 't':
532 if (n == 0) {
533 n = 3;
534 if (threaded)
535 for (i = msgCount; i > 999; i /= 10)
536 ++n;
538 if (UICMP(32, ABS(n), >, wleft))
539 n = (n < 0) ? -wleft : wleft;
540 n = fprintf(f, "%*lu",
541 n, (threaded ? (ul_i)mp->m_threadpos : (ul_i)msgno));
542 wleft = (n >= 0) ? wleft - n : 0;
543 break;
544 default:
545 if (options & OPT_D_V)
546 n_err(_("Unkown *headline* format: %%%c\n"), c);
547 c = '?';
548 goto jputcb;
551 if (wleft <= 0)
552 break;
555 #ifdef HAVE_COLOUR
556 n_colour_reset(f);
557 #endif
558 putc('\n', f);
560 if (subjline != NULL && subjline != (char*)-1)
561 free(subjline);
562 NYD_LEAVE;
565 static char *
566 __subject(struct message *mp, bool_t threaded, size_t yetprinted)
568 struct str in, out;
569 char *rv = (char*)-1, *ms;
570 NYD_ENTER;
572 if ((ms = hfield1("subject", mp)) == NULL)
573 goto jleave;
575 in.l = strlen(in.s = ms);
576 mime_fromhdr(&in, &out, TD_ICONV | TD_ISPR);
577 rv = ms = out.s;
579 if (!threaded || mp->m_level == 0)
580 goto jleave;
582 /* In a display thread - check whether this message uses the same
583 * Subject: as it's parent or elder neighbour, suppress printing it if
584 * this is the case. To extend this a bit, ignore any leading Re: or
585 * Fwd: plus follow-up WS. Ignore invisible messages along the way */
586 ms = subject_re_trim(ms);
588 for (; (mp = prev_in_thread(mp)) != NULL && yetprinted-- > 0;) {
589 char *os;
591 if (visible(mp) && (os = hfield1("subject", mp)) != NULL) {
592 struct str oout;
593 int x;
595 in.l = strlen(in.s = os);
596 mime_fromhdr(&in, &oout, TD_ICONV | TD_ISPR);
597 x = asccasecmp(ms, subject_re_trim(oout.s));
598 free(oout.s);
600 if (!x) {
601 free(out.s);
602 rv = (char*)-1;
604 break;
607 jleave:
608 NYD_LEAVE;
609 return rv;
612 static int
613 __putindent(FILE *fp, struct message *mp, int maxwidth)/* XXX no magic consts */
615 struct message *mq;
616 int *us, indlvl, indw, i, important = MNEW | MFLAGGED;
617 char *cs;
618 NYD_ENTER;
620 if (mp->m_level == 0 || maxwidth == 0) {
621 indw = 0;
622 goto jleave;
625 cs = ac_alloc(mp->m_level);
626 us = ac_alloc(mp->m_level * sizeof *us);
628 i = mp->m_level - 1;
629 if (mp->m_younger && UICMP(32, i + 1, ==, mp->m_younger->m_level)) {
630 if (mp->m_parent && mp->m_parent->m_flag & important)
631 us[i] = mp->m_flag & important ? 0x2523 : 0x2520;
632 else
633 us[i] = mp->m_flag & important ? 0x251D : 0x251C;
634 cs[i] = '+';
635 } else {
636 if (mp->m_parent && mp->m_parent->m_flag & important)
637 us[i] = mp->m_flag & important ? 0x2517 : 0x2516;
638 else
639 us[i] = mp->m_flag & important ? 0x2515 : 0x2514;
640 cs[i] = '\\';
643 mq = mp->m_parent;
644 for (i = mp->m_level - 2; i >= 0; --i) {
645 if (mq) {
646 if (UICMP(32, i, >, mq->m_level - 1)) {
647 us[i] = cs[i] = ' ';
648 continue;
650 if (mq->m_younger) {
651 if (mq->m_parent && (mq->m_parent->m_flag & important))
652 us[i] = 0x2503;
653 else
654 us[i] = 0x2502;
655 cs[i] = '|';
656 } else
657 us[i] = cs[i] = ' ';
658 mq = mq->m_parent;
659 } else
660 us[i] = cs[i] = ' ';
663 --maxwidth;
664 for (indlvl = indw = 0; (ui8_t)indlvl < mp->m_level && indw < maxwidth;
665 ++indlvl) {
666 if (indw < maxwidth - 1)
667 indw += (int)putuc(us[indlvl], cs[indlvl] & 0xFF, fp);
668 else
669 indw += (int)putuc(0x21B8, '^', fp);
671 indw += putuc(0x25B8, '>', fp);
673 ac_free(us);
674 ac_free(cs);
675 jleave:
676 NYD_LEAVE;
677 return indw;
680 static int
681 _dispc(struct message *mp, char const *a)
683 int i = ' ';
684 NYD_ENTER;
686 if ((mp->m_flag & (MREAD | MNEW)) == MREAD)
687 i = a[3];
688 if ((mp->m_flag & (MREAD | MNEW)) == (MREAD | MNEW))
689 i = a[2];
690 if (mp->m_flag & MANSWERED)
691 i = a[8];
692 if (mp->m_flag & MDRAFTED)
693 i = a[9];
694 if ((mp->m_flag & (MREAD | MNEW)) == MNEW)
695 i = a[0];
696 if (!(mp->m_flag & (MREAD | MNEW)))
697 i = a[1];
698 if (mp->m_flag & MSPAM)
699 i = a[12];
700 if (mp->m_flag & MSPAMUNSURE)
701 i = a[13];
702 if (mp->m_flag & MSAVED)
703 i = a[4];
704 if (mp->m_flag & MPRESERVE)
705 i = a[5];
706 if (mp->m_flag & (MBOX | MBOXED))
707 i = a[6];
708 if (mp->m_flag & MFLAGGED)
709 i = a[7];
710 if (mb.mb_threaded == 1 && mp->m_collapsed > 0)
711 i = a[11];
712 if (mb.mb_threaded == 1 && mp->m_collapsed < 0)
713 i = a[10];
714 NYD_LEAVE;
715 return i;
718 static int
719 a_cmd_scroll(char const *arg, bool_t onlynew){
720 long l;
721 char *eptr;
722 bool_t isabs;
723 int msgspec, size, maxs;
724 NYD2_ENTER;
726 msgspec = onlynew ? -1 : 0;
727 size = screensize();
728 maxs = msgCount / size;
730 switch(*arg){
731 case '\0':
732 ++_screen;
733 goto jfwd;
734 case '$':
735 if(arg[1] != '\0')
736 goto jerr;
737 if(_screen == maxs)
738 goto jerrfwd;
739 _screen = maxs;
740 break;
741 case '+':
742 if(arg[1] == '\0')
743 ++_screen;
744 else{
745 isabs = FAL0;
747 ++arg;
748 if(0){
749 case '1': case '2': case '3': case '4': case '5':
750 case '6': case '7': case '8': case '9': case '0':
751 isabs = TRU1;
753 l = strtol(arg, &eptr, 10);
754 if(*eptr != '\0')
755 goto jerr;
756 if(l > maxs - (isabs ? 0 : _screen))
757 goto jerrfwd;
758 _screen = isabs ? (int)l : _screen + l;
760 jfwd:
761 if(_screen > maxs){
762 jerrfwd:
763 _screen = maxs;
764 printf(_("On last screenful of messages\n"));
766 break;
768 case '-':
769 if(arg[1] == '\0')
770 --_screen;
771 else{
772 ++arg;
773 l = strtol(arg, &eptr, 10);
774 if(*eptr != '\0')
775 goto jerr;
776 if(l > _screen)
777 goto jerrbwd;
778 _screen -= l;
780 if(_screen < 0){
781 jerrbwd:
782 _screen = 0;
783 printf(_("On first screenful of messages\n"));
785 if(msgspec == -1)
786 msgspec = -2;
787 break;
788 default:
789 jerr:
790 n_err(_("Unrecognized scrolling command: %s\n"), arg);
791 size = 1;
792 goto jleave;
795 size = _headers(msgspec);
796 jleave:
797 NYD2_LEAVE;
798 return size;
801 static int
802 _headers(int msgspec) /* TODO rework v15 */
804 struct n_sigman sm;
805 bool_t volatile isrelax;
806 ui32_t volatile flag;
807 int g, k, mesg, size;
808 int volatile lastg = 1;
809 struct message *mp, *mq, *lastmq = NULL;
810 enum mflag fl = MNEW | MFLAGGED;
811 NYD_ENTER;
813 time_current_update(&time_current, FAL0);
815 flag = 0;
816 isrelax = FAL0;
817 n_SIGMAN_ENTER_SWITCH(&sm, n_SIGMAN_ALL) {
818 case 0:
819 break;
820 default:
821 goto jleave;
824 #ifdef HAVE_COLOUR
825 if (options & OPT_INTERACTIVE)
826 n_colour_env_create(n_COLOUR_CTX_SUM, FAL0);
827 #endif
829 size = screensize();
830 if (_screen < 0)
831 _screen = 0;
832 #if 0 /* FIXME original code path */
833 k = _screen * size;
834 #else
835 if (msgspec <= 0)
836 k = _screen * size;
837 else
838 k = msgspec;
839 #endif
840 if (k >= msgCount)
841 k = msgCount - size;
842 if (k < 0)
843 k = 0;
845 if (mb.mb_threaded == 0) {
846 g = 0;
847 mq = message;
848 for (mp = message; PTRCMP(mp, <, message + msgCount); ++mp)
849 if (visible(mp)) {
850 if (g % size == 0)
851 mq = mp;
852 if (mp->m_flag & fl) {
853 lastg = g;
854 lastmq = mq;
856 if ((msgspec > 0 && PTRCMP(mp, ==, message + msgspec - 1)) ||
857 (msgspec == 0 && g == k) ||
858 (msgspec == -2 && g == k + size && lastmq) ||
859 (msgspec < 0 && g >= k && (mp->m_flag & fl) != 0))
860 break;
861 g++;
863 if (lastmq && (msgspec == -2 ||
864 (msgspec == -1 && PTRCMP(mp, ==, message + msgCount)))) {
865 g = lastg;
866 mq = lastmq;
868 _screen = g / size;
870 mp = mq;
871 mesg = (int)PTR2SIZE(mp - message);
872 if (PTRCMP(dot, !=, message + msgspec - 1)) { /* TODO really?? */
873 for (mq = mp; PTRCMP(mq, <, message + msgCount); ++mq)
874 if (visible(mq)) {
875 setdot(mq);
876 break;
880 srelax_hold();
881 isrelax = TRU1;
882 for (; PTRCMP(mp, <, message + msgCount); ++mp) {
883 ++mesg;
884 if (!visible(mp))
885 continue;
886 if (UICMP(32, flag++, >=, size))
887 break;
888 _print_head(0, mesg, stdout, 0);
889 srelax();
891 srelax_rele();
892 isrelax = FAL0;
893 } else { /* threaded */
894 g = 0;
895 mq = threadroot;
896 for (mp = threadroot; mp; mp = next_in_thread(mp))
897 if (visible(mp) &&
898 (mp->m_collapsed <= 0 ||
899 PTRCMP(mp, ==, message + msgspec - 1))) {
900 if (g % size == 0)
901 mq = mp;
902 if (mp->m_flag & fl) {
903 lastg = g;
904 lastmq = mq;
906 if ((msgspec > 0 && PTRCMP(mp, ==, message + msgspec - 1)) ||
907 (msgspec == 0 && g == k) ||
908 (msgspec == -2 && g == k + size && lastmq) ||
909 (msgspec < 0 && g >= k && (mp->m_flag & fl) != 0))
910 break;
911 g++;
913 if (lastmq && (msgspec == -2 ||
914 (msgspec == -1 && PTRCMP(mp, ==, message + msgCount)))) {
915 g = lastg;
916 mq = lastmq;
918 _screen = g / size;
919 mp = mq;
920 if (PTRCMP(dot, !=, message + msgspec - 1)) { /* TODO really?? */
921 for (mq = mp; mq; mq = next_in_thread(mq))
922 if (visible(mq) && mq->m_collapsed <= 0) {
923 setdot(mq);
924 break;
928 srelax_hold();
929 isrelax = TRU1;
930 while (mp) {
931 if (visible(mp) &&
932 (mp->m_collapsed <= 0 ||
933 PTRCMP(mp, ==, message + msgspec - 1))) {
934 if (UICMP(32, flag++, >=, size))
935 break;
936 _print_head(flag - 1, PTR2SIZE(mp - message + 1), stdout,
937 mb.mb_threaded);
938 srelax();
940 mp = next_in_thread(mp);
942 srelax_rele();
943 isrelax = FAL0;
946 if (!flag) {
947 printf(_("No more mail.\n"));
948 if (pstate & (PS_HOOK_MASK | PS_ROBOT))
949 flag = !flag;
952 n_sigman_cleanup_ping(&sm);
953 jleave:
954 if (isrelax)
955 srelax_rele();
956 n_COLOUR( n_colour_env_gut((sm.sm_signo != SIGPIPE) ? stdout : NULL); )
957 NYD_LEAVE;
958 n_sigman_leave(&sm, n_SIGMAN_VIPSIGS_NTTYOUT);
959 return !flag;
962 static int
963 _type1(int *msgvec, bool_t doign, bool_t dopage, bool_t dopipe,
964 bool_t dodecode, char *cmd, ui64_t *tstats)
966 struct n_sigman sm;
967 ui64_t mstats[1];
968 int volatile rv = 1;
969 int *ip;
970 struct message *mp;
971 char const *cp;
972 FILE * volatile obuf;
973 bool_t volatile isrelax = FAL0;
974 NYD_ENTER;
975 {/* C89.. */
976 enum sendaction const action = ((dopipe && ok_blook(piperaw))
977 ? SEND_MBOX : dodecode
978 ? SEND_SHOW : doign
979 ? SEND_TODISP : SEND_TODISP_ALL);
980 bool_t const volatile formfeed = (dopipe && ok_blook(page));
981 obuf = stdout;
983 n_SIGMAN_ENTER_SWITCH(&sm, n_SIGMAN_ALL) {
984 case 0:
985 break;
986 default:
987 goto jleave;
990 if (dopipe) {
991 if ((obuf = Popen(cmd, "w", ok_vlook(SHELL), NULL, 1)) == NULL) {
992 n_perr(cmd, 0);
993 obuf = stdout;
995 } else if ((options & OPT_TTYOUT) && (dopage ||
996 ((options & OPT_INTERACTIVE) && (cp = ok_vlook(crt)) != NULL))) {
997 size_t nlines = 0;
999 if (!dopage) {
1000 for (ip = msgvec; *ip && PTRCMP(ip - msgvec, <, msgCount); ++ip) {
1001 mp = message + *ip - 1;
1002 if (!(mp->m_have & HAVE_BODY))
1003 if (get_body(mp) != OKAY)
1004 goto jcleanup_leave;
1005 nlines += mp->m_lines + 1; /* Message info XXX and PARTS... */
1009 /* >= not <: we return to the prompt */
1010 if (dopage || UICMP(z, nlines, >=,
1011 (*cp != '\0' ? strtoul(cp, NULL, 0) : (size_t)realscreenheight))) {
1012 if ((obuf = n_pager_open()) == NULL)
1013 obuf = stdout;
1015 #ifdef HAVE_COLOUR
1016 if ((options & OPT_INTERACTIVE) &&
1017 (action == SEND_TODISP || action == SEND_TODISP_ALL ||
1018 action == SEND_SHOW))
1019 n_colour_env_create(n_COLOUR_CTX_VIEW, obuf != stdout);
1020 #endif
1022 #ifdef HAVE_COLOUR
1023 else if ((options & OPT_INTERACTIVE) &&
1024 (action == SEND_TODISP || action == SEND_TODISP_ALL))
1025 n_colour_env_create(n_COLOUR_CTX_VIEW, FAL0);
1026 #endif
1028 /*TODO unless we have our signal manager special care must be taken */
1029 srelax_hold();
1030 isrelax = TRU1;
1031 for (ip = msgvec; *ip && PTRCMP(ip - msgvec, <, msgCount); ++ip) {
1032 mp = message + *ip - 1;
1033 touch(mp);
1034 setdot(mp);
1035 pstate |= PS_DID_PRINT_DOT;
1036 uncollapse1(mp, 1);
1037 if (!dopipe && ip != msgvec)
1038 fprintf(obuf, "\n");
1039 if (action != SEND_MBOX)
1040 _show_msg_overview(obuf, mp, *ip);
1041 sendmp(mp, obuf, (doign ? ignore : NULL), NULL, action, mstats);
1042 srelax();
1043 if (formfeed) /* TODO a nicer way to separate piped messages! */
1044 putc('\f', obuf);
1045 if (tstats != NULL)
1046 tstats[0] += mstats[0];
1048 srelax_rele();
1049 isrelax = FAL0;
1051 rv = 0;
1052 jcleanup_leave:
1053 n_sigman_cleanup_ping(&sm);
1054 jleave:
1055 if (isrelax)
1056 srelax_rele();
1057 n_COLOUR( n_colour_env_gut((sm.sm_signo != SIGPIPE) ? obuf : NULL); )
1058 if (obuf != stdout)
1059 n_pager_close(obuf);
1061 NYD_LEAVE;
1062 n_sigman_leave(&sm, n_SIGMAN_VIPSIGS_NTTYOUT);
1063 return rv;
1066 static int
1067 _pipe1(char *str, int doign)
1069 ui64_t stats[1];
1070 char const *cmd, *cmdq;
1071 int *msgvec, rv = 1;
1072 bool_t needs_list;
1073 NYD_ENTER;
1075 if ((cmd = laststring(str, &needs_list, TRU1)) == NULL) {
1076 cmd = ok_vlook(cmd);
1077 if (cmd == NULL || *cmd == '\0') {
1078 n_err(_("Variable *cmd* not set\n"));
1079 goto jleave;
1083 msgvec = salloc((msgCount + 2) * sizeof *msgvec);
1085 if (!needs_list) {
1086 *msgvec = first(0, MMNORM);
1087 if (*msgvec == 0) {
1088 if (pstate & (PS_HOOK_MASK | PS_ROBOT)) {
1089 rv = 0;
1090 goto jleave;
1092 puts(_("No messages to pipe."));
1093 goto jleave;
1095 msgvec[1] = 0;
1096 } else if (getmsglist(str, msgvec, 0) < 0)
1097 goto jleave;
1098 if (*msgvec == 0) {
1099 if (pstate & (PS_HOOK_MASK | PS_ROBOT)) {
1100 rv = 0;
1101 goto jleave;
1103 printf("No applicable messages.\n");
1104 goto jleave;
1107 cmdq = n_shexp_quote_cp(cmd, FAL0);
1108 printf(_("Pipe to: %s\n"), cmdq);
1109 stats[0] = 0;
1110 if ((rv = _type1(msgvec, doign, FAL0, TRU1, FAL0, UNCONST(cmd), stats)) == 0)
1111 printf("%s %" PRIu64 " bytes\n", cmdq, stats[0]);
1112 jleave:
1113 NYD_LEAVE;
1114 return rv;
1117 static int
1118 a_cmd_top(void *vp, struct ignoretab *itp){
1119 struct n_string s;
1120 int *msgvec, *ip;
1121 enum{a_NONE, a_SQUEEZE = 1u<<0,
1122 a_EMPTY = 1u<<8, a_STOP = 1u<<9, a_WORKMASK = 0xFF00u} f;
1123 size_t tmax, plines;
1124 FILE *iobuf, *pbuf;
1125 NYD2_ENTER;
1127 if((iobuf = Ftmp(NULL, "topio", OF_RDWR | OF_UNLINK | OF_REGISTER)) == NULL){
1128 n_perr(_("`top': I/O temporary file"), 0);
1129 vp = NULL;
1130 goto jleave;
1132 if((pbuf = Ftmp(NULL, "toppag", OF_RDWR | OF_UNLINK | OF_REGISTER)) == NULL){
1133 n_perr(_("`top': temporary pager file"), 0);
1134 vp = NULL;
1135 goto jleave1;
1138 /* TODO In v15 we should query the m_message object, and directly send only
1139 * TODO those parts, optionally over empty-line-squeeze and quote-strip
1140 * TODO filters, in which we are interested in: only text content!
1141 * TODO And: with *topsqueeze*, header/content separating empty line.. */
1142 pstate &= ~PS_MSGLIST_DIRECT; /* TODO NO ATTACHMENTS */
1143 plines = 0;
1145 #ifdef HAVE_COLOUR
1146 if (options & OPT_INTERACTIVE)
1147 n_colour_env_create(n_COLOUR_CTX_VIEW, TRU1);
1148 #endif
1149 n_string_creat_auto(&s);
1150 /* C99 */{
1151 long l;
1153 if((l = strtol(ok_vlook(toplines), NULL, 0)) <= 0){
1154 tmax = (size_t)screensize();
1155 if(l < 0){
1156 l = ABS(l);
1157 tmax >>= l;
1159 }else
1160 tmax = (size_t)l;
1162 f = ok_blook(topsqueeze) ? a_SQUEEZE : a_NONE;
1164 for(ip = msgvec = vp;
1165 *ip != 0 && UICMP(z, PTR2SIZE(ip - msgvec), <, msgCount); ++ip){
1166 struct message *mp;
1168 mp = &message[*ip - 1];
1169 touch(mp);
1170 setdot(mp);
1171 pstate |= PS_DID_PRINT_DOT;
1172 uncollapse1(mp, 1);
1174 rewind(iobuf);
1175 if(ftruncate(fileno(iobuf), 0)){
1176 n_perr(_("`top': ftruncate(2)"), 0);
1177 vp = NULL;
1178 break;
1180 if(sendmp(mp, iobuf, itp, NULL, SEND_TODISP_ALL, NULL) < 0){
1181 n_err(_("`top': failed to prepare message %d\n"), *ip);
1182 vp = NULL;
1183 break;
1185 fflush_rewind(iobuf);
1187 _show_msg_overview(pbuf, mp, *ip);
1188 ++plines;
1189 /* C99 */{
1190 size_t l;
1192 n_string_trunc(&s, 0);
1193 for(l = 0, f &= ~a_WORKMASK; !(f & a_STOP);){
1194 int c;
1196 if((c = getc(iobuf)) == EOF){
1197 f |= a_STOP;
1198 c = '\n';
1201 if(c != '\n')
1202 n_string_push_c(&s, c);
1203 else if((f & a_SQUEEZE) && s.s_len == 0){
1204 if(!(f & a_STOP) && ((f & a_EMPTY) || tmax - 1 <= l))
1205 continue;
1206 if(putc('\n', pbuf) == EOF){
1207 vp = NULL;
1208 break;
1210 f |= a_EMPTY;
1211 ++l;
1212 }else{
1213 char const *cp, *xcp;
1215 cp = n_string_cp_const(&s);
1216 /* TODO Brute simple skip part overviews; see above.. */
1217 if(!(f & a_SQUEEZE))
1218 c = '\1';
1219 else if(s.s_len > 8 &&
1220 (xcp = strstr(cp, "[-- ")) != NULL &&
1221 PTRCMP(xcp, <, strstr(cp, " --]")))
1222 c = '\0';
1223 else for(; (c = *cp) != '\0'; ++cp){
1224 if(!asciichar(c))
1225 break;
1226 if(!blankspacechar(c)){
1227 if(!ISQUOTE(c))
1228 break;
1229 c = '\0';
1230 break;
1234 if(c != '\0'){
1235 if(fputs(n_string_cp_const(&s), pbuf) == EOF ||
1236 putc('\n', pbuf) == EOF){
1237 vp = NULL;
1238 break;
1240 if(++l >= tmax)
1241 break;
1242 f &= ~a_EMPTY;
1243 }else
1244 f |= a_EMPTY;
1245 n_string_trunc(&s, 0);
1248 if(vp == NULL)
1249 break;
1250 if(l > 0)
1251 plines += l;
1252 else{
1253 if(!(f & a_EMPTY) && putc('\n', pbuf) == EOF){
1254 vp = NULL;
1255 break;
1257 ++plines;
1262 n_string_gut(&s);
1263 n_COLOUR( n_colour_env_gut(pbuf); )
1265 fflush(pbuf);
1266 page_or_print(pbuf, plines);
1268 Fclose(pbuf);
1269 jleave1:
1270 Fclose(iobuf);
1271 jleave:
1272 NYD2_LEAVE;
1273 return (vp != NULL);
1276 FL int
1277 c_cmdnotsupp(void *v) /* TODO -> lex.c */
1279 NYD_ENTER;
1280 UNUSED(v);
1281 n_err(_("The requested feature is not compiled in\n"));
1282 NYD_LEAVE;
1283 return 1;
1286 FL int
1287 c_headers(void *v)
1289 int rv;
1290 NYD_ENTER;
1292 rv = print_header_group((int*)v);
1293 NYD_LEAVE;
1294 return rv;
1297 FL int
1298 print_header_group(int *vector)
1300 int rv;
1301 NYD_ENTER;
1303 assert(vector != NULL && vector != (void*)-1);
1304 rv = _headers(vector[0]);
1305 NYD_LEAVE;
1306 return rv;
1309 FL int
1310 c_scroll(void *v)
1312 int rv;
1313 NYD_ENTER;
1315 rv = a_cmd_scroll(v, FAL0);
1316 NYD_LEAVE;
1317 return rv;
1320 FL int
1321 c_Scroll(void *v)
1323 int rv;
1324 NYD_ENTER;
1326 rv = a_cmd_scroll(v, TRU1);
1327 NYD_LEAVE;
1328 return rv;
1331 FL int
1332 c_from(void *v)
1334 struct n_sigman sm;
1335 int *msgvec = v, *ip, n;
1336 char *cp;
1337 FILE * volatile obuf;
1338 bool_t volatile isrelax;
1339 NYD_ENTER;
1341 time_current_update(&time_current, FAL0);
1343 obuf = stdout;
1344 isrelax = FAL0;
1345 n_SIGMAN_ENTER_SWITCH(&sm, n_SIGMAN_ALL) {
1346 case 0:
1347 break;
1348 default:
1349 goto jleave;
1352 if (options & OPT_INTERACTIVE) {
1353 if ((cp = ok_vlook(crt)) != NULL) {
1354 for (n = 0, ip = msgvec; *ip != 0; ++ip)
1355 ++n;
1356 if (UICMP(z, n, >, (*cp == '\0'
1357 ? (size_t)screensize() : strtoul(cp, NULL, 0)) + 3) &&
1358 (obuf = n_pager_open()) == NULL)
1359 obuf = stdout;
1361 n_COLOUR( n_colour_env_create(n_COLOUR_CTX_SUM, obuf != stdout); )
1364 /* Update dot before display so that the dotmark etc. are correct */
1365 for (ip = msgvec; *ip != 0; ++ip)
1367 if (--ip >= msgvec)
1368 setdot(message + *ip - 1);
1370 srelax_hold();
1371 isrelax = TRU1;
1372 for (n = 0, ip = msgvec; *ip != 0; ++ip) { /* TODO join into _print_head() */
1373 _print_head((size_t)n++, (size_t)*ip, obuf, mb.mb_threaded);
1374 srelax();
1376 srelax_rele();
1377 isrelax = FAL0;
1379 n_sigman_cleanup_ping(&sm);
1380 jleave:
1381 if (isrelax)
1382 srelax_rele();
1383 n_COLOUR( n_colour_env_gut((sm.sm_signo != SIGPIPE) ? obuf : NULL); )
1384 if (obuf != stdout)
1385 n_pager_close(obuf);
1386 NYD_LEAVE;
1387 n_sigman_leave(&sm, n_SIGMAN_VIPSIGS_NTTYOUT);
1388 return 0;
1391 FL void
1392 print_headers(size_t bottom, size_t topx, bool_t only_marked)
1394 struct n_sigman sm;
1395 bool_t volatile isrelax;
1396 size_t printed;
1397 NYD_ENTER;
1399 time_current_update(&time_current, FAL0);
1401 isrelax = FAL0;
1402 n_SIGMAN_ENTER_SWITCH(&sm, n_SIGMAN_ALL) {
1403 case 0:
1404 break;
1405 default:
1406 goto jleave;
1409 #ifdef HAVE_COLOUR
1410 if (options & OPT_INTERACTIVE)
1411 n_colour_env_create(n_COLOUR_CTX_SUM, FAL0);
1412 #endif
1414 srelax_hold();
1415 isrelax = TRU1;
1416 for (printed = 0; bottom <= topx; ++bottom) {
1417 struct message *mp = message + bottom - 1;
1418 if (only_marked) {
1419 if (!(mp->m_flag & MMARK))
1420 continue;
1421 } else if (!visible(mp))
1422 continue;
1423 _print_head(printed++, bottom, stdout, FAL0);
1424 srelax();
1426 srelax_rele();
1427 isrelax = FAL0;
1429 n_sigman_cleanup_ping(&sm);
1430 jleave:
1431 if (isrelax)
1432 srelax_rele();
1433 n_COLOUR( n_colour_env_gut((sm.sm_signo != SIGPIPE) ? stdout : NULL); )
1434 NYD_LEAVE;
1435 n_sigman_leave(&sm, n_SIGMAN_VIPSIGS_NTTYOUT);
1438 FL int
1439 c_pdot(void *v)
1441 NYD_ENTER;
1442 UNUSED(v);
1443 printf("%d\n", (int)PTR2SIZE(dot - message + 1));
1444 NYD_LEAVE;
1445 return 0;
1448 FL int
1449 c_more(void *v)
1451 int *msgvec = v, rv;
1452 NYD_ENTER;
1454 rv = _type1(msgvec, TRU1, TRU1, FAL0, FAL0, NULL, NULL);
1455 NYD_LEAVE;
1456 return rv;
1459 FL int
1460 c_More(void *v)
1462 int *msgvec = v, rv;
1463 NYD_ENTER;
1465 rv = _type1(msgvec, FAL0, TRU1, FAL0, FAL0, NULL, NULL);
1466 NYD_LEAVE;
1467 return rv;
1470 FL int
1471 c_type(void *v)
1473 int *msgvec = v, rv;
1474 NYD_ENTER;
1476 rv = _type1(msgvec, TRU1, FAL0, FAL0, FAL0, NULL, NULL);
1477 NYD_LEAVE;
1478 return rv;
1481 FL int
1482 c_Type(void *v)
1484 int *msgvec = v, rv;
1485 NYD_ENTER;
1487 rv = _type1(msgvec, FAL0, FAL0, FAL0, FAL0, NULL, NULL);
1488 NYD_LEAVE;
1489 return rv;
1492 FL int
1493 c_show(void *v)
1495 int *msgvec = v, rv;
1496 NYD_ENTER;
1498 rv = _type1(msgvec, FAL0, FAL0, FAL0, TRU1, NULL, NULL);
1499 NYD_LEAVE;
1500 return rv;
1503 FL int
1504 c_pipe(void *v)
1506 char *str = v;
1507 int rv;
1508 NYD_ENTER;
1510 rv = _pipe1(str, 1);
1511 NYD_LEAVE;
1512 return rv;
1515 FL int
1516 c_Pipe(void *v)
1518 char *str = v;
1519 int rv;
1520 NYD_ENTER;
1522 rv = _pipe1(str, 0);
1523 NYD_LEAVE;
1524 return rv;
1527 FL int
1528 c_top(void *v){
1529 struct ignoretab it[2];
1530 int rv;
1531 NYD_ENTER;
1533 n_ignoretab_creat(&it[0], TRU1);
1534 n_ignoretab_creat(&it[1], TRU1);
1535 n_ignoretab_insert(&it[1], "from", sizeof("from") -1);
1536 n_ignoretab_insert(&it[1], "to", sizeof("to") -1);
1537 n_ignoretab_insert(&it[1], "cc", sizeof("cc") -1);
1538 n_ignoretab_insert(&it[1], "subject", sizeof("subject") -1);
1540 rv = !a_cmd_top(v, it);
1541 NYD_LEAVE;
1542 return rv;
1545 FL int
1546 c_Top(void *v){
1547 int rv;
1548 NYD_ENTER;
1550 rv = !a_cmd_top(v, ignore);
1551 NYD_LEAVE;
1552 return rv;
1555 FL int
1556 c_folders(void *v)
1558 char const *cp;
1559 char **argv;
1560 int rv;
1561 NYD_ENTER;
1563 rv = 1;
1565 if(*(argv = v) != NULL){
1566 if((cp = fexpand(*argv, FEXP_NSHELL | FEXP_LOCAL)) == NULL)
1567 goto jleave;
1568 }else
1569 cp = folder_query();
1571 run_command(ok_vlook(LISTER), 0, COMMAND_FD_PASS, COMMAND_FD_PASS, cp,
1572 NULL, NULL, NULL);
1573 jleave:
1574 NYD_LEAVE;
1575 return rv;
1578 /* s-it-mode */