/* userface.c -- Default methods of displaying a users face. */

/* Copyright (C) 1988,1990,1992 Free Software Foundation, Inc.

   This file is part of GNU Finger.

   GNU Finger is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published
   by the Free Software Foundation; either version 1, or (at your
   option) any later version.

   GNU Finger is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with GNU Finger; see the file COPYING.  If not, write to the
   Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */

#include <stdio.h>
#include <sys/types.h>

#include <config.h>
#include <bitmap.h>

#ifndef savestring
#define savestring(s) (char *)strcpy ((char *)xmalloc (1 + strlen (s)), (s))
#endif

/* Return the face bits of USER.  If we can't, return a NULL pointer. */
BITMAP *
site_read_face (user)
     char *user;
{
  BITMAP *result = (BITMAP *)NULL;

#if defined (MIT_MUGSHOTS)
  {
    extern BITMAP *read_lispmug ();
    result = read_lispmug (user);
  }
#endif

#if defined (FACE_MUGSHOTS)
  {
    extern BITMAP *read_face ();
    result = read_face (user);
  }
#endif

#if defined (BITMAP_MUGSHOTS)
  {
    extern BITMAP *read_bitmap ();
    result = read_bitmap (user);
  }
#endif

#if defined (X11_MUGSHOTS)
  {
    extern BITMAP *read_x_bitmap ();
    result = read_x_bitmap (user);
  }
#endif

#if defined (RAST_MUGSHOTS)
  {
    extern BITMAP *read_rasterfile ();
    result = read_rasterfile (user);
  }
#endif

  return (result);
}

/* Duplicate memory block BLK of size SIZE, make sure there are N
   extra characters of uninitialized space in the buffer. */
static char *
memdup_oversize (blk, size, n)
  char *blk;
  int size, n;
{
  register char *tmp;

  bcopy (blk, tmp = (char *) malloc (size + n), size);
  return tmp;
}


/* Create an array of the mugshot files in DIR. */
char **
mugshot_files_in_dir (dir)
     char *dir;
{
  DIR *directory;
  char *name, **result = (char **)NULL;
  int result_index, result_size;
  struct dirent *entry = (struct dirent *)NULL;
  int dir_is_dot;

  result_index = result_size = 0;

  directory = opendir (dir);

  if (!directory)
    return ((char **)NULL);

  dir_is_dot = (strcmp (dir, ".") == 0);

  while ((entry = readdir (directory)) != (struct dirent *)NULL)
    {
      int len = NLENGTH (entry);

      /* Skip files that start with `.' or end in `~' */
      if (entry->d_name[0] == '.'
	  || (len && entry->d_name[len -1 ] == '~'))
	continue;

      name = memdup_oversize (entry->d_name, len, 1);
      name[len] = '\0';

      /* If current directory, then skip files that do not end in ".mug". */
      if (dir_is_dot)
	{
	  char *tail = (char *)rindex (name, '.');

	  if (!tail || strcmp (tail, ".mug") != 0)
	    {
	      free (name);
	      continue;
	    }
	}

      if (result_index + 1 >= result_size)
	{
	  if (result)
	    {
	      result = (char **)
		xrealloc (result, (result_size += 50) * sizeof (char **));
	    }
	  else
	    {
	      result = (char **)
		xmalloc ((result_size = 50) * sizeof (char **));
	    }
	}

      result[result_index] = (char *)xmalloc (1 + strlen (name));
      strcpy (result[result_index], name);
      result[++result_index] = (char *)NULL;
      free (name);
    }

  closedir (directory);
  return (result);
}

/* List the available faces on STREAM.  Return the number of
   faces listed. */
int
site_list_faces (stream)
     FILE *stream;
{
  char *dir, *path;
  int path_index = 0;
  int total_mugshots = 0;

  path = (char *)getenv ("MUGSHOT_PATH");

  if (!path)
    path = MUGSHOT_PATH;

  while (dir = (char *)extract_colon_unit (path, &path_index))
    {
      register int i;
      char **array;

      if (!*dir)
	{
	  free (dir);
	  dir = savestring (".");
	}

      array = mugshot_files_in_dir (dir);

      for (i = 0; array && array[i]; i++)
	{
	  fprintf (stream, "%s\n", array[i]);
	  fflush (stream);
	  free (array[i]);
	}

      if (array)
	free (array);

      total_mugshots += i;
    }

  return (total_mugshots);
}

/* Show the FACE of USER on the local display. */
int
site_show_face (user, face)
     char *user;
     BITMAP *face;
{
  int result;
#if defined (HAVE_X11)
  if (getenv ("DISPLAY"))
    {
      if (!fork ())
	exit (x_show_face (user, face));
      result = 0;
    }
  else
#endif
    {
#if defined (HAVE_SUN_WINDOWS)
      result = sun_show_face (user, face);
#endif /* HAVE_SUN_WINDOWS */
    }
  return (result);
}

/* Save this user's face in a file. */
int
site_save_face (user, face)
     char *user;
     BITMAP *face;
{
  int result = -1;

#if defined (MIT_MUGSHOTS)
  {
    extern int save_lispmug ();
    result = save_lispmug (user, face);
  }
#endif

#if defined (BITMAP_MUGSHOTS)
  {
    extern int save_bitmap ();
    result = save_bitmap (user, face);
  }
#endif

#if defined (X11_MUGSHOTS)
  {
    extern int save_x_bitmap ();
    result = save_x_bitmap (user, face);
  }
#endif

#if defined (RAST_MUGSHOTS)
  {
    extern int save_rasterfile ();
    result = save_rasterfile (user, face);
  }
#endif

  return (result);
}

