Mercurial > hg > Applications > mh
diff sbr/formatsbr.c @ 0:bce86c4163a3
Initial revision
author | kono |
---|---|
date | Mon, 18 Apr 2005 23:46:02 +0900 |
parents | |
children | 441a2190cfae |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sbr/formatsbr.c Mon Apr 18 23:46:02 2005 +0900 @@ -0,0 +1,1129 @@ +/* formatsbr.c - format string interpretation */ +#ifndef lint +static char ident[] = "@(#)$Id$"; +#endif /* lint */ + +#include "../h/mh.h" +#include "../h/addrsbr.h" +#include "../h/formatsbr.h" +#include "../zotnet/tws.h" +#include "../h/fmtcompile.h" +#include <ctype.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> + +/* */ + + +#define NFMTS MAXARGS +#define QUOTE '\\' + +static char *formats = 0; +extern char *formataddr (); /* hook for custom address formatting */ +#ifdef LBL +struct msgs *fmt_current_folder; /* current folder (set by main program) */ +#endif + +static normalize(); +static int get_x400_comp(); + +extern int fmt_norm; /* defined in sbr/formatdef.c = AD_NAME */ +struct mailname fmt_mnull; + +#ifdef JAPAN +extern int japan_environ; +#endif /* JAPAN */ + +time_t time (); + +/* */ + +/* MAJOR HACK: See MHCHANGES for discussion */ + +char *new_fs (form, format, def) +register char *form, + *format, + *def; +{ + struct stat st; + register FILE *fp; + + if (formats) + free (formats); + + if (form) { + if ((fp = fopen (libpath (form), "r")) == NULL) + adios (form, "unable to open format file"); + + if (fstat (fileno (fp), &st) == NOTOK) + adios (form, "unable to stat format file"); + + if ((formats = malloc ((unsigned) st.st_size + 1)) == NULLCP) + adios (form, "unable to allocate space for format"); + + if (read (fileno(fp), formats, (int) st.st_size) != st.st_size) + adios (form, "error reading format file"); + + formats[st.st_size] = '\0'; + + (void) fclose (fp); + } + else { + formats = getcpy (format ? format : def); + } + +#ifdef JAPAN + (void) ml_conv(formats); +#endif /* JAPAN */ + + normalize (formats); + + return formats; +} + +/* */ + +static normalize (cp) +register char *cp; +{ + register char *dp; + + for (dp = cp; *cp; cp++) + if (*cp != QUOTE) + *dp++ = *cp; + else + switch (*++cp) { +#define grot(y,z) case y: *dp++ = z; break; + grot ('b', '\b'); + grot ('f', '\f'); + grot ('n', '\n'); + grot ('r', '\r'); + grot ('t', '\t'); + + case '\n': + break; + + case 0: + cp--; /* fall */ + default: + *dp++ = *cp; + break; + } + + *dp = 0; +} + +/* */ +/* + * test if string "sub" appears anywhere in string "str" + * (case insensitive). + */ + +static int match (str, sub) +register unsigned char *str, + *sub; +{ + register unsigned int c1; + register unsigned int c2; + register unsigned char *s1; + register unsigned char *s2; + +#ifdef JAPAN + while (c1 = *sub) { + c1 = (isalpha(c1) && isupper(c1)) ? tolower(c1) : c1; + while ((c2 = *str++) + && c1 != ((isalpha(c2) && isupper(c2)) ? tolower(c2) : c2)) + ; + if (! c2) + return 0; + s1 = sub + 1; s2 = str; + while ((c1 = *s1++) && + ((isalpha(c1) && isupper(c1)) ? tolower(c1) : c1) + == ((isalpha(c2 = *s2++) && isupper(c2)) ? tolower(c2) : c2)) + ; + if (! c1) + return 1; + } +#else /* JAPAN */ +#ifdef LOCALE + while (c1 = *sub) { + c1 = (isalpha(c1) && isupper(c1)) ? tolower(c1) : c1; + while ((c2 = *str++) && c1 != ((isalpha(c2) && isupper(c2)) ? tolower(c2) : c2)) + ; + if (! c2) + return 0; + s1 = sub + 1; s2 = str; + while ((c1 = *s1++) && ((isalpha(c1) && isupper(c1)) ? tolower(c1) : c1) == ((isalpha(c2 =*s2++) && isupper(c2)) ? tolower(c2) : c2)) + ; + if (! c1) + return 1; + } +#else + while (c1 = *sub) { + while ((c2 = *str++) && (c1 | 040) != (c2 | 040)) + ; + if (! c2) + return 0; + s1 = sub + 1; s2 = str; + while ((c1 = *s1++) && (c1 | 040) == (*s2++ | 040)) + ; + if (! c1) + return 1; + } +#endif +#endif /* JAPAN */ + return 1; +} +/* */ + +/* macros to format data */ + +#define PUTDF(cp, num, wid, fill) if (cp + wid < ep){\ + if((i = (num))<0) i = -(num);\ + if((c = (wid))<0) c = -c;\ + sp = cp + c;\ + do {\ + *--sp = (i % 10) + '0';\ + i /= 10;\ + } while (i > 0 && sp > cp);\ + if (i > 0)\ + *sp = '?';\ + else if ((num) < 0 && sp > cp)\ + *--sp = '-';\ + while (sp > cp)\ + *--sp = fill;\ + cp += c;\ + } +#define PUTD(cp, num) if (cp < ep){\ + if((i = (num))==0) *cp++ = '0';\ + else {\ + if((i = (num))<0) \ + *cp++ = '-', i = -(num);\ + c = 10;\ + while (1) {\ + int j;\ + if (c > i) {\ + c /= 10; break;\ + }\ + j = c;\ + c *= 10;\ + if (c % 10) { /* overflow */\ + c = j; break;\ + }\ + }\ + while (cp < ep && c > 0) {\ + *cp++ = (i / c) + '0';\ + i %= c;\ + c /= 10;\ + }\ + }\ + } +#ifdef LOCALE +#define PUTSF(cp, str, wid, fill) {\ + ljust = 0;\ + if ((i = (wid)) < 0) {\ + i = -i;\ + ljust++;\ + }\ + if (sp = (str)) {\ + if (ljust) {\ + c = strlen(sp);\ + if (c > i)\ + sp += c - i;\ + else {\ + while( --i >= c && cp < ep)\ + *cp++ = fill;\ + i++;\ + }\ + } else {\ + while ((c = (unsigned char) *sp) && (iscntrl(c) || isspace(c)))\ + sp++;\ + }\ + while ((c = (unsigned char) *sp++) && --i >= 0 && cp < ep)\ + if (isgraph(c)) \ + *cp++ = c;\ + else {\ + while ((c = (unsigned char) *sp) && (iscntrl(c) || isspace(c)))\ + sp++;\ + *cp++ = ' ';\ + }\ + }\ + if (!ljust)\ + while( --i >= 0 && cp < ep)\ + *cp++ = fill;\ + } +#define PUTS(cp, str) {\ + if (sp = (str)) {\ + while ((c = (unsigned char) *sp) && (iscntrl(c) || isspace(c)))\ + sp++;\ + while((c = (unsigned char) *sp++) && cp < ep)\ + if (isgraph(c)) \ + *cp++ = c;\ + else {\ + while ((c = (unsigned char) *sp) && (iscntrl(c) || isspace(c)))\ + sp++;\ + *cp++ = ' ';\ + }\ + }\ + } +#else /* LOCALE */ +#define PUTSF(cp, str, wid, fill) {\ + ljust = 0;\ + if ((i = (wid)) < 0) {\ + i = -i;\ + ljust++;\ + }\ + if (sp = (str)) {\ + if (ljust) {\ + c = strlen(sp);\ + if (c > i)\ + sp += c - i;\ + else {\ + while( --i >= c && cp < ep)\ + *cp++ = fill;\ + i++;\ + }\ + } else {\ + while ((c = (unsigned char) *sp) && c <= 32)\ + sp++;\ + }\ + while ((c = (unsigned char) *sp++) && --i >= 0 && cp < ep)\ + if (c > 32) \ + *cp++ = c;\ + else {\ + while ((c = (unsigned char) *sp) && c <= 32)\ + sp++;\ + *cp++ = ' ';\ + }\ + }\ + if (!ljust)\ + while( --i >= 0 && cp < ep)\ + *cp++ = fill;\ + } +#define PUTS(cp, str) {\ + if (sp = (str)) {\ + while ((c = (unsigned char) *sp) && c <= 32)\ + sp++;\ + while( (c = (unsigned char) *sp++) && cp < ep)\ + if ( c > 32 ) \ + *cp++ = c;\ + else {\ + while ( (c = (unsigned char) *sp) && c <= 32 )\ + sp++;\ + *cp++ = ' ';\ + }\ + }\ + } +#endif + +#ifdef JAPAN + +#undef PUTSF +#undef PUTS + +#ifndef isgraph +#define isgraph(c) ((040<(c))&&((c)!=0177)) +#endif + +#define ISSPACE(c1) (isspace((c1) & 0x7f)) +#define ISGRAPH(c1) ((isgraph((c1) & 0x7f))\ + || (japan_environ && (((c1) & 0xff) == 0x1b))) +#define ISCNTRL(c1) ((((c1) & 0xff) == 0x1b)\ + ? !japan_environ : (iscntrl((c1) & 0x7f))) +#define ISJSPACE(c1,c2) ((((c1) & 0xff) == 0xa1) && (((c2) & 0xff) == 0xa1)) +#define ISJGRAPH(c1,c2) ((isgraph((c1) & 0x7f)) &&\ + (isgraph((c2) & 0x7f)) &&\ + (!ISJSPACE((c1), (c2)))) + +#define SKIP_SPACE(sp) {\ + while (ch = *(sp)) {\ + if (ISCNTRL(ch) || ISSPACE(ch)) {\ + (sp)++;\ + } else if (ch2 = *((sp)+1)) {\ + if (ISJSPACE(ch, ch2)) {\ + (sp) += 2;\ + } else {\ + break;\ + }\ + } else {\ + break;\ + }\ + }\ +} + +#define PUTSF(cp, str, wid, fill) {\ + ljust = 0;\ + if ((i = (wid)) < 0) {\ + i = -i; ljust++;\ + }\ + if (sp = (str)) {\ + if (ljust) {\ + c = strlen(sp);\ + if (c > i)\ + sp += c - i;\ + else {\ + while (--i >= c && cp < ep)\ + *cp++ = fill;\ + i++;\ + }\ + } else {\ + SKIP_SPACE(sp);\ + }\ + while ((ch = *sp++) && (--i >= 0) && (cp < ep)) {\ + if (ml_ismlchar(ch)) {\ + if ((ch2 = *sp) && ((i-1) >= 0) && ((cp+1) < ep)) {\ + if (ISJGRAPH(ch, ch2)) {\ + *cp++ = ch; *cp++ = ch2; sp++; --i;\ + } else {\ + sp++; SKIP_SPACE(sp); *cp++ = ' ';\ + }\ + } else {\ + *cp++ = ' ';\ + }\ + } else {\ + if (ISGRAPH(ch)) {\ + *cp++ = ch;\ + } else {\ + SKIP_SPACE(sp); *cp++ = ' ';\ + }\ + }\ + }\ + }\ + if (!ljust)\ + while ((--i >= 0) && (cp < ep))\ + *cp++ = fill;\ +} + +#define PUTS(cp, str) {\ + if (sp = (str)) {\ + SKIP_SPACE(sp);\ + while ((ch = *sp++) && (cp < ep)) {\ + if (ml_ismlchar(ch)) {\ + if ((ch2 = *sp) && ((cp+1) < ep)) {\ + if (ISJGRAPH(ch, ch2)) {\ + *cp++ = ch; *cp++ = ch2; sp++;\ + } else {\ + sp++; SKIP_SPACE(sp); *cp++ = ' ';\ + }\ + } else {\ + *cp++ = ' ';\ + }\ + } else {\ + if (ISGRAPH(ch)) {\ + *cp++ = ch;\ + } else {\ + SKIP_SPACE(sp); *cp++ = ' ';\ + }\ + }\ + }\ + }\ +} + +#endif /* JAPAN */ + +static char *lmonth[] = { "January", "February","March", "April", + "May", "June", "July", "August", + "September","October", "November","December" }; + +static char *get_x400_friendly (mbox, buffer) +char *mbox, + *buffer; +{ + char given[BUFSIZ], + surname[BUFSIZ]; + + if (mbox == NULLCP) + return NULLCP; + if (*mbox == '"') + mbox++; + if (*mbox != '/') + return NULLCP; + + if (get_x400_comp (mbox, "/PN=", buffer)) { + for (mbox = buffer; mbox = index (mbox, '.'); ) + *mbox++ = ' '; + + return buffer; + } + + if (!get_x400_comp (mbox, "/S=", surname)) + return NULLCP; + + if (get_x400_comp (mbox, "/G=", given)) + (void) sprintf (buffer, "%s %s", given, surname); + else + (void) strcpy (buffer, surname); + + return buffer; +} + +static int get_x400_comp (mbox, key, buffer) +char *mbox, + *key, + *buffer; +{ + int idx; + char *cp; + + if ((idx = stringdex (key, mbox)) < 0 + || !(cp = index (mbox += idx + strlen (key), '/'))) + return 0; + + (void) sprintf (buffer, "%*.*s", cp - mbox, cp - mbox, mbox); + return 1; +} + +struct format * +fmtscan (format, scanl, width, dat) + struct format *format; + char *scanl; + int width; + int dat[]; +{ + register char *cp = scanl; + register char *ep = scanl + width - 1; + register struct format *fmt = format; + register char *str = NULLCP; + register int value = 0; + register char *sp; + register int i; + register int c; + register unsigned char ch, ch2; + register struct comp *comp; + register struct tws *tws; + register struct mailname *mn; + int ljust; + time_t l; + char *savestr; + char buffer[BUFSIZ]; + + while (cp < ep) { + switch (fmt->f_type) { + + case FT_COMP: + PUTS (cp, fmt->f_comp->c_text); + break; + case FT_COMPF: + PUTSF (cp, fmt->f_comp->c_text, fmt->f_width, fmt->f_fill); + break; + + case FT_LIT: + sp = fmt->f_text; + while( (ch = *sp++) && cp < ep) + *cp++ = ch; + break; + case FT_LITF: + sp = fmt->f_text; + ljust = 0; + i = fmt->f_width; + if (i < 0) { + i = -i; + ljust++; /* XXX should do something with this */ + } + while ((ch = *sp++) && --i >= 0 && cp < ep) + *cp++ = ch; + while( --i >= 0 && cp < ep) + *cp++ = fmt->f_fill; + break; + + case FT_STR: + PUTS (cp, str); + break; + case FT_STRF: + PUTSF (cp, str, fmt->f_width, fmt->f_fill); + break; + case FT_STRFW: + adios (NULLCP, "internal error (FT_STRFW)"); + + case FT_NUM: + PUTD (cp, value); + break; + case FT_NUMF: + PUTDF (cp, value, fmt->f_width, fmt->f_fill); + break; + + case FT_CHAR: + *cp++ = fmt->f_char; + break; + + case FT_DONE: + goto finished; + + case FT_IF_S: + if (!(value = (str && *str))) { + fmt += fmt->f_skip; + continue; + } + break; + + case FT_IF_S_NULL: + if (!(value = (str == NULLCP || *str == 0))) { + fmt += fmt->f_skip; + continue; + } + break; + + case FT_IF_V_EQ: + if (value != fmt->f_value) { + fmt += fmt->f_skip; + continue; + } + break; + + case FT_IF_V_NE: + if (value == fmt->f_value) { + fmt += fmt->f_skip; + continue; + } + break; + + case FT_IF_V_GT: + if (value <= fmt->f_value) { + fmt += fmt->f_skip; + continue; + } + break; + + case FT_IF_MATCH: + if (!(value = (str && match (str, fmt->f_text)))) { + fmt += fmt->f_skip; + continue; + } + break; + + case FT_V_MATCH: + if (str) + value = match (str, fmt->f_text); + else + value = 0; + break; + + case FT_IF_AMATCH: + if (!(value = (str && uprf (str, fmt->f_text)))) { + fmt += fmt->f_skip; + continue; + } + break; + + case FT_V_AMATCH: + value = uprf (str, fmt->f_text); + break; + + case FT_S_NONNULL: + value = (str != NULLCP && *str != 0); + break; + + case FT_S_NULL: + value = (str == NULLCP || *str == 0); + break; + + case FT_V_EQ: + value = (fmt->f_value == value); + break; + + case FT_V_NE: + value = (fmt->f_value != value); + break; + + case FT_V_GT: + value = (fmt->f_value > value); + break; + + case FT_GOTO: + fmt += fmt->f_skip; + continue; + + case FT_NOP: + break; + +#ifdef MIME_HEADERS + case FT_LS_HENCODE: + if (str) { + char *ep; + if ((ep = malloc((unsigned)strlen(str)*10+1)) == NULL) + adios(NULLCP, "out of memory"); + (void) exthdr_encode(str, ep, 0, ""); + (void) strncpy(buffer, ep, BUFSIZ); + buffer[BUFSIZ-1] = '\0'; + str = buffer; + } + break; + case FT_LS_HDECODE: + if (str) { + char *ep; + if ((ep = malloc((unsigned)strlen(str)+1)) == NULL) + adios(NULLCP, "out of memory"); + (void) exthdr_decode(str, ep); + (void) strncpy(buffer, ep, BUFSIZ); + buffer[BUFSIZ-1] = '\0'; + str = buffer; + } + break; +#endif /* MIME_HEADERS */ + + case FT_LS_COMP: + str = fmt->f_comp->c_text; + break; + case FT_LS_LIT: + str = fmt->f_text; + break; + case FT_LS_GETENV: + if (!(str = getenv (fmt->f_text))) + str = ""; + break; + case FT_LS_MFIND: + if (!(str = m_find (fmt->f_text))) + str = ""; + break; + case FT_LS_TRIM: + if (str) { + register char *xp; + +#if 1 + (void) strncpy(buffer, str, BUFSIZ); + buffer[BUFSIZ-1] = '\0'; +#else + (void) strcpy(buffer, str); +#endif + str = buffer; +#ifdef JAPAN + SKIP_SPACE(str); +#else /* JAPAN */ + while (isspace(*str & 0xff)) + str++; +#endif /* JAPAN */ + ljust = 0; + if ((i = fmt->f_width) < 0) { + i = -i; + ljust++; + } + + if (!ljust && i > 0 && strlen(str) > i) + str[i] = '\0'; + xp = str; +#ifdef JAPAN + sp = str + strlen(str); + while (ch = *xp++) { + if (ISCNTRL(ch) || ISSPACE(ch)) + continue; + if (ch & 0x80) { + if (ch2 = *xp++) { + if (! ISJSPACE(ch, ch2)) + sp = xp; + } else { + sp = xp - 2; + break; + } + } else + sp = xp; + } + *sp = '\0'; + if (ljust && i > 0 && strlen(str) > i) { + sp = str + strlen(str) - i; + while (ch = *str) { + str++; + if (ch & 0x80) + str++; + if (str >= sp) + break; + } + } +#else /* JAPAN */ + xp += strlen(str) - 1; + while (xp > str && isspace(*xp & 0xff)) + *xp-- = '\0'; + if (ljust && i > 0 && strlen(str) > i) + str += strlen(str) - i; +#endif /* JAPAN */ + } + break; + + case FT_LV_COMPFLAG: + value = fmt->f_comp->c_flags; + break; + case FT_LV_COMP: + value = (comp = fmt->f_comp)->c_text ? atoi(comp->c_text) : 0; + break; + case FT_LV_LIT: + value = fmt->f_value; + break; + case FT_LV_DAT: + value = dat[fmt->f_value]; + break; + case FT_LV_STRLEN: + value = strlen(str); + break; + case FT_LV_CHAR_LEFT: + value = width - (cp - scanl); + break; + case FT_LV_PLUS_L: + value += fmt->f_value; + break; + case FT_LV_MINUS_L: + value = fmt->f_value - value; + break; + case FT_LV_DIVIDE_L: + if (fmt->f_value) + value = value / fmt->f_value; + else + value = 0; + break; + case FT_LV_MODULO_L: + if (fmt->f_value) + value = value % fmt->f_value; + else + value = 0; + break; + case FT_SAVESTR: + savestr = str; + break; + + case FT_LV_SEC: + value = fmt->f_comp->c_tws->tw_sec; + break; + case FT_LV_MIN: + value = fmt->f_comp->c_tws->tw_min; + break; + case FT_LV_HOUR: + value = fmt->f_comp->c_tws->tw_hour; + break; + case FT_LV_MDAY: + value = fmt->f_comp->c_tws->tw_mday; + break; + case FT_LV_MON: + value = fmt->f_comp->c_tws->tw_mon + 1; + break; + case FT_LS_MONTH: + str = tw_moty[fmt->f_comp->c_tws->tw_mon]; + break; + case FT_LS_LMONTH: + str = lmonth[fmt->f_comp->c_tws->tw_mon]; + break; + case FT_LS_ZONE: + str = dtwszone (fmt->f_comp->c_tws); + break; + case FT_LV_YEAR: +#ifndef YEARMOD + value = fmt->f_comp->c_tws->tw_year; +#else /* YEARMOD */ + value = (fmt->f_comp->c_tws->tw_year) % 100; +#endif /* YEARMOD */ + break; + case FT_LV_WDAY: + if (!(((tws = fmt->f_comp->c_tws)->tw_flags) & (TW_SEXP|TW_SIMP))) + set_dotw (tws); + value = tws->tw_wday; + break; + case FT_LS_DAY: + if (!(((tws = fmt->f_comp->c_tws)->tw_flags) & (TW_SEXP|TW_SIMP))) + set_dotw (tws); + str = tw_dotw[tws->tw_wday]; + break; + case FT_LS_WEEKDAY: + if (!(((tws = fmt->f_comp->c_tws)->tw_flags) & (TW_SEXP|TW_SIMP))) + set_dotw (tws); + str = tw_ldotw[tws->tw_wday]; + break; + case FT_LV_YDAY: + value = fmt->f_comp->c_tws->tw_yday; + break; + case FT_LV_ZONE: + value = fmt->f_comp->c_tws->tw_zone; + break; + case FT_LV_CLOCK: + if ((value = fmt->f_comp->c_tws->tw_clock) == 0) + value = twclock(fmt->f_comp->c_tws); + break; + case FT_LV_RCLOCK: + if ((l = fmt->f_comp->c_tws->tw_clock) == 0) + l = twclock(fmt->f_comp->c_tws); + value = time((time_t *) 0) - l; + break; + case FT_LV_DAYF: + if (!(((tws = fmt->f_comp->c_tws)->tw_flags) & (TW_SEXP|TW_SIMP))) + set_dotw (tws); + switch (fmt->f_comp->c_tws->tw_flags & TW_SDAY) { + case TW_SEXP: + value = 1; break; + case TW_SIMP: + value = 0; break; + default: + value = -1; break; + } + case FT_LV_ZONEF: + if ((fmt->f_comp->c_tws->tw_flags & TW_SZONE) == TW_SZEXP) + value = 1; + else + value = -1; + break; + case FT_LV_DST: + value = fmt->f_comp->c_tws->tw_flags & TW_DST; + break; + case FT_LS_822DATE: + str = dasctime ( fmt->f_comp->c_tws , TW_ZONE); + break; + case FT_LS_PRETTY: + str = dasctime ( fmt->f_comp->c_tws, TW_NULL); + break; + + case FT_LS_PERS: + str = fmt->f_comp->c_mn->m_pers; + break; + case FT_LS_MBOX: + str = fmt->f_comp->c_mn->m_mbox; + break; + case FT_LS_HOST: + str = fmt->f_comp->c_mn->m_host; + break; + case FT_LS_PATH: + str = fmt->f_comp->c_mn->m_path; + break; + case FT_LS_GNAME: + str = fmt->f_comp->c_mn->m_gname; + break; + case FT_LS_NOTE: + str = fmt->f_comp->c_mn->m_note; + break; + case FT_LS_822ADDR: + str = adrformat( fmt->f_comp->c_mn ); + break; + case FT_LV_HOSTTYPE: + value = fmt->f_comp->c_mn->m_type; + break; + case FT_LV_INGRPF: + value = fmt->f_comp->c_mn->m_ingrp; + break; + case FT_LV_NOHOSTF: + value = fmt->f_comp->c_mn->m_nohost; + break; + case FT_LS_ADDR: + case FT_LS_FRIENDLY: +#ifdef BERK + str = fmt->f_comp->c_mn->m_mbox; +#else /* not BERK */ + if ((mn = fmt -> f_comp -> c_mn) == &fmt_mnull) { + str = fmt -> f_comp -> c_text; + break; + } + if (fmt -> f_type == FT_LS_ADDR) + goto unfriendly; + if (!(str = mn -> m_pers) + && (!(str = get_x400_friendly (mn -> m_mbox, buffer)))) { + if (str = mn -> m_note) { + (void) strcpy (buffer, str); + str = buffer; + if (*str == '(') + str++; + sp = str + strlen (str) - 1; + if (*sp == ')') { + *sp-- = '\0'; + while (sp >= str) + if (*sp == ' ') + *sp-- = '\0'; + else + break; + } + if (*str) + break; + } + +unfriendly: ; + switch (mn -> m_type) { + case LOCALHOST: + str = mn -> m_mbox; + break; + case UUCPHOST: + (void) sprintf (str = buffer, "%s!%s", + mn -> m_host, mn -> m_mbox); + break; + default: + if (mn -> m_mbox) + (void) sprintf (str= buffer, "%s@%s", mn -> m_mbox, + mn -> m_host); + else + str = mn -> m_text; + break; + } + } +#endif /* BERK */ + break; + + case FT_LOCALDATE: + comp = fmt->f_comp; + if ((l = comp->c_tws->tw_clock) == 0) + l = twclock(comp->c_tws); + tws = dlocaltime(&l); + *comp->c_tws = *tws; + break; + + case FT_GMTDATE: + comp = fmt->f_comp; + if ((l = comp->c_tws->tw_clock) == 0) + l = twclock(comp->c_tws); + tws = dgmtime(&l); + *comp->c_tws = *tws; + break; + + case FT_PARSEDATE: + comp = fmt->f_comp; + if ((sp = comp->c_text) && (tws = dparsetime(sp))) { + *comp->c_tws = *tws; + comp->c_flags = 0; + } else if (comp->c_flags >= 0) { + bzero ((char *) comp -> c_tws, sizeof *comp -> c_tws); + comp->c_flags = 1; + } + break; + + case FT_FORMATADDR: + /* hook for custom address list formatting (see replsbr.c) */ + str = formataddr (savestr, str); + break; + + case FT_PUTADDR: + /* output the str register as an address component, + * splitting it into multiple lines if necessary. The + * value reg. contains the max line length. The lit. + * field may contain a string to prepend to the result + * (e.g., "To: ") + */ + { + register char *lp = str; + register int indent; + register int wid = value; + register int len = strlen (str); + register char *lastb; + + sp = fmt->f_text; + indent = strlen (sp); + wid -= indent; + if (wid <= 0) wid = 1; /* avoid core dump */ + while ((ch = *sp++) && (cp < ep)) + *cp++ = ch; + while (len > wid) { + /* try to break at a comma; failing that, break at a + * space, failing that, just split the line. + */ + lastb = 0; sp = lp + wid; + while (sp > lp && (ch = *--sp) != ',') { + if (! lastb && isspace(ch)) + lastb = sp - 1; + } + if (sp == lp) + if (! (sp = lastb)) { + sp = lp + wid - 1; +#ifdef MIME_HEADERS + if (uprf(lp + (*lp == '(' ? 1 : 0), "=?")) { + /* avoid to split MIME encoded-word */ + char *pp; + for (pp = sp + 1; *pp && !isspace(*pp & 0xff); pp++) + ; + if (uprf(pp - (*(pp-1) == ')' ? 3 : 2), "?=")) { + int l = pp - lp; + if (l <= 75 && indent + l > 76) { + int i; + for (i = indent + l - 76; i > 0; i--) + if (*(cp - i) != ' ') { + *cp++ = '\n'; + for (i = 0; i < 76 - l; i++) + *cp++ = ' '; + break; + } + if (i == 0) + cp -= indent + l - 76; + } + sp = pp - 1; + } + } +#endif /* MIME_HEADERS */ + } else + while (sp >= lp && isspace(*sp & 0xff)) + sp--; + len -= sp - lp + 1; + while (cp < ep && lp <= sp) + *cp++ = *lp++; + while (isspace(*lp & 0xff)) + lp++, len--; + if (*lp) { + *cp++ = '\n'; + for (i=indent; cp < ep && i > 0; i--) + *cp++ = ' '; + } + } + PUTS (cp, lp); + } + break; + + case FT_PARSEADDR: + comp = fmt->f_comp; + if (comp->c_mn != &fmt_mnull) + mnfree (comp->c_mn); + if ((sp = comp->c_text) && (sp = getname(sp)) && + (mn = getm (sp, NULLCP, 0, fmt_norm, NULLCP))) { + comp->c_mn = mn; + while (getname("")) + ; + } else { + while (getname("")) /* XXX */ + ; + comp->c_mn = &fmt_mnull; + } + break; + + case FT_MYMBOX: + /* + * if there's no component, we say true. Otherwise we + * say "true" only if we can parse the address and it + * matches one of our addresses. + */ + comp = fmt->f_comp; + if (comp->c_mn != &fmt_mnull) + mnfree (comp->c_mn); + if ((sp = comp->c_text) && (sp = getname(sp)) && + (mn = getm (sp, NULLCP, 0, AD_NAME, NULLCP))) { + comp->c_mn = mn; + comp->c_flags = ismymbox(mn); + while (sp = getname(sp)) + if (comp->c_flags == 0 && + (mn = getm (sp, NULLCP, 0, AD_NAME, NULLCP))) + comp->c_flags |= ismymbox(mn); + } else { + while (getname("")) /* XXX */ + ; + comp->c_flags = (comp->c_text == 0); + comp->c_mn = &fmt_mnull; + } + break; + + case FT_ADDTOSEQ: +#ifdef LBL + /* If we're working on a folder (as opposed to a file), add the + * current msg to sequence given in literal field. Don't + * disturb string or value registers. + */ + if (fmt_current_folder) + (void)m_seqadd(fmt_current_folder, fmt->f_text, dat[0], -1); +#endif + break; + } + fmt++; + } +#ifndef JLR + finished:; + if (cp[-1] != '\n') + *cp++ = '\n'; + *cp = 0; + return ((struct format *)0); +#else /* JLR */ + if (cp[-1] != '\n') + *cp++ = '\n'; + while (fmt->f_type != FT_DONE) + fmt++; + + finished:; + *cp = '\0'; + return (fmt -> f_value ? ++fmt : (struct format *)0); + +#endif /* JLR */ +}