]> diplodocus.org Git - nmh/blobdiff - sbr/fmt_scan.c
Try including termcap.h before curses.h to see if that solves
[nmh] / sbr / fmt_scan.c
index 6cceff3266588ab15cc7b454cca6d34c4c040a29..ab5940ab55e0abde5ddde00c3258b58e28d4db22 100644 (file)
@@ -25,7 +25,6 @@
 #  include <wchar.h>
 #endif
 
-extern int fmt_norm;           /* defined in sbr/fmt_def.c = AD_NAME */
 struct mailname fmt_mnull = { NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0,
                              NULL, NULL };
 
@@ -134,6 +133,7 @@ cptrimmed(char **dest, char **ep, char *str, unsigned int wid, char fill,
     int char_len;      /* bytes in current character */
     int w;
     wchar_t wide_char;
+    char *altstr = NULL;
 #endif
     char *sp;          /* current position in source string */
     char *cp = *dest;  /* current position in destination string */
@@ -154,6 +154,17 @@ cptrimmed(char **dest, char **ep, char *str, unsigned int wid, char fill,
 #ifdef MULTIBYTE_SUPPORT
            char_len = mbtowc(&wide_char, sp, end);
 
+           /*
+            * See the relevant comments in cpstripped() to explain what's
+            * going on here; we want to handle the case where we get
+            * characters that mbtowc() cannot handle
+            */
+
+           if (char_len < 0) {
+               altstr = "?";
+               char_len = mbtowc(&wide_char, altstr, 1);
+           }
+
            if (char_len <= 0)
                break;
 
@@ -196,9 +207,10 @@ cptrimmed(char **dest, char **ep, char *str, unsigned int wid, char fill,
 
 #ifdef MULTIBYTE_SUPPORT
            if (w >= 0 && remaining >= w) {
-               strncpy(cp, sp, char_len);
+               strncpy(cp, altstr ? altstr : sp, char_len);
                cp += char_len;
                remaining -= w;
+               altstr = NULL;
            }
            sp += char_len;
 #else
@@ -239,6 +251,7 @@ cpstripped (char **dest, char **end, char *max, char *str)
 #ifdef MULTIBYTE_SUPPORT
     int char_len, w;
     wchar_t wide_char;
+    char *altstr = NULL;
 #endif /* MULTIBYTE_SUPPORT */
 
     if (!str)
@@ -269,6 +282,19 @@ cpstripped (char **dest, char **end, char *max, char *str)
            *end += char_len - w;
        }
 
+       /*
+        * If mbrtowc() failed, then we have a character that isn't valid
+        * in the current encoding.  Replace it with a '?'.  We do that by
+        * setting the alstr variable to the value of the replacement string;
+        * altstr is used below when the bytes are copied into the output
+        * buffer.
+        */
+
+       if (char_len < 0) {
+           altstr = "?";
+           char_len = mbtowc(&wide_char, altstr, 1);
+       }
+
        if (char_len <= 0 || *dest + char_len > *end)
            break;
 
@@ -293,9 +319,10 @@ cpstripped (char **dest, char **end, char *max, char *str)
        prevCtrl = 0;
 
 #ifdef MULTIBYTE_SUPPORT
-       memcpy(*dest, str, char_len);
+       memcpy(*dest, altstr ? altstr : str, char_len);
        str += char_len;
        *dest += char_len;
+       altstr = NULL;
 #else /* MULTIBYE_SUPPORT */
        *(*dest)++ = *str++
 #endif /* MULTIBYTE_SUPPORT */
@@ -351,7 +378,8 @@ get_x400_comp (char *mbox, char *key, char *buffer, int buffer_len)
 }
 
 struct format *
-fmt_scan (struct format *format, char *scanl, size_t max, int width, int *dat)
+fmt_scan (struct format *format, char *scanl, size_t max, int width, int *dat,
+         struct fmt_callbacks *callbacks)
 {
     char *cp, *ep, *sp;
     char *savestr = NULL, *str = NULL;
@@ -483,10 +511,16 @@ fmt_scan (struct format *format, char *scanl, size_t max, int width, int *dat)
            break;
 
        case FT_DONE:
+           if (callbacks && callbacks->trace_func)
+               callbacks->trace_func(callbacks->trace_context, fmt, value,
+                                     str, scanl);
            goto finished;
 
        case FT_IF_S:
            if (!(value = (str && *str))) {
+               if (callbacks && callbacks->trace_func)
+                   callbacks->trace_func(callbacks->trace_context, fmt, value,
+                                         str, scanl);
                fmt += fmt->f_skip;
                continue;
            }
@@ -494,6 +528,9 @@ fmt_scan (struct format *format, char *scanl, size_t max, int width, int *dat)
 
        case FT_IF_S_NULL:
            if (!(value = (str == NULL || *str == 0))) {
+               if (callbacks && callbacks->trace_func)
+                   callbacks->trace_func(callbacks->trace_context, fmt, value,
+                                         str, scanl);
                fmt += fmt->f_skip;
                continue;
            }
@@ -501,6 +538,9 @@ fmt_scan (struct format *format, char *scanl, size_t max, int width, int *dat)
 
        case FT_IF_V_EQ:
            if (value != fmt->f_value) {
+               if (callbacks && callbacks->trace_func)
+                   callbacks->trace_func(callbacks->trace_context, fmt, value,
+                                         str, scanl);
                fmt += fmt->f_skip;
                continue;
            }
@@ -508,6 +548,9 @@ fmt_scan (struct format *format, char *scanl, size_t max, int width, int *dat)
 
        case FT_IF_V_NE:
            if (value == fmt->f_value) {
+               if (callbacks && callbacks->trace_func)
+                   callbacks->trace_func(callbacks->trace_context, fmt, value,
+                                         str, scanl);
                fmt += fmt->f_skip;
                continue;
            }
@@ -515,6 +558,9 @@ fmt_scan (struct format *format, char *scanl, size_t max, int width, int *dat)
 
        case FT_IF_V_GT:
            if (value <= fmt->f_value) {
+               if (callbacks && callbacks->trace_func)
+                   callbacks->trace_func(callbacks->trace_context, fmt, value,
+                                         str, scanl);
                fmt += fmt->f_skip;
                continue;
            }
@@ -522,6 +568,9 @@ fmt_scan (struct format *format, char *scanl, size_t max, int width, int *dat)
 
        case FT_IF_MATCH:
            if (!(value = (str && match (str, fmt->f_text)))) {
+               if (callbacks && callbacks->trace_func)
+                   callbacks->trace_func(callbacks->trace_context, fmt, value,
+                                         str, scanl);
                fmt += fmt->f_skip;
                continue;
            }
@@ -536,6 +585,9 @@ fmt_scan (struct format *format, char *scanl, size_t max, int width, int *dat)
 
        case FT_IF_AMATCH:
            if (!(value = (str && uprf (str, fmt->f_text)))) {
+               if (callbacks && callbacks->trace_func)
+                   callbacks->trace_func(callbacks->trace_context, fmt, value,
+                                         str, scanl);
                fmt += fmt->f_skip;
                continue;
            }
@@ -566,6 +618,9 @@ fmt_scan (struct format *format, char *scanl, size_t max, int width, int *dat)
            break;
 
        case FT_GOTO:
+           if (callbacks && callbacks->trace_func)
+               callbacks->trace_func(callbacks->trace_context, fmt, value,
+                                     str, scanl);
            fmt += fmt->f_skip;
            continue;
 
@@ -836,32 +891,10 @@ fmt_scan (struct format *format, char *scanl, size_t max, int width, int *dat)
                /* 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;
@@ -898,12 +931,18 @@ fmt_scan (struct format *format, char *scanl, size_t max, int width, int *dat)
 
        case FT_FORMATADDR:
            /* hook for custom address list formatting (see replsbr.c) */
-           str = formataddr (savestr, str);
+           if (callbacks && callbacks->formataddr)
+               str = callbacks->formataddr (savestr, str);
+           else
+               str = formataddr (savestr, str);
            break;
 
        case FT_CONCATADDR:
            /* The same as formataddr, but doesn't do duplicate suppression */
-           str = concataddr (savestr, str);
+           if (callbacks && callbacks->concataddr)
+               str = callbacks->concataddr (savestr, str);
+           else
+               str = concataddr (savestr, str);
            break;
 
        case FT_PUTADDR:
@@ -971,7 +1010,7 @@ fmt_scan (struct format *format, char *scanl, size_t max, int width, int *dat)
            if (comp->c_mn != &fmt_mnull)
                mnfree (comp->c_mn);
            if ((sp = comp->c_text) && (sp = getname(sp)) &&
-               (mn = getm (sp, NULL, 0, fmt_norm, NULL))) {
+               (mn = getm (sp, NULL, 0, NULL, 0))) {
                comp->c_mn = mn;
                while (getname(""))
                    ;
@@ -993,7 +1032,7 @@ fmt_scan (struct format *format, char *scanl, size_t max, int width, int *dat)
            if (comp->c_mn != &fmt_mnull)
                mnfree (comp->c_mn);
            if ((sp = comp->c_text) && (sp = getname(sp)) &&
-               (mn = getm (sp, NULL, 0, AD_NAME, NULL))) {
+               (mn = getm (sp, NULL, 0, NULL, 0))) {
                comp->c_mn = mn;
                if (ismymbox(mn))
                    comp->c_flags |= CF_TRUE;
@@ -1001,7 +1040,7 @@ fmt_scan (struct format *format, char *scanl, size_t max, int width, int *dat)
                    comp->c_flags &= ~CF_TRUE;
                while ((sp = getname(sp)))
                    if ((comp->c_flags & CF_TRUE) == 0 &&
-                       (mn = getm (sp, NULL, 0, AD_NAME, NULL)))
+                       (mn = getm (sp, NULL, 0, NULL, 0)))
                        if (ismymbox(mn))
                            comp->c_flags |= CF_TRUE;
            } else {
@@ -1015,6 +1054,14 @@ fmt_scan (struct format *format, char *scanl, size_t max, int width, int *dat)
            }
            break;
        }
+
+       /*
+        * Call our tracing callback function, if one was supplied
+        */
+
+       if (callbacks && callbacks->trace_func)
+           callbacks->trace_func(callbacks->trace_context, fmt, value,
+                                 str, scanl);
        fmt++;
     }
 
@@ -1022,6 +1069,9 @@ fmt_scan (struct format *format, char *scanl, size_t max, int width, int *dat)
     while (fmt->f_type != FT_DONE) {
        if (fmt->f_type == FT_LS_LIT) {
            str = fmt->f_text;
+           if (callbacks && callbacks->trace_func)
+               callbacks->trace_func(callbacks->trace_context, fmt, value,
+                                     str, scanl);
        } else if (fmt->f_type == FT_STRLITZ) {
            /* Don't want to emit part of an escape sequence.  So if
               there isn't enough room in the buffer for the entire
@@ -1030,6 +1080,9 @@ fmt_scan (struct format *format, char *scanl, size_t max, int width, int *dat)
            if (cp - scanl + strlen (str) + 1 < max) {
                for (sp = str; *sp; *cp++ = *sp++) continue;
            }
+           if (callbacks && callbacks->trace_func)
+               callbacks->trace_func(callbacks->trace_context, fmt, value,
+                                     str, scanl);
        }
        fmt++;
     }