/*
 * Al-backdrop.c Michael Saunby	M.Saunby@reading.ac.uk
 *
 * Release 1.1  December 1992 Jpeg backdrop using Albert HAM8 public screen and
 * Independent JPEG Group's jpeg decompressor.
 */
#define PROG_NAME "Al-backdrop JPEG display"

#include <intuition/intuition.h>
#include <intuition/gadgetclass.h>
#include <graphics/gfxbase.h>
#include <graphics/displayinfo.h>
#include <intuition/screens.h>
#include <dos/dosextens.h>
#include <exec/memory.h>
#include <dos/dosasl.h>
#include <dos/rdargs.h>
#include <libraries/gadtools.h>

#include <clib/asl_protos.h>
#include <clib/dos_protos.h>
#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/layers_protos.h>
#include <clib/graphics_protos.h>
#include <clib/gadtools_protos.h>
#include <clib/alib_protos.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "display24.h"

/* This should work with bigger numbers, but... */
#define ARRAY24_MAX_ROWS 1

/*
 * ReadArgs() template
 */
#define TEMPLATE "NAME"
#define OPT_NAME 0
#define OPT_COUNT 1

/*
 * Message structure used to get screen size changed, see ham8.c
 */
struct TestMsg
{
  struct Message msg;
  USHORT Width;
  USHORT Height;
  BOOL Lores;
};

struct IntuitionBase *IntuitionBase = NULL;
struct GfxBase *GfxBase = NULL;
struct Library *AslBase = NULL;
extern struct ExecBase *SysBase;

/* following for 24 bit put row */
int JPEG_restart = 0;
SHORT ham8_line = 0;		/* screen line number to draw at */
UBYTE *ham8_pens = NULL;
struct RastPort ham8_temprp;
struct BitMap *temp_bm = NULL;
struct Screen *screen = NULL;
struct FileRequester *filereq = NULL;
struct BitMap *bitmap = NULL;

struct EasyStruct failedES =
{sizeof (struct EasyStruct), 0, PROG_NAME,
 "%s", "OK",};

void
Cleanup ()
{
  if (screen)
    {
      ReleasePens (&(screen->ViewPort));
      UnlockPubScreen (NULL, screen);
    }
  if (ham8_pens)
    FreeMem (ham8_pens, ((temp_bm->BytesPerRow << 3) * temp_bm->Rows));
  if (temp_bm)
    FreeBitMap (temp_bm);
  if (filereq)
    FreeAslRequest (filereq);
  if (AslBase)
    CloseLibrary (AslBase);
  if (IntuitionBase)
    CloseLibrary ((struct Library *) IntuitionBase);
  if (GfxBase)
    CloseLibrary ((struct Library *) GfxBase);
}

void
Quit (char whytext[], UBYTE failcode)
{
  EasyRequest (NULL, &failedES, NULL, whytext);
  Cleanup ();
  exit (failcode);
}


char *
Startup (char *namebuf)
{
  LONG result[OPT_COUNT] =
  {0};
  struct RDArgs *rda;

  if ((GfxBase =
       (struct GfxBase *) OpenLibrary ("graphics.library", 36)) == NULL)
    Quit ("graphics.library is too old <V36", 25);

  if ((IntuitionBase =
    (struct IntuitionBase *) OpenLibrary ("intuition.library", 36)) == NULL)
    Quit ("intuition.library is too old <V36", 25);

  if ((AslBase = OpenLibrary ("asl.library", 36)) == NULL)
    Quit ("asl.library is too old <V36", 25);

  rda = ReadArgs (TEMPLATE, result, NULL);

  if (result[OPT_NAME])
    {
      strcpy (namebuf, (UBYTE *) result[OPT_NAME]);
      FreeArgs (rda);
    }
  else
    {
      struct Screen *screen;
      FreeArgs (rda);		/* In case we quit */
      /*
       * Opening the File Requester does not bring screen to front. Passing
       * the name ie. UnlockPubscreen(HAM8_ALBERT_NAME, NULL) is allowed
       * but not recommended. I haven't tried it.
       */
      if ((screen = LockPubScreen (HAM8_ALBERT_NAME)) != NULL)
	{
	  ScreenToFront (screen);
	  UnlockPubScreen (NULL, screen);
	}
      if ((filereq =
	   (struct FileRequester *) AllocAslRequestTags (ASL_FileRequest,
				      ASLFR_PubScreenName, HAM8_ALBERT_NAME,
							 TAG_END))
	  == NULL)
	Quit ("could not build file requster", 25);
      if (AslRequest (filereq, 0L))
	{
	  if(filereq->rf_Dir[strlen(filereq->rf_Dir)-1] == ':')
	  sprintf (namebuf, "%s%s", filereq->rf_Dir, filereq->rf_File);
	  else
	  sprintf (namebuf, "%s/%s", filereq->rf_Dir, filereq->rf_File);
	}
    }

  return (namebuf);
}


void
CreateWindow (UWORD width, UWORD height)
{
  int pen_errors;
  const int guess_barheight = 24;	/* First guess at menu bar
					 * height */
  int screen_height;
  BOOL lores = FALSE;		/* why bother? */
  BOOL screenok = FALSE;	/* set to true if screen accepts new
				 * dimensions */
  struct MsgPort *testport, *progport;
  struct TestMsg *msg;

  /*
   * Size of screen needed to take this picture.
   */
  screen_height = height + guess_barheight + 1;

  if (testport = CreatePort (NULL, NULL))
    {
      if (msg = AllocMem (sizeof (struct TestMsg), MEMF_PUBLIC | MEMF_CLEAR))
	{
	  msg->msg.mn_ReplyPort = testport;
	  msg->msg.mn_Length = sizeof (struct TestMsg);
	  msg->Width = width;
	  msg->Height = screen_height;
	  msg->Lores = lores;
	  Forbid ();
	  if (progport = FindPort (HAM8_ALBERT_NAME))
	    {
	      PutMsg (progport, (struct Message *) msg);
	      Permit ();
	      /* This could be quite a wait - the screen may have visitors. */
	      WaitPort (testport);
	      msg = (struct TestMsg *) GetMsg (testport);
	      screenok = TRUE;
	    }
	  /* extra Permit() in case FindPort() failed */
	  Permit ();
	  FreeMem (msg, (ULONG) sizeof (struct TestMsg));
	}
      DeletePort (testport);
    }
  if (!screenok)
    Quit ("could not find screen", 25);

  Delay (100);
  if ((screen = LockPubScreen (HAM8_ALBERT_NAME)) == NULL)
    Quit ("could not find screen", 25);


  /*
   * Dont draw on menu bar.
   */
  ham8_line = (screen->BarHeight < guess_barheight) ? screen->BarHeight :
    guess_barheight;
  ham8_line++;

  CopyMem (&(screen->RastPort), &ham8_temprp, sizeof (struct RastPort));
  ham8_temprp.Layer = NULL;
  if ((temp_bm = AllocBitMap (width, ARRAY24_MAX_ROWS, 8, 0L, bitmap)) == NULL)
    Quit ("cannot get line bitmap", 25);
  ham8_temprp.BitMap = temp_bm;
  ham8_pens = AllocMem (((temp_bm->BytesPerRow << 3) * temp_bm->Rows), 0L);
  /*
   * Get a copy of the special palette. The palette is set when the screen
   * is created.
   */
  pen_errors = StandardPalette (&(screen->ViewPort), TRUE);
  if (pen_errors)
    EasyRequest (NULL, &failedES,
		 NULL,
		 "Could not find full HAM-8 Albert palette");

}


#undef GLOBAL
#include "jinclude.h"


#ifndef EIGHT_BIT_SAMPLES
Sorry, this code only copes with 8 - bit JSAMPLEs.	/* deliberate syntax err */
#endif


/*
 * Write the file header.
 */

METHODDEF void
output_init (decompress_info_ptr cinfo)
{
  CreateWindow ((SHORT) cinfo->image_width, (SHORT) cinfo->image_height);

}


/*
 * Write some pixel data.
 */

METHODDEF void
put_pixel_rows (decompress_info_ptr cinfo, int num_rows,
		JSAMPIMAGE pixel_data)
{
  JSAMPROW ptr0, ptr1, ptr2;
  long width = cinfo->image_width;
  int row, height;


  if (cinfo->out_color_space == CS_GRAYSCALE)
    {
      for (row = 0; row < num_rows; row += height)
	{
	  ptr0 = pixel_data[0][row];
	  height = num_rows - row;	/* ie rows left */
	  height = (ARRAY24_MAX_ROWS < height) ? ARRAY24_MAX_ROWS : height;

	  WritePixelArray24 (&(screen->RastPort), 0, ham8_line,
			     width, height,
			     ptr0, ptr0, ptr0, ham8_pens, &ham8_temprp);
	  ham8_line += height;
	}
    }
  else
    {
      for (row = 0; row < num_rows; row += height)
	{
	  ptr0 = pixel_data[0][row];
	  ptr1 = pixel_data[1][row];
	  ptr2 = pixel_data[2][row];
	  height = num_rows - row;	/* ie rows left */
	  height = (ARRAY24_MAX_ROWS < height) ? ARRAY24_MAX_ROWS : height;

	  WritePixelArray24 (&(screen->RastPort), 0, ham8_line,
			     width, height,
			     ptr0, ptr1, ptr2, ham8_pens, &ham8_temprp);
	  ham8_line += height;
	}

    }
}


/*
 * Finish up at the end of the file.
 */

METHODDEF void
output_term (decompress_info_ptr cinfo)
{
  /* Cleanup(); */
}


/*
 * The method selection routine for HAM8 format output. This should be called
 * from d_ui_method_selection if HAM8 output is wanted.
 */

GLOBAL void
jselwham8 (decompress_info_ptr cinfo)
{


  cinfo->methods->output_init = output_init;
  cinfo->methods->put_pixel_rows = put_pixel_rows;
  cinfo->methods->output_term = output_term;
  if ((cinfo->out_color_space != CS_GRAYSCALE) &&
      (cinfo->out_color_space != CS_RGB))
    ERREXIT (cinfo->emethods, "HAM8 output must be grayscale or RGB");


}
