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