1 /* formatsbr.c - format string interpretation */
4 #include "../h/addrsbr.h"
5 #include "../h/formatsbr.h"
6 #include "../zotnet/tws.h"
7 #include "../h/fmtcompile.h"
10 #include <sys/types.h>
16 static char *formats = 0;
17 extern char *formataddr(); /* hook for custom address formatting */
18 struct msgs *fmt_current_folder;/* current folder (set by main program) */
20 int fmt_norm = AD_NAME;
21 struct mailname fmt_mnull;
30 for (dp = cp; *cp; cp++)
67 new_fs(form, format, def)
68 register char *form, *format, *def;
77 if ((fp = fopen(libpath(form), "r")) == NULL)
78 adios(form, "unable to open format file");
80 if (fstat(fileno(fp), &st) == NOTOK)
81 adios(form, "unable to stat format file");
83 if ((formats = malloc((unsigned) st.st_size + 1)) == NULLCP)
84 adios(form, "unable to allocate space for format");
86 if (read(fileno(fp), formats, st.st_size) != st.st_size)
87 adios(form, "error reading format file");
89 formats[st.st_size] = '\0';
92 formats = getcpy(format ? format : def);
101 * test if string "sub" appears anywhere in string "str"
102 * (case insensitive).
106 register char *str, *sub;
114 while ((c2 = *str++) && (c1 | 040) != (c2 | 040))
120 while ((c1 = *s1++) && (c1 | 040) == (*s2++ | 040))
128 /* macros to format data */
130 #define PUTDF(cp, num, wid, fill) {\
131 if (cp + wid < ep) {\
132 if ((i = (num)) < 0)\
134 if ((c = (wid)) < 0)\
138 *--sp = (i % 10) + '0';\
140 } while (i > 0 && sp > cp);\
143 else if ((num) < 0 && sp > cp)\
149 #define PUTD(cp, num) {\
151 if ((i = (num)) == 0)\
154 if ((i = (num)) < 0) \
155 *cp++ = '-', i = -(num);\
159 while (cp < ep && c > 1) {\
161 *cp++ = (i / c) + '0';\
166 #define PUTSF(cp, str, wid, fill) {\
169 if ((i = (wid)) < 0) {\
179 while (--i >= c && cp < ep)\
184 while ((c = *sp) && c <= 32)\
187 while ((c = *sp++) && --i >= 0 && cp < ep)\
190 else if (c == '\010') {\
194 while ((c = *sp) && c <= 32)\
200 while (--i >= 0 && cp < ep)\
204 #define PUTS(cp, str) {\
207 while ((c = *sp) && c <= 32)\
209 while ((c = *sp++) && cp < ep)\
212 else if (c == '\010') {\
216 while ((c = *sp) && c <= 32)\
222 static char *lmonth[] = {
223 "January", "February", "March", "April", "May", "June",
224 "July", "August", "September", "October", "November", "December"
228 fmtscan(format, scanl, width, dat)
229 struct format *format;
234 register char *cp = scanl;
235 register char *ep = scanl + width - 1;
236 register struct format *fmt = format;
237 register char *str = NULLCP;
238 register int value = 0;
242 register struct comp *comp;
243 register struct tws *tws;
244 register struct mailname *mn;
252 switch (fmt->f_type) {
255 PUTS(cp, fmt->f_comp->c_text);
258 PUTSF(cp, fmt->f_comp->c_text, fmt->f_width,
265 ep += i; /* forced lits are `invisible' */
272 while ((c = *sp++) && cp < ep)
278 /* By default we left justify */
280 if ((i = fmt->f_width) < 0) {
289 else while (j < i && cp < ep) {
295 while ((c = *sp++) && --i >= 0 && cp < ep)
298 while (--i >= 0 && cp < ep)
306 PUTSF(cp, str, fmt->f_width, fmt->f_fill);
309 adios(NULLCP, "internal error (FT_STRFW)");
315 PUTDF(cp, value, fmt->f_width, fmt->f_fill);
325 if (str == NULLCP || *str == NULL) {
332 if (str != NULLCP && *str != NULL) {
339 if (value != fmt->f_value) {
346 if (value == fmt->f_value) {
353 if (value <= fmt->f_value) {
360 if (!str || !match(str, fmt->f_text)) {
368 value = match(str, fmt->f_text);
374 if (!str || !uprf(str, fmt->f_text)) {
382 value = uprf(str, fmt->f_text);
388 value = (str != NULLCP && *str != NULL);
392 value = (str == NULLCP || *str == NULL);
396 value = (fmt->f_value == value);
400 value = (fmt->f_value != value);
404 value = (fmt->f_value > value);
415 str = fmt->f_comp->c_text;
424 /* Be careful since str can point into buffer */
425 bcopy(str, buffer, strlen(str) + 1);
428 /* Eat leading whitespace */
429 while (isspace(*str))
432 /* Trim trailing whitespace */
433 xp = str + strlen(str) - 1;
434 while (xp > str && isspace(*xp))
437 /* By default we left justify */
439 if ((i = fmt->f_width) < 0) {
444 /* If necessary, limit width and/or justify */
445 if (i > 0 && (j = strlen(str)) > i) {
455 value = fmt->f_comp->c_flags;
458 value = (comp = fmt->f_comp)->c_text ?
459 atoi(comp->c_text) : 0;
462 value = fmt->f_value;
465 value = dat[fmt->f_value];
470 case FT_LV_CHAR_LEFT:
471 value = width - (cp - scanl);
474 value += fmt->f_value;
477 value = fmt->f_value - value;
481 value = value / fmt->f_value;
490 value = fmt->f_comp->c_tws->tw_sec;
493 value = fmt->f_comp->c_tws->tw_min;
496 value = fmt->f_comp->c_tws->tw_hour;
499 value = fmt->f_comp->c_tws->tw_mday;
502 value = fmt->f_comp->c_tws->tw_mon + 1;
505 str = tw_moty[fmt->f_comp->c_tws->tw_mon];
508 str = lmonth[fmt->f_comp->c_tws->tw_mon];
511 str = dtwszone(fmt->f_comp->c_tws);
514 value = fmt->f_comp->c_tws->tw_year;
517 if (!(((tws = fmt->f_comp->c_tws)->tw_flags) &
518 (TW_SEXP | TW_SIMP)))
520 value = tws->tw_wday;
523 if (!(((tws = fmt->f_comp->c_tws)->tw_flags) &
524 (TW_SEXP | TW_SIMP)))
526 str = tw_dotw[tws->tw_wday];
529 if (!(((tws = fmt->f_comp->c_tws)->tw_flags) &
530 (TW_SEXP | TW_SIMP)))
532 str = tw_ldotw[tws->tw_wday];
535 value = fmt->f_comp->c_tws->tw_yday;
538 value = fmt->f_comp->c_tws->tw_zone;
541 if ((value = fmt->f_comp->c_tws->tw_clock) == 0)
542 value = twclock(fmt->f_comp->c_tws);
545 if ((value = fmt->f_comp->c_tws->tw_clock) == 0)
546 value = twclock(fmt->f_comp->c_tws);
547 value = time((long *) 0) - value;
550 if (!(((tws = fmt->f_comp->c_tws)->tw_flags) &
551 (TW_SEXP | TW_SIMP)))
553 switch (fmt->f_comp->c_tws->tw_flags & TW_SDAY) {
565 if ((fmt->f_comp->c_tws->tw_flags & TW_SZONE) ==
572 value = fmt->f_comp->c_tws->tw_flags & TW_DST;
575 str = dasctime(fmt->f_comp->c_tws, TW_ZONE);
578 str = dasctime(fmt->f_comp->c_tws, TW_NULL);
582 str = fmt->f_comp->c_mn->m_pers;
585 str = fmt->f_comp->c_mn->m_mbox;
588 str = fmt->f_comp->c_mn->m_host;
591 str = fmt->f_comp->c_mn->m_path;
594 str = fmt->f_comp->c_mn->m_gname;
597 str = fmt->f_comp->c_mn->m_note;
600 str = adrformat(fmt->f_comp->c_mn);
603 value = fmt->f_comp->c_mn->m_type;
606 value = fmt->f_comp->c_mn->m_ingrp;
609 value = fmt->f_comp->c_mn->m_nohost;
613 str = fmt->f_comp->c_mn->m_mbox;
615 mn = fmt->f_comp->c_mn;
616 if ((str = mn->m_pers) == NULL)
617 switch (mn->m_type) {
623 (void) sprintf(buffer, "%s!%s",
624 mn->m_host, mn->m_mbox);
629 (void) sprintf(buffer, "%s@%s",
630 mn->m_mbox, mn->m_host);
641 if ((l = comp->c_tws->tw_clock) == 0)
642 l = twclock(comp->c_tws);
643 tws = dlocaltime(&l);
649 if ((l = comp->c_tws->tw_clock) == 0)
650 l = twclock(comp->c_tws);
657 if ((sp = comp->c_text) && (tws = dparsetime(sp))) {
660 } else if (comp->c_flags >= 0) {
661 bzero((char *)comp->c_tws,
662 sizeof(*comp->c_tws));
668 /* custom address list formatting hook */
669 str = formataddr(savestr, str);
674 * Output the str register as an address component,
675 * splitting it into multiple lines if necessary.
676 * The value reg. contains the max line length. The
677 * lit. field may contain a string to prepend to the
678 * result (e.g., "To: ")
681 register char *lp = str;
683 register int wid = value;
684 register int len = strlen(str);
685 register char *lastb;
690 while ((c = *sp++) && cp < ep)
694 * Try to break at a comma; failing
695 * that, break at a space, failing
696 * that, just split the line.
700 while (sp > lp && (c = *--sp) != ',') {
701 if (!lastb && isspace(c))
708 while (cp < ep && lp <= sp)
711 for (i = indent; cp < ep && i > 0; i--)
722 if (comp->c_mn != &fmt_mnull)
724 if ((sp = comp->c_text) && (sp = getname(sp)) &&
725 (mn = getm(sp, NULLCP, 0, fmt_norm, NULLCP))) {
730 comp->c_mn = &fmt_mnull;
735 * If there's no component, we say true. Otherwise
736 * we say "true" only if we can parse the address and
737 * it matches one of our addresses.
740 if (comp->c_mn != &fmt_mnull)
742 if ((sp = comp->c_text) && (sp = getname(sp)) &&
743 (mn = getm(sp, NULLCP, 0, AD_NAME, NULLCP))) {
745 comp->c_flags = ismymbox(mn);
746 while (sp = getname(sp))
747 if (comp->c_flags == 0 &&
748 (mn = getm(sp, NULLCP, 0,
750 comp->c_flags |= ismymbox(mn);
752 comp->c_flags = (comp->c_text == 0);
753 comp->c_mn = &fmt_mnull;
759 * If we're working on a folder (as opposed to a
760 * file), add the current msg to sequence given in
761 * literal field. Don't disturb string or value
764 if (fmt_current_folder)
765 (void) m_seqadd(fmt_current_folder,
766 fmt->f_text, dat[0], -1);