Add n_msleep(), and use it..
[s-mailx.git] / cmd1.c
blob9f729d0036e75105a575bfdb8baffb9c39ea7bb4
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 - 2015 Steffen (Daode) Nurpmeso <sdaoden@users.sf.net>.
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;
43 static sigjmp_buf _cmd1_pipejmp;
45 static void _cmd1_onpipe(int signo);
47 /* Prepare and print "[Message: xy]:" intro */
48 static void _show_msg_overview(FILE *obuf, struct message *mp, int msg_no);
50 /* ... And place the extracted date in `date' */
51 static void _parse_from_(struct message *mp, char date[FROM_DATEBUF]);
53 /* Print out the header of a specific message
54 * __hprf: handle *headline*
55 * __subject: return -1 if Subject: yet seen, otherwise smalloc()d Subject:
56 * __putindent: print out the indenting in threaded display */
57 static void _print_head(size_t yetprinted, size_t msgno, FILE *f,
58 bool_t threaded);
59 static void __hprf(size_t yetprinted, char const *fmt, size_t msgno,
60 FILE *f, bool_t threaded, char const *attrlist);
61 static char * __subject(struct message *mp, bool_t threaded,
62 size_t yetprinted);
63 static int __putindent(FILE *fp, struct message *mp, int maxwidth);
65 static int _dispc(struct message *mp, char const *a);
67 /* Shared `z' implementation */
68 static int a_cmd_scroll(char const *arg, bool_t onlynew);
70 /* Shared `headers' implementation */
71 static int _headers(int msgspec);
73 /* Show the requested messages */
74 static int _type1(int *msgvec, bool_t doign, bool_t dopage, bool_t dopipe,
75 bool_t dodecode, char *cmd, ui64_t *tstats);
77 /* Pipe the requested messages */
78 static int _pipe1(char *str, int doign);
80 static void
81 _cmd1_onpipe(int signo)
83 NYD_X; /* Signal handler */
84 UNUSED(signo);
85 siglongjmp(_cmd1_pipejmp, 1);
88 static void
89 _show_msg_overview(FILE *obuf, struct message *mp, int msg_no)
91 char const *cpre = "", *csuf = "";
92 NYD_ENTER;
94 #ifdef HAVE_COLOUR
95 if (pstate & PS_COLOUR_ACTIVE) {
96 struct n_colour_pen *cpen;
98 if ((cpen = n_colour_pen_create(n_COLOUR_ID_VIEW_MSGINFO, NULL)) != NULL){
99 struct str const *sp;
101 if ((sp = n_colour_pen_to_str(cpen)) != NULL)
102 cpre = sp->s;
103 if ((sp = n_colour_reset_to_str()) != NULL)
104 csuf = sp->s;
107 #endif
108 fprintf(obuf, _("%s[-- Message %2d -- %lu lines, %lu bytes --]:%s\n"),
109 cpre, msg_no, (ul_i)mp->m_lines, (ul_i)mp->m_size, csuf);
110 NYD_LEAVE;
113 static void
114 _parse_from_(struct message *mp, char date[FROM_DATEBUF]) /* TODO line pool */
116 FILE *ibuf;
117 int hlen;
118 char *hline = NULL;
119 size_t hsize = 0;
120 NYD_ENTER;
122 if ((ibuf = setinput(&mb, mp, NEED_HEADER)) != NULL &&
123 (hlen = readline_restart(ibuf, &hline, &hsize, 0)) > 0)
124 extract_date_from_from_(hline, hlen, date);
125 if (hline != NULL)
126 free(hline);
127 NYD_LEAVE;
130 static void
131 _print_head(size_t yetprinted, size_t msgno, FILE *f, bool_t threaded)
133 enum {attrlen = 14};
134 char attrlist[attrlen +1], *cp;
135 char const *fmt;
136 NYD_ENTER;
138 if ((cp = ok_vlook(attrlist)) != NULL) {
139 if (strlen(cp) == attrlen) {
140 memcpy(attrlist, cp, attrlen +1);
141 goto jattrok;
143 n_err(_("*attrlist* is not of the correct length, using builtin\n"));
146 if (ok_blook(bsdcompat) || ok_blook(bsdflags)) {
147 char const bsdattr[attrlen +1] = "NU *HMFAT+-$~";
148 memcpy(attrlist, bsdattr, sizeof bsdattr);
149 } else if (env_blook("SYSV3", FAL0)) {
150 char const bsdattr[attrlen +1] = "NU *HMFAT+-$~";
151 memcpy(attrlist, bsdattr, sizeof bsdattr);
152 OBSOLETE(_("*SYSV3*: please use *bsdcompat* or *bsdflags*, "
153 "or set *attrlist*"));
154 } else {
155 char const pattr[attrlen +1] = "NUROSPMFAT+-$~";
156 memcpy(attrlist, pattr, sizeof pattr);
159 jattrok:
160 if ((fmt = ok_vlook(headline)) == NULL) {
161 fmt = ((ok_blook(bsdcompat) || ok_blook(bsdheadline))
162 ? "%>%a%m %-20f %16d %3l/%-5o %i%-S"
163 : "%>%a%m %-18f %16d %4l/%-5o %i%-s");
166 __hprf(yetprinted, fmt, msgno, f, threaded, attrlist);
167 NYD_LEAVE;
170 static void
171 __hprf(size_t yetprinted, char const *fmt, size_t msgno, FILE *f,
172 bool_t threaded, char const *attrlist)
174 char buf[16], datebuf[FROM_DATEBUF], cbuf[8], *cp, *subjline;
175 char const *datefmt, *date, *name, *fp n_COLOUR( COMMA *colo_tag );
176 int i, n, s, wleft, subjlen;
177 struct message *mp;
178 time_t datet;
179 n_COLOUR( struct n_colour_pen *cpen_new COMMA *cpen_cur COMMA *cpen_bas; )
180 enum {
181 _NONE = 0,
182 _ISDOT = 1<<0,
183 _ISADDR = 1<<1,
184 _ISTO = 1<<2,
185 _IFMT = 1<<3,
186 _LOOP_MASK = (1<<4) - 1,
187 _SFMT = 1<<4
188 } flags = _NONE;
189 NYD_ENTER;
190 UNUSED(buf);
192 if ((mp = message + msgno - 1) == dot)
193 flags = _ISDOT;
194 datet = mp->m_time;
195 date = NULL;
196 n_COLOUR( colo_tag = NULL; )
198 datefmt = ok_vlook(datefield);
199 jredo:
200 if (datefmt != NULL) {
201 fp = hfield1("date", mp);/* TODO use m_date field! */
202 if (fp == NULL) {
203 datefmt = NULL;
204 goto jredo;
206 datet = rfctime(fp);
207 date = fakedate(datet);
208 fp = ok_vlook(datefield_markout_older);
209 i = (*datefmt != '\0');
210 if (fp != NULL)
211 i |= (*fp != '\0') ? 2 | 4 : 2; /* XXX no magics */
213 /* May we strftime(3)? */
214 if (i & (1 | 4))
215 memcpy(&time_current.tc_local, localtime(&datet),
216 sizeof time_current.tc_local);
218 if ((i & 2) && (datet > time_current.tc_time + DATE_SECSDAY ||
219 #define _6M ((DATE_DAYSYEAR / 2) * DATE_SECSDAY)
220 (datet + _6M < time_current.tc_time))) {
221 #undef _6M
222 if ((datefmt = (i & 4) ? fp : NULL) == NULL) {
223 memset(datebuf, ' ', FROM_DATEBUF); /* xxx ur */
224 memcpy(datebuf + 4, date + 4, 7);
225 datebuf[4 + 7] = ' ';
226 memcpy(datebuf + 4 + 7 + 1, date + 20, 4);
227 datebuf[4 + 7 + 1 + 4] = '\0';
228 date = datebuf;
230 n_COLOUR( colo_tag = n_COLOUR_TAG_SUM_OLDER; )
231 } else if ((i & 1) == 0)
232 datefmt = NULL;
233 } else if (datet == (time_t)0 && !(mp->m_flag & MNOFROM)) {
234 /* TODO eliminate this path, query the FROM_ date in setptr(),
235 * TODO all other codepaths do so by themselves ALREADY ?????
236 * TODO assert(mp->m_time != 0);, then
237 * TODO ALSO changes behaviour of datefield_markout_older */
238 _parse_from_(mp, datebuf);
239 date = datebuf;
240 } else
241 date = fakedate(datet);
243 flags |= _ISADDR;
244 name = name1(mp, 0);
245 if (name != NULL && ok_blook(showto) && is_myname(skin(name))) {
246 if ((cp = hfield1("to", mp)) != NULL) {
247 name = cp;
248 flags |= _ISTO;
251 if (name == NULL) {
252 name = "";
253 flags &= ~_ISADDR;
255 if (flags & _ISADDR)
256 name = ok_blook(showname) ? realname(name) : prstr(skin(name));
258 subjline = NULL;
260 /* Detect the width of the non-format characters in *headline*;
261 * like that we can simply use putc() in the next loop, since we have
262 * already calculated their column widths (TODO it's sick) */
263 wleft = subjlen = scrnwidth;
265 for (fp = fmt; *fp != '\0'; ++fp) {
266 if (*fp == '%') {
267 if (*++fp == '-')
268 ++fp;
269 else if (*fp == '+')
270 ++fp;
271 if (digitchar(*fp)) {
272 n = 0;
274 n = 10*n + *fp - '0';
275 while (++fp, digitchar(*fp));
276 subjlen -= n;
278 if (*fp == 'i')
279 flags |= _IFMT;
281 if (*fp == '\0')
282 break;
283 } else {
284 #ifdef HAVE_WCWIDTH
285 if (mb_cur_max > 1) {
286 wchar_t wc;
287 if ((s = mbtowc(&wc, fp, mb_cur_max)) == -1)
288 n = s = 1;
289 else if ((n = wcwidth(wc)) == -1)
290 n = 1;
291 } else
292 #endif
293 n = s = 1;
294 subjlen -= n;
295 wleft -= n;
296 while (--s > 0)
297 ++fp;
301 /* Walk *headline*, producing output TODO not (really) MB safe */
302 #ifdef HAVE_COLOUR
303 if (flags & _ISDOT)
304 colo_tag = n_COLOUR_TAG_SUM_DOT;
305 cpen_bas = n_colour_pen_create(n_COLOUR_ID_SUM_HEADER, colo_tag);
306 n_colour_pen_put(cpen_new = cpen_cur = cpen_bas, f);
307 #endif
309 for (fp = fmt; *fp != '\0'; ++fp) {
310 char c;
312 if ((c = *fp & 0xFF) != '%') {
313 #ifdef HAVE_COLOUR
314 if ((cpen_new = cpen_bas) != cpen_cur)
315 n_colour_pen_put(cpen_cur = cpen_new, f);
316 #endif
317 putc(c, f);
318 continue;
321 flags &= _LOOP_MASK;
322 n = 0;
323 s = 1;
324 if ((c = *++fp) == '-') {
325 s = -1;
326 ++fp;
327 } else if (c == '+')
328 ++fp;
329 if (digitchar(*fp)) {
331 n = 10*n + *fp - '0';
332 while (++fp, digitchar(*fp));
335 if ((c = *fp & 0xFF) == '\0')
336 break;
337 n *= s;
339 cbuf[1] = '\0';
340 switch (c) {
341 case '%':
342 goto jputcb;
343 case '>':
344 case '<':
345 if (flags & _ISDOT) {
346 n_COLOUR( cpen_new = n_colour_pen_create(n_COLOUR_ID_SUM_DOTMARK,
347 colo_tag); );
348 if (options & OPT_UNICODE) {
349 if (c == '>')
350 /* 25B8;BLACK RIGHT-POINTING SMALL TRIANGLE: â–¸ */
351 cbuf[1] = (char)0x96, cbuf[2] = (char)0xB8;
352 else
353 /* 25C2;BLACK LEFT-POINTING SMALL TRIANGLE: â—‚ */
354 cbuf[1] = (char)0x97, cbuf[2] = (char)0x82;
355 c = (char)0xE2;
356 cbuf[3] = '\0';
358 } else
359 c = ' ';
360 goto jputcb;
361 case '$':
362 #ifdef HAVE_SPAM
363 if (n == 0)
364 n = 5;
365 if (UICMP(32, ABS(n), >, wleft))
366 n = (n < 0) ? -wleft : wleft;
367 snprintf(buf, sizeof buf, "%u.%02u",
368 (mp->m_spamscore >> 8), (mp->m_spamscore & 0xFF));
369 n = fprintf(f, "%*s", n, buf);
370 wleft = (n >= 0) ? wleft - n : 0;
371 break;
372 #else
373 c = '?';
374 goto jputcb;
375 #endif
376 case 'a':
377 c = _dispc(mp, attrlist);
378 jputcb:
379 #ifdef HAVE_COLOUR
380 if (cpen_new == cpen_cur)
381 cpen_new = cpen_bas;
382 if (cpen_new != cpen_cur)
383 n_colour_pen_put(cpen_cur = cpen_new, f);
384 #endif
385 if (UICMP(32, ABS(n), >, wleft))
386 n = (n < 0) ? -wleft : wleft;
387 cbuf[0] = c;
388 n = fprintf(f, "%*s", n, cbuf);
389 wleft = (n >= 0) ? wleft - n : 0;
390 #ifdef HAVE_COLOUR
391 if ((cpen_new = cpen_bas) != cpen_cur)
392 n_colour_pen_put(cpen_cur = cpen_new, f);
393 #endif
394 break;
395 case 'd':
396 if (datefmt != NULL) {
397 i = strftime(datebuf, sizeof datebuf, datefmt,
398 &time_current.tc_local);
399 if (i != 0)
400 date = datebuf;
401 else
402 n_err(_("Ignored date format, it excesses the target "
403 "buffer (%lu bytes)\n"), (ul_i)sizeof(datebuf));
404 datefmt = NULL;
406 if (n == 0)
407 n = 16;
408 if (UICMP(32, ABS(n), >, wleft))
409 n = (n < 0) ? -wleft : wleft;
410 n = fprintf(f, "%*.*s", n, n, date);
411 wleft = (n >= 0) ? wleft - n : 0;
412 break;
413 case 'e':
414 if (n == 0)
415 n = 2;
416 if (UICMP(32, ABS(n), >, wleft))
417 n = (n < 0) ? -wleft : wleft;
418 n = fprintf(f, "%*u", n, (threaded == 1 ? mp->m_level : 0));
419 wleft = (n >= 0) ? wleft - n : 0;
420 break;
421 case 'f':
422 if (n == 0) {
423 n = 18;
424 if (s < 0)
425 n = -n;
427 i = ABS(n);
428 if (i > wleft) {
429 i = wleft;
430 n = (n < 0) ? -wleft : wleft;
432 if (flags & _ISTO) /* XXX tr()! */
433 i -= 3;
434 n = fprintf(f, "%s%s", ((flags & _ISTO) ? "To " : ""),
435 colalign(name, i, n, &wleft));
436 if (n < 0)
437 wleft = 0;
438 else if (flags & _ISTO)
439 wleft -= 3;
440 break;
441 case 'i':
442 if (threaded) {
443 #ifdef HAVE_COLOUR
444 cpen_new = n_colour_pen_create(n_COLOUR_ID_SUM_THREAD, colo_tag);
445 if (cpen_new != cpen_cur)
446 n_colour_pen_put(cpen_cur = cpen_new, f);
447 #endif
448 n = __putindent(f, mp, MIN(wleft, scrnwidth - 60));
449 wleft = (n >= 0) ? wleft - n : 0;
450 #ifdef HAVE_COLOUR
451 if ((cpen_new = cpen_bas) != cpen_cur)
452 n_colour_pen_put(cpen_cur = cpen_new, f);
453 #endif
455 break;
456 case 'l':
457 if (n == 0)
458 n = 4;
459 if (UICMP(32, ABS(n), >, wleft))
460 n = (n < 0) ? -wleft : wleft;
461 if (mp->m_xlines) {
462 n = fprintf(f, "%*ld", n, mp->m_xlines);
463 wleft = (n >= 0) ? wleft - n : 0;
464 } else {
465 n = ABS(n);
466 wleft -= n;
467 while (n-- != 0)
468 putc(' ', f);
470 break;
471 case 'm':
472 if (n == 0) {
473 n = 3;
474 if (threaded)
475 for (i = msgCount; i > 999; i /= 10)
476 ++n;
478 if (UICMP(32, ABS(n), >, wleft))
479 n = (n < 0) ? -wleft : wleft;
480 n = fprintf(f, "%*lu", n, (ul_i)msgno);
481 wleft = (n >= 0) ? wleft - n : 0;
482 break;
483 case 'o':
484 if (n == 0)
485 n = -5;
486 if (UICMP(32, ABS(n), >, wleft))
487 n = (n < 0) ? -wleft : wleft;
488 n = fprintf(f, "%*lu", n, (ul_i)mp->m_xsize);
489 wleft = (n >= 0) ? wleft - n : 0;
490 break;
491 case 'S':
492 flags |= _SFMT;
493 /*FALLTHRU*/
494 case 's':
495 if (n == 0)
496 n = subjlen - 2;
497 if (n > 0 && s < 0)
498 n = -n;
499 if (subjlen > wleft)
500 subjlen = wleft;
501 if (UICMP(32, ABS(n), >, subjlen))
502 n = (n < 0) ? -subjlen : subjlen;
503 if (flags & _SFMT)
504 n -= (n < 0) ? -2 : 2;
505 if (n == 0)
506 break;
507 if (subjline == NULL)
508 subjline = __subject(mp, (threaded && (flags & _IFMT)), yetprinted);
509 if (subjline == (char*)-1) {
510 n = fprintf(f, "%*s", n, "");
511 wleft = (n >= 0) ? wleft - n : 0;
512 } else {
513 n = fprintf(f, ((flags & _SFMT) ? "\"%s\"" : "%s"),
514 colalign(subjline, ABS(n), n, &wleft));
515 if (n < 0)
516 wleft = 0;
518 break;
519 case 'T': { /* Message recipient flags */
520 /* We never can reuse "name" since it's the full name */
521 struct name const *np = lextract(hfield1("to", mp), GTO | GSKIN);
522 c = ' ';
523 i = 0;
524 j_A_redo:
525 for (; np != NULL; np = np->n_flink) {
526 switch (is_mlist(np->n_name, FAL0)) {
527 case MLIST_SUBSCRIBED: c = 'S'; goto jputcb;
528 case MLIST_KNOWN: c = 'L'; goto jputcb;
529 case MLIST_OTHER:
530 default: break;
533 if (i != 0)
534 goto jputcb;
535 ++i;
536 np = lextract(hfield1("cc", mp), GCC | GSKIN);
537 goto j_A_redo;
539 case 't':
540 if (n == 0) {
541 n = 3;
542 if (threaded)
543 for (i = msgCount; i > 999; i /= 10)
544 ++n;
546 if (UICMP(32, ABS(n), >, wleft))
547 n = (n < 0) ? -wleft : wleft;
548 n = fprintf(f, "%*lu",
549 n, (threaded ? (ul_i)mp->m_threadpos : (ul_i)msgno));
550 wleft = (n >= 0) ? wleft - n : 0;
551 break;
552 default:
553 if (options & OPT_D_V)
554 n_err(_("Unkown *headline* format: \"%%%c\"\n"), c);
555 c = '?';
556 goto jputcb;
559 if (wleft <= 0)
560 break;
563 #ifdef HAVE_COLOUR
564 n_colour_reset(f);
565 #endif
566 putc('\n', f);
568 if (subjline != NULL && subjline != (char*)-1)
569 free(subjline);
570 NYD_LEAVE;
573 static char *
574 __subject(struct message *mp, bool_t threaded, size_t yetprinted)
576 struct str in, out;
577 char *rv = (char*)-1, *ms;
578 NYD_ENTER;
580 if ((ms = hfield1("subject", mp)) == NULL)
581 goto jleave;
583 in.l = strlen(in.s = ms);
584 mime_fromhdr(&in, &out, TD_ICONV | TD_ISPR);
585 rv = ms = out.s;
587 if (!threaded || mp->m_level == 0)
588 goto jleave;
590 /* In a display thread - check wether this message uses the same
591 * Subject: as it's parent or elder neighbour, suppress printing it if
592 * this is the case. To extend this a bit, ignore any leading Re: or
593 * Fwd: plus follow-up WS. Ignore invisible messages along the way */
594 ms = subject_re_trim(ms);
596 for (; (mp = prev_in_thread(mp)) != NULL && yetprinted-- > 0;) {
597 char *os;
599 if (visible(mp) && (os = hfield1("subject", mp)) != NULL) {
600 struct str oout;
601 int x;
603 in.l = strlen(in.s = os);
604 mime_fromhdr(&in, &oout, TD_ICONV | TD_ISPR);
605 x = asccasecmp(ms, subject_re_trim(oout.s));
606 free(oout.s);
608 if (!x) {
609 free(out.s);
610 rv = (char*)-1;
612 break;
615 jleave:
616 NYD_LEAVE;
617 return rv;
620 static int
621 __putindent(FILE *fp, struct message *mp, int maxwidth)/* XXX no magic consts */
623 struct message *mq;
624 int *us, indlvl, indw, i, important = MNEW | MFLAGGED;
625 char *cs;
626 NYD_ENTER;
628 if (mp->m_level == 0 || maxwidth == 0) {
629 indw = 0;
630 goto jleave;
633 cs = ac_alloc(mp->m_level);
634 us = ac_alloc(mp->m_level * sizeof *us);
636 i = mp->m_level - 1;
637 if (mp->m_younger && UICMP(32, i + 1, ==, mp->m_younger->m_level)) {
638 if (mp->m_parent && mp->m_parent->m_flag & important)
639 us[i] = mp->m_flag & important ? 0x2523 : 0x2520;
640 else
641 us[i] = mp->m_flag & important ? 0x251D : 0x251C;
642 cs[i] = '+';
643 } else {
644 if (mp->m_parent && mp->m_parent->m_flag & important)
645 us[i] = mp->m_flag & important ? 0x2517 : 0x2516;
646 else
647 us[i] = mp->m_flag & important ? 0x2515 : 0x2514;
648 cs[i] = '\\';
651 mq = mp->m_parent;
652 for (i = mp->m_level - 2; i >= 0; --i) {
653 if (mq) {
654 if (UICMP(32, i, >, mq->m_level - 1)) {
655 us[i] = cs[i] = ' ';
656 continue;
658 if (mq->m_younger) {
659 if (mq->m_parent && (mq->m_parent->m_flag & important))
660 us[i] = 0x2503;
661 else
662 us[i] = 0x2502;
663 cs[i] = '|';
664 } else
665 us[i] = cs[i] = ' ';
666 mq = mq->m_parent;
667 } else
668 us[i] = cs[i] = ' ';
671 --maxwidth;
672 for (indlvl = indw = 0; (ui8_t)indlvl < mp->m_level && indw < maxwidth;
673 ++indlvl) {
674 if (indw < maxwidth - 1)
675 indw += (int)putuc(us[indlvl], cs[indlvl] & 0xFF, fp);
676 else
677 indw += (int)putuc(0x21B8, '^', fp);
679 indw += putuc(0x25B8, '>', fp);
681 ac_free(us);
682 ac_free(cs);
683 jleave:
684 NYD_LEAVE;
685 return indw;
688 static int
689 _dispc(struct message *mp, char const *a)
691 int i = ' ';
692 NYD_ENTER;
694 if ((mp->m_flag & (MREAD | MNEW)) == MREAD)
695 i = a[3];
696 if ((mp->m_flag & (MREAD | MNEW)) == (MREAD | MNEW))
697 i = a[2];
698 if (mp->m_flag & MANSWERED)
699 i = a[8];
700 if (mp->m_flag & MDRAFTED)
701 i = a[9];
702 if ((mp->m_flag & (MREAD | MNEW)) == MNEW)
703 i = a[0];
704 if (!(mp->m_flag & (MREAD | MNEW)))
705 i = a[1];
706 if (mp->m_flag & MSPAM)
707 i = a[12];
708 if (mp->m_flag & MSPAMUNSURE)
709 i = a[13];
710 if (mp->m_flag & MSAVED)
711 i = a[4];
712 if (mp->m_flag & MPRESERVE)
713 i = a[5];
714 if (mp->m_flag & (MBOX | MBOXED))
715 i = a[6];
716 if (mp->m_flag & MFLAGGED)
717 i = a[7];
718 if (mb.mb_threaded == 1 && mp->m_collapsed > 0)
719 i = a[11];
720 if (mb.mb_threaded == 1 && mp->m_collapsed < 0)
721 i = a[10];
722 NYD_LEAVE;
723 return i;
726 static int
727 a_cmd_scroll(char const *arg, bool_t onlynew){
728 long l;
729 char *eptr;
730 bool_t isabs;
731 int msgspec, size, maxs;
732 NYD2_ENTER;
734 msgspec = onlynew ? -1 : 0;
735 size = screensize();
736 maxs = msgCount / size;
738 switch(*arg){
739 case '\0':
740 ++_screen;
741 goto jfwd;
742 case '$':
743 if(arg[1] != '\0')
744 goto jerr;
745 if(_screen == maxs)
746 goto jerrfwd;
747 _screen = maxs;
748 break;
749 case '+':
750 if(arg[1] == '\0')
751 ++_screen;
752 else{
753 isabs = FAL0;
755 ++arg;
756 if(0){
757 case '1': case '2': case '3': case '4': case '5':
758 case '6': case '7': case '8': case '9': case '0':
759 isabs = TRU1;
761 l = strtol(arg, &eptr, 10);
762 if(*eptr != '\0')
763 goto jerr;
764 if(l > maxs - (isabs ? 0 : _screen))
765 goto jerrfwd;
766 _screen = isabs ? (int)l : _screen + l;
768 jfwd:
769 if(_screen > maxs){
770 jerrfwd:
771 _screen = maxs;
772 printf(_("On last screenful of messages\n"));
774 break;
776 case '-':
777 if(arg[1] == '\0')
778 --_screen;
779 else{
780 ++arg;
781 l = strtol(arg, &eptr, 10);
782 if(*eptr != '\0')
783 goto jerr;
784 if(l > _screen)
785 goto jerrbwd;
786 _screen -= l;
788 if(_screen < 0){
789 jerrbwd:
790 _screen = 0;
791 printf(_("On first screenful of messages\n"));
793 if(msgspec == -1)
794 msgspec = -2;
795 break;
796 default:
797 jerr:
798 n_err(_("Unrecognized scrolling command \"%s\"\n"), arg);
799 size = 1;
800 goto jleave;
803 size = _headers(msgspec);
804 jleave:
805 NYD2_LEAVE;
806 return size;
809 static int
810 _headers(int msgspec) /* TODO rework v15 */
812 bool_t volatile isrelax;
813 sighandler_type volatile opipe;
814 ui32_t volatile flag;
815 int g, k, mesg, size, lastg = 1;
816 struct message *mp, *mq, *lastmq = NULL;
817 enum mflag fl = MNEW | MFLAGGED;
818 NYD_ENTER;
820 time_current_update(&time_current, FAL0);
822 isrelax = FAL0;
823 opipe = NULL;
824 flag = 0;
825 if (sigsetjmp(_cmd1_pipejmp, 1))
826 goto jleave;
827 opipe = safe_signal(SIGPIPE, &_cmd1_onpipe);
829 #ifdef HAVE_COLOUR
830 if (options & OPT_INTERACTIVE)
831 n_colour_env_create(n_COLOUR_GROUP_SUM, FAL0);
832 #endif
834 size = screensize();
835 if (_screen < 0)
836 _screen = 0;
837 #if 0 /* FIXME original code path */
838 k = _screen * size;
839 #else
840 if (msgspec <= 0)
841 k = _screen * size;
842 else
843 k = msgspec;
844 #endif
845 if (k >= msgCount)
846 k = msgCount - size;
847 if (k < 0)
848 k = 0;
850 if (mb.mb_threaded == 0) {
851 g = 0;
852 mq = message;
853 for (mp = message; PTRCMP(mp, <, message + msgCount); ++mp)
854 if (visible(mp)) {
855 if (g % size == 0)
856 mq = mp;
857 if (mp->m_flag & fl) {
858 lastg = g;
859 lastmq = mq;
861 if ((msgspec > 0 && PTRCMP(mp, ==, message + msgspec - 1)) ||
862 (msgspec == 0 && g == k) ||
863 (msgspec == -2 && g == k + size && lastmq) ||
864 (msgspec < 0 && g >= k && (mp->m_flag & fl) != 0))
865 break;
866 g++;
868 if (lastmq && (msgspec == -2 ||
869 (msgspec == -1 && PTRCMP(mp, ==, message + msgCount)))) {
870 g = lastg;
871 mq = lastmq;
873 _screen = g / size;
875 mp = mq;
876 mesg = (int)PTR2SIZE(mp - message);
877 if (PTRCMP(dot, !=, message + msgspec - 1)) { /* TODO really?? */
878 for (mq = mp; PTRCMP(mq, <, message + msgCount); ++mq)
879 if (visible(mq)) {
880 setdot(mq);
881 break;
885 srelax_hold();
886 isrelax = TRU1;
887 for (; PTRCMP(mp, <, message + msgCount); ++mp) {
888 ++mesg;
889 if (!visible(mp))
890 continue;
891 if (UICMP(32, flag++, >=, size))
892 break;
893 _print_head(0, mesg, stdout, 0);
894 srelax();
896 srelax_rele();
897 isrelax = FAL0;
898 } else { /* threaded */
899 g = 0;
900 mq = threadroot;
901 for (mp = threadroot; mp; mp = next_in_thread(mp))
902 if (visible(mp) &&
903 (mp->m_collapsed <= 0 ||
904 PTRCMP(mp, ==, message + msgspec - 1))) {
905 if (g % size == 0)
906 mq = mp;
907 if (mp->m_flag & fl) {
908 lastg = g;
909 lastmq = mq;
911 if ((msgspec > 0 && PTRCMP(mp, ==, message + msgspec - 1)) ||
912 (msgspec == 0 && g == k) ||
913 (msgspec == -2 && g == k + size && lastmq) ||
914 (msgspec < 0 && g >= k && (mp->m_flag & fl) != 0))
915 break;
916 g++;
918 if (lastmq && (msgspec == -2 ||
919 (msgspec == -1 && PTRCMP(mp, ==, message + msgCount)))) {
920 g = lastg;
921 mq = lastmq;
923 _screen = g / size;
924 mp = mq;
925 if (PTRCMP(dot, !=, message + msgspec - 1)) { /* TODO really?? */
926 for (mq = mp; mq; mq = next_in_thread(mq))
927 if (visible(mq) && mq->m_collapsed <= 0) {
928 setdot(mq);
929 break;
933 srelax_hold();
934 isrelax = TRU1;
935 while (mp) {
936 if (visible(mp) &&
937 (mp->m_collapsed <= 0 ||
938 PTRCMP(mp, ==, message + msgspec - 1))) {
939 if (UICMP(32, flag++, >=, size))
940 break;
941 _print_head(flag - 1, PTR2SIZE(mp - message + 1), stdout,
942 mb.mb_threaded);
943 srelax();
945 mp = next_in_thread(mp);
947 srelax_rele();
948 isrelax = FAL0;
951 if (!flag)
952 printf(_("No more mail.\n"));
953 jleave:
954 if (isrelax)
955 srelax_rele();
956 n_COLOUR( n_colour_env_gut(stdout); )
957 if (opipe != NULL)
958 safe_signal(SIGPIPE, opipe);
959 NYD_LEAVE;
960 return !flag;
963 static int
964 _type1(int *msgvec, bool_t doign, bool_t dopage, bool_t dopipe,
965 bool_t dodecode, char *cmd, ui64_t *tstats)
967 ui64_t mstats[1];
968 int rv = 1, *ip;
969 struct message *mp;
970 char const *cp;
971 FILE * volatile obuf;
972 bool_t volatile isrelax = FAL0;
973 sighandler_type opipe = NULL;
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 if (sigsetjmp(_cmd1_pipejmp, 1))
984 goto jleave;
985 opipe = safe_signal(SIGPIPE, &_cmd1_onpipe);
987 if (dopipe) {
988 if ((cp = ok_vlook(SHELL)) == NULL)
989 cp = XSHELL;
990 if ((obuf = Popen(cmd, "w", cp, NULL, 1)) == NULL) {
991 n_perr(cmd, 0);
992 obuf = stdout;
994 } else if ((options & OPT_TTYOUT) && (dopage ||
995 ((options & OPT_INTERACTIVE) && (cp = ok_vlook(crt)) != NULL))) {
996 size_t nlines = 0;
998 if (!dopage) {
999 for (ip = msgvec; *ip && PTRCMP(ip - msgvec, <, msgCount); ++ip) {
1000 mp = message + *ip - 1;
1001 if (!(mp->m_have & HAVE_BODY))
1002 if (get_body(mp) != OKAY)
1003 goto jleave;
1004 nlines += mp->m_lines + 1; /* Message info XXX and PARTS... */
1008 /* >= not <: we return to the prompt */
1009 if (dopage || UICMP(z, nlines, >=,
1010 (*cp != '\0' ? atoi(cp) : realscreenheight))) {
1011 char const *env_add[2], *pager = get_pager(env_add + 0);
1012 env_add[1] = NULL;
1013 obuf = Popen(pager, "w", NULL, env_add, 1);
1014 if (obuf == NULL) {
1015 n_perr(pager, 0);
1016 obuf = stdout;
1019 #ifdef HAVE_COLOUR
1020 if ((options & OPT_INTERACTIVE) &&
1021 (action == SEND_TODISP || action == SEND_TODISP_ALL ||
1022 action == SEND_SHOW))
1023 n_colour_env_create(n_COLOUR_GROUP_VIEW, obuf != stdout);
1024 #endif
1026 #ifdef HAVE_COLOUR
1027 else if ((options & OPT_INTERACTIVE) &&
1028 (action == SEND_TODISP || action == SEND_TODISP_ALL))
1029 n_colour_env_create(n_COLOUR_GROUP_VIEW, FAL0);
1030 #endif
1032 /*TODO unless we have our signal manager special care must be taken */
1033 srelax_hold();
1034 isrelax = TRU1;
1035 for (ip = msgvec; *ip && PTRCMP(ip - msgvec, <, msgCount); ++ip) {
1036 mp = message + *ip - 1;
1037 touch(mp);
1038 setdot(mp);
1039 uncollapse1(mp, 1);
1040 if (!dopipe && ip != msgvec)
1041 fprintf(obuf, "\n");
1042 if (action != SEND_MBOX)
1043 _show_msg_overview(obuf, mp, *ip);
1044 sendmp(mp, obuf, (doign ? ignore : NULL), NULL, action, mstats);
1045 srelax();
1046 if (formfeed) /* TODO a nicer way to separate piped messages! */
1047 putc('\f', obuf);
1048 if (tstats != NULL)
1049 tstats[0] += mstats[0];
1051 srelax_rele();
1052 isrelax = FAL0;
1054 rv = 0;
1055 jleave:
1056 if (obuf != stdout)
1057 /* Ignore SIGPIPE so it can't cause a duplicate close */
1058 safe_signal(SIGPIPE, SIG_IGN);
1059 if (isrelax)
1060 srelax_rele();
1061 n_COLOUR( n_colour_env_gut(obuf); )
1062 if (obuf != stdout)
1063 Pclose(obuf, TRU1);
1064 if (opipe != NULL)
1065 safe_signal(SIGPIPE, dflpipe);
1067 NYD_LEAVE;
1068 return rv;
1071 static int
1072 _pipe1(char *str, int doign)
1074 ui64_t stats[1];
1075 char *cmd;
1076 int *msgvec, rv = 1;
1077 bool_t needs_list;
1078 NYD_ENTER;
1080 if ((cmd = laststring(str, &needs_list, TRU1)) == NULL) {
1081 cmd = ok_vlook(cmd);
1082 if (cmd == NULL || *cmd == '\0') {
1083 n_err(_("Variable *cmd* not set\n"));
1084 goto jleave;
1088 msgvec = salloc((msgCount + 2) * sizeof *msgvec);
1090 if (!needs_list) {
1091 *msgvec = first(0, MMNORM);
1092 if (*msgvec == 0) {
1093 if (pstate & PS_HOOK_MASK) {
1094 rv = 0;
1095 goto jleave;
1097 puts(_("No messages to pipe."));
1098 goto jleave;
1100 msgvec[1] = 0;
1101 } else if (getmsglist(str, msgvec, 0) < 0)
1102 goto jleave;
1103 if (*msgvec == 0) {
1104 if (pstate & PS_HOOK_MASK) {
1105 rv = 0;
1106 goto jleave;
1108 printf("No applicable messages.\n");
1109 goto jleave;
1112 printf(_("Pipe to: \"%s\"\n"), cmd);
1113 stats[0] = 0;
1114 if ((rv = _type1(msgvec, doign, FAL0, TRU1, FAL0, cmd, stats)) == 0)
1115 printf("\"%s\" %" PRIu64 " bytes\n", cmd, stats[0]);
1116 jleave:
1117 NYD_LEAVE;
1118 return rv;
1121 FL int
1122 c_cmdnotsupp(void *v) /* TODO -> lex.c */
1124 NYD_ENTER;
1125 UNUSED(v);
1126 n_err(_("The requested feature is not compiled in\n"));
1127 NYD_LEAVE;
1128 return 1;
1131 FL int
1132 c_headers(void *v)
1134 int rv;
1135 NYD_ENTER;
1137 rv = print_header_group((int*)v);
1138 NYD_LEAVE;
1139 return rv;
1142 FL int
1143 print_header_group(int *vector)
1145 int rv;
1146 NYD_ENTER;
1148 assert(vector != NULL && vector != (void*)-1);
1149 rv = _headers(vector[0]);
1150 NYD_LEAVE;
1151 return rv;
1154 FL int
1155 c_scroll(void *v)
1157 int rv;
1158 NYD_ENTER;
1160 rv = a_cmd_scroll(v, FAL0);
1161 NYD_LEAVE;
1162 return rv;
1165 FL int
1166 c_Scroll(void *v)
1168 int rv;
1169 NYD_ENTER;
1171 rv = a_cmd_scroll(v, TRU1);
1172 NYD_LEAVE;
1173 return rv;
1176 FL int
1177 c_from(void *v)
1179 int *msgvec = v, *ip, n;
1180 char *cp;
1181 FILE * volatile obuf;
1182 bool_t volatile isrelax;
1183 sighandler_type volatile opipe;
1184 NYD_ENTER;
1186 time_current_update(&time_current, FAL0);
1188 obuf = stdout;
1189 isrelax = FAL0;
1190 opipe = NULL;
1191 if (sigsetjmp(_cmd1_pipejmp, 1))
1192 goto jleave;
1193 opipe = safe_signal(SIGPIPE, &_cmd1_onpipe);
1195 if (options & OPT_INTERACTIVE) {
1196 if ((cp = ok_vlook(crt)) != NULL) {
1197 for (n = 0, ip = msgvec; *ip != 0; ++ip)
1198 ++n;
1199 if (n > (*cp == '\0' ? screensize() : atoi(cp)) + 3) {
1200 char const *p = get_pager(NULL);
1201 if ((obuf = Popen(p, "w", NULL, NULL, 1)) == NULL) {
1202 n_perr(p, 0);
1203 obuf = stdout;
1207 n_COLOUR( n_colour_env_create(n_COLOUR_GROUP_SUM, obuf != stdout); )
1210 /* Update dot before display so that the dotmark etc. are correct */
1211 for (ip = msgvec; *ip != 0; ++ip)
1213 if (--ip >= msgvec)
1214 setdot(message + *ip - 1);
1216 srelax_hold();
1217 isrelax = TRU1;
1218 for (n = 0, ip = msgvec; *ip != 0; ++ip) { /* TODO join into _print_head() */
1219 _print_head((size_t)n++, (size_t)*ip, obuf, mb.mb_threaded);
1220 srelax();
1222 srelax_rele();
1223 isrelax = FAL0;
1225 jleave:
1226 if (obuf != stdout)
1227 /* Ignore SIGPIPE so it can't cause a duplicate close */
1228 safe_signal(SIGPIPE, SIG_IGN);
1229 if (isrelax)
1230 srelax_rele();
1231 n_COLOUR( n_colour_env_gut(obuf); )
1232 if (obuf != stdout)
1233 Pclose(obuf, TRU1);
1234 if (opipe != NULL)
1235 safe_signal(SIGPIPE, opipe);
1236 NYD_LEAVE;
1237 return 0;
1240 FL void
1241 print_headers(size_t bottom, size_t topx, bool_t only_marked)
1243 bool_t volatile isrelax;
1244 sighandler_type volatile opipe;
1245 size_t printed;
1246 NYD_ENTER;
1248 time_current_update(&time_current, FAL0);
1250 isrelax = FAL0;
1251 opipe = NULL;
1252 if (sigsetjmp(_cmd1_pipejmp, 1))
1253 goto jleave;
1254 opipe = safe_signal(SIGPIPE, &_cmd1_onpipe);
1256 #ifdef HAVE_COLOUR
1257 if (options & OPT_INTERACTIVE)
1258 n_colour_env_create(n_COLOUR_GROUP_SUM, FAL0);
1259 #endif
1261 srelax_hold();
1262 isrelax = TRU1;
1263 for (printed = 0; bottom <= topx; ++bottom) {
1264 struct message *mp = message + bottom - 1;
1265 if (only_marked) {
1266 if (!(mp->m_flag & MMARK))
1267 continue;
1268 } else if (!visible(mp))
1269 continue;
1270 _print_head(printed++, bottom, stdout, FAL0);
1271 srelax();
1273 srelax_rele();
1274 isrelax = FAL0;
1276 jleave:
1277 if (isrelax)
1278 srelax_rele();
1279 n_COLOUR( n_colour_env_gut(stdout); )
1280 if (opipe != NULL)
1281 safe_signal(SIGPIPE, opipe);
1282 NYD_LEAVE;
1285 FL int
1286 c_pdot(void *v)
1288 NYD_ENTER;
1289 UNUSED(v);
1290 printf("%d\n", (int)PTR2SIZE(dot - message + 1));
1291 NYD_LEAVE;
1292 return 0;
1295 FL int
1296 c_more(void *v)
1298 int *msgvec = v, rv;
1299 NYD_ENTER;
1301 rv = _type1(msgvec, TRU1, TRU1, FAL0, FAL0, NULL, NULL);
1302 NYD_LEAVE;
1303 return rv;
1306 FL int
1307 c_More(void *v)
1309 int *msgvec = v, rv;
1310 NYD_ENTER;
1312 rv = _type1(msgvec, FAL0, TRU1, FAL0, FAL0, NULL, NULL);
1313 NYD_LEAVE;
1314 return rv;
1317 FL int
1318 c_type(void *v)
1320 int *msgvec = v, rv;
1321 NYD_ENTER;
1323 rv = _type1(msgvec, TRU1, FAL0, FAL0, FAL0, NULL, NULL);
1324 NYD_LEAVE;
1325 return rv;
1328 FL int
1329 c_Type(void *v)
1331 int *msgvec = v, rv;
1332 NYD_ENTER;
1334 rv = _type1(msgvec, FAL0, FAL0, FAL0, FAL0, NULL, NULL);
1335 NYD_LEAVE;
1336 return rv;
1339 FL int
1340 c_show(void *v)
1342 int *msgvec = v, rv;
1343 NYD_ENTER;
1345 rv = _type1(msgvec, FAL0, FAL0, FAL0, TRU1, NULL, NULL);
1346 NYD_LEAVE;
1347 return rv;
1350 FL int
1351 c_pipe(void *v)
1353 char *str = v;
1354 int rv;
1355 NYD_ENTER;
1357 rv = _pipe1(str, 1);
1358 NYD_LEAVE;
1359 return rv;
1362 FL int
1363 c_Pipe(void *v)
1365 char *str = v;
1366 int rv;
1367 NYD_ENTER;
1369 rv = _pipe1(str, 0);
1370 NYD_LEAVE;
1371 return rv;
1374 FL int
1375 c_top(void *v)
1377 int *msgvec = v, *ip, c, topl, lines, empty_last;
1378 struct message *mp;
1379 char *cp, *linebuf = NULL;
1380 size_t linesize = 0;
1381 FILE *ibuf;
1382 NYD_ENTER;
1384 topl = 5;
1385 cp = ok_vlook(toplines);
1386 if (cp != NULL) {
1387 topl = atoi(cp);
1388 if (topl < 0 || topl > 10000)
1389 topl = 5;
1392 /* XXX Colours of `top' only for message and part info lines */
1393 #ifdef HAVE_COLOUR
1394 if (options & OPT_INTERACTIVE)
1395 n_colour_env_create(n_COLOUR_GROUP_VIEW, FAL0);
1396 #endif
1397 empty_last = 1;
1398 for (ip = msgvec; *ip != 0 && UICMP(z, PTR2SIZE(ip - msgvec), <, msgCount);
1399 ++ip) {
1400 mp = message + *ip - 1;
1401 touch(mp);
1402 setdot(mp);
1403 pstate |= PS_DID_PRINT_DOT;
1404 if (!empty_last)
1405 printf("\n");
1406 _show_msg_overview(stdout, mp, *ip);
1407 if (mp->m_flag & MNOFROM)
1408 /* XXX c_top(): coloured output? */
1409 printf("From %s %s\n", fakefrom(mp), fakedate(mp->m_time));
1410 if ((ibuf = setinput(&mb, mp, NEED_BODY)) == NULL) { /* XXX use TOP */
1411 v = NULL;
1412 break;
1414 c = mp->m_lines;
1415 for (lines = 0; lines < c && UICMP(32, lines, <=, topl); ++lines) {
1416 if (readline_restart(ibuf, &linebuf, &linesize, 0) < 0)
1417 break;
1418 puts(linebuf);
1420 for (cp = linebuf; *cp != '\0' && blankchar(*cp); ++cp)
1422 empty_last = (*cp == '\0');
1426 n_COLOUR( n_colour_env_gut(stdout); )
1427 if (linebuf != NULL)
1428 free(linebuf);
1429 NYD_LEAVE;
1430 return (v != NULL);
1433 FL int
1434 c_stouch(void *v)
1436 int *msgvec = v, *ip;
1437 NYD_ENTER;
1439 for (ip = msgvec; *ip != 0; ++ip) {
1440 setdot(message + *ip - 1);
1441 dot->m_flag |= MTOUCH;
1442 dot->m_flag &= ~MPRESERVE;
1443 pstate |= PS_DID_PRINT_DOT;
1445 NYD_LEAVE;
1446 return 0;
1449 FL int
1450 c_mboxit(void *v)
1452 int *msgvec = v, *ip;
1453 NYD_ENTER;
1455 if (pstate & PS_EDIT) {
1456 n_err(_("`mbox' can only be used in a system mailbox\n")); /* TODO */
1457 goto jleave;
1460 for (ip = msgvec; *ip != 0; ++ip) {
1461 setdot(message + *ip - 1);
1462 dot->m_flag |= MTOUCH | MBOX;
1463 dot->m_flag &= ~MPRESERVE;
1464 pstate |= PS_DID_PRINT_DOT;
1466 jleave:
1467 NYD_LEAVE;
1468 return 0;
1471 FL int
1472 c_folders(void *v)
1474 char dirname[PATH_MAX], *name, **argv = v;
1475 char const *cmd;
1476 int rv = 1;
1477 NYD_ENTER;
1479 if (*argv) {
1480 name = expand(*argv);
1481 if (name == NULL)
1482 goto jleave;
1483 } else if (!getfold(dirname, sizeof dirname)) {
1484 n_err(_("No value set for \"folder\"\n"));
1485 goto jleave;
1486 } else
1487 name = dirname;
1489 if ((cmd = ok_vlook(LISTER)) == NULL)
1490 cmd = XLISTER;
1491 run_command(cmd, 0, COMMAND_FD_PASS, COMMAND_FD_PASS, name, NULL, NULL,
1492 NULL);
1493 jleave:
1494 NYD_LEAVE;
1495 return rv;
1498 /* s-it-mode */