legend/
legend/area/
legend/player/
/******************************************************************************
 *  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.                   *
 *                                                                            *
 ******************************************************************************/
/***************************************************************************
 *  God Wars Mud copyright (C) 1994, 1995, 1996 by Richard Woolcock        *
 *                                                                         *
 *  Legend of Chrystancia copyright (C) 1999, 2000, 2001 by Matthew Little *
 *  This mud is NOT to be copied in whole or in part, or to be run without *
 *  the permission of Matthew Little. Nobody else has permission to        *
 *  authorise the use of this code.                                        *
 ***************************************************************************/

#define send_to_char send_to_char2
#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <ctype.h>
#include <stdarg.h>		//printf_to_char
#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);
void spell_check (CHAR_DATA * ch, char *string);

void printf_to_char (CHAR_DATA * ch, char *fmt, ...)
{
   char buf[MAX_STRING_LENGTH];
   va_list args;
   va_start (args, fmt);
   vsprintf (buf, fmt, args);
   va_end (args);

   send_to_char (buf, ch);
}


int arg_count (char *argument)
{
   int total;
   char *s;

   total = 0;
   s = argument;

   while (*s != '\0')
   {
      if (*s != ' ')
      {
	 total++;
	 while (*s != ' ' && *s != '\0')
	    s++;
      }
      else
      {
	 s++;
      }
   }

   return total;
}


/*****************************************************************************
 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:`n ", 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:`n ", 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;
      stc ("Done.\n\r", ch);
      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`n", 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", 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");
   strcpy (xbuf2, xbuf);
   return (xbuf2);
}

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

void ospell_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*`n", 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;
}

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

void do_spellcheck (CHAR_DATA * ch, char *argument)
{
   if (IS_NPC (ch))
      return;

   if (argument[0] == '\0')
   {
      stc ("Spell Check what?\n\r", ch);
      return;
   }

   spell_check (ch, argument);

   stc ("Spelling Check COMPLETE.\n\r", ch);

   return;
}

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*#n", ch);
	    newstr[i] = *rstr;
	    i++;
	 }
      }
      free_string (rstr);
      newstr[i] = 0;
      strcat (newstr, "\n\r\n\r");
      send_to_char (newstr, ch);
   }
   return;
}