diff --git a/pd/nw/index.css b/pd/nw/index.css
new file mode 100644
index 0000000000000000000000000000000000000000..4b9fd1b1e28adeb5d78c1b39a12a606d7138c2ac
--- /dev/null
+++ b/pd/nw/index.css
@@ -0,0 +1,35 @@
+body {
+    margin: 0px;
+}
+
+.noselect {
+    -webkit-touch-callout: none;
+    -webkit-user-select: none;
+    -khtml-user-select: none;
+    -moz-user-select: none;
+    -ms-user-select: none;
+    user-select: none;
+}
+
+#console_controls {
+    background-color: LightGray;
+    height: 50px; 
+} 
+
+#control_frame {
+    padding: 12px;
+}
+
+#printout {
+    margin: 8px;
+}
+
+#bottom {
+    position: absolute;
+    top: 50px;
+    left: 0px;
+    right: 0px;
+    bottom: 0px;
+    overflow-y: scroll;    
+
+}
diff --git a/pd/nw/index.html b/pd/nw/index.html
index b8f71616f4addcecd22240fb5702e1af4bf852fa..8d64aaf256ec717bde14e17e28b98f94160e1c91 100644
--- a/pd/nw/index.html
+++ b/pd/nw/index.html
@@ -1,9 +1,15 @@
 <!DOCTYPE html>
 <html>
   <head>
+    <link rel="stylesheet" type="text/css" href="index.css">
   </head>
   <body>
     <input style="display:none;" id="fileDialog" type="file" nwworkingdir multiple />
+    <div id="console_controls" class="noselect">
+      <div id="control_frame">
+    <label><input type="checkbox" id="dsp_control" name="dsp_control" value="on"/>Compute Audio</label>
+      </div>
+    </div>
     <script>
         'use strict';
         var nw = require('nw.gui');
@@ -32,7 +38,12 @@
             console.log("tried to open something");
         }, false);
 
-
+        document.getElementById("dsp_control").addEventListener("click",
+            function(evt) {
+                var dsp_state = this.checked ? 1 : 0;
+                pdgui.pdsend("pd dsp " + dsp_state);
+            }
+        );
 
 //        prompt("hey", "you");
 
@@ -449,12 +460,13 @@ function nw_close_window(window) {
     window.close(true);
 }
 
-function nw_create_window(cid, width, height, xpos, ypos, menu_flag, resize, topmost, cnv_color,
-    canvas_string, dir, dirty_flag, cargs) {
+function nw_create_window(cid, type, width, height, xpos, ypos, menu_flag, resize, topmost, cnv_color,
+    canvas_string, dir, dirty_flag, cargs, attr_array) {
         // todo: make a separate way to format the title for OSX
     var my_title =  pdgui.format_window_title(canvas_string, dirty_flag, cargs, dir);
+    var my_file = (type === 'pd-canvas' ? 'pdcanvas.html' : 'pdproperties.html');
 
-    var new_win = nw.Window.open('pdcanvas.html', {
+    var new_win = nw.Window.open(my_file, {
         title: my_title,
         position: "center",
         toolbar: true,
@@ -464,6 +476,14 @@ function nw_create_window(cid, width, height, xpos, ypos, menu_flag, resize, top
         x: xpos,
         y: ypos
     });
+    var eval_string = "register_canvas_id('" + cid + "', [" + attr_array + "]);";
+    pdgui.gui_post("eval string is " + eval_string);
+    if (attr_array !== null) {
+        pdgui.gui_post("attr_array is " + attr_array.toString());
+    }
+    new_win.on("loaded", function() {
+        new_win.eval(null, eval_string);
+    });
     return new_win;
 }
 
@@ -477,10 +497,12 @@ function canvasNew(args) {
 
     </script>
     <input style="display:none;" id="saveDialog" type="file" nwsaveas />
-
-    <pre id="p1" style="white-space: pre-wrap;">Welcome to Pd GUI using Node-Webkit
-      <script>document.write(process.versions['node-webkit'])</script><br/></pre> 
-
+    <div id = "bottom">
+      <div id = "printout">
+      <pre id="p1" style="white-space: pre-wrap;">Welcome to Pd GUI using Node-Webkit
+        <script>document.write(process.versions['node-webkit'])</script><br/></pre> 
+      </div>
+    </div>
     <script>
 
 
diff --git a/pd/nw/pdcanvas.html b/pd/nw/pdcanvas.html
index 9bd9af314103021e2233b364dd70403d8478956f..f295f3ab35d096ba467c5e271b1deee13cd3ed0f 100644
--- a/pd/nw/pdcanvas.html
+++ b/pd/nw/pdcanvas.html
@@ -1,11 +1,16 @@
 <!DOCTYPE html>
 <html>
   <head>
-  </head>
   <link rel="stylesheet" type="text/css" href="pdcanvas.css">
+  </head>
   <body>
   <input style="display:none;" id="fileDialog" type="file" multiple />
   <input style="display:none;" id="saveDialog" type="file" nwsaveas nwworkingdir accept=".pd" />
+
+  <input style="display:none;" id="openpanel_dialog" type="file" />
+  <input style="display:none;" id="savepanel_dialog" type="file" nwsaveas nwworkingdir />
+
+
   <svg xmlns="http://www.w3.org/2000/svg" version="1.1" id="patchsvg" height="1000" width="1000" class="noselect">
   <rect/>
   </svg>
@@ -14,7 +19,7 @@
     var nw = require('nw.gui'); 
     var pdgui = require('./pdgui.js');
 
-    var name = pdgui.last_loaded();
+    //var name = pdgui.last_loaded();
     
     console.log("my working dire is " + pdgui.get_pwd());
     document.getElementById("saveDialog").setAttribute("nwworkingdir", pdgui.get_pwd());
@@ -23,8 +28,29 @@
     document.getElementById("fileDialog").setAttribute("accept",
         Object.keys(pdgui.pd_filetypes).toString());
 
+    var last_keydown = "";
+
+    // This gets called from the nw_create_window function in index.html
+    // It provides us with our canvas id from the C side.  Once we have it
+    // we can create the menu and register event callbacks
+    function register_canvas_id(cid) {
+console.log("fuck you");
+        create_popup_menu(cid);
+        add_events(cid);
+        nw_create_patch_window_menus(cid);
+        pdgui.canvas_map(cid);
+    }
+
 
 
+// This could probably be in pdgui.js
+function add_keymods(key, evt) {
+    var shift = evt.shiftKey ? "Shift" : "";
+    var ctrl = evt.ctrlKey ? "Ctrl" : "";
+    return shift + ctrl + key;
+}
+
+function create_popup_menu(name) {
     // The right-click popup menu
     var popup_menu = new nw.Menu();
     pdgui.add_popup(name, popup_menu);
@@ -47,7 +73,9 @@
             pdgui.popup_action(name, 2);
         }
     }));
+}
 
+function add_events(name) {
     document.querySelector("#saveDialog").addEventListener("change", function(evt) {
         pdgui.saveas_callback(name, this.value);
         console.log("tried to open something");
@@ -62,6 +90,26 @@
         console.log("tried to open something");
     }, false);
 
+    document.querySelector("#openpanel_dialog").addEventListener("change",
+        function(evt) {
+            var file_string = this.value;
+            // reset value so that we can open the same file twice
+            this.value = null;
+            pdgui.file_dialog_callback(file_string);
+            console.log("tried to openpanel something");
+        }, false
+    );
+
+    document.querySelector("#savepanel_dialog").addEventListener("change",
+        function(evt) {
+            var file_string = this.value;
+            // reset value so that we can open the same file twice
+            this.value = null;
+            pdgui.file_dialog_callback(file_string);
+            console.log("tried to savepanel something");
+        }, false
+    );
+
 
     document.addEventListener("mousemove", function(evt) {
         //pdgui.gui_post("x: " + evt.pageX + " y: " + evt.pageY +
@@ -73,15 +121,6 @@
         return false;
     });
 
-    var last_keydown = "";
-
-
-    function add_keymods(key, evt) {
-        var shift = evt.shiftKey ? "Shift" : "";
-        var ctrl = evt.ctrlKey ? "Ctrl" : "";
-        return shift + ctrl + key;
-    }
-
     document.addEventListener("keydown", function(evt) {
         var key_code = evt.keyCode; 
         var hack = null; // hack for unprintable ascii codes
@@ -170,17 +209,16 @@
     nw.Window.get().on("close", function() {
         pdgui.pdsend(name + " menuclose 0");
     });
-    // draw the objects in the patch once we've finished loading this boilerplate page
-    // We could probably use the window.onload here, which would make it standard javascript
-    this.onload = function() {
-        pdgui.canvas_map(name);
-    };
+
+
+}
 
 
 
 
 
-nw_create_patch_window_menus(name);
+
+//nw_create_patch_window_menus(name);
 
         function menu_generic () {
             alert("Please implement this");
@@ -259,7 +297,7 @@ nw_create_patch_window_menus(name);
         }
 
 // Menus for the Patch window
-function nw_create_patch_window_menus () {
+function nw_create_patch_window_menus (name) {
 
     // Window menu
     var windowMenu = new nw.Menu({
@@ -287,7 +325,7 @@ function nw_create_patch_window_menus () {
         label: 'Open',
         key: 'o',
         modifiers: "ctrl",
-        click: function (){
+        click: function() {
             var chooser = document.querySelector('#fileDialog');
             chooser.click();
         }
@@ -392,44 +430,60 @@ function nw_create_patch_window_menus () {
 
     editMenu.append(new nw.MenuItem({
         label: 'Cut',
-        click: menu_generic,
+        click: function () {
+            pdgui.pdsend(name + " cut");
+        },
         key: 'c',
         modifiers: "ctrl"
     }));
 
     editMenu.append(new nw.MenuItem({
         label: 'Copy',
-        click: menu_generic,
-        key: 'c',
+        click: function () {
+            pdgui.pdsend(name + " copy");
+        },
+        key: 'x',
         modifiers: "ctrl"
     }));
 
     editMenu.append(new nw.MenuItem({
         label: 'Paste',
-        click: menu_generic,
-        key: 'c',
+        click: function () {
+            pdgui.pdsend(name + " paste");
+        },
+        key: 'v',
         modifiers: "ctrl"
     }));
 
 
     editMenu.append(new nw.MenuItem({
         label: 'Duplicate',
-        click: menu_generic,
-        key: 'c',
+        click: function () {
+            pdgui.pdsend(name + " duplicate");
+        },
+        key: 'd',
         modifiers: "ctrl"
     }));
 
     editMenu.append(new nw.MenuItem({
         label: 'Select All',
-        click: menu_generic,
+        click: function () {
+            pdgui.pdsend(name + " selectall");
+        },
         key: 'a',
         modifiers: "ctrl"
     }));
 
     editMenu.append(new nw.MenuItem({
         label: 'Reselect',
-        click: menu_generic,
-        key: 'a',
+        // Unfortunately nw.js doesn't allow
+        // key: "Return" or key: "Enter", so we
+        // can't bind to ctrl-Enter here. (Even
+        // tried fromCharCode...)
+        click: function () {
+            pdgui.pdsend(name + " reselect");
+        },
+        key: String.fromCharCode(10),
         modifiers: "ctrl"
     }));
 
diff --git a/pd/nw/pdgui.js b/pd/nw/pdgui.js
index 825bafcca3a97700da137998c8579acad0dca7fa..73d2b0324e949e8933c9e4f83b1e8bd6397acb36 100644
--- a/pd/nw/pdgui.js
+++ b/pd/nw/pdgui.js
@@ -15,6 +15,12 @@ exports.get_pwd = function() {
 var fs = require('fs');     // for fs.existsSync
 var path = require('path'); // for path.dirname path.extname
 
+var flub = { flash_interrupt_label: "this thing does stuff" };
+exports.tr = function(arg) {
+    return flub[arg];
+}
+
+
 var pd_window; 
 exports.pd_window;
 
@@ -161,7 +167,9 @@ function gui_post(string, color) {
     var text = pd_window.document.createTextNode(string + "\n"); 
     span.appendChild(text);
     myp.appendChild(span);
-    pd_window.window.scrollTo(0, pd_window.document.body.scrollHeight);
+    var printout = pd_window.document.getElementById("bottom");
+    printout.scrollTop = printout.scrollHeight;
+//    printout.scrollTo(0, pd_window.document.body.scrollHeight);
 }
 
 exports.gui_post = gui_post;
@@ -838,12 +846,18 @@ var scroll = {},
     loaded = {},
     popup_menu = {};
 
-    var patchwin = {}; // Associative array of patch windows
+    var patchwin = {}; // object filled with cid: [Window object] pairs
+    var dialogwin = {}; // object filled with did: [Window object] pairs
 
 exports.get_patchwin = function(name) {
     return patchwin[name];
 }
 
+exports.remove_dialogwin = function(name) {
+    dialogwin[name] = null;
+}
+
+
 // stopgap...
 pd_colors['canvas_color'] = "white";
 
@@ -968,8 +982,8 @@ function gui_canvas_new(cid, width, height, geometry, editable, name, dir, dirty
     }
     last_loaded = cid;
     // Not sure why resize and topmost are here-- but we'll pass them on for the time being...
-    patchwin[cid] = nw_create_window(cid, width, height, xpos, ypos, menu_flag,
-        resize[cid], topmost[cid], my_canvas_color, name, dir, dirty_flag, cargs);
+    patchwin[cid] = nw_create_window(cid, 'pd-canvas', width, height, xpos, ypos, menu_flag,
+        resize[cid], topmost[cid], my_canvas_color, name, dir, dirty_flag, cargs, null);
      
     // initialize variable to reflect that this window has been opened
     loaded[cid] = 1;
@@ -1804,6 +1818,13 @@ function configure_item(item, attributes) {
     }
 }
 
+// A bit of a stopgap. The GUI side probably shouldn't know about "items"
+// on SVG.
+function gui_configure_item(cid, tag, attributes) {
+    var item = get_item(cid, tag);
+    configure_item(item, attributes);
+}
+
 // Most of these map either to pd.tk procs, or in some cases Tk canvas subcommands
 function gui_text_create_gobj(cid, tag, xpos, ypos) {
     var svg = get_item(cid, "patchsvg"); // "patchsvg" is id for the svg in the DOM
@@ -1845,6 +1866,7 @@ function gui_canvas_drawio(cid, parenttag, tag, x1, y1, x2, y2, basex, basey) {
         height: y2 - y1,
         x: x1 - basex,
         y: y1 - basey,
+        id: tag,
         class: 'xlet'
     });
     g.appendChild(rect);
@@ -2000,6 +2022,7 @@ function gui_text_set (cid, tag, text) {
         svg_text.textContent = text;
     } else {
         gui_post("gui_text_set: svg_text doesn't exist!");
+        console.log("gui_text_set: " + cid + " " + tag + " " + text + " :" + "svg_text doesn't exist!");
     }
 }
 
@@ -2115,10 +2138,9 @@ function gui_create_bng(cid, tag, cx, cy, radius) {
     g.appendChild(circle);
 }
 
-function gui_bng_update(cid, tag, flashed) {
+function gui_bng_flash(cid, tag, color) {
     var button = get_item(cid, tag + 'button');
-    var fill = flashed ? 'red' : 'none';
-    configure_item(button, { fill: fill });
+    configure_item(button, { fill: color });
 }
 
 function gui_create_toggle(cid, tag, color, width, p1,p2,p3,p4,p5,p6,p7,p8,basex,basey) {
@@ -2150,15 +2172,36 @@ function gui_create_toggle(cid, tag, color, width, p1,p2,p3,p4,p5,p6,p7,p8,basex
     g.appendChild(cross2);
 }
 
-function gui_toggle_update(cid, tag, state) {
+function gui_toggle_resize_cross(cid,tag,w,p1,p2,p3,p4,p5,p6,p7,p8,basex,basey) {
+    var g = get_gobj(cid, tag);
+    var points_array = [p1 - basex, p2 - basey,
+                        p3 - basex, p4 - basey
+    ];
+    var cross1 = get_item(cid, tag + 'cross1');
+    configure_item(cross1, {
+        points: points_array.join(" "),
+        'stroke-width': w
+    });
+
+    points_array = [p5 - basex, p6 - basey,
+                    p7 - basex, p8 - basey
+    ];
+    var cross2 = get_item(cid, tag + 'cross2');
+    configure_item(cross2, {
+        points: points_array.join(" "),
+        'stroke-width': w
+    });
+}
+
+function gui_toggle_update(cid, tag, state, color) {
     var cross1 = get_item(cid, tag + 'cross1');
     var cross2 = get_item(cid, tag + 'cross2');
     if (state) {
-        configure_item(cross1, { display: 'inline' });
-        configure_item(cross2, { display: 'inline' });
+        configure_item(cross1, { display: 'inline', stroke: color });
+        configure_item(cross2, { display: 'inline', stroke: color });
     } else {
-        configure_item(cross1, { display: 'none' });
-        configure_item(cross2, { display: 'none' });
+        configure_item(cross1, { display: 'none', stroke: color });
+        configure_item(cross2, { display: 'none', stroke: color });
     }
 }
 
@@ -2356,6 +2399,13 @@ function gui_iemgui_drawborder(cid, tag, bgcolor, x1, y1, x2, y2) {
     g.appendChild(rect);
 }
 
+function gui_iemgui_redraw_border(cid, tag, x1, y1, x2, y2) {
+    var item = get_item(cid, tag + 'border');
+    configure_item(item, {
+        width: x2 - x1,
+        height: y2 - y1
+    });
+}
 
 function gui_create_mycanvas(cid,tag,color,x1,y1,x2_vis,y2_vis,x2,y2) {
     var rect_vis = create_item(cid,'rect', {
@@ -2693,3 +2743,47 @@ function gui_cord_inspector_flash(cid) {
 function gui_raise_window(cid) {
     patchwin[cid].focus();
 }
+
+// Openpanel and Savepanel
+
+var file_dialog_target;
+
+function file_dialog(cid, type, target, path) {
+    file_dialog_target = target;
+    var query_string = (type === 'open' ?
+        'openpanel_dialog' : 'savepanel_dialog');
+    var d = patchwin[cid].window.document.querySelector('#' + query_string);
+    gui_post("set path to " + path);
+    d.setAttribute("nwworkingdir", path);
+    d.click();
+}
+
+function gui_openpanel(cid, target, path) {
+    file_dialog(cid, "open", target, path);
+}
+
+function gui_savepanel(cid, target, path) {
+    file_dialog(cid, "save", target, path);
+}
+
+exports.file_dialog_callback = function(file_string) {
+    pdsend(file_dialog_target + " callback " + enquote(file_string));
+}
+
+function gui_iemgui_dialog(did, attr_array) {
+    gui_post("got a gfxstub " + did + "!!!");
+   
+    for (var i = 0; i < attr_array.length; i++) {
+        attr_array[i] = '"' + attr_array[i] + '"';
+    }
+    dialogwin[did] = nw_create_window(did, 'pd-properties', 235, 430, 20, 20, 0,
+        0, 1, 'white', 'Properties', '', 0, null, attr_array);
+
+}
+
+function gui_remove_gfxstub(did) {
+    if (dialogwin[did] !== null) {
+        dialogwin[did].window.close(true);
+        dialogwin[did] = null;
+    }
+}
diff --git a/pd/nw/pdproperties.css b/pd/nw/pdproperties.css
new file mode 100644
index 0000000000000000000000000000000000000000..88baa317e9d4a9598f82761739c0cbe90abfa5d3
--- /dev/null
+++ b/pd/nw/pdproperties.css
@@ -0,0 +1,50 @@
+@font-face {
+    font-family: "DejaVu Sans Mono";
+    src: url("DejaVuSansMono.ttf");
+}
+
+body {
+    margin: 0px;
+    font-family: "DejaVu Sans Mono";
+}
+
+.noselect {
+    -webkit-touch-callout: none;
+    -webkit-user-select: none;
+    -khtml-user-select: none;
+    -moz-user-select: none;
+    -ms-user-select: none;
+    user-select: none;
+}
+
+text {
+    // fill: red;
+    cursor: default;
+}
+
+.selected_border {
+    stroke: blue;
+    stroke-dasharray: none;
+    stroke-width: 1;
+}
+
+.selected_line {
+    stroke: blue;
+}
+
+.broken_border {
+    fill: #f7f7f7;
+    stroke: red;
+    stroke-dasharray: 3 2;
+}
+
+.xlet {
+    stroke: black;
+    fill: gray;
+    stroke-width: 1;
+    shape-rendering: optimizeSpeed;
+}
+
+//.xlet:hover {
+//    stroke: red;
+//}
diff --git a/pd/nw/pdproperties.html b/pd/nw/pdproperties.html
new file mode 100644
index 0000000000000000000000000000000000000000..f38ece9c4401224318770d494f476fb71eb8ebf4
--- /dev/null
+++ b/pd/nw/pdproperties.html
@@ -0,0 +1,336 @@
+<!DOCTYPE html>
+<html>
+  <head>
+  <link rel="stylesheet" type="text/css" href="pdproperties.css">
+
+<style>body{font-family:Verdana;}
+fieldset{font-family:Georgia; background-color:#eeeeee;
+		 border-radius:3px; border:2px solid black;
+		 margin:5px; padding:8px; }
+
+input[type="text"]{width:3em;}
+
+.prop{display: none;}
+
+</style>
+
+
+
+  </head>
+  <body>
+
+ <form> 
+     <fieldset> 
+      <legend>size and behavior</legend> 
+
+      <span class="size prop">
+        <label title="size of the iemgui">
+          size <input type="text" name="size"></label><br>
+      </span>
+
+      <span class="nonzero-value prop">
+        <label title="value to output when the toggle shows an 'x'">
+          nonzero value <input type="text" name="nonzero-value"></label><br>
+      </span>
+
+      <span class="flash-interrupt prop">
+        <label title="the amount of time (in milliseconds) that Pd will wait before interrupting the flashing of the button">
+          interrupt <input type="text" name="flash-interrupt"></label>
+      </span>
+
+      <span class="flash-hold prop">
+        <label title="the amount of time (in milliseconds) that Pd will display the flash animation">
+          hold <input type="text" name="flash-hold"></label>  <br>
+      </span>
+
+      <span class="min-range prop">
+        <label title="the lowest number to output. Anything lower will be replaced by this number">
+          minimum <input type="text" name="min-range"></label>
+        <label title="the largest number to output. Anything higher will be replaced by this number">
+          maximum <input type="text" name="max-range"></label>  <br>
+      </span>
+
+      <span class="init prop">
+        <label title="when checked, this will save the state of the iemgui with the patch, and output a value when the patch is loaded (as if you had an invisible [loadbang] connected to the input).">
+          init <input type="checkbox" name="init" value="on" ></label> <br>
+      </span>
+     </fieldset> 
+
+     <fieldset> 
+      <legend>messages</legend> 
+
+      <span class="send-symbol prop">
+        <label title="symbol you can use to send wireless messages to other iemguis (or a [receive] object)">
+          send-symbol <input type="text" name="send-symbol" ></label> <br>
+      </span>
+
+      <span class="receive-symbol prop">
+        <label title="symbol you can use to receive wireless messages from other iemguis (or from a [send] object)">
+          receive-symbol <input type="text" name="receive-symbol" ></label> <br>
+      </span>
+     </fieldset> 
+
+     <fieldset> 
+      <legend>label</legend> 
+
+      <span class="label prop">
+        <label title="a label displayed next to this iemgui">
+          label <input type="text" name="label" > <br>
+      </span>
+
+      <span class="x-offset prop">
+        <label title="horizontal offset (from the top-left corner of the object) for the label">
+          x offset <input type="text" name="x-offset" ></label>
+        <label title="vertical offset (from the top-left corner of the object) for the label">
+          y offset <input type="text" name="y-offset"></label> <br>
+      </span>
+
+      <span class="font-style prop">
+        <label title="which font to use to display the label">
+          font <input type="text" name="font-style"></label>
+        <label title="size of the label">size <input type="text" name="font-size"><label> <br>
+      </span>
+     </fieldset> 
+
+     <fieldset> 
+      <legend>colors</legend> 
+
+      <span class="background-color prop">
+        <label title="background color for the object">
+          background <input type="color" name="background-color"></label> <br>
+      </span>
+
+      <span class="foreground-color prop">
+        <label title="foreground color for the object">
+          foreground <input type="color" name="foreground-color"></label> <br>
+      </span>
+
+      <span class="label-color prop">
+        <label title="color of the label text">
+          label <input type="color" name="label-color"></title> <br>
+      </span>
+     </fieldset> 
+
+     <span class="prop">
+       <input type="hidden" name="minimum-size">
+       <input type="hidden" name="range-schedule">
+     </span>
+
+     <div style="text-align: center">
+      <button type="button" onClick="ok()" title="Apply these settings and close the window">Ok</button>
+      <button type="button" onClick="apply()" title="Apply these settings without closing the window">Apply</button>
+      <button type="button" onClick="cancel()" title="Close window without applying any changes">Cancel</button>
+     </div>
+
+ </form> 
+        
+
+  <script>
+    'use strict';
+    var nw = require('nw.gui'); 
+    var pdgui = require('./pdgui.js');
+
+    console.log("my working dire is " + pdgui.get_pwd());
+
+    var pd_object_callback;
+
+    function ok() {
+        apply();
+        cancel();
+    }
+
+    function substitute_space(arg) {
+        var fake_space = String.fromCharCode(11);
+        return arg.split(' ').join(fake_space);
+    }
+
+    function strip_problem_chars(arg) {
+        var problem_chars = [';', ',', '{', '}', '\\'];
+        var ret = arg;
+        for(var i = 0; i < problem_chars.length; i++) {
+            ret = ret.split(';').join('');
+        }
+        return ret;
+    }
+
+    function apply() {
+        pdgui.gui_post("we're applying shits!");
+
+        /* Not sure what these are...
+            iemgui_clip_dim $id
+            iemgui_clip_num $id
+            iemgui_sched_rng $id
+            iemgui_verify_rng $id
+            iemgui_sched_rng $id
+            iemgui_clip_fontsize $id
+        */	
+
+        var send_symbol = document.getElementsByName('send-symbol')[0].value;
+        var receive_symbol = document.getElementsByName('receive-symbol')[0].value;
+        var label =  document.getElementsByName('label')[0].value;
+        if (send_symbol === null || send_symbol === '') { send_symbol = 'empty'; }
+        if (receive_symbol === null || receive_symbol === '') { receive_symbol = 'empty'; }
+        if (label === null || label === '') { label = 'empty'; }
+
+        console.log("send_symbol is " + send_symbol);
+
+        if (send_symbol.charAt(0) === '$') {
+            send_symbol = '#' + send_symbol.slice(1);
+        }
+        if (receive_symbol.charAt(0) === '$') {
+            receive_symbol = '#' + receive_symbol.slice(1);
+        }
+        if (label.charAt(0) === '$') {
+            label = '#' + label.slice(1);
+        }
+
+        send_symbol = substitute_space(send_symbol);
+        receive_symbol = substitute_space(receive_symbol);
+        label = substitute_space(label);
+
+        send_symbol = strip_problem_chars(send_symbol);
+        receive_symbol = strip_problem_chars(receive_symbol);
+        label = strip_problem_chars(label);
+
+        var label_x_offset =  document.getElementsByName('x-offset')[0].value;
+        var label_y_offset =  document.getElementsByName('y-offset')[0].value;
+
+	// make sure the offset boxes have a value
+        if (label_x_offset === null) { label_x_offset = 0; }
+        if (label_y_offset === null) { label_y_offset = 0; }
+
+        var height, width;
+        var size = document.getElementsByName('size')[0].value;
+        if (size !== null) {
+            height = size;
+            width = size;
+        }
+
+        var slot3 = document.getElementsByName('min-range')[0].value;
+        var slot4 = document.getElementsByName('max-range')[0].value;
+
+        pdgui.gui_post("min-range is " + slot3);
+
+        if (slot3 === '') {
+            slot3 = document.getElementsByName('flash-interrupt')[0].value;
+            slot4 = document.getElementsByName('flash-hold')[0].value;
+         pdgui.gui_post("slot3 is now " + slot3);
+        }
+
+        if (slot3 === '') { // toggle
+            slot3 = document.getElementsByName('nonzero-value')[0].value;
+            slot4 = 0;
+        }
+
+        var init = document.getElementsByName('init')[0].value;
+        if (init !== null) { init = 0; }
+
+        var font_style = document.getElementsByName('font-style')[0].value;
+        if (font_style !== null) { font_style = 0; }
+
+        var font_size = document.getElementsByName('font-size')[0].value;
+        if (font_size !== null) { font_size = 0; }
+
+        var foreground_color = parseInt(document.getElementsByName('foreground-color')[0].value.slice(1), 16);
+        var background_color = parseInt(document.getElementsByName('background-color')[0].value.slice(1), 16);
+        var label_color = parseInt(document.getElementsByName('label-color')[0].value.slice(1), 16);
+
+        pdgui.pdsend([pd_object_callback, 'dialog',
+            width, height,
+            slot3, // flash-interrupt, min-range, or nonzero-value
+            slot4, // flash-hold or max-range
+            0, // this should be the lin/log thingy
+            init,
+            0, // this should be the number for toggle
+            send_symbol, receive_symbol, label,
+            label_x_offset, label_y_offset,
+            font_style, font_size,
+            background_color, foreground_color,
+            label_color,
+            0, // steady on click
+            0].join(' '));
+/*
+	pd [concat $id dialog \
+		$::dialog($vid:wdt) $::dialog($vid:hgt) \
+		$::dialog($vid:min_rng) $::dialog($vid:max_rng) \
+		$::dialog($vid:lin0_log1) $::dialog($vid:loadbang) \
+		$::dialog($vid:num) \
+		$hhhsnd $hhhrcv $hhhgui_nam \
+		$::dialog($vid:gn_dx) $::dialog($vid:gn_dy) \
+		$::dialog($vid:gn_f) $::dialog($vid:gn_fs) \
+		$::dialog($vid:bcol) $::dialog($vid:fcol) \
+		$::dialog($vid:lcol) \
+		$::dialog($vid:steady) $::dialog($vid:hide) \;]
+*/
+
+    }
+
+    function cancel() {
+        pdgui.gui_post("closing the window at this point");
+//        window.close(true);
+        pdgui.pdsend(pd_object_callback + " cancel");
+    }
+
+    // This gets called from the nw_create_window function in index.html
+    // It provides us with our window id from the C side.  Once we have it
+    // we can create the menu and register event callbacks
+    function register_canvas_id(gfxstub, attr_array) {
+        pd_object_callback = gfxstub;
+
+        console.log('attr array is ' + attr_array.toString());
+        for (var i = 0; i < attr_array.length; i+=2) {
+            console.log(attr_array[i] + ": " + attr_array[i+1]);
+        }
+        add_events(gfxstub);
+        // not sure that we need this for properties windows
+//        pdgui.canvas_map(gfxstub);
+        populate_form(attr_array);
+//        document.getElementsByClass("fumbles")[0].setAttribute('style', 'display: inline;');
+    }
+
+function populate_form(attr_array) {
+    for(var i = 0; i < attr_array.length; i+=2) {
+        // Unhide the span with the class with the same name as the id
+        var prop_group = document.getElementsByClassName(attr_array[i])[0];
+        if (prop_group !== undefined) {
+            console.log("the thing here is " + attr_array[i]);
+            prop_group.style.setProperty('display', 'inline');
+        } else {
+            pdgui.gui_post("Error: couldn't find iemgui prop group for " + attr_array[i]);
+        }
+        // iemguis use the string 'empty' for null because of
+        // the limitations of Pd's state-saving API.  So we have
+        // to filter that one out
+        if(attr_array[i+1] !== 'empty') {
+            var elem = document.getElementsByName(attr_array[i]);
+            if (elem.length > 0) {
+                if(attr_array[i].slice(-5) === 'color') {
+                    var hex_string = Number(attr_array[i+1]).toString(16);
+                    var color_string = "#" + (hex_string === '0' ? '000000' : hex_string);
+                    pdgui.gui_post("color is " + color_string);
+                    elem[0].value = color_string;
+                } else {
+                    elem[0].value = attr_array[i+1];
+                }
+            }
+        }
+    }
+}
+
+function add_events(name) {
+    // let's handle some events for this window...
+
+    // closing the Window
+    nw.Window.get().on("close", function() {
+        // this needs to do whatever the "cancel" button does
+//        pdgui.pdsend(name + " menuclose 0");
+//        cancel();
+        pdgui.remove_dialogwin(pd_object_callback);
+        this.close(true);
+    });
+
+}
+
+  </script>
+  </body>
+</html>
diff --git a/pd/nw/todo.txt b/pd/nw/todo.txt
index 9946e7abf9e596cc2a3c491b25b0ad069eb1cb87..99327ecda8b9ee8ed0051599fb292837c110b05d 100644
--- a/pd/nw/todo.txt
+++ b/pd/nw/todo.txt
@@ -78,3 +78,13 @@ Everything else:
   it will try to flash a non-existent svg item.  (Probably want to either make a permanent item in
   the pdcanvas.html for it, or hard-code a separate div.)
 * for data structures, change "" to 'none'
+* fix "Reselect" <ctrl-Enter> Keybinding.  It doesn't work atm because nw.js
+  cannot bind to Enter.
+* looks like nwworkingdir isn't working for open/save dialogs atm
+* keyup doesn't register autokeypresses, but keyname and key do
+* text_set doesn't work when a numbox is first created (but works otherwise)
+* clean up nw_create_window (doesn't need so many parameters)
+* make a nice window API in C.  Window "foo-bar" type maps to "foo-bar.html"
+* implement the crappy iemgui color dialog presets
+* find a simple translation API
+* use underscores for iemgui dialog element names
diff --git a/pd/src/g_all_guis.c b/pd/src/g_all_guis.c
index 312d1e51c4865840ad682ac87fc9b56cb3a07c02..5d3ecbe35f0e0f1b4baa6cd67e5bb982967f6aa9 100644
--- a/pd/src/g_all_guis.c
+++ b/pd/src/g_all_guis.c
@@ -1041,10 +1041,12 @@ void iemgui_draw_io(t_iemgui *x, int old_sr_flags)
              canvas, x1+i*k, y2-1, x1+i*k + IOWIDTH, y2,
              iem_get_tag(canvas, x), i, x,
              x->x_selected == x->x_glist ? "iemgui selected" : "iemgui");
+        char parenttagbuf[MAXPDSTRING];
         char tagbuf[MAXPDSTRING];
-        sprintf(tagbuf, "x%lx", (long unsigned int)x);
-        gui_vmess("gui_canvas_drawio", "sssiiiiii", canvas_string(canvas), tagbuf,
-            iem_get_tag(canvas, x), x1+i*k, y2-1, x1+i*k + IOWIDTH, y2, x1, y1);
+        sprintf(parenttagbuf, "x%lx", (long unsigned int)x);
+        sprintf(tagbuf, "%so%d", iem_get_tag(canvas, x), i);
+        gui_vmess("gui_canvas_drawio", "sssiiiiii", canvas_string(canvas), parenttagbuf,
+            tagbuf, x1+i*k, y2-1, x1+i*k + IOWIDTH, y2, x1, y1);
     }
     if(!a && b) for (i=0; i<n; i++)
         sys_vgui(".x%lx.c delete %so%d\n", canvas, iem_get_tag(canvas, x), i);
@@ -1060,10 +1062,12 @@ void iemgui_draw_io(t_iemgui *x, int old_sr_flags)
              canvas, x1+i*k, y1, x1+i*k + IOWIDTH, y1+1,
              iem_get_tag(canvas, x), i, x,
              x->x_selected == x->x_glist ? "iemgui selected" : "iemgui");
+        char parenttagbuf[MAXPDSTRING];
         char tagbuf[MAXPDSTRING];
-        sprintf(tagbuf, "x%lx", (long unsigned int)x);
-        gui_vmess("gui_canvas_drawio", "sssiiiiii", canvas_string(canvas), tagbuf,
-            iem_get_tag(canvas, x), x1+i*k, y1, x1+i*k + IOWIDTH, y1+1, x1, y1);
+        sprintf(parenttagbuf, "x%lx", (long unsigned int)x);
+        sprintf(tagbuf, "%si%d", iem_get_tag(canvas, x), i);
+        gui_vmess("gui_canvas_drawio", "sssiiiiii", canvas_string(canvas), parenttagbuf,
+            tagbuf, x1+i*k, y1, x1+i*k + IOWIDTH, y1+1, x1, y1);
     }
     if(!a && b) for (i=0; i<n; i++)
         sys_vgui(".x%lx.c delete %si%d\n", canvas, iem_get_tag(canvas, x), i);
@@ -1076,11 +1080,36 @@ void iemgui_io_draw_move(t_iemgui *x) {
     c->c_wb->w_getrectfn((t_gobj *)x,canvas,&x1,&y1,&x2,&y2);
     int i, n = c==vu_class ? 2 : 1, k=(x2-x1)-IOWIDTH;
     if(!iemgui_has_snd(x) && canvas == x->x_glist) for (i=0; i<n; i++)
-        sys_vgui(".x%lx.c coords %so%d %d %d %d %d\n",
-            canvas, iem_get_tag(canvas, x), i, x1+i*k, y2-1, x1+i*k+IOWIDTH, y2);
+    {
+        //sys_vgui(".x%lx.c coords %so%d %d %d %d %d\n",
+        //    canvas, iem_get_tag(canvas, x), i, x1+i*k, y2-1, x1+i*k+IOWIDTH, y2);
+        char tagbuf[MAXPDSTRING];
+        sprintf(tagbuf, "%so%d", iem_get_tag(canvas, x), i);
+        gui_start_vmess("gui_configure_item", "ss",
+            canvas_string(canvas), tagbuf);
+        gui_start_array();
+        gui_string_elem("x");
+        gui_int_elem(i*k);
+        gui_string_elem("y");
+        gui_int_elem(y2 - y1 - 1);
+        gui_end_array();
+        gui_end_vmess();
+    }
     if(!iemgui_has_rcv(x) && canvas == x->x_glist) for (i=0; i<n; i++)
+    {
         sys_vgui(".x%lx.c coords %si%d %d %d %d %d\n",
             canvas, iem_get_tag(canvas, x), i, x1+i*k, y1, x1+i*k+IOWIDTH, y1+1);
+        char tagbuf[MAXPDSTRING];
+        sprintf(tagbuf, "%si%d", iem_get_tag(canvas, x), i);
+        gui_start_vmess("gui_configure_item", "ss",
+            canvas_string(canvas), tagbuf);
+        gui_start_array();
+        gui_string_elem("x");
+        gui_int_elem(i*k);
+        gui_end_array();
+        gui_end_vmess();
+
+    }
 }
 
 void iemgui_base_draw_new(t_iemgui *x) {
@@ -1109,13 +1138,27 @@ void iemgui_base_draw_move(t_iemgui *x) {
     int x1,y1,x2,y2,gr=gop_redraw; gop_redraw=0;
     c->c_wb->w_getrectfn((t_gobj *)x,x->x_glist,&x1,&y1,&x2,&y2);
     gop_redraw=gr;
-    sys_vgui(".x%lx.c coords %lxBASE %d %d %d %d\n", canvas, x, x1, y1, x2, y2);
+    //sys_vgui(".x%lx.c coords %lxBASE %d %d %d %d\n", canvas, x, x1, y1, x2, y2);
+    char tagbuf[MAXPDSTRING];
+    sprintf(tagbuf, "x%lx", (long unsigned int)x);
+    gui_vmess("gui_iemgui_redraw_border", "ssiiii",
+        canvas_string(canvas), tagbuf, x1, y1, x2, y2);
 }
 
 void iemgui_base_draw_config(t_iemgui *x) {
     t_canvas *canvas=glist_getcanvas(x->x_glist);
     char fcol[8]; sprintf(fcol,"#%6.6x", x->x_fcol);
-    sys_vgui(".x%lx.c itemconfigure %lxBASE -fill #%6.6x\n", canvas, x, x->x_bcol);
+    //sys_vgui(".x%lx.c itemconfigure %lxBASE -fill #%6.6x\n", canvas, x, x->x_bcol);
+    char tagbuf[MAXPDSTRING];
+    char bcol[8]; sprintf(bcol, "#%6.6x", x->x_bcol);
+    sprintf(tagbuf, "x%lxborder", (long unsigned int)x);
+    gui_start_vmess("gui_configure_item", "ss",
+        canvas_string(canvas), tagbuf);
+    gui_start_array();
+    gui_string_elem("fill");
+    gui_string_elem(bcol);
+    gui_end_array();
+    gui_end_vmess();
 }
 
 void iemgui_draw_update(t_iemgui *x, t_glist *glist) {
diff --git a/pd/src/g_bang.c b/pd/src/g_bang.c
index 3ca7b2e71265f89cb277c1f8d9ce1fbb4337affb..5dce220836980340399826dac8761573ebb280d3 100644
--- a/pd/src/g_bang.c
+++ b/pd/src/g_bang.c
@@ -25,6 +25,7 @@ static t_class *bng_class;
 void bng_draw_update(t_gobj *xgobj, t_glist *glist)
 {
     char tagbuf[MAXPDSTRING];
+    char flashcol[8];
     t_bng *x = (t_bng *)xgobj;
     sprintf(tagbuf, "x%lx", (long unsigned int)&x->x_gui);
     if (x->x_gui.x_changed != x->x_flashed && glist_isvisible(glist))
@@ -32,8 +33,10 @@ void bng_draw_update(t_gobj *xgobj, t_glist *glist)
 //        sys_vgui(".x%lx.c itemconfigure %lxBUT -fill #%6.6x\n",
 //            glist_getcanvas(glist), x,
 //            x->x_flashed?x->x_gui.x_fcol:x->x_gui.x_bcol);
-        gui_vmess("gui_bng_update", "ssi",
-            canvas_string(glist_getcanvas(glist)), tagbuf, x->x_flashed);
+        sprintf(flashcol, "#%6.6x",
+            x->x_flashed ? x->x_gui.x_fcol : x->x_gui.x_bcol);
+        gui_vmess("gui_bng_flash", "sss",
+            canvas_string(glist_getcanvas(glist)), tagbuf, flashcol);
     }
     x->x_gui.x_changed = x->x_flashed;
 }
@@ -70,17 +73,45 @@ void bng_draw_move(t_bng *x, t_glist *glist)
     t_float cr = (x->x_gui.x_w-2)/2.0;
     t_float cx = x1+cr+1.5;
     t_float cy = y1+cr+1.5;
-    sys_vgui(".x%lx.c coords %lxBUT %f %f\n", canvas, x, cx, cy);
-    sys_vgui(".x%lx.c itemconfigure %lxBUT -fill #%6.6x -r %f\n",
-        canvas, x, x->x_flashed?x->x_gui.x_fcol:x->x_gui.x_bcol, cr);
+    //sys_vgui(".x%lx.c coords %lxBUT %f %f\n", canvas, x, cx, cy);
+    //sys_vgui(".x%lx.c itemconfigure %lxBUT -fill #%6.6x -r %f\n",
+    //    canvas, x, x->x_flashed?x->x_gui.x_fcol:x->x_gui.x_bcol, cr);
+    char tagbuf[MAXPDSTRING];
+    sprintf(tagbuf, "x%lxbutton", (long unsigned int)x);
+    char col[8];
+    sprintf(col, "#%6.6x", x->x_flashed ? x->x_gui.x_fcol : x->x_gui.x_bcol);
+    gui_start_vmess("gui_configure_item", "ss",
+        canvas_string(canvas), tagbuf);
+    gui_start_array();
+    gui_string_elem("cx");
+    gui_float_elem(cx - x1 - 0.5); // 0.5 is fudge factor... might be better
+    gui_string_elem("cy");
+    gui_float_elem(cy - y1 - 0.5); // handled by shape-rendering css attr
+    gui_string_elem("r");
+    gui_float_elem(cr);
+    gui_string_elem("fill");
+    gui_string_elem(col);
+    gui_end_array();
+    gui_end_vmess();
 }
 
 void bng_draw_config(t_bng* x, t_glist* glist)
 {
     t_canvas *canvas=glist_getcanvas(glist);
     iemgui_base_draw_config(&x->x_gui);
-    sys_vgui(".x%lx.c itemconfigure %lxBUT -fill #%6.6x\n",
-        canvas, x, x->x_flashed?x->x_gui.x_fcol:x->x_gui.x_bcol);
+    //sys_vgui(".x%lx.c itemconfigure %lxBUT -fill #%6.6x\n",
+    //    canvas, x, x->x_flashed?x->x_gui.x_fcol:x->x_gui.x_bcol);
+    char tagbuf[MAXPDSTRING];
+    sprintf(tagbuf, "x%lxbutton", (long unsigned int)x);
+    char fcol[8];
+    sprintf(fcol, "#%6.6x", x->x_flashed ? x->x_gui.x_fcol : x->x_gui.x_bcol);
+    gui_start_vmess("gui_configure_item", "ss",
+        canvas_string(canvas), tagbuf);
+    gui_start_array();
+    gui_string_elem("fill");
+    gui_string_elem(fcol);
+    gui_end_array();
+    gui_end_vmess();
 }
 
 static void bng__clickhook(t_scalehandle *sh, int newstate)
@@ -181,7 +212,7 @@ void bng_check_minmax(t_bng *x, int ftbreak, int fthold)
 static void bng_properties(t_gobj *z, t_glist *owner)
 {
     t_bng *x = (t_bng *)z;
-    char buf[800];
+    char buf[800], *gfx_tag;
     t_symbol *srl[3];
 
     iemgui_properties(&x->x_gui, srl);
@@ -189,14 +220,83 @@ static void bng_properties(t_gobj *z, t_glist *owner)
         ----------dimensions(pix):----------- %d %d size: 0 0 empty \
         --------flash-time(ms)(ms):--------- %d intrrpt: %d hold: %d \
         %d empty empty %d %d empty %d {%s} {%s} {%s} %d %d %d %d %d %d %d\n",
-        x->x_gui.x_w, IEM_GUI_MINSIZE,
-        x->x_flashtime_break, x->x_flashtime_hold, 2,/*min_max_schedule+clip*/
-        -1, x->x_gui.x_loadinit, -1, -1,/*no linlog, no multi*/
+
+        x->x_gui.x_w,
+        IEM_GUI_MINSIZE,
+        x->x_flashtime_break,
+        x->x_flashtime_hold,
+        2, /*min_max_schedule+clip*/
+        -1,
+        x->x_gui.x_loadinit,
+        -1,
+        -1, /*no linlog, no multi*/
         srl[0]->s_name, srl[1]->s_name, srl[2]->s_name,
         x->x_gui.x_ldx, x->x_gui.x_ldy,
         x->x_gui.x_font_style, x->x_gui.x_fontsize,
-        0xffffff & x->x_gui.x_bcol, 0xffffff & x->x_gui.x_fcol, 0xffffff & x->x_gui.x_lcol);
-    gfxstub_new(&x->x_gui.x_obj.ob_pd, x, buf);
+        0xffffff & x->x_gui.x_bcol,
+        0xffffff & x->x_gui.x_fcol,
+        0xffffff & x->x_gui.x_lcol);
+
+    gfx_tag = gfxstub_new2(&x->x_gui.x_obj.ob_pd, x);
+    /* todo: send along the x/y of the object here so we can
+       create the window in the right place */
+
+    gui_start_vmess("gui_iemgui_dialog", "s", gfx_tag);
+    gui_start_array();
+
+    gui_string_elem("type");
+    gui_string_elem("bng");
+
+    gui_string_elem("size"); 
+    gui_int_elem(x->x_gui.x_w);
+
+    gui_string_elem("minimum-size");
+    gui_int_elem(IEM_GUI_MINSIZE);
+
+    gui_string_elem("range-schedule"); // no idea what this is...
+    gui_int_elem(2);
+
+    gui_string_elem("flash-interrupt");
+    gui_int_elem(x->x_flashtime_break);
+
+    gui_string_elem("flash-hold");
+    gui_int_elem(x->x_flashtime_hold);
+
+    gui_string_elem("init");
+    gui_int_elem(x->x_gui.x_loadinit);
+
+    gui_string_elem("send-symbol");
+    gui_string_elem(srl[0]->s_name);
+
+    gui_string_elem("receive-symbol");
+    gui_string_elem(srl[1]->s_name);
+
+    gui_string_elem("label");
+    gui_string_elem(srl[2]->s_name);
+
+    gui_string_elem("x-offset");
+    gui_int_elem(x->x_gui.x_ldx);
+
+    gui_string_elem("y-offset");
+    gui_int_elem(x->x_gui.x_ldy);
+
+    gui_string_elem("font-style");
+    gui_int_elem(x->x_gui.x_font_style);
+
+    gui_string_elem("font-size");
+    gui_int_elem(x->x_gui.x_fontsize);
+
+    gui_string_elem("background-color");
+    gui_int_elem(0xffffff & x->x_gui.x_bcol);
+
+    gui_string_elem("foreground-color");
+    gui_int_elem(0xffffff & x->x_gui.x_fcol);
+
+    gui_string_elem("label-color");
+    gui_int_elem(0xffffff & x->x_gui.x_lcol);
+
+    gui_end_array();
+    gui_end_vmess();
 }
 
 static void bng_set(t_bng *x)
diff --git a/pd/src/g_toggle.c b/pd/src/g_toggle.c
index f91af52f49af9f933b6b38841cb1d7b07eb6d1c1..2d51e3f0b18ba3fec010845c8ffb7589af329ddc 100644
--- a/pd/src/g_toggle.c
+++ b/pd/src/g_toggle.c
@@ -31,9 +31,11 @@ void toggle_draw_update(t_gobj *xgobj, t_glist *glist)
             sys_vgui(".x%lx.c itemconfigure %lxX2 -stroke #%6.6x\n", canvas, x,
                      (x->x_on!=0.0)?x->x_gui.x_fcol:x->x_gui.x_bcol);
             char tagbuf[MAXPDSTRING];
+            char colorbuf[MAXPDSTRING];
             sprintf(tagbuf, "x%lx", (long unsigned int)x);
-            gui_vmess("gui_toggle_update", "ssi", canvas_string(canvas),
-                tagbuf, x->x_on != 0.0);
+            sprintf(colorbuf, "#%6.6x", x->x_gui.x_fcol);
+            gui_vmess("gui_toggle_update", "ssis", canvas_string(canvas),
+                tagbuf, x->x_on != 0.0, colorbuf);
         }
         x->x_gui.x_changed = 0;
     }
@@ -52,12 +54,12 @@ void toggle_draw_new(t_toggle *x, t_glist *glist)
     sprintf(colorbuf, "#%6.6x", x->x_gui.x_fcol);
 
     iemgui_base_draw_new(&x->x_gui);
-    sys_vgui(".x%lx.c create polyline %d %d %d %d -strokewidth %d "
-        "-stroke #%6.6x -tags {%lxX1 x%lx text iemgui}\n",
-        canvas, x1+w+1, y1+w+1, x2-w-1, y2-w-1, w, col, x, x);
-    sys_vgui(".x%lx.c create polyline %d %d %d %d -strokewidth %d "
-        "-stroke #%6.6x -tags {%lxX2 x%lx text iemgui}\n",
-        canvas, x1+w+1, y2-w-1, x2-w-1, y1+w+1, w, col, x, x);
+    //sys_vgui(".x%lx.c create polyline %d %d %d %d -strokewidth %d "
+    //    "-stroke #%6.6x -tags {%lxX1 x%lx text iemgui}\n",
+    //    canvas, x1+w+1, y1+w+1, x2-w-1, y2-w-1, w, col, x, x);
+    //sys_vgui(".x%lx.c create polyline %d %d %d %d -strokewidth %d "
+    //    "-stroke #%6.6x -tags {%lxX2 x%lx text iemgui}\n",
+    //    canvas, x1+w+1, y2-w-1, x2-w-1, y1+w+1, w, col, x, x);
     gui_vmess("gui_create_toggle", "sssiiiiiiiiiii", canvas_string(canvas), tagbuf,
         colorbuf, w,
         x1+w+1, y1+w+1, x2-w-1, y2-w-1,
@@ -74,18 +76,32 @@ void toggle_draw_move(t_toggle *x, t_glist *glist)
 
     iemgui_base_draw_move(&x->x_gui);
     sys_vgui(".x%lx.c itemconfigure {%lxX1||%lxX2} -strokewidth %d\n", canvas, x, x, w);
-    sys_vgui(".x%lx.c coords %lxX1 %d %d %d %d\n",
-        canvas, x, x1+s, y1+s, x2-s, y2-s);
-    sys_vgui(".x%lx.c coords %lxX2 %d %d %d %d\n",
-        canvas, x, x1+s, y2-s, x2-s, y1+s);
+    //sys_vgui(".x%lx.c coords %lxX1 %d %d %d %d\n",
+    //    canvas, x, x1+s, y1+s, x2-s, y2-s);
+    //sys_vgui(".x%lx.c coords %lxX2 %d %d %d %d\n",
+    //    canvas, x, x1+s, y2-s, x2-s, y1+s);
+    char tagbuf[MAXPDSTRING];
+    sprintf(tagbuf, "x%lx", (long unsigned int)x);
+    gui_vmess("gui_toggle_resize_cross", "ssiiiiiiiiiii",
+        canvas_string(canvas), tagbuf,
+        w,
+        x1+s, y1+s, x2-s, y2-s,
+        x1+s, y2-s, x2-s, y1+s,
+        x1, y1);
 }
 
 void toggle_draw_config(t_toggle* x, t_glist* glist)
 {
     t_canvas *canvas=glist_getcanvas(glist);
     iemgui_base_draw_config(&x->x_gui);
-    sys_vgui(".x%lx.c itemconfigure {%lxX1||%lxX2} -stroke #%6.6x\n",
-        canvas, x, x, x->x_on?x->x_gui.x_fcol:x->x_gui.x_bcol);
+    //sys_vgui(".x%lx.c itemconfigure {%lxX1||%lxX2} -stroke #%6.6x\n",
+    //    canvas, x, x, x->x_on?x->x_gui.x_fcol:x->x_gui.x_bcol);
+    char tagbuf[MAXPDSTRING];
+    char colorbuf[MAXPDSTRING];
+    sprintf(tagbuf, "x%lx", (long unsigned int)x);
+    sprintf(colorbuf, "#%6.6x", x->x_gui.x_fcol);
+    gui_vmess("gui_toggle_update", "ssis", canvas_string(canvas),
+    tagbuf, x->x_on != 0.0, colorbuf);
 }
 
 static void toggle__clickhook(t_scalehandle *sh, int newstate)
@@ -171,7 +187,7 @@ static void toggle_save(t_gobj *z, t_binbuf *b)
 static void toggle_properties(t_gobj *z, t_glist *owner)
 {
     t_toggle *x = (t_toggle *)z;
-    char buf[800];
+    char buf[800], *gfx_tag;
     t_symbol *srl[3];
     iemgui_properties(&x->x_gui, srl);
     sprintf(buf, "pdtk_iemgui_dialog %%s |tgl| \
@@ -185,7 +201,62 @@ static void toggle_properties(t_gobj *z, t_glist *owner)
         x->x_gui.x_ldx, x->x_gui.x_ldy,
         x->x_gui.x_font_style, x->x_gui.x_fontsize,
         0xffffff & x->x_gui.x_bcol, 0xffffff & x->x_gui.x_fcol, 0xffffff & x->x_gui.x_lcol);
-    gfxstub_new(&x->x_gui.x_obj.ob_pd, x, buf);
+    //gfxstub_new(&x->x_gui.x_obj.ob_pd, x, buf);
+    gfx_tag = gfxstub_new2(&x->x_gui.x_obj.ob_pd, x);
+
+    gui_start_vmess("gui_iemgui_dialog", "s", gfx_tag);
+    gui_start_array();
+
+    gui_string_elem("type");
+    gui_string_elem("tgl");
+
+    gui_string_elem("size");
+    gui_int_elem(x->x_gui.x_w);
+
+    gui_string_elem("minimum-size");
+    gui_int_elem(IEM_GUI_MINSIZE);
+
+    gui_string_elem("nonzero-value");
+    gui_float_elem(x->x_nonzero);
+
+    gui_string_elem("nonzero_schedule");  // no idea what this is...
+    gui_float_elem(1.0);
+
+    gui_string_elem("init");
+    gui_int_elem(x->x_gui.x_loadinit); 
+
+    gui_string_elem("send-symbol");
+    gui_string_elem(srl[0]->s_name);
+
+    gui_string_elem("receive-symbol");
+    gui_string_elem(srl[1]->s_name);
+
+    gui_string_elem("label");
+    gui_string_elem(srl[2]->s_name);
+
+    gui_string_elem("x-offset");
+    gui_int_elem(x->x_gui.x_ldx);
+
+    gui_string_elem("y-offset");
+    gui_int_elem(x->x_gui.x_ldy);
+
+    gui_string_elem("font-style");
+    gui_int_elem(x->x_gui.x_font_style);
+
+    gui_string_elem("font-size");
+    gui_int_elem(x->x_gui.x_fontsize);
+
+    gui_string_elem("background-color");
+    gui_int_elem(0xffffff & x->x_gui.x_bcol);
+
+    gui_string_elem("foreground-color");
+    gui_int_elem(0xffffff & x->x_gui.x_fcol);
+
+    gui_string_elem("label-color");
+    gui_int_elem(0xffffff & x->x_gui.x_lcol);
+
+    gui_end_array();
+    gui_end_vmess();
 }
 
 static void toggle_bang(t_toggle *x)
diff --git a/pd/src/m_pd.h b/pd/src/m_pd.h
index 1d939d6c49dc3ee28cc8ea6d435f8df0328ecb49..4df43257fff4f8085a2451174068f4f98942aa0d 100644
--- a/pd/src/m_pd.h
+++ b/pd/src/m_pd.h
@@ -682,6 +682,7 @@ EXTERN void sys_queuegui(void *client, t_glist *glist, t_guicallbackfn f);
 EXTERN void sys_unqueuegui(void *client);
     /* dialog window creation and destruction */
 EXTERN void gfxstub_new(t_pd *owner, void *key, const char *cmd);
+EXTERN char *gfxstub_new2(t_pd *owner, void *key);
 EXTERN void gfxstub_deleteforkey(void *key);
 
 extern t_class *glob_pdobject;  /* object to send "pd" messages */
diff --git a/pd/src/x_gui.c b/pd/src/x_gui.c
index 9cb78dec38123c4a4c9367072f38766bec6df275..fd09cce3ce0e6d405dbaa97a9ff4f64167d1c43d 100644
--- a/pd/src/x_gui.c
+++ b/pd/src/x_gui.c
@@ -87,6 +87,32 @@ void gfxstub_new(t_pd *owner, void *key, const char *cmd)
     sys_gui(buf);
 }
 
+/* This is the new API for gfxstub.  We forgo all the
+   string formatting junk and just return the string id */
+char *gfxstub_new2(t_pd *owner, void *key)
+{
+    static char namebuf[80];
+    t_gfxstub *x;
+    t_symbol *s;
+        /* if any exists with matching key, burn it. */
+    for (x = gfxstub_list; x; x = x->x_next)
+        if (x->x_key == key)
+            gfxstub_deleteforkey(key);
+    x = (t_gfxstub *)pd_new(gfxstub_class);
+    sprintf(namebuf, ".gfxstub%lx", (t_int)x);
+    s = gensym(namebuf);
+    pd_bind(&x->x_pd, s);
+    x->x_owner = owner;
+    x->x_sym = s;
+    x->x_key = key;
+    x->x_next = gfxstub_list;
+    gfxstub_list = x;
+    return (namebuf);
+}
+
+
+
+
 int gfxstub_haveproperties(void *key)
 {
     t_gfxstub *x;
@@ -127,7 +153,12 @@ void gfxstub_deleteforkey(void *key)
         {
             if (y->x_key == key)
             {
-                sys_vgui("destroy .gfxstub%lx\n", y);
+                //sys_vgui("destroy .gfxstub%lx\n", y);
+                char tagbuf[MAXPDSTRING];
+                sprintf(tagbuf, ".gfxstub%lx", (long unsigned int)y);
+                gui_vmess("gui_remove_gfxstub", "s",
+                    tagbuf);
+                 
                 y->x_owner = 0;
                 gfxstub_offlist(y);
                 didit = 1;
@@ -206,6 +237,7 @@ static t_class *openpanel_class;
 typedef struct _openpanel
 {
     t_object x_obj;
+    t_canvas *x_canvas;
     t_symbol *x_s;
 } t_openpanel;
 
@@ -213,6 +245,7 @@ static void *openpanel_new( void)
 {
     char buf[50];
     t_openpanel *x = (t_openpanel *)pd_new(openpanel_class);
+    x->x_canvas = canvas_getcurrent();
     sprintf(buf, "d%lx", (t_int)x);
     x->x_s = gensym(buf);
     pd_bind(&x->x_obj.ob_pd, x->x_s);
@@ -220,10 +253,15 @@ static void *openpanel_new( void)
     return (x);
 }
 
+extern char *canvas_string(t_canvas *x);
 static void openpanel_symbol(t_openpanel *x, t_symbol *s)
 {
     char *path = (s && s->s_name) ? s->s_name : "$pd_opendir";
     sys_vgui("pdtk_openpanel {%s} {%s}\n", x->x_s->s_name, path);
+    gui_vmess("gui_openpanel", "sss",
+        canvas_string(x->x_canvas),
+        x->x_s->s_name,
+        path);
 }
 
 static void openpanel_bang(t_openpanel *x)
@@ -280,6 +318,10 @@ static void savepanel_symbol(t_savepanel *x, t_symbol *s)
 {
     char *path = (s && s->s_name) ? s->s_name : "$pd_opendir";
     sys_vgui("pdtk_savepanel {%s} {%s}\n", x->x_s->s_name, path);
+    gui_vmess("gui_savepanel", "sss",
+        canvas_string(x->x_canvas),
+        x->x_s->s_name,
+        path);
 }
 
 static void savepanel_bang(t_savepanel *x)