2 * Parts were written/modified by:
3 * Andreas Krennmair <ak@synflood.at>
4 * Peter J. Holzer <hjp@hjp.net>
5 * Rocco Rutte <pdmef@cs.tu-berlin.de>
7 * This file is part of mutt-ng, see http://www.muttng.org/.
8 * It's licensed under the GNU General Public License,
9 * please see the file GPL in the top level source directory.
24 #include "mutt_curses.h"
33 #include "lib/debug.h"
37 static int get_quote_level (char *line)
41 for (quoted = 0; line[quoted] == '>'; quoted++);
45 static void print_flowed_line (char *line, STATE * s, int ql) {
48 int len = str_len (line);
51 if (MaxLineLength > 0) {
52 width = MaxLineLength - WrapMargin - ql - 1;
53 if (!(s->flags & M_REPLYING) && option (OPTSTUFFQUOTED))
56 width = MaxLineLength;
59 if (option (OPTMBOXPANE))
60 width = COLS - SidebarWidth - WrapMargin - ql - 1;
62 width = COLS - WrapMargin - ql - 1;
64 if (!(s->flags & M_REPLYING) && option (OPTSTUFFQUOTED))
70 if (str_len (line) == 0) {
71 if (option (OPTQUOTEEMPTY)) {
73 state_puts(s->prefix,s);
74 for (i=0;i<ql;++i) state_putc('>',s);
75 if (!(s->flags & M_REPLYING) && option(OPTSTUFFQUOTED))
85 for (; oldpos < line + len; pos += width) {
86 /* only search a new position when we're not over
87 * the end of the string w/ pos */
88 if (pos < line + len) {
90 debug_print (4, ("f=f: found space directly at width\n"));
96 debug_print (4, ("f=f: need to search for space\n"));
98 while (pos >= oldpos && *pos != ' ') {
102 debug_print (4, ("f=f: no space found while searching "
103 "to left; going right\n"));
105 while (pos < line + len && *pos && *pos != ' ') {
108 debug_print (4, ("f=f: found space at pos %d\n", pos-line));
110 debug_print (4, ("f=f: found space while searching to left\n"));
117 debug_print (4, ("f=f: line completely fits on screen\n"));
120 state_puts (s->prefix, s);
122 for (i = 0; i < ql; ++i)
124 if (!(s->flags & M_REPLYING) && option (OPTSTUFFQUOTED) &&
125 (ql > 0 || s->prefix))
127 state_puts (oldpos, s);
128 /* fprintf(stderr,"print_flowed_line: `%s'\n",oldpos); */
129 if (pos < line + len)
131 state_putc ('\n', s);
136 int rfc3676_handler (BODY * a, STATE * s) {
137 int bytes = a->length;
138 char buf[LONG_STRING];
139 char *curline = str_dup ("");
141 unsigned int curline_len = 1,
142 quotelevel = 0, newql = 0;
143 int buf_off, buf_len;
144 int delsp = 0, fixed = 0;
146 /* respect DelSP of RfC3676 only with f=f parts */
147 if ((t = (char*) mutt_get_parameter ("delsp", a->parameter))) {
148 delsp = str_len (t) == 3 && ascii_strncasecmp (t, "yes", 3) == 0;
152 debug_print (2, ("f=f: DelSp: %s\n", delsp ? "yes" : "no"));
154 while (bytes > 0 && fgets (buf, sizeof (buf), s->fpin)) {
156 buf_len = str_len (buf);
159 newql = get_quote_level (buf);
161 /* a change of quoting level in a paragraph - shouldn't happen,
162 * but has to be handled - see RFC 3676, sec. 4.5.
164 if (newql != quotelevel && curline && *curline) {
165 print_flowed_line (curline, s, quotelevel);
171 /* XXX - If a line is longer than buf (shouldn't happen), it is split.
172 * This will almost always cause an unintended line break, and
173 * possibly a change in quoting level. But that's better than not
174 * displaying it at all.
176 if ((t = strrchr (buf, '\n')) || (t = strrchr (buf, '\r'))) {
182 /* respect space-stuffing */
183 if (buf[buf_off] == ' ')
186 /* for DelSp=yes, we need to strip one SP prior to CRLF
187 * which may make the line look like fixed although it wasn't
188 * so keep this in mind for later processing */
189 fixed = buf_len == 0 || buf[buf_len - 1] != ' ' ||
190 (strcmp(buf + buf_off, "-- ") == 0);
192 if (delsp && buf_len >= 1 && buf[buf_len-1] == ' ')
193 buf[--buf_len] = '\0';
195 /* signature separator also flushes the previous paragraph */
196 if (strcmp(buf + buf_off, "-- ") == 0 && curline && *curline) {
197 print_flowed_line (curline, s, quotelevel);
202 mem_realloc (&curline, curline_len + buf_len - buf_off);
203 strcpy (curline + curline_len - 1, buf + buf_off);
204 curline_len += buf_len - buf_off;
206 /* if this was a fixed line the paragraph is finished */
208 print_flowed_line (curline, s, quotelevel);
218 void rfc3676_space_stuff (HEADER* hdr) {
222 unsigned char c = '\0';
224 FILE* in = NULL, *out = NULL;
225 char buf[LONG_STRING];
226 char tmpfile[_POSIX_PATH_MAX];
228 if (!hdr || !hdr->content || !hdr->content->filename)
231 debug_print (2, ("f=f: postprocess %s\n", hdr->content->filename));
232 if ((in = safe_fopen (hdr->content->filename, "r")) == NULL)
234 mutt_mktemp (tmpfile);
235 if ((out = safe_fopen (tmpfile, "w+")) == NULL) {
240 while (fgets (buf, sizeof (buf), in)) {
241 if (ascii_strncmp ("From ", buf, 4) == 0 || buf[0] == ' ') {
250 debug_print (4, ("f=f: line %d needs space-stuffing: '%s'\n",
260 mutt_set_mtime (hdr->content->filename, tmpfile);
261 unlink (hdr->content->filename);
262 str_replace (&hdr->content->filename, tmpfile);