sync with sylpheed 0.6.4cvs18
authorPaul Mangan <paul@claws-mail.org>
Wed, 7 Nov 2001 10:29:45 +0000 (10:29 +0000)
committerPaul Mangan <paul@claws-mail.org>
Wed, 7 Nov 2001 10:29:45 +0000 (10:29 +0000)
41 files changed:
ChangeLog
ChangeLog.claws
ChangeLog.jp
INSTALL
INSTALL.jp
NEWS
README
README.jp
TODO
TODO.jp
configure.in
po/POTFILES.in
src/Makefile.am
src/account.c
src/compose.c
src/compose.h
src/defs.h
src/filter.c
src/inputdialog.c
src/inputdialog.h
src/mainwindow.c
src/mh.c
src/mimeview.c
src/news.c
src/pixmaps/checkbox_off.xpm [new file with mode: 0644]
src/pixmaps/checkbox_on.xpm [new file with mode: 0644]
src/prefs_common.c
src/prefs_common.h
src/prefs_template.c [new file with mode: 0644]
src/prefs_template.h [new file with mode: 0644]
src/procheader.c
src/quote_fmt.h
src/quote_fmt_lex.l
src/quote_fmt_parse.y
src/send.c
src/summaryview.c
src/template.c
src/template.h
src/textview.c
src/utils.c
src/utils.h

index 9eb88d3..e4d040a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,118 @@
+2001-11-06
+
+       * src/template.c: changed the format of template file to
+         RFC2822-like.
+       * src/compose.c: compose_template_apply(): freeze the text widget
+         while inserting strings.
+
+2001-11-05
+
+       * po/POTFILES.in: removed src/template_select.c.
+       * src/summaryview.c: summary_set_header()
+         src/address.c: address_parse_str()
+         src/filter.c: filter_read_str()
+         src/news.c: news_parse_xover()
+         src/procheader.c: procheader_get_fromname()
+         src/utils.c: subject_compare():
+         replaced Xalloca() + strcpy() with Xstrdup_a().
+       * src/inputdialog.[ch]: added combo mode.
+         input_dialog_combo(): new.
+       * src/prefs_common.[ch]: added MIME open command setting.
+         prefs_common_{read, save}_config(): read / write command history.
+       * src/mimeview.c: mimeview_open_with(): use combo input dialog.
+       * src/utils.[ch]: add_history(): history list management function.
+
+2001-11-04
+
+       * src/compose.c: select templates from the menu.
+         compose_set_template_menu(): new.
+         compose_reflect_prefs_all(): new.
+         compose_template_apply(): new. Use dummy MsgInfo for parsing.
+       * src/template.[ch]: store template list to the static heap.
+         template_get_config(): new.
+         template_set_config(): new.
+       * src/prefs_template.c: don't store template list to the global area.
+       * src/template_select.[ch]: removed.
+       * src/quote_fmt_parse.y: check folderitem when quoting messages.
+       * src/mh.c: mh_add_msg(): try to copy file whenever link() failed
+         (thanks to OSHIRO Naoki).
+
+2001-11-03
+
+       * src/utils.[ch]: get_template_dir(): new.
+       * src/template.c: use get_template_dir().
+
+2001-11-02
+
+       * src/prefs_template.c: modified the dialog layout.
+         Added symbol description button.
+       * src/summaryview.c: show an arrow mark to the column of the sort
+         target.
+         summary_set_column_titles(): new.
+       * INSTALL
+         INSTALL.jp
+         README
+         README.jp
+         TODO
+         TODO.jp: updated the documents.
+
+2001-11-02
+
+       * src/Makefile.am: add missing checkbox_{on, off}.xpm.
+       * src/textview.c: textview_key_pressed()
+         src/mimeview.c: mimeview_key_pressed()
+         src/summaryview.c: summary_key_pressed(): delete messages with
+         Delete key.
+
+2001-11-01
+
+       * src/socket.c: ssl_gets(): fixed a bug that caused infinite loop
+         when SSL_read() returned 0.
+       * src/utils.[ch]: strcrchomp(): new. It removes CR from the tail
+         of strings.
+       * src/quote_fmt_parse.y: convert CRLF to LF when inserting messages.
+         Add prototype of yylex() to suppress the warning.
+       * merged the template function.
+       * src/prefs_template.[ch]
+         src/template.[ch]
+         src/template_select.[ch]: new.
+         Renamed prefs_templates_* -> prefs_template_*.
+       * src/compose.c: added template menu. Added replyinfo to Compose.
+       * src/mainwindow.c: added template setting menu.
+       * src/quote_fmt_lex.l: output literal tab and return as is.
+       * src/prefs_common.c: changed the pref. name of quote format to
+         'reply_quote_{mark, format}' and 'fw_quote_{mark, format}'.
+
+2001-10-31
+
+       * src/prefs_common.[ch]: added Quote tab, and moved the quote
+         setting from Compose tab.
+       * merged the new quote format parser.
+       * src/quote_fmt_lex.h
+         src/quote_fmt.h
+         src/quote_fmt_lex.l
+         src/quote_fmt_parse.y: new files for quote format parser.
+       * configure.in: added checks for lex and yacc.
+       * src/compose.c: compose_quote_file(), compose_quote_parse_fmt():
+         removed.
+         compose_quote_fmt(): new.
+       * src/prefs_common.[ch]: added forward format setting to the
+         Quote tab. Updated the quote description dialog.
+       * src/quote_fmt_parse.y: fixed bugs that tried to read file even
+         if they couldn't get text part.
+
+2001-10-31
+
+       * src/pixmaps/checkbox_off.xpm
+         src/pixmaps/checkbox_on.xpm: new.
+       * src/account.c: display `get all' status with the checkbox pixmaps.
+
+2001-10-30
+
+       * src/send.c: code cleanup. Pass account prefs structure instead
+         of many arguments.
+         Query password for SMTP AUTH if not specified (thanks to Mio).
+
 2001-10-30
 
        * src/procheader.c: procheader_parse(): fixed a bug that didn't
index dbcb358..e3680e8 100644 (file)
@@ -1,3 +1,9 @@
+2001-11-07 [paul]      0.6.4claws31
+
+       * sync with sylpheed 0.6.4cvs18
+               see ChangeLog entries 2001-10-30 to 2001-11-07
+               prefs_templates.[ch] renamed prefs_template.[ch]
+
 2001-11-06 [alfons]
        
        * src/utils.h
index d86e404..4818130 100644 (file)
@@ -1,3 +1,123 @@
+2001-11-06
+
+       * src/template.c: ¥Æ¥ó¥×¥ì¡¼¥È¥Õ¥¡¥¤¥ë¤Î¥Õ¥©¡¼¥Þ¥Ã¥È¤ò RFC2822
+         ¥é¥¤¥¯¤ËÊѹ¹¡£
+       * src/compose.c: compose_template_apply(): Ê¸»úÎó¤òÁÞÆþ¤·¤Æ¤¤¤ë
+         ´Ö¥Æ¥­¥¹¥È¥¦¥£¥¸¥§¥Ã¥È¤ò freeze ¤¹¤ë¤è¤¦¤Ë¤·¤¿¡£
+
+2001-11-05
+
+       * po/POTFILES.in: src/template_select.c ¤òºï½ü¡£
+       * src/summaryview.c: summary_set_header()
+         src/address.c: address_parse_str()
+         src/filter.c: filter_read_str()
+         src/news.c: news_parse_xover()
+         src/procheader.c: procheader_get_fromname()
+         src/utils.c: subject_compare():
+         Xalloca() + strcpy() ¤ò Xstrdup_a() ¤ÇÃÖ´¹¡£
+       * src/inputdialog.[ch]: combo ¥â¡¼¥É¤òÄɲá£
+         input_dialog_combo(): ¿·µ¬¡£
+       * src/prefs_common.[ch]: MIME ¥ª¡¼¥×¥ó¥³¥Þ¥ó¥É¤ÎÀßÄê¤òÄɲá£
+         prefs_common_{read, save}_config(): ¥³¥Þ¥ó¥É¥Ò¥¹¥È¥ê¤ÎÆɤ߽ñ¤­¡£
+       * src/mimeview.c: mimeview_open_with(): combo ÆþÎÏ¥À¥¤¥¢¥í¥°¤ò»ÈÍÑ¡£
+       * src/utils.[ch]: add_history(): ¥Ò¥¹¥È¥ê¥ê¥¹¥È´ÉÍý´Ø¿ô¡£
+
+2001-11-04
+
+       * src/compose.c: ¥Æ¥ó¥×¥ì¡¼¥È¤ò¥á¥Ë¥å¡¼¤«¤éÁªÂò¤¹¤ë¤è¤¦¤Ë¤·¤¿¡£
+         compose_set_template_menu(): ¿·µ¬¡£
+         compose_reflect_prefs_all(): ¿·µ¬¡£
+         compose_template_apply(): ¿·µ¬¡£¥Ñ¡¼¥¹¤¹¤ë¤¿¤á¤Ë¥À¥ß¡¼¤Î MsgInfo
+         ¤ò»ÈÍÑ¡£
+       * src/template.[ch]: ¥Æ¥ó¥×¥ì¡¼¥È¥ê¥¹¥È¤ò static ¤Ê¥Ò¡¼¥×¤ËÊݸ¡£
+         template_get_config(): ¿·µ¬¡£
+         template_set_config(): ¿·µ¬¡£
+       * src/prefs_template.c: ¥Æ¥ó¥×¥ì¡¼¥È¥ê¥¹¥È¤ò¥°¥í¡¼¥Ð¥ë¤ÊÎΰè¤ËÊݸ
+         ¤·¤Ê¤¤¤è¤¦¤Ë¤·¤¿¡£
+       * src/template_select.[ch]: ºï½ü¡£
+       * src/quote_fmt_parse.y: ¥á¥Ã¥»¡¼¥¸¤ò°úÍѤ¹¤ë¤È¤­¤Ë folderitem ¤ò
+         ¥Á¥§¥Ã¥¯¡£
+       * src/mh.c: mh_add_msg(): link() ¤¬¼ºÇÔ¤·¤¿¤È¤­¤Ï¾ï¤Ë¥Õ¥¡¥¤¥ë¤ò
+         ¥³¥Ô¡¼¤¹¤ë¤è¤¦¤Ë¤·¤¿(Âç¾ë¤µ¤ó thanks)¡£
+
+2001-11-03
+
+       * src/utils.[ch]: get_template_dir(): ¿·µ¬¡£
+       * src/template.c: get_template_dir() ¤ò»ÈÍÑ¡£
+
+2001-11-02
+
+       * src/prefs_template.c: ¥À¥¤¥¢¥í¥°¤Î¥ì¥¤¥¢¥¦¥È¤ò½¤Àµ¡£
+         µ­¹æ¤ÎÀâÌÀ¥Ü¥¿¥ó¤òÄɲá£
+       * src/summaryview.c: ¥½¡¼¥ÈÂоݤΥ«¥é¥à¤ËÌð°õ¥Þ¡¼¥¯¤òɽ¼¨¡£
+         summary_set_column_titles(): ¿·µ¬¡£
+       * INSTALL
+         INSTALL.jp
+         README
+         README.jp
+         TODO
+         TODO.jp: ¥É¥­¥å¥á¥ó¥È¤ò¹¹¿·¡£
+
+2001-11-02
+
+       * src/Makefile.am: checkbox_{on, off}.xpm ¤¬È´¤±¤Æ¤¤¤¿¤Î¤ÇÄɲá£
+       * src/textview.c: textview_key_pressed()
+         src/mimeview.c: mimeview_key_pressed()
+         src/summaryview.c: summary_key_pressed(): Delete ¥­¡¼¤Ç¥á¥Ã¥»¡¼¥¸
+         ¤òºï½ü¤¹¤ë¤è¤¦¤Ë¤·¤¿¡£
+
+2001-11-01
+
+       * src/socket.c: ssl_gets(): SSL_read() ¤¬ 0 ¤òÊÖ¤·¤¿¤È¤­¤Ë̵¸Â
+         ¥ë¡¼¥×¤Ë´Ù¤ë¥Ð¥°¤ò½¤Àµ¡£
+       * src/utils.[ch]: strcrchomp(): ¿·µ¬¡£Ê¸»úÎó¤ÎËöÈø¤«¤é CR ¤ò½üµî
+         ¤¹¤ë¡£
+       * src/quote_fmt_parse.y: ¥á¥Ã¥»¡¼¥¸ÁÞÆþ»þ¤Ë CRLF ¤ò LF ¤ËÊÑ´¹¡£
+         ·Ù¹ð¤òÍÞÀ©¤¹¤ë¤¿¤á¤Ë yylex() ¤Î¥×¥í¥È¥¿¥¤¥×¤òÄɲá£
+       * ¥Æ¥ó¥×¥ì¡¼¥Èµ¡Ç½¤ò¥Þ¡¼¥¸¡£
+       * src/prefs_template.[ch]
+         src/template.[ch]
+         src/template_select.[ch]: ¿·µ¬¡£
+         prefs_templates_* -> prefs_template_* ¤Ë̾¾ÎÊѹ¹¡£
+       * src/compose.c: ¥Æ¥ó¥×¥ì¡¼¥È¥á¥Ë¥å¡¼¤òÄɲᣠreplyinfo ¤ò Compose
+         ¤ËÄɲá£
+       * src/mainwindow.c: ¥Æ¥ó¥×¥ì¡¼¥ÈÀßÄê¥á¥Ë¥å¡¼¤òÄɲá£
+       * src/quote_fmt_lex.l: ¥¿¥Ö¤È²þ¹Ôʸ»ú¤ò¤½¤Î¤Þ¤Þ½ÐÎϤ¹¤ë¤è¤¦¤Ë¤·¤¿¡£
+       * src/prefs_common.c: °úÍÑ¥Õ¥©¡¼¥Þ¥Ã¥È¤ÎÀßÄê̾¤ò
+         'reply_quote_{mark, format}' ¤È 'fw_quote_{mark, format}' ¤ËÊѹ¹¡£
+
+2001-10-31
+
+       * src/prefs_common.[ch]: °úÍÑ¥¿¥Ö¤òÄɲä·¡¢°úÍÑÀßÄê¤òºîÀ®¥¿¥Ö¤«¤é
+         °ÜÆ°¡£
+       * ¿·°úÍÑ¥Õ¥©¡¼¥Þ¥Ã¥È¥Ñ¡¼¥µ¤ò¥Þ¡¼¥¸¡£
+       * src/quote_fmt_lex.h
+         src/quote_fmt.h
+         src/quote_fmt_lex.l
+         src/quote_fmt_parse.y: °úÍÑ¥Õ¥©¡¼¥Þ¥Ã¥È¥Ñ¡¼¥µÍÑ¿·µ¬¥Õ¥¡¥¤¥ë¡£
+       * configure.in: lex ¤È yacc ¤Î¥Á¥§¥Ã¥¯¤òÄɲá£
+       * src/compose.c: compose_quote_file(), compose_quote_parse_fmt():
+         ºï½ü¡£
+         compose_quote_fmt(): ¿·µ¬¡£
+       * src/prefs_common.[ch]: °úÍÑ¥¿¥Ö¤ËžÁ÷¥Õ¥©¡¼¥Þ¥Ã¥È¤ÎÀßÄê¤òÄɲá£
+         °úÍѵ­¹æ¤ÎÀâÌÀ¥À¥¤¥¢¥í¥°¤ò¹¹¿·¡£
+       * src/quote_fmt_parse.y: ¥Æ¥­¥¹¥È¥Ñ¡¼¥È¤¬¼èÆÀ¤Ç¤­¤Ê¤¯¤Æ¤â¥Õ¥¡¥¤¥ë¤ò
+         Æɤ߹þ¤â¤¦¤È¤¹¤ë¥Ð¥°¤ò½¤Àµ¡£
+
+2001-10-31
+
+       * src/pixmaps/checkbox_off.xpm
+         src/pixmaps/checkbox_on.xpm: ¿·µ¬¡£
+       * src/account.c: ¡ÖÁ´¼õ¿®¡×¤Î¥¹¥Æ¡¼¥¿¥¹¤ò¥Á¥§¥Ã¥¯¥Ü¥Ã¥¯¥¹¤Î pixmap
+         ¤Çɽ¼¨¤¹¤ë¤è¤¦¤Ë¤·¤¿¡£
+
+2001-10-30
+
+       * src/send.c: ¥³¡¼¥É¤ÎÀ°Íý¡£¤¿¤¯¤µ¤ó¤Î°ú¿ô¤ÎÂå¤ï¤ê¤Ë¥¢¥«¥¦¥ó¥È
+         ÀßÄ깽¤ÂΤòÅϤ¹¤è¤¦¤Ë¤·¤¿¡£
+         SMTP AUTH ¤Î¥Ñ¥¹¥ï¡¼¥É¤¬»ØÄꤵ¤ì¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ï¿Ò¤Í¤ë¤è¤¦¤Ë¤·¤¿¡£
+         (Mio ¤µ¤ó thanks)¡£
+
 2001-10-30
 
        * src/procheader.c: procheader_parse(): In-Reply-To: ¥Ø¥Ã¥À¤Î
diff --git a/INSTALL b/INSTALL
index 556d9b4..0f2e8c3 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -45,6 +45,7 @@ o Linux Mandrake 7.0
 o Linux Mandrake 7.1
 o Linux Mandrake 7.2
 o Linux Mandrake 8.0
+o Linux Mandrake 8.1
 o SuSE Linux 6.3 (glibc 2.1.2)
 o SuSE Linux 6.4
 o SuSE Linux 7.0
index 20d88a7..7686a79 100644 (file)
@@ -44,6 +44,7 @@ o Linux Mandrake 7.0
 o Linux Mandrake 7.1
 o Linux Mandrake 7.2
 o Linux Mandrake 8.0
+o Linux Mandrake 8.1
 o SuSE Linux 6.3 (glibc 2.1.2)
 o SuSE Linux 6.4
 o SuSE Linux 7.0
diff --git a/NEWS b/NEWS
index 53df349..25e7583 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,18 @@
 Changes of Sylpheed
 
+* 0.6.5
+
+    * The template function has been implemented.
+    * The quotation format parser has been enhanced.
+    * The forwarding format has become customizable.
+    * The "Open with..." dialog on the MIME view now retains command history.
+    * An arrow mark is put on the column of the sorting target.
+    * The Delete key now deletes messages.
+    * The password for SMTP AUTH is asked now when not specified.
+    * The mime.types file is searched from several directories now.
+    * The preferences dialogs have been sorted out a bit.
+    * Some bugs have been fixed.
+
 * 0.6.4
 
     * The performance of summary display on large number of messages
diff --git a/README b/README
index 50bbb31..d526c56 100644 (file)
--- a/README
+++ b/README
@@ -58,6 +58,7 @@ Currently implemented features are:
        o message queueing
        o automatic mail checking
        o draft message function
+       o template function
        o line-wrapping
        o clickable URI
        o XML-based address book
@@ -86,6 +87,24 @@ See INSTALL for installation instructions.
 Usage
 =====
 
+Preparation before running
+--------------------------
+
+If you want to use characters other than English (aka US-ASCII),
+you must specify some environmental variables related to locale.
+For example:
+
+% export LANG=de_DE    (sh, bash etc.)
+
+or
+
+% setenv LANG de_DE    (csh, tcsh etc.)
+
+(replace de_DE to appropriate locale name)
+
+If you don't want translated messages, set LC_MESSAGES to "C"
+(and unset LC_ALL if specified).
+
 How to run
 ----------
 
@@ -156,5 +175,5 @@ To update to the newest source tree, run the command:
 
 on the top directory of the source tree.
 
---
+-- 
 Hiroyuki Yamamoto <hiro-y@kcn.ne.jp>
index 0eba7d7..e34c18f 100644 (file)
--- a/README.jp
+++ b/README.jp
@@ -76,6 +76,7 @@ Wanderlust 
        o Á÷¿®ÂÔµ¡µ¡Ç½
        o ¼«Æ°¥á¡¼¥ë¥Á¥§¥Ã¥¯µ¡Ç½
        o Áð¹Æµ¡Ç½
+       o ¥Æ¥ó¥×¥ì¡¼¥Èµ¡Ç½
        o ¼«Æ°²þ¹Ôµ¡Ç½
        o ¥¯¥ê¥Ã¥«¥Ö¥ë URI
        o XML ¥Ù¡¼¥¹¤Î¥¢¥É¥ì¥¹Ä¢
@@ -110,16 +111,16 @@ Wanderlust 
 ´Ä¶­ÊÑ¿ô¤ò»ØÄꤷ¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó(ÆüËܸì Linux ¥Ç¥£¥¹¥È¥ê¥Ó¥å¡¼¥·¥ç¥ó
 ¤Î¾ì¹ç¤ÏÂçÄñ¤¹¤Ç¤ËÀßÄꤵ¤ì¤Æ¤¤¤Þ¤¹)¡£Î㤨¤Ð¡¢
 
-% export LANG=ja_JP.eucJP
+% export LANG=ja_JP.eucJP      (sh, bash etc.)
 
 ¤Þ¤¿¤Ï
 
-% setenv LANG ja_JP.eucJP
+% setenv LANG ja_JP.eucJP      (csh, tcsh etc.)
 
 (ja_JP.eucJP ¤ÏŬÀÚ¤Ê¥í¥«¡¼¥ë̾¤ËÃÖ¤­´¹¤¨¤Æ¤¯¤À¤µ¤¤¡£)
 
-ËÝÌõ¤µ¤ì¤¿¥á¥Ã¥»¡¼¥¸¤ÎÊý¤¬Îɤ±¤ì¤Ð¡¢ LANG ¤ÈƱÍͤˠLC_MESSAGES ¤â»ØÄꤷ¤Æ
-¤¯¤À¤µ¤¤¡£
+ËÝÌõ¤µ¤ì¤¿¥á¥Ã¥»¡¼¥¸¤¬É¬Íפʤ±¤ì¤Ð¡¢ LC_MESSAGES ¤ò "C" ¤Ë»ØÄꤷ¤Æ
+¤¯¤À¤µ¤¤(LC_ALL ¤¬»ØÄꤵ¤ì¤Æ¤¤¤ì¤Ð³°¤·¤Æ¤¯¤À¤µ¤¤)¡£
 
 µ¯Æ°ÊýË¡
 --------
diff --git a/TODO b/TODO
index a45a789..4da8c1c 100644 (file)
--- a/TODO
+++ b/TODO
@@ -6,7 +6,6 @@ TODO
 o POP before SMTP
 o original icons and logos
 o autosave
-o template function
 o speed-up of filtering
 o regular expression support at filtering
 o support for some formats other than MH and mbox (ex. Maildir)
@@ -68,3 +67,4 @@ Implemented features
 * SSL support
 * LDAP support
 * full-text search of messages (plain)
+* template function
diff --git a/TODO.jp b/TODO.jp
index 46405dc..b56f7c7 100644 (file)
--- a/TODO.jp
+++ b/TODO.jp
@@ -6,7 +6,6 @@ TODO
 o POP before SMTP
 o ¥ª¥ê¥¸¥Ê¥ë¤Î¥¢¥¤¥³¥ó¤È¥í¥´
 o ¼«Æ°Êݸµ¡Ç½
-o ¥Æ¥ó¥×¥ì¡¼¥Èµ¡Ç½
 o ¿¶¤êʬ¤±½èÍý¤Î¶¯²½
 o ¿¶¤êʬ¤±¤ÇÀµµ¬É½¸½¤ËÂбþ¤¹¤ë
 o MH, mbox °Ê³°¤Î·Á¼°¤Ø¤ÎÂбþ(Maildir Åù)
@@ -69,3 +68,4 @@ o 
 * SSLÂбþ
 * LDAPÂбþ
 * ¥á¥Ã¥»¡¼¥¸¤ÎÁ´Ê¸¸¡º÷ (¥Ù¥¿)
+* ¥Æ¥ó¥×¥ì¡¼¥Èµ¡Ç½
index 7683cf1..03c42d4 100644 (file)
@@ -8,7 +8,7 @@ MINOR_VERSION=6
 MICRO_VERSION=4
 INTERFACE_AGE=0
 BINARY_AGE=0
-EXTRA_VERSION=claws30
+EXTRA_VERSION=claws31
 VERSION=$MAJOR_VERSION.$MINOR_VERSION.$MICRO_VERSION$EXTRA_VERSION
 
 dnl
index a37d82c..35543da 100644 (file)
@@ -66,7 +66,8 @@ src/prefs_filter.c
 src/prefs_filtering.c
 src/prefs_matcher.c
 src/prefs_scoring.c
-src/prefs_templates.c
+src/prefs_summary_column.c
+src/prefs_template.c
 src/procheader.c
 src/procmime.c
 src/procmsg.c
@@ -88,6 +89,7 @@ src/statusbar.c
 src/summary_search.c
 src/summaryview.c
 src/syldap.c
+src/template.c
 src/textview.c
 src/unmime.c
 src/utils.c
index b027ff5..22640f7 100644 (file)
@@ -31,9 +31,11 @@ sylpheed_SOURCES = \
        prefs_display_header.c prefs_display_header.h \
        prefs_customheader.c prefs_customheader.h \
        prefs_summary_column.c prefs_summary_column.h \
+       prefs_template.c prefs_template.h \
        account.c account.h \
        displayheader.c displayheader.h \
        customheader.c customheader.h \
+       template.c template.h \
        addressbook.c addressbook.h \
        addr_compl.c addr_compl.h \
        addressitem.h \
@@ -118,10 +120,12 @@ sylpheed_SOURCES = \
        quote_fmt_lex.l quote_fmt_lex.h \
        quote_fmt_parse.y quote_fmt.h \
        gtkspell.c gtkspell.h gtkxtext.h \
-       template.c template.h \
-       prefs_templates.c prefs_templates.h \
        template_select.c template_select.h
 
+BUILT_SOURCES = \
+       quote_fmt_lex.c \
+       quote_fmt_parse.c \
+       quote_fmt_parse.h
 
 EXTRA_DIST = \
        quote_fmt_parse.h \
@@ -135,6 +139,8 @@ EXTRA_DIST = \
        pixmaps/group.xpm \
        pixmaps/inbox.xpm \
        pixmaps/mark.xpm \
+       pixmaps/checkbox_on.xpm \
+       pixmaps/checkbox_off.xpm \
        pixmaps/new.xpm \
        pixmaps/outbox.xpm \
        pixmaps/regular.xpm \
@@ -202,9 +208,3 @@ CPPFLAGS = \
        -DSYSCONFDIR=\""$(sysconfdir)"\"
 
 YFLAGS = -d
-
-
-BUILT_SOURCES = \
-       quote_fmt_lex.c \
-       quote_fmt_parse.c \
-       quote_fmt_parse.h
index a7ff826..8b07889 100644 (file)
@@ -46,6 +46,8 @@
 #include "alertpanel.h"
 
 #include "pixmaps/mark.xpm"
+#include "pixmaps/checkbox_on.xpm"
+#include "pixmaps/checkbox_off.xpm"
 
 typedef enum
 {
@@ -72,6 +74,10 @@ static struct EditAccount {
 
 static GdkPixmap *markxpm;
 static GdkBitmap *markxpmmask;
+static GdkPixmap *checkboxonxpm;
+static GdkPixmap *checkboxonxpmmask;
+static GdkPixmap *checkboxoffxpm;
+static GdkPixmap *checkboxoffxpmmask;
 
 static void account_edit_create                (void);
 
@@ -418,8 +424,8 @@ static void account_edit_create(void)
        gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
 
        label = gtk_label_new
-               (_("New messages will be checked in this order. Click in the 'G' column\n"
-                  "to enable message retrieval by `Get all' for that account."));
+               (_("New messages will be checked in this order. Check the boxes\n"
+                  "on the `G' column to enable message retrieval by `Get all'."));
        gtk_widget_show (label);
        gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 4);
        gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
@@ -446,10 +452,14 @@ static void account_edit_create(void)
        gtk_widget_show (clist);
        gtk_container_add (GTK_CONTAINER (scrolledwin), clist);
        gtk_clist_set_column_width (GTK_CLIST(clist), COL_DEFAULT , 10);
-       gtk_clist_set_column_width (GTK_CLIST(clist), COL_GETALL  , 10);
+       gtk_clist_set_column_width (GTK_CLIST(clist), COL_GETALL  , 11);
        gtk_clist_set_column_width (GTK_CLIST(clist), COL_NAME    , 100);
        gtk_clist_set_column_width (GTK_CLIST(clist), COL_PROTOCOL, 100);
        gtk_clist_set_column_width (GTK_CLIST(clist), COL_SERVER  , 100);
+       gtk_clist_set_column_justification (GTK_CLIST(clist), COL_DEFAULT,
+                                           GTK_JUSTIFY_CENTER);
+       gtk_clist_set_column_justification (GTK_CLIST(clist), COL_GETALL,
+                                           GTK_JUSTIFY_CENTER);
        gtk_clist_set_selection_mode (GTK_CLIST(clist), GTK_SELECTION_BROWSE);
 
        for (i = 0; i < N_EDIT_ACCOUNT_COLS; i++)
@@ -518,6 +528,9 @@ static void account_edit_create(void)
                            NULL);
 
        PIXMAP_CREATE(clist, markxpm, markxpmmask, mark_xpm);
+       PIXMAP_CREATE(clist, checkboxonxpm, checkboxonxpmmask, checkbox_on_xpm);
+       PIXMAP_CREATE(clist, checkboxoffxpm, checkboxoffxpmmask,
+                     checkbox_off_xpm);
 
        edit_account.window    = window;
        edit_account.clist     = clist;
@@ -708,12 +721,12 @@ static gint account_clist_set_row(PrefsAccount *ac_prefs, gint row)
 {
        GtkCList *clist = GTK_CLIST(edit_account.clist);
        gchar *text[N_EDIT_ACCOUNT_COLS];
+       gboolean has_getallbox;
+       gboolean getall;
 
-       text[COL_DEFAULT] = ac_prefs->is_default ? "*" : "";
-       text[COL_GETALL] = (ac_prefs->protocol == A_POP3 ||
-                           ac_prefs->protocol == A_APOP) &&
-                           ac_prefs->recv_at_getall ? "*" : "";
-       text[COL_NAME] = ac_prefs->account_name;
+       text[COL_DEFAULT] = "";
+       text[COL_GETALL]  = "";
+       text[COL_NAME]    = ac_prefs->account_name;
 #if USE_SSL
        text[COL_PROTOCOL] = ac_prefs->protocol == A_POP3 ?
                             (ac_prefs->ssl_pop ? "POP3 (SSL)" : "POP3") :
@@ -744,12 +757,19 @@ static gint account_clist_set_row(PrefsAccount *ac_prefs, gint row)
                gtk_clist_set_text(clist, row, COL_SERVER, text[COL_SERVER]);
        }
 
-       if (*text[COL_DEFAULT])
+       has_getallbox = (ac_prefs->protocol == A_POP3 ||
+                        ac_prefs->protocol == A_APOP);
+       getall = has_getallbox && ac_prefs->recv_at_getall;
+
+       if (ac_prefs->is_default)
                gtk_clist_set_pixmap(clist, row, COL_DEFAULT,
                                     markxpm, markxpmmask);
-       if (*text[COL_GETALL])
+       if (getall)
                gtk_clist_set_pixmap(clist, row, COL_GETALL,
-                                    markxpm, markxpmmask);
+                                    checkboxonxpm, checkboxonxpmmask);
+       else if (has_getallbox)
+               gtk_clist_set_pixmap(clist, row, COL_GETALL,
+                                    checkboxoffxpm, checkboxoffxpmmask);
 
        gtk_clist_set_row_data(clist, row, ac_prefs);
 
index 24a3290..7e6ec9e 100644 (file)
 #include "folder.h"
 #include "addr_compl.h"
 #include "template_select.h"
+#include "quote_fmt.h"
+#include "template.h"
 
 #if USE_GPGME
 #  include "rfc2015.h"
 #endif
 
-#include "quote_fmt.h"
-
 typedef enum
 {
        COL_MIMETYPE = 0,
@@ -130,18 +130,19 @@ static void compose_toolbar_create                (Compose        *compose,
                                                 GtkWidget      *container);
 static GtkWidget *compose_account_option_menu_create
                                                (Compose        *compose);
+static void compose_set_template_menu          (Compose        *compose);
 static void compose_destroy                    (Compose        *compose);
 
 static gint compose_parse_header               (Compose        *compose,
                                                 MsgInfo        *msginfo);
 static gchar *compose_parse_references         (const gchar    *ref,
                                                 const gchar    *msgid);
-static void compose_quote_file                 (Compose        *compose,
-                                                MsgInfo        *msginfo,
-                                                FILE           *fp);
-static gchar *compose_quote_parse_fmt          (Compose        *compose,
+
+static gchar *compose_quote_fmt                        (Compose        *compose,
                                                 MsgInfo        *msginfo,
-                                                const gchar    *fmt);
+                                                const gchar    *fmt,
+                                                const gchar    *qmark);
+
 static void compose_reply_set_entry            (Compose        *compose,
                                                 MsgInfo        *msginfo,
                                                 gboolean        to_all,
@@ -290,9 +291,12 @@ static void compose_insert_file_cb (gpointer        data,
 static void compose_close_cb           (gpointer        data,
                                         guint           action,
                                         GtkWidget      *widget);
+
 static void compose_address_cb         (gpointer        data,
                                         guint           action,
                                         GtkWidget      *widget);
+static void compose_template_activate_cb(GtkWidget     *widget,
+                                        gpointer        data);
 
 static void compose_ext_editor_cb      (gpointer        data,
                                         guint           action,
@@ -389,11 +393,6 @@ static void followupto_activated   (GtkWidget      *widget,
 static void compose_attach_parts(Compose * compose,
                                 MsgInfo * msginfo);
 
-static gchar *compose_quote_fmt                (Compose        *compose,
-                                        MsgInfo        *msginfo,
-                                        const gchar    *fmt,
-                                        const gchar    * qmark);
-
 static void compose_generic_reply(MsgInfo *msginfo, gboolean quote,
                                  gboolean to_all,
                                  gboolean ignore_replyto,
@@ -469,7 +468,7 @@ static GtkItemFactoryEntry compose_entries[] =
        {N_("/_Tool"),                  NULL, NULL, 0, "<Branch>"},
        {N_("/_Tool/Show _ruler"),      NULL, compose_toggle_ruler_cb, 0, "<ToggleItem>"},
        {N_("/_Tool/_Address book"),    "<alt>A", compose_address_cb , 0, NULL},
-       {N_("/_Tool/_Templates ..."),   NULL, template_select_cb, 0, NULL},
+       {N_("/_Tool/_Template"),        NULL, NULL, 0, "<Branch>"},
        {N_("/_Help"),                  NULL, NULL, 0, "<LastBranch>"},
        {N_("/_Help/_About"),           NULL, about_show, 0, NULL}
 };
@@ -724,7 +723,7 @@ static void compose_generic_reply(MsgInfo *msginfo, gboolean quote,
        CHANGE_FLAGS(msginfo);
 
        compose = compose_create(account, COMPOSE_REPLY);
-       compose->replyinfo = msginfo;
+       compose->replyinfo = procmsg_msginfo_copy(msginfo);
 
 #if 0 /* NEW COMPOSE GUI */
        if (followup_and_reply_to) {
@@ -749,35 +748,17 @@ static void compose_generic_reply(MsgInfo *msginfo, gboolean quote,
        gtk_stext_freeze(text);
 
        if (quote) {
-               FILE *fp;
+               gchar *qmark;
                gchar *quote_str;
 
-               if ((fp = procmime_get_first_text_content(msginfo)) == NULL)
-                       g_warning(_("Can't get text part\n"));
-               else {
-                       gchar * qmark;
+               if (prefs_common.quotemark && *prefs_common.quotemark)
+                       qmark = prefs_common.quotemark;
+               else
+                       qmark = "> ";
 
-                       if (prefs_common.quotemark && *prefs_common.quotemark)
-                               qmark = prefs_common.quotemark;
-                       else
-                               qmark = "> ";
-
-                       quote_str = compose_quote_fmt(compose, msginfo,
-                                                     prefs_common.quotefmt,
-                                                     qmark);
-
-                       /*
-                       quote_str = compose_quote_parse_fmt
-                               (compose, msginfo, prefs_common.quotefmt);
-                       */
-
-                       if (quote_str != NULL)
-                               gtk_stext_insert(text, NULL, NULL, NULL,
-                                                quote_str, -1);
-                       /*                      g_free(quote_str); */
-                       /* compose_quote_file(compose, msginfo, fp); */
-                       fclose(fp);
-               }
+               quote_str = compose_quote_fmt(compose, msginfo,
+                                             prefs_common.quotefmt,
+                                             qmark);
        }
 
        if (prefs_common.auto_sig)
@@ -1025,8 +1006,6 @@ Compose *compose_forward(PrefsAccount * account, MsgInfo *msginfo,
        Compose *compose;
        /*      PrefsAccount *account; */
        GtkSText *text;
-       FILE *fp;
-       gchar buf[BUFFSIZE];
 
        g_return_val_if_fail(msginfo != NULL, NULL);
        g_return_val_if_fail(msginfo->folder != NULL, NULL);
@@ -1083,30 +1062,16 @@ Compose *compose_forward(PrefsAccount * account, MsgInfo *msginfo,
 
                g_free(msgfile);
        } else {
-               FILE *fp;
+               gchar *qmark;
                gchar *quote_str;
-               if ((fp = procmime_get_first_text_content(msginfo)) == NULL)
-                       g_warning(_("Can't get text part\n"));
-               else {
-                       gchar * qmark;
 
-                       if (prefs_common.fw_quotemark &&
-                           *prefs_common.fw_quotemark)
-                               qmark = prefs_common.fw_quotemark;
-                       else
-                               qmark = "> ";
-
-                       quote_str = compose_quote_fmt(compose, msginfo,
-                                                     prefs_common.fw_quotefmt,
-                                                     qmark);
-
-                       if (quote_str != NULL)
-                               gtk_stext_insert(text, NULL, NULL, NULL,
-                                                quote_str, -1);
-
-                       fclose(fp);
-               }
+               if (prefs_common.fw_quotemark && *prefs_common.fw_quotemark)
+                       qmark = prefs_common.quotemark;
+               else
+                       qmark = "> ";
 
+               quote_str = compose_quote_fmt(compose, msginfo,
+                                             prefs_common.fw_quotefmt, qmark);
                compose_attach_parts(compose, msginfo);
        }
 
@@ -1460,269 +1425,55 @@ static gchar *compose_parse_references(const gchar *ref, const gchar *msgid)
        return new_ref_str;
 }
 
-/*
-static void compose_quote_file(Compose *compose, MsgInfo *msginfo, FILE *fp)
+static gchar *compose_quote_fmt(Compose *compose, MsgInfo *msginfo,
+                               const gchar *fmt, const gchar *qmark)
 {
        GtkSText *text = GTK_STEXT(compose->text);
-       gchar *qmark;
-       gchar *quote_str;
-       GdkColor *qcolor = NULL;
-       gchar buf[BUFFSIZE];
-       gint qlen;
-       gchar *linep, *cur, *leftp;
-       gint line_len, cur_len;
-       gint wrap_len;
-       gint str_len;
-       gint ch_len;
-
-       // if (prefs_common.enable_color) qcolor = &quote_color;
-       if (prefs_common.quotemark && *prefs_common.quotemark)
-               qmark = prefs_common.quotemark;
-       else
-               qmark = "> ";
-       quote_str = compose_quote_parse_fmt(compose, msginfo, qmark);
-       g_return_if_fail(quote_str != NULL);
-       qlen = strlen(quote_str);
-
-       if (!prefs_common.linewrap_quote ||
-           prefs_common.linewrap_len <= qlen) {
-               while (fgets(buf, sizeof(buf), fp) != NULL) {
-                       gtk_stext_insert(text, NULL, qcolor, NULL,
-                                       quote_str, -1);
-                       gtk_stext_insert(text, NULL, qcolor, NULL, buf, -1);
-               }
-               g_free(quote_str);
-               return;
-       }
-
-       wrap_len = prefs_common.linewrap_len - qlen;
-
-       while (fgets(buf, sizeof(buf), fp) != NULL) {
-               strretchomp(buf);
-               str_len = strlen(buf);
-
-               if (str_len <= wrap_len) {
-                       gtk_stext_insert(text, NULL, qcolor, NULL,
-                                       quote_str, -1);
-                       gtk_stext_insert(text, NULL, qcolor, NULL, buf, -1);
-                       gtk_stext_insert(text, NULL, NULL, NULL, "\n", 1);
-                       continue;
-               }
-
-               linep = cur = leftp = buf;
-               line_len = cur_len = 0;
-
-               while (*cur != '\0') {
-                       ch_len = mblen(cur, MB_CUR_MAX);
-                       if (ch_len < 0) ch_len = 1;
-
-                       if (ch_len == 1 && isspace(*cur)) {
-                               linep = cur + ch_len;
-                               line_len = cur_len + ch_len;
-                       }
-
-                       if (cur_len + ch_len > wrap_len && line_len > 0) {
-                               gtk_stext_insert(text, NULL, qcolor, NULL,
-                                               quote_str, -1);
-
-                               if (isspace(*(linep - 1)))
-                                       gtk_stext_insert(text, NULL,
-                                                       qcolor, NULL,
-                                                       leftp, line_len - 1);
-                               else
-                                       gtk_stext_insert(text, NULL,
-                                                       qcolor, NULL,
-                                                       leftp, line_len);
-                               gtk_stext_insert(text, NULL, NULL, NULL,
-                                               "\n", 1);
-
-                               leftp = linep;
-                               cur_len = cur_len - line_len + ch_len;
-                               line_len = 0;
-                               cur += ch_len;
-                               continue;
-                       }
+       gchar *quote_str = NULL;
+       gchar *buf;
+       gchar *p, *lastp;
+       gint len;
 
-                       if (ch_len > 1) {
-                               linep = cur + ch_len;
-                               line_len = cur_len + ch_len;
-                       }
-                       cur_len += ch_len;
-                       cur += ch_len;
-               }
+       if (qmark != NULL) {
+               quote_fmt_init(msginfo, NULL);
+               quote_fmt_scan_string(qmark);
+               quote_fmt_parse();
 
-               if (*leftp) {
-                       gtk_stext_insert(text, NULL, qcolor, NULL,
-                                       quote_str, -1);
-                       gtk_stext_insert(text, NULL, qcolor, NULL, leftp, -1);
-                       gtk_stext_insert(text, NULL, NULL, NULL, "\n", 1);
-               }
+               buf = quote_fmt_get_buffer();
+               if (buf == NULL)
+                       alertpanel_error(_("Quote mark format error."));
+               else
+                       Xstrdup_a(quote_str, buf, return NULL)
        }
 
-       g_free(quote_str);
-}
-*/
-
-/*
-static gchar *compose_quote_parse_fmt(Compose *compose, MsgInfo *msginfo,
-                                     const gchar *fmt)
-{
-       gchar *ext_str;
-       size_t buf_len = 1024;
-       size_t ext_len = 0;
-       gchar *str;
-       gchar *mbs;
-       wchar_t *wcsfmt;
-       wchar_t *sp;
-       gchar tmp[3];
-
-       if (!fmt || *fmt == '\0') return 0;
-
-       Xalloca(mbs, sizeof(wchar_t) + 1, return 0);
-       Xalloca(wcsfmt, (strlen(fmt) + 1) * sizeof(wchar_t), return 0);
-       mbstowcs(wcsfmt, fmt, strlen(fmt) + 1);
-       sp = wcsfmt;
-
-       ext_str = g_malloc(sizeof(gchar) * buf_len);
-       g_return_val_if_fail(ext_str != NULL, NULL);
-
-       while (*sp) {
-               gint len;
-
-               len = wctomb(mbs, *sp);
-               mbs[len] = '\0';
-
-               if (*mbs == '%') {
-                       gchar *p;
-
-                       wctomb(mbs, *(++sp));
-                       str = NULL;
-
-                       switch (*mbs) {
-                       case 'd':
-                               str = msginfo->date;
-                               sp++;
-                               break;
-                       case 'f':
-                               str = msginfo->from;
-                               sp++;
-                               break;
-                       case 'I':
-                               if (!msginfo->fromname) {sp++; break;}
-                               p = msginfo->fromname;
-                               tmp[0] = tmp[1] = tmp[2] = '\0';
-
-                               if (*p && isalnum(*p))
-                                       tmp[0] = toupper(*p);
-                               else {
-                                       sp++;
-                                       break;
-                               }
-
-                               while (*p) {
-                                       while (*p && !isspace(*p)) p++;
-                                       while (*p && isspace(*p)) p++;
-                                       if (*p && isalnum(*p))
-                                               tmp[1] = toupper(*p);
-                               }
-
-                               if (tmp[1]) str = tmp;
-                               sp++;
-                               break;
-                       case 'n':
-                               str = msginfo->fromname;
-                               sp++;
-                               break;
-                       case 'N':
-                               if (!msginfo->fromname) {sp++; break;}
-                               Xstrdup_a(str, msginfo->fromname,
-                                         {sp++; break;});
-                               p = str;
-                               while (*p && !isspace(*p)) p++;
-                               *p = '\0';
-                               sp++;
-                               break;
-                       case 's':
-                               str = msginfo->subject;
-                               sp++;
-                               break;
-                       case 't':
-                               str = msginfo->to;
-                               sp++;
-                               break;
-                       case 'c':
-                               str = msginfo->cc;
-                               sp++;
-                               break;
-                       case 'i':
-                               if (!msginfo->msgid) {sp++; break;}
-                               Xalloca(str, strlen(msginfo->msgid) + 3,
-                                       {sp++; break;});
-                               g_snprintf(str, strlen(msginfo->msgid) + 3,
-                                          "<%s>", msginfo->msgid);
-                               sp++;
-                               break;
-                       case '%':
-                               str = "%";
-                               sp++;
-                               break;
-                       default:
-                               break;
-                       }
-
-                       if (str) {
-                               while (ext_len + strlen(str) + 1 > buf_len)
-                                       buf_len += 1024;
-                               ext_str = g_realloc(ext_str,
-                                                   sizeof(gchar) * buf_len);
-                               g_return_val_if_fail(ext_str != NULL, NULL);
-                               strcpy(ext_str + ext_len, str);
-                               ext_len += strlen(str);
-                       }
-               } else if (*mbs == '\\') {
-                       wctomb(mbs, *(++sp));
-                       str = NULL;
+       quote_fmt_init(msginfo, quote_str);
+       quote_fmt_scan_string(fmt);
+       quote_fmt_parse();
 
-                       switch (*mbs) {
-                       case 'n':
-                               str = "\n";
-                               break;
-                       case 't':
-                               str = "\t";
-                               break;
-                       case '\\':
-                               str = "\\";
-                               break;
-                       default:
-                               break;
-                       }
+       buf = quote_fmt_get_buffer();
+       if (buf == NULL) {
+               alertpanel_error(_("Message reply/forward format error."));
+               return NULL;
+       }
 
-                       if (str) {
-                               while (ext_len + strlen(str) + 1 > buf_len)
-                                       buf_len += 1024;
-                               ext_str = g_realloc(ext_str,
-                                                   sizeof(gchar) * buf_len);
-                               g_return_val_if_fail(ext_str != NULL, NULL);
-                               strcpy(ext_str + ext_len, str);
-                               ext_len += strlen(str);
-                               sp++;
-                       }
-               } else {
-                       while (ext_len + len + 1 > buf_len) buf_len += 1024;
-                       ext_str = g_realloc(ext_str, sizeof(gchar) * buf_len);
-                       g_return_val_if_fail(ext_str != NULL, NULL);
-                       strcpy(ext_str + ext_len, mbs);
-                       ext_len += len;
-                       sp++;
-               }
+       gtk_stext_freeze(text);
+       gtk_stext_set_point(text, 0);
+       gtk_stext_forward_delete(text, gtk_stext_get_length(text));
+
+       for (p = buf; *p != '\0'; ) {
+               lastp = strchr(p, '\n');
+               len = lastp ? lastp - p + 1 : -1;
+               gtk_stext_insert(text, NULL, NULL, NULL, p, len);
+               if (lastp)
+                       p = lastp + 1;
+               else
+                       break;
        }
 
-       if (ext_str)
-               ext_str = g_realloc(ext_str, strlen(ext_str) + 1);
+       gtk_stext_thaw(text);
 
-       return ext_str;
+       return buf;
 }
-*/
 
 static void compose_reply_set_entry(Compose *compose, MsgInfo *msginfo,
                                    gboolean to_all, gboolean ignore_replyto,
@@ -3204,12 +2955,7 @@ static void compose_write_attach(Compose *compose, FILE *fp)
                        gchar buf[BUFFSIZE];
 
                        while (fgets(buf, sizeof(buf), attach_fp) != NULL) {
-                               len = strlen(buf);
-                               if (len > 1 && buf[len - 1] == '\n' &&
-                                   buf[len - 2] == '\r') {
-                                       buf[len - 2] = '\n';
-                                       buf[len - 1] = '\0';
-                               }
+                               strcrchomp(buf);
                                fputs(buf, fp);
                        }
                } else {
@@ -3765,6 +3511,7 @@ static Compose *compose_create(PrefsAccount *account, ComposeMode mode)
        GtkWidget *menuitem;
        GtkItemFactory *popupfactory;
        GtkItemFactory *ifactory;
+       GtkWidget *tmpl_menu;
        gint n_entries;
        gint count = 0;
        gint i;
@@ -4089,6 +3836,7 @@ static Compose *compose_create(PrefsAccount *account, ComposeMode mode)
        menu_set_sensitive(ifactory, "/Edit/Undo", FALSE);
        menu_set_sensitive(ifactory, "/Edit/Redo", FALSE);
 
+       tmpl_menu = gtk_item_factory_get_item(ifactory, "/Tool/Template");
 #if 0 /* NEW COMPOSE GUI */
        if (account->protocol == A_NNTP) {
                gtk_widget_hide(to_hbox);
@@ -4170,8 +3918,13 @@ static Compose *compose_create(PrefsAccount *account, ComposeMode mode)
        compose->popupmenu    = popupmenu;
        compose->popupfactory = popupfactory;
 
+       compose->tmpl_menu = tmpl_menu;
+
        compose->mode = mode;
 
+       compose->targetinfo = NULL;
+       compose->replyinfo  = NULL;
+
        compose->replyto     = NULL;
        compose->mailinglist = NULL;
        compose->cc          = NULL;
@@ -4277,6 +4030,7 @@ static Compose *compose_create(PrefsAccount *account, ComposeMode mode)
 #endif /* USE_GPGME */
 
        addressbook_set_target_compose(compose);
+       compose_set_template_menu(compose);
 
        compose_list = g_list_append(compose_list, compose);
 
@@ -4487,6 +4241,74 @@ static GtkWidget *compose_account_option_menu_create(Compose *compose)
        return hbox;
 }
 
+static void compose_set_template_menu(Compose *compose)
+{
+       GSList *tmpl_list, *cur;
+       GtkWidget *menu;
+       GtkWidget *item;
+
+       tmpl_list = template_get_config();
+
+       menu = gtk_menu_new();
+
+       for (cur = tmpl_list; cur != NULL; cur = cur->next) {
+               Template *tmpl = (Template *)cur->data;
+
+               item = gtk_menu_item_new_with_label(tmpl->name);
+               gtk_menu_append(GTK_MENU(menu), item);
+               gtk_signal_connect(GTK_OBJECT(item), "activate",
+                                  GTK_SIGNAL_FUNC(compose_template_activate_cb),
+                                  compose);
+               gtk_object_set_data(GTK_OBJECT(item), "template", tmpl);
+               gtk_widget_show(item);
+       }
+
+       gtk_widget_show(menu);
+       gtk_menu_item_set_submenu(GTK_MENU_ITEM(compose->tmpl_menu), menu);
+}
+
+void compose_reflect_prefs_all(void)
+{
+       GList *cur;
+       Compose *compose;
+
+       for (cur = compose_list; cur != NULL; cur = cur->next) {
+               compose = (Compose *)cur->data;
+               compose_set_template_menu(compose);
+       }
+}
+
+static void compose_template_apply(Compose *compose, const gchar *tmpl_str)
+{
+       gchar *qmark;
+       gchar *parsed_str;
+
+       if (!tmpl_str) return;
+
+       gtk_stext_freeze(GTK_TEXT(compose->text));
+
+       if (compose->replyinfo == NULL) {
+               MsgInfo dummyinfo;
+
+               memset(&dummyinfo, 0, sizeof(MsgInfo));
+               parsed_str = compose_quote_fmt(compose, &dummyinfo, tmpl_str,
+                                              NULL);
+       } else {
+               if (prefs_common.quotemark && *prefs_common.quotemark)
+                       qmark = prefs_common.quotemark;
+               else
+                       qmark = "> ";
+
+               parsed_str = compose_quote_fmt(compose, compose->replyinfo, tmpl_str,
+                                              qmark);
+       }
+
+       if (parsed_str && prefs_common.auto_sig)
+               compose_insert_sig(compose);
+
+       gtk_stext_thaw(GTK_TEXT(compose->text));
+}
+
 static void compose_destroy(Compose *compose)
 {
        gint row;
@@ -4505,6 +4327,7 @@ static void compose_destroy(Compose *compose)
        g_slist_free(compose->header_list);
 
        procmsg_msginfo_free(compose->targetinfo);
+       procmsg_msginfo_free(compose->replyinfo);
 
        g_free(compose->replyto);
        g_free(compose->cc);
@@ -5478,6 +5301,17 @@ static void compose_address_cb(gpointer data, guint action, GtkWidget *widget)
        addressbook_open(compose);
 }
 
+static void compose_template_activate_cb(GtkWidget *widget, gpointer data)
+{
+       Compose *compose = (Compose *)data;
+       Template *tmpl;
+
+       tmpl = gtk_object_get_data(GTK_OBJECT(widget), "template");
+       g_return_if_fail(tmpl != NULL);
+
+       compose_template_apply(compose, tmpl->value);
+}
+
 static void compose_ext_editor_cb(gpointer data, guint action,
                                  GtkWidget *widget)
 {
@@ -5848,42 +5682,6 @@ static void compose_toggle_return_receipt_cb(gpointer data, guint action,
                compose->return_receipt = FALSE;
 }
 
-static gchar *compose_quote_fmt                (Compose        *compose,
-                                        MsgInfo        *msginfo,
-                                        const gchar    *fmt,
-                                        const gchar    *qmark)
-{
-       gchar * quote_str = NULL;
-
-       if (qmark != NULL) {
-               gchar * p;
-
-               quote_fmt_init(msginfo, NULL);
-               quote_fmt_scan_string(qmark);
-               quote_fmtparse();
-
-               p = quote_fmt_get_buffer();
-               if (p == NULL) {
-                       alertpanel_error
-                               (_("Quote mark format error."));
-               }
-               else {
-                       quote_str = alloca(strlen(p) + 1);
-                       strcpy(quote_str, p);
-               }
-       }
-
-       quote_fmt_init(msginfo, quote_str);
-       quote_fmt_scan_string(fmt);
-       quote_fmtparse();
-
-       if (quote_fmt_get_buffer() == NULL)
-               alertpanel_error
-                       (_("Message reply/forward format error."));
-
-       return quote_fmt_get_buffer();
-}
-
 static void template_apply_cb(gchar *s, gpointer data)
 {
        Compose *compose = (Compose*)data;
index 2cfe04e..22fb594 100644 (file)
@@ -127,6 +127,8 @@ struct _Compose
 
        GtkItemFactory *popupfactory;
 
+       GtkWidget *tmpl_menu;
+
        ComposeMode mode;
 
        MsgInfo *targetinfo;
@@ -222,5 +224,6 @@ void compose_entry_append   (Compose          *compose,
                                 const gchar      *address,
                                 ComposeEntryType  type);
 gint compose_send(Compose *compose);
+void compose_reflect_prefs_all (void);
 
 #endif /* __COMPOSE_H__ */
index ca953de..d211d94 100644 (file)
@@ -51,6 +51,8 @@
 #define SCORING_RC              "scoringrc"
 #define FILTERING_RC           "filteringrc"
 #define MENU_RC                        "menurc"
+#define COMMAND_HISTORY                "command_history"
+#define TEMPLATE_DIR           "templates"
 #define NEWSGROUP_LIST         ".newsgroup_list"
 #define ADDRESS_BOOK           "addressbook.xml"
 #define MANUAL_HTML_INDEX      "sylpheed.html"
@@ -60,7 +62,6 @@
 #define MARK_FILE              ".sylpheed_mark"
 #define CACHE_VERSION          19
 #define MARK_VERSION           2
-#define TEMPLATES_DIR          "templates"
 
 #define DEFAULT_SIGNATURE      ".signature"
 #define DEFAULT_INC_PATH       "/usr/bin/mh/inc"
@@ -92,6 +93,7 @@
 #define FOLDER_SPACING                 4
 #define COLOR_DIM                      35000
 #define UI_REFRESH_INTERVAL            50000
+#define MAX_HISTORY_SIZE               16
 
 #define NORMAL_FONT prefs_common.normalfont
 #define BOLD_FONT   prefs_common.boldfont
index e2235c6..74d9802 100644 (file)
@@ -189,8 +189,7 @@ Filter *filter_read_str(const gchar *str)
        gchar *name1, *body1, *op, *name2, *body2, *dest;
        gchar *flag1 = NULL, *flag2 = NULL, *action = NULL;
 
-       Xalloca(tmp, strlen(str) + 1, return NULL);
-       strcpy(tmp, str);
+       Xstrdup_a(tmp, str, return NULL);
 
        name1 = tmp;
        PARSE_ONE_PARAM(body1, name1);
index 2ffb28a..cc8d7d0 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999,2000 Hiroyuki Yamamoto
+ * Copyright (C) 1999-2001 Hiroyuki Yamamoto
  *
  * 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
@@ -32,6 +32,7 @@
 #include <gtk/gtkhbox.h>
 #include <gtk/gtklabel.h>
 #include <gtk/gtkentry.h>
+#include <gtk/gtkcombo.h>
 #include <gtk/gtkbutton.h>
 #include <gtk/gtkhbbox.h>
 
 
 #define INPUT_DIALOG_WIDTH     420
 
+typedef enum
+{
+       INPUT_DIALOG_NORMAL,
+       INPUT_DIALOG_INVISIBLE,
+       INPUT_DIALOG_COMBO
+} InputDialogType;
+
 static gboolean ack;
 
+static InputDialogType type;
+
 static GtkWidget *dialog;
 static GtkWidget *msg_label;
 static GtkWidget *entry;
+static GtkWidget *combo;
 static GtkWidget *ok_button;
 
 static void input_dialog_create        (void);
+static gchar *input_dialog_open        (const gchar    *title,
+                                const gchar    *message,
+                                const gchar    *default_string);
 static void input_dialog_set   (const gchar    *title,
                                 const gchar    *message,
                                 const gchar    *default_string);
@@ -66,41 +80,23 @@ static void key_pressed             (GtkWidget      *widget,
                                 GdkEventKey    *event,
                                 gpointer        data);
 static void entry_activated    (GtkEditable    *editable);
+static void combo_activated    (GtkEditable    *editable);
+
 
 gchar *input_dialog(const gchar *title, const gchar *message,
                    const gchar *default_string)
 {
-       gchar *str;
-
        if (dialog && GTK_WIDGET_VISIBLE(dialog)) return NULL;
 
        if (!dialog)
                input_dialog_create();
 
-       input_dialog_set(title, message, default_string);
-       gtk_widget_show(dialog);
-       gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
-       manage_window_set_transient(GTK_WINDOW(dialog));
-
-       gtk_main();
-
-       manage_window_focus_out(dialog, NULL, NULL);
-       gtk_widget_hide(dialog);
+       type = INPUT_DIALOG_NORMAL;
+       gtk_widget_hide(combo);
+       gtk_widget_show(entry);
        gtk_entry_set_visibility(GTK_ENTRY(entry), TRUE);
 
-       if (ack) {
-               str = gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1);
-               if (str && *str == '\0') {
-                       g_free(str);
-                       str = NULL;
-               }
-       } else
-               str = NULL;
-
-       GTK_EVENTS_FLUSH();
-
-       debug_print("return string = %s\n", str ? str : "(none)");
-       return str;
+       return input_dialog_open(title, message, default_string);
 }
 
 gchar *input_dialog_with_invisible(const gchar *title, const gchar *message,
@@ -111,9 +107,37 @@ gchar *input_dialog_with_invisible(const gchar *title, const gchar *message,
        if (!dialog)
                input_dialog_create();
 
+       type = INPUT_DIALOG_INVISIBLE;
+       gtk_widget_hide(combo);
+       gtk_widget_show(entry);
        gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE);
 
-       return input_dialog(title, message, default_string);
+       return input_dialog_open(title, message, default_string);
+}
+
+gchar *input_dialog_combo(const gchar *title, const gchar *message,
+                         const gchar *default_string, GList *list)
+{
+       if (dialog && GTK_WIDGET_VISIBLE(dialog)) return NULL;
+
+       if (!dialog)
+               input_dialog_create();
+
+       type = INPUT_DIALOG_COMBO;
+       gtk_widget_hide(entry);
+       gtk_widget_show(combo);
+
+       if (!list) {
+               GList empty_list;
+
+               empty_list.data = (gpointer)"";
+               empty_list.next = NULL;
+               empty_list.prev = NULL;
+               gtk_combo_set_popdown_strings(GTK_COMBO(combo), &empty_list);
+       } else
+               gtk_combo_set_popdown_strings(GTK_COMBO(combo), list);
+
+       return input_dialog_open(title, message, default_string);
 }
 
 static void input_dialog_create(void)
@@ -156,6 +180,11 @@ static void input_dialog_create(void)
        gtk_signal_connect(GTK_OBJECT(entry), "activate",
                           GTK_SIGNAL_FUNC(entry_activated), NULL);
 
+       combo = gtk_combo_new();
+       gtk_box_pack_start(GTK_BOX(vbox), combo, FALSE, FALSE, 0);
+       gtk_signal_connect(GTK_OBJECT(GTK_COMBO(combo)->entry), "activate",
+                          GTK_SIGNAL_FUNC(combo_activated), NULL);
+
        gtkut_button_set_create(&confirm_area,
                                &ok_button,     _("OK"),
                                &cancel_button, _("Cancel"),
@@ -173,20 +202,69 @@ static void input_dialog_create(void)
        gtk_widget_show_all(GTK_DIALOG(dialog)->vbox);
 }
 
+static gchar *input_dialog_open(const gchar *title, const gchar *message,
+                               const gchar *default_string)
+{
+       gchar *str;
+
+       if (dialog && GTK_WIDGET_VISIBLE(dialog)) return NULL;
+
+       if (!dialog)
+               input_dialog_create();
+
+       input_dialog_set(title, message, default_string);
+       gtk_widget_show(dialog);
+       gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
+       manage_window_set_transient(GTK_WINDOW(dialog));
+
+       gtk_main();
+
+       manage_window_focus_out(dialog, NULL, NULL);
+       gtk_widget_hide(dialog);
+
+       if (ack) {
+               GtkEditable *editable;
+
+               if (type == INPUT_DIALOG_COMBO)
+                       editable = GTK_EDITABLE(GTK_COMBO(combo)->entry);
+               else
+                       editable = GTK_EDITABLE(entry);
+
+               str = gtk_editable_get_chars(editable, 0, -1);
+               if (str && *str == '\0') {
+                       g_free(str);
+                       str = NULL;
+               }
+       } else
+               str = NULL;
+
+       GTK_EVENTS_FLUSH();
+
+       debug_print("return string = %s\n", str ? str : "(none)");
+       return str;
+}
+
 static void input_dialog_set(const gchar *title, const gchar *message,
                             const gchar *default_string)
 {
+       GtkWidget *entry_;
+
+       if (type == INPUT_DIALOG_COMBO)
+               entry_ = GTK_COMBO(combo)->entry;
+       else
+               entry_ = entry;
+
        gtk_window_set_title(GTK_WINDOW(dialog), title);
        gtk_label_set_text(GTK_LABEL(msg_label), message);
        if (default_string && *default_string)
-               gtk_entry_set_text(GTK_ENTRY(entry), default_string);
+               gtk_entry_set_text(GTK_ENTRY(entry_), default_string);
        else
-               gtk_entry_set_text(GTK_ENTRY(entry), "");
-       gtk_entry_set_position(GTK_ENTRY(entry), 0);
-       gtk_entry_select_region(GTK_ENTRY(entry), 0, -1);
+               gtk_entry_set_text(GTK_ENTRY(entry_), "");
+       gtk_entry_set_position(GTK_ENTRY(entry_), 0);
+       gtk_entry_select_region(GTK_ENTRY(entry_), 0, -1);
 
        gtk_widget_grab_focus(ok_button);
-       gtk_widget_grab_focus(entry);
+       gtk_widget_grab_focus(entry_);
 }
 
 static void ok_clicked(GtkWidget *widget, gpointer data)
@@ -222,3 +300,9 @@ static void entry_activated(GtkEditable *editable)
        ack = TRUE;
        gtk_main_quit();
 }
+
+static void combo_activated(GtkEditable *editable)
+{
+       ack = TRUE;
+       gtk_main_quit();
+}
index b399353..02b996f 100644 (file)
@@ -28,5 +28,9 @@ gchar *input_dialog                   (const gchar    *title,
 gchar *input_dialog_with_invisible     (const gchar    *title,
                                         const gchar    *message,
                                         const gchar    *default_string);
+gchar *input_dialog_combo              (const gchar    *title,
+                                        const gchar    *message,
+                                        const gchar    *default_string,
+                                        GList          *list);
 
 #endif /* __INPUTDIALOG_H__ */
index 408e991..a960920 100644 (file)
@@ -64,6 +64,7 @@
 #include "prefs_account.h"
 #include "prefs_folder_item.h"
 #include "prefs_summary_column.h"
+#include "prefs_template.h"
 #include "account.h"
 #include "addressbook.h"
 #include "headerwindow.h"
@@ -77,7 +78,6 @@
 #include "codeconv.h"
 #include "about.h"
 #include "manual.h"
-#include "prefs_templates.h"
 #include "version.h"
 
 #define AC_LABEL_WIDTH 240
@@ -371,6 +371,9 @@ static void prefs_filtering_open_cb (MainWindow     *mainwin,
 static void prefs_account_open_cb(MainWindow   *mainwin,
                                  guint          action,
                                  GtkWidget     *widget);
+static void prefs_template_open_cb     (MainWindow     *mainwin,
+                                        guint           action,
+                                        GtkWidget      *widget);
 static void new_account_cb      (MainWindow    *mainwin,
                                  guint          action,
                                  GtkWidget     *widget);
@@ -390,10 +393,6 @@ static void activate_compose_button (MainWindow *mainwin,
                                ToolbarStyle      style,
                                ComposeButtonType type);
 
-static void prefs_templates_open_cb(MainWindow *mainwin,
-                                 guint          action,
-                                 GtkWidget     *widget);
-
 #define  SEPARATE_ACTION  667
 
 static GtkItemFactoryEntry mainwin_entries[] =
@@ -607,9 +606,8 @@ static GtkItemFactoryEntry mainwin_entries[] =
                                                NULL, prefs_scoring_open_cb, 0, NULL},
        {N_("/_Configuration/_Filtering ..."),
                                                NULL, prefs_filtering_open_cb, 0, NULL},
-       {N_("/_Configuration/_Templates ..."),
-                                               NULL, prefs_templates_open_cb, 0, NULL},
-       {N_("/_Configuration/_Preferences per account..."),
+       {N_("/_Configuration/_Template..."),    NULL, prefs_template_open_cb, 0, NULL},
+       {N_("/_Configuration/_Preferences for current account..."),
                                                NULL, prefs_account_open_cb, 0, NULL},
        {N_("/_Configuration/---"),             NULL, NULL, 0, "<Separator>"},
        {N_("/_Configuration/Create _new account..."),
@@ -2723,6 +2721,12 @@ static void prefs_filtering_open_cb(MainWindow *mainwin, guint action,
        prefs_filtering_open();
 }
 
+static void prefs_template_open_cb(MainWindow *mainwin, guint action,
+                                  GtkWidget *widget)
+{
+       prefs_template_open();
+}
+
 static void prefs_account_open_cb(MainWindow *mainwin, guint action,
                                  GtkWidget *widget)
 {
@@ -2812,9 +2816,3 @@ void main_window_toolbar_set_compose_button(MainWindow *mainwin, ComposeButtonTy
                                        prefs_common.toolbar_style,
                                        compose_btn_type);
 }
-
-static void prefs_templates_open_cb(MainWindow *mainwin, guint action,
-                                   GtkWidget *widget)
-{
-       prefs_templates_open();
-}
index ae10a65..9f483fe 100644 (file)
--- a/src/mh.c
+++ b/src/mh.c
@@ -153,15 +153,9 @@ gint mh_add_msg(Folder *folder, FolderItem *dest, const gchar *file,
                                   dest->last_num + 1);
 
        if (link(file, destfile) < 0) {
-               if (EXDEV == errno) {
-                       if (copy_file(file, destfile) < 0) {
-                               g_warning(_("can't copy message %s to %s\n"),
-                                         file, destfile);
-                               g_free(destfile);
-                               return -1;
-                       }
-               } else {
-                       FILE_OP_ERROR(file, "link");
+               if (copy_file(file, destfile) < 0) {
+                       g_warning(_("can't copy message %s to %s\n"),
+                                 file, destfile);
                        g_free(destfile);
                        return -1;
                }
index bfe3d78..ad063ef 100644 (file)
@@ -624,7 +624,6 @@ static void mimeview_key_pressed(GtkWidget *widget, GdkEventKey *event,
                }
                break;
        case GDK_BackSpace:
-       case GDK_Delete:
                textview_scroll_page(mimeview->textview, TRUE);
                return;
        case GDK_Return:
@@ -773,6 +772,7 @@ static void mimeview_open_with(MimeView *mimeview)
 {
        MimeInfo *partinfo;
        gchar *filename;
+       gchar *cmd;
 
        if (!mimeview->opened) return;
        if (!mimeview->file) return;
@@ -783,21 +783,29 @@ static void mimeview_open_with(MimeView *mimeview)
 
        filename = procmime_get_tmp_file_name(partinfo);
 
-       if (procmime_get_part(filename, mimeview->file, partinfo) < 0)
+       if (procmime_get_part(filename, mimeview->file, partinfo) < 0) {
                alertpanel_error
                        (_("Can't save the part of multipart message."));
-       else {
-               gchar *cmd;
-
-               cmd = input_dialog
-                       (_("Open with"),
-                        _("Enter the command line to open file:\n"
-                          "(`%s' will be replaced with file name)"),
-                        "gedit '%s'");
-               if (cmd) {
-                       mimeview_view_file(filename, partinfo, cmd);
-                       g_free(cmd);
-               }
+               g_free(filename);
+               return;
+       }
+
+       if (!prefs_common.mime_open_cmd_history)
+               prefs_common.mime_open_cmd_history =
+                       add_history(NULL, prefs_common.mime_open_cmd);
+
+       cmd = input_dialog_combo
+               (_("Open with"),
+                _("Enter the command line to open file:\n"
+                  "(`%s' will be replaced with file name)"),
+                prefs_common.mime_open_cmd,
+                prefs_common.mime_open_cmd_history);
+       if (cmd) {
+               mimeview_view_file(filename, partinfo, cmd);
+               g_free(prefs_common.mime_open_cmd);
+               prefs_common.mime_open_cmd = cmd;
+               prefs_common.mime_open_cmd_history =
+                       add_history(prefs_common.mime_open_cmd_history, cmd);
        }
 
        g_free(filename);
index 3247836..38bbf3b 100644 (file)
@@ -711,8 +711,7 @@ static MsgInfo *news_parse_xover(const gchar *xover_str)
        gint num, size_int, line_int;
        gchar *xover_buf;
 
-       Xalloca(xover_buf, strlen(xover_str) + 1, return NULL);
-       strcpy(xover_buf, xover_str);
+       Xstrdup_a(xover_buf, xover_str, return NULL);
 
        PARSE_ONE_PARAM(subject, xover_buf);
        PARSE_ONE_PARAM(sender, subject);
diff --git a/src/pixmaps/checkbox_off.xpm b/src/pixmaps/checkbox_off.xpm
new file mode 100644 (file)
index 0000000..1b926b3
--- /dev/null
@@ -0,0 +1,20 @@
+/* XPM */
+static char * checkbox_off_xpm[] = {
+"13 13 4 1",
+"      c None",
+".     c #000000",
+"+     c #FFFFFF",
+"@     c #DFDFDF",
+"             ",
+" ........... ",
+" .+++++++++@ ",
+" .+++++++++@ ",
+" .+++++++++@ ",
+" .+++++++++@ ",
+" .+++++++++@ ",
+" .+++++++++@ ",
+" .+++++++++@ ",
+" .+++++++++@ ",
+" .+++++++++@ ",
+" .@@@@@@@@@@ ",
+"             "};
diff --git a/src/pixmaps/checkbox_on.xpm b/src/pixmaps/checkbox_on.xpm
new file mode 100644 (file)
index 0000000..e4fe1c7
--- /dev/null
@@ -0,0 +1,20 @@
+/* XPM */
+static char * checkbox_on_xpm[] = {
+"13 13 4 1",
+"      c None",
+".     c #000000",
+"+     c #FFFFFF",
+"@     c #DFDFDF",
+"             ",
+" ........... ",
+" .+++++++++@ ",
+" .+++++++.+@ ",
+" .++++++..+@ ",
+" .+.+++...+@ ",
+" .+..+...++@ ",
+" .+.....+++@ ",
+" .++...++++@ ",
+" .+++.+++++@ ",
+" .+++++++++@ ",
+" .@@@@@@@@@@ ",
+"             "};
index 1d7a21a..0f7b6ec 100644 (file)
@@ -32,6 +32,7 @@
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <errno.h>
 
 #include "intl.h"
 #include "main.h"
@@ -97,9 +98,6 @@ static struct Send {
 } send;
 
 static struct Compose {
-       GtkWidget *checkbtn_quote;
-       GtkWidget *entry_quotemark;
-       GtkWidget *text_quotefmt;
        GtkWidget *checkbtn_autosig;
        GtkWidget *entry_sigsep;
 
@@ -107,7 +105,6 @@ static struct Compose {
        GtkWidget *text_fw_quotefmt;
 
        GtkWidget *checkbtn_autoextedit;
-       GtkWidget *checkbtn_reply_account_autosel;
        GtkWidget *checkbtn_forward_account_autosel;
        GtkWidget *checkbtn_reedit_account_autosel;
 
@@ -116,6 +113,8 @@ static struct Compose {
        GtkWidget *checkbtn_wrapquote;
        GtkWidget *checkbtn_wrapatsend;
 
+       GtkWidget *checkbtn_reply_account_autosel;
+       GtkWidget *checkbtn_quote;
        GtkWidget * checkbtn_forward_as_attachment;
        GtkWidget * checkbtn_smart_wrapping;
        GtkWidget * checkbtn_block_cursor;
@@ -130,6 +129,14 @@ static struct Compose {
 
 } compose;
 
+static struct Quote {
+       GtkWidget *entry_quotemark;
+       GtkWidget *text_quotefmt;
+
+       GtkWidget *entry_fw_quotemark;
+       GtkWidget *text_fw_quotefmt;
+} quote;
+
 static struct Display {
        GtkWidget *entry_textfont;
        GtkWidget *button_textfont;
@@ -301,21 +308,6 @@ static PrefParam param[] = {
         prefs_common_charset_set_optmenu},
 
        /* Compose */
-       {"reply_with_quote", "TRUE", &prefs_common.reply_with_quote, P_BOOL,
-        &compose.checkbtn_quote,
-        prefs_set_data_from_toggle, prefs_set_toggle},
-       {"quote_mark", "> ", &prefs_common.quotemark, P_STRING,
-        &compose.entry_quotemark, prefs_set_data_from_entry, prefs_set_entry},
-       {"quote_format", "On %d\\n%f wrote:\\n\\n%Q",
-
-        &prefs_common.quotefmt, P_STRING, &compose.text_quotefmt,
-        prefs_set_data_from_text, prefs_set_text},
-       {"fw_quote_mark", "> ", &prefs_common.fw_quotemark, P_STRING,
-        &compose.entry_fw_quotemark, prefs_set_data_from_entry, prefs_set_entry},
-       {"fw_quote_format", "----------  Forwarded message ----------\\n?d(Date: %d\\n)?f(From: %f\\n)?t(To: %t\\n)?c(Cc: %c\\n)?n(Newsgroups: %n\\n)?s(Subject: %s\\n)\\n%Q",
-        &prefs_common.fw_quotefmt, P_STRING, &compose.text_fw_quotefmt,
-        prefs_set_data_from_text, prefs_set_text},
-
        {"auto_signature", "TRUE", &prefs_common.auto_sig, P_BOOL,
         &compose.checkbtn_autosig,
         prefs_set_data_from_toggle, prefs_set_toggle},
@@ -325,18 +317,6 @@ static PrefParam param[] = {
        {"auto_ext_editor", "FALSE", &prefs_common.auto_exteditor, P_BOOL,
         &compose.checkbtn_autoextedit,
         prefs_set_data_from_toggle, prefs_set_toggle},
-        {"reply_account_autoselect", "TRUE",
-        &prefs_common.reply_account_autosel, P_BOOL,
-        &compose.checkbtn_reply_account_autosel,
-        prefs_set_data_from_toggle, prefs_set_toggle},
-       {"forward_account_autoselect", "TRUE",
-        &prefs_common.forward_account_autosel, P_BOOL,
-        &compose.checkbtn_forward_account_autosel,
-        prefs_set_data_from_toggle, prefs_set_toggle},
-       {"reedit_account_autoselect", "TRUE",
-        &prefs_common.reedit_account_autosel, P_BOOL,
-        &compose.checkbtn_reedit_account_autosel,
-        prefs_set_data_from_toggle, prefs_set_toggle},
 
        {"linewrap_length", "74", &prefs_common.linewrap_len, P_INT,
         &compose.spinbtn_linewrap,
@@ -368,9 +348,34 @@ static PrefParam param[] = {
         P_STRING, &compose.optmenu_dictionary, 
         prefs_dictionary_set_data_from_optmenu, prefs_dictionary_set_optmenu },
 #endif
+       {"reply_with_quote", "TRUE", &prefs_common.reply_with_quote, P_BOOL,
+        &compose.checkbtn_quote,
+        prefs_set_data_from_toggle, prefs_set_toggle},
+       {"reply_account_autoselect", "TRUE",
+        &prefs_common.reply_account_autosel, P_BOOL,
+        &compose.checkbtn_reply_account_autosel,
+        prefs_set_data_from_toggle, prefs_set_toggle},
+
        {"show_ruler", "TRUE", &prefs_common.show_ruler, P_BOOL,
         NULL, NULL, NULL},
 
+       /* Quote */
+       {"reply_quote_mark", "> ", &prefs_common.quotemark, P_STRING,
+        &quote.entry_quotemark, prefs_set_data_from_entry, prefs_set_entry},
+       {"reply_quote_format", "On %d\\n%f wrote:\\n\\n%Q",
+        &prefs_common.quotefmt, P_STRING, &quote.text_quotefmt,
+        prefs_set_data_from_text, prefs_set_text},
+
+       {"fw_quote_mark", "> ", &prefs_common.fw_quotemark, P_STRING,
+        &quote.entry_fw_quotemark,
+        prefs_set_data_from_entry, prefs_set_entry},
+       {"fw_quote_format",
+        "\\n\\nBegin forwarded message:\\n\\n"
+        "?d(Date: %d\\n)?f(From: %f\\n)?t(To: %t\\n)?c(Cc: %c\\n)"
+        "?n(Newsgroups: %n\\n)?s(Subject: %s\\n)\\n\\n%M",
+        &prefs_common.fw_quotefmt, P_STRING, &quote.text_fw_quotefmt,
+        prefs_set_data_from_text, prefs_set_text},
+
        /* Display */
        {"widget_font", NULL, &prefs_common.widgetfont, P_STRING,
         NULL, NULL, NULL},
@@ -585,6 +590,8 @@ static PrefParam param[] = {
         &prefs_common.mime_image_viewer, P_STRING, NULL, NULL, NULL},
        {"mime_audio_player", "play '%s'",
         &prefs_common.mime_audio_player, P_STRING, NULL, NULL, NULL},
+       {"mime_open_command", "gedit '%s'",
+        &prefs_common.mime_open_cmd, P_STRING, NULL, NULL, NULL},
 
 #if USE_GPGME
        /* Privacy */
@@ -688,6 +695,7 @@ static void prefs_common_create             (void);
 static void prefs_receive_create       (void);
 static void prefs_send_create          (void);
 static void prefs_compose_create       (void);
+static void prefs_quote_create         (void);
 static void prefs_display_create       (void);
 static void prefs_message_create       (void);
 #if USE_GPGME
@@ -716,8 +724,11 @@ static void date_format_select_row         (GtkWidget      *date_format_list,
 static GtkWidget *date_format_create           (GtkButton      *button,
                                                 void           *data);
 
-static void prefs_quote_description            (void);
 static void prefs_quote_description_create     (void);
+static void prefs_quote_description_key_pressed        (GtkWidget      *widget,
+                                                GdkEventKey    *event,
+                                                gpointer        data);
+
 static void prefs_quote_colors_dialog          (void);
 static void prefs_quote_colors_dialog_create   (void);
 static void prefs_quote_colors_key_pressed     (GtkWidget      *widget,
@@ -754,9 +765,6 @@ static void prefs_common_ok         (void);
 static void prefs_common_apply         (void);
 static void prefs_common_cancel                (void);
 
-static void compose_prefs_fmt_open(void);
-static void compose_prefs_fmt_create(void);
-
 void prefs_common_init() {
        prefs_common.fltlist = NULL;
        prefs_common.disphdr_list = NULL;
@@ -764,12 +772,56 @@ void prefs_common_init() {
 
 void prefs_common_read_config(void)
 {
+       FILE *fp;
+       gchar *path;
+       gchar buf[PREFSBUFSIZE];
+
        prefs_read_config(param, "Common", COMMON_RC);
+
+       path = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, COMMAND_HISTORY,
+                          NULL);
+       if ((fp = fopen(path, "r")) == NULL) {
+               if (ENOENT != errno) FILE_OP_ERROR(path, "fopen");
+               g_free(path);
+               return;
+       }
+       g_free(path);
+       while (fgets(buf, sizeof(buf), fp) != NULL) {
+               g_strstrip(buf);
+               if (buf[0] == '\0') continue;
+               prefs_common.mime_open_cmd_history =
+                       add_history(prefs_common.mime_open_cmd_history, buf);
+       }
+       fclose(fp);
+
+       prefs_common.mime_open_cmd_history =
+               g_list_reverse(prefs_common.mime_open_cmd_history);
 }
 
 void prefs_common_save_config(void)
 {
+       GList *cur;
+       FILE *fp;
+       gchar *path;
+
        prefs_save_config(param, "Common", COMMON_RC);
+
+       path = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, COMMAND_HISTORY,
+                          NULL);
+       if ((fp = fopen(path, "w")) == NULL) {
+               FILE_OP_ERROR(path, "fopen");
+               g_free(path);
+               return;
+       }
+
+       for (cur = prefs_common.mime_open_cmd_history;
+            cur != NULL; cur = cur->next) {
+               fputs((gchar *)cur->data, fp);
+               fputc('\n', fp);
+       }
+
+       fclose(fp);
+       g_free(path);
 }
 
 void prefs_common_open(void)
@@ -824,6 +876,8 @@ static void prefs_common_create(void)
        SET_NOTEBOOK_LABEL(dialog.notebook, _("Send"),      page++);
        prefs_compose_create();
        SET_NOTEBOOK_LABEL(dialog.notebook, _("Compose"),   page++);
+       prefs_quote_create();
+       SET_NOTEBOOK_LABEL(dialog.notebook, _("Quote"),   page++);
        prefs_display_create();
        SET_NOTEBOOK_LABEL(dialog.notebook, _("Display"),   page++);
        prefs_message_create();
@@ -837,8 +891,6 @@ static void prefs_common_create(void)
        prefs_other_create();
        SET_NOTEBOOK_LABEL(dialog.notebook, _("Other"),     page++);
 
-       compose_prefs_fmt_create();
-
        gtk_widget_show_all(dialog.window);
 }
 
@@ -903,11 +955,13 @@ static void prefs_receive_create(void)
        entry_incext = gtk_entry_new ();
        gtk_widget_show (entry_incext);
        gtk_box_pack_start (GTK_BOX (hbox), entry_incext, TRUE, TRUE, 0);
+
 #if 0
        button_incext = gtk_button_new_with_label ("... ");
        gtk_widget_show (button_incext);
        gtk_box_pack_start (GTK_BOX (hbox), button_incext, FALSE, FALSE, 0);
 #endif
+
        PACK_FRAME(vbox1, frame_spool, _("Local spool"));
 
        vbox2 = gtk_vbox_new (FALSE, VSPACING_NARROW);
@@ -977,7 +1031,6 @@ static void prefs_receive_create(void)
        PACK_CHECK_BUTTON (vbox2, checkbtn_scan_after_inc,
                           _("Update all local folders after incorporation"));
 
-
        PACK_FRAME(vbox1, frame_news, _("News"));
 
        hbox = gtk_hbox_new (FALSE, 8);
@@ -1266,21 +1319,6 @@ static void prefs_compose_create(void)
        GtkWidget *vbox1;
         GtkWidget *vbox2;
         GtkWidget *vbox3;
-
-       /*
-       GtkWidget *frame_quote;
-       GtkWidget *vbox_quote;
-       GtkWidget *checkbtn_quote;
-       GtkWidget *hbox1;
-       GtkWidget *label_quotemark;
-       GtkWidget *entry_quotemark;
-       GtkWidget *hbox2;
-       GtkWidget *label_quotefmt;
-       GtkWidget *btn_quotedesc;
-       GtkWidget *scrolledwin_quotefmt;
-       GtkWidget *text_quotefmt;
-*/
-
        GtkWidget *hbox1;
        GtkWidget *hbox2;
        GtkWidget *btn_quotefmt;
@@ -1291,13 +1329,14 @@ static void prefs_compose_create(void)
        GtkWidget *label_sigsep;
        GtkWidget *entry_sigsep;
 
+       GtkWidget *frame_editor;
        GtkWidget *frame_autosel;
         GtkWidget *hbox_autosel;
         GtkWidget *vbox_autosel;
-       GtkWidget *checkbtn_reply_account_autosel;
        GtkWidget *checkbtn_forward_account_autosel;
        GtkWidget *checkbtn_reedit_account_autosel;
 
+       GtkWidget *hbox_editor;
        GtkWidget *checkbtn_autoextedit;
 
         GtkWidget *vbox_linewrap;
@@ -1311,6 +1350,9 @@ static void prefs_compose_create(void)
        GtkWidget *checkbtn_wrapquote;
        GtkWidget *checkbtn_wrapatsend;
 
+       GtkWidget *frame_reply;
+       GtkWidget *checkbtn_reply_account_autosel;
+       GtkWidget *checkbtn_quote;
        GtkWidget *checkbtn_forward_as_attachment;
        GtkWidget *checkbtn_smart_wrapping;
        GtkWidget *checkbtn_block_cursor;
@@ -1333,75 +1375,20 @@ static void prefs_compose_create(void)
        gtk_container_add (GTK_CONTAINER (dialog.notebook), vbox1);
        gtk_container_set_border_width (GTK_CONTAINER (vbox1), VBOX_BORDER);
 
-       /*
-       PACK_FRAME(vbox1, frame_quote, _("Quotation"));
 
-       vbox_quote = gtk_vbox_new (FALSE, VSPACING_NARROW);
-       gtk_widget_show (vbox_quote);
-       gtk_container_add (GTK_CONTAINER (frame_quote), vbox_quote);
-       gtk_container_set_border_width (GTK_CONTAINER (vbox_quote), 8);
 
        hbox1 = gtk_hbox_new (FALSE, 32);
        gtk_widget_show (hbox1);
-       gtk_box_pack_start (GTK_BOX (vbox_quote), hbox1, FALSE, FALSE, 0);
 
        hbox2 = gtk_hbox_new (FALSE, 8);
        gtk_widget_show (hbox2);
        gtk_box_pack_start (GTK_BOX (hbox1), hbox2, FALSE, FALSE, 0);
 
-       label_quotemark = gtk_label_new (_("Quotation mark"));
-       gtk_widget_show (label_quotemark);
-       gtk_box_pack_start (GTK_BOX (hbox2), label_quotemark, FALSE, FALSE, 0);
-
-       entry_quotemark = gtk_entry_new ();
-       gtk_widget_show (entry_quotemark);
-       gtk_box_pack_start (GTK_BOX (hbox2), entry_quotemark, FALSE, FALSE, 0);
-       gtk_widget_set_usize (entry_quotemark, 64, -1);
-
-       PACK_CHECK_BUTTON (hbox1, checkbtn_quote,
-                          _("Quote message when replying"));
-
-       hbox2 = gtk_hbox_new (FALSE, 0);
-       gtk_widget_show (hbox2);
-       gtk_box_pack_start (GTK_BOX (vbox_quote), hbox2, TRUE, TRUE, 0);
-
-       label_quotefmt = gtk_label_new (_("Quotation format:"));
-       gtk_widget_show (label_quotefmt);
-       gtk_box_pack_start (GTK_BOX (hbox2), label_quotefmt, FALSE, FALSE, 0);
-
-       btn_quotedesc =
-               gtk_button_new_with_label (_(" Description of symbols "));
-
-       gtk_widget_show (btn_quotedesc);
-       gtk_box_pack_end (GTK_BOX (hbox2), btn_quotedesc, FALSE, FALSE, 0);
-       gtk_signal_connect(GTK_OBJECT(btn_quotedesc), "clicked",
-                          GTK_SIGNAL_FUNC(prefs_quote_description), NULL);
-
-
-       scrolledwin_quotefmt = gtk_scrolled_window_new (NULL, NULL);
-       gtk_widget_show (scrolledwin_quotefmt);
-       gtk_box_pack_start (GTK_BOX (vbox_quote), scrolledwin_quotefmt, TRUE, TRUE, 0);
-       gtk_scrolled_window_set_policy
-               (GTK_SCROLLED_WINDOW (scrolledwin_quotefmt),
-                GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
-
-       text_quotefmt = gtk_text_new (NULL, NULL);
-       gtk_widget_show (text_quotefmt);
-       gtk_container_add(GTK_CONTAINER(scrolledwin_quotefmt), text_quotefmt);
-       gtk_text_set_editable (GTK_TEXT (text_quotefmt), TRUE);
-       gtk_widget_set_usize(text_quotefmt, -1, 60);
-       */
 
        hbox1 = gtk_hbox_new (FALSE, 32);
        gtk_widget_show (hbox1);
        gtk_box_pack_start (GTK_BOX (vbox1), hbox1, FALSE, FALSE, 0);
 
-       btn_quotefmt = gtk_button_new_with_label (_(" Quote format "));
-       gtk_widget_show (btn_quotefmt);
-       gtk_box_pack_start (GTK_BOX (hbox1), btn_quotefmt, FALSE, FALSE, 0);
-       gtk_signal_connect(GTK_OBJECT(btn_quotefmt), "clicked",
-                          GTK_SIGNAL_FUNC(compose_prefs_fmt_open), NULL);
-
        PACK_FRAME(vbox1, frame_sig, _("Signature"));
 
        vbox_sig = gtk_vbox_new (FALSE, VSPACING_NARROW);
@@ -1581,6 +1568,125 @@ static void prefs_compose_create(void)
 #endif
 }
 
+static void prefs_quote_create(void)
+{
+       GtkWidget *vbox1;
+       GtkWidget *frame_quote;
+       GtkWidget *vbox_quote;
+       GtkWidget *hbox1;
+       GtkWidget *hbox2;
+       GtkWidget *label_quotemark;
+       GtkWidget *entry_quotemark;
+       GtkWidget *scrolledwin_quotefmt;
+       GtkWidget *text_quotefmt;
+
+       GtkWidget *entry_fw_quotemark;
+       GtkWidget *text_fw_quotefmt;
+
+       GtkWidget *btn_quotedesc;
+
+       vbox1 = gtk_vbox_new (FALSE, VSPACING);
+       gtk_widget_show (vbox1);
+       gtk_container_add (GTK_CONTAINER (dialog.notebook), vbox1);
+       gtk_container_set_border_width (GTK_CONTAINER (vbox1), VBOX_BORDER);
+
+       /* reply */
+
+       PACK_FRAME (vbox1, frame_quote, _("Reply format"));
+
+       vbox_quote = gtk_vbox_new (FALSE, VSPACING_NARROW);
+       gtk_widget_show (vbox_quote);
+       gtk_container_add (GTK_CONTAINER (frame_quote), vbox_quote);
+       gtk_container_set_border_width (GTK_CONTAINER (vbox_quote), 8);
+
+       hbox1 = gtk_hbox_new (FALSE, 32);
+       gtk_widget_show (hbox1);
+       gtk_box_pack_start (GTK_BOX (vbox_quote), hbox1, FALSE, FALSE, 0);
+
+       hbox2 = gtk_hbox_new (FALSE, 8);
+       gtk_widget_show (hbox2);
+       gtk_box_pack_start (GTK_BOX (hbox1), hbox2, FALSE, FALSE, 0);
+
+       label_quotemark = gtk_label_new (_("Quotation mark"));
+       gtk_widget_show (label_quotemark);
+       gtk_box_pack_start (GTK_BOX (hbox2), label_quotemark, FALSE, FALSE, 0);
+
+       entry_quotemark = gtk_entry_new ();
+       gtk_widget_show (entry_quotemark);
+       gtk_box_pack_start (GTK_BOX (hbox2), entry_quotemark, FALSE, FALSE, 0);
+       gtk_widget_set_usize (entry_quotemark, 64, -1);
+
+       scrolledwin_quotefmt = gtk_scrolled_window_new (NULL, NULL);
+       gtk_widget_show (scrolledwin_quotefmt);
+       gtk_box_pack_start (GTK_BOX (vbox_quote), scrolledwin_quotefmt, TRUE, TRUE, 0);
+       gtk_scrolled_window_set_policy
+               (GTK_SCROLLED_WINDOW (scrolledwin_quotefmt),
+                GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
+
+       text_quotefmt = gtk_text_new (NULL, NULL);
+       gtk_widget_show (text_quotefmt);
+       gtk_container_add(GTK_CONTAINER(scrolledwin_quotefmt), text_quotefmt);
+       gtk_text_set_editable (GTK_TEXT (text_quotefmt), TRUE);
+       gtk_widget_set_usize(text_quotefmt, -1, 60);
+
+       /* forward */
+
+       PACK_FRAME (vbox1, frame_quote, _("Forward format"));
+
+       vbox_quote = gtk_vbox_new (FALSE, VSPACING_NARROW);
+       gtk_widget_show (vbox_quote);
+       gtk_container_add (GTK_CONTAINER (frame_quote), vbox_quote);
+       gtk_container_set_border_width (GTK_CONTAINER (vbox_quote), 8);
+
+       hbox1 = gtk_hbox_new (FALSE, 32);
+       gtk_widget_show (hbox1);
+       gtk_box_pack_start (GTK_BOX (vbox_quote), hbox1, FALSE, FALSE, 0);
+
+       hbox2 = gtk_hbox_new (FALSE, 8);
+       gtk_widget_show (hbox2);
+       gtk_box_pack_start (GTK_BOX (hbox1), hbox2, FALSE, FALSE, 0);
+
+       label_quotemark = gtk_label_new (_("Quotation mark"));
+       gtk_widget_show (label_quotemark);
+       gtk_box_pack_start (GTK_BOX (hbox2), label_quotemark, FALSE, FALSE, 0);
+
+       entry_fw_quotemark = gtk_entry_new ();
+       gtk_widget_show (entry_fw_quotemark);
+       gtk_box_pack_start (GTK_BOX (hbox2), entry_fw_quotemark,
+                           FALSE, FALSE, 0);
+       gtk_widget_set_usize (entry_fw_quotemark, 64, -1);
+
+       scrolledwin_quotefmt = gtk_scrolled_window_new (NULL, NULL);
+       gtk_widget_show (scrolledwin_quotefmt);
+       gtk_box_pack_start (GTK_BOX (vbox_quote), scrolledwin_quotefmt, TRUE, TRUE, 0);
+       gtk_scrolled_window_set_policy
+               (GTK_SCROLLED_WINDOW (scrolledwin_quotefmt),
+                GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
+
+       text_fw_quotefmt = gtk_text_new (NULL, NULL);
+       gtk_widget_show (text_fw_quotefmt);
+       gtk_container_add(GTK_CONTAINER(scrolledwin_quotefmt),
+                         text_fw_quotefmt);
+       gtk_text_set_editable (GTK_TEXT (text_fw_quotefmt), TRUE);
+       gtk_widget_set_usize(text_fw_quotefmt, -1, 60);
+
+       hbox1 = gtk_hbox_new (FALSE, 32);
+       gtk_widget_show (hbox1);
+       gtk_box_pack_start (GTK_BOX (vbox1), hbox1, FALSE, FALSE, 0);
+
+       btn_quotedesc =
+               gtk_button_new_with_label (_(" Description of symbols "));
+       gtk_widget_show (btn_quotedesc);
+       gtk_box_pack_start (GTK_BOX (hbox1), btn_quotedesc, FALSE, FALSE, 0);
+       gtk_signal_connect(GTK_OBJECT(btn_quotedesc), "clicked",
+                          GTK_SIGNAL_FUNC(prefs_quote_description), NULL);
+
+       quote.entry_quotemark    = entry_quotemark;
+       quote.text_quotefmt      = text_quotefmt;
+       quote.entry_fw_quotemark = entry_fw_quotemark;
+       quote.text_fw_quotefmt   = text_fw_quotefmt;
+}
+
 static void prefs_display_create(void)
 {
        GtkWidget *vbox1;
@@ -2952,11 +3058,12 @@ static void prefs_recycle_colors_toggled(GtkWidget *widget)
        prefs_common.recycle_quote_colors = is_active;
 }
 
-static void prefs_quote_description(void)
+void prefs_quote_description(void)
 {
        if (!quote_desc_win)
                prefs_quote_description_create();
 
+       manage_window_set_transient(GTK_WINDOW(quote_desc_win));
        gtk_widget_show(quote_desc_win);
        gtk_main();
        gtk_widget_hide(quote_desc_win);
@@ -2988,10 +3095,10 @@ static void prefs_quote_description_create(void)
                ("SYMBOL\n\n"
                  "%d\n"                /* date */
                 "%f\n"         /* from */
-                "%N\n"         /* full name */
-                "%F\n"         /* first name */
-                "%I\n"         /* sender's initial */
-                "%s\n"         /* subject line */
+                "%N\n"         /* full name of sender */
+                "%F\n"         /* first name of sender */
+                "%I\n"         /* initial of sender */
+                "%s\n"         /* subject */
                 "%t\n"         /* to */
                 "%c\n"         /* cc */
                 "%n\n"         /* newsgroups */
@@ -2999,13 +3106,13 @@ static void prefs_quote_description_create(void)
                 "%r\n"         /* references */
                 "\n"
                 "%x\n"
-                "?x(expr)\n"
+                "?x(expr)\n"   /* condition */
                 "\n"
-                "%M\n"
-                "%Q\n"
-                "%m\n"
-                "%q\n"
-                "%%");
+                "%M\n"         /* message body */
+                "%Q\n"         /* quoted message body */
+                "%m\n"         /* message body without signature */
+                "%q\n"         /* quoted message body without signature */
+                "%%");         /* literal percent */
 
        gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
        gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
@@ -3031,7 +3138,7 @@ static void prefs_quote_description_create(void)
                   "Quoted message body\n"
                   "Message body without signature\n"
                   "Quoted message body without signature\n"
-                  "%"));
+                  "Literal %"));
 
        gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
        gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
@@ -3042,14 +3149,25 @@ static void prefs_quote_description_create(void)
 
        gtk_widget_grab_default(ok_btn);
        gtk_signal_connect(GTK_OBJECT(ok_btn), "clicked",
-                                 GTK_SIGNAL_FUNC(gtk_main_quit), NULL);
-
+                          GTK_SIGNAL_FUNC(gtk_main_quit), NULL);
+       gtk_signal_connect
+               (GTK_OBJECT(quote_desc_win), "key_press_event",
+                GTK_SIGNAL_FUNC(prefs_quote_description_key_pressed),
+                NULL);
        gtk_signal_connect(GTK_OBJECT(quote_desc_win), "delete_event",
-                                         GTK_SIGNAL_FUNC(gtk_main_quit), NULL);
+                          GTK_SIGNAL_FUNC(gtk_main_quit), NULL);
 
        gtk_widget_show_all(vbox);
 }
 
+static void prefs_quote_description_key_pressed(GtkWidget *widget,
+                                               GdkEventKey *event,
+                                               gpointer data)
+{
+       if (event && event->keyval == GDK_Escape)
+               gtk_main_quit();
+}
+
 static void prefs_font_select(GtkButton *button, GtkEntry *entry)
 {
        gchar *font_name;
@@ -3287,156 +3405,6 @@ static gint compose_prefs_delete_event(GtkWidget *widget, GdkEventAny *event);
 static void compose_prefs_close(GtkWidget *widget);
 static void compose_prefs_fmt_create(void);
 
-static void compose_prefs_fmt_open(void)
-{
-       if (composeprefs.window == NULL)
-               compose_prefs_fmt_create();
-       gtk_widget_show(composeprefs.window);
-}
-
-
-static void compose_prefs_fmt_create(void)
-{
-       GtkWidget *window;
-       GtkWidget *close_btn;
-
-       GtkWidget *frame_quote;
-       GtkWidget *vbox_quote;
-       GtkWidget *hbox1;
-       GtkWidget *checkbtn_quote;
-       GtkWidget *label_quotemark;
-       GtkWidget *entry_quotemark;
-       GtkWidget *scrolledwin_quotefmt;
-       GtkWidget *text_quotefmt;
-       GtkWidget *label_quotefmt;
-       GtkWidget *btn_quotedesc;
-
-       GtkWidget *label_fw_quotemark;
-       GtkWidget *entry_fw_quotemark;
-       GtkWidget *label_fw_quotefmt;
-       GtkWidget *text_fw_quotefmt;
-
-       window = gtk_window_new(GTK_WINDOW_DIALOG);
-       gtk_container_set_border_width(GTK_CONTAINER(window), 8);
-       gtk_window_set_title(GTK_WINDOW(window), _("Compose Preferences"));
-       gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
-       gtk_window_set_modal(GTK_WINDOW(window), TRUE);
-       gtk_window_set_policy(GTK_WINDOW(window), FALSE, FALSE, FALSE);
-       gtk_signal_connect(GTK_OBJECT(window), "delete_event",
-                          GTK_SIGNAL_FUNC(compose_prefs_delete_event),
-                          NULL);
-       gtk_signal_connect(GTK_OBJECT(window), "key_press_event",
-                          GTK_SIGNAL_FUNC(compose_prefs_key_pressed),
-                          NULL);
-
-       vbox_quote = gtk_vbox_new(FALSE, 8);
-       gtk_container_add(GTK_CONTAINER(window), vbox_quote);
-
-       PACK_CHECK_BUTTON (vbox_quote, checkbtn_quote,
-                          _("Quote message when replying"));
-
-       hbox1 = gtk_hbox_new (FALSE, 8);
-       gtk_widget_show (hbox1);
-       gtk_box_pack_start (GTK_BOX (vbox_quote), hbox1, TRUE, TRUE, 0);
-
-       label_quotemark = gtk_label_new (_("Quotation mark"));
-       gtk_widget_show (label_quotemark);
-       gtk_box_pack_start (GTK_BOX (hbox1), label_quotemark, FALSE, FALSE, 0);
-
-       entry_quotemark = gtk_entry_new ();
-       gtk_widget_show (entry_quotemark);
-       gtk_box_pack_start (GTK_BOX (hbox1), entry_quotemark, FALSE, FALSE, 0);
-       gtk_widget_set_usize (entry_quotemark, 64, -1);
-
-       hbox1 = gtk_hbox_new (FALSE, 0);
-       gtk_widget_show (hbox1);
-       gtk_box_pack_start (GTK_BOX (vbox_quote), hbox1, TRUE, TRUE, 0);
-
-       label_quotefmt = gtk_label_new (_("Quotation format:"));
-       gtk_widget_show (label_quotefmt);
-       gtk_box_pack_start (GTK_BOX (hbox1), label_quotefmt, FALSE, FALSE, 0);
-
-       scrolledwin_quotefmt = gtk_scrolled_window_new (NULL, NULL);
-       gtk_widget_show (scrolledwin_quotefmt);
-       gtk_box_pack_start (GTK_BOX (vbox_quote), scrolledwin_quotefmt, TRUE, TRUE, 0);
-       gtk_scrolled_window_set_policy
-               (GTK_SCROLLED_WINDOW (scrolledwin_quotefmt),
-                GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
-
-       text_quotefmt = gtk_text_new (NULL, NULL);
-       gtk_widget_show (text_quotefmt);
-       gtk_container_add(GTK_CONTAINER(scrolledwin_quotefmt), text_quotefmt);
-       gtk_text_set_editable (GTK_TEXT (text_quotefmt), TRUE);
-       gtk_widget_set_usize(text_quotefmt, 400, 60);
-
-       hbox1 = gtk_hbox_new (FALSE, 8);
-       gtk_widget_show (hbox1);
-       gtk_box_pack_start (GTK_BOX (vbox_quote), hbox1, TRUE, TRUE, 0);
-
-       label_fw_quotemark = gtk_label_new (_("Forward quotation mark"));
-       gtk_widget_show (label_fw_quotemark);
-       gtk_box_pack_start (GTK_BOX (hbox1), label_fw_quotemark, FALSE, FALSE, 0);
-
-       entry_fw_quotemark = gtk_entry_new ();
-       gtk_widget_show (entry_fw_quotemark);
-       gtk_box_pack_start (GTK_BOX (hbox1), entry_fw_quotemark, FALSE, FALSE, 0);
-       gtk_widget_set_usize (entry_fw_quotemark, 64, -1);
-
-       hbox1 = gtk_hbox_new (FALSE, 0);
-       gtk_widget_show (hbox1);
-       gtk_box_pack_start (GTK_BOX (vbox_quote), hbox1, TRUE, TRUE, 0);
-
-       label_fw_quotefmt = gtk_label_new (_("Forward format:"));
-       gtk_widget_show (label_fw_quotefmt);
-       gtk_box_pack_start (GTK_BOX (hbox1), label_fw_quotefmt, FALSE, FALSE, 0);
-
-       scrolledwin_quotefmt = gtk_scrolled_window_new (NULL, NULL);
-       gtk_widget_show (scrolledwin_quotefmt);
-       gtk_box_pack_start (GTK_BOX (vbox_quote), scrolledwin_quotefmt, TRUE, TRUE, 0);
-       gtk_scrolled_window_set_policy
-               (GTK_SCROLLED_WINDOW (scrolledwin_quotefmt),
-                GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
-
-       text_fw_quotefmt = gtk_text_new (NULL, NULL);
-       gtk_widget_show (text_fw_quotefmt);
-       gtk_container_add(GTK_CONTAINER(scrolledwin_quotefmt), text_fw_quotefmt);
-       gtk_text_set_editable (GTK_TEXT (text_fw_quotefmt), TRUE);
-       gtk_widget_set_usize(text_fw_quotefmt, 400, 60);
-
-       hbox1 = gtk_hbox_new (FALSE, 0);
-       gtk_widget_show (hbox1);
-       gtk_box_pack_start (GTK_BOX (vbox_quote), hbox1, FALSE, FALSE, 0);
-
-       btn_quotedesc =
-               gtk_button_new_with_label (_(" Description of symbols "));
-       gtk_widget_show (btn_quotedesc);
-       gtk_box_pack_start (GTK_BOX (hbox1), btn_quotedesc,
-                           FALSE, FALSE, 0);
-
-       gtk_signal_connect(GTK_OBJECT(btn_quotedesc), "clicked",
-                          GTK_SIGNAL_FUNC(prefs_quote_description), NULL);
-
-
-       gtkut_button_set_create(&hbox1, &close_btn, _("Close"),
-                               NULL, NULL, NULL, NULL);
-       gtk_box_pack_end(GTK_BOX(vbox_quote), hbox1, FALSE, FALSE, 0);
-       gtk_widget_grab_default(close_btn);
-
-       gtk_signal_connect(GTK_OBJECT(close_btn), "clicked",
-                          GTK_SIGNAL_FUNC(compose_prefs_close), NULL);
-
-       gtk_widget_show_all(vbox_quote);
-
-       composeprefs.window = window;
-       composeprefs.close_btn = close_btn;
-
-       compose.checkbtn_quote = checkbtn_quote;
-       compose.entry_quotemark = entry_quotemark;
-       compose.text_quotefmt = text_quotefmt;
-       compose.entry_fw_quotemark = entry_fw_quotemark;
-       compose.text_fw_quotefmt = text_fw_quotefmt;
-}
-
 static void compose_prefs_close(GtkWidget *widget)
 {
        gtk_widget_hide(composeprefs.window);
index 9546c64..0787c69 100644 (file)
@@ -69,9 +69,6 @@ struct _PrefsCommon
        gchar *outgoing_charset;
 
        /* Compose */
-       gboolean reply_with_quote;
-       gchar *quotemark;
-       gchar *quotefmt;
        gboolean auto_sig;
        gchar *sig_sep;
        gint linewrap_len;
@@ -82,6 +79,11 @@ struct _PrefsCommon
        gboolean forward_account_autosel;
        gboolean reedit_account_autosel;
        gboolean show_ruler;
+
+       /* Quote */
+       gboolean reply_with_quote;
+       gchar *quotemark;
+       gchar *quotefmt;
        gchar *fw_quotemark;
        gchar *fw_quotefmt;
        gboolean forward_as_attachment;
@@ -176,6 +178,9 @@ struct _PrefsCommon
        /* MIME viewer */
        gchar *mime_image_viewer;
        gchar *mime_audio_player;
+       gchar *mime_open_cmd;
+
+       GList *mime_open_cmd_history;
 
        /* Privacy */
        gboolean default_encrypt;
@@ -217,6 +222,6 @@ void prefs_common_read_config       (void);
 void prefs_common_save_config  (void);
 void prefs_common_open         (void);
 
-void prefs_summary_display_item_set    (void);
+void prefs_quote_description   (void);
 
 #endif /* __PREFS_COMMON_H__ */
diff --git a/src/prefs_template.c b/src/prefs_template.c
new file mode 100644 (file)
index 0000000..739389a
--- /dev/null
@@ -0,0 +1,449 @@
+/*
+ * Sylpheed templates subsystem 
+ * Copyright (C) 2001 Alexander Barinov
+ * Copyright (C) 2001 Hiroyuki Yamamoto
+ *
+ * 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 2 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "defs.h"
+
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
+#include <dirent.h>
+#include <sys/stat.h>
+
+#include "intl.h"
+#include "template.h"
+#include "main.h"
+#include "inc.h"
+#include "utils.h"
+#include "gtkutils.h"
+#include "alertpanel.h"
+#include "manage_window.h"
+#include "prefs_common.h"
+#include "compose.h"
+
+static struct Templates {
+       GtkWidget *window;
+       GtkWidget *ok_btn;
+       GtkWidget *clist_tmpls;
+       GtkWidget *entry_name;
+       GtkWidget *text_value;
+} templates;
+
+/* widget creating functions */
+static void prefs_template_window_create       (void);
+static void prefs_template_window_setup                (void);
+static void prefs_template_clear               (void);
+
+static GSList *prefs_template_get_list         (void);
+
+/* callbacks */
+static gint prefs_template_deleted_cb          (GtkWidget      *widget,
+                                                GdkEventAny    *event,
+                                                gpointer        data);
+static void prefs_template_key_pressed_cb      (GtkWidget      *widget,
+                                                GdkEventKey    *event,
+                                                gpointer        data);
+static void prefs_template_cancel_cb           (void);
+static void prefs_template_ok_cb               (void);
+static void prefs_template_select_cb           (GtkCList       *clist,
+                                                gint            row,
+                                                gint            column,
+                                                GdkEvent       *event);
+static void prefs_template_register_cb         (void);
+static void prefs_template_substitute_cb       (void);
+static void prefs_template_delete_cb           (void);
+
+/* Called from mainwindow.c */
+void prefs_template_open(void)
+{
+       inc_lock();
+
+       if (!templates.window)
+               prefs_template_window_create();
+
+       prefs_template_window_setup();
+       gtk_widget_show(templates.window);
+}
+
+static void prefs_template_window_create(void)
+{
+       /* window structure ;) */
+       GtkWidget *window;
+       GtkWidget   *vpaned;
+       GtkWidget     *vbox1;
+       GtkWidget       *hbox1;
+       GtkWidget         *label1;
+       GtkWidget         *entry_name;
+       GtkWidget       *scroll2;
+       GtkWidget         *text_value;
+       GtkWidget     *vbox2;
+       GtkWidget       *hbox2;
+       GtkWidget         *arrow1;
+       GtkWidget         *hbox3;
+       GtkWidget           *reg_btn;
+       GtkWidget           *subst_btn;
+       GtkWidget           *del_btn;
+       GtkWidget         *desc_btn;
+       GtkWidget       *scroll1;
+       GtkWidget         *clist_tmpls;
+       GtkWidget       *confirm_area;
+       GtkWidget         *ok_btn;
+       GtkWidget         *cancel_btn;
+
+       gchar *title[1];
+
+       /* main window */
+       window = gtk_window_new(GTK_WINDOW_DIALOG);
+       gtk_window_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
+       gtk_window_set_modal(GTK_WINDOW(window), TRUE);
+       gtk_window_set_policy(GTK_WINDOW(window), FALSE, TRUE, FALSE);
+       gtk_window_set_default_size(GTK_WINDOW(window), 400, -1);
+
+       /* vpaned to separate template settings from templates list */
+       vpaned = gtk_vpaned_new();
+       gtk_widget_show(vpaned);
+       gtk_container_add(GTK_CONTAINER(window), vpaned);
+
+       /* vbox to handle template name and content */
+       vbox1 = gtk_vbox_new(FALSE, 6);
+       gtk_widget_show(vbox1);
+       gtk_container_set_border_width(GTK_CONTAINER(vbox1), 8);
+       gtk_paned_pack1(GTK_PANED(vpaned), vbox1, FALSE, FALSE);
+
+       /* hbox for a label and template name entry */
+       hbox1 = gtk_hbox_new(FALSE, 8);
+       gtk_widget_show(hbox1);
+       gtk_box_pack_start(GTK_BOX(vbox1), hbox1, FALSE, FALSE, 0);
+       gtk_container_set_border_width(GTK_CONTAINER(hbox1), 2);
+
+       /* self-documenting */
+       label1 = gtk_label_new(_("Template name"));
+       gtk_widget_show(label1);
+       gtk_box_pack_start(GTK_BOX(hbox1), label1, FALSE, FALSE, 0);
+
+       /* holds template name */
+       entry_name = gtk_entry_new();
+       gtk_widget_show(entry_name);
+       gtk_box_pack_start(GTK_BOX(hbox1), entry_name, TRUE, TRUE, 0);
+
+       /* template content */
+       scroll2 = gtk_scrolled_window_new(NULL, NULL);
+       gtk_widget_show(scroll2);
+       gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll2),
+                                      GTK_POLICY_NEVER,
+                                      GTK_POLICY_ALWAYS);
+       gtk_box_pack_start(GTK_BOX(vbox1), scroll2, TRUE, TRUE, 0);
+
+       text_value = gtk_text_new(NULL, NULL);
+       gtk_widget_show(text_value);
+       gtk_widget_set_usize(text_value, -1, 120);
+       gtk_container_add(GTK_CONTAINER(scroll2), text_value);
+       gtk_text_set_editable(GTK_TEXT(text_value), TRUE);
+       gtk_text_set_word_wrap(GTK_TEXT(text_value), TRUE);
+
+       /* vbox for buttons and templates list */
+       vbox2 = gtk_vbox_new(FALSE, 6);
+       gtk_widget_show(vbox2);
+       gtk_container_set_border_width(GTK_CONTAINER(vbox2), 8);
+       gtk_paned_pack2(GTK_PANED(vpaned), vbox2, TRUE, FALSE);
+
+       /* register | substitute | delete */
+       hbox2 = gtk_hbox_new(FALSE, 4);
+       gtk_widget_show(hbox2);
+       gtk_box_pack_start(GTK_BOX(vbox2), hbox2, FALSE, FALSE, 0);
+
+       arrow1 = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_OUT);
+       gtk_widget_show(arrow1);
+       gtk_box_pack_start(GTK_BOX(hbox2), arrow1, FALSE, FALSE, 0);
+       gtk_widget_set_usize(arrow1, -1, 16);
+
+       hbox3 = gtk_hbox_new(TRUE, 4);
+       gtk_widget_show(hbox3);
+       gtk_box_pack_start(GTK_BOX(hbox2), hbox3, FALSE, FALSE, 0);
+
+       reg_btn = gtk_button_new_with_label(_("Register"));
+       gtk_widget_show(reg_btn);
+       gtk_box_pack_start(GTK_BOX(hbox3), reg_btn, FALSE, TRUE, 0);
+       gtk_signal_connect(GTK_OBJECT (reg_btn), "clicked",
+                          GTK_SIGNAL_FUNC (prefs_template_register_cb), NULL);
+
+       subst_btn = gtk_button_new_with_label(_(" Substitute "));
+       gtk_widget_show(subst_btn);
+       gtk_box_pack_start(GTK_BOX(hbox3), subst_btn, FALSE, TRUE, 0);
+       gtk_signal_connect(GTK_OBJECT(subst_btn), "clicked",
+                          GTK_SIGNAL_FUNC(prefs_template_substitute_cb),
+                          NULL);
+
+       del_btn = gtk_button_new_with_label(_("Delete"));
+       gtk_widget_show(del_btn);
+       gtk_box_pack_start(GTK_BOX(hbox3), del_btn, FALSE, TRUE, 0);
+       gtk_signal_connect(GTK_OBJECT(del_btn), "clicked",
+                          GTK_SIGNAL_FUNC(prefs_template_delete_cb), NULL);
+
+       desc_btn = gtk_button_new_with_label(_(" Symbols "));
+       gtk_widget_show(desc_btn);
+       gtk_box_pack_end(GTK_BOX(hbox2), desc_btn, FALSE, FALSE, 0);
+       gtk_signal_connect(GTK_OBJECT(desc_btn), "clicked",
+                          GTK_SIGNAL_FUNC(prefs_quote_description), NULL);
+
+       /* templates list */
+       scroll1 = gtk_scrolled_window_new(NULL, NULL);
+       gtk_widget_show(scroll1);
+       gtk_box_pack_start(GTK_BOX(vbox2), scroll1, TRUE, TRUE, 0);
+       gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll1),
+                                      GTK_POLICY_AUTOMATIC,
+                                      GTK_POLICY_AUTOMATIC);
+
+       title[0] = _("Registered templates");
+       clist_tmpls = gtk_clist_new_with_titles(1, title);
+       gtk_widget_show(clist_tmpls);
+       gtk_widget_set_usize(scroll1, -1, 140);
+       gtk_container_add(GTK_CONTAINER(scroll1), clist_tmpls);
+       gtk_clist_set_column_width(GTK_CLIST(clist_tmpls), 0, 80);
+       gtk_clist_set_selection_mode(GTK_CLIST(clist_tmpls),
+                                    GTK_SELECTION_BROWSE);
+       GTK_WIDGET_UNSET_FLAGS(GTK_CLIST(clist_tmpls)->column[0].button,
+                              GTK_CAN_FOCUS);
+       gtk_signal_connect(GTK_OBJECT (clist_tmpls), "select_row",
+                          GTK_SIGNAL_FUNC (prefs_template_select_cb), NULL);
+
+       /* ok | cancel */
+       gtkut_button_set_create(&confirm_area, &ok_btn, _("OK"),
+                               &cancel_btn, _("Cancel"), NULL, NULL);
+       gtk_widget_show(confirm_area);
+       gtk_box_pack_end(GTK_BOX(vbox2), confirm_area, FALSE, FALSE, 0);
+       gtk_widget_grab_default(ok_btn);
+
+       gtk_window_set_title(GTK_WINDOW(window), _("Templates"));
+
+       gtk_signal_connect(GTK_OBJECT(window), "delete_event",
+                          GTK_SIGNAL_FUNC(prefs_template_deleted_cb), NULL);
+       gtk_signal_connect(GTK_OBJECT(window), "key_press_event",
+                          GTK_SIGNAL_FUNC(prefs_template_key_pressed_cb), NULL);
+       gtk_signal_connect(GTK_OBJECT(window), "focus_in_event",
+                          GTK_SIGNAL_FUNC(manage_window_focus_in), NULL);
+       gtk_signal_connect(GTK_OBJECT(window), "focus_out_event",
+                          GTK_SIGNAL_FUNC(manage_window_focus_out), NULL);
+       gtk_signal_connect(GTK_OBJECT(ok_btn), "clicked",
+                          GTK_SIGNAL_FUNC(prefs_template_ok_cb), NULL);
+       gtk_signal_connect(GTK_OBJECT(cancel_btn), "clicked",
+                           GTK_SIGNAL_FUNC(prefs_template_cancel_cb), NULL);
+
+       templates.window = window;
+       templates.ok_btn = ok_btn;
+       templates.clist_tmpls = clist_tmpls;
+       templates.entry_name = entry_name;
+       templates.text_value = text_value;
+}
+
+static void prefs_template_window_setup(void)
+{
+       GtkCList *clist = GTK_CLIST(templates.clist_tmpls);
+       GSList *tmpl_list;
+       GSList *cur;
+       gchar *title[1];
+       gint row;
+       Template *tmpl;
+
+       manage_window_set_transient(GTK_WINDOW(templates.window));
+       gtk_widget_grab_focus(templates.ok_btn);
+
+       gtk_clist_freeze(clist);
+       gtk_clist_clear(clist);
+
+       title[0] = _("(New)");
+       row = gtk_clist_append(clist, title);
+       gtk_clist_set_row_data(clist, row, NULL);
+
+       tmpl_list = template_read_config();
+
+       for (cur = tmpl_list; cur != NULL; cur = cur->next) {
+               tmpl = (Template *)cur->data;
+               title[0] = tmpl->name;
+               row = gtk_clist_append(clist, title);
+               gtk_clist_set_row_data(clist, row, tmpl);
+       }
+
+       g_slist_free(tmpl_list);
+
+       gtk_clist_thaw(clist);
+}
+
+static void prefs_template_clear(void)
+{
+       Template *tmpl;
+       gint row = 1;
+
+       while ((tmpl = gtk_clist_get_row_data
+               (GTK_CLIST(templates.clist_tmpls), row)) != NULL) {
+               template_free(tmpl);
+               row++;
+       }
+
+       gtk_clist_clear(GTK_CLIST(templates.clist_tmpls));
+}
+
+static gint prefs_template_deleted_cb(GtkWidget *widget, GdkEventAny *event,
+                                     gpointer data)
+{
+       prefs_template_cancel_cb();
+       return TRUE;
+}
+
+static void prefs_template_key_pressed_cb(GtkWidget *widget,
+                                         GdkEventKey *event, gpointer data)
+{
+       if (event && event->keyval == GDK_Escape)
+               prefs_template_cancel_cb();
+}
+
+static void prefs_template_ok_cb(void)
+{
+       GSList *tmpl_list;
+
+       tmpl_list = prefs_template_get_list();
+       template_set_config(tmpl_list);
+       compose_reflect_prefs_all();
+       gtk_clist_clear(GTK_CLIST(templates.clist_tmpls));
+       gtk_widget_hide(templates.window);
+       inc_unlock();
+}
+
+static void prefs_template_cancel_cb(void)
+{
+       prefs_template_clear();
+       gtk_widget_hide(templates.window);
+       inc_unlock();
+}
+
+static void prefs_template_select_cb(GtkCList *clist, gint row, gint column,
+                                    GdkEvent *event)
+{
+       Template *tmpl;
+       Template tmpl_def;
+
+       tmpl_def.name = _("Template");
+       tmpl_def.value = "";
+
+       if (!(tmpl = gtk_clist_get_row_data(clist, row)))
+               tmpl = &tmpl_def;
+
+       gtk_entry_set_text(GTK_ENTRY(templates.entry_name), tmpl->name);
+       
+       gtk_text_freeze(GTK_TEXT(templates.text_value));
+       gtk_text_set_point(GTK_TEXT(templates.text_value), 0);
+       gtk_text_forward_delete
+               (GTK_TEXT(templates.text_value), 
+                gtk_text_get_length(GTK_TEXT(templates.text_value)));
+       gtk_text_insert(GTK_TEXT(templates.text_value), NULL, NULL, NULL,
+                       tmpl->value, -1);
+       gtk_text_thaw(GTK_TEXT(templates.text_value));
+}
+
+static GSList *prefs_template_get_list(void)
+{
+       gint row = 1;
+       GSList *tmpl_list = NULL;
+       Template *tmpl;
+
+       while ((tmpl = gtk_clist_get_row_data
+               (GTK_CLIST(templates.clist_tmpls), row)) != NULL) {
+               tmpl_list = g_slist_append(tmpl_list, tmpl);
+               row++;
+       }
+
+       return tmpl_list;
+}
+
+static gint prefs_template_clist_set_row(gint row)
+{
+       GtkCList *clist = GTK_CLIST(templates.clist_tmpls);
+       Template *tmpl;
+       Template *tmp_tmpl;
+       gchar *name;
+       gchar *value;
+       gchar *title[1];
+
+       g_return_val_if_fail(row != 0, -1);
+
+       name = gtk_editable_get_chars(GTK_EDITABLE(templates.entry_name),
+                                     0, -1);
+       value = gtk_editable_get_chars(GTK_EDITABLE(templates.text_value),
+                                      0, -1);
+
+       tmpl = g_new(Template, 1);
+       tmpl->name = name;
+       tmpl->value = value;
+
+       title[0] = name;
+
+       if (row < 0) {
+               row = gtk_clist_append(clist, title);
+       } else {
+               gtk_clist_set_text(clist, row, 0, name);
+               tmp_tmpl = gtk_clist_get_row_data(clist, row);
+               if (tmp_tmpl)
+                       template_free(tmp_tmpl);
+       }
+
+       gtk_clist_set_row_data(clist, row, tmpl);
+       return row;
+}
+
+static void prefs_template_register_cb(void)
+{
+       prefs_template_clist_set_row(-1);
+}
+
+static void prefs_template_substitute_cb(void)
+{
+       GtkCList *clist = GTK_CLIST(templates.clist_tmpls);
+       Template *tmpl;
+       gint row;
+
+       if (!clist->selection) return;
+
+       row = GPOINTER_TO_INT(clist->selection->data);
+       if (row == 0) return;
+
+       tmpl = gtk_clist_get_row_data(clist, row);
+       if (!tmpl) return;
+
+       prefs_template_clist_set_row(row);
+}
+
+static void prefs_template_delete_cb(void)
+{
+       GtkCList *clist = GTK_CLIST(templates.clist_tmpls);
+       Template *tmpl;
+       gint row;
+
+       if (!clist->selection) return;
+       row = GPOINTER_TO_INT(clist->selection->data);
+       if (row == 0) return;
+
+       if (alertpanel(_("Delete template"),
+                      _("Do you really want to delete this template?"),
+                      _("Yes"), _("No"), NULL) == G_ALERTALTERNATE)
+               return;
+
+       tmpl = gtk_clist_get_row_data(clist, row);
+       template_free(tmpl);
+       gtk_clist_remove(clist, row);
+}
diff --git a/src/prefs_template.h b/src/prefs_template.h
new file mode 100644 (file)
index 0000000..c9e9551
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Sylpheed templates subsystem 
+ * Copyright (C) 2001 Alexander Barinov
+ *
+ * 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 2 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PREFS_TEMPLATES_H__
+#define __PREFS_TEMPLATES_H__
+
+void prefs_template_open(void);
+
+#endif /* __PREFS_TEMPLATES_H__ */
index a0b2a59..249eeb4 100644 (file)
@@ -659,8 +659,7 @@ gchar *procheader_get_fromname(const gchar *str)
 {
        gchar *tmp, *name;
 
-       Xalloca(tmp, strlen(str) + 1, return NULL);
-       strcpy(tmp, str);
+       Xstrdup_a(tmp, str, return NULL);
 
        if (*tmp == '\"') {
                extract_quote(tmp, '\"');
index a7278e8..cbeda39 100644 (file)
@@ -1,9 +1,12 @@
-#ifndef QUOTE_FMT_H
+#ifndef __QUOTE_FMT_H__
 
-#define QUOTE_FMT_H
+#define __QUOTE_FMT_H__
 
-gchar * quote_fmt_get_buffer();
-void quote_fmt_init(MsgInfo * info, gchar * my_quote_str);
-int quote_fmtparse(void);
+#define quote_fmt_parse        quote_fmtparse
 
-#endif
+gchar *quote_fmt_get_buffer(void);
+void quote_fmt_init(MsgInfo *info, gchar *my_quote_str);
+gint quote_fmtparse(void);
+void quote_fmt_scan_string(const gchar *str);
+
+#endif /* __QUOTE_FMT_H__ */
index 4216b64..63b8b46 100644 (file)
@@ -9,9 +9,9 @@
 %%
 
 "%d" /* date */ return SHOW_DATE;
-"%f" /* From */ return SHOW_FROM;
-"%N" /* Full name */ return SHOW_FULLNAME;
-"%F" /* firt name */ return SHOW_FIRST_NAME;
+"%f" /* from */ return SHOW_FROM;
+"%N" /* full name */ return SHOW_FULLNAME;
+"%F" /* first name */ return SHOW_FIRST_NAME;
 "%I" /* initial of sender */ return SHOW_SENDER_INITIAL;
 "%s" /* subject */ return SHOW_SUBJECT;
 "%t" /* to */ return SHOW_TO;
@@ -25,8 +25,8 @@
 "%q" /* quoted message with no signature */ return SHOW_QUOTED_MESSAGE_NO_SIGNATURE;
 "%%" /* % */ return SHOW_PERCENT;
 "\\\\" /* \ */ return SHOW_BACKSLASH;
-"\\t" /* tab */ return SHOW_TAB;
-"\\n" /* retour à la ligne */ return SHOW_EOL;
+"\\t"|"\t" /* tab */ return SHOW_TAB;
+"\\n"|"\n" /* return */ return SHOW_EOL;
 "\\?" /* ? */ return SHOW_QUESTION_MARK;
 "\\(" return SHOW_OPARENT;
 "\\)" return SHOW_CPARENT;
index 23ad275..55a25ba 100644 (file)
@@ -2,9 +2,8 @@
 
 #include "defs.h"
 
-#include <ctype.h>
-#include <gtk/gtk.h>
 #include <glib.h>
+#include <ctype.h>
 
 #include "procmsg.h"
 #include "procmime.h"
@@ -20,20 +19,22 @@ flex quote_fmt.l
 bison -p quote_fmt quote_fmt.y
 */
 
-static MsgInfo * msginfo = NULL;
-static gboolean * visible = NULL;
+int yylex(void);
+
+static MsgInfo *msginfo = NULL;
+static gboolean *visible = NULL;
 static gint maxsize = 0;
 static gint stacksize = 0;
 
-static gchar * buffer = NULL;
+static gchar *buffer = NULL;
 static gint bufmax = 0;
 static gint bufsize = 0;
-static gchar * quote_str = NULL;
+static gchar *quote_str = NULL;
 static gint error = 0;
 
 static void add_visibility(gboolean val)
 {
-       stacksize ++;
+       stacksize++;
        if (maxsize < stacksize) {
                maxsize += 128;
                visible = g_realloc(visible, maxsize * sizeof(gboolean));
@@ -44,16 +45,16 @@ static void add_visibility(gboolean val)
        visible[stacksize - 1] = val;
 }
 
-static void remove_visibility()
+static void remove_visibility(void)
 {
-       stacksize --;
+       stacksize--;
 }
 
-
-static void add_buffer(gchar * s)
+static void add_buffer(gchar *s)
 {
-       gint len = strlen(s);
-       
+       gint len;
+
+       len = strlen(s);
        if (bufsize + len + 1 > bufmax) {
                if (bufmax == 0)
                        bufmax = 128;
@@ -65,14 +66,14 @@ static void add_buffer(gchar * s)
        bufsize += len;
 }
 
-static void flush_buffer()
+static void flush_buffer(void)
 {
        if (buffer != NULL)
-               *buffer = 0;
+               *buffer = '\0';
        bufsize = 0;
 }
 
-gchar * quote_fmt_get_buffer()
+gchar *quote_fmt_get_buffer(void)
 {
        if (error != 0)
                return NULL;
@@ -92,7 +93,7 @@ gchar * quote_fmt_get_buffer()
                add_buffer(tmp); \
        }
 
-void quote_fmt_init(MsgInfo * info, gchar * my_quote_str)
+void quote_fmt_init(MsgInfo *info, gchar *my_quote_str)
 {
        quote_str = my_quote_str;
        msginfo = info;
@@ -104,7 +105,7 @@ void quote_fmt_init(MsgInfo * info, gchar * my_quote_str)
        error = 0;
 }
 
-void quote_fmterror(char * str)
+void quote_fmterror(char *str)
 {
        g_warning(_("Error %s\n"), str);
        error = 1;
@@ -189,8 +190,8 @@ special:
        | SHOW_FIRST_NAME
        {
                if (msginfo->fromname) {
-                       gchar * p;
-                       gchar * str;
+                       gchar *p;
+                       gchar *str;
 
                        str = alloca(strlen(msginfo->fromname) + 1);
                        if (str != NULL) {
@@ -207,8 +208,8 @@ special:
 #define MAX_SENDER_INITIAL 20
                if (msginfo->fromname) {
                        gchar tmp[MAX_SENDER_INITIAL];
-                       gchar * p;      
-                       gchar * cur;
+                       gchar *p;
+                       gchar *cur;
                        gint len = 0;
 
                        p = msginfo->fromname;
@@ -216,12 +217,11 @@ special:
                        while (*p) {
                                if (*p && isalnum(*p)) {
                                        *cur = toupper(*p);
-                                               cur ++;
-                                       len ++;
+                                               cur++;
+                                       len++;
                                        if (len >= MAX_SENDER_INITIAL - 1)
                                                break;
-                               }
-                               else
+                               } else
                                        break;
                                while (*p && !isseparator(*p)) p++;
                                while (*p && isseparator(*p)) p++;
@@ -256,64 +256,88 @@ special:
        }
        | SHOW_REFERENCES
        {
-               if (msginfo->references)
-                       INSERT(msginfo->references);
+               /* if (msginfo->references)
+                       INSERT(msginfo->references); */
        }
        | SHOW_MESSAGE
        {
-               gchar buf[BUFFSIZE];
-               FILE * fp;
-
-               if ((fp = procmime_get_first_text_content(msginfo)) == NULL)
-                       g_warning(_("Can't get text part\n"));
-               while (fgets(buf, sizeof(buf), fp) != NULL) {
-                       INSERT(buf);
+               if (msginfo->folder) {
+                       gchar buf[BUFFSIZE];
+                       FILE *fp;
+
+                       if ((fp = procmime_get_first_text_content(msginfo))
+                           == NULL)
+                               g_warning(_("Can't get text part\n"));
+                       else {
+                               while (fgets(buf, sizeof(buf), fp) != NULL) {
+                                       strcrchomp(buf);
+                                       INSERT(buf);
+                               }
+                               fclose(fp);
+                       }
                }
-               fclose(fp);
        }
        | SHOW_QUOTED_MESSAGE
        {
-               gchar buf[BUFFSIZE];
-               FILE * fp;
-
-               if ((fp = procmime_get_first_text_content(msginfo)) == NULL)
-                       g_warning(_("Can't get text part\n"));
-               while (fgets(buf, sizeof(buf), fp) != NULL) {
-                       if (quote_str)
-                               INSERT(quote_str);
-                       INSERT(buf);
+               if (msginfo->folder) {
+                       gchar buf[BUFFSIZE];
+                       FILE *fp;
+
+                       if ((fp = procmime_get_first_text_content(msginfo))
+                           == NULL)
+                               g_warning(_("Can't get text part\n"));
+                       else {
+                               while (fgets(buf, sizeof(buf), fp) != NULL) {
+                                       strcrchomp(buf);
+                                       if (quote_str)
+                                               INSERT(quote_str);
+                                       INSERT(buf);
+                               }
+                               fclose(fp);
+                       }
                }
-               fclose(fp);
        }
        | SHOW_MESSAGE_NO_SIGNATURE
        {
-               gchar buf[BUFFSIZE];
-               FILE * fp;
-
-               if ((fp = procmime_get_first_text_content(msginfo)) == NULL)
-                       g_warning(_("Can't get text part\n"));
-               while (fgets(buf, sizeof(buf), fp) != NULL) {
-                       if (strncmp(buf, "-- ", 3) == 0)
-                               break;
-                       INSERT(buf);
+               if (msginfo->folder) {
+                       gchar buf[BUFFSIZE];
+                       FILE *fp;
+
+                       if ((fp = procmime_get_first_text_content(msginfo))
+                           == NULL)
+                               g_warning(_("Can't get text part\n"));
+                       else {
+                               while (fgets(buf, sizeof(buf), fp) != NULL) {
+                                       strcrchomp(buf);
+                                       if (strncmp(buf, "-- ", 3) == 0)
+                                               break;
+                                       INSERT(buf);
+                               }
+                               fclose(fp);
+                       }
                }
-               fclose(fp);
        }
        | SHOW_QUOTED_MESSAGE_NO_SIGNATURE
        {
-               gchar buf[BUFFSIZE];
-               FILE * fp;
-
-               if ((fp = procmime_get_first_text_content(msginfo)) == NULL)
-                       g_warning(_("Can't get text part\n"));
-               while (fgets(buf, sizeof(buf), fp) != NULL) {
-                       if (strncmp(buf, "-- ", 3) == 0)
-                               break;
-                       if (quote_str)
-                               INSERT(quote_str);
-                       INSERT(buf);
+               if (msginfo->folder) {
+                       gchar buf[BUFFSIZE];
+                       FILE *fp;
+
+                       if ((fp = procmime_get_first_text_content(msginfo))
+                           == NULL)
+                               g_warning(_("Can't get text part\n"));
+                       else {
+                               while (fgets(buf, sizeof(buf), fp) != NULL) {
+                                       strcrchomp(buf);
+                                       if (strncmp(buf, "-- ", 3) == 0)
+                                               break;
+                                       if (quote_str)
+                                               INSERT(quote_str);
+                                       INSERT(buf);
+                               }
+                               fclose(fp);
+                       }
                }
-               fclose(fp);
        }
        | SHOW_BACKSLASH
        {
@@ -407,7 +431,7 @@ query:
        }
        | QUERY_REFERENCES
        {
-               add_visibility(msginfo->references != NULL);
+               /* add_visibility(msginfo->references != NULL); */
        }
        OPARENT quote_fmt CPARENT
        {
index cc4dfb0..97df31b 100644 (file)
 #include "account.h"
 #include "compose.h"
 #include "progressdialog.h"
+#include "inputdialog.h"
 #include "manage_window.h"
 #include "procmsg.h"
 #include "procheader.h"
 #include "utils.h"
 #include "gtkutils.h"
-#include "inputdialog.h"
 
 #define SMTP_PORT      25
 #if USE_SSL
@@ -67,9 +67,9 @@ struct _SendProgressDialog
 
 static gint send_message_local (const gchar *command, FILE *fp);
 
-static gint send_message_smtp  (GSList *to_list, const gchar *from,
-                                const gchar *server, PrefsAccount *ac,
+static gint send_message_smtp  (PrefsAccount *ac_prefs, GSList *to_list,
                                 FILE *fp);
+
 #if USE_SSL
 static SockInfo *send_smtp_open        (const gchar *server, gushort port,
                                 const gchar *domain, gboolean use_smtp_auth,
@@ -86,6 +86,9 @@ static SendProgressDialog *send_progress_dialog_create(void);
 static void send_progress_dialog_destroy(SendProgressDialog *dialog);
 static void send_cancel(GtkWidget *widget, gpointer data);
 
+static gchar *send_query_password(const gchar *server, const gchar *user);
+
+
 gint send_message(const gchar *file, PrefsAccount *ac_prefs, GSList *to_list)
 {
        FILE *fp;
@@ -106,7 +109,7 @@ gint send_message(const gchar *file, PrefsAccount *ac_prefs, GSList *to_list)
                return val;
        }
 
-       val = send_message_smtp(to_list, NULL, NULL, ac_prefs, fp);
+       val = send_message_smtp(ac_prefs, to_list, fp);
 
        fclose(fp);
        return val;
@@ -179,12 +182,18 @@ gint send_message_queue(const gchar *file)
                        }
                }
 
-               if (ac) {
-                       val = send_message_smtp(to_list, from, NULL, ac, fp);
-               } else {
+               if (ac)
+                       val = send_message_smtp(ac, to_list, fp);
+               else {
+                       PrefsAccount tmp_ac;
+
                        g_warning(_("Account not found.\n"));
-                       val = send_message_smtp(to_list, from, server, NULL,
-                                               fp);
+
+                       memset(&tmp_ac, 0, sizeof(PrefsAccount));
+                       tmp_ac.address = from;
+                       tmp_ac.smtp_server = server;
+                       tmp_ac.smtpport = SMTP_PORT;
+                       val = send_message_smtp(&tmp_ac, to_list, fp);
                }
        }
 
@@ -230,7 +239,6 @@ static gint send_message_local(const gchar *command, FILE *fp)
        if (dialog->cancelled) { \
                sock_close(smtp_sock); \
                send_progress_dialog_destroy(dialog); \
-               g_free(passwd); \
                return -1; \
        } \
 }
@@ -242,7 +250,6 @@ static gint send_message_local(const gchar *command, FILE *fp)
                log_warning("Error occurred while %s\n", s); \
                sock_close(smtp_sock); \
                send_progress_dialog_destroy(dialog); \
-               g_free(passwd); \
                return -1; \
        } \
 }
@@ -250,113 +257,79 @@ static gint send_message_local(const gchar *command, FILE *fp)
 #define SEND_EXIT_IF_NOTOK(f, s) \
 { \
        gint ok; \
+ \
        EXIT_IF_CANCELLED(); \
        if ((ok = (f)) != SM_OK) { \
                log_warning("Error occurred while %s\n", s); \
                if (ok == SM_AUTHFAIL) { \
-                       if (ac && ac->tmp_smtp_passwd) { \
-                               g_free(ac->tmp_smtp_passwd); \
-                               ac->tmp_smtp_passwd = NULL; \
+                       log_warning("SMTP AUTH failed\n"); \
+                       if (ac_prefs->tmp_pass) { \
+                               g_free(ac_prefs->tmp_pass); \
+                               ac_prefs->tmp_pass = NULL; \
                        } \
                } \
                if (smtp_quit(smtp_sock) != SM_OK) \
                        log_warning("Error occurred while sending QUIT\n"); \
                sock_close(smtp_sock); \
                send_progress_dialog_destroy(dialog); \
-               g_free(passwd); \
                return -1; \
        } \
 }
 
-static gint send_message_smtp(GSList *to_list, const gchar *from,
-                             const gchar *server, PrefsAccount *ac,
+static gint send_message_smtp(PrefsAccount *ac_prefs, GSList *to_list,
                              FILE *fp)
 {
-       gushort port;
-       const gchar *domain;
-       const gchar *userid;
-       gchar *passwd = NULL;
-       gboolean use_smtp_auth;
-#if USE_SSL
-       SSLSMTPType ssl_type;
-#endif
        SockInfo *smtp_sock = NULL;
        SendProgressDialog *dialog;
        GtkCList *clist;
        const gchar *text[3];
        gchar buf[BUFFSIZE];
+       gushort port;
+       gchar *domain;
+       gchar *pass = NULL;
        GSList *cur;
        gint size;
 
+       g_return_val_if_fail(ac_prefs != NULL, -1);
+       g_return_val_if_fail(ac_prefs->address != NULL, -1);
+       g_return_val_if_fail(ac_prefs->smtp_server != NULL, -1);
        g_return_val_if_fail(to_list != NULL, -1);
        g_return_val_if_fail(fp != NULL, -1);
 
-       if (ac == NULL) {
-               g_return_val_if_fail(from != NULL, -1);
-               g_return_val_if_fail(server != NULL, -1);
-               port = SMTP_PORT;
-               domain = userid = passwd = NULL;
-               use_smtp_auth = FALSE;
-#if USE_SSL
-               ssl_type = FALSE;
-#endif
-       } else {
-               if (from == NULL)
-                       from = ac->address;
-               if (server == NULL)
-                       server = ac->smtp_server;
-               g_return_val_if_fail(from != NULL, -1);
-               g_return_val_if_fail(server != NULL, -1);
+       size = get_left_file_size(fp);
+       if (size < 0) return -1;
 
 #if USE_SSL
-               port = ac->set_smtpport ? ac->smtpport :
-                       ac->ssl_smtp == SSL_SMTP_TUNNEL ?
-                       SSMTP_PORT : SMTP_PORT;
-               ssl_type = ac->ssl_smtp;
+       port = ac_prefs->set_smtpport ? ac_prefs->smtpport :
+               ac_prefs->ssl_smtp == SSL_SMTP_TUNNEL ? SSMTP_PORT : SMTP_PORT;
 #else
-               port = ac->set_smtpport ? ac->smtpport : SMTP_PORT;
+       port = ac_prefs->set_smtpport ? ac_prefs->smtpport : SMTP_PORT;
 #endif
-               domain = ac->set_domain ? ac->domain : NULL;
-               userid = ac->smtp_userid;
-               use_smtp_auth = ac->use_smtp_auth;
-               if (ac->smtp_passwd)
-                       passwd = g_strdup(ac->smtp_passwd);
-               else if (ac->tmp_smtp_passwd)
-                       passwd = g_strdup(ac->tmp_smtp_passwd);
-               else if (use_smtp_auth && userid) {
-                       gchar *pass;
-                       gchar *message;
-
-                       message = g_strdup_printf
-                               (_("Input password for %s on %s:"),
-                                userid, server);
-
-                       pass = input_dialog_with_invisible(_("Input password"),
-                                                          message, NULL);
-                       g_free(message);
-                       if (pass) {
-                               ac->tmp_smtp_passwd = g_strdup(pass);
-                               passwd = pass;
-                       }
+       domain = ac_prefs->set_domain ? ac_prefs->domain : NULL;
+
+       if (ac_prefs->use_smtp_auth) {
+               if (ac_prefs->passwd)
+                       pass = ac_prefs->passwd;
+               else if (ac_prefs->tmp_pass)
+                       pass = ac_prefs->tmp_pass;
+               else {
+                       pass = send_query_password(ac_prefs->smtp_server,
+                                                  ac_prefs->userid);
+                       if (!pass) pass = g_strdup("");
+                       ac_prefs->tmp_pass = pass;
                }
        }
 
-       if (use_smtp_auth && (!userid || !passwd))
-               use_smtp_auth = FALSE;
-
-       size = get_left_file_size(fp);
-       if (size < 0) return -1;
-
        dialog = send_progress_dialog_create();
 
        text[0] = NULL;
-       text[1] = server;
+       text[1] = ac_prefs->smtp_server;
        text[2] = _("Standby");
        clist = GTK_CLIST(dialog->dialog->clist);
        gtk_clist_append(clist, (gchar **)text);
 
        g_snprintf(buf, sizeof(buf), _("Connecting to SMTP server: %s ..."),
-                  server);
+                  ac_prefs->smtp_server);
        log_message("%s\n", buf);
        progress_dialog_set_label(dialog->dialog, buf);
        gtk_clist_set_text(clist, 0, 2, _("Connecting"));
@@ -364,11 +337,13 @@ static gint send_message_smtp(GSList *to_list, const gchar *from,
 
 #if USE_SSL
        SEND_EXIT_IF_ERROR((smtp_sock = send_smtp_open
-                               (server, port, domain, use_smtp_auth, ssl_type)),
+                               (ac_prefs->smtp_server, port, domain,
+                                ac_prefs->use_smtp_auth, ac_prefs->ssl_smtp)),
                           "connecting to server");
 #else
        SEND_EXIT_IF_ERROR((smtp_sock = send_smtp_open
-                               (server, port, domain, use_smtp_auth)),
+                               (ac_prefs->smtp_server, port, domain,
+                                ac_prefs->use_smtp_auth)),
                           "connecting to server");
 #endif
 
@@ -377,7 +352,8 @@ static gint send_message_smtp(GSList *to_list, const gchar *from,
        GTK_EVENTS_FLUSH();
 
        SEND_EXIT_IF_NOTOK
-               (smtp_from(smtp_sock, from, userid, passwd, use_smtp_auth),
+               (smtp_from(smtp_sock, ac_prefs->address, ac_prefs->userid,
+                          pass, ac_prefs->use_smtp_auth),
                 "sending MAIL FROM");
 
        progress_dialog_set_label(dialog->dialog, _("Sending RCPT TO..."));
@@ -404,7 +380,6 @@ static gint send_message_smtp(GSList *to_list, const gchar *from,
 
        sock_close(smtp_sock);
        send_progress_dialog_destroy(dialog);
-       g_free(passwd);
 
        return 0;
 }
@@ -624,3 +599,16 @@ static void send_cancel(GtkWidget *widget, gpointer data)
 
        dialog->cancelled = TRUE;
 }
+
+static gchar *send_query_password(const gchar *server, const gchar *user)
+{
+       gchar *message;
+       gchar *pass;
+
+       message = g_strdup_printf(_("Input password for %s on %s:"),
+                                 user, server);
+       pass = input_dialog_with_invisible(_("Input password"), message, NULL);
+       g_free(message);
+
+       return pass;
+}
index 7794f50..d6ff599 100644 (file)
@@ -186,6 +186,7 @@ static void summary_update_status   (SummaryView            *summaryview);
 
 /* display functions */
 static void summary_status_show                (SummaryView            *summaryview);
+static void summary_set_column_titles  (SummaryView            *summaryview);
 static void summary_set_ctree_from_list        (SummaryView            *summaryview,
                                         GSList                 *mlist);
 static void summary_set_header         (SummaryView            *summaryview,
@@ -537,11 +538,6 @@ void summary_init(SummaryView *summaryview)
        PIXMAP_CREATE(summaryview->hbox, folderxpm, folderxpmmask,
                      dir_open_xpm);
 
-       pixmap = gtk_pixmap_new(clipxpm, clipxpmmask);
-       gtk_clist_set_column_widget(GTK_CLIST(summaryview->ctree),
-                                   summaryview->col_pos[S_COL_MIME], pixmap);
-       gtk_widget_show(pixmap);
-
        if (!small_style) {
                small_style = gtk_style_copy
                        (gtk_widget_get_style(summaryview->ctree));
@@ -582,6 +578,7 @@ void summary_init(SummaryView *summaryview)
        gtk_widget_show(pixmap);
 
        summary_clear_list(summaryview);
+       summary_set_column_titles(summaryview);
        summary_colorlabel_menu_create(summaryview);
        summary_set_menu_sensitive(summaryview);
 
@@ -712,6 +709,7 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item,
        gtk_clist_freeze(GTK_CLIST(ctree));
 
        summary_clear_list(summaryview);
+       summary_set_column_titles(summaryview);
        summary_set_menu_sensitive(summaryview);
        if (!is_refresh)
                messageview_clear(summaryview->messageview);
@@ -848,9 +846,7 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item,
        }
 
        summary_status_show(summaryview);
-
        summary_set_menu_sensitive(summaryview);
-
        main_window_set_toolbar_sensitive(summaryview->mainwin);
 
        debug_print("\n");
@@ -1703,6 +1699,89 @@ static void summary_status_show(SummaryView *summaryview)
                                  summaryview->messages);
 }
 
+static void summary_set_column_titles(SummaryView *summaryview)
+{
+       GtkCList *clist = GTK_CLIST(summaryview->ctree);
+       GtkWidget *hbox;
+       GtkWidget *label;
+       GtkWidget *arrow;
+       gint pos;
+       const gchar *title;
+       SummaryColumnType type;
+       gboolean single_char;
+       GtkJustification justify;
+
+       static SummarySortType sort_by[N_SUMMARY_COLS] = {
+               SORT_BY_MARK,
+               SORT_BY_UNREAD,
+               SORT_BY_MIME,
+               SORT_BY_SUBJECT,
+               SORT_BY_FROM,
+               SORT_BY_DATE,
+               SORT_BY_SIZE,
+               SORT_BY_NUMBER
+       };
+
+       for (pos = 0; pos < N_SUMMARY_COLS; pos++) {
+               type = summaryview->col_state[pos].type;
+
+               single_char = (type == S_COL_MIME ||
+                              type == S_COL_MARK || type == S_COL_UNREAD);
+               justify = (type == S_COL_NUMBER || type == S_COL_SIZE)
+                       ? GTK_JUSTIFY_RIGHT : GTK_JUSTIFY_LEFT;
+
+               switch (type) {
+               case S_COL_SUBJECT:
+               case S_COL_FROM:
+               case S_COL_DATE:
+               case S_COL_NUMBER:
+                       if (prefs_common.trans_hdr)
+                               title = gettext(col_label[type]);
+                       else
+                               title = col_label[type];
+                       break;
+               default:
+                       title = gettext(col_label[type]);
+               }
+
+               if (type == S_COL_MIME) {
+                       label = gtk_pixmap_new(clipxpm, clipxpmmask);
+                       gtk_widget_show(label);
+                       gtk_clist_set_column_widget(clist, pos, label);
+                       continue;
+               }
+               if (single_char) {
+                       gtk_clist_set_column_title(clist, pos, title);
+                       continue;
+               }
+
+               hbox = gtk_hbox_new(FALSE, 4);
+               label = gtk_label_new(title);
+               if (justify == GTK_JUSTIFY_RIGHT)
+                       gtk_box_pack_end(GTK_BOX(hbox), label,
+                                        FALSE, FALSE, 0);
+               else
+                       gtk_box_pack_start(GTK_BOX(hbox), label,
+                                          FALSE, FALSE, 0);
+
+               if (summaryview->sort_mode == sort_by[type]) {
+                       arrow = gtk_arrow_new
+                               (summaryview->sort_type == GTK_SORT_ASCENDING
+                                ? GTK_ARROW_DOWN : GTK_ARROW_UP,
+                                GTK_SHADOW_IN);
+                       if (justify == GTK_JUSTIFY_RIGHT)
+                               gtk_box_pack_start(GTK_BOX(hbox), arrow,
+                                                  FALSE, FALSE, 0);
+                       else
+                               gtk_box_pack_end(GTK_BOX(hbox), arrow,
+                                                FALSE, FALSE, 0);
+               }
+
+               gtk_widget_show_all(hbox);
+               gtk_clist_set_column_widget(clist, pos, hbox);
+       }
+}
+
 void summary_sort(SummaryView *summaryview, SummarySortType type)
 {
        GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
@@ -1764,11 +1843,11 @@ void summary_sort(SummaryView *summaryview, SummarySortType type)
        gtk_clist_set_sort_type(clist, summaryview->sort_type);
        summaryview->sort_mode = type;
 
+       summary_set_column_titles(summaryview);
+
        gtk_ctree_sort_node(ctree, NULL);
 
        gtk_ctree_node_moveto(ctree, summaryview->selected, -1, 0.5, 0);
-       /*gtkut_ctree_set_focus_row(ctree, summaryview->selected);*/
-
        prefs_folder_item_set_config(summaryview->folder_item,
                                     summaryview->sort_type,
                                     summaryview->sort_mode);
@@ -3679,35 +3758,22 @@ static GtkWidget *summary_ctree_create(SummaryView *summaryview)
        GtkWidget *ctree;
        gint *col_pos = summaryview->col_pos;
        SummaryColumnState *col_state;
-       const gchar *titles[N_SUMMARY_COLS];
+       gchar *titles[N_SUMMARY_COLS];
        SummaryColumnType type;
        gint pos;
 
+       memset(titles, 0, sizeof(titles));
+
        col_state = prefs_summary_column_get_config();
        for (pos = 0; pos < N_SUMMARY_COLS; pos++) {
                summaryview->col_state[pos] = col_state[pos];
                type = col_state[pos].type;
                col_pos[type] = pos;
-
-               switch (type) {
-               case S_COL_NUMBER:
-               case S_COL_DATE:
-               case S_COL_FROM:
-               case S_COL_SUBJECT:
-               case S_COL_SCORE:
-                       if (prefs_common.trans_hdr)
-                               titles[pos] = gettext(col_label[type]);
-                       else
-                               titles[pos] = col_label[type];
-                       break;
-               default:
-                       titles[pos] = gettext(col_label[type]);
-               }
        }
        col_state = summaryview->col_state;
 
        ctree = gtk_sctree_new_with_titles
-               (N_SUMMARY_COLS, col_pos[S_COL_SUBJECT], (gchar **)titles);
+               (N_SUMMARY_COLS, col_pos[S_COL_SUBJECT], titles);
 
        gtk_clist_set_selection_mode(GTK_CLIST(ctree), GTK_SELECTION_EXTENDED);
        gtk_clist_set_column_justification(GTK_CLIST(ctree), col_pos[S_COL_MARK],
@@ -3981,7 +4047,6 @@ static void summary_key_pressed(GtkWidget *widget, GdkEventKey *event,
                summary_step(summaryview, GTK_SCROLL_STEP_FORWARD);
                break;
        case GDK_BackSpace:     /* Page up */
-       case GDK_Delete:
                textview_scroll_page(summaryview->messageview->textview, TRUE);
                break;
        case GDK_p:             /* Prev */
@@ -4015,6 +4080,7 @@ static void summary_key_pressed(GtkWidget *widget, GdkEventKey *event,
                summary_mark_as_unread(summaryview);
                break;
        case GDK_d:             /* Delete */
+       case GDK_Delete:
                RETURN_IF_LOCKED();
                BREAK_ON_MODIFIER_KEY();
                summary_delete(summaryview);
index df50e87..1bc5ace 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Sylpheed templates subsystem 
  * Copyright (C) 2001 Alexander Barinov
+ * Copyright (C) 2001 Hiroyuki Yamamoto
  *
  * 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
 
 #include "defs.h"
 
-#include <gdk/gdk.h>
+#include <glib.h>
 #include <stdio.h>
 #include <dirent.h>
 #include <sys/stat.h>
+#include <ctype.h>
 
-#include "utils.h"
+#include "intl.h"
 #include "main.h"
 #include "template.h"
-#include "intl.h"
+#include "utils.h"
+
+static GSList *template_list;
 
-static GSList* template_load(GSList *tmpl_list, gchar *filename)
+static Template *template_load(gchar *filename)
 {
        Template *tmpl;
        FILE *fp;
-       char buf[32000];
+       gchar buf[BUFFSIZE];
        gint bytes_read;
 
        debug_print(_("%s:%d loading template from %s\n"), __FILE__, __LINE__, filename);
 
        if ((fp = fopen(filename, "r")) == NULL) {
                FILE_OP_ERROR(filename, "fopen");
-               return tmpl_list;
+               return NULL;
        }
 
        tmpl = g_new(Template, 1);
-       
-       if (fgets(buf, sizeof(buf), fp) == NULL) {
-               FILE_OP_ERROR(filename, "fgets");
-               g_free(tmpl);
-               debug_print(_("%s:%d exiting\n"), __FILE__, __LINE__);
-               return tmpl_list;
+       tmpl->name = NULL;
+
+       while (fgets(buf, sizeof(buf), fp) != NULL) {
+               if (buf[0] == '\n')
+                       break;
+               else if (!g_strncasecmp(buf, "Name:", 5))
+                       tmpl->name = g_strdup(g_strstrip(buf + 5));
        }
-       tmpl->name = g_strdup(g_strstrip(buf));
 
-       memset(buf, 0, sizeof(buf));
-       if ((bytes_read = fread(buf, 1, sizeof(buf)-1, fp)) == 0) {
-               FILE_OP_ERROR(filename, "fread");
-               g_free(tmpl->name);
+       if (!tmpl->name) {
+               g_warning("wrong template format\n");
                g_free(tmpl);
-               return tmpl_list;
+               return NULL;
        }
-       tmpl->value = g_strdup(buf);
 
-       tmpl_list = g_slist_append(tmpl_list, tmpl);
+       if ((bytes_read = fread(buf, 1, sizeof(buf), fp)) == 0) {
+               if (ferror(fp)) {
+                       FILE_OP_ERROR(filename, "fread");
+                       g_free(tmpl->name);
+                       g_free(tmpl);
+                       return NULL;
+               }
+       }
        fclose(fp);
-       return tmpl_list;
+       tmpl->value = g_strndup(buf, bytes_read);
+
+       return tmpl;
 }
 
 void template_free(Template *tmpl)
@@ -76,33 +86,44 @@ void template_free(Template *tmpl)
 
 void template_clear_config(GSList *tmpl_list)
 {
+       GSList *cur;
        Template *tmpl;
 
-       while (tmpl_list != NULL) {
-               tmpl = tmpl_list->data;
+       for (cur = tmpl_list; cur != NULL; cur = cur->next) {
+               tmpl = (Template *)cur->data;
                template_free(tmpl);
-               tmpl_list = g_slist_remove(tmpl_list, tmpl);
        }
+       g_slist_free(tmpl_list);
 }
 
-GSListtemplate_read_config(void)
+GSList *template_read_config(void)
 {
        gchar *path;
        gchar *filename;
        DIR *dp;
        struct dirent *de;
        struct stat s;
+       Template *tmpl;
        GSList *tmpl_list = NULL;
 
-       path = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, TEMPLATES_DIR, NULL);
+       path = get_template_dir();
        debug_print(_("%s:%d reading templates dir %s\n"), __FILE__, __LINE__, path);
 
+       if (!is_dir_exist(path)) {
+               if (mkdir(path, S_IRWXU) < 0) {
+                       FILE_OP_ERROR(path, "mkdir");
+                       return NULL;
+               }
+       }
+
        if ((dp = opendir(path)) == NULL) {
                FILE_OP_ERROR(path, "opendir");
-               return tmpl_list;
+               return NULL;
        }
 
        while ((de = readdir(dp)) != NULL) {
+               if (*de->d_name == '.') continue;
+
                filename = g_strconcat(path, G_DIR_SEPARATOR_S, de->d_name, NULL);
                debug_print(_("%s:%d found file %s\n"), __FILE__, __LINE__, filename);
 
@@ -112,46 +133,48 @@ GSList* template_read_config(void)
                        continue;
                }
 
-               tmpl_list = template_load(tmpl_list, filename);
+               tmpl = template_load(filename);
+               if (tmpl)
+                       tmpl_list = g_slist_append(tmpl_list, tmpl);
                g_free(filename);
        }
 
        closedir(dp);
-       g_free(path);
+
        return tmpl_list;
 }
 
 void template_write_config(GSList *tmpl_list)
 {
        gchar *path;
-       gchar *filename;
        GSList *cur;
        Template *tmpl;
        FILE *fp;
-       gint tmpl_num = 1;
+       gint tmpl_num;
 
-       path = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, TEMPLATES_DIR, NULL);
+       path = get_template_dir();
 
        if (!is_dir_exist(path)) {
                if (is_file_exist(path)) {
-                       debug_print(_("%s:%d file %s allready exists\n"), 
-                                   __FILE__, __LINE__, filename);
-                       g_free(path);
+                       g_warning(_("file %s allready exists\n"), path);
                        return;
                }
                if (mkdir(path, S_IRWXU) < 0) {
                        FILE_OP_ERROR(path, "mkdir");
-                       g_free(path);
                        return;
                }
        }
 
        remove_all_files(path);
 
-       for (cur = tmpl_list; cur != NULL; cur = cur->next) {
+       for (cur = tmpl_list, tmpl_num = 1; cur != NULL;
+            cur = cur->next, tmpl_num++) {
+               gchar *filename;
+
                tmpl = cur->data;
 
-               filename = g_strconcat(path, G_DIR_SEPARATOR_S, itos(tmpl_num), NULL);
+               filename = g_strconcat(path, G_DIR_SEPARATOR_S,
+                                      itos(tmpl_num), NULL);
 
                if ((fp = fopen(filename, "w")) == NULL) {
                        FILE_OP_ERROR(filename, "fopen");
@@ -160,15 +183,27 @@ void template_write_config(GSList *tmpl_list)
                        return;
                }
 
-               debug_print(_("%s:%d writing template \"%s\" to %s\n"), 
+               debug_print(_("%s:%d writing template \"%s\" to %s\n"),
                            __FILE__, __LINE__, tmpl->name, filename);
-               fputs(tmpl->name, fp);
+               fprintf(fp, "Name: %s\n", tmpl->name);
                fputs("\n", fp);
-               fwrite(tmpl->value, sizeof(gchar), strlen(tmpl->value), fp);
+               fwrite(tmpl->value, sizeof(gchar) * strlen(tmpl->value), 1,
+                      fp);
                fclose(fp);
-
-               tmpl_num ++;
        }
+}
+
+GSList *template_get_config(void)
+{
+       if (!template_list)
+               template_list = template_read_config();
+
+       return template_list;
+}
 
-       g_free(path);
+void template_set_config(GSList *tmpl_list)
+{
+       template_clear_config(template_list);
+       template_write_config(tmpl_list);
+       template_list = tmpl_list;
 }
index c57dafa..2d23979 100644 (file)
 #ifndef __TEMPLATE_H__
 #define __TEMPLATE_H__
 
+#include <glib.h>
+
+typedef struct _Template       Template;
+
 struct _Template {
        gchar *name;
        gchar *value;
 };
 
-typedef struct _Template Template;
+void template_free             (Template       *tmpl);
+void template_clear_config     (GSList         *tmpl_list);
+
+GSList *template_read_config   (void);
+void template_write_config     (GSList         *tmpl_list);
 
-void template_free (Template *tmpl);
-void template_clear_config (GSList *tmpl_list);
-GSList* template_read_config (void);
-void template_write_config (GSList *tmpl_list);
+GSList *template_get_config    (void);
+void template_set_config       (GSList         *tmpl_list);
 
 #endif /* __TEMPLATE_H__ */
index 1e0c516..f62de07 100644 (file)
@@ -806,7 +806,6 @@ static void textview_write_line(TextView *textview, const gchar *str,
 {
        GtkText *text = GTK_TEXT(textview->text);
        gchar buf[BUFFSIZE];
-       size_t len;
        GdkColor *fg_color;
        gint quotelevel = -1;
 
@@ -821,11 +820,7 @@ static void textview_write_line(TextView *textview, const gchar *str,
                return;
        }
 
-       len = strlen(buf);
-       if (len > 1 && buf[len - 1] == '\n' && buf[len - 2] == '\r') {
-               buf[len - 2] = '\n';
-               buf[len - 1] = '\0';
-       }
+       strcrchomp(buf);
        if (prefs_common.conv_mb_alnum) conv_mb_alnum(buf);
        fg_color = NULL;
 
@@ -1397,7 +1392,6 @@ static void textview_key_pressed(GtkWidget *widget, GdkEventKey *event,
                        textview_scroll_page(textview, FALSE);
                break;
        case GDK_BackSpace:
-       case GDK_Delete:
                textview_scroll_page(textview, TRUE);
                break;
        case GDK_Return:
index bbfcf0d..1d6bc32 100644 (file)
@@ -211,6 +211,21 @@ gchar *strtailchomp(gchar *str, gchar tail_char)
        return str;
 }
 
+/* remove CR (carriage return) */
+gchar *strcrchomp(gchar *str)
+{
+       register gchar *s;
+
+       if (!*str) return str;
+
+       s = str + strlen(str) - 1;
+       if (*s == '\n' && s > str && *(s - 1) == '\r') {
+               *(s - 1) = '\n';
+               *s = '\0';
+       }
+
+       return str;
+}
 
 /* Similar to `strstr' but this function ignores the case of both strings.  */
 gchar *strcasestr(const gchar *haystack, const gchar *needle)
@@ -494,10 +509,8 @@ gint subject_compare(const gchar *s1, const gchar *s2)
        if (!s1 || !s2) return -1;
        if (!*s1 || !*s2) return -1;
 
-       Xalloca(str1, strlen(s1) + 1, return -1);
-       Xalloca(str2, strlen(s2) + 1, return -1);
-       strcpy(str1, s1);
-       strcpy(str2, s2);
+       Xstrdup_a(str1, s1, return -1);
+       Xstrdup_a(str2, s2, return -1);
 
        trim_subject(str1);
        trim_subject(str2);
@@ -845,6 +858,31 @@ GSList *newsgroup_list_append(GSList *group_list, const gchar *str)
        return group_list;
 }
 
+GList *add_history(GList *list, const gchar *str)
+{
+       GList *old;
+
+       g_return_val_if_fail(str != NULL, list);
+
+       old = g_list_find_custom(list, (gpointer)str, (GCompareFunc)strcmp2);
+       if (old) {
+               g_free(old->data);
+               list = g_list_remove(list, old->data);
+       } else if (g_list_length(list) >= MAX_HISTORY_SIZE) {
+               GList *last;
+
+               last = g_list_last(list);
+               if (last) {
+                       g_free(last->data);
+                       g_list_remove(list, last->data);
+               }
+       }
+
+       list = g_list_prepend(list, g_strdup(str));
+
+       return list;
+}
+
 void remove_return(gchar *str)
 {
        register gchar *p = str;
@@ -1178,6 +1216,17 @@ gchar *get_mime_tmp_dir(void)
        return mime_tmp_dir;
 }
 
+gchar *get_template_dir(void)
+{
+       static gchar *template_dir = NULL;
+
+       if (!template_dir)
+               template_dir = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
+                                          TEMPLATE_DIR, NULL);
+
+       return template_dir;
+}
+
 gchar *get_tmp_file(void)
 {
        static gchar *tmp_file = NULL;
index 57d9de0..8cc6174 100644 (file)
@@ -150,6 +150,7 @@ gint path_cmp               (const gchar    *s1,
 gchar *strretchomp     (gchar          *str);
 gchar *strtailchomp    (gchar          *str,
                         gchar           tail_char);
+gchar *strcrchomp      (gchar          *str);
 gchar *strcasestr      (const gchar    *haystack,
                         const gchar    *needle);
 gchar *strncpy2                (gchar          *dest,
@@ -227,12 +228,17 @@ gchar *strrchr_with_skip_quote            (const gchar    *str,
                                         gint            quote_chr,
                                         gint            c);
 void extract_address                   (gchar          *str);
+
 GSList *address_list_append            (GSList         *addr_list,
                                         const gchar    *str);
 GSList *references_list_append         (GSList         *msgid_list,
                                         const gchar    *str);
 GSList *newsgroup_list_append          (GSList         *group_list,
                                         const gchar    *str);
+
+GList *add_history                     (GList          *list,
+                                        const gchar    *str);
+
 void remove_return                     (gchar          *str);
 void remove_space                      (gchar          *str);
 void unfold_line                       (gchar          *str);
@@ -256,6 +262,7 @@ gchar *get_news_cache_dir   (void);
 gchar *get_imap_cache_dir      (void);
 gchar *get_mbox_cache_dir      (void);
 gchar *get_mime_tmp_dir                (void);
+gchar *get_template_dir                (void);
 gchar *get_tmp_file            (void);
 gchar *get_domain_name         (void);