#
# Machekku Smart Reply and Forward
#
# Version: 0.5
# Date: 2005-05-17
#
# http://machekku.uaznia.net/jabber/psi/patches/
#
# psics.pri                                   |   12
# src/common.cpp                              |   63 +
# src/common.h                                |   31
# src/eventdlg.cpp                            |  170 ++++-
# src/eventdlg.h                              |   23
# src/options/opt_messages-ui.ui              |  895 ++++++++++++++++++++++++++++
# src/options/opt_messages-ui.ui.h            |   18
# src/options/opt_messages.cpp                |  540 ++++++++++++++++
# src/options/opt_messages.h                  |   68 ++
# src/options/options.pri                     |    3
# src/options/optionsdlg.cpp                  |    2
# src/psi_profiles.cpp                        |  152 ++++
# src/psiaccount.cpp                          |  222 ++++++
# src/psiaccount.h                            |   10
# src/psicon.cpp                              |    4
# src/tools/multilineinput/multilineinput.cpp |  162 +++++
# src/tools/multilineinput/multilineinput.h   |   36 +
# src/tools/multilineinput/multilineinput.pri |    4
# src/tools/templates/templates.cpp           |  277 ++++++++
# src/tools/templates/templates.h             |   86 ++
# src/tools/templates/templates.pri           |    4
# 21 files changed, 2735 insertions(+), 47 deletions(-)
#
diff -X exclude -Naru psi_cvs-2005.05.17/psi/psics.pri psi/psi/psics.pri
--- psi_cvs-2005.05.17/psi/psics.pri	Tue Apr 12 17:51:40 2005
+++ psi/psi/psics.pri	Tue May 17 20:51:18 2005
@@ -85,6 +85,18 @@
 	ADVWIDGET_CPP = $$PSICS_CPP/advwidget
 	INCLUDEPATH += $$ADVWIDGET_CPP
 	include($$ADVWIDGET_CPP/advwidget.pri)
+	
+	# multiline text input
+	CONFIG += multilineinput
+	MULTILINEINPUT_CPP = $$PSICS_CPP/multilineinput
+	INCLUDEPATH += $$MULTILINEINPUT_CPP
+	include($$MULTILINEINPUT_CPP/multilineinput.pri)
+
+	# templates utils
+	CONFIG += templates
+	TEMPLATES_CPP = $$PSICS_CPP/templates
+	INCLUDEPATH += $$TEMPLATES_CPP
+	include($$TEMPLATES_CPP/templates.pri)
 
 	use_crash {
 		# crash
diff -X exclude -Naru psi_cvs-2005.05.17/psi/src/common.cpp psi/psi/src/common.cpp
--- psi_cvs-2005.05.17/psi/src/common.cpp	Sun May 15 22:26:44 2005
+++ psi/psi/src/common.cpp	Tue May 17 20:54:18 2005
@@ -146,11 +146,68 @@
 	return txt;
 }
 
-QString qstrquote(const QString &toquote, int width, bool quoteEmpty)
+/*!
+	Quotes \a toquote string,
+	by dividing it into lines with max witdh \a width,
+	each line starting with '>' quote character.
+	
+	If \a quoteEmpty is false, empty lines are not prepended with '>'.
+
+	If \a stripEmptyLines is true, empty lines from beginning and end
+	of the quoted text are removed.
+
+	If \a removeSignature is true, all text after signature delimiter ("-- \n")
+	is removed from output, including the delimiter.
+*/
+
+QString qstrquote(const QString &toquote, int width, bool quoteEmpty, bool stripEmptyLines /* = FALSE */, bool removeSignature /* = FALSE */)
 {
-	int ql = 0, col = 0, atstart = 1, ls=0;
+	const QString quotedEmpty = ">\n\n\n";
+
+	int ql = 0, col = 0, atstart = 1, ls=0;	
+
+	QString quoted = toquote;
+	
+	if ( removeSignature ) {
+		int sig = -1;
+		if ( (sig = quoted.find("\n-- \n")) != -1 )
+			quoted.truncate(sig+1);	// +1 -> don't trunc '\n'
+		else if (toquote.startsWith("-- \n"))	// message was just a signature
+			return quotedEmpty;	// two empty lines at the end...
+	}
+
+	if ( stripEmptyLines ) {
+		int len = quoted.length();
+
+		// check for empty lines at the beginning
+		int last = 0;
+		while ( last < len && quoted[last] == '\n' )
+			++last;
+
+		if ( last == len ) {
+			// message contained only empty lines
+			return quotedEmpty;
+		}
+
+		// now, quoted[last] is the first not '\n' character
+		if ( last > 0 ) {
+			quoted.remove(0, last);	// last = length of removed part
+			len -= last;
+		}
+
+		// check for empty lines at the end
+		int first = len - 1;
+		while ( first > 0 && quoted[first] == '\n')
+			--first;
+
+		// now, quoted[first] is the last not-'\n' character
+		if ( first < len - 1) {
+			quoted.truncate(first + 1);		
+		}
+	}
+
+	quoted = "> " + quoted;	// quote first line
 
-	QString quoted = "> "+toquote;  // quote first line
 	QString rxs  = quoteEmpty ? "\n" : "\n(?!\\s*\n)";
 	QRegExp rx(rxs);                // quote following lines
 	quoted.replace(rx, "\n> ");
diff -X exclude -Naru psi_cvs-2005.05.17/psi/src/common.h psi/psi/src/common.h
--- psi_cvs-2005.05.17/psi/src/common.h	Wed May  4 18:18:20 2005
+++ psi/psi/src/common.h	Tue May 17 20:54:18 2005
@@ -35,6 +35,7 @@
 //#include"xmpp_types.h"
 #include"varlist.h"
 #include"psiiconset.h"
+#include"templates.h"
 
 #define PROXY_NONE       0
 #define PROXY_HTTPS      1
@@ -200,6 +201,33 @@
 	int dtPort;
 	QString dtExternal;
 
+ 	// machekku: smart forward and reply
+
+ 	Template quoteHeaderQuote;
+ 	Template quoteHeaderReply;
+ 	Template quoteHeaderForward;
+
+ 	bool  useQuoteHeaderQuote;
+ 	bool  useQuoteHeaderReply;
+ 	bool  useQuoteHeaderForward;
+
+ 	Template messageSignature;
+ 	bool  useMessageSignature;
+ 	bool autoMessageSignatureDelimiter;
+
+	bool hideQuoteBtn;
+	bool defaultReplyWithoutQuoting;
+	bool hideChatBtn;
+	bool replyInAuthReq;
+
+ 	bool cursorAtTopInEventDlg;
+ 	int  wrapAtColumn;
+ 	bool quoteEmptyLines;
+ 	bool stripEmptyLines;
+ 	bool removeSignature;
+
+ 	QValueVector<QString> fortunes;
+
 	// Last used path remembering
 	QString lastPath;
 	QString lastSavePath;
@@ -228,7 +256,7 @@
 QString status2txt(int status);
 
 QString eatptag(QString txt);
-QString qstrquote(const QString &, int width=60, bool quoteEmpty=FALSE);
+QString qstrquote(const QString &, int width=60, bool quoteEmpty=FALSE, bool stripEmptyLines=FALSE, bool removeSignature=FALSE);
 QString plain2rich(const QString &);
 QString rich2plain(const QString &);
 QString clipStatus(const QString &str, int width, int height);
@@ -323,5 +351,6 @@
 typedef QValueList<XMPP::Jid> JidList;
 typedef QValueListIterator<XMPP::Jid> JidListIt;
 
+enum ComposeType { ctNew, ctReply, ctQuote, ctForward };
 
 #endif
diff -X exclude -Naru psi_cvs-2005.05.17/psi/src/eventdlg.cpp psi/psi/src/eventdlg.cpp
--- psi_cvs-2005.05.17/psi/src/eventdlg.cpp	Sun May 15 22:26:44 2005
+++ psi/psi/src/eventdlg.cpp	Tue May 17 21:36:30 2005
@@ -49,6 +49,17 @@
 #include"iconselect.h"
 #include"iconwidget.h"
 
+/*!
+	\enum ComposeType
+
+	This enum represents different types of Compose action:
+
+	\value ctNew - a new message
+	\value ctReply - a reply to a message (without quoting)
+	\value ctQuote - a reply to a message (with quoting)
+	\value ctForward - a forwarding of a message
+*/                                              
+
 static QString findJid(const QString &s, int x, int *p1, int *p2)
 {
 	// scan backward for the beginning of a Jid
@@ -90,6 +101,29 @@
 }
 
 //----------------------------------------------------------------------------
+// HLineEdit - helper class to enable hotkeys while lineedit is focused
+//----------------------------------------------------------------------------
+
+/*!
+	\class HLineEdit
+
+	HLineEdit is a specialised QLineEdit which prevents text box
+	from catching some hotkeys.
+*/
+
+HLineEdit::HLineEdit(EventDlg *parent, const char *name)
+	: QLineEdit(parent, name) {}
+
+
+void HLineEdit::keyPressEvent(QKeyEvent *e)
+{
+	if((e->key() == Key_H || e->key() == Key_I ) && (e->state() & ControlButton))
+		e->ignore();
+	else
+		QLineEdit::keyPressEvent(e);
+}
+
+//----------------------------------------------------------------------------
 // ELineEdit - a line edit that handles advanced Jid entry
 //----------------------------------------------------------------------------
 // hack hack hack hack
@@ -124,7 +158,7 @@
 };
 
 ELineEdit::ELineEdit(EventDlg *parent, const char *name)
-:QLineEdit(parent, name)
+:HLineEdit(parent, name)
 {
 	setAcceptDrops(TRUE);
 }
@@ -173,7 +207,8 @@
 
 void ELineEdit::keyPressEvent(QKeyEvent *e)
 {
-	QLineEdit::keyPressEvent(e);
+	HLineEdit::keyPressEvent(e);
+
 	if(e->ascii() >= 32 && e->ascii() < 127)
 		tryComplete();
 }
@@ -443,14 +478,14 @@
 	QLabel *lb_ident, *lb_time;
 	IconLabel *lb_status;
 	ELineEdit *le_to;
-	QLineEdit *le_from, *le_subj;
+	HLineEdit *le_from, *le_subj;
 	QLCDNumber *lcd_count;
 	IconToolButton *tb_url, *tb_info, *tb_history, *tb_pgp, *tb_icon;
 	IconLabel *lb_pgp;
 	bool enc;
 	int transid;
 	IconButton *pb_next;
-	IconButton *pb_close, *pb_quote, *pb_deny, *pb_send, *pb_reply, *pb_chat, *pb_auth;
+	IconButton *pb_close, *pb_forward, *pb_quote, *pb_deny, *pb_send, *pb_reply, *pb_auth, *pb_chat;	
 	ChatView *mle;
 	AttachView *attachView;
 	QTimer *whois;
@@ -466,6 +501,10 @@
 	Message m;
 	QStringList sendLeft;
 
+	QDateTime messageTime;
+	
+	bool mayShowReplyingBtns;
+
 public slots:
 	void addEmoticon(const Icon *icon) {
 		if ( !dlg->isActiveWindow() )
@@ -503,6 +542,7 @@
 {
 	d = new Private(this);
 	d->composing = true;
+	d->mayShowReplyingBtns = false;
 	d->psi = psi;
 	d->pa = 0;
 	d->psi->dialogRegister(this);
@@ -569,6 +609,7 @@
 {
 	d = new Private(this);
 	d->composing = false;
+	d->mayShowReplyingBtns = false;
 	d->psi = pa->psi();
 	d->pa = pa;
 	d->jid = j;
@@ -672,7 +713,7 @@
 		l = new QLabel(tr("From:"), this);
 		hb2->addWidget(l);
 		hb2->addWidget(d->lb_status);
-		d->le_from = new QLineEdit(this);
+		d->le_from = new HLineEdit(this);
 		d->le_from->setReadOnly(true);
 		hb2->addWidget(d->le_from);
 	}
@@ -690,7 +731,7 @@
 		d->tb_icon->setEnabled(false);
 
 	// message length counter
-	d->le_subj = new QLineEdit(this);
+	d->le_subj = new HLineEdit(this);
 	d->lcd_count = new QLCDNumber(this);
 	QToolTip::add(d->lcd_count, tr("Message length"));
 	d->lcd_count->setFixedWidth(50);
@@ -785,6 +826,7 @@
 	connect(d->pb_close, SIGNAL(clicked()), SLOT(close()));
 	d->pb_close->setMinimumWidth(80);
 	hb4->addWidget(d->pb_close);
+	hb4->addSpacing(16);
 	hb4->addStretch(1);
 	d->pb_next = new IconButton(this);
 	connect(d->pb_next, SIGNAL(clicked()), SLOT(doReadNext()));
@@ -793,6 +835,18 @@
 	d->pb_next->setMinimumWidth(96);
 	d->pb_next->setEnabled(false);
 	hb4->addWidget(d->pb_next);
+	d->pb_forward = new IconButton(this);
+	d->pb_forward->setText(tr("&Forward"));
+	connect(d->pb_forward, SIGNAL(clicked()), SLOT(doForward()));
+	d->pb_forward->hide();
+	d->pb_forward->setMinimumWidth(96);
+	hb4->addWidget(d->pb_forward);
+	d->pb_chat = new IconButton(this);
+	d->pb_chat->setText(tr("&Chat"));
+	connect(d->pb_chat, SIGNAL(clicked()), SLOT(doChat()));
+	d->pb_chat->hide();
+	d->pb_chat->setMinimumWidth(96);
+	hb4->addWidget(d->pb_chat);
 	d->pb_quote = new IconButton(this);
 	d->pb_quote->setText(tr("&Quote"));
 	connect(d->pb_quote, SIGNAL(clicked()), SLOT(doQuote()));
@@ -818,12 +872,6 @@
 	d->pb_send->hide();
 	d->pb_send->setMinimumWidth(96);
 	hb4->addWidget(d->pb_send);
-	d->pb_chat = new IconButton(this);
-	d->pb_chat->setText(tr("&Chat"));
-	connect(d->pb_chat, SIGNAL(clicked()), SLOT(doChat()));
-	d->pb_chat->hide();
-	d->pb_chat->setMinimumWidth(96);
-	hb4->addWidget(d->pb_chat);
 	d->pb_reply = new IconButton(this);
 	d->pb_reply->setText(tr("&Reply"));
 	connect(d->pb_reply, SIGNAL(clicked()), SLOT(doReply()));
@@ -873,10 +921,10 @@
 	return d->mle->text();
 }
 
-void EventDlg::setText(const QString &s)
+void EventDlg::setText(const QString &s, bool moveCursorToTop)
 {
 	d->mle->setText(s);
-	d->mle->moveCursor(QTextEdit::MoveEnd, false);
+	d->mle->moveCursor((moveCursorToTop)? QTextEdit::MoveHome : QTextEdit::MoveEnd, false);
 }
 
 void EventDlg::setSubject(const QString &s)
@@ -894,6 +942,15 @@
 	d->urlOnShow = true;
 }
 
+/*!
+	Adds attachement with URL \a url and description \a desc to the message.
+*/
+
+void EventDlg::addAttachement(const QString &url, const QString &desc)	// machekku
+{
+	d->attachView->urlAdd(url, desc);
+}
+
 PsiAccount *EventDlg::psiAccount()
 {
 	return d->pa;
@@ -1210,6 +1267,9 @@
 			setIcon(d->anim->impix());
 	}
 #endif
+
+	// update replying buttons
+	updateReplyingButtons();
 }
 
 QSize EventDlg::defaultSize()
@@ -1243,6 +1303,14 @@
 #endif
 	else if(d->composing && e->key() == Key_Return && ((e->state() & ControlButton) || (e->state() & AltButton)) )
 		doSend();
+	else if(!d->composing && e->key() == Key_R && (e->state() & ControlButton)) {
+		if(option.defaultReplyWithoutQuoting)
+			doReply();
+		else
+			doQuote();
+	}
+	else if(!d->composing && e->key() == Key_L && (e->state() & ControlButton))
+		doForward();
 	else if(e->key() == Key_H && (e->state() & ControlButton))
 		doHistory();
 	else if(e->key() == Key_I && (e->state() & ControlButton))
@@ -1344,7 +1412,7 @@
 	if(list.isEmpty())
 		return;
 	Jid j(list[0]);
-	aReply(j, "", d->le_subj->text(), d->thread);
+	aCompose(j, "", d->le_subj->text(), d->thread, ctReply, j, d->pa->jid(), d->messageTime, d->attachView->urlList());
 }
 
 void EventDlg::doQuote()
@@ -1360,7 +1428,32 @@
 	else
 		body = rich2plain(d->mle->text());
 
-	aReply(j, body, d->le_subj->text(), d->thread);
+	aCompose(j, body, d->le_subj->text(), d->thread, ctQuote, j, d->pa->jid(), d->messageTime, d->attachView->urlList());
+}
+
+/*!
+	Forwards the message.
+	Forwarded message will contain selected part of the text
+	or all text if there was no selection.
+	
+	All attachemenets are forwarded, too.
+*/
+
+void EventDlg::doForward()
+{
+	QStringList list = stringToList(d->le_from->text());
+	Jid jFrom;
+	if(!list.isEmpty())
+		jFrom = Jid(list[0]);
+
+	QString body;
+	if(d->mle->hasSelectedText())
+		body = rich2plain(d->mle->selectedText());
+	else
+		body = rich2plain(d->mle->text());
+
+	Jid jTo;
+	aCompose(jTo, body, d->le_subj->text(), d->thread, ctForward, jFrom, d->pa->jid(), d->messageTime, d->attachView->urlList());	
 }
 
 void EventDlg::doDeny()
@@ -1484,6 +1577,31 @@
 		str = QString("<font color=\"red\">") + str + "</font>";
 
 	d->lb_time->setText(str);
+
+	d->messageTime = t;
+}
+
+void EventDlg::updateReplyingButtons()
+{
+	const bool showChat  = !option.hideChatBtn;
+	const bool showReply = !option.hideQuoteBtn ||  option.defaultReplyWithoutQuoting;	// (two buttons) or (one button which is 'reply')
+	const bool showQuote = !option.hideQuoteBtn || !option.defaultReplyWithoutQuoting;	// (two buttons) or (one button which is 'quote')
+
+	d->pb_quote->setText( ( option.hideQuoteBtn && !option.defaultReplyWithoutQuoting ) ? tr("&Reply") : tr("&Quote") );
+
+	if ( d->mayShowReplyingBtns ) {
+		(showChat )? d->pb_chat ->show() : d->pb_chat ->hide();
+		(showReply)? d->pb_reply->show() : d->pb_reply->hide();
+		(showQuote)? d->pb_quote->show() : d->pb_quote->hide();
+        d->pb_forward->show();
+	}
+	else {
+		d->pb_chat->hide();
+		d->pb_forward->hide();
+		d->pb_reply->hide();
+		d->pb_quote->hide();
+	}
+
 }
 
 void EventDlg::updateEvent(PsiEvent *e)
@@ -1510,9 +1628,7 @@
 		d->pb_auth->hide();
 		d->pb_deny->hide();
 
-		d->pb_chat->show();
-		d->pb_reply->show();
-		d->pb_quote->show();
+		d->mayShowReplyingBtns = true;
 
 		QString txt = plain2rich(m.body());
 
@@ -1551,9 +1667,7 @@
 			d->mle->setTextFormat(RichText);
 			d->mle->setText("<qt>" + body + "</qt>");
 
-			d->pb_chat->show();
-			d->pb_reply->hide();
-			d->pb_quote->hide();
+			d->mayShowReplyingBtns = option.replyInAuthReq;
 
 			d->pb_auth->setEnabled(true);
 			d->pb_auth->show();
@@ -1567,9 +1681,8 @@
 
 			d->pb_auth->hide();
 			d->pb_deny->hide();
-			d->pb_chat->show();
-			d->pb_reply->show();
-			d->pb_quote->show();
+
+			d->mayShowReplyingBtns = true;
 		}
 		else if(type == "unsubscribed") {
 			QString body(tr("<big>[System Message]</big><br>Your authorization has been removed!"));
@@ -1579,11 +1692,12 @@
 
 			d->pb_auth->hide();
 			d->pb_deny->hide();
-			d->pb_chat->show();
-			d->pb_reply->show();
-			d->pb_quote->show();
+	
+			d->mayShowReplyingBtns = true;
 		}
 	}
+	
+	updateReplyingButtons();
 
 	if(d->lb_pgp)
 		d->lb_pgp->setIcon( IconsetFactory::iconPtr(d->enc ? "psi/cryptoYes" : "psi/cryptoNo") );
diff -X exclude -Naru psi_cvs-2005.05.17/psi/src/eventdlg.h psi/psi/src/eventdlg.h
--- psi_cvs-2005.05.17/psi/src/eventdlg.h	Sun May 15 22:26:44 2005
+++ psi/psi/src/eventdlg.h	Tue May 17 21:35:24 2005
@@ -30,6 +30,7 @@
 #include"im.h"
 #include"userlist.h"
 #include"ui_addurl.h"
+#include"common.h"
 
 using namespace XMPP;
 
@@ -41,7 +42,18 @@
 class Icon;
 
 class EventDlg;
-class ELineEdit : public QLineEdit
+
+// helper class to enable hotkeys while lineedit is focused
+class HLineEdit : public QLineEdit
+{
+	Q_OBJECT
+public:
+	HLineEdit(EventDlg *parent, const char *name=0);
+protected:
+	void keyPressEvent(QKeyEvent *);
+};
+
+class ELineEdit : public HLineEdit
 {
 	Q_OBJECT
 public:
@@ -112,18 +124,20 @@
 	~EventDlg();
 
 	QString text() const;
-	void setText(const QString &);
+	void setText(const QString &, bool moveCursorToTop = false);
 	void setSubject(const QString &);
 	void setThread(const QString &);
 	void setUrlOnShow();
 
+	void addAttachement(const QString &url, const QString &desc);
+
 	PsiAccount *psiAccount();
 
 	static QSize defaultSize();
 
 signals:
 	void aChat(const Jid& jid);
-	void aReply(const Jid &jid, const QString &body, const QString &subject, const QString &thread);
+	void aCompose(const Jid &jid, const QString &body, const QString &subject, const QString &thread, ComposeType ct, const Jid &originalJid_Sender, const Jid &originalJid_Me, const QDateTime &originalMessageTime, const UrlList &originalMessageAttachements);
 	void aReadNext(const Jid &);
 	void aDeny(const Jid &);
 	void aAuth(const Jid &);
@@ -154,6 +168,7 @@
 	void doReadNext();
 	void doChat();
 	void doReply();
+	void doForward();
 	void doQuote();
 	void doDeny();
 	void doAuth();
@@ -165,6 +180,8 @@
 	void updatePGP();
 	void encryptedMessageSent(int, bool);
 	void trySendEncryptedNext();
+	
+	void updateReplyingButtons();
 
 public:
 	class Private;
diff -X exclude -Naru psi_cvs-2005.05.17/psi/src/options/opt_messages-ui.ui psi/psi/src/options/opt_messages-ui.ui
--- psi_cvs-2005.05.17/psi/src/options/opt_messages-ui.ui	Thu Jan  1 01:00:00 1970
+++ psi/psi/src/options/opt_messages-ui.ui	Tue May 17 20:54:18 2005
@@ -0,0 +1,895 @@
+<!DOCTYPE UI><UI version="3.1" stdsetdef="1">
+<class>OptMessagesUI</class>
+<widget class="QWidget">
+    <property name="name">
+        <cstring>OptMessagesUI</cstring>
+    </property>
+    <property name="geometry">
+        <rect>
+            <x>0</x>
+            <y>0</y>
+            <width>300</width>
+            <height>403</height>
+        </rect>
+    </property>
+    <property name="caption">
+        <string>OptMessagesUI</string>
+    </property>
+    <vbox>
+        <property name="name">
+            <cstring>unnamed</cstring>
+        </property>
+        <property name="margin">
+            <number>0</number>
+        </property>
+        <widget class="QTabWidget">
+            <property name="name">
+                <cstring>tabWidget3</cstring>
+            </property>
+            <widget class="QWidget">
+                <property name="name">
+                    <cstring>TabPage</cstring>
+                </property>
+                <attribute name="title">
+                    <string>Signature</string>
+                </attribute>
+                <vbox>
+                    <property name="name">
+                        <cstring>unnamed</cstring>
+                    </property>
+                    <widget class="QCheckBox">
+                        <property name="name">
+                            <cstring>ck_signature</cstring>
+                        </property>
+                        <property name="text">
+                            <string>Add a signature when sending a message</string>
+                        </property>
+                    </widget>
+                    <widget class="QGroupBox">
+                        <property name="name">
+                            <cstring>gb_signature</cstring>
+                        </property>
+                        <property name="sizePolicy">
+                            <sizepolicy>
+                                <hsizetype>5</hsizetype>
+                                <vsizetype>4</vsizetype>
+                                <horstretch>0</horstretch>
+                                <verstretch>0</verstretch>
+                            </sizepolicy>
+                        </property>
+                        <property name="title">
+                            <string>&amp;Signature</string>
+                        </property>
+                        <vbox>
+                            <property name="name">
+                                <cstring>unnamed</cstring>
+                            </property>
+                            <widget class="QLayoutWidget">
+                                <property name="name">
+                                    <cstring>layout18</cstring>
+                                </property>
+                                <grid>
+                                    <property name="name">
+                                        <cstring>unnamed</cstring>
+                                    </property>
+                                    <widget class="QTextEdit" row="1" column="0" rowspan="1" colspan="2">
+                                        <property name="name">
+                                            <cstring>te_signature</cstring>
+                                        </property>
+                                        <property name="sizePolicy">
+                                            <sizepolicy>
+                                                <hsizetype>7</hsizetype>
+                                                <vsizetype>7</vsizetype>
+                                                <horstretch>0</horstretch>
+                                                <verstretch>0</verstretch>
+                                            </sizepolicy>
+                                        </property>
+                                        <property name="maximumSize">
+                                            <size>
+                                                <width>32767</width>
+                                                <height>90</height>
+                                            </size>
+                                        </property>
+                                        <property name="wordWrap">
+                                            <enum>NoWrap</enum>
+                                        </property>
+                                    </widget>
+                                    <widget class="QPushButton" row="0" column="0">
+                                        <property name="name">
+                                            <cstring>pb_insSignature</cstring>
+                                        </property>
+                                        <property name="enabled">
+                                            <bool>true</bool>
+                                        </property>
+                                        <property name="text">
+                                            <string>Special symbols</string>
+                                        </property>
+                                    </widget>
+                                    <spacer row="0" column="1">
+                                        <property name="name">
+                                            <cstring>spacer9_4</cstring>
+                                        </property>
+                                        <property name="orientation">
+                                            <enum>Horizontal</enum>
+                                        </property>
+                                        <property name="sizeType">
+                                            <enum>Expanding</enum>
+                                        </property>
+                                        <property name="sizeHint">
+                                            <size>
+                                                <width>182</width>
+                                                <height>20</height>
+                                            </size>
+                                        </property>
+                                    </spacer>
+                                </grid>
+                            </widget>
+                            <widget class="QCheckBox">
+                                <property name="name">
+                                    <cstring>ck_signatureAutoDelimiter</cstring>
+                                </property>
+                                <property name="text">
+                                    <string>Automatically add signature &amp;delimiter</string>
+                                </property>
+                                <property name="accel">
+                                    <string>Alt+D</string>
+                                </property>
+                            </widget>
+                        </vbox>
+                    </widget>
+                    <widget class="QGroupBox">
+                        <property name="name">
+                            <cstring>groupBox10</cstring>
+                        </property>
+                        <property name="sizePolicy">
+                            <sizepolicy>
+                                <hsizetype>5</hsizetype>
+                                <vsizetype>4</vsizetype>
+                                <horstretch>0</horstretch>
+                                <verstretch>0</verstretch>
+                            </sizepolicy>
+                        </property>
+                        <property name="title">
+                            <string>&amp;Fortunes</string>
+                        </property>
+                        <vbox>
+                            <property name="name">
+                                <cstring>unnamed</cstring>
+                            </property>
+                            <property name="spacing">
+                                <number>2</number>
+                            </property>
+                            <widget class="QLayoutWidget">
+                                <property name="name">
+                                    <cstring>layout29</cstring>
+                                </property>
+                                <grid>
+                                    <property name="name">
+                                        <cstring>unnamed</cstring>
+                                    </property>
+                                    <widget class="FortunesListBox" row="0" column="0" rowspan="3" colspan="1">
+                                        <property name="name">
+                                            <cstring>lb_fortunes</cstring>
+                                        </property>
+                                        <property name="sizePolicy">
+                                            <sizepolicy>
+                                                <hsizetype>7</hsizetype>
+                                                <vsizetype>7</vsizetype>
+                                                <horstretch>0</horstretch>
+                                                <verstretch>0</verstretch>
+                                            </sizepolicy>
+                                        </property>
+                                        <property name="maximumSize">
+                                            <size>
+                                                <width>32767</width>
+                                                <height>62</height>
+                                            </size>
+                                        </property>
+                                    </widget>
+                                    <widget class="QPushButton" row="0" column="1">
+                                        <property name="name">
+                                            <cstring>pb_fortuneNew</cstring>
+                                        </property>
+                                        <property name="text">
+                                            <string>New</string>
+                                        </property>
+                                    </widget>
+                                    <spacer row="1" column="1">
+                                        <property name="name">
+                                            <cstring>Spacer6</cstring>
+                                        </property>
+                                        <property name="orientation">
+                                            <enum>Vertical</enum>
+                                        </property>
+                                        <property name="sizeType">
+                                            <enum>Maximum</enum>
+                                        </property>
+                                        <property name="sizeHint">
+                                            <size>
+                                                <width>16</width>
+                                                <height>0</height>
+                                            </size>
+                                        </property>
+                                    </spacer>
+                                    <widget class="QPushButton" row="2" column="1">
+                                        <property name="name">
+                                            <cstring>pb_fortuneDelete</cstring>
+                                        </property>
+                                        <property name="text">
+                                            <string>Delete</string>
+                                        </property>
+                                    </widget>
+                                </grid>
+                            </widget>
+                            <widget class="QLabel">
+                                <property name="name">
+                                    <cstring>TextLabel2_2</cstring>
+                                </property>
+                                <property name="text">
+                                    <string>Content:</string>
+                                </property>
+                            </widget>
+                            <widget class="QTextEdit">
+                                <property name="name">
+                                    <cstring>te_fortune</cstring>
+                                </property>
+                                <property name="sizePolicy">
+                                    <sizepolicy>
+                                        <hsizetype>7</hsizetype>
+                                        <vsizetype>7</vsizetype>
+                                        <horstretch>0</horstretch>
+                                        <verstretch>0</verstretch>
+                                    </sizepolicy>
+                                </property>
+                                <property name="maximumSize">
+                                    <size>
+                                        <width>32767</width>
+                                        <height>62</height>
+                                    </size>
+                                </property>
+                            </widget>
+                        </vbox>
+                    </widget>
+                    <spacer>
+                        <property name="name">
+                            <cstring>spacer88</cstring>
+                        </property>
+                        <property name="orientation">
+                            <enum>Vertical</enum>
+                        </property>
+                        <property name="sizeType">
+                            <enum>Minimum</enum>
+                        </property>
+                        <property name="sizeHint">
+                            <size>
+                                <width>20</width>
+                                <height>0</height>
+                            </size>
+                        </property>
+                    </spacer>
+                </vbox>
+            </widget>
+            <widget class="QWidget">
+                <property name="name">
+                    <cstring>TabPage</cstring>
+                </property>
+                <attribute name="title">
+                    <string>Quote &amp;&amp; Reply</string>
+                </attribute>
+                <vbox>
+                    <property name="name">
+                        <cstring>unnamed</cstring>
+                    </property>
+                    <widget class="QCheckBox">
+                        <property name="name">
+                            <cstring>ck_headerQuote</cstring>
+                        </property>
+                        <property name="text">
+                            <string>Add a header when quoting a message</string>
+                        </property>
+                    </widget>
+                    <widget class="QGroupBox">
+                        <property name="name">
+                            <cstring>gb_headerQuote</cstring>
+                        </property>
+                        <property name="sizePolicy">
+                            <sizepolicy>
+                                <hsizetype>5</hsizetype>
+                                <vsizetype>4</vsizetype>
+                                <horstretch>0</horstretch>
+                                <verstretch>0</verstretch>
+                            </sizepolicy>
+                        </property>
+                        <property name="title">
+                            <string>&amp;Quote header</string>
+                        </property>
+                        <grid>
+                            <property name="name">
+                                <cstring>unnamed</cstring>
+                            </property>
+                            <widget class="QLayoutWidget" row="0" column="0">
+                                <property name="name">
+                                    <cstring>layout8</cstring>
+                                </property>
+                                <grid>
+                                    <property name="name">
+                                        <cstring>unnamed</cstring>
+                                    </property>
+                                    <widget class="QPushButton" row="0" column="0">
+                                        <property name="name">
+                                            <cstring>pb_insQuote</cstring>
+                                        </property>
+                                        <property name="text">
+                                            <string>Special symbols</string>
+                                        </property>
+                                    </widget>
+                                    <spacer row="0" column="1">
+                                        <property name="name">
+                                            <cstring>spacer9_2</cstring>
+                                        </property>
+                                        <property name="orientation">
+                                            <enum>Horizontal</enum>
+                                        </property>
+                                        <property name="sizeType">
+                                            <enum>Expanding</enum>
+                                        </property>
+                                        <property name="sizeHint">
+                                            <size>
+                                                <width>40</width>
+                                                <height>20</height>
+                                            </size>
+                                        </property>
+                                    </spacer>
+                                    <widget class="QTextEdit" row="1" column="0" rowspan="1" colspan="2">
+                                        <property name="name">
+                                            <cstring>te_headerQuote</cstring>
+                                        </property>
+                                        <property name="sizePolicy">
+                                            <sizepolicy>
+                                                <hsizetype>7</hsizetype>
+                                                <vsizetype>7</vsizetype>
+                                                <horstretch>0</horstretch>
+                                                <verstretch>0</verstretch>
+                                            </sizepolicy>
+                                        </property>
+                                        <property name="maximumSize">
+                                            <size>
+                                                <width>32767</width>
+                                                <height>90</height>
+                                            </size>
+                                        </property>
+                                    </widget>
+                                </grid>
+                            </widget>
+                        </grid>
+                    </widget>
+                    <widget class="QCheckBox">
+                        <property name="name">
+                            <cstring>ck_headerReply</cstring>
+                        </property>
+                        <property name="text">
+                            <string>Add a header when replying a message</string>
+                        </property>
+                    </widget>
+                    <widget class="QGroupBox">
+                        <property name="name">
+                            <cstring>gb_headerReply</cstring>
+                        </property>
+                        <property name="sizePolicy">
+                            <sizepolicy>
+                                <hsizetype>5</hsizetype>
+                                <vsizetype>4</vsizetype>
+                                <horstretch>0</horstretch>
+                                <verstretch>0</verstretch>
+                            </sizepolicy>
+                        </property>
+                        <property name="title">
+                            <string>&amp;Reply header</string>
+                        </property>
+                        <grid>
+                            <property name="name">
+                                <cstring>unnamed</cstring>
+                            </property>
+                            <widget class="QLayoutWidget" row="0" column="0">
+                                <property name="name">
+                                    <cstring>layout9</cstring>
+                                </property>
+                                <grid>
+                                    <property name="name">
+                                        <cstring>unnamed</cstring>
+                                    </property>
+                                    <widget class="QTextEdit" row="1" column="0" rowspan="1" colspan="2">
+                                        <property name="name">
+                                            <cstring>te_headerReply</cstring>
+                                        </property>
+                                        <property name="sizePolicy">
+                                            <sizepolicy>
+                                                <hsizetype>7</hsizetype>
+                                                <vsizetype>7</vsizetype>
+                                                <horstretch>0</horstretch>
+                                                <verstretch>0</verstretch>
+                                            </sizepolicy>
+                                        </property>
+                                        <property name="maximumSize">
+                                            <size>
+                                                <width>32767</width>
+                                                <height>90</height>
+                                            </size>
+                                        </property>
+                                        <property name="wordWrap">
+                                            <enum>NoWrap</enum>
+                                        </property>
+                                    </widget>
+                                    <widget class="QPushButton" row="0" column="0">
+                                        <property name="name">
+                                            <cstring>pb_insReply</cstring>
+                                        </property>
+                                        <property name="text">
+                                            <string>Special symbols</string>
+                                        </property>
+                                    </widget>
+                                    <spacer row="0" column="1">
+                                        <property name="name">
+                                            <cstring>spacer9_3</cstring>
+                                        </property>
+                                        <property name="orientation">
+                                            <enum>Horizontal</enum>
+                                        </property>
+                                        <property name="sizeType">
+                                            <enum>Expanding</enum>
+                                        </property>
+                                        <property name="sizeHint">
+                                            <size>
+                                                <width>40</width>
+                                                <height>20</height>
+                                            </size>
+                                        </property>
+                                    </spacer>
+                                </grid>
+                            </widget>
+                        </grid>
+                    </widget>
+                    <spacer>
+                        <property name="name">
+                            <cstring>spacer10</cstring>
+                        </property>
+                        <property name="orientation">
+                            <enum>Vertical</enum>
+                        </property>
+                        <property name="sizeType">
+                            <enum>Minimum</enum>
+                        </property>
+                        <property name="sizeHint">
+                            <size>
+                                <width>20</width>
+                                <height>0</height>
+                            </size>
+                        </property>
+                    </spacer>
+                </vbox>
+            </widget>
+            <widget class="QWidget">
+                <property name="name">
+                    <cstring>TabPage</cstring>
+                </property>
+                <attribute name="title">
+                    <string>Forward</string>
+                </attribute>
+                <vbox>
+                    <property name="name">
+                        <cstring>unnamed</cstring>
+                    </property>
+                    <widget class="QCheckBox">
+                        <property name="name">
+                            <cstring>ck_headerForward</cstring>
+                        </property>
+                        <property name="text">
+                            <string>Add a header when forwarding a message</string>
+                        </property>
+                    </widget>
+                    <widget class="QGroupBox">
+                        <property name="name">
+                            <cstring>gb_headerForward</cstring>
+                        </property>
+                        <property name="sizePolicy">
+                            <sizepolicy>
+                                <hsizetype>5</hsizetype>
+                                <vsizetype>4</vsizetype>
+                                <horstretch>0</horstretch>
+                                <verstretch>0</verstretch>
+                            </sizepolicy>
+                        </property>
+                        <property name="title">
+                            <string>&amp;Forward header</string>
+                        </property>
+                        <grid>
+                            <property name="name">
+                                <cstring>unnamed</cstring>
+                            </property>
+                            <widget class="QLayoutWidget" row="0" column="0">
+                                <property name="name">
+                                    <cstring>layout7</cstring>
+                                </property>
+                                <grid>
+                                    <property name="name">
+                                        <cstring>unnamed</cstring>
+                                    </property>
+                                    <spacer row="0" column="1">
+                                        <property name="name">
+                                            <cstring>spacer9</cstring>
+                                        </property>
+                                        <property name="orientation">
+                                            <enum>Horizontal</enum>
+                                        </property>
+                                        <property name="sizeType">
+                                            <enum>Expanding</enum>
+                                        </property>
+                                        <property name="sizeHint">
+                                            <size>
+                                                <width>160</width>
+                                                <height>20</height>
+                                            </size>
+                                        </property>
+                                    </spacer>
+                                    <widget class="QTextEdit" row="1" column="0" rowspan="1" colspan="2">
+                                        <property name="name">
+                                            <cstring>te_headerForward</cstring>
+                                        </property>
+                                        <property name="sizePolicy">
+                                            <sizepolicy>
+                                                <hsizetype>7</hsizetype>
+                                                <vsizetype>7</vsizetype>
+                                                <horstretch>0</horstretch>
+                                                <verstretch>0</verstretch>
+                                            </sizepolicy>
+                                        </property>
+                                        <property name="minimumSize">
+                                            <size>
+                                                <width>0</width>
+                                                <height>10</height>
+                                            </size>
+                                        </property>
+                                        <property name="maximumSize">
+                                            <size>
+                                                <width>32767</width>
+                                                <height>90</height>
+                                            </size>
+                                        </property>
+                                        <property name="tabChangesFocus">
+                                            <bool>false</bool>
+                                        </property>
+                                    </widget>
+                                    <widget class="QPushButton" row="0" column="0">
+                                        <property name="name">
+                                            <cstring>pb_insForward</cstring>
+                                        </property>
+                                        <property name="text">
+                                            <string>Special symbols</string>
+                                        </property>
+                                    </widget>
+                                </grid>
+                            </widget>
+                        </grid>
+                    </widget>
+                    <spacer>
+                        <property name="name">
+                            <cstring>spacer86</cstring>
+                        </property>
+                        <property name="orientation">
+                            <enum>Vertical</enum>
+                        </property>
+                        <property name="sizeType">
+                            <enum>Minimum</enum>
+                        </property>
+                        <property name="sizeHint">
+                            <size>
+                                <width>20</width>
+                                <height>0</height>
+                            </size>
+                        </property>
+                    </spacer>
+                </vbox>
+            </widget>
+            <widget class="QWidget">
+                <property name="name">
+                    <cstring>TabPage</cstring>
+                </property>
+                <attribute name="title">
+                    <string>Misc</string>
+                </attribute>
+                <vbox>
+                    <property name="name">
+                        <cstring>unnamed</cstring>
+                    </property>
+                    <widget class="QGroupBox">
+                        <property name="name">
+                            <cstring>groupBox6</cstring>
+                        </property>
+                        <property name="sizePolicy">
+                            <sizepolicy>
+                                <hsizetype>5</hsizetype>
+                                <vsizetype>4</vsizetype>
+                                <horstretch>0</horstretch>
+                                <verstretch>0</verstretch>
+                            </sizepolicy>
+                        </property>
+                        <property name="title">
+                            <string>&amp;Quoting options</string>
+                        </property>
+                        <vbox>
+                            <property name="name">
+                                <cstring>unnamed</cstring>
+                            </property>
+                            <widget class="QCheckBox">
+                                <property name="name">
+                                    <cstring>ck_quoteEmptyLines</cstring>
+                                </property>
+                                <property name="text">
+                                    <string>&amp;Quote empty lines</string>
+                                </property>
+                                <property name="accel">
+                                    <string>Alt+Q</string>
+                                </property>
+                            </widget>
+                            <widget class="QCheckBox">
+                                <property name="name">
+                                    <cstring>ck_stripEmptyLines</cstring>
+                                </property>
+                                <property name="text">
+                                    <string>&amp;Strip empty lines</string>
+                                </property>
+                                <property name="accel">
+                                    <string>Alt+S</string>
+                                </property>
+                            </widget>
+                            <widget class="QCheckBox">
+                                <property name="name">
+                                    <cstring>ck_removeSignature</cstring>
+                                </property>
+                                <property name="text">
+                                    <string>&amp;Remove signature from quoted text</string>
+                                </property>
+                                <property name="accel">
+                                    <string>Alt+R</string>
+                                </property>
+                            </widget>
+                            <widget class="QLayoutWidget">
+                                <property name="name">
+                                    <cstring>layout21</cstring>
+                                </property>
+                                <hbox>
+                                    <property name="name">
+                                        <cstring>unnamed</cstring>
+                                    </property>
+                                    <widget class="QLabel">
+                                        <property name="name">
+                                            <cstring>textLabel3</cstring>
+                                        </property>
+                                        <property name="text">
+                                            <string>&amp;Wrap at column:</string>
+                                        </property>
+                                        <property name="buddy" stdset="0">
+                                            <cstring>sb_wrapAtColumn</cstring>
+                                        </property>
+                                    </widget>
+                                    <widget class="QSpinBox">
+                                        <property name="name">
+                                            <cstring>sb_wrapAtColumn</cstring>
+                                        </property>
+                                    </widget>
+                                    <spacer>
+                                        <property name="name">
+                                            <cstring>spacer19</cstring>
+                                        </property>
+                                        <property name="orientation">
+                                            <enum>Horizontal</enum>
+                                        </property>
+                                        <property name="sizeType">
+                                            <enum>Expanding</enum>
+                                        </property>
+                                        <property name="sizeHint">
+                                            <size>
+                                                <width>44</width>
+                                                <height>20</height>
+                                            </size>
+                                        </property>
+                                    </spacer>
+                                </hbox>
+                            </widget>
+                        </vbox>
+                    </widget>
+                    <widget class="QGroupBox">
+                        <property name="name">
+                            <cstring>groupBox7</cstring>
+                        </property>
+                        <property name="sizePolicy">
+                            <sizepolicy>
+                                <hsizetype>5</hsizetype>
+                                <vsizetype>4</vsizetype>
+                                <horstretch>0</horstretch>
+                                <verstretch>0</verstretch>
+                            </sizepolicy>
+                        </property>
+                        <property name="title">
+                            <string>Q&amp;uote or reply</string>
+                        </property>
+                        <vbox>
+                            <property name="name">
+                                <cstring>unnamed</cstring>
+                            </property>
+                            <widget class="QCheckBox">
+                                <property name="name">
+                                    <cstring>ck_hideQuoteBtn</cstring>
+                                </property>
+                                <property name="text">
+                                    <string>Hide '&amp;Quote' button</string>
+                                </property>
+                                <property name="accel">
+                                    <string>Alt+Q</string>
+                                </property>
+                            </widget>
+                            <widget class="QCheckBox">
+                                <property name="name">
+                                    <cstring>ck_defaultReplyWithoutQuoting</cstring>
+                                </property>
+                                <property name="text">
+                                    <string>&amp;Reply without quoting by default</string>
+                                </property>
+                                <property name="accel">
+                                    <string>Alt+R</string>
+                                </property>
+                            </widget>
+                        </vbox>
+                    </widget>
+                    <widget class="QGroupBox">
+                        <property name="name">
+                            <cstring>groupBox9</cstring>
+                        </property>
+                        <property name="sizePolicy">
+                            <sizepolicy>
+                                <hsizetype>5</hsizetype>
+                                <vsizetype>4</vsizetype>
+                                <horstretch>0</horstretch>
+                                <verstretch>0</verstretch>
+                            </sizepolicy>
+                        </property>
+                        <property name="title">
+                            <string>&amp;Other</string>
+                        </property>
+                        <vbox>
+                            <property name="name">
+                                <cstring>unnamed</cstring>
+                            </property>
+                            <widget class="QCheckBox">
+                                <property name="name">
+                                    <cstring>ck_hideChatBtn</cstring>
+                                </property>
+                                <property name="text">
+                                    <string>Hide 'Start &amp;Chat' button</string>
+                                </property>
+                                <property name="accel">
+                                    <string>Alt+C</string>
+                                </property>
+                            </widget>
+                            <widget class="QCheckBox">
+                                <property name="name">
+                                    <cstring>ck_showReplyInAuthRequests</cstring>
+                                </property>
+                                <property name="text">
+                                    <string>Show replying buttons for authorization requests</string>
+                                </property>
+                                <property name="accel">
+                                    <string></string>
+                                </property>
+                            </widget>
+                            <widget class="QCheckBox">
+                                <property name="name">
+                                    <cstring>ck_cursorAtTop</cstring>
+                                </property>
+                                <property name="text">
+                                    <string>&amp;Move cursor to the top of edit field</string>
+                                </property>
+                                <property name="accel">
+                                    <string>Alt+M</string>
+                                </property>
+                            </widget>
+                        </vbox>
+                    </widget>
+                    <spacer>
+                        <property name="name">
+                            <cstring>spacer85</cstring>
+                        </property>
+                        <property name="orientation">
+                            <enum>Vertical</enum>
+                        </property>
+                        <property name="sizeType">
+                            <enum>Minimum</enum>
+                        </property>
+                        <property name="sizeHint">
+                            <size>
+                                <width>20</width>
+                                <height>0</height>
+                            </size>
+                        </property>
+                    </spacer>
+                </vbox>
+            </widget>
+        </widget>
+    </vbox>
+</widget>
+<customwidgets>
+    <customwidget>
+        <class>FortunesListBox</class>
+        <header location="local">opt_messages.h</header>
+        <sizehint>
+            <width>-1</width>
+            <height>-1</height>
+        </sizehint>
+        <container>0</container>
+        <sizepolicy>
+            <hordata>5</hordata>
+            <verdata>5</verdata>
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+        </sizepolicy>
+        <pixmap>image0</pixmap>
+    </customwidget>
+</customwidgets>
+<images>
+    <image name="image0">
+        <data format="XPM.GZ" length="65">789cd3d7528808f055d0d2e72a2e492cc94c5648ce482c52d04a29cdcdad8c8eb5ade65232540043251d2e253d856405650b03100473956aadb9003aff0fa0</data>
+    </image>
+</images>
+<connections>
+    <connection>
+        <sender>ck_headerForward</sender>
+        <signal>toggled(bool)</signal>
+        <receiver>gb_headerForward</receiver>
+        <slot>setEnabled(bool)</slot>
+    </connection>
+    <connection>
+        <sender>ck_headerQuote</sender>
+        <signal>toggled(bool)</signal>
+        <receiver>gb_headerQuote</receiver>
+        <slot>setEnabled(bool)</slot>
+    </connection>
+    <connection>
+        <sender>ck_headerReply</sender>
+        <signal>toggled(bool)</signal>
+        <receiver>gb_headerReply</receiver>
+        <slot>setEnabled(bool)</slot>
+    </connection>
+    <connection>
+        <sender>ck_signature</sender>
+        <signal>toggled(bool)</signal>
+        <receiver>gb_signature</receiver>
+        <slot>setEnabled(bool)</slot>
+    </connection>
+</connections>
+<tabstops>
+    <tabstop>tabWidget3</tabstop>
+    <tabstop>ck_headerForward</tabstop>
+    <tabstop>pb_insForward</tabstop>
+    <tabstop>te_headerForward</tabstop>
+    <tabstop>ck_headerQuote</tabstop>
+    <tabstop>pb_insQuote</tabstop>
+    <tabstop>te_headerQuote</tabstop>
+    <tabstop>ck_headerReply</tabstop>
+    <tabstop>pb_insReply</tabstop>
+    <tabstop>te_headerReply</tabstop>
+    <tabstop>ck_signature</tabstop>
+    <tabstop>pb_insSignature</tabstop>
+    <tabstop>te_signature</tabstop>
+    <tabstop>ck_signatureAutoDelimiter</tabstop>
+</tabstops>
+<includes>
+    <include location="local" impldecl="in implementation">opt_messages-ui.ui.h</include>
+</includes>
+<slots>
+    <slot>destroy()</slot>
+</slots>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+    <includehint>fortuneslistbox.h</includehint>
+</includehints>
+</UI>
diff -X exclude -Naru psi_cvs-2005.05.17/psi/src/options/opt_messages-ui.ui.h psi/psi/src/options/opt_messages-ui.ui.h
--- psi_cvs-2005.05.17/psi/src/options/opt_messages-ui.ui.h	Thu Jan  1 01:00:00 1970
+++ psi/psi/src/options/opt_messages-ui.ui.h	Tue May 17 20:54:18 2005
@@ -0,0 +1,18 @@
+/****************************************************************************
+** ui.h extension file, included from the uic-generated form implementation.
+**
+** If you wish to add, delete or rename functions or slots use
+** Qt Designer which will update this file, preserving your code. Create an
+** init() function in place of a constructor, and a destroy() function in
+** place of a destructor.
+*****************************************************************************/
+
+#include <qpopupmenu.h>
+
+void OptMessagesUI::destroy()
+{
+    delete pb_insForward->popup();
+    delete pb_insQuote->popup();
+    delete pb_insReply->popup();   
+    delete pb_insSignature->popup();   
+}
diff -X exclude -Naru psi_cvs-2005.05.17/psi/src/options/opt_messages.cpp psi/psi/src/options/opt_messages.cpp
--- psi_cvs-2005.05.17/psi/src/options/opt_messages.cpp	Thu Jan  1 01:00:00 1970
+++ psi/psi/src/options/opt_messages.cpp	Tue May 17 20:54:18 2005
@@ -0,0 +1,540 @@
+/*
+ * opt_messages.cpp - options tab for messages options
+ * Copyright (C) 2005  Maciej Niedzielski
+ *
+ * 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 library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "opt_messages.h"
+#include "opt_messages-ui.h"
+
+#include "common.h"
+#include "templates.h"
+#include "multilineinput.h"
+
+#include <qwhatsthis.h>
+#include <qcheckbox.h>
+#include <qgroupbox.h>
+#include <qtextedit.h>
+#include <qspinbox.h>
+#include <qpushbutton.h>
+#include <qregexp.h>
+
+//----------------------------------------------------------------------------
+// ListBoxFortune
+//----------------------------------------------------------------------------
+
+/*!
+	\class ListBoxFortune
+
+	ListBoxFortune is a QListBoxText descendent class used to display
+	multiline fortune text in a single line.
+	
+	Use setFortune()/getFortune() methods instead of setText()/getText().
+*/
+
+class ListBoxFortune : public QListBoxText
+{
+public:
+
+	/*!
+		Constructs a new fortune list item with \a aFortune fortune.
+	*/
+
+	ListBoxFortune(const QString &aFortune)
+		: QListBoxText(singleLine(aFortune)), fortune(aFortune) {
+	}
+
+	/*!
+		Changes fortune contained in this list item.
+		This method will also change item's text (used to draw this item)
+		with a single-line representation of the fortune, provided by
+		singleLine() method.
+	*/
+
+	void setFortune(const QString &f) {
+		fortune = f;
+		setText(singleLine(f));
+	}
+
+	/*!
+		Retrieves multi-line fortune stored in this item.
+	*/
+
+	QString getFortune() {
+		return fortune;
+	}
+
+protected:
+
+	/*!
+		Prepares fortune \a f to be displayed as a single-line list item
+		by replacing new line character with "\\" string
+		and tab character with a space.
+	*/
+
+	QString singleLine(const QString &f) {
+		QString sl = f;
+		sl.replace(QRegExp("\\n"), "\\");
+		sl.replace(QRegExp("\\t"), " ");
+		return sl;
+	}
+
+private:
+	QString fortune;
+};
+
+//----------------------------------------------------------------------------
+// FortunesListBox
+//----------------------------------------------------------------------------
+
+/*!
+	\class FortunesListBox opt_messages.h
+	\brief A list box class designed to represent fortunes.
+
+	FortunesListBox class is a QListBox derived class,
+	designed to manage a list of ListBoxFortune items.
+	
+	With this class you may display multi-line fortunes
+	using single-line items (new line characters are replaced by "\".
+*/
+
+/*!
+	Constructs a new fortunes list box with parent \a parent, name \a name
+	and flags \a f.
+*/
+
+FortunesListBox::FortunesListBox(QWidget* parent, const char* name, WFlags f)
+: QListBox(parent, name, f) {
+}
+
+/*!
+	Inserts \a fortune as a new fortune.
+*/
+
+void FortunesListBox::insertFortune(const QString &fortune) {
+	insertItem(new ListBoxFortune(fortune));
+}
+
+/*!
+	Changes fortune with is \a id.
+*/
+
+void FortunesListBox::updateFortune(const QString &fortune, int id) {
+	((ListBoxFortune*)item(id))->setFortune(fortune);
+	updateItem(id);
+}
+
+/*!
+	Retrieves fortune from item with id \a id.
+*/
+
+QString FortunesListBox::getFortune(int id) {
+	return ((ListBoxFortune*)item(id))->getFortune();
+}
+
+//----------------------------------------------------------------------------
+// QuoteHeaderPopup
+//----------------------------------------------------------------------------
+
+/*!
+	\class QuoteHeaderPopup
+
+	QuoteHeaderPopup is a class representing a popup menu with
+	template items which may be used in quote header template.
+*/
+
+class QuoteHeaderPopup : public TemplatePopup {
+	Q_OBJECT
+public:
+	QuoteHeaderPopup(QTextEdit *edt, QWidget *parent = 0, const char *name = 0)
+		: TemplatePopup(edt, parent, name)
+	{
+		insertTemplateItem(tr("Sender's bare jid"), "Sender.jid.bare");
+		insertTemplateItem(tr("Sender's full jid"), "Sender.jid.full");
+		insertTemplateItem(tr("Sender's nick"), "Sender.nick");
+		insertTemplateItem(tr("Sender's nick or jid"), "Sender.nick-jid");
+		insertSeparator();
+		insertTemplateItem(tr("Your bare jid"), "Me.jid.bare");
+		insertTemplateItem(tr("Your full jid"), "Me.jid.full");
+		insertTemplateItem(tr("Your nick"), "Me.nick");
+		insertTemplateItem(tr("Your nick or jid"), "Me.nick-jid");
+		insertSeparator();
+		insertTemplateItem(tr("Message date and time"), "Message.DateTime");
+		insertTemplateItem(tr("Message subject"), "Message.subject");
+		insertSeparator();
+		insertTemplateItem(tr("\'<\' character"), "");
+	}
+};
+
+//----------------------------------------------------------------------------
+// SignaturePopup
+//----------------------------------------------------------------------------
+
+/*!
+	\class SignaturePopup
+
+	SignaturePopup is a class representing a popup menu with
+	template items which may be used in signature template.
+*/
+
+class SignaturePopup : public TemplatePopup {
+	Q_OBJECT
+public:
+	SignaturePopup(QTextEdit *edt, QWidget *parent = 0, const char *name = 0)
+		: TemplatePopup(edt, parent, name)
+	{
+		insertTemplateItem(tr("Fortune"), "Fortune");
+		insertSeparator();
+		insertTemplateItem(tr("\'<\' character"), "");
+	}
+};
+
+//----------------------------------------------------------------------------
+// OptionsTabMessages
+//----------------------------------------------------------------------------
+
+OptionsTabMessages::OptionsTabMessages(QObject *parent)
+: OptionsTab(parent, "messages", "", tr("Messages"), tr("Advanced options for quoting and replying messages"), "psi/sendMessage")
+{
+	w = 0;
+	o = new Options;
+}
+
+OptionsTabMessages::~OptionsTabMessages()
+{
+	delete o;
+}
+
+QWidget *OptionsTabMessages::widget()
+{
+	if ( w )
+		return 0;
+
+	w = new OptMessagesUI();
+
+	OptMessagesUI *d = (OptMessagesUI *)w;
+	
+	// signature
+	QWhatsThis::add(d->ck_signature,
+		tr("Check this option if you want to include signature in messages that you send."));
+	QWhatsThis::add(d->pb_insSignature,
+		tr("Press this button if you want to add special symbols to your signature."));
+	QWhatsThis::add(d->te_signature,
+		tr("You may edit your signature here."));
+	QWhatsThis::add(d->ck_signatureAutoDelimiter,
+		tr("Check this option if you want Psi to automatically prepend your signature with"
+				" a signature delimiter ('-- ')."));
+
+	QWhatsThis::add(d->pb_fortuneNew,
+		tr("Press this button to create a new fortune."));
+	QWhatsThis::add(d->pb_fortuneDelete,
+		tr("Press this button to delete a fortune."));
+	QWhatsThis::add(d->lb_fortunes,
+		tr("Use this list to select a fortune"
+		" to view or edit in the box to the bottom."));
+	QWhatsThis::add(d->te_fortune,
+		tr("Here you may edit the fortune selected in the list above."));
+
+	// quote & reply
+	QWhatsThis::add(d->ck_headerQuote,
+		tr("Check this option if you want to include a header when quoting a message."));
+	QWhatsThis::add(d->pb_insQuote,
+		tr("Press this button if you want to add special symbols to your header."));
+	QWhatsThis::add(d->te_headerQuote,
+		tr("You may edit your header here."));
+
+	QWhatsThis::add(d->ck_headerReply,
+		tr("Check this option if you want to include a header when replying a message."));
+	QWhatsThis::add(d->pb_insReply,
+		tr("Press this button if you want to add special symbols to your header."));
+	QWhatsThis::add(d->te_headerReply,
+		tr("You may edit your header here."));
+
+	// forward
+	QWhatsThis::add(d->ck_headerForward,
+		tr("Check this option if you want to include a header when forwarding a message."));
+	QWhatsThis::add(d->pb_insForward,
+		tr("Press this button if you want to add special symbols to your header."));
+	QWhatsThis::add(d->te_headerForward,
+		tr("You may edit your header here."));
+
+	// misc
+	QWhatsThis::add(d->ck_quoteEmptyLines,
+		tr("Uncheck this option if you don't want empty lines to be"
+				" prepended with '>' character when quoting."));
+	QWhatsThis::add(d->ck_stripEmptyLines,
+		tr("Check this option if you want to remove empty lines at the beginning"
+				" and ending of a message when quoting it."));
+	QWhatsThis::add(d->ck_removeSignature,
+		tr("Check this option if you don't want to include sender's signature"
+				" in the quoted text."));
+	QWhatsThis::add(d->sb_wrapAtColumn,
+		tr("Here you may change the maximum length of a line in the quoted message."));
+
+	QWhatsThis::add(d->ck_hideQuoteBtn,
+		tr("Check this option if you want to have only 'Reply' button, instead of 'Quote'"
+				" and 'Reply'. In one-button mode, you may change 'Reply' button to work"
+				" as 'Quote' by changing your default way of replying."));
+	QWhatsThis::add(d->ck_defaultReplyWithoutQuoting,
+		tr("This option is used to determine your default way of replying a message."
+				" Default way of replying if used by Ctrl+R hotkey."
+				" In addition, this action is invoked by 'Reply' button when 'Quote' button is hidden."));
+
+	QWhatsThis::add(d->ck_hideChatBtn,
+		tr("Check this option to hide 'Chat' button."));
+	QWhatsThis::add(d->ck_showReplyInAuthRequests,
+		tr("Check this option if you want to have replying buttons in authorization request windows."));
+	QWhatsThis::add(d->ck_cursorAtTop,
+		tr("Check this option if you want cursor to be at the top of the edit."));
+
+
+	// don't worry: these menus are deleted in OptMessagesUI::destroy()
+	d->pb_insForward->setPopup(new QuoteHeaderPopup(d->te_headerForward));
+	d->pb_insReply->setPopup(new QuoteHeaderPopup(d->te_headerReply));
+	d->pb_insQuote->setPopup(new QuoteHeaderPopup(d->te_headerQuote));
+	d->pb_insSignature->setPopup(new SignaturePopup(d->te_signature));
+
+
+	// tags for header template
+	TemplateEditHighlighter::TagsVector headerTags;
+
+	headerTags.push_back("Sender.jid.bare");
+	headerTags.push_back("Sender.jid.full");
+	headerTags.push_back("Sender.nick");
+	headerTags.push_back("Sender.nick-jid");
+
+	headerTags.push_back("Me.jid.bare");
+	headerTags.push_back("Me.jid.full");
+	headerTags.push_back("Me.nick");
+	headerTags.push_back("Me.nick-jid");
+
+	headerTags.push_back("Message.DateTime");
+	headerTags.push_back("Message.subject");
+
+	headerTags.push_back("");
+
+	// tags for signature template
+	TemplateEditHighlighter::TagsVector signatureTags;
+
+	signatureTags.push_back("Fortune");
+	signatureTags.push_back("");
+
+	// syntax highlighters are deleted by edit boxes
+	new TemplateEditHighlighter(d->te_headerForward, headerTags);
+	new TemplateEditHighlighter(d->te_headerReply,   headerTags);
+	new TemplateEditHighlighter(d->te_headerQuote,   headerTags);
+	new TemplateEditHighlighter(d->te_signature,  signatureTags);
+
+	// fortunes editing
+	d->pb_fortuneNew->setEnabled(TRUE);
+	d->pb_fortuneDelete->setEnabled(FALSE);
+	d->te_fortune->setEnabled(FALSE);
+
+	connect(d->pb_fortuneNew, SIGNAL(clicked()), SLOT(newFortune()));
+	connect(d->pb_fortuneDelete, SIGNAL(clicked()), SLOT(removeFortune()));
+	connect(d->lb_fortunes, SIGNAL(highlighted(int)), SLOT(selectFortune(int)));
+	connect(d->te_fortune, SIGNAL(textChanged()), SLOT(changeFortune()));
+
+	return w;
+}
+
+void OptionsTabMessages::applyOptions(Options *opt)
+{
+	if ( !w )
+		return;
+
+	OptMessagesUI *d = (OptMessagesUI *)w;
+
+	opt->useQuoteHeaderForward = d->ck_headerForward->isChecked();
+	opt->quoteHeaderForward = d->te_headerForward->text();
+	opt->useQuoteHeaderQuote = d->ck_headerQuote->isChecked();
+	opt->quoteHeaderQuote = d->te_headerQuote->text();
+	opt->useQuoteHeaderReply = d->ck_headerReply->isChecked();
+	opt->quoteHeaderReply = d->te_headerReply->text();
+
+	opt->useMessageSignature = d->ck_signature->isChecked();
+	opt->messageSignature = d->te_signature->text();
+	opt->autoMessageSignatureDelimiter = d->ck_signatureAutoDelimiter->isChecked();
+
+	opt->fortunes = o->fortunes;
+
+	opt->wrapAtColumn = d->sb_wrapAtColumn->value();
+	opt->quoteEmptyLines = d->ck_quoteEmptyLines->isChecked();
+	opt->stripEmptyLines = d->ck_stripEmptyLines->isChecked();
+	opt->removeSignature = d->ck_removeSignature->isChecked();
+
+	opt->hideQuoteBtn = d->ck_hideQuoteBtn->isChecked();
+	opt->defaultReplyWithoutQuoting = d->ck_defaultReplyWithoutQuoting->isChecked();
+	opt->hideChatBtn = d->ck_hideChatBtn->isChecked();
+	opt->replyInAuthReq = d->ck_showReplyInAuthRequests->isChecked();
+
+	opt->cursorAtTopInEventDlg = d->ck_cursorAtTop->isChecked();
+}
+
+void OptionsTabMessages::restoreOptions(const Options *opt)
+{
+	if ( !w )
+		return;
+
+	OptMessagesUI *d = (OptMessagesUI *)w;
+
+	d->ck_headerForward->setChecked( true );
+	d->ck_headerForward->setChecked( opt->useQuoteHeaderForward );
+	d->te_headerForward->setText( opt->quoteHeaderForward );
+	d->ck_headerQuote->setChecked( true );
+	d->ck_headerQuote->setChecked( opt->useQuoteHeaderQuote );
+	d->te_headerQuote->setText( opt->quoteHeaderQuote );
+	d->ck_headerReply->setChecked( true );
+	d->ck_headerReply->setChecked( opt->useQuoteHeaderReply );
+	d->te_headerReply->setText( opt->quoteHeaderReply );
+
+	d->ck_signature->setChecked( true );
+	d->ck_signature->setChecked( opt->useMessageSignature );
+	d->te_signature->setText( opt->messageSignature );
+	d->ck_signatureAutoDelimiter->setChecked( opt->autoMessageSignatureDelimiter );
+
+	o->fortunes = opt->fortunes;
+	d->lb_fortunes->clear();
+	for ( QValueVector<QString>::ConstIterator it = o->fortunes.begin(); it != o->fortunes.end(); ++it ) {
+		d->lb_fortunes->insertFortune(*it);
+	}
+	if ( d->lb_fortunes->count() >= 1 )
+		d->lb_fortunes->setSelected(0, TRUE);
+
+	d->sb_wrapAtColumn->setValue( opt->wrapAtColumn );
+	d->ck_quoteEmptyLines->setChecked( opt->quoteEmptyLines );
+	d->ck_stripEmptyLines->setChecked( opt->stripEmptyLines );
+	d->ck_removeSignature->setChecked( opt->removeSignature );
+
+	d->ck_hideQuoteBtn->setChecked( opt->hideQuoteBtn );
+	d->ck_defaultReplyWithoutQuoting->setChecked( opt->defaultReplyWithoutQuoting );
+	d->ck_hideChatBtn->setChecked( opt->hideChatBtn );
+	d->ck_showReplyInAuthRequests->setChecked( opt->replyInAuthReq );
+	d->ck_cursorAtTop->setChecked( opt->cursorAtTopInEventDlg );
+}
+
+void OptionsTabMessages::setData(PsiCon *, QWidget *parentDialog)
+{
+	parentWidget = parentDialog;
+}
+
+void OptionsTabMessages::selectFortune(int x)
+{
+	OptMessagesUI *d = (OptMessagesUI *)w;
+
+	disconnect(d->te_fortune, SIGNAL(textChanged()), 0, 0);
+
+	if ( x == -1 ) {
+		d->pb_fortuneDelete->setEnabled(false);
+		d->te_fortune->setText("");
+		d->te_fortune->setEnabled(false);
+
+		connect(d->te_fortune, SIGNAL(textChanged()), SLOT(changeFortune()));
+		return;
+	}
+
+	d->pb_fortuneDelete->setEnabled(true);
+
+	d->te_fortune->setText(d->lb_fortunes->getFortune(x));
+	d->te_fortune->setEnabled(true);
+
+	connect(d->te_fortune, SIGNAL(textChanged()), SLOT(changeFortune()));
+}
+
+void OptionsTabMessages::newFortune()
+{
+	OptMessagesUI *d = (OptMessagesUI *)w;
+
+	QString text;
+
+	while(1) {
+		bool ok = FALSE;
+		text = MultiLineInputDialog::getMultiLineText(
+			CAP(tr("New Fortune")),
+			tr("Please enter the new fortune:"), true,
+			text, &ok, parentWidget);
+		if(!ok)
+			return;
+
+		if(text.isEmpty())
+			QMessageBox::information(parentWidget, tr("Error"), tr("Can't create a blank fortune!"));
+		else if(qFind(o->fortunes.begin(), o->fortunes.end(), text) != o->fortunes.end())
+			QMessageBox::information(parentWidget, tr("Error"), tr("This fortune already exists!"));
+		else
+			break;
+	}
+
+	o->fortunes.push_back(text);
+	d->lb_fortunes->insertFortune(text);
+	d->lb_fortunes->setSelected(d->lb_fortunes->count()-1, TRUE);
+	d->lb_fortunes->ensureCurrentVisible();
+
+	d->te_fortune->setFocus();
+
+	emit dataChanged();
+}
+
+void OptionsTabMessages::removeFortune()
+{
+	OptMessagesUI *d = (OptMessagesUI *)w;
+	int id = d->lb_fortunes->currentItem();
+	if(id == -1)
+		return;
+
+	emit dataChanged();
+
+	QValueVector<QString>::Iterator it = o->fortunes.begin();
+	for ( int i = 0; it != o->fortunes.end() && i != id; ++i, ++it)
+		;
+	o->fortunes.erase(it);
+
+	d->lb_fortunes->removeItem(id);
+
+	// select a new entry if possible
+	if(d->lb_fortunes->count() == 0) {
+		selectFortune(-1);
+		return;
+	}
+
+	if(id >= (int)d->lb_fortunes->count())
+		id = d->lb_fortunes->count()-1;
+
+	d->lb_fortunes->setSelected(id, TRUE);
+	selectFortune(id);
+}
+
+void OptionsTabMessages::changeFortune()
+{
+	OptMessagesUI *d = (OptMessagesUI *)w;
+	int id = d->lb_fortunes->currentItem();
+	if(id == -1)
+		return;
+
+	int para, index;
+	d->te_fortune->getCursorPosition(&para, &index);
+
+	const QString text = d->te_fortune->text();
+	o->fortunes[id] = text;
+	d->lb_fortunes->updateFortune(text, id);
+
+	d->te_fortune->setFocus();
+	d->te_fortune->setCursorPosition(para, index);
+
+	emit dataChanged();
+}
+
+#include "opt_messages.moc"
diff -X exclude -Naru psi_cvs-2005.05.17/psi/src/options/opt_messages.h psi/psi/src/options/opt_messages.h
--- psi_cvs-2005.05.17/psi/src/options/opt_messages.h	Thu Jan  1 01:00:00 1970
+++ psi/psi/src/options/opt_messages.h	Tue May 17 20:54:18 2005
@@ -0,0 +1,68 @@
+/*
+ * opt_messages.h - options tab for messages options
+ * Copyright (C) 2005  Maciej Niedzielski
+ *
+ * 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 library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef OPT_MESSAGES_H
+#define OPT_MESSAGES_H
+
+#include "optionstab.h"
+
+#include <qlistbox.h>
+
+class QWidget;
+
+class OptionsTabMessages: public OptionsTab
+{
+	Q_OBJECT
+public:
+	OptionsTabMessages(QObject *parent);
+	~OptionsTabMessages();
+
+	QWidget *widget();
+	void applyOptions(Options *opt);
+	void restoreOptions(const Options *opt);
+
+	void setData(PsiCon *, QWidget *parentDialog);
+
+private slots:
+	void selectFortune(int x);
+	void newFortune();
+	void removeFortune();
+	void changeFortune();
+
+private:
+	QWidget *w, *parentWidget;
+	Options *o;
+};
+
+
+// dynamic listbox of fortunes
+
+class FortunesListBox : public QListBox
+{
+	Q_OBJECT
+public:
+	FortunesListBox(QWidget* parent=0, const char* name=0, WFlags f=0);
+
+	void insertFortune(const QString &fortune);
+	void updateFortune(const QString &fortune, int id);
+	QString getFortune(int id);
+};
+
+#endif
diff -X exclude -Naru psi_cvs-2005.05.17/psi/src/options/options.pri psi/psi/src/options/options.pri
--- psi_cvs-2005.05.17/psi/src/options/options.pri	Thu Nov 27 14:09:12 2003
+++ psi/psi/src/options/options.pri	Tue May 17 20:54:18 2005
@@ -16,6 +16,7 @@
 	$$PSI_CPP/options/opt_application.h \
 	$$PSI_CPP/options/opt_chat.h \
 	$$PSI_CPP/options/opt_events.h \
+	$$PSI_CPP/options/opt_messages.h \
 	$$PSI_CPP/options/opt_status.h \
 	$$PSI_CPP/options/opt_appearance.h \
 	$$PSI_CPP/options/opt_lookfeel.h \
@@ -28,6 +29,7 @@
 	$$PSI_CPP/options/opt_application.cpp \
 	$$PSI_CPP/options/opt_chat.cpp \
 	$$PSI_CPP/options/opt_events.cpp \
+	$$PSI_CPP/options/opt_messages.cpp \
 	$$PSI_CPP/options/opt_status.cpp \
 	$$PSI_CPP/options/opt_appearance.cpp \
 	$$PSI_CPP/options/opt_lookfeel.cpp \
@@ -40,6 +42,7 @@
 	$$PSI_CPP/options/opt_application-ui.ui \
 	$$PSI_CPP/options/opt_chat-ui.ui \
 	$$PSI_CPP/options/opt_events-ui.ui \
+	$$PSI_CPP/options/opt_messages-ui.ui \
 	$$PSI_CPP/options/opt_status-ui.ui \
 	$$PSI_CPP/options/opt_appearance-ui.ui \
 	$$PSI_CPP/options/opt_sound-ui.ui \
diff -X exclude -Naru psi_cvs-2005.05.17/psi/src/options/optionsdlg.cpp psi/psi/src/options/optionsdlg.cpp
--- psi_cvs-2005.05.17/psi/src/options/optionsdlg.cpp	Sun May 15 22:26:44 2005
+++ psi/psi/src/options/optionsdlg.cpp	Tue May 17 20:54:18 2005
@@ -19,6 +19,7 @@
 #include "opt_appearance.h"
 #include "opt_chat.h"
 #include "opt_events.h"
+#include "opt_messages.h"
 #include "opt_status.h"
 #include "opt_iconset.h"
 #include "opt_groupchat.h"
@@ -306,6 +307,7 @@
 	tabs.append( new OptionsTabApplication(this) );
 	tabs.append( new OptionsTabChat(this) );
 	tabs.append( new OptionsTabEvents(this) );
+	tabs.append( new OptionsTabMessages(this) );
 	tabs.append( new OptionsTabStatus(this) );
 	tabs.append( new OptionsTabAppearance(this) );
 	//tabs.append( new OptionsTabIconsetSystem(this) );
diff -X exclude -Naru psi_cvs-2005.05.17/psi/src/psi_profiles.cpp psi/psi/src/psi_profiles.cpp
--- psi_cvs-2005.05.17/psi/src/psi_profiles.cpp	Sun May 15 22:26:44 2005
+++ psi/psi/src/psi_profiles.cpp	Tue May 17 20:54:18 2005
@@ -615,6 +615,30 @@
 	prefs.dtPort = 8010;
 	prefs.dtExternal = "";
 
+  	// machekku: smart forward and reply
+	prefs.quoteHeaderQuote		= QObject::tr("On <Message.DateTime>, <Sender.nick-jid> wrote:");
+  	prefs.quoteHeaderReply		= QObject::tr("In reply to your message from <Message.DateTime>:");
+  	prefs.quoteHeaderForward	= QObject::tr("On <Message.DateTime>, <Sender.nick-jid> wrote:");
+
+  	prefs.useQuoteHeaderQuote	= true;
+  	prefs.useQuoteHeaderReply	= false;
+  	prefs.useQuoteHeaderForward	= true;
+  
+  	prefs.messageSignature		= "";
+  	prefs.useMessageSignature	= false;
+  	prefs.autoMessageSignatureDelimiter	= true;
+   
+  	prefs.wrapAtColumn			= 60;
+  	prefs.quoteEmptyLines		= true;
+  	prefs.stripEmptyLines		= true;
+	prefs.removeSignature		= true;
+
+  	prefs.cursorAtTopInEventDlg	= false;
+	prefs.hideQuoteBtn			= false;
+	prefs.hideChatBtn			= false;
+	prefs.replyInAuthReq		= true;
+	prefs.defaultReplyWithoutQuoting	= true;
+
 	// Avatars
 	prefs.avatarsEnabled = true;
 	prefs.avatarsChatdlgEnabled = true;
@@ -925,6 +949,61 @@
 		}
 	}
 
+	{	// machekku: smart forward and reply
+		QDomElement p_messages = doc.createElement("messages");
+		p.appendChild(p_messages);
+
+		{
+			QDomElement p_quoteHeaders = doc.createElement("quoteHeaders");
+			p_messages.appendChild(p_quoteHeaders);
+
+			QDomElement headerQuote = textTag(doc, "quote", prefs.quoteHeaderQuote);
+			setBoolAttribute(headerQuote, "use", prefs.useQuoteHeaderQuote);
+			p_quoteHeaders.appendChild(headerQuote);
+
+			QDomElement headerReply = textTag(doc, "reply", prefs.quoteHeaderReply);
+			setBoolAttribute(headerReply, "use", prefs.useQuoteHeaderReply);
+			p_quoteHeaders.appendChild(headerReply);
+
+			QDomElement headerForward = textTag(doc, "forward", prefs.quoteHeaderForward);
+			setBoolAttribute(headerForward, "use", prefs.useQuoteHeaderForward);			
+			p_quoteHeaders.appendChild(headerForward);
+		}
+		{
+			QDomElement p_messageSignature = textTag(doc, "signature", prefs.messageSignature);
+			p_messages.appendChild(p_messageSignature);
+
+			setBoolAttribute(p_messageSignature, "use", prefs.useMessageSignature);
+			setBoolAttribute(p_messageSignature, "autoAddDelimiter", prefs.autoMessageSignatureDelimiter);
+		}
+		{
+			QDomElement p_fortunes = doc.createElement("fortunes");
+			p_messages.appendChild(p_fortunes);
+
+			for(QValueVector<QString>::ConstIterator it = prefs.fortunes.begin(); it != prefs.fortunes.end(); ++it)
+				p_fortunes.appendChild(textTag(doc, "item", *it));
+		}
+		{
+			QDomElement p_quote = doc.createElement("quote");
+			p_messages.appendChild(p_quote);
+
+			p_quote.appendChild(textTag(doc, "wrapAtColumn",	prefs.wrapAtColumn			));
+			p_quote.appendChild(textTag(doc, "quoteEmptyLines",	prefs.quoteEmptyLines		));
+			p_quote.appendChild(textTag(doc, "stripEmptyLines",	prefs.stripEmptyLines		));
+			p_quote.appendChild(textTag(doc, "removeSignature",	prefs.removeSignature		));
+		}
+		{
+			QDomElement p_misc = doc.createElement("misc");
+			p_messages.appendChild(p_misc);
+
+			p_misc.appendChild(textTag(doc, "cursorAtTop",		prefs.cursorAtTopInEventDlg	));
+			p_misc.appendChild(textTag(doc, "hideQuoteBtn",		prefs.hideQuoteBtn			));
+			p_misc.appendChild(textTag(doc, "hideChatBtn",		prefs.hideChatBtn			));
+			p_misc.appendChild(textTag(doc, "replyInAuthReq",	prefs.replyInAuthReq		));
+			p_misc.appendChild(textTag(doc, "defaultReplyWithoutQuoting",	prefs.defaultReplyWithoutQuoting	));
+		}
+	}
+
 	{
 		QDomElement p_sound = doc.createElement("sound");
 		p.appendChild(p_sound);
@@ -1469,6 +1548,79 @@
 				readEntry(tag, "message", &prefs.font[fMessage]);
 				readEntry(tag, "chat", &prefs.font[fChat]);
 				readEntry(tag, "popup", &prefs.font[fPopup]);
+			}
+		}
+
+		// machekku: smart forward and reply
+		QDomElement p_messages = findSubTag(p, "messages", &found);
+		if(found) {
+			bool found;
+
+			QDomElement p_quoteHeaders = findSubTag(p_messages, "quoteHeaders", &found);	
+			if(found) {
+				bool found;
+
+				QDomElement headerQuote = findSubTag(p_quoteHeaders, "quote", &found);
+				if(found) {
+					readBoolAttribute(headerQuote, "use", &prefs.useQuoteHeaderQuote);
+					prefs.quoteHeaderQuote = tagContent(headerQuote);
+				}
+
+				QDomElement headerReply = findSubTag(p_quoteHeaders, "reply", &found);
+				if(found) {
+					readBoolAttribute(headerReply, "use", &prefs.useQuoteHeaderReply);
+					prefs.quoteHeaderReply = tagContent(headerReply);
+				}
+
+				QDomElement headerForward = findSubTag(p_quoteHeaders, "forward", &found);
+				if(found) {
+					readBoolAttribute(headerForward, "use", &prefs.useQuoteHeaderForward);
+					prefs.quoteHeaderForward = tagContent(headerForward);
+				}
+			}
+
+			QDomElement p_messageSignature = findSubTag(p_messages, "signature", &found);
+			if(found) {
+				readBoolAttribute(p_messageSignature, "use", &prefs.useMessageSignature);
+				readBoolAttribute(p_messageSignature, "autoAddDelimiter", &prefs.autoMessageSignatureDelimiter);
+				prefs.messageSignature = tagContent(p_messageSignature);
+			}
+
+			QDomElement p_random = findSubTag(p_messages, "fortunes", &found);
+
+			// FIX-ME!
+			// This is to be backward compatible with previous versions of Smart Forward and Reply.
+			// When including into CVS, this should probably be removed.
+			if(!found) p_random = findSubTag(p_messages, "randomSignatures", &found);			
+
+			if(found) {
+				for(QDomNode n = p_random.firstChild(); !n.isNull(); n = n.nextSibling()) {
+					QDomElement i = n.toElement();
+					if(i.isNull())
+						continue;
+					if(i.tagName() == "item") {
+						QDomText t = i.firstChild().toText();
+						if(!t.isNull())
+							prefs.fortunes.push_back(t.data());
+					}
+				}					
+			}
+
+			QDomElement p_quote = findSubTag(p_messages, "quote", &found);
+			if(found) {
+				readNumEntry (p_quote, "wrapAtColumn",		&prefs.wrapAtColumn				);
+				readBoolEntry(p_quote, "quoteEmptyLines",	&prefs.quoteEmptyLines			);
+				readBoolEntry(p_quote, "stripEmptyLines",	&prefs.stripEmptyLines			);
+				readBoolEntry(p_quote, "removeSignature",	&prefs.removeSignature			);
+			}			
+
+			QDomElement p_misc = findSubTag(p_messages, "misc", &found);
+			if(found) {
+				readBoolEntry(p_misc, "cursorAtTop",		&prefs.cursorAtTopInEventDlg	);
+				readBoolEntry(p_misc, "hideQuoteBtn",		&prefs.hideQuoteBtn				);
+				readBoolEntry(p_misc, "hideChatBtn",		&prefs.hideChatBtn				);
+				readBoolEntry(p_misc, "replyInAuthReq",		&prefs.replyInAuthReq			);
+				readBoolEntry(p_misc, "defaultReplyWithoutQuoting",	&prefs.defaultReplyWithoutQuoting	);
 			}
 		}
 
diff -X exclude -Naru psi_cvs-2005.05.17/psi/src/psiaccount.cpp psi/psi/src/psiaccount.cpp
--- psi_cvs-2005.05.17/psi/src/psiaccount.cpp	Sun May 15 22:26:44 2005
+++ psi/psi/src/psiaccount.cpp	Tue May 17 20:54:18 2005
@@ -39,6 +39,8 @@
 #include<qca.h>
 #include<qfileinfo.h>
 
+#include<stdlib.h>
+
 #include"psicon.h"
 #include"profiles.h"
 #include"im.h"
@@ -77,6 +79,7 @@
 #include"filetransdlg.h"
 #include"avatars.h"
 #include"tabdlg.h"
+#include"templates.h"
 
 #if defined(Q_WS_MAC) && defined(HAVE_GROWL)
 #include "psigrowlnotifier.h"
@@ -2195,7 +2198,7 @@
 		w = new EventDlg(j, this, true);
 		connect(w, SIGNAL(aReadNext(const Jid &)), SLOT(processReadNext(const Jid &)));
 		connect(w, SIGNAL(aChat(const Jid &)), SLOT(actionOpenChat(const Jid&)));
-		connect(w, SIGNAL(aReply(const Jid &, const QString &, const QString &, const QString &)), SLOT(dj_composeMessage(const Jid &, const QString &, const QString &, const QString &)));
+		connect(w, SIGNAL(aCompose(const Jid &, const QString &, const QString &, const QString &, ComposeType, const Jid &, const Jid &, const QDateTime &, const UrlList &)), SLOT(dj_composeMessage(const Jid &, const QString &, const QString &, const QString &, ComposeType, const Jid &, const Jid &, const QDateTime &, const UrlList &)));
 		connect(w, SIGNAL(aAuth(const Jid &)), SLOT(dj_addAuth(const Jid &)));
 		connect(w, SIGNAL(aDeny(const Jid &)), SLOT(dj_deny(const Jid &)));
 		connect(d->psi, SIGNAL(emitOptionsUpdate()), w, SLOT(optionsUpdate()));
@@ -2339,6 +2342,10 @@
 void PsiAccount::actionSendMessage(const Jid &j)
 {
 	EventDlg *w = d->psi->createEventDlg(j.full(), this);
+
+	if(option.useMessageSignature)
+		w->setText(expandSignatureTemplate(option.messageSignature, option.autoMessageSignatureDelimiter), option.cursorAtTopInEventDlg);
+
 	w->show();
 }
 
@@ -2355,6 +2362,10 @@
 	}
 
 	EventDlg *w = d->psi->createEventDlg(str, this);
+
+	if(option.useMessageSignature)
+		w->setText(expandSignatureTemplate(option.messageSignature, option.autoMessageSignatureDelimiter), option.cursorAtTopInEventDlg);
+
 	w->show();
 }
 
@@ -2362,6 +2373,10 @@
 {
 	EventDlg *w = d->psi->createEventDlg(j.full(), this);
 	w->setUrlOnShow();
+
+	if(option.useMessageSignature)
+		w->setText(expandSignatureTemplate(option.messageSignature, option.autoMessageSignatureDelimiter), option.cursorAtTopInEventDlg);
+
 	w->show();
 }
 
@@ -2419,7 +2434,7 @@
 {
 	EventDlg *w = new EventDlg(e->from(), this, false);
 	connect(w, SIGNAL(aChat(const Jid &)), SLOT(actionOpenChat(const Jid&)));
-	connect(w, SIGNAL(aReply(const Jid &, const QString &, const QString &, const QString &)), SLOT(dj_composeMessage(const Jid &, const QString &, const QString &, const QString &)));
+	connect(w, SIGNAL(aCompose(const Jid &, const QString &, const QString &, const QString &, ComposeType, const Jid &, const Jid &,const QDateTime &, const UrlList &)), SLOT(dj_composeMessage(const Jid &, const QString &, const QString &, const QString &, ComposeType, const Jid &, const Jid &,const QDateTime &, const UrlList &)));
 	connect(w, SIGNAL(aAuth(const Jid &)), SLOT(dj_addAuth(const Jid &)));
 	connect(w, SIGNAL(aDeny(const Jid &)), SLOT(dj_deny(const Jid &)));
 	connect(d->psi, SIGNAL(emitOptionsUpdate()), w, SLOT(optionsUpdate()));
@@ -2666,26 +2681,211 @@
 	}
 }
 
-void PsiAccount::dj_composeMessage(const Jid &jid, const QString &body, const QString &subject, const QString &thread)
+// machekku: smart forward and reply
+
+/*!
+	Expands quote header template \a headerTemplate for a message with
+	subject \a subject, sender's JID \a jidSender, user's JID \a jidMe,
+	sent on \a originalMessageTime.
+*/
+
+QString PsiAccount::expandQuoteHeadlineTemplate(const Template &headerTemplate,
+					const QString &subject, const Jid &jidSender,
+					const Jid &jidMe, const QDateTime &originalMessageTime)
 {
+	QString header;
+
+	if ( !headerTemplate.isEmpty() ) {
+
+		QPtrList<UserListItem> ul = findRelavent(jidSender);
+		UserListItem *uSender = 0;
+		if(!ul.isEmpty()) uSender = ul.first();
+
+		ul = findRelavent(jidMe);
+		UserListItem *uMe = 0;
+		if(!ul.isEmpty()) uMe = ul.first();
+
+		Template::ExpandData values;
+
+		values["Message.DateTime"] = originalMessageTime.toString(LocalDate);
+		values["Message.subject"]  = subject;
+
+		values["Sender.jid.full"] = jidSender.full();
+		values["Sender.jid.bare"] = jidSender.bare();
+		values["Sender.nick"]     = (uSender)? uSender->name() : "";
+		values["Sender.nick-jid"] = jidnick(jidSender.bare(), (uSender)? uSender->name() : "");
+
+		values["Me.jid.full"] = jidMe.resource().isEmpty()? jidMe.full() + "/" + d->client->resource() : jidMe.full();
+		values["Me.jid.bare"] = jidMe.bare();
+		values["Me.nick"]     = (uMe)? uMe->name() : "";;
+		values["Me.nick-jid"] = jidnick(jidMe.bare(), (uMe)? uMe->name() : "");
+
+		header = headerTemplate.expand(values);
+	}
+
+	return header;
+}
+
+/*!
+	Expands signature template \a signatureTemplate.
+
+	If \a ensureDelimiter is true and signature template does not start with
+	signature delimiter ("-- \n"), it will be added at the beginning of expanded string.
+
+	If \a signatureForNewMessage is true, this method will make sure that
+	there will be two empty lines before the real signature starts.
+*/
+
+QString PsiAccount::expandSignatureTemplate(const Template &signatureTemplate, bool ensureDelimiter, bool signatureForNewMessage /* = TRUE */)
+{
+	QString signature;
+
+	if ( !signatureTemplate.isEmpty() ) {
+
+		Template::ExpandData values;
+		
+		values["fortune"] = (option.fortunes.count())? option.fortunes[rand()%option.fortunes.count()] : "";
+
+		signature = signatureTemplate.expand(values);
+
+		// add delimiter
+		if(ensureDelimiter && !signature.startsWith("-- \n"))
+			signature = "-- \n" + signature;
+
+		if(signatureForNewMessage && !signature.startsWith("\n\n")) {	// new message - two empty lines before sig
+			if (signature[0]=='\n')
+				signature = "\n" + signature;
+			else
+				signature = "\n\n" + signature;
+		}
+	}
+
+	return signature;
+}
+
+/*!
+	Composes a message to \a jid with body \a body, subject \a subject and thread \a thread.
+
+	If compose type \ct is ctNew (new message is being created), rest of the arguments is ignored.
+	In other case \a originalJid_Sender is sender of the original message and
+	\a originalJid_Sender is receiver of the original message, which was sent on
+	\a originalMessageTime and contained \a originalMessageAttachements attachements.
+*/
+
+void PsiAccount::dj_composeMessage(const Jid &jid, const QString &body, const QString &subject, const QString &thread,
+								   ComposeType ct, const Jid &originalJid_Sender, const Jid &originalJid_Me,
+								   const QDateTime &originalMessageTime, const UrlList &originalMessageAttachements)
+{
+
 	EventDlg *w = d->psi->createEventDlg(jid.full(), this);
-	if(!body.isEmpty())
-		w->setText(qstrquote(body));
 
-	if(!subject.isEmpty() && subject.left(3) != "Re:")
-		w->setSubject("Re: " + subject);
-	else if (subject.left(3) == "Re:")
-		w->setSubject(subject);
+	// header
+	QString headerTemplate = "";
+
+	if ( ct == ctQuote && option.useQuoteHeaderQuote ) {
+		headerTemplate = option.quoteHeaderQuote;
+	}
+	else if ( ct == ctReply && option.useQuoteHeaderReply ) {
+		headerTemplate = option.quoteHeaderReply;
+	}
+	else if ( ct == ctForward && option.useQuoteHeaderForward ) {
+		headerTemplate = option.quoteHeaderForward;
+	}
+	QString header = expandQuoteHeadlineTemplate(headerTemplate, subject, originalJid_Sender, originalJid_Me, originalMessageTime);
+
+	// body
+	QString messageBody = "";
+	if ( ct == ctNew ) {
+		messageBody = body;
+	}
+	else if ( ct != ctReply ) {	// ctReply -> empty body
+		messageBody = qstrquote(body, option.wrapAtColumn, option.quoteEmptyLines, option.stripEmptyLines, option.removeSignature);
+	}
+
+	// header/body separator
+	//		we want to have one '\n' between header and body
+	QString sepBody = "";
+	if (!header.isEmpty() && !messageBody.isEmpty() && !header.endsWith("\n") && !messageBody.startsWith("\n"))
+		sepBody = "\n";
+
+	// signature
+	QString signature = (option.useMessageSignature)? expandSignatureTemplate(option.messageSignature, option.autoMessageSignatureDelimiter,FALSE) : "";
+
+	// body/signature separator
+	//		we want to have one empty line between body and signature (at least two '\n');
+	//		or, when body is empty, an empty line between header and signature
+	QString sepSig = "";
+	const QString &separated = (messageBody.isEmpty())? header : messageBody;
 
-	if(!thread.isEmpty())
+	if (!signature.isEmpty()) {
+		int nNewLines = 0;
+
+		if ( separated.endsWith("\n\n") )
+			nNewLines = 2;
+		else if ( separated.endsWith("\n") )
+			nNewLines = 1;
+		if ( signature.startsWith("\n\n") )
+			nNewLines += 2;
+		else if ( signature.startsWith("\n") )
+			++nNewLines;
+
+		if ( nNewLines == 1 )
+			sepSig = "\n";
+		else if ( nNewLines == 0 )
+			sepSig = "\n\n";
+	}
+
+	// message text is ready
+	w->setText(header + sepBody + messageBody + sepSig + signature, option.cursorAtTopInEventDlg);
+
+	// subject
+	QString prefix;
+	if ( ct == ctForward ) {
+		prefix = "Fw:";
+	}
+	else if ( ct == ctReply || ct == ctQuote ) {
+		prefix = "Re:";
+	}
+
+	if (!prefix.isEmpty()) {
+		const int pl = prefix.length();
+		if(!subject.isEmpty() && subject.left(pl) != prefix)
+			w->setSubject(prefix + " " + subject);
+		else if (subject.left(pl) == prefix)
+			w->setSubject(subject);
+	}
+	
+	// thread - copy thread only for reply/quote, not for forward
+	if(!thread.isEmpty() && (ct == ctReply || ct == ctQuote))
 		w->setThread(thread);
 
+	// attachements - copy when forwarding
+	if (ct == ctForward) {
+		for(QValueList<Url>::ConstIterator it = originalMessageAttachements.begin(); it != originalMessageAttachements.end(); ++it) {
+			const Url &u = *it;
+			w->addAttachement(u.url(), u.desc());
+		}
+	}
+
 	w->show();
 }
 
+void PsiAccount::dj_composeMessage(const Jid &jid, const QString &body, const QString &subject, const QString &thread)
+{
+	Jid jDummy;
+	QDateTime qdtDummy;
+	UrlList ulDummy;
+	dj_composeMessage(jid, body, subject, thread, ctQuote , jDummy, jDummy, qdtDummy, ulDummy);
+}
+
 void PsiAccount::dj_composeMessage(const Jid &j, const QString &body)
 {
-	dj_composeMessage(j, body, QString::null, QString::null);
+	Jid jDummy;
+	QDateTime qdtDummy;
+	UrlList ulDummy;
+	dj_composeMessage(j, body, QString::null, QString::null,
+		ctNew, jDummy, jDummy, qdtDummy, ulDummy);
+
 }
 
 void PsiAccount::dj_addAuth(const Jid &j)
diff -X exclude -Naru psi_cvs-2005.05.17/psi/src/psiaccount.h psi/psi/src/psiaccount.h
--- psi_cvs-2005.05.17/psi/src/psiaccount.h	Sun May 15 22:26:44 2005
+++ psi/psi/src/psiaccount.h	Tue May 17 22:17:30 2005
@@ -230,6 +230,10 @@
 	void dj_sendMessage(const Message &, bool log=true);
 	void dj_composeMessage(const Jid &jid, const QString &body);
 	void dj_composeMessage(const Jid &jid, const QString &body, const QString &subject, const QString &thread);
+	// machekku: smart forward and reply
+	void dj_composeMessage(const Jid &jid, const QString &body, const QString &subject, const QString &thread,
+								   ComposeType ct, const Jid &originalJid_Sender, const Jid &originalJid_Me,
+								   const QDateTime &originalMessageTime, const UrlList &originalMessageAttachements);
 	void dj_addAuth(const Jid &);
 	void dj_add(const Jid &, const QString &, const QStringList &, bool authReq);
 	void dj_authReq(const Jid &);
@@ -237,7 +241,6 @@
 	void dj_deny(const Jid &);
 	void dj_rename(const Jid &, const QString &);
 	void dj_remove(const Jid &);
-
 	void actionDefault(const Jid &);
 	void actionRecvEvent(const Jid &);
 	void actionSendMessage(const Jid &);
@@ -361,11 +364,16 @@
 	void promptPassphrase();
 	void processChats(const Jid &);
 	void openChat(const Jid &);
+
 	EventDlg *ensureEventDlg(const Jid &);
 	friend class PsiCon;
 
 	bool isDisconnecting, notifyOnlineOk, doReconnect, usingAutoStatus, rosterDone, presenceSent, v_isActive;
 	void cleanupStream();
+	
+ 	QString expandQuoteHeadlineTemplate(const Template &headerTemplate,
+				const QString &subject, const Jid &jidSender, const Jid &jidMe, const QDateTime &originalMessageTime);
+ 	QString expandSignatureTemplate(const Template &signatureTemplate, bool ensureDelimiter, bool signatureForNewMessage = TRUE);
 
 	friend class Private;
 };
diff -X exclude -Naru psi_cvs-2005.05.17/psi/src/psicon.cpp psi/psi/src/psicon.cpp
--- psi_cvs-2005.05.17/psi/src/psicon.cpp	Sun May 15 22:26:44 2005
+++ psi/psi/src/psicon.cpp	Tue May 17 20:54:18 2005
@@ -728,6 +728,10 @@
 		return;
 
 	EventDlg *w = createEventDlg("", pa);
+
+	if(option.useMessageSignature)
+		w->setText(pa->expandSignatureTemplate(option.messageSignature, option.autoMessageSignatureDelimiter), option.cursorAtTopInEventDlg);
+
 	w->show();
 }
 
diff -X exclude -Naru psi_cvs-2005.05.17/psi/src/tools/multilineinput/multilineinput.cpp psi/psi/src/tools/multilineinput/multilineinput.cpp
--- psi_cvs-2005.05.17/psi/src/tools/multilineinput/multilineinput.cpp	Thu Jan  1 01:00:00 1970
+++ psi/psi/src/tools/multilineinput/multilineinput.cpp	Tue May 17 20:54:20 2005
@@ -0,0 +1,162 @@
+/*
+ * multilineinput.h - simple dialog to get MultiLine text from user
+ * Copyright (C) 2005  Maciej Niedzielski
+ *
+ * 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 library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "multilineinput.h"
+
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qpushbutton.h>
+#include <qtextedit.h>
+
+/*
+	Multiline edit control for MultiLineInputDialog class,
+	introduced to control hotkeys.
+*/
+
+class MultiLineInputDialog::Mle : public QTextEdit {
+public:
+	Mle(QWidget *parent) : QTextEdit(parent) {}
+
+	void keyPressEvent(QKeyEvent *e) {
+		if(e->key() == Key_Return && ((e->state() & ControlButton) || (e->state() & AltButton)) )
+			e->ignore();
+		else
+			QTextEdit::keyPressEvent(e);
+	}
+};
+
+
+/*!
+	\class MultiLineInputDialog multilineinput.h
+	\brief The MultiLineInputDialog class provides a simple dialog to get a multiline string from the user.
+
+	\mainclass
+
+	MultiLineInputDialog class is a QInputDialog like class, providing a way to get a multiline string from the user.
+
+	\code
+	bool ok;
+	QString text = MultiLineInputDialog::getMultiLineText(
+			"New Fortune", "Please enter the new fortune:", true,
+			QString::null, &ok, this);
+
+	if ( ok && !text.isEmpty() ) {
+		// user entered something and pressed OK
+	} else {
+		// user entered nothing or pressed Cancel
+	}
+	\endcode
+
+	Pressing Ctrl+Tab will always input tab into the edit field.
+	Ctrl+Enter or Alt+Enter will invoke Ok.
+
+	\sa QInputDialog
+*/
+
+/*!
+	Constructs the dialog. The \a caption is the text in dialog's caption,
+	the \a label test is information for user what they are expected to enter.
+	The \a parent is the dialog's parent widget. The widget is called \a name. If \a
+	modal is TRUE (the default) the dialog will be modal.
+
+	\sa getMultiLineText()
+*/
+
+MultiLineInputDialog::MultiLineInputDialog(const QString &caption, const QString &label, bool tabChangesFocus,
+					const QString &text, QWidget *parent, const char *name, bool modal, WFlags f)
+	: QDialog (parent, name, modal, f) {
+
+	setCaption(caption);
+
+	QVBoxLayout *vbox = new QVBoxLayout(this, 3);
+	vbox->addWidget(new QLabel(label, this));
+
+	mle = new Mle(this);
+	mle->setText(text);
+	mle->setTabChangesFocus(tabChangesFocus);
+
+	vbox->addWidget(mle);
+
+	QHBoxLayout *hbox = new QHBoxLayout(6);
+	vbox->addLayout(hbox, AlignRight);
+
+	QPushButton *ok = new QPushButton(tr("OK"), this, "qt_ok_btn" );
+	ok->setDefault(TRUE);
+	QPushButton *cancel = new QPushButton(tr("Cancel"), this, "qt_cancel_btn" );
+
+	QSize bs = ok->sizeHint().expandedTo(cancel->sizeHint());
+	ok->setFixedSize(bs);
+	cancel->setFixedSize(bs);
+
+	hbox->addStretch();
+	hbox->addWidget(ok);
+	hbox->addWidget(cancel);
+
+	connect( ok, SIGNAL( clicked() ), this, SLOT( accept() ) );
+	connect( cancel, SIGNAL( clicked() ), this,SLOT( reject() ) );
+
+	QSize sh = sizeHint().expandedTo(QSize(400, 10));
+	resize(sh.width(),vbox->heightForWidth(sh.width()));
+}
+
+/*!
+	Static function to input multiline text from user.
+
+	The \a caption is the text in dialog's caption,
+	the \a label test is information for user what they are expected to enter.
+	The \a parent is the dialog's parent widget. The widget is called \a name. If \a
+	tabChangesFocus is TRUE, pressing Tab key while edit area is focused will change focused
+	widget - otherwise it will input tab character.
+*/
+
+QString MultiLineInputDialog::getMultiLineText(const QString &caption, const QString &label, bool tabChangesFocus,
+							const QString &text, bool *ok, QWidget *parent, const char *name) {
+
+	MultiLineInputDialog *dlg = new MultiLineInputDialog(caption, label, tabChangesFocus, text, parent,
+		name? name : "input_MultiLine_text_dlg", TRUE);
+	QString result;
+
+	bool isOk = ( dlg->exec() == QDialog::Accepted );
+
+	if ( ok ) {
+		*ok = isOk;
+	}
+
+	if ( isOk ) {
+		result = dlg->mle->text();
+	}
+
+	delete dlg;
+	return result;
+}
+
+/*!
+	Keyboard events filter to enable desired hotkeys.
+*/
+    
+void MultiLineInputDialog::keyPressEvent(QKeyEvent *e)
+{
+	if ( e->key() == Key_Tab && e->state() & ControlButton )
+		mle->insert("\t");
+	else if ( e->key() == Key_Return && ((e->state() & ControlButton) || (e->state() & AltButton)) )
+		accept();		
+	else
+		e->ignore();		
+}
diff -X exclude -Naru psi_cvs-2005.05.17/psi/src/tools/multilineinput/multilineinput.h psi/psi/src/tools/multilineinput/multilineinput.h
--- psi_cvs-2005.05.17/psi/src/tools/multilineinput/multilineinput.h	Thu Jan  1 01:00:00 1970
+++ psi/psi/src/tools/multilineinput/multilineinput.h	Tue May 17 20:54:20 2005
@@ -0,0 +1,36 @@
+/*
+ * multilineinput.h - simple dialog to get multiline text from user
+ * Copyright (C) 2005  Maciej Niedzielski
+ *
+ * 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 library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <qdialog.h>
+
+class MultiLineInputDialog : public QDialog
+{   	
+public:
+	static QString getMultiLineText(const QString &caption, const QString &label, bool tabChangesFocus,
+							const QString &text, bool *ok=0, QWidget *parent=0, const char *name=0);
+protected:
+	void keyPressEvent(QKeyEvent *);
+
+private:
+	class Mle;
+	Mle *mle;
+	MultiLineInputDialog(const QString &caption, const QString &label, bool tabChangesFocus,
+					const QString &text, QWidget *parent=0, const char *name=0, bool modal=FALSE, WFlags f=0);
+};
diff -X exclude -Naru psi_cvs-2005.05.17/psi/src/tools/multilineinput/multilineinput.pri psi/psi/src/tools/multilineinput/multilineinput.pri
--- psi_cvs-2005.05.17/psi/src/tools/multilineinput/multilineinput.pri	Thu Jan  1 01:00:00 1970
+++ psi/psi/src/tools/multilineinput/multilineinput.pri	Tue May 17 20:54:20 2005
@@ -0,0 +1,4 @@
+multilineinput {
+	HEADERS += $$MULTILINEINPUT_CPP/multilineinput.h
+	SOURCES += $$MULTILINEINPUT_CPP/multilineinput.cpp
+}
diff -X exclude -Naru psi_cvs-2005.05.17/psi/src/tools/templates/templates.cpp psi/psi/src/tools/templates/templates.cpp
--- psi_cvs-2005.05.17/psi/src/tools/templates/templates.cpp	Thu Jan  1 01:00:00 1970
+++ psi/psi/src/tools/templates/templates.cpp	Tue May 17 20:54:18 2005
@@ -0,0 +1,277 @@
+/*
+ * templates.cpp - set of utils to make editing templates easier
+ * Copyright (C) 2005  Maciej Niedzielski
+ *
+ * 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 library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "templates.h"
+
+#include <qtextedit.h>
+#include <qmap.h>
+#include <qregexp.h>
+
+//----------------------------------------------------------------------------
+// TemplatePopup
+//----------------------------------------------------------------------------
+
+/*!
+	\class TemplatePopup templates.h
+	\brief The TemplatePopup provides a convenient class to create a popup menu for template edition.
+
+	TemplatePopup is a specialised QPopupMenu designed to be used when
+	editing templates in an edit box.
+
+	insertTemplateItem() function is used to add new menu item which will automatically
+	insert an <item> into the template's edit box.
+*/
+
+class TemplatePopup::Private {
+public:
+	QTextEdit *edit;
+	QMap<int, QString> tags;
+};
+
+/*!
+	Constructs a menu called \a name with parent \a parent.
+	The menu will be associated with \a edit edit box - the items
+	will be inserted into this widget.
+*/
+
+TemplatePopup::TemplatePopup(QTextEdit *edit, QWidget *parent, const char *name)
+	: QPopupMenu(parent, name)
+{
+	d = new Private;
+	d->edit = edit;
+	connect(this, SIGNAL(activated(int)), this, SLOT(onActivated(int)));	
+}
+
+/*!
+	Destroys the popup menu.
+*/
+
+TemplatePopup::~TemplatePopup()
+{
+	delete d;
+	d = 0;
+}
+
+/*!
+	Inserts new menuitem representing a template tag.
+	The item will be displayed as \a text and will insert \a tag tag.
+*/
+int TemplatePopup::insertTemplateItem(const QString &text, const QString &tag, const QString &/*desc*/ /* ="" */)
+{
+	int id = insertItem(text);
+	//setWhatsThis(id, "<b><i>" + tag + "</i></b><br>" + ((desc!="")?desc:name));
+	d->tags[id] = tag;
+
+	return id;
+}
+
+/*!
+	Internal slot inserting template tags when a menuitem is choosen.
+*/
+
+void TemplatePopup::onActivated(int id)
+{
+	if ( d->edit && d->tags.contains(id) ) {
+		d->edit->insert("<" + d->tags[id] + ">");
+		d->edit->setFocus();
+	}
+}       
+
+//----------------------------------------------------------------------------
+// TemplateEditHighlighter
+//----------------------------------------------------------------------------
+
+
+/*!
+	\class TemplateEditHighlighter templates.h
+	\brief The TemplateEditHighlighter provides a highlighter class for template edit boxes.
+
+	TemplateEditHighlighter a specialised QSyntaxHighlighter designed to be used when
+	editing templates in an edit box.
+*/
+
+/*!
+	Constructs a syntax highlighter for \a edit edit box,
+	which will highlight all tahs listed in \a template tags vector.
+*/
+
+TemplateEditHighlighter::TemplateEditHighlighter(QTextEdit *edit, TagsVector templateTags)
+	: QSyntaxHighlighter(edit), tags(templateTags)
+{
+}
+
+/*!
+	Formats a paragraph contained in \a text, highlighting all tags.
+	\a endStateOfLastPara is ignored.
+*/
+
+int TemplateEditHighlighter::highlightParagraph(const QString & text, int /*endStateOfLastPara*/)
+{
+	setFormat(0, text.length(), textEdit()->colorGroup().text());
+
+	for ( int ver = 0; ver <= 1; ++ver ) {
+
+		// every stick has two ends: beginning and ending
+		// every tag has two versions: with and without '!'
+		const QString tagStart = (ver)? "<" : "<!";
+
+		for ( unsigned i = 0; i < tags.size(); ++i ) {
+			int first = 0;
+			int start = -1;
+
+			const QString tag = tagStart + tags[i] + ">";
+			const int len = tag.length();
+
+			while ( (start = text.find(tag, first, false)) != -1 ) {
+				setFormat(start, len, textEdit()->colorGroup().link());
+				// color of a link - it suggests something 'special' ;-)
+				// (and has good contrast)
+
+				first = start + len + 1;
+			}
+		}
+	}
+
+	return 0;
+}
+
+//----------------------------------------------------------------------------
+// Template
+//----------------------------------------------------------------------------
+
+/*!
+	\class Template templates.h
+	\brief The Template is an extension of QString which makes working with templates easier.
+
+	Template is a specialised QString representing a template.
+	
+	A template is a string with special parts (template items) written inside <> brackets.
+	Items may be filled by providing a list of values in the Template::ExpandData object
+	to expand() method.
+
+	\code
+
+	Template t = "Hello <name>! You just won <item>?";
+	Template::ExpandData data;
+	data["name"] = "John";
+	data["item"] = "a pen";
+	QString s = t.expand(data);	// s is now "Hello John! You just won <item>?";
+
+	\endcode
+
+	In addition, every template <item> has a corresponding <!item> version.
+	If information provided for such item is a not-empty string, it will be prepended by new line character.
+
+	\code
+
+	Template t = "<title><subtitle>";
+
+	Template::ExpandData book1;
+	book1["title"] = "Blue dot";
+	book1["subtitle"] = "";
+
+	QString title1 = t.expand(book1);	// title1 is now "Blue dot";
+
+	Template::ExpandData book2;
+	book2["title"] = "The God Particle";
+	book2["subtitle"] = "If the Universe Is the Answer, What Is the Question?";
+
+	QString title2 = t.expand(book2);	// title2 is now "The God Particle\nIf the Universe Is the Answer, What Is the Question?";
+
+	\endcode
+*/
+
+
+/*!
+	\function Template()
+	
+	Constructs a new empty template.
+*/
+
+/*!
+	\function Template(const QString &s)
+	
+	Constructs a new template basing on \a s string.
+*/
+
+/*!
+	\function Template(const Template &t)
+
+	Constructs a new template basing on \a t template.
+*/
+
+/*!
+	\function Template(const char *str)
+
+	Constructs a new template basing on \a str string.
+*/
+
+
+/*!
+	Expands a template using \a values data.
+
+	If \a values does not contain a value for a template item, the item is left unchanged
+	in the output.
+	Otherwise, "<item>" is replaced by a corresponding value
+	and "<!item>" is either replaced by the value prepended with '\n' or with empty string if
+	the value is empty.
+
+	ExpandData type is defined as:
+	typedef QMap<QString, QString> ExpandData;
+	
+	Note that if there was no value provided for an item, it is left unchanged.
+	The return type of this method is Template, so it may be easily expanded further
+	with another \a values.
+*/
+
+Template Template::expand(const Template::ExpandData &values) const
+{
+	Template res = *this;
+
+	QRegExp repl;
+	repl.setCaseSensitive(FALSE);
+
+	QString ins;
+
+	for ( ExpandData::ConstIterator it = values.begin(); it != values.end(); ++it ) {
+
+		ins = it.data();
+		repl.setPattern("<" + it.key() + ">");
+		res.replace(repl, ins);
+
+		// every tag has <!tag> version, which adds new line before the value
+
+		if( !ins.isEmpty() ) {
+			repl.setPattern("<!" + it.key() + ">");
+			res.replace(repl, QString("\n") + ins);
+		}
+	}
+
+	// "<>" is a safe way to write "<" inside the template
+
+	ins = "<";
+	repl.setPattern("<>");
+	res.replace(repl, ins);
+
+	return res;
+}
+
+
+#include "moc_templates.cpp"
diff -X exclude -Naru psi_cvs-2005.05.17/psi/src/tools/templates/templates.h psi/psi/src/tools/templates/templates.h
--- psi_cvs-2005.05.17/psi/src/tools/templates/templates.h	Thu Jan  1 01:00:00 1970
+++ psi/psi/src/tools/templates/templates.h	Tue May 17 20:54:20 2005
@@ -0,0 +1,86 @@
+/*
+ * templates.h - set of utils to make editing templates easier
+ * Copyright (C) 2005  Maciej Niedzielski
+ *
+ * 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 library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef TEMPLATES_UTILS_H
+#define TEMPLATES_UTILS_H
+
+#include <qpopupmenu.h>
+#include <qsyntaxhighlighter.h>
+#include <qvaluevector.h>
+#include <qmap.h>
+
+class QTextEdit;
+
+//----------------------------------------------------------------------------
+// TemplatePopup
+//----------------------------------------------------------------------------
+
+// popup menu containing template tags
+
+class TemplatePopup : public QPopupMenu {
+	Q_OBJECT
+public:
+	TemplatePopup(QTextEdit *edt, QWidget * parent = 0, const char * name = 0);
+	~TemplatePopup();
+
+	int insertTemplateItem(const QString &name, const QString &tag, const QString &desc="");
+private:
+	class Private;
+	Private *d;
+private slots:
+	void onActivated(int id);
+};
+
+//----------------------------------------------------------------------------
+// TemplateEditHighlighter
+//----------------------------------------------------------------------------
+
+// text highlighter highlighting template tags
+
+class TemplateEditHighlighter : public QSyntaxHighlighter {
+public:
+
+	typedef QValueVector<QString> TagsVector;
+
+	TemplateEditHighlighter(QTextEdit *edt, TagsVector templateTags);
+	int highlightParagraph(const QString & text, int endStateOfLastPara);
+private:
+	TagsVector tags;
+};
+
+//----------------------------------------------------------------------------
+// Template
+//----------------------------------------------------------------------------
+
+class Template : public QString
+{
+public:
+	Template() : QString() {}
+	Template(const QString &s) : QString(s) {}
+	Template(const Template &t) : QString(t) {}
+	Template(const char *str) : QString(str) {}
+
+	typedef QMap<QString, QString> ExpandData;
+
+	Template expand(const ExpandData &values) const;
+};
+
+
+#endif
diff -X exclude -Naru psi_cvs-2005.05.17/psi/src/tools/templates/templates.pri psi/psi/src/tools/templates/templates.pri
--- psi_cvs-2005.05.17/psi/src/tools/templates/templates.pri	Thu Jan  1 01:00:00 1970
+++ psi/psi/src/tools/templates/templates.pri	Tue May 17 21:57:30 2005
@@ -0,0 +1,4 @@
+templates {
+	HEADERS += $$TEMPLATES_CPP/templates.h
+	SOURCES += $$TEMPLATES_CPP/templates.cpp
+}
