4921854610200f384f90c36160f926fa816aa637
[mmh] / sbr / fmt_scan.c
1
2 /*
3  * fmt_scan.c -- format string interpretation
4  *
5  * $Id$
6  *
7  * This code is Copyright (c) 2002, by the authors of nmh.  See the
8  * COPYRIGHT file in the root directory of the nmh distribution for
9  * complete copyright information.
10  */
11
12 #include <h/mh.h>
13 #include <h/addrsbr.h>
14 #include <h/fmt_scan.h>
15 #include <h/tws.h>
16 #include <h/fmt_compile.h>
17
18 #ifdef TIME_WITH_SYS_TIME
19 # include <sys/time.h>
20 # include <time.h>
21 #else
22 # ifdef TM_IN_SYS_TIME
23 #  include <sys/time.h>
24 # else
25 #  include <time.h>
26 # endif
27 #endif
28
29 #define NFMTS MAXARGS
30
31 extern char *formataddr ();     /* hook for custom address formatting */
32
33 #ifdef LBL
34 struct msgs *fmt_current_folder; /* current folder (set by main program) */
35 #endif
36
37 extern int fmt_norm;            /* defined in sbr/fmt_def.c = AD_NAME */
38 struct mailname fmt_mnull;
39
40 /*
41  * static prototypes
42  */
43 static int match (char *, char *);
44 static char *get_x400_friendly (char *, char *, int);
45 static int get_x400_comp (char *, char *, char *, int);
46
47
48 /*
49  * test if string "sub" appears anywhere in
50  * string "str" (case insensitive).
51  */
52
53 static int
54 match (char *str, char *sub)
55 {
56     int c1, c2;
57     char *s1, *s2;
58
59 #ifdef LOCALE
60     while ((c1 = *sub)) {
61         c1 = (isalpha(c1) && isupper(c1)) ? tolower(c1) : c1;
62         while ((c2 = *str++) && c1 != ((isalpha(c2) && isupper(c2)) ? tolower(c2) : c2))
63             ;
64         if (! c2)
65             return 0;
66         s1 = sub + 1; s2 = str;
67         while ((c1 = *s1++) && ((isalpha(c1) && isupper(c1)) ? tolower(c1) : c1) == ((isalpha(c2 =*s2++) && isupper(c2)) ? tolower(c2) : c2))
68             ;
69         if (! c1)
70             return 1;
71     }
72 #else
73     while ((c1 = *sub)) {
74         while ((c2 = *str++) && (c1 | 040) != (c2 | 040))
75             ;
76         if (! c2)
77             return 0;
78         s1 = sub + 1; s2 = str;
79         while ((c1 = *s1++) && (c1 | 040) == (*s2++ | 040))
80             ;
81         if (! c1)
82             return 1;
83     }
84 #endif
85     return 1;
86 }
87
88 /*
89  * macros to format data
90  */
91 #define PUTDF(cp, num, wid, fill)\
92         if (cp + wid < ep) {\
93             if ((i = (num)) < 0)\
94                 i = -(num);\
95             if ((c = (wid)) < 0)\
96                 c = -c;\
97             sp = cp + c;\
98             do {\
99                 *--sp = (i % 10) + '0';\
100                 i /= 10;\
101             } while (i > 0 && sp > cp);\
102             if (i > 0)\
103                 *sp = '?';\
104             else if ((num) < 0 && sp > cp)\
105                 *--sp = '-';\
106             while (sp > cp)\
107                 *--sp = fill;\
108             cp += c;\
109             }
110
111 char * PUTSF(char *cp, char *str, unsigned int wid, char fill) {
112
113     unsigned int i, j;
114     unsigned int char_len;
115     unsigned int term_len = 0;
116     wchar_t wide_char;
117
118     for (i = 0 ; i < wid && i < strlen(str) && term_len < wid; ) {
119         char_len = mblen(str + i, strlen(str + i));
120         if (char_len <= 0) {
121             continue;
122         }
123         mbtowc(&wide_char, str + i, strlen(str + i));
124         term_len += wcwidth(wide_char);
125
126         for (j = 0 ; j < char_len ; j++) {
127             *(cp + i) = *(str + i);
128             i++;
129         }
130     }
131
132     if (term_len < wid) {
133         for (j = term_len ; j <= wid ; j++) {
134             *(cp + i++) = fill;
135         }
136     }
137
138     return cp + i;
139 }
140
141 #define PUTS(cp, str) {\
142                 if ((sp = (str))) {\
143                     while ((c = (unsigned char) *sp) && (iscntrl(c) || isspace(c)))\
144                         sp++;\
145                     while((c = (unsigned char) *sp++) && cp < ep)\
146                         if (!iscntrl(c) && !isspace(c)) \
147                             *cp++ = c;\
148                         else {\
149                             while ((c = (unsigned char) *sp) && (iscntrl(c) || isspace(c)))\
150                                 sp++;\
151                             *cp++ = ' ';\
152                         }\
153                 }\
154         }
155
156 static char *lmonth[] = { "January",  "February","March",   "April",
157                           "May",      "June",    "July",    "August",
158                           "September","October", "November","December" };
159
160 static char *
161 get_x400_friendly (char *mbox, char *buffer, int buffer_len)
162 {
163     char given[BUFSIZ], surname[BUFSIZ];
164
165     if (mbox == NULL)
166         return NULL;
167     if (*mbox == '"')
168         mbox++;
169     if (*mbox != '/')
170         return NULL;
171
172     if (get_x400_comp (mbox, "/PN=", buffer, buffer_len)) {
173         for (mbox = buffer; (mbox = strchr(mbox, '.')); )
174             *mbox++ = ' ';
175
176         return buffer;
177     }
178
179     if (!get_x400_comp (mbox, "/S=", surname, sizeof(surname)))
180         return NULL;
181
182     if (get_x400_comp (mbox, "/G=", given, sizeof(given)))
183         snprintf (buffer, buffer_len, "%s %s", given, surname);
184     else
185         snprintf (buffer, buffer_len, "%s", surname);
186
187     return buffer;
188 }
189
190 static int
191 get_x400_comp (char *mbox, char *key, char *buffer, int buffer_len)
192 {
193     int idx;
194     char *cp;
195
196     if ((idx = stringdex (key, mbox)) < 0
197             || !(cp = strchr(mbox += idx + strlen (key), '/')))
198         return 0;
199
200     snprintf (buffer, buffer_len, "%*.*s", cp - mbox, cp - mbox, mbox);
201     return 1;
202 }
203
204 struct format *
205 fmt_scan (struct format *format, char *scanl, int width, int *dat)
206 {
207     char *cp, *ep, *sp;
208     char *savestr, *str = NULL;
209     char buffer[BUFSIZ], buffer2[BUFSIZ];
210     int i, c, ljust, n;
211     int value = 0;
212     time_t t;
213     struct format *fmt;
214     struct comp *comp;
215     struct tws *tws;
216     struct mailname *mn;
217
218     cp = scanl;
219     ep = scanl + width - 1;
220
221     for (fmt = format; fmt->f_type != FT_DONE; fmt++)
222         switch (fmt->f_type) {
223         case FT_PARSEADDR:
224         case FT_PARSEDATE:
225             fmt->f_comp->c_flags &= ~CF_PARSED;
226             break;
227         }
228
229     fmt = format;
230
231     while (cp < ep) {
232         switch (fmt->f_type) {
233
234         case FT_COMP:
235             PUTS (cp, fmt->f_comp->c_text);
236             break;
237         case FT_COMPF:
238             cp = PUTSF(cp, fmt->f_comp->c_text, fmt->f_width, fmt->f_fill);
239             break;
240
241         case FT_LIT:
242             sp = fmt->f_text;
243             while( (c = *sp++) && cp < ep)
244                 *cp++ = c;
245             break;
246         case FT_LITF:
247             sp = fmt->f_text;
248             ljust = 0;
249             i = fmt->f_width;
250             if (i < 0) {
251                 i = -i;
252                 ljust++;                /* XXX should do something with this */
253             }
254             while( (c = *sp++) && --i >= 0 && cp < ep)
255                 *cp++ = c;
256             while( --i >= 0 && cp < ep)
257                 *cp++ = fmt->f_fill;
258             break;
259
260         case FT_STR:
261             PUTS (cp, str);
262             break;
263         case FT_STRF:
264             cp =PUTSF (cp, str, fmt->f_width, fmt->f_fill);
265             break;
266         case FT_STRFW:
267             adios (NULL, "internal error (FT_STRFW)");
268
269         case FT_NUM:
270             n = snprintf(cp, ep - cp, "%d", value);
271             if (n >= 0) cp += n;
272             break;
273         case FT_NUMF:
274             PUTDF (cp, value, fmt->f_width, fmt->f_fill);
275             break;
276
277         case FT_CHAR:
278             *cp++ = fmt->f_char;
279             break;
280
281         case FT_DONE:
282             goto finished;
283
284         case FT_IF_S:
285             if (!(value = (str && *str))) {
286                 fmt += fmt->f_skip;
287                 continue;
288             }
289             break;
290
291         case FT_IF_S_NULL:
292             if (!(value = (str == NULL || *str == 0))) {
293                 fmt += fmt->f_skip;
294                 continue;
295             }
296             break;
297
298         case FT_IF_V_EQ:
299             if (value != fmt->f_value) {
300                 fmt += fmt->f_skip;
301                 continue;
302             }
303             break;
304
305         case FT_IF_V_NE:
306             if (value == fmt->f_value) {
307                 fmt += fmt->f_skip;
308                 continue;
309             }
310             break;
311
312         case FT_IF_V_GT:
313             if (value <= fmt->f_value) {
314                 fmt += fmt->f_skip;
315                 continue;
316             }
317             break;
318
319         case FT_IF_MATCH:
320             if (!(value = (str && match (str, fmt->f_text)))) {
321                 fmt += fmt->f_skip;
322                 continue;
323             }
324             break;
325
326         case FT_V_MATCH:
327             if (str)
328                 value = match (str, fmt->f_text);
329             else
330                 value = 0;
331             break;
332
333         case FT_IF_AMATCH:
334             if (!(value = (str && uprf (str, fmt->f_text)))) {
335                 fmt += fmt->f_skip;
336                 continue;
337             }
338             break;
339
340         case FT_V_AMATCH:
341             value = uprf (str, fmt->f_text);
342             break;
343
344         case FT_S_NONNULL:
345             value = (str != NULL && *str != 0);
346             break;
347
348         case FT_S_NULL:
349             value = (str == NULL || *str == 0);
350             break;
351
352         case FT_V_EQ:
353             value = (fmt->f_value == value);
354             break;
355
356         case FT_V_NE:
357             value = (fmt->f_value != value);
358             break;
359
360         case FT_V_GT:
361             value = (fmt->f_value > value);
362             break;
363
364         case FT_GOTO:
365             fmt += fmt->f_skip;
366             continue;
367
368         case FT_NOP:
369             break;
370
371         case FT_LS_COMP:
372             str = fmt->f_comp->c_text;
373             break;
374         case FT_LS_LIT:
375             str = fmt->f_text;
376             break;
377         case FT_LS_GETENV:
378             if (!(str = getenv (fmt->f_text)))
379                 str = "";
380             break;
381         case FT_LS_CFIND:
382             if (!(str = context_find (fmt->f_text)))
383                 str = "";
384             break;
385
386         case FT_LS_DECODECOMP:
387             if (decode_rfc2047(fmt->f_comp->c_text, buffer2, sizeof(buffer2)))
388                 str = buffer2;
389             else
390                 str = fmt->f_comp->c_text;
391             break;
392
393         case FT_LS_DECODE:
394             if (str && decode_rfc2047(str, buffer2, sizeof(buffer2)))
395                 str = buffer2;
396             break;
397
398         case FT_LS_TRIM:
399             if (str) {
400                     char *xp;
401
402                     strncpy(buffer, str, sizeof(buffer));
403                     buffer[sizeof(buffer)-1] = '\0';
404                     str = buffer;
405                     while (isspace(*str))
406                             str++;
407                     ljust = 0;
408                     if ((i = fmt->f_width) < 0) {
409                             i = -i;
410                             ljust++;
411                     }
412
413                     if (!ljust && i > 0 && strlen(str) > i)
414                             str[i] = '\0';
415                     xp = str;
416                     xp += strlen(str) - 1;
417                     while (xp > str && isspace(*xp))
418                             *xp-- = '\0';
419                     if (ljust && i > 0 && strlen(str) > i)
420                         str += strlen(str) - i;
421             }
422             break;
423
424         case FT_LV_COMPFLAG:
425             value = (fmt->f_comp->c_flags & CF_TRUE) != 0;
426             break;
427         case FT_LV_COMP:
428             value = (comp = fmt->f_comp)->c_text ? atoi(comp->c_text) : 0;
429             break;
430         case FT_LV_LIT:
431             value = fmt->f_value;
432             break;
433         case FT_LV_DAT:
434             value = dat[fmt->f_value];
435             break;
436         case FT_LV_STRLEN:
437             if (str != NULL)
438                     value = strlen(str);
439             else
440                     value = 0;
441             break;
442         case FT_LV_CHAR_LEFT:
443             value = width - (cp - scanl);
444             break;
445         case FT_LV_PLUS_L:
446             value += fmt->f_value;
447             break;
448         case FT_LV_MINUS_L:
449             value = fmt->f_value - value;
450             break;
451         case FT_LV_DIVIDE_L:
452             if (fmt->f_value)
453                 value = value / fmt->f_value;
454             else
455                 value = 0;
456             break;
457         case FT_LV_MODULO_L:
458             if (fmt->f_value)
459                 value = value % fmt->f_value;
460             else
461                 value = 0;
462             break;
463         case FT_SAVESTR:
464             savestr = str;
465             break;
466
467         case FT_LV_SEC:
468             value = fmt->f_comp->c_tws->tw_sec;
469             break;
470         case FT_LV_MIN:
471             value = fmt->f_comp->c_tws->tw_min;
472             break;
473         case FT_LV_HOUR:
474             value = fmt->f_comp->c_tws->tw_hour;
475             break;
476         case FT_LV_MDAY:
477             value = fmt->f_comp->c_tws->tw_mday;
478             break;
479         case FT_LV_MON:
480             value = fmt->f_comp->c_tws->tw_mon + 1;
481             break;
482         case FT_LS_MONTH:
483             str = tw_moty[fmt->f_comp->c_tws->tw_mon];
484             break;
485         case FT_LS_LMONTH:
486             str = lmonth[fmt->f_comp->c_tws->tw_mon];
487             break;
488         case FT_LS_ZONE:
489             str = dtwszone (fmt->f_comp->c_tws);
490             break;
491         case FT_LV_YEAR:
492             value = fmt->f_comp->c_tws->tw_year;
493             break;
494         case FT_LV_WDAY:
495             if (!(((tws = fmt->f_comp->c_tws)->tw_flags) & (TW_SEXP|TW_SIMP)))
496                 set_dotw (tws);
497             value = tws->tw_wday;
498             break;
499         case FT_LS_DAY:
500             if (!(((tws = fmt->f_comp->c_tws)->tw_flags) & (TW_SEXP|TW_SIMP)))
501                 set_dotw (tws);
502             str = tw_dotw[tws->tw_wday];
503             break;
504         case FT_LS_WEEKDAY:
505             if (!(((tws = fmt->f_comp->c_tws)->tw_flags) & (TW_SEXP|TW_SIMP)))
506                 set_dotw (tws);
507             str = tw_ldotw[tws->tw_wday];
508             break;
509         case FT_LV_YDAY:
510             value = fmt->f_comp->c_tws->tw_yday;
511             break;
512         case FT_LV_ZONE:
513             value = fmt->f_comp->c_tws->tw_zone;
514             break;
515         case FT_LV_CLOCK:
516             if ((value = fmt->f_comp->c_tws->tw_clock) == 0)
517                 value = dmktime(fmt->f_comp->c_tws);
518             break;
519         case FT_LV_RCLOCK:
520             if ((value = fmt->f_comp->c_tws->tw_clock) == 0)
521                 value = dmktime(fmt->f_comp->c_tws);
522             value = time((time_t *) 0) - value;
523             break;
524         case FT_LV_DAYF:
525             if (!(((tws = fmt->f_comp->c_tws)->tw_flags) & (TW_SEXP|TW_SIMP)))
526                 set_dotw (tws);
527             switch (fmt->f_comp->c_tws->tw_flags & TW_SDAY) {
528                 case TW_SEXP:
529                     value = 1; break;
530                 case TW_SIMP:
531                     value = 0; break;
532                 default:
533                     value = -1; break;
534             }
535         case FT_LV_ZONEF:
536             if ((fmt->f_comp->c_tws->tw_flags & TW_SZONE) == TW_SZEXP)
537                     value = 1;
538             else
539                     value = -1;
540             break;
541         case FT_LV_DST:
542             value = fmt->f_comp->c_tws->tw_flags & TW_DST;
543             break;
544         case FT_LS_822DATE:
545             str = dasctime (fmt->f_comp->c_tws , TW_ZONE);
546             break;
547         case FT_LS_PRETTY:
548             str = dasctime (fmt->f_comp->c_tws, TW_NULL);
549             break;
550
551         case FT_LS_PERS:
552             str = fmt->f_comp->c_mn->m_pers;
553             break;
554         case FT_LS_MBOX:
555             str = fmt->f_comp->c_mn->m_mbox;
556             break;
557         case FT_LS_HOST:
558             str = fmt->f_comp->c_mn->m_host;
559             break;
560         case FT_LS_PATH:
561             str = fmt->f_comp->c_mn->m_path;
562             break;
563         case FT_LS_GNAME:
564             str = fmt->f_comp->c_mn->m_gname;
565             break;
566         case FT_LS_NOTE:
567             str = fmt->f_comp->c_mn->m_note;
568             break;
569         case FT_LS_822ADDR:
570             str = adrformat( fmt->f_comp->c_mn );
571             break;
572         case FT_LV_HOSTTYPE:
573             value = fmt->f_comp->c_mn->m_type;
574             break;
575         case FT_LV_INGRPF:
576             value = fmt->f_comp->c_mn->m_ingrp;
577             break;
578         case FT_LV_NOHOSTF:
579             value = fmt->f_comp->c_mn->m_nohost;
580             break;
581         case FT_LS_ADDR:
582         case FT_LS_FRIENDLY:
583             if ((mn = fmt->f_comp->c_mn) == &fmt_mnull) {
584                 str = fmt->f_comp->c_text;
585                 break;
586             }
587             if (fmt->f_type == FT_LS_ADDR)
588                 goto unfriendly;
589             if ((str = mn->m_pers) == NULL) {
590                 if ((str = mn->m_note)) {
591                     strncpy (buffer, str, sizeof(buffer));
592                     buffer[sizeof(buffer)-1] = '\0';
593                     str = buffer;
594                     if (*str == '(')
595                         str++;
596                     sp = str + strlen(str) - 1;
597                     if (*sp == ')') {
598                         *sp-- = '\0';
599                         while (sp >= str)
600                             if (*sp == ' ')
601                                 *sp-- = '\0';
602                             else
603                                 break;
604                     }
605                 } else if (!(str = get_x400_friendly (mn->m_mbox,
606                                 buffer, sizeof(buffer)))) {
607         unfriendly: ;
608                   switch (mn->m_type) {
609                     case LOCALHOST:
610                         str = mn->m_mbox;
611                         break;
612                     case UUCPHOST:
613                         snprintf (buffer, sizeof(buffer), "%s!%s",
614                                 mn->m_host, mn->m_mbox);
615                         str = buffer;
616                         break;
617                     default:
618                         if (mn->m_mbox) {
619                             snprintf (buffer, sizeof(buffer), "%s@%s",
620                                 mn->m_mbox, mn->m_host);
621                             str= buffer;
622                         }
623                         else
624                             str = mn->m_text;
625                         break;
626                   }
627                 }
628             }
629             break;  
630
631
632                 /* UNQUOTEs RFC-2822 quoted-string and quoted-pair */
633         case FT_LS_UNQUOTE:
634             if (str) {          
635                 int m;
636                 strncpy(buffer, str, sizeof(buffer));
637                 /* strncpy doesn't NUL-terminate if it fills the buffer */
638                 buffer[sizeof(buffer)-1] = '\0';
639                 str = buffer;
640         
641                 /* we will parse from buffer to buffer2 */
642                 n = 0; /* n is the input position in str */
643                 m = 0; /* m is the ouput position in buffer2 */
644
645                 while ( str[n] != '\0') {
646                     switch ( str[n] ) {
647                         case '\\':
648                             n++;
649                             if ( str[n] != '\0') 
650                                 buffer2[m++] = str[n++];
651                             break;
652                         case '"':
653                             n++;
654                             break;
655                         default:
656                             buffer2[m++] = str[n++];
657                             break;
658                         }                
659                 }
660                 buffer2[m] = '\0';
661                 str = buffer2;
662             }
663             break;
664
665         case FT_LOCALDATE:
666             comp = fmt->f_comp;
667             if ((t = comp->c_tws->tw_clock) == 0)
668                 t = dmktime(comp->c_tws);
669             tws = dlocaltime(&t);
670             *comp->c_tws = *tws;
671             break;
672
673         case FT_GMTDATE:
674             comp = fmt->f_comp;
675             if ((t = comp->c_tws->tw_clock) == 0)
676                 t = dmktime(comp->c_tws);
677             tws = dgmtime(&t);
678             *comp->c_tws = *tws;
679             break;
680
681         case FT_PARSEDATE:
682             comp = fmt->f_comp;
683             if (comp->c_flags & CF_PARSED)
684                 break;
685             if ((sp = comp->c_text) && (tws = dparsetime(sp))) {
686                 *comp->c_tws = *tws;
687                 comp->c_flags &= ~CF_TRUE;
688             } else if ((comp->c_flags & CF_DATEFAB) == 0) {
689                 memset ((char *) comp->c_tws, 0, sizeof *comp->c_tws);
690                 comp->c_flags = CF_TRUE;
691             }
692             comp->c_flags |= CF_PARSED;
693             break;
694
695         case FT_FORMATADDR:
696             /* hook for custom address list formatting (see replsbr.c) */
697             str = formataddr (savestr, str);
698             break;
699
700         case FT_PUTADDR:
701             /* output the str register as an address component,
702              * splitting it into multiple lines if necessary.  The
703              * value reg. contains the max line length.  The lit.
704              * field may contain a string to prepend to the result
705              * (e.g., "To: ")
706              */
707             {
708             char *lp, *lastb;
709             int indent, wid, len;
710
711             lp = str;
712             wid = value;
713             len = strlen (str);
714             sp = fmt->f_text;
715             indent = strlen (sp);
716             wid -= indent;
717             while( (c = *sp++) && cp < ep)
718                 *cp++ = c;
719             while (len > wid) {
720                 /* try to break at a comma; failing that, break at a
721                  * space.
722                  */
723                 lastb = 0; sp = lp + wid;
724                 while (sp > lp && (c = *--sp) != ',') {
725                     if (! lastb && isspace(c))
726                         lastb = sp - 1;
727                 }
728                 if (sp == lp) {
729                     if (! (sp = lastb)) {
730                         sp = lp + wid - 1;
731                         while (*sp && *sp != ',' && !isspace(*sp))
732                             sp++;
733                         if (*sp != ',')
734                             sp--;
735                     }
736                 }
737                 len -= sp - lp + 1;
738                 while (cp < ep && lp <= sp)
739                     *cp++ = *lp++;
740                 while (isspace(*lp))
741                     lp++, len--;
742                 if (*lp) {
743                     if (cp < ep)
744                         *cp++ = '\n';
745                     for (i=indent; cp < ep && i > 0; i--)
746                         *cp++ = ' ';
747                 }
748             }
749             PUTS (cp, lp);
750             }
751             break;
752
753         case FT_PARSEADDR:
754             comp = fmt->f_comp;
755             if (comp->c_flags & CF_PARSED)
756                 break;
757             if (comp->c_mn != &fmt_mnull)
758                 mnfree (comp->c_mn);
759             if ((sp = comp->c_text) && (sp = getname(sp)) &&
760                 (mn = getm (sp, NULL, 0, fmt_norm, NULL))) {
761                 comp->c_mn = mn;
762                 while (getname(""))
763                     ;
764                 comp->c_flags |= CF_PARSED;
765             } else {
766                 while (getname(""))             /* XXX */
767                     ;
768                 comp->c_mn = &fmt_mnull;
769             }
770             break;
771             
772         case FT_MYMBOX:
773             /*
774              * if there's no component, we say true.  Otherwise we
775              * say "true" only if we can parse the address and it
776              * matches one of our addresses.
777              */
778             comp = fmt->f_comp;
779             if (comp->c_mn != &fmt_mnull)
780                 mnfree (comp->c_mn);
781             if ((sp = comp->c_text) && (sp = getname(sp)) &&
782                 (mn = getm (sp, NULL, 0, AD_NAME, NULL))) {
783                 comp->c_mn = mn;
784                 if (ismymbox(mn))
785                     comp->c_flags |= CF_TRUE;
786                 else
787                     comp->c_flags &= ~CF_TRUE;
788                 while ((sp = getname(sp)))
789                     if ((comp->c_flags & CF_TRUE) == 0 &&
790                         (mn = getm (sp, NULL, 0, AD_NAME, NULL)))
791                         if (ismymbox(mn))
792                             comp->c_flags |= CF_TRUE;
793             } else {
794                 while (getname(""))             /* XXX */
795                     ;
796                 if (comp->c_text == 0)
797                     comp->c_flags |= CF_TRUE;
798                 else
799                     comp->c_flags &= ~CF_TRUE;
800                 comp->c_mn = &fmt_mnull;
801             }
802             break;
803
804         case FT_ADDTOSEQ:
805 #ifdef LBL
806             /* If we're working on a folder (as opposed to a file), add the
807              * current msg to sequence given in literal field.  Don't
808              * disturb string or value registers.
809              */
810             if (fmt_current_folder)
811                     seq_addmsg(fmt_current_folder, fmt->f_text, dat[0], -1);
812 #endif
813             break;
814         }
815         fmt++;
816     }
817 #ifndef JLR
818     finished:;
819     if (cp[-1] != '\n')
820         *cp++ = '\n';
821     *cp   = 0;
822     return ((struct format *)0);
823 #else /* JLR */
824     if (cp[-1] != '\n')
825         *cp++ = '\n';
826     while (fmt->f_type != FT_DONE)
827         fmt++;
828
829     finished:;    
830     *cp = '\0';
831     return (fmt->f_value ? ++fmt : (struct format *) 0);
832
833 #endif /* JLR */
834 }