/*============================================================================*/
/*  Pages.c: swap pages around						      */
/*============================================================================*/

#include "equates.h"
#include <functions.h>
#include <exec/types.h>
#include <intuition/intuition.h>

#include <graphics/gfx.h>
#include "iff/jiff.h"

/*============================================================================*/

struct Page *PageList,*CurrentPage = NULL;

extern struct Screen *MPaintScreen;
extern struct RastPort TempRastPort;
extern struct BitMap TempBitMap;
extern int MaxColor;
extern struct Window *MPaintWindow;
extern struct RastPort UndoRastPort;
extern SHORT PaintWidth,PaintHeight;
extern UWORD *ColorPTR;

/*============================================================================*/

struct Page *
InitPage()
{
    int i;
    struct Page *TempPage;
    long Depth;
    struct Remember *PRem;

    PRem = NULL;
    Depth = Num2Bit((long)MaxColor);

    TempPage = (struct Page *)AllocRemember(&PRem,(long)sizeof(struct Page),MEMF_CLEAR);
    if(!TempPage)
	cleanup("out of memory",ERR_NOMEM);

    TempPage->RastPort = (struct RastPort *)AllocRemember(&PRem,(long)sizeof(struct RastPort),MEMF_CLEAR);
    if(!TempPage->RastPort)
     {
	FreeRemember(&PRem,TRUE);
	return(NULL);
     }
    InitRastPort(TempPage->RastPort);

    TempPage->RastPort->BitMap = (struct BitMap *)AllocRemember(&PRem,(long)sizeof(struct BitMap),MEMF_CLEAR);
    if(!TempPage->RastPort->BitMap)
     {
	FreeRemember(&PRem,TRUE);
	return(NULL);
     }

    InitBitMap(TempPage->RastPort->BitMap,Depth,(long)PaintWidth,(long)PaintHeight);

    for (i=0; i<Depth; i++)
	if ((TempPage->RastPort->BitMap->Planes[i] = ralloc(PaintHeight*(PaintWidth/8))) == NULL)
	 {
	    myfree_planes( TempPage->RastPort->BitMap );
	    FreeRemember(&PRem,TRUE);
	    return(NULL);
	 }
    TempPage->ColorTable = (UWORD *)AllocRemember(&PRem,(long)sizeof(UWORD[32]),MEMF_CLEAR);
    if(!TempPage->ColorTable)
     {
	myfree_planes( TempPage->RastPort->BitMap );
	FreeRemember(&PRem,TRUE);
	return(NULL);
     }

    for(i=0;i<32;i++)
	TempPage->ColorTable[i] = ColorPTR[i];

    FreeRemember(&PRem,FALSE);
    return(TempPage);
}

/*============================================================================*/

struct Page *
ScanToEndOfPages()
{
    struct Page *TempPage;

    TempPage = PageList->NextPage;

    if(TempPage)
     {
	while(TempPage->NextPage)
	    TempPage = TempPage->NextPage;
	return(TempPage);
    }
   return(PageList);
}

/*============================================================================*/

InitSpare()
{
    struct Page *TempPage;

    PageList = AllocMem((long)sizeof(struct Page),MEMF_CLEAR);
    if(!PageList)
	return();

    PageList->NextPage = InitPage();
    if(PageList->NextPage)
     {
	CurrentPage = PageList->NextPage;
	SetRast(CurrentPage->RastPort,0L);     /* clear newly aquired page */
     }
}

/*============================================================================*/

SwapWithSpare()
{
    int i;
    long Depth;
    FLAG NoBackUp = FALSE;
    struct Page *TempPage;
    UWORD *TempPTR;

     if(PageList->NextPage)
      {
	TempPage = CurrentPage->NextPage;
	if(!TempPage)
	    TempPage = PageList->NextPage;
	CurrentPage = TempPage;

	Depth = Num2Bit((long)MaxColor);

	SaveToUndoBuffer();
						    /* restore old picture */
	TempPTR = ColorPTR;
	ColorPTR = TempPage->ColorTable;
	TempPage->ColorTable = TempPTR;
	LoadRGB4(&MPaintScreen->ViewPort,ColorPTR,MaxColor);

	ClipBlit(TempPage->RastPort, (long)0, (long)0,
		 MPaintWindow->RPort, (long)0, (long)0,
		(long)PaintWidth, (long)PaintHeight, (long)COPY_MINTERM);

	ClipBlit(&UndoRastPort, (long)0, (long)0,
		 TempPage->RastPort, (long)0, (long)0,
		(long)PaintWidth, (long)PaintHeight, (long)COPY_MINTERM);

	UpdatePropGadgets();
     }
}

/*============================================================================*/

AddPage()
{
    struct Page *TempPage;
    TempPage = ScanToEndOfPages();

    TempPage->NextPage = InitPage();
    if(TempPage->NextPage)
     {
	SetRast(TempPage->NextPage->RastPort,0L);
	CurrentPage = TempPage;
	SwapWithSpare();
     }
}
/*============================================================================*/

struct Page *
ScanToPageBefore(TempPage)
struct Page *TempPage;
{
    struct Page *ScanPage;
    ScanPage = PageList;
    while(ScanPage->NextPage != TempPage)
	ScanPage = ScanPage->NextPage;
    return(ScanPage);
}

/*============================================================================*/

DeletePage(TempPage)
struct Page *TempPage;
{
    if(PageList->NextPage)
     {
	struct Page *ScanPage;
	if(TempPage)
	 {
	    ScanToPageBefore(TempPage)->NextPage = TempPage->NextPage;
	    CurrentPage = TempPage->NextPage;
	    if(!CurrentPage)
		CurrentPage = PageList->NextPage;
	    myfree_planes( TempPage->RastPort->BitMap);
	    FreeMem(TempPage->RastPort->BitMap,(long)sizeof(struct BitMap));
	    FreeMem(TempPage->RastPort,(long)sizeof(struct RastPort));
	    FreeMem(TempPage->ColorTable,(long)sizeof(UWORD[32]));
	    FreeMem(TempPage,(long)sizeof(struct Page));
	 }
     }
}

/*============================================================================*/

DeleteAllPages()
{
    struct Page *TempPage;
    if(PageList)
     {
	while(PageList->NextPage)
	    DeletePage(PageList->NextPage);
	FreeMem(PageList,(long)sizeof(struct Page));
     }
    PageList = NULL;
}

