/* bitmap.c -- Some useful functions for manipulating BITMAPs. */

/* 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.  */

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


#if defined (HAVE_X11)

#include <bitmap.h>


/* **************************************************************** */
/*								    */
/*			Useful Utilities			    */
/*								    */
/* **************************************************************** */

/* Modify the bitmap pointed to by FACE so that each row is
   padded to WORD_SIZE.  To pad to a single byte, WORD_SIZE should
   be 1, 16-bit boundary is 2, etc. */
void
pad_face (face, word_size)
     BITMAP *face;
     int word_size;
{
  int padding = 8 * word_size;
  int new_rowlen = ((face->width + (padding - 1)) / padding) * word_size;

  if (new_rowlen == face->rowlen)
    return;

  {
    register int i;
    register byte *old_row, *new_row;
    byte *new_bits = (byte *)xmalloc (new_rowlen * face->height);

    old_row = face->bits;
    new_row = new_bits;

    for (i = 0; i < face->height; i++)
      {
	bcopy (old_row, new_row, new_rowlen);
	old_row += face->rowlen;
	new_row += new_rowlen;
      }

    free (face->bits);
    face->bits = new_bits;
    face->rowlen = new_rowlen;
  }
}

#endif

/* Given a string containing units of information separated by colons,
   return the next one pointed to by INDEX, or NULL if there are no more.
   Advance INDEX to the character after the colon. */
char *
extract_colon_unit (string, idx)
     char *string;
     int *idx;
{
  int i, start;

  i = *idx;

  if (!string || (i >= strlen (string)))
    return ((char *) 0);

  start = i;

  while (string[i] && string[i] != ':') i++;

  *idx = i;

  if (i == start)
    {
      if (!string[i])
	return ((char *) 0);

      (*idx)++;

      return (savestring (""));
    }
  else
    {
      char *value;

      value = (char *)xmalloc (1 + (i - start));
      strncpy (value, &string[start], (i - start));
      value [i - start] = '\0';

      return (value);
    }
}


#if defined (HAVE_X11)

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

/* Return a malloc'ed string which is the name of a mugshot file for USER.
   Search through the list of possible pathnames taken from the environment
   variable `MUGSHOT_PATH', or defaulting to the CPP variable MUGSHOT_PATH.
   If the file exists, return that name, otherwise return the first possible
   filename for USER. */
char *
mugshot_filename (user)
     char *user;
{
  char *getenv (), *path, *new_file, *path_string;
  struct stat finfo;
  int idx = 0;

  path_string = getenv ("MUGSHOT_PATH");

  if (!path_string)
    path_string = MUGSHOT_PATH;

  if (rindex (user, '/'))
    return (savestring (user));

  while ((path = extract_colon_unit (path_string, &idx)))
    {
      char *file =
	(char *)alloca (3 + strlen (user) + strlen (".mug") + strlen (path));

      if (!file)
	abort ();

      if (!*path)
	{
	  free (path);
	  path = savestring ("."); /* by definition. */
	}

      strcpy (file, path);
      if (path[strlen (path) - 1] != '/')
	strcat (file, "/");
      strcat (file, user);

      free (path);

      if (stat (file, &finfo) == 0)
	return (savestring (file));

      strcat (file, ".mug");

      if (stat (file, &finfo) == 0)
	return (savestring (file));
    }


  idx = 0;
  path = extract_colon_unit (path_string, &idx);

  if (!path)
    path = savestring ("./");

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

  new_file = (char *)xmalloc (2 + strlen (path));

  strcpy (new_file, path);
  if (new_file[strlen (new_file) - 1] != '/')
    strcat (new_file, "/");
  strcat (new_file, user);

  free (path);

  return (new_file);
}

/* Some machines expect the bit ordering to be in one order, some in 
   another order.  This function changes the LSBit to MSBit in each
   byte of BITMAP. */
void
reverse_image_bit_order (bitmap)
     BITMAP *bitmap;
{
  register int i, j, size;
  register unsigned char oldbyte, newbyte, *bits;

  size = bitmap->rowlen * bitmap->height;
  bits = bitmap->bits;

  for (i = 0; i < size; i++)
    {
      newbyte = 0, oldbyte = *bits;

      for (j = 0; j < 8; j++) {
	newbyte <<=  1;
	newbyte |=  (0x1 & oldbyte);
	oldbyte >>= 1;
      }

      *bits++ = newbyte;
    }
}

/* Some machines have 0 as white and 1 as black.  Swap the bits in BITMAP. */
void
invert_image_bits (bitmap)
     BITMAP *bitmap;
{
  register int i, size;
  register unsigned char *bits;

  size = bitmap->rowlen * bitmap->height;
  bits = bitmap->bits;

  for (i = 0; i < size; i++, bits++)
    *bits = ~*bits;
}

#endif				/* HAVE_X */
