add Last Name placeholder for quoting
[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 gint maxsize = 0;
27 static gint stacksize = 0;
28
29 static gchar *buffer = NULL;
30 static gint bufmax = 0;
31 static gint bufsize = 0;
32 static const gchar *quote_str = NULL;
33 static const gchar *body = 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(const 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, const gchar *my_quote_str,
98                     const gchar *my_body)
99 {
100         quote_str = my_quote_str;
101         body = my_body;
102         msginfo = info;
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         char str[256];
131 }
132
133 %token SHOW_NEWSGROUPS
134 %token SHOW_DATE SHOW_FROM SHOW_FULLNAME SHOW_FIRST_NAME SHOW_LAST_NAME
135 %token SHOW_SENDER_INITIAL SHOW_SUBJECT SHOW_TO SHOW_MESSAGEID
136 %token SHOW_PERCENT SHOW_CC SHOW_REFERENCES SHOW_MESSAGE
137 %token SHOW_QUOTED_MESSAGE SHOW_BACKSLASH SHOW_TAB
138 %token SHOW_QUOTED_MESSAGE_NO_SIGNATURE SHOW_MESSAGE_NO_SIGNATURE
139 %token SHOW_EOL SHOW_QUESTION_MARK SHOW_PIPE SHOW_OPARENT SHOW_CPARENT
140 %token QUERY_DATE QUERY_FROM
141 %token QUERY_FULLNAME QUERY_SUBJECT QUERY_TO QUERY_NEWSGROUPS
142 %token QUERY_MESSAGEID QUERY_CC QUERY_REFERENCES
143 %token INSERT_FILE INSERT_PROGRAMOUTPUT
144 %token OPARENT CPARENT
145 %token CHARACTER
146
147 %start quote_fmt
148
149 %token <chr> CHARACTER
150 %type <chr> character
151 %type <str> string
152
153 %%
154
155 quote_fmt:
156         character_or_special_or_insert_or_query_list;
157
158 character_or_special_or_insert_or_query_list:
159         character_or_special_or_insert_or_query character_or_special_or_insert_or_query_list
160         | character_or_special_or_insert_or_query ;
161
162 character_or_special_or_insert_or_query:
163         special
164         | character
165         {
166                 INSERT_CHARACTER($1);
167         }
168         | query ;
169         | insert ;
170
171 character:
172         CHARACTER
173         ;
174
175 string:
176         CHARACTER
177         {
178                 $$[0] = $1;
179                 $$[1] = '\0';
180         }
181         | string CHARACTER
182         {
183                 strcpy($$, $1);
184                 $$[strlen($$) + 1] = '\0';
185                 $$[strlen($$)] = $2;
186         };
187
188 special:
189         SHOW_NEWSGROUPS
190         {
191                 if (msginfo->newsgroups)
192                         INSERT(msginfo->newsgroups);
193         }
194         | SHOW_DATE
195         {
196                 if (msginfo->date)
197                         INSERT(msginfo->date);
198         }
199         | SHOW_FROM
200         {
201                 if (msginfo->from)
202                         INSERT(msginfo->from);
203         }
204         | SHOW_FULLNAME
205         {
206                 if (msginfo->fromname)
207                         INSERT(msginfo->fromname);
208         }
209         | SHOW_FIRST_NAME
210         {
211                 if (msginfo->fromname) {
212                         gchar *p;
213                         gchar *str;
214
215                         str = alloca(strlen(msginfo->fromname) + 1);
216                         if (str != NULL) {
217                                 strcpy(str, msginfo->fromname);
218                                 p = str;
219                                 while (*p && !isspace(*p)) p++;
220                                 *p = '\0';
221                                 INSERT(str);
222                         }
223                 }
224         }
225         | SHOW_LAST_NAME
226         {
227                 /* This probably won't work together very well with Middle
228                  names and the like - thth */
229                 if (msginfo->fromname) {
230                         gchar *p;
231                         gchar *str;
232
233                         str = alloca(strlen(msginfo->fromname) + 1);
234                         if (str != NULL) {
235                                 strcpy(str, msginfo->fromname);
236                                 p = str;
237                                 while (*p && !isspace(*p)) p++;
238                                 if (*p) {
239                                     /* We found a space. Get first none-space char and
240                                      insert rest of string from there. */
241                                     while (*p && isspace(*p)) p++;
242                                     if (*p) {
243                                         INSERT(p);
244                                     } else {
245                                         /* If there is no none-space char, just insert
246                                          whole fromname. */
247                                         INSERT(str);
248                                     }
249                                 } else {
250                                     /* If there is no space, just insert whole fromname. */
251                                     INSERT(str);
252                                 }
253                         }
254                 }
255         }
256         | SHOW_SENDER_INITIAL
257         {
258 #define MAX_SENDER_INITIAL 20
259                 if (msginfo->fromname) {
260                         gchar tmp[MAX_SENDER_INITIAL];
261                         gchar *p;
262                         gchar *cur;
263                         gint len = 0;
264
265                         p = msginfo->fromname;
266                         cur = tmp;
267                         while (*p) {
268                                 if (*p && isalnum(*p)) {
269                                         *cur = toupper(*p);
270                                                 cur++;
271                                         len++;
272                                         if (len >= MAX_SENDER_INITIAL - 1)
273                                                 break;
274                                 } else
275                                         break;
276                                 while (*p && !isseparator(*p)) p++;
277                                 while (*p && isseparator(*p)) p++;
278                         }
279                         *cur = '\0';
280                         INSERT(tmp);
281                 }
282         }
283         | SHOW_SUBJECT
284         {
285                 if (msginfo->subject)
286                         INSERT(msginfo->subject);
287         }
288         | SHOW_TO
289         {
290                 if (msginfo->to)
291                         INSERT(msginfo->to);
292         }
293         | SHOW_MESSAGEID
294         {
295                 if (msginfo->msgid)
296                         INSERT(msginfo->msgid);
297         }
298         | SHOW_PERCENT
299         {
300                 INSERT("%");
301         }
302         | SHOW_CC
303         {
304                 if (msginfo->cc)
305                         INSERT(msginfo->cc);
306         }
307         | SHOW_REFERENCES
308         {
309                 /* if (msginfo->references)
310                         INSERT(msginfo->references); */
311         }
312         | SHOW_MESSAGE
313         {
314                 if (msginfo->folder) {
315                         gchar buf[BUFFSIZE];
316                         FILE *fp;
317
318                         if (body)
319                                 fp = str_open_as_stream(body);
320                         else
321                                 fp = procmime_get_first_text_content(msginfo);
322
323                         if (fp == NULL)
324                                 g_warning(_("Can't get text part\n"));
325                         else {
326                                 while (fgets(buf, sizeof(buf), fp) != NULL) {
327                                         strcrchomp(buf);
328                                         INSERT(buf);
329                                 }
330                                 fclose(fp);
331                         }
332                 }
333         }
334         | SHOW_QUOTED_MESSAGE
335         {
336                 if (msginfo->folder) {
337                         gchar buf[BUFFSIZE];
338                         FILE *fp;
339
340                         if (body)
341                                 fp = str_open_as_stream(body);
342                         else
343                                 fp = procmime_get_first_text_content(msginfo);
344
345                         if (fp == NULL)
346                                 g_warning(_("Can't get text part\n"));
347                         else {
348                                 while (fgets(buf, sizeof(buf), fp) != NULL) {
349                                         strcrchomp(buf);
350                                         if (quote_str)
351                                                 INSERT(quote_str);
352                                         INSERT(buf);
353                                 }
354                                 fclose(fp);
355                         }
356                 }
357         }
358         | SHOW_MESSAGE_NO_SIGNATURE
359         {
360                 if (msginfo->folder) {
361                         gchar buf[BUFFSIZE];
362                         FILE *fp;
363
364                         if (body)
365                                 fp = str_open_as_stream(body);
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                                         INSERT(buf);
377                                 }
378                                 fclose(fp);
379                         }
380                 }
381         }
382         | SHOW_QUOTED_MESSAGE_NO_SIGNATURE
383         {
384                 if (msginfo->folder) {
385                         gchar buf[BUFFSIZE];
386                         FILE *fp;
387
388                         if (body)
389                                 fp = str_open_as_stream(body);
390                         else
391                                 fp = procmime_get_first_text_content(msginfo);
392
393                         if (fp == NULL)
394                                 g_warning(_("Can't get text part\n"));
395                         else {
396                                 while (fgets(buf, sizeof(buf), fp) != NULL) {
397                                         strcrchomp(buf);
398                                         if (strncmp(buf, "-- ", 3) == 0)
399                                                 break;
400                                         if (quote_str)
401                                                 INSERT(quote_str);
402                                         INSERT(buf);
403                                 }
404                                 fclose(fp);
405                         }
406                 }
407         }
408         | SHOW_BACKSLASH
409         {
410                 INSERT("\\");
411         }
412         | SHOW_TAB
413         {
414                 INSERT("\t");
415         }
416         | SHOW_EOL
417         {
418                 INSERT("\n");
419         }
420         | SHOW_QUESTION_MARK
421         {
422                 INSERT("?");
423         }
424         | SHOW_PIPE
425         {
426                 INSERT("|");
427         }
428         | SHOW_OPARENT
429         {
430                 INSERT("{");
431         }
432         | SHOW_CPARENT
433         {
434                 INSERT("}");
435         };
436
437 query:
438         QUERY_DATE
439         {
440                 add_visibility(msginfo->date != NULL);
441         }
442         OPARENT quote_fmt CPARENT
443         {
444                 remove_visibility();
445         }
446         | QUERY_FROM
447         {
448                 add_visibility(msginfo->from != NULL);
449         }
450         OPARENT quote_fmt CPARENT
451         {
452                 remove_visibility();
453         }
454         | QUERY_FULLNAME
455         {
456                 add_visibility(msginfo->fromname != NULL);
457         }
458         OPARENT quote_fmt CPARENT
459         {
460                 remove_visibility();
461         }
462         | QUERY_SUBJECT
463         {
464                 add_visibility(msginfo->subject != NULL);
465         }
466         OPARENT quote_fmt CPARENT
467         {
468                 remove_visibility();
469         }
470         | QUERY_TO
471         {
472                 add_visibility(msginfo->to != NULL);
473         }
474         OPARENT quote_fmt CPARENT
475         {
476                 remove_visibility();
477         }
478         | QUERY_NEWSGROUPS
479         {
480                 add_visibility(msginfo->newsgroups != NULL);
481         }
482         OPARENT quote_fmt CPARENT
483         {
484                 remove_visibility();
485         }
486         | QUERY_MESSAGEID
487         {
488                 add_visibility(msginfo->msgid != NULL);
489         }
490         OPARENT quote_fmt CPARENT
491         {
492                 remove_visibility();
493         }
494         | QUERY_CC
495         {
496                 add_visibility(msginfo->cc != NULL);
497         }
498         OPARENT quote_fmt CPARENT
499         {
500                 remove_visibility();
501         }
502         | QUERY_REFERENCES
503         {
504                 /* add_visibility(msginfo->references != NULL); */
505         }
506         OPARENT quote_fmt CPARENT
507         {
508                 remove_visibility();
509         };
510
511 insert:
512         INSERT_FILE OPARENT string CPARENT
513         {
514                 {
515                         FILE *file;
516                         char buffer[256];
517                         
518                         if(file = fopen($3, "rb")) {
519                                 while(fgets(buffer, sizeof(buffer), file)) {
520                                         INSERT(buffer);
521                                 }
522                                 fclose(file);
523                         }
524                 }
525         }
526         | INSERT_PROGRAMOUTPUT OPARENT string CPARENT
527         {
528                 {
529                         FILE *file;
530                         char buffer[256];
531
532                         if(file = popen($3, "r")) {
533                                 while(fgets(buffer, sizeof(buffer), file)) {
534                                         INSERT(buffer);
535                                 }
536                                 fclose(file);
537                         }
538                 }
539         };