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