From 852ff1985a45be4a885e7b9f96ce7ef0b5d50c96 Mon Sep 17 00:00:00 2001
From: Radek Czajka <radoslaw.czajka@nowoczesnapolska.org.pl>
Date: Tue, 3 Aug 2010 11:32:09 +0200
Subject: [PATCH] better auto-correction

---
 apps/toolbar/fixtures/initial_data.yaml | 193 ++++++++++++------------
 redakcja/static/js/button_scripts.js    |  86 +++++------
 2 files changed, 133 insertions(+), 146 deletions(-)

diff --git a/apps/toolbar/fixtures/initial_data.yaml b/apps/toolbar/fixtures/initial_data.yaml
index 723732d2..c7b5af60 100644
--- a/apps/toolbar/fixtures/initial_data.yaml
+++ b/apps/toolbar/fixtures/initial_data.yaml
@@ -38,8 +38,8 @@
     model: toolbar.buttongroup
     pk: 17
 -   fields:
-        group: [14, 12]
         accesskey: a
+        group: [14, 12]
         label: akapit
         link: ''
         params: '{"tag": "akap"}'
@@ -49,8 +49,8 @@
     model: toolbar.button
     pk: 39
 -   fields:
-        group: [14]
         accesskey: ''
+        group: [14]
         label: akapit cd.
         link: ''
         params: '{"tag": "akap_cd"}'
@@ -60,8 +60,8 @@
     model: toolbar.button
     pk: 40
 -   fields:
-        group: [14]
         accesskey: d
+        group: [14]
         label: akapit dialogowy
         link: ''
         params: '{"tag": "akap_dialog"}'
@@ -71,8 +71,8 @@
     model: toolbar.button
     pk: 41
 -   fields:
-        group: [1]
         accesskey: ''
+        group: [1]
         label: akt
         link: ''
         params: '{"tag": "akt"}'
@@ -82,8 +82,8 @@
     model: toolbar.button
     pk: 14
 -   fields:
-        group: [13]
         accesskey: ''
+        group: [13]
         label: autor
         link: ''
         params: '{"tag": "autor_utworu"}'
@@ -93,24 +93,25 @@
     model: toolbar.button
     pk: 32
 -   fields:
-        group: [2]
         accesskey: ''
+        group: [2]
         label: Podstawowa
         link: ''
         params: '[["fulltextregexp", {"exprs": [["\ufeff", ""], ["$[\\s]*\\d+[\\s]*^",
-            ""], ["-\\s*^", ""], ["\\,\\.\\.|\\.\\,\\.|\\.\\.\\,", "..."]]}], ["lineregexp",
-            {"exprs": [["^\\s+|\\s+$", ""], ["\\s+", " "], ["(,,)\\s+|\\s+(\")", "$1"],
-            ["(\\d)[\u2014-](\\d)", "$1--$2"], ["[\u2014]", "---"], ["<(/?)P([aert])",
-            "<$1p$2"], ["([^\\.])(\\s*)</p", "$1.$2</p"], ["([,\\.:;!\\?])([^\\s\\\\])",
-            "$1 $2"], ["([^\\s])\\s+([,\\.:;!\\?])", "$1$2"]]}]]'
+            ""], ["-\\s*^", ""], ["\\,\\.\\.|\\.\\,\\.|\\.\\.\\,", "..."], ["<(/?)P([aert])",
+            "<$1p$2"], ["[\u2014\u2013\u2010-]+", "---"], ["(\\d)---(\\d)", "$1--$2"],
+            ["(\\S)---(\\S)", "$1-$2"]]}], ["lineregexp", {"exprs": [["^\\s+|\\s+$",
+            ""], ["\\s+", " "], ["(,,)\\s+", "$1"], ["\\s+(\")", "$1"], ["([^\\.])(\\s*)</p",
+            "$1.$2</p"], ["([,\\.:;!\\?])([^\\s\\\\])", "$1 $2"], ["([^\\s])\\s+([,\\.:;!\\?])",
+            "$1$2"]]}]]'
         scriptlet: macro
         slug: basic_correction
-        tooltip: "Wykonuj\u0119 operacj\u0119 z novel-pages i poem-pages."
+        tooltip: "Wykonuj\u0119 podstawow\u0105 korekt\u0119 tekstu."
     model: toolbar.button
     pk: 4
 -   fields:
-        group: [2]
         accesskey: ''
+        group: [2]
         label: "zamiana cudzys\u0142ow\xF3w 1"
         link: ''
         params: '{"exprs": [["\u00ab|\u201e", ",,"], ["\u00bb", "\""], ["([^=])\"([\u0104\u0118\u00d3\u0141\u017b\u0179\u0106\u0143\u0105\u017c\u017a\u015b\u0144\u00f3\u0142\u0107\\w])",
@@ -122,8 +123,8 @@
     model: toolbar.button
     pk: 89
 -   fields:
-        group: [2]
         accesskey: ''
+        group: [2]
         label: "zamiana cudzys\u0142ow\xF3w 2"
         link: ''
         params: '{"exprs": [["\u00bb|\u201e", ",,"], ["\u00ab", "\""], ["([^=])\"([\u0104\u0118\u00d3\u0141\u017b\u0179\u0106\u0143\u0105\u017c\u017a\u015b\u0144\u00f3\u0142\u0107\\w])",
@@ -135,8 +136,8 @@
     model: toolbar.button
     pk: 77
 -   fields:
-        group: [1]
         accesskey: ''
+        group: [1]
         label: "cz\u0119\u015B\u0107/ksi\u0119ga"
         link: ''
         params: '{"tag": "naglowek_czesc"}'
@@ -146,8 +147,8 @@
     model: toolbar.button
     pk: 10
 -   fields:
-        group: [13, 22]
         accesskey: ''
+        group: [13, 22]
         label: dedykacja
         link: ''
         params: '{"tag": "dedykacja"}'
@@ -157,8 +158,8 @@
     model: toolbar.button
     pk: 74
 -   fields:
-        group: [12]
         accesskey: ''
+        group: [12]
         label: didaskalia
         link: ''
         params: '{"tag": "didaskalia"}'
@@ -168,8 +169,8 @@
     model: toolbar.button
     pk: 62
 -   fields:
-        group: [22]
         accesskey: ''
+        group: [22]
         label: "didaskalia pocz\u0105tkowe"
         link: ''
         params: '{"tag": "miejsce_czas"}'
@@ -179,8 +180,8 @@
     model: toolbar.button
     pk: 79
 -   fields:
-        group: [12]
         accesskey: ''
+        group: [12]
         label: didaskalia tekstowe
         link: ''
         params: '{"tag": "didask_tekst"}'
@@ -190,8 +191,8 @@
     model: toolbar.button
     pk: 63
 -   fields:
-        group: [21]
         accesskey: ''
+        group: [21]
         label: "d\u0142ugi cyt. poet."
         link: ''
         params: '{"tag": "poezja_cyt"}'
@@ -201,8 +202,8 @@
     model: toolbar.button
     pk: 67
 -   fields:
-        group: [21]
         accesskey: ''
+        group: [21]
         label: "d\u0142ugi cytat"
         link: ''
         params: '{"tag": "dlugi_cyt"}'
@@ -212,8 +213,8 @@
     model: toolbar.button
     pk: 42
 -   fields:
-        group: [11]
         accesskey: ''
+        group: [11]
         label: dramat wiersz.
         link: ''
         params: '{"tag": "dramat_wierszowany_l"}'
@@ -223,8 +224,8 @@
     model: toolbar.button
     pk: 20
 -   fields:
-        group: [11]
         accesskey: ''
+        group: [11]
         label: "dramat wiersz./w. \u0142am"
         link: ''
         params: '{"tag": "dramat_wierszowany_lp"}'
@@ -234,8 +235,8 @@
     model: toolbar.button
     pk: 22
 -   fields:
-        group: [11]
         accesskey: ''
+        group: [11]
         label: "dramat wsp\xF3\u0142czesny"
         link: ''
         params: '{"tag": "dramat_wspolczesny"}'
@@ -245,8 +246,8 @@
     model: toolbar.button
     pk: 21
 -   fields:
-        group: [13]
         accesskey: ''
+        group: [13]
         label: "dzie\u0142o nadrz\u0119dne"
         link: ''
         params: '{"tag": "dzielo_nadrzedne"}'
@@ -256,8 +257,8 @@
     model: toolbar.button
     pk: 38
 -   fields:
-        group: [27]
         accesskey: ''
+        group: [27]
         label: extra
         link: ''
         params: '{"tag": "extra"}'
@@ -267,8 +268,8 @@
     model: toolbar.button
     pk: 96
 -   fields:
-        group: []
         accesskey: ''
+        group: []
         label: Wydrukuj
         link: print/html
         params: '[]'
@@ -278,8 +279,8 @@
     model: toolbar.button
     pk: 87
 -   fields:
-        group: [12]
         accesskey: k
+        group: [12]
         label: kwestia
         link: ''
         params: '{"tag": "kwestia"}'
@@ -289,8 +290,8 @@
     model: toolbar.button
     pk: 82
 -   fields:
-        group: [11]
         accesskey: ''
+        group: [11]
         label: liryka
         link: ''
         params: '{"tag": "liryka_l"}'
@@ -300,8 +301,8 @@
     model: toolbar.button
     pk: 23
 -   fields:
-        group: [11]
         accesskey: ''
+        group: [11]
         label: "liryka/w. \u0142am"
         link: ''
         params: '{"tag": "liryka_lp"}'
@@ -311,8 +312,8 @@
     model: toolbar.button
     pk: 24
 -   fields:
-        group: [22]
         accesskey: ''
+        group: [22]
         label: "lista os\xF3b"
         link: ''
         params: '{"tag": "lista_osob"}'
@@ -322,8 +323,8 @@
     model: toolbar.button
     pk: 93
 -   fields:
-        group: [22]
         accesskey: ''
+        group: [22]
         label: 'typ osoby '
         link: ''
         params: '{"tag": "lista_osoba", "attrs": {"typ": ""}}'
@@ -333,8 +334,8 @@
     model: toolbar.button
     pk: 78
 -   fields:
-        group: [15]
         accesskey: ''
+        group: [15]
         label: matemat.
         link: ''
         params: '{"tag": "mat"}'
@@ -344,8 +345,8 @@
     model: toolbar.button
     pk: 47
 -   fields:
-        group: [13, 22]
         accesskey: ''
+        group: [13, 22]
         label: motto
         link: ''
         params: '{"tag": "motto"}'
@@ -355,8 +356,8 @@
     model: toolbar.button
     pk: 75
 -   fields:
-        group: [13, 22]
         accesskey: ''
+        group: [13, 22]
         label: motto podpis
         link: ''
         params: '{"tag": "motto_podpis"}'
@@ -366,8 +367,30 @@
     model: toolbar.button
     pk: 37
 -   fields:
-        group: [12]
         accesskey: ''
+        group: [2]
+        label: ",,\u2026\" na \xAB\u2026\xBB"
+        link: ''
+        params: '{"exprs": [[",,", "\u00ab"], ["\"", "\u00bb"]]}'
+        scriptlet: fulltextregexp
+        slug: na-francuskie
+        tooltip: "Zamienia cudzys\u0142owy podw\xF3jne na francuskie"
+    model: toolbar.button
+    pk: 2
+-   fields:
+        accesskey: ''
+        group: [2]
+        label: ",,\u2026\" na \xBB\u2026\xAB"
+        link: ''
+        params: '{"exprs": [[",,", "\u00bb"], ["\"", "\u00ab"]]}'
+        scriptlet: fulltextregexp
+        slug: na-niemieckie
+        tooltip: "Zamienia cudzys\u0142owy podw\xF3jne na niemieckie"
+    model: toolbar.button
+    pk: 3
+-   fields:
+        accesskey: ''
+        group: [12]
         label: "nag\u0142\xF3wek kwestii"
         link: ''
         params: '{"tag": "naglowek_osoba"}'
@@ -377,8 +400,8 @@
     model: toolbar.button
     pk: 16
 -   fields:
-        group: [22]
         accesskey: ''
+        group: [22]
         label: "nag\u0142\xF3wek listy"
         link: ''
         params: '{"tag": "naglowek_listy"}'
@@ -388,8 +411,8 @@
     model: toolbar.button
     pk: 94
 -   fields:
-        group: [13]
         accesskey: ''
+        group: [13]
         label: nazwa utworu
         link: ''
         params: '{"tag": "nazwa_utworu"}'
@@ -399,8 +422,8 @@
     model: toolbar.button
     pk: 33
 -   fields:
-        group: [13]
         accesskey: ''
+        group: [13]
         label: nota
         link: ''
         params: '{"tag": "nota"}'
@@ -410,8 +433,8 @@
     model: toolbar.button
     pk: 35
 -   fields:
-        group: [11]
         accesskey: ''
+        group: [11]
         label: opowiadanie
         link: ''
         params: '{"tag": "opowiadanie"}'
@@ -421,8 +444,8 @@
     model: toolbar.button
     pk: 18
 -   fields:
-        group: [12]
         accesskey: b
+        group: [12]
         label: osoba
         link: ''
         params: '{"tag": "osoba"}'
@@ -432,8 +455,8 @@
     model: toolbar.button
     pk: 64
 -   fields:
-        group: [22]
         accesskey: ''
+        group: [22]
         label: osoba na liscie
         link: ''
         params: '{"tag": "lista_osoba"}'
@@ -443,8 +466,8 @@
     model: toolbar.button
     pk: 95
 -   fields:
-        group: [1]
         accesskey: ''
+        group: [1]
         label: "podrozdzia\u0142"
         link: ''
         params: '{"tag": "naglowek_podrozdzial"}'
@@ -454,8 +477,8 @@
     model: toolbar.button
     pk: 12
 -   fields:
-        group: [1]
         accesskey: ''
+        group: [1]
         label: "podtytu\u0142"
         link: ''
         params: '{"tag": "podtytul"}'
@@ -465,8 +488,8 @@
     model: toolbar.button
     pk: 34
 -   fields:
-        group: [11]
         accesskey: ''
+        group: [11]
         label: "powie\u015B\u0107"
         link: ''
         params: '{"tag": "powiesc"}'
@@ -476,8 +499,8 @@
     model: toolbar.button
     pk: 19
 -   fields:
-        group: []
         accesskey: ''
+        group: []
         label: Wydrukuj
         link: print/xml
         params: '[]'
@@ -487,8 +510,8 @@
     model: toolbar.button
     pk: 86
 -   fields:
-        group: [26]
         accesskey: ''
+        group: [26]
         label: przypis autorski
         link: ''
         params: '{"tag": "pa"}'
@@ -498,8 +521,8 @@
     model: toolbar.button
     pk: 68
 -   fields:
-        group: [26]
         accesskey: ''
+        group: [26]
         label: przypis edytorski
         link: ''
         params: '{"tag": "pe"}'
@@ -509,8 +532,8 @@
     model: toolbar.button
     pk: 71
 -   fields:
-        group: [26]
         accesskey: ''
+        group: [26]
         label: przypis redaktorski
         link: ''
         params: '{"tag": "pr"}'
@@ -520,8 +543,8 @@
     model: toolbar.button
     pk: 70
 -   fields:
-        group: [26]
         accesskey: ''
+        group: [26]
         label: "przypis t\u0142umacza"
         link: ''
         params: '{"tag": "pt"}'
@@ -531,8 +554,8 @@
     model: toolbar.button
     pk: 69
 -   fields:
-        group: [1]
         accesskey: ''
+        group: [1]
         label: "rozdzia\u0142"
         link: ''
         params: '{"tag": "naglowek_rozdzial"}'
@@ -542,8 +565,8 @@
     model: toolbar.button
     pk: 11
 -   fields:
-        group: [1]
         accesskey: ''
+        group: [1]
         label: scena
         link: ''
         params: '{"tag": "naglowek_scena"}'
@@ -553,8 +576,8 @@
     model: toolbar.button
     pk: 15
 -   fields:
-        group: [16]
         accesskey: ''
+        group: [16]
         label: asterysk
         link: ''
         params: '{"nocontent": "true", "tag": "sekcja_asterysk"}'
@@ -564,8 +587,8 @@
     model: toolbar.button
     pk: 54
 -   fields:
-        group: [16]
         accesskey: ''
+        group: [16]
         label: linia
         link: ''
         params: '{"nocontent": "true", "tag": "separator_linia"}'
@@ -575,8 +598,8 @@
     model: toolbar.button
     pk: 55
 -   fields:
-        group: [16]
         accesskey: ''
+        group: [16]
         label: "\u015Bwiat\u0142o"
         link: ''
         params: '{"nocontent": "true", "tag": "sekcja_swiatlo"}'
@@ -586,8 +609,8 @@
     model: toolbar.button
     pk: 53
 -   fields:
-        group: [15]
         accesskey: ''
+        group: [15]
         label: "s\u0142owo obce"
         link: ''
         params: '{"tag": "slowo_obce"}'
@@ -597,8 +620,8 @@
     model: toolbar.button
     pk: 46
 -   fields:
-        group: [1]
         accesskey: ''
+        group: [1]
         label: "\u015Br\xF3dtytu\u0142"
         link: ''
         params: '{"tag": "srodtytul"}'
@@ -608,20 +631,8 @@
     model: toolbar.button
     pk: 13
 -   fields:
-        group: [2]
-        accesskey: ''
-        label: "Usu\u0144 spacj\u0119"
-        link: ''
-        params: '{"exprs": [["^\\s+|\\s+$", ""], ["\\s+", " "], ["(,,)\\s+", "$1"],
-            ["\\s+(\")", "$1"]]}'
-        scriptlet: lineregexp
-        slug: strip_whitespace
-        tooltip: "Usuwa zb\u0119dne spacj\u0119 z dokumentu."
-    model: toolbar.button
-    pk: 3
--   fields:
-        group: [12, 17]
         accesskey: s
+        group: [12, 17]
         label: strofa
         link: ''
         params: '{"tag": "strofa"}'
@@ -631,8 +642,8 @@
     model: toolbar.button
     pk: 81
 -   fields:
-        group: [11]
         accesskey: ''
+        group: [11]
         label: "tag g\u0142\xF3wny"
         link: ''
         params: '{"tag": "utwor"}'
@@ -642,8 +653,8 @@
     model: toolbar.button
     pk: 17
 -   fields:
-        group: [2]
         accesskey: u
+        group: [2]
         label: "A<sup>\u2193</sup>"
         link: ''
         params: '[]'
@@ -653,8 +664,8 @@
     model: toolbar.button
     pk: 76
 -   fields:
-        group: [15]
         accesskey: ''
+        group: [15]
         label: "tytu\u0142 dzie\u0142a"
         link: ''
         params: '{"tag": "tytul_dziela"}'
@@ -664,8 +675,8 @@
     model: toolbar.button
     pk: 92
 -   fields:
-        group: [15]
         accesskey: ''
+        group: [15]
         label: "tytu\u0142 dzie\u0142a typ 1"
         link: ''
         params: '{"tag": "tytul_dziela", "attrs": {"typ": "1"}}'
@@ -675,8 +686,8 @@
     model: toolbar.button
     pk: 45
 -   fields:
-        group: [27]
         accesskey: ''
+        group: [27]
         label: uwaga
         link: ''
         params: '{"tag": "uwaga"}'
@@ -686,8 +697,8 @@
     model: toolbar.button
     pk: 51
 -   fields:
-        group: [14, 17]
         accesskey: ''
+        group: [14, 17]
         label: wers akap.
         link: ''
         params: '{"tag": "wers_akap"}'
@@ -697,8 +708,8 @@
     model: toolbar.button
     pk: 83
 -   fields:
-        group: [12, 17]
         accesskey: ''
+        group: [12, 17]
         label: wers cd.
         link: ''
         params: '{"tag": "wers_cd"}'
@@ -708,8 +719,8 @@
     model: toolbar.button
     pk: 85
 -   fields:
-        group: [12, 17]
         accesskey: w
+        group: [12, 17]
         label: "wers mocno wci\u0119ty"
         link: ''
         params: '{"tag": "wers_wciety", "attrs": {"typ": ""}}'
@@ -719,8 +730,8 @@
     model: toolbar.button
     pk: 84
 -   fields:
-        group: [12, 17]
         accesskey: q
+        group: [12, 17]
         label: "wers wci\u0119ty"
         link: ''
         params: '{"tag": "wers_wciety", "attrs": {"typ": "1"}}'
@@ -730,8 +741,8 @@
     model: toolbar.button
     pk: 91
 -   fields:
-        group: [15]
         accesskey: ''
+        group: [15]
         label: www
         link: ''
         params: '{"tag": "www"}'
@@ -741,8 +752,8 @@
     model: toolbar.button
     pk: 48
 -   fields:
-        group: [15]
         accesskey: ''
+        group: [15]
         label: "wyr\xF3\u017Cnienie"
         link: ''
         params: '{"tag": "wyroznienie"}'
@@ -752,8 +763,8 @@
     model: toolbar.button
     pk: 44
 -   fields:
-        group: [11]
         accesskey: ''
+        group: [11]
         label: wywiad
         link: ''
         params: '{"tag": "wywiad"}'
@@ -763,8 +774,8 @@
     model: toolbar.button
     pk: 25
 -   fields:
-        group: [21]
         accesskey: ''
+        group: [21]
         label: "wywiad odpowied\u017A"
         link: ''
         params: '{"tag": "wywiad_odp"}'
@@ -774,8 +785,8 @@
     model: toolbar.button
     pk: 73
 -   fields:
-        group: [21]
         accesskey: ''
+        group: [21]
         label: wywiad pytanie
         link: ''
         params: '{"tag": "wywiad_pyt"}'
@@ -785,21 +796,8 @@
     model: toolbar.button
     pk: 72
 -   fields:
-        group: [2]
         accesskey: ''
-        label: "Zamie\u0144 dywiz"
-        link: ''
-        params: '{"exprs": [["(\\s)-(\\s)", "$1---$2"], ["^(\\s*)-(\\s)", "$1---$2"],
-            ["(\\s)-(\\s*)$", "$1---$2"], ["(\\d)[\u2014\u2013\u2010-](\\d)", "$1--$2"],
-            ["\u2014\u2013\u2010", "---"]]}'
-        scriptlet: lineregexp
-        slug: zamien_dywiz
-        tooltip: "Zamienia '\u2014' na '---', oraz '1\u20142' na '1--2'."
-    model: toolbar.button
-    pk: 2
--   fields:
         group: [16]
-        accesskey: ''
         label: "zast\u0119pnik wersu"
         link: ''
         params: '{"tag": "zastepnik_wersu"}'
@@ -892,4 +890,3 @@
             \r\n\r\n\r\n\r\n\r\n\r\n\r\npanel.fireEvent('contentChanged');"}
     model: toolbar.scriptlet
     pk: insert_stanza
-
diff --git a/redakcja/static/js/button_scripts.js b/redakcja/static/js/button_scripts.js
index 2a585dc5..4aa0c95a 100644
--- a/redakcja/static/js/button_scripts.js
+++ b/redakcja/static/js/button_scripts.js
@@ -48,9 +48,8 @@ function ScriptletCenter()
 {
     this.scriptlets = {};
 
-    this.scriptlets['insert_tag'] = function(context, params, done)
+    this.scriptlets['insert_tag'] = function(context, params, text, move_forward, done)
     {
-        var text = this.XMLEditorSelectedText(context);
         var start_tag = '<'+params.tag;
         var move_cursor = false;
 
@@ -95,18 +94,14 @@ function ScriptletCenter()
             }
         }
 
-        this.XMLEditorReplaceSelectedText(context, output);
-
-        try {
-            if (move_cursor) {
-                this.XMLEditorMoveCursorForward(context, params.tag.length+2);
-            }
-        } catch(e) {}
+        if (move_cursor) {
+            move_forward += params.tag.length+2;
+        }
 
-		done();
+        done(output, move_forward);
     }.bind(this);
 
-    this.scriptlets['lineregexp'] = function(context, params, done) {
+    this.scriptlets['lineregexp'] = function(context, params, text, move_forward, done) {
 		var self = this;
 
         var exprs = $.map(params.exprs, function(expr) {
@@ -120,8 +115,7 @@ function ScriptletCenter()
         });
 
         var partial = true;
-        var text = this.XMLEditorSelectedText(context);
-        if(!text) return done();
+        if(!text) done(text, move_forward);
 
         var changed = 0;
         var lines = text.split('\n');
@@ -138,15 +132,15 @@ function ScriptletCenter()
             if(old_line != line) changed += 1;
             return line;
         }, function(newlines) {
-			if(changed > 0) {
-				self.XMLEditorReplaceSelectedText(context, newlines.join('\n') );
-			};
+            if(changed > 0) {
+                text = newlines.join('\n');
+            };
 
-			done();
+            done(text, move_forward);
 		});
     }.bind(this);
 
-    this.scriptlets['fulltextregexp'] = function(context, params, done) {
+    this.scriptlets['fulltextregexp'] = function(context, params, text, move_forward, done) {
 		var self = this;
 
         var exprs = $.map(params.exprs, function(expr) {
@@ -160,47 +154,39 @@ function ScriptletCenter()
                 };
         });
 
-        var text = this.XMLEditorSelectedText(context);
-        if(!text) return done();
+        if(!text) done(text, move_forward);
         var original = text;$
 
 		nblck_each(exprs, function(expr, index) {
 			$progress.html(600 + index);
             text = text.replace(expr.rx, expr.repl);
         }, function() {
-			if( original != text) {
-         	   self.XMLEditorReplaceSelectedText(context, text);
-        	}
-
-			done();
+			done(text, move_forward);
 		});
     }.bind(this);
 
-    this.scriptlets['macro'] = function(context, params, done) {
+    this.scriptlets['macro'] = function(context, params, text, move_forward, done) {
         var self = this;
 		var i = 0;
 
-		function next() {
+		function next(text, move_forward) {
         	if (i < params.length) {
 				var e = params[i];
 				i = i + 1;
-				self.scriptlets[e[0]](context, e[1], next);
+				self.scriptlets[e[0]](context, e[1], text, move_forward, next);
 			}
 			else {
-				done();
+				done(text, move_forward);
 			}
         };
 
-		next();
+		next(text, move_forward);
     }.bind(this);
 
-    this.scriptlets['lowercase'] = function(context, params, done)
+    this.scriptlets['lowercase'] = function(context, params, text, move_forward, done)
     {
-        var text = this.XMLEditorSelectedText(context);
-
-        if(!text) return;
+        if(!text) done(text, move_forward);
 
-        var repl = '';
         var lcase = text.toLowerCase();
         var ucase = text.toUpperCase();
 
@@ -214,18 +200,14 @@ function ScriptletCenter()
                     return '';
                 }
             });
-            repl = words.join(' ');
+            text = words.join(' ');
         }
 
-        if(repl != text) this.XMLEditorReplaceSelectedText(context, repl);
-
-		done();
+        done(text, move_forward);
     }.bind(this);
 
 
-    this.scriptlets["insert_stanza"] = function(context, params, done) {
-        var text = this.XMLEditorSelectedText(context);
-
+    this.scriptlets["insert_stanza"] = function(context, params, text, move_forward, done) {
         if(text) {
             var verses = text.split('\n');
             text = ''; var buf = ''; var ebuf = '';
@@ -243,14 +225,12 @@ function ScriptletCenter()
                 }
             }
             text = text + buf + '\n</strofa>' + ebuf;
-            this.XMLEditorReplaceSelectedText(context, text);
         }
-
-        if (!text) {
-            this.XMLEditorMoveCursorForward(context, params.tag.length + 2);
+        else {
+            move_forward += params.tag.length + 2;
         }
 
-		done();
+        done(text, move_forward);
     }.bind(this);
 
 }
@@ -267,10 +247,20 @@ ScriptletCenter.prototype.callInteractive = function(opts) {
 
 	$.blockUI({message: $progress, showOverlay: false});
 
-	self.scriptlets[opts.action](opts.context, opts.extra, function(){
+    var input = self.XMLEditorSelectedText(opts.context);
+	self.scriptlets[opts.action](opts.context, opts.extra, input, 0, function(output, move_forward){
 	    /*if(timer)
 	        clearTimeout(timer);
 	    else */
+        if (input != output) {
+            self.XMLEditorReplaceSelectedText(opts.context, output)
+        }
+        if (move_forward) {
+            try {
+                self.XMLEditorMoveCursorForward(opts.context, move_forward)
+            }
+            catch(e) {}
+        }
 	    $.unblockUI(); // done
 	});
 }
-- 
2.20.1