GmudV33/
GmudV33/player/
GmudV33/public_html/
GmudV33/public_html/IMAGES/_VTI_CNF/
GmudV33/src_linux/Debug/
GmudV33/text/clans/
/***************************************************************************
 *  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.                *
 *                                                                         *
 ***************************************************************************/


#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "merc.h"
#include "tables.h"
#include "olc.h"

char *string_linedel (char *, int);
char *string_lineadd (char *, char *, int);
char *numlineas (char *);

/*****************************************************************************
 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 ("-========- Entering EDIT Mode -=========-\n\r", ch);
	send_to_char ("    Type .h on a new line for help\n\r", ch);
	send_to_char (" Terminate with a ~ or @ on a blank line.\n\r", ch);
	send_to_char ("-=======================================-\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 ("-=======- Entering APPEND Mode -========-\n\r", ch);
	send_to_char ("    Type .h on a new line for help\n\r", ch);
	send_to_char (" Terminate with a ~ or @ on a blank line.\n\r", ch);
	send_to_char ("-=======================================-\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.
 *  Notes:         modified by Calath (gblues@jps.net) to prevent buffer
 *                 overruns
 * ****************************************************************************/


char *string_replace (char *orig, char *old, char *new)
{
	char buf[MAX_STRING_LENGTH];
	char *ptr = strstr (orig, old);
	int a, b;

	if ((ptr == NULL
		 || (a = ptr - orig) + strlen (new) >= (MAX_STRING_LENGTH - 4))) {
		return orig;
	}
	b = MAX_STRING_LENGTH - 4 - a - strlen (new);
	strncpy (buf, orig, MAX_STRING_LENGTH);
	strncpy (buf + a, new, strlen (new));
	strncpy (buf + a + strlen (new), ptr + strlen (old), b);
	buf[MAX_STRING_LENGTH - 4] = '\0';

	free_string (orig);
	return str_dup (buf);
}

/*****************************************************************************
 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 ("Linea borrada.\n\r", ch);
			return;
		}

		if (!str_cmp (arg1, ".li")) {
			*ch->desc->pString =
				string_lineadd (*ch->desc->pString, tmparg3, atoi (arg2));
			send_to_char ("Linea insertada.\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 ("Linea reemplazada.\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>        - borra linea numero <num>\n\r",
						  ch);
			send_to_char (".li <num> <str>  - anade <str> en linea <num>\n\r",
						  ch);
			send_to_char
				(".lr <num> <str>  - reemplaza linea <num> por <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) {
								sprintf (buf, "Arreglando mob %ld.\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;
			int hash;
			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 )
							{
								sprintf( 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;
			int hash;
			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 )
							{
								sprintf( buf, "Fixing room %d.\n\r", room->vnum );
								send_to_char( buf, ch );
								rpl->code = rpc->code;
							}
		}

		ch->desc->pString = NULL;
		return;
	}

	strcpy (buf, *ch->desc->pString);

	/*
	 * Truncate strings to MAX_STRING_LENGTH.
	 * --------------------------------------
	 */
/*	if (strlen (buf) + strlen (argument) >= (MAX_STRING_LENGTH - 4))
	*removed 050801 next line added */
	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;
}

/* Technically doesn't need fixing, but this is a little more efficient I think.
 * Plus it doesn't use evil strcpy or strcat!
 * Modified by Calath (gblues@jps.net) to prevent buffer
 * overruns.
 */
char *string_linedel (char *string, int line)
{
	char *lineend, *linestart = string;
	char buf[MAX_STRING_LENGTH];
	int bytes = 0, cnt = 1, done = FALSE;
	if (strlen (string) >= MAX_STRING_LENGTH - 4)
		return string;
	do {
		int len;
		if ((lineend = strstr (linestart, "\n\r")) == NULL)
			done = TRUE;
		len = lineend ? (lineend + 2) - linestart : strlen (linestart);
		if (cnt != line)
			strncpy (buf + bytes, linestart, len);
		linestart = lineend ? lineend + 2 : linestart;
		cnt++;
	}
	while (!done);
	buf[bytes] = '\0';
	free_string (string);
	return str_dup (buf);
}


/*
 * Similar to above. Again, avoids evil strcat and strcpy.
 * Modified by Calath (gblues@jps.net) to prevent buffer
 * overruns.
 */

char *string_lineadd (char *string, char *newstr, int line)
{
	char *lineend, *linestart = string;
	char buf[MAX_STRING_LENGTH];
	char newline[MAX_INPUT_LENGTH];
	int bytes = 0, cnt = 1, done = FALSE;
	int len;
	sprintf (newline, "%s\n\r", newstr);
	newstr = newline;
	if (strlen (string) + strlen (newstr) >= MAX_STRING_LENGTH - 4)
		return string;
	do {
		if (cnt == line) {
			strncpy (buf + bytes, newstr, strlen (newstr));
			bytes += strlen (newstr);
			cnt++;
			continue;
		}
		if ((lineend = strstr (linestart, "\n\r")) == NULL)
			done = TRUE;
		len = lineend ? (lineend + 2) - linestart : strlen (linestart);
		strncpy (buf + bytes, linestart, len);
		bytes += len;
		linestart = lineend ? lineend + 2 : linestart;
		cnt++;
	}
	while (!done);
	buf[bytes] = '\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;
	}							/* para que quedemos en el inicio de la prox linea */

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