/***************************************************************************
* 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;
}