]> diplodocus.org Git - nmh/blobdiff - sbr/fmt_compile.c
Add a new (but incomplete) test for mhbuild's new functionality.
[nmh] / sbr / fmt_compile.c
index 4ae85bc96e8def9e8ef1760a2e3a0945e8715f69..970e71e5abd3d489bd7f66ff765c32b37670bcd8 100644 (file)
@@ -49,9 +49,6 @@
 #include <h/mts.h>
 #include <h/utils.h>
 
-#include <curses.h>
-#include <term.h>
-
 #ifdef HAVE_SYS_TIME_H
 # include <sys/time.h>
 #endif
@@ -69,10 +66,6 @@ static struct comp *cm;                      /* most recent comp ref  */
 static struct ftable *ftbl;            /* most recent func ref  */
 static int ncomp;
 static int infunction;                 /* function nesting cnt  */
-static int termstatus = 0;             /* 0=uninit,1=ok,-1=fail */
-static char *termcbuf = NULL;          /* Capability output str */
-static char *termcbufp = NULL;         /* Capability buf ptr    */
-static size_t termcbufsz = 0;          /* Size of termcbuf      */
 
 extern struct mailname fmt_mnull;
 
@@ -91,7 +84,11 @@ extern struct mailname fmt_mnull;
 #define TF_LMBOX   11       /* special - get full local mailbox   */
 #define TF_BOLD    12      /* special - enter terminal bold mode */
 #define TF_UNDERLN 13       /* special - enter underline mode     */
-#define TF_RESET   14       /* special - reset terminal modes     */
+#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
@@ -110,7 +107,9 @@ extern struct mailname fmt_mnull;
  *         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.
@@ -227,11 +226,43 @@ static struct ftable functable[] = {
 
      { "bold",       TF_BOLD,  FT_LS_LIT,      0,              TFL_PUTS },
      { "underline",  TF_UNDERLN,FT_LS_LIT,     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
@@ -302,9 +333,6 @@ static char *do_loop(char *);
 static char *do_if(char *);
 static void free_component(struct comp *);
 static void free_comptable(void);
-static void initialize_terminfo(void);
-static void get_term_stringcap(struct ftable *, char *);
-static int termbytes(int);
 
 /*
  * Lookup a function name in the functable
@@ -336,11 +364,7 @@ compile_error(char *str, char *cp)
     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] = '_';
     }
 
@@ -649,16 +673,60 @@ do_func(char *sp)
        break;
 
     case TF_BOLD:
-       get_term_stringcap(t, "bold");
+       LS(t->f_type, get_term_stringcap("bold"));
        break;
 
     case TF_UNDERLN:
-       get_term_stringcap(t, "smul");
+       LS(t->f_type, get_term_stringcap("smul"));
+       break;
+
+    case TF_STNDOUT:
+       LS(t->f_type, get_term_stringcap("smso"));
        break;
 
     case TF_RESET:
-       get_term_stringcap(t, "sgr0");
+       LS(t->f_type, get_term_stringcap("sgr0"));
+       break;
+
+    case TF_HASCLR:
+       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));
@@ -1063,101 +1131,3 @@ free_component(struct comp *cm)
        free(cm);
     }
 }
-
-/*
- * These functions handles the case of outputting terminal strings depending
- * on the terminfo setting.
- */
-
-/*
- * We should only be called if we haven't yet called setupterm()
- */
-
-void
-initialize_terminfo(void)
-{
-    int errret, rc;
-
-    rc = setupterm(NULL, fileno(stdout), &errret);
-
-    if (rc != 0 || errret != 1)
-       termstatus = -1;
-    else
-       termstatus = 1;
-}
-
-/*
- * Place the results of the specified string entry into the str register.
- *
- * Arguments are:
- *
- * t   - Pointer to instruction table entry (used to create fmt instruction)
- * cap - Name of terminfo capability to insert (e.g., "bold", or "sgr0").
- *
- * This ended up being more complicated than I hoped.  You need to fetch the
- * entry via tigetstr(), but there MAY be a padding format embedded in what
- * gets returned by tigetstr(), so you have to run it through tputs().
- * And of course tputs() is designed to output to a terminal, so you have
- * capture every byte output by the tputs() callback to get the final
- * string to write to the format engine.
- *
- * If padding bytes are NULs that will be a problem for us, but some quick
- * experimentation suggests that padding bytes are mostly a non-issue anymore.
- * If they still crop up we'll have to figure out how to deal with them.
- */
-
-void
-get_term_stringcap(struct ftable *t, char *cap)
-{
-    char *parm;
-
-    /*
-     * Common to all functions; initialize the termcap if we need it.
-     * If it didn't initialize successfully, return silently
-     */
-
-    if (termstatus == 0)
-       initialize_terminfo();
-
-    if (termstatus == -1)
-       return;
-
-    parm = tigetstr(cap);
-
-    if (parm == (char *) -1 || parm == NULL) {
-       return;
-    }
-
-    termcbufp = termcbuf;
-
-    tputs(parm, 1, termbytes);
-
-    termcbufp = '\0';
-
-    LS(t->f_type, termcbuf);
-}
-
-/*
- * Store a sequence of characters in our local buffer
- */
-
-static int
-termbytes(int c)
-{
-    size_t offset;
-
-    /*
-     * Bump up the buffer size if we've reached the end (leave room for
-     * a trailing NUL)
-     */
-
-    if ((offset = termcbufp - termcbuf) - 1 >= termcbufsz) {
-        termcbufsz += 64;
-       termcbuf = mh_xrealloc(termcbuf, termcbufsz);
-       termcbufp = termcbuf + offset;
-    }
-
-    *termcbufp++ = c;
-
-    return 0;
-}