#define TF_STNDOUT 14 /* special - enter underline mode */
#define TF_RESET 15 /* special - reset terminal modes */
#define TF_HASCLR 16 /* special - terminal have color? */
+#define TF_FGCOLR 17 /* special - foreground term color */
+#define TF_BGCOLR 18 /* special - background term color */
/* ftable->flags */
/* NB that TFL_PUTS is also used to decide whether the test
* what maps a particular function name into a format instruction.
* type - The type of argument this function expects. Those types are
* listed above (with the TF_ prefix). This affects what gets
- * placed in the format instruction (the f_un union).
+ * placed in the format instruction (the f_un union). Also,
+ * instructions that require special handling are distinguished
+ * here (TF_MYMBOX is one example).
* f_type - The instruction corresponding to this function (from the list
* in fmt_compile.h).
* extra - Used by some functions to provide extra data to the compiler.
{ "decodecomp", TF_COMP, FT_LS_DECODECOMP, 0, TFL_PUTS },
{ "decode", TF_EXPR, FT_LS_DECODE, 0, TFL_PUTS },
{ "trim", TF_EXPR, FT_LS_TRIM, 0, 0 },
+ { "kilo", TF_EXPR, FT_LS_KILO, 0, TFL_PUTS },
+ { "kibi", TF_EXPR, FT_LS_KIBI, 0, TFL_PUTS },
{ "compval", TF_COMP, FT_LV_COMP, 0, TFL_PUTN },
{ "compflag", TF_COMP, FT_LV_COMPFLAG, 0, TFL_PUTN },
{ "num", TF_NUM, FT_LV_LIT, 0, TFL_PUTN },
{ "localmbox", TF_LMBOX, FT_LS_LIT, 0, TFL_PUTS },
{ "plus", TF_NUM, FT_LV_PLUS_L, 0, TFL_PUTN },
{ "minus", TF_NUM, FT_LV_MINUS_L, 0, TFL_PUTN },
+ { "multiply", TF_NUM, FT_LV_MULTIPLY_L, 0, TFL_PUTN },
{ "divide", TF_NUM, FT_LV_DIVIDE_L, 0, TFL_PUTN },
{ "modulo", TF_NUM, FT_LV_MODULO_L, 0, TFL_PUTN },
{ "charleft", TF_NONE, FT_LV_CHAR_LEFT, 0, TFL_PUTN },
{ "friendly", TF_COMP, FT_LS_FRIENDLY, FT_PARSEADDR, TFL_PUTS },
{ "mymbox", TF_COMP, FT_LV_COMPFLAG, FT_MYMBOX, TFL_PUTN },
+ { "getmymbox", TF_COMP, FT_STR, FT_GETMYMBOX, 0 },
+ { "getmyaddr", TF_COMP, FT_LS_ADDR, FT_GETMYADDR, TFL_PUTS },
{ "unquote", TF_EXPR, FT_LS_UNQUOTE, 0, TFL_PUTS },
{ "standout", TF_STNDOUT,FT_LS_LIT, 0, TFL_PUTS },
{ "resetterm", TF_RESET, FT_LS_LIT, 0, TFL_PUTS },
{ "hascolor", TF_HASCLR, FT_LV_LIT, 0, 0 },
+ { "fgcolor", TF_FGCOLR, FT_LS_LIT, 0, TFL_PUTS },
+ { "bgcolor", TF_BGCOLR, FT_LS_LIT, 0, TFL_PUTS },
{ NULL, 0, 0, 0, 0 }
};
+/*
+ * A mapping of color names to terminfo color numbers.
+ *
+ * There are two sets of terminal-setting codes: 'setaf/setab' (ANSI) and
+ * 'setf/setb'. Different terminals support different capabilities, so
+ * we provide a mapping for both. I'm not crazy about putting numbers
+ * directly in here, but it seems these are well defined by terminfo
+ * so it should be okay.
+ */
+
+struct colormap {
+ char *colorname; /* Name of color */
+ int ansinum; /* The ANSI escape color number */
+ int nonansinum; /* The non-ANSI escape color number */
+};
+
+static struct colormap colortable[] = {
+ { "black", 0, 0 },
+ { "red", 1, 4 },
+ { "green", 2, 2 },
+ { "yellow", 3, 6 },
+ { "blue", 4, 1 },
+ { "magenta", 5, 5 },
+ { "cyan", 6, 3 },
+ { "white", 7, 7 },
+ { NULL, 0, 0 }
+};
+
/*
* Hash function for component name. The function should be
* case independent and probably shouldn't involve a routine
/* Add new component to the hash table */
#define NEWCOMP(cm,name) do { \
- cm = ((struct comp *) calloc(1, sizeof (struct comp)));\
+ cm = ((struct comp *) mh_xcalloc (1, sizeof (struct comp)));\
cm->c_name = getcpy(name);\
cm->c_refcount++;\
ncomp++;\
usr_fstring[errpos] = '\0';
for (i = errpos-errctx; i < errpos; i++) {
-#ifdef LOCALE
if (iscntrl((unsigned char) usr_fstring[i]))
-#else
- if (usr_fstring[i] < 32)
-#endif
usr_fstring[i] = '_';
}
*/
i = strlen(fstring)/2 + 1;
if (i==1) i++;
- next_fp = formatvec = (struct format *)calloc ((size_t) i,
+ next_fp = formatvec = (struct format *)mh_xcalloc ((size_t) i,
sizeof(struct format));
if (next_fp == NULL)
adios (NULL, "unable to allocate format storage");
if (cm->c_type & CT_ADDR) {
CERROR("component used as both date and address");
}
- cm->c_tws = (struct tws *)
- calloc((size_t) 1, sizeof(*cm->c_tws));
+ if (cm->c_tws) {
+ memset (cm->c_tws, 0, sizeof *cm->c_tws);
+ } else {
+ cm->c_tws = mh_xcalloc (1, sizeof *cm->c_tws);
+ }
fp->f_type = preprocess;
PUTCOMP(sp);
cm->c_type |= CT_DATE;
break;
case FT_MYMBOX:
+ case FT_GETMYMBOX:
+ case FT_GETMYADDR:
if (!primed) {
ismymbox ((struct mailname *) 0);
primed++;
LV(t->f_type, get_term_numcap("colors") > 1);
break;
+ case TF_FGCOLR:
+ case TF_BGCOLR: {
+ struct colormap *cmap = colortable;
+ char *code;
+
+ sp = cp - 1;
+ while (c && c != ')')
+ c = *cp++;
+ cp[-1] = '\0';
+
+ while (cmap->colorname != NULL) {
+ if (strcasecmp(sp, cmap->colorname) == 0)
+ break;
+ cmap++;
+ }
+
+ if (cmap->colorname == NULL) {
+ CERROR("Unknown color name");
+ break;
+ }
+
+ code = get_term_stringparm(t->type == TF_FGCOLR ? "setaf" : "setab",
+ cmap->ansinum, 0);
+
+ /*
+ * If this doesn't have anything, try falling back to setf/setb
+ */
+
+ if (! code)
+ code = get_term_stringparm(t->type == TF_FGCOLR ? "setf" : "setb",
+ cmap->nonansinum, 0);
+
+ LS(t->f_type, code);
+ break;
+ }
+
case TF_NOW:
LV(t->f_type, time((time_t *) 0));
break;
}
}
+/*
+ * Iterate over our component hash table
+ */
+
+struct comp *
+fmt_nextcomp(struct comp *comp, unsigned int *bucket)
+{
+ if (comp == NULL)
+ *bucket = 0;
+ else
+ comp = comp->c_next;
+
+ while (comp == NULL && *bucket < sizeof(wantcomp)/sizeof(wantcomp[0])) {
+ comp = wantcomp[(*bucket)++];
+ }
+
+ return comp;
+}
+
/*
* Free and reset our component hash table
*/