#include <exec/types.h>
#include <intuition/intuition.h>
#include <clib/graphics_protos.h>
#include <scan/modall.h>
#include <scan/prev.h>



static struct ViewPort *vport;
static struct RastPort *rport;


/*
 * VM_InitNS()
 *
 * Prepare the NewScreen structure that ImageFX is about to open for the
 * preview display.
 *
 *    ns = pointer to NewScreen structure to be initialized
 *    swid = source buffer width, in pixels
 *    sht = source buffer height, in pixels
 *    sdepth = source buffer depth, in 8-bit planes (1 or 3)
 *    vwid = where to store pixel width of preview (number of pixels shown)
 *    vht = where to store pixel height of preview (number of pixels shown)
 *
 */
BOOL __saveds __asm VM_InitNS (register __a0 struct NewScreen *ns,
                      register __d0 short swid,
                      register __d1 short sht,
                      register __d2 short sdepth,
                      register __a1 short *vwid,
                      register __a2 short *vht)
{
   /* our example is a lores greyscale only preview */

   ns->Width = 320;
   ns->Height = 200;
   ns->Depth = 4;
   ns->ViewModes = 0;

   *vwid = 320;
   *vht = 200;

   return(TRUE);
}

static BOOL clear_text = FALSE;

/*
 * VM_Init()
 *
 * Initialize preview display after the preview screen and window have been
 * opened.
 *
 *    screen = pointer to preview screen.
 *    window = pointer to preview window.
 *
 */
BOOL __saveds __asm VM_Init (register __a0 struct Screen *screen,
                    register __a1 struct Window *window)
{
//   if (ModuleBase->Text == NULL) {
//      clear_text = TRUE;
//      ModuleBase->Text = Default_Strings;
//   }

   vport = &screen->ViewPort;
   rport = &screen->RastPort;

   return(TRUE);
}

/*
 * VM_Cleanup()
 *
 * Cleanup your preview display before ImageFX closes the screen and window.
 *
 *    screen = pointer to preview screen.
 *    window = pointer to preview window.
 *
 */
void __saveds __asm VM_Cleanup (register __a0 struct Screen *screen,
                       register __a1 struct Window *window)
{
//   if (clear_text) ModuleBase->Text = NULL;
}

/*
 * VM_Clear()
 *
 * Clear preview display to black.
 *
 */
void __saveds VM_Clear (void)
{
   SetRast(rport, 0);
}

/*
 * VM_Palette()
 *
 * Set the colors used in your preview display.  24-bit previews shouldn't have
 * to do anything here.
 *
 */
void __saveds __asm VM_Palette (register __d0 short type)
{
   int i;

   /* our example just sets a greyscale palette no matter what */
   for (i = 0; i < 16; i++) SetRGB4(vport, i, i, i, i);
}

/*
 * VM_InitBrushEncode()
 *
 * ImageFX calls this when redrawing a brush.  It should do any special
 * initialization that needs to be done for brushes on your preview.
 * ImageFX calls the same functions for rendering to the preview display
 * and the brush, so you can use this function to set a flag to know when
 * ImageFX is rendering to a brush.
 *
 *    clip = pointer to Clip structure describing brush.
 *
 */
BOOL __saveds __asm VM_InitBrushEncode (register __a0 struct Clip *clip)
{
   /* our example needs no special setup */
   return(TRUE);
}

/*
 * VM_CleanupBrushEncode()
 *
 * Cleanup after rendering a brush.
 *
 *    clip = pointer to Clip structure describing the brush.
 *
 */
void __saveds __asm VM_CleanupBrushEncode (register __a0 struct Clip *clip)
{
}

/*
 * VM_MapCoordsFrom()
 *
 * Convert screen coordinates into actual preview coordinates.  This should
 * be used if your preview display uses more than one pixel to represent
 * each pixel the user sees (eg. the HAM-E uses 2 hires pixels to display
 * 1 lores 8-bit pixel).  This can also be used to take into account any
 * "magic cookies" built into the bitmap.
 *
 *    x, y = pointer to X and Y coordinates to modify
 *    clip = if TRUE, we're asking about a brush and not the preview screen.
 *
 */
void __saveds __asm VM_MapCoordsFrom (register __a0 short *x,
                             register __a1 short *y,
                             register __d0 BOOL clip)
{
}

/*
 * VM_MapCoordsTo()
 *
 * Convert preview coordinates into actual screen pixel coordinates.  The
 * exact opposite of VM_MapCoordsFrom().
 *
 *    x, y = pointer to X and Y coordinates to modify
 *    clip = if TRUE, we're asking about a brush and not the preview screen.
 *
 */
void __saveds __asm VM_MapCoordsTo (register __a0 short *x,
                           register __a1 short *y,
                           register __d0 BOOL clip)
{
}

/*****************************************************************************\

                               Palette Functions

\*****************************************************************************/

static struct ViewPort *palvport;
static struct RastPort *palrport;

/*
 * VM_PalInitNS ()
 *
 * Initialize a NewScreen structure to open a palette on for this device.
 * Returns the width of the viewable area (in terms of the display device
 * pixels) for the screen.  Sets the top offset from the top of the screen
 * to the beginning of the palette color data (to account for magic cookies
 * and such).
 */
int __saveds __asm VM_PalInitNS (register __a0 struct NewScreen *ns,
                        register __a1 short *top)
{
   ns->Width = 320;
   ns->Depth = 4;
   ns->ViewModes = 0;

   *top = 1;

   return(320);
}

/*
 * VM_PalInit ()
 *
 * Called after the palette screen is open to setup whatever is necessary
 * to show a palette on this display device.  Entirely for the module's use.
 */
void __saveds __asm VM_PalInit (register __a0 struct Screen *screen)
{
   int i;

   palvport = &screen->ViewPort;
   palrport = &screen->RastPort;

   for (i = 0; i < 16; i++) SetRGB4(palvport, i, i, i, i);
}

/*
 * VM_PalCleanup ()
 *
 * Called before closing the palette screen to cleanup whatever was
 * done by the VM_PalInit() function above.  Entirely for the module's use.
 */
void __saveds __asm VM_PalCleanup (register __a0 struct Screen *screen)
{
}

/*
 * VM_PalSetRGB8 (reg, r, g, b, le, te, w, h)
 *
 * Set the color of the given register; if this display device does not
 * support a palette (ie. 24-bit displays), then simply draw the color
 * at the given location.  This is called as the user adjust RGB sliders,
 * and should be as fast as humanly possible.  Coordinates given are
 * in terms of the display device pixels.
 */
void __saveds __asm VM_PalSetRGB8 (register __a0 struct Screen *screen,
                          register __d0 short reg,
                          register __d1 short r,
                          register __d2 short g,
                          register __d3 short b,
                          register __d4 short le,
                          register __d5 short te,
                          register __d6 short w,
                          register __d7 short h)
{
   /* our example only shows in greyscale */
   int v = ((r + g + b) / 3) >> 4;
   SetDrMd(palrport, JAM1);
   SetAPen(palrport, v);
   RectFill(palrport, le, te, le + w - 1, te + h - 1);
}

/*
 * VM_PalDraw (reg, r, g, b, le, te, w, h)
 *
 * Draw a box in the given color at the given location.  For palette mapped
 * devices, the register is used to index the colormap; for 24-bit devices
 * the actual RGB value is used.  This is usually called for palette
 * initialization.  Coordinates given are in terms of the display device
 * pixels.
 */
void __saveds __asm VM_PalDraw (register __a0 struct Screen *screen,
                       register __d0 short reg,
                       register __d1 short r,
                       register __d2 short g,
                       register __d3 short b,
                       register __d4 short le,
                       register __d5 short te,
                       register __d6 short w,
                       register __d7 short h)
{
   int v = ((r + g + b) / 3) >> 4;
   SetDrMd(palrport, JAM1);
   SetAPen(palrport, v);
   RectFill(palrport, le, te, le + w - 1, te + h - 1);
}

/*
 * VM_PalBox (highlight, le, te, w, h)
 *
 * Draw a box (presumabely) around a palette color.  If highlight is TRUE,
 * then the box should be drawn, otherwise, the box should be erased.
 * Called when the user selects and unselects palette colors... also
 * used to show palette ranges (by erasing boxes in the midst of palette
 * colors).  Coordinates given are in terms of the display device pixels.
 */
void __saveds __asm VM_PalBox (register __a0 struct Screen *screen,
                      register __d0 BOOL highlight,
                      register __d1 short le,
                      register __d2 short te,
                      register __d3 short w,
                      register __d4 short h)
{
   SetAPen(palrport, highlight ? 15 : 0);
   SetDrMd(palrport, JAM1);

   Move(palrport, le, te);
   Draw(palrport, le + w - 1, te);
   Draw(palrport, le + w - 1, te + h - 1);
   Draw(palrport, le, te + h - 1);
   Draw(palrport, le, te);
}

/*
 * VM_PalRange (le, te, w, h)
 *
 * Used to show a color as being part of a range.
 *
 */
void __saveds __asm VM_PalRange (register __a0 struct Screen *screen,
                        register __d0 short le,
                        register __d1 short te,
                        register __d2 short w,
                        register __d3 short h)
{
   SetAPen(palrport, 0);
   SetDrMd(palrport, JAM1);
   RectFill(palrport, le + 1, te + 1, le + w - 2, te + h - 2);
}


/*****************************************************************************\

                               Miscellaneous functions

\*****************************************************************************/

void __saveds __asm VM_InitStencil (register __a0 short *wid,
                           register __a1 short *ht,
                           register __a2 UBYTE *initmask,
                           register __a3 short *shift)
{
   *initmask = 0x80;
   *shift = 1;
}


/*
 * VM_Hide()
 *
 * Called by ImageFX when the user pushes the ImageFX screen to the back.
 * You can use this to do any special code to turn off the preview
 * display, if necessary (like turning off genlocking or whatever).
 *
 */
void __saveds VM_Hide (void)
{
}

/*
 * VM_Show()
 *
 * Called by ImageFX when the user brings ImageFX back to the front.
 *
 */
void __saveds VM_Show (void)
{
}

/*
 * VM_Pause()
 *
 * This is used to avoid contention between a render module and a preview
 * module on a display output that is exclusive access.  The render module
 * will signal ImageFX that it is about to open a display on a certain
 * hardware device, and ImageFX will call the VM_Pause vector of the
 * current preview module with the 4-byte key of the hardware that the
 * render module is about to use.  If the preview module recognizes that
 * the key is what *it* is also using, it should shut down its access to
 * the hardware while the render module shows the picture.
 *
 */
void __saveds __asm VM_Pause (register __d0 ULONG key)
{
   if (key == 'GREY') {
      /* shut us down - this example doesn't need to though */
   }
}

/*
 * VM_Resume()
 *
 * Restore access to the preview display hardware.
 *
 */
void __saveds __asm VM_Resume (register __d0 ULONG key)
{
   if (key == 'GREY') {
      /* restore us - this example doesn't need to though */
   }
}

/*
 * This structure defines the format for your preferences.  ImageFX
 * will store this structure in the user's prefs files.
 */
struct MyPrefs {
   UBYTE    Stuff[4];
   UBYTE    Reserved[12];
};

/*
 * VM_SavePrefs()
 *
 * Store your current module configuration into the supplied
 * preferences structure.  ImageFX will then save it to disk.
 *
 */
BOOL __saveds __asm VM_SavePrefs (register __a0 struct MyPrefs *prefs)
{
   /* no prefs in this example */
   return(TRUE);
}

/*
 * VM_LoadPrefs()
 *
 * Configure your module based on the settings in the supplied
 * preferences structure.  Note that your module does not necessarily
 * have to be displayed for this function to be called, so make sure
 * that your gadgets exist before fiddling with them.  Return TRUE
 * on success, or FALSE on failure.
 *
 */
BOOL __saveds __asm VM_LoadPrefs (register __a0 struct MyPrefs *prefs)
{
   /* no prefs in this example */
   return(TRUE);
}

static struct RastPort temprp;

void __saveds __asm VM_OutputRow24 (register __a0 struct BitMap *bm,
                           register __a1 UBYTE *outpix,
                           register __d0 int row,
                           register __d1 int leftedge,
                           register __d2 int width)
{
   int i, c;

   /* this example just writes grey lines very slowly... */
   for (i = 0; i < width; i++) {
      c = ((outpix[0] + outpix[1] + outpix[2]) / 3) >> 4;
      SetAPen(&temprp, c);
      WritePixel(&temprp, i + leftedge, row);
      outpix += 3;
   }
}

void __saveds __asm VM_OutputRow8 (register __a0 struct BitMap *bm,
                          register __a1 UBYTE *outpix,
                          register __d0 int row,
                          register __d1 int leftedge,
                          register __d2 int width)
{
   int i;

   /* this example just writes grey lines very slowly... */
   for (i = 0; i < width; i++) {
      SetAPen(&temprp, (*outpix++) >> 4);
      WritePixel(&temprp, i + leftedge, row);
   }
}

void __saveds __asm VM_InitUpdate (register __a0 struct BitMap *bm,
                          register __d0 int leftedge,
                          register __d1 int topedge,
                          register __d2 int width,
                          register __d3 int height)
{
   InitRastPort(&temprp);
   temprp.BitMap = bm;
}

void __saveds __asm VM_CleanupUpdate (register __a0 struct BitMap *bm)
{
}


void __saveds __asm VM_Identification (register __a0 struct PreviewInfo *pi)
{
   /* this example has nothing special */
}

/**********************************************************************\

                         Standard Module Stuff

\**********************************************************************/


/*
 * Function table.  Referenced in "lib.o".
 *
 * The first four entries are the standard library vectors, defined
 * in "lib.o", the remaining entries define functions specific to
 * this module.
 *
 * The table ends with -1.
 *
 */
ULONG FuncTable[] = {
   (ULONG) LibOpen,
   (ULONG) LibClose,
   (ULONG) LibExpunge,
   (ULONG) LibNull,

   (ULONG) 0,              /* unused */
   (ULONG) VM_InitNS,
   (ULONG) VM_Init,
   (ULONG) VM_Cleanup,
   (ULONG) VM_Clear,
   (ULONG) VM_Palette,
   (ULONG) 0,              /* unused */
   (ULONG) 0,              /* unused */
   (ULONG) 0,              /* unused */
   (ULONG) 0,              /* unused */
   (ULONG) VM_MapCoordsFrom,
   (ULONG) VM_MapCoordsTo,

   (ULONG) VM_PalInit,
   (ULONG) VM_PalCleanup,
   (ULONG) VM_PalInitNS,
   (ULONG) VM_PalSetRGB8,
   (ULONG) VM_PalDraw,
   (ULONG) VM_PalBox,
   (ULONG) VM_PalRange,

   (ULONG) 0,              /* unused */
   (ULONG) VM_InitBrushEncode,
   (ULONG) VM_CleanupBrushEncode,
   (ULONG) VM_InitStencil,
   (ULONG) 0,              /* unused */
   (ULONG) 0,              /* unused */
   (ULONG) 0,              /* unused */
   (ULONG) 0,              /* unused */

   (ULONG) VM_Hide,
   (ULONG) VM_Show,
   (ULONG) VM_Pause,
   (ULONG) VM_Resume,
   (ULONG) VM_SavePrefs,
   (ULONG) VM_LoadPrefs,

   (ULONG) VM_OutputRow24,
   (ULONG) VM_OutputRow8,
   (ULONG) VM_InitUpdate,
   (ULONG) VM_CleanupUpdate,

   (ULONG) VM_Identification,

   (ULONG) -1L
};

/*
 * ID string for this module.  References in "lib.o".
 *
 * Should be given in the standard 2.0 version string style.
 */
UBYTE LibraryID[] = "$VER: Untitled 1.00.00 (19.6.92)";

/*
 * Type of module.  Referenced in "lib.o".
 *
 * Should be one of the NT_* defines in <scan/mod.h>
 *
 */
UBYTE LibraryType = NT_PREVIEW;

/*
 * Module initialization code.  Referenced by "lib.o".
 *
 * This is where you would initialize the ModuleBase structure that
 * is passed to you.
 *
 * Returns TRUE if all went well, or FALSE if something went wrong and
 * the module open should fail.
 *
 */
LONG __saveds __stdargs UserOpen (struct ModuleBase *modbase)
{
// modbase->NewWin = newWindow;                 /* Preview Options window */
// modbase->NewGad = newGads;                   /* GUI for Preview Options */
// modbase->Language = "Preview_Skeleton";      /* Language tag */
// modbase->LangCount = TXT_COUNT;              /* Number of texts */
   modbase->PrefID = 'PSKL';                    /* Preferences tag */
   modbase->PrefLen = sizeof(struct MyPrefs);   /* Size of prefs data */
   return(TRUE);
}

/*
 * Module cleanup code.  Referenced by "lib.o".
 *
 * This should cleanup anything you allocated or opened in UserOpen()
 * above.
 *
 * Always return TRUE.
 *
 */
LONG __saveds __stdargs UserClose (struct ModuleBase *modbase)
{
   return(TRUE);
}

