[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [22435] branches/blender2.5/blender/source /blender: added string max length option for unit functions bUnit_AsString and bUnit_ReplaceString

Campbell Barton ideasman42 at gmail.com
Thu Aug 13 19:05:27 CEST 2009


Revision: 22435
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=22435
Author:   campbellbarton
Date:     2009-08-13 19:05:27 +0200 (Thu, 13 Aug 2009)

Log Message:
-----------
added string max length option for unit functions bUnit_AsString and bUnit_ReplaceString

Modified Paths:
--------------
    branches/blender2.5/blender/source/blender/blenkernel/BKE_unit.h
    branches/blender2.5/blender/source/blender/blenkernel/intern/unit.c
    branches/blender2.5/blender/source/blender/editors/interface/interface.c
    branches/blender2.5/blender/source/blender/editors/transform/transform.c

Modified: branches/blender2.5/blender/source/blender/blenkernel/BKE_unit.h
===================================================================
--- branches/blender2.5/blender/source/blender/blenkernel/BKE_unit.h	2009-08-13 16:59:52 UTC (rev 22434)
+++ branches/blender2.5/blender/source/blender/blenkernel/BKE_unit.h	2009-08-13 17:05:27 UTC (rev 22435)
@@ -31,10 +31,10 @@
 /* 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);

Modified: branches/blender2.5/blender/source/blender/blenkernel/intern/unit.c
===================================================================
--- branches/blender2.5/blender/source/blender/blenkernel/intern/unit.c	2009-08-13 16:59:52 UTC (rev 22434)
+++ branches/blender2.5/blender/source/blender/blenkernel/intern/unit.c	2009-08-13 17:05:27 UTC (rev 22435)
@@ -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 @@
 	{"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 @@
 	*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 @@
 
 	/* 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 @@
 			 * 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 @@
 
 		/* 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_replace(char *str, char *str_tmp, double scale_pref, bUnitDef *unit)
+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, 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 @@
  *
  * 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 @@
 			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 @@
 						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 @@
 		/* no units given so infer a unit from the previous string or default */
 		if(str_prev) {
 			/* see which units the original value had */

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list