2007-05-22 [wwp] 2.9.2cvs10
authorTristan Chabredier <wwp@claws-mail.org>
Tue, 22 May 2007 21:36:07 +0000 (21:36 +0000)
committerTristan Chabredier <wwp@claws-mail.org>
Tue, 22 May 2007 21:36:07 +0000 (21:36 +0000)
* src/compose.c
* src/prefs_template.c
* src/quote_fmt.c
* src/quote_fmt.h
* src/quote_fmt_lex.l
* src/quote_fmt_parse.y
* src/gtk/gtkaspell.c
* src/gtk/gtkaspell.h
Added template/quote format syntactical elements
to show and query:
- current dictionary
  %T to show (shows empty if not set or not enabled),
  ?T and !T to check if the default dictionary is
  enabled and set
- current account's default dictionary
  %aT to show (empty if not set or not enabled),
  ?aT and !aT to check if it's enabled and set
- name completion for an address, from the address
  book
  %ABf, %ABt, %ABc respectively show the full name got
  from the address book if From, To or Cc match a single
  contact.
  ?ABf, !ABf, ?ABt, !ABt, ?ABc and !ABc check if completion
  matches any contact and if the full name is non-empty.
  If From, To or Cc are lists of email addresses, only
  the first address will be checked.
In compose.c, fix msginfo's To, Cc and Newsgroup address lists,
that could show a trailing ','.
Also, template/quote_fmt parser now shows the line number in case
of parser error.

ChangeLog
PATCHSETS
configure.ac
src/compose.c
src/gtk/gtkaspell.c
src/gtk/gtkaspell.h
src/prefs_template.c
src/quote_fmt.c
src/quote_fmt.h
src/quote_fmt_lex.l
src/quote_fmt_parse.y

index b49d0e368a3c9edae3c847ad1b4a7394067a3a53..1cbf08affa677269b8e3ec1b05991f94c5735b75 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,36 @@
+2007-05-22 [wwp]       2.9.2cvs10
+
+       * src/compose.c
+       * src/prefs_template.c
+       * src/quote_fmt.c
+       * src/quote_fmt.h
+       * src/quote_fmt_lex.l
+       * src/quote_fmt_parse.y
+       * src/gtk/gtkaspell.c
+       * src/gtk/gtkaspell.h
+               Added template/quote format syntactical elements
+               to show and query:
+                       - current dictionary
+                         %T to show (shows empty if not set or not enabled),
+                         ?T and !T to check if the default dictionary is
+                         enabled and set
+                       - current account's default dictionary
+                         %aT to show (empty if not set or not enabled),
+                         ?aT and !aT to check if it's enabled and set
+                       - name completion for an address, from the address
+                         book
+                         %ABf, %ABt, %ABc respectively show the full name got
+                         from the address book if From, To or Cc match a single
+                         contact.
+                         ?ABf, !ABf, ?ABt, !ABt, ?ABc and !ABc check if completion
+                         matches any contact and if the full name is non-empty.
+                         If From, To or Cc are lists of email addresses, only
+                         the first address will be checked.
+               In compose.c, fix msginfo's To, Cc and Newsgroup address lists,
+               that could show a trailing ','.
+               Also, template/quote_fmt parser now shows the line number in case
+               of parser error.
+
 2007-05-15 [colin]     2.9.2cvs9
 
        * src/main.c
index dc976e481f9eb42320972a6bd19204492e5c37ba..8d007495c3f550d7ed0031c3378302d970bc1702 100644 (file)
--- a/PATCHSETS
+++ b/PATCHSETS
 ( cvs diff -u -r 1.1.4.29 -r 1.1.4.30 src/gtk/logwindow.c;  ) > 2.9.2cvs7.patchset
 ( cvs diff -u -r 1.1.2.5 -r 1.1.2.6 manual/xml2pdf;  ) > 2.9.2cvs8.patchset
 ( cvs diff -u -r 1.213.2.144 -r 1.213.2.145 src/folder.c;  cvs diff -u -r 1.87.2.40 -r 1.87.2.41 src/folder.h;  cvs diff -u -r 1.115.2.152 -r 1.115.2.153 src/main.c;  cvs diff -u -r 1.7.2.10 -r 1.7.2.11 src/main.h;  cvs diff -u -r 1.94.2.133 -r 1.94.2.134 src/messageview.c;  cvs diff -u -r 1.204.2.134 -r 1.204.2.135 src/prefs_common.c;  cvs diff -u -r 1.103.2.82 -r 1.103.2.83 src/prefs_common.h;  cvs diff -u -r 1.1.2.40 -r 1.1.2.41 src/prefs_summaries.c;  cvs diff -u -r 1.395.2.302 -r 1.395.2.303 src/summaryview.c;  ) > 2.9.2cvs9.patchset
+( cvs diff -u -r 1.382.2.377 -r 1.382.2.378 src/compose.c;  cvs diff -u -r 1.12.2.41 -r 1.12.2.42 src/prefs_template.c;  cvs diff -u -r 1.8.2.15 -r 1.8.2.16 src/quote_fmt.c;  cvs diff -u -r 1.5.12.6 -r 1.5.12.7 src/quote_fmt.h;  cvs diff -u -r 1.8.2.9 -r 1.8.2.10 src/quote_fmt_lex.l;  cvs diff -u -r 1.22.2.28 -r 1.22.2.29 src/quote_fmt_parse.y;  cvs diff -u -r 1.9.2.50 -r 1.9.2.51 src/gtk/gtkaspell.c;  cvs diff -u -r 1.5.2.11 -r 1.5.2.12 src/gtk/gtkaspell.h;  ) > 2.9.2cvs10.patchset
index 87402c5212a3d8dab121d4f1301c27f57e0f9c63..0a063a41225f6757cf0f817e5d2753175b312d8f 100644 (file)
@@ -11,7 +11,7 @@ MINOR_VERSION=9
 MICRO_VERSION=2
 INTERFACE_AGE=0
 BINARY_AGE=0
-EXTRA_VERSION=9
+EXTRA_VERSION=10
 EXTRA_RELEASE=
 EXTRA_GTK2_VERSION=
 
index db7faf2d676f60f8e438191c891cd89308cf7e0b..4190805ccce968f134a124c47521c6436e57e323 100644 (file)
@@ -1041,7 +1041,8 @@ Compose *compose_generic_new(PrefsAccount *account, const gchar *mailto, FolderI
                        pref_get_unescaped_pref(tmp, prefs_common.compose_subject_format);
 
                        subject = gtk_editable_get_chars(GTK_EDITABLE(compose->subject_entry), 0, -1);
-                       quote_fmt_init(dummyinfo, NULL, subject, FALSE, compose->account);
+                       quote_fmt_init(dummyinfo, NULL, subject, FALSE, compose->account,
+                                       compose->gtkaspell);
                        quote_fmt_scan_string(tmp);
                        quote_fmt_parse();
 
@@ -2533,7 +2534,8 @@ static gchar *compose_quote_fmt(Compose *compose, MsgInfo *msginfo,
        }
 
        if (qmark != NULL) {
-               quote_fmt_init(msginfo, NULL, NULL, FALSE, compose->account);
+               quote_fmt_init(msginfo, NULL, NULL, FALSE, compose->account,
+                               compose->gtkaspell);
                quote_fmt_scan_string(qmark);
                quote_fmt_parse();
 
@@ -2550,7 +2552,8 @@ static gchar *compose_quote_fmt(Compose *compose, MsgInfo *msginfo,
                        while (*trimmed_body == '\n')
                                trimmed_body++;
 
-               quote_fmt_init(msginfo, quote_str, trimmed_body, FALSE, compose->account);
+               quote_fmt_init(msginfo, quote_str, trimmed_body, FALSE, compose->account,
+                               compose->gtkaspell);
                if (need_unescape) {
                        gchar *tmp = NULL;
 
@@ -7150,7 +7153,8 @@ static void compose_template_apply_fields(Compose *compose, Template *tmpl)
        }
 
        if (tmpl->to && *tmpl->to != '\0') {
-               quote_fmt_init(msginfo, NULL, NULL, FALSE, compose->account);
+               quote_fmt_init(msginfo, NULL, NULL, FALSE, compose->account,
+                               compose->gtkaspell);
                quote_fmt_scan_string(tmpl->to);
                quote_fmt_parse();
 
@@ -7163,7 +7167,8 @@ static void compose_template_apply_fields(Compose *compose, Template *tmpl)
        }
 
        if (tmpl->cc && *tmpl->cc != '\0') {
-               quote_fmt_init(msginfo, NULL, NULL, FALSE, compose->account);
+               quote_fmt_init(msginfo, NULL, NULL, FALSE, compose->account,
+                               compose->gtkaspell);
                quote_fmt_scan_string(tmpl->cc);
                quote_fmt_parse();
 
@@ -7176,7 +7181,8 @@ static void compose_template_apply_fields(Compose *compose, Template *tmpl)
        }
 
        if (tmpl->bcc && *tmpl->bcc != '\0') {
-               quote_fmt_init(msginfo, NULL, NULL, FALSE, compose->account);
+               quote_fmt_init(msginfo, NULL, NULL, FALSE, compose->account,
+                               compose->gtkaspell);
                quote_fmt_scan_string(tmpl->bcc);
                quote_fmt_parse();
 
@@ -7190,7 +7196,8 @@ static void compose_template_apply_fields(Compose *compose, Template *tmpl)
 
        /* process the subject */
        if (tmpl->subject && *tmpl->subject != '\0') {
-               quote_fmt_init(msginfo, NULL, NULL, FALSE, compose->account);
+               quote_fmt_init(msginfo, NULL, NULL, FALSE, compose->account,
+                               compose->gtkaspell);
                quote_fmt_scan_string(tmpl->subject);
                quote_fmt_parse();
 
@@ -9760,7 +9767,7 @@ static MsgInfo *compose_msginfo_new_from_compose(Compose *compose)
                if ( strcasecmp(header, prefs_common_translated_header_name("To:")) == 0 ) {
                        if ( newmsginfo->to == NULL ) {
                                newmsginfo->to = g_strdup(entry);
-                       } else {
+                       } else if (entry && *entry) {
                                gchar *tmp = g_strconcat(newmsginfo->to, ", ", entry, NULL);
                                g_free(newmsginfo->to);
                                newmsginfo->to = tmp;
@@ -9769,7 +9776,7 @@ static MsgInfo *compose_msginfo_new_from_compose(Compose *compose)
                if ( strcasecmp(header, prefs_common_translated_header_name("Cc:")) == 0 ) {
                        if ( newmsginfo->cc == NULL ) {
                                newmsginfo->cc = g_strdup(entry);
-                       } else {
+                       } else if (entry && *entry) {
                                gchar *tmp = g_strconcat(newmsginfo->cc, ", ", entry, NULL);
                                g_free(newmsginfo->cc);
                                newmsginfo->cc = tmp;
@@ -9779,7 +9786,7 @@ static MsgInfo *compose_msginfo_new_from_compose(Compose *compose)
                                                prefs_common_translated_header_name("Newsgroups:")) == 0 ) {
                        if ( newmsginfo->newsgroups == NULL ) {
                                newmsginfo->newsgroups = g_strdup(entry);
-                       } else {
+                       } else if (entry && *entry) {
                                gchar *tmp = g_strconcat(newmsginfo->newsgroups, ", ", entry, NULL);
                                g_free(newmsginfo->newsgroups);
                                newmsginfo->newsgroups = tmp;
index 8f564a31c4b2abae1d8afbac49222a1c9a057fb9..40bf9c4313b193dbd0da69dd139b6aa36a5931e2 100644 (file)
@@ -2588,4 +2588,13 @@ static gint find_gtkaspeller(gconstpointer aa, gconstpointer bb)
 
        return 1;
 }
+
+gchar *gtkaspell_get_default_dictionary(GtkAspell *gtkaspell)
+{
+       if (gtkaspell && gtkaspell->gtkaspeller &&
+                       gtkaspell->gtkaspeller->dictionary)
+               return gtkaspell->gtkaspeller->dictionary->dictname;
+       else
+               return NULL;
+}
 #endif
index f986955a81174f876ffa8ef8b9c6a404200e0f2f..39d7cac25b56022071b66de7feed35b4931ffdf3 100644 (file)
@@ -103,5 +103,7 @@ void                gtkaspell_sugmode_option_menu_set       (GtkOptionMenu *optmenu,
 gint           gtkaspell_get_sugmode_from_option_menu  (GtkOptionMenu *optmenu);
 GSList*                gtkaspell_make_config_menu              (GtkAspell      *gtkaspell);
 
+gchar *gtkaspell_get_default_dictionary(GtkAspell *gtkaspell);
+
 #endif /* USE_ASPELL */
 #endif /* __GTKASPELL_H__ */
index 0f2fa3ab759b08d3cf0e4ac202b246f67c0fed11..569536996a368a4c1e77056019f40d5c11d528d3 100644 (file)
@@ -557,7 +557,7 @@ gboolean prefs_template_string_is_valid(gchar *string)
                MsgInfo dummyinfo;
 
                memset(&dummyinfo, 0, sizeof(MsgInfo));
-               quote_fmt_init(&dummyinfo, NULL, NULL, TRUE, NULL);
+               quote_fmt_init(&dummyinfo, NULL, NULL, TRUE, NULL, NULL);
                quote_fmt_scan_string(string);
                quote_fmt_parse();
                parsed_buf = quote_fmt_get_buffer();
index 2fc9a2d521bf5f50ea2bbbc4d238ae41e9f39e59..e0729fb8246c92d59bd21e90b66520df2bac4a22 100644 (file)
@@ -55,11 +55,16 @@ static gchar *quote_desc_strings[] = {
        "%Q",           N_("quoted message body"), /* quoted message */
        "%m",           N_("message body without signature"), /* message with no signature */
        "%q",           N_("quoted message body without signature"), /* quoted message with no signature */
+       "%T",           N_("current dictionary"), /* current dictionary */
        "%X",           N_("cursor position"), /* X marks the cursor spot */
-       "%af",          N_("Account property: your name"), /* full name in compose account */
-       "%am",          N_("Account property: your email address"), /* mail address in compose account */
-       "%an",          N_("Account property: account name"), /* compose account name itself */
-       "%ao",          N_("Account property: organization"), /* organization in compose account */
+       "%af",          N_("account property: your name"), /* full name in compose account */
+       "%am",          N_("account property: your email address"), /* mail address in compose account */
+       "%an",          N_("account property: account name"), /* compose account name itself */
+       "%ao",          N_("account property: organization"), /* organization in compose account */
+       "%aT",          N_("account property: default dictionary"), /* main dict (if enabled) in account */
+       "%ABc",         N_("address book completion: Cc"), /* completion of 'Cc' from address book */
+       "%ABf",         N_("address book completion: From"), /* completion of 'From' from address book */
+       "%ABt",         N_("address book completion: To"), /* completion of 'To' from address book */
        "\\%",          N_("literal %"),
        "\\\\",         N_("literal backslash"),
        "\\?",          N_("literal question mark"),
@@ -70,8 +75,8 @@ static gchar *quote_desc_strings[] = {
        "\\t",          N_("tab"),
        "\\n",          N_("linefeed"),
        "",             NULL,
-       "?x{expr}\n",   N_("insert expr if x is set\n(where x is one of the dfNFLIstcnri characters or af, ao)"),
-       "!x{expr}\n",   N_("insert expr if x is not set\n(where x is one of the dfNFLIstcnri characters or af, ao)"),
+       "?x{expr}\n",   N_("insert expr if x is set\n(where x is one of the dfNFLIstcnriT characters or ad, af, ao, aT, ABc, ABf, ABt)"),
+       "!x{expr}\n",   N_("insert expr if x is not set\n(where x is one of the dfNFLIstcnriT characters or ad, af, ao, aT, ABc, ABf, ABt)"),
        "|f{sub_expr}\n",       N_("insert file:\nsub_expr is evaluated as a filename to insert"), /* insert file */
        "|p{sub_expr}\n\n",     N_("insert program output:\nsub_expr is evaluated as a command-line to get\nthe output from"), /* insert program output */
        "|i{sub_expr}\n\n",     N_("insert user input:\nsub_expr is a variable to be replaced by\nuser-entered text"), /* insert user input */
index 26d9b6a38b4bbd69f09bf2c3e8c5ba027f37c19d..8e43d3cdb62a9b52693e7f559c8786bd7a53730f 100644 (file)
@@ -2,6 +2,8 @@
 
 #define __QUOTE_FMT_H__
 
+#include "gtkaspell.h"
+
 #define quote_fmt_parse        quote_fmtparse
 
 void quote_fmt_quote_description(void);
@@ -9,7 +11,8 @@ void quote_fmt_quote_description(void);
 gchar *quote_fmt_get_buffer(void);
 void quote_fmt_init(MsgInfo *info, const gchar *my_quote_str,
                    const gchar *my_body, gboolean my_dry_run,
-                       PrefsAccount *account);
+                       PrefsAccount *account,
+                       GtkAspell *gtkaspell);
 gint quote_fmtparse(void);
 void quote_fmt_scan_string(const gchar *str);
 void quote_fmt_reset_vartable(void);
index 4022c06b85968acc53e677b801e7367e479f5355..13ac3fab19145304049d02e72132bf24e81b39ba 100644 (file)
@@ -35,6 +35,7 @@
  * see notes below.
  */
 int quote_fmt_firsttime = 1;
+int line = -1;
 %}
 
 %%
@@ -86,16 +87,21 @@ int quote_fmt_firsttime = 1;
 <S_NORMAL>"%r" /* references */ return SHOW_REFERENCES;
 <S_NORMAL>"%s" /* subject */ return SHOW_SUBJECT;
 <S_NORMAL>"%t" /* to */ return SHOW_TO;
+<S_NORMAL>"%T" /* current dictionary */ return SHOW_DICT;
 <S_NORMAL>"%Q" /* quoted message */ return SHOW_QUOTED_MESSAGE;
 <S_NORMAL>"%q" /* quoted message with no signature */ return SHOW_QUOTED_MESSAGE_NO_SIGNATURE;
 <S_NORMAL>"%af" /* full name in compose account */ return SHOW_ACCOUNT_FULL_NAME;
 <S_NORMAL>"%am" /* mail address in compose account */ return SHOW_ACCOUNT_MAIL_ADDRESS;
 <S_NORMAL>"%an" /* compose account name itself */ return SHOW_ACCOUNT_NAME;
 <S_NORMAL>"%ao" /* organization in compose account */ return SHOW_ACCOUNT_ORGANIZATION;
+<S_NORMAL>"%aT" /* main dict (if enabled) in compose account */ return SHOW_ACCOUNT_DICT;
+<S_NORMAL>"%ABc" /* completion of 'Cc' from the address book */ return SHOW_ADDRESSBOOK_COMPLETION_FOR_CC;
+<S_NORMAL>"%ABf" /* completion of 'From' from the address book */ return SHOW_ADDRESSBOOK_COMPLETION_FOR_FROM;
+<S_NORMAL>"%ABt" /* completion of 'To' from the address book */ return SHOW_ADDRESSBOOK_COMPLETION_FOR_TO;
 "\\\%" /* % */ return SHOW_PERCENT;
 "\\\\" /* \ */ return SHOW_BACKSLASH;
 "\\t"|"\t" /* tab */ return SHOW_TAB;
-"\\n"|"\n" /* return */ return SHOW_EOL;
+"\\n"|"\n" /* return */ { if (yytext[0] == '\n') line++; return SHOW_EOL; }
 "\\?" /* ? */ return SHOW_QUESTION_MARK;
 "\\!" return SHOW_EXCLAMATION_MARK;
 "\\|" return SHOW_PIPE;
@@ -106,12 +112,17 @@ int quote_fmt_firsttime = 1;
 "?N"|"?F"|"?L"|"?I" /* query from name */ return QUERY_FULLNAME;
 "?s" /* query subject */ return QUERY_SUBJECT;
 "?t" /* query to */ return QUERY_TO;
+"?T" /* query current dictionary set and enabled */ return QUERY_DICT;
 "?c" /* query cc */ return QUERY_CC;
 "?n" /* query newsgroups */ return QUERY_NEWSGROUPS;
 "?i" /* query message-id */ return QUERY_MESSAGEID;
 "?r" /* query references */ return QUERY_REFERENCES;
 "?af" /* query full name in compose account */ return QUERY_ACCOUNT_FULL_NAME;
 "?ao" /* query organization in compose account */ return QUERY_ACCOUNT_ORGANIZATION;
+"?aT" /* query account main dict enabled */ return QUERY_ACCOUNT_DICT;
+"?ABc" /* query completion for 'Cc' in address book */ return QUERY_CC_FOUND_IN_ADDRESSBOOK;
+"?ABf" /* query completion for 'From' in address book */ return QUERY_FROM_FOUND_IN_ADDRESSBOOK;
+"?ABt" /* query completion for 'To' in address book */ return QUERY_TO_FOUND_IN_ADDRESSBOOK;
 "|f" /* insert file */ return INSERT_FILE;
 "|p" /* insert program output */ return INSERT_PROGRAMOUTPUT;
 "|i" /* insert user input */ return INSERT_USERINPUT;
@@ -120,12 +131,17 @@ int quote_fmt_firsttime = 1;
 "!N"|"!F"|"!L"|"!I" /* query not(from name) */ return QUERY_NOT_FULLNAME;
 "!s" /* query not(subject) */ return QUERY_NOT_SUBJECT;
 "!t" /* query not(to) */ return QUERY_NOT_TO;
+"!T" /* query not(current dictionary set and enabled) */ return QUERY_NOT_DICT;
 "!c" /* query not(cc) */ return QUERY_NOT_CC;
 "!n" /* query not(newsgroups) */ return QUERY_NOT_NEWSGROUPS;
 "!i" /* query not(message-id) */ return QUERY_NOT_MESSAGEID;
 "!r" /* query not(references) */ return QUERY_NOT_REFERENCES;
 "!af" /* query not(full name in compose account) */ return QUERY_NOT_ACCOUNT_FULL_NAME;
 "!ao" /* query not(organization in compose account) */ return QUERY_NOT_ACCOUNT_ORGANIZATION;
+"!aT" /* query not(account main dict enabled and set) */ return QUERY_NOT_ACCOUNT_DICT;
+"!ABc" /* query not(completion for 'Cc' in address book) */ return QUERY_NOT_CC_FOUND_IN_ADDRESSBOOK;
+"!ABf" /* query not(completion for 'From' in address book) */ return QUERY_NOT_FROM_FOUND_IN_ADDRESSBOOK;
+"!ABt" /* query not(completion for 'To' in address book) */ return QUERY_NOT_TO_FOUND_IN_ADDRESSBOOK;
 <S_DATE>"{" return OPARENT;
 <S_DATE>"}" { BEGIN S_NORMAL; return CPARENT; }
 <S_NORMAL>"{" return OPARENT;
index 42e92ab42558af56cf5e7743805cf088f55a2bb2..4fc60904ba737e9d20a26c3c4cefe40b2ee36353 100644 (file)
@@ -31,6 +31,7 @@
 #include "utils.h"
 #include "codeconv.h"
 #include "procheader.h"
+#include "addr_compl.h"
 #include "gtk/inputdialog.h"
 
 #include "quote_fmt.h"
@@ -46,6 +47,7 @@ int yylex(void);
 
 static MsgInfo *msginfo = NULL;
 static PrefsAccount *account = NULL;
+static gchar default_dictionary[BUFFSIZE];
 static gboolean *visible = NULL;
 static gboolean dry_run = FALSE;
 static gint maxsize = 0;
@@ -70,6 +72,7 @@ static gint error = 0;
 static gint cursor_pos = -1;
 
 extern int quote_fmt_firsttime;
+extern int line;
 
 static void add_visibility(gboolean val)
 {
@@ -160,12 +163,18 @@ void quote_fmt_reset_vartable(void)
 
 void quote_fmt_init(MsgInfo *info, const gchar *my_quote_str,
                    const gchar *my_body, gboolean my_dry_run,
-                       PrefsAccount *compose_account)
+                       PrefsAccount *compose_account,
+                       GtkAspell *compose_gtkaspell)
 {
+       gchar *dict = gtkaspell_get_default_dictionary(compose_gtkaspell);
        quote_str = my_quote_str;
        body = my_body;
        msginfo = info;
        account = compose_account;
+       if (dict)
+               strncpy2(default_dictionary, dict, sizeof(default_dictionary));
+       else
+               *default_dictionary = '\0';
        dry_run = my_dry_run;
        stacksize = 0;
        add_visibility(TRUE);
@@ -174,6 +183,7 @@ void quote_fmt_init(MsgInfo *info, const gchar *my_quote_str,
        current = &main_expr;
        clear_buffer();
        error = 0;
+       line = 1;
 
        if (!var_table)
                var_table = g_hash_table_new_full(g_str_hash, g_str_equal, 
@@ -188,7 +198,7 @@ void quote_fmt_init(MsgInfo *info, const gchar *my_quote_str,
 
 void quote_fmterror(char *str)
 {
-       g_warning("Error: %s\n", str);
+       g_warning("Error: %s at line %d\n", str, line);
        error = 1;
 }
 
@@ -478,6 +488,44 @@ static void quote_fmt_insert_user_input(const gchar *varname)
        g_free(text);
 }
 
+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 {
@@ -494,16 +542,29 @@ static void quote_fmt_insert_user_input(const gchar *varname)
 %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
+%token SHOW_DICT
+%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
+%token QUERY_ACCOUNT_FULL_NAME QUERY_ACCOUNT_ORGANIZATION QUERY_ACCOUNT_DICT
+%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
+%token QUERY_NOT_ACCOUNT_FULL_NAME QUERY_NOT_ACCOUNT_ORGANIZATION QUERY_NOT_ACCOUNT_DICT
+%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 OPARENT CPARENT
@@ -684,6 +745,18 @@ special:
                if (account && account->organization)
                        INSERT(account->organization);
        }
+       | SHOW_ACCOUNT_DICT
+       {
+               if (account && account->enable_default_dictionary) {
+                       gchar *dictname = g_path_get_basename(account->default_dictionary);
+                       INSERT(dictname);
+                       g_free(dictname);
+               }
+       }
+       | SHOW_DICT
+       {
+               INSERT(default_dictionary);
+       }
        | SHOW_BACKSLASH
        {
                INSERT("\\");
@@ -719,6 +792,30 @@ special:
        | SET_CURSOR_POS
        {
                cursor_pos = current->bufsize;
+       }
+       | 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:
@@ -814,6 +911,53 @@ query:
                add_visibility(account != NULL && account->organization != NULL);
        }
        OPARENT quote_fmt CPARENT
+       {
+               remove_visibility();
+       }
+       | QUERY_ACCOUNT_DICT
+       {
+               add_visibility(account != NULL && account->enable_default_dictionary == TRUE &&
+                               account->default_dictionary != NULL && *account->default_dictionary != '\0');
+       }
+       OPARENT quote_fmt CPARENT
+       {
+               remove_visibility();
+       }
+       | QUERY_DICT
+       {
+               add_visibility(*default_dictionary != '\0');
+       }
+       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();
        };
@@ -911,6 +1055,53 @@ query_not:
                add_visibility(account == NULL || account->organization == NULL);
        }
        OPARENT quote_fmt CPARENT
+       {
+               remove_visibility();
+       }
+       | QUERY_NOT_ACCOUNT_DICT
+       {
+               add_visibility(account == NULL || account->enable_default_dictionary == FALSE
+                               || *account->default_dictionary == '\0');
+       }
+       OPARENT quote_fmt CPARENT
+       {
+               remove_visibility();
+       }
+       | QUERY_NOT_DICT
+       {
+               add_visibility(*default_dictionary == '\0');
+       }
+       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();
        };