talker/
talker/bin/
talker/files/whois/
talker/update/
talker/update/bin/
/*
 * lists.c
 */

#include <ctype.h>
#include <string.h>
#include <malloc.h>
#include <fcntl.h>
#include <memory.h>

#include "config.h"
#include "player.h"
#include "fix.h"

/* externs */

extern char    *store_string(), *store_int();
extern char    *get_string(), *get_int();
extern void     log(char *, char *);


player         *find_player_absolute_quiet(char *name)
{
   player         *scan;

   if (!isalpha(*name))
      return 0;

   strcpy(stack, name);
   lower_case(stack);

   scan = hashlist[(int) (*stack) - (int) 'a' + 1];
   for (; scan; scan = scan->hash_next)
      if (!strcmp(stack, scan->lower_name))
    return scan;

   return 0;
}

/* delete and entry from someones list */

void            delete_entry(saved_player * sp, list_ent * l)
{
   list_ent       *scan;
   if (!sp)
      return;
   scan = sp->list_top;
   if (scan == l)
   {
      sp->list_top = l->next;
      FREE(l);
      return;
   }
   while (scan)
      if (scan->next == l)
      {
    scan->next = l->next;
    FREE(l);
    return;
      } else
    scan = scan->next;
   log("error", "Tried to delete list entry that wasn't there.\n");
}

/* compress list */

void            tmp_comp_list(saved_player * sp)
{
  char           *oldstack;
  list_ent       *l, *next;
  
  l = sp->list_top;
  
  oldstack = stack;
  stack = store_int(stack, 0);
  
  while (l)
  {
    next = l->next;
    if (!l->name[0])
    {
      log("error", "Bad list entry on compress .. auto deleted.\n");
      delete_entry(sp, l);
    } else
    {
      stack = store_string(stack, l->name);
      stack = store_int(stack, l->flags);
    }
    l = next;
  }
  store_int(oldstack, ((int) stack - (int) oldstack));
}

void            compress_list(saved_player * sp)
{
   char           *oldstack;
   int             length;
   list_ent       *new, *l, *next;
   if (sp->system_flags & COMPRESSED_LIST)
      return;
   sp->system_flags |= COMPRESSED_LIST;
   oldstack = stack;
   tmp_comp_list(sp);
   length = (int) stack - (int) oldstack;
   if (length == 4)
   {
      sp->list_top = 0;
      stack = oldstack;
      return;
   }
   new = (list_ent *) MALLOC(length);
   memcpy(new, oldstack, length);

   l = sp->list_top;
   while (l)
   {
      next = l->next;
      FREE(l);
      l = next;
   }
   sp->list_top = new;
   stack = oldstack;
}

/* decompress list */

void            decompress_list(saved_player * sp)
{
   list_ent       *l;
   char           *old, *end, *start;
   int             length;

   if (!(sp->system_flags & COMPRESSED_LIST))
      return;
   sp->system_flags &= ~COMPRESSED_LIST;

   old = (char *) sp->list_top;
   start = old;
   if (!old)
      return;
   old = get_int(&length, old);
   end = old + length - 4;
   sp->list_top = 0;
   while (old < end)
   {
      l = (list_ent *) MALLOC(sizeof(list_ent));
      old = get_string(stack, old);
      strncpy(l->name, stack, MAX_NAME - 2);
      old = get_int(&(l->flags), old);
      l->next = sp->list_top;
      sp->list_top = l;
   }
   FREE(start);
}

/* save list */

void            construct_list_save(saved_player * sp)
{
   int             length;
   char           *where;

   if (!(sp->system_flags & COMPRESSED_LIST) &&
       (!find_player_absolute_quiet(sp->lower_name)))
      compress_list(sp);

   if (sp->system_flags & COMPRESSED_LIST)
   {
      if (sp->list_top)
      {
    where = (char *) sp->list_top;
    (void) get_int(&length, where);
    memcpy(stack, where, length);
    stack += length;
      } else
    stack = store_int(stack, 4);
   } else
      tmp_comp_list(sp);
}

/* retrieve list */

char           *retrieve_list_data(saved_player * sp, char *where)
{
   int             length;
   (void) get_int(&length, where);
   if (length == 4)
      sp->list_top = 0;
   else
   {
      sp->system_flags |= COMPRESSED_LIST;
      sp->list_top = (list_ent *) MALLOC(length);
      memcpy(sp->list_top, where, length);
   }
   where += length;
   return where;
}