From 2dff35615f5daa9a29bd19e4c568674ec9eb5ac5 Mon Sep 17 00:00:00 2001
From: Mathieu L Bouchard <matju@artengine.ca>
Date: Wed, 6 Aug 2014 16:42:48 -0400
Subject: [PATCH] 4th refactor of scalehandle

---
 pd/src/g_all_guis.c | 105 +++++++++++++++++++++++--
 pd/src/g_all_guis.h |  10 +++
 pd/src/g_bang.c     | 152 ++++--------------------------------
 pd/src/g_canvas.c   | 126 +++++++++++-------------------
 pd/src/g_hdial.c    | 146 ++++------------------------------
 pd/src/g_hslider.c  | 155 ++++--------------------------------
 pd/src/g_mycanvas.c | 148 ++++-------------------------------
 pd/src/g_numbox.c   | 186 +++++++++-----------------------------------
 pd/src/g_toggle.c   | 158 ++++---------------------------------
 pd/src/g_vdial.c    | 149 ++++-------------------------------
 pd/src/g_vslider.c  | 155 +++++-------------------------------
 pd/src/g_vumeter.c  | 159 ++++---------------------------------
 12 files changed, 309 insertions(+), 1340 deletions(-)

diff --git a/pd/src/g_all_guis.c b/pd/src/g_all_guis.c
index cbe1cbe6b..d0b34989f 100644
--- a/pd/src/g_all_guis.c
+++ b/pd/src/g_all_guis.c
@@ -13,6 +13,7 @@
 #include <ctype.h>
 #include "m_pd.h"
 #include "g_canvas.h"
+#include "m_imp.h"
 #include "t_tk.h"
 #include "g_all_guis.h"
 #include <math.h>
@@ -895,6 +896,11 @@ char *iem_get_tag(t_canvas *glist, t_iemgui *iem_obj)
 //----------------------------------------------------------------
 // SCALEHANDLE COMMON CODE
 
+extern int gfxstub_haveproperties(void *key);
+
+int mini(int a, int b) {return a<b?a:b;}
+int maxi(int a, int b) {return a>b?a:b;}
+
 // in all 20 cases :
 // [bng], [tgl], [hradio], [vradio], [hsl], [vsl], [cnv], [nbx], [vu]
 // for both scale & label, plus canvas' scale & move.
@@ -944,6 +950,15 @@ const char *nlet_tag, const char *class_tag) {
     h->h_vis = 1;
 }
 
+void scalehandle_draw_select2(t_iemgui *x, t_glist *canvas, const char *class_tag) {
+    char *nlet_tag = iem_get_tag(canvas, (t_iemgui *)x);
+    scalehandle_draw_select(x->x_handle,canvas,x->x_w-1,x->x_h-1,nlet_tag,class_tag);
+    if (strcmp(x->x_lab->s_name, "empty") != 0)
+    {
+        scalehandle_draw_select(x->x_lhandle,canvas,x->x_ldx,x->x_ldy,nlet_tag,class_tag);
+    }
+}
+
 void scalehandle_draw_erase(t_scalehandle *h, t_glist *canvas) {
         sys_vgui("destroy %s\n", h->h_pathname);
         sys_vgui(".x%lx.c delete %lx%s\n", canvas, h->h_master, h->h_scale ? "SCALE" : "LABELH");
@@ -970,8 +985,8 @@ t_scalehandle *scalehandle_new(t_class *c, t_iemgui *x, int scale) {
     sprintf(h->h_outlinetag, "h%lx", (t_int)h);
     h->h_dragon = 0;
     h->h_scale = scale;
-    h->h_offset_x = 0;
-    h->h_offset_y = 0;
+    //h->h_offset_x = 0; // unused (maybe keep for later)
+    //h->h_offset_y = 0; // unused (maybe keep for later)
     h->h_vis = 0;
     return h;
 }
@@ -996,8 +1011,8 @@ void scalehandle_dragon_label(t_scalehandle *h, float f1, float f2) {
         int properties = gfxstub_haveproperties((void *)x);
         if (properties)
         {
-            int new_x = x->x_ldx - h->h_offset_x + h->h_dragx;
-            int new_y = x->x_ldy - h->h_offset_y + h->h_dragy;
+            int new_x = x->x_ldx + h->h_dragx;
+            int new_y = x->x_ldy + h->h_dragy;
             properties_set_field_int(properties,"label.xy.x_entry",new_x);
             properties_set_field_int(properties,"label.xy.y_entry",new_y);
         }
@@ -1006,10 +1021,84 @@ void scalehandle_dragon_label(t_scalehandle *h, float f1, float f2) {
             int xpos=text_xpix(&x->x_obj, x->x_glist);
             int ypos=text_ypix(&x->x_obj, x->x_glist);
             t_canvas *canvas=glist_getcanvas(x->x_glist);
-            sys_vgui(".x%lx.c coords %lxLABEL %d %d\n",
-                canvas, x,
-                xpos+x->x_ldx + h->h_dragx - h->h_offset_x,
-                ypos+x->x_ldy + h->h_dragy - h->h_offset_y);
+            sys_vgui(".x%lx.c coords %lxLABEL %d %d\n", canvas, x,
+                xpos+x->x_ldx + h->h_dragx,
+                ypos+x->x_ldy + h->h_dragy);
         }
     }
 }
+
+void scalehandle_unclick_label(t_scalehandle *h) {
+    t_iemgui *x = (t_iemgui *)h->h_master;
+    canvas_apply_setundo(x->x_glist, (t_gobj *)x);
+    if (h->h_dragx || h->h_dragy)
+    {
+        x->x_ldx += h->h_dragx;
+        x->x_ldy += h->h_dragy;
+        canvas_dirty(x->x_glist, 1);
+    }
+    if (glist_isvisible(x->x_glist))
+    {
+        iemgui_select((t_gobj *)x, x->x_glist, 1);
+        canvas_fixlinesfor(x->x_glist, (t_text *)x);
+        sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", x->x_glist);
+    }
+}
+
+void scalehandle_click_label(t_scalehandle *h) {
+    t_iemgui *x = (t_iemgui *)h->h_master;
+    if (glist_isvisible(x->x_glist))
+    {
+        sys_vgui("lower %s\n", h->h_pathname);
+        t_scalehandle *othersh = x->x_handle;
+        sys_vgui("lower .x%lx.h%lx\n",
+            (t_int)glist_getcanvas(x->x_glist), (t_int)othersh);
+    }
+    h->h_dragx = 0;
+    h->h_dragy = 0;
+}
+
+extern t_class *my_canvas_class;
+void scalehandle_getrect_master(t_scalehandle *h, int *x1, int *y1, int *x2, int *y2) {
+    t_iemgui *x = (t_iemgui *)h->h_master;
+    t_class *c = pd_class((t_pd *)x);
+    c->c_wb->w_getrectfn((t_gobj *)x,x->x_glist,x1,y1,x2,y2);
+    //printf("%s\n",c->c_name->s_name);
+    if (c==my_canvas_class) {
+        t_my_canvas *xx = (t_my_canvas *)x;
+        *x2=*x1+xx->x_vis_w;
+        *y2=*y1+xx->x_vis_h;
+    }
+}
+
+void scalehandle_click_scale(t_scalehandle *h) {
+    int x1,y1,x2,y2;
+    t_iemgui *x = (t_iemgui *)h->h_master;
+    scalehandle_getrect_master(h,&x1,&y1,&x2,&y2);
+    if (glist_isvisible(x->x_glist)) {
+        sys_vgui("lower %s\n", h->h_pathname);
+        sys_vgui(".x%x.c create prect %d %d %d %d -stroke $pd_colors(selection) -strokewidth 1 -tags %s\n",
+            x->x_glist, x1, y1, x2, y2, h->h_outlinetag);
+    }
+    h->h_dragx = 0;
+    h->h_dragy = 0;
+}
+
+void scalehandle_unclick_scale(t_scalehandle *h) {
+    t_iemgui *x = (t_iemgui *)h->h_master;
+    sys_vgui(".x%x.c delete %s\n", x->x_glist, h->h_outlinetag);
+    iemgui_select((t_gobj *)x, x->x_glist, 1);
+    canvas_fixlinesfor(x->x_glist, (t_text *)x);
+    sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", x->x_glist);
+}
+
+void scalehandle_drag_scale(t_scalehandle *h) {
+    int x1,y1,x2,y2;
+    t_iemgui *x = (t_iemgui *)h->h_master;
+    scalehandle_getrect_master(h,&x1,&y1,&x2,&y2);
+    if (glist_isvisible(x->x_glist)) {
+        sys_vgui(".x%x.c coords %s %d %d %d %d\n", x->x_glist, h->h_outlinetag,
+            x1, y1, x2+h->h_dragx, y2+h->h_dragy);
+    }
+}
+
diff --git a/pd/src/g_all_guis.h b/pd/src/g_all_guis.h
index bb7d390ba..2ff856009 100644
--- a/pd/src/g_all_guis.h
+++ b/pd/src/g_all_guis.h
@@ -405,6 +405,7 @@ EXTERN void canvas_apply_setundo(t_canvas *x, t_gobj *y);
 // scalehandle code, as refactored by Mathieu
 EXTERN void scalehandle_bind(t_scalehandle *h);
 EXTERN void scalehandle_draw_select(t_scalehandle *h, t_glist *canvas, int px, int py, const char *nlet_tag, const char *class_tag);
+EXTERN void scalehandle_draw_select2(t_iemgui *x, t_glist *canvas, const char *class_tag);
 EXTERN void scalehandle_draw_erase(t_scalehandle *h, t_glist *canvas);
 EXTERN void scalehandle_draw_erase2(t_iemgui *x, t_glist *canvas);
 EXTERN void scalehandle_draw_new(t_scalehandle *x, t_glist *canvas);
@@ -412,3 +413,12 @@ EXTERN t_scalehandle *scalehandle_new(t_class *c, t_iemgui *x, int scale);
 EXTERN void scalehandle_free(t_scalehandle *h);
 EXTERN void properties_set_field_int(long props, const char *gui_field, int value);
 EXTERN void scalehandle_dragon_label(t_scalehandle *h, float f1, float f2);
+EXTERN void scalehandle_unclick_label(t_scalehandle *h);
+EXTERN void scalehandle_click_label(t_scalehandle *h);
+EXTERN void scalehandle_click_scale(t_scalehandle *h);
+EXTERN void scalehandle_unclick_scale(t_scalehandle *h);
+EXTERN void scalehandle_drag_scale(t_scalehandle *h);
+
+EXTERN int mini(int a, int b);
+EXTERN int maxi(int a, int b);
+
diff --git a/pd/src/g_bang.c b/pd/src/g_bang.c
index 397ff92fd..807294b0b 100644
--- a/pd/src/g_bang.c
+++ b/pd/src/g_bang.c
@@ -224,32 +224,20 @@ void bng_draw_io(t_bng* x, t_glist* glist, int old_snd_rcv_flags)
 void bng_draw_select(t_bng* x, t_glist* glist)
 {
     t_canvas *canvas=glist_getcanvas(glist);
-    t_scalehandle *sh = (t_scalehandle *)(x->x_gui.x_handle);
-    t_scalehandle *lh = (t_scalehandle *)(x->x_gui.x_lhandle);
-
     //if (glist_isvisible(canvas)) {
-
     if(x->x_gui.x_fsf.x_selected)
     {
         /* check if we are drawing inside a gop abstraction visible
            on parent canvas -- if so, disable highlighting */
         if (x->x_gui.x_glist == glist_getcanvas(glist))
         {
-
-            char *nlet_tag = iem_get_tag(glist, (t_iemgui *)x);
-
             sys_vgui(".x%lx.c itemconfigure %lxBASE "
                      "-stroke $pd_colors(selection)\n", canvas, x);
             sys_vgui(".x%lx.c itemconfigure %lxBUT "
                      "-stroke $pd_colors(selection)\n", canvas, x);
             sys_vgui(".x%lx.c itemconfigure %lxLABEL "
                      "-fill $pd_colors(selection)\n", canvas, x);
-
-            scalehandle_draw_select(sh,canvas,x->x_gui.x_w-1,x->x_gui.x_h-1,nlet_tag,"BNG");
-            if (strcmp(x->x_gui.x_lab->s_name, "empty") != 0)
-            {
-                scalehandle_draw_select(lh,canvas,x->x_gui.x_ldx,x->x_gui.x_ldy,nlet_tag,"BNG");
-            }
+            scalehandle_draw_select2(&x->x_gui,glist,"BNG");
         }
         sys_vgui(".x%lx.c addtag selected withtag %lxBNG\n", canvas, x);
     }
@@ -270,120 +258,34 @@ void bng_draw_select(t_bng* x, t_glist* glist)
 static void bng__clickhook(t_scalehandle *sh, t_floatarg f,
     t_floatarg xxx, t_floatarg yyy)
 {
-
     t_bng *x = (t_bng *)(sh->h_master);
-
-    if (xxx)
-    {
-        sh->h_offset_x = xxx;
-    }
-    if (yyy)
-    {
-        sh->h_offset_y = yyy;
-    }
-
     int newstate = (int)f;
     if (sh->h_dragon && newstate == 0 && sh->h_scale)
     {
-        /* done dragging */
-
-        /* first set up the undo apply */
         canvas_apply_setundo(x->x_gui.x_glist, (t_gobj *)x);
-
         if (sh->h_dragx || sh->h_dragy)
         {
-            if (sh->h_dragx > sh->h_dragy)
-                sh->h_dragx = sh->h_dragy;
-            else sh->h_dragy = sh->h_dragx;
-
-            x->x_gui.x_w = x->x_gui.x_w + sh->h_dragx - sh->h_offset_x;
-            if (x->x_gui.x_w < SCALE_BNG_MINWIDTH)
-                x->x_gui.x_w = SCALE_BNG_MINWIDTH;
-            x->x_gui.x_h = x->x_gui.x_h + sh->h_dragy - sh->h_offset_y;
-            if (x->x_gui.x_h < SCALE_BNG_MINHEIGHT)
-                x->x_gui.x_h = SCALE_BNG_MINHEIGHT;
-
+            x->x_gui.x_w += sh->h_dragx;
+            x->x_gui.x_h += sh->h_dragy;
             canvas_dirty(x->x_gui.x_glist, 1);
         }
-
-        int properties = gfxstub_haveproperties((void *)x);
-
-        if (properties)
-        {
-            properties_set_field_int(properties,"dim.w_ent",x->x_gui.x_w);
-        }
-
         if (glist_isvisible(x->x_gui.x_glist))
         {
-            sys_vgui(".x%x.c delete %s\n", x->x_gui.x_glist, sh->h_outlinetag);
             bng_draw_move(x, x->x_gui.x_glist);
-            iemgui_select((t_gobj *)x, x->x_gui.x_glist, 1);
-            canvas_fixlinesfor(x->x_gui.x_glist, (t_text *)x);
-            sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", x->x_gui.x_glist);
+            scalehandle_unclick_scale(sh);
         }
     }
     else if (!sh->h_dragon && newstate && sh->h_scale)
     {
-        /* dragging */
-        if (glist_isvisible(x->x_gui.x_glist))
-        {
-            sys_vgui("lower %s\n", sh->h_pathname);
-            sys_vgui(".x%x.c create prect %d %d %d %d\
-     -stroke $pd_colors(selection) -strokewidth 1 -tags %s\n",
-                x->x_gui.x_glist, x->x_gui.x_obj.te_xpix,
-                x->x_gui.x_obj.te_ypix,
-                x->x_gui.x_obj.te_xpix + x->x_gui.x_w,
-                x->x_gui.x_obj.te_ypix + x->x_gui.x_h, sh->h_outlinetag);
-        }
-
-        sh->h_dragx = 0;
-        sh->h_dragy = 0;
+        scalehandle_click_scale(sh);
     }
     else if (sh->h_dragon && newstate == 0 && !sh->h_scale)
     {
-        /* done dragging */
-
-        /* first set up the undo apply */
-        canvas_apply_setundo(x->x_gui.x_glist, (t_gobj *)x);
-
-        if (sh->h_dragx || sh->h_dragy)
-        {
-            x->x_gui.x_ldx = x->x_gui.x_ldx + sh->h_dragx -
-                sh->h_offset_x;
-            x->x_gui.x_ldy = x->x_gui.x_ldy + sh->h_dragy -
-                sh->h_offset_y;
-            canvas_dirty(x->x_gui.x_glist, 1);
-        }
-
-        int properties = gfxstub_haveproperties((void *)x);
-
-        if (properties)
-        {
-            properties_set_field_int(properties,"dim.w_ent",x->x_gui.x_w);
-        }
-
-        if (glist_isvisible(x->x_gui.x_glist))
-        {
-            sys_vgui(".x%x.c delete %s\n", x->x_gui.x_glist, sh->h_outlinetag);
-            bng_draw_move(x, x->x_gui.x_glist);
-            iemgui_select((t_gobj *)x, x->x_gui.x_glist, 1);
-            canvas_fixlinesfor(x->x_gui.x_glist, (t_text *)x);
-            sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", x->x_gui.x_glist);
-        }
+        scalehandle_unclick_label(sh);
     }
     else if (!sh->h_dragon && newstate && !sh->h_scale)
     {
-        /* dragging */
-        if (glist_isvisible(x->x_gui.x_glist))
-        {
-            sys_vgui("lower %s\n", sh->h_pathname);
-            t_scalehandle *othersh = x->x_gui.x_handle;
-            sys_vgui("lower .x%lx.h%lx\n",
-                (t_int)glist_getcanvas(x->x_gui.x_glist), (t_int)othersh);
-        }
-
-        sh->h_dragx = 0;
-        sh->h_dragy = 0;
+        scalehandle_click_label(sh);
     }
     sh->h_dragon = newstate;
 }
@@ -394,44 +296,16 @@ static void bng__motionhook(t_scalehandle *sh,
     if (sh->h_dragon && sh->h_scale)
     {
         t_bng *x = (t_bng *)(sh->h_master);
-        int dx = (int)f1, dy = (int)f2;
-        int newx, newy;
-
-        if (dx > dy)
-        {
-            dx = dy;
-            sh->h_offset_x = sh->h_offset_y;
-        }
-        else
-        {
-            dy = dx;
-            sh->h_offset_y = sh->h_offset_x;
-        }
-
-        newx = x->x_gui.x_obj.te_xpix + x->x_gui.x_w -
-            sh->h_offset_x + dx;
-        newy = x->x_gui.x_obj.te_ypix + x->x_gui.x_h -
-            sh->h_offset_y + dy;
-
-        if (newx < x->x_gui.x_obj.te_xpix + SCALE_BNG_MINWIDTH)
-            newx = x->x_gui.x_obj.te_xpix + SCALE_BNG_MINWIDTH;
-        if (newy < x->x_gui.x_obj.te_ypix + SCALE_BNG_MINHEIGHT)
-            newy = x->x_gui.x_obj.te_ypix + SCALE_BNG_MINHEIGHT;
-
-        if (glist_isvisible(x->x_gui.x_glist))
-        {
-            sys_vgui(".x%x.c coords %s %d %d %d %d\n",
-                 x->x_gui.x_glist, sh->h_outlinetag, x->x_gui.x_obj.te_xpix,
-                 x->x_gui.x_obj.te_ypix, newx, newy);
-        }
-        sh->h_dragx = dx;
-        sh->h_dragy = dy;
+        int d = maxi((int)f1,(int)f2);
+        d = maxi(d,IEM_GUI_MINSIZE-x->x_gui.x_w);
+        sh->h_dragx = d;
+        sh->h_dragy = d;
+        scalehandle_drag_scale(sh);
 
         int properties = gfxstub_haveproperties((void *)x);
-
         if (properties)
         {
-            int new_w = x->x_gui.x_w - sh->h_offset_x + sh->h_dragx;
+            int new_w = x->x_gui.x_w + sh->h_dragx;
             properties_set_field_int(properties,"dim.w_ent",new_w);
         }
     }
diff --git a/pd/src/g_canvas.c b/pd/src/g_canvas.c
index 5b6fbf98e..817756826 100644
--- a/pd/src/g_canvas.c
+++ b/pd/src/g_canvas.c
@@ -730,15 +730,11 @@ void canvas_drawredrect(t_canvas *x, int doit)
 {
     if (doit)
     {
-        //fprintf(stderr,"GOP %d %d\n", x->gl_pixwidth, x->gl_pixheight);
+        int x1=x->gl_xmargin, y1=x->gl_ymargin;
+        int x2=x1+x->gl_pixwidth, y2=y1+x->gl_pixheight;
         sys_vgui(".x%lx.c create line\
             %d %d %d %d %d %d %d %d %d %d -fill #ff8080 -tags GOP\n",
-            glist_getcanvas(x),
-            x->gl_xmargin, x->gl_ymargin,
-            x->gl_xmargin + x->gl_pixwidth, x->gl_ymargin,
-            x->gl_xmargin + x->gl_pixwidth, x->gl_ymargin + x->gl_pixheight,
-            x->gl_xmargin, x->gl_ymargin + x->gl_pixheight,
-            x->gl_xmargin, x->gl_ymargin);
+            glist_getcanvas(x), x1, y1, x2, y1, x2, y2, x1, y2, x1, y1);
         //dpsaha@vt.edu for drawing the GOP_blobs
         if (x->gl_goprect && x->gl_edit)
             canvas_draw_gop_resize_hooks(x);
@@ -756,10 +752,6 @@ void canvas_map(t_canvas *x, t_floatarg f)
     t_gobj *y;
     if (flag)
     {
-        //fprintf(stderr,"canvas_map 1\n");
-        //if (!glist_isvisible(x))
-        //{
-        //fprintf(stderr,"canvas_map 1 isvisible\n");
         t_selection *sel;
         if (!x->gl_havewindow)
         {
@@ -1896,8 +1888,6 @@ void canvasgop_draw_move(t_canvas *x, int doit)
     {
         canvas_redraw(x);
     }
-    //fprintf(stderr,"%d %d\n", (x->gl_owner ? 1:0),
-    //    glist_isvisible(x->gl_owner));
 
     if (x->gl_owner && glist_isvisible(x->gl_owner))
     {
@@ -1929,13 +1919,8 @@ extern void graph_checkgop_rect(t_gobj *z, t_glist *glist,
 
 void canvasgop__clickhook(t_scalehandle *sh, t_floatarg f, t_floatarg xxx, t_floatarg yyy)
 {
-    int x1=0, y1=0, x2=0, y2=0; //for getrect
-
     t_canvas *x = (t_canvas *)(sh->h_master);
 
-    if (xxx) sh->h_offset_x = xxx;
-    if (yyy) sh->h_offset_y = yyy;
-
     int newstate = (int)f;
     if (sh->h_dragon && newstate == 0)
     {
@@ -1948,39 +1933,30 @@ void canvasgop__clickhook(t_scalehandle *sh, t_floatarg f, t_floatarg xxx, t_flo
 
             if (sh->h_dragx || sh->h_dragy) 
             {
-                x->gl_pixwidth = x->gl_pixwidth + sh->h_dragx -
-                    sh->h_offset_x;
-                if (x->gl_pixwidth < SCALE_GOP_MINWIDTH)
-                    x->gl_pixwidth = SCALE_GOP_MINWIDTH;
-                x->gl_pixheight = x->gl_pixheight + sh->h_dragy -
-                    sh->h_offset_y;
-                if (x->gl_pixheight < SCALE_GOP_MINHEIGHT)
-                    x->gl_pixheight = SCALE_GOP_MINHEIGHT;
-
-                // check if the text is not hidden
-                // if so make minimum width and height based retrieved
-                // from getrect
+                x->gl_pixwidth += sh->h_dragx;
+                x->gl_pixheight += sh->h_dragy;
+                // check if the text is not hidden. if so, make minimum
+                // width and height based retrieved from getrect.
                 if (!x->gl_hidetext)
                 {
+                    int x1=0, y1=0, x2=0, y2=0;
                     if (x->gl_owner)
                     {
                         gobj_getrect((t_gobj*)x, x->gl_owner,
                             &x1, &y1, &x2, &y2);
-                        if (x2-x1 > x->gl_pixwidth) x->gl_pixwidth = x2-x1;
-                        if (y2-y1 > x->gl_pixheight) x->gl_pixheight = y2-y1;
                     }
                     else
                     {
                         graph_checkgop_rect((t_gobj*)x, x, &x1, &y1, &x2, &y2);
-                        if (x2-x1 > x->gl_pixwidth) x->gl_pixwidth = x2-x1;
-                        if (y2-y1 > x->gl_pixheight) x->gl_pixheight = y2-y1;
                     }
+                    if (x2-x1 > x->gl_pixwidth) x->gl_pixwidth = x2-x1;
+                    if (y2-y1 > x->gl_pixheight) x->gl_pixheight = y2-y1;
                 }
                 canvas_dirty(x, 1);
             }
 
+            // can't remove this update because the text size check above is not in motionhook
             int properties = gfxstub_haveproperties((void *)x);
-
             if (properties)
             {
                 properties_set_field_int(properties,"n.canvasdialog.x.f2.entry3",x->gl_pixwidth);
@@ -1996,24 +1972,14 @@ void canvasgop__clickhook(t_scalehandle *sh, t_floatarg f, t_floatarg xxx, t_flo
             }
         }
         else //enter if move_gop hook
-        {
-            /* first set up the undo apply */
-            //canvas_canvas_setundo(x);
+        {// this block is similar to scalehandle_unclick_label but not enough
             canvas_undo_add(x, 8, "apply", canvas_undo_set_canvas(x));
-
             if (sh->h_dragx || sh->h_dragy) 
             {
-                x->gl_xmargin = x->gl_xmargin + sh->h_dragx - sh->h_offset_x;
-                x->gl_ymargin = x->gl_ymargin + sh->h_dragy - sh->h_offset_y;
+                x->gl_xmargin += sh->h_dragx;
+                x->gl_ymargin += sh->h_dragy;
                 canvas_dirty(x, 1);
             }
-
-            int properties = gfxstub_haveproperties((void *)x);
-            if (properties) {
-                properties_set_field_int(properties,"n.canvasdialog.x.f2.entry4",x->gl_xmargin);
-                properties_set_field_int(properties,"n.canvasdialog.y.f2.entry4",x->gl_ymargin);
-            }
-        
             if (glist_isvisible(x))
             {
                 canvasgop_draw_move(x,1);
@@ -2028,15 +1994,12 @@ void canvasgop__clickhook(t_scalehandle *sh, t_floatarg f, t_floatarg xxx, t_flo
         {
             sys_vgui("lower %s\n", sh->h_pathname);
             //delete GOP rect where it started from
-            sys_vgui(".x%lx.c delete GOP \n",  x);
+            sys_vgui(".x%lx.c delete GOP\n", x);
             sys_vgui(".x%x.c create rectangle %d %d %d %d\
-                 -outline $pd_colors(selection) -width 1 -tags %s\n",\
-                 x, x->gl_xmargin, x->gl_ymargin,\
-                    x->gl_xmargin + x->gl_pixwidth,\
+                 -outline $pd_colors(selection) -width 1 -tags %s\n",
+                 x, x->gl_xmargin, x->gl_ymargin,
+                    x->gl_xmargin + x->gl_pixwidth,
                     x->gl_ymargin + x->gl_pixheight, sh->h_outlinetag);
-
-            sh->h_dragx = 0;
-            sh->h_dragy = 0;
         }
         else //enter if move_gop hook
         {
@@ -2044,10 +2007,9 @@ void canvasgop__clickhook(t_scalehandle *sh, t_floatarg f, t_floatarg xxx, t_flo
             sys_vgui("lower %s\n", sh->h_pathname);
             //delete GOP_resblob when moving the whole GOP
             sys_vgui(".x%lx.c delete GOP_resblob \n",  x);
-
-            sh->h_dragx = 0;
-            sh->h_dragy = 0;
         }
+        sh->h_dragx = 0;
+        sh->h_dragy = 0;
     }
     sh->h_dragon = newstate;
 }
@@ -2061,41 +2023,47 @@ void canvasgop__motionhook(t_scalehandle *sh,t_floatarg f1, t_floatarg f2)
     if (sh->h_dragon)
     {
         if(sh->h_scale) //enter if resize_gop hook
-        {            
-            newx = x->gl_xmargin + x->gl_pixwidth - sh->h_offset_x + dx;
-            newy = x->gl_ymargin + x->gl_pixheight - sh->h_offset_y + dy;
-
-            if (newx < x->gl_xmargin + SCALE_GOP_MINWIDTH)
-                newx = x->gl_xmargin + SCALE_GOP_MINWIDTH;
-            if (newy < x->gl_ymargin + SCALE_GOP_MINHEIGHT)
-                newy = x->gl_ymargin + SCALE_GOP_MINHEIGHT;
+        {
+            int sx = maxi(SCALE_GOP_MINWIDTH ,x->gl_pixwidth +dx);
+            int sy = maxi(SCALE_GOP_MINHEIGHT,x->gl_pixheight+dy);
+            //int x1=0, y1=0, x2=0, y2=0;
+            // if text is not hidden, use it as min height & width.
+            /*if (!x->gl_hidetext)
+            {
+                if (x->gl_owner)
+                    gobj_getrect((t_gobj*)x, x->gl_owner, &x1, &y1, &x2, &y2);
+                else
+                    graph_checkgop_rect((t_gobj*)x, x, &x1, &y1, &x2, &y2);
+                sx = maxi(sx,x2-x1);
+                sy = maxi(sy,y2-y1);
+            }*/ // does not work, needs a gobj_getrect that does not use pixwidth & pixheight
+            newx = x->gl_xmargin + sx;
+            newy = x->gl_ymargin + sy;
 
             sys_vgui(".x%x.c coords %s %d %d %d %d\n",
-                 x, sh->h_outlinetag, x->gl_xmargin,
-                 x->gl_ymargin, newx, newy);
+                x, sh->h_outlinetag, x->gl_xmargin, x->gl_ymargin, newx, newy);
 
-            sh->h_dragx = dx;
-            sh->h_dragy = dy;
+            sh->h_dragx = sx-x->gl_pixwidth;
+            sh->h_dragy = sy-x->gl_pixheight;
 
             int properties = gfxstub_haveproperties((void *)x);
             if (properties)
             {
-                int new_w = x->gl_pixwidth - sh->h_offset_x + sh->h_dragx;
-                int new_h = x->gl_pixheight - sh->h_offset_y + sh->h_dragy;
-                properties_set_field_int(properties,"n.canvasdialog.x.f2.entry3",new_w);
-                properties_set_field_int(properties,"n.canvasdialog.y.f2.entry3",new_h);
+                properties_set_field_int(properties,
+                    "n.canvasdialog.x.f2.entry3",x->gl_pixwidth + sh->h_dragx);
+                properties_set_field_int(properties,
+                    "n.canvasdialog.y.f2.entry3",x->gl_pixheight + sh->h_dragy);
             }
         }
         else //enter if move_gop hook
         {
-            newx = x->gl_xmargin - sh->h_offset_x + dx;
-            newy = x->gl_ymargin - sh->h_offset_y + dy;
-        
             int properties = gfxstub_haveproperties((void *)x);
             if (properties)
             {
-                properties_set_field_int(properties,"n.canvasdialog.x.f2.entry4",newx);
-                properties_set_field_int(properties,"n.canvasdialog.y.f2.entry4",newy);
+                properties_set_field_int(properties,
+                    "n.canvasdialog.x.f2.entry4",x->gl_xmargin + dx);
+                properties_set_field_int(properties,
+                    "n.canvasdialog.y.f2.entry4",x->gl_ymargin + dy);
             }
 
             sys_vgui(".x%x.c coords GOP %d %d %d %d %d %d %d %d %d %d\n",
diff --git a/pd/src/g_hdial.c b/pd/src/g_hdial.c
index 6c8e926cb..de08254d4 100644
--- a/pd/src/g_hdial.c
+++ b/pd/src/g_hdial.c
@@ -241,10 +241,7 @@ void hradio_draw_io(t_hradio* x, t_glist* glist, int old_snd_rcv_flags)
 void hradio_draw_select(t_hradio* x, t_glist* glist)
 {
     t_canvas *canvas=glist_getcanvas(glist);
-    t_scalehandle *sh = (t_scalehandle *)(x->x_gui.x_handle);
-    t_scalehandle *lh = (t_scalehandle *)(x->x_gui.x_lhandle);
     int n=x->x_number, i;
-
     //if (glist_isvisible(canvas)) {
 
         if(x->x_gui.x_fsf.x_selected)
@@ -253,26 +250,15 @@ void hradio_draw_select(t_hradio* x, t_glist* glist)
             // visible on parent canvas.  If so, disable highlighting
             if (x->x_gui.x_glist == glist_getcanvas(glist))
             {
-
-                char *nlet_tag = iem_get_tag(glist, (t_iemgui *)x);
-
                 for(i=0; i<n; i++)
                 {
                     sys_vgui(".x%lx.c itemconfigure %lxBASE%d "
-                             "-stroke $pd_colors(selection)\n",
-                         canvas, x, i);
+                             "-stroke $pd_colors(selection)\n", canvas, x, i);
                 }
                 sys_vgui(".x%lx.c itemconfigure %lxLABEL "
-                         "-fill $pd_colors(selection)\n",
-                    canvas, x);
-
-                scalehandle_draw_select(sh,canvas,x->x_gui.x_w*x->x_number-1,x->x_gui.x_h-1,nlet_tag,"HRDO");
-                if (strcmp(x->x_gui.x_lab->s_name, "empty") != 0)
-                {
-                    scalehandle_draw_select(lh,canvas,x->x_gui.x_ldx,x->x_gui.x_ldy,nlet_tag,"HRDO");
-                }
+                         "-fill $pd_colors(selection)\n", canvas, x);
+                scalehandle_draw_select2(&x->x_gui,glist,"HRDO");
             }
-
             sys_vgui(".x%lx.c addtag selected withtag %lxHRDO\n", canvas, x);
         }
         else
@@ -294,157 +280,53 @@ static void hradio__clickhook(t_scalehandle *sh, t_floatarg f, t_floatarg xxx,
     t_floatarg yyy)
 {
     t_hradio *x = (t_hradio *)(sh->h_master);
-
-     if (xxx)
-     {
-         sh->h_offset_x = xxx;
-     }
-     if (yyy)
-     {
-         sh->h_offset_y = yyy;
-     }
-
     int newstate = (int)f;
     if (sh->h_dragon && newstate == 0 && sh->h_scale)
     {
-        /* done dragging */
-
-        /* first set up the undo apply */
         canvas_apply_setundo(x->x_gui.x_glist, (t_gobj *)x);
-
         if (sh->h_dragx || sh->h_dragy)
         {
-
-            sh->h_dragx = sh->h_dragy;
-
-            x->x_gui.x_w = x->x_gui.x_w + sh->h_dragx - sh->h_offset_y;
-            if (x->x_gui.x_w < SCALE_HRDO_MINWIDTH)
-                x->x_gui.x_w = SCALE_HRDO_MINWIDTH;
-            x->x_gui.x_h = x->x_gui.x_h + sh->h_dragy - sh->h_offset_y;
-            if (x->x_gui.x_h < SCALE_HRDO_MINHEIGHT)
-                x->x_gui.x_h = SCALE_HRDO_MINHEIGHT;
-
+            x->x_gui.x_w += sh->h_dragy;
+            x->x_gui.x_h += sh->h_dragy;
             canvas_dirty(x->x_gui.x_glist, 1);
         }
-
-        int properties = gfxstub_haveproperties((void *)x);
-
-        if (properties)
-        {
-            properties_set_field_int(properties,"dim.w_ent",x->x_gui.x_w);
-        }
-
         if (glist_isvisible(x->x_gui.x_glist))
         {
-            sys_vgui(".x%x.c delete %s\n", x->x_gui.x_glist, sh->h_outlinetag);
             hradio_draw_move(x, x->x_gui.x_glist);
-            iemgui_select((t_gobj *)x, x->x_gui.x_glist, 1);
-            canvas_fixlinesfor(x->x_gui.x_glist, (t_text *)x);
-            sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", x->x_gui.x_glist);
+            scalehandle_unclick_scale(sh);
         }
     }
     else if (!sh->h_dragon && newstate && sh->h_scale)
     {
-        /* dragging */
-        if (glist_isvisible(x->x_gui.x_glist))
-        {
-            sys_vgui("lower %s\n", sh->h_pathname);
-            sys_vgui(".x%x.c create prect %d %d %d %d "
-                     "-stroke $pd_colors(selection) -strokewidth 1 -tags %s\n",
-                x->x_gui.x_glist, x->x_gui.x_obj.te_xpix,
-                x->x_gui.x_obj.te_ypix,
-                x->x_gui.x_obj.te_xpix + (x->x_gui.x_w * x->x_number),
-                x->x_gui.x_obj.te_ypix + x->x_gui.x_h, sh->h_outlinetag);
-        }
-
-        sh->h_dragx = 0;
-        sh->h_dragy = 0;
+        scalehandle_click_scale(sh);
     }
     else if (sh->h_dragon && newstate == 0 && !sh->h_scale)
     {
-        /* done dragging */
-
-        /* first set up the undo apply */
-        canvas_apply_setundo(x->x_gui.x_glist, (t_gobj *)x);
-
-        if (sh->h_dragx || sh->h_dragy)
-        {
-            x->x_gui.x_ldx =
-                x->x_gui.x_ldx + sh->h_dragx - sh->h_offset_x;
-            x->x_gui.x_ldy =
-                x->x_gui.x_ldy + sh->h_dragy - sh->h_offset_y;
-
-            canvas_dirty(x->x_gui.x_glist, 1);
-        }
-
-        int properties = gfxstub_haveproperties((void *)x);
-        if (properties)
-        {
-            properties_set_field_int(properties,"dim.w_ent",x->x_gui.x_w);
-        }
-
-        if (glist_isvisible(x->x_gui.x_glist))
-        {
-            sys_vgui(".x%x.c delete %s\n", x->x_gui.x_glist, sh->h_outlinetag);
-            hradio_draw_move(x, x->x_gui.x_glist);
-            iemgui_select((t_gobj *)x, x->x_gui.x_glist, 1);
-            canvas_fixlinesfor(x->x_gui.x_glist, (t_text *)x);
-            sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", x->x_gui.x_glist);
-        }
+        scalehandle_unclick_label(sh);
     }
     else if (!sh->h_dragon && newstate && !sh->h_scale)
     {
-        /* started dragging label */
-        if (glist_isvisible(x->x_gui.x_glist))
-        {
-            sys_vgui("lower %s\n", sh->h_pathname);
-            t_scalehandle *othersh = x->x_gui.x_handle;
-            sys_vgui("lower .x%lx.h%lx\n",
-                (t_int)glist_getcanvas(x->x_gui.x_glist), (t_int)othersh);
-        }
-
-        sh->h_dragx = 0;
-        sh->h_dragy = 0;
+        scalehandle_click_label(sh);
     }
-
     sh->h_dragon = newstate;
 }
 
-static void hradio__motionhook(t_scalehandle *sh,
-                    t_floatarg f1, t_floatarg f2)
+static void hradio__motionhook(t_scalehandle *sh, t_floatarg f1, t_floatarg f2)
 {
     if (sh->h_dragon && sh->h_scale)
     {
         t_hradio *x = (t_hradio *)(sh->h_master);
         int dx = (int)f1, dy = (int)f2;
-        int newx, newy;
-
-        dx = dy;
-
-        newx = x->x_gui.x_obj.te_xpix + x->x_gui.x_w*x->x_number +
-            (dx - sh->h_offset_y) * x->x_number;
-        newy = x->x_gui.x_obj.te_ypix + x->x_gui.x_h +
-            (dy - sh->h_offset_y);
-
-        if (newx < x->x_gui.x_obj.te_xpix + SCALE_HRDO_MINWIDTH*x->x_number)
-            newx = x->x_gui.x_obj.te_xpix + SCALE_HRDO_MINWIDTH*x->x_number;
-        if (newy < x->x_gui.x_obj.te_ypix + SCALE_HRDO_MINHEIGHT)
-            newy = x->x_gui.x_obj.te_ypix + SCALE_HRDO_MINHEIGHT;
-
-        if (glist_isvisible(x->x_gui.x_glist))
-        {
-            sys_vgui(".x%x.c coords %s %d %d %d %d\n",
-                 x->x_gui.x_glist, sh->h_outlinetag, x->x_gui.x_obj.te_xpix,
-                 x->x_gui.x_obj.te_ypix, newx, newy);
-        }
+        dx = maxi(dx,(IEM_GUI_MINSIZE-x->x_gui.x_w)*x->x_number);
+        dy = dx/x->x_number;
         sh->h_dragx = dx;
         sh->h_dragy = dy;
+        scalehandle_drag_scale(sh);
 
         int properties = gfxstub_haveproperties((void *)x);
-
         if (properties)
         {
-            int new_w = x->x_gui.x_w - sh->h_offset_x + sh->h_dragx;
+            int new_w = x->x_gui.x_w + sh->h_dragx;
             properties_set_field_int(properties,"dim.w_ent",new_w);
         }
     }
diff --git a/pd/src/g_hslider.c b/pd/src/g_hslider.c
index ea75543fe..3f8e79196 100644
--- a/pd/src/g_hslider.c
+++ b/pd/src/g_hslider.c
@@ -227,34 +227,19 @@ static void hslider_draw_io(t_hslider* x,t_glist* glist, int old_snd_rcv_flags)
 static void hslider_draw_select(t_hslider* x,t_glist* glist)
 {
     t_canvas *canvas=glist_getcanvas(glist);
-    t_scalehandle *sh = (t_scalehandle *)(x->x_gui.x_handle);
-    t_scalehandle *lh = (t_scalehandle *)(x->x_gui.x_lhandle);
-
     //if (glist_isvisible(canvas)) {
-
         if(x->x_gui.x_fsf.x_selected)
         {
             // check if we are drawing inside a gop abstraction
             // visible on parent canvas. If so, disable highlighting
             if (x->x_gui.x_glist == glist_getcanvas(glist))
             {
-
-                char *nlet_tag = iem_get_tag(glist, (t_iemgui *)x);
-
                 sys_vgui(".x%lx.c itemconfigure %lxBASE "
-                         "-stroke $pd_colors(selection)\n",
-                     canvas, x);
+                         "-stroke $pd_colors(selection)\n", canvas, x);
                 sys_vgui(".x%lx.c itemconfigure %lxLABEL "
-                         "-fill $pd_colors(selection)\n",
-                     canvas, x);
-
-                scalehandle_draw_select(sh,canvas,x->x_gui.x_w+5-1,x->x_gui.x_h-1,nlet_tag,"HSLDR");
-                if (strcmp(x->x_gui.x_lab->s_name, "empty") != 0)
-                {
-                    scalehandle_draw_select(lh,canvas,x->x_gui.x_ldx,x->x_gui.x_ldy,nlet_tag,"HSLDR");
-                }
+                         "-fill $pd_colors(selection)\n", canvas, x);
+                scalehandle_draw_select2(&x->x_gui,glist,"HSLDR");
             }
-
             sys_vgui(".x%lx.c addtag selected withtag %lxHSLDR\n", canvas, x);
         }
         else
@@ -265,7 +250,6 @@ static void hslider_draw_select(t_hslider* x,t_glist* glist)
                 canvas, x, x->x_gui.x_lcol);
             sys_vgui(".x%lx.c dtag %lxHSLDR selected\n", canvas, x);
             scalehandle_draw_erase2(&x->x_gui,glist);
-
         }
     //}
 }
@@ -276,164 +260,59 @@ void hslider_check_width(t_hslider *x, int w);
 static void hslider__clickhook(t_scalehandle *sh, t_floatarg f,
     t_floatarg xxx, t_floatarg yyy)
 {
-
     t_hslider *x = (t_hslider *)(sh->h_master);
-
-     if (xxx)
-     {
-         sh->h_offset_x = xxx;
-     }
-     if (yyy)
-     {
-         sh->h_offset_y = yyy;
-     }
-
     int newstate = (int)f;
     if (sh->h_dragon && newstate == 0 && sh->h_scale)
     {
-        /* done dragging */
-
-        /* first set up the undo apply */
         canvas_apply_setundo(x->x_gui.x_glist, (t_gobj *)x);
-
         if (sh->h_dragx || sh->h_dragy)
         {
-
             double width_change_ratio = (double)(x->x_gui.x_w +
-                sh->h_dragx - sh->h_offset_x)/(double)x->x_gui.x_w;
+                sh->h_dragx)/(double)x->x_gui.x_w;
             x->x_val = x->x_val * width_change_ratio;
-
-            x->x_gui.x_w = x->x_gui.x_w + sh->h_dragx - sh->h_offset_x;
-            if (x->x_gui.x_w < SCALE_HSLD_MINWIDTH)
-                x->x_gui.x_w = SCALE_HSLD_MINWIDTH;
-            x->x_gui.x_h = x->x_gui.x_h + sh->h_dragy - sh->h_offset_y;
-            if (x->x_gui.x_h < SCALE_HSLD_MINHEIGHT)
-                x->x_gui.x_h = SCALE_HSLD_MINHEIGHT;
-
+            hslider_check_width(x, x->x_gui.x_w + sh->h_dragx);
+            x->x_gui.x_h += sh->h_dragy;
+            hslider_check_minmax(x, x->x_min, x->x_max);
             canvas_dirty(x->x_gui.x_glist, 1);
         }
-
-        int properties = gfxstub_haveproperties((void *)x);
-
-        if (properties)
-        {
-            properties_set_field_int(properties,"dim.w_ent",x->x_gui.x_w);
-            properties_set_field_int(properties,"dim.h_ent",x->x_gui.x_h);
-        }
-
-        hslider_check_width(x, x->x_gui.x_w);
-        hslider_check_minmax(x, x->x_min, x->x_max);
-
         if (glist_isvisible(x->x_gui.x_glist))
         {
-            sys_vgui(".x%x.c delete %s\n", x->x_gui.x_glist, sh->h_outlinetag);
             hslider_draw_move(x, x->x_gui.x_glist);
-            iemgui_select((t_gobj *)x, x->x_gui.x_glist, 1);
-            canvas_fixlinesfor(x->x_gui.x_glist, (t_text *)x);
-            sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", x->x_gui.x_glist);
+            scalehandle_unclick_scale(sh);
         }
     }
     else if (!sh->h_dragon && newstate && sh->h_scale)
     {
-        /* dragging */
-        if (glist_isvisible(x->x_gui.x_glist))
-        {
-            sys_vgui("lower %s\n", sh->h_pathname);
-            sys_vgui(".x%x.c create prect %d %d %d %d "
-                     "-stroke $pd_colors(selection) -strokewidth 1 -tags %s\n",
-                x->x_gui.x_glist, x->x_gui.x_obj.te_xpix,
-                x->x_gui.x_obj.te_ypix,
-                x->x_gui.x_obj.te_xpix + 5 + x->x_gui.x_w,
-                x->x_gui.x_obj.te_ypix + x->x_gui.x_h, sh->h_outlinetag);
-        }
-
-        sh->h_dragx = 0;
-        sh->h_dragy = 0;
+        scalehandle_click_scale(sh);
     }
     else if (sh->h_dragon && newstate == 0 && !sh->h_scale)
     {
-        /* done dragging */
-
-        /* first set up the undo apply */
-        canvas_apply_setundo(x->x_gui.x_glist, (t_gobj *)x);
-
-        if (sh->h_dragx || sh->h_dragy)
-        {
-
-            x->x_gui.x_ldx = x->x_gui.x_ldx +
-                sh->h_dragx - sh->h_offset_x;
-            x->x_gui.x_ldy = x->x_gui.x_ldy +
-                sh->h_dragy - sh->h_offset_y;
-
-            canvas_dirty(x->x_gui.x_glist, 1);
-        }
-
-        int properties = gfxstub_haveproperties((void *)x);
-
-        if (properties)
-        {
-            properties_set_field_int(properties,"dim.w_ent",x->x_gui.x_w);
-        }
-
-        if (glist_isvisible(x->x_gui.x_glist))
-        {
-            sys_vgui(".x%x.c delete %s\n", x->x_gui.x_glist, sh->h_outlinetag);
-            hslider_draw_move(x, x->x_gui.x_glist);
-            iemgui_select((t_gobj *)x, x->x_gui.x_glist, 1);
-            canvas_fixlinesfor(x->x_gui.x_glist, (t_text *)x);
-            sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", x->x_gui.x_glist);
-        }
+        scalehandle_unclick_label(sh);
     }
     else if (!sh->h_dragon && newstate && !sh->h_scale)
     {
-        /* dragging */
-        if (glist_isvisible(x->x_gui.x_glist))
-        {
-            sys_vgui("lower %s\n", sh->h_pathname);
-            t_scalehandle *othersh = x->x_gui.x_handle;
-            sys_vgui("lower .x%lx.h%lx\n",
-                (t_int)glist_getcanvas(x->x_gui.x_glist), (t_int)othersh);
-        }
-
-        sh->h_dragx = 0;
-        sh->h_dragy = 0;
+        scalehandle_click_label(sh);
     }
     sh->h_dragon = newstate;
 }
 
-static void hslider__motionhook(t_scalehandle *sh,
-                    t_floatarg f1, t_floatarg f2)
+static void hslider__motionhook(t_scalehandle *sh, t_floatarg f1, t_floatarg f2)
 {
     if (sh->h_dragon && sh->h_scale)
     {
         t_hslider *x = (t_hslider *)(sh->h_master);
         int dx = (int)f1, dy = (int)f2;
-        int newx, newy;
-        newx = x->x_gui.x_obj.te_xpix +
-            x->x_gui.x_w - sh->h_offset_x + dx;
-        newy = x->x_gui.x_obj.te_ypix +
-            x->x_gui.x_h - sh->h_offset_y + dy;
-
-        if (newx < x->x_gui.x_obj.te_xpix + SCALE_HSLD_MINWIDTH)
-            newx = x->x_gui.x_obj.te_xpix + SCALE_HSLD_MINWIDTH;
-        if (newy < x->x_gui.x_obj.te_ypix + SCALE_HSLD_MINHEIGHT)
-            newy = x->x_gui.x_obj.te_ypix + SCALE_HSLD_MINHEIGHT;
-
-        if (glist_isvisible(x->x_gui.x_glist))
-        {
-            sys_vgui(".x%x.c coords %s %d %d %d %d\n",
-                 x->x_gui.x_glist, sh->h_outlinetag, x->x_gui.x_obj.te_xpix,
-                 x->x_gui.x_obj.te_ypix, newx + 5, newy);
-        }
+        dx = maxi(dx, IEM_SL_MINSIZE-x->x_gui.x_w);
+        dy = maxi(dy,IEM_GUI_MINSIZE-x->x_gui.x_h);
         sh->h_dragx = dx;
         sh->h_dragy = dy;
+        scalehandle_drag_scale(sh);
 
         int properties = gfxstub_haveproperties((void *)x);
-
         if (properties)
         {
-            int new_w = x->x_gui.x_w - sh->h_offset_x + sh->h_dragx;
-            int new_h = x->x_gui.x_h - sh->h_offset_y + sh->h_dragy;
+            int new_w = x->x_gui.x_w + sh->h_dragx;
+            int new_h = x->x_gui.x_h + sh->h_dragy;
             properties_set_field_int(properties,"dim.w_ent",new_w);
             properties_set_field_int(properties,"dim.h_ent",new_h);
         }
diff --git a/pd/src/g_mycanvas.c b/pd/src/g_mycanvas.c
index 4e47e1503..08984e69c 100644
--- a/pd/src/g_mycanvas.c
+++ b/pd/src/g_mycanvas.c
@@ -31,7 +31,7 @@ void my_canvas_draw_select(t_my_canvas* x, t_glist* glist);
 /* ---------- cnv  my gui-canvas for a window ---------------- */
 
 t_widgetbehavior my_canvas_widgetbehavior;
-static t_class *my_canvas_class;
+/*static*/ t_class *my_canvas_class;
 
 /* widget helper functions */
 
@@ -133,11 +133,7 @@ void my_canvas_draw_config(t_my_canvas* x, t_glist* glist)
 void my_canvas_draw_select(t_my_canvas* x, t_glist* glist)
 {
     t_canvas *canvas=glist_getcanvas(glist);
-    t_scalehandle *sh = (t_scalehandle *)(x->x_gui.x_handle);
-    t_scalehandle *lh = (t_scalehandle *)(x->x_gui.x_lhandle);
-
     //if (glist_isvisible(canvas)) {
-
         if(x->x_gui.x_fsf.x_selected)
         {
             // check if we are drawing inside a gop abstraction
@@ -145,19 +141,11 @@ void my_canvas_draw_select(t_my_canvas* x, t_glist* glist)
             // if so, disable highlighting
             if (x->x_gui.x_glist == glist_getcanvas(glist))
             {
-
                 char *nlet_tag = iem_get_tag(glist, (t_iemgui *)x);
-
                 sys_vgui(".x%lx.c itemconfigure %lxBASE "
                          "-stroke $pd_colors(selection)\n", canvas, x);
-
-                scalehandle_draw_select(sh,canvas,x->x_vis_w-1,x->x_vis_h-1,nlet_tag,"MYCNV");
-                if (strcmp(x->x_gui.x_lab->s_name, "empty") != 0)
-                {
-                    scalehandle_draw_select(lh,canvas,x->x_gui.x_ldx,x->x_gui.x_ldy,nlet_tag,"MYCNV");
-                }
+                scalehandle_draw_select2(&x->x_gui,glist,"MYCNV");
             }
-
             sys_vgui(".x%lx.c addtag selected withtag %lxMYCNV\n", canvas, x);
         }
         else
@@ -173,163 +161,55 @@ void my_canvas_draw_select(t_my_canvas* x, t_glist* glist)
 static void my_canvas__clickhook(t_scalehandle *sh, t_floatarg f,
     t_floatarg xxx, t_floatarg yyy)
 {
-
     t_my_canvas *x = (t_my_canvas *)(sh->h_master);
-
-    if (xxx)
-    {
-        sh->h_offset_x = xxx;
-    }
-    if (yyy)
-    {
-        sh->h_offset_y = yyy;
-    }
-
     int newstate = (int)f;
     if (sh->h_dragon && newstate == 0 && sh->h_scale)
     {
-        /* done dragging */
-
-        /* first set up the undo apply */
         canvas_apply_setundo(x->x_gui.x_glist, (t_gobj *)x);
-
         if (sh->h_dragx || sh->h_dragy)
         {
-
-            x->x_vis_w = x->x_vis_w + sh->h_dragx - sh->h_offset_x;
-            if (x->x_vis_w < SCALE_CNV_MINWIDTH)
-                x->x_vis_w = SCALE_CNV_MINWIDTH;
-            x->x_vis_h = x->x_vis_h + sh->h_dragy - sh->h_offset_y;
-            if (x->x_vis_h < SCALE_CNV_MINHEIGHT)
-                x->x_vis_h = SCALE_CNV_MINHEIGHT;
-
-            if (x->x_gui.x_w > x->x_vis_w || x->x_gui.x_h > x->x_vis_h)
-            {
-                x->x_gui.x_w = (x->x_vis_w > x->x_vis_h ? x->x_vis_h : x->x_vis_w);
-                x->x_gui.x_h = x->x_gui.x_w;
-            }
+            x->x_vis_w += sh->h_dragx;
+            x->x_vis_h += sh->h_dragy;
             canvas_dirty(x->x_gui.x_glist, 1);
         }
-
-        int properties = gfxstub_haveproperties((void *)x);
-
-        if (properties)
-        {
-            properties_set_field_int(properties,"rng.min_ent",x->x_vis_w);
-            properties_set_field_int(properties,"rng.max_ent",x->x_vis_h);
-            properties_set_field_int(properties,"dim.w_ent",x->x_gui.x_w);
-        }
-
         if (glist_isvisible(x->x_gui.x_glist))
         {
-            sys_vgui(".x%x.c delete %s\n", x->x_gui.x_glist, sh->h_outlinetag);
             my_canvas_draw_move(x, x->x_gui.x_glist);
-            iemgui_select((t_gobj *)x, x->x_gui.x_glist, 1);
-            canvas_fixlinesfor(x->x_gui.x_glist, (t_text *)x);
-            sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", x->x_gui.x_glist);
+            scalehandle_unclick_scale(sh);
         }
     }
     else if (!sh->h_dragon && newstate && sh->h_scale)
     {
-        /* dragging */
-        if (glist_isvisible(x->x_gui.x_glist))
-        {
-            sys_vgui("lower %s\n", sh->h_pathname);
-            sys_vgui(".x%x.c create prect %d %d %d %d "
-                     "-stroke $pd_colors(selection) -strokewidth 1 -tags %s\n",
-                x->x_gui.x_glist, x->x_gui.x_obj.te_xpix,
-                x->x_gui.x_obj.te_ypix,
-                x->x_gui.x_obj.te_xpix + x->x_vis_w,
-                x->x_gui.x_obj.te_ypix + x->x_vis_h, sh->h_outlinetag);
-        }
-
-        sh->h_dragx = 0;
-        sh->h_dragy = 0;
+        scalehandle_click_scale(sh);
     }
     else if (sh->h_dragon && newstate == 0 && !sh->h_scale)
     {
-        /* done dragging */
-
-        /* first set up the undo apply */
-        canvas_apply_setundo(x->x_gui.x_glist, (t_gobj *)x);
-
-        if (sh->h_dragx || sh->h_dragy)
-        {
-
-            x->x_gui.x_ldx = x->x_gui.x_ldx + sh->h_dragx -
-                sh->h_offset_x;
-            x->x_gui.x_ldy = x->x_gui.x_ldy + sh->h_dragy -
-                sh->h_offset_y;
-
-            canvas_dirty(x->x_gui.x_glist, 1);
-        }
-
-        int properties = gfxstub_haveproperties((void *)x);
-
-        if (properties)
-        {
-            properties_set_field_int(properties,"label.xy.x_entry",x->x_gui.x_ldx);
-            properties_set_field_int(properties,"label.xy.y_entry",x->x_gui.x_ldy);
-        }
-
-        if (glist_isvisible(x->x_gui.x_glist))
-        {
-            my_canvas_draw_move(x, x->x_gui.x_glist);
-            iemgui_select((t_gobj *)x, x->x_gui.x_glist, 1);
-            canvas_fixlinesfor(x->x_gui.x_glist, (t_text *)x);
-            sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", x->x_gui.x_glist);
-        }
+        scalehandle_unclick_label(sh);
     }
     else if (!sh->h_dragon && newstate && !sh->h_scale)
     {
-        /* dragging */
-        if (glist_isvisible(x->x_gui.x_glist))
-        {
-            sys_vgui("lower %s\n", sh->h_pathname);
-            t_scalehandle *othersh = x->x_gui.x_handle;
-            sys_vgui("lower .x%lx.h%lx\n",
-                (t_int)glist_getcanvas(x->x_gui.x_glist), (t_int)othersh);
-        }
-
-        sh->h_dragx = 0;
-        sh->h_dragy = 0;
+        scalehandle_click_label(sh);
     }
     sh->h_dragon = newstate;
 }
 
-static void my_canvas__motionhook(t_scalehandle *sh,
-                    t_floatarg f1, t_floatarg f2)
+static void my_canvas__motionhook(t_scalehandle *sh, t_floatarg f1, t_floatarg f2)
 {
     if (sh->h_dragon && sh->h_scale)
     {
         t_my_canvas *x = (t_my_canvas *)(sh->h_master);
         int dx = (int)f1, dy = (int)f2;
-        int newx, newy;
-        newx = x->x_gui.x_obj.te_xpix + x->x_vis_w -
-            sh->h_offset_x + dx;
-        newy = x->x_gui.x_obj.te_ypix + x->x_vis_h -
-            sh->h_offset_y + dy;
-
-        if (newx < x->x_gui.x_obj.te_xpix + SCALE_CNV_MINWIDTH)
-            newx = x->x_gui.x_obj.te_xpix + SCALE_CNV_MINWIDTH;
-        if (newy < x->x_gui.x_obj.te_ypix + SCALE_CNV_MINHEIGHT)
-            newy = x->x_gui.x_obj.te_ypix + SCALE_CNV_MINHEIGHT;
-
-        if (glist_isvisible(x->x_gui.x_glist))
-        {
-            sys_vgui(".x%x.c coords %s %d %d %d %d\n",
-                 x->x_gui.x_glist, sh->h_outlinetag, x->x_gui.x_obj.te_xpix,
-                 x->x_gui.x_obj.te_ypix, newx, newy);
-        }
+        dx = maxi(dx,1-x->x_vis_w);
+        dy = maxi(dy,1-x->x_vis_h);        
         sh->h_dragx = dx;
         sh->h_dragy = dy;
+        scalehandle_drag_scale(sh);
 
         int properties = gfxstub_haveproperties((void *)x);
-
         if (properties)
         {
-            int new_w = x->x_vis_w - sh->h_offset_x + sh->h_dragx;
-            int new_h = x->x_vis_h - sh->h_offset_y + sh->h_dragy;
+            int new_w = x->x_vis_w + sh->h_dragx;
+            int new_h = x->x_vis_h + sh->h_dragy;
             properties_set_field_int(properties,"rng.min_ent",new_w);
             properties_set_field_int(properties,"rng.max_ent",new_h);
 
diff --git a/pd/src/g_numbox.c b/pd/src/g_numbox.c
index 074e3856d..5423423fc 100644
--- a/pd/src/g_numbox.c
+++ b/pd/src/g_numbox.c
@@ -64,19 +64,18 @@ void my_numbox_clip(t_my_numbox *x)
         x->x_val = x->x_max;
 }
 
-int my_numbox_calc_fontwidth(t_my_numbox *x)
+int my_numbox_calc_fontwidth2(t_my_numbox *x, int w, int h, int fontsize)
 {
-    int w, f=31;
-
-    if(x->x_gui.x_fsf.x_font_style == 1)
-        f = 27;
-    else if(x->x_gui.x_fsf.x_font_style == 2)
-        f = 25;
+    int f=31;
+    if     (x->x_gui.x_fsf.x_font_style == 1) f = 27;
+    else if(x->x_gui.x_fsf.x_font_style == 2) f = 25;
+    return (fontsize * f * w) / 36 + (h / 2) + 4;
+}
 
-    w = x->x_gui.x_fontsize * f * x->x_gui.x_w;
-    w /= 36;
-    w = w + (x->x_gui.x_h / 2) + 4;
-    return w;    
+int my_numbox_calc_fontwidth(t_my_numbox *x)
+{
+    return my_numbox_calc_fontwidth2(x,x->x_gui.x_w,x->x_gui.x_h,
+        x->x_gui.x_fontsize);
 }
 
 void my_numbox_ftoa(t_my_numbox *x)
@@ -439,11 +438,7 @@ static void my_numbox_draw_io(t_my_numbox* x,t_glist* glist,
 static void my_numbox_draw_select(t_my_numbox *x, t_glist *glist)
 {
     t_canvas *canvas=glist_getcanvas(glist);
-    t_scalehandle *sh = (t_scalehandle *)(x->x_gui.x_handle);
-    t_scalehandle *lh = (t_scalehandle *)(x->x_gui.x_lhandle);
-
     //if (glist_isvisible(canvas)) {
-
         if(x->x_gui.x_fsf.x_selected)
         {
             if(x->x_gui.x_fsf.x_change)
@@ -453,35 +448,18 @@ static void my_numbox_draw_select(t_my_numbox *x, t_glist *glist)
                 x->x_buf[0] = 0;
                 sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update);
             }
-
             // check if we are drawing inside a gop abstraction
             // visible on parent canvas
             // if so, disable highlighting
             if (x->x_gui.x_glist == glist_getcanvas(glist))
             {
-
                 char *nlet_tag = iem_get_tag(glist, (t_iemgui *)x);
-
-                sys_vgui(".x%lx.c itemconfigure %lxBASE1 "
-                         "-stroke $pd_colors(selection)\n",
-                    canvas, x);
-                sys_vgui(".x%lx.c itemconfigure %lxBASE2 "
-                         "-stroke $pd_colors(selection)\n",
-                    canvas, x);
-                sys_vgui(".x%lx.c itemconfigure %lxLABEL "
-                         "-fill $pd_colors(selection)\n",
-                    canvas, x);
-                sys_vgui(".x%lx.c itemconfigure %lxNUMBER "
-                         "-fill $pd_colors(selection)\n",
-                    canvas, x);
-
-                scalehandle_draw_select(sh,canvas,x->x_numwidth-1,x->x_gui.x_h-1,nlet_tag,"NUM");
-                if (strcmp(x->x_gui.x_lab->s_name, "empty") != 0)
-                {
-                    scalehandle_draw_select(lh,canvas,x->x_gui.x_ldx,x->x_gui.x_ldy,nlet_tag,"NUM");
-                }
+                sys_vgui(".x%lx.c itemconfigure {%lxBASE1||%lxBASE2} "
+                         "-stroke $pd_colors(selection)\n", canvas, x, x);
+                sys_vgui(".x%lx.c itemconfigure {%lxLABEL||%lxNUMBER} "
+                         "-fill $pd_colors(selection)\n", canvas, x, x);
+                scalehandle_draw_select2(&x->x_gui,glist,"NUM");
             }
-
             sys_vgui(".x%lx.c addtag selected withtag %lxNUM\n", canvas, x);
         }
         else
@@ -508,124 +486,41 @@ static void my_numbox_draw_select(t_my_numbox *x, t_glist *glist)
 static void my_numbox__clickhook(t_scalehandle *sh, t_floatarg f,
     t_floatarg xxx, t_floatarg yyy)
 {
-
     t_my_numbox *x = (t_my_numbox *)(sh->h_master);
-
-     if (xxx)
-     {
-         sh->h_offset_x = xxx;
-     }
-     if (yyy)
-     {
-         sh->h_offset_y = yyy;
-     }
-
     int newstate = (int)f;
     if (sh->h_dragon && newstate == 0 && sh->h_scale)
     {
-        /* done dragging */
-
-        /* first set up the undo apply */
         canvas_apply_setundo(x->x_gui.x_glist, (t_gobj *)x);
-
         if (sh->h_dragx || sh->h_dragy)
         {
-
             x->x_gui.x_fontsize = x->x_tmpfontsize;
             x->x_gui.x_w = x->x_scalewidth;
             x->x_gui.x_h = x->x_scaleheight;
-
             x->x_numwidth = my_numbox_calc_fontwidth(x);
-
             canvas_dirty(x->x_gui.x_glist, 1);
         }
-
-        int properties = gfxstub_haveproperties((void *)x);
-        if (properties)
-        {
-            properties_set_field_int(properties,"dim.w_ent",x->x_gui.x_w);
-            properties_set_field_int(properties,"dim.h_ent",x->x_gui.x_h);
-            properties_set_field_int(properties,"dim.fontsize_entry",
-                x->x_gui.x_fontsize);
-        }
-
         if (glist_isvisible(x->x_gui.x_glist))
         {
-            sys_vgui(".x%x.c delete %s\n", x->x_gui.x_glist, sh->h_outlinetag);
             my_numbox_draw_move(x, x->x_gui.x_glist);
             my_numbox_draw_config(x, x->x_gui.x_glist);
             my_numbox_draw_update((t_gobj*)x, x->x_gui.x_glist);
-            iemgui_select((t_gobj *)x, x->x_gui.x_glist, 1);
-            canvas_fixlinesfor(x->x_gui.x_glist, (t_text *)x);
-            sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", x->x_gui.x_glist);
+            scalehandle_unclick_scale(sh);
         }
     }
     else if (!sh->h_dragon && newstate && sh->h_scale)
     {
-        /* dragging */
-        if (glist_isvisible(x->x_gui.x_glist))
-        {
-            sys_vgui("lower %s\n", sh->h_pathname);
-            sys_vgui(".x%x.c create prect %d %d %d %d "
-                     "-stroke $pd_colors(selection) -strokewidth 1 -tags %s\n",
-                x->x_gui.x_glist, x->x_gui.x_obj.te_xpix,
-                x->x_gui.x_obj.te_ypix,
-                x->x_gui.x_obj.te_xpix + x->x_numwidth,
-                x->x_gui.x_obj.te_ypix + x->x_gui.x_h, sh->h_outlinetag);
-        }
-
+        scalehandle_click_scale(sh);
         x->x_scalewidth = x->x_gui.x_w;
         x->x_scaleheight = x->x_gui.x_h;
         x->x_tmpfontsize = x->x_gui.x_fontsize;
-        sh->h_dragx = 0;
-        sh->h_dragy = 0;
     }
     else if (sh->h_dragon && newstate == 0 && !sh->h_scale)
     {
-        /* done dragging */
-
-        /* first set up the undo apply */
-        canvas_apply_setundo(x->x_gui.x_glist, (t_gobj *)x);
-
-        if (sh->h_dragx || sh->h_dragy)
-        {
-
-            x->x_gui.x_ldx =
-                x->x_gui.x_ldx + sh->h_dragx - sh->h_offset_x;
-            x->x_gui.x_ldy =
-                x->x_gui.x_ldy + sh->h_dragy - sh->h_offset_y;
-
-            canvas_dirty(x->x_gui.x_glist, 1);
-        }
-
-        int properties = gfxstub_haveproperties((void *)x);
-        if (properties)
-        {
-            properties_set_field_int(properties,"dim.w_ent",x->x_gui.x_w);
-        }
-
-        if (glist_isvisible(x->x_gui.x_glist))
-        {
-            sys_vgui(".x%x.c delete %s\n", x->x_gui.x_glist, sh->h_outlinetag);
-            my_numbox_draw_move(x, x->x_gui.x_glist);
-            iemgui_select((t_gobj *)x, x->x_gui.x_glist, 1);
-            canvas_fixlinesfor(x->x_gui.x_glist, (t_text *)x);
-            sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", x->x_gui.x_glist);
-        }
+        scalehandle_unclick_label(sh);
     }
     else if (!sh->h_dragon && newstate && !sh->h_scale)
     {
-        /* dragging */
-        if (glist_isvisible(x->x_gui.x_glist))
-        {
-            sys_vgui("lower %s\n", sh->h_pathname);
-            t_scalehandle *othersh = x->x_gui.x_handle;
-            sys_vgui("lower .x%lx.h%lx\n",
-                (t_int)glist_getcanvas(x->x_gui.x_glist), (t_int)othersh);
-        }
-
-        sh->h_dragx = 0;
-        sh->h_dragy = 0;
+        scalehandle_click_label(sh);
     }
     sh->h_dragon = newstate;
 }
@@ -637,29 +532,22 @@ static void my_numbox__motionhook(t_scalehandle *sh,
     {
         t_my_numbox *x = (t_my_numbox *)(sh->h_master);
         int dx = (int)f1, dy = (int)f2;
-        int newx, newy;
 
         /* first calculate y */
-        newy = x->x_gui.x_obj.te_ypix + x->x_gui.x_h +
-            (dy - sh->h_offset_y);
-        if (newy < x->x_gui.x_obj.te_ypix + SCALE_NUM_MINHEIGHT)
-            newy = x->x_gui.x_obj.te_ypix + SCALE_NUM_MINHEIGHT;
+        int newy = maxi(x->x_gui.x_obj.te_ypix + x->x_gui.x_h +
+            dy, x->x_gui.x_obj.te_ypix + SCALE_NUM_MINHEIGHT);
 
         /* then readjust fontsize */
-        x->x_tmpfontsize = (newy - x->x_gui.x_obj.te_ypix) * 0.8;
-        if (x->x_tmpfontsize < IEM_FONT_MINSIZE)
-            x->x_tmpfontsize = IEM_FONT_MINSIZE;
+        x->x_tmpfontsize = maxi((newy - x->x_gui.x_obj.te_ypix) * 0.8,
+            IEM_FONT_MINSIZE);
 
         int f = 31;
-        if(x->x_gui.x_fsf.x_font_style == 1)
-            f = 27;
-        else if(x->x_gui.x_fsf.x_font_style == 2)
-            f = 25;
-        int char_w = x->x_tmpfontsize * f;
-        char_w /= 36;
+        if     (x->x_gui.x_fsf.x_font_style == 1) f = 27;
+        else if(x->x_gui.x_fsf.x_font_style == 2) f = 25;
+        int char_w = (x->x_tmpfontsize * f) / 36;
 
         /* get the new total width */
-        int new_total_width = x->x_numwidth + (dx - sh->h_offset_x);
+        int new_total_width = x->x_numwidth + dx;
         
         /* now figure out what does this translate into in terms of
            character length */
@@ -668,21 +556,17 @@ static void my_numbox__motionhook(t_scalehandle *sh,
         if (new_char_len < SCALE_NUM_MINWIDTH)
             new_char_len = SCALE_NUM_MINWIDTH;
 
-        newx = x->x_gui.x_obj.te_xpix +
-            new_char_len * char_w +
-            ((newy - x->x_gui.x_obj.te_ypix) / 2) + 4;
-
-        if (glist_isvisible(x->x_gui.x_glist))
-        {
-            sys_vgui(".x%x.c coords %s %d %d %d %d\n",
-                 x->x_gui.x_glist, sh->h_outlinetag, x->x_gui.x_obj.te_xpix,
-                 x->x_gui.x_obj.te_ypix, newx, newy);
-        }
-        sh->h_dragx = dx;
-        sh->h_dragy = dy;
         x->x_scalewidth = new_char_len;
         x->x_scaleheight = newy - x->x_gui.x_obj.te_ypix;
 
+        int numwidth = my_numbox_calc_fontwidth2(x,new_char_len,
+            x->x_scaleheight,x->x_tmpfontsize);
+        sh->h_dragx = numwidth - x->x_numwidth;
+        sh->h_dragy = dy;
+        //printf("dx=%-4d dy=%-4d scalewidth=%-4d scaleheight=%-4d numwidth=%-4d dragx=%-4d\n",
+        //    dx,dy,x->x_scalewidth,x->x_scaleheight,numwidth,sh->h_dragx);
+        scalehandle_drag_scale(sh);
+
         int properties = gfxstub_haveproperties((void *)x);
         if (properties)
         {
diff --git a/pd/src/g_toggle.c b/pd/src/g_toggle.c
index 19316029a..e8869bb58 100644
--- a/pd/src/g_toggle.c
+++ b/pd/src/g_toggle.c
@@ -247,34 +247,20 @@ void toggle_draw_io(t_toggle* x, t_glist* glist, int old_snd_rcv_flags)
 void toggle_draw_select(t_toggle* x, t_glist* glist)
 {
     t_canvas *canvas=glist_getcanvas(glist);
-    t_scalehandle *sh = (t_scalehandle *)(x->x_gui.x_handle);
-    t_scalehandle *lh = (t_scalehandle *)(x->x_gui.x_lhandle);
-
     //if (glist_isvisible(canvas)) {
-
         if(x->x_gui.x_fsf.x_selected)
         {
-
             // check if we are drawing inside a gop abstraction
             // visible on parent canvas
             // if so, disable highlighting
             if (x->x_gui.x_glist == glist_getcanvas(glist))
             {
-
-                char *nlet_tag = iem_get_tag(glist, (t_iemgui *)x);
-
                 sys_vgui(".x%lx.c itemconfigure %lxBASE "
                          "-stroke $pd_colors(selection)\n", canvas, x);
                 sys_vgui(".x%lx.c itemconfigure %lxLABEL "
                          "-fill $pd_colors(selection)\n", canvas, x);
-
-                scalehandle_draw_select(sh,canvas,x->x_gui.x_w-1,x->x_gui.x_h-1,nlet_tag,"TGL");
-                if (strcmp(x->x_gui.x_lab->s_name, "empty") != 0)
-                {
-                    scalehandle_draw_select(lh,canvas,x->x_gui.x_ldx,x->x_gui.x_ldy,nlet_tag,"TGL");
-                }
+                scalehandle_draw_select2(&x->x_gui,glist,"TGL");
             }
-
             sys_vgui(".x%lx.c addtag selected withtag %lxTGL\n", canvas, x);
         }
         else
@@ -292,125 +278,35 @@ void toggle_draw_select(t_toggle* x, t_glist* glist)
 static void toggle__clickhook(t_scalehandle *sh, t_floatarg f,
     t_floatarg xxx, t_floatarg yyy)
 {
-
     t_toggle *x = (t_toggle *)(sh->h_master);
-
-    if (xxx)
-    {
-        sh->h_offset_x = xxx;
-    }
-    if (yyy)
-    {
-        sh->h_offset_y = yyy;
-    }
-
     int newstate = (int)f;
     if (sh->h_dragon && newstate == 0 && sh->h_scale)
     {
-        /* done dragging */
-
-        /* first set up the undo apply */
         canvas_apply_setundo(x->x_gui.x_glist, (t_gobj *)x);
-
         if (sh->h_dragx || sh->h_dragy)
         {
-
-            if (sh->h_dragx > sh->h_dragy)
-                sh->h_dragx = sh->h_dragy;
-            else sh->h_dragy = sh->h_dragx;
-
-            x->x_gui.x_w = x->x_gui.x_w + sh->h_dragx - sh->h_offset_x;
-            if (x->x_gui.x_w < SCALE_TGL_MINWIDTH)
-                x->x_gui.x_w = SCALE_TGL_MINWIDTH;
-            x->x_gui.x_h = x->x_gui.x_h + sh->h_dragy - sh->h_offset_y;
-            if (x->x_gui.x_h < SCALE_TGL_MINHEIGHT)
-                x->x_gui.x_h = SCALE_TGL_MINHEIGHT;
-
+            x->x_gui.x_w += sh->h_dragx;
+            x->x_gui.x_h += sh->h_dragy;
             canvas_dirty(x->x_gui.x_glist, 1);
         }
-
-        int properties = gfxstub_haveproperties((void *)x);
-
-        if (properties)
-        {
-            properties_set_field_int(properties,"dim.w_ent",x->x_gui.x_w);
-        }
-
         if (glist_isvisible(x->x_gui.x_glist))
         {
-            sys_vgui(".x%x.c delete %s\n", x->x_gui.x_glist, sh->h_outlinetag);
             toggle_draw_move(x, x->x_gui.x_glist);
-            iemgui_select((t_gobj *)x, x->x_gui.x_glist, 1);
-            canvas_fixlinesfor(x->x_gui.x_glist, (t_text *)x);
-            sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", x->x_gui.x_glist);
+            scalehandle_unclick_scale(sh);
         }
     }
     else if (!sh->h_dragon && newstate && sh->h_scale)
     {
-        /* dragging */
-        if (glist_isvisible(x->x_gui.x_glist))
-        {
-            sys_vgui("lower %s\n", sh->h_pathname);
-            sys_vgui(".x%x.c create prect %d %d %d %d "
-                     "-stroke $pd_colors(selection) -strokewidth 1 -tags %s\n",
-                x->x_gui.x_glist, x->x_gui.x_obj.te_xpix,
-                x->x_gui.x_obj.te_ypix,
-                x->x_gui.x_obj.te_xpix + x->x_gui.x_w,
-                x->x_gui.x_obj.te_ypix + x->x_gui.x_h, sh->h_outlinetag);
-        }
-
-        sh->h_dragx = 0;
-        sh->h_dragy = 0;
+        scalehandle_click_scale(sh);
     }
     else if (sh->h_dragon && !newstate && !sh->h_scale)
     {
-        /* done dragging */
-
-        /* first set up the undo apply */
-        canvas_apply_setundo(x->x_gui.x_glist, (t_gobj *)x);
-
-        if (sh->h_dragx || sh->h_dragy)
-        {
-
-            x->x_gui.x_ldx =
-                x->x_gui.x_ldx + sh->h_dragx - sh->h_offset_x;
-            x->x_gui.x_ldy =
-                x->x_gui.x_ldy + sh->h_dragy - sh->h_offset_y;
-
-            canvas_dirty(x->x_gui.x_glist, 1);
-        }
-
-        int properties = gfxstub_haveproperties((void *)x);
-
-        if (properties)
-        {
-            properties_set_field_int(properties,"dim.w_ent",x->x_gui.x_w);
-        }
-
-        if (glist_isvisible(x->x_gui.x_glist))
-        {
-            sys_vgui(".x%x.c delete %s\n", x->x_gui.x_glist, sh->h_outlinetag);
-            toggle_draw_move(x, x->x_gui.x_glist);
-            iemgui_select((t_gobj *)x, x->x_gui.x_glist, 1);
-            canvas_fixlinesfor(x->x_gui.x_glist, (t_text *)x);
-            sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", x->x_gui.x_glist);
-        }
+        scalehandle_unclick_label(sh);
     }
     else if(!sh->h_dragon && newstate && !sh->h_scale)
     {
-        /* dragging */
-        if (glist_isvisible(x->x_gui.x_glist))
-        {
-            sys_vgui("lower %s\n", sh->h_pathname);
-            t_scalehandle *othersh = x->x_gui.x_handle;
-            sys_vgui("lower .x%lx.h%lx\n",
-                (t_int)glist_getcanvas(x->x_gui.x_glist), (t_int)othersh);
-        }
-
-        sh->h_dragx = 0;
-        sh->h_dragy = 0;
+        scalehandle_click_label(sh);
     }
-
     sh->h_dragon = newstate;
 }
 
@@ -419,44 +315,16 @@ static void toggle__motionhook(t_scalehandle *sh, t_floatarg f1, t_floatarg f2)
     if (sh->h_dragon && sh->h_scale)
     {
         t_toggle *x = (t_toggle *)(sh->h_master);
-        int dx = (int)f1, dy = (int)f2;
-        int newx, newy;
-
-        if (dx > dy)
-        {
-            dx = dy;
-            sh->h_offset_x = sh->h_offset_y;
-        }
-        else
-        {
-            dy = dx;
-            sh->h_offset_y = sh->h_offset_x;
-        }
-
-        newx = x->x_gui.x_obj.te_xpix + x->x_gui.x_w -
-            sh->h_offset_x + dx;
-        newy = x->x_gui.x_obj.te_ypix + x->x_gui.x_h -
-            sh->h_offset_y + dy;
-
-        if (newx < x->x_gui.x_obj.te_xpix + SCALE_TGL_MINWIDTH)
-            newx = x->x_gui.x_obj.te_xpix + SCALE_TGL_MINWIDTH;
-        if (newy < x->x_gui.x_obj.te_ypix + SCALE_TGL_MINHEIGHT)
-            newy = x->x_gui.x_obj.te_ypix + SCALE_TGL_MINHEIGHT;
-
-        if (glist_isvisible(x->x_gui.x_glist))
-        {
-            sys_vgui(".x%x.c coords %s %d %d %d %d\n",
-                 x->x_gui.x_glist, sh->h_outlinetag, x->x_gui.x_obj.te_xpix,
-                 x->x_gui.x_obj.te_ypix, newx, newy);
-        }
-        sh->h_dragx = dx;
-        sh->h_dragy = dy;
+        int d = maxi((int)f1,(int)f2);
+        d = maxi(d,IEM_GUI_MINSIZE-x->x_gui.x_w);
+        sh->h_dragx = d;
+        sh->h_dragy = d;
+        scalehandle_drag_scale(sh);
 
         int properties = gfxstub_haveproperties((void *)x);
-
         if (properties)
         {
-            int new_w = x->x_gui.x_w - sh->h_offset_x + sh->h_dragx;
+            int new_w = x->x_gui.x_w + sh->h_dragx;
             properties_set_field_int(properties,"dim.w_ent",new_w);
         }
     }
diff --git a/pd/src/g_vdial.c b/pd/src/g_vdial.c
index 8fdde3c4d..93d05594b 100644
--- a/pd/src/g_vdial.c
+++ b/pd/src/g_vdial.c
@@ -243,36 +243,23 @@ void vradio_draw_io(t_vradio* x, t_glist* glist, int old_snd_rcv_flags)
 void vradio_draw_select(t_vradio* x, t_glist* glist)
 {
     t_canvas *canvas=glist_getcanvas(glist);
-    t_scalehandle *sh = (t_scalehandle *)(x->x_gui.x_handle);
-    t_scalehandle *lh = (t_scalehandle *)(x->x_gui.x_lhandle);
     int n=x->x_number, i;
-
     //if (glist_isvisible(canvas)) {
-
         if(x->x_gui.x_fsf.x_selected)
         {
-
             /* check if we are drawing inside a gop abstraction visible
                on parent canvas. If so, disable highlighting */
             if (x->x_gui.x_glist == glist_getcanvas(glist))
             {
                 char *nlet_tag = iem_get_tag(glist, (t_iemgui *)x);
-
                 for(i=0; i<n; i++)
                 {
                     sys_vgui(".x%lx.c itemconfigure %lxBASE%d "
-                             "-stroke $pd_colors(selection)\n",
-                        canvas, x, i);
+                             "-stroke $pd_colors(selection)\n", canvas, x, i);
                 }
                 sys_vgui(".x%lx.c itemconfigure %lxLABEL "
-                         "-fill $pd_colors(selection)\n",
-                    canvas, x);
-
-                scalehandle_draw_select(sh,canvas,x->x_gui.x_w-1,x->x_gui.x_h*x->x_number-1,nlet_tag,"VRDO");
-                if (strcmp(x->x_gui.x_lab->s_name, "empty") != 0)
-                {
-                    scalehandle_draw_select(lh,canvas,x->x_gui.x_ldx,x->x_gui.x_ldy,nlet_tag,"VRDO");
-                }
+                         "-fill $pd_colors(selection)\n", canvas, x);
+                scalehandle_draw_select2(&x->x_gui,glist,"VRDO");
             }
 
             sys_vgui(".x%lx.c addtag selected withtag %lxVRDO\n", canvas, x);
@@ -295,162 +282,54 @@ void vradio_draw_select(t_vradio* x, t_glist* glist)
 static void vradio__clickhook(t_scalehandle *sh, t_floatarg f, t_floatarg xxx,
     t_floatarg yyy)
 {
-
     t_vradio *x = (t_vradio *)(sh->h_master);
-
-    if (xxx)
-    {
-        sh->h_offset_x = xxx;
-    }
-    if (yyy)
-    {
-        sh->h_offset_y = yyy;
-    }
-
     int newstate = (int)f;
     if (sh->h_dragon && newstate == 0 && sh->h_scale)
     {
-        /* done dragging */
-
-        /* first set up the undo apply */
         canvas_apply_setundo(x->x_gui.x_glist, (t_gobj *)x);
-
         if (sh->h_dragx || sh->h_dragy)
         {
-
-            sh->h_dragy = sh->h_dragx;
-
-            x->x_gui.x_w = x->x_gui.x_w + sh->h_dragx - sh->h_offset_x;
-            if (x->x_gui.x_w < SCALE_VRDO_MINWIDTH)
-                x->x_gui.x_w = SCALE_VRDO_MINWIDTH;
-            x->x_gui.x_h = x->x_gui.x_h + sh->h_dragy - sh->h_offset_x;
-            if (x->x_gui.x_h < SCALE_VRDO_MINHEIGHT)
-                x->x_gui.x_h = SCALE_VRDO_MINHEIGHT;
-
+            x->x_gui.x_w += sh->h_dragx;
+            x->x_gui.x_h += sh->h_dragx;
             canvas_dirty(x->x_gui.x_glist, 1);
         }
-
-        int properties = gfxstub_haveproperties((void *)x);
-        if (properties)
-        {
-            properties_set_field_int(properties,"dim.w_ent",x->x_gui.x_w);
-        }
-
         if (glist_isvisible(x->x_gui.x_glist))
         {
-            sys_vgui(".x%x.c delete %s\n", x->x_gui.x_glist, sh->h_outlinetag);
             vradio_draw_move(x, x->x_gui.x_glist);
-            iemgui_select((t_gobj *)x, x->x_gui.x_glist, 1);
-            canvas_fixlinesfor(x->x_gui.x_glist, (t_text *)x);
-            sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", x->x_gui.x_glist);
+            scalehandle_unclick_scale(sh);
         }
     }
     else if (!sh->h_dragon && newstate && sh->h_scale)
     {
-        /* dragging */
-        if (glist_isvisible(x->x_gui.x_glist))
-        {
-            sys_vgui("lower %s\n", sh->h_pathname);
-            sys_vgui(".x%x.c create prect %d %d %d %d "
-                     "-stroke $pd_colors(selection) -strokewidth 1 "
-                     "-tags %s\n",
-                 x->x_gui.x_glist,
-                 x->x_gui.x_obj.te_xpix, x->x_gui.x_obj.te_ypix,
-                 x->x_gui.x_obj.te_xpix + x->x_gui.x_w,
-                 x->x_gui.x_obj.te_ypix + (x->x_gui.x_h * x->x_number),
-                 sh->h_outlinetag);
-        }
-
-        sh->h_dragx = 0;
-        sh->h_dragy = 0;
+        scalehandle_click_scale(sh);
     }
     else if (sh->h_dragon && newstate == 0 && !sh->h_scale)
     {
-        /* done dragging */
-
-        /* first set up the undo apply */
-        canvas_apply_setundo(x->x_gui.x_glist, (t_gobj *)x);
-
-        if (sh->h_dragx || sh->h_dragy)
-        {
-
-            x->x_gui.x_ldx =
-                x->x_gui.x_ldx + sh->h_dragx - sh->h_offset_x;
-            x->x_gui.x_ldy =
-                x->x_gui.x_ldy + sh->h_dragy - sh->h_offset_y;
-
-            canvas_dirty(x->x_gui.x_glist, 1);
-        }
-
-        int properties = gfxstub_haveproperties((void *)x);
-
-        if (properties)
-        {
-            properties_set_field_int(properties,"dim.w_ent",x->x_gui.x_w);
-        }
-
-        if (glist_isvisible(x->x_gui.x_glist))
-        {
-            sys_vgui(".x%x.c delete %s\n", x->x_gui.x_glist, sh->h_outlinetag);
-            vradio_draw_move(x, x->x_gui.x_glist);
-            iemgui_select((t_gobj *)x, x->x_gui.x_glist, 1);
-            canvas_fixlinesfor(x->x_gui.x_glist, (t_text *)x);
-            sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", x->x_gui.x_glist);
-        }
+        scalehandle_unclick_label(sh);
     }
     else if (!sh->h_dragon && newstate && !sh->h_scale)
     {
-        /* dragging */
-        if (glist_isvisible(x->x_gui.x_glist))
-        {
-            sys_vgui("lower %s\n", sh->h_pathname);
-            t_scalehandle *othersh = x->x_gui.x_handle;
-            sys_vgui("lower .x%lx.h%lx\n",
-                (t_int)glist_getcanvas(x->x_gui.x_glist), (t_int)othersh);
-        }
-
-        sh->h_dragx = 0;
-        sh->h_dragy = 0;
+        scalehandle_click_label(sh);
     }
-
     sh->h_dragon = newstate;
 }
 
-static void vradio__motionhook(t_scalehandle *sh,
-                    t_floatarg f1, t_floatarg f2)
+static void vradio__motionhook(t_scalehandle *sh, t_floatarg f1, t_floatarg f2)
 {
     if (sh->h_dragon && sh->h_scale)
     {
         t_vradio *x = (t_vradio *)(sh->h_master);
         int dx = (int)f1, dy = (int)f2;
-        int newx, newy;
-
-        dy = dx;
-
-        newx = x->x_gui.x_obj.te_xpix + x->x_gui.x_h +
-            (dx - sh->h_offset_x);
-        newy = x->x_gui.x_obj.te_ypix + x->x_gui.x_h * x->x_number +
-            (dy - sh->h_offset_x) * x->x_number;
-
-        if (newx < x->x_gui.x_obj.te_xpix + SCALE_VRDO_MINWIDTH)
-            newx = x->x_gui.x_obj.te_xpix + SCALE_VRDO_MINWIDTH;
-        if (newy < x->x_gui.x_obj.te_ypix + SCALE_VRDO_MINHEIGHT*x->x_number)
-            newy = x->x_gui.x_obj.te_ypix + SCALE_VRDO_MINHEIGHT*x->x_number;
-
-        if (glist_isvisible(x->x_gui.x_glist))
-        {
-            sys_vgui(".x%x.c coords %s %d %d %d %d\n",
-                 x->x_gui.x_glist, sh->h_outlinetag, x->x_gui.x_obj.te_xpix,
-                 x->x_gui.x_obj.te_ypix, newx, newy);
-        }
+        dy = maxi(dy,(IEM_GUI_MINSIZE-x->x_gui.x_h)*x->x_number);
+        dx = dy/x->x_number;
         sh->h_dragx = dx;
         sh->h_dragy = dy;
+        scalehandle_drag_scale(sh);
 
         int properties = gfxstub_haveproperties((void *)x);
-
         if (properties)
         {
-            int new_w = x->x_gui.x_h - sh->h_offset_y + sh->h_dragy;
+            int new_w = x->x_gui.x_h + sh->h_dragy;
             properties_set_field_int(properties,"dim.w_ent",new_w);
         }
     }
diff --git a/pd/src/g_vslider.c b/pd/src/g_vslider.c
index 4d6aae719..b1897b6a5 100644
--- a/pd/src/g_vslider.c
+++ b/pd/src/g_vslider.c
@@ -243,34 +243,19 @@ static void vslider_draw_io(t_vslider* x,t_glist* glist, int old_snd_rcv_flags)
 static void vslider_draw_select(t_vslider *x, t_glist *glist)
 {
     t_canvas *canvas=glist_getcanvas(glist);
-    t_scalehandle *sh = (t_scalehandle *)(x->x_gui.x_handle);
-    t_scalehandle *lh = (t_scalehandle *)(x->x_gui.x_lhandle);
-
     //if (glist_isvisible(canvas)) {
-
         if(x->x_gui.x_fsf.x_selected)
         {
             // check if we are drawing inside a gop abstraction
             // visible on parent canvas. If so, disable highlighting
             if (x->x_gui.x_glist == glist_getcanvas(glist))
             {
-
-                char *nlet_tag = iem_get_tag(glist, (t_iemgui *)x);
-
                 sys_vgui(".x%lx.c itemconfigure %lxBASE "
-                         "-stroke $pd_colors(selection)\n",
-                     canvas, x);
+                         "-stroke $pd_colors(selection)\n", canvas, x);
                 sys_vgui(".x%lx.c itemconfigure %lxLABEL "
-                         "-fill $pd_colors(selection)\n",
-                     canvas, x);
-
-                scalehandle_draw_select(sh,canvas,x->x_gui.x_w-1,x->x_gui.x_h+5-1,nlet_tag,"VSLDR");
-                if (strcmp(x->x_gui.x_lab->s_name, "empty") != 0)
-                {
-                    scalehandle_draw_select(lh,canvas,x->x_gui.x_ldx,x->x_gui.x_ldy,nlet_tag,"VSLDR");
-                }
+                         "-fill $pd_colors(selection)\n", canvas, x);
+                scalehandle_draw_select2(&x->x_gui,glist,"VSLDR");
             }
-
             sys_vgui(".x%lx.c addtag selected withtag %lxVSLDR\n", canvas, x);
         }
         else
@@ -291,163 +276,59 @@ void vslider_check_height(t_vslider *x, int w);
 static void vslider__clickhook(t_scalehandle *sh, t_floatarg f, t_floatarg xxx,
     t_floatarg yyy)
 {
-
     t_vslider *x = (t_vslider *)(sh->h_master);
-
-     if (xxx)
-     {
-         sh->h_offset_x = xxx;
-     }
-     if (yyy)
-     {
-         sh->h_offset_y = yyy;
-     }
-
     int newstate = (int)f;
     if (sh->h_dragon && newstate == 0 && sh->h_scale)
     {
-        /* done dragging */
-
-        /* first set up the undo apply */
         canvas_apply_setundo(x->x_gui.x_glist, (t_gobj *)x);
-
         if (sh->h_dragx || sh->h_dragy)
         {
-
-            double height_change_ratio = (double)(x->x_gui.x_h + sh->h_dragy -
-                sh->h_offset_y)/(double)x->x_gui.x_h;
+            double height_change_ratio = (double)(x->x_gui.x_h + sh->h_dragy)
+                /(double)x->x_gui.x_h;
             x->x_val = x->x_val * height_change_ratio;
-
-            x->x_gui.x_w = x->x_gui.x_w + sh->h_dragx - sh->h_offset_x;
-            if (x->x_gui.x_w < SCALE_VSLD_MINWIDTH)
-                x->x_gui.x_w = SCALE_VSLD_MINWIDTH;
-            x->x_gui.x_h = x->x_gui.x_h + sh->h_dragy - sh->h_offset_y;
-            if (x->x_gui.x_h < SCALE_VSLD_MINHEIGHT)
-                x->x_gui.x_h = SCALE_VSLD_MINHEIGHT;
-
+            x->x_gui.x_w += sh->h_dragx;
+            vslider_check_height(x, x->x_gui.x_h + sh->h_dragy);
+            vslider_check_minmax(x, x->x_min, x->x_max);
             canvas_dirty(x->x_gui.x_glist, 1);
         }
-
-        vslider_check_height(x, x->x_gui.x_h);
-        vslider_check_minmax(x, x->x_min, x->x_max);
-
-        int properties = gfxstub_haveproperties((void *)x);
-
-        if (properties)
-        {
-            properties_set_field_int(properties,"dim.w_ent",x->x_gui.x_w);
-            properties_set_field_int(properties,"dim.h_ent",x->x_gui.x_h);
-        }
-
         if (glist_isvisible(x->x_gui.x_glist))
         {
-            sys_vgui(".x%x.c delete %s\n", x->x_gui.x_glist, sh->h_outlinetag);
             vslider_draw_move(x, x->x_gui.x_glist);
-            iemgui_select((t_gobj *)x, x->x_gui.x_glist, 1);
-            canvas_fixlinesfor(x->x_gui.x_glist, (t_text *)x);
-            sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", x->x_gui.x_glist);
+            scalehandle_unclick_scale(sh);
         }
     }
     else if (!sh->h_dragon && newstate && sh->h_scale)
     {
-        /* dragging */
-        if (glist_isvisible(x->x_gui.x_glist))
-        {
-            sys_vgui("lower %s\n", sh->h_pathname);
-            sys_vgui(".x%x.c create prect %d %d %d %d "
-                     "-stroke $pd_colors(selection) -strokewidth 1 -tags %s\n",
-                x->x_gui.x_glist, x->x_gui.x_obj.te_xpix,
-                x->x_gui.x_obj.te_ypix,
-                x->x_gui.x_obj.te_xpix + x->x_gui.x_w,
-                x->x_gui.x_obj.te_ypix + 5 + x->x_gui.x_h, sh->h_outlinetag);
-        }
-
-        sh->h_dragx = 0;
-        sh->h_dragy = 0;
+        scalehandle_click_scale(sh);
     }
     else if (sh->h_dragon && newstate == 0 && !sh->h_scale)
     {
-        /* done dragging */
-
-        /* first set up the undo apply */
-        canvas_apply_setundo(x->x_gui.x_glist, (t_gobj *)x);
-
-        if (sh->h_dragx || sh->h_dragy)
-        {
-
-            x->x_gui.x_ldx = x->x_gui.x_ldx +
-                sh->h_dragx - sh->h_offset_x;
-            x->x_gui.x_ldy = x->x_gui.x_ldy +
-                sh->h_dragy - sh->h_offset_y;
-
-            canvas_dirty(x->x_gui.x_glist, 1);
-        }
-
-        int properties = gfxstub_haveproperties((void *)x);
-        if (properties)
-        {
-            properties_set_field_int(properties,"dim.w_ent",x->x_gui.x_w);
-        }
-
-        if (glist_isvisible(x->x_gui.x_glist))
-        {
-            sys_vgui(".x%x.c delete %s\n", x->x_gui.x_glist, sh->h_outlinetag);
-            vslider_draw_move(x, x->x_gui.x_glist);
-            iemgui_select((t_gobj *)x, x->x_gui.x_glist, 1);
-            canvas_fixlinesfor(x->x_gui.x_glist, (t_text *)x);
-            sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", x->x_gui.x_glist);
-        }
+        scalehandle_unclick_label(sh);
     }
     else if (!sh->h_dragon && newstate && !sh->h_scale)
     {
-        /* dragging */
-        if (glist_isvisible(x->x_gui.x_glist))
-        {
-            sys_vgui("lower %s\n", sh->h_pathname);
-            t_scalehandle *othersh = x->x_gui.x_handle;
-            sys_vgui("lower .x%lx.h%lx\n",
-                (t_int)glist_getcanvas(x->x_gui.x_glist), (t_int)othersh);
-        }
-
-        sh->h_dragx = 0;
-        sh->h_dragy = 0;
+        scalehandle_click_label(sh);
     }
-
     sh->h_dragon = newstate;
 }
 
-static void vslider__motionhook(t_scalehandle *sh,
-                    t_floatarg f1, t_floatarg f2)
+static void vslider__motionhook(t_scalehandle *sh, t_floatarg f1, t_floatarg f2)
 {
     if (sh->h_dragon && sh->h_scale)
     {
         t_vslider *x = (t_vslider *)(sh->h_master);
         int dx = (int)f1, dy = (int)f2;
-        int newx, newy;
-        newx = x->x_gui.x_obj.te_xpix + x->x_gui.x_w -
-            sh->h_offset_x + dx;
-        newy = x->x_gui.x_obj.te_ypix + x->x_gui.x_h -
-            sh->h_offset_y + dy;
-
-        if (newx < x->x_gui.x_obj.te_xpix + SCALE_VSLD_MINWIDTH)
-            newx = x->x_gui.x_obj.te_xpix + SCALE_VSLD_MINWIDTH;
-        if (newy < x->x_gui.x_obj.te_ypix + SCALE_VSLD_MINHEIGHT)
-            newy = x->x_gui.x_obj.te_ypix + SCALE_VSLD_MINHEIGHT;
-
-        if (glist_isvisible(x->x_gui.x_glist))
-        {
-            sys_vgui(".x%x.c coords %s %d %d %d %d\n",
-                 x->x_gui.x_glist, sh->h_outlinetag, x->x_gui.x_obj.te_xpix,
-                 x->x_gui.x_obj.te_ypix, newx, newy + 5);
-        }
+        dx = maxi(dx,IEM_GUI_MINSIZE-x->x_gui.x_w);
+        dy = maxi(dy, IEM_SL_MINSIZE-x->x_gui.x_h);
         sh->h_dragx = dx;
         sh->h_dragy = dy;
+        scalehandle_drag_scale(sh);
 
         int properties = gfxstub_haveproperties((void *)x);
         if (properties)
         {
-            int new_w = x->x_gui.x_w - sh->h_offset_x + sh->h_dragx;
-            int new_h = x->x_gui.x_h - sh->h_offset_y + sh->h_dragy;
+            int new_w = x->x_gui.x_w + sh->h_dragx;
+            int new_h = x->x_gui.x_h + sh->h_dragy;
             properties_set_field_int(properties,"dim.w_ent",new_w);
             properties_set_field_int(properties,"dim.h_ent",new_h);
         }
diff --git a/pd/src/g_vumeter.c b/pd/src/g_vumeter.c
index 23ada02fc..5b4d3dc86 100644
--- a/pd/src/g_vumeter.c
+++ b/pd/src/g_vumeter.c
@@ -419,46 +419,30 @@ static void vu_draw_select(t_vu* x,t_glist* glist)
 {
     int i;
     t_canvas *canvas=glist_getcanvas(glist);
-    t_scalehandle *sh = (t_scalehandle *)(x->x_gui.x_handle);
-    t_scalehandle *lh = (t_scalehandle *)(x->x_gui.x_lhandle);
-
     //if (glist_isvisible(canvas)) {
-
         if(x->x_gui.x_fsf.x_selected)
         {
             // check if we are drawing inside a gop abstraction
             // visible on parent canvas. If so, disable highlighting
             if (x->x_gui.x_glist == glist_getcanvas(glist))
             {
-
-                char *nlet_tag = iem_get_tag(glist, (t_iemgui *)x);
-
                 sys_vgui(".x%lx.c itemconfigure %lxBASE "
-                         "-stroke $pd_colors(selection)\n",
-                     canvas, x);
+                         "-stroke $pd_colors(selection)\n", canvas, x);
                 for(i = 1; i <= IEM_VU_STEPS; i++)
                 {
                     if(((i + 2) & 3) && (x->x_scale))
                         sys_vgui(".x%lx.c itemconfigure %lxSCALE%d "
-                                 "-fill $pd_colors(selection)\n",
-                            canvas, x, i);
+                            "-fill $pd_colors(selection)\n", canvas, x, i);
                 }
                 if(x->x_scale)
                 {
                     i=IEM_VU_STEPS+1;
                     sys_vgui(".x%lx.c itemconfigure %lxSCALE%d "
-                             "-fill $pd_colors(selection)\n",
-                        canvas, x, i);
+                             "-fill $pd_colors(selection)\n", canvas, x, i);
                 }
                 sys_vgui(".x%lx.c itemconfigure %lxLABEL "
-                         "-fill $pd_colors(selection)\n",
-                    canvas, x);
-
-                scalehandle_draw_select(sh,canvas,x->x_gui.x_w+2-1,x->x_gui.x_h+4-1,nlet_tag,"VU");
-                if (strcmp(x->x_gui.x_lab->s_name, "empty") != 0)
-                {
-                    scalehandle_draw_select(lh,canvas,x->x_gui.x_ldx,x->x_gui.x_ldy,nlet_tag,"VU");
-                }
+                         "-fill $pd_colors(selection)\n", canvas, x);
+                scalehandle_draw_select2(&x->x_gui,glist,"BNG");
             }
 
             sys_vgui(".x%lx.c addtag selected withtag %lxVU\n", canvas, x);
@@ -490,166 +474,58 @@ static void vu_draw_select(t_vu* x,t_glist* glist)
 static void vu__clickhook(t_scalehandle *sh, t_floatarg f, t_floatarg xxx,
     t_floatarg yyy)
 {
-
     t_vu *x = (t_vu *)(sh->h_master);
-
-    if (xxx)
-    {
-        sh->h_offset_x = xxx;
-    }
-    if (yyy)
-    {
-        sh->h_offset_y = yyy;
-    }
-
     int newstate = (int)f;
     if (sh->h_dragon && newstate == 0  && sh->h_scale)
     {
-        /* done dragging */
-
-        /* first set up the undo apply */
         canvas_apply_setundo(x->x_gui.x_glist, (t_gobj *)x);
-
         if (sh->h_dragx || sh->h_dragy)
         {
-
-            x->x_gui.x_w = x->x_gui.x_w + sh->h_dragx - sh->h_offset_x;
-            if (x->x_gui.x_w < SCALE_BNG_MINWIDTH)
-                x->x_gui.x_w = SCALE_BNG_MINWIDTH;
-            x->x_gui.x_h = x->x_gui.x_h + sh->h_dragy - sh->h_offset_y;
-            if (x->x_gui.x_h < SCALE_BNG_MINHEIGHT)
-                x->x_gui.x_h = SCALE_BNG_MINHEIGHT;
-
+            x->x_gui.x_w += sh->h_dragx;
+            x->x_gui.x_h += sh->h_dragy;
             canvas_dirty(x->x_gui.x_glist, 1);
         }
-
-        int properties = gfxstub_haveproperties((void *)x);
-
-        if (properties)
-        {
-            properties_set_field_int(properties,"dim.w_ent",x->x_gui.x_w);
-            properties_set_field_int(properties,"dim.h_ent",x->x_gui.x_h);
-        }
-
         if (glist_isvisible(x->x_gui.x_glist))
         {
-            sys_vgui(".x%x.c delete %s\n", x->x_gui.x_glist, sh->h_outlinetag);
             vu_check_height(x, x->x_gui.x_h);
             vu_draw_move(x, x->x_gui.x_glist);
             vu_draw_config(x, x->x_gui.x_glist);
             vu_draw_update((t_gobj *)x, x->x_gui.x_glist);
-            iemgui_select((t_gobj *)x, x->x_gui.x_glist, 1);
-            canvas_fixlinesfor(x->x_gui.x_glist, (t_text *)x);
-            sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", x->x_gui.x_glist);
+            scalehandle_unclick_scale(sh);
         }
     }
     else if (!sh->h_dragon && newstate && sh->h_scale)
     {
-        /* dragging */
-        if (glist_isvisible(x->x_gui.x_glist))
-        {
-            sys_vgui("lower %s\n", sh->h_pathname);
-            sys_vgui(".x%x.c create prect %d %d %d %d "
-                     "-stroke $pd_colors(selection) -strokewidth 1 -tags %s\n",
-                x->x_gui.x_glist,
-                x->x_gui.x_obj.te_xpix, x->x_gui.x_obj.te_ypix,
-                x->x_gui.x_obj.te_xpix + x->x_gui.x_w + 2,
-                x->x_gui.x_obj.te_ypix + x->x_gui.x_h + 4, sh->h_outlinetag);
-        }
-
-        sh->h_dragx = 0;
-        sh->h_dragy = 0;
+        scalehandle_click_scale(sh);
     }
     else if (sh->h_dragon && newstate == 0 && !sh->h_scale)
     {
-        /* done dragging */
-
-        /* first set up the undo apply */
-        canvas_apply_setundo(x->x_gui.x_glist, (t_gobj *)x);
-
-        if (sh->h_dragx || sh->h_dragy)
-        {
-
-            x->x_gui.x_ldx = x->x_gui.x_ldx +
-                sh->h_dragx - sh->h_offset_x;
-            x->x_gui.x_ldy = x->x_gui.x_ldy +
-                sh->h_dragy - sh->h_offset_y;
-
-            canvas_dirty(x->x_gui.x_glist, 1);
-        }
-
-        int properties = gfxstub_haveproperties((void *)x);
-
-        if (properties)
-        {
-            properties_set_field_int(properties,"dim.w_ent",x->x_gui.x_w);
-        }
-
-        if (glist_isvisible(x->x_gui.x_glist))
-        {
-            sys_vgui(".x%x.c delete %s\n", x->x_gui.x_glist, sh->h_outlinetag);
-            vu_draw_move(x, x->x_gui.x_glist);
-            iemgui_select((t_gobj *)x, x->x_gui.x_glist, 1);
-            canvas_fixlinesfor(x->x_gui.x_glist, (t_text *)x);
-            sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", x->x_gui.x_glist);
-        }
+        scalehandle_unclick_label(sh);
     }
     else if (!sh->h_dragon && newstate && !sh->h_scale)
     {
-        /* dragging */
-        if (glist_isvisible(x->x_gui.x_glist))
-        {
-            sys_vgui("lower %s\n", sh->h_pathname);
-            t_scalehandle *othersh = x->x_gui.x_handle;
-            sys_vgui("lower .x%lx.h%lx\n",
-                (t_int)glist_getcanvas(x->x_gui.x_glist), (t_int)othersh);
-        }
-
-        sh->h_dragx = 0;
-        sh->h_dragy = 0;
+        scalehandle_click_label(sh);
     }
-
     sh->h_dragon = newstate;
 }
 
-static void vu__motionhook(t_scalehandle *sh,
-                    t_floatarg f1, t_floatarg f2)
+static void vu__motionhook(t_scalehandle *sh, t_floatarg f1, t_floatarg f2)
 {
     if (sh->h_dragon && sh->h_scale)
     {
         t_vu *x = (t_vu *)(sh->h_master);
         int dx = (int)f1, dy = (int)f2;
-        int newx, newy;
-
-        int y_incr = (int)((dy - sh->h_offset_y) / IEM_VU_STEPS);
-        if (dy - sh->h_offset_y < 0)
-            y_incr -= 1;
-
-        newx = x->x_gui.x_obj.te_xpix +
-            x->x_gui.x_w - sh->h_offset_x + dx;
-        newy = x->x_gui.x_obj.te_ypix +
-            x->x_gui.x_h + y_incr * IEM_VU_STEPS;
-
-        if (newx < x->x_gui.x_obj.te_xpix + SCALE_BNG_MINWIDTH)
-            newx = x->x_gui.x_obj.te_xpix + SCALE_BNG_MINWIDTH;
-        if (newy < x->x_gui.x_obj.te_ypix + SCALE_BNG_MINHEIGHT)
-            newy = x->x_gui.x_obj.te_ypix + SCALE_BNG_MINHEIGHT;
-
-        if (glist_isvisible(x->x_gui.x_glist))
-        {
-            sys_vgui(".x%x.c coords %s %d %d %d %d\n",
-                 x->x_gui.x_glist, sh->h_outlinetag, x->x_gui.x_obj.te_xpix,
-                 x->x_gui.x_obj.te_ypix, newx + 2, newy + 4);
-        }
+        dx = maxi(dx, 8-x->x_gui.x_w);
+        dy = maxi(dy,80-x->x_gui.x_h);        
         sh->h_dragx = dx;
         sh->h_dragy = dy;
+        scalehandle_drag_scale(sh);
 
         int properties = gfxstub_haveproperties((void *)x);
-
         if (properties)
         {
-            int new_w = x->x_gui.x_w - sh->h_offset_x + sh->h_dragx;
-            int new_h = x->x_gui.x_h - sh->h_offset_y + sh->h_dragy;
+            int new_w = x->x_gui.x_w + sh->h_dragx;
+            int new_h = x->x_gui.x_h + sh->h_dragy;
             properties_set_field_int(properties,"dim.w_ent",new_w);
             properties_set_field_int(properties,"dim.h_ent",new_h);
         }
@@ -659,7 +535,6 @@ static void vu__motionhook(t_scalehandle *sh,
 
 void vu_draw(t_vu *x, t_glist *glist, int mode)
 {
-    //fprintf(stderr,"vu_draw %d\n", mode);
     if(mode == IEM_GUI_DRAW_MODE_UPDATE)
         sys_queuegui((t_gobj*)x, x->x_gui.x_glist, vu_draw_update);
     if(mode == IEM_GUI_DRAW_MODE_MOVE)
-- 
GitLab