diff options
-rw-r--r-- | generic/Color.c | 139 |
1 files changed, 91 insertions, 48 deletions
diff --git a/generic/Color.c b/generic/Color.c index f23dc49..6518aa0 100644 --- a/generic/Color.c +++ b/generic/Color.c @@ -1169,14 +1169,16 @@ ZnGetGradient(Tcl_Interp *interp, Tk_Window tkwin, Tk_Uid desc) { + #define SEGMENT_SIZE 64 Tcl_HashEntry *hash; ZnGradient *grad; - int i, j, new, num_colors; + int i, j, nspace, new, num_colors; + unsigned int size; char type; - char const *scan_ptr; - int num_tok, angle, position, control; - double x, y; - char *color_ptr, color_name[COLOR_NAME_SIZE]; + char const *scan_ptr, *next_ptr, *str_ptr; + int angle, position, control; + double x=0, y=0; + char *color_ptr, *end, segment[SEGMENT_SIZE]; ZnGradientColor *first, *last; XColor color; int red_range, green_range, blue_range; @@ -1221,7 +1223,7 @@ ZnGetGradient(Tcl_Interp *interp, * If the first section is the gradient description, start color * counts up from zero. */ - num_colors = (*scan_ptr == '@') ? 0 : 1; + num_colors = (*scan_ptr == '=') ? 0 : 1; while ((scan_ptr = strchr(scan_ptr, '|'))) { num_colors++; scan_ptr++; @@ -1238,44 +1240,53 @@ ZnGetGradient(Tcl_Interp *interp, * Then look at the gradient type. */ scan_ptr = desc; - if (*scan_ptr == '@') { + /* + * next_ptr can't be NULL in the following code, + * we checked that at least one color was specified + * after the gradient description. + */ + next_ptr = strchr(scan_ptr, '|'); + if (*scan_ptr == '=') { scan_ptr++; if ((*scan_ptr == 'a') && (strncmp(scan_ptr, "axial", 5) == 0)) { scan_ptr += 5; - num_tok = sscanf(scan_ptr, "%d", &angle); - if (num_tok != 1) { - Tcl_AppendResult(interp, "invalid axial gradient parameter \"", + angle = strtol(scan_ptr, &end, 10); + nspace = strspn(end, " \t"); + if ((end+nspace) != next_ptr) { + grad_err3: + Tcl_AppendResult(interp, "invalid gradient parameter \"", desc, "\",", NULL); goto grad_err1; } } - else if ((*scan_ptr == 'r') && (strncmp(scan_ptr, "radial", 6) == 0)) { - scan_ptr += 6; - num_tok = sscanf(scan_ptr, "%lf %lf", (double *) &x, (double *) &y); - if (num_tok != 2) { - Tcl_AppendResult(interp, "invalid radial gradient parameter \"", - desc, "\",", NULL); - goto grad_err1; + else if (((*scan_ptr == 'r') && (strncmp(scan_ptr, "radial", 6) == 0)) || + ((*scan_ptr == 'p') && (strncmp(scan_ptr, "path", 4) == 0))) { + if (*scan_ptr == 'r') { + type = ZN_RADIAL_GRADIENT; + scan_ptr += 6; } - type = ZN_RADIAL_GRADIENT; - } - else if ((*scan_ptr == 'p') && (strncmp(scan_ptr, "path", 4) == 0)) { - scan_ptr += 4; - num_tok = sscanf(scan_ptr, "%lf %lf", (double *) &x, (double *) &y); - if (num_tok == 2) { - Tcl_AppendResult(interp, "invalid path gradient parameter \"", - desc, "\",", NULL); - goto grad_err1; + else { + type = ZN_PATH_GRADIENT; + scan_ptr += 4; + } + x = strtod(scan_ptr, &end); + if (end == scan_ptr) { + goto grad_err3; + } + scan_ptr = end; + y = strtod(scan_ptr, &end); + nspace = strspn(end, " \t"); + if ((end+nspace) != next_ptr) { + goto grad_err3; } - type = ZN_PATH_GRADIENT; } else { Tcl_AppendResult(interp, "invalid gradient type \"", desc, "\",", NULL); goto grad_err1; } - scan_ptr = strchr(scan_ptr, '|'); - scan_ptr++; + scan_ptr = next_ptr + 1; + next_ptr = strchr(scan_ptr, '|'); } /* * Create the gradient structure. @@ -1296,12 +1307,21 @@ ZnGetGradient(Tcl_Interp *interp, Tcl_SetHashValue(hash, grad); for (i = 0; i < num_colors; i++) { - grad->colors[i].position = 0; - grad->colors[i].control = 50; grad->colors[i].alpha = 100; - num_tok = sscanf(scan_ptr, "%s %d %d", color_name, &position, &control); - if (num_tok == 0) { - Tcl_AppendResult(interp, "incorrect color description in gradient \"", + /* + * Try to parse the color name. + */ + nspace = strspn(scan_ptr, " \t"); + scan_ptr += nspace; + str_ptr = strpbrk(scan_ptr, " \t|"); + if (str_ptr) { + size = str_ptr - scan_ptr; + } + else { + size = strlen(scan_ptr); + } + if (size > (SEGMENT_SIZE-1)) { + Tcl_AppendResult(interp, "color name too long in gradient \"", desc, "\",", NULL); grad_err2: for (j = 0; j < i; j++) { @@ -1310,17 +1330,39 @@ ZnGetGradient(Tcl_Interp *interp, ZnFree(grad); goto grad_err1; } - if (num_tok > 1) { + strncpy(segment, scan_ptr, size); + segment[size] = 0; + scan_ptr += size; + /* + * Try to parse the color position. + */ + grad->colors[i].position = 0; + grad->colors[i].control = 50; + position = strtol(scan_ptr, &end, 10); + if (end != scan_ptr) { grad->colors[i].position = position; + scan_ptr = end; + /* + * Try to parse the control point + */ + control = strtol(scan_ptr, &end, 10); + if (end != scan_ptr) { + grad->colors[i].control = control; + scan_ptr = end; + } } - if (num_tok > 2) { - grad->colors[i].control = control; + nspace = strspn(scan_ptr, " \t"); + if ((scan_ptr[nspace] != 0) && (scan_ptr+nspace != next_ptr)) { + Tcl_AppendResult(interp, "incorrect color description in gradient \"", + desc, "\",", NULL); + goto grad_err2; } - color_ptr = strchr(color_name, ';'); + + color_ptr = strchr(segment, ';'); if (color_ptr) { *color_ptr = 0; } - grad->colors[i].rgb = ZnGetColor(interp, tkwin, Tk_GetUid(color_name)); + grad->colors[i].rgb = ZnGetColor(interp, tkwin, Tk_GetUid(segment)); if (grad->colors[i].rgb == NULL) { Tcl_AppendResult(interp, "incorrect color value in gradient \"", desc, "\",", NULL); @@ -1336,13 +1378,12 @@ ZnGetGradient(Tcl_Interp *interp, else if (i == num_colors - 1) { grad->colors[i].position = 100; } - if ((num_tok > 2) && (i > 0)) { - if ((grad->colors[i].position > 100) || - (grad->colors[i].position < grad->colors[i-1].position)) { - Tcl_AppendResult(interp, "incorrect color position in gradient \"", - desc, "\",", NULL); - goto grad_err2; - } + if ((i > 0) && + ((grad->colors[i].position > 100) || + (grad->colors[i].position < grad->colors[i-1].position))) { + Tcl_AppendResult(interp, "incorrect color position in gradient \"", + desc, "\",", NULL); + goto grad_err2; } if (grad->colors[i].control > 100) { grad->colors[i].control = 100; @@ -1350,8 +1391,10 @@ ZnGetGradient(Tcl_Interp *interp, if (grad->colors[i].alpha > 100) { grad->colors[i].alpha = 100; } - scan_ptr = strchr(scan_ptr, '|'); - scan_ptr++; + if (next_ptr) { + scan_ptr = next_ptr + 1; + next_ptr = strchr(scan_ptr, '|'); + } } } |