/*
 *  FILE: dbufquick.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.
 *
 *  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_DBUFQUICK
#include "gimmelib/gimmefuncs.h"
#include "gimmelib/minterm.h"


short makeDBufQuick( screen, bmptr, lcprptr, scprptr )
    struct Screen   *screen;
    struct BitMap   **bmptr;
    struct cprlist  **lcprptr, **scprptr;
{
    struct BitMap   *bm;
    struct cprlist  *lcpr, *scpr;
    struct View     *view;

#ifdef GIMME_WIMPY
    if( !screen || !bmptr || !lcprptr || !scprptr ) {
	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 */
    view = ViewAddress();
    lcpr = view->LOFCprList;		    /* save these copper lists */
    scpr = view->SHFCprList;
    view->LOFCprList = NULL;
    view->SHFCprList = NULL;
    screen->ViewPort.RasInfo->BitMap = *bmptr;	    /* set to back buffer */
    MakeScreen( screen );
    MrgCop( view );                         /* make new copper lists */
    *lcprptr = view->LOFCprList;	    /* save new copper lists */
    *scprptr = view->SHFCprList;
    view->LOFCprList = lcpr;		    /* restore old copper lists */
    view->SHFCprList = scpr;
    screen->ViewPort.RasInfo->BitMap = bm;  /* restore main viewing buffer */
    Permit();

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


short unmakeDBufQuick( screen, bmptr, bm, lcprptr, scprptr )
    struct Screen   *screen;
    struct BitMap   **bmptr;
    struct BitMap   *bm;
    struct cprlist  **lcprptr, **scprptr;
{
    struct BitMap   *viewbm;

#ifdef GIMME_WIMPY
    if( !screen || !bmptr || !lcprptr || !scprptr ) {
	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 );
	swapDBufQuick( screen, GIM_MINTERM_DEST, lcprptr, scprptr );
    }
    if( viewbm != screen->RastPort.BitMap ) {
	screen->RastPort.BitMap = viewbm;
    }
    if( bm ) {
	getRidOfBitMap( bm );
    }
    if( *lcprptr ) {
	FreeCprList( *lcprptr );
    }
    if( *scprptr ) {
	FreeCprList( *scprptr );
    }
    return( 0 );
} /* unmakeDBufQuick */


short swapDBufQuick( screen, minterm, lcprptr, scprptr )
    register struct Screen  *screen;
    SHORT   minterm;
    struct cprlist  **lcprptr, **scprptr;
{
    struct BitMap   *bm;
    struct cprlist  *lcpr, *scpr;
    struct View     *view;

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

    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 );
} /* swapDBufQuick */
