1 /*
2  *  QUOTE.C
3  *
4  *  Written on 10-Jul-94 by John Dennis and released to the public domain.
5  *
6  *  Contains routines relevant to detection of quotes and quoting.
7  */
8 
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <time.h>
13 #include <ctype.h>
14 #include "addr.h"
15 #include "nedit.h"
16 #include "memextra.h"
17 #include "strextra.h"
18 #include "mctype.h"
19 #include "msged.h"
20 #include "wrap.h"
21 #include "quote.h"
22 
23 #define TEXTLEN 128
24 #define INPLEN 60
25 
26 /* is the passed line a quote? */
27 
is_quote(char * text)28 int is_quote(char *text)
29 {
30     char *s = text, *c = text;
31 
32     while (*s && s && s - text < 12)
33     {
34         if (*s == '>')
35         {
36             break;
37         }
38         s++;
39     }
40 
41     if (*s != '>')
42     {
43         return FALSE;
44     }
45 
46     while (c && *c && c < s)
47     {
48         switch (*c)
49         {
50         case '<':
51             return FALSE;
52 
53         case ' ':
54         case ':':
55         case '-':
56         case '@':
57             c++;
58             continue;
59 
60         default:
61             if (!m_isalnum(*c))
62             {
63                 return FALSE;
64             }
65             c++;
66             break;
67         }
68     }
69 
70     return TRUE;
71 }
72 
is_same_quote(LINE * l,LINE * o)73 int is_same_quote(LINE * l, LINE * o)
74 {
75     char *s, *c;
76     int lenl, leno;
77 
78     lenl = strlen(l->text);
79     leno = strlen(o->text);
80 
81     if (l->quote && o->quote)
82     {
83         if (lenl >= 12)
84         {
85             s = l->text + 11;
86         }
87         else
88         {
89             s = l->text + lenl - 1;
90         }
91 
92         if (leno >= 12)
93         {
94             c = o->text + 11;
95         }
96         else
97         {
98             c = o->text + leno - 1;
99         }
100 
101         while (*s && *s != '>')
102         {
103             s--;
104         }
105 
106         while (*c && *c != '>')
107         {
108             c--;
109         }
110 
111         if (*s == '>' && *(s + 1))
112         {
113             s++;
114         }
115 
116         if (*c == '>' && *(c + 1))
117         {
118             c++;
119         }
120 
121         if (!strncmpi(l->text, o->text, (size_t) max((s - l->text),
122           c - o->text)))
123         {
124             return TRUE;
125         }
126 
127         return FALSE;
128     }
129 
130     return FALSE;
131 }
132 
is_blank(LINE * l)133 int is_blank(LINE * l)
134 {
135     char *s;
136     int len;
137 
138     if (!l || !l->text || *l->text == '\n' || *l->text == '\0')
139     {
140         return TRUE;
141     }
142 
143     len = strlen(l->text);
144     if (l->quote)
145     {
146         if (len >= 12)
147         {
148             s = l->text + 11;
149         }
150         else
151         {
152             s = l->text + len - 1;
153         }
154 
155         while (*s && *s != '>')
156         {
157             s--;
158         }
159 
160         if (*s == '>' && *(s + 1))
161         {
162             s++;
163         }
164 
165         while (*s && m_isspace(*s))
166         {
167             s++;
168         }
169 
170         if (*s == '\0')
171         {
172             return TRUE;
173         }
174         else
175         {
176             return FALSE;
177         }
178     }
179     else
180     {
181         s = l->text;
182         while (*s && m_isspace(*s))
183         {
184             s++;
185         }
186 
187         if (*s == '\0')
188         {
189             return TRUE;
190         }
191         else
192         {
193             return FALSE;
194         }
195     }
196 }
197 
replace_noise(char * text)198 char *replace_noise(char *text)
199 {
200     char *s = text;
201     char *c;
202 
203     /* replace nasty bits */
204 
205     if (*text == '\01')
206     {
207         *text = '@';
208     }
209 
210     if (!SW->soteot)
211     {
212         if (!strncmp(text, " * Ori", 6))
213         {
214             *(text + 1) = '+';
215         }
216 
217         if (!strncmp(text, "---", 3) && strncmp(text, "----", 4))
218         {
219             *(text + 1) = '+';
220         }
221 
222         if (!strncmp(text, "SEEN-BY:", 8))
223         {
224             *(text + 4) = '+';
225         }
226     }
227 
228     /* strip leading spaces unless hard-quoting */
229 
230     if (!SW->hardquote)
231     {
232         while (*s && m_isspace(*s))
233         {
234             s++;
235         }
236     }
237 
238     if (!*s)
239     {
240         return text;
241     }
242 
243     c = xstrdup(s);
244     release(text);
245 
246     return c;
247 }
248 
249 
makequote(LINE * l,char * isfrom)250 LINE *makequote(LINE * l, char *isfrom)
251 {
252     int i;
253     char *qs;
254     char *s, c;
255     LINE *t, *o;
256     char initial[10];
257     char line2[256];
258 
259     if (l == NULL)
260     {
261         return l;
262     }
263 
264     i = 0;
265     s = isfrom;
266 
267     while (s && *s && i < 10)
268     {
269         while (*s && m_isspace(*s))
270         {
271             s++;
272         }
273 	if (!m_isalnum(*s)) s++; /* mtt */
274         initial[i++] = *s;
275         while (*s && !m_isspace(*s))
276         {
277             s++;
278         }
279     }
280 
281     initial[i] = '\0';
282 
283     s = strchr(ST->quotestr, '&');
284     if (s == NULL)
285     {
286         qs = xstrdup(ST->quotestr);
287     }
288     else
289     {
290         qs = xmalloc(strlen(ST->quotestr) + strlen(initial) + 1);
291         *s = '\0';
292         strcpy(qs, ST->quotestr);
293         strcat(qs, initial);
294         strcat(qs, s + 1);
295         *s = '&';
296     }
297 
298     s = qs;
299     s = strchr(s, '^');
300     while (s != NULL)
301     {
302         if (initial[0])
303         {
304             *s = initial[0];
305         }
306         else
307         {
308             strdel(s, 1);
309         }
310         s = strchr(s, '^');
311     }
312 
313     s = qs;
314     s = strchr(s, '*');
315     while (s != NULL)
316     {
317         if (initial[1])
318         {
319             *s = initial[1];
320         }
321         else
322         {
323             strdel(s, 1);
324         }
325         s = strchr(s, '*');
326     }
327 
328     t = l;
329 
330     while (t)
331     {
332         t->hide = t->block = 0;
333         if (!t->text || strlen(t->text) == 0)
334         {
335             release(t->text);
336             t->text = xstrdup("\n");
337             t = t->next;
338             continue;
339         }
340         if (!t->quote)
341         {
342             if (SW->hardquote)
343             {
344                 wrap(t, 1, maxy, SW->qm - strlen(qs));
345             }
346             if (strchr(t->text, '\n') != NULL)
347             {
348                 /* don't quote a blank line */
349                 if (*t->text == ' ')
350                 {
351                     char *p;
352 
353                     p = t->text;
354                     while (*p == ' ')
355                     {
356                         p++;
357                     }
358                     if (*p == '\n' && *(p + 1) == '\0')
359                     {
360                         strcpy(t->text, "\n");
361                     }
362                 }
363                 if (*t->text != '\n' && *t->text)
364                 {
365                     t->hide = t->block = 0;
366                     t->text = replace_noise(t->text);
367                     sprintf(line2, "%s%s", qs, t->text);
368                     release(t->text);
369                     t->text = xstrdup(line2);
370                     t->quote = 1;
371                 }
372             }
373             else
374             {
375                 if (!SW->hardquote)
376                 {
377                     wrap(t, 1, maxy, SW->qm - strlen(qs));
378                 }
379                 while (t != NULL && strchr(t->text, '\n') == NULL)
380                 {
381                     t->hide = t->block = 0;
382                     t->text = replace_noise(t->text);
383                     sprintf(line2, "%s%s\n", qs, t->text);
384                     release(t->text);
385                     t->text = xstrdup(line2);
386                     t->quote = 1;
387                     t = t->next;
388                 }
389                 continue;
390             }
391         }
392         else
393         {
394             if (SW->qquote)
395             {
396                 s = strchr(t->text, '>');
397                 if (s)
398                 {
399                     if (s - t->text <= 11)
400                     {
401                         c = *s;
402                         *s = '\0';
403                         strcpy(line2, t->text);
404                         strcat(line2, ">");
405                         *s = c;
406                         strcat(line2, s);
407                     }
408                     else
409                     {
410                         strcpy(line2, t->text);
411                     }
412                 }
413                 else
414                 {
415                     strcpy(line2, t->text);
416                 }
417             }
418             else
419             {
420                 if (t->text)
421                 {
422                     strcpy(line2, t->text);
423                 }
424                 else
425                 {
426                     strcpy(line2, "");
427                 }
428             }
429             release(t->text);
430 
431             if (!strchr(line2, '\n'))
432             {
433                 strcat(line2, "\n");
434             }
435 
436             if (*line2 == ' ')
437             {
438                 t->text = xstrdup(line2 + 1);
439             }
440             else
441             {
442                 t->text = xstrdup(line2);
443             }
444         }
445         t = t->next;
446     }
447 
448     xfree(qs);
449 
450     t = l;  /* returns the last line of the msg */
451     while (t->next != NULL)
452     {
453         if (strlen(t->text) > SW->qm)
454         {
455             wrap(t, 1, maxy, SW->qm);
456             t = t->next;
457         }
458         else
459         {
460             t = t->next;
461         }
462     }
463 
464     t = l;
465 
466     while (t)
467     {
468         if (strchr(t->text, '\n') && t->prev && !strchr(t->prev->text, '\n'))
469         {
470             if (t->next && !is_blank(t->next) && is_same_quote(t, t->next))
471             {
472                 *((char *)strchr(t->text, '\n')) = '\0';
473             }
474 
475             wrap(t, 1, maxy, SW->qm);
476             o = t;
477 
478             while (t && !strchr(t->text, '\n'))
479             {
480                 t = t->next;
481             }
482 
483             if (t == o)
484             {
485                 t = t->next;
486             }
487         }
488         else
489         {
490             t = t->next;
491         }
492     }
493 
494     t = l;
495 
496     /* make sure the quotes are all terminated with '\n' */
497 
498     while (t->next)
499     {
500         if (t->text && strlen(t->text) > 1 && *ST->quotestr == ' ' && *(t->text) != ' ')
501         {
502             strcpy(line2, " ");
503             strcat(line2, t->text);
504             xfree(t->text);
505             t->text = xstrdup(line2);
506         }
507         if (t->text && !strchr(t->text, '\n') && t->quote)
508         {
509             strcpy(line2, t->text);
510             strcat(line2, "\n");
511             xfree(t->text);
512             t->text = xstrdup(line2);
513         }
514         t = t->next;
515     }
516 
517     return t;  /* last line of message */
518 }
519