/* read_x_bitmap.c -- How to read an X bitmap. */

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

   This file is part of GNU Finger.

   This program 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 2, or (at your option)
   any later version.

   This program 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 this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */

/* This code requires functions in bitmaps.c. */

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

#define identifier_char(c) (pure_alphabetic(c) || digit (c) || (c) == '_')
#define hexdigit(c) (digit(c) || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'A'))

BITMAP *
read_x_bitmap (user)
     char *user;
{
  register int i;
  FILE *file;
  BITMAP *face = (BITMAP *)NULL;
  char *filename = mugshot_filename (user);
  char line[128], *res;
  int size, width = -1, height = -1;

  file = fopen (filename, "r");
  free (filename);

  if (!file)
    return (BITMAP *)NULL;

  /* Get info about this file.  The standard format has #defines ending
     in "width" and "height". */
  while (width == -1 || height == -1)
    {
      res = fgets (line, sizeof (line), file);

      if (res == (char *)NULL)
	break;

      /* Skip leading whitespace. */
      while (whitespace (*res))
	res++;

      /* Ignore comment lines and blank lines.
	 Bitmap files have comments like C code. */
      if (!*res || *res == '/')
	continue;

      /* If this is a #define line, then get width or height. */
      if (strncmp (res, "#define", 7) == 0)
	{
	  char identifier[128];

	  res += 7;
	  while (whitespace (*res))
	    res++;

	  /* Isolate identifier. */
	  i = 0;
	  while (identifier_char (*res))
	    identifier[i++] = *res++;

	  identifier[i] = '\0';

	  if (i > 4 && strncmp (&identifier[i - 5], "width", 5) == 0)
	    {
	      sscanf (res, "%d", &width);
	      continue;
	    }

	  if (i > 5 && strncmp (&identifier[i - 6], "height", 6) == 0)
	    {
	      sscanf (res, "%d", &height);
	      continue;
	    }
	}
    }

  /* If we found the width and the height, then we can read in the bits
     and return them. */
  if (width != -1 && height != -1)
    {
      int row, offset, tem;
      byte *image_row;

      face = (BITMAP *)xmalloc (sizeof (BITMAP));

      face->width = width;
      face->height = height;
      face->rowlen = (width + 7) / 8;

      size = face->rowlen * height;

      face->bits = (byte *)xmalloc (size);

      row = offset = 0;

      while (res = fgets (line, sizeof (line), file))
	{
	  char hex_rep[128];

	next_row:
	  /* Protect against malformed input files. */
	  if (row >= height)
	    break;

	  image_row = face->bits + (row * face->rowlen);

	next_byte:

	  /* Skip leading whitespace. */
	  while (whitespace (*res) || *res == ',')
	    res++;

	  /* Skip leading "0x". */
	  if (*res == '0' && (*(res + 1) == 'x' || *(res + 1) == 'X'))
	    res += 2;

	  i = 0;

	  while (hexdigit (*res) || *res == 'x')
	    hex_rep[i++] = *res++;

	  hex_rep[i] = '\0';

	  /* If no byte defined on this line, then skip it. */
	  if (!hex_rep[0] || sscanf (hex_rep, "%x", &tem) == 0)
	    continue;

	  /* Else, add this byte to the current row. */
	  image_row[offset++] = tem;

	  if (offset == face->rowlen)
	    {
	      offset = 0;
	      row++;
	      goto next_row;
	    }

	  goto next_byte;
	}

    }

  fclose (file);

  return (face);
}

#ifdef TEST
/* Load an X bitmap file from disk and display it. */

main (argc, argv)
     int argc;
     char **argv;
{
  int arg_index = 1;

  while (arg_index != argc)
    {
      char *file = argv[arg_index++];
      BITMAP *face = read_x_bitmap_file (file);

      if (face)
	{
	  x_show_face (file, face);
	  free (face->bits);
	  free (face);
	}
      else
	fprintf (stderr, "No face bits for `%s'.\n", file);
      
    }
}

site_save_face () {}
#endif
