greed-0.99.6/
greed-0.99.6/area/
greed-0.99.6/backup/
greed-0.99.6/clans/
greed-0.99.6/classes/
greed-0.99.6/dict/
greed-0.99.6/doc/mprogs/
greed-0.99.6/log/
greed-0.99.6/notes/
greed-0.99.6/player/
/***************************************************************************
 *  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.                              *
 *                                                                         *
 *  Envy Diku Mud improvements copyright (C) 1994 by Michael Quan, David   *
 *  Love, Guilherme 'Willie' Arnold, and Mitchell Tse.                     *
 *                                                                         *
 *  EnvyMud 2.0 improvements copyright (C) 1995 by Michael Quan and        *
 *  Mitchell Tse.                                                          *
 *                                                                         *
 *  EnvyMud 2.2 improvements copyright (C) 1996, 1997 by Michael Quan.     *
 *                                                                         *
 *  GreedMud 0.99.3 improvements copyright (C) 1997, 1998, 1999            *
 *  by Vasco Costa.                                                        *
 *                                                                         *
 *  In order to use any part of this Envy Diku Mud, you must comply with   *
 *  the original Diku license in 'license.doc', the Merc license in        *
 *  'license.txt', as well as the Envy license in 'license.nvy'.           *
 *  In particular, you may not remove either of these copyright notices.   *
 *                                                                         *
 *  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"


/*
 * Pick off one argument from a string and return the rest.
 * Understands quotes.
 */
char *one_line( char *argument, char *arg_first )
{
    char cEnd;

    cEnd = '\n';

    while ( *argument != '\0' )
    {
        if ( *argument == cEnd )
        {
            argument++;
            break;
        }
        *arg_first = *argument;
        arg_first++;
        argument++;
    }
    *arg_first = '\0';

    return argument;
}


void string_edit( CHAR_DATA *ch, char **pString )
{
    send_to_char( "{o{cBegin entering your text now (.h = help .s = show .c = clear @ = save){x\n\r", ch );
    send_to_char( "{o{c-----------------------------------------------------------------------{x\n\r", ch );

    if ( !*pString )
        *pString = str_dup( "" );
    else
        **pString = '\0';

    ch->desc->str_editing = pString;

    return;
}


void string_append( CHAR_DATA *ch, char **pString )
{
    send_to_char( "{o{cBegin entering your text now (.h = help .s = show .c = clear @ = save){x\n\r", ch );
    send_to_char( "{o{c-----------------------------------------------------------------------{x\n\r", ch );

    if ( !*pString )
        *pString = str_dup( "" );
    send_to_char( *pString, ch );
    
    if ( *(*pString + strlen( *pString ) - 1) != '\r' )
    send_to_char( "\n\r", ch );

    ch->desc->str_editing = pString;

    return;
}


char *string_replace( char * orig_s, char * old_s, char * new_s )
{
    char xbuf [ MAX_STRING_LENGTH ];
    int i;

    xbuf[0] = '\0';
    strcpy( xbuf, orig_s );
    if ( strstr( orig_s, old_s ) )
    {
        i = strlen( orig_s ) - strlen( strstr( orig_s, old_s ) );
        xbuf[i] = '\0';
        strcat( xbuf, new_s );
        strcat( xbuf, &orig_s[i+strlen( old_s )] );
        free_string( orig_s );
    }

    return str_dup( xbuf );
}


/*
 * Name:	string_delete_last_line (Made by Zen)
 * Purpose:	Deletes the last line from a string.
 * Called by:	string_add (string.c)
 */
char *string_delete_last_line( char * old )
{
    char *ptr;
    char  buf [ MAX_STRING_LENGTH ];

    strcpy( buf, old );
    ptr = strrchr( buf, '\n' );
    if ( ptr )
	*ptr = '\0';
    ptr = strrchr( buf, '\n' );
    if ( ptr )
	*(ptr + 2) = '\0';
    else
	buf[0] = '\0';

    free_string( old );

    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 ];
	int   line;
	char *start;
	char *end;

        argument = one_argument( argument, arg1        );
        argument = first_arg   ( argument, arg2, FALSE );
        argument = first_arg   ( argument, arg3, FALSE );

        if ( !str_cmp( arg1, ".d" ) )
        {
	    int  val;
	    int  i;

	    if ( arg2[0] == '\0' )
	    {
		send_to_char( "SEdit: Last line of string deleted.\n\r", ch );
		*ch->desc->str_editing =
			    string_delete_last_line( *ch->desc->str_editing );
		return;
	    }

	    val = atoi( arg2 );

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

	    start = &buf[0];

	    for ( line = 1; ( val >= line ); start += 2, line++ )
		if ( !( start = strchr( start, '\n' ) ) )	return;

	    if ( *start == '\n' )
		start += 2;

	    if ( !( end = strchr( start, '\n' ) ) )
	    {
		*start = '\0';		
	    }
	    else
	    {
		for ( i = 0; end[i+2] != '\0'; i++ )
		    start[i] = end[i+2];
		start[i] = '\0';
	    }

	    free_string( *ch->desc->str_editing );
	    *ch->desc->str_editing = str_dup( buf );
	    return;
        }

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

        if ( !str_cmp( arg1, ".s" ) )
        {
	    char  tmp [MAX_STRING_LENGTH];

            send_to_char( "{o{cString so far:{x\n\r", ch );
	    send_to_char( "{o{c-----------------------------------------------------------------------{x\n\r", ch );

	    strcpy( tmp, *ch->desc->str_editing );

	    buf[0] = '\0';
	    
	    start = &tmp[0];

	    for ( line = 0; *start != '\0'; line++ )
	    {
		sprintf ( buf+strlen( buf ), "{o{c%2d>{x ", line );

		end = strstr( start, "\n\r" );

		strncat( buf, start, end ? end-start+2 : strlen( start ) );

		start = end ? end+2 : start+strlen( start );
	    }

	    send_to_char( buf, ch );
	    send_to_char( "{o{c-----------------------------------------------------------------------{x\n\r", 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->str_editing =
                string_replace( *ch->desc->str_editing, arg2, arg3 );
            sprintf( buf, "SEdit: '%s' replaced with '%s'.\n\r", arg2, arg3 );
            send_to_char( buf, ch );
            return;
        }

        if ( !str_cmp( arg1, ".f" ) )
        {
            *ch->desc->str_editing = format_string( *ch->desc->str_editing );
            send_to_char( "SEdit: String formatted.\n\r", ch );
            return;
        }
        
        if ( !str_cmp( arg1, ".h" ) )
        {
            send_to_char( "{o{cSedit help (commands on blank line):{x\n\r", ch );
	    send_to_char( "{o{c-----------------------------------------------------------------------{x\n\r", ch );
            send_to_char( "{o{y.r {w'{yold{w' '{ynew{w'{x     Replace a substring (requires '', \"\").{x\n\r", ch );
            send_to_char( "{o{y.h            {x     Get help (this info).{x\n\r", ch );
            send_to_char( "{o{y.s            {x     Show string so far.{x\n\r", ch );
            send_to_char( "{o{y.f            {x     Word wrap string.{x\n\r", ch );
            send_to_char( "{o{y.c            {x     Clear string so far.{x\n\r", ch );
            send_to_char( "{o{y.d            {x     Delete last line.{x\n\r", ch );
            send_to_char( "{o{y@             {x     End string.{x\n\r", ch );
	    send_to_char( "{o{c-----------------------------------------------------------------------{x\n\r", ch );
            return;
        }
            

        send_to_char( "SEdit:  Invalid dot command.\n\r", ch );
        return;
    }

    if ( *argument == '@' )
    {
        ch->desc->str_editing = NULL;
        return;
    }

    /*
     * 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->str_editing = NULL;
        return;
    }

    strcpy( buf, *ch->desc->str_editing );
    strcat( buf, argument );
    strcat( buf, "\n\r" );
    free_string( *ch->desc->str_editing );
    *ch->desc->str_editing = str_dup( buf );
    return;
}



/*
 *  Thanks to Kalgen for the new procedure (no more bug!)
 *  Original wordwrap() written by Surreality.
 */
char *format_string( char *oldstring /*, bool fSpace */)
{
  char *rdesc;
  char  xbuf	[ MAX_STRING_LENGTH ];
  char  xbuf2	[ MAX_STRING_LENGTH ];
  int   i	= 0;
  bool  cap	= TRUE;
  
  xbuf[0] = xbuf2[0] = 0;
  
  i = 0;
  
  if ( strlen( oldstring ) >= ( MAX_STRING_LENGTH - 4 ) )
  {
     bug( "String to format_string() longer than MAX_STRING_LENGTH.", 0 );
     return ( oldstring );
  }

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



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