** This code is Copyright (c) 2002, by the authors of nmh. See the
** COPYRIGHT file in the root directory of the nmh distribution for
** complete copyright information.
+**
+** This is the engine that processes the format instructions created by
+** fmt_compile (found in fmt_compile.c).
*/
#include <h/mh.h>
#include <h/fmt_scan.h>
#include <h/tws.h>
#include <h/fmt_compile.h>
+#include <ctype.h>
+#include <sysexits.h>
-#ifdef TIME_WITH_SYS_TIME
+#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
-# include <time.h>
-#else
-# ifdef TM_IN_SYS_TIME
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
#endif
+#include <time.h>
+
#ifdef MULTIBYTE_SUPPORT
# include <wctype.h>
# include <wchar.h>
#endif
-#define NFMTS MAXARGS
-
-extern char *formataddr(); /* hook for custom address formatting */
-
-#ifdef LBL
-struct msgs *fmt_current_folder; /* current folder (set by main program) */
-#endif
-
extern int fmt_norm; /* defined in sbr/fmt_def.c = AD_NAME */
struct mailname fmt_mnull;
static int match(char *, char *);
static char *get_x400_friendly(char *, char *, int);
static int get_x400_comp(char *, char *, char *, int);
+static char *fmt_trim(char *, int);
/*
int c1, c2;
char *s1, *s2;
-#ifdef LOCALE
while ((c1 = *sub)) {
- c1 = (isalpha(c1) && isupper(c1)) ? tolower(c1) : c1;
- while ((c2 = *str++) && c1 != ((isalpha(c2) && isupper(c2)) ? tolower(c2) : c2))
+ while ((c2 = *str++) && tolower(c1) != tolower(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))
+ while ((c1 = *s1++) && tolower(c1) == tolower(*s2++))
;
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
return 1;
}
static void
cpstripped(char **start, char *end, char *str)
{
+#ifdef MULTIBYTE_SUPPORT
+ int char_len; /* bytes in current character */
+ int nbytes;
+ wchar_t wide_char;
+#else
int c;
+#endif
char *s = str;
if (!s)
return;
/* skip any initial control characters or spaces */
- while ((c = (unsigned char) *s) &&
-#ifdef LOCALE
- (iscntrl(c) || isspace(c)))
+#ifdef MULTIBYTE_SUPPORT
+ nbytes = end - *start + 1;
+ mbtowc(NULL, NULL, 0); /* reset shift state */
+ while ((char_len = mbtowc(&wide_char, s, nbytes)) > 0 && (iswcntrl(wide_char) || iswspace(wide_char))) {
+ s += char_len;
+ nbytes -= char_len;
+ }
#else
- (c <= 32))
-#endif
+ while ((c = (unsigned char) *s) && (iscntrl(c) || isspace(c)))
s++;
+#endif
/* compact repeated control characters and spaces into a single space */
- while((c = (unsigned char) *s++) && *start < end)
- if (!iscntrl(c) && !isspace(c))
+#ifdef MULTIBYTE_SUPPORT
+ while ((char_len = mbtowc(&wide_char, s, nbytes)) > 0 && *start < end) {
+ if (!iswcntrl(wide_char) && !iswspace(wide_char)) {
+ strncpy(*start, s, char_len);
+ s += char_len;
+ *start += char_len;
+ nbytes -= char_len;
+ } else {
+ while ((char_len = mbtowc(&wide_char, s, nbytes)) > 0 && (iswcntrl(wide_char) || iswspace(wide_char))) {
+ s += char_len;
+ nbytes -= char_len;
+ }
+ *(*start)++ = ' ';
+ }
+ }
+#else
+ while((c = (unsigned char) *s++) && *start < end) {
+ if (!iscntrl(c) && !isspace(c)) {
*(*start)++ = c;
- else {
+ } else {
while ((c = (unsigned char) *s) &&
-#ifdef LOCALE
- (iscntrl(c) || isspace(c)))
-#else
- (c <= 32))
-#endif
+ (iscntrl(c) || isspace(c)))
s++;
*(*start)++ = ' ';
}
+ }
+#endif
}
static char *lmonth[] = {
return 1;
}
+static char *
+fmt_trim(char *str, int width)
+{
+ char *xp;
+ int ljust, i;
+ char buffer[BUFSIZ];
+ char *dst;
+
+ strncpy(buffer, str, sizeof(buffer));
+ dst = buffer;
+ dst[sizeof(buffer)-1] = '\0';
+ while (isspace(*dst)) {
+ dst++;
+ }
+ ljust = 0;
+ if ((i = width) < 0) {
+ i = -i;
+ ljust++;
+ }
+
+ if (!ljust && i > 0 && (int)strlen(dst) > i) {
+ dst[i] = '\0';
+ }
+ xp = dst;
+ xp += strlen(dst) - 1;
+ while (xp > dst && isspace(*xp)) {
+ *xp-- = '\0';
+ }
+ if (ljust && i > 0 && (int)strlen(dst) > i) {
+ dst += strlen(dst) - i;
+ }
+ strncpy(str, dst, strlen(str) + 1);
+ return str;
+}
+
struct format *
fmt_scan(struct format *format, char *scanl, int width, int *dat)
{
cptrimmed(&cp, str, fmt->f_width, fmt->f_fill, ep - cp);
break;
case FT_STRFW:
- adios(NULL, "internal error (FT_STRFW)");
+ adios(EX_SOFTWARE, NULL, "internal error (FT_STRFW)");
case FT_NUM:
n = snprintf(cp, ep - cp + 1, "%d", value);
case FT_LS_TRIM:
if (str) {
- unsigned char *xp;
-
- strncpy(buffer, str, sizeof(buffer));
- buffer[sizeof(buffer)-1] = '\0';
- str = buffer;
- while (isspace(*str))
- str++;
- ljust = 0;
- if ((i = fmt->f_width) < 0) {
- i = -i;
- ljust++;
- }
-
- if (!ljust && i > 0 && strlen(str) > i)
- str[i] = '\0';
- xp = str;
- xp += strlen(str) - 1;
- while (xp > str && isspace(*xp))
- *xp-- = '\0';
- if (ljust && i > 0 && strlen(str) > i)
- str += strlen(str) - i;
+ str = fmt_trim(str, fmt->f_width);
}
break;
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 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 = 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);
+ str = dasctime(fmt->f_comp->c_tws);
break;
case FT_LS_PERS:
case LOCALHOST:
str = mn->m_mbox;
break;
- case UUCPHOST:
- snprintf(buffer, sizeof(buffer), "%s!%s",
- mn->m_host, mn->m_mbox);
- str = buffer;
- break;
default:
if (mn->m_mbox) {
- snprintf(buffer, sizeof(buffer), "%s@%s",
- mn->m_mbox, mn->m_host);
+ snprintf(buffer, sizeof(buffer), "%s@%s", mn->m_mbox, mn->m_host);
str= buffer;
} else
str = mn->m_text;
break;
- }
+ }
}
}
break;
/* UNQUOTEs RFC-2822 quoted-string and quoted-pair */
case FT_LS_UNQUOTE:
if (str) {
- int m;
strncpy(buffer, str, sizeof(buffer));
/* strncpy doesn't NUL-terminate if it fills the buffer */
buffer[sizeof(buffer)-1] = '\0';
- str = buffer;
-
- /* we will parse from buffer to buffer2 */
- n = 0; /* n is the input position in str */
- m = 0; /* m is the ouput position in buffer2 */
-
- while ( str[n] != '\0') {
- switch ( str[n] ) {
- case '\\':
- n++;
- if ( str[n] != '\0')
- buffer2[m++] = str[n++];
- break;
- case '"':
- n++;
- break;
- default:
- buffer2[m++] = str[n++];
- break;
- }
- }
- buffer2[m] = '\0';
+ unquote_string(buffer, buffer2);
str = buffer2;
}
break;
sp = fmt->f_text;
indent = strlen(sp);
wid -= indent;
+ if (wid <= 0) {
+ adios(EX_SOFTWARE, NULL, "putaddr -- num register (%d) "
+ "must be greater than label "
+ "width (%d)", value, indent);
+ }
while( (c = *sp++) && cp < ep)
*cp++ = c;
while (len > wid) {
- /* try to break at a comma; failing that,
- * break at a space.
- */
+ /*
+ ** try to break at a comma; failing that,
+ ** break at a space.
+ */
lastb = 0; sp = lp + wid;
while (sp > lp && (c = *--sp) != ',') {
if (! lastb && isspace(c))
}
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)
- seq_addmsg(fmt_current_folder, fmt->f_text, dat[0], -1);
-#endif
+ case FT_LS_UNMAILTO:
+ if (!str) {
+ break;
+ }
+ str = trim(str);
+ if (*str == '<' && str[strlen(str)-1] == '>') {
+ str++;
+ str[strlen(str)-1] = '\0';
+ }
+ if (strncmp("mailto:", str, 7)==0) {
+ str += 7;
+ }
break;
+
}
fmt++;
}
-#ifndef JLR
- finished:;
- if (cp[-1] != '\n')
- *cp++ = '\n';
- *cp = 0;
- return ((struct format *)0);
-#else /* JLR */
+finished:;
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 */
+ return ((struct format *)0);
}