diff --git a/code/__HELPERS/sanitize_values.dm b/code/__HELPERS/sanitize_values.dm index cbe1817233..21ae7df940 100644 --- a/code/__HELPERS/sanitize_values.dm +++ b/code/__HELPERS/sanitize_values.dm @@ -51,40 +51,106 @@ return default return default -/proc/sanitize_hexcolor(color, desired_format=3, include_crunch=0, default) +#define RGB_FORMAT_INVALID 0 +#define RGB_FORMAT_SHORT 1 +#define RGB_FORMAT_LONG 2 + +/** + * Sanitizes a hexadecimal color. + * + * @params + * * color - input color, 3 or 6 characters without the #. + * * desired_format - 3 or 6 characters without the potential #. can only put in 3 or 6 here. + * * include_crunch - do we put a # at the start + * * default - default color. must be 3 or 6 characters with or without #. + * * default_replacement - what we replace broken letters with. + */ +/proc/sanitize_hexcolor(color, desired_format = 3, include_crunch = 0, default = "ffffff", default_replacement = "f") + if(!istext(default) || (length(default) < 3)) + CRASH("Default should be a text string of RGB format, with or without the crunch, 3 or 6 characters. Default was instead [default]") + if(!istext(default_replacement) || length(default_replacement) != 1)) + CRASH("Invalid default_replacement: [default_replacement]") + switch(text2ascii(default_replacement)) + if(48 to 57) + if(97 to 102) + if(65 to 70) + else // yeah yeah i know 3 empty if's.. + CRASH("Invalid default_replacement: [default_replacement]") var/crunch = include_crunch ? "#" : "" if(!istext(color)) - color = "" + color = default - var/start = 1 + (text2ascii(color, 1) == 35) var/len = length(color) - var/char = "" - // RRGGBB -> RGB but awful - var/convert_to_shorthand = desired_format == 3 && length_char(color) > 3 + // get rid of crunch + if(len && color[1] == "#") + if(len >= 2) + color = copytext(color, 2) - . = "" - var/i = start - while(i <= len) + switch(desired_format) + if(3) + desired_format = RGB_FORMAT_SHORT + if(6) + desired_format = RGB_FORMAT_LONG + else + CRASH("Invalid desired_format: [desired_format]. Must be 3 or 6.") + var/current_format = RGB_FORMAT_INVALID + switch(length(color)) + if(3) + current_format = RGB_FORMAT_SHORT + if(6) + current_format = RGB_FORMAT_LONG + else + current_format = RGB_FORMAT_INVALID + + if(current_format == RGB_FORMAT_INVALID) // nah + color = default // process default + if(color[1] == "#") // we checked default was at least 3 chars long earlier + color = copytext(color, 2) + len = length(color) + switch(len) + if(3) + current_format = RGB_FORMAT_SHORT + if(6) + current_format = RGB_FORMAT_LONG + else + CRASH("Default was not 3 or 6 RGB hexadecimal characters: [default]") + + var/sanitized = "" + // first, sanitize hex + for(var/i in 1 to len) char = color[i] switch(text2ascii(char)) - if(48 to 57) //numbers 0 to 9 - . += char - if(97 to 102) //letters a to f - . += char - if(65 to 70) //letters A to F - . += lowertext(char) + if(48 to 57) // 0 to 9 + sanitized += char + if(97 to 102) // a to f + sanitized += char + if(65 to 70) // A to F (capitalized!) + sanitized += lowertext(char) else - break - i += length(char) - if(convert_to_shorthand && i <= len) //skip next one - i += length(color[i]) + sanitized += lowertext(default_replacement) + // do we need to convert? + if(desired_format == current_format) + return crunch + sanitized // no + // yes + if((desired_format == RGB_FORMAT_SHORT) && (current_format == RGB_FORMAT_LONG)) // downconvert + var/temp = "" + // we could do some math but we're lazy and in practice floor()ing this. + for(var/i in 1 to 6 step 2) + temp += sanitized[i] + sanitized = temp + else if((desired_format == RGB_FORMAT_LONG) && (current_format == RGB_FORMAT_SHORT)) // upconvert + var/temp = "" + for(var/i in 1 to 3) + temp += sanitized[i] + temp += sanitized[i] + sanitized = temp + else + CRAHS("Invalid desired_format and current_format pair: [desired_format], [current_format]. Could not determine which way to convert.") + return crunch + sanitized - if(length_char(.) != desired_format) - if(default) - return default - return crunch + repeat_string(desired_format, "0") - - return crunch + . +#undef RGB_FORMAT_INVALID +#undef RGB_FORMAT_SHORT +#undef RGB_FORMAT_LONG /proc/sanitize_ooccolor(color) if(length(color) != length_char(color))