From 09225a41ec7135031a4c0304b8dcdccd45904939 Mon Sep 17 00:00:00 2001
From: Aleksander Machniak <alec@alec.pl>
Date: Thu, 16 Apr 2015 04:55:32 -0400
Subject: [PATCH] Add option to place signature at bottom of the quoted text even in top-posting mode [sig_below]

---
 CHANGELOG                             |    1 
 program/steps/mail/compose.inc        |    7 ++-
 program/js/editor.js                  |   51 ++++++++++++-------------
 program/steps/settings/func.inc       |   14 +++++++
 program/localization/en_US/labels.inc |    1 
 program/js/app.js                     |    6 ++-
 program/steps/settings/save_prefs.inc |    1 
 config/defaults.inc.php               |    5 ++
 8 files changed, 56 insertions(+), 30 deletions(-)

diff --git a/CHANGELOG b/CHANGELOG
index 6c584fc..c3049eb 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -7,6 +7,7 @@
 - Plugin API: Added message_part_body hook
 - Plugin API: Added message_ready hook
 - Plugin API: Add special onload() method to execute plugin actions before startup (session and GUI initialization)
+- Add option to place signature at bottom of the quoted text even in top-posting mode [sig_below]
 - Fix handling of %-encoded entities in mailto: URLs (#1490346)
 - Fix zipped messages downloads after selecting all messages in a folder (#1490339)
 - Fix vpopmaild driver of password plugin
diff --git a/config/defaults.inc.php b/config/defaults.inc.php
index 50ae71e..df8b612 100644
--- a/config/defaults.inc.php
+++ b/config/defaults.inc.php
@@ -1086,6 +1086,11 @@
 // 3 - Forwards and Replies only
 $config['show_sig'] = 1;
 
+// By default the signature is placed depending on cursor position (reply_mode).
+// Sometimes it might be convenient to start the reply on top but keep
+// the signature below the quoted text (sig_below = true).
+$config['sig_below'] = false;
+
 // Use MIME encoding (quoted-printable) for 8bit characters in message body
 $config['force_7bit'] = false;
 
diff --git a/program/js/app.js b/program/js/app.js
index 64fd548..b6b4d31 100644
--- a/program/js/app.js
+++ b/program/js/app.js
@@ -3384,14 +3384,16 @@
 
     if (!html_mode) {
       pos = this.env.top_posting ? 0 : input_message.value.length;
-      this.set_caret_pos(input_message, pos);
 
       // add signature according to selected identity
-      // if we have HTML editor, signature is added in callback
+      // if we have HTML editor, signature is added in a callback
       if (input_from.prop('type') == 'select-one') {
         this.change_identity(input_from[0]);
       }
 
+      // set initial cursor position
+      this.set_caret_pos(input_message, pos);
+
       // scroll to the bottom of the textarea (#1490114)
       if (pos) {
         $(input_message).scrollTop(input_message.scrollHeight);
diff --git a/program/js/editor.js b/program/js/editor.js
index 296a161..abd800c 100644
--- a/program/js/editor.js
+++ b/program/js/editor.js
@@ -485,32 +485,37 @@
         sig = rcmail.env.signatures[id].text;
         sig = sig.replace(/\r\n/g, '\n');
 
-        if (rcmail.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 (!message) { // empty message
-            cursor_pos = 0;
-            message = '\n\n' + sig;
-          }
-          else if (pos = rcmail.get_caret_pos(input_message.get(0))) { // at cursor position
+        // in place of removed signature
+        if (p >= 0) {
+          message = message.substring(0, p) + sig + message.substring(p, message.length);
+          cursor_pos = p - 1;
+        }
+        // empty message
+        else if (!message) {
+          message = '\n\n' + sig;
+          cursor_pos = 0;
+        }
+        else if (rcmail.env.top_posting && !rcmail.env.sig_below) {
+          // at cursor position
+          if (pos = rcmail.get_caret_pos(input_message.get(0))) {
             message = message.substring(0, pos) + '\n' + sig + '\n\n' + message.substring(pos, message.length);
             cursor_pos = pos;
           }
-          else { // on top
-            cursor_pos = 0;
+          // on top
+          else {
             message = '\n\n' + sig + '\n\n' + message.replace(/^[\r\n]+/, '');
+            cursor_pos = 0;
           }
         }
         else {
           message = message.replace(/[\r\n]+$/, '');
-          cursor_pos = !rcmail.env.top_posting && message.length ? message.length+1 : 0;
+          cursor_pos = !rcmail.env.top_posting && message.length ? message.length + 1 : 0;
           message += '\n\n' + sig;
         }
       }
-      else
+      else {
         cursor_pos = rcmail.env.top_posting ? 0 : message.length;
+      }
 
       input_message.val(message);
 
@@ -528,24 +533,18 @@
         sigElem = doc.createElement('div');
         sigElem.setAttribute('id', '_rc_sig');
 
-        if (rcmail.env.top_posting) {
-          // if no existing sig and top posting then insert at caret pos
+        if (rcmail.env.top_posting && !rcmail.env.sig_below) {
           this.editor.getWin().focus(); // correct focus in IE & Chrome
 
           var node = this.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);
-          }
+
+          // insert at start or at cursor position if found
+          body.insertBefore(sigElem, node.nodeName == 'BODY' ? body.firstChild : node.nextSibling);
+          body.insertBefore(doc.createElement('p'), sigElem);
         }
         else {
           body.appendChild(sigElem);
-          position_element = $(sigElem).prev();
+          position_element = rcmail.env.top_posting ? body.firstChild : $(sigElem).prev();
         }
       }
 
diff --git a/program/localization/en_US/labels.inc b/program/localization/en_US/labels.inc
index fac52ba..8202b14 100644
--- a/program/localization/en_US/labels.inc
+++ b/program/localization/en_US/labels.inc
@@ -509,6 +509,7 @@
 $labels['newmessageonly'] = 'new message only';
 $labels['replyandforwardonly'] = 'replies and forwards only';
 $labels['insertsignature'] = 'Insert signature';
+$labels['sigbelow'] = 'Place signature below the quoted message';
 $labels['previewpanemarkread']  = 'Mark previewed messages as read';
 $labels['afternseconds']  = 'after $n seconds';
 $labels['reqmdn'] = 'Always request a return receipt';
diff --git a/program/steps/mail/compose.inc b/program/steps/mail/compose.inc
index ba6f334..5009c52 100644
--- a/program/steps/mail/compose.inc
+++ b/program/steps/mail/compose.inc
@@ -91,6 +91,7 @@
 $OUTPUT->set_env('session_id', session_id());
 $OUTPUT->set_env('mailbox', $RCMAIL->storage->get_folder());
 $OUTPUT->set_env('top_posting', intval($RCMAIL->config->get('reply_mode')) > 0);
+$OUTPUT->set_env('sig_below', $RCMAIL->config->get('sig_below'));
 $OUTPUT->set_env('recipients_separator', trim($RCMAIL->config->get('recipients_separator', ',')));
 $OUTPUT->set_env('save_localstorage', (bool)$RCMAIL->config->get('compose_save_localstorage'));
 $OUTPUT->set_env('is_sent', false);
@@ -612,8 +613,10 @@
     if (count($MESSAGE->identities)) {
         $a_signatures = array();
         $identities   = array();
-        $separator    = intval($RCMAIL->config->get('reply_mode')) > 0
-            && ($compose_mode == RCUBE_COMPOSE_REPLY || $compose_mode == RCUBE_COMPOSE_FORWARD) ? '---' : '-- ';
+        $top_posting  = intval($RCMAIL->config->get('reply_mode')) > 0
+            && !$RCMAIL->config->get('sig_below')
+            && ($compose_mode == RCUBE_COMPOSE_REPLY || $compose_mode == RCUBE_COMPOSE_FORWARD);
+        $separator = $top_posting ? '---' : '-- ';
 
         $field_attrib['onchange'] = rcmail_output::JS_OBJECT_NAME.".change_identity(this)";
         $select_from = new html_select($field_attrib);
diff --git a/program/steps/settings/func.inc b/program/steps/settings/func.inc
index 46aed30..c763dd3 100644
--- a/program/steps/settings/func.inc
+++ b/program/steps/settings/func.inc
@@ -845,6 +845,20 @@
                 );
             }
 
+            if (!isset($no_override['sig_below'])) {
+                if (!$current) {
+                    continue 2;
+                }
+
+                $field_id = 'rcmfd_sig_below';
+                $input    = new html_checkbox(array('name' => '_sig_below', 'id' => $field_id, 'value' => 1));
+
+                $blocks['sig']['options']['sig_below'] = array(
+                    'title'   => html::label($field_id, rcube::Q($RCMAIL->gettext('sigbelow'))),
+                    'content' => $input->show($RCMAIL->config->get('sig_below') ? 1 : 0),
+                );
+            }
+
             if (!isset($no_override['strip_existing_sig'])) {
                 if (!$current) {
                     continue 2;
diff --git a/program/steps/settings/save_prefs.inc b/program/steps/settings/save_prefs.inc
index f0ce9c9..4ecaa70 100644
--- a/program/steps/settings/save_prefs.inc
+++ b/program/steps/settings/save_prefs.inc
@@ -85,6 +85,7 @@
         'spellcheck_ignore_caps' => isset($_POST['_spellcheck_ignore_caps']) ? true : false,
         'show_sig'           => isset($_POST['_show_sig']) ? intval($_POST['_show_sig']) : 1,
         'reply_mode'         => isset($_POST['_reply_mode']) ? intval($_POST['_reply_mode']) : 0,
+        'sig_below'          => isset($_POST['_sig_below']) ? true : false,
         'strip_existing_sig' => isset($_POST['_strip_existing_sig']),
         'default_font'       => rcube_utils::get_input_value('_default_font', rcube_utils::INPUT_POST),
         'default_font_size'  => rcube_utils::get_input_value('_default_font_size', rcube_utils::INPUT_POST),

--
Gitblit v1.9.1