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 <stdlib.h>
#include "externs.h"
#include "commands.h"
#include "hash.h"

static HASH *find_hash(DDATA *d, CS *com)
{
  HASH *h;

  for(h = d->hashtable;h;h = h->next)
    if(h->command == com)
      break;

  return(h);
}

void add_hash(DDATA *d, CS *com)
{
  HASH *h, *newh;

  if(!d)
    return;

  if((h = find_hash(d, com)))
  {
    (h->hits)++;
    return;
  }
  newh = (HASH *)stack_alloc(sizeof(HASH), 1, 0);
  newh->command = com;
  newh->hits = 1;
  newh->next = d->hashtable;
  d->hashtable = newh;
}

void do_hash(DDATA *d, OBJ *player)
{
  HASH *h;
  CALIAS *c;

  if(!d)
  {
    if(!(d = is_connected_raw(player)))
    {
      notify(player, "Hashed commands only exist on connected players.");
      return;
    }
  }

  if(!d->hashtable)
  {
    notify(player, "No commands found.");
    return;
  }

  notify(player, "|+Y|Hashed commands|+W|:");
  notify(player, "|+G| HITS    COMMAND         ALIAS");

  for(h = d->hashtable;h;h = h->next)
  {
    c = find_comm_alias(player, h->command);
    
    notify(player, tprintf("|+C|%7d  |+B|%s %s",
      h->hits, my_ljust(h->command->name, 15), (c)?c->alias:""));
  }
}

CS *match_hash(DDATA *d, char *command)
{
  HASH *h;

  if(!d)
    return(NULL);

  for(h = d->hashtable;h;h = h->next)
    if(!strcmp(h->command->name, command))
      return(h->command);

  return(NULL);
}

void free_hashtable(DDATA *d)
{
  HASH *h, *hnext;

  for(h = d->hashtable;h;h = hnext)
  {
    hnext = h->next;
    stack_free(h);
  }
}

CS *match_comm_alias(OBJ *player, char *matchstr)
{
  CALIAS *c;

  for(c = player->comm_aliases;c;c = c->next)
    if(!strcmp(c->alias, matchstr))
      return(c->command);

  return((CS *)NULL);
}

CALIAS *find_comm_alias(OBJ *player, CS *command)
{
  CALIAS *c;

  for(c = player->comm_aliases;c;c = c->next)
    if(c->command == command)
      break;

  return(c);
}

void add_comm_alias(OBJ *player, char *arg1, char *arg2)
{
  CALIAS *cnew, *c, *cprev = NULL;
  CS *command;

  if((command = match_command(NULL, player, arg1)) == (CS *)-1)
    return;     /* Ambiguous command */

  if(!command)
  {
    notify(player, tprintf("No such command: %s", arg1));
    return;
  }

  if(!(cnew = find_comm_alias(player, command)))
  {
    if(!*arg2)     /* No sense in creating a new one if no alias */
      return;

    cnew = (CALIAS *)stack_alloc(sizeof(CALIAS), 1, 0);
    cnew->command = command;
    cnew->alias = NULL;
    cnew->next = player->comm_aliases;
    player->comm_aliases = cnew;
  }

  if(*arg2)
  {
    if(!cnew->alias)
      cnew->alias = stack_string_alloc(arg2, 1);
    else
      cnew->alias = stack_string_realloc(cnew->alias, arg2);
    notify(player, tprintf("Command alias for %s set to: %s",
      command->name, arg2));
  }
  else
  {
    for(c = player->comm_aliases;c;c = c->next)
    {
      if(c == cnew)
        break;
      cprev = c;
    }
    if(!c)
      return;
    if(cprev)
      cprev->next = c->next;
    else
      player->comm_aliases = c->next;
    stack_free(cnew->alias);
    stack_free(cnew);
    notify(player, tprintf("Command alias for %s removed.",
      command->name));
  }
}

void do_calias(OBJ *player, char *arg1, char *arg2)
{
  CALIAS *c;

  if(*arg1)
  {
    add_comm_alias(player, arg1, arg2);
    return;
  }

  if(!player->comm_aliases)
  {
    notify(player, "You have no command aliases.");
    return;
  }

  notify(player, "|+Y|Command aliases|+W|:");
  notify(player, "|+G|ALIAS     COMMAND");

  for(c = player->comm_aliases;c;c = c->next)
    notify(player, tprintf("|+R|%s|+B|%s", my_ljust(c->alias, 10),
      c->command->name));
}

void free_caliases(OBJ *player)
{
  CALIAS *c, *cnext;

  for(c = player->comm_aliases;c;c = cnext)
  {
    cnext = c->next;

    stack_free(c->alias);
    stack_free(c);
  }
}