diff options
author | Campbell Barton <ideasman42@gmail.com> | 2009-08-13 21:05:27 +0400 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2009-08-13 21:05:27 +0400 |
commit | 52a6a07d67f48c6c3465cbaf156bf8057755e1bc (patch) | |
tree | e10f280438fc1d2f14765bd918e54d3110d08ad8 /source | |
parent | e8d9e0823ee73e3c3fdd596fd3945abec40d21c1 (diff) |
added string max length option for unit functions bUnit_AsString and bUnit_ReplaceString
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/blenkernel/BKE_unit.h | 4 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/unit.c | 189 | ||||
-rw-r--r-- | source/blender/editors/interface/interface.c | 29 | ||||
-rw-r--r-- | source/blender/editors/transform/transform.c | 4 |
4 files changed, 141 insertions, 85 deletions
diff --git a/source/blender/blenkernel/BKE_unit.h b/source/blender/blenkernel/BKE_unit.h index df299718673..54d5bba057a 100644 --- a/source/blender/blenkernel/BKE_unit.h +++ b/source/blender/blenkernel/BKE_unit.h @@ -31,10 +31,10 @@ extern "C" { /* in all cases the value is assumed to be scaled by the user preference */ /* humanly readable representation of a value in units (used for button drawing) */ -void bUnit_AsString(char *str, double value, int prec, int system, int type, int split, int pad); +void bUnit_AsString(char *str, int len_max, double value, int prec, int system, int type, int split, int pad); /* replace units with values, used before python button evaluation */ -int bUnit_ReplaceString(char *str, char *str_orig, char *str_prev, double scale_pref, int system, int type); +int bUnit_ReplaceString(char *str, int len_max, char *str_prev, double scale_pref, int system, int type); /* the size of the unit used for this value (used for calculating the ckickstep) */ double bUnit_ClosestScalar(double value, int system, int type); diff --git a/source/blender/blenkernel/intern/unit.c b/source/blender/blenkernel/intern/unit.c index dfec54eb5ea..fde0ac5391d 100644 --- a/source/blender/blenkernel/intern/unit.c +++ b/source/blender/blenkernel/intern/unit.c @@ -27,6 +27,8 @@ #include <string.h> #include <math.h> +#define TEMP_STR_SIZE 256 + /* define a single unit */ typedef struct bUnitDef { char *name; @@ -89,7 +91,7 @@ static struct bUnitDef buImperialLenDef[] = { {"thou", "Thous", "mil", NULL,0.0000254, 0.0, B_UNIT_DEF_NONE}, {NULL, NULL, NULL, NULL, 0.0, 0.0} }; -static struct bUnitCollection buImperialLenCollecton = {buImperialLenDef, 3, 0, sizeof(buImperialLenDef)/sizeof(bUnitDef)}; +static struct bUnitCollection buImperialLenCollecton = {buImperialLenDef, 4, 0, sizeof(buImperialLenDef)/sizeof(bUnitDef)}; /* Time */ @@ -156,7 +158,7 @@ static void unit_dual_convert(double value, bUnitCollection *usys, *unit_b= unit_best_fit(*value_b, usys, *unit_a, 1); } -static int unit_as_string(char *str, double value, int prec, bUnitCollection *usys, +static int unit_as_string(char *str, int len_max, double value, int prec, bUnitCollection *usys, /* non exposed options */ bUnitDef *unit, char pad) { @@ -178,32 +180,33 @@ static int unit_as_string(char *str, double value, int prec, bUnitCollection *us /* Convert to a string */ { - char conv_str[5] = {'%', '.', '0'+prec, 'f', '\0'}; /* "%.2f" when prec is 2, must be under 10 */ - len= sprintf(str, conv_str, (float)value_conv); + char conv_str[6] = {'%', '.', '0'+prec, 'l', 'f', '\0'}; /* "%.2lf" when prec is 2, must be under 10 */ + len= snprintf(str, len_max, conv_str, (float)value_conv); + + if(len >= len_max) + len= len_max; } - /* Add unit prefix and strip zeros */ - { - /* replace trailing zero's with spaces - * so the number is less complicated but allignment in a button wont - * jump about while dragging */ - int j; - i= len-1; + /* replace trailing zero's with spaces + * so the number is less complicated but allignment in a button wont + * jump about while dragging */ + i= len-1; + + while(i>0 && str[i]=='0') { /* 4.300 -> 4.3 */ + str[i--]= pad; + } + + if(i>0 && str[i]=='.') { /* 10. -> 10 */ + str[i--]= pad; + } - while(i>0 && str[i]=='0') { /* 4.300 -> 4.3 */ - str[i--]= pad; - } - - if(i>0 && str[i]=='.') { /* 10. -> 10 */ - str[i--]= pad; - } - - /* Now add the suffix */ + /* Now add the suffix */ + if(i<len_max) { + int j=0; i++; - j=0; - while(unit->name_short[j]) { + while(unit->name_short[j] && (i < len_max)) { str[i++]= unit->name_short[j++]; } @@ -212,21 +215,23 @@ static int unit_as_string(char *str, double value, int prec, bUnitCollection *us * the unit name only used padded chars, * In that case add padding for the name. */ - while(i<=len+j) { + while(i<=len+j && (i < len_max)) { str[i++]= pad; } } - - /* terminate no matter whats done with padding above */ - str[i] = '\0'; } + /* terminate no matter whats done with padding above */ + if(i >= len_max) + i= len_max-1; + + str[i] = '\0'; return i; } /* Used for drawing number buttons, try keep fast */ -void bUnit_AsString(char *str, double value, int prec, int system, int type, int split, int pad) +void bUnit_AsString(char *str, int len_max, double value, int prec, int system, int type, int split, int pad) { bUnitCollection *usys = unit_get_system(system, type); @@ -242,56 +247,111 @@ void bUnit_AsString(char *str, double value, int prec, int system, int type, int /* check the 2 is a smaller unit */ if(unit_b > unit_a) { - i= unit_as_string(str, value_a, prec, usys, unit_a, '\0'); - str[i++]= ','; - str[i++]= ' '; + i= unit_as_string(str, len_max, value_a, prec, usys, unit_a, '\0'); - /* use low precision since this is a smaller unit */ - unit_as_string(str+i, value_b, prec?1:0, usys, unit_b, '\0'); + /* is there enough space for at least 1 char of the next unit? */ + if(i+3 < len_max) { + str[i++]= ','; + str[i++]= ' '; + + /* use low precision since this is a smaller unit */ + unit_as_string(str+i, len_max-i, value_b, prec?1:0, usys, unit_b, '\0'); + } return; } } - unit_as_string(str, value, prec, usys, NULL, pad?' ':'\0'); + unit_as_string(str, len_max, value, prec, usys, NULL, pad?' ':'\0'); } -static int unit_scale_str(char *str, char *str_tmp, double scale_pref, bUnitDef *unit, char *replace_str) +static char *unit_find_str(char *str, char *substr) { char *str_found; - int change= 0; - if(replace_str==NULL || replace_str[0] == '\0') - return 0; + if(substr && substr[0] != '\0') { + str_found= strstr(str, substr); + if(str_found) { + /* previous char cannot be a letter */ + if (str_found == str || isalpha(*(str_found-1))==0) { + /* next char cannot be alphanum */ + int len_name = strlen(substr); - if((str_found= strstr(str, replace_str))) { - /* previous char cannot be a letter */ - if (str_found == str || isalpha(*(str_found-1))==0) { - int len_name = strlen(replace_str); - - /* next char cannot be alphanum */ - if (!isalpha(*(str_found+len_name))) { - int len= strlen(str); - int len_num= sprintf(str_tmp, "*%g", unit->scalar/scale_pref); - memmove(str_found+len_num, str_found+len_name, (len+1)-(int)((str_found+len_name)-str)); /* may grow or shrink the string, 1+ to copy the string terminator */ - memcpy(str_found, str_tmp, len_num); /* without the string terminator */ - change= 1; + if (!isalpha(*(str_found+len_name))) { + return str_found; + } } } + } - return change; + return NULL; + +} + +static int unit_scale_str(char *str, int len_max, char *str_tmp, double scale_pref, bUnitDef *unit, char *replace_str) +{ + char *str_found= unit_find_str(str, replace_str); + + if(str_found) { /* XXX - investigate, does not respect len_max properly */ + int len, len_num, len_name, len_move, found_ofs; + + found_ofs = (int)(str_found-str); + + len= strlen(str); + + len_name = strlen(replace_str); + len_move= (len - (found_ofs+len_name)) + 1; /* 1+ to copy the string terminator */ + len_num= snprintf(str_tmp, TEMP_STR_SIZE, "*%lg", unit->scalar/scale_pref); + + if(len_num > len_max) + len_num= len_max; + + if(found_ofs+len_num+len_move > len_max) { + /* can't move the whole string, move just as much as will fit */ + len_move -= (found_ofs+len_num+len_move) - len_max; + } + + if(len_move>0) { + /* resize the last part of the string */ + memmove(str_found+len_num, str_found+len_name, len_move); /* may grow or shrink the string */ + } + + if(found_ofs+len_num > len_max) { + /* not even the number will fit into the string, only copy part of it */ + len_num -= (found_ofs+len_num) - len_max; + } + + if(len_num > 0) { + /* its possible none of the number could be copied in */ + memcpy(str_found, str_tmp, len_num); /* without the string terminator */ + } + + str[len_max-1]= '\0'; /* since the null terminator wont be moved */ + return 1; + } + return 0; } -static int unit_replace(char *str, char *str_tmp, double scale_pref, bUnitDef *unit) +static int unit_replace(char *str, int len_max, char *str_tmp, double scale_pref, bUnitDef *unit) { int change= 0; - change |= unit_scale_str(str, str_tmp, scale_pref, unit, unit->name_short); - change |= unit_scale_str(str, str_tmp, scale_pref, unit, unit->name_plural); - change |= unit_scale_str(str, str_tmp, scale_pref, unit, unit->name_alt); - change |= unit_scale_str(str, str_tmp, scale_pref, unit, unit->name); + change |= unit_scale_str(str, len_max, str_tmp, scale_pref, unit, unit->name_short); + change |= unit_scale_str(str, len_max, str_tmp, scale_pref, unit, unit->name_plural); + change |= unit_scale_str(str, len_max, str_tmp, scale_pref, unit, unit->name_alt); + change |= unit_scale_str(str, len_max, str_tmp, scale_pref, unit, unit->name); return change; } +static int unit_find(char *str, bUnitDef *unit) +{ + if (unit_find_str(str, unit->name_short)) return 1; + if (unit_find_str(str, unit->name_plural)) return 1; + if (unit_find_str(str, unit->name_alt)) return 1; + if (unit_find_str(str, unit->name)) return 1; + + return 0; +} + /* make a copy of the string that replaces the units with numbers * this is used before parsing * This is only used when evaluating user input and can afford to be a bit slower @@ -304,15 +364,13 @@ static int unit_replace(char *str, char *str_tmp, double scale_pref, bUnitDef *u * * return true of a change was made. */ -int bUnit_ReplaceString(char *str, char *str_orig, char *str_prev, double scale_pref, int system, int type) +int bUnit_ReplaceString(char *str, int len_max, char *str_prev, double scale_pref, int system, int type) { bUnitCollection *usys = unit_get_system(system, type); bUnitDef *unit; - char str_tmp[256]; + char str_tmp[TEMP_STR_SIZE]; int change= 0; - - strcpy(str, str_orig); if(usys==NULL || usys->units[0].name==NULL) { return 0; @@ -324,7 +382,7 @@ int bUnit_ReplaceString(char *str, char *str_orig, char *str_prev, double scale_ continue; /* incase there are multiple instances */ - while(unit_replace(str, str_tmp, scale_pref, unit)) + while(unit_replace(str, len_max, str_tmp, scale_pref, unit)) change= 1; } unit= NULL; @@ -343,7 +401,7 @@ int bUnit_ReplaceString(char *str, char *str_orig, char *str_prev, double scale_ continue; /* incase there are multiple instances */ - while(unit_replace(str, str_tmp, scale_pref, unit)) + while(unit_replace(str, len_max, str_tmp, scale_pref, unit)) change= 1; } } @@ -355,25 +413,24 @@ int bUnit_ReplaceString(char *str, char *str_orig, char *str_prev, double scale_ /* no units given so infer a unit from the previous string or default */ if(str_prev) { /* see which units the original value had */ - strcpy(str, str_prev); /* temp overwrite */ for(unit= usys->units; unit->name; unit++) { if(unit->flag & B_UNIT_DEF_SUPPRESS) continue; - if (unit_replace(str, str_tmp, scale_pref, unit)) + if (unit_find(str_prev, unit)) break; } - strcpy(str, str_orig); /* temp overwrite */ } if(unit==NULL) unit= unit_default(usys); /* add the unit prefic and re-run */ - sprintf(str_tmp, "%s %s", str, unit->name); + snprintf(str_tmp, sizeof(str_tmp), "%s %s", str, unit->name); + strncpy(str, str_tmp, len_max); - return bUnit_ReplaceString(str, str_tmp, NULL, scale_pref, system, type); + return bUnit_ReplaceString(str, len_max, NULL, scale_pref, system, type); } // printf("replace %s\n", str); diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index bbdaad5fd5d..ac26fe86364 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -1339,7 +1339,7 @@ static double ui_get_but_scale_unit(uiBut *but, double value) } } -static void ui_get_but_string_unit(uiBut *but, char *str, double value, int pad) +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; @@ -1352,7 +1352,7 @@ static void ui_get_but_string_unit(uiBut *but, char *str, double value, int pad) if(precission>4) precission= 4; else if(precission==0) precission= 2; - bUnit_AsString(str, ui_get_but_scale_unit(but, value), precission, scene->unit.system, unit_type, do_split, pad); + bUnit_AsString(str, len_max, ui_get_but_scale_unit(but, value), precission, scene->unit.system, unit_type, do_split, pad); } static float ui_get_but_step_unit(uiBut *but, double value, float step_default) @@ -1428,7 +1428,7 @@ void ui_get_but_string(uiBut *but, char *str, int maxlen) if(ui_is_but_float(but)) { if(ui_is_but_unit(but)) { - ui_get_but_string_unit(but, str, value, 0); + ui_get_but_string_unit(but, str, maxlen, value, 0); } else if(but->a2) { /* amount of digits defined */ if(but->a2==1) BLI_snprintf(str, maxlen, "%.1f", value); @@ -1505,21 +1505,20 @@ int ui_set_but_string(bContext *C, uiBut *but, const char *str) #ifndef DISABLE_PYTHON { - Scene *scene= CTX_data_scene((bContext *)but->block->evil_C); char str_unit_convert[256]; int unit_type; - - if (but->rnaprop) - RNA_SUBTYPE_UNIT_VALUE(RNA_property_subtype(but->rnaprop)); + Scene *scene= CTX_data_scene((bContext *)but->block->evil_C); + + if(but->rnaprop) + unit_type= RNA_SUBTYPE_UNIT_VALUE(RNA_property_subtype(but->rnaprop)); else unit_type= 0; - + + BLI_strncpy(str_unit_convert, str, sizeof(str_unit_convert)); + if(scene->unit.system != USER_UNIT_NONE && unit_type) { /* 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, (char *)str, but->drawstr, ui_get_but_scale_unit(but, 1.0), scene->unit.system, unit_type); - } - else { - strcpy(str_unit_convert, str); + bUnit_ReplaceString(str_unit_convert, sizeof(str_unit_convert), but->drawstr, ui_get_but_scale_unit(but, 1.0), scene->unit.system, unit_type); } if(BPY_button_eval(C, str_unit_convert, &value)) { @@ -1875,9 +1874,9 @@ void ui_check_but(uiBut *but) else if(value == -FLT_MAX) sprintf(but->drawstr, "%s-inf", but->str); /* support length type buttons */ else if(ui_is_but_unit(but)) { - char new_str[256]; - ui_get_but_string_unit(but, new_str, value, TRUE); - sprintf(but->drawstr, "%s%s", but->str, new_str); + char new_str[sizeof(but->drawstr)]; + ui_get_but_string_unit(but, new_str, sizeof(new_str), value, TRUE); + snprintf(but->drawstr, sizeof(but->drawstr), "%s%s", but->str, new_str); } else if(but->a2) { /* amount of digits defined */ if(but->a2==1) sprintf(but->drawstr, "%s%.1f", but->str, value); diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 042e4a1941a..dd7cebdfe3f 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -3044,7 +3044,7 @@ static void headerTranslation(TransInfo *t, float vec[3], char *str) { int i, do_split= t->scene->unit.flag & USER_UNIT_OPT_SPLIT ? 1:0; for(i=0; i<3; i++) - bUnit_AsString(&tvec[i*20], dvec[i]*t->scene->unit.scale_length, 4, t->scene->unit.system, B_UNIT_LENGTH, do_split, 1); + bUnit_AsString(&tvec[i*20], 20, dvec[i]*t->scene->unit.scale_length, 4, t->scene->unit.system, B_UNIT_LENGTH, do_split, 1); } else { sprintf(&tvec[0], "%.4f", dvec[0]); @@ -3054,7 +3054,7 @@ static void headerTranslation(TransInfo *t, float vec[3], char *str) { } if(t->scene->unit.system) - bUnit_AsString(distvec, dist*t->scene->unit.scale_length, 4, t->scene->unit.system, B_UNIT_LENGTH, t->scene->unit.flag & USER_UNIT_OPT_SPLIT, 0); + bUnit_AsString(distvec, sizeof(distvec), dist*t->scene->unit.scale_length, 4, t->scene->unit.system, B_UNIT_LENGTH, t->scene->unit.flag & USER_UNIT_OPT_SPLIT, 0); else if( dist > 1e10 || dist < -1e10 ) /* prevent string buffer overflow */ sprintf(distvec, "%.4e", dist); else |