/*
 *  FILE: dbufvquick.c
 *  Support routines for converting a single-buffered Intuition screen
 *  into a double-buffered screen and back.
 *  It is faster than dbuf.c because copper lists are stored and manipulated
 *  quickly by these routines.
 *  It is slightly faster than dbufquick.c because copper lis pointers do not
 *  need to be passed as extra parameters.
 *
 *  NOTE: these routines are not very forgiving with respect to moving the
 *  screen around under Intuition.
 *
 *  Public Domain, but keep my name in it as the original author.
 *  31-Aug-88	Jan Sven Trabandt   first release version
 */


#define I_AM_DBUFVQUICK
#include "gimmelib/gimmefuncs.h"
#include "gimmelib/minterm.h"

static struct View	*gimView = NULL;
static struct cprlist	*gimShCpr = NULL;
static struct cprlist	*gimLoCpr = NULL;


short makeDBufVQuick( screen, bmptr )
    struct Screen   *screen;
    struct BitMap   **bmptr;
{
    struct BitMap   *bm;
    struct cprlist  *lcpr, *scpr;

#ifdef GIMME_WIMPY
    if( !screen || !bmptr ) {
	return( -1 );
    }
#endif
    if( !*bmptr ) {
	*bmptr = gimmeBitMap( screen->BitMap.Depth, screen->Width,
				screen->Height );
	if( !*bmptr ) {
	    return( -1 );
	}
    }

    Forbid();
    bm = screen->RastPort.BitMap;	    /* save main bitmap pointer */
    gimView = ViewAddress();
    lcpr = gimView->LOFCprList; 	       /* save these copper lists */
    scpr = gimView->SHFCprList;
    gimView->LOFCprList = NULL;
    gimView->SHFCprList = NULL;
    screen->ViewPort.RasInfo->BitMap = *bmptr;	    /* set to back buffer */
    MakeScreen( screen );
    MrgCop( gimView );                         /* make new copper lists */
    gimLoCpr = gimView->LOFCprList;	       /* save new copper lists */
    gimShCpr = gimView->SHFCprList;
    gimView->LOFCprList = lcpr; 	       /* restore old copper lists */
    gimView->SHFCprList = scpr;
    screen->ViewPort.RasInfo->BitMap = bm;  /* restore main viewing buffer */
    Permit();

    screen->RastPort.BitMap = *bmptr;	    /* draw to back buffer */
    return( 0 );
} /* makeDBufVQuick */


short unmakeDBufVQuick( screen, bmptr, bm )
    struct Screen   *screen;
    struct BitMap   **bmptr;
    struct BitMap   *bm;
{
    struct BitMap   *viewbm;

#ifdef GIMME_WIMPY
    if( !screen || !bmptr ) {
	return( -1 );
    }
#endif
    viewbm = screen->ViewPort.RasInfo->BitMap;
    if( !(screen->Flags & CUSTOMBITMAP) && viewbm == *bmptr ) {
	BltBitMap( viewbm, 0L, 0L, screen->RastPort.BitMap, 0L, 0L,
		    (ULONG)(bm->BytesPerRow) << 3, (ULONG) bm->Rows,
		    (ULONG) GIM_MINTERM_COPY, 0x0ffL, NULL );
	swapDBufVQuick( screen, GIM_MINTERM_DEST );
    }
    if( viewbm != screen->RastPort.BitMap ) {
	screen->RastPort.BitMap = viewbm;
    }
    if( bm ) {
	getRidOfBitMap( bm );
    }
    if( gimLoCpr ) {
	FreeCprList( gimLoCpr );
    }
    if( gimShCpr ) {
	FreeCprList( gimShCpr );
    }
    return( 0 );
} /* unmakeDBufVQuick */


short swapDBufVQuick( screen, minterm )
    register struct Screen  *screen;
    SHORT   minterm;
{
    struct BitMap   *bm;
    struct cprlist  *lcpr, *scpr;

#ifdef GIMME_WIMPY
    if( !screen ) {
	return( -1 );
    }
#endif
    Forbid();
    bm = screen->ViewPort.RasInfo->BitMap;
    if( bm == screen->RastPort.BitMap ) {
	Permit();
	return( 0 );
    }
    lcpr = gimView->LOFCprList; 	       /* get current copper lists */
    scpr = gimView->SHFCprList;
    gimView->LOFCprList = gimLoCpr;	       /* set other copper lists */
    gimView->SHFCprList = gimShCpr;
    gimLoCpr = lcpr;			    /* save new other copper lists */
    gimShCpr = scpr;
    LoadView( gimView );

    screen->ViewPort.RasInfo->BitMap = screen->RastPort.BitMap;
    screen->RastPort.BitMap = bm;
    Permit();
    if( minterm != GIM_MINTERM_DEST ) {
	BltBitMap( screen->ViewPort.RasInfo->BitMap, 0L, 0L, bm, 0L, 0L,
		    (ULONG)(bm->BytesPerRow) << 3, (ULONG) bm->Rows,
		    (ULONG) minterm, 0x0ffL, NULL );
    }
    return( 0 );
} /* swapDBufVQuick */
