TinyMAZE/
TinyMAZE/config/
TinyMAZE/doc/
TinyMAZE/run/msgs/
TinyMAZE/src/
TinyMAZE/src/db/
TinyMAZE/src/ident/
TinyMAZE/src/io/
TinyMAZE/src/prog/
TinyMAZE/src/softcode/
TinyMAZE/src/util/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "db.h"
#include "config.h"
#include "externs.h"

#define DOWNCASE(x) tolower(x)

int string_compare(char *s1, char *s2)
{
  while(*s1 && *s2 && DOWNCASE(*s1) == DOWNCASE(*s2))
  {
    s1++;
    s2++;
  }
  
  return(DOWNCASE(*s1) - DOWNCASE(*s2));
}

int string_prefix(char *string, char *prefix)
{
  while(*string && *prefix && DOWNCASE(*string) == DOWNCASE(*prefix))
  {
    string++;
    prefix++;
  }
  return(!*prefix);
}

/* Accepts only nonempty matches starting at the beginning of a word */
char *string_match(char *src, char *sub)
{
  if(*sub)
  {
    while(*src)
    {
      if(string_prefix(src, sub))
        return(src);
      while(*src && isalnum(*src))
        src++;
      while(*src && !isalnum(*src))
        src++;
    }
  }
  
  return(NULL);
}

char *str_index(char *what, int chr)
{
  char *x;

  for(x = what;*x;x++)
    if(chr == *x)      
      return(x);
  return((char *)0);
}

char *my_ljust(char *str, int field)
{
  int colorlen, textlen, len = 0;
  char buf[4096];
  char colorbuf[1024];
  char *b = buf;
  char *c = colorbuf;
  char *p = str;

  if(field > 80)
    return("FIELD LENGTH OUT OF RANGE!");

  colorlen = str_colorlen(str);
  textlen = strlen(str)-colorlen;

  if(textlen <= field)
  {
    strcpy(buf, str);
    len = strlen(buf);
    b = buf+len;
    field += colorlen;
    while(len < field)
    {
      *b++ = ' ';
      len++;
    }
    *b = '\0';

    return(stack_string_alloc(buf, 0));
  }

  if(!strchr(str, '|'))
  {
    while(b-buf < field)
      *b++ = *p++;
    *b = '\0';

    return(stack_string_alloc(buf, 0));
  }

  while(*p && len < field)
  {
    while(*p && *p != '|' && len < field)
    {
      *b++ = *p++;
      len++;
    }
    *b = '\0';
    if(!*p || len == field)
      break;
    *b++ = *p++;
    while(*p && *p != '|')
      *b++ = *p++;
    if(*p)
      *b++ = *p++;
    *b = '\0';
  }

  p = str+strlen(str)-1;

  if(*p != '|')
    return(stack_string_alloc(buf, 0));

  p--;
  while(p != str && *p != '|')
    p--;
  if(p == str)
    return(stack_string_alloc(buf, 0));
  *c++ = *p++;
  while(*p != '|')
    *c++ = *p++;
  *c = '\0';
  if(!my_is_color(colorbuf+1))
    return(stack_string_alloc(buf, 0));
  *c++ = '|';
  *c = '\0';
  strcat(buf, colorbuf);

  return(stack_string_alloc(buf, 0));
}

char *my_rjust(char *str, int len)
{
  char buf[4096];
  char *b;
  int nocolorlen = strlen(strip_color(str));

  for(b = buf;b-buf < len-nocolorlen;b++)
    *b = ' ';
  strcpy(b, str);

  return(stack_string_alloc(buf, 0));
}

char *my_string(char *str, int num)
{
  int i, j, k = 0;
  char buffer[4096];

  if(num > 250)
    return("NUM OUT OF RANGE");

  for(i = 0;i < num;i++)
  {
    for(j = 0;j < strlen(str);++j)
      buffer[k+j] = str[j];
    k += strlen(str);
  }

  buffer[k] = '\0';

  return(stack_string_alloc(buffer, 0));
}

char *my_center(char *str, int width)
{
  int i;
  int num = (width/2)-(strlen(str)/2);
  int color_len = str_colorlen(str);
  char buffer[4096];
  char *b = buffer;

  if(width > 80)
    return("WIDTH OUT OF RANGE");

  for(i = 0;i < num+color_len/2;++i)
    *b++ = ' ';

  while(*str)
    *b++ = *str++;
  *b = '\0';

  for(i = strlen(buffer)-color_len;i < width;++i)
    *b++ = ' ';

  *b = '\0';

  return(stack_string_alloc(buffer, 0));
}

char *comma(char *num)
{
  char buf[4096], buf2[4096];
  char array[(strlen(num)/3)+3][5];
  char *p = num;
  int i, len, ctr = 0, negative = 0;

  if(*p == '-')
    negative = 1;

  if(strchr(p, '.'))
  {
    p = strchr(p, '.');
    strcpy(buf2, p);
    *p = '\0';
    p = num;
  }
  else
    strcpy(buf2, "");

  p = (negative)?num+1:num;

  if(strlen(p) < 4)
  {
    sprintf(buf, "%s%s", num, buf2);
    return(stack_string_alloc(buf, 0));
  }

  if((len = strlen(p)%3))
  {
    for(i = 0;i < len;++i)
      array[0][i] = *p++;
    array[0][i] = '\0';
    ctr = 1;
  }

  while(*p)
  {
    for(i = 0;i < 3;++i)
      array[ctr][i] = *p++;
    array[ctr++][i] = '\0';
  }

  strcpy(buf, (num[0] == '-')?"-":"");

  for(i = 0;i < ctr-1;++i)
    strcat(buf, tprintf("%s,", array[i]));
  strcat(buf, array[i]);
  strcat(buf, buf2);

  return(stack_string_alloc(buf, 0));
}

char *strip_color(char *str)
{
  char buffer[4096], buf[4096];
  char *p, *b = buffer;
  char *s = str;

  if(!*str || !strchr(str, '|'))
  {
    strcpy(buffer, str);
    return(stack_string_alloc(buffer, 0));
  }

  *buffer = '\0';

  while(*s)
  {
    b = buffer+strlen(buffer);

    while(*s != '|' && *s)
      *b++ = *s++;
    *b = '\0';

    if(!*s)             /* Done searching the string, ready to return */
      break;

    p = buf;
    *p++ = *s++;      /* Point to the character right after the '|' */

    if(!strchr(s, '|'))  /* If there's only 1 '|' there can't be color */
    {
      while(*s)
        *p++ = *s++;
      *p = '\0';
      strcat(buffer, buf);
      return(stack_string_alloc(buffer, 0));
    }

    while(*s != '|')     /* Don't need to check for \0 since we just   */
      *p++ = *s++;       /* determined that there's another '|' in str */
    *p = '\0';           /* Let's make buf a null-terminated string    */

    if(my_is_color(buf+1)) /* Was the stuff between |'s really a color? */
    {
      s++;
      continue;
    }

    *p++ = *s++;         /* Get the '|'                                */
    *p = '\0';
    strcat(buffer, buf);
  }

  return(stack_string_alloc(buffer, 0));
}

int str_colorlen(char *str)
{
  return(strlen(str)-strlen(strip_color(str)));
}

char *box_header(char *str, char *color, int len)
{
  char buff[4096];

  sprintf(buff, "|%s|.%s.", color, my_string("-", len));
  sprintf(buff+strlen(buff), "\n|%s||%s|%s||",
    color, my_center(str, len), color);
  sprintf(buff+strlen(buff), "\n|%s||%s|", color, my_string("-", len));

  return(stack_string_alloc(buff, 0));
}

void extract_char(char *start)
{
  char *p, *q;

  if(!*start)
    return;

  for(p = start, q = start+1;*q;p++, q++)
    *p = *q;
  *p = '\0';
}

char *check_plural(int amt, char *singular, char *plural)
{
  return((amt == 1)?singular:plural);
}

void del_whitespace(char **str)
{
  char *p;

  while(isspace(**str))
    (*str)++;

  for(p = *str;*p;p++)
    while(isspace(*p) && isspace(*(p+1)))
      strcpy(p, p+1);

  p--;
  while(p > *str && isspace(*p))
    *p-- = '\0';
}

char *first_word(char *str)
{
  char buf[4096];
  char *b;

  while(isspace(*str))
    str++;

  for(b = buf;*str && !isspace(*str);str++, b++)
    *b = *str;
  *b = '\0';

  return(stack_string_alloc(buf, 0));
}

char *rest(char *str)
{
  while(*str && !isspace(*str))
    str++;

  while(isspace(*str))
    str++;

  return(str);
}

char *last_char(char *str)
{
  return(str+strlen(str)-1);
}

/* Help will be set to one of the following */
/* 0 - Normal match              */
/* 1 - subcommand matches "help" */
/* 2 - subcommand is blank ("")  */
SUBCOMMAND *subcommand_match(OBJ *player, char *str, SUBCOMMAND *commands,
                             int *help)
{
  SUBCOMMAND *sc, **sclist;
  int ctr = 0;

  if(!*str || !string_compare(str, "help"))
  {
    if(help)
      *help = (*str)?1:2;
    return(NULL);
  }

  if(help)
    *help = 0;

  for(sc = commands;sc->name;sc++)
  {
    if(sc->admin_only && !Wizard(player))
      continue;

    if(string_prefix(sc->name, str))
    {
      if(strlen(sc->name) == strlen(str))
        return(sc);

      if(!ctr)
        sclist = (SUBCOMMAND **)stack_alloc(sizeof(SUBCOMMAND *), 0, 0);
      else
        sclist = (SUBCOMMAND **)stack_realloc_tmp(sclist,
          sizeof(SUBCOMMAND *)*(ctr+1));
      sclist[ctr++] = sc;
    }
  }

  if(ctr != 1)
    return(NULL);

  if(sc->admin_only && !Wizard(player))
  {
    notify(player, perm_denied());
    return(NULL);
  }

  return(*sclist);
}

void subcommand_print(OBJ *player, char *name, SUBCOMMAND *commands)
{
  SUBCOMMAND *sc;
  bool init = 0;

  for(sc = commands;sc->name;sc++)
    if(!sc->admin_only || Wizard(player))
    {
      if(!init)
      {
        notify(player, tprintf("|+Y|%s Subcommands|+W|:", name));
        init++;
      }
      notify(player, tprintf("|+B|  %s", sc->name));
    }

  if(!init)
    notify(player,
      tprintf("There are no %s subcommands available to you.", name));
}