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