Fix compilation warnings in mutt_idna.c
[apps/madmutt.git] / rfc3676.c
index 3869b33..c194540 100644 (file)
--- a/rfc3676.c
+++ b/rfc3676.c
 #include <sys/wait.h>
 #include <sys/stat.h>
 
+#include <lib-lib/mem.h>
+#include <lib-lib/str.h>
+#include <lib-lib/ascii.h>
+#include <lib-lib/macros.h>
+#include <lib-lib/file.h>
+
 #include "mutt.h"
 #include "mutt_curses.h"
-#include "ascii.h"
 #include "handler.h"
 #include "state.h"
 #include "lib.h"
 
-#include "lib/mem.h"
-#include "lib/intl.h"
-#include "lib/str.h"
 #include "lib/debug.h"
 
-typedef int handler_f (BODY *, STATE *);
-typedef handler_f *handler_t;
-
 #define FLOWED_MAX 77
 
 static int get_quote_level (char *line)
@@ -45,17 +44,15 @@ static int get_quote_level (char *line)
   return quoted;
 }
 
-static void print_flowed_line (char *line, STATE * s,
-                               int ql, int delsp,
-                               int* spaces, int space_len) {
+static void print_flowed_line (char *line, STATE * s, int ql) {
   int width;
   char *pos, *oldpos;
-  int len = str_len (line);
+  int len = m_strlen(line);
   int i;
 
   if (MaxLineLength > 0) {
     width = MaxLineLength - WrapMargin - ql - 1;
-    if (option (OPTSTUFFQUOTED))
+    if (!(s->flags & M_REPLYING) && option (OPTSTUFFQUOTED))
       --width;
     if (width < 0)
       width = MaxLineLength;
@@ -66,18 +63,18 @@ static void print_flowed_line (char *line, STATE * s,
     else
       width = COLS - WrapMargin - ql - 1;
 
-    if (option (OPTSTUFFQUOTED))
+    if (!(s->flags & M_REPLYING) && option (OPTSTUFFQUOTED))
       --width;
     if (width < 0)
       width = COLS;
   }
 
-  if (str_len (line) == 0) {
-    if (option (OPTQUOTEEMPTY)) {
+  if (m_strlen(line) == 0) {
+    if (!(s->flags & M_REPLYING) || option (OPTQUOTEEMPTY)) {
       if (s->prefix)
         state_puts(s->prefix,s);
       for (i=0;i<ql;++i) state_putc('>',s);
-      if (option(OPTSTUFFQUOTED))
+      if (!(s->flags & M_REPLYING) && option(OPTSTUFFQUOTED))
         state_putc(' ',s);
     }
     state_putc('\n',s);
@@ -91,60 +88,45 @@ static void print_flowed_line (char *line, STATE * s,
     /* only search a new position when we're not over
      * the end of the string w/ pos */
     if (pos < line + len) {
-      /* fprintf(stderr,"if 1\n"); */
       if (*pos == ' ') {
-        /* fprintf(stderr,"if 2: good luck! found a space\n"); */
+        debug_print (4, ("f=f: found space directly at width\n"));
         *pos = '\0';
         ++pos;
       }
       else {
-        /* fprintf(stderr,"if 2: else\n"); */
         char *save = pos;
+        debug_print (4, ("f=f: need to search for space\n"));
 
         while (pos >= oldpos && *pos != ' ') {
-          /* fprintf(stderr,"pos(%p) > oldpos(%p)\n",pos,oldpos); */
           --pos;
         }
         if (pos < oldpos) {
-          /* fprintf(stderr,"wow, no space found,
-           * searching the other direction\n"); */
+          debug_print (4, ("f=f: no space found while searching "
+                           "to left; going right\n"));
           pos = save;
           while (pos < line + len && *pos && *pos != ' ') {
-            /* fprintf(stderr,"pos(%p) < line+len(%p)\n",pos,line+len); */
             ++pos;
           }
-          /* fprintf(stderr,"found a space pos = %p\n",pos); */
+          debug_print (4, ("f=f: found space at pos %d\n", pos-line));
+        } else {
+          debug_print (4, ("f=f: found space while searching to left\n"));
         }
         *pos = '\0';
         ++pos;
       }
     }
     else {
-      /* fprintf(stderr,"if 1 else\n"); */
+      debug_print (4, ("f=f: line completely fits on screen\n"));
     }
     if (s->prefix)
       state_puts (s->prefix, s);
 
     for (i = 0; i < ql; ++i)
       state_putc ('>', s);
-    if (option (OPTSTUFFQUOTED) && (ql > 0 || s->prefix))
+    if (!(s->flags & M_REPLYING) && option (OPTSTUFFQUOTED) &&
+        (ql > 0 || s->prefix))
       state_putc (' ', s);
-
-    if (delsp && spaces && space_len > 0) {
-      /* here, we need to character-wise step through the line
-       * to eliminate all spaces which were trailing due to DelSp */
-      for (i = 0; i < str_len (oldpos); i++) {
-        if (oldpos[i] == ' ' && spaces[&(oldpos[i])-line] != 0) {
-          debug_print (4, ("DelSp: spaces[%d] forces space removal\n",
-                           &(oldpos[i])-line));
-          continue;
-        }
-        /* print space at oldpos[i] if it was non-trailing */
-        state_putc (oldpos[i], s);
-      }
-    } else
-      /* for no DelSp, just do whole line as per usual */
-      state_puts (oldpos, s);
+    state_puts (oldpos, s);
     /* fprintf(stderr,"print_flowed_line: `%s'\n",oldpos); */
     if (pos < line + len)
       state_putc (' ', s);
@@ -156,24 +138,26 @@ static void print_flowed_line (char *line, STATE * s,
 int rfc3676_handler (BODY * a, STATE * s) {
   int bytes = a->length;
   char buf[LONG_STRING];
-  char *curline = str_dup ("");
+  char *curline = p_new(char, 1);
   char *t = NULL;
-  unsigned int curline_len = 1, space_len = 1,
+  unsigned int curline_len = 1,
                quotelevel = 0, newql = 0;
   int buf_off, buf_len;
-  int delsp = 0;
-  int* spaces = NULL;
+  int delsp = 0, fixed = 0;
+
+  *curline='\0';
 
   /* respect DelSP of RfC3676 only with f=f parts */
   if ((t = (char*) mutt_get_parameter ("delsp", a->parameter))) {
-    delsp = str_len (t) == 3 && ascii_strncasecmp (t, "yes", 3) == 0;
+    delsp = m_strlen(t) == 3 && ascii_strncasecmp (t, "yes", 3) == 0;
     t = NULL;
   }
 
-  debug_print (2, ("DelSp: %s\n", delsp ? "yes" : "no"));
+  debug_print (2, ("f=f: DelSp: %s\n", delsp ? "yes" : "no"));
 
   while (bytes > 0 && fgets (buf, sizeof (buf), s->fpin)) {
-    buf_len = str_len (buf);
+
+    buf_len = m_strlen(buf);
     bytes -= buf_len;
 
     newql = get_quote_level (buf);
@@ -182,10 +166,9 @@ int rfc3676_handler (BODY * a, STATE * s) {
      * but has to be handled - see RFC 3676, sec. 4.5.
      */
     if (newql != quotelevel && curline && *curline) {
-      print_flowed_line (curline, s, quotelevel, delsp, spaces, space_len);
+      print_flowed_line (curline, s, quotelevel);
       *curline = '\0';
       curline_len = 1;
-      space_len = 0;
     }
     quotelevel = newql;
 
@@ -194,52 +177,100 @@ int rfc3676_handler (BODY * a, STATE * s) {
      * possibly a change in quoting level. But that's better than not
      * displaying it at all.
      */
-    if ((t = strrchr (buf, '\n')) || (t = strrchr (buf, '\r'))) {
+    if ((t = strrchr (buf, '\r')) || (t = strrchr (buf, '\n'))) {
       *t = '\0';
       buf_len = t - buf;
     }
+
     buf_off = newql;
     /* respect space-stuffing */
     if (buf[buf_off] == ' ')
       buf_off++;
 
+    /* for DelSp=yes, we need to strip one SP prior to CRLF
+     * which may make the line look like fixed although it wasn't
+     * so keep this in mind for later processing */
+    fixed = buf_len == 0 || buf[buf_len - 1] != ' ' ||
+            (strcmp(buf + buf_off, "-- ") == 0);
+
+    if (delsp && buf_len >= 1 && buf[buf_len-1] == ' ')
+      buf[--buf_len] = '\0';
+
+    /* we're here when last space removed 'cause of DelSp was
+     * the last space and there isn't more -> done */
+    if ((buf_len - buf_off) < 0) {
+      print_flowed_line (curline, s, quotelevel);
+      *curline = '\0';
+      curline_len = 1;
+      continue;
+    }
+
     /* signature separator also flushes the previous paragraph */
     if (strcmp(buf + buf_off, "-- ") == 0 && curline && *curline) {
-      print_flowed_line (curline, s, quotelevel, delsp, spaces, space_len);
+      print_flowed_line (curline, s, quotelevel);
       *curline = '\0';
       curline_len = 1;
-      space_len = 0;
     }
 
-    mem_realloc (&curline, curline_len + buf_len - buf_off);
-    mem_realloc (&spaces, (curline_len + buf_len - buf_off)*sizeof (int));
+    p_realloc(&curline, curline_len + buf_len - buf_off);
     strcpy (curline + curline_len - 1, buf + buf_off);
-    memset (&spaces[space_len], 0, (buf_len - buf_off)*sizeof (int));
     curline_len += buf_len - buf_off;
-    space_len += buf_len - buf_off;
 
     /* if this was a fixed line the paragraph is finished */
-    if (buf_len == 0 || buf[buf_len - 1] != ' ' || strcmp(buf + buf_off, "-- ") == 0) {
-      print_flowed_line (curline, s, quotelevel, delsp, spaces, space_len);
+    if (fixed) {
+      print_flowed_line (curline, s, quotelevel);
       *curline = '\0';
       curline_len = 1;
-      space_len = 0;
-    } else {
-      /* if last line we appended had a space and we have DelSp=yes,
-       * get a 1 into spaces array at proper position so that
-       * print_flowed_line() can handle it; don't kill the space
-       * right here 'cause we maybe need soft linebreaks to search for break
-       */
-      if (delsp && curline && *curline && curline_len-2 >= 0 &&
-          curline[curline_len-2] == ' ') {
-        debug_print (4, ("DelSp: marking spaces[%d] for later removal\n",
-                         curline_len-2));
-        spaces[curline_len-2] = 1;
-      }
     }
 
   }
-  mem_free (&spaces);
-  mem_free (&curline);
+  p_delete(&curline);
   return (0);
 }
+
+void rfc3676_space_stuff (HEADER* hdr) {
+#if DEBUG
+  int lc = 0;
+  size_t len = 0;
+  unsigned char c = '\0';
+#endif
+  FILE* in = NULL, *out = NULL;
+  char buf[LONG_STRING];
+  char tmpfile[_POSIX_PATH_MAX];
+
+  if (!hdr || !hdr->content || !hdr->content->filename)
+    return;
+
+  debug_print (2, ("f=f: postprocess %s\n", hdr->content->filename));
+  if ((in = safe_fopen (hdr->content->filename, "r")) == NULL)
+    return;
+  mutt_mktemp (tmpfile);
+  if ((out = safe_fopen (tmpfile, "w+")) == NULL) {
+    fclose (in);
+    return;
+  }
+
+  while (fgets (buf, sizeof (buf), in)) {
+    if (ascii_strncmp ("From ", buf, 4) == 0 || buf[0] == ' ') {
+      fputc (' ', out);
+#if DEBUG
+      lc++;
+      len = m_strlen(buf);
+      if (len > 0) {
+        c = buf[len-1];
+        buf[len-1] = '\0';
+      }
+      debug_print (4, ("f=f: line %d needs space-stuffing: '%s'\n",
+                       lc, buf));
+      if (len > 0)
+        buf[len-1] = c;
+#endif
+    }
+    fputs (buf, out);
+  }
+  fclose (in);
+  fclose (out);
+  mutt_set_mtime (hdr->content->filename, tmpfile);
+  unlink (hdr->content->filename);
+  m_strreplace(&hdr->content->filename, tmpfile);
+}