claws-mail/src/quote_fmt_parse.y
wwp 1b450742d6 Templates: add a way to attach a file, 'attach_output' or 'A', file whose absolute path+filename
is the output of a command-line (it s a mix of 'attach' and 'program'). The first line of the
command-line output is taken into account, trailing newline being stripped down.
Like 'attach', if the filename is not found or not accessible, CM will raise an error. Like
'program', if the command-line fails, no error raises but the standard output of CM shows it.
2016-09-02 00:40:27 +02:00

1344 lines
26 KiB
Text

/*
* Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
* Copyright (C) 1999-2007 Hiroyuki Yamamoto and the Claws Mail Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
%{
#include "defs.h"
#include <glib.h>
#include <glib/gi18n.h>
#include <ctype.h>
#include "procmsg.h"
#include "procmime.h"
#include "utils.h"
#include "codeconv.h"
#include "procheader.h"
#include "addr_compl.h"
#include "gtk/inputdialog.h"
#include "quote_fmt.h"
#include "quote_fmt_lex.h"
#include "account.h"
/* decl */
/*
flex quote_fmt.l
bison -p quote_fmt quote_fmt.y
*/
int yylex(void);
static MsgInfo *msginfo = NULL;
static PrefsAccount *account = NULL;
#ifdef USE_ENCHANT
static gchar default_dictionary[BUFFSIZE];
#endif
static gboolean *visible = NULL;
static gboolean dry_run = FALSE;
static gint maxsize = 0;
static gint stacksize = 0;
static GHashTable *var_table = NULL;
static GList *attachments = NULL;
typedef struct st_buffer
{
gchar *buffer;
gint bufsize;
gint bufmax;
} st_buffer;
static struct st_buffer main_expr = { NULL, 0, 0 };
static struct st_buffer sub_expr = { NULL, 0, 0 };
static struct st_buffer* current = NULL;
static const gchar *quote_str = NULL;
static const gchar *body = NULL;
static gint error = 0;
static gint cursor_pos = -1;
extern int quote_fmt_firsttime;
extern int line;
extern int escaped_string;
static void add_visibility(gboolean val)
{
stacksize++;
if (maxsize < stacksize) {
maxsize += 128;
visible = g_realloc(visible, maxsize * sizeof(gboolean));
if (visible == NULL)
maxsize = 0;
}
if (visible != NULL)
visible[stacksize - 1] = val;
}
static void remove_visibility(void)
{
stacksize--;
if (stacksize < 0) {
g_warning("Error: visibility stack underflow");
stacksize = 0;
}
}
static void add_buffer(const gchar *s)
{
gint len;
if (s == NULL)
return;
len = strlen(s);
if (current->bufsize + len + 1 > current->bufmax) {
if (current->bufmax == 0)
current->bufmax = 128;
while (current->bufsize + len + 1 > current->bufmax)
current->bufmax *= 2;
current->buffer = g_realloc(current->buffer, current->bufmax);
}
strcpy(current->buffer + current->bufsize, s);
current->bufsize += len;
}
static void clear_buffer(void)
{
if (current->buffer)
*current->buffer = '\0';
else
/* force to an empty string, as buffer should not be left unallocated */
add_buffer("");
current->bufsize = 0;
}
gchar *quote_fmt_get_buffer(void)
{
if (current != &main_expr)
g_warning("Error: parser still in sub-expr mode");
if (error != 0)
return NULL;
else
return current->buffer;
}
GList *quote_fmt_get_attachments_list(void)
{
return attachments;
}
gint quote_fmt_get_line(void)
{
return line;
}
gint quote_fmt_get_cursor_pos(void)
{
return cursor_pos;
}
#define INSERT(buf) \
if (stacksize != 0 && visible[stacksize - 1])\
add_buffer(buf); \
#define INSERT_CHARACTER(chr) \
if (stacksize != 0 && visible[stacksize - 1]) { \
gchar tmp[2]; \
tmp[0] = (chr); \
tmp[1] = '\0'; \
add_buffer(tmp); \
}
void quote_fmt_reset_vartable(void)
{
if (var_table) {
g_hash_table_destroy(var_table);
var_table = NULL;
}
if (attachments) {
GList *cur = attachments;
while (cur) {
g_free(cur->data);
cur = g_list_next(cur);
}
g_list_free(attachments);
attachments = NULL;
}
}
#ifdef USE_ENCHANT
void quote_fmt_init(MsgInfo *info, const gchar *my_quote_str,
const gchar *my_body, gboolean my_dry_run,
PrefsAccount *compose_account,
gboolean string_is_escaped,
GtkAspell *compose_gtkaspell)
#else
void quote_fmt_init(MsgInfo *info, const gchar *my_quote_str,
const gchar *my_body, gboolean my_dry_run,
PrefsAccount *compose_account,
gboolean string_is_escaped)
#endif
{
quote_str = my_quote_str;
body = my_body;
msginfo = info;
account = compose_account;
#ifdef USE_ENCHANT
gchar *dict = gtkaspell_get_default_dictionary(compose_gtkaspell);
if (dict)
strncpy2(default_dictionary, dict, sizeof(default_dictionary));
else
*default_dictionary = '\0';
#endif
dry_run = my_dry_run;
stacksize = 0;
add_visibility(TRUE);
main_expr.bufmax = 0;
sub_expr.bufmax = 0;
current = &main_expr;
clear_buffer();
error = 0;
line = 1;
escaped_string = string_is_escaped;
if (!var_table)
var_table = g_hash_table_new_full(g_str_hash, g_str_equal,
g_free, g_free);
/*
* force LEX initialization
*/
quote_fmt_firsttime = 1;
cursor_pos = -1;
}
void quote_fmterror(char *str)
{
g_warning("Error: %s at line %d", str, line);
error = 1;
}
int quote_fmtwrap(void)
{
return 1;
}
static int isseparator(int ch)
{
return g_ascii_isspace(ch) || ch == '.' || ch == '-';
}
/*
* Search for glibc extended strftime timezone specs within haystack.
* If not found NULL is returned and the integer pointed by tzspeclen is
* not changed.
* If found a pointer to the start of the specification within haystack
* is returned and the integer pointed by tzspeclen is set to the lenght
* of specification.
*/
static const char* strtzspec(const char *haystack, int *tzspeclen)
{
const char *p = NULL;
const char *q = NULL;
const char *r = NULL;
p = strstr(haystack, "%");
while (p != NULL) {
q = p + 1;
if (!*q) return NULL;
r = strchr("_-0^#", *q); /* skip flags */
if (r != NULL) {
++q;
if (!*q) return NULL;
}
while (*q >= '0' && *q <= '9') ++q; /* skip width */
if (!*q) return NULL;
if (*q == 'z' || *q == 'Z') { /* numeric or name */
*tzspeclen = 1 + (q - p);
return p;
}
p = strstr(q, "%");
}
return NULL;
}
static void quote_fmt_show_date(const MsgInfo *msginfo, const gchar *format)
{
char result[100];
char *rptr;
char zone[6];
struct tm lt;
const char *fptr;
const char *zptr;
if (!msginfo->date)
return;
/*
* ALF - GNU C's strftime() has a nice format specifier
* for time zone offset (%z). Non-standard however, so
* emulate it.
*/
#define RLEFT (sizeof result) - (rptr - result)
zone[0] = 0;
if (procheader_date_parse_to_tm(msginfo->date, &lt, zone)) {
/*
* break up format string in tiny bits delimited by valid %z's and
* feed it to strftime(). don't forget that '%%z' mean literal '%z'.
*/
for (rptr = result, fptr = format; fptr && *fptr && rptr < &result[sizeof result - 1];) {
int perc, zlen;
const char *p;
char *tmp;
if (NULL != (zptr = strtzspec(fptr, &zlen))) {
/*
* count nr. of prepended percent chars
*/
for (perc = 0, p = zptr; p && p >= format && *p == '%'; p--, perc++)
;
/*
* feed to strftime()
*/
tmp = g_strndup(fptr, zptr - fptr + (perc % 2 ? 0 : zlen));
if (tmp) {
rptr += strftime(rptr, RLEFT, tmp, &lt);
g_free(tmp);
}
/*
* append time zone offset
*/
if (zone[0] && perc % 2)
rptr += g_snprintf(rptr, RLEFT, "%s", zone);
fptr = zptr + zlen;
} else {
rptr += strftime(rptr, RLEFT, fptr, &lt);
fptr = NULL;
}
}
if (g_utf8_validate(result, -1, NULL)) {
INSERT(result);
} else {
gchar *utf = conv_codeset_strdup(result,
conv_get_locale_charset_str_no_utf8(),
CS_INTERNAL);
if (utf == NULL ||
!g_utf8_validate(utf, -1, NULL)) {
g_free(utf);
utf = g_malloc(strlen(result)*2+1);
conv_localetodisp(utf,
strlen(result)*2+1, result);
}
if (g_utf8_validate(utf, -1, NULL)) {
INSERT(utf);
}
g_free(utf);
}
}
#undef RLEFT
}
static void quote_fmt_show_first_name(const MsgInfo *msginfo)
{
guchar *p;
gchar *str;
if (!msginfo->fromname)
return;
p = (guchar*)strchr(msginfo->fromname, ',');
if (p != NULL) {
/* fromname is like "Duck, Donald" */
p++;
while (*p && isspace(*p)) p++;
str = alloca(strlen((char *)p) + 1);
if (str != NULL) {
strcpy(str, (char *)p);
INSERT(str);
}
} else {
/* fromname is like "Donald Duck" */
str = alloca(strlen(msginfo->fromname) + 1);
if (str != NULL) {
strcpy(str, msginfo->fromname);
p = (guchar *)str;
while (*p && !isspace(*p)) p++;
*p = '\0';
INSERT(str);
}
}
}
static void quote_fmt_show_last_name(const MsgInfo *msginfo)
{
gchar *p;
gchar *str;
/* This probably won't work together very well with Middle
names and the like - thth */
if (!msginfo->fromname)
return;
str = alloca(strlen(msginfo->fromname) + 1);
if (str != NULL) {
strcpy(str, msginfo->fromname);
p = strchr(str, ',');
if (p != NULL) {
/* fromname is like "Duck, Donald" */
*p = '\0';
INSERT(str);
} else {
/* fromname is like "Donald Duck" */
p = str;
while (*p && !isspace(*p)) p++;
if (*p) {
/* We found a space. Get first
none-space char and insert
rest of string from there. */
while (*p && isspace(*p)) p++;
if (*p) {
INSERT(p);
} else {
/* If there is no none-space
char, just insert whole
fromname. */
INSERT(str);
}
} else {
/* If there is no space, just
insert whole fromname. */
INSERT(str);
}
}
}
}
static void quote_fmt_show_sender_initial(const MsgInfo *msginfo)
{
#define MAX_SENDER_INITIAL 20
gchar tmp[MAX_SENDER_INITIAL];
guchar *p;
gchar *cur;
gint len = 0;
if (!msginfo->fromname)
return;
p = (guchar *)msginfo->fromname;
cur = tmp;
while (*p) {
if (*p && g_utf8_validate((gchar *)p, 1, NULL)) {
*cur = toupper(*p);
cur++;
len++;
if (len >= MAX_SENDER_INITIAL - 1)
break;
} else
break;
while (*p && !isseparator(*p)) p++;
while (*p && isseparator(*p)) p++;
}
*cur = '\0';
INSERT(tmp);
}
static void quote_fmt_show_msg(MsgInfo *msginfo, const gchar *body,
gboolean quoted, gboolean signature,
const gchar *quote_str)
{
gchar buf[BUFFSIZE];
FILE *fp;
if (!(msginfo->folder || body))
return;
if (body)
fp = str_open_as_stream(body);
else {
if (MSG_IS_ENCRYPTED(msginfo->flags))
fp = procmime_get_first_encrypted_text_content(msginfo);
else
fp = procmime_get_first_text_content(msginfo);
}
if (fp == NULL)
g_warning("Can't get text part");
else {
while (fgets(buf, sizeof(buf), fp) != NULL) {
strcrchomp(buf);
if (!signature && strncmp(buf, "-- \n", 4) == 0)
break;
if (quoted && quote_str)
INSERT(quote_str);
INSERT(buf);
}
fclose(fp);
}
}
static void quote_fmt_insert_file(const gchar *filename)
{
FILE *file;
char buffer[256];
if ((file = g_fopen(filename, "rb")) != NULL) {
while (fgets(buffer, sizeof(buffer), file)) {
INSERT(buffer);
}
fclose(file);
}
}
static void quote_fmt_insert_program_output(const gchar *progname)
{
FILE *file;
char buffer[256];
if ((file = popen(progname, "r")) != NULL) {
while (fgets(buffer, sizeof(buffer), file)) {
INSERT(buffer);
}
pclose(file);
}
}
static void quote_fmt_insert_user_input(const gchar *varname)
{
gchar *buf = NULL;
gchar *text = NULL;
if (dry_run)
return;
if ((text = g_hash_table_lookup(var_table, varname)) == NULL) {
buf = g_strdup_printf(_("Enter text to replace '%s'"), varname);
text = input_dialog(_("Enter variable"), buf, "");
g_free(buf);
if (!text)
return;
g_hash_table_insert(var_table, g_strdup(varname), g_strdup(text));
} else {
/* don't free the one in hashtable at the end */
text = g_strdup(text);
}
if (!text)
return;
INSERT(text);
g_free(text);
}
static void quote_fmt_attach_file(const gchar *filename)
{
attachments = g_list_append(attachments, g_strdup(filename));
}
static void quote_fmt_attach_file_program_output(const gchar *progname)
{
FILE *file;
char buffer[PATH_MAX];
if ((file = popen(progname, "r")) != NULL) {
/* get first line only */
if (fgets(buffer, sizeof(buffer), file)) {
/* trim trailing CR/LF */
strretchomp(buffer);
attachments = g_list_append(attachments, g_strdup(buffer));
}
pclose(file);
}
}
static gchar *quote_fmt_complete_address(const gchar *addr)
{
gint count;
gchar *res, *tmp, *email_addr;
gchar **split;
debug_print("quote_fmt_complete_address: %s\n", addr);
if (addr == NULL)
return NULL;
/* if addr is a list of message, try the 1st element only */
split = g_strsplit(addr, ",", -1);
if (!split || !split[0] || *split[0] == '\0') {
g_strfreev(split);
return NULL;
}
Xstrdup_a(email_addr, split[0], return NULL);
extract_address(email_addr);
if (!*email_addr) {
g_strfreev(split);
return NULL;
}
res = NULL;
start_address_completion(NULL);
if (1 < (count = complete_address(email_addr))) {
tmp = get_complete_address(1);
res = procheader_get_fromname(tmp);
g_free(tmp);
}
end_address_completion();
g_strfreev(split);
debug_print("quote_fmt_complete_address: matched %s\n", res);
return res;
}
%}
%union {
char chr;
char str[256];
}
/* tokens SHOW */
%token SHOW_NEWSGROUPS
%token SHOW_DATE SHOW_FROM SHOW_FULLNAME SHOW_FIRST_NAME SHOW_LAST_NAME
%token SHOW_SENDER_INITIAL SHOW_SUBJECT SHOW_TO SHOW_MESSAGEID
%token SHOW_PERCENT SHOW_CC SHOW_REFERENCES SHOW_MESSAGE
%token SHOW_QUOTED_MESSAGE SHOW_BACKSLASH SHOW_TAB SHOW_MAIL_ADDRESS
%token SHOW_QUOTED_MESSAGE_NO_SIGNATURE SHOW_MESSAGE_NO_SIGNATURE
%token SHOW_EOL SHOW_QUESTION_MARK SHOW_EXCLAMATION_MARK SHOW_PIPE SHOW_OPARENT SHOW_CPARENT
%token SHOW_ACCOUNT_FULL_NAME SHOW_ACCOUNT_MAIL_ADDRESS SHOW_ACCOUNT_NAME SHOW_ACCOUNT_ORGANIZATION
%token SHOW_ACCOUNT_DICT SHOW_ACCOUNT_SIG SHOW_ACCOUNT_SIGPATH
%token SHOW_DICT SHOW_TAGS
%token SHOW_ADDRESSBOOK_COMPLETION_FOR_CC
%token SHOW_ADDRESSBOOK_COMPLETION_FOR_FROM
%token SHOW_ADDRESSBOOK_COMPLETION_FOR_TO
/* tokens QUERY */
%token QUERY_DATE QUERY_FROM
%token QUERY_FULLNAME QUERY_SUBJECT QUERY_TO QUERY_NEWSGROUPS
%token QUERY_MESSAGEID QUERY_CC QUERY_REFERENCES
%token QUERY_ACCOUNT_FULL_NAME QUERY_ACCOUNT_ORGANIZATION QUERY_ACCOUNT_DICT
%token QUERY_ACCOUNT_SIG QUERY_ACCOUNT_SIGPATH
%token QUERY_DICT
%token QUERY_CC_FOUND_IN_ADDRESSBOOK
%token QUERY_FROM_FOUND_IN_ADDRESSBOOK
%token QUERY_TO_FOUND_IN_ADDRESSBOOK
/* tokens QUERY_NOT */
%token QUERY_NOT_DATE QUERY_NOT_FROM
%token QUERY_NOT_FULLNAME QUERY_NOT_SUBJECT QUERY_NOT_TO QUERY_NOT_NEWSGROUPS
%token QUERY_NOT_MESSAGEID QUERY_NOT_CC QUERY_NOT_REFERENCES
%token QUERY_NOT_ACCOUNT_FULL_NAME QUERY_NOT_ACCOUNT_ORGANIZATION QUERY_NOT_ACCOUNT_DICT
%token QUERY_NOT_ACCOUNT_SIG QUERY_NOT_ACCOUNT_SIGPATH
%token QUERY_NOT_DICT
%token QUERY_NOT_CC_FOUND_IN_ADDRESSBOOK
%token QUERY_NOT_FROM_FOUND_IN_ADDRESSBOOK
%token QUERY_NOT_TO_FOUND_IN_ADDRESSBOOK
/* other tokens */
%token INSERT_FILE INSERT_PROGRAMOUTPUT INSERT_USERINPUT
%token ATTACH_FILE ATTACH_PROGRAMOUTPUT
%token OPARENT CPARENT
%token CHARACTER
%token SHOW_DATE_EXPR
%token SET_CURSOR_POS
%start quote_fmt
%type <chr> CHARACTER
%type <chr> character
%type <str> string
%%
quote_fmt:
character_or_special_or_insert_or_query_list ;
sub_expr:
character_or_special_list ;
character_or_special_or_insert_or_query_list:
character_or_special_or_insert_or_query character_or_special_or_insert_or_query_list
| character_or_special_or_insert_or_query ;
character_or_special_list:
character_or_special character_or_special_list
| character_or_special ;
character_or_special_or_insert_or_query:
character_or_special
| query
| query_not
| insert
| attach ;
character_or_special:
special
| character
{
INSERT_CHARACTER($1);
};
character:
CHARACTER
;
string:
CHARACTER
{
$$[0] = $1;
$$[1] = '\0';
}
| string CHARACTER
{
size_t len;
strncpy($$, $1, sizeof($$));
$$[sizeof($$) - 1] = '\0';
len = strlen($$);
if (len + 1 < sizeof($$)) {
$$[len + 1] = '\0';
$$[len] = $2;
}
};
special:
SHOW_NEWSGROUPS
{
if (msginfo->newsgroups)
INSERT(msginfo->newsgroups);
}
| SHOW_DATE_EXPR OPARENT string CPARENT
{
quote_fmt_show_date(msginfo, $3);
}
| SHOW_DATE
{
if (msginfo->date)
INSERT(msginfo->date);
}
| SHOW_FROM
{
if (msginfo->from)
INSERT(msginfo->from);
}
| SHOW_MAIL_ADDRESS
{
if (msginfo->from) {
gchar *stripped_address = g_strdup(msginfo->from);
extract_address(stripped_address);
INSERT(stripped_address);
g_free(stripped_address);
}
}
| SHOW_FULLNAME
{
if (msginfo->fromname)
INSERT(msginfo->fromname);
}
| SHOW_FIRST_NAME
{
quote_fmt_show_first_name(msginfo);
}
| SHOW_LAST_NAME
{
quote_fmt_show_last_name(msginfo);
}
| SHOW_SENDER_INITIAL
{
quote_fmt_show_sender_initial(msginfo);
}
| SHOW_SUBJECT
{
if (msginfo->subject)
INSERT(msginfo->subject);
}
| SHOW_TO
{
if (msginfo->to)
INSERT(msginfo->to);
}
| SHOW_MESSAGEID
{
if (msginfo->msgid)
INSERT(msginfo->msgid);
}
| SHOW_PERCENT
{
INSERT("%");
}
| SHOW_CC
{
if (msginfo->cc)
INSERT(msginfo->cc);
}
| SHOW_REFERENCES
{
GSList *item;
INSERT(msginfo->inreplyto);
for (item = msginfo->references; item != NULL; item = g_slist_next(item))
if (item->data)
INSERT(item->data);
}
| SHOW_MESSAGE
{
quote_fmt_show_msg(msginfo, body, FALSE, TRUE, quote_str);
}
| SHOW_QUOTED_MESSAGE
{
quote_fmt_show_msg(msginfo, body, TRUE, TRUE, quote_str);
}
| SHOW_MESSAGE_NO_SIGNATURE
{
quote_fmt_show_msg(msginfo, body, FALSE, FALSE, quote_str);
}
| SHOW_QUOTED_MESSAGE_NO_SIGNATURE
{
quote_fmt_show_msg(msginfo, body, TRUE, FALSE, quote_str);
}
| SHOW_ACCOUNT_FULL_NAME
{
if (account && account->name)
INSERT(account->name);
}
| SHOW_ACCOUNT_MAIL_ADDRESS
{
if (account && account->address)
INSERT(account->address);
}
| SHOW_ACCOUNT_NAME
{
if (account && account->account_name)
INSERT(account->account_name);
}
| SHOW_ACCOUNT_ORGANIZATION
{
if (account && account->organization)
INSERT(account->organization);
}
| SHOW_ACCOUNT_SIG
{
gchar *str = account_get_signature_str(account);
INSERT(str);
g_free(str);
}
| SHOW_ACCOUNT_SIGPATH
{
if (account && account->sig_path)
INSERT(account->sig_path);
}
| SHOW_ACCOUNT_DICT
{
#ifdef USE_ENCHANT
if (account && account->enable_default_dictionary) {
gchar *dictname = g_path_get_basename(account->default_dictionary);
INSERT(dictname);
g_free(dictname);
}
#endif
}
| SHOW_DICT
{
#ifdef USE_ENCHANT
INSERT(default_dictionary);
#endif
}
| SHOW_TAGS
{
gchar *tags = procmsg_msginfo_get_tags_str(msginfo);
if (tags) {
INSERT(tags);
}
g_free(tags);
}
| SHOW_BACKSLASH
{
INSERT("\\");
}
| SHOW_TAB
{
INSERT("\t");
}
| SHOW_EOL
{
INSERT("\n");
}
| SHOW_QUESTION_MARK
{
INSERT("?");
}
| SHOW_EXCLAMATION_MARK
{
INSERT("!");
}
| SHOW_PIPE
{
INSERT("|");
}
| SHOW_OPARENT
{
INSERT("{");
}
| SHOW_CPARENT
{
INSERT("}");
}
| SET_CURSOR_POS
{
if (current->buffer)
cursor_pos = g_utf8_strlen(current->buffer, -1);
else
cursor_pos = 0;
}
| SHOW_ADDRESSBOOK_COMPLETION_FOR_CC
{
gchar *tmp = quote_fmt_complete_address(msginfo->cc);
if (tmp) {
INSERT(tmp);
g_free(tmp);
}
}
| SHOW_ADDRESSBOOK_COMPLETION_FOR_FROM
{
gchar *tmp = quote_fmt_complete_address(msginfo->from);
if (tmp) {
INSERT(tmp);
g_free(tmp);
}
}
| SHOW_ADDRESSBOOK_COMPLETION_FOR_TO
{
gchar *tmp = quote_fmt_complete_address(msginfo->to);
if (tmp) {
INSERT(tmp);
g_free(tmp);
}
};
query:
QUERY_DATE
{
add_visibility(msginfo->date != NULL);
}
OPARENT quote_fmt CPARENT
{
remove_visibility();
}
| QUERY_FROM
{
add_visibility(msginfo->from != NULL);
}
OPARENT quote_fmt CPARENT
{
remove_visibility();
}
| QUERY_FULLNAME
{
add_visibility(msginfo->fromname != NULL);
}
OPARENT quote_fmt CPARENT
{
remove_visibility();
}
| QUERY_SUBJECT
{
add_visibility(msginfo->subject != NULL);
}
OPARENT quote_fmt CPARENT
{
remove_visibility();
}
| QUERY_TO
{
add_visibility(msginfo->to != NULL);
}
OPARENT quote_fmt CPARENT
{
remove_visibility();
}
| QUERY_NEWSGROUPS
{
add_visibility(msginfo->newsgroups != NULL);
}
OPARENT quote_fmt CPARENT
{
remove_visibility();
}
| QUERY_MESSAGEID
{
add_visibility(msginfo->msgid != NULL);
}
OPARENT quote_fmt CPARENT
{
remove_visibility();
}
| QUERY_CC
{
add_visibility(msginfo->cc != NULL);
}
OPARENT quote_fmt CPARENT
{
remove_visibility();
}
| QUERY_REFERENCES
{
gboolean found;
GSList *item;
found = (msginfo->inreplyto != NULL);
for (item = msginfo->references; found == FALSE && item != NULL; item = g_slist_next(item))
if (item->data)
found = TRUE;
add_visibility(found == TRUE);
}
OPARENT quote_fmt CPARENT
{
remove_visibility();
}
| QUERY_ACCOUNT_FULL_NAME
{
add_visibility(account != NULL && account->name != NULL);
}
OPARENT quote_fmt CPARENT
{
remove_visibility();
}
| QUERY_ACCOUNT_ORGANIZATION
{
add_visibility(account != NULL && account->organization != NULL);
}
OPARENT quote_fmt CPARENT
{
remove_visibility();
}
| QUERY_ACCOUNT_SIG
{
gchar *str = account_get_signature_str(account);
add_visibility(str != NULL && * str != '\0');
g_free(str);
}
OPARENT quote_fmt CPARENT
{
remove_visibility();
}
| QUERY_ACCOUNT_SIGPATH
{
add_visibility(account != NULL && account->sig_path != NULL
&& *account->sig_path != '\0');
}
OPARENT quote_fmt CPARENT
{
remove_visibility();
}
| QUERY_ACCOUNT_DICT
{
#ifdef USE_ENCHANT
add_visibility(account != NULL && account->enable_default_dictionary == TRUE &&
account->default_dictionary != NULL && *account->default_dictionary != '\0');
#else
add_visibility(FALSE);
#endif
}
OPARENT quote_fmt CPARENT
{
remove_visibility();
}
| QUERY_DICT
{
#ifdef USE_ENCHANT
add_visibility(*default_dictionary != '\0');
#else
add_visibility(FALSE);
#endif
}
OPARENT quote_fmt CPARENT
{
remove_visibility();
}
| QUERY_CC_FOUND_IN_ADDRESSBOOK
{
gchar *tmp = quote_fmt_complete_address(msginfo->cc);
add_visibility(tmp != NULL && *tmp != '\0');
g_free(tmp);
}
OPARENT quote_fmt CPARENT
{
remove_visibility();
}
| QUERY_FROM_FOUND_IN_ADDRESSBOOK
{
gchar *tmp = quote_fmt_complete_address(msginfo->from);
add_visibility(tmp != NULL && *tmp != '\0');
g_free(tmp);
}
OPARENT quote_fmt CPARENT
{
remove_visibility();
}
| QUERY_TO_FOUND_IN_ADDRESSBOOK
{
gchar *tmp = quote_fmt_complete_address(msginfo->to);
add_visibility(tmp != NULL && *tmp != '\0');
g_free(tmp);
}
OPARENT quote_fmt CPARENT
{
remove_visibility();
};
query_not:
QUERY_NOT_DATE
{
add_visibility(msginfo->date == NULL);
}
OPARENT quote_fmt CPARENT
{
remove_visibility();
}
| QUERY_NOT_FROM
{
add_visibility(msginfo->from == NULL);
}
OPARENT quote_fmt CPARENT
{
remove_visibility();
}
| QUERY_NOT_FULLNAME
{
add_visibility(msginfo->fromname == NULL);
}
OPARENT quote_fmt CPARENT
{
remove_visibility();
}
| QUERY_NOT_SUBJECT
{
add_visibility(msginfo->subject == NULL);
}
OPARENT quote_fmt CPARENT
{
remove_visibility();
}
| QUERY_NOT_TO
{
add_visibility(msginfo->to == NULL);
}
OPARENT quote_fmt CPARENT
{
remove_visibility();
}
| QUERY_NOT_NEWSGROUPS
{
add_visibility(msginfo->newsgroups == NULL);
}
OPARENT quote_fmt CPARENT
{
remove_visibility();
}
| QUERY_NOT_MESSAGEID
{
add_visibility(msginfo->msgid == NULL);
}
OPARENT quote_fmt CPARENT
{
remove_visibility();
}
| QUERY_NOT_CC
{
add_visibility(msginfo->cc == NULL);
}
OPARENT quote_fmt CPARENT
{
remove_visibility();
}
| QUERY_NOT_REFERENCES
{
gboolean found;
GSList *item;
found = (msginfo->inreplyto != NULL);
for (item = msginfo->references; found == FALSE && item != NULL; item = g_slist_next(item))
if (item->data)
found = TRUE;
add_visibility(found == FALSE);
}
OPARENT quote_fmt CPARENT
{
remove_visibility();
}
| QUERY_NOT_ACCOUNT_FULL_NAME
{
add_visibility(account == NULL || account->name == NULL);
}
OPARENT quote_fmt CPARENT
{
remove_visibility();
}
| QUERY_NOT_ACCOUNT_ORGANIZATION
{
add_visibility(account == NULL || account->organization == NULL);
}
OPARENT quote_fmt CPARENT
{
remove_visibility();
}
| QUERY_NOT_ACCOUNT_SIG
{
gchar *str = account_get_signature_str(account);
add_visibility(str == NULL || *str == '\0');
g_free(str);
}
OPARENT quote_fmt CPARENT
{
remove_visibility();
}
| QUERY_NOT_ACCOUNT_SIGPATH
{
add_visibility(account == NULL || account->sig_path == NULL
|| *account->sig_path == '\0');
}
OPARENT quote_fmt CPARENT
{
remove_visibility();
}
| QUERY_NOT_ACCOUNT_DICT
{
#ifdef USE_ENCHANT
add_visibility(account == NULL || account->enable_default_dictionary == FALSE
|| *account->default_dictionary == '\0');
#else
add_visibility(FALSE);
#endif
}
OPARENT quote_fmt CPARENT
{
remove_visibility();
}
| QUERY_NOT_DICT
{
#ifdef USE_ENCHANT
add_visibility(*default_dictionary == '\0');
#else
add_visibility(FALSE);
#endif
}
OPARENT quote_fmt CPARENT
{
remove_visibility();
}
| QUERY_NOT_CC_FOUND_IN_ADDRESSBOOK
{
gchar *tmp = quote_fmt_complete_address(msginfo->cc);
add_visibility(tmp == NULL || *tmp == '\0');
g_free(tmp);
}
OPARENT quote_fmt CPARENT
{
remove_visibility();
}
| QUERY_NOT_FROM_FOUND_IN_ADDRESSBOOK
{
gchar *tmp = quote_fmt_complete_address(msginfo->from);
add_visibility(tmp == NULL || *tmp == '\0');
g_free(tmp);
}
OPARENT quote_fmt CPARENT
{
remove_visibility();
}
| QUERY_NOT_TO_FOUND_IN_ADDRESSBOOK
{
gchar *tmp = quote_fmt_complete_address(msginfo->to);
add_visibility(tmp == NULL || *tmp == '\0');
g_free(tmp);
}
OPARENT quote_fmt CPARENT
{
remove_visibility();
};
insert:
INSERT_FILE
{
current = &sub_expr;
clear_buffer();
}
OPARENT sub_expr CPARENT
{
current = &main_expr;
if (!dry_run) {
quote_fmt_insert_file(sub_expr.buffer);
}
}
| INSERT_PROGRAMOUTPUT
{
current = &sub_expr;
clear_buffer();
}
OPARENT sub_expr CPARENT
{
current = &main_expr;
if (!dry_run) {
quote_fmt_insert_program_output(sub_expr.buffer);
}
}
| INSERT_USERINPUT
{
current = &sub_expr;
clear_buffer();
}
OPARENT sub_expr CPARENT
{
current = &main_expr;
if (!dry_run) {
quote_fmt_insert_user_input(sub_expr.buffer);
}
};
attach:
ATTACH_FILE
{
current = &sub_expr;
clear_buffer();
}
OPARENT sub_expr CPARENT
{
current = &main_expr;
if (!dry_run) {
quote_fmt_attach_file(sub_expr.buffer);
}
}
| ATTACH_PROGRAMOUTPUT
{
current = &sub_expr;
clear_buffer();
}
OPARENT sub_expr CPARENT
{
current = &main_expr;
if (!dry_run) {
quote_fmt_attach_file_program_output(sub_expr.buffer);
}
};
;