diff --git a/css/thread.css b/css/thread.css
index 6a9ebbd38d8aa81bc266ddb29f083f951f10ff15..049165780c799beed80f45e1e4fc8f1f24a0cb65 100644
--- a/css/thread.css
+++ b/css/thread.css
@@ -277,6 +277,7 @@
   padding: 10px 20px;
   margin: 0 0 20px;
   border-left: 5px solid #eeeeee;
+  color: #777;
 }
 .thread-body blockquote p {
   font-weight: 300;
@@ -415,7 +416,6 @@
 .thread-body ol,
 .thread-body table,
 .thread-body dl,
-.thread-body blockquote,
 .thread-body pre {
 	margin: 0;
 	margin-bottom: 10px;
diff --git a/include/ajax.kbase.php b/include/ajax.kbase.php
index c6bbd3156ecba7893839e0e1bc8c1404a32f9266..2f5bc75bfa6e0a8c88c9ab7ab2b4a0961224eb23 100644
--- a/include/ajax.kbase.php
+++ b/include/ajax.kbase.php
@@ -18,7 +18,7 @@ if(!defined('INCLUDE_DIR')) die('!');
 
 class KbaseAjaxAPI extends AjaxController {
 
-    function cannedResp($id, $format='') {
+    function cannedResp($id, $format='text') {
         global $thisstaff, $cfg;
 
         include_once(INCLUDE_DIR.'class.canned.php');
@@ -26,39 +26,10 @@ class KbaseAjaxAPI extends AjaxController {
         if(!$id || !($canned=Canned::lookup($id)) || !$canned->isEnabled())
             Http::response(404, 'No such premade reply');
 
-        //Load ticket.
-        if($_GET['tid']) {
-            include_once(INCLUDE_DIR.'class.ticket.php');
-            $ticket = Ticket::lookup($_GET['tid']);
-        }
-
-        $resp = array();
-        switch($format) {
-            case 'json':
-                $resp['id'] = $canned->getId();
-                $resp['ticket'] = $canned->getTitle();
-                $resp['response'] = $ticket
-                    ? $ticket->replaceVars($canned->getResponseWithImages())
-                    : $canned->getResponseWithImages();
-                $resp['files'] = $canned->attachments->getSeparates();
-
-                if (!$cfg->isHtmlThreadEnabled()) {
-                    $resp['response'] = Format::html2text($resp['response'], 90);
-                    $resp['files'] += $canned->attachments->getInlines();
-                }
-
-                $response = $this->json_encode($resp);
-                break;
-
-            case 'txt':
-            default:
-                $response =$ticket?$ticket->replaceVars($canned->getResponse()):$canned->getResponse();
-
-                if (!$cfg->isHtmlThreadEnabled())
-                    $response = Format::html2text($response, 90);
-        }
+        if (!$cfg->isHtmlThreadEnabled())
+            $format .= '.plain';
 
-        return $response;
+        return $canned->getFormattedResponse($format);
     }
 
     function faq($id, $format='html') {
diff --git a/include/ajax.tickets.php b/include/ajax.tickets.php
index 445733dc6f80fc0283e72740e742f79aabd19b24..5722a76a78dac30cb36667808fc32e47c8fc8924 100644
--- a/include/ajax.tickets.php
+++ b/include/ajax.tickets.php
@@ -657,5 +657,40 @@ class TicketsAjaxAPI extends AjaxController {
         Http::response(201, 'Successfully managed');
     }
 
+    function cannedResponse($tid, $cid, $format='text') {
+        global $thisstaff, $cfg;
+
+        if (!($ticket = Ticket::lookup($tid))
+                || !$ticket->checkStaffAccess($thisstaff))
+            Http::response(404, 'Unknown ticket ID');
+
+
+        if ($cid && !is_numeric($cid)) {
+            if (!($response=$ticket->getThread()->getVar($cid)))
+                Http::response(422, 'Unknown ticket variable');
+
+            // Ticket thread variables are assumed to be quotes
+            $response = "<br/><blockquote>$response</blockquote><br/>";
+            //  Return text if html thread is not enabled
+            if (!$cfg->isHtmlThreadEnabled())
+                $response = Format::html2text($response, 90);
+
+            // XXX: assuming json format for now.
+            return Format::json_encode(array('response' => $response));
+        }
+
+        if (!$cfg->isHtmlThreadEnabled())
+            $format.='.plain';
+
+        $varReplacer = function (&$var) use($ticket) {
+            return $ticket->replaceVars($var);
+        };
+
+        include_once(INCLUDE_DIR.'class.canned.php');
+        if (!$cid || !($canned=Canned::lookup($cid)) || !$canned->isEnabled())
+            Http::response(404, 'No such premade reply');
+
+        return $canned->getFormattedResponse($format, $varReplacer);
+    }
 }
 ?>
diff --git a/include/class.ajax.php b/include/class.ajax.php
index c852a551734a572662e75de6a6d18c43e1bc8892..3be9713d89be8d1d2391f4c49c22919a5baccf78 100644
--- a/include/class.ajax.php
+++ b/include/class.ajax.php
@@ -38,9 +38,7 @@ class AjaxController extends ApiController {
      * Convert a PHP array into a JSON-encoded string
      */
     function json_encode($what) {
-        require_once (INCLUDE_DIR.'class.json.php');
-        $encoder = new JsonDataEncoder();
-        return $encoder->encode($what);
+        return Format::json_encode($what);
     }
 
     function encode($what) {
diff --git a/include/class.canned.php b/include/class.canned.php
index 457c6d8f904eaaf476bc3744422989f17c940169..bfb5e82ce5e09a6eca8dab6f16aeda2e0485cc4f 100644
--- a/include/class.canned.php
+++ b/include/class.canned.php
@@ -86,6 +86,60 @@ class Canned {
         return $this->getResponse();
     }
 
+    function getHtml() {
+        return $this->getFormattedResponse('html');
+    }
+
+    function getPlainText() {
+        return $this->getFormattedResponse('text.plain');
+    }
+
+    function getFormattedResponse($format='text', $cb=null) {
+
+        $resp = array();
+        $html = true;
+        switch($format) {
+            case 'json.plain':
+                $html = false;
+                // fall-through
+            case 'json':
+                $resp['id'] = $this->getId();
+                $resp['title'] = $this->getTitle();
+                $resp['response'] = $this->getResponseWithImages();
+
+                // Callback to strip or replace variables!
+                if ($cb && is_callable($cb))
+                    $resp = $cb($resp);
+
+                $resp['files'] = $this->attachments->getSeparates();
+                // strip html
+                if (!$html) {
+                    $resp['response'] = Format::html2text($resp['response'], 90);
+                    $resp['files'] += $this->attachments->getInlines();
+                }
+                return Format::json_encode($resp);
+                break;
+            case 'html':
+            case 'text.html':
+                $response = $this->getResponseWithImages();
+                break;
+            case 'text.plain':
+                $html = false;
+            case 'text':
+            default:
+                $response = $this->getResponse();
+                if (!$html)
+                    $response = Format::html2text($response, 90);
+                break;
+        }
+
+        // Callback to strip or replace variables!
+        if ($response && $cb && is_callable($cb))
+            $response = $cb($response);
+
+        return $response;
+    }
+
     function getNotes() {
         return $this->ht['notes'];
     }
diff --git a/include/class.format.php b/include/class.format.php
index 3b841a4a585db66be41e2485acd5cf866b319d00..4c73d5188f5c1ab46e5b4d712f80c57f7106c9cc 100644
--- a/include/class.format.php
+++ b/include/class.format.php
@@ -99,6 +99,15 @@ class Format {
             return $filename;
     }
 
+    /**
+     * Json Encoder
+     *
+     */
+    function json_encode($what) {
+        require_once (INCLUDE_DIR.'class.json.php');
+        return JsonDataEncoder::encode($what);
+    }
+
 	function phone($phone) {
 
 		$stripped= preg_replace("/[^0-9]/", "", $phone);
diff --git a/include/class.ticket.php b/include/class.ticket.php
index 57a8077e5d6361ba5ee048e42be7f8242960c912..63dde20fa9e247ca48643e82d1b407347ce7e2f1 100644
--- a/include/class.ticket.php
+++ b/include/class.ticket.php
@@ -1670,9 +1670,16 @@ class Ticket {
         foreach ($canned->attachments->getAll() as $file)
             $files[] = $file['id'];
 
+        if ($cfg->isHtmlThreadEnabled())
+            $response = new HtmlThreadBody(
+                    $this->replaceVars($canned->getHtml()));
+        else
+            $response = new TextThreadBody(
+                    $this->replaceVars($canned->getPlainText()));
+
         $info = array('msgId' => $msgId,
                       'poster' => 'SYSTEM (Canned Reply)',
-                      'response' => $this->replaceVars($canned->getResponse()),
+                      'response' => $response,
                       'cannedattachments' => $files);
 
         $errors = array();
diff --git a/include/i18n/en_US/templates/premade.yaml b/include/i18n/en_US/templates/premade.yaml
index 26880b7c13739628a43620da83cf1e266a3259fa..94f2def11c938a70694010cb9de61542e24f735b 100644
--- a/include/i18n/en_US/templates/premade.yaml
+++ b/include/i18n/en_US/templates/premade.yaml
@@ -2,7 +2,8 @@
 # Canned response templates
 #
 ---
-- title: What is osTicket (sample)?
+- isenabled:1
+  title: What is osTicket (sample)?
   response: |
     osTicket is a widely-used open source support ticket system, an
     attractive alternative to higher-cost and complex customer support
@@ -15,7 +16,8 @@
       type: text/plain
       data: Canned Attachments Rock!
 
-- title: Sample (with variables)
+- isenabled: 1
+  title: Sample (with variables)
   response: |
     Hi %{ticket.name.first},
     <br>
diff --git a/include/staff/ticket-view.inc.php b/include/staff/ticket-view.inc.php
index d0b1b34d757b858a64c83faab0fb1b28175aa8f8..a63df79ea83538377ed3c84512c1fddac1077807 100644
--- a/include/staff/ticket-view.inc.php
+++ b/include/staff/ticket-view.inc.php
@@ -505,19 +505,21 @@ $tcount+= $ticket->getNumNotes();
                     <label><strong>Response:</strong></label>
                 </td>
                 <td>
-                    <?php
-                    if(($cannedResponses=Canned::responsesByDeptId($ticket->getDeptId()))) {?>
-                        <select id="cannedResp" name="cannedResp">
-                            <option value="0" selected="selected">Select a canned response</option>
-                            <?php
-                            foreach($cannedResponses as $id =>$title) {
+                    <select id="cannedResp" name="cannedResp">
+                        <option value="0" selected="selected">Select a canned response</option>
+                        <option value='lastmessage'>Original Message</option>
+                        <option value='original'>Last Message</option>
+                        <?php
+                        if(($cannedResponses=Canned::responsesByDeptId($ticket->getDeptId()))) {
+                            echo '<option value="0" disabled="disabled">
+                                ------------- Premade Replies ------------- </option>';
+                            foreach($cannedResponses as $id =>$title)
                                 echo sprintf('<option value="%d">%s</option>',$id,$title);
-                            }
-                            ?>
-                        </select>
-                        <br>
+                        }
+                        ?>
+                    </select>
+                    <br>
                     <?php
-                    }
                     $signature = '';
                     switch ($thisstaff->getDefaultSignatureType()) {
                     case 'dept':
diff --git a/scp/ajax.php b/scp/ajax.php
index 6f784080b2d8d018a35274792b4e6f8005403a9f..a192cce8cf92da76bf185a441840093133d03099 100644
--- a/scp/ajax.php
+++ b/scp/ajax.php
@@ -137,7 +137,8 @@ $dispatcher = patterns('',
         url_get('^lookup', 'lookup'),
         url_get('^search', 'search'),
         url_get('^(?P<tid>\d+)/forms/manage$', 'manageForms'),
-        url_post('^(?P<tid>\d+)/forms/manage$', 'updateForms')
+        url_post('^(?P<tid>\d+)/forms/manage$', 'updateForms'),
+        url_get('^(?P<tid>\d+)/canned-resp/(?P<cid>\w+).(?P<format>json|txt)', 'cannedResponse')
     )),
     url('^/collaborators/', patterns('ajax.tickets.php:TicketsAjaxAPI',
         url_get('^(?P<cid>\d+)/view$', 'viewCollaborator'),
diff --git a/scp/js/scp.js b/scp/js/scp.js
index 254ba5fd568deff7433400721bb67ff05864edc5..d79b03955150d2221fe8a3ef920c1a021db5b301 100644
--- a/scp/js/scp.js
+++ b/scp/js/scp.js
@@ -195,16 +195,18 @@ var scp_prep = function() {
 
     $('form select#cannedResp').change(function() {
 
-        var fObj=$(this).closest('form');
-        var cannedId = $(this).val();
-        var ticketId = $(':input[name=id]',fObj).val();
-
+        var fObj = $(this).closest('form');
+        var cid = $(this).val();
+        var tid = $(':input[name=id]',fObj).val();
         $(this).find('option:first').attr('selected', 'selected').parent('select');
 
+        var $url = 'ajax.php/kb/canned-response/'+cid+'.json';
+        if (tid)
+            $url =  'ajax.php/tickets/'+tid+'/canned-resp/'+cid+'.json';
+
         $.ajax({
                 type: "GET",
-                url: 'ajax.php/kb/canned-response/'+cannedId+'.json',
-                data: 'tid='+ticketId,
+                url: $url,
                 dataType: 'json',
                 cache: false,
                 success: function(canned){