diff --git a/src/dg_olc.c b/src/dg_olc.c index 92f7268..b0e2cba 100644 --- a/src/dg_olc.c +++ b/src/dg_olc.c @@ -260,6 +260,228 @@ static void trigedit_disp_types(struct descriptor_data *d) } +/**************************************************************************************** + DG Scripts Code Syntax Highlighting + Created by Victor Almeida (aka Stoneheart) in Brazil + from BrMUD:Tormenta www.tormenta.com.br (mudbrasil@gmail.com) + + License: Attribution 4.0 International (CC BY 4.0) + http://creativecommons.org/licenses/by/4.0/ + + You are free to: + Share — copy and redistribute the material in any medium or format + Adapt — remix, transform, and build upon the material for any purpose, even commercially. + + The licensor cannot revoke these freedoms as long as you follow the license terms. + + Under the following terms: + Attribution — You must give appropriate credit, provide a link to the license, and indicate + if changes were made. You may do so in any reasonable manner, but not in any way that + suggests the licensor endorses you or your use. + *****************************************************************************************/ + +// Change a string for another without memory bugs +char *str_replace(const char *string, const char *substr, const char *replacement) { + char *tok = NULL; + char *newstr = NULL; + char *oldstr = NULL; + char *head = NULL; + + // if either substr or replacement is NULL, duplicate string a let caller handle it + if (substr == NULL || replacement == NULL) { + return strdup (string); + } + + newstr = strdup (string); + head = newstr; + while ((tok = strstr(head, substr))) { + oldstr = newstr; + newstr = malloc(strlen(oldstr) - strlen(substr) + strlen (replacement) + 1); + // Failed to alloc mem, free old string and return NULL + if (newstr == NULL) { + free (oldstr); + return NULL; + } + memcpy (newstr, oldstr, tok - oldstr); + memcpy (newstr + (tok - oldstr), replacement, strlen (replacement)); + memcpy (newstr + (tok - oldstr) + strlen(replacement), tok + strlen (substr), strlen (oldstr) - strlen (substr) - (tok - oldstr)); + memset (newstr + strlen (oldstr) - strlen(substr) + strlen (replacement) , 0, 1 ); + + // move back head right after the last replacement + head = newstr + (tok - oldstr) + strlen( replacement); + free (oldstr); + } + + return newstr; +} + +// You can easily change the color code (\tn) to the old one (@n or &n) +#define SYNTAX_TERMS 49 +const char *syntax_color_replacement[SYNTAX_TERMS][2] = +{ + // script logic (10) + { "if", "\tcif\tn" }, // 0 + { "elseif", "\tcelseif\tn" }, + { "else", "\tcelse\tn" }, + { "end", "\tcend\tn" }, + { "switch", "\tcswitch\tn" }, + { "case", "\tccase\tY" }, + { "default", "\tcdefault\tn" }, + { "break", "\tcbreak\tn" }, + { "while", "\tcwhile\tn" }, + { "done", "\tcdone\tn" }, + // commands (15) + { "eval ", "\tceval\tY " }, //10 + { "nop ", "\tcnop\tY " }, + { "extract ", "\tcextract\tY " }, + { "dg_letter ", "\tcdg_letter\tY " }, + { "makeuid ", "\tcmakeuid\tY " }, + { "dg_cast ", "\tcdg_cast\tY " }, + { "dg_affect ", "\tcdg_affect\tY " }, + { "global ", "\tcglobal\tY " }, + { "context ", "\tccontext\tY " }, + { "remote ", "\tcremot\tce\tY " }, + { "rdelete ", "\tcrdelete\tY " }, // 20 + { "set ", "\tcset\tY " }, + { "unset ", "\tcunset\tY " }, + { "attach ", "\tcattach\tY " }, + { "detach ", "\tcdetach\tY " }, + // stopping (3) + { "wait", "\trwait" }, + { "return", "\trreturn" }, + { "halt", "\trhalt" }, + // operands (12) + { "||", "\tc||\tY" }, + { "&&", "\tc&&\tY" }, + { "==", "\tc==\tY" }, // 30 + { "!=", "\tc!=\tY" }, + { "<=", "\tc<=\tY" }, + { ">=", "\tc>=\tY" }, + { "< ", "\tc< \tY" }, + { "> ", "\tc> \tY" }, + { "/=", "\tc/=\tY" }, + { "!", "\tc!\tn" }, + { "(", "\tc(\tY" }, + { ")", "\tc)\tn" }, + // corrective (4) + { "\tc!\tn=", "\tc!=\tY" }, // 40 + { "%s\tcend\tn%", "\tm%\tosend%\tn" }, + { "%\tc)", "\tm%\tc)" }, + { ")\tn%", ")\tm%"}, + // variables (5) + { "% ", "\tm%\tn " }, + { "%,", "\tm%\tn," }, + { "%.", "\tm%\tn." }, + { "%:", "\tm%\tn:" }, + { "%", "\tm%\to" } // 48 +}; + +// Here you can include more commands usually used in your triggers +#define COMMAND_TERMS 35 +const char *command_color_replacement[COMMAND_TERMS][2] = +{ + // Mob specific commands (25) + { "marena", "\tcmarena\tn" }, // 0 + { "masound", "\tcmasound\tn" }, + { "mkill", "\tcmkill\tn" }, + { "mjunk", "\tcmjunk\tn" }, + { "mdamage", "\tcmdamage\tn" }, + { "mdoor", "\tcmdoor\tn" }, + { "mecho", "\tcmecho\tn" }, + { "mrecho", "\tcmrecho\tn" }, + { "mechoaround", "\tcmechoaround\tn" }, + { "msend", "\tcmsend\tn" }, + { "mload", "\tcmload\tn" }, // 10 + { "mpurge", "\tcmpurge\tn" }, + { "mgoto", "\tcmgoto\tn" }, + { "mteleport", "\tcmteleport\tn" }, + { "mforce", "\tcmforce\tn" }, + { "mhunt", "\tcmhunt\tn" }, + { "mremember", "\tcmremember\tn" }, + { "mforget", "\tcmforget\tn" }, + { "mtransform", "\tcmtransform\tn" }, + { "mzoneecho", "\tcmzoneecho\tn" }, + { "mfollow", "\tcmfollow\tn" }, // 20 + { "mquest", "\tcmquest\tn" }, + { "malign", "\tcmalign\tn" }, + { "mcast", "\tcmcast\tn" }, + { "mdismiss", "\tcmdismiss\tn" }, + // common commands (10) + { "drop ", "\tcdrop \tn" }, + { "emote ", "\tcemote \tn" }, + { "give ", "\tcgive \tn" }, + { "say ", "\tcsay \tn" }, + { "tell ", "\tctell \tn" }, + { "unlock ", "\tcunlock \tn" }, // 30 + { "lock ", "\tclock \tn" }, + { "open ", "\tcopen \tn" }, + { "close ", "\tcclose \tn" }, + { "junk ", "\tcjunk \tn" } // 34 +}; + + +void script_syntax_highlighting(struct descriptor_data *d, char *string) +{ + ACMD(do_action); + char buffer[MAX_STRING_LENGTH] = ""; + char *newlist, *curtok; + int i; + + // Parse script text line by line + newlist = strdup(string); + for (curtok = strtok(newlist, "\r\n"); curtok; curtok = strtok(NULL, "\r\n")) { + char *line = strdup(curtok); + bool comment = FALSE; + + // Find if is a comment + for (i=0;i <= strlen(line);i++) { + // skip initial spaces + if (strncmp(&line[i], " ", 1) == 0) { + continue; + } + // is a comment, highlight + if (strncmp(&line[i], "*", 1) == 0) { + line = str_replace(line, "*", "\tg*"); + comment = TRUE; + break; + } + // not a comment + else { + comment = FALSE; + break; + } + } + + // Highlight lines + if (!comment) { + // Syntax replacement + for (i=0;i <= SYNTAX_TERMS;i++) { + line = str_replace(line, syntax_color_replacement[i][0], syntax_color_replacement[i][1]); + } + + // Commands replacement + for (i=0;i <= COMMAND_TERMS;i++) { + line = str_replace(line, command_color_replacement[i][0], command_color_replacement[i][1]); + } + + // Socials replacement (experimental) + int cmd; + for (cmd = 0; *complete_cmd_info[cmd].command != '\n'; cmd++) { + if (complete_cmd_info[cmd].command_pointer == do_action) { + char replace_social[MAX_INPUT_LENGTH]; + sprintf(replace_social, "\tc%s\tn", complete_cmd_info[cmd].command); + line = str_replace(line, complete_cmd_info[cmd].command, replace_social); + } + } + } + + sprintf(buffer, "%s%s\tn\r\n", buffer, line); + } + + page_string(d, buffer, TRUE); +} +/****************************************************************************************/ + void trigedit_parse(struct descriptor_data *d, char *arg) { int i = 0; @@ -302,7 +524,8 @@ void trigedit_parse(struct descriptor_data *d, char *arg) write_to_output(d, "Enter trigger commands: (/s saves /h for help)\r\n\r\n"); d->backstr = NULL; if (OLC_STORAGE(d)) { - write_to_output(d, "%s", OLC_STORAGE(d)); + clear_screen(d); + script_syntax_highlighting(d, OLC_STORAGE(d)); d->backstr = strdup(OLC_STORAGE(d)); } d->str = &OLC_STORAGE(d);