/**************************************************************************** * ^ +----- | / ^ ^ | | +-\ * * / \ | | / |\ /| | | | \ * * / \ +--- |< | \ / | | | | | * * /-----\ | | \ | v | | | | / * * / \ | | \ | | +-----+ +-/ * **************************************************************************** * AFKMud Copyright 1997-2005 by Roger Libiez (Samson), * * Levi Beckerson (Whir), Michael Ward (Tarl), Erik Wolfe (Dwip), * * Cameron Carroll (Cam), Cyberfox, Karangi, Rathian, Raine, and Adjani. * * All Rights Reserved. * * Registered with the United States Copyright Office. TX 5-877-286 * * * * External contributions from Xorith, Quixadhal, Zarius, and many others. * * * * Original SMAUG 1.4a written by Thoric (Derek Snider) with Altrag, * * Blodkai, Haus, Narn, Scryn, Swordbearer, Tricops, Gorog, Rennard, * * Grishnakh, Fireblade, and Nivek. * * * * Original MERC 2.1 code by Hatchet, Furey, and Kahn. * * * * Original DikuMUD code by: Hans Staerfeldt, Katja Nyboe, Tom Madsen, * * Michael Seifert, and Sebastian Hammer. * **************************************************************************** * Color Module -- Allow user customizable Colors. * * --Matthew * * Enhanced ANSI parser by Samson * ****************************************************************************/ /* * The following instructions assume you know at least a little bit about * coding. I firmly believe that if you can't code (at least a little bit), * you don't belong running a mud. So, with that in mind, I don't hold your * hand through these instructions. * * You may use this code provided that: * * 1) You understand that the authors _DO NOT_ support this code * Any help you need must be obtained from other sources. The * authors will ignore any and all requests for help. * 2) You will mention the authors if someone asks about the code. * You will not take credit for the code, but you can take credit * for any enhancements you make. * 3) This message remains intact. * * If you would like to find out how to send the authors large sums of money, * you may e-mail the following address: * * Matthew Bafford & Christopher Wigginton * wiggy@mudservices.com */ /* * To add new color types: * * 1. Edit color.h, and: * 1. Add a new AT_ define. * 2. Increment MAX_COLORS by however many AT_'s you added. * 2. Edit color.c and: * 1. Add the name(s) for your new color(s) to the end of the pc_displays array. * 2. Add the default color(s) to the end of the default_set array. */ #include <ctype.h> #include <stdio.h> #include <stdarg.h> #include <string.h> #include <dirent.h> #include "h/mud.h" int count_mxp_tags(const int bMXP, const char *txt, int length); void convert_mxp_tags(const int bMXP, char *dest, const char *src, int length); const char *const pc_displays[MAX_COLORS] = { "lblue", "orange", "cyan", "red", "blue", "white", "blood", "dblue", "grey", "green", "pink", "dgreen", "purple", "dgrey", "yellow", "black", "blink", // 17 "bdred", "bdgreen", "bdorange", "bdblue", "bpurple", "bcyan", "bgrey", "bdgrey", "bred", "bgreen", "byellow", "bblue", "bpink", "blblue", "bwhite", "plain", "action", "say", "chat", "yells", "tell", "hit", "hitme", // 40 "immortal", "hurt", "falling", "danger", "magic", "consider", "report", "poison", "social", "dying", "dead", "skill", "carnage", "damage", "fleeing", "rmname", // 56 "rmdesc", "objects", "people", "list", "bye", "gold", "gtells", "note", "hungry", "thirsty", "fire", "sober", "wearoff", "exits", "score", "reset", // 72 "log", "die_msg", "wartalk", "arena", "muse", "think", "aflags", "who", // 80 "racetalk", "ignore", "whisper", "divider", "morph", "shout", "rflags", "stype", "aname", "auction", "score2", "score3", "score4", "who2", "who3", "who4", "intermud", "helpfiles", "who5", "score5", // 100 "who6", "who7", "prac", "prac2", "prac3", "prac4", "mxpprompt", "guildtalk", "board", "board2", "board3" }; /* All defaults are set to Alsherok default scheme, if you don't like it, change it around to suite your own needs - Samson */ const short default_set[MAX_COLORS] = { AT_LBLUE, AT_ORANGE, AT_CYAN, AT_RED, /* 3 */ AT_BLUE, AT_WHITE, AT_BLOOD, AT_DBLUE, /* 7 */ AT_GREY, AT_GREEN, AT_PINK, AT_DGREEN, /* 11 */ AT_PURPLE, AT_DGREY, AT_YELLOW, AT_BLACK, /* 15 */ AT_BLACK_BLINK, AT_BLOOD_BLINK, AT_DGREEN_BLINK, AT_ORANGE_BLINK, /* 19 */ AT_DBLUE_BLINK, AT_PURPLE_BLINK, AT_CYAN_BLINK, AT_GREY_BLINK, /* 23 */ AT_DGREY_BLINK, AT_RED_BLINK, AT_GREEN_BLINK, AT_YELLOW_BLINK, /* 27 */ AT_BLUE_BLINK, AT_PINK_BLINK, AT_LBLUE_BLINK, AT_WHITE_BLINK, /* 31 */ AT_GREY, AT_GREY, AT_BLUE, /* 34 */ AT_GREEN, AT_LBLUE, AT_WHITE, AT_GREY, /* 38 */ AT_GREY, AT_YELLOW, AT_GREY, AT_GREY, /* 42 */ AT_GREY, AT_BLUE, AT_GREY, AT_GREY, /* 46 */ AT_DGREEN, AT_CYAN, AT_GREY, AT_GREY, /* 50 */ AT_BLUE, AT_GREY, AT_GREY, AT_GREY, /* 54 */ AT_RED, AT_GREY, AT_BLUE, AT_PINK, /* 58 */ AT_GREY, AT_GREY, AT_YELLOW, AT_GREY, /* 62 */ AT_GREY, AT_ORANGE, AT_BLUE, AT_RED, /* 66 */ AT_GREY, AT_GREY, AT_GREEN, AT_DGREEN, /* 70 */ AT_DGREEN, AT_ORANGE, AT_GREY, AT_RED, /* 74 */ AT_GREY, AT_DGREEN, AT_RED, AT_BLUE, /* 78 */ AT_RED, AT_CYAN, AT_YELLOW, AT_PINK, /* 82 */ AT_DGREEN, AT_PINK, AT_WHITE, AT_BLUE, /* 86 */ AT_BLUE, AT_BLUE, AT_GREEN, AT_GREY, /* 90 */ AT_GREEN, AT_GREEN, AT_YELLOW, AT_DGREY, /* 94 */ AT_GREEN, AT_PINK, AT_DGREEN, AT_CYAN, /* 98 */ AT_RED, AT_WHITE, AT_BLUE, AT_DGREEN, /* 102 */ AT_CYAN, AT_BLOOD, AT_RED, AT_DGREEN, /* 106 */ AT_GREEN, AT_GREY, AT_GREEN, AT_WHITE /* 110 */ }; const char *const valid_color[] = { "lblue", "orange", "cyan", "red", "blue", "white", "blood", "dblue", "grey", "green", "pink", "dgreen", "purple", "dgrey", "yellow", "black", "\0" }; void show_colorthemes(CHAR_DATA *ch) { DIR *dp; struct dirent *dentry; int count = 0, col = 0; send_to_pager("&YThe following themes are available:\r\n", ch); dp = opendir(COLOR_DIR); dentry = readdir(dp); while(dentry) { /* * Added by Tarl 3 Dec 02 because we are now using CVS */ if(!str_cmp(dentry->d_name, "CVS")) { dentry = readdir(dp); continue; } if(dentry->d_name[0] != '.') { ++count; pager_printf(ch, "%s%-15.15s", color_str(AT_PLAIN, ch), dentry->d_name); if(++col % 6 == 0) send_to_pager("\r\n", ch); } dentry = readdir(dp); } closedir(dp); if(count == 0) send_to_pager("No themes defined yet.\r\n", ch); if(col % 6 != 0) send_to_pager("\r\n", ch); return; } void show_colors(CHAR_DATA *ch) { short count; send_to_pager("&CSyntax: color [color type] [color] | default\r\n", ch); send_to_pager("&CSyntax: color _reset_ (Resets all colors to default set)\r\n", ch); send_to_pager("&CSyntax: color _all_ [color] (Sets all color types to [color])\r\n", ch); send_to_pager("&CSyntax: color theme [name] (Sets all color types to a defined theme)\r\n", ch); if(ch->level >= LEVEL_AJ_COLONEL) { send_to_pager("&CSyntax: color savetheme [name]\r\n", ch); } send_to_pager("&W****************************[ AVAILABLE COLORS ]****************************\r\n", ch); for(count = 0; count < 16; ++count) { if((count % 8) == 0 && count != 0) { send_to_pager("\r\n", ch); } pager_printf(ch, "%s%-10s", color_str(count, ch), pc_displays[count]); } send_to_pager("\r\r\n\n&W******************************[ COLOR TYPES ]******************************\r\n", ch); for(count = 32; count < MAX_COLORS; ++count) { if((count % 8) == 0 && count != 32) { send_to_pager("\r\n", ch); } pager_printf(ch, "%s%-10s%s", color_str(count, ch), pc_displays[count], ANSI_RESET); } send_to_pager("\r\r\n\n", ch); show_colorthemes(ch); return; } void reset_colors(CHAR_DATA *ch) { int x; if(!IS_NPC(ch)) { char filename[256]; FILE *fp; int max_colors = 0; snprintf(filename, 256, "%s%s", COLOR_DIR, "default"); if(!(fp = FileOpen(filename, "r"))) { memcpy(&ch->colors, &default_set, sizeof(default_set)); return; } while(!feof(fp)) { char *word = fread_word(fp); if(!str_cmp(word, "MaxColors")) { int temp = fread_number(fp); max_colors = UMIN(temp, MAX_COLORS); continue; } if(!str_cmp(word, "Colors")) { for(x = 0; x < max_colors; ++x) ch->colors[x] = fread_number(fp); fread_to_eol(fp); continue; } if(!str_cmp(word, "End")) { FileClose(fp); fp = NULL; return; } } FileClose(fp); fp = NULL; return; } else log_printf("%s: Attempting to reset NPC colors: %s", __FUNCTION__, ch->short_descr); } void do_color(CHAR_DATA *ch, char *argument) { bool dMatch, cMatch; short count = 0, y = 0; int x; char arg[MAX_INPUT_LENGTH], arg2[MAX_INPUT_LENGTH]; char log_buf[MAX_STRING_LENGTH]; dMatch = FALSE; cMatch = FALSE; if(IS_NPC(ch)) { send_to_pager("Only PC's can change colors.\r\n", ch); return; } if(!argument || argument[0] == '\0') { show_colors(ch); return; } argument = one_argument(argument, arg); if(!str_cmp(arg, "savetheme") && IS_IMMORTAL(ch)) { FILE *fp; char filename[256]; if(!argument || argument[0] == '\0') { send_to_char("You must specify a name for this theme to save it.\r\n", ch); return; } if(strstr(argument, ".") || strstr(argument, "/") || strstr(argument, "\\")) { send_to_char("Invalid theme name.\r\n", ch); return; } snprintf(filename, sizeof(filename), "%s%s", COLOR_DIR, argument); if(!(fp = FileOpen(filename, "w"))) { ch_printf(ch, "Unable to write to color file %s\r\n", filename); return; } fprintf(fp, "%s", "#COLORTHEME\n"); fprintf(fp, "Name %s~\n", argument); fprintf(fp, "MaxColors %d\n", MAX_COLORS); fprintf(fp, "%s", "Colors "); for(x = 0; x < MAX_COLORS; ++x) fprintf(fp, " %d", ch->colors[x]); fprintf(fp, "%s", "\nEnd\n"); FileClose(fp); fp = NULL; ch_printf(ch, "Color theme %s saved.\r\n", argument); return; } if(!str_cmp(arg, "theme")) { FILE *fp; char filename[256]; int max_colors = 0; if(!argument || argument[0] == '\0') { show_colorthemes(ch); return; } if(strstr(argument, ".") || strstr(argument, "/") || strstr(argument, "\\")) { send_to_char("Invalid theme.\r\n", ch); return; } snprintf(filename, sizeof(filename), "%s%s", COLOR_DIR, argument); if(!(fp = FileOpen(filename, "r"))) { ch_printf(ch, "There is no theme called %s.\r\n", argument); return; } while(!feof(fp)) { char *word = fread_word(fp); if(!str_cmp(word, "MaxColors")) { int temp = fread_number(fp); max_colors = UMIN(temp, MAX_COLORS); continue; } if(!str_cmp(word, "Colors")) { for(x = 0; x < max_colors; ++x) ch->colors[x] = fread_number(fp); fread_to_eol(fp); continue; } if(!str_cmp(word, "End")) { FileClose(fp); fp = NULL; ch_printf(ch, "Color theme has been changed to %s.\r\n", argument); save_char_obj(ch); return; } } FileClose(fp); fp = NULL; ch_printf(ch, "An error occured while trying to set color theme %s.\r\n", argument); return; } if(!str_cmp(arg, "ansitest")) { snprintf(log_buf, MAX_STRING_LENGTH, "%sBlack\r\n", ANSI_BLACK); write_to_buffer(ch->desc, log_buf, 0); snprintf(log_buf, MAX_STRING_LENGTH, "%sDark Red\r\n", ANSI_DRED); write_to_buffer(ch->desc, log_buf, 0); snprintf(log_buf, MAX_STRING_LENGTH, "%sDark Green\r\n", ANSI_DGREEN); write_to_buffer(ch->desc, log_buf, 0); snprintf(log_buf, MAX_STRING_LENGTH, "%sOrange/Brown\r\n", ANSI_ORANGE); write_to_buffer(ch->desc, log_buf, 0); snprintf(log_buf, MAX_STRING_LENGTH, "%sDark Blue\r\n", ANSI_DBLUE); write_to_buffer(ch->desc, log_buf, 0); snprintf(log_buf, MAX_STRING_LENGTH, "%sPurple\r\n", ANSI_PURPLE); write_to_buffer(ch->desc, log_buf, 0); snprintf(log_buf, MAX_STRING_LENGTH, "%sCyan\r\n", ANSI_CYAN); write_to_buffer(ch->desc, log_buf, 0); snprintf(log_buf, MAX_STRING_LENGTH, "%sGrey\r\n", ANSI_GREY); write_to_buffer(ch->desc, log_buf, 0); snprintf(log_buf, MAX_STRING_LENGTH, "%sDark Grey\r\n", ANSI_DGREY); write_to_buffer(ch->desc, log_buf, 0); snprintf(log_buf, MAX_STRING_LENGTH, "%sRed\r\n", ANSI_RED); write_to_buffer(ch->desc, log_buf, 0); snprintf(log_buf, MAX_STRING_LENGTH, "%sGreen\r\n", ANSI_GREEN); write_to_buffer(ch->desc, log_buf, 0); snprintf(log_buf, MAX_STRING_LENGTH, "%sYellow\r\n", ANSI_YELLOW); write_to_buffer(ch->desc, log_buf, 0); snprintf(log_buf, MAX_STRING_LENGTH, "%sBlue\r\n", ANSI_BLUE); write_to_buffer(ch->desc, log_buf, 0); snprintf(log_buf, MAX_STRING_LENGTH, "%sPink\r\n", ANSI_PINK); write_to_buffer(ch->desc, log_buf, 0); snprintf(log_buf, MAX_STRING_LENGTH, "%sLight Blue\r\n", ANSI_LBLUE); write_to_buffer(ch->desc, log_buf, 0); snprintf(log_buf, MAX_STRING_LENGTH, "%sWhite\r\n", ANSI_WHITE); write_to_buffer(ch->desc, log_buf, 0); snprintf(log_buf, MAX_STRING_LENGTH, "%sBlack\r\n", BLINK_BLACK); write_to_buffer(ch->desc, log_buf, 0); snprintf(log_buf, MAX_STRING_LENGTH, "%sDark Red\r\n", BLINK_DRED); write_to_buffer(ch->desc, log_buf, 0); snprintf(log_buf, MAX_STRING_LENGTH, "%sDark Green\r\n", BLINK_DGREEN); write_to_buffer(ch->desc, log_buf, 0); snprintf(log_buf, MAX_STRING_LENGTH, "%sOrange/Brown\r\n", BLINK_ORANGE); write_to_buffer(ch->desc, log_buf, 0); snprintf(log_buf, MAX_STRING_LENGTH, "%sDark Blue\r\n", BLINK_DBLUE); write_to_buffer(ch->desc, log_buf, 0); snprintf(log_buf, MAX_STRING_LENGTH, "%sPurple\r\n", BLINK_PURPLE); write_to_buffer(ch->desc, log_buf, 0); snprintf(log_buf, MAX_STRING_LENGTH, "%sCyan\r\n", BLINK_CYAN); write_to_buffer(ch->desc, log_buf, 0); snprintf(log_buf, MAX_STRING_LENGTH, "%sGrey\r\n", BLINK_GREY); write_to_buffer(ch->desc, log_buf, 0); snprintf(log_buf, MAX_STRING_LENGTH, "%sDark Grey\r\n", BLINK_DGREY); write_to_buffer(ch->desc, log_buf, 0); snprintf(log_buf, MAX_STRING_LENGTH, "%sRed\r\n", BLINK_RED); write_to_buffer(ch->desc, log_buf, 0); snprintf(log_buf, MAX_STRING_LENGTH, "%sGreen\r\n", BLINK_GREEN); write_to_buffer(ch->desc, log_buf, 0); snprintf(log_buf, MAX_STRING_LENGTH, "%sYellow\r\n", BLINK_YELLOW); write_to_buffer(ch->desc, log_buf, 0); snprintf(log_buf, MAX_STRING_LENGTH, "%sBlue\r\n", BLINK_BLUE); write_to_buffer(ch->desc, log_buf, 0); snprintf(log_buf, MAX_STRING_LENGTH, "%sPink\r\n", BLINK_PINK); write_to_buffer(ch->desc, log_buf, 0); snprintf(log_buf, MAX_STRING_LENGTH, "%sLight Blue\r\n", BLINK_LBLUE); write_to_buffer(ch->desc, log_buf, 0); snprintf(log_buf, MAX_STRING_LENGTH, "%sWhite\r\n", BLINK_WHITE); write_to_buffer(ch->desc, log_buf, 0); write_to_buffer(ch->desc, ANSI_RESET, 0); snprintf(log_buf, MAX_STRING_LENGTH, "%s%sBlack\r\n", ANSI_WHITE, BACK_BLACK); write_to_buffer(ch->desc, log_buf, 0); snprintf(log_buf, MAX_STRING_LENGTH, "%s%sDark Red\r\n", ANSI_BLACK, BACK_DRED); write_to_buffer(ch->desc, log_buf, 0); snprintf(log_buf, MAX_STRING_LENGTH, "%s%sDark Green\r\n", ANSI_BLACK, BACK_DGREEN); write_to_buffer(ch->desc, log_buf, 0); snprintf(log_buf, MAX_STRING_LENGTH, "%s%sOrange/Brown\r\n", ANSI_BLACK, BACK_ORANGE); write_to_buffer(ch->desc, log_buf, 0); snprintf(log_buf, MAX_STRING_LENGTH, "%s%sDark Blue\r\n", ANSI_BLACK, BACK_DBLUE); write_to_buffer(ch->desc, log_buf, 0); snprintf(log_buf, MAX_STRING_LENGTH, "%s%sPurple\r\n", ANSI_BLACK, BACK_PURPLE); write_to_buffer(ch->desc, log_buf, 0); snprintf(log_buf, MAX_STRING_LENGTH, "%s%sCyan\r\n", ANSI_BLACK, BACK_CYAN); write_to_buffer(ch->desc, log_buf, 0); snprintf(log_buf, MAX_STRING_LENGTH, "%s%sGrey\r\n", ANSI_BLACK, BACK_GREY); write_to_buffer(ch->desc, log_buf, 0); snprintf(log_buf, MAX_STRING_LENGTH, "%s%sDark Grey Background\r\n", ANSI_BLACK, BACK_DGREY); write_to_buffer(ch->desc, log_buf, 0); snprintf(log_buf, MAX_STRING_LENGTH, "%s%sRed Background\r\n", ANSI_BLACK, BACK_RED); write_to_buffer(ch->desc, log_buf, 0); snprintf(log_buf, MAX_STRING_LENGTH, "%s%sGreen Background\r\n", ANSI_BLACK, BACK_GREEN); write_to_buffer(ch->desc, log_buf, 0); snprintf(log_buf, MAX_STRING_LENGTH, "%s%sYellow Background\r\n", ANSI_BLACK, BACK_YELLOW); write_to_buffer(ch->desc, log_buf, 0); snprintf(log_buf, MAX_STRING_LENGTH, "%s%sBlue Background\r\n", ANSI_BLACK, BACK_BLUE); write_to_buffer(ch->desc, log_buf, 0); snprintf(log_buf, MAX_STRING_LENGTH, "%s%sPink Background\r\n", ANSI_BLACK, BACK_PINK); write_to_buffer(ch->desc, log_buf, 0); snprintf(log_buf, MAX_STRING_LENGTH, "%s%sLight Blue Background\r\n", ANSI_BLACK, BACK_LBLUE); write_to_buffer(ch->desc, log_buf, 0); snprintf(log_buf, MAX_STRING_LENGTH, "%s%sWhite Background\r\n", ANSI_BLACK, BACK_WHITE); write_to_buffer(ch->desc, log_buf, 0); snprintf(log_buf, MAX_STRING_LENGTH, "%s%sItalics%s\r\n", ANSI_GREY, ANSI_ITALIC, ANSI_RESET); write_to_buffer(ch->desc, log_buf, 0); snprintf(log_buf, MAX_STRING_LENGTH, "%sStrikeout%s\r\n", ANSI_STRIKEOUT, ANSI_RESET); write_to_buffer(ch->desc, log_buf, 0); snprintf(log_buf, MAX_STRING_LENGTH, "%sUnderline\r\n", ANSI_UNDERLINE); write_to_buffer(ch->desc, log_buf, 0); write_to_buffer(ch->desc, ANSI_RESET, 0); return; } if(!str_prefix(arg, "_reset_")) { reset_colors(ch); send_to_pager("All color types reset to default colors.\r\n", ch); return; } argument = one_argument(argument, arg2); if(!arg || arg[0] == '\0') { send_to_char("Change which color type?\r\n", ch); return; } if(!str_prefix(arg, "_all_")) { dMatch = TRUE; count = -1; /* * search for a valid color setting */ for(y = 0; y < 16; y++) { if(!str_cmp(arg2, valid_color[y])) { cMatch = TRUE; break; } } } else if(!arg || arg2[0] == '\0') cMatch = FALSE; else { /* * search for the display type and str_cmp */ for(count = 0; count < MAX_COLORS; count++) { if(!str_prefix(arg, pc_displays[count])) { dMatch = TRUE; break; } } if(!dMatch) { ch_printf(ch, "%s is an invalid color type.\r\n", arg); send_to_char("Type color with no arguments to see available options.\r\n", ch); return; } if(!str_cmp(arg2, "default")) { ch->colors[count] = default_set[count]; count = count -1; // no idea why ch_printf(ch, "Display %s set back to default.\r\n", pc_displays[count]); return; } /* * search for a valid color setting */ for(y = 0; y < 16; y++) { if(!str_cmp(arg2, valid_color[y])) { cMatch = TRUE; break; } } } if(!cMatch) { if(arg[0]) ch_printf(ch, "Invalid color for type %s.\n", arg); else send_to_pager("Invalid color.\r\n", ch); send_to_pager("Choices are:\r\n", ch); for(count = 0; count < 16; count++) { if(count % 5 == 0 && count != 0) send_to_pager("\r\n", ch); pager_printf(ch, "%-10s", valid_color[count]); } pager_printf(ch, "%-10s\r\n", "default"); return; } else pager_printf(ch, "Color type %s set to color %s.\r\n", count == -1 ? "_all_" : pc_displays[count], valid_color[y]); if(!str_cmp(argument, "blink")) y += AT_BLINK; if(count == -1) { int ccount; for(ccount = 0; ccount < MAX_COLORS; ++ccount) ch->colors[ccount] = y; set_pager_color(y, ch); pager_printf(ch, "All color types set to color %s%s.%s\r\n", valid_color[y > AT_BLINK ? y - AT_BLINK : y], y > AT_BLINK ? " [BLINKING]" : "", ANSI_RESET); } else { ch->colors[count] = y; set_pager_color(count, ch); if(!str_cmp(argument, "blink")) ch_printf(ch, "Display %s set to color %s [BLINKING]%s\r\n", pc_displays[count], valid_color[y - AT_BLINK], ANSI_RESET); else ch_printf(ch, "Display %s set to color %s.\r\n", pc_displays[count], valid_color[y]); } return; } const char *color_str(short AType, CHAR_DATA *ch) { if(!ch) { bug("%s", "color_str: NULL ch!"); return (""); } if(IS_NPC(ch) || !xIS_SET(ch->act, PLR_ANSI)) return (""); switch (ch->colors[AType]) { case 0: return (ANSI_LBLUE); case 1: return (ANSI_ORANGE); case 2: return (ANSI_CYAN); case 3: return (ANSI_RED); case 4: return (ANSI_BLUE); case 5: return (ANSI_WHITE); case 6: return (ANSI_DRED); case 7: return (ANSI_DBLUE); case 8: return (ANSI_GREY); case 9: return (ANSI_GREEN); case 10: return (ANSI_PINK); case 11: return (ANSI_DGREEN); case 12: return (ANSI_PURPLE); case 13: return (ANSI_DGREY); case 14: return (ANSI_YELLOW); case 15: return (ANSI_BLACK); /* * 16 thru 31 are for blinking colors */ case 16: return (BLINK_BLACK); case 17: return (BLINK_DRED); case 18: return (BLINK_DGREEN); case 19: return (BLINK_ORANGE); case 20: return (BLINK_DBLUE); case 21: return (BLINK_PURPLE); case 22: return (BLINK_CYAN); case 23: return (BLINK_GREY); case 24: return (BLINK_DGREY); case 25: return (BLINK_RED); case 26: return (BLINK_GREEN); case 27: return (BLINK_YELLOW); case 28: return (BLINK_BLUE); case 29: return (BLINK_PINK); case 30: return (BLINK_LBLUE); case 31: return (BLINK_WHITE); default: return (ANSI_RESET); } } /* Random Ansi Color Code -- Xorith */ const char *random_ansi(short type) { switch (type) { default: case 1: /* Default ANSI Fore-ground */ switch (number_range(1, 15)) { case 1: return (ANSI_DRED); case 2: return (ANSI_DGREEN); case 3: return (ANSI_ORANGE); case 4: return (ANSI_DBLUE); case 5: return (ANSI_PURPLE); case 6: return (ANSI_CYAN); case 7: return (ANSI_GREY); case 8: return (ANSI_DGREY); case 9: return (ANSI_RED); case 10: return (ANSI_GREEN); case 11: return (ANSI_YELLOW); case 12: return (ANSI_BLUE); case 13: return (ANSI_PINK); case 14: return (ANSI_LBLUE); case 15: return (ANSI_WHITE); default: return (ANSI_RESET); } case 2: /* ANSI Blinking */ switch (number_range(1, 14)) { case 1: return (BLINK_DGREEN); case 2: return (BLINK_ORANGE); case 3: return (BLINK_DBLUE); case 4: return (BLINK_PURPLE); case 5: return (BLINK_CYAN); case 6: return (BLINK_GREY); case 7: return (BLINK_DGREY); case 8: return (BLINK_RED); case 9: return (BLINK_GREEN); case 10: return (BLINK_YELLOW); case 11: return (BLINK_BLUE); case 12: return (BLINK_PINK); case 13: return (BLINK_LBLUE); default: case 14: return (BLINK_WHITE); } case 3: /* ANSI Background */ switch (number_range(1, 15)) { case 1: return (BACK_DRED); case 2: return (BACK_DGREEN); case 3: return (BACK_ORANGE); case 4: return (BACK_DBLUE); case 5: return (BACK_PURPLE); case 6: return (BACK_CYAN); case 7: return (BACK_GREY); case 8: return (BACK_DGREY); case 9: return (BACK_RED); case 10: return (BACK_GREEN); case 11: return (BACK_YELLOW); case 12: return (BACK_BLUE); case 13: return (BACK_PINK); case 14: return (BACK_LBLUE); default: case 15: return (BACK_WHITE); } } } /* * Quixadhal - I rewrote this from scratch. It now returns the number of * characters in the SOURCE string that should be skipped, it always fills * the DESTINATION string with a valid translation (even if that is itself, * or an empty string), and the default for ANSI is FALSE, since mobs and * logfiles shouldn't need colour. * * NOTE: dstlen is the length of your pre-allocated buffer that you passed * in. It must be at least 3 bytes, but should be long enough to hold the * longest translation sequence (probably around 16-32). * * NOTE: vislen is the "visible" length of the translation token. This is * used by color_strlen to properly figure the visual length of a string. * If you need the number of bytes (such as for output buffering), use the * normal strlen function. */ int colorcode(const char *src, char *dst, DESCRIPTOR_DATA *d, int dstlen, int *vislen) { CHAR_DATA *ch = NULL; bool ansi = FALSE; const char *sympos = NULL; /* * No descriptor, assume ANSI conversion can't be done. */ if(!d) ansi = FALSE; /* * But, if we have one, check for a PC and set accordingly. If no PC, assume ANSI can be done. For color logins. */ else { ch = d->original ? d->original : d->character; if(ch) ansi = (!IS_NPC(ch) && xIS_SET(ch->act, PLR_ANSI)); else ansi = TRUE; } if(!dst) return 0; /* HEY, I said at least 3 BYTES! */ dst[0] = '\0'; /* Initialize the the default NOTHING */ /* * Move along, nothing to see here */ if(!src || !*src) return 0; switch (*src) { case '&': /* NORMAL, Foreground colour */ switch (src[1]) { case '&': /* Escaped self, return one of us */ dst[0] = src[0]; dst[1] = '\0'; if(vislen) *vislen = 1; return 2; case 'Z': /* Random Ansi Foreground */ if(ansi) mudstrlcpy(dst, random_ansi(1), dstlen); break; case '[': /* Symbolic color name */ if((sympos = strchr(src + 2, ']'))) { register int subcnt = 0; unsigned int sublen = 0; sublen = sympos - src - 2; for(subcnt = 0; subcnt < MAX_COLORS; subcnt++) { if(!strncmp(src + 2, pc_displays[subcnt], sublen)) { if(strlen(pc_displays[subcnt]) == sublen) { /* * These can only be used with a logged in char */ if(ansi && ch) mudstrlcpy(dst, color_str(subcnt, ch), dstlen); if(vislen) *vislen = 0; return sublen + 3; } } } } /* found matching ] */ /* * Unknown symbolic name, return just the sequence */ dst[0] = src[0]; dst[1] = src[1]; dst[2] = '\0'; if(vislen) *vislen = 2; return 2; case 'i': /* Italic text */ case 'I': if(ansi) mudstrlcpy(dst, ANSI_ITALIC, dstlen); break; case 'v': /* Reverse colors */ case 'V': if(ansi) mudstrlcpy(dst, ANSI_REVERSE, dstlen); break; case 'u': /* Underline */ case 'U': if(ansi) mudstrlcpy(dst, ANSI_UNDERLINE, dstlen); break; case 's': /* Strikeover */ case 'S': if(ansi) mudstrlcpy(dst, ANSI_STRIKEOUT, dstlen); break; case 'd': /* Player's client default color */ if(ansi) mudstrlcpy(dst, ANSI_RESET, dstlen); break; case 'D': /* Reset to custom color for * * * * whatever is being displayed */ if(ansi) { /* * Yes, this reset here is quite necessary to cancel out other things */ mudstrlcpy(dst, ANSI_RESET, dstlen); if(ch && ch->desc) mudstrlcat(dst, color_str(ch->desc->pagecolor, ch), dstlen); } break; case 'x': /* Black */ if(ansi) mudstrlcpy(dst, ANSI_BLACK, dstlen); break; case 'O': /* Orange/Brown */ if(ansi) mudstrlcpy(dst, ANSI_ORANGE, dstlen); break; case 'c': /* Cyan */ if(ansi) mudstrlcpy(dst, ANSI_CYAN, dstlen); break; case 'z': /* Dark Grey */ if(ansi) mudstrlcpy(dst, ANSI_DGREY, dstlen); break; case 'g': /* Dark Green */ if(ansi) mudstrlcpy(dst, ANSI_DGREEN, dstlen); break; case 'G': /* Light Green */ if(ansi) mudstrlcpy(dst, ANSI_GREEN, dstlen); break; case 'P': /* Pink/Light Purple */ if(ansi) mudstrlcpy(dst, ANSI_PINK, dstlen); break; case 'r': /* Dark Red */ if(ansi) mudstrlcpy(dst, ANSI_DRED, dstlen); break; case 'b': /* Dark Blue */ if(ansi) mudstrlcpy(dst, ANSI_DBLUE, dstlen); break; case 'w': /* Grey */ if(ansi) mudstrlcpy(dst, ANSI_GREY, dstlen); break; case 'Y': /* Yellow */ if(ansi) mudstrlcpy(dst, ANSI_YELLOW, dstlen); break; case 'C': /* Light Blue */ if(ansi) mudstrlcpy(dst, ANSI_LBLUE, dstlen); break; case 'p': /* Purple */ if(ansi) mudstrlcpy(dst, ANSI_PURPLE, dstlen); break; case 'R': /* Red */ if(ansi) mudstrlcpy(dst, ANSI_RED, dstlen); break; case 'B': /* Blue */ if(ansi) mudstrlcpy(dst, ANSI_BLUE, dstlen); break; case 'W': /* White */ if(ansi) mudstrlcpy(dst, ANSI_WHITE, dstlen); break; default: /* Unknown sequence, return all * * * * * * * * * * * * the chars */ dst[0] = src[0]; dst[1] = src[1]; dst[2] = '\0'; if(vislen) *vislen = 2; return 2; } break; case '^': /* BACKGROUND colour */ switch (src[1]) { case '^': /* Escaped self, return one of us */ dst[0] = src[0]; dst[1] = '\0'; if(vislen) *vislen = 1; return 2; case 'Z': /* Random Ansi Background */ if(ansi) mudstrlcpy(dst, random_ansi(3), dstlen); break; case 'x': /* Black */ if(ansi) mudstrlcpy(dst, BACK_BLACK, dstlen); break; case 'r': /* Dark Red */ if(ansi) mudstrlcpy(dst, BACK_DRED, dstlen); break; case 'g': /* Dark Green */ if(ansi) mudstrlcpy(dst, BACK_DGREEN, dstlen); break; case 'O': /* Orange/Brown */ if(ansi) mudstrlcpy(dst, BACK_ORANGE, dstlen); break; case 'b': /* Dark Blue */ if(ansi) mudstrlcpy(dst, BACK_DBLUE, dstlen); break; case 'p': /* Purple */ if(ansi) mudstrlcpy(dst, BACK_PURPLE, dstlen); break; case 'c': /* Cyan */ if(ansi) mudstrlcpy(dst, BACK_CYAN, dstlen); break; case 'w': /* Grey */ if(ansi) mudstrlcpy(dst, BACK_GREY, dstlen); break; case 'z': /* Dark Grey */ if(ansi) mudstrlcpy(dst, BACK_DGREY, dstlen); break; case 'R': /* Red */ if(ansi) mudstrlcpy(dst, BACK_RED, dstlen); break; case 'G': /* Green */ if(ansi) mudstrlcpy(dst, BACK_GREEN, dstlen); break; case 'Y': /* Yellow */ if(ansi) mudstrlcpy(dst, BACK_YELLOW, dstlen); break; case 'B': /* Blue */ if(ansi) mudstrlcpy(dst, BACK_BLUE, dstlen); break; case 'P': /* Pink */ if(ansi) mudstrlcpy(dst, BACK_PINK, dstlen); break; case 'C': /* Light Blue */ if(ansi) mudstrlcpy(dst, BACK_LBLUE, dstlen); break; case 'W': /* White */ if(ansi) mudstrlcpy(dst, BACK_WHITE, dstlen); break; default: /* Unknown sequence, return all * * * * * * * * * * * * the chars */ dst[0] = src[0]; dst[1] = src[1]; dst[2] = '\0'; if(vislen) *vislen = 2; return 2; } break; case '}': /* BLINK Foreground colour */ switch (src[1]) { case '}': /* Escaped self, return one of us */ dst[0] = src[0]; dst[1] = '\0'; if(vislen) *vislen = 1; return 2; case 'Z': /* Random Ansi Blink */ if(ansi) mudstrlcpy(dst, random_ansi(2), dstlen); break; case 'x': /* Black */ if(ansi) mudstrlcpy(dst, BLINK_BLACK, dstlen); break; case 'O': /* Orange/Brown */ if(ansi) mudstrlcpy(dst, BLINK_ORANGE, dstlen); break; case 'c': /* Cyan */ if(ansi) mudstrlcpy(dst, BLINK_CYAN, dstlen); break; case 'z': /* Dark Grey */ if(ansi) mudstrlcpy(dst, BLINK_DGREY, dstlen); break; case 'g': /* Dark Green */ if(ansi) mudstrlcpy(dst, BLINK_DGREEN, dstlen); break; case 'G': /* Light Green */ if(ansi) mudstrlcpy(dst, BLINK_GREEN, dstlen); break; case 'P': /* Pink/Light Purple */ if(ansi) mudstrlcpy(dst, BLINK_PINK, dstlen); break; case 'r': /* Dark Red */ if(ansi) mudstrlcpy(dst, BLINK_DRED, dstlen); break; case 'b': /* Dark Blue */ if(ansi) mudstrlcpy(dst, BLINK_DBLUE, dstlen); break; case 'w': /* Grey */ if(ansi) mudstrlcpy(dst, BLINK_GREY, dstlen); break; case 'Y': /* Yellow */ if(ansi) mudstrlcpy(dst, BLINK_YELLOW, dstlen); break; case 'C': /* Light Blue */ if(ansi) mudstrlcpy(dst, BLINK_LBLUE, dstlen); break; case 'p': /* Purple */ if(ansi) mudstrlcpy(dst, BLINK_PURPLE, dstlen); break; case 'R': /* Red */ if(ansi) mudstrlcpy(dst, BLINK_RED, dstlen); break; case 'B': /* Blue */ if(ansi) mudstrlcpy(dst, BLINK_BLUE, dstlen); break; case 'W': /* White */ if(ansi) mudstrlcpy(dst, BLINK_WHITE, dstlen); break; default: /* Unknown sequence, return all * * * * * * * * * * * * the chars */ dst[0] = src[0]; dst[1] = src[1]; dst[2] = '\0'; if(vislen) *vislen = 2; return 2; } break; default: /* Just a normal character */ dst[0] = *src; dst[1] = '\0'; if(vislen) *vislen = 1; return 1; } if(vislen) *vislen = 0; return 2; } /* * Quixadhal - I rewrote this too, so that it uses colorcode. It may not * be as efficient as just walking over the string and counting, but it * keeps us from duplicating the code several times. * * This function returns the intended screen length of a string which has * color codes embedded in it. It does this by stripping the codes out * entirely (A NULL descriptor means ANSI will be FALSE). */ int color_strlen(const char *src) { register unsigned int i = 0; int len = 0; if(!src || !*src) /* Move along, nothing to see here */ return 0; for(i = 0; i < strlen(src);) { char dst[20]; int vislen; switch (src[i]) { case '&': /* NORMAL, Foreground colour */ case '^': /* BACKGROUND colour */ case '}': /* BLINK Foreground colour */ *dst = '\0'; vislen = 0; i += colorcode(&src[i], dst, NULL, 20, &vislen); /* Skip input token */ len += vislen; /* Count output token length */ break; /* this was missing - if you have issues, remove it */ default: /* No conversion, just count */ ++len; ++i; break; } } return len; } /* * Quixadhal - And this one needs to use the new version too. */ char *color_align(const char *argument, int size, int align) { int space = 0; int len = 0; static char buf[MAX_STRING_LENGTH]; len = color_strlen(argument); space = (size - len); if(align == ALIGN_RIGHT || len >= size) snprintf(buf, MAX_STRING_LENGTH, "%*.*s", len, len, argument); else if(align == ALIGN_CENTER) snprintf(buf, MAX_STRING_LENGTH, "%*s%s%*s", (space / 2), "", argument, ((space / 2) * 2) == space ? (space / 2) : ((space / 2) + 1), ""); else if(align == ALIGN_LEFT) snprintf(buf, MAX_STRING_LENGTH, "%s%*s", argument, space, ""); return buf; } /* Updated to use less lines of code with same affects. * Also added a default of white incase its a different color type. * - Remcon */ void colorize_equipment(OBJ_DATA *obj, CHAR_DATA *ch) { if(obj->color == 0) set_char_color(AT_LBLUE, ch); else if(obj->color == 1) set_char_color(AT_ORANGE, ch); else if(obj->color == 2) set_char_color(AT_CYAN, ch); else if(obj->color == 3) set_char_color(AT_RED, ch); else if(obj->color == 4) set_char_color(AT_MAGIC, ch); else if(obj->color == 5) set_char_color(AT_WHITE, ch); else if(obj->color == 6) set_char_color(AT_BLOOD, ch); else if(obj->color == 7) set_char_color(AT_DBLUE, ch); else if(obj->color == 8) set_char_color(AT_GREY, ch); else if(obj->color == 9) set_char_color(AT_GREEN, ch); else if(obj->color == 10) set_char_color(AT_PINK, ch); else if(obj->color == 11) set_char_color(AT_DGREEN, ch); else if(obj->color == 12) set_char_color(AT_PURPLE, ch); else if(obj->color == 13) set_char_color(AT_DGREY, ch); else if(obj->color == 14) set_char_color(AT_YELLOW, ch); else set_char_color(AT_WHITE, ch); return; } /* * Quixadhal - This takes a string and converts any and all color tokens * in it to the desired output tokens, using the provided character's * preferences. */ char *colorize(const char *txt, DESCRIPTOR_DATA *d) { static char result[MAX_STRING_LENGTH * 10]; *result = '\0'; if(txt && *txt && d) { const char *colstr; const char *prevstr = txt; char colbuf[20]; int ln; while((colstr = strpbrk(prevstr, "&^}hH")) != NULL) { register int reslen = 0; if(colstr > prevstr) { if((MAX_STRING_LENGTH * 10 - (reslen = strlen(result))) <= (colstr - prevstr)) { bug("%s: OVERFLOW in internal MAX_STRING_LENGTH buffer!", __PRETTY_FUNCTION__); break; } strncat(result, prevstr, (colstr - prevstr)); /* Leave this one alone! BAD * THINGS(TM) will happen if you * don't! */ result[reslen + (colstr - prevstr)] = '\0'; /* strncat will NOT NULL terminate * this! */ } if(colstr[0] == 'h' || colstr[0] == 'H') if(colstr[1] == 't' || colstr[1] == 'T') if(colstr[2] == 't' || colstr[2] == 'T') if(colstr[3] == 'p' || colstr[3] == 'P') { char http[MAX_INPUT_LENGTH]; one_http_argument((char *)colstr, http); mudstrlcat(result, http, sizeof(result)); ln = strlen(http); prevstr = colstr + ln; continue; } ln = colorcode(colstr, colbuf, d, 20, NULL); if(ln > 0) { mudstrlcat(result, colbuf, MAX_STRING_LENGTH * 10); prevstr = colstr + ln; } else prevstr = colstr + 1; } if(*prevstr) mudstrlcat(result, prevstr, MAX_STRING_LENGTH * 10); } return result; } /* Moved from comm.c */ void set_char_color(short AType, CHAR_DATA *ch) { if(!ch || !ch->desc) return; if(IS_NPC(ch)) return; send_to_char(color_str(AType, ch), ch); if(!ch->desc) { bug("%s: NULL descriptor after send_to_char! CH: %s", __FUNCTION__, ch->name ? ch->name : "Unknown?!?"); return; } ch->desc->pagecolor = ch->colors[AType]; } void write_to_pager(DESCRIPTOR_DATA *d, const char *txt, unsigned int length) { int pageroffset; /* Pager fix by thoric */ if(length <= 0) length = strlen(txt); if(length == 0) return; if(!d->pagebuf) { d->pagesize = MSL; CREATE(d->pagebuf, char, d->pagesize); } if(!d->pagepoint) { d->pagepoint = d->pagebuf; d->pagetop = 0; d->pagecmd = '\0'; } if(d->pagetop == 0 && !d->fcommand) { d->pagebuf[0] = '\r'; d->pagebuf[1] = '\n'; d->pagetop = 2; } pageroffset = d->pagepoint - d->pagebuf; /* pager fix (goofup fixed 08/21/97) */ while(d->pagetop + length >= d->pagesize) { if(d->pagesize > MSL * 16) { bug("%s: Pager overflow. Ignoring.", __FUNCTION__); d->pagetop = 0; d->pagepoint = NULL; DISPOSE(d->pagebuf); d->pagesize = MSL; return; } d->pagesize *= 2; RECREATE(d->pagebuf, char, d->pagesize); } d->pagepoint = d->pagebuf + pageroffset; /* pager fix (goofup fixed 08/21/97) */ strncpy(d->pagebuf + d->pagetop, txt, length); /* Leave this one alone! BAD THINGS(TM) * will happen if you don't! */ d->pagetop += length; d->pagebuf[d->pagetop] = '\0'; } void set_pager_color(short AType, CHAR_DATA *ch) { if(!ch || !ch->desc) return; if(IS_NPC(ch)) return; send_to_pager(color_str(AType, ch), ch); if(!ch->desc) { bug("%s: NULL descriptor after send_to_pager! CH: %s", __FUNCTION__, ch->name ? ch->name : "Unknown?!?"); return; } ch->desc->pagecolor = ch->colors[AType]; } /* Writes to a descriptor, usually best used when there's no character to send to ( like logins ) */ void send_to_desc(const char *txt, DESCRIPTOR_DATA *d) { if(!d) { bug("%s: NULL *d", __FUNCTION__); return; } if(!txt || !d->descriptor) return; write_to_buffer(d, colorize(txt, d), 0); } /* * Write to one char. Convert color into ANSI sequences. */ void send_to_char(const char *txt, CHAR_DATA *ch) { if(!ch) { bug("%s", "send_to_char: NULL ch!"); return; } if(txt && ch->desc) send_to_desc(txt, ch->desc); } void send_to_pager(const char *txt, CHAR_DATA *ch) { if(!ch) { bug("%s", "send_to_pager: NULL ch!"); return; } if(txt && ch->desc) { DESCRIPTOR_DATA *d = ch->desc; ch = d->character; if(IS_NPC(ch) || !IS_SET(ch->pcdata->flags, PCFLAG_PAGERON)) { if(ch->desc) send_to_desc(txt, ch->desc); } else { if(ch->desc) write_to_pager(ch->desc, colorize(txt, ch->desc), 0); } } } void ch_printf(CHAR_DATA *ch, const char *fmt, ...) { char buf[MSL * 2]; va_list args; va_start(args, fmt); vsnprintf(buf, sizeof(buf), fmt, args); va_end(args); send_to_char(buf, ch); } /* Made to handle the act and to set the reply trigger */ void act_tell(CHAR_DATA *to, CHAR_DATA *teller, const char *format, CHAR_DATA *ch, void *arg1, void *arg2, int type) { act(AT_TELL, format, ch, arg1, arg2, type); to->reply = teller; } void act_printf(short AType, CHAR_DATA *ch, void *arg1, void *arg2, int type, const char *fmt, ...) { char buf[MSL * 2]; va_list args; va_start(args, fmt); vsnprintf(buf, sizeof(buf), fmt, args); va_end(args); act(AType, buf, ch, arg1, arg2, type); } /* Sends to all playing characters except ch */ void playing_printf(CHAR_DATA *ch, const char *fmt, ...) { DESCRIPTOR_DATA *d; char buf[MSL * 2]; va_list args; va_start(args, fmt); vsnprintf(buf, sizeof(buf), fmt, args); va_end(args); for(d = first_descriptor; d; d = d->next) if(d->connected == CON_PLAYING && d->character != ch) send_to_char(buf, d->character); } void pager_printf(CHAR_DATA *ch, const char *fmt, ...) { char buf[MSL * 2]; va_list args; va_start(args, fmt); vsnprintf(buf, sizeof(buf), fmt, args); va_end(args); send_to_pager(buf, ch); } /* * The primary output interface for formatted output. */ /* Major overhaul. -- Alty */ void ch_printf_color(CHAR_DATA *ch, const char *fmt, ...) { char buf[MSL * 2]; va_list args; va_start(args, fmt); vsnprintf(buf, sizeof(buf), fmt, args); va_end(args); send_to_char(buf, ch); } void paint(short AType, CHAR_DATA *ch, const char *fmt, ...) { char buf[MSL * 2]; /* better safe than sorry */ va_list args; va_start(args, fmt); vsnprintf(buf, sizeof(buf), fmt, args); va_end(args); set_char_color(AType, ch); send_to_char(buf, ch); set_char_color(AType, ch); } /* Wrapper function for any "legacy" code that may be installed later */ void send_to_char_color(const char *txt, CHAR_DATA *ch) { send_to_char(txt, ch); } /* Wrapper function for any "legacy" code that may be installed later */ void send_to_pager_color(const char *txt, CHAR_DATA *ch) { send_to_pager(txt, ch); } void pager_printf_color(CHAR_DATA *ch, const char *fmt, ...) { char buf[MAX_STRING_LENGTH * 2]; va_list args; va_start(args, fmt); vsnprintf(buf, MAX_STRING_LENGTH * 2, fmt, args); va_end(args); send_to_pager(buf, ch); } void string_stripblink(char *argument, char *string) { bool color = FALSE; while(*argument != '\0') { if(color == TRUE) { string--; argument++; color = FALSE; continue; } if(*argument == '}') color = TRUE; *string = *argument; argument++; string++; } *string = '\0'; } void string_stripcolor(char *argument, char *string) { bool color = FALSE; while(*argument != '\0') { if(color == TRUE) { string--; argument++; color = FALSE; continue; } if(*argument == '&') color = TRUE; *string = *argument; argument++; string++; } *string = '\0'; }