remove unused includes
[blender.git] / source / blender / editors / interface / interface_handlers.c
index fdd751a8fd8188f022eb8a7adf6467534d598602..e1a760628b05b090605ef7dc62f28f23a049c3d2 100644 (file)
@@ -13,7 +13,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  *
  * The Original Code is Copyright (C) 2008 Blender Foundation.
  * All rights reserved.
  */
 
 #include <float.h>
+#include <limits.h>
 #include <math.h>
 #include <stdlib.h>
 #include <string.h>
+#include <ctype.h>
 
 #include "MEM_guardedalloc.h"
 
-#include "DNA_color_types.h"
 #include "DNA_object_types.h"
 #include "DNA_scene_types.h"
-#include "DNA_screen_types.h"
-#include "DNA_texture_types.h"
-#include "DNA_userdef_types.h"
-#include "DNA_windowmanager_types.h"
 
 #include "BLI_math.h"
 #include "BLI_blenlib.h"
@@ -47,7 +44,6 @@
 #include "BKE_idprop.h"
 #include "BKE_report.h"
 #include "BKE_texture.h"
-#include "BKE_utildefines.h"
 
 #include "ED_screen.h"
 #include "ED_util.h"
@@ -89,6 +85,7 @@ typedef enum uiHandleButtonState {
        BUTTON_STATE_TEXT_EDITING,
        BUTTON_STATE_TEXT_SELECTING,
        BUTTON_STATE_MENU_OPEN,
+       BUTTON_STATE_WAIT_DRAG,
        BUTTON_STATE_EXIT
 } uiHandleButtonState;
 
@@ -180,6 +177,7 @@ typedef struct uiAfterFunc {
        int autokey;
 } uiAfterFunc;
 
+static int ui_but_contains_pt(uiBut *but, int mx, int my);
 static int ui_mouse_inside_button(ARegion *ar, uiBut *but, int x, int y);
 static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState state);
 static int ui_handler_region_menu(bContext *C, wmEvent *event, void *userdata);
@@ -188,11 +186,16 @@ static void button_timers_tooltip_remove(bContext *C, uiBut *but);
 
 /* ******************** menu navigation helpers ************** */
 
+static int ui_but_editable(uiBut *but)
+{
+       return ELEM5(but->type, LABEL, SEPR, ROUNDBOX, LISTBOX, PROGRESSBAR);
+}
+
 static uiBut *ui_but_prev(uiBut *but)
 {
        while(but->prev) {
                but= but->prev;
-               if(!ELEM4(but->type, LABEL, SEPR, ROUNDBOX, LISTBOX)) return but;
+               if(!ui_but_editable(but)) return but;
        }
        return NULL;
 }
@@ -201,7 +204,7 @@ static uiBut *ui_but_next(uiBut *but)
 {
        while(but->next) {
                but= but->next;
-               if(!ELEM4(but->type, LABEL, SEPR, ROUNDBOX, LISTBOX)) return but;
+               if(!ui_but_editable(but)) return but;
        }
        return NULL;
 }
@@ -212,7 +215,7 @@ static uiBut *ui_but_first(uiBlock *block)
        
        but= block->buttons.first;
        while(but) {
-               if(!ELEM4(but->type, LABEL, SEPR, ROUNDBOX, LISTBOX)) return but;
+               if(!ui_but_editable(but)) return but;
                but= but->next;
        }
        return NULL;
@@ -224,7 +227,7 @@ static uiBut *ui_but_last(uiBlock *block)
        
        but= block->buttons.last;
        while(but) {
-               if(!ELEM4(but->type, LABEL, SEPR, ROUNDBOX, LISTBOX)) return but;
+               if(!ui_but_editable(but)) return but;
                but= but->prev;
        }
        return NULL;
@@ -233,7 +236,7 @@ static uiBut *ui_but_last(uiBlock *block)
 static int ui_is_a_warp_but(uiBut *but)
 {
        if(U.uiflag & USER_CONTINUOUS_MOUSE)
-               if(ELEM(but->type, NUM, NUMABS))
+               if(ELEM3(but->type, NUM, NUMABS, HSVCIRCLE))
                        return TRUE;
 
        return FALSE;
@@ -323,7 +326,7 @@ static void ui_apply_autokey_undo(bContext *C, uiBut *but)
        }
 
        /* try autokey */
-       ui_but_anim_autokey(but, scene, scene->r.cfra);
+       ui_but_anim_autokey(C, but, scene, scene->r.cfra);
 }
 
 static void ui_apply_but_funcs_after(bContext *C)
@@ -402,11 +405,7 @@ static void ui_apply_but_BUTM(bContext *C, uiBut *but, uiHandleButtonData *data)
 
 static void ui_apply_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data)
 {
-       if(but->type == COL) {
-               if(but->a1 != -1) // this is not a color picker (weak!)
-                       ui_set_but_vectorf(but, data->vec);
-       }
-       else if(ELEM3(but->type, MENU, ICONROW, ICONTEXTROW))
+       if(ELEM3(but->type, MENU, ICONROW, ICONTEXTROW))
                ui_set_but_val(but, data->value);
 
        ui_check_but(but);
@@ -606,6 +605,53 @@ static void ui_apply_but_CHARTAB(bContext *C, uiBut *but, uiHandleButtonData *da
 }
 #endif
 
+/* ****************** drag drop code *********************** */
+
+static int ui_but_mouse_inside_icon(uiBut *but, ARegion *ar, wmEvent *event)
+{
+       rcti rect;
+       int x= event->x, y= event->y; 
+       
+       ui_window_to_block(ar, but->block, &x, &y);
+       
+       rect.xmin= but->x1; rect.xmax= but->x2;
+       rect.ymin= but->y1; rect.ymax= but->y2;
+       
+       if(but->imb); /* use button size itself */
+       else if(but->flag & UI_ICON_LEFT) {
+               rect.xmax= rect.xmin + (rect.ymax-rect.ymin);
+       }
+       else {
+               int delta= (rect.xmax-rect.xmin) - (rect.ymax-rect.ymin);
+               rect.xmin += delta/2;
+               rect.xmax -= delta/2;
+       }
+       
+       return BLI_in_rcti(&rect, x, y);
+}
+
+#define UI_DRAG_THRESHOLD      3
+static int ui_but_start_drag(bContext *C, uiBut *but, uiHandleButtonData *data, wmEvent *event)
+{
+       /* prevent other WM gestures to start while we try to drag */
+       WM_gestures_remove(C);
+
+       if( ABS(data->dragstartx - event->x) + ABS(data->dragstarty - event->y) > UI_DRAG_THRESHOLD ) {
+               wmDrag *drag;
+               
+               button_activate_state(C, but, BUTTON_STATE_EXIT);
+               data->cancel= 1;
+               
+               drag= WM_event_start_drag(C, but->icon, but->dragtype, but->dragpoin, ui_get_but_val(but));
+               if(but->imb)
+                       WM_event_drag_image(drag, but->imb, but->imb_scale, but->x2-but->x1, but->y2-but->y1);
+               return 1;
+       }
+       
+       return 0;
+}
+
+/* ********************** linklines *********************** */
 
 static void ui_delete_active_linkline(uiBlock *block)
 {
@@ -688,23 +734,19 @@ static void ui_add_link(uiBut *from, uiBut *to)
        if( (line= ui_is_a_link(from, to)) ) {
                line->flag |= UI_SELECT;
                ui_delete_active_linkline(from->block);
-               printf("already exists, means deletion now\n");
                return;
        }
 
        if (from->type==INLINK && to->type==INLINK) {
-               printf("cannot link\n");
                return;
        }
        else if (from->type==LINK && to->type==INLINK) {
                if( from->link->tocode != (int)to->hardmin ) {
-                       printf("cannot link\n");
                        return;
                }
        }
        else if(from->type==INLINK && to->type==LINK) {
                if( to->link->tocode == (int)from->hardmin ) {
-                       printf("cannot link\n");
                        return;
                }
        }
@@ -742,6 +784,8 @@ static void ui_apply_but_LINK(bContext *C, uiBut *but, uiHandleButtonData *data)
                        break;
        }
        if(bt && bt!=but) {
+               if (!ELEM(bt->type, LINK, INLINK) || !ELEM(but->type, LINK, INLINK))
+                       return;
                
                if(but->type==LINK) ui_add_link(but, bt);
                else ui_add_link(bt, but);
@@ -755,11 +799,25 @@ static void ui_apply_but_LINK(bContext *C, uiBut *but, uiHandleButtonData *data)
 static void ui_apply_but_IMAGE(bContext *C, uiBut *but, uiHandleButtonData *data)
 {
        ui_apply_but_func(C, but);
+       data->retval= but->retval;
+       data->applied= 1;
+}
+
+static void ui_apply_but_HISTOGRAM(bContext *C, uiBut *but, uiHandleButtonData *data)
+{
+       ui_apply_but_func(C, but);
+       data->retval= but->retval;
+       data->applied= 1;
+}
 
+static void ui_apply_but_WAVEFORM(bContext *C, uiBut *but, uiHandleButtonData *data)
+{
+       ui_apply_but_func(C, but);
        data->retval= but->retval;
        data->applied= 1;
 }
 
+
 static void ui_apply_button(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, int interactive)
 {
        char *editstr;
@@ -882,6 +940,12 @@ static void ui_apply_button(bContext *C, uiBlock *block, uiBut *but, uiHandleBut
                case BUT_IMAGE: 
                        ui_apply_but_IMAGE(C, but, data);
                        break;
+               case HISTOGRAM: 
+                       ui_apply_but_HISTOGRAM(C, but, data);
+                       break;
+               case WAVEFORM:
+                       ui_apply_but_WAVEFORM(C, but, data);
+                       break;
                default:
                        break;
        }
@@ -893,6 +957,30 @@ static void ui_apply_button(bContext *C, uiBlock *block, uiBut *but, uiHandleBut
        but->editcumap= editcumap;
 }
 
+/* ******************* drop event ********************  */
+
+/* only call if event type is EVT_DROP */
+static void ui_but_drop(bContext *C, wmEvent *event, uiBut *but, uiHandleButtonData *data)
+{
+       wmDrag *wmd;
+       ListBase *drags= event->customdata; /* drop event type has listbase customdata by default */
+       
+       for(wmd= drags->first; wmd; wmd= wmd->next) {
+               if(wmd->type==WM_DRAG_ID) {
+                       /* align these types with UI_but_active_drop_name */
+                       if(ELEM3(but->type, TEX, IDPOIN, SEARCH_MENU)) {
+                               ID *id= (ID *)wmd->poin;
+                               
+                               if(but->poin==NULL && but->rnapoin.data==NULL) {}
+                               button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
+                               BLI_strncpy(data->str, id->name+2, data->maxlen);
+                               button_activate_state(C, but, BUTTON_STATE_EXIT);
+                       }
+               }
+       }
+       
+}
+
 /* ******************* copy and paste ********************  */
 
 /* c = copy, v = paste */
@@ -925,7 +1013,11 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data,
                
                if(but->poin==NULL && but->rnapoin.data==NULL);
                else if(mode=='c') {
-                       sprintf(buf, "%f", ui_get_but_val(but));
+                       if(ui_is_but_float(but))
+                               sprintf(buf, "%f", ui_get_but_val(but));
+                       else
+                               sprintf(buf, "%d", (int)ui_get_but_val(but));
+
                        WM_clipboard_text_set(buf, 0);
                }
                else {
@@ -952,14 +1044,14 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data,
                else {
                        if (sscanf(buf, "[%f, %f, %f]", &rgb[0], &rgb[1], &rgb[2]) == 3) {
                                button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
-                               VECCOPY(data->vec, rgb);
+                               ui_set_but_vectorf(but, rgb);
                                button_activate_state(C, but, BUTTON_STATE_EXIT);
                        }
                }
        }
 
        /* text/string and ID data */
-       else if(ELEM(but->type, TEX, IDPOIN)) {
+       else if(ELEM3(but->type, TEX, IDPOIN, SEARCH_MENU)) {
                uiHandleButtonData *data= but->active;
 
                if(but->poin==NULL && but->rnapoin.data==NULL);
@@ -979,7 +1071,7 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data,
        /* colorband (not supported by system clipboard) */
        else if(but->type==BUT_COLORBAND) {
                if(mode=='c') {
-                       if(but->poin)
+                       if(but->poin==NULL)
                                return;
 
                        memcpy(&but_copypaste_coba, but->poin, sizeof(ColorBand));
@@ -1059,55 +1151,76 @@ static short test_special_char(char ch)
 
 static int ui_textedit_delete_selection(uiBut *but, uiHandleButtonData *data)
 {
-       char *str;
-       int x, changed;
-       
-       str= data->str;
-       changed= (but->selsta != but->selend);
-       
-       for(x=0; x< strlen(str); x++) {
-               if (but->selend + x <= strlen(str) ) {
-                       str[but->selsta + x]= str[but->selend + x];
-               } else {
-                       str[but->selsta + x]= '\0';
-                       break;
-               }
+       char *str= data->str;
+       int len= strlen(str);
+       int change= 0;
+       if(but->selsta != but->selend && len) {
+               memmove( str+but->selsta, str+but->selend, len-but->selsta+1 );
+               change= 1;
        }
-
+       
        but->pos = but->selend = but->selsta;
-
-       return changed;
+       return change;
 }
 
+/* note, but->block->aspect is used here, when drawing button style is getting scaled too */
 static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, short x)
 {
        uiStyle *style= U.uistyles.first;       // XXX pass on as arg
+       uiFontStyle *fstyle = &style->widget;
        int startx= but->x1;
        char *origstr;
 
-       uiStyleFontSet(&style->widget);
+       uiStyleFontSet(fstyle);
 
-       origstr= MEM_callocN(sizeof(char)*(data->maxlen+1), "ui_textedit origstr");
+       if (fstyle->kerning==1) /* for BLF_width */
+               BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
        
-       BLI_strncpy(origstr, but->drawstr, data->maxlen+1);
-       but->pos= strlen(origstr)-but->ofs;
+       origstr= MEM_callocN(sizeof(char)*data->maxlen, "ui_textedit origstr");
+       
+       BLI_strncpy(origstr, but->drawstr, data->maxlen);
        
        /* XXX solve generic */
        if(but->type==NUM || but->type==NUMSLI)
                startx += (int)(0.5f*(but->y2 - but->y1));
-       else if(but->type==TEX)
+       else if(ELEM(but->type, TEX, SEARCH_MENU)) {
                startx += 5;
-       
-       /* XXX does not take zoom level into account */
-       while((BLF_width(origstr+but->ofs) + startx) > x) {
-               if (but->pos <= 0) break;
-               but->pos--;
-               origstr[but->pos+but->ofs] = 0;
+               if (but->flag & UI_HAS_ICON)
+                       startx += 16;
        }
        
-       but->pos += but->ofs;
-       if(but->pos<0) but->pos= 0;
+       /* mouse dragged outside the widget to the left */
+       if (x < startx && but->ofs > 0) {       
+               int i= but->ofs;
 
+               origstr[but->ofs] = 0;
+               
+               while (i > 0) {
+                       i--;
+                       if (BLF_width(fstyle->uifont_id, origstr+i) > (startx - x)*0.25) break; // 0.25 == scale factor for less sensitivity
+               }
+               but->ofs = i;
+               but->pos = but->ofs;
+       }
+       /* mouse inside the widget */
+       else if (x >= startx) {
+               float aspect= sqrt(but->block->aspect);
+               
+               but->pos= strlen(origstr)-but->ofs;
+               
+               /* XXX does not take zoom level into account */
+               while (aspect*startx + aspect*BLF_width(fstyle->uifont_id, origstr+but->ofs) > x) {
+                       if (but->pos <= 0) break;
+                       but->pos--;
+                       origstr[but->pos+but->ofs] = 0;
+               }               
+               but->pos += but->ofs;
+               if(but->pos<0) but->pos= 0;
+       }
+       
+       if (fstyle->kerning == 1)
+               BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
+       
        MEM_freeN(origstr);
 }
 
@@ -1138,7 +1251,7 @@ static int ui_textedit_type_ascii(uiBut *but, uiHandleButtonData *data, char asc
                        changed= ui_textedit_delete_selection(but, data);
 
                len= strlen(str);
-               if(len < data->maxlen) {
+               if(len+1 < data->maxlen) {
                        for(x= data->maxlen; x>but->pos; x--)
                                str[x]= str[x-1];
                        str[but->pos]= ascii;
@@ -1365,13 +1478,15 @@ static int ui_textedit_copypaste(uiBut *but, uiHandleButtonData *data, int paste
                        buf[i]= 0;
 
                        /* paste over the current selection */
-                       if ((but->selend - but->selsta) > 0)
+                       if ((but->selend - but->selsta) > 0) {
                                ui_textedit_delete_selection(but, data);
+                               len= strlen(str);
+                       }
                        
                        for (y=0; y<strlen(buf); y++)
                        {
                                /* add contents of buffer */
-                               if(len < data->maxlen) {
+                               if(len+1 < data->maxlen) {
                                        for(x= data->maxlen; x>but->pos; x--)
                                                str[x]= str[x-1];
                                        str[but->pos]= buf[y];
@@ -1417,9 +1532,22 @@ static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data)
 
        /* retrieve string */
        data->maxlen= ui_get_but_string_max_length(but);
-       data->str= MEM_callocN(sizeof(char)*(data->maxlen+1), "textedit str");
-       ui_get_but_string(but, data->str, data->maxlen+1);
-
+       data->str= MEM_callocN(sizeof(char)*data->maxlen + 1, "textedit str");
+       ui_get_but_string(but, data->str, data->maxlen);
+
+       if(ELEM3(but->type, NUM, NUMABS, NUMSLI)) {
+               /* XXX: we dont have utf editing yet so for numbers its best to strip out utf chars 
+                * this is so the deg' synbol isnt included in number editing fields: bug 22274 */
+               int i;
+               for(i=0; data->str[i]; i++) {
+                       if(!isascii(data->str[i])) {
+                               data->str[i]= '\0';
+                               break;
+                       }
+               }
+       }
+       
+       
        data->origstr= BLI_strdup(data->str);
        data->selextend= 0;
        data->selstartx= 0;
@@ -1437,6 +1565,8 @@ static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data)
        }
        
        ui_check_but(but);
+       
+       WM_cursor_modal(CTX_wm_window(C), BC_TEXTEDITCURSOR);
 }
 
 static void ui_textedit_end(bContext *C, uiBut *but, uiHandleButtonData *data)
@@ -1453,6 +1583,8 @@ static void ui_textedit_end(bContext *C, uiBut *but, uiHandleButtonData *data)
                but->editstr= NULL;
                but->pos= -1;
        }
+       
+       WM_cursor_restore(CTX_wm_window(C));
 }
 
 static void ui_textedit_next_but(uiBlock *block, uiBut *actbut, uiHandleButtonData *data)
@@ -1542,7 +1674,7 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
                                my= event->y;
                                ui_window_to_block(data->region, block, &mx, &my);
 
-                               if ((but->y1 <= my) && (my <= but->y2) && (but->x1 <= mx) && (mx <= but->x2)) {
+                               if (ui_but_contains_pt(but, mx, my)) {
                                        ui_textedit_set_cursor_pos(but, data, mx);
                                        but->selsta = but->selend = but->pos;
                                        data->selstartx= mx;
@@ -1648,7 +1780,11 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
                if(event->ascii && (retval == WM_UI_HANDLER_CONTINUE)) {
                        changed= ui_textedit_type_ascii(but, data, event->ascii);
                        retval= WM_UI_HANDLER_BREAK;
+                       
                }
+               /* textbutton with magnifier icon: do live update for search button */
+               if(but->icon==ICON_VIEWZOOM)
+                       update= 1;
        }
 
        if(changed) {
@@ -1868,37 +2004,39 @@ static int ui_do_but_HOTKEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data
        if(data->state == BUTTON_STATE_HIGHLIGHT) {
                if(ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val==KM_PRESS) {
                        but->drawstr[0]= 0;
-                       *(short *)but->func_arg3= 0;
+                       but->modifier_key= 0;
                        button_activate_state(C, but, BUTTON_STATE_WAIT_KEY_EVENT);
                        return WM_UI_HANDLER_BREAK;
                }
        }
        else if(data->state == BUTTON_STATE_WAIT_KEY_EVENT) {
-               short *sp= (short *)but->func_arg3;
                
                if(event->type == MOUSEMOVE)
                        return WM_UI_HANDLER_CONTINUE;
                
-               if(event->type == ESCKEY) {
-                       /* data->cancel doesnt work, this button opens immediate */
-                       if(but->flag & UI_BUT_IMMEDIATE)
-                               ui_set_but_val(but, 0);
-                       else
-                               data->cancel= 1;
-                       button_activate_state(C, but, BUTTON_STATE_EXIT);
-                       return WM_UI_HANDLER_BREAK;
+               if(event->type == LEFTMOUSE && event->val==KM_PRESS) {
+                       /* only cancel if click outside the button */
+                       if(ui_mouse_inside_button(but->active->region, but, event->x, event->y) == 0) {
+                               /* data->cancel doesnt work, this button opens immediate */
+                               if(but->flag & UI_BUT_IMMEDIATE)
+                                       ui_set_but_val(but, 0);
+                               else
+                                       data->cancel= 1;
+                               button_activate_state(C, but, BUTTON_STATE_EXIT);
+                               return WM_UI_HANDLER_BREAK;
+                       }
                }
                
                /* always set */
-               *sp= 0; 
+               but->modifier_key = 0;
                if(event->shift)
-                       *sp |= KM_SHIFT;
+                       but->modifier_key |= KM_SHIFT;
                if(event->alt)
-                       *sp |= KM_ALT;
+                       but->modifier_key |= KM_ALT;
                if(event->ctrl)
-                       *sp |= KM_CTRL;
+                       but->modifier_key |= KM_CTRL;
                if(event->oskey)
-                       *sp |= KM_OSKEY;
+                       but->modifier_key |= KM_OSKEY;
                
                ui_check_but(but);
                ED_region_tag_redraw(data->region);
@@ -1920,15 +2058,11 @@ static int ui_do_but_HOTKEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data
        return WM_UI_HANDLER_CONTINUE;
 }
 
-
 static int ui_do_but_KEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data, wmEvent *event)
 {
        if(data->state == BUTTON_STATE_HIGHLIGHT) {
                if(ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val==KM_PRESS) {
-                       short event= (short)ui_get_but_val(but);
-                       /* hardcoded prevention from editing or assigning ESC */
-                       if(event!=ESCKEY)
-                               button_activate_state(C, but, BUTTON_STATE_WAIT_KEY_EVENT);
+                       button_activate_state(C, but, BUTTON_STATE_WAIT_KEY_EVENT);
                        return WM_UI_HANDLER_BREAK;
                }
        }
@@ -1937,7 +2071,7 @@ static int ui_do_but_KEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data, w
                        return WM_UI_HANDLER_CONTINUE;
 
                if(event->val==KM_PRESS) {
-                       if(event->type!=ESCKEY && WM_key_event_string(event->type)[0])
+                       if(WM_key_event_string(event->type)[0])
                                ui_set_but_val(but, event->type);
                        else
                                data->cancel= 1;
@@ -1952,7 +2086,7 @@ static int ui_do_but_KEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data, w
 static int ui_do_but_TEX(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, wmEvent *event)
 {
        if(data->state == BUTTON_STATE_HIGHLIGHT) {
-               if(ELEM4(event->type, LEFTMOUSE, PADENTER, RETKEY, EVT_BUT_OPEN) && event->val==KM_PRESS) {
+               if(ELEM(event->type, LEFTMOUSE, EVT_BUT_OPEN) && event->val==KM_PRESS) {
                        if(but->dt == UI_EMBOSSN && !event->ctrl);
                        else {
                                button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
@@ -1987,13 +2121,52 @@ static int ui_do_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data, wmEv
 
 static int ui_do_but_EXIT(bContext *C, uiBut *but, uiHandleButtonData *data, wmEvent *event)
 {
+       
        if(data->state == BUTTON_STATE_HIGHLIGHT) {
+
+               /* first handle click on icondrag type button */
+               if(event->type==LEFTMOUSE && but->dragpoin) {
+                       if(ui_but_mouse_inside_icon(but, data->region, event)) {
+                               
+                               /* tell the button to wait and keep checking further events to
+                                * see if it should start dragging */
+                               button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG);
+                               data->dragstartx= event->x;
+                               data->dragstarty= event->y;
+                               return WM_UI_HANDLER_CONTINUE;
+                       }
+               }
+               
                if(ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val==KM_PRESS) {
+                       int ret = WM_UI_HANDLER_BREAK;
+                       /* XXX (a bit ugly) Special case handling for filebrowser drag button */
+                       if(but->dragpoin && but->imb && ui_but_mouse_inside_icon(but, data->region, event)) {
+                               ret = WM_UI_HANDLER_CONTINUE;
+                       }
                        button_activate_state(C, but, BUTTON_STATE_EXIT);
+                       return ret;
+               }
+       }
+       else if(data->state == BUTTON_STATE_WAIT_DRAG) {
+               
+               /* this function also ends state */
+               if(ui_but_start_drag(C, but, data, event)) {
                        return WM_UI_HANDLER_BREAK;
                }
+               
+               /* If the mouse has been pressed and released, getting to 
+                * this point without triggering a drag, then clear the 
+                * drag state for this button and continue to pass on the event */
+               if(event->type==LEFTMOUSE && event->val==KM_RELEASE) {
+                       button_activate_state(C, but, BUTTON_STATE_EXIT);
+                       return WM_UI_HANDLER_CONTINUE;
+               }
+               
+               /* while waiting for a drag to be triggered, always block 
+                * other events from getting handled */
+               return WM_UI_HANDLER_BREAK;
        }
-
+       
        return WM_UI_HANDLER_CONTINUE;
 }
 
@@ -2064,7 +2237,6 @@ static int ui_numedit_but_NUM(uiBut *but, uiHandleButtonData *data, float fac, i
        softmax= but->softmax;
        softrange= softmax - softmin;
 
-
        if(ui_is_a_warp_but(but)) {
                /* Mouse location isn't screen clamped to the screen so use a linear mapping
                 * 2px == 1-int, or 1px == 1-ClickStep */
@@ -2092,7 +2264,9 @@ static int ui_numedit_but_NUM(uiBut *but, uiHandleButtonData *data, float fac, i
                        }
                }
                else {
-                       fac = 0.5; /* simple 2px == 1 */
+                       if(softrange > 256)             fac= 1.0;               /* 1px == 1 */
+                       else if(softrange > 32) fac= 1.0/2.0;   /* 2px == 1 */
+                       else                                    fac= 1.0/16.0;  /* 16px == 1? */
 
                        temp= data->startvalue + ((mx - data->dragstartx) * fac);
                        temp= ui_numedit_apply_snap(temp, softmin, softmax, snap);
@@ -2122,15 +2296,18 @@ static int ui_numedit_but_NUM(uiBut *but, uiHandleButtonData *data, float fac, i
                /* Use a non-linear mapping of the mouse drag especially for large floats (normal behavior) */
                deler= 500;
                if(!ui_is_but_float(but)) {
-                       if((softrange)<100) deler= 200.0;
-                       if((softrange)<25) deler= 50.0;
+                       /* prevent large ranges from getting too out of control */
+                       if (softrange > 600) deler = powf(softrange, 0.75);
+                       
+                       if (softrange < 100) deler= 200.0;
+                       if (softrange < 25) deler= 50.0;
                }
                deler /= fac;
 
-               if(ui_is_but_float(but) && softrange > 11) {
+               if(softrange > 11) {
                        /* non linear change in mouse input- good for high precicsion */
                        data->dragf+= (((float)(mx-data->draglastx))/deler) * (fabs(data->dragstartx-mx)*0.002);
-               } else if (!ui_is_but_float(but) && softrange > 129) { /* only scale large int buttons */
+               } else if (softrange > 129) { /* only scale large int buttons */
                        /* non linear change in mouse input- good for high precicsionm ints need less fine tuning */
                        data->dragf+= (((float)(mx-data->draglastx))/deler) * (fabs(data->dragstartx-mx)*0.004);
                } else {
@@ -2138,8 +2315,7 @@ static int ui_numedit_but_NUM(uiBut *but, uiHandleButtonData *data, float fac, i
                        data->dragf+= ((float)(mx-data->draglastx))/deler ;
                }
        
-               if(data->dragf>1.0) data->dragf= 1.0;
-               if(data->dragf<0.0) data->dragf= 0.0;
+               CLAMP(data->dragf, 0.0, 1.0);
                data->draglastx= mx;
                tempf= (softmin + data->dragf*softrange);
 
@@ -2151,7 +2327,7 @@ static int ui_numedit_but_NUM(uiBut *but, uiHandleButtonData *data, float fac, i
 
                        CLAMP(temp, softmin, softmax);
                        lvalue= (int)data->value;
-
+                       
                        if(temp != lvalue) {
                                data->dragchange= 1;
                                data->value= (double)temp;
@@ -2210,6 +2386,12 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
                        }
                        else if(ELEM(event->type, PADENTER, RETKEY) && event->val==KM_PRESS)
                                click= 1;
+                       else if (event->type == MINUSKEY && event->val==KM_PRESS) {
+                               button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
+                               data->value = -data->value;
+                               button_activate_state(C, but, BUTTON_STATE_EXIT);
+                               retval= WM_UI_HANDLER_BREAK;
+                       }
                }
                
        }
@@ -2427,6 +2609,12 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
                        }
                        else if(ELEM(event->type, PADENTER, RETKEY) && event->val==KM_PRESS)
                                click= 1;
+                       else if (event->type == MINUSKEY && event->val==KM_PRESS) {
+                               button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
+                               data->value = -data->value;
+                               button_activate_state(C, but, BUTTON_STATE_EXIT);
+                               retval= WM_UI_HANDLER_BREAK;
+                       }
                }
        }
        else if(data->state == BUTTON_STATE_NUM_EDITING) {
@@ -2557,10 +2745,23 @@ static int ui_do_but_SCROLL(bContext *C, uiBlock *block, uiBut *but, uiHandleBut
        return retval;
 }
 
+
 static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, wmEvent *event)
 {
        
        if(data->state == BUTTON_STATE_HIGHLIGHT) {
+               
+               /* first handle click on icondrag type button */
+               if(event->type==LEFTMOUSE && but->dragpoin && event->val==KM_PRESS) {
+                       if(ui_but_mouse_inside_icon(but, data->region, event)) {
+                               button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG);
+                               data->dragstartx= event->x;
+                               data->dragstarty= event->y;
+                               return WM_UI_HANDLER_BREAK;
+                       }
+               }
+               
+               /* regular open menu */
                if(ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val==KM_PRESS) {
                        button_activate_state(C, but, BUTTON_STATE_MENU_OPEN);
                        return WM_UI_HANDLER_BREAK;
@@ -2593,6 +2794,7 @@ static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, wm
                                        but->hsv[2]= CLAMPIS(but->hsv[2]+0.05f, 0.0f, 1.0f);
                                
                                hsv_to_rgb(but->hsv[0], but->hsv[1], but->hsv[2], data->vec, data->vec+1, data->vec+2);
+                               ui_set_but_vectorf(but, data->vec);
                                
                                button_activate_state(C, but, BUTTON_STATE_EXIT);
                                ui_apply_button(C, but->block, but, data, 1);
@@ -2600,6 +2802,26 @@ static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, wm
                        }
                }
        }
+       else if(data->state == BUTTON_STATE_WAIT_DRAG) {
+               
+               /* this function also ends state */
+               if(ui_but_start_drag(C, but, data, event)) {
+                       return WM_UI_HANDLER_BREAK;
+               }
+               
+               /* outside icon quit, not needed if drag activated */
+               if(0==ui_but_mouse_inside_icon(but, data->region, event)) {
+                       button_activate_state(C, but, BUTTON_STATE_EXIT);
+                       data->cancel= 1;
+                       return WM_UI_HANDLER_BREAK;
+               }
+               
+               if(event->type==LEFTMOUSE && event->val==KM_RELEASE) {
+                       button_activate_state(C, but, BUTTON_STATE_MENU_OPEN);
+                       return WM_UI_HANDLER_BREAK;
+               }
+
+       }
 
        return WM_UI_HANDLER_CONTINUE;
 }
@@ -2701,9 +2923,19 @@ static int ui_do_but_NORMAL(bContext *C, uiBlock *block, uiBut *but, uiHandleBut
 
 static int ui_numedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, int mx, int my)
 {
+       float rgb[3], hsv[3];
        float x, y;
        int changed= 1;
-
+       int color_profile = but->block->color_profile;
+       
+       if (but->rnaprop) {
+               if (RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA)
+                       color_profile = BLI_PR_NONE;
+       }
+       
+       ui_get_but_vectorf(but, rgb);
+       rgb_to_hsv(rgb[0], rgb[1], rgb[2], hsv, hsv+1, hsv+2);
+               
        /* relative position within box */
        x= ((float)mx-but->x1)/(but->x2-but->x1);
        y= ((float)my-but->y1)/(but->y2-but->y1);
@@ -2711,27 +2943,44 @@ static int ui_numedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, int mx,
        CLAMP(y, 0.0, 1.0);
        
        if(but->a1==0) {
-               but->hsv[0]= x; 
-               but->hsv[2]= y; 
+               hsv[2]= x; 
+               hsv[1]= y; 
        }
        else if(but->a1==1) {
-               but->hsv[0]= x;                                 
-               but->hsv[1]= y;                                 
+               hsv[0]= x;                              
+               hsv[2]= y;                              
        }
        else if(but->a1==2) {
-               but->hsv[2]= x; 
-               but->hsv[1]= y; 
+               hsv[0]= x; 
+               hsv[1]= y; 
        }
        else if(but->a1==3) {
-               but->hsv[0]= x; 
+               hsv[0]= x; 
        }
-       else
-               but->hsv[2]= y; 
+       else if(but->a1==4) {
+               hsv[1]= x; 
+       }
+       else if(but->a1==5) {
+               hsv[2]= x; 
+       }
+       else if (but->a1==9){
+               float range;
+               
+               /* vertical 'value' strip */
 
-       ui_set_but_hsv(but);    // converts to rgb
-       
-       // update button values and strings
-       ui_update_block_buts_hsv(but->block, but->hsv);
+               /* exception only for value strip - use the range set in but->min/max */
+               range = but->softmax - but->softmin;
+               hsv[2] = y*range + but->softmin;
+               
+               if (color_profile)
+                       hsv[2] = srgb_to_linearrgb(hsv[2]);
+               
+               if (hsv[2] > but->softmax)
+                       hsv[2] = but->softmax;
+       }
+
+       hsv_to_rgb(hsv[0], hsv[1], hsv[2], rgb, rgb+1, rgb+2);
+       copy_v3_v3(data->vec, rgb);
 
        data->draglastx= mx;
        data->draglasty= my;
@@ -2761,9 +3010,42 @@ static int ui_do_but_HSVCUBE(bContext *C, uiBlock *block, uiBut *but, uiHandleBu
                        
                        return WM_UI_HANDLER_BREAK;
                }
+               else if (event->type == ZEROKEY && event->val == KM_PRESS) {
+                       if (but->a1==9){
+                               float rgb[3], hsv[3], def_hsv[3];
+                               float *def;
+                               int len;
+                               
+                               /* reset only value */
+                               
+                               len= RNA_property_array_length(&but->rnapoin, but->rnaprop);
+                               if (len >= 3) {
+                                       def= MEM_callocN(sizeof(float)*len, "reset_defaults - float");
+                                       
+                                       RNA_property_float_get_default_array(&but->rnapoin, but->rnaprop, def);
+                                       rgb_to_hsv(def[0], def[1], def[2], def_hsv, def_hsv+1, def_hsv+2);
+                                       
+                                       ui_get_but_vectorf(but, rgb);
+                                       rgb_to_hsv(rgb[0], rgb[1], rgb[2], hsv, hsv+1, hsv+2);
+                                       
+                                       hsv_to_rgb(hsv[0], hsv[1], def_hsv[2], rgb, rgb+1, rgb+2);
+                                       ui_set_but_vectorf(but, rgb);
+                                       
+                                       RNA_property_update(C, &but->rnapoin, but->rnaprop);
+                                       
+                                       MEM_freeN(def);
+                               }
+                               return WM_UI_HANDLER_BREAK;
+                       }
+               }
        }
        else if(data->state == BUTTON_STATE_NUM_EDITING) {
-               if(event->type == MOUSEMOVE) {
+               if(event->type == ESCKEY) {
+                       data->cancel= 1;
+                       data->escapecancel= 1;
+                       button_activate_state(C, but, BUTTON_STATE_EXIT);
+               }
+               else if(event->type == MOUSEMOVE) {
                        if(mx!=data->draglastx || my!=data->draglasty) {
                                if(ui_numedit_but_HSVCUBE(but, data, mx, my))
                                        ui_numedit_apply(C, block, but, data);
@@ -2778,20 +3060,44 @@ static int ui_do_but_HSVCUBE(bContext *C, uiBlock *block, uiBut *but, uiHandleBu
        return WM_UI_HANDLER_CONTINUE;
 }
 
-static int ui_numedit_but_HSVCIRCLE(uiBut *but, uiHandleButtonData *data, int mx, int my)
+static int ui_numedit_but_HSVCIRCLE(uiBut *but, uiHandleButtonData *data, int mx, int my, int shift)
 {
        rcti rect;
        int changed= 1;
-
+       float rgb[3], hsv[3];
+       
        rect.xmin= but->x1; rect.xmax= but->x2;
        rect.ymin= but->y1; rect.ymax= but->y2;
        
-       ui_hsvcircle_vals_from_pos(but->hsv, but->hsv+1, &rect, (float)mx, (float)my);
-       
-       ui_set_but_hsv(but);    // converts to rgb
+       ui_get_but_vectorf(but, rgb);
+       rgb_to_hsv(rgb[0], rgb[1], rgb[2], hsv, hsv+1, hsv+2);
        
-       // update button values and strings
-       // XXX ui_update_block_buts_hsv(but->block, but->hsv);
+       /* exception, when using color wheel in 'locked' value state:
+        * allow choosing a hue for black values, by giving a tiny increment */
+       if (but->flag & UI_BUT_COLOR_LOCK) { // lock
+               if (hsv[2] == 0.f) hsv[2] = 0.0001f;
+       }
+
+       if(U.uiflag & USER_CONTINUOUS_MOUSE) {
+               float fac= shift ? 0.05 : 1.0f;
+               /* slow down the mouse, this is fairly picky */
+               mx = (data->dragstartx*(1.0f-fac) + mx*fac);
+               my = (data->dragstarty*(1.0f-fac) + my*fac);
+       }
+
+       ui_hsvcircle_vals_from_pos(hsv, hsv+1, &rect, (float)mx, (float)my);
+
+       if(but->flag & UI_BUT_COLOR_CUBIC)
+               hsv[1]= 1.0f - sqrt3f(1.0f - hsv[1]);
+
+       hsv_to_rgb(hsv[0], hsv[1], hsv[2], rgb, rgb+1, rgb+2);
+
+       if((but->flag & UI_BUT_VEC_SIZE_LOCK) && (rgb[0] || rgb[1] || rgb[2])) {
+               normalize_v3(rgb);
+               mul_v3_fl(rgb, but->a2);
+       }
+
+       ui_set_but_vectorf(but, rgb);
        
        data->draglastx= mx;
        data->draglasty= my;
@@ -2817,15 +3123,46 @@ static int ui_do_but_HSVCIRCLE(bContext *C, uiBlock *block, uiBut *but, uiHandle
                        button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
                        
                        /* also do drag the first time */
-                       if(ui_numedit_but_HSVCIRCLE(but, data, mx, my))
+                       if(ui_numedit_but_HSVCIRCLE(but, data, mx, my, event->shift))
                                ui_numedit_apply(C, block, but, data);
                        
                        return WM_UI_HANDLER_BREAK;
                }
+               else if (event->type == ZEROKEY && event->val == KM_PRESS) {
+                       float rgb[3], hsv[3], def_hsv[3];
+                       float *def;
+                       int len;
+                       
+                       /* reset only saturation */
+                       
+                       len= RNA_property_array_length(&but->rnapoin, but->rnaprop);
+                       if (len >= 3) {
+                               def= MEM_callocN(sizeof(float)*len, "reset_defaults - float");
+                               
+                               RNA_property_float_get_default_array(&but->rnapoin, but->rnaprop, def);
+                               rgb_to_hsv(def[0], def[1], def[2], def_hsv, def_hsv+1, def_hsv+2);
+                               
+                               ui_get_but_vectorf(but, rgb);
+                               rgb_to_hsv(rgb[0], rgb[1], rgb[2], hsv, hsv+1, hsv+2);
+                               
+                               hsv_to_rgb(hsv[0], def_hsv[1], hsv[2], rgb, rgb+1, rgb+2);
+                               ui_set_but_vectorf(but, rgb);
+                               
+                               RNA_property_update(C, &but->rnapoin, but->rnaprop);
+                               
+                               MEM_freeN(def);
+                       }
+                       return WM_UI_HANDLER_BREAK;
+               }
        }
        else if(data->state == BUTTON_STATE_NUM_EDITING) {
+               if(event->type == ESCKEY) {
+                       data->cancel= 1;
+                       data->escapecancel= 1;
+                       button_activate_state(C, but, BUTTON_STATE_EXIT);
+               }
                /* XXX hardcoded keymap check.... */
-               if(event->type == WHEELDOWNMOUSE) {
+               else if(event->type == WHEELDOWNMOUSE) {
                        but->hsv[2]= CLAMPIS(but->hsv[2]-0.05f, 0.0f, 1.0f);
                        ui_set_but_hsv(but);    // converts to rgb
                        ui_numedit_apply(C, block, but, data);
@@ -2837,13 +3174,13 @@ static int ui_do_but_HSVCIRCLE(bContext *C, uiBlock *block, uiBut *but, uiHandle
                }
                else if(event->type == MOUSEMOVE) {
                        if(mx!=data->draglastx || my!=data->draglasty) {
-                               if(ui_numedit_but_HSVCIRCLE(but, data, mx, my))
+                               if(ui_numedit_but_HSVCIRCLE(but, data, mx, my, event->shift))
                                        ui_numedit_apply(C, block, but, data);
                        }
                }
-               else if(event->type==LEFTMOUSE && event->val!=KM_PRESS)
+               else if(event->type==LEFTMOUSE && event->val!=KM_PRESS) {
                        button_activate_state(C, but, BUTTON_STATE_EXIT);
-               
+               }
                return WM_UI_HANDLER_BREAK;
        }
        
@@ -2913,24 +3250,8 @@ static int ui_do_but_COLORBAND(bContext *C, uiBlock *block, uiBut *but, uiHandle
 
                        if(event->ctrl) {
                                /* insert new key on mouse location */
-                               if(coba->tot < MAXCOLORBAND-1) {
-                                       float pos= ((float)(mx - but->x1))/(but->x2-but->x1);
-                                       float col[4];
-                                       
-                                       do_colorband(coba, pos, col);   /* executes it */
-                                       
-                                       coba->tot++;
-                                       coba->cur= coba->tot-1;
-                                       
-                                       coba->data[coba->cur].r= col[0];
-                                       coba->data[coba->cur].g= col[1];
-                                       coba->data[coba->cur].b= col[2];
-                                       coba->data[coba->cur].a= col[3];
-                                       coba->data[coba->cur].pos= pos;
-
-                                       ui_colorband_update(coba);
-                               }
-
+                               float pos= ((float)(mx - but->x1))/(but->x2-but->x1);
+                               colorband_element_add(coba, pos);
                                button_activate_state(C, but, BUTTON_STATE_EXIT);
                        }
                        else {
@@ -2986,6 +3307,16 @@ static int ui_numedit_but_CURVE(uiBut *but, uiHandleButtonData *data, int snap,
        offsx= cumap->curr.xmin;
        offsy= cumap->curr.ymin;
 
+       if(snap) {
+               float d[2];
+
+               d[0]= mx - data->dragstartx;
+               d[1]= my - data->dragstarty;
+
+               if(len_v2(d) < 3.0f)
+                       snap= 0;
+       }
+
        if(data->dragsel != -1) {
                int moved_point= 0;             /* for ctrl grid, can't use orig coords because of sorting */
                
@@ -3122,10 +3453,13 @@ static int ui_do_but_CURVE(bContext *C, uiBlock *block, uiBut *but, uiHandleButt
                        if(sel!= -1) {
                                /* ok, we move a point */
                                /* deselect all if this one is deselect. except if we hold shift */
-                               if(event->shift==0 && (cmp[sel].flag & SELECT)==0)
+                               if(event->shift==0) {
                                        for(a=0; a<cuma->totpoint; a++)
                                                cmp[a].flag &= ~SELECT;
-                               cmp[sel].flag |= SELECT;
+                                       cmp[sel].flag |= SELECT;
+                               }
+                               else
+                                       cmp[sel].flag ^= SELECT;
                        }
                        else {
                                /* move the view */
@@ -3146,7 +3480,7 @@ static int ui_do_but_CURVE(bContext *C, uiBlock *block, uiBut *but, uiHandleButt
        else if(data->state == BUTTON_STATE_NUM_EDITING) {
                if(event->type == MOUSEMOVE) {
                        if(mx!=data->draglastx || my!=data->draglasty) {
-                               if(ui_numedit_but_CURVE(but, data, event->shift, mx, my))
+                               if(ui_numedit_but_CURVE(but, data, event->ctrl, mx, my))
                                        ui_numedit_apply(C, block, but, data);
                        }
                }
@@ -3177,33 +3511,271 @@ static int ui_do_but_CURVE(bContext *C, uiBlock *block, uiBut *but, uiHandleButt
        return WM_UI_HANDLER_CONTINUE;
 }
 
-#ifdef INTERNATIONAL
-static int ui_do_but_CHARTAB(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, wmEvent *event)
+static int in_scope_resize_zone(uiBut *but, int x, int y)
 {
-       /* XXX 2.50 bad global and state access */
-#if 0
-       float sx, sy, ex, ey;
-       float width, height;
-       float butw, buth;
-       int mx, my, x, y, cs, che;
-
-       mx= event->x;
-       my= event->y;
-       ui_window_to_block(data->region, block, &mx, &my);
-
-       if(data->state == BUTTON_STATE_HIGHLIGHT) {
-               if(ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val==KM_PRESS) {
-                       /* Calculate the size of the button */
-                       width = abs(but->x2 - but->x1);
-                       height = abs(but->y2 - but->y1);
-
-                       butw = floor(width / 12);
-                       buth = floor(height / 6);
+       // bottom corner return (x > but->x2 - SCOPE_RESIZE_PAD) && (y < but->y1 + SCOPE_RESIZE_PAD);
+       return (y < but->y1 + SCOPE_RESIZE_PAD);
+}
 
-                       /* Initialize variables */
-                       sx = but->x1;
-                       ex = but->x1 + butw;
-                       sy = but->y1 + height - buth;
+static int ui_numedit_but_HISTOGRAM(uiBut *but, uiHandleButtonData *data, int mx, int my)
+{
+       Histogram *hist = (Histogram *)but->poin;
+       rcti rect;
+       int changed= 1;
+       float dx, dy, yfac=1.f;
+       
+       rect.xmin= but->x1; rect.xmax= but->x2;
+       rect.ymin= but->y1; rect.ymax= but->y2;
+       
+       dx = mx - data->draglastx;
+       dy = my - data->draglasty;
+       
+       
+       if (in_scope_resize_zone(but, data->dragstartx, data->dragstarty)) {
+                /* resize histogram widget itself */
+               hist->height = (but->y2 - but->y1) + (data->dragstarty - my);
+       } else {
+               /* scale histogram values */
+               yfac = MIN2(powf(hist->ymax, 2.f), 1.f) * 0.5;
+               hist->ymax += dy * yfac;
+       
+               CLAMP(hist->ymax, 1.f, 100.f);
+       }
+       
+       data->draglastx= mx;
+       data->draglasty= my;
+       
+       return changed;
+}
+
+static int ui_do_but_HISTOGRAM(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, wmEvent *event)
+{
+       int mx, my;
+       
+       mx= event->x;
+       my= event->y;
+       ui_window_to_block(data->region, block, &mx, &my);
+       
+       if(data->state == BUTTON_STATE_HIGHLIGHT) {
+               if(event->type==LEFTMOUSE && event->val==KM_PRESS) {
+                       data->dragstartx= mx;
+                       data->dragstarty= my;
+                       data->draglastx= mx;
+                       data->draglasty= my;
+                       button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
+                       
+                       /* also do drag the first time */
+                       if(ui_numedit_but_HISTOGRAM(but, data, mx, my))
+                               ui_numedit_apply(C, block, but, data);
+                       
+                       return WM_UI_HANDLER_BREAK;
+               }
+               else if (event->type == ZEROKEY && event->val == KM_PRESS) {
+                       Histogram *hist = (Histogram *)but->poin;
+                       hist->ymax = 1.f;
+                       
+                       button_activate_state(C, but, BUTTON_STATE_EXIT);
+                       return WM_UI_HANDLER_BREAK;
+               }
+       }
+       else if(data->state == BUTTON_STATE_NUM_EDITING) {
+               if(event->type == ESCKEY) {
+                       data->cancel= 1;
+                       data->escapecancel= 1;
+                       button_activate_state(C, but, BUTTON_STATE_EXIT);
+               }
+               else if(event->type == MOUSEMOVE) {
+                       if(mx!=data->draglastx || my!=data->draglasty) {
+                               if(ui_numedit_but_HISTOGRAM(but, data, mx, my))
+                                       ui_numedit_apply(C, block, but, data);
+                       }
+               }
+               else if(event->type==LEFTMOUSE && event->val!=KM_PRESS) {
+                       button_activate_state(C, but, BUTTON_STATE_EXIT);
+               }
+               return WM_UI_HANDLER_BREAK;
+       }
+       
+       return WM_UI_HANDLER_CONTINUE;
+}
+
+static int ui_numedit_but_WAVEFORM(uiBut *but, uiHandleButtonData *data, int mx, int my)
+{
+       Scopes *scopes = (Scopes *)but->poin;
+       rcti rect;
+       int changed= 1;
+       float dx, dy, yfac=1.f;
+
+       rect.xmin= but->x1; rect.xmax= but->x2;
+       rect.ymin= but->y1; rect.ymax= but->y2;
+
+       dx = mx - data->draglastx;
+       dy = my - data->draglasty;
+
+
+       if (in_scope_resize_zone(but, data->dragstartx, data->dragstarty)) {
+                /* resize waveform widget itself */
+               scopes->wavefrm_height = (but->y2 - but->y1) + (data->dragstarty - my);
+       } else {
+               /* scale waveform values */
+               yfac = scopes->wavefrm_yfac;
+               scopes->wavefrm_yfac += dy/200.0f;
+
+               CLAMP(scopes->wavefrm_yfac, 0.5f, 2.f);
+       }
+
+       data->draglastx= mx;
+       data->draglasty= my;
+
+       return changed;
+}
+
+static int ui_do_but_WAVEFORM(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, wmEvent *event)
+{
+       int mx, my;
+
+       mx= event->x;
+       my= event->y;
+       ui_window_to_block(data->region, block, &mx, &my);
+
+       if(data->state == BUTTON_STATE_HIGHLIGHT) {
+               if(event->type==LEFTMOUSE && event->val==KM_PRESS) {
+                       data->dragstartx= mx;
+                       data->dragstarty= my;
+                       data->draglastx= mx;
+                       data->draglasty= my;
+                       button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
+
+                       /* also do drag the first time */
+                       if(ui_numedit_but_WAVEFORM(but, data, mx, my))
+                               ui_numedit_apply(C, block, but, data);
+
+                       return WM_UI_HANDLER_BREAK;
+               }
+               else if (event->type == ZEROKEY && event->val == KM_PRESS) {
+                       Scopes *scopes = (Scopes *)but->poin;
+                       scopes->wavefrm_yfac = 1.f;
+
+                       button_activate_state(C, but, BUTTON_STATE_EXIT);
+                       return WM_UI_HANDLER_BREAK;
+               }
+       }
+       else if(data->state == BUTTON_STATE_NUM_EDITING) {
+               if(event->type == ESCKEY) {
+                       data->cancel= 1;
+                       data->escapecancel= 1;
+                       button_activate_state(C, but, BUTTON_STATE_EXIT);
+               }
+               else if(event->type == MOUSEMOVE) {
+                       if(mx!=data->draglastx || my!=data->draglasty) {
+                               if(ui_numedit_but_WAVEFORM(but, data, mx, my))
+                                       ui_numedit_apply(C, block, but, data);
+                       }
+               }
+               else if(event->type==LEFTMOUSE && event->val!=KM_PRESS) {
+                       button_activate_state(C, but, BUTTON_STATE_EXIT);
+               }
+               return WM_UI_HANDLER_BREAK;
+       }
+
+       return WM_UI_HANDLER_CONTINUE;
+}
+
+static int ui_numedit_but_VECTORSCOPE(uiBut *but, uiHandleButtonData *data, int mx, int my)
+{
+       Scopes *scopes = (Scopes *)but->poin;
+       rcti rect;
+       int changed= 1;
+       float dx, dy;
+
+       rect.xmin= but->x1; rect.xmax= but->x2;
+       rect.ymin= but->y1; rect.ymax= but->y2;
+
+       dx = mx - data->draglastx;
+       dy = my - data->draglasty;
+
+       if (in_scope_resize_zone(but, data->dragstartx, data->dragstarty)) {
+                /* resize vectorscope widget itself */
+               scopes->vecscope_height = (but->y2 - but->y1) + (data->dragstarty - my);
+       }
+
+       data->draglastx= mx;
+       data->draglasty= my;
+
+       return changed;
+}
+
+static int ui_do_but_VECTORSCOPE(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, wmEvent *event)
+{
+       int mx, my;
+
+       mx= event->x;
+       my= event->y;
+       ui_window_to_block(data->region, block, &mx, &my);
+
+       if(data->state == BUTTON_STATE_HIGHLIGHT) {
+               if(event->type==LEFTMOUSE && event->val==KM_PRESS) {
+                       data->dragstartx= mx;
+                       data->dragstarty= my;
+                       data->draglastx= mx;
+                       data->draglasty= my;
+                       button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
+
+                       /* also do drag the first time */
+                       if(ui_numedit_but_VECTORSCOPE(but, data, mx, my))
+                               ui_numedit_apply(C, block, but, data);
+
+                       return WM_UI_HANDLER_BREAK;
+               }
+       }
+       else if(data->state == BUTTON_STATE_NUM_EDITING) {
+               if(event->type == ESCKEY) {
+                       data->cancel= 1;
+                       data->escapecancel= 1;
+                       button_activate_state(C, but, BUTTON_STATE_EXIT);
+               }
+               else if(event->type == MOUSEMOVE) {
+                       if(mx!=data->draglastx || my!=data->draglasty) {
+                               if(ui_numedit_but_VECTORSCOPE(but, data, mx, my))
+                                       ui_numedit_apply(C, block, but, data);
+                       }
+               }
+               else if(event->type==LEFTMOUSE && event->val!=KM_PRESS) {
+                       button_activate_state(C, but, BUTTON_STATE_EXIT);
+               }
+               return WM_UI_HANDLER_BREAK;
+       }
+
+       return WM_UI_HANDLER_CONTINUE;
+}
+
+#ifdef INTERNATIONAL
+static int ui_do_but_CHARTAB(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, wmEvent *event)
+{
+       /* XXX 2.50 bad global and state access */
+#if 0
+       float sx, sy, ex, ey;
+       float width, height;
+       float butw, buth;
+       int mx, my, x, y, cs, che;
+
+       mx= event->x;
+       my= event->y;
+       ui_window_to_block(data->region, block, &mx, &my);
+
+       if(data->state == BUTTON_STATE_HIGHLIGHT) {
+               if(ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val==KM_PRESS) {
+                       /* Calculate the size of the button */
+                       width = abs(but->x2 - but->x1);
+                       height = abs(but->y2 - but->y1);
+
+                       butw = floor(width / 12);
+                       buth = floor(height / 6);
+
+                       /* Initialize variables */
+                       sx = but->x1;
+                       ex = but->x1 + butw;
+                       sy = but->y1 + height - buth;
                        ey = but->y1 + height;
 
                        cs = G.charstart;
@@ -3316,69 +3888,135 @@ static int ui_do_but_LINK(bContext *C, uiBut *but, uiHandleButtonData *data, wmE
        return WM_UI_HANDLER_CONTINUE;
 }
 
-/* callback for hotkey change button/menu */
-static void do_menu_change_hotkey(bContext *C, void *but_v, void *key_v)
+static void but_shortcut_name_func(bContext *C, void *arg1, int event)
 {
-       uiBut *but= but_v;
-       IDProperty *prop= (but->opptr)? but->opptr->data: NULL;
-       short *key= key_v;
-       char buf[512], *butstr, *cpoin;
+       uiBut *but = (uiBut *)arg1;
        
-       /* signal for escape */
-       if(key[0]==0) return;
+       char buf[512], *butstr, *cpoin;
        
-       WM_key_event_operator_change(C, but->optype->idname, but->opcontext, prop, key[0], key[1]);
-
-       /* complex code to change name of button */
-       if(WM_key_event_operator_string(C, but->optype->idname, but->opcontext, prop, buf, sizeof(buf))) {
-               
-               butstr= MEM_mallocN(strlen(but->str)+strlen(buf)+2, "menu_block_set_keymaps");
-               
-               /* XXX but->str changed... should not, remove the hotkey from it */
-               cpoin= strchr(but->str, '|');
-               if(cpoin) *cpoin= 0;            
-
-               strcpy(butstr, but->str);
-               strcat(butstr, "|");
-               strcat(butstr, buf);
-               
-               but->str= but->strdata;
-               BLI_strncpy(but->str, butstr, sizeof(but->strdata));
-               MEM_freeN(butstr);
+       if (but->optype) {
+               IDProperty *prop= (but->opptr)? but->opptr->data: NULL;
                
-               ui_check_but(but);
+               /* complex code to change name of button */
+               if(WM_key_event_operator_string(C, but->optype->idname, but->opcontext, prop, buf, sizeof(buf))) {
+                       
+                       butstr= MEM_mallocN(strlen(but->str)+strlen(buf)+2, "menu_block_set_keymaps");
+                       
+                       // XXX but->str changed... should not, remove the hotkey from it
+                       cpoin= strchr(but->str, '|');
+                       if(cpoin) *cpoin= 0;            
+                       
+                       strcpy(butstr, but->str);
+                       strcat(butstr, "|");
+                       strcat(butstr, buf);
+                       
+                       but->str= but->strdata;
+                       BLI_strncpy(but->str, butstr, sizeof(but->strdata));
+                       MEM_freeN(butstr);
+                       
+                       ui_check_but(but);
+               } else {
+                       /* shortcut was removed */
+                       cpoin= strchr(but->str, '|');
+                       if(cpoin) *cpoin= 0;
+               }
        }
-                               
 }
 
+static uiBlock *menu_change_shortcut(bContext *C, ARegion *ar, void *arg)
+{
+       uiBlock *block;
+       uiBut *but = (uiBut *)arg;
+       wmKeyMap *km;
+       wmKeyMapItem *kmi;
+       PointerRNA ptr;
+       uiLayout *layout;
+       uiStyle *style= U.uistyles.first;
+       IDProperty *prop= (but->opptr)? but->opptr->data: NULL;
+       int kmi_id = WM_key_event_operator_id(C, but->optype->idname, but->opcontext, prop, 1, &km);
+
+       kmi = WM_keymap_item_find_id(km, kmi_id);
+       
+       RNA_pointer_create(NULL, &RNA_KeyMapItem, kmi, &ptr);
+       
+       block= uiBeginBlock(C, ar, "_popup", UI_EMBOSS);
+       uiBlockSetHandleFunc(block, but_shortcut_name_func, but);
+       uiBlockSetFlag(block, UI_BLOCK_RET_1|UI_BLOCK_MOVEMOUSE_QUIT);
+       uiBlockSetDirection(block, UI_CENTER);
+       
+       layout= uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, 200, 20, style);
+       
+       uiItemR(layout, &ptr, "type", UI_ITEM_R_FULL_EVENT|UI_ITEM_R_IMMEDIATE, "", 0);
+       
+       uiPopupBoundsBlock(block, 6, 100, 10);
+       uiEndBlock(C, block);
+       
+       return block;
+}
 
-static uiBlock *menu_change_hotkey(bContext *C, ARegion *ar, void *arg_but)
+static uiBlock *menu_add_shortcut(bContext *C, ARegion *ar, void *arg)
 {
        uiBlock *block;
-       uiBut *but= arg_but;
-       wmOperatorType *ot= WM_operatortype_find(but->optype->idname, 1);
-       static short dummy[2];
-       char buf[OP_MAX_TYPENAME+10];
+       uiBut *but = (uiBut *)arg;
+       wmKeyMap *km;
+       wmKeyMapItem *kmi;
+       PointerRNA ptr;
+       uiLayout *layout;
+       uiStyle *style= U.uistyles.first;
+       IDProperty *prop= (but->opptr)? but->opptr->data: NULL;
        
-       dummy[0]= 0;
-       dummy[1]= 0;
+       km = WM_keymap_guess_opname(C, but->optype->idname);            
+       kmi = WM_keymap_add_item(km, but->optype->idname, AKEY, KM_PRESS, 0, 0);
+       MEM_freeN(kmi->properties);
+       if (prop)
+               kmi->properties= IDP_CopyProperty(prop);
        
-       block= uiBeginBlock(C, ar, "_popup", UI_EMBOSSP);
-       uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_MOVEMOUSE_QUIT|UI_BLOCK_RET_1|UI_BLOCK_MOVEMOUSE_QUIT);
+       RNA_pointer_create(NULL, &RNA_KeyMapItem, kmi, &ptr);
        
-       BLI_strncpy(buf, ot->name, OP_MAX_TYPENAME);
-       strcat(buf, " |");
+       block= uiBeginBlock(C, ar, "_popup", UI_EMBOSS);
+       uiBlockSetHandleFunc(block, but_shortcut_name_func, but);
+       uiBlockSetFlag(block, UI_BLOCK_RET_1);
+       uiBlockSetDirection(block, UI_CENTER);
        
-       but= uiDefHotKeyevtButS(block, 0, buf, 0, 0, 200, 20, dummy, dummy+1, "");
-       uiButSetFlag(but, UI_BUT_IMMEDIATE);
-       uiButSetFunc(but, do_menu_change_hotkey, arg_but, dummy);
+       layout= uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, 200, 20, style);
 
-       uiPopupBoundsBlock(block, 6.0f, 50, -10);
+       uiItemR(layout, &ptr, "type", UI_ITEM_R_FULL_EVENT|UI_ITEM_R_IMMEDIATE, "", 0);
+       
+       uiPopupBoundsBlock(block, 6, 100, 10);
        uiEndBlock(C, block);
        
        return block;
 }
 
+static void popup_change_shortcut_func(bContext *C, void *arg1, void *arg2)
+{
+       uiBut *but = (uiBut *)arg1;
+       button_timers_tooltip_remove(C, but);
+       uiPupBlock(C, menu_change_shortcut, but);
+}
+
+static void remove_shortcut_func(bContext *C, void *arg1, void *arg2)
+{
+       uiBut *but = (uiBut *)arg1;
+       wmKeyMap *km;
+       wmKeyMapItem *kmi;
+       IDProperty *prop= (but->opptr)? but->opptr->data: NULL;
+       int kmi_id = WM_key_event_operator_id(C, but->optype->idname, but->opcontext, prop, 1, &km);
+       
+       kmi = WM_keymap_item_find_id(km, kmi_id);
+       WM_keymap_remove_item(km, kmi);
+       
+       but_shortcut_name_func(C, but, 0);
+}
+
+static void popup_add_shortcut_func(bContext *C, void *arg1, void *arg2)
+{
+       uiBut *but = (uiBut *)arg1;
+       button_timers_tooltip_remove(C, but);
+       uiPupBlock(C, menu_add_shortcut, but);
+}
+
+
 static int ui_but_menu(bContext *C, uiBut *but)
 {
        uiPopupMenu *pup;
@@ -3388,7 +4026,8 @@ static int ui_but_menu(bContext *C, uiBut *but)
 
        if((but->rnapoin.data && but->rnaprop)==0 && but->optype==NULL)
                return 0;
-
+       
+       button_timers_tooltip_remove(C, but);
 
        if(but->rnaprop)
                name= (char*)RNA_property_ui_name(but->rnaprop);
@@ -3481,14 +4120,54 @@ static int ui_but_menu(bContext *C, uiBut *but)
                //Copy Property Value
                //Paste Property Value
                
-               //uiItemO(layout, "Reset to Default Value", 0, "WM_OT_property_value_reset_button");
+               if(length) {
+                       uiItemBooleanO(layout, "Reset All to Default Values", 0, "UI_OT_reset_default_button", "all", 1);
+                       uiItemBooleanO(layout, "Reset Single to Default Value", 0, "UI_OT_reset_default_button", "all", 0);
+               }
+               else
+                       uiItemO(layout, "Reset to Default Value", 0, "UI_OT_reset_default_button");
                
-               uiItemO(layout, "Copy Data Path", 0, "ANIM_OT_copy_clipboard_button");
+               uiItemO(layout, "Copy Data Path", 0, "UI_OT_copy_data_path_button");
+               uiItemO(layout, "Copy To Selected", 0, "UI_OT_copy_to_selected_button");
 
                uiItemS(layout);
        }
 
+       /* Operator buttons */
+       if(but->optype) {
+               uiBlock *block = uiLayoutGetBlock(layout);
+               uiBut *but2;
+               IDProperty *prop= (but->opptr)? but->opptr->data: NULL;
+               int w = uiLayoutGetWidth(layout);
+               wmKeyMap *km;
+               wmKeyMapItem *kmi= NULL;
+               int kmi_id= WM_key_event_operator_id(C, but->optype->idname, but->opcontext, prop, 1, &km);
+
+               if (kmi_id)
+                       kmi= WM_keymap_item_find_id(km, kmi_id);
+
+               /* keyboard shortcuts */
+               if ((kmi) && ISKEYBOARD(kmi->type)) {
+
+                       // would rather use a block but, but gets weirdly positioned...
+                       //uiDefBlockBut(block, menu_change_shortcut, but, "Change Shortcut", 0, 0, uiLayoutGetWidth(layout), UI_UNIT_Y, "");
+                       
+                       but2 = uiDefIconTextBut(block, BUT, 0, 0, "Change Shortcut", 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
+                       uiButSetFunc(but2, popup_change_shortcut_func, but, NULL);
 
+                       but2 = uiDefIconTextBut(block, BUT, 0, 0, "Remove Shortcut", 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
+                       uiButSetFunc(but2, remove_shortcut_func, but, NULL);
+               }
+               /* only show 'add' if there's a suitable key map for it to go in */
+               else if (WM_keymap_guess_opname(C, but->optype->idname)) {
+                       but2 = uiDefIconTextBut(block, BUT, 0, 0, "Add Shortcut", 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
+                       uiButSetFunc(but2, popup_add_shortcut_func, but, NULL);
+               }
+               
+               uiItemS(layout);
+       }
+
+       
        {       /* Docs */
                char buf[512];
                PointerRNA ptr_props;
@@ -3498,28 +4177,28 @@ static int ui_but_menu(bContext *C, uiBut *but)
 
                        WM_operator_properties_create(&ptr_props, "WM_OT_doc_view");
                        RNA_string_set(&ptr_props, "doc_id", buf);
-                       uiItemFullO(layout, "View Docs", 0, "WM_OT_doc_view", ptr_props.data, WM_OP_EXEC_DEFAULT, 0);
+                       uiItemFullO(layout, "WM_OT_doc_view", "View Docs", 0, ptr_props.data, WM_OP_EXEC_DEFAULT, 0);
 
 
                        WM_operator_properties_create(&ptr_props, "WM_OT_doc_edit");
                        RNA_string_set(&ptr_props, "doc_id", buf);
                        RNA_string_set(&ptr_props, "doc_new", RNA_property_description(but->rnaprop));
 
-                       uiItemFullO(layout, "Submit Description", 0, "WM_OT_doc_edit", ptr_props.data, WM_OP_INVOKE_DEFAULT, 0);
+                       uiItemFullO(layout, "WM_OT_doc_edit", "Submit Description", 0, ptr_props.data, WM_OP_INVOKE_DEFAULT, 0);
                }
                else if (but->optype) {
                        WM_operator_py_idname(buf, but->optype->idname);
 
                        WM_operator_properties_create(&ptr_props, "WM_OT_doc_view");
                        RNA_string_set(&ptr_props, "doc_id", buf);
-                       uiItemFullO(layout, "View Docs", 0, "WM_OT_doc_view", ptr_props.data, WM_OP_EXEC_DEFAULT, 0);
+                       uiItemFullO(layout, "WM_OT_doc_view", "View Docs", 0, ptr_props.data, WM_OP_EXEC_DEFAULT, 0);
 
 
                        WM_operator_properties_create(&ptr_props, "WM_OT_doc_edit");
                        RNA_string_set(&ptr_props, "doc_id", buf);
                        RNA_string_set(&ptr_props, "doc_new", but->optype->description);
 
-                       uiItemFullO(layout, "Submit Description", 0, "WM_OT_doc_edit", ptr_props.data, WM_OP_INVOKE_DEFAULT, 0);
+                       uiItemFullO(layout, "WM_OT_doc_edit", "Submit Description", 0, ptr_props.data, WM_OP_INVOKE_DEFAULT, 0);
                }
        }
 
@@ -3545,8 +4224,12 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, wmEvent *event)
                        ui_but_copy_paste(C, but, data, (event->type == CKEY)? 'c': 'v');
                        return WM_UI_HANDLER_BREAK;
                }
+               /* handle drop */
+               else if(event->type == EVT_DROP) {
+                       ui_but_drop     (C, event, but, data);
+               }
                /* handle keyframing */
-               else if(event->type == IKEY && event->val == KM_PRESS) {
+               else if(event->type == IKEY && !ELEM3(1, event->ctrl, event->oskey, event->shift) && event->val == KM_PRESS) {
                        if(event->alt)
                                ui_but_anim_delete_keyframe(C);
                        else
@@ -3557,7 +4240,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, wmEvent *event)
                        return WM_UI_HANDLER_BREAK;
                }
                /* handle drivers */
-               else if(event->type == DKEY && event->val == KM_PRESS) {
+               else if(event->type == DKEY && !ELEM3(1, event->ctrl, event->oskey, event->shift) && event->val == KM_PRESS) {
                        if(event->alt)
                                ui_but_anim_remove_driver(C);
                        else
@@ -3568,31 +4251,25 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, wmEvent *event)
                        return WM_UI_HANDLER_BREAK;
                }
                /* handle keyingsets */
-               else if(event->type == KKEY && event->val == KM_PRESS) {
+               else if(event->type == KKEY && !ELEM3(1, event->ctrl, event->oskey, event->shift) && event->val == KM_PRESS) {
                        if(event->alt)
                                ui_but_anim_remove_keyingset(C);
                        else
-                               ui_but_anim_remove_keyingset(C);
+                               ui_but_anim_add_keyingset(C);
                                
                        ED_region_tag_redraw(CTX_wm_region(C));
                        
                        return WM_UI_HANDLER_BREAK;
                }
+               /* reset to default */
+               else if(event->type == ZEROKEY && event->val == KM_PRESS) {
+                       if (!(ELEM3(but->type, HSVCIRCLE, HSVCUBE, HISTOGRAM)))
+                               ui_set_but_default(C, but);
+               }
                /* handle menu */
                else if(event->type == RIGHTMOUSE && event->val == KM_PRESS) {
                        /* RMB has two options now */
-
-                       if((but->block->flag & UI_BLOCK_LOOP) && but->optype) {
-                               IDProperty *prop= (but->opptr)? but->opptr->data: NULL;
-                               char buf[512];
-                               
-                               if(WM_key_event_operator_string(C, but->optype->idname, but->opcontext, prop, buf, sizeof(buf))) {
-                                       
-                                       uiPupBlock(C, menu_change_hotkey, but);
-
-                               }
-                       }
-                       else if (ui_but_menu(C, but)) {
+                       if (ui_but_menu(C, but)) {
                                return WM_UI_HANDLER_BREAK;
                        }
                }
@@ -3656,8 +4333,18 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, wmEvent *event)
        case ROW:
        case LISTROW:
        case BUT_IMAGE:
+       case PROGRESSBAR:
                retval= ui_do_but_EXIT(C, but, data, event);
                break;
+       case HISTOGRAM:
+               retval= ui_do_but_HISTOGRAM(C, block, but, data, event);
+               break;
+       case WAVEFORM:
+               retval= ui_do_but_WAVEFORM(C, block, but, data, event);
+               break;
+       case VECTORSCOPE:
+               retval= ui_do_but_VECTORSCOPE(C, block, but, data, event);
+               break;
        case TEX:
        case IDPOIN:
        case SEARCH_MENU:
@@ -3674,7 +4361,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, wmEvent *event)
                retval= ui_do_but_BUT(C, but, data, event);
                break;
        case COL:
-               if(but->a1 == -1)  // signal to prevent calling up color picker
+               if(but->a1 == 9)  // signal to prevent calling up color picker
                        retval= ui_do_but_EXIT(C, but, data, event);
                else
                        retval= ui_do_but_BLOCK(C, but, data, event);
@@ -3734,6 +4421,21 @@ int ui_button_is_active(ARegion *ar)
        return (ui_but_find_activated(ar) != NULL);
 }
 
+/* returns TRUE if highlighted button allows drop of names */
+/* called in region context */
+int UI_but_active_drop_name(bContext *C)
+{
+       ARegion *ar= CTX_wm_region(C);
+       uiBut *but= ui_but_find_activated(ar);
+
+       if(but) {
+               if(ELEM3(but->type, TEX, IDPOIN, SEARCH_MENU))
+                       return 1;
+       }
+       
+       return 0;
+}
+
 static void ui_blocks_set_tooltips(ARegion *ar, int enable)
 {
        uiBlock *block;
@@ -3751,7 +4453,6 @@ static int ui_mouse_inside_region(ARegion *ar, int x, int y)
 {
        uiBlock *block;
        
-
        /* check if the mouse is in the region */
        if(!BLI_in_rcti(&ar->winrct, x, y)) {
                for(block=ar->uiblocks.first; block; block=block->next)
@@ -3781,13 +4482,13 @@ static int ui_mouse_inside_region(ARegion *ar, int x, int y)
                mask_rct.ymin= v2d->mask.ymin;
                mask_rct.ymax= v2d->mask.ymax;
                
-               if (v2d->scroll & V2D_SCROLL_VERTICAL_HIDE) {
+               if (v2d->scroll & (V2D_SCROLL_VERTICAL_HIDE|V2D_SCROLL_VERTICAL_FULLR)) {
                        if (v2d->scroll & V2D_SCROLL_LEFT)
                                mask_rct.xmin= v2d->vert.xmin;
                        else if (v2d->scroll & V2D_SCROLL_RIGHT)
                                mask_rct.xmax= v2d->vert.xmax;
                }
-               if (v2d->scroll & V2D_SCROLL_HORIZONTAL_HIDE) {
+               if (v2d->scroll & (V2D_SCROLL_HORIZONTAL_HIDE|V2D_SCROLL_HORIZONTAL_FULLR)) {
                        if (v2d->scroll & (V2D_SCROLL_BOTTOM|V2D_SCROLL_BOTTOM_O))
                                mask_rct.ymin= v2d->hor.ymin;
                        else if (v2d->scroll & V2D_SCROLL_TOP)
@@ -3815,12 +4516,14 @@ static int ui_mouse_inside_button(ARegion *ar, uiBut *but, int x, int y)
        return 1;
 }
 
-static uiBut *ui_but_find_mouse_over(ARegion *ar, int x, int y)
+static uiBut *ui_but_find_mouse_over(wmWindow *win, ARegion *ar, int x, int y)
 {
        uiBlock *block;
        uiBut *but, *butover= NULL;
        int mx, my;
 
+//     if(!win->active)
+//             return NULL;
        if(!ui_mouse_inside_region(ar, x, y))
                return NULL;
 
@@ -3830,7 +4533,10 @@ static uiBut *ui_but_find_mouse_over(ARegion *ar, int x, int y)
                ui_window_to_block(ar, block, &mx, &my);
 
                for(but=block->buttons.first; but; but= but->next) {
-                       if(ELEM4(but->type, LABEL, ROUNDBOX, SEPR, LISTBOX))
+                       /* note, LABEL is included for hilights, this allows drags */
+                       if(but->type==LABEL && but->dragpoin==NULL)
+                               continue;
+                       if(ELEM3(but->type, ROUNDBOX, SEPR, LISTBOX))
                                continue;
                        if(but->flag & UI_HIDDEN)
                                continue;
@@ -3842,12 +4548,14 @@ static uiBut *ui_but_find_mouse_over(ARegion *ar, int x, int y)
        return butover;
 }
 
-static uiBut *ui_list_find_mouse_over(ARegion *ar, int x, int y)
+static uiBut *ui_list_find_mouse_over(wmWindow *win, ARegion *ar, int x, int y)
 {
        uiBlock *block;
        uiBut *but;
        int mx, my;
 
+//     if(!win->active)
+//             return NULL;
        if(!ui_mouse_inside_region(ar, x, y))
                return NULL;
 
@@ -3894,8 +4602,9 @@ static void button_timers_tooltip_remove(bContext *C, uiBut *but)
        }
 }
 
-static void button_tooltip_timer_reset(uiBut *but)
+static void button_tooltip_timer_reset(bContext *C, uiBut *but)
 {
+       wmWindowManager *wm= CTX_wm_manager(C);
        uiHandleButtonData *data;
 
        data= but->active;
@@ -3907,7 +4616,8 @@ static void button_tooltip_timer_reset(uiBut *but)
 
        if(U.flag & USER_TOOLTIPS)
                if(!but->block->tooltipdisabled)
-                       data->tooltiptimer= WM_event_add_timer(data->wm, data->window, TIMER, BUTTON_TOOLTIP_DELAY);
+                       if(!wm->drags.first)
+                               data->tooltiptimer= WM_event_add_timer(data->wm, data->window, TIMER, BUTTON_TOOLTIP_DELAY);
 }
 
 static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState state)
@@ -3922,7 +4632,7 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
        if(state == BUTTON_STATE_HIGHLIGHT) {
                but->flag &= ~UI_SELECT;
 
-               button_tooltip_timer_reset(but);
+               button_tooltip_timer_reset(C, but);
 
                /* automatic open pulldown block timer */
                if(ELEM3(but->type, BLOCK, PULLDOWN, ICONTEXTROW)) {
@@ -3930,7 +4640,7 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
                                int time;
 
                                if(but->block->auto_open==2) time= 1;    // test for toolbox
-                               else if(but->block->flag & UI_BLOCK_LOOP || but->block->auto_open) time= 5*U.menuthreshold2;
+                               else if((but->block->flag & UI_BLOCK_LOOP && but->type != BLOCK) || but->block->auto_open) time= 5*U.menuthreshold2;
                                else if(U.uiflag & USER_MENUOPENAUTO) time= 5*U.menuthreshold1;
                                else time= -1;
 
@@ -3943,12 +4653,14 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
                but->flag |= UI_SELECT;
                button_timers_tooltip_remove(C, but);
        }
-
+       
        /* text editing */
        if(state == BUTTON_STATE_TEXT_EDITING && data->state != BUTTON_STATE_TEXT_SELECTING)
                ui_textedit_begin(C, but, data);
        else if(data->state == BUTTON_STATE_TEXT_EDITING && state != BUTTON_STATE_TEXT_SELECTING)
                ui_textedit_end(C, but, data);
+       else if(data->state == BUTTON_STATE_TEXT_SELECTING && state != BUTTON_STATE_TEXT_EDITING)
+               ui_textedit_end(C, but, data);
        
        /* number editing */
        if(state == BUTTON_STATE_NUM_EDITING) {
@@ -3987,10 +4699,19 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
                                WM_event_remove_ui_handler(&data->window->modalhandlers, ui_handler_region_menu, NULL, data);
                }
        }
+       
+       /* wait for mousemove to enable drag */
+       if(state == BUTTON_STATE_WAIT_DRAG) {
+               but->flag &= ~UI_SELECT;
+       }
 
        data->state= state;
 
-       ui_check_but(but);
+       if(state != BUTTON_STATE_EXIT) {
+               /* When objects for eg. are removed, running ui_check_but()
+                * can access the removed data - so disable update on exit */
+               ui_check_but(but);
+       }
 
        /* redraw */
        ED_region_tag_redraw(data->region);
@@ -4154,10 +4875,11 @@ static uiBut *uit_but_find_open_event(ARegion *ar, wmEvent *event)
 
 static int ui_handle_button_over(bContext *C, wmEvent *event, ARegion *ar)
 {
+       wmWindow *win= CTX_wm_window(C);
        uiBut *but;
 
        if(event->type == MOUSEMOVE) {
-               but= ui_but_find_mouse_over(ar, event->x, event->y);
+               but= ui_but_find_mouse_over(win, ar, event->x, event->y);
                if(but)
                        button_activate_init(C, ar, but, BUTTON_ACTIVATE_OVER);
        }
@@ -4223,21 +4945,26 @@ static int ui_handle_button_event(bContext *C, wmEvent *event, uiBut *but)
        
        if(data->state == BUTTON_STATE_HIGHLIGHT) {
                switch(event->type) {
-                       
+                       case WINDEACTIVATE:
+                       case EVT_BUT_CANCEL:
+                               data->cancel= 1;
+                               button_activate_state(C, but, BUTTON_STATE_EXIT);
+                               retval= WM_UI_HANDLER_CONTINUE;
+                               break;
                        case MOUSEMOVE:
                                /* verify if we are still over the button, if not exit */
                                if(!ui_mouse_inside_button(ar, but, event->x, event->y)) {
                                        data->cancel= 1;
                                        button_activate_state(C, but, BUTTON_STATE_EXIT);
                                }
-                               else if(ui_but_find_mouse_over(ar, event->x, event->y) != but) {
+                               else if(ui_but_find_mouse_over(data->window, ar, event->x, event->y) != but) {
                                        data->cancel= 1;
                                        button_activate_state(C, but, BUTTON_STATE_EXIT);
                                }
                                else if(event->x!=event->prevx || event->y!=event->prevy) {
                                        /* re-enable tooltip on mouse move */
                                        ui_blocks_set_tooltips(ar, 1);
-                                       button_tooltip_timer_reset(but);
+                                       button_tooltip_timer_reset(C, but);
                                }
 
                                break;
@@ -4278,8 +5005,12 @@ static int ui_handle_button_event(bContext *C, wmEvent *event, uiBut *but)
        }
        else if(data->state == BUTTON_STATE_WAIT_RELEASE) {
                switch(event->type) {
+                       case WINDEACTIVATE:
+                               data->cancel= 1;
+                               button_activate_state(C, but, BUTTON_STATE_EXIT);
+                               break;
+
                        case MOUSEMOVE:
-                               
                                if(ELEM(but->type,LINK, INLINK)) {
                                        but->flag |= UI_SELECT;
                                        ui_do_button(C, block, but, event);
@@ -4324,7 +5055,7 @@ static int ui_handle_button_event(bContext *C, wmEvent *event, uiBut *but)
        else if(data->state == BUTTON_STATE_MENU_OPEN) {
                switch(event->type) {
                        case MOUSEMOVE: {
-                               uiBut *bt= ui_but_find_mouse_over(ar, event->x, event->y);
+                               uiBut *bt= ui_but_find_mouse_over(data->window, ar, event->x, event->y);
 
                                if(bt && bt->active != data) {
                                        if(but->type != COL) /* exception */
@@ -4339,8 +5070,8 @@ static int ui_handle_button_event(bContext *C, wmEvent *event, uiBut *but)
                retval= WM_UI_HANDLER_CONTINUE;
        }
        else {
-               ui_do_button(C, block, but, event);
-               retval= WM_UI_HANDLER_BREAK;
+               retval= ui_do_button(C, block, but, event);
+               // retval= WM_UI_HANDLER_BREAK; XXX why ? 
        }
 
        if(data->state == BUTTON_STATE_EXIT) {
@@ -4359,7 +5090,8 @@ static int ui_handle_button_event(bContext *C, wmEvent *event, uiBut *but)
 
 static int ui_handle_list_event(bContext *C, wmEvent *event, ARegion *ar)
 {
-       uiBut *but= ui_list_find_mouse_over(ar, event->x, event->y);
+       wmWindow *win= CTX_wm_window(C);
+       uiBut *but= ui_list_find_mouse_over(win, ar, event->x, event->y);
        int retval= WM_UI_HANDLER_CONTINUE;
        int value, min, max;
 
@@ -4457,7 +5189,8 @@ static void ui_handle_button_return_submenu(bContext *C, wmEvent *event, uiBut *
                        button_activate_state(C, but, BUTTON_STATE_HIGHLIGHT);
                }
                else {
-                       if(event->type != MOUSEMOVE) {
+                       if (ISKEYBOARD(event->type)) {
+                               /* keyboard menu hierarchy navigation, going back to previous level */
                                but->active->used_mouse= 0;
                                button_activate_state(C, but, BUTTON_STATE_HIGHLIGHT);
                        }
@@ -4669,7 +5402,7 @@ int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle *menu,
                                case ZEROKEY:   case PAD0: 
                                        if(act==0) act= 10;
                                
-                                       if(block->flag & UI_BLOCK_NUMSELECT) {
+                                       if((block->flag & UI_BLOCK_NUMSELECT) && event->val==KM_PRESS) {
                                                if(event->alt) act+= 10;
                                                
                                                count= 0;
@@ -4678,9 +5411,16 @@ int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle *menu,
                                                        
                                                        if(but->type!=LABEL && but->type!=SEPR)
                                                                count++;
-
+                                                       
+                                                       /* exception for rna layer buts */
+                                                       if(but->rnapoin.data && but->rnaprop) {
+                                                               if (ELEM(RNA_property_subtype(but->rnaprop), PROP_LAYER, PROP_LAYER_MEMBER)) {
+                                                                       if (but->rnaindex== act-1)
+                                                                               doit=1;
+                                                               }
+                                                       }
                                                        /* exception for menus like layer buts, with button aligning they're not drawn in order */
-                                                       if(but->type==TOGR) {
+                                                       else if(but->type==TOGR) {
                                                                if(but->bitnr==act-1)
                                                                        doit= 1;
                                                        }
@@ -4707,9 +5447,14 @@ int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle *menu,
                        if(inside==0) {
                                uiSafetyRct *saferct= block->saferct.first;
 
-                               if(ELEM3(event->type, LEFTMOUSE, MIDDLEMOUSE, RIGHTMOUSE) && event->val==KM_PRESS)
-                                       if(saferct && !BLI_in_rctf(&saferct->parent, event->x, event->y))
-                                               menu->menuretval= UI_RETURN_OK;
+                               if(ELEM3(event->type, LEFTMOUSE, MIDDLEMOUSE, RIGHTMOUSE) && event->val==KM_PRESS) {
+                                       if(saferct && !BLI_in_rctf(&saferct->parent, event->x, event->y)) {
+                                               if(block->flag & (UI_BLOCK_OUT_1|UI_BLOCK_KEEP_OPEN))
+                                                       menu->menuretval= UI_RETURN_OK;
+                                               else
+                                                       menu->menuretval= UI_RETURN_OUT;
+                                       }
+                               }
                        }
 
                        if(menu->menuretval);
@@ -4745,10 +5490,10 @@ int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle *menu,
 
                                        /* strict check, and include the parent rect */
                                        if(!menu->dotowards && !saferct) {
-                                               if(block->flag & UI_BLOCK_OUT_1)
+                                               if(block->flag & (UI_BLOCK_OUT_1|UI_BLOCK_KEEP_OPEN))
                                                        menu->menuretval= UI_RETURN_OK;
                                                else
-                                                       menu->menuretval= (block->flag & UI_BLOCK_KEEP_OPEN)? UI_RETURN_OK: UI_RETURN_OUT;
+                                                       menu->menuretval= UI_RETURN_OUT;
                                        }
                                        else if(menu->dotowards && event->type==MOUSEMOVE)
                                                retval= WM_UI_HANDLER_BREAK;
@@ -4759,7 +5504,7 @@ int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle *menu,
 
        /* if we are didn't handle the event yet, lets pass it on to
         * buttons inside this region. disabled inside check .. not sure
-        * anymore why it was there? but i meant enter enter didn't work
+        * anymore why it was there? but it meant enter didn't work
         * for example when mouse was not over submenu */
        if((/*inside &&*/ (!menu->menuretval || menu->menuretval == UI_RETURN_UPDATE) && retval == WM_UI_HANDLER_CONTINUE) || event->type == TIMER) {
                but= ui_but_find_activated(ar);
@@ -4818,8 +5563,6 @@ static int ui_handle_menu_return_submenu(bContext *C, wmEvent *event, uiPopupBlo
                }
 
                update= (submenu->menuretval == UI_RETURN_UPDATE);
-               if(update)
-                       menu->menuretval = UI_RETURN_UPDATE;
 
                /* now let activated button in this menu exit, which
                 * will actually close the submenu too */
@@ -4886,8 +5629,7 @@ static int ui_handler_region(bContext *C, wmEvent *event, void *userdata)
        /* either handle events for already activated button or try to activate */
        but= ui_but_find_activated(ar);
 
-       if(!but || !button_modal_state(but->active->state))
-               retval= ui_handler_panel_region(C, event);
+       retval= ui_handler_panel_region(C, event);
 
        if(retval == WM_UI_HANDLER_CONTINUE)
                retval= ui_handle_list_event(C, event, ar);