/*************************************************************************** * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. * * * * Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * * * In order to use any part of this Merc Diku Mud, you must comply with * * both the original Diku license in 'license.doc' as well the Merc * * license in 'license.txt'. In particular, you may not remove either of * * these copyright notices. * * * * Dystopia Mud improvements copyright (C) 2000, 2001 by Brian Graversen * * * * Much time and thought has gone into this software and you are * * benefitting. We hope that you share your changes too. What goes * * around, comes around. * ***************************************************************************/ /*************************************************************************** * File: string.c * * * * Much time and thought has gone into this software and you are * * benefitting. We hope that you share your changes too. What goes * * around, comes around. * * * * This code was freely distributed with the The Isles 1.1 source code, * * and has been used here for OLC - OLC would not be what it is without * * all the previous coders who released their source code. * * * ***************************************************************************/ /*************************************************************************** * _/ _/ * * _/_/_/ _/_/ _/_/_/ _/ _/_/ _/ _/ _/_/_/ * * _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ * * _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ * * _/ _/ _/ _/_/_/ _/ _/_/ _/_/_/ _/_/_/ * *************************************************************************** * Mindcloud Copyright 2001-2003 by Jeff Boschee (Zarius), * * Additional credits are in the help file CODECREDITS * * All Rights Reserved. * ***************************************************************************/ #include <sys/types.h> #include <ctype.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include "merc.h" #include "olc.h" char *string_linedel(char *, int); char *string_lineadd(char *, char *, int); char *numlineas(char *); /* * Returns an all-caps string. OLC 1.1b */ char *all_capitalize(const char *str) { static char strcap[MAX_STRING_LENGTH]; int i; for (i = 0; str[i] != '\0'; i++) strcap[i] = UPPER(str[i]); strcap[i] = '\0'; return strcap; } /***************************************************************************** Name: commanum Purpose: Places a comma in appropriate places for large numbers Notes: Written originally by Kagai for SoH ****************************************************************************/ char *commanum(int number) { static char string[MAX_STRING_LENGTH]; char string2[MAX_STRING_LENGTH]; char thing[MAX_STRING_LENGTH]; char negative[MAX_STRING_LENGTH]; int x, y; xprintf(thing, "%d", number); strcpy(string, ""); for (x = (strlen(thing) - 1), y = 0; x >= 0; x--) { xprintf(string2, "%s%s%c", string, (y >= 3) ? "," : "", thing[x]); if (y >= 3) y = 0; strcpy(string, string2); xprintf(negative, "%c", thing[x]); if (str_cmp(negative, "-")) y++; } strcpy(thing, string); strcpy(string, ""); for (x = (strlen(thing) - 1); x >= 0; x--) { xprintf(string2, "%s%c", string, thing[x]); strcpy(string, string2); } return &string[0]; } /***************************************************************************** Name: string_edit Purpose: Clears string and puts player into editing mode. Called by: none ****************************************************************************/ void string_edit(CHAR_DATA * ch, char **pString) { send_to_char("#Y-========- #wEntering EDIT Mode#Y -=========-\n\r", ch); send_to_char("#w Type .h on a new line for help\n\r", ch); send_to_char("#w Terminate with a ~ or @ on a blank line.\n\r", ch); send_to_char("#Y-=======================================-\n\r", ch); if (*pString == NULL) { *pString = str_dup(""); } else { **pString = '\0'; } ch->desc->pString = pString; return; } /***************************************************************************** Name: string_append Purpose: Puts player into append mode for given string. Called by: (many)olc_act.c ****************************************************************************/ void string_append(CHAR_DATA * ch, char **pString) { send_to_char("#Y-=======- #wEntering APPEND Mode #Y-========-\n\r", ch); send_to_char("#w Type .h on a new line for help\n\r", ch); send_to_char("#w Terminate with a ~ or @ on a blank line.\n\r", ch); send_to_char("#Y-=======================================-\n\r", ch); if (*pString == NULL) { *pString = str_dup(""); } send_to_char(numlineas(*pString), ch); /* numlineas entrega el string con \n\r */ /* if ( *(*pString + strlen( *pString ) - 1) != '\r' ) send_to_char( "\n\r", ch ); */ ch->desc->pString = pString; return; } /***************************************************************************** Name: string_replace Purpose: Substitutes one string for another. Called by: string_add(string.c) (aedit_builder)olc_act.c. ****************************************************************************/ char *string_replace(char *orig, char *old, char *new) { char xbuf[MAX_STRING_LENGTH]; int i; xbuf[0] = '\0'; strcpy(xbuf, orig); if (strstr(orig, old) != NULL) { i = strlen(orig) - strlen(strstr(orig, old)); xbuf[i] = '\0'; strcat(xbuf, new); strcat(xbuf, &orig[i + strlen(old)]); free_string(orig); } return str_dup(xbuf); } /* OLC 1.1b */ /***************************************************************************** Name: string_add Purpose: Interpreter for string editing. Called by: game_loop_xxxx(comm.c). ****************************************************************************/ void string_add(CHAR_DATA * ch, char *argument) { char buf[MAX_STRING_LENGTH]; /* * Thanks to James Seng */ smash_tilde(argument); if (*argument == '.') { char arg1[MAX_INPUT_LENGTH]; char arg2[MAX_INPUT_LENGTH]; char arg3[MAX_INPUT_LENGTH]; char tmparg3[MAX_INPUT_LENGTH]; argument = one_argument(argument, arg1); argument = first_arg(argument, arg2, FALSE); strcpy(tmparg3, argument); argument = first_arg(argument, arg3, FALSE); if (!str_cmp(arg1, ".c")) { send_to_char("String cleared.\n\r", ch); free_string(*ch->desc->pString); *ch->desc->pString = str_dup(""); return; } if (!str_cmp(arg1, ".s")) { send_to_char("String so far:\n\r", ch); send_to_char(numlineas(*ch->desc->pString), ch); return; } if (!str_cmp(arg1, ".r")) { if (arg2[0] == '\0') { send_to_char ("usage: .r \"old string\" \"new string\"\n\r", ch); return; } *ch->desc->pString = string_replace(*ch->desc->pString, arg2, arg3); sprintf(buf, "'%s' replaced with '%s'.\n\r", arg2, arg3); send_to_char(buf, ch); return; } if (!str_cmp(arg1, ".f")) { *ch->desc->pString = format_string(*ch->desc->pString); send_to_char("String formatted.\n\r", ch); return; } if (!str_cmp(arg1, ".ld")) { *ch->desc->pString = string_linedel(*ch->desc->pString, atoi(arg2)); send_to_char("Line deleted\n\r", ch); return; } if (!str_cmp(arg1, ".li")) { *ch->desc->pString = string_lineadd(*ch->desc->pString, tmparg3, atoi(arg2)); send_to_char("Line inserted.\n\r", ch); return; } if (!str_cmp(arg1, ".lr")) { *ch->desc->pString = string_linedel(*ch->desc->pString, atoi(arg2)); *ch->desc->pString = string_lineadd(*ch->desc->pString, tmparg3, atoi(arg2)); send_to_char("Line replaced.\n\r", ch); return; } if (!str_cmp(arg1, ".h")) { send_to_char ("Sedit help (commands on blank line): \n\r", ch); send_to_char (".r 'old' 'new' - replace a substring \n\r", ch); send_to_char (" (requires '', \"\") \n\r", ch); send_to_char (".h - get help (this info)\n\r", ch); send_to_char (".s - show string so far \n\r", ch); send_to_char (".f - (word wrap) string \n\r", ch); send_to_char (".c - clear string so far \n\r", ch); send_to_char (".ld <num> - delete line number <num>\n\r", ch); send_to_char (".li <num> <str> - insert <str> on line <num>\n\r", ch); send_to_char (".lr <num> <str> - replace line <num> with <str>\n\r", ch); send_to_char ("@ - end string \n\r", ch); return; } send_to_char("SEdit: Invalid dot command.\n\r", ch); return; } if (*argument == '~' || *argument == '@') { if (ch->desc->editor == ED_MPCODE) /* para los mobprogs */ { MOB_INDEX_DATA *mob; int hash; PROG_LIST *mpl; PROG_CODE *mpc; EDIT_MPCODE(ch, mpc); if (mpc != NULL) for (hash = 0; hash < MAX_KEY_HASH; hash++) for (mob = mob_index_hash[hash]; mob; mob = mob->next) for (mpl = mob->mprogs; mpl; mpl = mpl->next) if (mpl->vnum == mpc->vnum) { xprintf(buf, "Fixing mob %d.\n\r", mob-> vnum); send_to_char (buf, ch); mpl->code = mpc-> code; } if (ch->desc->editor == ED_OPCODE) /* for the objprogs */ { OBJ_INDEX_DATA *obj; PROG_LIST *opl; PROG_CODE *opc; EDIT_OPCODE(ch, opc); if (opc != NULL) for (hash = 0; hash < MAX_KEY_HASH; hash++) for (obj = obj_index_hash[hash]; obj; obj = obj->next) for (opl = obj->oprogs; opl; opl = opl->next) if (opl-> vnum == opc->vnum) { xprintf(buf, "Fixing object %d.\n\r", obj->vnum); send_to_char (buf, ch); opl->code = opc->code; } } if (ch->desc->editor == ED_RPCODE) /* for the roomprogs */ { ROOM_INDEX_DATA *room; PROG_LIST *rpl; PROG_CODE *rpc; EDIT_RPCODE(ch, rpc); if (rpc != NULL) for (hash = 0; hash < MAX_KEY_HASH; hash++) for (room = room_index_hash[hash]; room; room = room->next) for (rpl = room->rprogs; rpl; rpl = rpl->next) if (rpl-> vnum == rpc->vnum) { xprintf(buf, "Fixing room %d.\n\r", room->vnum); send_to_char (buf, ch); rpl->code = rpc->code; } } } ch->desc->pString = NULL; send_to_char("You have exited the editor.\n\r", ch); return; } strcpy(buf, *ch->desc->pString); /* * Truncate strings to MAX_STRING_LENGTH. * -------------------------------------- */ //if ( strlen( buf ) + strlen( argument ) >= ( MAX_STRING_LENGTH - 4 ) ) if (strlen(*ch->desc->pString) + strlen(argument) >= (MAX_STRING_LENGTH - 4)) { send_to_char("String too long, last line skipped.\n\r", ch); /* * Force character out of editing mode. */ ch->desc->pString = NULL; return; } /* * Ensure no tilde's inside string. * -------------------------------- */ smash_tilde(argument); strcat(buf, argument); strcat(buf, "\n\r"); free_string(*ch->desc->pString); *ch->desc->pString = str_dup(buf); return; } /* * Thanks to Kalgen for the new procedure (no more bug!) * Original wordwrap() written by Surreality. */ /***************************************************************************** Name: format_string Purpose: Special string formating and word-wrapping. Called by: string_add(string.c) (many)olc_act.c ****************************************************************************/ char *format_string(char *oldstring /*, bool fSpace */ ) { char xbuf[MAX_STRING_LENGTH]; char xbuf2[MAX_STRING_LENGTH]; char *rdesc; int i = 0; bool cap = TRUE; xbuf[0] = xbuf2[0] = 0; i = 0; for (rdesc = oldstring; *rdesc; rdesc++) { if (*rdesc == '\n') { if (xbuf[i - 1] != ' ') { xbuf[i] = ' '; i++; } } else if (*rdesc == '\r'); else if (*rdesc == ' ') { if (xbuf[i - 1] != ' ') { xbuf[i] = ' '; i++; } } else if (*rdesc == ')') { if (xbuf[i - 1] == ' ' && xbuf[i - 2] == ' ' && (xbuf[i - 3] == '.' || xbuf[i - 3] == '?' || xbuf[i - 3] == '!')) { xbuf[i - 2] = *rdesc; xbuf[i - 1] = ' '; xbuf[i] = ' '; i++; } else { xbuf[i] = *rdesc; i++; } } else if (*rdesc == '.' || *rdesc == '?' || *rdesc == '!') { if (xbuf[i - 1] == ' ' && xbuf[i - 2] == ' ' && (xbuf[i - 3] == '.' || xbuf[i - 3] == '?' || xbuf[i - 3] == '!')) { xbuf[i - 2] = *rdesc; if (*(rdesc + 1) != '\"') { xbuf[i - 1] = ' '; xbuf[i] = ' '; i++; } else { xbuf[i - 1] = '\"'; xbuf[i] = ' '; xbuf[i + 1] = ' '; i += 2; rdesc++; } } else { xbuf[i] = *rdesc; if (*(rdesc + 1) != '\"') { xbuf[i + 1] = ' '; xbuf[i + 2] = ' '; i += 3; } else { xbuf[i + 1] = '\"'; xbuf[i + 2] = ' '; xbuf[i + 3] = ' '; i += 4; rdesc++; } } cap = TRUE; } else { xbuf[i] = *rdesc; if (cap) { cap = FALSE; xbuf[i] = UPPER(xbuf[i]); } i++; } } xbuf[i] = 0; strcpy(xbuf2, xbuf); rdesc = xbuf2; xbuf[0] = 0; for (;;) { for (i = 0; i < 77; i++) { if (!*(rdesc + i)) break; } if (i < 77) { break; } for (i = (xbuf[0] ? 76 : 73); i; i--) { if (*(rdesc + i) == ' ') break; } if (i) { *(rdesc + i) = 0; strcat(xbuf, rdesc); strcat(xbuf, "\n\r"); rdesc += i + 1; while (*rdesc == ' ') rdesc++; } else { bug("No spaces", 0); *(rdesc + 75) = 0; strcat(xbuf, rdesc); strcat(xbuf, "-\n\r"); rdesc += 76; } } while (*(rdesc + i) && (*(rdesc + i) == ' ' || *(rdesc + i) == '\n' || *(rdesc + i) == '\r')) i--; *(rdesc + i + 1) = 0; strcat(xbuf, rdesc); if (xbuf[strlen(xbuf) - 2] != '\n') strcat(xbuf, "\n\r"); free_string(oldstring); return (str_dup(xbuf)); } /* * Used above in string_add. Because this function does not * modify case if fCase is FALSE and because it understands * parenthesis, it would probably make a nice replacement * for one_argument. */ /***************************************************************************** Name: first_arg Purpose: Pick off one argument from a string and return the rest. Understands quates, parenthesis (barring ) ('s) and percentages. Called by: string_add(string.c) ****************************************************************************/ char *first_arg(char *argument, char *arg_first, bool fCase) { char cEnd; while (*argument == ' ') argument++; cEnd = ' '; if (*argument == '\'' || *argument == '"' || *argument == '%' || *argument == '(') { if (*argument == '(') { cEnd = ')'; argument++; } else cEnd = *argument++; } while (*argument != '\0') { if (*argument == cEnd) { argument++; break; } if (fCase) *arg_first = LOWER(*argument); else *arg_first = *argument; arg_first++; argument++; } *arg_first = '\0'; while (*argument == ' ') argument++; return argument; } /* * Used in olc_act.c for aedit_builders. */ char *string_unpad(char *argument) { char buf[MAX_STRING_LENGTH]; char *s; s = argument; while (*s == ' ') s++; strcpy(buf, s); s = buf; if (*s != '\0') { while (*s != '\0') s++; s--; while (*s == ' ') s--; s++; *s = '\0'; } free_string(argument); return str_dup(buf); } /* * Same as capitalize but changes the pointer's data. * Used in olc_act.c in aedit_builder. */ char *string_proper(char *argument) { char *s; s = argument; while (*s != '\0') { if (*s != ' ') { *s = UPPER(*s); while (*s != ' ' && *s != '\0') s++; } else { s++; } } return argument; } char *string_linedel(char *string, int line) { char *strtmp = string; char buf[MAX_STRING_LENGTH]; int cnt = 1, tmp = 0; buf[0] = '\0'; for (; *strtmp != '\0'; strtmp++) { if (cnt != line) buf[tmp++] = *strtmp; if (*strtmp == '\n') { if (*(strtmp + 1) == '\r') { if (cnt != line) buf[tmp++] = *(++strtmp); else ++strtmp; } cnt++; } } buf[tmp] = '\0'; free_string(string); return str_dup(buf); } char *string_lineadd(char *string, char *newstr, int line) { char *strtmp = string; int cnt = 1, tmp = 0; bool done = FALSE; char buf[MAX_STRING_LENGTH]; buf[0] = '\0'; for (; *strtmp != '\0' || (!done && cnt == line); strtmp++) { if (cnt == line && !done) { strcat(buf, newstr); strcat(buf, "\n\r"); tmp += strlen(newstr) + 2; cnt++; done = TRUE; } buf[tmp++] = *strtmp; if (done && *strtmp == '\0') break; if (*strtmp == '\n') { if (*(strtmp + 1) == '\r') buf[tmp++] = *(++strtmp); cnt++; } buf[tmp] = '\0'; } free_string(string); return str_dup(buf); } /* buf queda con la linea sin \n\r */ char *getline(char *str, char *buf) { int tmp = 0; bool found = FALSE; while (*str) { if (*str == '\n') { found = TRUE; break; } buf[tmp++] = *(str++); } if (found) { if (*(str + 1) == '\r') str += 2; else str += 1; } buf[tmp] = '\0'; return str; } char *numlineas(char *string) { int cnt = 1; static char buf[MAX_STRING_LENGTH * 2]; char buf2[MAX_STRING_LENGTH], tmpb[MAX_STRING_LENGTH]; buf[0] = '\0'; while (*string) { string = getline(string, tmpb); sprintf(buf2, "%2d. %s\n\r", cnt++, tmpb); strcat(buf, buf2); } return buf; }