asgard/
asgard/.settings/
asgard/area/
asgard/data/clans/
asgard/data/clans/history/
asgard/data/rosters/
asgard/src/notice/
/***************************************************************************
 *  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)
{
	/* Put into quiet mode */
	if (!IS_SET(ch->comm, COMM_QUIET))
		SET_BIT (ch->comm, COMM_QUIET);

	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)
{
	/* Put into quiet mode */
	if (!IS_SET(ch->comm, COMM_QUIET))
		SET_BIT (ch->comm, COMM_QUIET);

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

/***************************************************************************** 
 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 removed.\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> at 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 == '@')
	{
		/* Remove quiet mode */
		if (IS_SET(ch->comm, COMM_QUIET))
			REMOVE_BIT(ch->comm, COMM_QUIET);

		if (ch->desc->editor == ED_MPCODE) /* for mobprogs */
		{
			MOB_INDEX_DATA *mob;
			int hash;
			MPROG_LIST *mpl;
			MPROG_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, "Fixing mob %d.\n\r", mob->vnum);
								send_to_char(buf, ch);
								mpl->code = mpc->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))
	{
		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
		{
			printf_debug("No spaces");
			*(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 *get_line(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 = get_line(string, tmpb);
		sprintf(buf2, "%2d. %s\n\r", cnt++, tmpb);
		strcat(buf, buf2);
	}

	return buf;
}

char *end_string(const char *txt, int length)
{
	static char buf[MAX_STRING_LENGTH];

	strcpy(buf, txt);

	if (length < 0)
	{
		printf_debug("End_string: negative length!");
		return buf;
	}

	if (strlen_color(buf) < length)
	{
		while (strlen_color(buf) < length)
			strcat(buf, " ");
	}
	else
	{
		int place = strlen(buf);

		while (strlen_color(buf) > length)
		{
			place--;
			buf[place] = '\0';
		}

		if (buf[place - 1] == '{' && buf[place - 2] != '{')
			buf[place - 1] = '\0';

		strcat(buf, "{x");
	}

	return buf;
}

char *begin_string(const char *txt, int length)
{
	static char buf[MAX_STRING_LENGTH];
	char str[MAX_STRING_LENGTH];

	strcpy(buf, txt);

	if (length < 0)
	{
		printf_debug("Begin_string: negative length!");
		return buf;
	}

	if (strlen_color(buf) < length)
	{
		while (strlen_color(buf) < length)
		{
			sprintf(str, " %s", buf);
			strcpy(buf, str);
		}
	}
	else
	{
		int place = strlen(buf);

		while (strlen_color(buf) > length)
		{
			place--;
			buf[place] = '\0';
		}

		if (buf[place - 1] == '{' && buf[place - 2] != '{')
			buf[place - 1] = '\0';

		strcat(buf, "{x");
	}

	return buf;
}

int strlen_color(char *argument)
{
	char *str;
	int length;

	if (argument == NULL || argument[0] == '\0')
		return 0;

	length = 0;
	str = argument;

	while (*str != '\0')
	{
		if (*str == '{')
		{
			str++;
			if (*str == '{' || *str == '-')
				length++;
			str++;
			continue;
		}

		str++;
		length++;
	}

	return length;
}

char *next_arg(char *argument, char *arg_first)
{
	while (*argument != '\0')
	{
		*arg_first++ = *argument++;

		if (*argument == ' ')
			break;
	}

	*arg_first = '\0';

	return argument;
}

char *length_argument(char *argument, char *arg_first, int length)
{
	char next[MAX_INPUT_LENGTH];

	*arg_first = '\0';

	while (*argument)
	{
		next_arg(argument, next);

		if (strlen_color(next) > length)
		{
			strcpy(arg_first,
					"{RHey dumbass, how about some SPACES between your words!{x");
			return "";
		}

		if (strlen_color(arg_first) + strlen_color(next) > length)
			break;

		strcat(arg_first, next);

		argument = next_arg(argument, next);
	}

	while (isspace( *argument ))
		argument++;

	return argument;
}

char *escape_colours(char *argument) {
	static char buf[MAX_STRING_LENGTH];
	int i;

	for (i = 0; *argument != '\0' && i < MAX_STRING_LENGTH-1; ++argument) {
		buf[i] = *argument;
		++i;
		if (i < MAX_STRING_LENGTH-1 && *argument == '{') {
			buf[i] = '{';
			++i;
		}
	}
	buf[i] = '\0';
	return buf;
}