/* How to show a face on a sun. */

/* 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>
#if defined (HAVE_SUN_WINDOWS)

#include <signal.h>
#include <sys/types.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <pwd.h>
#include <utmp.h>
#include <suntool/tool_hs.h>

#include <bitmap.h>

typedef int Function ();	/* So I can say Function *foo; */

/* Obscure, mindless, sun lossage. */
struct gfxsubwindow {
  int gfx_windowfd;		/* The window file descriptor. */
  int gfx_flags;		/* Some random flags. */
  int gfx_reps;			/* I don't know. */
  struct pixwin *gfx_pixwin;
  struct rect gfx_rect;		/* Window offset x, offset y, width, height. */
  /* Contains a string describing the file that this window
     is, e.g. /dev/win0 is the screen. */
  caddr_t gfx_takeoverdata;
};

/* For the gfx_flags from above.  Indicates window has changed. */
#define GFX_RESTART 0x01
#define	GFX_DAMAGED 0x02

/* We only display faces on the console of a Sun.  We use UTMP to
   determine which tty line we are using. */
#define UTMP "/etc/utmp"

extern struct gfxsubwindow *gfxsw_init ();

/* This describes the environment in which the display takes place. */
struct gfxsubwindow *display;


/* Display FACE of USER on the sun console if that is possible.  If we are
   using the Sun window system, display the face in a window.  Otherwise,
   just blast it onto the screen. Return zero on success, non-zero error
   code on failure. */
int
sun_show_face (user, face)
     char *user;
     BITMAP *face;
{
  extern int errno;
  Function *old_winch;
  int fd, using_screen;

  if (!(display = gfxsw_init (0, 0)))
    return (errno);

  using_screen = (strcmp (display->gfx_takeoverdata, "/dev/win0") == 0);

  /* Make sure we are the console of a Sun.  If not, then we can't display
     the face. */
  {
    int fd = open (UTMP, O_RDONLY, 0666);
    struct utmp user;
    struct passwd *entry;

    if (fd < 0)
      return (errno);

    entry = getpwuid (getuid ());
    if (!entry) exit (1);	/* Barf on hairy hackers. */

    while (read (fd, &user, sizeof (user)) == sizeof (user))
      {
	if (!nonuser (user))
	  {
	    if ((strncmp
		 (user.ut_line, "console", sizeof (user.ut_line)) == 0) &&
		(strncmp
		 (user.ut_name, entry->pw_name, sizeof (user.ut_name)) != 0))
	      {
		exit (1);
	      }
	  }
      }
    close (fd);
  }

  /* Sun pixmaps are on 4 byte boundaries. */
  pad_face (face, 4);

  reverse_image_bit_order (face);
  invert_image_bits (face);
  (void) sun_display_face (user, face);
  reverse_image_bit_order (face);
  invert_image_bits (face);

}

#define screen_width display->gfx_rect.r_width
#define screen_height display->gfx_rect.r_height

sun_display_face (user, face)
     char *user;
     BITMAP *face;
{
  struct pixrect *image;
  int x, y, w, h, size;

  w = face->width;  h = face->height;
  size = face->rowlen * h;

  /* ras_depth is always 1 for black and white. */
  image = mem_create (w, h, 1);

  bcopy (face->bits, mpr_d (image)->md_image, size);

  /* Center the image in the window/screen. */
  x = (screen_width - w) / 2;
  y = (screen_height - h) / 2;

  pw_write (display->gfx_pixwin, x, y, w, h, PIX_SRC, image, 0, 0);
  if (image)
    pr_destroy (image);
}

#ifdef TEST

#ifdef NULL
#undef NULL			/* Because stdio.h defines it. */
#endif

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

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

  while (--argc)
    get_face_and_display (*++argv);
}

get_face_and_display (filename)
     char *filename;
{
  struct rasterfile header;
  BITMAP *face;
  int f, size;

  f = open (filename, O_RDONLY);
  if (f < 0)
    {
      perror (filename);
      exit (1);
    }

  read (f, &header, sizeof (struct rasterfile));

  if (header.ras_magic != RAS_MAGIC)
    {
      fprintf (stderr, "%s: not a rasterfile.\n", filename);
      exit (1);
    }

  if (header.ras_depth != 1)
    {
      fprintf (stderr, "%s: Can't hack %d bit deep rasterfiles.\n",
	       filename, header.ras_depth);
      exit (1);
    }

  face = (BITMAP *)malloc (sizeof (BITMAP));
  face->width = header.ras_width;
  face->height = header.ras_height;
  face->rowlen = ((face->width + 15) / 16) * 2;
  size = face->rowlen * face->height;
  face->bits = (unsigned char *)malloc (size);

  lseek (f, header.ras_maplength, L_INCR);
  read (f, face->bits, size);

  {
    char *rindex (), *user = rindex (filename, '/');
    register int i;

    if (user)
      user++;
    else
      user = filename;

    for (i = 0; i < size; i++)
      face->bits[i] = ~face->bits[i];

    sun_show_face (user, face);
    free (face->bits);
    free (face);
  }
}

pad_face () {}

#endif  /* TEST */
#endif /* HAVE_SUN_WINDOWS */
