diff --git a/pd/nw/pdgui.js b/pd/nw/pdgui.js
index 07f3ff80cbfcad632910ad2aeb9020ec00901400..1d6ce8ac362da6df13e8f488dfb90484d31f25dd 100644
--- a/pd/nw/pdgui.js
+++ b/pd/nw/pdgui.js
@@ -5560,31 +5560,25 @@ var skin = exports.skin = (function () {
     };
 }());
 
-function select_text(cid, elem, state) {
+function select_text(cid, elem, sel_start, sel_end) {
     var range, win = patchwin[cid].window;
     if (win.document.selection) {
         range = win.document.body.createTextRange();
         range.moveToElementText(elem);
-        if(state & (0b1 << 31))
-        {
-            var e = state & 0xFFFF, b = (state >>> 16) & 0x7FFF, l = elem.textContent.length;
-            var ms = Math.max(Math.min(b, l), 0);
-            var me = Math.max(Math.min(e, l), ms);
-            range.moveStart("character", ms);
-            range.moveEnd("character", me-l);
-        }
+        var len = elem.textContent.length,
+            ms = Math.max(Math.min(sel_start, len), 0),
+            me = Math.max(Math.min(sel_end, len), ms);
+        if(sel_start != -1) range.moveStart("character", ms);
+        if(sel_end != -1) range.moveEnd("character", me-len);
         range.select();
     } else if (win.getSelection) {
         range = win.document.createRange();
         range.selectNodeContents(elem);
-        if(state & (0b1 << 31))
-        {
-            var e = state & 0xFFFF, b = (state >>> 16) & 0x7FFF, l = elem.textContent.length;
-            var ms = Math.max(Math.min(b, l), 0);
-            var me = Math.max(Math.min(e, l), ms);
-            range.setStart(elem.firstChild, ms);
-            range.setEnd(elem.firstChild, me);
-        }
+        var len = elem.textContent.length,
+            ms = Math.max(Math.min(sel_start, len), 0),
+            me = Math.max(Math.min(sel_end, len), ms);
+        if(sel_start != -1) range.setStart(elem.firstChild, ms);
+        if(sel_end != -1) range.setEnd(elem.firstChild, me);
         win.getSelection().removeAllRanges();
         win.getSelection().addRange(range);
     }
@@ -5673,7 +5667,7 @@ function shove_svg_background_data_into_css(w) {
 }
 
 function gui_textarea(cid, tag, type, x, y, width_spec, height_spec, text,
-    font_size, is_gop, state) {
+    font_size, is_gop, state, sel_start, sel_end) {
     var range, svg_view, p,
         gobj = get_gobj(cid, tag);
     if (state !== 0) {
@@ -5724,11 +5718,11 @@ function gui_textarea(cid, tag, type, x, y, width_spec, height_spec, text,
         // append to doc body
         patchwin[cid].window.document.body.appendChild(p);
         p.focus();
-        select_text(cid, p, state);
-        if (state == 2) {
-            patchwin[cid].window.canvas_events.floating_text();
-        } else {
+        select_text(cid, p, sel_start, sel_end);
+        if (state === 1) {
             patchwin[cid].window.canvas_events.text();
+        } else {
+            patchwin[cid].window.canvas_events.floating_text();
         }
     } else {
         configure_item(gobj, { visibility: "normal" });
diff --git a/pd/src/g_rtext.c b/pd/src/g_rtext.c
index b82f34701c7dc14e0206fdb1a7f91b4af8ce0f86..b350f8a46c516f72a2410813e1a9aa0f3ccc377e 100644
--- a/pd/src/g_rtext.c
+++ b/pd/src/g_rtext.c
@@ -560,7 +560,8 @@ void rtext_select(t_rtext *x, int state)
 void rtext_activate(t_rtext *x, int state)
 {
     //fprintf(stderr,"rtext_activate state=%d\n", state);
-    int w = 0, h = 0, widthspec, heightspec, indx, isgop;
+    int w = 0, h = 0, widthspec, heightspec, indx, isgop,
+        selstart = -1, selend = -1;
     char *tmpbuf;
     t_glist *glist = x->x_glist;
     t_canvas *canvas = glist_getcanvas(glist);
@@ -612,6 +613,13 @@ void rtext_activate(t_rtext *x, int state)
         isgop = 0;
     }
 
+    if(state & (0b1 << 31)) /* arbitray selection */
+    {
+        selstart = (state >> 16) & 0x7FFF;
+        selend = state & 0xFFFF;
+        state = 1; // set to editing state
+    }
+
     /* we need to get scroll to make sure we've got the
        correct bbox for the svg */
     canvas_getscroll(glist_getcanvas(canvas));
@@ -622,7 +630,7 @@ void rtext_activate(t_rtext *x, int state)
     sprintf(tmpbuf, "%.*s", x->x_bufsize, x->x_buf);
     /* in case x_bufsize is 0... */
     tmpbuf[x->x_bufsize] = '\0';
-    gui_vmess("gui_textarea", "xssiiiisiii",
+    gui_vmess("gui_textarea", "xssiiiisiiiii",
         canvas,
         x->x_tag,
         (pd_class((t_pd *)x->x_text) == message_class ? "msg" : "obj"),
@@ -633,7 +641,10 @@ void rtext_activate(t_rtext *x, int state)
         tmpbuf,
         sys_hostfontsize(glist_getfont(glist)),
         isgop,
-        state);
+        state,
+        selstart,
+        selend
+        );
     freebytes(tmpbuf, x->x_bufsize + 1);
 }