Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2009-08-13 21:05:27 +0400
committerCampbell Barton <ideasman42@gmail.com>2009-08-13 21:05:27 +0400
commit52a6a07d67f48c6c3465cbaf156bf8057755e1bc (patch)
treee10f280438fc1d2f14765bd918e54d3110d08ad8 /source/blender/blenkernel/intern/unit.c
parente8d9e0823ee73e3c3fdd596fd3945abec40d21c1 (diff)
added string max length option for unit functions bUnit_AsString and bUnit_ReplaceString
Diffstat (limited to 'source/blender/blenkernel/intern/unit.c')
-rw-r--r--source/blender/blenkernel/intern/unit.c189
1 files changed, 123 insertions, 66 deletions
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);