- fix numpad comma replacement which was broken since unicode input was added.
[blender.git] / source / blender / editors / interface / interface_handlers.c
index 6417a6b..e49cb48 100644 (file)
@@ -107,6 +107,12 @@ typedef enum uiHandleButtonState {
        BUTTON_STATE_EXIT
 } uiHandleButtonState;
 
+typedef enum uiButtonJumpType {
+       BUTTON_EDIT_JUMP_NONE,
+       BUTTON_EDIT_JUMP_DELIM,
+       BUTTON_EDIT_JUMP_ALL
+} uiButtonJumpType;
+
 typedef struct uiHandleButtonData {
        wmWindowManager *wm;
        wmWindow *window;
@@ -260,7 +266,7 @@ static int ui_is_a_warp_but(uiBut *but)
 }
 
 /* file selectors are exempt from utf-8 checks */
-static int ui_is_utf8_but(uiBut *but)
+int ui_is_but_utf8(uiBut *but)
 {
        if (but->rnaprop) {
                const int subtype= RNA_property_subtype(but->rnaprop);
@@ -1163,7 +1169,10 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data,
                }
                else {
                        button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
-                       BLI_strncpy(active_data->str, buf, active_data->maxlen);
+
+                       if(ui_is_but_utf8(but)) BLI_strncpy_utf8(active_data->str, buf, active_data->maxlen);
+                       else                    BLI_strncpy(active_data->str, buf, active_data->maxlen);
+
                        if(but->type == SEARCH_MENU) {
                                /* else uiSearchboxData.active member is not updated [#26856] */
                                ui_searchbox_update(C, data->searchbox, but, 1);
@@ -1252,6 +1261,86 @@ static short test_special_char(char ch)
        return 0;
 }
 
+static int ui_textedit_step_next_utf8(const char *str, size_t maxlen, short *pos)
+{
+       const char *str_end= str + (maxlen + 1);
+       const char *str_pos= str + (*pos);
+       const char *str_next= BLI_str_find_next_char_utf8(str_pos, str_end);
+       if (str_next) {
+               (*pos) += (str_next - str_pos);
+               if((*pos) > maxlen) (*pos)= maxlen;
+               return TRUE;
+       }
+
+       return FALSE;
+}
+
+static int ui_textedit_step_prev_utf8(const char *str, size_t UNUSED(maxlen), short *pos)
+{
+       if((*pos) > 0) {
+               const char *str_pos= str + (*pos);
+               const char *str_prev= BLI_str_find_prev_char_utf8(str, str_pos);
+               if (str_prev) {
+                       (*pos) -= (str_pos - str_prev);
+                       return TRUE;
+               }
+       }
+
+       return FALSE;
+}
+
+static void ui_textedit_step_utf8(const char *str, size_t maxlen,
+                                  short *pos, const char direction,
+                                  uiButtonJumpType jump)
+{
+       const short pos_prev= *pos;
+
+       if(direction) { /* right*/
+               if(jump != BUTTON_EDIT_JUMP_NONE) {
+                       /* jump between special characters (/,\,_,-, etc.),
+                        * look at function test_special_char() for complete
+                        * list of special character, ctr -> */
+                       while((*pos) < maxlen) {
+                               if (ui_textedit_step_next_utf8(str, maxlen, pos)) {
+                                       if((jump != BUTTON_EDIT_JUMP_ALL) && test_special_char(str[(*pos)])) break;
+                               }
+                               else {
+                                       break; /* unlikely but just incase */
+                               }
+                       }
+               }
+               else {
+                       ui_textedit_step_next_utf8(str, maxlen, pos);
+               }
+       }
+       else { /* left */
+               if(jump != BUTTON_EDIT_JUMP_NONE) {
+                       /* left only: compensate for index/change in direction */
+                       ui_textedit_step_prev_utf8(str, maxlen, pos);
+
+                       /* jump between special characters (/,\,_,-, etc.),
+                        * look at function test_special_char() for complete
+                        * list of special character, ctr -> */
+                       while ((*pos) > 0) {
+                               if (ui_textedit_step_prev_utf8(str, maxlen, pos)) {
+                                       if((jump != BUTTON_EDIT_JUMP_ALL) && test_special_char(str[(*pos)])) break;
+                               }
+                               else {
+                                       break;
+                               }
+                       }
+
+                       /* left only: compensate for index/change in direction */
+                       if(((*pos) != 0) && ABS(pos_prev - (*pos)) > 1) {
+                               ui_textedit_step_next_utf8(str, maxlen, pos);
+                       }
+               }
+               else {
+                       ui_textedit_step_prev_utf8(str, maxlen, pos);
+               }
+       }
+}
+
 static int ui_textedit_delete_selection(uiBut *but, uiHandleButtonData *data)
 {
        char *str= data->str;
@@ -1294,13 +1383,17 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, sho
        
        /* mouse dragged outside the widget to the left */
        if (x < startx && but->ofs > 0) {       
-               int i= but->ofs;
+               short i= but->ofs;
 
                origstr[but->ofs] = 0;
                
                while (i > 0) {
-                       i--;
-                       if (BLF_width(fstyle->uifont_id, origstr+i) > (startx - x)*0.25f) break;        // 0.25 == scale factor for less sensitivity
+                       if (ui_textedit_step_prev_utf8(origstr, but->ofs, &i)) {
+                               if (BLF_width(fstyle->uifont_id, origstr+i) > (startx - x)*0.25f) break;        // 0.25 == scale factor for less sensitivity
+                       }
+                       else {
+                               break; /* unlikely but possible */
+                       }
                }
                but->ofs = i;
                but->pos = but->ofs;
@@ -1314,9 +1407,13 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, sho
                /* XXX does not take zoom level into account */
                while (startx + aspect_sqrt * BLF_width(fstyle->uifont_id, origstr+but->ofs) > x) {
                        if (but->pos <= 0) break;
-                       but->pos--;
-                       origstr[but->pos+but->ofs] = 0;
-               }               
+                       if (ui_textedit_step_prev_utf8(origstr, but->ofs, &but->pos)) {
+                               origstr[but->pos+but->ofs] = 0;
+                       }
+                       else {
+                               break; /* unlikely but possible */
+                       }
+               }
                but->pos += but->ofs;
                if(but->pos<0) but->pos= 0;
        }
@@ -1340,27 +1437,31 @@ static void ui_textedit_set_cursor_select(uiBut *but, uiHandleButtonData *data,
        ui_check_but(but);
 }
 
-static int ui_textedit_type_ascii(uiBut *but, uiHandleButtonData *data, char ascii)
+/* this is used for both utf8 and ascii, its meant to be used for single keys,
+ * notie the buffer is either copied or not, so its not suitable for pasting in
+ * - campbell */
+static int ui_textedit_type_buf(uiBut *but, uiHandleButtonData *data,
+                                const char *utf8_buf, int utf8_buf_len)
 {
        char *str;
-       int len, x, changed= 0;
+       int len, changed= 0;
 
        str= data->str;
        len= strlen(str);
 
        if(len-(but->selend - but->selsta)+1 <= data->maxlen) {
+               int step= utf8_buf_len;
+
                /* type over the current selection */
-               if ((but->selend - but->selsta) > 0)
+               if ((but->selend - but->selsta) > 0) {
                        changed= ui_textedit_delete_selection(but, data);
+                       len= strlen(str);
+               }
 
-               len= strlen(str);
-               if(len+1 < data->maxlen) {
-                       for(x= data->maxlen; x>but->pos; x--)
-                               str[x]= str[x-1];
-                       str[but->pos]= ascii;
-                       str[len+1]= '\0';
-
-                       but->pos++; 
+               if(len + step < data->maxlen) {
+                       memmove(&str[but->pos + step], &str[but->pos], (len + 1) - but->pos);
+                       memcpy(&str[but->pos], utf8_buf, step * sizeof(char));
+                       but->pos += step;
                        changed= 1;
                }
        }
@@ -1368,7 +1469,22 @@ static int ui_textedit_type_ascii(uiBut *but, uiHandleButtonData *data, char asc
        return changed;
 }
 
-static void ui_textedit_move(uiBut *but, uiHandleButtonData *data, int direction, int select, int jump, int jump_all)
+static int ui_textedit_type_ascii(uiBut *but, uiHandleButtonData *data, char ascii)
+{
+       char buf[2]= {ascii, '\0'};
+
+       if (ui_is_but_utf8(but) && (BLI_str_utf8_size(buf) == -1)) {
+               printf("%s: entering invalid ascii char into an ascii key (%d)\n",
+                      __func__, (int)(unsigned char)ascii);
+
+               return 0;
+       }
+
+       /* in some cases we want to allow invalid utf8 chars */
+       return ui_textedit_type_buf(but, data, buf, 1);
+}
+
+static void ui_textedit_move(uiBut *but, uiHandleButtonData *data, int direction, int select, uiButtonJumpType jump)
 {
        const char *str= data->str;
        const int len= strlen(str);
@@ -1377,7 +1493,7 @@ static void ui_textedit_move(uiBut *but, uiHandleButtonData *data, int direction
 
        /* special case, quit selection and set cursor */
        if (has_sel && !select) {
-               if (jump_all) {
+               if (jump == BUTTON_EDIT_JUMP_ALL) {
                        but->selsta = but->selend= but->pos = direction ? len : 0;
                }
                else {
@@ -1391,48 +1507,7 @@ static void ui_textedit_move(uiBut *but, uiHandleButtonData *data, int direction
                data->selextend = 0;
        }
        else {
-               if(direction) { /* right*/
-                       if(jump) {
-                               /* jump between special characters (/,\,_,-, etc.),
-                                * look at function test_special_char() for complete
-                                * list of special character, ctr -> */
-                               while(but->pos < len) {
-                                       but->pos++;
-                                       if(!jump_all && test_special_char(str[but->pos])) break;
-                               }
-                       }
-                       else {
-                               but->pos++;
-                               if(but->pos > len) but->pos= len;
-                       }
-               }
-               else { /* left */
-                       if(jump) {
-
-                               /* left only: compensate for index/change in direction */
-                               if(but->pos > 0) {
-                                       but->pos--;
-                               }
-
-                               /* jump between special characters (/,\,_,-, etc.),
-                                * look at function test_special_char() for complete
-                                * list of special character, ctr -> */
-                               while(but->pos > 0){
-                                       but->pos--;
-                                       if(!jump_all && test_special_char(str[but->pos])) break;
-                               }
-
-                               /* left only: compensate for index/change in direction */
-                               if((but->pos != 0) && ABS(pos_prev - but->pos) > 1) {
-                                       but->pos++;
-                               }
-
-                       }
-                       else {
-                               if(but->pos>0) but->pos--;
-                       }
-               }
-
+               ui_textedit_step_utf8(str, len, &but->pos, direction, jump);
 
                if(select) {
                        /* existing selection */
@@ -1481,69 +1556,43 @@ static void ui_textedit_move(uiBut *but, uiHandleButtonData *data, int direction
        }
 }
 
-static int ui_textedit_delete(uiBut *but, uiHandleButtonData *data, int direction, const int all, const int jump)
+static int ui_textedit_delete(uiBut *but, uiHandleButtonData *data, int direction, uiButtonJumpType jump)
 {
        char *str= data->str;
        const int len= strlen(str);
 
-       int x, changed= 0;
+       int changed= 0;
 
-       if(all) {
+       if(jump == BUTTON_EDIT_JUMP_ALL) {
                if(len) changed=1;
-               str[0]= 0;
+               str[0]= '\0';
                but->pos= 0;
        }
        else if(direction) { /* delete */
                if ((but->selend - but->selsta) > 0) {
                        changed= ui_textedit_delete_selection(but, data);
                }
-               else if(but->pos>=0 && but->pos<len) {
+               else if (but->pos>=0 && but->pos<len) {
+                       short pos= but->pos;
                        int step;
-
-                       if (jump) {
-                               x = but->pos;
-                               step= 0;
-                               while(x < len) {
-                                       x++;
-                                       step++;
-                                       if(test_special_char(str[x])) break;
-                               }
-                       }
-                       else {
-                               step= 1;
-                       }
-
-                       for(x=but->pos; x<len; x++)
-                               str[x]= str[x+step];
-                       str[len-step]='\0';
+                       ui_textedit_step_utf8(str, len, &pos, direction, jump);
+                       step= pos - but->pos;
+                       memmove(&str[but->pos], &str[but->pos + step], (len + 1) - but->pos);
                        changed= 1;
                }
        }
        else { /* backspace */
-               if(len!=0) {
+               if (len != 0) {
                        if ((but->selend - but->selsta) > 0) {
                                changed= ui_textedit_delete_selection(but, data);
                        }
                        else if(but->pos>0) {
+                               short pos= but->pos;
                                int step;
 
-                               if (jump) {
-                                       x = but->pos;
-                                       step= 0;
-                                       while(x > 0) {
-                                               x--;
-                                               step++;
-                                               if((step > 1) && test_special_char(str[x])) break;
-                                       }
-                               }
-                               else {
-                                       step= 1;
-                               }
-
-                               for(x=but->pos; x<len; x++)
-                                       str[x-step]= str[x];
-                               str[len-step]='\0';
-
+                               ui_textedit_step_utf8(str, len, &pos, direction, jump);
+                               step= but->pos - pos;
+                               memmove(&str[but->pos - step], &str[but->pos], (len + 1) - but->pos);
                                but->pos -= step;
                                changed= 1;
                        }
@@ -1653,19 +1702,9 @@ static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data)
        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])) {
-                               /* no stripping actually: just convert to alt name */
-                               ui_convert_to_unit_alt_name(but, data->str, data->maxlen);
-                               break;
-                       }
-               }
+               ui_convert_to_unit_alt_name(but, data->str, data->maxlen);
        }
-       
-       
+
        data->origstr= BLI_strdup(data->str);
        data->selextend= 0;
        data->selstartx= 0;
@@ -1690,7 +1729,7 @@ static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data)
 static void ui_textedit_end(bContext *C, uiBut *but, uiHandleButtonData *data)
 {
        if(but) {
-               if(ui_is_utf8_but(but)) {
+               if(ui_is_but_utf8(but)) {
                        int strip= BLI_utf8_invalid_strip(but->editstr, strlen(but->editstr));
                        /* not a file?, strip non utf-8 chars */
                        if(strip) {
@@ -1842,11 +1881,11 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
                                }
                                break;
                        case RIGHTARROWKEY:
-                               ui_textedit_move(but, data, 1, event->shift, event->ctrl, FALSE);
+                               ui_textedit_move(but, data, 1, event->shift, event->ctrl ? BUTTON_EDIT_JUMP_DELIM : BUTTON_EDIT_JUMP_NONE);
                                retval= WM_UI_HANDLER_BREAK;
                                break;
                        case LEFTARROWKEY:
-                               ui_textedit_move(but, data, 0, event->shift, event->ctrl, FALSE);
+                               ui_textedit_move(but, data, 0, event->shift, event->ctrl ? BUTTON_EDIT_JUMP_DELIM : BUTTON_EDIT_JUMP_NONE);
                                retval= WM_UI_HANDLER_BREAK;
                                break;
                        case DOWNARROWKEY:
@@ -1856,7 +1895,7 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
                                }
                                /* pass on purposedly */
                        case ENDKEY:
-                               ui_textedit_move(but, data, 1, event->shift, TRUE, TRUE);
+                               ui_textedit_move(but, data, 1, event->shift, BUTTON_EDIT_JUMP_ALL);
                                retval= WM_UI_HANDLER_BREAK;
                                break;
                        case UPARROWKEY:
@@ -1866,7 +1905,7 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
                                }
                                /* pass on purposedly */
                        case HOMEKEY:
-                               ui_textedit_move(but, data, 0, event->shift, TRUE, TRUE);
+                               ui_textedit_move(but, data, 0, event->shift, BUTTON_EDIT_JUMP_ALL);
                                retval= WM_UI_HANDLER_BREAK;
                                break;
                        case PADENTER:
@@ -1875,12 +1914,12 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
                                retval= WM_UI_HANDLER_BREAK;
                                break;
                        case DELKEY:
-                               changed= ui_textedit_delete(but, data, 1, 0, event->ctrl);
+                               changed= ui_textedit_delete(but, data, 1, event->ctrl ? BUTTON_EDIT_JUMP_DELIM : BUTTON_EDIT_JUMP_NONE);
                                retval= WM_UI_HANDLER_BREAK;
                                break;
 
                        case BACKSPACEKEY:
-                               changed= ui_textedit_delete(but, data, 0, event->shift, event->ctrl);
+                               changed= ui_textedit_delete(but, data, 0, event->shift ? BUTTON_EDIT_JUMP_ALL :  (event->ctrl ? BUTTON_EDIT_JUMP_DELIM : BUTTON_EDIT_JUMP_NONE));
                                retval= WM_UI_HANDLER_BREAK;
                                break;
                                
@@ -1903,16 +1942,33 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
                                break;
                }
 
-               if(event->ascii && (retval == WM_UI_HANDLER_CONTINUE)) {
+               if((event->ascii || event->utf8_buf[0]) && (retval == WM_UI_HANDLER_CONTINUE)) {
                        char ascii = event->ascii;
+                       const char *utf8_buf= event->utf8_buf;
 
                        /* exception that's useful for number buttons, some keyboard
                           numpads have a comma instead of a period */
-                       if(ELEM3(but->type, NUM, NUMABS, NUMSLI))
-                               if(event->type == PADPERIOD && ascii == ',')
+                       if(ELEM3(but->type, NUM, NUMABS, NUMSLI)) { /* could use data->min*/
+                               if(event->type == PADPERIOD && ascii == ',') {
                                        ascii = '.';
+                                       utf8_buf= NULL; /* force ascii fallback */
+                               }
+                       }
+
+                       if(utf8_buf && utf8_buf[0]) {
+                               int utf8_buf_len= BLI_str_utf8_size(utf8_buf);
+                               /* keep this printf until utf8 is well tested */
+                               if (utf8_buf_len != 1) {
+                                       printf("%s: utf8 char '%.*s'\n", __func__, utf8_buf_len, utf8_buf);
+                               }
+
+                               // strcpy(utf8_buf, "12345");
+                               changed= ui_textedit_type_buf(but, data, event->utf8_buf, utf8_buf_len);
+                       }
+                       else {
+                               changed= ui_textedit_type_ascii(but, data, ascii);
+                       }
 
-                       changed= ui_textedit_type_ascii(but, data, ascii);
                        retval= WM_UI_HANDLER_BREAK;
                        
                }
@@ -1966,8 +2022,6 @@ static void ui_do_but_textedit_select(bContext *C, uiBlock *block, uiBut *but, u
 
 static void ui_numedit_begin(uiBut *but, uiHandleButtonData *data)
 {
-       float softrange, softmin, softmax;
-
        if(but->type == BUT_CURVE) {
                but->editcumap= (CurveMapping*)but->poin;
        }
@@ -1977,10 +2031,12 @@ static void ui_numedit_begin(uiBut *but, uiHandleButtonData *data)
        }
        else if(ELEM3(but->type, BUT_NORMAL, HSVCUBE, HSVCIRCLE)) {
                ui_get_but_vectorf(but, data->origvec);
-               VECCOPY(data->vec, data->origvec);
+               copy_v3_v3(data->vec, data->origvec);
                but->editvec= data->vec;
        }
        else {
+               float softrange, softmin, softmax;
+
                data->startvalue= ui_get_but_val(but);
                data->origvalue= data->startvalue;
                data->value= data->origvalue;
@@ -2163,15 +2219,11 @@ static int ui_do_but_HOTKEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data
                
                /* always set */
                but->modifier_key = 0;
-               if(event->shift)
-                       but->modifier_key |= KM_SHIFT;
-               if(event->alt)
-                       but->modifier_key |= KM_ALT;
-               if(event->ctrl)
-                       but->modifier_key |= KM_CTRL;
-               if(event->oskey)
-                       but->modifier_key |= KM_OSKEY;
-               
+               if(event->shift) but->modifier_key |= KM_SHIFT;
+               if(event->alt)   but->modifier_key |= KM_ALT;
+               if(event->ctrl)  but->modifier_key |= KM_CTRL;
+               if(event->oskey) but->modifier_key |= KM_OSKEY;
+
                ui_check_but(but);
                ED_region_tag_redraw(data->region);
                        
@@ -3004,6 +3056,9 @@ static int ui_numedit_but_NORMAL(uiBut *but, uiHandleButtonData *data, int mx, i
        /* button is presumed square */
        /* if mouse moves outside of sphere, it does negative normal */
 
+       /* note that both data->vec and data->origvec should be normalized
+        * else we'll get a hamrless but annoying jump when first clicking */
+
        fp= data->origvec;
        rad= (but->x2 - but->x1);
        radsq= rad*rad;
@@ -3634,7 +3689,7 @@ 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) {
+                               if(event->shift == FALSE) {
                                        for(a=0; a<cuma->totpoint; a++)
                                                cmp[a].flag &= ~SELECT;
                                        cmp[sel].flag |= SELECT;
@@ -3673,7 +3728,7 @@ static int ui_do_but_CURVE(bContext *C, uiBlock *block, uiBut *but, uiHandleButt
 
                                if(!data->dragchange) {
                                        /* deselect all, select one */
-                                       if(event->shift==0) {
+                                       if(event->shift == FALSE) {
                                                for(a=0; a<cuma->totpoint; a++)
                                                        cmp[a].flag &= ~SELECT;
                                                cmp[data->dragsel].flag |= SELECT;
@@ -4408,6 +4463,9 @@ static int ui_but_menu(bContext *C, uiBut *but)
                }
        }
 
+       /* perhaps we should move this into (G.f & G_DEBUG) - campbell */
+       uiItemFullO(layout, "UI_OT_editsource", "Edit Source", ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0);
+
        uiPupMenuEnd(C, pup);
 
        return 1;
@@ -4429,7 +4487,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, wmEvent *event)
                /* check prevval because of modal operators [#24016],
                 * modifier check is to allow Ctrl+C for copy.
                 * if this causes other problems, remove this check and suffer the bug :) - campbell */
-               (event->prevval != KM_PRESS || ISKEYMODIFIER(event->prevtype))
+               ((event->prevval != KM_PRESS) || (ISKEYMODIFIER(event->prevtype)) || (event->type == EVT_DROP))
        ) {
                /* handle copy-paste */
                if(ELEM(event->type, CKEY, VKEY) && event->val==KM_PRESS && (event->ctrl || event->oskey)) {
@@ -4441,7 +4499,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, wmEvent *event)
                        ui_but_drop     (C, event, but, data);
                }
                /* handle keyframing */
-               else if(event->type == IKEY && !ELEM3(1, event->ctrl, event->oskey, event->shift) && event->val == KM_PRESS) {
+               else if(event->type == IKEY && !ELEM3(KM_MOD_FIRST, event->ctrl, event->oskey, event->shift) && event->val == KM_PRESS) {
                        if(event->alt)
                                ui_but_anim_delete_keyframe(C);
                        else
@@ -4452,7 +4510,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 && !ELEM3(1, event->ctrl, event->oskey, event->shift) && event->val == KM_PRESS) {
+               else if(event->type == DKEY && !ELEM3(KM_MOD_FIRST, event->ctrl, event->oskey, event->shift) && event->val == KM_PRESS) {
                        if(event->alt)
                                ui_but_anim_remove_driver(C);
                        else
@@ -4463,7 +4521,7 @@ 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 && !ELEM3(1, event->ctrl, event->oskey, event->shift) && event->val == KM_PRESS) {
+               else if(event->type == KKEY && !ELEM3(KM_MOD_FIRST, event->ctrl, event->oskey, event->shift) && event->val == KM_PRESS) {
                        if(event->alt)
                                ui_but_anim_remove_keyingset(C);
                        else
@@ -5100,9 +5158,10 @@ void ui_button_active_free(const bContext *C, uiBut *but)
        }
 }
 
-static uiBut *ui_context_rna_button_active(const bContext *C)
+/* returns the active button with an optional checking function */
+static uiBut *ui_context_button_active(const bContext *C, int (*but_check_cb)(uiBut *))
 {
-       uiBut *rnabut= NULL;
+       uiBut *but_found= NULL;
 
        ARegion *ar= CTX_wm_region(C);
 
@@ -5120,26 +5179,40 @@ static uiBut *ui_context_rna_button_active(const bContext *C)
                        }
                }
 
-               if(activebut && activebut->rnapoin.data) {
+               if(activebut && (but_check_cb == NULL || but_check_cb(activebut))) {
                        uiHandleButtonData *data= activebut->active;
 
-                       rnabut= activebut;
+                       but_found= activebut;
 
                        /* recurse into opened menu, like colorpicker case */
                        if(data && data->menu && (ar != data->menu->region)) {
                                ar = data->menu->region;
                        }
                        else {
-                               return rnabut;
+                               return but_found;
                        }
                }
                else {
                        /* no active button */
-                       return rnabut;
+                       return but_found;
                }
        }
 
-       return rnabut;
+       return but_found;
+}
+
+static int ui_context_rna_button_active_test(uiBut *but)
+{
+       return (but->rnapoin.data != NULL);
+}
+static uiBut *ui_context_rna_button_active(const bContext *C)
+{
+       return ui_context_button_active(C, ui_context_rna_button_active_test);
+}
+
+uiBut *uiContextActiveButton(const struct bContext *C)
+{
+       return ui_context_button_active(C, NULL);
 }
 
 /* helper function for insert keyframe, reset to default, etc operators */
@@ -5933,9 +6006,9 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle
                                case ZKEY:
                                {
                                        if(     (event->val == KM_PRESS) &&
-                                               (event->shift == FALSE) &&
-                                               (event->ctrl == FALSE) &&
-                                               (event->oskey == FALSE)
+                                           (event->shift == FALSE) &&
+                                           (event->ctrl ==  FALSE) &&
+                                           (event->oskey == FALSE)
                                        ) {
                                                for(but= block->buttons.first; but; but= but->next) {