diff --git a/gmap.module b/gmap.module
index ebc6a5d..ffeb314 100644
--- a/gmap.module
+++ b/gmap.module
@@ -513,7 +513,7 @@ function _gmap_filter_process($text, $filter, $format) {
  */
 function _gmap_filter_tips($filter, $format, $long = FALSE) {
   if (user_access('create gmap macro')) { // only display macro if user can create one
-    return t('Insert Google Map macro.') . '<a href="' . url('map/macro') . '" target="_blank" >' . t('Create a macro') . '</a>';
+    return t('Insert Google Map macro.') . '<a class="gmap_open_macrobuilder" href="' . url('map/macro') . '" target="_blank" >' . t('Create a macro') . '</a>';
   }
   else {
     return t('Insert Google Map macro.');
diff --git a/gmap_macro_builder.module b/gmap_macro_builder.module
index dfcf073..5544af9 100644
--- a/gmap_macro_builder.module
+++ b/gmap_macro_builder.module
@@ -55,6 +55,12 @@ function gmap_macro_builder_menu() {
  */
 function gmap_macro_builder_form($form, &$form_state, $settings = array(), $hide = array()) {
   $path = drupal_get_path('module', 'gmap');
+  
+  if ( isset($_GET['macro']) and $_GET['macro']
+        and is_array( $d = gmap_parse_macro( $_GET['macro'] ) ) ) {
+    unset( $d['id'] );
+    $settings += $d;
+  }
 
   $form['macroform'] = array(
     '#type' => 'fieldset',
@@ -65,7 +71,7 @@ function gmap_macro_builder_form($form, &$form_state, $settings = array(), $hide
   $form['macroform']['mapdiv'] = array(
     '#type' => 'gmap',
     '#map' => 'macro_map',
-    '#settings' => array_merge(array(
+    '#gmap_settings' => array_merge(array(
       'points' => array(),
       'pointsOverlays' => array(),
       'behavior' => array(
@@ -73,6 +79,9 @@ function gmap_macro_builder_form($form, &$form_state, $settings = array(), $hide
       ),
     ), $settings),
   );
+  
+  $form['macroform']['mapdiv']['#settings'] 
+  = $form['macroform']['mapdiv']['#gmap_settings'];
 
   $defaults = array_merge(gmap_defaults(), $settings);
 
diff --git a/js/gmap.js b/js/gmap.js
index d122cd5..e3337c7 100755
--- a/js/gmap.js
+++ b/js/gmap.js
@@ -175,6 +175,10 @@ Drupal.gmap.map = function (v) {
       this.change('all', -1, name, userdata);
     }
   };
+  
+  this.clearCallbacks = function (name) {
+    if (_bindings[name]) _bindings[name] = [];
+  }
 
   /**
    * Deferred change notification.
@@ -591,3 +595,11 @@ Drupal.behaviors.GMap = {
     jQuery('.gmap-control:not(.gmap-processed)', context).addClass('gmap-processed').each(function () {Drupal.gmap.setup.call(this)});
   }
 };
+
+jQuery(document).ready( function() {
+  jQuery('.gmap_open_macrobuilder').click( function() {
+    var macro = jQuery(this).parents('.field-type-text-long:first').find('textarea').val();
+    window.open( jQuery(this).attr('href')+'?macro='+macro , '');
+    return false;
+  } );
+} );
diff --git a/js/overlay_edit.js b/js/overlay_edit.js
index 36895d4..9c2ae52 100755
--- a/js/overlay_edit.js
+++ b/js/overlay_edit.js
@@ -182,14 +182,13 @@ Drupal.gmap.addHandler('overlayedit', function (elem) {
     obj.vars.overlay_add_mode = 'Points'; //elem.value;
     obj.vars.overlay_del_mode = 'Remove';
     var edit_text_elem;
-
+    
     if (obj.map) {
       obj._oe.features = [];
       obj._oe.featuresRef = {};
       obj._oe.editing = false;
       obj._oe.markerseq = {};
       GEvent.addListener(obj.map, 'click', function (overlay, point) {
-        var ctx, s, p;
         if (overlay) {
           if (obj._oe.editing) {
             // Work around problem where double clicking to finish a poly fires a click event.
@@ -200,177 +199,221 @@ Drupal.gmap.addHandler('overlayedit', function (elem) {
         }
         else if (point && !obj._oe.editing) {
           obj._oe.editing = true;
-          switch (obj.vars.overlay_add_mode) {
-            case 'Points':
-              var m = elem.value; // @@@ It's kinda silly to be binding the whole shebang to this dropdown..
-              if (!obj._oe.markerseq.hasOwnProperty(m)) {
-                obj._oe.markerseq[m] = -1;
-              }
-              obj._oe.markerseq[m] = obj._oe.markerseq[m] + 1;
-              p = new GMarker(point, {icon: Drupal.gmap.getIcon(m, obj._oe.markerseq[m])});
-              obj.map.addOverlay(p);
-              ctx = {
-                'type' : 'point',
-                'marker' : m,
-                'overlay' : p
-              };
-              var offset = obj._oe.features.push(ctx) - 1;
-              obj._oe.editing = false;
-              GEvent.addListener(p, "click", function () {
-                switch (obj.vars.overlay_del_mode) {
-                  case 'Remove':
-                    obj._oe.markerseq[m] = obj._oe.markerseq[m] - 1;
-                    ctx.type = 'deleted';
-                    obj.map.removeOverlay(p);
-                    ctx.overlay = null;
-                    var tmpcnt = 0;
-                    // Renumber markers in set.
-                    jQuery.each(obj._oe.features, function (i, n) {
-                      if (n.type && n.type === 'point' && n.marker === m) {
-                        var pt = n.overlay.getLatLng();
-                        n.overlay.setImage(Drupal.gmap.getIcon(n.marker, tmpcnt).image);
-                        tmpcnt = tmpcnt + 1;
-                      }
-                    });
-                    break;
-                  case 'Edit info':
-                    // @@@
-                    break;
-                }
-                obj.change('mapedited', -1);
-              });
-              obj.change('mapedited', -1);
-              break;
+          obj.addPointToEditor( point, elem.value, obj.vars.overlay_add_mode );
+        }
+      });
+    }
+    
+    obj.clearCallbacks('addshape');
+    obj.bind('addshape', function ( shape ) {
+      var points = [];
+      for ( var i in shape.points )
+        points.push( new GLatLng( shape.points[i][0], shape.points[i][1] ) );
+      obj.addPointToEditor( points, null, ( 'line' == shape.type.toLowerCase() ? 'Lines'
+                                            : ( 'polygon' == shape.type.toLowerCase() ? 'GPolygon'
+                                            : '' ) ) );
+    } );
+    obj.clearCallbacks('addmarker');
+    obj.bind('addmarker', function ( marker ) {
+      obj.addPointToEditor( new GLatLng( marker.latitude, marker.longitude ), marker.markername, 'Points' );
+    } );
+  
+  });
 
-            case 'Lines':
-              ctx = {
-                'type' : 'polyline',
-                'style' : [],
-                'overlay' : null
-              };
-              s = obj.vars.styles.line_default;
-              if (obj.vars.overlay_linestyle_apply) {
-                ctx.style = obj.vars.styles.overlayline.slice();
-                s = ctx.style;
+});
+
+Drupal.gmap.map.prototype.addPointToEditor = function( point, m, type ) {
+  
+  var obj = this;
+  var ctx, s, p, points;
+        
+  switch (type) {
+    case 'Points':
+      if (!obj._oe.markerseq.hasOwnProperty(m)) {
+        obj._oe.markerseq[m] = -1;
+      }
+      obj._oe.markerseq[m] = obj._oe.markerseq[m] + 1;
+      p = new GMarker(point, {
+        icon: Drupal.gmap.getIcon(m, obj._oe.markerseq[m])
+      });
+      obj.map.addOverlay(p);
+      ctx = {
+        'type' : 'point',
+        'marker' : m,
+        'overlay' : p
+      };
+      var offset = obj._oe.features.push(ctx) - 1;
+      obj._oe.editing = false;
+      GEvent.addListener(p, "click", function () {
+        switch (obj.vars.overlay_del_mode) {
+          case 'Remove':
+            obj._oe.markerseq[m] = obj._oe.markerseq[m] - 1;
+            ctx.type = 'deleted';
+            obj.map.removeOverlay(p);
+            ctx.overlay = null;
+            var tmpcnt = 0;
+            // Renumber markers in set.
+            jQuery.each(obj._oe.features, function (i, n) {
+              if (n.type && n.type === 'point' && n.marker === m) {
+                var pt = n.overlay.getLatLng();
+                n.overlay.setImage(Drupal.gmap.getIcon(n.marker, tmpcnt).image);
+                tmpcnt = tmpcnt + 1;
               }
-              p = new GPolyline([point], '#' + s[0], Number(s[1]), s[2] / 100);
-              obj.map.addOverlay(p);
-              ctx.overlay = p;
-              obj._oe.featuresRef[p] = obj._oe.features.push(ctx) - 1;
+            });
+            break;
+          case 'Edit info':
+            // @@@
+            break;
+        }
+        obj.change('mapedited', -1);
+      });
+      obj.change('mapedited', -1);
+      break;
 
-              p.enableDrawing();
-              p.enableEditing({onEvent: "mouseover"});
-              p.disableEditing({onEvent: "mouseout"});
-              GEvent.addListener(p, "endline", function () {
-                //obj._oe.editing = false;
-                GEvent.addListener(p, "lineupdated", function () {
-                  obj.change('mapedited', -1);
-                });
-                GEvent.addListener(p, "click", function (latlng, index) {
-                  if (typeof index === "number") {
-                    // Delete vertex on click.
-                    p.deleteVertex(index);
-                  }
-                  else {
-                    var feature = obj._oe.features[obj._oe.featuresRef[p]];
-                    feature.stroke = obj.vars.stroke; // @@@
-                    p.setStrokeStyle(feature.stroke);
-                  }
-                });
-                obj.change('mapedited', -1);
-              });
-              break;
+    case 'Lines':
+      ctx = {
+        'type' : 'polyline',
+        'style' : [],
+        'overlay' : null
+      };
+      s = obj.vars.styles.line_default;
+      if (obj.vars.overlay_linestyle_apply) {
+        ctx.style = obj.vars.styles.overlayline.slice();
+        s = ctx.style;
+      }
+      points = ( ( point instanceof Array ) ? point : [point] );
+      p = new GPolyline(points, '#' + s[0], Number(s[1]), s[2] / 100);
+      obj.map.addOverlay(p);
+      ctx.overlay = p;
+      obj._oe.featuresRef[p] = obj._oe.features.push(ctx) - 1;
 
-            case 'GPolygon':
-              ctx = {
-                'type' : 'polygon',
-                'style' : [],
-                'overlay' : null
-              };
-              s = obj.vars.styles.poly_default;
-              if (obj.vars.overlay_polystyle_apply) {
-                ctx.style = obj.vars.styles.overlaypoly.slice();
-                s = ctx.style;
-              }
-              p = new GPolygon([point], '#' + s[0], Number(s[1]), s[2] / 100, '#' + s[3], s[4] / 100);
-              obj.map.addOverlay(p);
-              ctx.overlay = p;
-              obj._oe.featuresRef[p] = obj._oe.features.push(ctx) - 1;
+      var lineListener = function () {
+        //obj._oe.editing = false;
+        GEvent.addListener(p, "lineupdated", function () {
+          obj.change('mapedited', -1);
+        });
+        GEvent.addListener(p, "click", function (latlng, index) {
+          if (typeof index === "number") {
+            // Delete vertex on click.
+            p.deleteVertex(index);
+          }
+          else {
+            var feature = obj._oe.features[obj._oe.featuresRef[p]];
+            feature.stroke = obj.vars.stroke; // @@@
+            p.setStrokeStyle(feature.stroke);
+          }
+        });
+        obj.change('mapedited', -1);
+      }
 
-              p.enableDrawing();
-              p.enableEditing({onEvent: "mouseover"});
-              p.disableEditing({onEvent: "mouseout"});
-              GEvent.addListener(p, "endline", function () {
-                //obj._oe.editing = false;
-                GEvent.addListener(p, "lineupdated", function () {
-                  obj.change('mapedited', -1);
-                });
-                GEvent.addListener(p, "click", function (latlng, index) {
-                  if (typeof index === "number") {
-                    p.deleteVertex(index);
-                  }
-                  else {
-                    var feature = obj._oe.features[obj._oe.featuresRef[p]];
-                    feature.stroke = obj.vars.stroke;
-                    feature.fill = obj.vars.fill;
-                    p.setStrokeStyle(feature.stroke);
-                    p.setFillStyle(feature.fill); // @@@
-                  }
-                });
-                obj.change('mapedited', -1);
-              });
-              break;
+      if ( !(point instanceof Array) ) p.enableDrawing();
+      p.enableEditing({
+        onEvent: "mouseover"
+      });
+      p.disableEditing({
+        onEvent: "mouseout"
+      });
+      GEvent.addListener(p, "endline", lineListener());
+      if ( !(point instanceof Array) ) lineListener();
+      break;
 
-            case 'Circles':
-              var temppoint = point;
-              // @@@ Translate
-              obj.status("Drawing circle. Click a point on the rim to place.");
+    case 'GPolygon':
+      ctx = {
+        'type' : 'polygon',
+        'style' : [],
+        'overlay' : null
+      };
+      s = obj.vars.styles.poly_default;
+      if (obj.vars.overlay_polystyle_apply) {
+        ctx.style = obj.vars.styles.overlaypoly.slice();
+        s = ctx.style;
+      }
+      points = ( ( point instanceof Array ) ? point : [point] );
+      p = new GPolygon(points, '#' + s[0], Number(s[1]), s[2] / 100, '#' + s[3], s[4] / 100);
+      obj.map.addOverlay(p);
+      ctx.overlay = p;
+      obj._oe.featuresRef[p] = obj._oe.features.push(ctx) - 1;
+      
+      var polyListener = function () {
+        //obj._oe.editing = false;
+        GEvent.addListener(p, "lineupdated", function () {
+          obj.change('mapedited', -1);
+        });
+        GEvent.addListener(p, "click", function (latlng, index) {
+          if (typeof index === "number") {
+            p.deleteVertex(index);
+          }
+          else {
+            var feature = obj._oe.features[obj._oe.featuresRef[p]];
+            feature.stroke = obj.vars.stroke;
+            feature.fill = obj.vars.fill;
+            p.setStrokeStyle(feature.stroke);
+            p.setFillStyle(feature.fill); // @@@
+          }
+        });
+        obj.change('mapedited', -1);
+      };
 
-              var handle = GEvent.addListener(obj.map, 'click', function (overlay, point) {
-                if (point) {
-                  var ctx = {
-                    'type' : 'circle',
-                    'center' : temppoint,
-                    'radius' : null,
-                    'style' : [],
-                    'overlay' : null
-                  };
-                  var s = obj.vars.styles.poly_default;
-                  if (obj.vars.overlay_polystyle_apply) {
-                    ctx.style = obj.vars.styles.overlaypoly.slice();
-                    s = ctx.style;
-                  }
-                  obj.status("Placed circle. Radius was " + temppoint.distanceFrom(point) / 1000 + " km.");
-                  ctx.radius = temppoint.distanceFrom(point);
-                  var p = new GPolygon(obj.poly.calcPolyPoints(ctx.center, ctx.radius, 32), '#' + s[0], Number(s[1]), s[2] / 100, '#' + s[3], s[4] / 100);
-                  obj.map.addOverlay(p);
-                  ctx.overlay = p;
-                  obj._oe.featuresRef[p] = obj._oe.features.push(ctx) - 1;
-                  GEvent.addListener(p, "click", function () {
-                    switch (obj.vars.overlay_del_mode) {
-                      case 'Remove':
-                        ctx.type = 'deleted';
-                        obj.map.removeOverlay(p);
-                        ctx.overlay = null;
-                        break;
-                      case 'Edit info':
-                        // @@@
-                        break;
-                    }
-                    obj.change('mapedited', -1);
-                  });
-                }
-                else {
-                  // @@@ Uh, do cleanup I suppose..
-                }
-                obj._oe.editing = false;
-                GEvent.removeListener(handle);
-                obj.change('mapedited', -1);
-              });
-              break;
+      if ( !(point instanceof Array) ) p.enableDrawing();
+      p.enableEditing({
+        onEvent: "mouseover"
+      });
+      p.disableEditing({
+        onEvent: "mouseout"
+      });
+      GEvent.addListener(p, "endline", polyListener());
+      if ( !(point instanceof Array) ) polyListener();
+      break;
+
+    case 'Circles':
+      var temppoint = point;
+      // @@@ Translate
+      obj.status("Drawing circle. Click a point on the rim to place.");
+
+      var handle = GEvent.addListener(obj.map, 'click', function (overlay, point) {
+        if (point) {
+          var ctx = {
+            'type' : 'circle',
+            'center' : temppoint,
+            'radius' : null,
+            'style' : [],
+            'overlay' : null
+          };
+          var s = obj.vars.styles.poly_default;
+          if (obj.vars.overlay_polystyle_apply) {
+            ctx.style = obj.vars.styles.overlaypoly.slice();
+            s = ctx.style;
           }
+          obj.status("Placed circle. Radius was " + temppoint.distanceFrom(point) / 1000 + " km.");
+          ctx.radius = temppoint.distanceFrom(point);
+          var p = new GPolygon(obj.poly.calcPolyPoints(ctx.center, ctx.radius, 32), '#' + s[0], Number(s[1]), s[2] / 100, '#' + s[3], s[4] / 100);
+          obj.map.addOverlay(p);
+          ctx.overlay = p;
+          obj._oe.featuresRef[p] = obj._oe.features.push(ctx) - 1;
+          GEvent.addListener(p, "click", function () {
+            switch (obj.vars.overlay_del_mode) {
+              case 'Remove':
+                ctx.type = 'deleted';
+                obj.map.removeOverlay(p);
+                ctx.overlay = null;
+                break;
+              case 'Edit info':
+                // @@@
+                break;
+            }
+            obj.change('mapedited', -1);
+          });
         }
+        else {
+        // @@@ Uh, do cleanup I suppose..
+        }
+        obj._oe.editing = false;
+        GEvent.removeListener(handle);
+        obj.change('mapedited', -1);
       });
-    }
-  });
-});
\ No newline at end of file
+      break;
+  }
+  
+  return p;
+  
+}
diff --git a/js/shapeloader_static.js b/js/shapeloader_static.js
index 7b269cb..ee73773 100644
--- a/js/shapeloader_static.js
+++ b/js/shapeloader_static.js
@@ -14,7 +14,7 @@ Drupal.gmap.addHandler('gmap', function (elem) {
   var obj = this;
   if (obj.vars.shapes) {
     // Inject shapes during init.
-    obj.bind('init', function () {
+    obj.bind('iconsready', function () {
       // We need to move the incoming shapes out of the way,
       // because addshape will readd them, causing an infinate loop.
       // Store the shapes in s and reset obj.vars.shapes.
