swr2.0/
swr2.0/area/
swr2.0/boards/
swr2.0/clans/
swr2.0/doc/
swr2.0/planets/
swr2.0/spacecraft/
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>

#include "swr_support.h"
#include "sha256.h"

extern FILE *out_stream;

#define HIDDEN_TILDE    '*'

typedef bool STRING_COMPARATOR( const char*, const char* );
typedef char *STRING_TOKENIZER( char*, char* );

#ifdef __cplusplus
extern "C" {
#endif
void bug( const char *str, ... );
#ifdef __cplusplus
}
#endif

static bool is_name2( const char*, const char* );
static bool is_name2_prefix( const char*, const char* );
static bool is_name_internal( const char*, const char*, STRING_COMPARATOR*, STRING_TOKENIZER* );
static bool nifty_is_name_internal( const char*, const char*,
				    STRING_COMPARATOR*, STRING_TOKENIZER* );
/*
 * See if a string is one of the names of an object.
 */
static bool is_name_internal( const char *str, const char *namelist,
			      STRING_COMPARATOR *compare_string,
			      STRING_TOKENIZER *tokenize_string )
{
  char name[MAX_INPUT_LENGTH];
  char tmp_buf[MAX_INPUT_LENGTH];
  char *tmp = tmp_buf;
  snprintf( tmp_buf, MAX_INPUT_LENGTH, "%s", namelist );

  for ( ; ; )
  {
    tmp = tokenize_string( tmp, name );

    if ( name[0] == '\0' )
      {
	return FALSE;
      }

    if ( !compare_string( str, name ) )
      {
	return TRUE;
      }
  }
}

bool is_name( const char *str, const char *namelist )
{
  return is_name_internal( str, namelist, str_cmp, one_argument );
}

bool is_name_prefix( const char *str, const char *namelist )
{
  return is_name_internal( str, namelist, str_prefix, one_argument );
}

/*
 * See if a string is one of the names of an object.            -Thoric
 * Treats a dash as a word delimiter as well as a space
 */
bool is_name2( const char *str, const char *namelist )
{
  return is_name_internal( str, namelist, str_cmp, one_argument2 );
}

bool is_name2_prefix( const char *str, const char *namelist )
{
  return is_name_internal( str, namelist, str_prefix, one_argument2 );
}

/*                                                              -Thoric
 * Checks if str is a name in namelist supporting multiple keywords
 */
static bool nifty_is_name_internal( const char *str, const char *namelist,
				    STRING_COMPARATOR *compare_string,
				    STRING_TOKENIZER *tokenize_string )
{
  char name[MAX_INPUT_LENGTH];
  char tmp_str_buf[MAX_INPUT_LENGTH];
  char *tmp_str = tmp_str_buf;
  char tmp_namelist_buf[MAX_INPUT_LENGTH];
  char *tmp_namelist = tmp_namelist_buf;

  if( !str || str[0] == '\0' )
    return FALSE;

  snprintf( tmp_str_buf, MAX_INPUT_LENGTH, "%s", str );
  snprintf( tmp_namelist_buf, MAX_INPUT_LENGTH, "%s", namelist );

  for ( ; ; )
  {
    tmp_str = tokenize_string( tmp_str, name );

    if ( name[0] == '\0' )
      return TRUE;

    if ( !compare_string( name, tmp_namelist ) )
      return FALSE;
  }
}

bool nifty_is_name( const char *str, const char *namelist )
{
  return nifty_is_name_internal( str, namelist, is_name2, one_argument2 );
}

bool nifty_is_name_prefix( const char *str, const char *namelist )
{
  return nifty_is_name_internal( str, namelist, is_name2_prefix, one_argument2 );
}

/*
 * Removes the tildes from a string.
 * Used for player-entered strings that go into disk files.
 */
void smash_tilde( char *str )
{
  replace_char( str, '~', '-' );
}

/*
 * Encodes the tildes in a string.                              -Thoric
 * Used for player-entered strings that go into disk files.
 */
void hide_tilde( char *str )
{
  replace_char( str, '~', HIDDEN_TILDE );
}

char *show_tilde( char *str )
{
  static char buf[MAX_STRING_LENGTH];
  char *bufptr = buf;

  for ( ; *str != '\0'; str++, bufptr++ )
  {
    if ( *str == HIDDEN_TILDE )
      *bufptr = '~';
    else
      *bufptr = *str;
  }
  *bufptr = '\0';

  return buf;
}

/*
 * Compare strings, case insensitive.
 * Return TRUE if different
 *   (compatibility with historical functions).
 */
bool str_cmp( const char *astr, const char *bstr )
{
  if ( !astr )
  {
    bug( "Str_cmp: null astr." );
    if ( bstr )
      fprintf( out_stream, "str_cmp: astr: (null)  bstr: %s\n", bstr );
    return TRUE;
  }

  if ( !bstr )
  {
    bug( "Str_cmp: null bstr." );
    if ( astr )
      fprintf( out_stream, "str_cmp: astr: %s  bstr: (null)\n", astr );
    return TRUE;
  }

  for ( ; *astr || *bstr; astr++, bstr++ )
  {
    if ( LOWER(*astr) != LOWER(*bstr) )
      return TRUE;
  }

  return FALSE;
}

/*
 * Compare strings, case insensitive, for prefix matching.
 * Return TRUE if astr not a prefix of bstr
 *   (compatibility with historical functions).
 */
bool str_prefix( const char *astr, const char *bstr )
{
  if ( !astr )
  {
    bug( "Strn_cmp: null astr." );
    return TRUE;
  }

  if ( !bstr )
  {
    bug( "Strn_cmp: null bstr." );
    return TRUE;
  }

  for ( ; *astr; astr++, bstr++ )
  {
    if ( LOWER(*astr) != LOWER(*bstr) )
      return TRUE;
  }

  return FALSE;
}

/*
 * Compare strings, case insensitive, for match anywhere.
 * Returns TRUE is astr not part of bstr.
 *   (compatibility with historical functions).
 */
bool str_infix( const char *astr, const char *bstr )
{
  int sstr1 = strlen(astr);
  int sstr2 = strlen(bstr);
  int ichar = 0;
  char c0 = 0;

  if ( ( c0 = LOWER(astr[0]) ) == '\0' )
    return FALSE;

  for ( ichar = 0; ichar <= sstr2 - sstr1; ichar++ )
    if ( c0 == LOWER(bstr[ichar]) && !str_prefix( astr, bstr + ichar ) )
      return FALSE;

  return TRUE;
}

/*
 * Compare strings, case insensitive, for suffix matching.
 * Return TRUE if astr not a suffix of bstr
 *   (compatibility with historical functions).
 */
bool str_suffix( const char *astr, const char *bstr )
{
  int sstr1 = strlen(astr);
  int sstr2 = strlen(bstr);

  if ( sstr1 <= sstr2 && !str_cmp( astr, bstr + sstr2 - sstr1 ) )
    return FALSE;
  else
    return TRUE;
}

/*
 * Returns an initial-capped string.
 * Rewritten by FearItself@AvP
 */
char *capitalize( const char *str )
{
  static char buf[MAX_STRING_LENGTH];
  char *dest = buf;
  enum { Normal, Color } state = Normal;
  bool bFirst = TRUE;
  char c = 0;

  while( (c = *str++) )
  {
    if( state == Normal )
    {
      if( c == '&' || c == '^' || c == '}' )
      {
	state = Color;
      }
      else if( isalpha( (int) c ) )
      {
	c = bFirst ? toupper( (int) c )  : tolower( (int) c );
	bFirst = FALSE;
      }
    }
    else
    {
      state = Normal;
    }

    *dest++ = c;
  }

  *dest = c;

  return buf;
}

/*
 * Returns a lowercase string.
 */
char *strlower( const char *str )
{
  static char strlow[MAX_STRING_LENGTH];
  int i = 0;

  for ( i = 0; str[i] != '\0'; i++ )
    strlow[i] = LOWER(str[i]);

  strlow[i] = '\0';
  return strlow;
}

/*
 * Returns an uppercase string.
 */
char *strupper( const char *str )
{
  static char strup[MAX_STRING_LENGTH];
  int i = 0;

  for ( i = 0; str[i] != '\0'; i++ )
    strup[i] = UPPER(str[i]);

  strup[i] = '\0';
  return strup;
}

/*
 * Returns TRUE or FALSE if a letter is a vowel                 -Thoric
 */
#if defined(AMIGA) || defined(__MORPHOS__)
static bool isavowel( unsigned letter )
#else
static bool isavowel( char letter )
#endif
{
  char c = tolower( (int)letter );

  if ( c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u' )
    return TRUE;
  else
    return FALSE;
}

/*
 * Shove either "a " or "an " onto the beginning of a string    -Thoric
 */
const char *aoran( const char *str )
{
  static char temp[MAX_STRING_LENGTH];

  if ( !str )
  {
    bug( "Aoran(): NULL str" );
    return "";
  }

  if ( isavowel(str[0])
      || ( strlen(str) > 1 && tolower((int)str[0]) == 'y'
	&& !isavowel(str[1])) )
    strcpy( temp, "an " );
  else
    strcpy( temp, "a " );

  strcat( temp, str );
  return temp;
}

void replace_char( char *buf, char replace, char with )
{
  size_t i = 0;

  for( i = 0; i < strlen( buf ); ++i )
  {
    if( buf[i] == replace )
    {
      buf[i] = with;
    }
  }
}

/*
 * Return true if an argument is completely numeric.
 */
bool is_number( const char *arg )
{
  if ( *arg == '\0' )
    return FALSE;

  for ( ; *arg != '\0'; arg++ )
  {
    if ( !isdigit((int) *arg) )
      return FALSE;
  }

  return TRUE;
}

/*
 * Given a string like 14.foo, return 14 and 'foo'
 */
int number_argument( const char *orig_argument, char *arg )
{
  char *pdot = NULL;
  int number = 0;
  char argument[MAX_STRING_LENGTH];
  snprintf( argument, MAX_STRING_LENGTH, "%s", orig_argument );

  for ( pdot = argument; *pdot != '\0'; pdot++ )
  {
    if ( *pdot == '.' )
    {
      *pdot = '\0';
      number = atoi( argument );
      *pdot = '.';
      strcpy( arg, pdot+1 );
      return number;
    }
  }

  strcpy( arg, argument );
  return 1;
}

/*
 * Pick off one argument from a string and return the rest.
 * Understands quotes.
 */
char *one_argument( char *argument, char *arg_first )
{
  char cEnd = ' ';
  short count = 0;

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

  if ( *argument == '\'' || *argument == '"' )
    cEnd = *argument++;

  while ( *argument != '\0' || ++count >= 255 )
  {
    if ( *argument == cEnd )
    {
      argument++;
      break;
    }

    *arg_first = *argument;
    arg_first++;
    argument++;
  }

  *arg_first = '\0';

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

  return argument;
}

/*
 * Pick off one argument from a string and return the rest.
 * Understands quotes.  Delimiters = { ' ', '-' }
 */
char *one_argument2( char *argument, char *arg_first )
{
  char cEnd = ' ';
  short count = 0;

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

  if ( *argument == '\'' || *argument == '"' )
    cEnd = *argument++;

  while ( *argument != '\0' || ++count >= 255 )
  {
    if ( *argument == cEnd || *argument == '-' )
    {
      argument++;
      break;
    }

    *arg_first = *argument;
    arg_first++;
    argument++;
  }

  *arg_first = '\0';

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

  return argument;
}

/*
 * Remove carriage returns from a line
 */
char *strip_cr( const char *str )
{
  static char newstr[MAX_STRING_LENGTH];
  int i = 0, j = 0;

  for ( i=j=0; str[i] != '\0'; i++ )
    if ( str[i] != '\r' )
    {
      newstr[j++] = str[i];
    }
  newstr[j] = '\0';
  return newstr;
}

/*
 * Removes the tildes from a line, except if it's the last character.
 */
void smush_tilde( char *str )
{
  char *strptr = str;
  size_t len = strlen( str );
  char last = len != 0 ? strptr[len-1] : '\0';

  for ( ; *str != '\0'; str++ )
  {
    if ( *str == '~' )
      *str = '-';
  }

  if ( len )
    strptr[len-1] = last;
}

static char *grab_word( char *argument, char *arg_first )
{
  char cEnd = ' ';
  short count = 0;

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

  if ( *argument == '\'' || *argument == '"' )
    cEnd = *argument++;

  while ( *argument != '\0' || ++count >= 255 )
  {
    if ( *argument == cEnd )
    {
      argument++;
      break;
    }

    *arg_first++ = *argument++;
  }

  *arg_first = '\0';

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

  return argument;
}

char *wordwrap( char *txt, unsigned short wrap )
{
  static char buf[MAX_STRING_LENGTH];
  char *bufp = buf;

  buf[0] = '\0';

  if ( txt != NULL )
  {
    char line[MAX_STRING_LENGTH];
    char temp[MAX_STRING_LENGTH];
    char *ptr = txt;

    ++bufp;
    line[0] = '\0';

    while ( *ptr )
    {
      size_t ln = strlen( line );
      size_t x = 0;

      ptr = grab_word( ptr, temp );
      x = strlen( temp );

      if ( (ln + x + 1) < wrap )
      {
	char *p = NULL;

	if ( line[ln-1] == '.' )
	  strcat( line, "  " );
	else
	  strcat( line, " " );
	strcat( line, temp );
	p = strchr( line, '\n' );
	if ( !p )
	  p = strchr( line, '\r' );
	if ( p )
	{
	  strcat( buf, line );
	  line[0] = '\0';
	}
      }
      else
      {
	strcat( line, "\r\n" );
	strcat( buf, line );
	strcpy( line, temp );
      }
    }
    if ( line[0] != '\0' )
      strcat( buf, line );
  }
  return bufp;
}

char *encode_string( const char *str )
{
  return sha256_crypt( str );
}

char *cat_sprintf(char *dest, const char *fmt, ...)
{
  char buf[MAX_STRING_LENGTH];

  va_list args;

  va_start(args, fmt);
  vsprintf(buf, fmt, args);
  va_end(args);

  return strcat(dest, buf);
}