summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG1
-rw-r--r--config/main.inc.php.dist10
-rw-r--r--program/js/app.js172
-rw-r--r--program/localization/en_US/labels.inc5
-rw-r--r--program/localization/pl_PL/labels.inc5
-rw-r--r--program/steps/mail/compose.inc28
-rw-r--r--program/steps/settings/func.inc24
-rw-r--r--program/steps/settings/save_prefs.inc2
-rw-r--r--skins/default/templates/compose.html1
9 files changed, 188 insertions, 60 deletions
diff --git a/CHANGELOG b/CHANGELOG
index d64b18a8f..b87677705 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,7 @@
CHANGELOG RoundCube Webmail
===========================
+- Allow inserting signatures above replied message body (#1484272)
- Managesieve 2.0: multi-script support
- Fix imap_auth_type regression (#1486263)
diff --git a/config/main.inc.php.dist b/config/main.inc.php.dist
index efa45957c..51c8ee450 100644
--- a/config/main.inc.php.dist
+++ b/config/main.inc.php.dist
@@ -450,5 +450,15 @@ $rcmail_config['display_next'] = FALSE;
// If true, messages list will be sorted by message index instead of message date
$rcmail_config['index_sort'] = TRUE;
+// When replying place cursor above original message (top posting)
+$rcmail_config['top_posting'] = FALSE;
+
+// Show signature:
+// 0 - Always
+// 1 - Never
+// 2 - New messages only
+// 3 - Forwards, Edits and Replies only
+$rcmail_config['show_sig'] = 0;
+
// end of config file
?>
diff --git a/program/js/app.js b/program/js/app.js
index 9dc9c9198..3ada69990 100644
--- a/program/js/app.js
+++ b/program/js/app.js
@@ -473,6 +473,9 @@ function rcube_webmail()
this.init_address_input_events($("[name='_cc']"));
this.init_address_input_events($("[name='_bcc']"));
+ if (!html_mode)
+ this.set_caret_pos(input_message, this.env.top_posting ? 0 : $(input_message).val().length);
+
// add signature according to selected identity
if (input_from.attr('type') == 'select-one' && $("input[name='_draft_saveid']").val() == ''
&& !html_mode) { // if we have HTML editor, signature is added in callback
@@ -972,6 +975,10 @@ function rcube_webmail()
clearTimeout(this.request_timer);
break;
+ case 'insert-sig':
+ this.change_identity($("[name='_from']")[0], true);
+ break;
+
case 'add-attachment':
this.show_attachment_form(true);
@@ -2295,103 +2302,156 @@ function rcube_webmail()
return str;
};
- this.change_identity = function(obj)
+ this.change_identity = function(obj, show_sig)
{
if (!obj || !obj.options)
return false;
+ if (!show_sig)
+ show_sig = this.env.show_sig;
+
var id = obj.options[obj.selectedIndex].value;
- var input_message = $("[name='_message']");
- var message = input_message.val();
var is_html = ($("input[name='_is_html']").val() == '1');
- var sig, p, len;
+ var sig;
+
+ // enable manual signature insert
+ if (this.env.signatures && this.env.signatures[id])
+ this.enable_command('insert-sig', true);
+ else {
+ this.enable_command('insert-sig', false);
+ if (!this.env.signatures)
+ return true;
+ }
if (!this.env.identity)
this.env.identity = id
+
+ if (!show_sig)
+ return false;
if (!is_html)
{
+ var input_message = $("[name='_message']");
+ var message = input_message.val();
+ var pos, cursor_pos, p = -1;
+
// remove the 'old' signature
- if (this.env.identity && this.env.signatures && this.env.signatures[this.env.identity])
+ if (this.env.identity && this.env.signatures[this.env.identity])
{
if (this.env.signatures[this.env.identity]['is_html'])
sig = this.env.signatures[this.env.identity]['plain_text'];
else
sig = this.env.signatures[this.env.identity]['text'];
-
- if (sig.indexOf('-- ')!=0)
- sig = '-- \n'+sig;
- p = message.lastIndexOf(sig);
+ if (this.env.top_posting)
+ p = message.indexOf(sig);
+ else {
+ if (sig.indexOf('-- ')!=0)
+ sig = '-- \n'+sig;
+ p = message.lastIndexOf(sig);
+ }
+
if (p>=0)
- message = message.substring(0, p-1) + message.substring(p+sig.length, message.length);
- }
+ message = message.substring(0, p) + message.substring(p+sig.length, message.length);
+ }
- message = message.replace(/[\r\n]+$/, '');
- len = message.length;
+ input_message.get(0).focus();
// add the new signature string
- if (this.env.signatures && this.env.signatures[id])
+ if (this.env.signatures[id])
{
- sig = this.env.signatures[id]['text'];
if (this.env.signatures[id]['is_html'])
- {
sig = this.env.signatures[id]['plain_text'];
- }
- if (sig.indexOf('-- ')!=0)
- sig = '-- \n'+sig;
- message += '\n\n'+sig;
- if (len) len += 1;
+ else
+ sig = this.env.signatures[id]['text'];
+
+ if (this.env.top_posting) {
+ if (p>=0) { // in place of removed signature
+ message = message.substring(0, p) + sig + message.substring(p, message.length);
+ cursor_pos = p - 1;
+ }
+ else if (pos = this.get_caret_pos(input_message.get(0))) { // at cursor position
+ message = message.substring(0, pos) + '\n' + sig + '\n' + message.substring(pos, message.length);
+ cursor_pos = pos;
+ }
+ else { // on top
+ cursor_pos = 0;
+ message = '\n\n' + sig + '\n' + message;
+ }
+ }
+ else {
+ message = message.replace(/[\r\n]+$/, '');
+
+ if (sig.indexOf('-- ')!=0)
+ sig = '-- \n'+sig;
+ cursor_pos = message.length ? message.length+1 : 0;
+ message += '\n\n' + sig;
+ }
}
+
+ input_message.val(message);
+
+ // move cursor before the signature
+ if (typeof(cursor_pos) != 'undefined')
+ this.set_caret_pos(input_message.get(0), cursor_pos);
}
+ // html
else
{
var editor = tinyMCE.get(this.env.composebody);
+ var sigElem = editor.dom.get('_rc_sig');
- if (this.env.signatures)
- {
- // Append the signature as a div within the body
- var sigElem = editor.dom.get('_rc_sig');
- var newsig = '';
- var htmlsig = true;
+ // Append the signature as a div within the body
+ if (!sigElem) {
+ var body = editor.getBody();
+ var doc = editor.getDoc();
+
+ sigElem = doc.createElement('div');
+ sigElem.setAttribute('id', '_rc_sig');
+
+ if (this.env.top_posting) {
+ // if no existing sig and top posting then insert at caret pos
+ editor.getWin().focus(); // correct focus in IE
- if (!sigElem)
- {
- // add empty line before signature on IE
- if (bw.ie)
- editor.getBody().appendChild(editor.getDoc().createElement('br'));
+ var node = editor.selection.getNode();
+
+ if (node.nodeName == 'BODY') {
+ // no real focus, insert at start
+ body.insertBefore(sigElem, body.firstChild);
+ body.insertBefore(doc.createElement('br'), body.firstChild);
+ }
+ else {
+ body.insertBefore(sigElem, node.nextSibling);
+ body.insertBefore(doc.createElement('br'), node.nextSibling);
+ }
+ }
+ else {
+ if (bw.ie)
+ // add empty line before signature on IE
+ body.appendChild(doc.createElement('br'));
- sigElem = editor.getDoc().createElement('div');
- sigElem.setAttribute('id', '_rc_sig');
- editor.getBody().appendChild(sigElem);
+ body.appendChild(sigElem);
}
+ }
- if (this.env.signatures[id])
+ if (this.env.signatures[id])
{
- newsig = this.env.signatures[id]['text'];
- htmlsig = this.env.signatures[id]['is_html'];
-
- if (newsig) {
- if (htmlsig && this.env.signatures[id]['plain_text'].indexOf('-- ')!=0)
- newsig = '<p>-- </p>' + newsig;
- else if (!htmlsig && newsig.indexOf('-- ')!=0)
- newsig = '-- \n' + newsig;
+ if (this.env.signatures[id]['is_html']) {
+ sig = this.env.signatures[id]['text'];
+ if (!this.env.top_posting && this.env.signatures[id]['plain_text'].indexOf('-- ')!=0)
+ sig = '-- <br />' + sig;
+ }
+ else {
+ sig = this.env.signatures[id]['text'];
+ if (!this.env.top_posting && sig.indexOf('-- ')!=0)
+ sig = '-- \n' + sig;
+ sig = '<pre>' + sig + '</pre>';
}
- }
-
- if (htmlsig)
- sigElem.innerHTML = newsig;
- else
- sigElem.innerHTML = '<pre>' + newsig + '</pre>';
+
+ sigElem.innerHTML = sig;
}
}
- input_message.val(message);
-
- // move cursor before the signature
- if (!is_html)
- this.set_caret_pos(input_message.get(0), len);
-
this.env.identity = id;
return true;
};
diff --git a/program/localization/en_US/labels.inc b/program/localization/en_US/labels.inc
index 7948cddf1..9ed0d0952 100644
--- a/program/localization/en_US/labels.inc
+++ b/program/localization/en_US/labels.inc
@@ -307,6 +307,11 @@ $labels['focusonnewmessage'] = 'Focus browser window on new message';
$labels['checkallfolders'] = 'Check all folders for new messages';
$labels['displaynext'] = 'After message delete/move display the next message';
$labels['indexsort'] = 'Use message index for sorting by date';
+$labels['top_posting'] = 'Start reply on top of the replied message body (not recommended)';
+$labels['auto_add_sig'] = 'Automatically add signature';
+$labels['new_msg_only'] = 'new messages only';
+$labels['reply_forward_only'] = 'edits, replies and forwards only';
+$labels['insertsig'] = 'Insert signature';
$labels['mainoptions'] = 'Main Options';
$labels['section'] = 'Section';
$labels['maintenance'] = 'Maintenance';
diff --git a/program/localization/pl_PL/labels.inc b/program/localization/pl_PL/labels.inc
index 886cc730c..654a2d97f 100644
--- a/program/localization/pl_PL/labels.inc
+++ b/program/localization/pl_PL/labels.inc
@@ -281,5 +281,10 @@ $labels['section'] = 'Sekcja';
$labels['maintenance'] = 'Konserwacja';
$labels['newmessage'] = 'Nowa wiadomość';
$labels['listoptions'] = 'Opcje list';
+$labels['top_posting'] = 'Odpowiadaj powyżej treści wiadomości (niezalecane)';
+$labels['auto_add_sig'] = 'Automatycznie wstaw podpis';
+$labels['new_msg_only'] = 'tylko nowe wiadomości';
+$labels['reply_forward_only'] = 'tylko dla edycji, przekazywania i odpowiedzi';
+$labels['insertsig'] = 'Wstaw podpis';
?>
diff --git a/program/steps/mail/compose.inc b/program/steps/mail/compose.inc
index 276efda56..0f4b6ac81 100644
--- a/program/steps/mail/compose.inc
+++ b/program/steps/mail/compose.inc
@@ -103,6 +103,7 @@ if (!empty($CONFIG['drafts_mbox'])) {
}
// set current mailbox in client environment
$OUTPUT->set_env('mailbox', $IMAP->get_mailbox_name());
+$OUTPUT->set_env('top_posting', $CONFIG['top_posting']);
// get reference message and set compose mode
if ($msg_uid = $_SESSION['compose']['param']['reply_uid'])
@@ -116,6 +117,13 @@ else if ($msg_uid = $_SESSION['compose']['param']['draft_uid']) {
$compose_mode = RCUBE_COMPOSE_DRAFT;
}
+if (!$CONFIG['show_sig'])
+ $OUTPUT->set_env('show_sig', true);
+else if ($CONFIG['show_sig'] == 2 && empty($compose_mode))
+ $OUTPUT->set_env('show_sig', true);
+else if ($CONFIG['show_sig'] == 3 && ($compose_mode == RCUBE_COMPOSE_REPLY || $compose_mode == RCUBE_COMPOSE_FORWARD))
+ $OUTPUT->set_env('show_sig', true);
+
if (!empty($msg_uid))
{
// similar as in program/steps/mail/show.inc
@@ -510,12 +518,14 @@ function rcmail_compose_body($attrib)
function rcmail_create_reply_body($body, $bodyIsHtml)
{
- global $IMAP, $MESSAGE, $OUTPUT;
+ global $MESSAGE;
+
+ $rcmail = rcmail::get_instance();
if (! $bodyIsHtml)
{
// try to remove the signature
- if (($sp = strrpos($body, '-- ')) !== false && ($sp == 0 || $body{$sp-1} == "\n"))
+ if (!$rcmail->config->get('top_posting') && ($sp = strrpos($body, '-- ')) !== false && ($sp == 0 || $body{$sp-1} == "\n"))
{
if ($body{$sp+3}==' ' || $body{$sp+3}=="\n" || $body{$sp+3}=="\r")
$body = substr($body, 0, max(0, $sp-1));
@@ -547,6 +557,9 @@ function rcmail_create_reply_body($body, $bodyIsHtml)
$MESSAGE->get_header('from')), 76);
$suffix = '';
+
+ if ($rcmail->config->get('top_posting'))
+ $prefix = "\n\n\n" . $prefix;
}
else
{
@@ -560,9 +573,16 @@ function rcmail_create_reply_body($body, $bodyIsHtml)
// build reply (quote content)
$prefix = sprintf("On %s, %s wrote:<br />\n",
$MESSAGE->headers->date,
- htmlspecialchars(Q($MESSAGE->get_header('from'), 'replace'), ENT_COMPAT, $OUTPUT->get_charset()));
+ htmlspecialchars(Q($MESSAGE->get_header('from'), 'replace'), ENT_COMPAT, $rcmail->output->get_charset()));
$prefix .= '<blockquote type="cite" style="padding-left:5px; border-left:#1010ff 2px solid; margin-left:5px; width:100%">';
- $suffix = "</blockquote><p></p>";
+
+ if ($rcmail->config->get('top_posting')) {
+ $prefix = "<p></p>" . $prefix;
+ $suffix = "</blockquote>";
+ }
+ else {
+ $suffix = "</blockquote><p></p>";
+ }
}
return $prefix.$body.$suffix;
diff --git a/program/steps/settings/func.inc b/program/steps/settings/func.inc
index 7bd30a3f4..e451d57d5 100644
--- a/program/steps/settings/func.inc
+++ b/program/steps/settings/func.inc
@@ -448,6 +448,30 @@ function rcmail_user_prefs($current=null)
'content' => $select_param_folding->show($config['mime_param_folding']),
);
}
+
+ if (!isset($no_override['top_posting'])) {
+ $field_id = 'rcmfd_top_posting';
+ $input_topposting = new html_checkbox(array('name' => '_top_posting', 'id' => $field_id, 'value' => 1));
+
+ $blocks['main']['options']['top_posting'] = array(
+ 'title' => html::label($field_id, Q(rcube_label('top_posting'))),
+ 'content' => $input_topposting->show($config['top_posting']?1:0),
+ );
+ }
+
+ if (!isset($no_override['show_sig'])) {
+ $field_id = 'rcmfd_show_sig';
+ $select_show_sig = new html_select(array('name' => '_show_sig', 'id' => $field_id));
+ $select_show_sig->add(rcube_label('always'), 0);
+ $select_show_sig->add(rcube_label('never'), 1);
+ $select_show_sig->add(rcube_label('new_msg_only'), 2);
+ $select_show_sig->add(rcube_label('reply_forward_only'), 3);
+
+ $blocks['main']['options']['show_sig'] = array(
+ 'title' => html::label($field_id, Q(rcube_label('auto_add_sig'))),
+ 'content' => $select_show_sig->show(intval($config['show_sig'])),
+ );
+ }
break;
diff --git a/program/steps/settings/save_prefs.inc b/program/steps/settings/save_prefs.inc
index ddb1367c8..e38a695a4 100644
--- a/program/steps/settings/save_prefs.inc
+++ b/program/steps/settings/save_prefs.inc
@@ -62,6 +62,8 @@ switch ($CURR_SECTION)
'htmleditor' => isset($_POST['_htmleditor']) ? TRUE : FALSE,
'draft_autosave' => isset($_POST['_draft_autosave']) ? intval($_POST['_draft_autosave']) : 0,
'mime_param_folding' => isset($_POST['_mime_param_folding']) ? intval($_POST['_mime_param_folding']) : 0,
+ 'show_sig' => isset($_POST['_show_sig']) ? intval($_POST['_show_sig']) : 0,
+ 'top_posting' => isset($_POST['_top_posting']) ? TRUE : FALSE,
);
break;
diff --git a/skins/default/templates/compose.html b/skins/default/templates/compose.html
index d2b36e045..35b198908 100644
--- a/skins/default/templates/compose.html
+++ b/skins/default/templates/compose.html
@@ -20,6 +20,7 @@
<roundcube:button command="send" type="link" class="buttonPas send" classAct="button send" classSel="button sendSel" title="sendmessage" content=" " />
<roundcube:button command="spellcheck" type="link" class="buttonPas spellcheck" classAct="button spellcheck" classSel="button spellcheckSel" title="checkspelling" content=" " />
<roundcube:button command="add-attachment" type="link" class="buttonPas attach" classAct="button attach" classSel="button attachSel" title="addattachment" content=" " />
+ <roundcube:button command="insert-sig" type="link" class="buttonPas insertsig" classAct="button insertsig" classSel="button insertsigSel" title="insertsig" content=" " />
<roundcube:button command="savedraft" type="link" class="buttonPas savedraft" classAct="button savedraft" classSel="button savedraftSel" title="savemessage" content=" " />
<roundcube:container name="toolbar" id="compose-toolbar" />
</td>