diff --git a/Dockerfile b/Dockerfile index ad347079cd..5f755e3dc1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM tgstation/byond:513.1490 as base +FROM tgstation/byond:513.1503 as base FROM base as build_base diff --git a/code/__DEFINES/typeids.dm b/code/__DEFINES/typeids.dm index 8bfe6216e2..275f7719f0 100644 --- a/code/__DEFINES/typeids.dm +++ b/code/__DEFINES/typeids.dm @@ -2,7 +2,7 @@ #define TYPEID_NULL "0" #define TYPEID_NORMAL_LIST "f" //helper macros -#define GET_TYPEID(ref) ( ( (length(ref) <= 10) ? "TYPEID_NULL" : copytext(ref, 4, length(ref)-6) ) ) +#define GET_TYPEID(ref) ( ( (length(ref) <= 10) ? "TYPEID_NULL" : copytext(ref, 4, -7) ) ) #define IS_NORMAL_LIST(L) (GET_TYPEID("\ref[L]") == TYPEID_NORMAL_LIST) diff --git a/code/__HELPERS/files.dm b/code/__HELPERS/files.dm index 4160c1976a..7c6c186bca 100644 --- a/code/__HELPERS/files.dm +++ b/code/__HELPERS/files.dm @@ -20,7 +20,7 @@ continue path += choice - if(copytext(path,-1,0) != "/") //didn't choose a directory, no need to iterate again + if(copytext_char(path, -1) != "/") //didn't choose a directory, no need to iterate again break var/extensions for(var/i in valid_extensions) diff --git a/code/__HELPERS/icons.dm b/code/__HELPERS/icons.dm index 8e88f869a9..aee0f3d7f7 100644 --- a/code/__HELPERS/icons.dm +++ b/code/__HELPERS/icons.dm @@ -985,7 +985,7 @@ world var/icon/atom_icon = new(A.icon, A.icon_state) if(!letter) - letter = copytext(A.name, 1, 2) + letter = A.name[1] if(uppercase == 1) letter = uppertext(letter) else if(uppercase == -1) @@ -1113,7 +1113,7 @@ GLOBAL_LIST_INIT(freon_color_matrix, list("#2E5E69", "#60A2A8", "#A1AFB1", rgb(0 WRITE_FILE(GLOB.iconCache[iconKey], icon) var/iconData = GLOB.iconCache.ExportText(iconKey) var/list/partial = splittext(iconData, "{") - return replacetext(copytext(partial[2], 3, -5), "\n", "") + return replacetext(copytext_char(partial[2], 3, -5), "\n", "") /proc/icon2html(thing, target, icon_state, dir, frame = 1, moving = FALSE) if (!thing) diff --git a/code/__HELPERS/pronouns.dm b/code/__HELPERS/pronouns.dm index d1add9cb4c..bab286bafe 100644 --- a/code/__HELPERS/pronouns.dm +++ b/code/__HELPERS/pronouns.dm @@ -28,10 +28,10 @@ . = "does" /datum/proc/p_theyve(capitalized, temp_gender) - . = p_they(capitalized, temp_gender) + "'" + copytext(p_have(temp_gender), 3) + . = p_they(capitalized, temp_gender) + "'" + copytext_char(p_have(temp_gender), 3) /datum/proc/p_theyre(capitalized, temp_gender) - . = p_they(capitalized, temp_gender) + "'" + copytext(p_are(temp_gender), 2) + . = p_they(capitalized, temp_gender) + "'" + copytext_char(p_are(temp_gender), 2) /datum/proc/p_s(temp_gender) //is this a descriptive proc name, or what? . = "s" diff --git a/code/__HELPERS/sanitize_values.dm b/code/__HELPERS/sanitize_values.dm index b511c61971..601ed966bf 100644 --- a/code/__HELPERS/sanitize_values.dm +++ b/code/__HELPERS/sanitize_values.dm @@ -43,24 +43,24 @@ if(!istext(color)) color = "" - var/start = 1 + (text2ascii(color,1)==35) + var/start = 1 + (text2ascii(color, 1) == 35) var/len = length(color) - var/step_size = 1 + ((len+1)-start != desired_format) + var/char = "" . = "" - for(var/i=start, i<=len, i+=step_size) - var/ascii = text2ascii(color,i) - switch(ascii) - if(48 to 57) - . += ascii2text(ascii) //numbers 0 to 9 - if(97 to 102) - . += ascii2text(ascii) //letters a to f - if(65 to 70) - . += ascii2text(ascii+32) //letters A to F - translates to lowercase + for(var/i = start, i <= len, i += length(char)) + 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 - translates to lowercase + . += lowertext(char) else break - if(length(.) != desired_format) + if(length_char(.) != desired_format) if(default) return default return crunch + repeat_string(desired_format, "0") @@ -68,7 +68,9 @@ return crunch + . /proc/sanitize_ooccolor(color) - var/list/HSL = rgb2hsl(hex2num(copytext(color,2,4)),hex2num(copytext(color,4,6)),hex2num(copytext(color,6,8))) + if(length(color) != length_char(color)) + CRASH("Invalid characters in color '[color]'") + var/list/HSL = rgb2hsl(hex2num(copytext(color, 2, 4)), hex2num(copytext(color, 4, 6)), hex2num(copytext(color, 6, 8))) HSL[3] = min(HSL[3],0.4) var/list/RGB = hsl2rgb(arglist(HSL)) return "#[num2hex(RGB[1],2)][num2hex(RGB[2],2)][num2hex(RGB[3],2)]" \ No newline at end of file diff --git a/code/__HELPERS/shell.dm b/code/__HELPERS/shell.dm index 8b615eac0a..3438f38b85 100644 --- a/code/__HELPERS/shell.dm +++ b/code/__HELPERS/shell.dm @@ -52,6 +52,6 @@ if(bad_chars) bad_match = url_encode(bad_chars_regex.match) scrubbed_url += bad_match - last_good = bad_chars + length(bad_match) + last_good = bad_chars + length(bad_chars_regex.match) while(bad_chars) . = scrubbed_url diff --git a/code/__HELPERS/text.dm b/code/__HELPERS/text.dm index 60c43b0869..3985659b71 100644 --- a/code/__HELPERS/text.dm +++ b/code/__HELPERS/text.dm @@ -40,8 +40,8 @@ for(var/char in repl_chars) var/index = findtext(t, char) while(index) - t = copytext(t, 1, index) + repl_chars[char] + copytext(t, index+1) - index = findtext(t, char, index+1) + t = copytext(t, 1, index) + repl_chars[char] + copytext(t, index + length(char)) + index = findtext(t, char, index + length(char)) return t /proc/sanitize_filename(t) @@ -63,22 +63,28 @@ //Returns null if there is any bad text in the string -/proc/reject_bad_text(text, max_length=512) - if(length(text) > max_length) - return //message too long - var/non_whitespace = 0 - for(var/i=1, i<=length(text), i++) - switch(text2ascii(text,i)) - if(62,60,92,47) - return //rejects the text if it contains these bad characters: <, >, \ or / - if(127 to 255) - return //rejects weird letters like � +/proc/reject_bad_text(text, max_length = 512, ascii_only = TRUE) + var/char_count = 0 + var/non_whitespace = FALSE + var/lenbytes = length(text) + var/char = "" + for(var/i = 1, i <= lenbytes, i += length(char)) + char = text[i] + char_count++ + if(char_count > max_length) + return + switch(text2ascii(char)) + if(62,60,92,47) // <, >, \, / + return if(0 to 31) - return //more weird stuff + return if(32) continue //whitespace + if(127 to INFINITY) + if(ascii_only) + return else - non_whitespace = 1 + non_whitespace = TRUE if(non_whitespace) return text //only accepts the text if it has some non-spaces @@ -101,73 +107,84 @@ else return trim(html_encode(name), max_length) +#define NO_CHARS_DETECTED 0 +#define SPACES_DETECTED 1 +#define SYMBOLS_DETECTED 2 +#define NUMBERS_DETECTED 3 +#define LETTERS_DETECTED 4 + //Filters out undesirable characters from names -/proc/reject_bad_name(t_in, allow_numbers=0, max_length=MAX_NAME_LEN) - if(!t_in || length(t_in) > max_length) - return //Rejects the input if it is null or if it is longer then the max length allowed +/proc/reject_bad_name(t_in, allow_numbers = FALSE, max_length = MAX_NAME_LEN, ascii_only = TRUE) + if(!t_in) + return //Rejects the input if it is null - var/number_of_alphanumeric = 0 - var/last_char_group = 0 + var/number_of_alphanumeric = 0 + var/last_char_group = NO_CHARS_DETECTED var/t_out = "" + var/t_len = length(t_in) + var/charcount = 0 + var/char = "" - for(var/i=1, i<=length(t_in), i++) - var/ascii_char = text2ascii(t_in,i) - switch(ascii_char) + + for(var/i = 1, i <= t_len, i += length(char)) + char = t_in[i] + + switch(text2ascii(char)) // A .. Z if(65 to 90) //Uppercase Letters - t_out += ascii2text(ascii_char) number_of_alphanumeric++ - last_char_group = 4 + last_char_group = LETTERS_DETECTED // a .. z if(97 to 122) //Lowercase Letters - if(last_char_group<2) - t_out += ascii2text(ascii_char-32) //Force uppercase first character - else - t_out += ascii2text(ascii_char) + if(last_char_group == NO_CHARS_DETECTED || last_char_group == SPACES_DETECTED || last_char_group == SYMBOLS_DETECTED) //start of a word + char = uppertext(char) number_of_alphanumeric++ - last_char_group = 4 + last_char_group = LETTERS_DETECTED // 0 .. 9 if(48 to 57) //Numbers - if(!last_char_group) - continue //suppress at start of string - if(!allow_numbers) + if(last_char_group == NO_CHARS_DETECTED || !allow_numbers) //suppress at start of string continue - t_out += ascii2text(ascii_char) number_of_alphanumeric++ - last_char_group = 3 + last_char_group = NUMBERS_DETECTED // ' - . if(39,45,46) //Common name punctuation - if(!last_char_group) + if(last_char_group == NO_CHARS_DETECTED) continue - t_out += ascii2text(ascii_char) - last_char_group = 2 + last_char_group = SYMBOLS_DETECTED // ~ | @ : # $ % & * + if(126,124,64,58,35,36,37,38,42,43) //Other symbols that we'll allow (mainly for AI) - if(!last_char_group) - continue //suppress at start of string - if(!allow_numbers) + if(last_char_group == NO_CHARS_DETECTED || !allow_numbers) //suppress at start of string continue - t_out += ascii2text(ascii_char) - last_char_group = 2 + last_char_group = SYMBOLS_DETECTED //Space if(32) - if(last_char_group <= 1) - continue //suppress double-spaces and spaces at start of string - t_out += ascii2text(ascii_char) - last_char_group = 1 + if(last_char_group == NO_CHARS_DETECTED || last_char_group == SPACES_DETECTED) //suppress double-spaces and spaces at start of string + continue + last_char_group = SPACES_DETECTED + + if(127 to INFINITY) + if(ascii_only) + continue + last_char_group = SYMBOLS_DETECTED //for now, we'll treat all non-ascii characters like symbols even though most are letters + else - return + continue + + t_out += char + charcount++ + if(charcount >= max_length) + break if(number_of_alphanumeric < 2) return //protects against tiny names like "A" and also names like "' ' ' ' ' ' ' '" - if(last_char_group == 1) - t_out = copytext(t_out,1,length(t_out)) //removes the last character (in this case a space) + if(last_char_group == SPACES_DETECTED) + t_out = copytext_char(t_out, 1, -1) //removes the last character (in this case a space) for(var/bad_name in list("space","floor","wall","r-wall","monkey","unknown","inactive ai")) //prevents these common metagamey names if(cmptext(t_out,bad_name)) @@ -175,6 +192,11 @@ return t_out +#undef NO_CHARS_DETECTED +#undef SPACES_DETECTED +#undef NUMBERS_DETECTED +#undef LETTERS_DETECTED + //html_encode helper proc that returns the smallest non null of two numbers //or 0 if they're both null (needed because of findtext returning 0 when a value is not present) /proc/non_zero_min(a, b) @@ -184,39 +206,6 @@ return a return (a < b ? a : b) -/* - * Text searches - */ - -//Checks the beginning of a string for a specified sub-string -//Returns the position of the substring or 0 if it was not found -/proc/dd_hasprefix(text, prefix) - var/start = 1 - var/end = length(prefix) + 1 - return findtext(text, prefix, start, end) - -//Checks the beginning of a string for a specified sub-string. This proc is case sensitive -//Returns the position of the substring or 0 if it was not found -/proc/dd_hasprefix_case(text, prefix) - var/start = 1 - var/end = length(prefix) + 1 - return findtextEx(text, prefix, start, end) - -//Checks the end of a string for a specified substring. -//Returns the position of the substring or 0 if it was not found -/proc/dd_hassuffix(text, suffix) - var/start = length(text) - length(suffix) - if(start) - return findtext(text, suffix, start, null) - return - -//Checks the end of a string for a specified substring. This proc is case sensitive -//Returns the position of the substring or 0 if it was not found -/proc/dd_hassuffix_case(text, suffix) - var/start = length(text) - length(suffix) - if(start) - return findtextEx(text, suffix, start, null) - //Checks if any of a given list of needles is in the haystack /proc/text_in_list(haystack, list/needle_list, start=1, end=0) for(var/needle in needle_list) @@ -231,23 +220,19 @@ return 1 return 0 -//Adds 'u' number of zeros ahead of the text 't' -/proc/add_zero(t, u) - while (length(t) < u) - t = "0[t]" - return t +//Adds 'char' ahead of 'text' until there are 'count' characters total +/proc/add_leading(text, count, char = " ") + text = "[text]" + var/charcount = count - length_char(text) + var/list/chars_to_add[max(charcount + 1, 0)] + return jointext(chars_to_add, char) + text -//Adds 'u' number of spaces ahead of the text 't' -/proc/add_lspace(t, u) - while(length(t) < u) - t = " [t]" - return t - -//Adds 'u' number of spaces behind the text 't' -/proc/add_tspace(t, u) - while(length(t) < u) - t = "[t] " - return t +//Adds 'char' behind 'text' until there are 'count' characters total +/proc/add_trailing(text, count, char = " ") + text = "[text]" + var/charcount = count - length_char(text) + var/list/chars_to_add[max(charcount + 1, 0)] + return text + jointext(chars_to_add, char) //Returns a string with reserved characters and spaces before the first letter removed /proc/trim_left(text) @@ -267,57 +252,41 @@ //Returns a string with reserved characters and spaces before the first word and after the last word removed. /proc/trim(text, max_length) if(max_length) - text = copytext(text, 1, max_length) + text = copytext_char(text, 1, max_length) return trim_left(trim_right(text)) //Returns a string with the first element of the string capitalized. /proc/capitalize(t as text) - return uppertext(copytext(t, 1, 2)) + copytext(t, 2) - -//Centers text by adding spaces to either side of the string. -/proc/dd_centertext(message, length) - var/new_message = message - var/size = length(message) - var/delta = length - size - if(size == length) - return new_message - if(size > length) - return copytext(new_message, 1, length + 1) - if(delta == 1) - return new_message + " " - if(delta % 2) - new_message = " " + new_message - delta-- - var/spaces = add_lspace("",delta/2-1) - return spaces + new_message + spaces - -//Limits the length of the text. Note: MAX_MESSAGE_LEN and MAX_NAME_LEN are widely used for this purpose -/proc/dd_limittext(message, length) - var/size = length(message) - if(size <= length) - return message - return copytext(message, 1, length + 1) - + . = t + if(t) + . = t[1] + return uppertext(.) + copytext(t, 1 + length(.)) /proc/stringmerge(text,compare,replace = "*") //This proc fills in all spaces with the "replace" var (* by default) with whatever //is in the other string at the same spot (assuming it is not a replace char). //This is used for fingerprints var/newtext = text - if(length(text) != length(compare)) - return 0 - for(var/i = 1, i < length(text), i++) - var/a = copytext(text,i,i+1) - var/b = copytext(compare,i,i+1) + var/text_it = 1 //iterators + var/comp_it = 1 + var/newtext_it = 1 + var/text_length = length(text) + var/comp_length = length(compare) + while(comp_it <= comp_length && text_it <= text_length) + var/a = text[text_it] + var/b = compare[comp_it] //if it isn't both the same letter, or if they are both the replacement character //(no way to know what it was supposed to be) if(a != b) if(a == replace) //if A is the replacement char - newtext = copytext(newtext,1,i) + b + copytext(newtext, i+1) + newtext = copytext(newtext, 1, newtext_it) + b + copytext(newtext, newtext_it + length(newtext[newtext_it])) else if(b == replace) //if B is the replacement char - newtext = copytext(newtext,1,i) + a + copytext(newtext, i+1) + newtext = copytext(newtext, 1, newtext_it) + a + copytext(newtext, newtext_it + length(newtext[newtext_it])) else //The lists disagree, Uh-oh! return 0 + text_it += length(a) + comp_it += length(b) + newtext_it += length(newtext[newtext_it]) return newtext /proc/stringpercent(text,character = "*") @@ -326,16 +295,21 @@ if(!text || !character) return 0 var/count = 0 - for(var/i = 1, i <= length(text), i++) - var/a = copytext(text,i,i+1) + var/lentext = length(text) + var/a = "" + for(var/i = 1, i <= lentext, i += length(a)) + a = text[i] if(a == character) count++ return count /proc/reverse_text(text = "") var/new_text = "" - for(var/i = length(text); i > 0; i--) - new_text += copytext(text, i, i+1) + var/lentext = length(text) + var/letter = "" + for(var/i = 1, i <= lentext, i += length(letter)) + letter = text[i] + new_text = letter + new_text return new_text GLOBAL_LIST_INIT(zero_character_only, list("0")) @@ -358,15 +332,6 @@ GLOBAL_LIST_INIT(binary, list("0","1")) /proc/random_color() return random_string(6, GLOB.hex_characters) -/proc/add_zero2(t, u) - var/temp1 - while (length(t) < u) - t = "0[t]" - temp1 = t - if (length(t) > u) - temp1 = copytext(t,2,u+1) - return temp1 - //merges non-null characters (3rd argument) from "from" into "into". Returns result //e.g. into = "Hello World" // from = "Seeya______" @@ -379,41 +344,48 @@ GLOBAL_LIST_INIT(binary, list("0","1")) into = "" if(!istext(from)) from = "" - var/null_ascii = istext(null_char) ? text2ascii(null_char,1) : null_char - - var/previous = 0 + var/null_ascii = istext(null_char) ? text2ascii(null_char, 1) : null_char + var/copying_into = FALSE + var/char = "" var/start = 1 - var/end = length(into) + 1 - - for(var/i=1, i= text2ascii("a") && ca <= text2ascii("m")) - ca += 13 - else if(ca >= text2ascii("n") && ca <= text2ascii("z")) - ca -= 13 - else if(ca >= text2ascii("A") && ca <= text2ascii("M")) - ca += 13 - else if(ca >= text2ascii("N") && ca <= text2ascii("Z")) - ca -= 13 - result += ascii2text(ca) - return jointext(result, "") + var/lentext = length(text) + var/char = "" + var/ascii = 0 + . = "" + for(var/i = 1, i <= lentext, i += length(char)) + char = text[i] + ascii = text2ascii(char) + switch(ascii) + if(65 to 77, 97 to 109) //A to M, a to m + ascii += 13 + if(78 to 90, 110 to 122) //N to Z, n to z + ascii -= 13 + . += ascii2text(ascii) //Takes a list of values, sanitizes it down for readability and character count, //then exports it as a json file at data/npc_saves/[filename].json. @@ -599,7 +576,8 @@ GLOBAL_LIST_INIT(binary, list("0","1")) return //Regular expressions are, as usual, absolute magic - var/regex/all_invalid_symbols = new("\[^ -~]+") + //Any characters outside of 32 (space) to 126 (~) because treating things you don't understand as "magic" is really stupid + var/regex/all_invalid_symbols = new(@"[^ -~]{1}") var/list/accepted = list() for(var/string in proposed) @@ -607,34 +585,44 @@ GLOBAL_LIST_INIT(binary, list("0","1")) continue var/buffer = "" var/early_culling = TRUE - for(var/pos = 1, pos <= length(string), pos++) - var/let = copytext(string, pos, (pos + 1) % length(string)) - if(early_culling && !findtext(let,GLOB.is_alphanumeric)) + var/lentext = length(string) + var/let = "" + + for(var/pos = 1, pos <= lentext, pos += length(let)) + let = string[pos] + if(!findtext(let, GLOB.is_alphanumeric)) continue early_culling = FALSE - buffer += let - if(!findtext(buffer,GLOB.is_alphanumeric)) + buffer = copytext(string, pos) + break + if(early_culling) //Never found any letters! Bail! continue + var/punctbuffer = "" - var/cutoff = length(buffer) - for(var/pos = length(buffer), pos >= 0, pos--) - var/let = copytext(buffer, pos, (pos + 1) % length(buffer)) - if(findtext(let,GLOB.is_alphanumeric)) + var/cutoff = 0 + lentext = length_char(buffer) + for(var/pos = 1, pos <= lentext, pos++) + let = copytext_char(buffer, -pos, -pos + 1) + if(!findtext(let, GLOB.is_punctuation)) //This won't handle things like Nyaaaa!~ but that's fine break - if(findtext(let,GLOB.is_punctuation)) - punctbuffer = let + punctbuffer //Note this isn't the same thing as using += - cutoff = pos + punctbuffer += let + cutoff += length(let) if(punctbuffer) //We clip down excessive punctuation to get the letter count lower and reduce repeats. It's not perfect but it helps. var/exclaim = FALSE var/question = FALSE var/periods = 0 - for(var/pos = length(punctbuffer), pos >= 0, pos--) - var/punct = copytext(punctbuffer, pos, (pos + 1) % length(punctbuffer)) - if(!exclaim && findtext(punct,"!")) + lentext = length(punctbuffer) + for(var/pos = 1, pos <= lentext, pos += length(let)) + let = punctbuffer[pos] + if(!exclaim && findtext(let, "!")) exclaim = TRUE - if(!question && findtext(punct,"?")) + if(question) + break + if(!question && findtext(let, "?")) question = TRUE - if(!exclaim && !question && findtext(punct,".")) + if(exclaim) + break + if(!exclaim && !question && findtext(let, ".")) //? and ! take priority over periods periods += 1 if(exclaim) if(question) @@ -643,15 +631,13 @@ GLOBAL_LIST_INIT(binary, list("0","1")) punctbuffer = "!" else if(question) punctbuffer = "?" - else if(periods) - if(periods > 1) - punctbuffer = "..." - else - punctbuffer = "" //Grammer nazis be damned - buffer = copytext(buffer, 1, cutoff) + punctbuffer - if(!findtext(buffer,GLOB.is_alphanumeric)) - continue - if(!buffer || length(buffer) > 280 || length(buffer) <= cullshort || buffer in accepted) + else if(periods > 1) + punctbuffer = "..." + else + punctbuffer = "" //Grammer nazis be damned + buffer = copytext(buffer, 1, -cutoff) + punctbuffer + lentext = length_char(buffer) + if(!buffer || lentext > 280 || lentext <= cullshort || (buffer in accepted)) continue accepted += buffer @@ -688,7 +674,7 @@ GLOBAL_LIST_INIT(binary, list("0","1")) var/leng = length(string) - var/next_space = findtext(string, " ", next_backslash + 1) + var/next_space = findtext(string, " ", next_backslash + length(string[next_backslash])) if(!next_space) next_space = leng - next_backslash @@ -696,8 +682,8 @@ GLOBAL_LIST_INIT(binary, list("0","1")) return string var/base = next_backslash == 1 ? "" : copytext(string, 1, next_backslash) - var/macro = lowertext(copytext(string, next_backslash + 1, next_space)) - var/rest = next_backslash > leng ? "" : copytext(string, next_space + 1) + var/macro = lowertext(copytext(string, next_backslash + length(string[next_space]), next_space)) + var/rest = next_backslash > leng ? "" : copytext(string, next_space + length(string[next_space])) //See https://secure.byond.com/docs/ref/info.html#/DM/text/macros switch(macro) @@ -769,28 +755,24 @@ GLOBAL_LIST_INIT(binary, list("0","1")) return "[number]\th" /proc/unintelligize(message) - var/prefix=copytext(message,1,2) + var/regex/word_boundaries = regex(@"\b[\S]+\b", "g") + var/prefix = message[1] if(prefix == ";") - message = copytext(message,2) - else if(prefix in list(":","#")) - prefix += copytext(message,2,3) - message = copytext(message,3) + message = copytext(message, 1 + length(prefix)) + else if(prefix in list(":", "#")) + prefix += message[1 + length(prefix)] + message = copytext(message, length(prefix)) else - prefix="" + prefix = "" - var/list/words = splittext(message," ") var/list/rearranged = list() - for(var/i=1;i<=words.len;i++) - var/cword = pick(words) - words.Remove(cword) - var/suffix = copytext(cword,length(cword)-1,length(cword)) - while(length(cword)>0 && suffix in list(".",",",";","!",":","?")) - cword = copytext(cword,1 ,length(cword)-1) - suffix = copytext(cword,length(cword)-1,length(cword) ) + while(word_boundaries.Find(message)) + var/cword = word_boundaries.match if(length(cword)) rearranged += cword - message = "[prefix][jointext(rearranged," ")]" - . = message + shuffle_inplace(rearranged) + return "[prefix][jointext(rearranged, " ")]" + #define is_alpha(X) ((text2ascii(X) <= 122) && (text2ascii(X) >= 97)) #define is_digit(X) ((length(X) == 1) && (length(text2num(X)) == 1)) \ No newline at end of file diff --git a/code/__HELPERS/text_vr.dm b/code/__HELPERS/text_vr.dm index 9be806fc54..3c1e1eff12 100644 --- a/code/__HELPERS/text_vr.dm +++ b/code/__HELPERS/text_vr.dm @@ -8,14 +8,15 @@ index = findtext(t, char) return t -proc/TextPreview(var/string,var/len=40) - if(length(string) <= len) - if(!length(string)) +/proc/TextPreview(string, len = 40) + var/char_len = length_char(string) + if(char_len <= len) + if(char_len) return "\[...\]" else return string else - return "[copytext(string, 1, 37)]..." + return "[copytext_char(string, 1, 37)]..." GLOBAL_LIST_EMPTY(mentorlog) GLOBAL_PROTECT(mentorlog) diff --git a/code/__HELPERS/type2type.dm b/code/__HELPERS/type2type.dm index 823e893670..09047d32bf 100644 --- a/code/__HELPERS/type2type.dm +++ b/code/__HELPERS/type2type.dm @@ -542,17 +542,17 @@ //assumes format #RRGGBB #rrggbb /proc/color_hex2num(A) - if(!A) + if(!A || length(A) != length_char(A)) return 0 - var/R = hex2num(copytext(A,2,4)) - var/G = hex2num(copytext(A,4,6)) - var/B = hex2num(copytext(A,6,0)) + var/R = hex2num(copytext(A, 2, 4)) + var/G = hex2num(copytext(A, 4, 6)) + var/B = hex2num(copytext(A, 6, 0)) return R+G+B //word of warning: using a matrix like this as a color value will simplify it back to a string after being set /proc/color_hex2color_matrix(string) var/length = length(string) - if(length != 7 && length != 9) + if((length != 7 && length != 9) || length != length_char(string)) return color_matrix_identity() var/r = hex2num(copytext(string, 2, 4))/255 var/g = hex2num(copytext(string, 4, 6))/255 diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index 2f960e350b..6dccfd62d8 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -6,25 +6,18 @@ //Inverts the colour of an HTML string /proc/invertHTML(HTMLstring) - - if (!( istext(HTMLstring) )) + if(!istext(HTMLstring)) CRASH("Given non-text argument!") return - else - if (length(HTMLstring) != 7) - CRASH("Given non-HTML argument!") - return + else if(length(HTMLstring) != 7) + CRASH("Given non-HTML argument!") + return + else if(length_char(HTMLstring) != 7) + CRASH("Given non-hex symbols in argument!") var/textr = copytext(HTMLstring, 2, 4) var/textg = copytext(HTMLstring, 4, 6) var/textb = copytext(HTMLstring, 6, 8) - var/r = hex2num(textr) - var/g = hex2num(textg) - var/b = hex2num(textb) - textr = num2hex(255 - r, 2) - textg = num2hex(255 - g, 2) - textb = num2hex(255 - b, 2) - return text("#[][][]", textr, textg, textb) - return + return rgb(255 - hex2num(textr), 255 - hex2num(textg), 255 - hex2num(textb)) /proc/Get_Angle(atom/movable/start,atom/movable/end)//For beams. if(!start || !end) @@ -184,15 +177,15 @@ Turf and target are separate in case you want to teleport some distance from a t //Returns whether or not a player is a guest using their ckey as an input /proc/IsGuestKey(key) if (findtext(key, "Guest-", 1, 7) != 1) //was findtextEx - return 0 + return FALSE var/i, ch, len = length(key) - for (i = 7, i <= len, ++i) + for (i = 7, i <= len, ++i) //we know the first 6 chars are Guest- ch = text2ascii(key, i) - if (ch < 48 || ch > 57) - return 0 - return 1 + if (ch < 48 || ch > 57) //0-9 + return FALSE + return TRUE //Generalised helper proc for letting mobs rename themselves. Used to be clname() and ainame() /mob/proc/apply_pref_name(role, client/C) @@ -1314,7 +1307,7 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new) /proc/GUID() var/const/GUID_VERSION = "b" var/const/GUID_VARIANT = "d" - var/node_id = copytext(md5("[rand()*rand(1,9999999)][world.name][world.hub][world.hub_password][world.internet_address][world.address][world.contents.len][world.status][world.port][rand()*rand(1,9999999)]"), 1, 13) + var/node_id = copytext_char(md5("[rand()*rand(1,9999999)][world.name][world.hub][world.hub_password][world.internet_address][world.address][world.contents.len][world.status][world.port][rand()*rand(1,9999999)]"), 1, 13) var/time_high = "[num2hex(text2num(time2text(world.realtime,"YYYY")), 2)][num2hex(world.realtime, 6)]" diff --git a/code/_compile_options.dm b/code/_compile_options.dm index af948086df..fe4761ddcd 100644 --- a/code/_compile_options.dm +++ b/code/_compile_options.dm @@ -39,6 +39,26 @@ #error You need version 512 or higher #endif +//Compatability -- These procs were added in 513.1493, not 513.1490 +//Which really shoulda bumped us up to 514 right then and there but instead Lummox is a dumb dumb +#if DM_BUILD < 1493 +#define length_char(args...) length(args) +#define text2ascii_char(args...) text2ascii(args) +#define copytext_char(args...) copytext(args) +#define splittext_char(args...) splittext(args) +#define spantext_char(args...) spantext(args) +#define nonspantext_char(args...) nonspantext(args) +#define findtext_char(args...) findtext(args) +#define findtextEx_char(args...) findtextEx(args) +#define findlasttext_char(args...) findlasttext(args) +#define findlasttextEx_char(args...) findlasttextEx(args) +#define replacetext_char(args...) replacetext(args) +#define replacetextEx_char(args...) replacetextEx(args) +// /regex procs +#define Find_char(args...) Find(args) +#define Replace_char(args...) Replace(args) +#endif + //Additional code for the above flags. #ifdef TESTING #warn compiling in TESTING mode. testing() debug messages will be visible. diff --git a/code/controllers/configuration/config_entry.dm b/code/controllers/configuration/config_entry.dm index d97e7c379a..d7323700e4 100644 --- a/code/controllers/configuration/config_entry.dm +++ b/code/controllers/configuration/config_entry.dm @@ -171,7 +171,8 @@ key_name = copytext(str_val, 1, key_pos) if(lowercase) key_name = lowertext(key_name) - key_value = copytext(str_val, key_pos + 1) + if(key_pos) + key_value = copytext(str_val, key_pos + length(str_val[key_pos])) var/new_key var/new_value var/continue_check_value diff --git a/code/controllers/configuration/configuration.dm b/code/controllers/configuration/configuration.dm index ad1f869057..79d125f608 100644 --- a/code/controllers/configuration/configuration.dm +++ b/code/controllers/configuration/configuration.dm @@ -109,13 +109,13 @@ if(!L) continue - var/firstchar = copytext(L, 1, 2) + var/firstchar = L[1] if(firstchar == "#") continue var/lockthis = firstchar == "@" if(lockthis) - L = copytext(L, 2) + L = copytext(L, length(firstchar) + 1) var/pos = findtext(L, " ") var/entry = null @@ -123,7 +123,7 @@ if(pos) entry = lowertext(copytext(L, 1, pos)) - value = copytext(L, pos + 1) + value = copytext(L, pos + length(L[pos])) else entry = lowertext(L) @@ -269,7 +269,7 @@ t = trim(t) if(length(t) == 0) continue - else if(copytext(t, 1, 2) == "#") + else if(t[1] == "#") continue var/pos = findtext(t, " ") @@ -278,7 +278,7 @@ if(pos) command = lowertext(copytext(t, 1, pos)) - data = copytext(t, pos + 1) + data = copytext(t, pos + length(t[pos])) else command = lowertext(t) diff --git a/code/controllers/subsystem/pai.dm b/code/controllers/subsystem/pai.dm index 5aa109b63a..dd9848e465 100644 --- a/code/controllers/subsystem/pai.dm +++ b/code/controllers/subsystem/pai.dm @@ -39,34 +39,34 @@ SUBSYSTEM_DEF(pai) switch(option) if("name") - t = input("Enter a name for your pAI", "pAI Name", candidate.name) as text + t = reject_bad_name(stripped_input(usr, "Enter a name for your pAI", "pAI Name", candidate.name, MAX_NAME_LEN), TRUE) if(t) - candidate.name = copytext(sanitize(t),1,MAX_NAME_LEN) + candidate.name = t if("desc") - t = input("Enter a description for your pAI", "pAI Description", candidate.description) as message + t = stripped_multiline_input(usr, "Enter a description for your pAI", "pAI Description", candidate.description, MAX_MESSAGE_LEN) if(t) - candidate.description = copytext(sanitize(t),1,MAX_MESSAGE_LEN) + candidate.description = t if("role") - t = input("Enter a role for your pAI", "pAI Role", candidate.role) as text + t = stripped_input(usr, "Enter a role for your pAI", "pAI Role", candidate.role, MAX_MESSAGE_LEN) if(t) - candidate.role = copytext(sanitize(t),1,MAX_MESSAGE_LEN) + candidate.role = t if("ooc") - t = input("Enter any OOC comments", "pAI OOC Comments", candidate.comments) as message + t = stripped_multiline_input(usr, "Enter any OOC comments", "pAI OOC Comments", candidate.comments, MAX_MESSAGE_LEN) if(t) - candidate.comments = copytext(sanitize(t),1,MAX_MESSAGE_LEN) + candidate.comments = t if("save") candidate.savefile_save(usr) if("load") candidate.savefile_load(usr) //In case people have saved unsanitized stuff. if(candidate.name) - candidate.name = copytext(sanitize(candidate.name),1,MAX_NAME_LEN) + candidate.name = copytext_char(sanitize(candidate.name),1,MAX_NAME_LEN) if(candidate.description) - candidate.description = copytext(sanitize(candidate.description),1,MAX_MESSAGE_LEN) + candidate.description = copytext_char(sanitize(candidate.description),1,MAX_MESSAGE_LEN) if(candidate.role) - candidate.role = copytext(sanitize(candidate.role),1,MAX_MESSAGE_LEN) + candidate.role = copytext_char(sanitize(candidate.role),1,MAX_MESSAGE_LEN) if(candidate.comments) - candidate.comments = copytext(sanitize(candidate.comments),1,MAX_MESSAGE_LEN) + candidate.comments = copytext_char(sanitize(candidate.comments),1,MAX_MESSAGE_LEN) if("submit") if(isobserver(usr)) diff --git a/code/controllers/subsystem/processing/networks.dm b/code/controllers/subsystem/processing/networks.dm index 03276d5b26..f7f16538a6 100644 --- a/code/controllers/subsystem/processing/networks.dm +++ b/code/controllers/subsystem/processing/networks.dm @@ -46,6 +46,6 @@ PROCESSING_SUBSYSTEM_DEF(networks) var/hex = md5(string) if(!hex) return //errored - . = "[copytext(hex, 1, 9)]" //16 ^ 8 possibilities I think. + . = "[copytext_char(hex, 1, 9)]" //16 ^ 8 possibilities I think. if(interfaces_by_id[.]) return resolve_collisions? make_address("[num2text(rand(HID_RESTRICTED_END, 999999999), 12)]"):null diff --git a/code/datums/brain_damage/imaginary_friend.dm b/code/datums/brain_damage/imaginary_friend.dm index 9005a788b7..d8bfe2c35c 100644 --- a/code/datums/brain_damage/imaginary_friend.dm +++ b/code/datums/brain_damage/imaginary_friend.dm @@ -153,7 +153,7 @@ to_chat(src, compose_message(speaker, message_language, raw_message, radio_freq, spans, message_mode, FALSE, source)) /mob/camera/imaginary_friend/proc/friend_talk(message) - message = capitalize(trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN))) + message = capitalize(trim(copytext_char(sanitize(message), 1, MAX_MESSAGE_LEN))) if(!message) return diff --git a/code/datums/brain_damage/mild.dm b/code/datums/brain_damage/mild.dm index 235417d62c..d653671b5a 100644 --- a/code/datums/brain_damage/mild.dm +++ b/code/datums/brain_damage/mild.dm @@ -199,13 +199,16 @@ var/list/new_message = list() for(var/word in message_split) - var/suffix = copytext(word,-1) + var/suffix = "" + var/suffix_foundon = 0 + for(var/potential_suffix in list("." , "," , ";" , "!" , ":" , "?")) + suffix_foundon = findtext(word, potential_suffix, -length(potential_suffix)) + if(suffix_foundon) + suffix = potential_suffix + break - // Check if we have a suffix and break it out of the word - if(suffix in list("." , "," , ";" , "!" , ":" , "?")) - word = copytext(word,1,-1) - else - suffix = "" + if(suffix_foundon) + word = copytext(word, 1, suffix_foundon) word = html_decode(word) @@ -216,10 +219,9 @@ new_message += pick("uh","erm") break else - var/list/charlist = string2charlist(word) // Stupid shit code + var/list/charlist = text2charlist(word) shuffle_inplace(charlist) - charlist.len = round(charlist.len * 0.5,1) - new_message += html_encode(jointext(charlist,"")) + suffix + new_message += jointext(charlist, "") + suffix message = jointext(new_message, " ") diff --git a/code/datums/dna.dm b/code/datums/dna.dm index 5fa991c10c..68c6839482 100644 --- a/code/datums/dna.dm +++ b/code/datums/dna.dm @@ -370,14 +370,14 @@ /////////////////////////// DNA HELPER-PROCS ////////////////////////////// /proc/getleftblocks(input,blocknumber,blocksize) if(blocknumber > 1) - return copytext(input,1,((blocksize*blocknumber)-(blocksize-1))) + return copytext_char(input,1,((blocksize*blocknumber)-(blocksize-1))) /proc/getrightblocks(input,blocknumber,blocksize) if(blocknumber < (length(input)/blocksize)) - return copytext(input,blocksize*blocknumber+1,length(input)+1) + return copytext_char(input,blocksize*blocknumber+1,length(input)+1) /proc/getblock(input, blocknumber, blocksize=DNA_BLOCK_SIZE) - return copytext(input, blocksize*(blocknumber-1)+1, (blocksize*blocknumber)+1) + return copytext_char(input, blocksize*(blocknumber-1)+1, (blocksize*blocknumber)+1) /proc/setblock(istring, blocknumber, replacement, blocksize=DNA_BLOCK_SIZE) if(!istring || !blocknumber || !replacement || !blocksize) diff --git a/code/datums/emotes.dm b/code/datums/emotes.dm index 599c492d4c..e653e3e36b 100644 --- a/code/datums/emotes.dm +++ b/code/datums/emotes.dm @@ -18,6 +18,7 @@ var/list/mob_type_ignore_stat_typecache var/stat_allowed = CONSCIOUS var/static/list/emote_list = list() + var/static/regex/stop_bad_mime = regex(@"says|exclaims|yells|asks") /datum/emote/New() if(key_third_person) diff --git a/code/datums/helper_datums/getrev.dm b/code/datums/helper_datums/getrev.dm index 420602cc7f..7d040a4982 100644 --- a/code/datums/helper_datums/getrev.dm +++ b/code/datums/helper_datums/getrev.dm @@ -43,7 +43,7 @@ for(var/line in testmerge) var/datum/tgs_revision_information/test_merge/tm = line var/cm = tm.pull_request_commit - var/details = ": '" + html_encode(tm.title) + "' by " + html_encode(tm.author) + " at commit " + html_encode(copytext(cm, 1, min(length(cm), 11))) + var/details = ": '" + html_encode(tm.title) + "' by " + html_encode(tm.author) + " at commit " + html_encode(copytext_char(cm, 1, 11)) if(details && findtext(details, "\[s\]") && (!usr || !usr.client.holder)) continue . += "#[tm.number][details]
" @@ -57,11 +57,11 @@ // Round ID if(GLOB.round_id) msg += "Round ID: [GLOB.round_id]" - + msg += "BYOND Version: [world.byond_version].[world.byond_build]" if(DM_VERSION != world.byond_version || DM_BUILD != world.byond_build) msg += "Compiled with BYOND Version: [DM_VERSION].[DM_BUILD]" - + // Revision information var/datum/getrev/revdata = GLOB.revdata msg += "Server revision compiled on: [revdata.date]" diff --git a/code/datums/holocall.dm b/code/datums/holocall.dm index 5a4600432d..72fe6f5a1c 100644 --- a/code/datums/holocall.dm +++ b/code/datums/holocall.dm @@ -257,8 +257,8 @@ var/splitpoint = findtext(prepared_line," ") if(!splitpoint) continue - var/command = copytext(prepared_line,1,splitpoint) - var/value = copytext(prepared_line,splitpoint+1) + var/command = copytext(prepared_line, 1, splitpoint) + var/value = copytext(prepared_line, splitpoint + length(prepared_line[splitpoint])) switch(command) if("DELAY") var/delay_value = text2num(value) diff --git a/code/datums/martial.dm b/code/datums/martial.dm index c8caa853c3..cf2adfce8c 100644 --- a/code/datums/martial.dm +++ b/code/datums/martial.dm @@ -31,7 +31,7 @@ reset_streak(D) streak = streak+element if(length(streak) > max_streak_length) - streak = copytext(streak,2) + streak = copytext(streak, 1 + length(streak[1])) return /datum/martial_art/proc/reset_streak(mob/living/carbon/human/new_target) diff --git a/code/datums/mind.dm b/code/datums/mind.dm index f4e675d98b..a3c5979b6e 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -139,7 +139,7 @@ SEND_SIGNAL(new_character, COMSIG_MOB_ON_NEW_MIND) /datum/mind/proc/store_memory(new_text) - if((length(memory) + length(new_text)) <= MAX_MESSAGE_LEN) + if((length_char(memory) + length_char(new_text)) <= MAX_MESSAGE_LEN) memory += "[new_text]
" /datum/mind/proc/wipe_memory() @@ -409,7 +409,7 @@ assigned_role = new_role else if (href_list["memory_edit"]) - var/new_memo = copytext(sanitize(input("Write new memory", "Memory", memory) as null|message),1,MAX_MESSAGE_LEN) + var/new_memo = stripped_multiline_input(usr, "Write new memory", "Memory", memory, MAX_MESSAGE_LEN) if (isnull(new_memo)) return memory = new_memo diff --git a/code/datums/mutations.dm b/code/datums/mutations.dm index f689ff903e..6397bbe66b 100644 --- a/code/datums/mutations.dm +++ b/code/datums/mutations.dm @@ -32,9 +32,9 @@ GLOBAL_LIST_EMPTY(mutations_list) /datum/mutation/human/proc/set_se(se_string, on = 1) if(!se_string || length(se_string) < DNA_STRUC_ENZYMES_BLOCKS * DNA_BLOCK_SIZE) return - var/before = copytext(se_string, 1, ((dna_block - 1) * DNA_BLOCK_SIZE) + 1) + var/before = copytext_char(se_string, 1, ((dna_block - 1) * DNA_BLOCK_SIZE) + 1) var/injection = num2hex(on ? rand(lowest_value, (256 * 16) - 1) : rand(0, lowest_value - 1), DNA_BLOCK_SIZE) - var/after = copytext(se_string, (dna_block * DNA_BLOCK_SIZE) + 1, 0) + var/after = copytext_char(se_string, (dna_block * DNA_BLOCK_SIZE) + 1, 0) return before + injection + after /datum/mutation/human/proc/set_block(mob/living/carbon/owner, on = 1) diff --git a/code/datums/verbs.dm b/code/datums/verbs.dm index 442997288a..39afde14d0 100644 --- a/code/datums/verbs.dm +++ b/code/datums/verbs.dm @@ -88,8 +88,8 @@ var/list/entry = list() entry["parent"] = "[type]" entry["name"] = verbpath.desc - if (copytext(verbpath.name,1,2) == "@") - entry["command"] = copytext(verbpath.name,2) + if (verbpath.name[1] == "@") + entry["command"] = copytext(verbpath.name, length(verbpath.name[1]) + 1) else entry["command"] = replacetext(verbpath.name, " ", "-") diff --git a/code/datums/wires/_wires.dm b/code/datums/wires/_wires.dm index fab5a1313c..e1cfe3a4c0 100644 --- a/code/datums/wires/_wires.dm +++ b/code/datums/wires/_wires.dm @@ -118,7 +118,7 @@ return TRUE /datum/wires/proc/is_dud(wire) - return dd_hasprefix(wire, WIRE_DUD_PREFIX) + return findtext(wire, WIRE_DUD_PREFIX) /datum/wires/proc/is_dud_color(color) return is_dud(get_wire(color)) diff --git a/code/game/machinery/computer/cloning.dm b/code/game/machinery/computer/cloning.dm index 90969bf4a1..4d21ae77b0 100644 --- a/code/game/machinery/computer/cloning.dm +++ b/code/game/machinery/computer/cloning.dm @@ -482,7 +482,7 @@ R.fields["ckey"] = mob_occupant.ckey R.fields["name"] = mob_occupant.real_name - R.fields["id"] = copytext(md5(mob_occupant.real_name), 2, 6) + R.fields["id"] = copytext_char(md5(mob_occupant.real_name), 2, 6) R.fields["UE"] = dna.unique_enzymes R.fields["UI"] = dna.uni_identity R.fields["SE"] = dna.struc_enzymes diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm index 1bc8a82147..59574bc603 100755 --- a/code/game/machinery/computer/communications.dm +++ b/code/game/machinery/computer/communications.dm @@ -443,7 +443,7 @@ var/dat = "" if(SSshuttle.emergency.mode == SHUTTLE_CALL) var/timeleft = SSshuttle.emergency.timeLeft() - dat += "Emergency shuttle\n
\nETA: [timeleft / 60 % 60]:[add_zero(num2text(timeleft % 60), 2)]" + dat += "Emergency shuttle\n
\nETA: [timeleft / 60 % 60]:[add_leading(num2text(timeleft % 60), 2, "0")]" var/datum/browser/popup = new(user, "communications", "Communications Console", 400, 500) diff --git a/code/game/machinery/computer/dna_console.dm b/code/game/machinery/computer/dna_console.dm index 7330ae26e7..9cf988884f 100644 --- a/code/game/machinery/computer/dna_console.dm +++ b/code/game/machinery/computer/dna_console.dm @@ -274,13 +274,18 @@ var/max_line_len = 7*DNA_BLOCK_SIZE if(viable_occupant) temp_html += "
1
" - var/len = length(viable_occupant.dna.uni_identity) - for(var/i=1, i<=len, i++) - temp_html += "[copytext(viable_occupant.dna.uni_identity,i,i+1)]" - if ((i % max_line_len) == 0) + var/char = "" + var/ui_text = viable_occupant.dna.uni_identity + var/len_byte = length(ui_text) + var/char_it = 0 + for(var/byte_it = 1, byte_it <= len_byte, byte_it += length(char)) + char_it++ + char = ui_text[byte_it] + temp_html += "[char]" + if((char_it % max_line_len) == 0) temp_html += "
" - if((i % DNA_BLOCK_SIZE) == 0 && i < len) - temp_html += "
[(i / DNA_BLOCK_SIZE) + 1]
" + if((char_it % DNA_BLOCK_SIZE) == 0 && byte_it < len_byte) + temp_html += "
[(char_it / DNA_BLOCK_SIZE) + 1]
" else temp_html += "----" temp_html += "

" @@ -288,13 +293,16 @@ temp_html += "
Structural Enzymes:
" if(viable_occupant) temp_html += "
1
" - var/len = length(viable_occupant.dna.struc_enzymes) - for(var/i=1, i<=len, i++) - temp_html += "[copytext(viable_occupant.dna.struc_enzymes,i,i+1)]" - if ((i % max_line_len) == 0) + var/char = "" + var/ui_text = viable_occupant.dna.uni_identity + var/len_byte = length(ui_text) + var/char_it = 0 + for(var/byte_it = 1, byte_it <= len_byte, byte_it += length(char)) + temp_html += "[char]" + if((char_it % max_line_len) == 0) temp_html += "
" - if((i % DNA_BLOCK_SIZE) == 0 && i < len) - temp_html += "
[(i / DNA_BLOCK_SIZE) + 1]
" + if((char_it % DNA_BLOCK_SIZE) == 0 && byte_it < len_byte) + temp_html += "
[(char_it / DNA_BLOCK_SIZE) + 1]
" else temp_html += "----" temp_html += "
" @@ -465,7 +473,7 @@ viable_occupant.radiation += (RADIATION_IRRADIATION_MULTIPLIER*radduration*radstrength)/(connected.damage_coeff ** 2) //Read comment in "transferbuffer" section above for explanation switch(href_list["task"]) //Same thing as there but values are even lower, on best part they are about 0.0*, effectively no damage if("pulseui") - var/len = length(viable_occupant.dna.uni_identity) + var/len = length_char(viable_occupant.dna.uni_identity) num = WRAP(num, 1, len+1) num = randomize_radiation_accuracy(num, radduration + (connected.precision_coeff ** 2), len) //Each manipulator level above 1 makes randomization as accurate as selected time + manipulator lvl^2 //Value is this high for the same reason as with laser - not worth the hassle of upgrading if the bonus is low @@ -473,12 +481,12 @@ var/subblock = num - block*DNA_BLOCK_SIZE last_change = "UI #[block]-[subblock]; " - var/hex = copytext(viable_occupant.dna.uni_identity, num, num+1) + var/hex = copytext_char(viable_occupant.dna.uni_identity, num, num+1) last_change += "[hex]" hex = scramble(hex, radstrength, radduration) last_change += "->[hex]" - viable_occupant.dna.uni_identity = copytext(viable_occupant.dna.uni_identity, 1, num) + hex + copytext(viable_occupant.dna.uni_identity, num+1, 0) + viable_occupant.dna.uni_identity = copytext_char(viable_occupant.dna.uni_identity, 1, num) + hex + copytext_char(viable_occupant.dna.uni_identity, num + 1) viable_occupant.updateappearance(mutations_overlay_update=1) if("pulsese") var/len = length(viable_occupant.dna.struc_enzymes) @@ -489,12 +497,12 @@ var/subblock = num - block*DNA_BLOCK_SIZE last_change = "SE #[block]-[subblock]; " - var/hex = copytext(viable_occupant.dna.struc_enzymes, num, num+1) + var/hex = copytext_char(viable_occupant.dna.struc_enzymes, num, num+1) last_change += "[hex]" hex = scramble(hex, radstrength, radduration) last_change += "->[hex]" - viable_occupant.dna.struc_enzymes = copytext(viable_occupant.dna.struc_enzymes, 1, num) + hex + copytext(viable_occupant.dna.struc_enzymes, num+1, 0) + viable_occupant.dna.struc_enzymes = copytext_char(viable_occupant.dna.struc_enzymes, 1, num) + hex + copytext_char(viable_occupant.dna.struc_enzymes, num + 1) viable_occupant.domutcheck() else current_screen = "mainmenu" diff --git a/code/game/machinery/computer/prisoner/management.dm b/code/game/machinery/computer/prisoner/management.dm index 653f6bf48b..496e14b8f1 100644 --- a/code/game/machinery/computer/prisoner/management.dm +++ b/code/game/machinery/computer/prisoner/management.dm @@ -125,7 +125,7 @@ to_chat(usr, "Unauthorized access.") else if(href_list["warn"]) - var/warning = copytext(sanitize(input(usr,"Message:","Enter your message here!","")),1,MAX_MESSAGE_LEN) + var/warning = stripped_input(usr, "Message:", "Enter your message here!", "", MAX_MESSAGE_LEN) if(!warning) return var/obj/item/implant/I = locate(href_list["warn"]) in GLOB.tracked_implants diff --git a/code/game/machinery/computer/security.dm b/code/game/machinery/computer/security.dm index aabb1fe408..dbdef571e0 100644 --- a/code/game/machinery/computer/security.dm +++ b/code/game/machinery/computer/security.dm @@ -544,7 +544,7 @@ What a mess.*/ switch(href_list["field"]) if("name") if(istype(active1, /datum/data/record) || istype(active2, /datum/data/record)) - var/t1 = copytext(sanitize(input("Please input name:", "Secure. records", active1.fields["name"], null) as text),1,MAX_MESSAGE_LEN) + var/t1 = stripped_input(usr, "Please input name:", "Secure. records", active1.fields["name"], MAX_MESSAGE_LEN) if(!canUseSecurityRecordsConsole(usr, t1, a1)) return if(istype(active1, /datum/data/record)) diff --git a/code/game/machinery/doors/brigdoors.dm b/code/game/machinery/doors/brigdoors.dm index beaf47d0a3..a513d7feed 100644 --- a/code/game/machinery/doors/brigdoors.dm +++ b/code/game/machinery/doors/brigdoors.dm @@ -168,7 +168,7 @@ if(timing) var/disp1 = id var/time_left = time_left(seconds = TRUE) - var/disp2 = "[add_zero(num2text((time_left / 60) % 60),2)]~[add_zero(num2text(time_left % 60), 2)]" + var/disp2 = "[add_leading(num2text((time_left / 60) % 60), 2, "0")]:[add_leading(num2text(time_left % 60), 2, "0")]" if(length(disp2) > CHARS_PER_LINE) disp2 = "Error" update_display(disp1, disp2) diff --git a/code/game/machinery/magnet.dm b/code/game/machinery/magnet.dm index 9a10ede1ac..b010f77cac 100644 --- a/code/game/machinery/magnet.dm +++ b/code/game/machinery/magnet.dm @@ -306,7 +306,7 @@ if(speed <= 0) speed = 1 if("setpath") - var/newpath = copytext(sanitize(input(usr, "Please define a new path!",,path) as text|null),1,MAX_MESSAGE_LEN) + var/newpath = stripped_input(usr, "Please define a new path!", "New Path", path, MAX_MESSAGE_LEN) if(newpath && newpath != "") moving = 0 // stop moving path = newpath @@ -368,13 +368,19 @@ // Generates the rpath variable using the path string, think of this as "string2list" // Doesn't use params2list() because of the akward way it stacks entities rpath = list() // clear rpath - var/maximum_character = min( 50, length(path) ) // chooses the maximum length of the iterator. 50 max length + var/maximum_characters = 50 - for(var/i=1, i<=maximum_character, i++) // iterates through all characters in path + var/lentext = length(path) + var/nextchar = "" + var/charcount = 0 - var/nextchar = copytext(path, i, i+1) // find next character - - if(!(nextchar in list(";", "&", "*", " "))) // if char is a separator, ignore - rpath += copytext(path, i, i+1) // else, add to list + for(var/i = 1, i <= lentext, i += length(nextchar)) // iterates through all characters in path + nextchar = path[i] // find next character + if(nextchar in list(";", "&", "*", " ")) // if char is a separator, ignore + continue + rpath += nextchar // else, add to list // there doesn't HAVE to be separators but it makes paths syntatically visible + charcount++ + if(charcount >= maximum_characters) + break diff --git a/code/game/machinery/navbeacon.dm b/code/game/machinery/navbeacon.dm index 5a567886b8..93c94ae8b6 100644 --- a/code/game/machinery/navbeacon.dm +++ b/code/game/machinery/navbeacon.dm @@ -62,7 +62,7 @@ var/index = findtext(e, "=") // format is "key=value" if(index) var/key = copytext(e, 1, index) - var/val = copytext(e, index+1) + var/val = copytext(e, index + length(e[index])) codes[key] = val else codes[e] = "1" @@ -167,7 +167,7 @@ Transponder Codes: