Context menu 'Edit Source' operator no longer needs to be enabled as a build option...
[blender.git] / source / blender / editors / interface / interface.c
index 37e4cc7..f999107 100644 (file)
 #include "BIF_gl.h"
 
 #include "BLF_api.h"
+#include "BLF_translation.h"
 
 #include "UI_interface.h"
 
+#include "IMB_imbuf.h"
 
 #include "WM_api.h"
 #include "WM_types.h"
 #define MENU_ITEM_HEIGHT       20
 #define MENU_SEP_HEIGHT                6
 
-#define PRECISION_FLOAT_MAX 7
-#define PRECISION_FLOAT_MAX_POW 10000000 /* pow(10, PRECISION_FLOAT_MAX)  */
+#define PRECISION_FLOAT_MAX 6
+#define PRECISION_FLOAT_MAX_POW 1000000 /* pow(10, PRECISION_FLOAT_MAX)  */
+
+/* avoid unneeded calls to ui_get_but_val */
+#define UI_BUT_VALUE_UNSET DBL_MAX
+#define UI_GET_BUT_VALUE_INIT(_but, _value) if(_value == DBL_MAX) {  (_value)= ui_get_but_val(_but); }
 
 /* 
  * a full doc with API notes can be found in bf-blender/trunk/blender/doc/guides/interface_API.txt
@@ -88,19 +94,46 @@ static void ui_free_but(const bContext *C, uiBut *but);
 
 /* ************* translation ************** */
 
-int ui_translate_buttons(void)
+int UI_translate_iface(void)
 {
-       return (U.transopts & USER_TR_BUTTONS);
+#ifdef WITH_INTERNATIONAL
+       return (U.transopts & USER_DOTRANSLATE) && (U.transopts & USER_TR_IFACE);
+#else
+       return 0;
+#endif
 }
 
-int ui_translate_menus(void)
+int UI_translate_tooltips(void)
 {
-       return (U.transopts & USER_TR_MENUS);
+#ifdef WITH_INTERNATIONAL
+       return (U.transopts & USER_DOTRANSLATE) && (U.transopts & USER_TR_TOOLTIPS);
+#else
+       return 0;
+#endif
 }
 
-int ui_translate_tooltips(void)
+const char *UI_translate_do_iface(const char *msgid)
 {
-       return (U.transopts & USER_TR_TOOLTIPS);
+#ifdef WITH_INTERNATIONAL
+       if(UI_translate_iface())
+               return BLF_gettext(msgid);
+       else
+               return msgid;
+#else
+       return msgid;
+#endif
+}
+
+const char *UI_translate_do_tooltip(const char *msgid)
+{
+#ifdef WITH_INTERNATIONAL
+       if(UI_translate_tooltips())
+               return BLF_gettext(msgid);
+       else
+               return msgid;
+#else
+       return msgid;
+#endif
 }
 
 /* ************* window matrix ************** */
@@ -224,7 +257,7 @@ void ui_block_translate(uiBlock *block, int x, int y)
 
 static void ui_text_bounds_block(uiBlock *block, float offset)
 {
-       uiStyle *style= U.uistyles.first;       // XXX pass on as arg
+       uiStyle *style=UI_GetStyle();
        uiBut *bt;
        int i = 0, j, x1addval= offset, nextcol;
        int lastcol= 0, col= 0;
@@ -233,9 +266,6 @@ static void ui_text_bounds_block(uiBlock *block, float offset)
        
        for(bt= block->buttons.first; bt; bt= bt->next) {
                if(bt->type!=SEPR) {
-                       //int transopts= ui_translate_buttons();
-                       //if(bt->type==TEX || bt->type==IDPOIN) transopts= 0;
-                       
                        j= BLF_width(style->widget.uifont_id, bt->drawstr);
 
                        if(j > i) i = j;
@@ -545,7 +575,7 @@ static void ui_draw_links(uiBlock *block)
 /* NOTE: if but->poin is allocated memory for every defbut, things fail... */
 static int ui_but_equals_old(uiBut *but, uiBut *oldbut)
 {
-       /* various properties are being compared here, hopfully sufficient
+       /* various properties are being compared here, hopefully sufficient
         * to catch all cases, but it is simple to add more checks later */
        if(but->retval != oldbut->retval) return 0;
        if(but->rnapoin.data != oldbut->rnapoin.data) return 0;
@@ -610,7 +640,7 @@ static int ui_but_update_from_old_block(const bContext *C, uiBlock *block, uiBut
 //                             but->flag= oldbut->flag;
 #else
                                /* exception! redalert flag can't be update from old button. 
-                                * perhaps it should only copy spesific flags rather than all. */
+                                * perhaps it should only copy specific flags rather than all. */
 //                             but->flag= (oldbut->flag & ~UI_BUT_REDALERT) | (but->flag & UI_BUT_REDALERT);
 #endif
 //                             but->active= oldbut->active;
@@ -648,6 +678,11 @@ static int ui_but_update_from_old_block(const bContext *C, uiBlock *block, uiBut
                                        SWAP(void *, oldbut->func_argN, but->func_argN)
                                }
                                
+                               /* copy hardmin for list rows to prevent 'sticking' highlight to mouse position
+                                  when scrolling without moving mouse (see [#28432]) */
+                               if(ELEM(oldbut->type, ROW, LISTROW))
+                                       oldbut->hardmax= but->hardmax;
+                               
                                ui_but_update_linklines(block, oldbut, but);
                                
                                BLI_remlink(&block->buttons, but);
@@ -706,6 +741,27 @@ int uiButActiveOnly(const bContext *C, uiBlock *block, uiBut *but)
        return 1;
 }
 
+/* use to check if we need to disable undo, but dont make any changes
+ * returns FALSE if undo needs to be disabled. */
+static int ui_but_is_rna_undo(uiBut *but)
+{
+       if(but->rnapoin.id.data) {
+               /* avoid undo push for buttons who's ID are screen or wm level
+                * we could disable undo for buttons with no ID too but may have
+                * unforeseen consequences, so best check for ID's we _know_ are not
+                * handled by undo - campbell */
+               ID *id= but->rnapoin.id.data;
+               if(ID_CHECK_UNDO(id) == FALSE) {
+                       return FALSE;
+               }
+               else {
+                       return TRUE;
+               }
+       }
+
+       return TRUE;
+}
+
 /* assigns automatic keybindings to menu items for fast access
  * (underline key in menu) */
 static void ui_menu_block_set_keyaccels(uiBlock *block)
@@ -809,7 +865,7 @@ void uiEndBlock(const bContext *C, uiBlock *block)
 
        /* inherit flags from 'old' buttons that was drawn here previous, based
         * on matching buttons, we need this to make button event handling non
-        * blocking, while still alowing buttons to be remade each redraw as it
+        * blocking, while still allowing buttons to be remade each redraw as it
         * is expected by blender code */
        for(but=block->buttons.first; but; but=but->next) {
                if(ui_but_update_from_old_block(C, block, &but))
@@ -904,7 +960,7 @@ static void ui_but_to_pixelrect(rcti *rect, const ARegion *ar, uiBlock *block, u
 /* uses local copy of style, to scale things down, and allow widgets to change stuff */
 void uiDrawBlock(const bContext *C, uiBlock *block)
 {
-       uiStyle style= *((uiStyle *)U.uistyles.first);  // XXX pass on as arg
+       uiStyle style= *UI_GetStyle();  // XXX pass on as arg
        ARegion *ar;
        uiBut *but;
        rcti rect;
@@ -967,17 +1023,16 @@ void uiDrawBlock(const bContext *C, uiBlock *block)
 
 /* ************* EVENTS ************* */
 
-static void ui_is_but_sel(uiBut *but)
+static void ui_is_but_sel(uiBut *but, double *value)
 {
-       double value; /* only initialized when needed, to avoid calling when not used */
        short push=0, true=1;
 
        if(ELEM3(but->type, TOGN, ICONTOGN, OPTIONN)) true= 0;
 
        if( but->bit ) {
                int lvalue;
-               value= ui_get_but_val(but);
-               lvalue= (int)value;
+               UI_GET_BUT_VALUE_INIT(but, *value)
+               lvalue= (int)*value;
                if( BTST(lvalue, (but->bitnr)) ) push= true;
                else push= !true;
        }
@@ -997,24 +1052,24 @@ static void ui_is_but_sel(uiBut *but)
                case BUT_TOGDUAL:
                case ICONTOG:
                case OPTION:
-                       value= ui_get_but_val(but);
-                       if(value != (double)but->hardmin) push= 1;
+                       UI_GET_BUT_VALUE_INIT(but, *value)
+                       if(*value != (double)but->hardmin) push= 1;
                        break;
                case ICONTOGN:
                case TOGN:
                case OPTIONN:
-                       value= ui_get_but_val(but);
-                       if(value==0.0) push= 1;
+                       UI_GET_BUT_VALUE_INIT(but, *value)
+                       if(*value==0.0) push= 1;
                        break;
                case ROW:
                case LISTROW:
-                       value= ui_get_but_val(but);
+                       UI_GET_BUT_VALUE_INIT(but, *value)
                        /* support for rna enum buts */
                        if(but->rnaprop && (RNA_property_flag(but->rnaprop) & PROP_ENUM_FLAG)) {
-                               if((int)value & (int)but->hardmax) push= 1;
+                               if((int)*value & (int)but->hardmax) push= 1;
                        }
                        else {
-                               if(value == (double)but->hardmax) push= 1;
+                               if(*value == (double)but->hardmax) push= 1;
                        }
                        break;
                case COL:
@@ -1156,7 +1211,7 @@ void ui_delete_linkline(uiLinkLine *line, uiBut *but)
  * an edit override pointer while dragging for example */
 
 /* for buttons pointing to color for example */
-void ui_get_but_vectorf(uiBut *but, float *vec)
+void ui_get_but_vectorf(uiBut *but, float vec[3])
 {
        PropertyRNA *prop;
        int a, tot;
@@ -1194,27 +1249,34 @@ void ui_get_but_vectorf(uiBut *but, float *vec)
                        vec[0]= vec[1]= vec[2]= 0.0f;
                }
        }
+
+       if (but->type == BUT_NORMAL) {
+               normalize_v3(vec);
+       }
 }
 
 /* for buttons pointing to color for example */
-void ui_set_but_vectorf(uiBut *but, float *vec)
+void ui_set_but_vectorf(uiBut *but, const float vec[3])
 {
        PropertyRNA *prop;
-       int a, tot;
 
        if(but->editvec) {
-               VECCOPY(but->editvec, vec);
+               copy_v3_v3(but->editvec, vec);
        }
 
        if(but->rnaprop) {
                prop= but->rnaprop;
 
                if(RNA_property_type(prop) == PROP_FLOAT) {
+                       int tot;
+                       int a;
+
                        tot= RNA_property_array_length(&but->rnapoin, prop);
                        tot= MIN2(tot, 3);
 
-                       for(a=0; a<tot; a++)
+                       for (a=0; a<tot; a++) {
                                RNA_property_float_set_index(&but->rnapoin, prop, a, vec[a]);
+                       }
                }
        }
        else if(but->pointype == CHA) {
@@ -1225,7 +1287,7 @@ void ui_set_but_vectorf(uiBut *but, float *vec)
        }
        else if(but->pointype == FLO) {
                float *fp= (float *)but->poin;
-               VECCOPY(fp, vec);
+               copy_v3_v3(fp, vec);
        }
 }
 
@@ -1242,14 +1304,14 @@ int ui_is_but_float(uiBut *but)
 
 int ui_is_but_unit(uiBut *but)
 {
-       Scene *scene= CTX_data_scene((bContext *)but->block->evil_C);
-       int unit_type= uiButGetUnitType(but);
+       UnitSettings *unit= but->block->unit;
+       const int unit_type= uiButGetUnitType(but);
 
        if(unit_type == PROP_UNIT_NONE)
                return 0;
 
 #if 1 // removed so angle buttons get correct snapping
-       if (scene->unit.system_rotation == USER_UNIT_ROT_RADIANS && unit_type == PROP_UNIT_ROTATION)
+       if (unit->system_rotation == USER_UNIT_ROT_RADIANS && unit_type == PROP_UNIT_ROTATION)
                return 0;
 #endif
        
@@ -1257,7 +1319,7 @@ int ui_is_but_unit(uiBut *but)
        if (unit_type == PROP_UNIT_TIME)
                return 0;
 
-       if (scene->unit.system == USER_UNIT_NONE) {
+       if (unit->system == USER_UNIT_NONE) {
                if (unit_type != PROP_UNIT_ROTATION) {
                        return 0;
                }
@@ -1290,19 +1352,19 @@ double ui_get_but_val(uiBut *but)
 
                switch(RNA_property_type(prop)) {
                        case PROP_BOOLEAN:
-                               if(RNA_property_array_length(&but->rnapoin, prop))
+                               if(RNA_property_array_check(prop))
                                        value= RNA_property_boolean_get_index(&but->rnapoin, prop, but->rnaindex);
                                else
                                        value= RNA_property_boolean_get(&but->rnapoin, prop);
                                break;
                        case PROP_INT:
-                               if(RNA_property_array_length(&but->rnapoin, prop))
+                               if(RNA_property_array_check(prop))
                                        value= RNA_property_int_get_index(&but->rnapoin, prop, but->rnaindex);
                                else
                                        value= RNA_property_int_get(&but->rnapoin, prop);
                                break;
                        case PROP_FLOAT:
-                               if(RNA_property_array_length(&but->rnapoin, prop))
+                               if(RNA_property_array_check(prop))
                                        value= RNA_property_float_get_index(&but->rnapoin, prop, but->rnaindex);
                                else
                                        value= RNA_property_float_get(&but->rnapoin, prop);
@@ -1385,6 +1447,10 @@ void ui_set_but_val(uiBut *but, double value)
                                        break;
                        }
                }
+
+               /* we can't be sure what RNA set functions actually do,
+                * so leave this unset */
+               value= UI_BUT_VALUE_UNSET;
        }
        else if(but->pointype==0);
        else if(but->type==HSVSLI ) {
@@ -1425,19 +1491,19 @@ void ui_set_but_val(uiBut *but, double value)
                
                /* then set value with possible edit override */
                if(but->editval)
-                       *but->editval= value;
+                       value= *but->editval= value;
                else if(but->pointype==CHA)
-                       *((char *)but->poin)= (char)value;
+                       value= *((char *)but->poin)= (char)value;
                else if(but->pointype==SHO)
-                       *((short *)but->poin)= (short)value;
+                       value= *((short *)but->poin)= (short)value;
                else if(but->pointype==INT)
-                       *((int *)but->poin)= (int)value;
+                       value= *((int *)but->poin)= (int)value;
                else if(but->pointype==FLO)
-                       *((float *)but->poin)= (float)value;
+                       value= *((float *)but->poin)= (float)value;
        }
 
        /* update select flag */
-       ui_is_but_sel(but);
+       ui_is_but_sel(but, &value);
 }
 
 int ui_get_but_string_max_length(uiBut *but)
@@ -1452,19 +1518,20 @@ int ui_get_but_string_max_length(uiBut *but)
 
 static double ui_get_but_scale_unit(uiBut *but, double value)
 {
-       Scene *scene= CTX_data_scene((bContext *)but->block->evil_C);
+       UnitSettings *unit= but->block->unit;
        int unit_type= uiButGetUnitType(but);
 
        if(unit_type == PROP_UNIT_LENGTH) {
-               return value * (double)scene->unit.scale_length;
+               return value * (double)unit->scale_length;
        }
        else if(unit_type == PROP_UNIT_AREA) {
-               return value * pow(scene->unit.scale_length, 2);
+               return value * pow(unit->scale_length, 2);
        }
        else if(unit_type == PROP_UNIT_VOLUME) {
-               return value * pow(scene->unit.scale_length, 3);
+               return value * pow(unit->scale_length, 3);
        }
        else if(unit_type == PROP_UNIT_TIME) { /* WARNING - using evil_C :| */
+               Scene *scene= CTX_data_scene(but->block->evil_C);
                return FRA2TIME(value);
        }
        else {
@@ -1473,17 +1540,17 @@ static double ui_get_but_scale_unit(uiBut *but, double value)
 }
 
 /* str will be overwritten */
-void ui_convert_to_unit_alt_name(uiBut *but, char *str, int maxlen)
+void ui_convert_to_unit_alt_name(uiBut *but, char *str, size_t maxlen)
 {
        if(ui_is_but_unit(but)) {
+               UnitSettings *unit= but->block->unit;
                int unit_type= uiButGetUnitType(but);
                char *orig_str;
-               Scene *scene= CTX_data_scene((bContext *)but->block->evil_C);
                
                orig_str= MEM_callocN(sizeof(char)*maxlen + 1, "textedit sub str");
                memcpy(orig_str, str, maxlen);
                
-               bUnit_ToUnitAltName(str, maxlen, orig_str, scene->unit.system, unit_type>>16);
+               bUnit_ToUnitAltName(str, maxlen, orig_str, unit->system, unit_type>>16);
                
                MEM_freeN(orig_str);
        }
@@ -1491,27 +1558,26 @@ void ui_convert_to_unit_alt_name(uiBut *but, char *str, int maxlen)
 
 static void ui_get_but_string_unit(uiBut *but, char *str, int len_max, double value, int pad)
 {
-       Scene *scene= CTX_data_scene((bContext *)but->block->evil_C);
-       int do_split= scene->unit.flag & USER_UNIT_OPT_SPLIT;
+       UnitSettings *unit= but->block->unit;
+       int do_split= unit->flag & USER_UNIT_OPT_SPLIT;
        int unit_type= uiButGetUnitType(but);
        int precision= but->a2;
 
-       if(scene->unit.scale_length<0.0001f) scene->unit.scale_length= 1.0f; // XXX do_versions
+       if(unit->scale_length<0.0001f) unit->scale_length= 1.0f; // XXX do_versions
 
        /* Sanity checks */
        if(precision > PRECISION_FLOAT_MAX)     precision= PRECISION_FLOAT_MAX;
        else if(precision==0)                           precision= 2;
 
-       bUnit_AsString(str, len_max, ui_get_but_scale_unit(but, value), precision, scene->unit.system, unit_type>>16, do_split, pad);
+       bUnit_AsString(str, len_max, ui_get_but_scale_unit(but, value), precision, unit->system, unit_type>>16, do_split, pad);
 }
 
 static float ui_get_but_step_unit(uiBut *but, float step_default)
 {
-       Scene *scene= CTX_data_scene((bContext *)but->block->evil_C);
        int unit_type= uiButGetUnitType(but)>>16;
        float step;
 
-       step = bUnit_ClosestScalar(ui_get_but_scale_unit(but, step_default), scene->unit.system, unit_type);
+       step = bUnit_ClosestScalar(ui_get_but_scale_unit(but, step_default), but->block->unit->system, unit_type);
 
        if(step > 0.0f) { /* -1 is an error value */
                return (float)((double)step/ui_get_but_scale_unit(but, 1.0))*100.0f;
@@ -1522,22 +1588,23 @@ static float ui_get_but_step_unit(uiBut *but, float step_default)
 }
 
 
-void ui_get_but_string(uiBut *but, char *str, int maxlen)
+void ui_get_but_string(uiBut *but, char *str, size_t maxlen)
 {
        if(but->rnaprop && ELEM3(but->type, TEX, IDPOIN, SEARCH_MENU)) {
                PropertyType type;
                char *buf= NULL;
+               int buf_len;
 
                type= RNA_property_type(but->rnaprop);
 
                if(type == PROP_STRING) {
                        /* RNA string */
-                       buf= RNA_property_string_get_alloc(&but->rnapoin, but->rnaprop, str, maxlen);
+                       buf= RNA_property_string_get_alloc(&but->rnapoin, but->rnaprop, str, maxlen, &buf_len);
                }
                else if(type == PROP_POINTER) {
                        /* RNA pointer */
                        PointerRNA ptr= RNA_property_pointer_get(&but->rnapoin, but->rnaprop);
-                       buf= RNA_struct_name_get_alloc(&ptr, str, maxlen);
+                       buf= RNA_struct_name_get_alloc(&ptr, str, maxlen, &buf_len);
                }
 
                if(!buf) {
@@ -1545,7 +1612,7 @@ void ui_get_but_string(uiBut *but, char *str, int maxlen)
                }
                else if(buf && buf != str) {
                        /* string was too long, we have to truncate */
-                       BLI_strncpy(str, buf, maxlen);
+                       memcpy(str, buf, MIN2(maxlen, buf_len+1));
                        MEM_freeN(buf);
                }
        }
@@ -1599,12 +1666,11 @@ static int ui_set_but_string_eval_num_unit(bContext *C, uiBut *but, const char *
 {
        char str_unit_convert[256];
        const int unit_type= uiButGetUnitType(but);
-       Scene *scene= CTX_data_scene((bContext *)but->block->evil_C);
 
        BLI_strncpy(str_unit_convert, str, sizeof(str_unit_convert));
 
        /* ugly, use the draw string to get the value, this could cause problems if it includes some text which resolves to a unit */
-       bUnit_ReplaceString(str_unit_convert, sizeof(str_unit_convert), but->drawstr, ui_get_but_scale_unit(but, 1.0), scene->unit.system, unit_type>>16);
+       bUnit_ReplaceString(str_unit_convert, sizeof(str_unit_convert), but->drawstr, ui_get_but_scale_unit(but, 1.0), but->block->unit->system, unit_type>>16);
 
        return (BPY_button_exec(C, str_unit_convert, value, TRUE) != -1);
 }
@@ -1682,7 +1748,9 @@ int ui_set_but_string(bContext *C, uiBut *but, const char *str)
        }
        else if(but->type == TEX) {
                /* string */
-               BLI_strncpy(but->poin, str, but->hardmax);
+               if(ui_is_but_utf8(but)) BLI_strncpy_utf8(but->poin, str, but->hardmax);
+               else                    BLI_strncpy(but->poin, str, but->hardmax);
+
                return 1;
        }
        else if(but->type == SEARCH_MENU) {
@@ -1694,6 +1762,10 @@ int ui_set_but_string(bContext *C, uiBut *but, const char *str)
                /* driver expression */
                return 1;
        }
+       else if(str[0]=='#') {
+               /* shortcut to create new driver expression (versus immediate Py-execution) */
+               return ui_but_anim_expression_create(but, str+1);
+       }
        else {
                /* number editing */
                double value;
@@ -1758,50 +1830,70 @@ static double soft_range_round_down(double value, double max)
 
 void ui_set_but_soft_range(uiBut *but, double value)
 {
-       PropertyType type;
-       double softmin, softmax /*, step, precision*/;
-       
+       /* ideally we would not limit this but practially, its more then
+        * enough worst case is very long vectors wont use a smart soft-range
+        * which isnt so bad. */
+
        if(but->rnaprop) {
-               type= RNA_property_type(but->rnaprop);
+               const PropertyType type= RNA_property_type(but->rnaprop);
+               double softmin, softmax /*, step, precision*/;
+               double value_min= value;
+               double value_max= value;
 
                /* clamp button range to something reasonable in case
                 * we get -inf/inf from RNA properties */
                if(type == PROP_INT) {
                        int imin, imax, istep;
+                       const int array_len= RNA_property_array_length(&but->rnapoin, but->rnaprop);
 
                        RNA_property_int_ui_range(&but->rnapoin, but->rnaprop, &imin, &imax, &istep);
                        softmin= (imin == INT_MIN)? -1e4: imin;
                        softmax= (imin == INT_MAX)? 1e4: imax;
                        /*step= istep;*/ /*UNUSED*/
                        /*precision= 1;*/ /*UNUSED*/
+
+                       if(array_len >= 2) {
+                               int value_range[2];
+                               RNA_property_int_get_array_range(&but->rnapoin, but->rnaprop, value_range);
+                               value_min= (double)value_range[0];
+                               value_max= (double)value_range[1];
+                       }
                }
                else if(type == PROP_FLOAT) {
                        float fmin, fmax, fstep, fprecision;
+                       const int array_len= RNA_property_array_length(&but->rnapoin, but->rnaprop);
 
                        RNA_property_float_ui_range(&but->rnapoin, but->rnaprop, &fmin, &fmax, &fstep, &fprecision);
                        softmin= (fmin == -FLT_MAX)? (float)-1e4: fmin;
                        softmax= (fmax == FLT_MAX)? (float)1e4: fmax;
                        /*step= fstep;*/ /*UNUSED*/
                        /*precision= fprecision;*/ /*UNUSED*/
+
+                       if(array_len >= 2) {
+                               float value_range[2];
+                               RNA_property_float_get_array_range(&but->rnapoin, but->rnaprop, value_range);
+                               value_min= (double)value_range[0];
+                               value_max= (double)value_range[1];
+                       }
                }
                else
                        return;
 
                /* if the value goes out of the soft/max range, adapt the range */
-               if(value+1e-10 < softmin) {
-                       if(value < 0.0)
-                               softmin= -soft_range_round_up(-value, -softmin);
+               if(value_min+1e-10 < softmin) {
+                       if(value_min < 0.0)
+                               softmin= -soft_range_round_up(-value_min, -softmin);
                        else
-                               softmin= soft_range_round_down(value, softmin);
+                               softmin= soft_range_round_down(value_min, softmin);
 
                        if(softmin < (double)but->hardmin)
                                softmin= (double)but->hardmin;
                }
-               else if(value-1e-10 > softmax) {
-                       if(value < 0.0)
-                               softmax= -soft_range_round_down(-value, -softmax);
+               else if(value_max-1e-10 > softmax) {
+                       if(value_max < 0.0)
+                               softmax= -soft_range_round_down(-value_max, -softmax);
                        else
-                               softmax= soft_range_round_up(value, softmax);
+                               softmax= soft_range_round_up(value_max, softmax);
 
                        if(softmax > (double)but->hardmax)
                                softmax= but->hardmax;
@@ -1843,6 +1935,8 @@ static void ui_free_but(const bContext *C, uiBut *but)
        if(but->str && but->str != but->strdata) MEM_freeN(but->str);
        ui_free_link(but->link);
 
+       if((but->type == BUT_IMAGE) && but->poin) IMB_freeImBuf((struct ImBuf *)but->poin);
+
        MEM_freeN(but);
 }
 
@@ -1856,6 +1950,9 @@ void uiFreeBlock(const bContext *C, uiBlock *block)
                ui_free_but(C, but);
        }
 
+       if(block->unit)
+               MEM_freeN(block->unit);
+
        if(block->func_argN)
                MEM_freeN(block->func_argN);
 
@@ -1931,7 +2028,15 @@ uiBlock *uiBeginBlock(const bContext *C, ARegion *region, const char *name, shor
        block->active= 1;
        block->dt= dt;
        block->evil_C= (void*)C; // XXX
-       if (scn) block->color_profile= (scn->r.color_mgt_flag & R_COLOR_MANAGEMENT);
+
+       if (scn) {
+               block->color_profile= (scn->r.color_mgt_flag & R_COLOR_MANAGEMENT);
+
+               /* copy to avoid crash when scene gets deleted with ui still open */
+               block->unit= MEM_mallocN(sizeof(scn->unit), "UI UnitSettings");
+               memcpy(block->unit, &scn->unit, sizeof(scn->unit));
+       }
+
        BLI_strncpy(block->name, name, sizeof(block->name));
 
        if(region)
@@ -1954,7 +2059,7 @@ uiBlock *uiBeginBlock(const bContext *C, ARegion *region, const char *name, shor
                wm_subwindow_getsize(window, window->screen->mainwin, &getsizex, &getsizey);
 
                block->aspect= 2.0/fabs(getsizex*block->winmat[0][0]);
-               block->auto_open= 2;
+               block->auto_open= TRUE;
                block->flag |= UI_BLOCK_LOOP; /* tag as menu */
        }
 
@@ -1974,17 +2079,16 @@ void uiBlockSetEmboss(uiBlock *block, char dt)
 void ui_check_but(uiBut *but)
 {
        /* if something changed in the button */
-       double value;
+       double value= UI_BUT_VALUE_UNSET;
 //     float okwidth; // UNUSED
-//     int transopts= ui_translate_buttons();
        
-       ui_is_but_sel(but);
+       ui_is_but_sel(but, &value);
        
-//     if(but->type==TEX || but->type==IDPOIN) transopts= 0;
-
        /* only update soft range while not editing */
-       if(but->rnaprop && !(but->editval || but->editstr || but->editvec))
-               ui_set_but_soft_range(but, ui_get_but_val(but));
+       if(but->rnaprop && !(but->editval || but->editstr || but->editvec)) {
+               UI_GET_BUT_VALUE_INIT(but, value)
+               ui_set_but_soft_range(but, value);
+       }
 
        /* test for min and max, icon sliders, etc */
        switch( but->type ) {
@@ -1993,17 +2097,20 @@ void ui_check_but(uiBut *but)
                case SCROLL:
                case NUMSLI:
                case HSVSLI:
-                       value= ui_get_but_val(but);
+                       UI_GET_BUT_VALUE_INIT(but, value)
                        if(value < (double)but->hardmin) ui_set_but_val(but, but->hardmin);
                        else if(value > (double)but->hardmax) ui_set_but_val(but, but->hardmax);
                        break;
                        
                case NUMABS:
-                       value= fabs( ui_get_but_val(but) );
-                       if(value < (double)but->hardmin) ui_set_but_val(but, but->hardmin);
-                       else if(value > (double)but->hardmax) ui_set_but_val(but, but->hardmax);
+               {
+                       double value_abs;
+                       UI_GET_BUT_VALUE_INIT(but, value)
+                       value_abs= fabs(value);
+                       if(value_abs < (double)but->hardmin) ui_set_but_val(but, but->hardmin);
+                       else if(value_abs > (double)but->hardmax) ui_set_but_val(but, but->hardmax);
                        break;
-                       
+               }
                case ICONTOG: 
                case ICONTOGN:
                        if(!but->rnaprop || (RNA_property_flag(but->rnaprop) & PROP_ICONS_CONSECUTIVE)) {
@@ -2014,14 +2121,14 @@ void ui_check_but(uiBut *but)
                        
                case ICONROW:
                        if(!but->rnaprop || (RNA_property_flag(but->rnaprop) & PROP_ICONS_CONSECUTIVE)) {
-                               value= ui_get_but_val(but);
+                               UI_GET_BUT_VALUE_INIT(but, value)
                                but->iconadd= (int)value- (int)(but->hardmin);
                        }
                        break;
                        
                case ICONTEXTROW:
                        if(!but->rnaprop || (RNA_property_flag(but->rnaprop) & PROP_ICONS_CONSECUTIVE)) {
-                               value= ui_get_but_val(but);
+                               UI_GET_BUT_VALUE_INIT(but, value)
                                but->iconadd= (int)value- (int)(but->hardmin);
                        }
                        break;
@@ -2038,7 +2145,7 @@ void ui_check_but(uiBut *but)
        case ICONTEXTROW:
                
                if(but->x2 - but->x1 > 24) {
-                       value= ui_get_but_val(but);
+                       UI_GET_BUT_VALUE_INIT(but, value)
                        ui_set_name_menu(but, (int)value);
                }
                break;
@@ -2048,11 +2155,11 @@ void ui_check_but(uiBut *but)
        case HSVSLI:
        case NUMABS:
 
-               value= ui_get_but_val(but);
+               UI_GET_BUT_VALUE_INIT(but, value)
 
                if(ui_is_but_float(but)) {
-                       if(value == (double) FLT_MAX) sprintf(but->drawstr, "%sinf", but->str);
-                       else if(value == (double) -FLT_MAX) sprintf(but->drawstr, "%s-inf", but->str);
+                       if(value == (double) FLT_MAX) BLI_snprintf(but->drawstr, sizeof(but->drawstr), "%sinf", but->str);
+                       else if(value == (double) -FLT_MAX) BLI_snprintf(but->drawstr, sizeof(but->drawstr), "%s-inf", but->str);
                        /* support length type buttons */
                        else if(ui_is_but_unit(but)) {
                                char new_str[sizeof(but->drawstr)];
@@ -2065,7 +2172,7 @@ void ui_check_but(uiBut *but)
                        }
                }
                else {
-                       sprintf(but->drawstr, "%s%d", but->str, (int)value);
+                       BLI_snprintf(but->drawstr, sizeof(but->drawstr), "%s%d", but->str, (int)value);
                }
                        
                if(but->rnaprop) {
@@ -2079,12 +2186,12 @@ void ui_check_but(uiBut *but)
        case LABEL:
                if(ui_is_but_float(but)) {
                        int prec;
-                       value= ui_get_but_val(but);
+                       UI_GET_BUT_VALUE_INIT(but, value)
                        prec= ui_but_float_precision(but, value);
                        BLI_snprintf(but->drawstr, sizeof(but->drawstr), "%s%.*f", but->str, prec, value);
                }
                else {
-                       strncpy(but->drawstr, but->str, UI_MAX_DRAW_STR);
+                       BLI_strncpy(but->drawstr, but->str, UI_MAX_DRAW_STR);
                }
                
                break;
@@ -2102,11 +2209,13 @@ void ui_check_but(uiBut *but)
                break;
        
        case KEYEVT:
-               strncpy(but->drawstr, but->str, UI_MAX_DRAW_STR);
+               BLI_strncpy(but->drawstr, but->str, UI_MAX_DRAW_STR);
                if (but->flag & UI_SELECT) {
                        strcat(but->drawstr, "Press a key");
-               } else {
-                       strcat(but->drawstr, WM_key_event_string((short) ui_get_but_val(but)));
+               }
+               else {
+                       UI_GET_BUT_VALUE_INIT(but, value)
+                       strcat(but->drawstr, WM_key_event_string((short)value));
                }
                break;
                
@@ -2132,15 +2241,15 @@ void ui_check_but(uiBut *but)
                                strcat(but->drawstr, "Press a key  ");
                }
                else
-                       strncpy(but->drawstr, but->str, UI_MAX_DRAW_STR);
+                       BLI_strncpy(but->drawstr, but->str, UI_MAX_DRAW_STR);
 
                break;
                
        case BUT_TOGDUAL:
                /* trying to get the dual-icon to left of text... not very nice */
                if(but->str[0]) {
-                       strncpy(but->drawstr, "  ", UI_MAX_DRAW_STR);
-                       strncpy(but->drawstr+2, but->str, UI_MAX_DRAW_STR-2);
+                       BLI_strncpy(but->drawstr, "  ", UI_MAX_DRAW_STR);
+                       BLI_strncpy(but->drawstr+2, but->str, UI_MAX_DRAW_STR-2);
                }
                break;
 
@@ -2148,13 +2257,13 @@ void ui_check_but(uiBut *but)
        case HSVCIRCLE:
                break;
        default:
-               strncpy(but->drawstr, but->str, UI_MAX_DRAW_STR);
+               BLI_strncpy(but->drawstr, but->str, UI_MAX_DRAW_STR);
                
        }
 
        /* if we are doing text editing, this will override the drawstr */
        if(but->editstr)
-               strncpy(but->drawstr, but->editstr, UI_MAX_DRAW_STR);
+               BLI_strncpy(but->drawstr, but->editstr, UI_MAX_DRAW_STR);
        
        /* text clipping moved to widget drawing code itself */
 }
@@ -2192,7 +2301,7 @@ int ui_but_can_align(uiBut *but)
        return !ELEM3(but->type, LABEL, OPTION, OPTIONN);
 }
 
-static void ui_block_do_align_but(uiBut *first, int nr)
+static void ui_block_do_align_but(uiBut *first, short nr)
 {
        uiBut *prev, *but=NULL, *next;
        int flag= 0, cols=0, rows=0;
@@ -2329,7 +2438,7 @@ static void ui_block_do_align_but(uiBut *first, int nr)
 void ui_block_do_align(uiBlock *block)
 {
        uiBut *but;
-       int nr;
+       short nr;
 
        /* align buttons with same align nr */
        for(but=block->buttons.first; but;) {
@@ -2373,7 +2482,7 @@ static uiBut *ui_def_but(uiBlock *block, int type, int retval, const char *str,
        but->pointype= type & BUTPOIN;
        but->bit= type & BIT;
        but->bitnr= type & 31;
-       but->icon = 0;
+       but->icon = ICON_NONE;
        but->iconadd=0;
 
        but->retval= retval;
@@ -2420,7 +2529,7 @@ static uiBut *ui_def_but(uiBlock *block, int type, int retval, const char *str,
        but->pos= -1;   /* cursor invisible */
 
        if(ELEM4(but->type, NUM, NUMABS, NUMSLI, HSVSLI)) {     /* add a space to name */
-               slen= strlen(but->str);
+               /* slen remains unchanged from previous assignment, ensure this stays true */
                if(slen>0 && slen<UI_MAX_NAME_STR-2) {
                        if(but->str[slen-1]!=' ') {
                                but->str[slen]= ' ';
@@ -2453,141 +2562,147 @@ static uiBut *ui_def_but(uiBlock *block, int type, int retval, const char *str,
        if(block->curlayout)
                ui_layout_add_but(block->curlayout, but);
 
+       /* if the 'UI_OT_editsource' is running, extract the source info from the button  */
+       if (UI_editsource_enable_check()) {
+               UI_editsource_active_but_test(but);
+       }
+
        return but;
 }
 
-static uiBut *ui_def_but_rna(uiBlock *block, int type, int retval, const char *str, int x1, int y1, short x2, short y2, PointerRNA *ptr, const char *propname, int index, float min, float max, float a1, float a2,  const char *tip)
+/* ui_def_but_rna_propname and ui_def_but_rna
+ * both take the same args except for propname vs prop, this is done so we can
+ * avoid an extra lookup on 'prop' when its already available.
+ *
+ * When this kind of change won't disrupt branches, best look into making more
+ * of our UI functions take prop rather then propname.
+ */
+
+#define UI_DEF_BUT_RNA_DISABLE(but) \
+       but->flag |= UI_BUT_DISABLED; \
+       but->lock = 1; \
+       but->lockstr = ""
+
+
+static uiBut *ui_def_but_rna(uiBlock *block, int type, int retval, const char *str, int x1, int y1, short x2, short y2, PointerRNA *ptr, PropertyRNA *prop, int index, float min, float max, float a1, float a2,  const char *tip)
 {
+       const PropertyType proptype= RNA_property_type(prop);
        uiBut *but;
-       PropertyRNA *prop;
-       PropertyType proptype;
        int freestr= 0, icon= 0;
 
-       prop= RNA_struct_find_property(ptr, propname);
-
-       if(prop) {
-               proptype= RNA_property_type(prop);
-
-               /* use rna values if parameters are not specified */
-               if(!str) {
-                       if(type == MENU && proptype == PROP_ENUM) {
-                               EnumPropertyItem *item;
-                               DynStr *dynstr;
-                               int i, totitem, value, free;
-
-                               RNA_property_enum_items(block->evil_C, ptr, prop, &item, &totitem, &free);
-                               value= RNA_property_enum_get(ptr, prop);
-
-                               dynstr= BLI_dynstr_new();
-                               BLI_dynstr_appendf(dynstr, "%s%%t", RNA_property_ui_name(prop));
-                               for(i=0; i<totitem; i++) {
-                                       if(!item[i].identifier[0]) {
-                                               if(item[i].name)
-                                                       BLI_dynstr_appendf(dynstr, "|%s%%l", item[i].name);
-                                               else
-                                                       BLI_dynstr_append(dynstr, "|%l");
-                                       }
-                                       else if(item[i].icon)
-                                               BLI_dynstr_appendf(dynstr, "|%s %%i%d %%x%d", item[i].name, item[i].icon, item[i].value);
+       /* use rna values if parameters are not specified */
+       if(!str) {
+               if(type == MENU && proptype == PROP_ENUM) {
+                       EnumPropertyItem *item;
+                       DynStr *dynstr;
+                       int i, totitem, value, free;
+
+                       RNA_property_enum_items_gettexted(block->evil_C, ptr, prop, &item, &totitem, &free);
+                       value= RNA_property_enum_get(ptr, prop);
+
+                       dynstr= BLI_dynstr_new();
+                       BLI_dynstr_appendf(dynstr, "%s%%t", RNA_property_ui_name(prop));
+                       for(i=0; i<totitem; i++) {
+                               if(!item[i].identifier[0]) {
+                                       if(item[i].name)
+                                               BLI_dynstr_appendf(dynstr, "|%s%%l", item[i].name);
                                        else
-                                               BLI_dynstr_appendf(dynstr, "|%s %%x%d", item[i].name, item[i].value);
+                                               BLI_dynstr_append(dynstr, "|%l");
+                               }
+                               else if(item[i].icon)
+                                       BLI_dynstr_appendf(dynstr, "|%s %%i%d %%x%d", item[i].name, item[i].icon, item[i].value);
+                               else
+                                       BLI_dynstr_appendf(dynstr, "|%s %%x%d", item[i].name, item[i].value);
 
-                                       if(value == item[i].value) {
-                                               icon= item[i].icon;
-                                               if(!tip)
-                                                       tip= item[i].description;
-                                       }
+                               if(value == item[i].value) {
+                                       icon= item[i].icon;
+                                       if(!tip)
+                                               tip= item[i].description;
                                }
-                               str= BLI_dynstr_get_cstring(dynstr);
-                               BLI_dynstr_free(dynstr);
+                       }
+                       str= BLI_dynstr_get_cstring(dynstr);
+                       BLI_dynstr_free(dynstr);
 
-                               if(free)
-                                       MEM_freeN(item);
+                       if(free)
+                               MEM_freeN(item);
 
-                               freestr= 1;
-                       }
-                       else if(ELEM(type, ROW, LISTROW) && proptype == PROP_ENUM) {
-                               EnumPropertyItem *item;
-                               int i, totitem, free;
-
-                               RNA_property_enum_items(block->evil_C, ptr, prop, &item, &totitem, &free);
-                               for(i=0; i<totitem; i++) {
-                                       if(item[i].identifier[0] && item[i].value == (int)max) {
-                                               str= item[i].name;
-                                               icon= item[i].icon;
-                                       }
-                               }
+                       freestr= 1;
+               }
+               else if(ELEM(type, ROW, LISTROW) && proptype == PROP_ENUM) {
+                       EnumPropertyItem *item;
+                       int i, totitem, free;
 
-                               if(!str)
-                                       str= RNA_property_ui_name(prop);
-                               if(free)
-                                       MEM_freeN(item);
+                       RNA_property_enum_items_gettexted(block->evil_C, ptr, prop, &item, &totitem, &free);
+                       for(i=0; i<totitem; i++) {
+                               if(item[i].identifier[0] && item[i].value == (int)max) {
+                                       str= item[i].name;
+                                       icon= item[i].icon;
+                               }
                        }
-                       else {
+
+                       if(!str)
                                str= RNA_property_ui_name(prop);
-                               icon= RNA_property_ui_icon(prop);
-                       }
+                       if(free)
+                               MEM_freeN(item);
                }
-               
-               if(!tip && proptype != PROP_ENUM)
-                       tip= RNA_property_ui_description(prop);
+               else {
+                       str= RNA_property_ui_name(prop);
+                       icon= RNA_property_ui_icon(prop);
+               }
+       }
 
-               if(min == max || a1 == -1 || a2 == -1) {
-                       if(proptype == PROP_INT) {
-                               int hardmin, hardmax, softmin, softmax, step;
+       if(!tip && proptype != PROP_ENUM)
+               tip= RNA_property_ui_description(prop);
 
-                               RNA_property_int_range(ptr, prop, &hardmin, &hardmax);
-                               RNA_property_int_ui_range(ptr, prop, &softmin, &softmax, &step);
+       if(min == max || a1 == -1 || a2 == -1) {
+               if(proptype == PROP_INT) {
+                       int hardmin, hardmax, softmin, softmax, step;
 
-                               if(!ELEM(type, ROW, LISTROW) && min == max) {
-                                       min= hardmin;
-                                       max= hardmax;
-                               }
-                               if(a1 == -1)
-                                       a1= step;
-                               if(a2 == -1)
-                                       a2= 0;
+                       RNA_property_int_range(ptr, prop, &hardmin, &hardmax);
+                       RNA_property_int_ui_range(ptr, prop, &softmin, &softmax, &step);
+
+                       if(!ELEM(type, ROW, LISTROW) && min == max) {
+                               min= hardmin;
+                               max= hardmax;
                        }
-                       else if(proptype == PROP_FLOAT) {
-                               float hardmin, hardmax, softmin, softmax, step, precision;
+                       if(a1 == -1)
+                               a1= step;
+                       if(a2 == -1)
+                               a2= 0;
+               }
+               else if(proptype == PROP_FLOAT) {
+                       float hardmin, hardmax, softmin, softmax, step, precision;
 
-                               RNA_property_float_range(ptr, prop, &hardmin, &hardmax);
-                               RNA_property_float_ui_range(ptr, prop, &softmin, &softmax, &step, &precision);
+                       RNA_property_float_range(ptr, prop, &hardmin, &hardmax);
+                       RNA_property_float_ui_range(ptr, prop, &softmin, &softmax, &step, &precision);
 
-                               if(!ELEM(type, ROW, LISTROW) && min == max) {
-                                       min= hardmin;
-                                       max= hardmax;
-                               }
-                               if(a1 == -1)
-                                       a1= step;
-                               if(a2 == -1)
-                                       a2= precision;
-                       }
-                       else if(proptype == PROP_STRING) {
-                               min= 0;
-                               max= RNA_property_string_maxlength(prop);
-                               if(max == 0) /* interface code should ideally support unlimited length */
-                                       max= UI_MAX_DRAW_STR; 
+                       if(!ELEM(type, ROW, LISTROW) && min == max) {
+                               min= hardmin;
+                               max= hardmax;
                        }
+                       if(a1 == -1)
+                               a1= step;
+                       if(a2 == -1)
+                               a2= precision;
+               }
+               else if(proptype == PROP_STRING) {
+                       min= 0;
+                       max= RNA_property_string_maxlength(prop);
+                       if(max == 0) /* interface code should ideally support unlimited length */
+                               max= UI_MAX_DRAW_STR;
                }
-       }
-       else {
-               RNA_warning("ui_def_but_rna: property not found: %s.%s\n", RNA_struct_identifier(ptr->type), propname);
-               str= propname;
        }
 
        /* now create button */
        but= ui_def_but(block, type, retval, str, x1, y1, x2, y2, NULL, min, max, a1, a2, tip);
 
-       if(prop) {
-               but->rnapoin= *ptr;
-               but->rnaprop= prop;
+       but->rnapoin= *ptr;
+       but->rnaprop= prop;
 
-               if(RNA_property_array_length(&but->rnapoin, but->rnaprop))
-                       but->rnaindex= index;
-               else
-                       but->rnaindex= 0;
-       }
+       if(RNA_property_array_length(&but->rnapoin, but->rnaprop))
+               but->rnaindex= index;
+       else
+               but->rnaindex= 0;
 
        if(icon) {
                but->icon= (BIFIconID)icon;
@@ -2595,15 +2710,18 @@ static uiBut *ui_def_but_rna(uiBlock *block, int type, int retval, const char *s
                but->flag|= UI_ICON_LEFT;
        }
        
-       if (!prop || !RNA_property_editable(&but->rnapoin, prop)) {
-               but->flag |= UI_BUT_DISABLED;
-               but->lock = 1;
-               but->lockstr = "";
+       if (!RNA_property_editable(&but->rnapoin, prop)) {
+               UI_DEF_BUT_RNA_DISABLE(but);
+       }
+
+       if (but->flag & UI_BUT_UNDO && (ui_but_is_rna_undo(but) == FALSE)) {
+               but->flag &= ~UI_BUT_UNDO;
        }
 
        /* If this button uses units, calculate the step from this */
-       if(ui_is_but_unit(but))
+       if((proptype == PROP_FLOAT) && ui_is_but_unit(but)) {
                but->a1= ui_get_but_step_unit(but, but->a1);
+       }
 
        if(freestr)
                MEM_freeN((void *)str);
@@ -2611,6 +2729,23 @@ static uiBut *ui_def_but_rna(uiBlock *block, int type, int retval, const char *s
        return but;
 }
 
+static uiBut *ui_def_but_rna_propname(uiBlock *block, int type, int retval, const char *str, int x1, int y1, short x2, short y2, PointerRNA *ptr, const char *propname, int index, float min, float max, float a1, float a2,  const char *tip)
+{
+       PropertyRNA *prop= RNA_struct_find_property(ptr, propname);
+       uiBut *but;
+
+       if(prop) {
+               but= ui_def_but_rna(block, type, retval, str, x1, y1, x2, y2, ptr, prop, index, min, max, a1, a2,  tip);
+       }
+       else {
+               but= ui_def_but(block, type, retval, propname, x1, y1, x2, y2, NULL, min, max, a1, a2, tip);
+
+               UI_DEF_BUT_RNA_DISABLE(but);
+       }
+
+       return but;
+}
+
 static uiBut *ui_def_but_operator(uiBlock *block, int type, const char *opname, int opcontext, const char *str, int x1, int y1, short x2, short y2, const char *tip)
 {
        uiBut *but;
@@ -2625,11 +2760,14 @@ static uiBut *ui_def_but_operator(uiBlock *block, int type, const char *opname,
        
        if ((!tip || tip[0]=='\0') && ot && ot->description) {
                tip= ot->description;
+
+               tip = TIP_(tip);
        }
 
        but= ui_def_but(block, type, -1, str, x1, y1, x2, y2, NULL, 0, 0, 0, 0, tip);
        but->optype= ot;
        but->opcontext= opcontext;
+       but->flag &= ~UI_BUT_UNDO; /* no need for ui_but_is_undo(), we never need undo here */
 
        if(!ot) {
                but->flag |= UI_BUT_DISABLED;
@@ -2659,6 +2797,7 @@ static uiBut *ui_def_but_operator_text(uiBlock *block, int type, const char *opn
        but= ui_def_but(block, type, -1, str, x1, y1, x2, y2, poin, min, max, a1, a2, tip);
        but->optype= ot;
        but->opcontext= opcontext;
+       but->flag &= ~UI_BUT_UNDO; /* no need for ui_but_is_undo(), we never need undo here */
 
        if(!ot) {
                but->flag |= UI_BUT_DISABLED;
@@ -2682,7 +2821,8 @@ uiBut *uiDefBut(uiBlock *block, int type, int retval, const char *str, int x1, i
         * otherwise return -1. 
         * (1<<findBitIndex(x))==x for powers of two.
         */
-static int findBitIndex(unsigned int x) {
+static int findBitIndex(unsigned int x)
+{
        if (!x || (x&(x-1))!=0) {       /* x&(x-1) strips lowest bit */
                return -1;
        } else {
@@ -2700,12 +2840,12 @@ static int findBitIndex(unsigned int x) {
 
 /* autocomplete helper functions */
 struct AutoComplete {
-       int maxlen;
+       size_t maxlen;
        char *truncate;
        const char *startname;
 };
 
-AutoComplete *autocomplete_begin(const char *startname, int maxlen)
+AutoComplete *autocomplete_begin(const char *startname, size_t maxlen)
 {
        AutoComplete *autocpl;
        
@@ -2778,6 +2918,16 @@ static void autocomplete_id(bContext *C, char *str, void *arg_v)
        }
 }
 
+static void ui_check_but_and_iconize(uiBut *but, int icon)
+{
+       if(icon) {
+               but->icon= (BIFIconID) icon;
+               but->flag|= UI_HAS_ICON;
+       }
+
+       ui_check_but(but);
+}
+
 static uiBut *uiDefButBit(uiBlock *block, int type, int bit, int retval, const char *str, int x1, int y1, short x2, short y2, void *poin, float min, float max, float a1, float a2,  const char *tip)
 {
        int bitIdx= findBitIndex(bit);
@@ -2822,31 +2972,29 @@ uiBut *uiDefButBitC(uiBlock *block, int type, int bit, int retval, const char *s
 uiBut *uiDefButR(uiBlock *block, int type, int retval, const char *str, int x1, int y1, short x2, short y2, PointerRNA *ptr, const char *propname, int index, float min, float max, float a1, float a2,  const char *tip)
 {
        uiBut *but;
-
-       but= ui_def_but_rna(block, type, retval, str, x1, y1, x2, y2, ptr, propname, index, min, max, a1, a2, tip);
-       if(but)
-               ui_check_but(but);
-
+       but= ui_def_but_rna_propname(block, type, retval, str, x1, y1, x2, y2, ptr, propname, index, min, max, a1, a2, tip);
+       ui_check_but(but);
+       return but;
+}
+uiBut *uiDefButR_prop(uiBlock *block, int type, int retval, const char *str, int x1, int y1, short x2, short y2, PointerRNA *ptr, PropertyRNA *prop, int index, float min, float max, float a1, float a2,  const char *tip)
+{
+       uiBut *but;
+       but= ui_def_but_rna(block, type, retval, str, x1, y1, x2, y2, ptr, prop, index, min, max, a1, a2, tip);
+       ui_check_but(but);
        return but;
 }
 uiBut *uiDefButO(uiBlock *block, int type, const char *opname, int opcontext, const char *str, int x1, int y1, short x2, short y2, const char *tip)
 {
        uiBut *but;
-
        but= ui_def_but_operator(block, type, opname, opcontext, str, x1, y1, x2, y2, tip);
-       if(but)
-               ui_check_but(but);
-
+       ui_check_but(but);
        return but;
 }
 
 uiBut *uiDefButTextO(uiBlock *block, int type, const char *opname, int opcontext, const char *str, int x1, int y1, short x2, short y2, void *poin, float min, float max, float a1, float a2,  const char *tip)
 {
        uiBut *but= ui_def_but_operator_text(block, type, opname, opcontext, str, x1, y1, x2, y2, poin, min, max, a1, a2, tip);
-
-       if(but)
-               ui_check_but(but);
-       
+       ui_check_but(but);
        return but;
 }
 
@@ -2854,12 +3002,7 @@ uiBut *uiDefButTextO(uiBlock *block, int type, const char *opname, int opcontext
 uiBut *uiDefIconBut(uiBlock *block, int type, int retval, int icon, int x1, int y1, short x2, short y2, void *poin, float min, float max, float a1, float a2,  const char *tip)
 {
        uiBut *but= ui_def_but(block, type, retval, "", x1, y1, x2, y2, poin, min, max, a1, a2, tip);
-       
-       but->icon= (BIFIconID) icon;
-       but->flag|= UI_HAS_ICON;
-
-       ui_check_but(but);
-       
+       ui_check_but_and_iconize(but, icon);
        return but;
 }
 static uiBut *uiDefIconButBit(uiBlock *block, int type, int bit, int retval, int icon, int x1, int y1, short x2, short y2, void *poin, float min, float max, float a1, float a2, const char *tip)
@@ -2907,29 +3050,22 @@ uiBut *uiDefIconButBitC(uiBlock *block, int type, int bit, int retval, int icon,
 uiBut *uiDefIconButR(uiBlock *block, int type, int retval, int icon, int x1, int y1, short x2, short y2, PointerRNA *ptr, const char *propname, int index, float min, float max, float a1, float a2,  const char *tip)
 {
        uiBut *but;
-
-       but= ui_def_but_rna(block, type, retval, "", x1, y1, x2, y2, ptr, propname, index, min, max, a1, a2, tip);
-       if(but) {
-               if(icon) {
-                       but->icon= (BIFIconID) icon;
-                       but->flag|= UI_HAS_ICON;
-               }
-               ui_check_but(but);
-       }
-
+       but= ui_def_but_rna_propname(block, type, retval, "", x1, y1, x2, y2, ptr, propname, index, min, max, a1, a2, tip);
+       ui_check_but_and_iconize(but, icon);
+       return but;
+}
+uiBut *uiDefIconButR_prop(uiBlock *block, int type, int retval, int icon, int x1, int y1, short x2, short y2, PointerRNA *ptr, PropertyRNA *prop, int index, float min, float max, float a1, float a2,  const char *tip)
+{
+       uiBut *but;
+       but= ui_def_but_rna(block, type, retval, "", x1, y1, x2, y2, ptr, prop, index, min, max, a1, a2, tip);
+       ui_check_but_and_iconize(but, icon);
        return but;
 }
 uiBut *uiDefIconButO(uiBlock *block, int type, const char *opname, int opcontext, int icon, int x1, int y1, short x2, short y2, const char *tip)
 {
        uiBut *but;
-
        but= ui_def_but_operator(block, type, opname, opcontext, "", x1, y1, x2, y2, tip);
-       if(but) {
-               but->icon= (BIFIconID) icon;
-               but->flag|= UI_HAS_ICON;
-               ui_check_but(but);
-       }
-
+       ui_check_but_and_iconize(but, icon);
        return but;
 }
 
@@ -2937,14 +3073,8 @@ uiBut *uiDefIconButO(uiBlock *block, int type, const char *opname, int opcontext
 uiBut *uiDefIconTextBut(uiBlock *block, int type, int retval, int icon, const char *str, int x1, int y1, short x2, short y2, void *poin, float min, float max, float a1, float a2,  const char *tip)
 {
        uiBut *but= ui_def_but(block, type, retval, str, x1, y1, x2, y2, poin, min, max, a1, a2, tip);
-
-       but->icon= (BIFIconID) icon;
-       but->flag|= UI_HAS_ICON;
-
+       ui_check_but_and_iconize(but, icon);
        but->flag|= UI_ICON_LEFT;
-
-       ui_check_but(but);
-
        return but;
 }
 static uiBut *uiDefIconTextButBit(uiBlock *block, int type, int bit, int retval, int icon, const char *str, int x1, int y1, short x2, short y2, void *poin, float min, float max, float a1, float a2,  const char *tip)
@@ -2992,31 +3122,25 @@ uiBut *uiDefIconTextButBitC(uiBlock *block, int type, int bit, int retval, int i
 uiBut *uiDefIconTextButR(uiBlock *block, int type, int retval, int icon, const char *str, int x1, int y1, short x2, short y2, PointerRNA *ptr, const char *propname, int index, float min, float max, float a1, float a2,  const char *tip)
 {
        uiBut *but;
-
-       but= ui_def_but_rna(block, type, retval, str, x1, y1, x2, y2, ptr, propname, index, min, max, a1, a2, tip);
-       if(but) {
-               if(icon) {
-                       but->icon= (BIFIconID) icon;
-                       but->flag|= UI_HAS_ICON;
-               }
-               but->flag|= UI_ICON_LEFT;
-               ui_check_but(but);
-       }
-
+       but= ui_def_but_rna_propname(block, type, retval, str, x1, y1, x2, y2, ptr, propname, index, min, max, a1, a2, tip);
+       ui_check_but_and_iconize(but, icon);
+       but->flag|= UI_ICON_LEFT;
+       return but;
+}
+uiBut *uiDefIconTextButR_prop(uiBlock *block, int type, int retval, int icon, const char *str, int x1, int y1, short x2, short y2, PointerRNA *ptr, PropertyRNA *prop, int index, float min, float max, float a1, float a2,  const char *tip)
+{
+       uiBut *but;
+       but= ui_def_but_rna(block, type, retval, str, x1, y1, x2, y2, ptr, prop, index, min, max, a1, a2, tip);
+       ui_check_but_and_iconize(but, icon);
+       but->flag|= UI_ICON_LEFT;
        return but;
 }
 uiBut *uiDefIconTextButO(uiBlock *block, int type, const char *opname, int opcontext, int icon, const char *str, int x1, int y1, short x2, short y2, const char *tip)
 {
        uiBut *but;
-
        but= ui_def_but_operator(block, type, opname, opcontext, str, x1, y1, x2, y2, tip);
-       if(but) {
-               but->icon= (BIFIconID) icon;
-               but->flag|= UI_HAS_ICON;
-               but->flag|= UI_ICON_LEFT;
-               ui_check_but(but);
-       }
-
+       ui_check_but_and_iconize(but, icon);
+       but->flag|= UI_ICON_LEFT;
        return but;
 }
 
@@ -3178,11 +3302,17 @@ void uiButSetUnitType(uiBut *but, const int unit_type)
 
 int uiButGetUnitType(uiBut *but)
 {
-       if(but->rnaprop) {
-               return RNA_SUBTYPE_UNIT(RNA_property_subtype(but->rnaprop));
+       int ownUnit = (int)but->unit_type;
+       
+       /* own unit define always takes precidence over RNA provided, allowing for overriding 
+        * default value provided in RNA in a few special cases (i.e. Active Keyframe in Graph Edit)
+        */
+       // XXX: this doesn't allow clearing unit completely, though the same could be said for icons
+       if ((ownUnit != 0) || (but->rnaprop == NULL)) {
+               return ownUnit << 16;
        }
        else {
-               return ((int)but->unit_type)<<16;
+               return RNA_SUBTYPE_UNIT(RNA_property_subtype(but->rnaprop));
        }
 }
 
@@ -3448,6 +3578,11 @@ void UI_init_userdef(void)
        uiStyleInit();
 }
 
+void UI_reinit_font()
+{
+       uiStyleInit();
+}
+
 void UI_exit(void)
 {
        ui_resources_free();