1 /* formatsbr.c - format string interpretation */
3 static char ident[] = "@(#)$Id: formatsbr.c,v 1.25 1995/12/06 20:59:41 jromine Exp shettich $";
7 #include "../h/addrsbr.h"
8 #include "../h/formatsbr.h"
9 #include "../zotnet/tws.h"
10 #include "../h/fmtcompile.h"
13 #include <sys/types.h>
22 static char *formats = 0;
23 extern char *formataddr (); /* hook for custom address formatting */
25 struct msgs *fmt_current_folder; /* current folder (set by main program) */
29 static int get_x400_comp();
31 extern int fmt_norm; /* defined in sbr/formatdef.c = AD_NAME */
32 struct mailname fmt_mnull;
39 /* MAJOR HACK: See MHCHANGES for discussion */
41 char *new_fs (form, format, def)
53 if ((fp = fopen (libpath (form), "r")) == NULL)
54 adios (form, "unable to open format file");
56 if (fstat (fileno (fp), &st) == NOTOK)
57 adios (form, "unable to stat format file");
59 if ((formats = malloc ((unsigned) st.st_size + 1)) == NULLCP)
60 adios (form, "unable to allocate space for format");
62 if (read (fileno(fp), formats, (int) st.st_size) != st.st_size)
63 adios (form, "error reading format file");
65 formats[st.st_size] = '\0';
70 formats = getcpy (format ? format : def);
85 for (dp = cp; *cp; cp++)
90 #define grot(y,z) case y: *dp++ = z; break;
112 * test if string "sub" appears anywhere in string "str"
113 * (case insensitive).
116 static int match (str, sub)
127 c1 = (isalpha(c1) && isupper(c1)) ? tolower(c1) : c1;
128 while ((c2 = *str++) && c1 != ((isalpha(c2) && isupper(c2)) ? tolower(c2) : c2))
132 s1 = sub + 1; s2 = str;
133 while ((c1 = *s1++) && ((isalpha(c1) && isupper(c1)) ? tolower(c1) : c1) == ((isalpha(c2 =*s2++) && isupper(c2)) ? tolower(c2) : c2))
140 while ((c2 = *str++) && (c1 | 040) != (c2 | 040))
144 s1 = sub + 1; s2 = str;
145 while ((c1 = *s1++) && (c1 | 040) == (*s2++ | 040))
155 /* macros to format data */
157 #define PUTDF(cp, num, wid, fill) if (cp + wid < ep){\
158 if((i = (num))<0) i = -(num);\
159 if((c = (wid))<0) c = -c;\
162 *--sp = (i % 10) + '0';\
164 } while (i > 0 && sp > cp);\
167 else if ((num) < 0 && sp > cp)\
173 #define PUTD(cp, num) if (cp < ep){\
174 if((i = (num))==0) *cp++ = '0';\
177 *cp++ = '-', i = -(num);\
181 while (cp < ep && c > 1) {\
183 *cp++ = (i / c) + '0';\
189 #define PUTSF(cp, str, wid, fill) {\
191 if ((i = (wid)) < 0) {\
201 while( --i >= c && cp < ep)\
206 while ((c = (unsigned char) *sp) && (iscntrl(c) || isspace(c)))\
209 while ((c = (unsigned char) *sp++) && --i >= 0 && cp < ep)\
213 while ((c = (unsigned char) *sp) && (iscntrl(c) || isspace(c)))\
219 while( --i >= 0 && cp < ep)\
222 #define PUTS(cp, str) {\
224 while ((c = (unsigned char) *sp) && (iscntrl(c) || isspace(c)))\
226 while((c = (unsigned char) *sp++) && cp < ep)\
230 while ((c = (unsigned char) *sp) && (iscntrl(c) || isspace(c)))\
237 #define PUTSF(cp, str, wid, fill) {\
239 if ((i = (wid)) < 0) {\
249 while( --i >= c && cp < ep)\
254 while ((c = *sp) && c <= 32)\
257 while ((c = *sp++) && --i >= 0 && cp < ep)\
261 while ((c = *sp) && c <= 32)\
267 while( --i >= 0 && cp < ep)\
270 #define PUTS(cp, str) {\
272 while ((c = *sp) && c <= 32)\
274 while( (c = *sp++) && cp < ep)\
278 while ( (c = *sp) && c <= 32 )\
287 static char *lmonth[] = { "January", "February","March", "April",
288 "May", "June", "July", "August",
289 "September","October", "November","December" };
291 static char *get_x400_friendly (mbox, buffer)
305 if (get_x400_comp (mbox, "/PN=", buffer)) {
306 for (mbox = buffer; mbox = index (mbox, '.'); )
312 if (!get_x400_comp (mbox, "/S=", surname))
315 if (get_x400_comp (mbox, "/G=", given))
316 (void) sprintf (buffer, "%s %s", given, surname);
318 (void) strcpy (buffer, surname);
323 static int get_x400_comp (mbox, key, buffer)
331 if ((idx = stringdex (key, mbox)) < 0
332 || !(cp = index (mbox += idx + strlen (key), '/')))
335 (void) sprintf (buffer, "%*.*s", cp - mbox, cp - mbox, mbox);
340 fmtscan (format, scanl, width, dat)
341 struct format *format;
346 register char *cp = scanl;
347 register char *ep = scanl + width - 1;
348 register struct format *fmt = format;
349 register char *str = NULLCP;
350 register int value = 0;
354 register struct comp *comp;
355 register struct tws *tws;
356 register struct mailname *mn;
363 switch (fmt->f_type) {
366 PUTS (cp, fmt->f_comp->c_text);
369 PUTSF (cp, fmt->f_comp->c_text, fmt->f_width, fmt->f_fill);
374 while( (c = *sp++) && cp < ep)
383 ljust++; /* XXX should do something with this */
385 while( (c = *sp++) && --i >= 0 && cp < ep)
387 while( --i >= 0 && cp < ep)
395 PUTSF (cp, str, fmt->f_width, fmt->f_fill);
398 adios (NULLCP, "internal error (FT_STRFW)");
404 PUTDF (cp, value, fmt->f_width, fmt->f_fill);
415 if (!(value = (str && *str))) {
422 if (!(value = (str == NULLCP || *str == 0))) {
429 if (value != fmt->f_value) {
436 if (value == fmt->f_value) {
443 if (value <= fmt->f_value) {
450 if (!(value = (str && match (str, fmt->f_text)))) {
458 value = match (str, fmt->f_text);
464 if (!(value = (str && uprf (str, fmt->f_text)))) {
471 value = uprf (str, fmt->f_text);
475 value = (str != NULLCP && *str != 0);
479 value = (str == NULLCP || *str == 0);
483 value = (fmt->f_value == value);
487 value = (fmt->f_value != value);
491 value = (fmt->f_value > value);
502 str = fmt->f_comp->c_text;
508 if (!(str = getenv (fmt->f_text)))
512 if (!(str = m_find (fmt->f_text)))
519 (void) strcpy(buffer, str);
521 while (isspace(*str))
524 if ((i = fmt->f_width) < 0) {
529 if (!ljust && i > 0 && strlen(str) > i)
532 xp += strlen(str) - 1;
533 while (xp > str && isspace(*xp))
535 if (ljust && i > 0 && strlen(str) > i)
536 str += strlen(str) - i;
541 value = fmt->f_comp->c_flags;
544 value = (comp = fmt->f_comp)->c_text ? atoi(comp->c_text) : 0;
547 value = fmt->f_value;
550 value = dat[fmt->f_value];
555 case FT_LV_CHAR_LEFT:
556 value = width - (cp - scanl);
559 value += fmt->f_value;
562 value = fmt->f_value - value;
566 value = value / fmt->f_value;
572 value = value % fmt->f_value;
581 value = fmt->f_comp->c_tws->tw_sec;
584 value = fmt->f_comp->c_tws->tw_min;
587 value = fmt->f_comp->c_tws->tw_hour;
590 value = fmt->f_comp->c_tws->tw_mday;
593 value = fmt->f_comp->c_tws->tw_mon + 1;
596 str = tw_moty[fmt->f_comp->c_tws->tw_mon];
599 str = lmonth[fmt->f_comp->c_tws->tw_mon];
602 str = dtwszone (fmt->f_comp->c_tws);
606 value = fmt->f_comp->c_tws->tw_year;
608 value = (fmt->f_comp->c_tws->tw_year) % 100;
612 if (!(((tws = fmt->f_comp->c_tws)->tw_flags) & (TW_SEXP|TW_SIMP)))
614 value = tws->tw_wday;
617 if (!(((tws = fmt->f_comp->c_tws)->tw_flags) & (TW_SEXP|TW_SIMP)))
619 str = tw_dotw[tws->tw_wday];
622 if (!(((tws = fmt->f_comp->c_tws)->tw_flags) & (TW_SEXP|TW_SIMP)))
624 str = tw_ldotw[tws->tw_wday];
627 value = fmt->f_comp->c_tws->tw_yday;
630 value = fmt->f_comp->c_tws->tw_zone;
633 if ((value = fmt->f_comp->c_tws->tw_clock) == 0)
634 value = twclock(fmt->f_comp->c_tws);
637 if ((value = fmt->f_comp->c_tws->tw_clock) == 0)
638 value = twclock(fmt->f_comp->c_tws);
639 value = time((time_t *) 0) - value;
642 if (!(((tws = fmt->f_comp->c_tws)->tw_flags) & (TW_SEXP|TW_SIMP)))
644 switch (fmt->f_comp->c_tws->tw_flags & TW_SDAY) {
653 if ((fmt->f_comp->c_tws->tw_flags & TW_SZONE) == TW_SZEXP)
659 value = fmt->f_comp->c_tws->tw_flags & TW_DST;
662 str = dasctime ( fmt->f_comp->c_tws , TW_ZONE);
665 str = dasctime ( fmt->f_comp->c_tws, TW_NULL);
669 str = fmt->f_comp->c_mn->m_pers;
672 str = fmt->f_comp->c_mn->m_mbox;
675 str = fmt->f_comp->c_mn->m_host;
678 str = fmt->f_comp->c_mn->m_path;
681 str = fmt->f_comp->c_mn->m_gname;
684 str = fmt->f_comp->c_mn->m_note;
687 str = adrformat( fmt->f_comp->c_mn );
690 value = fmt->f_comp->c_mn->m_type;
693 value = fmt->f_comp->c_mn->m_ingrp;
696 value = fmt->f_comp->c_mn->m_nohost;
701 str = fmt->f_comp->c_mn->m_mbox;
703 if ((mn = fmt -> f_comp -> c_mn) == &fmt_mnull) {
704 str = fmt -> f_comp -> c_text;
707 if (fmt -> f_type == FT_LS_ADDR)
709 if (!(str = mn -> m_pers)
710 && (!(str = get_x400_friendly (mn -> m_mbox, buffer)))) {
711 if (str = mn -> m_note) {
712 (void) strcpy (buffer, str);
716 sp = str + strlen (str) - 1;
730 switch (mn -> m_type) {
735 (void) sprintf (str = buffer, "%s!%s",
736 mn -> m_host, mn -> m_mbox);
740 (void) sprintf (str= buffer, "%s@%s", mn -> m_mbox,
752 if ((l = comp->c_tws->tw_clock) == 0)
753 l = twclock(comp->c_tws);
754 tws = dlocaltime(&l);
760 if ((l = comp->c_tws->tw_clock) == 0)
761 l = twclock(comp->c_tws);
768 if ((sp = comp->c_text) && (tws = dparsetime(sp))) {
771 } else if (comp->c_flags >= 0) {
772 bzero ((char *) comp -> c_tws, sizeof *comp -> c_tws);
778 /* hook for custom address list formatting (see replsbr.c) */
779 str = formataddr (savestr, str);
783 /* output the str register as an address component,
784 * splitting it into multiple lines if necessary. The
785 * value reg. contains the max line length. The lit.
786 * field may contain a string to prepend to the result
790 register char *lp = str;
792 register int wid = value;
793 register int len = strlen (str);
794 register char *lastb;
797 indent = strlen (sp);
799 while( (c = *sp++) && cp < ep)
802 /* try to break at a comma; failing that, break at a
803 * space, failing that, just split the line.
805 lastb = 0; sp = lp + wid;
806 while (sp > lp && (c = *--sp) != ',') {
807 if (! lastb && isspace(c))
814 while (cp < ep && lp <= sp)
817 for (i=indent; cp < ep && i > 0; i--)
828 if (comp->c_mn != &fmt_mnull)
830 if ((sp = comp->c_text) && (sp = getname(sp)) &&
831 (mn = getm (sp, NULLCP, 0, fmt_norm, NULLCP))) {
836 while (getname("")) /* XXX */
838 comp->c_mn = &fmt_mnull;
844 * if there's no component, we say true. Otherwise we
845 * say "true" only if we can parse the address and it
846 * matches one of our addresses.
849 if (comp->c_mn != &fmt_mnull)
851 if ((sp = comp->c_text) && (sp = getname(sp)) &&
852 (mn = getm (sp, NULLCP, 0, AD_NAME, NULLCP))) {
854 comp->c_flags = ismymbox(mn);
855 while (sp = getname(sp))
856 if (comp->c_flags == 0 &&
857 (mn = getm (sp, NULLCP, 0, AD_NAME, NULLCP)))
858 comp->c_flags |= ismymbox(mn);
860 while (getname("")) /* XXX */
862 comp->c_flags = (comp->c_text == 0);
863 comp->c_mn = &fmt_mnull;
869 /* If we're working on a folder (as opposed to a file), add the
870 * current msg to sequence given in literal field. Don't
871 * disturb string or value registers.
873 if (fmt_current_folder)
874 (void)m_seqadd(fmt_current_folder, fmt->f_text, dat[0], -1);
885 return ((struct format *)0);
889 while (fmt->f_type != FT_DONE)
894 return (fmt -> f_value ? ++fmt : (struct format *)0);