From 71b30e83ce0d9bf5796e6fb52468ecbdcba5308a Mon Sep 17 00:00:00 2001
From: Nick Clemens <nick@bywatersolutions.com>
Date: Tue, 18 Jul 2017 19:23:18 +0000
Subject: [PATCH] Bug 17179 - Add keyboard shortcuts to repeat (duplicate) a
 field, and cut text

This patchset introduces an internal clipboard to the advanced editor
and provides some new functionality to make use of this:

Ctrl-X:       Now cuts a line into the clipboard area
Ctrl-Shift-X: Now cuts current subfield into clipboard area
Ctrl-C:       Copies a line into the clipboard area
Ctrl-Shift-C: Copies current subfield into clipboard area
Ctrl-P:       Pastes the selected item from the clipboard at cursor
Ctrl-I:       Copies the current line and inserts onto a new line below
Ctrl-Z:       Functions as undo - this was supported but now in the
dropdown help

To test:
Verify all functionality above and confirm it behaves as expected

Note:
Ctrl-v pastes from the system clipboard - codemirror does not have
access and this is why we use our "Clipboard"
For browser cut/paste please use mouse right click or context menus
Ctrl-P can be accessed as print by focusing outside the editor window
---
 .../lib/koha/cateditor/marc-editor.js              | 47 +++++++++++++++++++++-
 .../prog/en/modules/cataloguing/editor.tt          | 30 ++++++++++++++
 2 files changed, 75 insertions(+), 2 deletions(-)

diff --git a/koha-tmpl/intranet-tmpl/lib/koha/cateditor/marc-editor.js b/koha-tmpl/intranet-tmpl/lib/koha/cateditor/marc-editor.js
index 3b8622a..b71e917 100644
--- a/koha-tmpl/intranet-tmpl/lib/koha/cateditor/marc-editor.js
+++ b/koha-tmpl/intranet-tmpl/lib/koha/cateditor/marc-editor.js
@@ -151,6 +151,8 @@ define( [ 'marc-record', 'koha-backend', 'preferences', 'text-marc', 'widget' ],
         'Ctrl-X': function( cm ) {
             // Delete line (or cut)
             if ( cm.somethingSelected() ) return true;
+            var curLine = cm.getLine( cm.getCursor().line );
+            $("#clipboard").prepend('<option>'+curLine+'</option>');
 
             cm.execCommand('deleteLine');
         },
@@ -160,8 +162,49 @@ define( [ 'marc-record', 'koha-backend', 'preferences', 'text-marc', 'widget' ],
             var field = cm.marceditor.getCurrentField();
             if ( !field ) return;
 
-            var subfield = field.getSubfieldAt( cm.getCursor().ch );
-            if ( subfield ) subfield.delete();
+            var curCursor = cm.getCursor();
+            var subfield = field.getSubfieldAt( curCursor.ch );
+            var subfieldText = cm.getRange({line:curCursor.line,ch:subfield.start},{line:curCursor.line,ch:subfield.end});
+            if ( subfield ) {
+                $("#clipboard").prepend('<option>'+subfieldText+'</option>');
+                subfield.delete();
+            }
+        },
+
+        'Ctrl-C': function( cm ) {
+            // Copy line
+            if ( cm.somethingSelected() ) return true;
+            var curLine = cm.getLine( cm.getCursor().line );
+            $("#clipboard").prepend('<option>'+curLine+'</option>');
+        },
+
+        'Shift-Ctrl-C': function( cm ) {
+            // Copy subfield
+            var field = cm.marceditor.getCurrentField();
+            if ( !field ) return;
+
+            var curCursor = cm.getCursor();
+            var subfield = field.getSubfieldAt( curCursor.ch );
+            var subfieldText = cm.getRange({line:curCursor.line,ch:subfield.start},{line:curCursor.line,ch:subfield.end});
+            if ( subfield ) {
+                $("#clipboard").prepend('<option>'+subfieldText+'</option>');
+            }
+        },
+
+        'Ctrl-P': function( cm ) {
+            // Paste line from "clipboard"
+            if ( cm.somethingSelected() ) return true;
+            var cBoard = document.getElementById("clipboard");
+            var strUser = cBoard.options[cBoard.selectedIndex].text;
+            cm.replaceRange( strUser, cm.getCursor(), null );
+        },
+
+        'Ctrl-I': function( cm ) {
+            // Copy line and insert below
+            if ( cm.somethingSelected() ) return true;
+            var curLine = cm.getLine( cm.getCursor().line );
+            cm.execCommand('newlineAndIndent');
+            cm.replaceRange( curLine, cm.getCursor(), null );
         },
 
         Tab: function( cm ) {
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/editor.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/editor.tt
index dd3ab74..dc80e27 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/editor.tt
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/editor.tt
@@ -92,6 +92,12 @@
     </fieldset>
 </form>
 
+<h3>Clipboard</h3>
+<fieldset class="brief">
+<select id="clipboard" name="clipboard" size=10>
+</select>
+</fieldset>
+
 </div>
 
 </div>
@@ -273,6 +279,22 @@
             <td>Save record</td>
         </tr>
         <tr>
+            <td>Ctrl-C</td>
+            <td>Copy current field</td>
+        </tr>
+        <tr>
+            <td>Ctrl-Shift-C</td>
+            <td>Copy current subfield</td>
+        </tr>
+        <tr>
+            <td>Ctrl-P</td>
+            <td>Paste selection from "clipboard"</td>
+        </tr>
+        <tr>
+            <td>Ctrl-V</td>
+            <td>Paste from system clipboard</td>
+        </tr>
+        <tr>
             <td>Ctrl-X</td>
             <td>Delete current field</td>
         </tr>
@@ -281,6 +303,10 @@
             <td>Delete current subfield</td>
         </tr>
         <tr>
+            <td>Ctrl-I</td>
+            <td>Copy current field on next line</td>
+        </tr>
+        <tr>
             <td>Enter</td>
             <td>New field on next line</td>
         </tr>
@@ -296,6 +322,10 @@
             <td>Shift-Tab</td>
             <td>Move to previous position</td>
         </tr>
+        <tr>
+            <td>Ctrl-Z</td>
+            <td>Undo previous action</td>
+        </tr>
     </tbody>
 </table>
 </div>
-- 
2.1.4