/******************************************************************************
 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,           *
 *  Michael Sefert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.       *
 *                                                                            *
 *  Merc Diku Mud improvements copyright (C) 1992, 1993 by Michael            *
 *  Chastain, Michael Quan, and Mitchell Tse.                                 *
 *                                                                            *
 *  Rivers of Mud (ROM 2.3) improvements copyright (C) 1993, 1994 by          *
 *  Russ Taylor.                                                              *
 *                                                                            *
 *  Turns of the Wheel (ToW 1.1) improvements copyright (C) 1995, 1998        *
 *  by Geoff Cook and Shawn Faucher.                                          *
 *                                                                            *
 *  In order to use any part of this Mud, you must comply with all license    *
 *  agreements, including Diku (license.doc), Merc (license.txt), and ROM     *
 *  (license.rom)  In particular, you may not remove  any of these copyright  *
 *  and all license agreements must be present and unmodified.                 *
 *                                                                            *
 *     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                                                            *
 *                                                                            *
 *  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"

/*
 * Called from act_comm.c for when someone is adjusting the body of 
 * a note that has already been posted. 
 */

void    write_all_notes (void);

/*****************************************************************************
 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 (*pString, ch);

	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_replace2
 Purpose:	Replaces a line of text.
 Called by:	string_add(string.c) (aedit_builder)olc_act.c.
 ****************************************************************************/
char   *string_replace2 (CHAR_DATA * ch, char *orig, int line, char *new)
{
	char   *rdesc;
	char    xbuf[MAX_STRING_LENGTH];
	int     current_line = 1;
	int     i;
	bool    fReplaced = FALSE;

	xbuf[0] = '\0';
	strcpy (xbuf, orig);

	i = 0;

	for (rdesc = orig; *rdesc; rdesc++)
	{
		if (current_line == line && !fReplaced)
		{
			xbuf[i] = '\0';

			if (*new)
				strcat (xbuf, new);
			strcat (xbuf, "\n\r");
			fReplaced = TRUE;
		}

		if (current_line == line + 1)
		{
			strcat (xbuf, &orig[i]);
			free_string (orig);

			send_to_char ("Line replaced.\n\r", ch);

			return str_dup (xbuf);
		}

		i++;

		if (*rdesc == '\r')
			current_line++;
	}

	if (current_line - 1 != line)
	{
		send_to_char ("That line does not exist.\n\r", ch);
		return str_dup (xbuf);
	}

	free_string (orig);
	send_to_char ("Line replaced.\n\r", ch);

	return str_dup (xbuf);
}

/*****************************************************************************
 Name:		string_insertline
 Purpose:	Inserts a line, blank or containing text.
 Called by:	string_add(string.c) (aedit_builder)olc_act.c.
 ****************************************************************************/
char   *string_insertline (CHAR_DATA * ch, char *orig, int line, char *addstring)
{
	char   *rdesc;
	char    xbuf[MAX_STRING_LENGTH];
	int     current_line = 1;
	int     i;

	xbuf[0] = '\0';
	strcpy (xbuf, orig);

	i = 0;

	for (rdesc = orig; *rdesc; rdesc++)
	{
		if (current_line == line)
			break;

		i++;

		if (*rdesc == '\r')
			current_line++;
	}

	if (!*rdesc)
	{
		send_to_char ("That line does not exist.\n\r", ch);
		return str_dup (xbuf);
	}

	xbuf[i] = '\0';

	if (*addstring)
		strcat (xbuf, addstring);
	strcat (xbuf, "\n\r");

	strcat (xbuf, &orig[i]);
	free_string (orig);

	send_to_char ("Line inserted.\n\r", ch);

	return str_dup (xbuf);
}


/*****************************************************************************
 Name:		string_deleteline
 Purpose:	Deletes a specified line of the string.
 Called by:	string_add(string.c) (aedit_builder)olc_act.c.
 ****************************************************************************/
char   *string_deleteline (char *orig, int line)
{
	char   *rdesc;
	char    xbuf[MAX_STRING_LENGTH];
	int     current_line = 1;
	int     i = 0;

	xbuf[0] = '\0';

	for (rdesc = orig; *rdesc; rdesc++)
	{
		if (current_line != line)
		{
			xbuf[i] = *rdesc;
			i++;
		}

		if (*rdesc == '\r')
			current_line++;
	}

	free_string (orig);
	xbuf[i] = 0;

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

		argument = one_argument (argument, arg1);
		
		if (!str_cmp (arg1, "./"))
		{
			interpret(ch, argument);
			send_to_char ("Command performed.\n\r", ch);
			return;
		}
		
		argument = first_arg (argument, arg2, FALSE);
		argument = first_arg (argument, arg3, FALSE);

		if (!str_cmp (arg1, ".c"))
		{
			send_to_char ("String cleared.\n\r", ch);
			**ch->desc->pString = '\0';
			return;
		}

		if (!str_cmp (arg1, ".s"))
		{
			char   *rdesc;
			int     i = 1;

			printf_to_char (ch, "`5%2d`` ", i);

			for (rdesc = *ch->desc->pString; *rdesc; rdesc++)
			{
				if (*rdesc != '`')
					printf_to_char (ch, "%c", rdesc[0]);
				else
				{
					if (rdesc[1] == 'Z')
						send_to_char ("{Z}", ch);
					else
						printf_to_char (ch, "%c%c", rdesc[0], rdesc[1]);
					rdesc++;
				}


				if (*rdesc == '\r' && *(rdesc + 1))
				{
					i++;
					printf_to_char (ch, "`5%2d`` ", i);
				}
			}
/*            send_to_char( *ch->desc->pString, ch ); */

			return;
		}

		if (!str_cmp (arg1, ".sp"))
		{
			spell_check (ch, *ch->desc->pString);
			return;
		}

		if (!str_cmp (arg1, ".r"))
		{
			if (arg2[0] == '\0')
			{
				send_to_char (
				   "usage:  .r \"old string\" \"new string\"\n\r", ch);
				return;
			}

			smash_tilde (arg3);	/* Just to be sure -- Hugin */
			*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, ".rl"))
		{
			if (arg2[0] == '\0' || !is_number (arg2))
			{
				send_to_char (
				   "usage:  .rl <line> <text>\n\r", ch);
				return;
			}

			smash_tilde (arg3);	/* Just to be sure -- Hugin */
			*ch->desc->pString =
			   string_replace2 (ch, *ch->desc->pString, atoi (arg2), arg3);
			return;
		}


		if (!str_cmp (arg1, ".i"))
		{
			if (arg2[0] == '\0' || !is_number (arg2))
			{
				send_to_char (
				   "usage:  .i <line> {text}\n\r", ch);
				return;
			}

			smash_tilde (arg3);	/* Just to be sure -- Hugin */
			*ch->desc->pString =
			   string_insertline (ch, *ch->desc->pString, atoi (arg2), arg3);
			return;
		}


		if (!str_cmp (arg1, ".d"))
		{
			if (arg2[0] == '\0' || !is_number (arg2))
			{
				send_to_char (
				   "usage:  .d <line>\n\r", ch);
				return;
			}

			*ch->desc->pString =
			   string_deleteline (*ch->desc->pString, atoi (arg2));
			sprintf (buf, "Line %d deleted.\n\r", atoi (arg2));
			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, ".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 (".rl <line> <text> - replaces a line    \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 (".sp              - spell check string  \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 (".d <line>        - deletes a line      \n\r", ch);
			send_to_char (".i <line> {text} - inserts a line	  \n\r", ch);
			send_to_char ("./ <command>     - do a regular command\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->string_editor == SE_NOTE_ADJUST)
			write_all_notes ();

		ch->desc->pString = NULL;
		ch->desc->string_editor = 0;
		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.
 * Modifications for color codes and blank lines by Geoff.
 */
/*****************************************************************************
 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;
	int     end_of_line;
	bool    cap = TRUE;
	bool    bFormat = TRUE;

	xbuf[0] = xbuf2[0] = 0;

	i = 0;

	for (rdesc = oldstring; *rdesc; rdesc++)
	{

		if (*rdesc != '`')
		{
			if (bFormat)
			{
				if (*rdesc == '\n')
				{
					if (*(rdesc + 1) == '\r' && *(rdesc + 2) == ' ' && *(rdesc + 3) == '\n' && xbuf[i - 1] != '\r')
					{
						xbuf[i] = '\n';
						xbuf[i + 1] = '\r';
						xbuf[i + 2] = '\n';
						xbuf[i + 3] = '\r';
						i += 4;
						rdesc += 2;
					}
					else if (*(rdesc + 1) == '\r' && *(rdesc + 2) == ' ' && *(rdesc + 2) == '\n' && xbuf[i - 1] == '\r')
					{
						xbuf[i] = '\n';
						xbuf[i + 1] = '\r';
						i += 2;
					}
					else if (*(rdesc + 1) == '\r' && *(rdesc + 2) == '\n' && xbuf[i - 1] != '\r')
					{
						xbuf[i] = '\n';
						xbuf[i + 1] = '\r';
						xbuf[i + 2] = '\n';
						xbuf[i + 3] = '\r';
						i += 4;
						rdesc += 1;
					}
					else if (*(rdesc + 1) == '\r' && *(rdesc + 2) == '\n' && xbuf[i - 1] == '\r')
					{
						xbuf[i] = '\n';
						xbuf[i + 1] = '\r';
						i += 2;
					}
					else if (xbuf[i - 1] != ' ' && xbuf[i - 1] != '\r')
					{
						xbuf[i] = ' ';
						i++;
					}
				}
				else if (*rdesc == '\r') ;
				else if (*rdesc == 'i' && *(rdesc + 1) == '.' && *(rdesc + 2) == 'e' && *(rdesc + 3) == '.')
				{
					xbuf[i] = 'i';
					xbuf[i + 1] = '.';
					xbuf[i + 2] = 'e';
					xbuf[i + 3] = '.';
					i += 4;
					rdesc += 3;
				}
				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 if (xbuf[i - 1] == ' ' && (xbuf[i - 2] == ',' || xbuf[i - 2] == ';'))
					{
						xbuf[i - 1] = *rdesc;
						xbuf[i] = ' ';
						i++;
					}
					else
					{
						xbuf[i] = *rdesc;
						i++;
					}
				}
				else if (*rdesc == ',' || *rdesc == ';')
				{
					if (xbuf[i - 1] == ' ')
					{
						xbuf[i - 1] = *rdesc;
						xbuf[i] = ' ';
						i++;
					}
					else
					{
						xbuf[i] = *rdesc;
						if (*(rdesc + 1) != '\"')
						{
							xbuf[i + 1] = ' ';
							i += 2;
						}
						else
						{
							xbuf[i + 1] = '\"';
							xbuf[i + 2] = ' ';
							i += 3;
							rdesc++;
						}
					}

				}
				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++;
				}
			}
			else
			{
				xbuf[i] = *rdesc;
				i++;
			}
		}
		else
		{
			if (*(rdesc + 1) == 'Z')
				bFormat = !bFormat;
			xbuf[i] = *rdesc;
			i++;
			rdesc++;
			xbuf[i] = *rdesc;
			i++;
		}
	}
	xbuf[i] = 0;
	strcpy (xbuf2, xbuf);

	rdesc = xbuf2;

	xbuf[0] = 0;

	for (;;)
	{
		end_of_line = 77;
		for (i = 0; i < end_of_line; i++)
		{
			if (*(rdesc + i) == '`')
			{
				end_of_line += 2;
				i++;
			}

			if (!*(rdesc + i))
				break;

			if (*(rdesc + i) == '\r')
				end_of_line = i;
		}
		if (i < end_of_line)
		{
			break;
		}
		if (*(rdesc + i - 1) != '\r')
		{
			for (i = (xbuf[0] ? (end_of_line - 1) : (end_of_line - 4)); 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 ("`5Wrap_string: `@No spaces``", 0);
				*(rdesc + (end_of_line - 2)) = 0;
				strcat (xbuf, rdesc);
				strcat (xbuf, "-\n\r");
				rdesc += end_of_line - 1;
			}
		}
		else
		{
			*(rdesc + i - 1) = 0;
			strcat (xbuf, rdesc);
			strcat (xbuf, "\r");
			rdesc += i;
			while (*rdesc == ' ')
				rdesc++;
		}
	}
	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));
}

/*****************************************************************************
 Name:		wrap_string
 Purpose:	String word-wrapping for those whose terms don't have it.
 Called by:	(many)act_comm.c (act_new)comm.c
 ****************************************************************************/

char   *wrap_string ( char *oldstring, int length )
{
	char    xbuf[MAX_STRING_LENGTH];
	static char    xbuf2[MAX_STRING_LENGTH];
	char   *rdesc;
	int     i = 0;
	int     end_of_line;
	
	if (!length)
	{
		strcpy (xbuf2, oldstring);
		return xbuf2;
	}
	
	xbuf[0] = xbuf2[0] = '\0';

	i = 0;

	rdesc = oldstring;

	for (;;)
	{
		end_of_line = length;
		for (i = 0; i < end_of_line; i++)
		{
			if (*(rdesc + i) == '`')
			{
				end_of_line += 2;
				i++;
			}

			if (!*(rdesc + i))
				break;

			if (*(rdesc + i) == '\r')
				end_of_line = i;
		}
		if (i < end_of_line)
		{
			break;
		}
		if (*(rdesc + i - 1) != '\r')
		{
			for (i = (xbuf[0] ? (end_of_line - 1) : (end_of_line - 4)); 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");
				*(rdesc + (end_of_line - 2)) = 0;
				strcat (xbuf, rdesc);
				strcat (xbuf, "-\n\r");
				rdesc += end_of_line - 1;
			}
		}
		else
		{
			*(rdesc + i - 1) = 0;
			strcat (xbuf, rdesc);
			strcat (xbuf, "\r");
			rdesc += i;
			while (*rdesc == ' ')
				rdesc++;
		}
	}
	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");
	strcpy(xbuf2, xbuf);
	return (xbuf2);
}

/*****************************************************************************
 Name:		spell_check
 Purpose:	Spell-check strings with ispell (*nix only)
 Called by:	(string_add)string.c
 ****************************************************************************/

void    spell_check (CHAR_DATA * ch, char *string)
{
	char    buf[MAX_STRING_LENGTH];
	char    newstr[MAX_STRING_LENGTH];
	char    line[MAX_STRING_LENGTH];
	char    chr;
	FILE   *fp;
	char   *rstr;
	int     i = 0;

	newstr[0] = 0;
	line[0] = 0;

	if (string == NULL)
		return;

	for (rstr = string; *rstr; rstr++)
	{
		if (*rstr != '\r' && *rstr != '~')
		{
			if (*rstr == '`')
			{
				rstr++;
			}
			else if (*rstr == '\n')
			{
				newstr[i] = ' ';
				i++;
			}
			else
			{
				newstr[i] = *rstr;
				i++;
			}
		}
	}
	newstr[i] = 0;

	fp = fopen ("spell_check.txt", "w");
	fprintf (fp, "!\n\r%s\n\r", newstr);
	fclose (fp);
	sprintf (buf, "cat spell_check.txt | ispell -a -f spell_check.txt");
	system (buf);
	if ((fp = fopen ("spell_check.txt", "r")) != NULL)
	{
		i = 0;
		while (!feof (fp))
		{
			chr = getc (fp);
			line[i] = chr;
			i++;
		}
		line[i] = 0;
		fclose (fp);
		system ("rm spell_check.txt");

		newstr[0] = 0;
		i = 0;
		for (rstr = str_dup (line); *rstr; rstr++)
		{
			if (*rstr == '\n' && *(rstr + 1) == '\n')
			{
				rstr++;
			}
			else
			{
				if (*rstr == '\r')
					send_to_char ("`5*``", ch);
				newstr[i] = *rstr;
				i++;
			}
		}
		free_string(rstr);
		newstr[i] = 0;
		strcat (newstr, "\n\r\n\r");
		send_to_char (newstr, ch);
	}
	return;
}




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