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