/*************************************************************************** * God Wars Mud copyright (C) 1994, 1995, 1996 by Richard Woolcock * * * * Legend of Chrystancia copyright (C) 1999, 2000, 2001 by Matthew Little * * This mud is NOT to be copied in whole or in part, or to be run without * * the permission of Matthew Little. Nobody else has permission to * * authorise the use of this code. * ***************************************************************************/ /* * source file for mxp * * Brian Graversen */ #include <sys/types.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include "merc.h" /* telnet negotiating */ const char mxp_will [] = { IAC, WILL, TELOPT_MXP, '\0' }; const char mxp_do [] = { IAC, DO, TELOPT_MXP, '\0' }; const char mxp_dont [] = { IAC, DONT, TELOPT_MXP, '\0' }; /* * mxp_to_char() * ------------- * * When sending MXP messages with this function, you should * always use <BR> instead of \n\r, since \n\r resets the * state of MXP. <BR> will do a linebreak just like \n\r, * but the state is kept. * * The following MXP tags are supported, and works well * in zmud 6.16 and mushclient 3.17. Other clients may * work, but it's very unlikely. * * <B>text</B> : BOLD * <I>text</I> : ITALIC * <U>text</U> : UNDERLINE * <BR> : LINEBREAK (is replaced with \n\r if no MXP) * * Some of these more advanced features are also supported * ------------------------------------------------------- * <A href="URL">text</A> : web hyperlinks. * <SEND [args]>text</SEND> : mud hyperlinks and menus. * */ void mxp_to_char(CHAR_DATA *ch, char *txt, int mxp_style) { char buf[2*MAX_STRING_LENGTH]; int i = 0, j = 0; if (!ch->desc) return; if (USE_MXP(ch)) { switch(mxp_style) { default: bug("Mxp_to_char: strange style '%d'.", mxp_style); strcpy(buf, txt); case MXP_SAFE: sprintf(buf, "%s%s%s", "\e[0z", txt, "\e[7z"); break; case MXP_ALL: /* There is a bug in zmud 6.16 so we can not do the obvious * here. Instead we'll use this workaround. In the future, * the bug in zmud might be fixed, and the following line * can replace everything else. * * NOTE: It now works with zmud 6.25 as well... not pretty. * * sprintf(buf, "%s%s%s", "\e[1z", txt, "\e[7z"); * */ buf[j++] = '\e'; buf[j++] = '['; buf[j++] = '1'; buf[j++] = 'z'; while (txt[i] != '\0') { switch(txt[i]) { default: buf[j++] = txt[i++]; break; case '<': if (!memcmp(&txt[i], "<BR>", strlen("<BR>"))) { i += strlen("<BR>"); buf[j++] = '\n'; buf[j++] = '\r'; buf[j++] = '\e'; buf[j++] = '['; buf[j++] = '1'; buf[j++] = 'z'; } else buf[j++] = txt[i++]; break; } } buf[j++] = '\e'; buf[j++] = '['; buf[j++] = '7'; buf[j++] = 'z'; buf[j] = '\0'; break; case MXP_NONE: sprintf(buf, "%s%s", "\e[7z", txt); break; } } else { while(txt[i] != '\0') { switch(txt[i]) { default: buf[j++] = txt[i++]; break; case '<': if (!memcmp(&txt[i], "<B>", strlen("<B>"))) i += strlen("<B>"); else if (!memcmp(&txt[i], "</B>", strlen("</B>"))) i += strlen("</B>"); else if (!memcmp(&txt[i], "<U>", strlen("<U>"))) i += strlen("<U>"); else if (!memcmp(&txt[i], "</U>", strlen("</U>"))) i += strlen("</U>"); else if (!memcmp(&txt[i], "<I>", strlen("<I>"))) i += strlen("<I>"); else if (!memcmp(&txt[i], "</I>", strlen("</I>"))) i += strlen("</I>"); else if (!memcmp(&txt[i], "<BR>", strlen("<BR>"))) { buf[j++] = '\n'; buf[j++] = '\r'; i += strlen("<BR>"); } else if (!memcmp(&txt[i], "<SEND", strlen("<SEND"))) { i += strlen("<SEND"); while(txt[i++] != '>') ; } else if (!memcmp(&txt[i], "<A href", strlen("<A href"))) { i += strlen("<A href"); while(txt[i++] != '>') ; } else if (!memcmp(&txt[i], "</SEND>", strlen("</SEND>"))) i += strlen("</SEND>"); else if (!memcmp(&txt[i], "</A>", strlen("</A>"))) i += strlen("</A>"); else buf[j++] = txt[i++]; break; } } buf[j] = '\0'; } send_to_char(buf, ch); } void mxp_to_cchar(CHAR_DATA *ch, char *txt, int mxp_style) { char buf[2*MAX_STRING_LENGTH]; int i = 0, j = 0; if (!ch->desc) return; if (USE_MXP(ch)) { switch(mxp_style) { default: bug("Mxp_to_char: strange style '%d'.", mxp_style); strcpy(buf, txt); case MXP_SAFE: sprintf(buf, "%s%s%s", "\e[0z", txt, "\e[7z"); break; case MXP_ALL: /* There is a bug in zmud 6.16 so we can not do the obvious * here. Instead we'll use this workaround. In the future, * the bug in zmud might be fixed, and the following line * can replace everything else. * * NOTE: It now works with zmud 6.25 as well... not pretty. * * sprintf(buf, "%s%s%s", "\e[1z", txt, "\e[7z"); * */ buf[j++] = '\e'; buf[j++] = '['; buf[j++] = '1'; buf[j++] = 'z'; while (txt[i] != '\0') { switch(txt[i]) { default: buf[j++] = txt[i++]; break; case '<': if (!memcmp(&txt[i], "<BR>", strlen("<BR>"))) { i += strlen("<BR>"); buf[j++] = '\n'; buf[j++] = '\r'; buf[j++] = '\e'; buf[j++] = '['; buf[j++] = '1'; buf[j++] = 'z'; } else buf[j++] = txt[i++]; break; } } buf[j++] = '\e'; buf[j++] = '['; buf[j++] = '7'; buf[j++] = 'z'; buf[j] = '\0'; break; case MXP_NONE: sprintf(buf, "%s%s", "\e[7z", txt); break; } } else { while(txt[i] != '\0') { switch(txt[i]) { default: buf[j++] = txt[i++]; break; case '<': if (!memcmp(&txt[i], "<B>", strlen("<B>"))) i += strlen("<B>"); else if (!memcmp(&txt[i], "</B>", strlen("</B>"))) i += strlen("</B>"); else if (!memcmp(&txt[i], "<U>", strlen("<U>"))) i += strlen("<U>"); else if (!memcmp(&txt[i], "</U>", strlen("</U>"))) i += strlen("</U>"); else if (!memcmp(&txt[i], "<I>", strlen("<I>"))) i += strlen("<I>"); else if (!memcmp(&txt[i], "</I>", strlen("</I>"))) i += strlen("</I>"); else if (!memcmp(&txt[i], "<BR>", strlen("<BR>"))) { buf[j++] = '\n'; buf[j++] = '\r'; i += strlen("<BR>"); } else if (!memcmp(&txt[i], "<SEND", strlen("<SEND"))) { i += strlen("<SEND"); while(txt[i++] != '>') ; } else if (!memcmp(&txt[i], "<A href", strlen("<A href"))) { i += strlen("<A href"); while(txt[i++] != '>') ; } else if (!memcmp(&txt[i], "</SEND>", strlen("</SEND>"))) i += strlen("</SEND>"); else if (!memcmp(&txt[i], "</A>", strlen("</A>"))) i += strlen("</A>"); else buf[j++] = txt[i++]; break; } } buf[j] = '\0'; } cent_to_char(buf, ch); } void init_mxp(DESCRIPTOR_DATA *d) { const char enable_mxp[] = { IAC, SB, TELOPT_MXP, IAC, SE, '\0' }; write_to_buffer(d, enable_mxp, 0); write_to_buffer(d, "\e[7z", 0); d->mxp = TRUE; } void shutdown_mxp(DESCRIPTOR_DATA *d) { d->mxp = FALSE; } void do_mxp(CHAR_DATA *ch, char *argument) { if (!ch->desc) return; if (!ch->desc->mxp) { send_to_char("Sorry, your client does not support MXP.\n\r", ch); return; } if (IS_SET(ch->extra2, PLR_MXP)) { REMOVE_BIT(ch->extra2, PLR_MXP); send_to_char("MXP has been disabled.\n\r", ch); } else { SET_BIT(ch->extra2, PLR_MXP); send_to_char("MXP has been enabled.\n\r", ch); } } void do_mudvote(CHAR_DATA *ch, char *argument) { mxp_to_char(ch, "<A href=\"http://www.mudconnect.com/cgi-bin/vote_rank.cgi?mud=YOUR+MUD+NAME\">Vote For Us at Mudconnector</A>\n\r", MXP_ALL); } void do_mxptest(CHAR_DATA *ch, char *argument) { mxp_to_char(ch, "<B>This is bold</B>\n\r", MXP_ALL); mxp_to_char(ch, "<I>This is italic</I>\n\r", MXP_ALL); mxp_to_char(ch, "<SEND href=\"say test\">click me</SEND>\n\r", MXP_ALL); mxp_to_char(ch, "<A href=\"http://groups.yahoo.com/group/Chrystancia\">Mailing List</A>\n\r", MXP_ALL); mxp_to_char(ch, "<A href=\"http://www.soton.ac.uk/~gc5/dirs.htm\">Quest Locations</A>\n\r", MXP_ALL); mxp_to_char(ch, "<SEND href=\"say i clicked it|smile|look\" hint=\"Click to see the menu|First entry|Second entry|Third entry\">A Menu</SEND>", MXP_ALL); } void do_showmxp(CHAR_DATA *ch, char *argument) { DESCRIPTOR_DATA *d; CHAR_DATA *gch; char buf[MAX_STRING_LENGTH]; int count1 = 0; int count2 = 0; if (IS_NPC(ch)) return; for (d = first_descriptor; d != NULL; d = d->next) { if (d->connected != CON_PLAYING) continue; if (d->character != NULL) gch = d->character; else continue; if USE_MXP(gch) { sprintf(buf, "%-15s uses MXP\n\r", gch->name); count1++; } else { sprintf(buf,"%-15s Does not use MXP.\n\r", gch->name); count2++; } send_to_char(buf, ch); } sprintf(buf,"\n\r%d out of %d players uses MXP\n\r", count1, count2 + count1); send_to_char(buf, ch); return; }