Use selected text on reply/forward.
[claws.git] / src / quote_fmt_parse.y
1 %{
2
3 #include "defs.h"
4
5 #include <glib.h>
6 #include <ctype.h>
7
8 #include "procmsg.h"
9 #include "procmime.h"
10 #include "utils.h"
11 #include "intl.h"
12
13 #include "quote_fmt.h"
14 #include "quote_fmt_lex.h"
15
16 /* decl */
17 /*
18 flex quote_fmt.l
19 bison -p quote_fmt quote_fmt.y
20 */
21
22 int yylex(void);
23
24 static MsgInfo *msginfo = NULL;
25 static gboolean *visible = NULL;
26 static gchar *seltext = NULL;
27 static gint maxsize = 0;
28 static gint stacksize = 0;
29
30 static gchar *buffer = NULL;
31 static gint bufmax = 0;
32 static gint bufsize = 0;
33 static gchar *quote_str = NULL;
34 static gint error = 0;
35
36 static void add_visibility(gboolean val)
37 {
38         stacksize++;
39         if (maxsize < stacksize) {
40                 maxsize += 128;
41                 visible = g_realloc(visible, maxsize * sizeof(gboolean));
42                 if (visible == NULL)
43                         maxsize = 0;
44         }
45
46         visible[stacksize - 1] = val;
47 }
48
49 static void remove_visibility(void)
50 {
51         stacksize--;
52 }
53
54 static void add_buffer(gchar *s)
55 {
56         gint len;
57
58         len = strlen(s);
59         if (bufsize + len + 1 > bufmax) {
60                 if (bufmax == 0)
61                         bufmax = 128;
62                 while (bufsize + len + 1 > bufmax)
63                         bufmax *= 2;
64                 buffer = g_realloc(buffer, bufmax);
65         }
66         strcpy(buffer + bufsize, s);
67         bufsize += len;
68 }
69
70 static void flush_buffer(void)
71 {
72         if (buffer != NULL)
73                 *buffer = '\0';
74         bufsize = 0;
75 }
76
77 gchar *quote_fmt_get_buffer(void)
78 {
79         if (error != 0)
80                 return NULL;
81         else
82                 return buffer;
83 }
84
85 #define INSERT(buf) \
86         if (stacksize != 0 && visible[stacksize - 1]) \
87                 add_buffer(buf)
88
89 #define INSERT_CHARACTER(chr) \
90         if (stacksize != 0 && visible[stacksize - 1]) { \
91                 gchar tmp[2]; \
92                 tmp[0] = (chr); \
93                 tmp[1] = '\0'; \
94                 add_buffer(tmp); \
95         }
96
97 void quote_fmt_init(MsgInfo *info, gchar *my_quote_str,
98                     const gchar *selectiontext)
99 {
100         quote_str = my_quote_str;
101         msginfo = info;
102         seltext = (gchar *) selectiontext;
103         stacksize = 0;
104         add_visibility(TRUE);
105         if (buffer != NULL)
106                 *buffer = 0;
107         bufsize = 0;
108         error = 0;
109 }
110
111 void quote_fmterror(char *str)
112 {
113         g_warning(_("Error: %s\n"), str);
114         error = 1;
115 }
116
117 int quote_fmtwrap(void)
118 {
119         return 1;
120 }
121
122 static int isseparator(char ch)
123 {
124         return isspace(ch) || ch == '.' || ch == '-';
125 }
126 %}
127
128 %union {
129         char chr;
130 }
131
132 %token SHOW_NEWSGROUPS
133 %token SHOW_DATE SHOW_FROM SHOW_FULLNAME SHOW_FIRST_NAME
134 %token SHOW_SENDER_INITIAL SHOW_SUBJECT SHOW_TO SHOW_MESSAGEID
135 %token SHOW_PERCENT SHOW_CC SHOW_REFERENCES SHOW_MESSAGE
136 %token SHOW_QUOTED_MESSAGE SHOW_BACKSLASH SHOW_TAB
137 %token SHOW_QUOTED_MESSAGE_NO_SIGNATURE SHOW_MESSAGE_NO_SIGNATURE
138 %token SHOW_EOL SHOW_QUESTION_MARK SHOW_OPARENT SHOW_CPARENT
139 %token QUERY_DATE QUERY_FROM
140 %token QUERY_FULLNAME QUERY_SUBJECT QUERY_TO QUERY_NEWSGROUPS
141 %token QUERY_MESSAGEID QUERY_CC QUERY_REFERENCES
142 %token OPARENT CPARENT
143 %token CHARACTER
144
145 %start quote_fmt
146
147 %token <chr> CHARACTER
148 %type <chr> character
149
150 %%
151
152 quote_fmt:
153         character_or_special_or_query_list;
154
155 character_or_special_or_query_list:
156         character_or_special_or_query character_or_special_or_query_list
157         | character_or_special_or_query ;
158
159 character_or_special_or_query:
160         special ;
161         | character
162         {
163                 INSERT_CHARACTER($1);
164         }
165         | query ;
166
167
168 character:
169         CHARACTER
170         ;
171
172 special:
173         SHOW_NEWSGROUPS
174         {
175                 if (msginfo->newsgroups)
176                         INSERT(msginfo->newsgroups);
177         }
178         | SHOW_DATE
179         {
180                 if (msginfo->date)
181                         INSERT(msginfo->date);
182         }
183         | SHOW_FROM
184         {
185                 if (msginfo->from)
186                         INSERT(msginfo->from);
187         }
188         | SHOW_FULLNAME
189         {
190                 if (msginfo->fromname)
191                         INSERT(msginfo->fromname);
192         }
193         | SHOW_FIRST_NAME
194         {
195                 if (msginfo->fromname) {
196                         gchar *p;
197                         gchar *str;
198
199                         str = alloca(strlen(msginfo->fromname) + 1);
200                         if (str != NULL) {
201                                 strcpy(str, msginfo->fromname);
202                                 p = str;
203                                 while (*p && !isspace(*p)) p++;
204                                 *p = '\0';
205                                 INSERT(str);
206                         }
207                 }
208         }
209         | SHOW_SENDER_INITIAL
210         {
211 #define MAX_SENDER_INITIAL 20
212                 if (msginfo->fromname) {
213                         gchar tmp[MAX_SENDER_INITIAL];
214                         gchar *p;
215                         gchar *cur;
216                         gint len = 0;
217
218                         p = msginfo->fromname;
219                         cur = tmp;
220                         while (*p) {
221                                 if (*p && isalnum(*p)) {
222                                         *cur = toupper(*p);
223                                                 cur++;
224                                         len++;
225                                         if (len >= MAX_SENDER_INITIAL - 1)
226                                                 break;
227                                 } else
228                                         break;
229                                 while (*p && !isseparator(*p)) p++;
230                                 while (*p && isseparator(*p)) p++;
231                         }
232                         *cur = '\0';
233                         INSERT(tmp);
234                 }
235         }
236         | SHOW_SUBJECT
237         {
238                 if (msginfo->subject)
239                         INSERT(msginfo->subject);
240         }
241         | SHOW_TO
242         {
243                 if (msginfo->to)
244                         INSERT(msginfo->to);
245         }
246         | SHOW_MESSAGEID
247         {
248                 if (msginfo->msgid)
249                         INSERT(msginfo->msgid);
250         }
251         | SHOW_PERCENT
252         {
253                 INSERT("%");
254         }
255         | SHOW_CC
256         {
257                 if (msginfo->cc)
258                         INSERT(msginfo->cc);
259         }
260         | SHOW_REFERENCES
261         {
262                 /* if (msginfo->references)
263                         INSERT(msginfo->references); */
264         }
265         | SHOW_MESSAGE
266         {
267                 if (seltext) {
268                         INSERT(seltext);
269                 }
270                 else if (msginfo->folder) {
271                         gchar buf[BUFFSIZE];
272                         FILE *fp;
273
274                         if ((fp = procmime_get_first_text_content(msginfo))
275                             == NULL)
276                                 g_warning(_("Can't get text part\n"));
277                         else {
278                                 while (fgets(buf, sizeof(buf), fp) != NULL) {
279                                         strcrchomp(buf);
280                                         INSERT(buf);
281                                 }
282                                 fclose(fp);
283                         }
284                 }
285         }
286         | SHOW_QUOTED_MESSAGE
287         {
288                 gchar *tmp_file = NULL;
289
290                 if (seltext)
291                         tmp_file = write_buffer_to_file(seltext,
292                                                         strlen(seltext));
293
294                 if (msginfo->folder || tmp_file) {
295                         gchar buf[BUFFSIZE];
296                         FILE *fp;
297
298                         if (tmp_file)
299                                 fp = fopen(tmp_file, "r");
300                         else
301                                 fp = procmime_get_first_text_content(msginfo);
302
303                         if (fp == NULL)
304                                 g_warning(_("Can't get text part\n"));
305                         else {
306                                 while (fgets(buf, sizeof(buf), fp) != NULL) {
307                                         strcrchomp(buf);
308                                         if (quote_str)
309                                                 INSERT(quote_str);
310                                         INSERT(buf);
311                                 }
312                                 fclose(fp);
313                         }
314                 }
315
316                 if (tmp_file)
317                         unlink(tmp_file);
318         }
319         | SHOW_MESSAGE_NO_SIGNATURE
320         {
321                 gchar *tmp_file = NULL;
322
323                 if (seltext)
324                         tmp_file = write_buffer_to_file(seltext,
325                                                         strlen(seltext));
326
327                 if (msginfo->folder) {
328                         gchar buf[BUFFSIZE];
329                         FILE *fp;
330
331                         if (tmp_file)
332                                 fp = fopen(tmp_file, "r");
333                         else
334                                 fp = procmime_get_first_text_content(msginfo);
335
336                         if (fp == NULL)
337                                 g_warning(_("Can't get text part\n"));
338                         else {
339                                 while (fgets(buf, sizeof(buf), fp) != NULL) {
340                                         strcrchomp(buf);
341                                         if (strncmp(buf, "-- ", 3) == 0)
342                                                 break;
343                                         INSERT(buf);
344                                 }
345                                 fclose(fp);
346                         }
347                 }
348
349                 if (tmp_file)
350                         unlink(tmp_file);
351         }
352         | SHOW_QUOTED_MESSAGE_NO_SIGNATURE
353         {
354                 gchar *tmp_file = NULL;
355
356                 if (seltext)
357                         tmp_file = write_buffer_to_file(seltext,
358                                                         strlen(seltext));
359
360                 if (msginfo->folder || tmp_file) {
361                         gchar buf[BUFFSIZE];
362                         FILE *fp;
363
364                         if (tmp_file)
365                                 fp = fopen(tmp_file, "r");
366                         else
367                                 fp = procmime_get_first_text_content(msginfo);
368
369                         if (fp == NULL)
370                                 g_warning(_("Can't get text part\n"));
371                         else {
372                                 while (fgets(buf, sizeof(buf), fp) != NULL) {
373                                         strcrchomp(buf);
374                                         if (strncmp(buf, "-- ", 3) == 0)
375                                                 break;
376                                         if (quote_str)
377                                                 INSERT(quote_str);
378                                         INSERT(buf);
379                                 }
380                                 fclose(fp);
381                         }
382                 }
383
384                 if (tmp_file)
385                         unlink(tmp_file);
386         }
387         | SHOW_BACKSLASH
388         {
389                 INSERT("\\");
390         }
391         | SHOW_TAB
392         {
393                 INSERT("\t");
394         }
395         | SHOW_EOL
396         {
397                 INSERT("\n");
398         }
399         | SHOW_QUESTION_MARK
400         {
401                 INSERT("?");
402         }
403         | SHOW_OPARENT
404         {
405                 INSERT("{");
406         }
407         | SHOW_CPARENT
408         {
409                 INSERT("}");
410         };
411
412 query:
413         QUERY_DATE
414         {
415                 add_visibility(msginfo->date != NULL);
416         }
417         OPARENT quote_fmt CPARENT
418         {
419                 remove_visibility();
420         }
421         | QUERY_FROM
422         {
423                 add_visibility(msginfo->from != NULL);
424         }
425         OPARENT quote_fmt CPARENT
426         {
427                 remove_visibility();
428         }
429         | QUERY_FULLNAME
430         {
431                 add_visibility(msginfo->fromname != NULL);
432         }
433         OPARENT quote_fmt CPARENT
434         {
435                 remove_visibility();
436         }
437         | QUERY_SUBJECT
438         {
439                 add_visibility(msginfo->subject != NULL);
440         }
441         OPARENT quote_fmt CPARENT
442         {
443                 remove_visibility();
444         }
445         | QUERY_TO
446         {
447                 add_visibility(msginfo->to != NULL);
448         }
449         OPARENT quote_fmt CPARENT
450         {
451                 remove_visibility();
452         }
453         | QUERY_NEWSGROUPS
454         {
455                 add_visibility(msginfo->newsgroups != NULL);
456         }
457         OPARENT quote_fmt CPARENT
458         {
459                 remove_visibility();
460         }
461         | QUERY_MESSAGEID
462         {
463                 add_visibility(msginfo->msgid != NULL);
464         }
465         OPARENT quote_fmt CPARENT
466         {
467                 remove_visibility();
468         }
469         | QUERY_CC
470         {
471                 add_visibility(msginfo->cc != NULL);
472         }
473         OPARENT quote_fmt CPARENT
474         {
475                 remove_visibility();
476         }
477         | QUERY_REFERENCES
478         {
479                 /* add_visibility(msginfo->references != NULL); */
480         }
481         OPARENT quote_fmt CPARENT
482         {
483                 remove_visibility();
484         };