[comp.sources.amiga] v02i077: gimme.lib - misc library routines, Part04/07

page@swan.ulowell.edu (Bob Page) (12/02/88)

Submitted-by: oscvax!jan@uunet.UU.NET (Jan Sven Trabandt)
Posting-number: Volume 2, Issue 77
Archive-name: libraries/gimme.4

#	This is a shell archive.
#	Remove everything above and including the cut line.
#	Then run the rest of the file through sh.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar:    Shell Archiver
#	Run the following text with /bin/sh to create:
#	bitmap.c
#	bitplane.c
#	color.c
#	communic.c
#	copystuff.c
#	dbuf.c
#	dbufquick.c
#	dbufvquick.c
#	dualpf.c
#	font.c
#	gadget.c
#	gadgstuff.c
# This archive created: Thu Dec  1 19:50:54 1988
cat << \SHAR_EOF > bitmap.c
/*
 *  FILE: bitmap.c
 *  Support routines for dynamic (de)allocation of bitmaps.
 *
 *  Public Domain, but keep my name in it as the original author.
 *  31-Aug-88	Jan Sven Trabandt   first release version
 */


#include "gimmelib/gimmefuncs.h"


struct BitMap *gimmeBitMap( depth, width, height )
    SHORT   depth, width, height;
{
    register struct BitMap  *bm;
    SHORT		    i;

    bm = (struct BitMap *) AllocMem( (ULONG)sizeof(struct BitMap),
					MEMF_PUBLIC | MEMF_CLEAR );
    if( !bm ) {
	return( NULL );
    }
    if( depth > 0 && width > 0 && height > 0 ) {
	InitBitMap( bm, (ULONG) depth, (ULONG) width, (ULONG) height );
	for( i = 0; i < depth; ++i ) {
	    if( !(bm->Planes[i] = (PLANEPTR)
				    AllocRaster((ULONG)width,(ULONG)height)) ) {
		bm->Depth = i;
		getRidOfBitMap( bm );
		return( NULL );
	    }
	    BltClear( bm->Planes[i],
			(ULONG)RASSIZE((ULONG)width,(ULONG)height), 0L );
	} /* for */
    }
    return( bm );
} /* gimmeBitMap */


short getRidOfBitMap( bitmap )
    register struct BitMap  *bitmap;
{
    SHORT   i;
    SHORT   width;

#ifdef GIMME_WIMPY
    if( !bitmap ) {
	return( -1 );
    }
#endif
    width = bitmap->BytesPerRow << 3;
    for( i = 0; i < bitmap->Depth && bitmap->Planes[i]; ++i ) {
	FreeRaster( bitmap->Planes[i], (ULONG) width, (ULONG) bitmap->Rows );
    } /* for */
    FreeMem( bitmap, (ULONG)sizeof(struct BitMap) );
    return( 0 );
} /* getRidOfBitMap */
SHAR_EOF
cat << \SHAR_EOF > bitplane.c
/*
 *  FILE: bitplane.c
 *  Support routines for dynamic (de)allocation of bitplanes for bitmaps
 *  and/or image data.
 *
 *  Public Domain, but keep my name in it as the original author.
 *  31-Aug-88	Jan Sven Trabandt   first release version
 */


#define I_AM_BITPLANE
#include "gimmelib/gimmefuncs.h"
#include "gimmelib/bitplane.h"


ULONG gimmeBitPlanes( bm, myflags )
    struct BitMap   *bm;
    ULONG	    myflags;
{
    SHORT   i;
    SHORT   width, height, depth;
    ULONG   planesize;

#ifdef GIMME_WIMPY
    if( !bm ) {
	return( GBP_ERROR );
    }
#endif
    width = bm->BytesPerRow << 3;
    height = bm->Rows;
    depth = bm->Depth;
    planesize = RASSIZE((ULONG)width, (ULONG)height);
    bm->Planes[0] = NULL;
    if( myflags & GBP_CONTIGUOUS ) {
	if( bm->Planes[0] = AllocMem( (ULONG)(depth) * planesize,
					MEMF_CHIP | MEMF_CLEAR) ) {
	    for( i = 1; i < depth; ++i ) {
		bm->Planes[i] = (UBYTE *)(bm->Planes[i-1]) + planesize;
	    } /* for */
	    return( GBP_CONTIGUOUS );
	}
    }
    if( (myflags & GBP_SEPARATE) || !myflags ) {
	for( i = 0; i < depth; ++i ) {
	    if( !(bm->Planes[i] = (PLANEPTR)
				    AllocRaster((ULONG)width,(ULONG)height)) ) {
		while( --i >= 0 ) {
		    FreeRaster( bm->Planes[i], (ULONG) bm->BytesPerRow << 3,
				    (ULONG) bm->Rows );
		} /* while */
		return( GBP_ERROR );
	    }
	    BltClear( bm->Planes[i], planesize, 0L );
	} /* for */
	return( GBP_SEPARATE );
    }
    return( GBP_ERROR );
} /* gimmeBitPlanes */


short getRidOfBitPlanes( bm, myflags )
    struct BitMap   *bm;
    ULONG	    myflags;
{
    SHORT   i;
    SHORT   width, height, depth;

#ifdef GIMME_WIMPY
    if( !bm ) {
	return( -1 );
    }
#endif
    width = bm->BytesPerRow << 3;
    height = bm->Rows;
    depth = bm->Depth;
    if( myflags & GBP_CONTIGUOUS ) {
	FreeMem( bm->Planes[0],
		    (ULONG)(depth) * RASSIZE((ULONG)width,(ULONG)height) );
    } else {
	for( i = 0; i < depth && bm->Planes[i]; ++i ) {
	    FreeRaster( bm->Planes[i], (ULONG) width, (ULONG) height );
	} /* for */
    }
    return( 0 );
} /* getRidOfBitPlanes */
SHAR_EOF
cat << \SHAR_EOF > color.c
/*
 *  FILE: color.c
 *  Support routines for dealing with the color of an Intuition screen.
 *
 *  Public Domain, but keep my name in it as the original author.
 *  31-Aug-88	Jan Sven Trabandt   first release version
 */


#define I_AM_COLOR
#include <clib/macros.h>
#include "gimmelib/gimmefuncs.h"
#include "gimmelib/color.h"


USHORT *getDefaultColors()
{
    if( DFLT_MAX_COLORS > 0 ) {
	return( gimColorTable );
    } else {
	return( NULL );
    }
} /* getDefaultColors */


short setColors( screen, ctable, colors )
    struct Screen   *screen;
    USHORT	    *ctable;
    SHORT	    colors;
{
#ifdef GIMME_WIMPY
    if( !screen || colors <= 0 ) {
	return( -1 );
    }
#endif
    if( ctable ) {
	colors = MIN( colors, screen->ViewPort.ColorMap->Count );
    } else {
	if( colors > DFLT_MAX_COLORS ) {
	    return( -1 );
	}
	ctable = gimColorTable;
    }
    LoadRGB4( &screen->ViewPort, ctable, (ULONG) colors );
    return( 0 );
} /* setColors */


#define TEST_TEXT	"hi!"
#define TEST_TEXT_LEN	3	/* strlen(TEST_TEXT) */

short checkColors( screen, colors )
    struct Screen   *screen;
    SHORT	    colors;
{
    register struct RastPort	*rp;
    SHORT   i, j;
    SHORT   x, y;

#ifdef GIMME_WIMPY
    if( !screen ) {
	return( -1 );
    }
#endif
    rp = &screen->RastPort;
    colors = MIN( colors, screen->ViewPort.ColorMap->Count );
    x = 0;
    y = screen->BarHeight + rp->TxHeight;
    j = 0;
    for( i = 0; i < colors; ++i ) {
	SetAPen( rp, (ULONG) i );
	if( !(i % 4) ) {
	    y += rp->TxHeight;
	    x = 0;
	} else {
	    x += (TEST_TEXT_LEN+1) * rp->TxWidth;
	}
	Move( rp, (ULONG) x, (ULONG) y );
	Text( rp, TEST_TEXT, (ULONG) TEST_TEXT_LEN );
    }
    return( 0 );
} /* checkColors */
SHAR_EOF
cat << \SHAR_EOF > communic.c
/*
 *  FILE: communic.c
 *  Support routines for accessing, reading and writing to the serial port.
 *
 *  NOTE: these routines provide EXCLUSIVE access to the serial port for one
 *  task only.	This shouldn't be too great a problem given the nature of the
 *  serial port.
 *
 *  Public Domain, but keep our names in it as the original authors.
 *  11-May-87	Scotte Zinn	    created
 *  15-Mar-88	Jan Sven Trabandt   changed c_set_error to a macro
 *				    made sure it works with short (16 bit) ints
 *  27-Apr-88	Jan Sven Trabandt   lots of goodies
 *  31-Oct-88	Jan Sven Trabandt   added to gimme.lib (finally)
 */


#define I_AM_COMMUNIC
#include "gimmelib/gimmefuncs.h"
#include "gimmelib/communic.h"
#include <devices/serial.h>


#define C_NOT_OPEN	0
#define BUFFER_LENGTH	4096
#define INIT_VALUE	29451

#define initialized()       ((SHORT)initial != 0)
#define channel_open()      ((SHORT)system_state != C_NOT_OPEN)
#define c_set_error(err)    (c_error = err)

static struct IOExtSer	*IORser = NULL;
static struct MsgPort	*SPort = NULL;
static struct timerequest *treq = NULL;
static char EOLchar = DEFAULT_EOL;
static SHORT system_state = C_NOT_OPEN;
static SHORT initial = 0;

short c_error;

/* forward declarations */
static short c_getchar();


short c_init()
{
    if( !initialized() ) {
	/* Set system state to channel not open and set initialized flag */
	Forbid();
	initial = INIT_VALUE;
	system_state = C_NOT_OPEN;
	Permit();
    }
    return( c_set_error(C_ERR_OK) );
} /* c_init */


short c_open( parms )
    struct c_parameters *parms;
{
    short   error;

    if( !parms ) {
	return( c_set_error(C_ERR_BADPARM) );
    }
    if( !initialized() )
	return( c_set_error(C_ERR_INITIAL) );
    if( channel_open() )
	return( c_set_error(C_ERR_OPEN) );

    /* Now access timer device for future time-outs and to get a Port */
    if( !(treq = accessTimer(UNIT_VBLANK, &SPort)) ) {
	return( c_set_error(C_ERR_CANT) );
    }

    IORser = (struct IOExtSer *) CreateExtIO( SPort,
					(ULONG)sizeof(struct IOExtSer) );
    if( !IORser ) {
	releaseTimer( treq, NULL );
	return( c_set_error(C_ERR_CANT) );
    }

    if( parms->C_MODE == C_SER_7 ) {
	IORser->io_SerFlags = SERB_7WIRE | SERB_XDISABLED;
    }
    if( OpenDevice(SERIALNAME, 0L, IORser, 0L) ) {
	DeleteExtIO( IORser, (ULONG)sizeof(struct IOExtSer) );
	releaseTimer( treq, NULL );
	return( c_set_error(C_ERR_CANT) );
    }

    system_state = -1;			/* Now set channel opened */

    if( error = c_setup(parms) ) {
	CloseDevice( IORser );
	DeleteExtIO( IORser, (ULONG)sizeof(struct IOExtSer) );
	releaseTimer( treq, NULL );
	system_state = C_NOT_OPEN;
	return( c_set_error(error) );
    }
    EOLchar = DEFAULT_EOL;

    /* Channel is now successfully opened */
    return( c_set_error(C_ERR_OK) );
} /* c_open */


short c_setup( parms )
    struct c_parameters *parms;
{
    if( !(initialized() && channel_open()) )    /* important to check here */
	return( c_set_error(C_ERR_CHAN) );
    if( !parms ) {
	return( c_set_error(C_ERR_BADPARM) );
    }

    /* Now set parameters as requested */
    IORser->io_ReadLen	= parms->C_RLEN;
    IORser->io_BrkTime	= 750000L;
    IORser->io_Baud	= parms->C_BAUD;
    IORser->io_WriteLen = parms->C_WLEN;
    IORser->io_StopBits = parms->C_STOP;
    IORser->io_RBufLen	 = BUFFER_LENGTH;

    /* Setup parity bits with validation */
    IORser->io_SerFlags &= ~(SERB_PARTY_ODD & SERB_PARTY_ON);

    switch( parms->C_PARITY ) {
      case C_NO_PARITY:
	break;
      case C_ODD_PARITY:
	IORser->io_SerFlags |= SERB_PARTY_ODD | SERB_PARTY_ON;
	break;
      case C_EVEN_PARITY:
	IORser->io_SerFlags |= SERB_PARTY_ON;
	break;
      default:
	return( c_set_error(C_ERR_PARITY) );
    } /* switch */

    IORser->IOSer.io_Command = SDCMD_SETPARAMS;
    IORser->io_TermArray.TermArray0 = 0x51040303;
    IORser->io_TermArray.TermArray1 = 0x03030303;

    if( DoIO(IORser) )
	return( c_set_error(C_ERR_PARAMS) );

    /* Parameters were changed as needed */
    return( c_set_error(C_ERR_OK) );
} /* c_setup */


/* internal use only!
static short c_getchar( cinput, secs, micros )
    char    *cinput;
    ULONG   secs, micros;
{
    APTR    myptr;
    short   iodone = 0;

    /* Send request for read a character */
    IORser->IOSer.io_Data = (APTR) cinput;
    IORser->IOSer.io_Length = 1;
    IORser->IOSer.io_Command = CMD_READ;
    SendIO( IORser );

    if( CheckIO(IORser) ) {
	Remove( IORser );
	return( c_set_error(C_ERR_OK) );
    } else {
	timeDelayAsync( secs, micros, UNIT_VBLANK, treq );
	WaitPort( SPort );
	while( myptr = (APTR) GetMsg(SPort) ) {
	    if( myptr == (APTR) IORser ) {
		iodone = -1;
	    }
	} /* while */
	if( iodone ) {
	    killTimeDelay( treq );
	    return( c_set_error(C_ERR_OK) );
	}
    }

    /* Abort the requested IO and return error condition */
    AbortIO( IORser );
    Remove( IORser );
    return( c_set_error(C_ERR_GET) );
} /* c_getchar */


short c_getc( cinput )
    char    *cinput;
{
#ifdef GIMME_WIMPY
    if( !(initialized() && channel_open()) )
	return( c_set_error(C_ERR_CHAN) );
    if( !buffer ) {
	return( c_set_error(C_ERR_BADPARM) );
    }
#endif
    return( c_getchar(cinput, BIG_SECS, BIG_MICROS) );
} /* c_getc */


short c_emptyc()
{
    short   err;
    char    cinput;

#ifdef GIMME_WIMPY
    if( !(initialized() && channel_open()) )
	return( c_set_error(C_ERR_CHAN) );
#endif
    /* Empty the buffer */
    while( (err = c_getchar(&cinput, SMALL_SECS, SMALL_MICROS)) == C_ERR_OK ) {
    } /* while */

    /* Check for a buffer empty error and replace with ok status */
    if( err == C_ERR_GET ) {
	c_set_error(err = C_ERR_OK);
    }
    /* Return status of empty */
    return( err );
} /* c_emptyc */


short c_putc( coutput )
    char coutput;
{
#ifdef GIMME_WIMPY
    if( !(initialized() && channel_open()) )
	return( c_set_error(C_ERR_CHAN) );
#endif
    /* Now send character thru channel */
    IORser->IOSer.io_Data = (APTR) &coutput;
    IORser->IOSer.io_Length = 1;
    IORser->IOSer.io_Command = CMD_WRITE;
    if( DoIO(IORser) ) {
	return( c_set_error(C_ERR_PUT) );
    }
    return( c_set_error(C_ERR_OK) );
} /* c_putc */


short c_gets( buffer, num_to_get )
    char    *buffer;
    SHORT   num_to_get;
{
    register SHORT  i;
    short	    error;

#ifdef GIMME_WIMPY
    if( !(initialized() && channel_open()) )
	return( c_set_error(C_ERR_CHAN) );
    if( !buffer ) {
	return( c_set_error(C_ERR_BADPARM) );
    }
#endif
    if( num_to_get <= 0 ) {
	return( c_set_error(C_ERR_ILLEGAL) );
    }

    /* Now get the specified number of characters */
    for( i = num_to_get; --i >= 0; ++buffer ) {
	if( error = c_getchar(buffer, BIG_SECS, BIG_MICROS) ) {
	    return( c_set_error(error) );
	}
    } /* for */

    return( c_set_error(C_ERR_OK) );
} /* c_gets */


short c_getline( buffer, num_to_get )
    char    *buffer;
    SHORT   num_to_get;
{
    register SHORT  i;
    short	    error;

#ifdef GIMME_WIMPY
    if( !(initialized() && channel_open()) )
	return( c_set_error(C_ERR_CHAN) );
    if( !buffer ) {
	return( c_set_error(C_ERR_BADPARM) );
    }
#endif
    if( num_to_get <= 0 ) {
	return( c_set_error(C_ERR_ILLEGAL) );
    }

    /* Now get the specified number of characters */
    for( i = num_to_get; --i >= 0; ++buffer ) {
	if( error = c_getchar(buffer, SMALL_SECS, SMALL_MICROS) ) {
	    *buffer = '\0';
	    return( c_set_error(error) );
	}
	if( *buffer == EOLchar ) {
	    break;
	}
    } /* for */

    return( c_set_error(C_ERR_OK) );
} /* c_getline */


short c_setEOL( character )
    char character;
{
#ifdef GIMME_WIMPY
    if( !(initialized() && channel_open()) )
	return( c_set_error(C_ERR_CHAN) );
#endif
    EOLchar = character;
    return( c_set_error(C_ERR_OK) );
} /* c_setEOL */


short c_puts( buffer, num_to_put )
    char    *buffer;
    SHORT   num_to_put;
{
    short   error;

#ifdef GIMME_WIMPY
    if( !(initialized() && channel_open()) )
	return( c_set_error(C_ERR_CHAN) );
    if( !buffer ) {
	return( c_set_error(C_ERR_BADPARM) );
    }
#endif
    if( num_to_put <= 0 ) {
	return( c_set_error(C_ERR_ILLEGAL) );
    }
    /* Now send the characters thru channel */
    IORser->IOSer.io_Data = (APTR) buffer;
    IORser->IOSer.io_Length = num_to_put;
    IORser->IOSer.io_Command = CMD_WRITE;
    if( DoIO(IORser) ) {
	return( c_set_error(C_ERR_PUT) );
    }
    return( c_set_error(C_ERR_OK) );
} /* c_puts */


short c_close()
{
    short   err;

#ifdef GIMME_WIMPY
    if( !(initialized() && channel_open()) )
	return( c_set_error(C_ERR_CHAN) );
#endif

    if( err = c_emptyc() ) {            /* Empty the buffer */
	return( err );
    }
    /* Now close device and channel */
    CloseDevice( IORser );
    DeleteExtIO( IORser, (ULONG)sizeof(struct IOExtSer) );
    releaseTimer( treq, NULL );         /* Now close timer device */
    SPort = NULL;
    system_state = C_NOT_OPEN;
    return( c_set_error(C_ERR_OK) );
} /* c_close */


short c_done()
{
    if( initialized() ) {
	/* Set system state to channel not open and clear initialized flag */
	Forbid();
	initial = 0;
	system_state = C_NOT_OPEN;
	Permit();
    }
    return( c_set_error(C_ERR_OK) );
} /* c_done */
SHAR_EOF
cat << \SHAR_EOF > copystuff.c
/*
 *  FILE: copystuff.c
 *  Support routines for copying (mainly intuition-type) structures.
 *
 *  Public Domain, but keep my name in it as the original author.
 *  31-Oct-88	Jan Sven Trabandt   split from intuistuff.c
 *				    added more functions
 */


#define I_AM_COPYSTUFF
#include "gimmelib/gimmefuncs.h"
#include "gimmelib/copystuff.h"
#include "gimmelib/intuistuff.h"
#define GIM_BUILTIN
#include "gimmelib/macros.h"


short copyDataImage( data, image )
    USHORT  *data;
    register struct Image   *image;
{
    register struct Image   *ip;
    ULONG   size;		    /* image datasize (bytes) for copying */
    UBYTE   *idata, *srcdata;	    /* UBYTE makes additions easier */

#ifdef GIMME_WIMPY
    if( !data || !image || !image->ImageData ) {
	return( -1 );
    }
#endif
    size = GIM_IMAGESIZE(image->Depth, image->Width, image->Height);
    if( size > 0x07fffL ) {
	idata = (UBYTE *) image->ImageData;
	srcdata = (UBYTE *) data;
	for( ; size > 0L; size -= 0x07fffL ) {
	    movmem( srcdata, idata, (int)(size & 0x07fffL) );
	    srcdata += 0x07fffL;
	    idata += 0x07fffL;
	} /* for */
    } else {
	movmem( data, image->ImageData, (int) size );
    }
    return( 0 );
} /* copyDataImage */


short copyImageData( image, data )
    register struct Image   *image;
    USHORT  *data;
{
    register struct Image   *ip;
    ULONG   size;		    /* image datasize (bytes) for copying */
    UBYTE   *idata, *destdata;	    /* UBYTE makes additions easier */

#ifdef GIMME_WIMPY
    if( !data || !image || !image->ImageData ) {
	return( -1 );
    }
#endif
    size = GIM_IMAGESIZE(image->Depth, image->Width, image->Height);
    if( size > 0x07fffL ) {
	idata = (UBYTE *) image->ImageData;
	destdata = (UBYTE *) data;
	for( ; size > 0L; size -= 0x07fffL ) {
	    movmem( idata, destdata, (int)(size & 0x07fffL) );
	    idata += 0x07fffL;
	    destdata += 0x07fffL;
	} /* for */
    } else {
	movmem( image->ImageData, data, (int) size );
    }
    return( 0 );
} /* copyImageData */


struct Border *copyBorder( mh, oldbp, numbord, myflags )
    void    **mh;
    register struct Border  *oldbp;
    SHORT   numbord;
    ULONG   myflags;
{
    register struct Border  *bp;
    struct Border	    *retbp, *temp;
    ULONG		    size;
    void		    *mymh = NULL;

#ifdef GIMME_WIMPY
    if( !mh ) {
	return( NULL );
    }
#endif
    retbp = bp = NULL;
    for( ; oldbp && numbord != 0; oldbp = oldbp->NextBorder, --numbord ) {
	if( !(temp = chainAllocMem(&mymh, (ULONG)sizeof(struct Border),
				    MEMF_PUBLIC)) ) {
	    if( !(myflags & GCP_SALVAGE) ) {
		chainFreeMem( mymh );
		retbp = NULL;
	    }
	    return( retbp );
	}
	if( !bp ) {
	    retbp = temp;
	} else {
	    bp->NextBorder = temp;
	}
	bp = temp;
	*bp = *oldbp;	    /* struct copy */
	if( oldbp->XY && !(myflags & GCP_NOT_POINTS) ) {
	    size = sizeof(SHORT) * 2L  * bp->Count;
	    if( !(bp->XY = chainAllocMem(&mymh, size, MEMF_PUBLIC)) ) {
		if( !(myflags & GCP_SALVAGE) ) {
		    chainFreeMem( mymh );
		    return( NULL );
		} else {
		    bp->Count = 0;
		}
	    } else {
		movmem( oldbp->XY, bp->XY, (int)size );
	    }
	}
    } /* for */
    linkChainMem( mh, mymh );
    return( retbp );
} /* copyBorder */


struct Image *copyImage( mh, oldip, numimage, myflags )
    void    **mh;
    register struct Image   *oldip;
    SHORT   numimage;
    ULONG   myflags;
{
    register struct Image   *ip;
    struct Image	    *retip, *temp;
    ULONG		    size;
    void		    *mymh = NULL;

#ifdef GIMME_WIMPY
    if( !mh ) {
	return( NULL );
    }
#endif
    retip = ip = NULL;
    for( ; oldip && numimage != 0; oldip = oldip->NextImage, --numimage ) {
	if( !(temp = chainAllocMem(&mymh, (ULONG)sizeof(struct Image),
				    MEMF_PUBLIC)) ) {
	    if( !(myflags & GCP_SALVAGE) ) {
		chainFreeMem( mymh );
		retip = NULL;
	    }
	    return( retip );
	}
	if( !ip ) {
	    retip = temp;
	} else {
	    ip->NextImage = temp;
	}
	ip = temp;
	*ip = *oldip;	    /* struct copy */
	if( oldip->ImageData && !(myflags & GCP_NOT_BYTES) ) {
	    size = GIM_IMAGESIZE(ip->Depth, ip->Width, ip->Height);
	    if( !(ip->ImageData = chainAllocMem(&mymh, size, MEMF_PUBLIC)) ) {
		if( !(myflags & GCP_SALVAGE) ) {
		    chainFreeMem( mymh );
		    return( NULL );
		}
	    } else {
		copyImageData( oldip, ip->ImageData );
	    }
	}
    } /* for */
    linkChainMem( mh, mymh );
    return( retip );
} /* copyImage */


struct IntuiText *copyIntuiText( mh, otext, numitext, myflags )
    void    **mh;
    register struct IntuiText	*otext;
    SHORT   numitext;
    ULONG   myflags;
{
    register struct IntuiText	*itext;
    struct IntuiText		*retitext, *temp;
    ULONG			size;
    void			*mymh = NULL;

#ifdef GIMME_WIMPY
    if( !mh ) {
	return( NULL );
    }
#endif
    retitext = itext = NULL;
    for( ; otext && numitext != 0; otext = otext->NextText, --numitext ) {
	if( !(temp = chainAllocMem(&mymh, (ULONG)sizeof(struct IntuiText),
				    MEMF_PUBLIC)) ) {
	    if( !(myflags & GCP_SALVAGE) ) {
		chainFreeMem( mymh );
		retitext = NULL;
	    }
	    return( retitext );
	}
	if( !itext ) {
	    retitext = temp;
	} else {
	    itext->NextText = temp;
	}
	itext = temp;
	*itext = *otext;       /* struct copy */
	if( otext->IText && !(myflags & GCP_NOT_STRING) ) {
	    size = strlen( otext->IText );
	    if( !(itext->IText = chainAllocMem(&mymh, size, MEMF_PUBLIC)) ) {
		if( !(myflags & GCP_SALVAGE) ) {
		    chainFreeMem( mymh );
		    return( NULL );
		}
	    } else {
		/* strcpy( itext->IText, otext->IText ); */
		movmem( otext->IText, itext->IText, (int) size + 1 );
	    }
	}
	if( otext->ITextFont && !(myflags & GCP_NOT_TEXTATTR) ) {
	    if( !(itext->ITextFont = chainAllocMem(&mymh,
			(ULONG)sizeof(struct TextAttr), MEMF_PUBLIC)) ) {
		if( !(myflags & GCP_SALVAGE) ) {
		    chainFreeMem( mymh );
		    return( NULL );
		}
	    } else {
		*itext->ITextFont = *otext->ITextFont;	    /* struct copy */
	    }
	}
    } /* for */
    linkChainMem( mh, mymh );
    return( retitext );
} /* copyIntuiText */


struct MenuItem *copyMenuItem( mhptr, olditem, numitem, numsub, myflags )
    void			**mhptr;
    register struct MenuItem	*olditem;
    SHORT			numitem, numsub;
    ULONG			myflags;
{
    register struct MenuItem	*item, *temp;
    struct MenuItem		*menuitem = NULL;
    APTR			(*copyfunc)();
    void			*mymh = NULL;

#ifdef GIMME_WIMPY
    if( !mhptr ) {
	return( NULL );
    }
#endif
    item = NULL;
    for( ; olditem && numitem != 0; olditem = olditem->NextItem ) {
	if( !(temp = chainAllocMem(&mymh, (ULONG)sizeof(struct MenuItem),
					    MEMF_PUBLIC)) ) {
	    chainFreeMem( mymh );
	    return( NULL );
	}
	if( !item ) {
	    menuitem = temp;
	} else {
	    item->NextItem = temp;
	}
	item = temp;
	*item = *olditem;	/* struct copy */
	if( !(myflags & GCP_NOT_STRUCTS) ) {
	    if( item->Flags & ITEMTEXT ) {
		(APTR) copyfunc = (APTR) copyIntuiText;
	    } else {
		(APTR) copyfunc = (APTR) copyImage;
	    }
	    if( olditem->ItemFill ) {
		if( !(item->ItemFill = copyfunc(&mymh, olditem->ItemFill,
					    -1, myflags)) ) {
		    chainFreeMem( mymh );
		    return( NULL );
		}
	    }
	    if( (item->Flags & HIGHIMAGE) && olditem->SelectFill ) {
		if( !(item->SelectFill = copyfunc(&mymh, olditem->SelectFill,
					    -1, 0L)) ) {
		    chainFreeMem( mymh );
		    return( NULL );
		}
	    }
	}
	if( numsub != 0 && olditem->SubItem ) {
	    if( !(item->SubItem = copyMenuItem(&mymh,
					olditem->SubItem, numsub, 0)) ) {
		chainFreeMem( mymh );
		return( NULL );
	    }
	} else {
	    item->SubItem = NULL;
	}
    } /* for */
    item->NextItem = NULL;
    if( mymh ) {
	linkChainMem( mhptr, mymh );
    }
    return( menuitem );
} /* copyMenuItem */


struct Menu *copyMenu( mhptr, oldmenu, nummenu, numitem, numsub, myflags )
    void		    **mhptr;
    register struct Menu    *oldmenu;
    SHORT		    nummenu, numitem, numsub;
    ULONG		    myflags;
{
    register struct Menu	*menu, *temp;
    struct Menu 		*menustrip = NULL;
    ULONG			size;
    void			*mymh = NULL;

#ifdef GIMME_WIMPY
    if( !mhptr ) {
	return( NULL );
    }
#endif
    menu = NULL;
    for( ; oldmenu && nummenu != 0; oldmenu = oldmenu->NextMenu, --nummenu ) {
	if( !(temp = chainAllocMem(&mymh, (ULONG)sizeof(struct Menu),
				    MEMF_PUBLIC)) ) {
	    chainFreeMem( mymh );
	    return( NULL );
	}
	if( !menu ) {
	    menustrip = temp;
	} else {
	    menu->NextMenu = temp;
	}
	menu = temp;
	*menu = *oldmenu;	/* struct copy */
	if( menu->MenuName && !(myflags & GCP_NOT_STRING) ) {
	    size = strlen( oldmenu->MenuName );
	    if( !(menu->MenuName = chainAllocMem(&mymh, size, MEMF_PUBLIC)) ) {
		if( !(myflags & GCP_SALVAGE) ) {
		    chainFreeMem( mymh );
		    return( NULL );
		}
	    } else {
		/* strcpy( menu->MenuName, oldmenu->MenuName ); */
		movmem( oldmenu->MenuName, menu->MenuName, (int) size + 1 );
	    }
	}
	if( numitem != 0 && oldmenu->FirstItem ) {
	    if( !(menu->FirstItem = copyMenuItem(&mymh,
			    oldmenu->FirstItem, numitem, numsub, myflags)) ) {
		chainFreeMem( mymh );
		return( NULL );
	    }
	} else {
	    menu->FirstItem = NULL;
	}
    } /* for */
    menu->NextMenu = NULL;
    if( mymh ) {
	linkChainMem( mhptr, mymh );
    }
    return( menustrip );
} /* copyMenu */
SHAR_EOF
cat << \SHAR_EOF > dbuf.c
/*
 *  FILE: dbuf.c
 *  Support routines for converting a single-buffered Intuition screen
 *  into a double-buffered screen and back.
 *
 *  Public Domain, but keep my name in it as the original author.
 *  31-Aug-88	Jan Sven Trabandt   first release version
 */


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


short makeDBuf( screen, bmptr )
    struct Screen   *screen;
    struct BitMap   **bmptr;
{
#ifdef GIMME_WIMPY
    if( !screen || !bmptr ) {
	return( -1 );
    }
#endif
    if( !*bmptr ) {
	*bmptr = gimmeBitMap( screen->BitMap.Depth, screen->Width,
				screen->Height );
	if( !*bmptr ) {
	    return( -1 );
	}
    }
    screen->RastPort.BitMap = *bmptr;	    /* draw to back buffer */
    return( 0 );
} /* makeDBuf */


short unmakeDBuf( 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 );
	swapDBuf( screen, GIM_MINTERM_DEST );
    }
    if( viewbm != screen->RastPort.BitMap ) {
	screen->RastPort.BitMap = viewbm;
    }
    if( bm ) {
	getRidOfBitMap( bm );
    }
    return( 0 );
} /* unmakeDBuf */


short swapDBuf( screen, minterm )
    register struct Screen  *screen;
    SHORT   minterm;
{
    struct BitMap   *bm;

#ifdef GIMME_WIMPY
    if( !screen ) {
	return( -1 );
    }
#endif
    Forbid();
    bm = screen->ViewPort.RasInfo->BitMap;
    if( bm == screen->RastPort.BitMap ) {
	Permit();
	return( 0 );
    }
    screen->ViewPort.RasInfo->BitMap = screen->RastPort.BitMap;
    screen->RastPort.BitMap = bm;
    Permit();
    MakeScreen( screen );
    RethinkDisplay();
    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 );
} /* swapDBuf */
SHAR_EOF
cat << \SHAR_EOF > dbufquick.c
/*
 *  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 */
SHAR_EOF
cat << \SHAR_EOF > dbufvquick.c
/*
 *  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 */
SHAR_EOF
cat << \SHAR_EOF > dualpf.c
/*
 *  FILE: dualpf.c
 *  Support routines for converting a single-playfield Intuition screen
 *  into a dual-playfield screen and back.
 *
 *  Public Domain, but keep my name in it as the original author.
 *  31-Aug-88	Jan Sven Trabandt   first release version
 */


#include "gimmelib/gimmefuncs.h"


short makeDualPlayfield( screen, ri, reldepth )
    struct Screen   *screen;
    struct RasInfo  *ri;
    SHORT	    reldepth;
{
    SHORT   depth;

#ifdef GIMME_WIMPY
    if( !screen ) {
	return( -1 );
    }
#endif
    if( (screen->ViewPort.Modes & DUALPF)
	|| reldepth < -1 || reldepth > 0 || screen->BitMap.Depth > 3 ) {
	return( -1 );
    }
    depth = screen->BitMap.Depth + reldepth;
    if( depth > 3 ) {
	return( -1 );
    }
    ri->BitMap = gimmeBitMap( depth, screen->Width, screen->Height );
    if( !ri->BitMap ) {
	return( -1 );
    }
    ri->Next = NULL;
    ri->RxOffset = 0;
    ri->RyOffset = 0;
    Forbid();
    screen->ViewPort.RasInfo->Next = ri;
    screen->ViewPort.Modes |= DUALPF;
    Permit();
    MakeScreen( screen );
    RethinkDisplay();
    return( 0 );
} /* makeDualPlayfield */


short unmakeDualPlayfield( screen )
    struct Screen   *screen;
{
    struct RasInfo  *ri;
    struct BitMap   *bm;

#ifdef GIMME_WIMPY
    if( !screen ) {
	return( -1 );
    }
#endif
    if( !(screen->ViewPort.Modes & DUALPF) ) {
	return( -1 );
    }
    Forbid();
    ri = screen->ViewPort.RasInfo->Next;
    bm = ri->BitMap;
    ri->BitMap = NULL;
    screen->ViewPort.RasInfo->Next = NULL;
    screen->ViewPort.Modes &= ~(DUALPF | PFBA);
    Permit();
    MakeScreen( screen );
    RethinkDisplay();
    if( bm ) {
	getRidOfBitMap( bm );
    }
    return( 0 );
} /* unmakeDualPlayfield */
SHAR_EOF
cat << \SHAR_EOF > font.c
/*
 *  FILE: font.c
 *  Support routines for accessign ROM or disk-based fonts.
 *
 *  Public Domain, but keep my name in it as the original author.
 *  31-Aug-88	Jan Sven Trabandt   first release version
 *  30-Sep-88	Jan Sven Trabandt   gimmeFont now alters given TextAttr
 *  31-Oct-88	Jan Sven Trabandt   added gimmeFontLazy
 */


#include "gimmelib/gimmefuncs.h"


struct TextFont *gimmeFont( textattr )
    struct TextAttr *textattr;
{
    struct TextFont *tf;

#ifdef GIMME_WIMPY
    if( !textattr ) {
	return( NULL );
    }
#endif
    tf = OpenDiskFont( textattr );
    if( tf ) {
	textattr->ta_YSize = tf->tf_YSize;
	textattr->ta_Style = tf->tf_Style;
    }
    return( tf );
} /* gimmeFont */


struct TextFont *gimmeFontLazy( name, size )
    UBYTE   *name;
    UWORD   size;
{
    struct TextAttr ta;

#ifdef GIMME_WIMPY
    if( !name ) {
	return( NULL );
    }
#endif
    ta.ta_Name = (STRPTR) name;
    ta.ta_YSize = size;
    ta.ta_Style = FS_NORMAL;
    ta.ta_Flags = FPF_DISKFONT;
    return( OpenDiskFont(&ta) );
} /* gimmeFontLazy */


short getRidOfFont( textfont )
    struct TextFont *textfont;
{
#ifdef GIMME_WIMPY
    if( !textfont ) {
	return( -1 );
    }
#endif
    CloseFont( textfont );
    return( 0 );
} /* getRidOfFont */
SHAR_EOF
cat << \SHAR_EOF > gadget.c
/*
 *  FILE: gadget.c
 *  Support routines for creating and dealing with gadgets.
 *
 *  Public Domain, but keep my name in it as the original author.
 *  31-Aug-88	Jan Sven Trabandt   first release version
 *  30-Sep-88	Jan Sven Trabandt   enhanced routines
 *				    renamed getRidOfGadget to getRidOfGadgets
 *  31-Oct-88	Jan Sven Trabandt   keep up with clearGadgets change
 *				    moved toggleBoolGadget to gadgstuff.c
 */


#define I_AM_GADGET
#include "gimmelib/gimmefuncs.h"
#include "gimmelib/gadget.h"
#include "gimmelib/postext.h"
#include <graphics/gfxbase.h>
#define GIM_BUILTIN
#include "gimmelib/macros.h"

extern struct GfxBase *GfxBase;

/* one undo buffer is safe for several string gadgets since under Intuition
 * only one string gadget can be truly active at any time (see manual)
static UBYTE defaultUndoBuffer[GIM_DFLT_UNDO_BUF_SIZE];


short getRidOfGadgets( gp )
    register struct Gadget  *gp;
{
    struct Gadget   *temp;

    while( gp ) {
	temp = gp->NextGadget;
	if( gp->UserData ) {
	    chainFreeMem( gp->UserData );
	}
	gp = temp;
    } /* while */
    return( 0 );
} /* getRidOfGadgets */


struct Gadget *gimmeBoolGadget( window, id, left, top, xsize, ysize, s, s2,
				    textattr, myflags )
    struct Window   *window;
    USHORT	    id;
    SHORT	    left, top;
    register SHORT  xsize, ysize;
    UBYTE	    *s, *s2;
    struct TextAttr *textattr;
    ULONG	    myflags;
{
    register struct Gadget  *gp;
    struct IntuiText	    *itp, *spitp;
    struct Border	    *bp;
    UBYTE   *spstr;
    void    *gadgmh = NULL;
    SHORT   wid, tempwid, maxlen;
    BYTE    fpen, bpen, drawmode, pad;
    SHORT   i;

    GUESS
	QUIF( !id );
	QUIF( !s );

	gp = chainAllocMem( &gadgmh, (ULONG)sizeof(struct Gadget),
				MEMF_CLEAR | MEMF_PUBLIC );
	QUIF( !gp );
	itp = gimmeIntuiText( &gadgmh, s, textattr, 0 );
	QUIF( !itp );
	if( window ) {
	    if( (fpen = window->RPort->FgPen) == (BYTE)(-1) ) {
		fpen = 1;
	    }
	    if( (bpen = window->RPort->BgPen) == (BYTE)(-1) ) {
		bpen = 0;
	    }
	    drawmode = window->RPort->DrawMode;
	    itp->FrontPen = fpen;
	    itp->BackPen = bpen;
	    itp->DrawMode = drawmode;
	}
	wid = IntuiTextLength( itp ) + (HORIZ_SPACE << 1);
	itp->LeftEdge = HORIZ_SPACE - AROUND_SPACE;
	itp->TopEdge = AROUND_SPACE;
	gp->GadgetText = itp;
	if( s2 ) {                      /* toggle type desired */
	    itp = gimmeIntuiText( &gadgmh, s2, textattr, 0 );
	    QUIF( !itp );
	    tempwid = IntuiTextLength( itp ) + (HORIZ_SPACE << 1);
	    itp->LeftEdge = HORIZ_SPACE - AROUND_SPACE;
	    itp->TopEdge = AROUND_SPACE;
	    if( window ) {
		itp->FrontPen = fpen;
		itp->BackPen = bpen;
		itp->DrawMode = drawmode;
	    }
	    spitp = gimmeIntuiText( &gadgmh, " ", textattr, 0 );
	    QUIF( !spitp );
	    if( window ) {
		spitp->FrontPen = fpen;
		spitp->BackPen = bpen;
		spitp->DrawMode = drawmode;
	    }
	    if( tempwid > wid ) {           /* second string is longer */
		gp->GadgetText->LeftEdge += (tempwid - wid) >> 1;
		wid = tempwid;
		maxlen = (wid - (HORIZ_SPACE << 1)) / IntuiTextLength( spitp );
		*spitp = *itp;		/* struct copy */
		spitp->NextText = gp->GadgetText;
		gp->GadgetText = spitp;
		gp->SelectRender = (APTR) itp;
	    } else {
		itp->LeftEdge += (wid - tempwid) >> 1;
		maxlen = (wid - (HORIZ_SPACE << 1)) / IntuiTextLength( spitp );
		*spitp = *(gp->GadgetText);         /* struct copy */
		spitp->NextText = itp;
		gp->SelectRender = (APTR) spitp;
	    }
	    spstr = (UBYTE *) chainAllocMem( &gadgmh,
			    (LONG)((maxlen+1) * sizeof(UBYTE)), MEMF_PUBLIC );
	    QUIF( !spstr );
	    spstr[maxlen] = '\0';
	    for( i = maxlen; --i >= 0; ) {
		spstr[i] = ' ';
	    } /* for */
	    spitp->IText = spstr;
	    /* use SelectRender since not using GADGHIMAGE so it's safe */
	    gp->Flags = GADGHNONE;
	    gp->Activation = GADGIMMEDIATE | TOGGLESELECT;
	} else {
	    gp->Flags = GADGHCOMP;
	    gp->Activation = RELVERIFY;
	}
	if( xsize <= 0 ) {
	    xsize = wid;
	}
	if( ysize <= 0 ) {
	    if( textattr ) {
		ysize = textattr->ta_YSize;
	    } else if( window ) {
		ysize = window->RPort->TxHeight;
	    } else {
		ysize = GfxBase->DefaultFont->tf_YSize;
	    }
	    ysize += VERT_SPACE << 1;
	}

	if( xsize == wid ) {            /* if xsize was exact or <= 0 */
	    tempwid = -wid;
	} else {
	    tempwid = xsize - wid;
	    if( !(myflags & GPT_FULLWIDTH) ) {
		xsize -= tempwid;
	    }
	}
	switch( myflags & GPT_XFLAGS ) {
	  case GPT_XCENTRE:
	    left += tempwid >> 1;
	    break;
	  case GPT_XRIGHT:	    /* right-align if width was given */
	    left += tempwid;
	  case GPT_XLEFT:
	  default:
	    break;
	} /* switch */

	switch( myflags & GPT_YFLAGS ) {
	  case GPT_YBOTTOM:
	    top -= ysize;
	    break;
	  case GPT_YCENTRE:
	  case GPT_YCENTREBASE:     /* approx */
	    top -= ysize >> 1;
	    break;
	  case GPT_YBASELINE:	    /* approx */
	    top -= ysize - (VERT_SPACE << 1);
	    break;
	  case GPT_YTOP:
	  default:
	    break;
	} /* switch */
	gp->LeftEdge = left + AROUND_SPACE;
	gp->TopEdge = top + AROUND_SPACE;
	gp->Width = xsize - (AROUND_SPACE << 1);
	gp->Height = ysize - (AROUND_SPACE << 1);
	bp = gimmeBorder( &gadgmh, xsize, ysize );
	QUIF( !bp );
	bp->LeftEdge = - AROUND_SPACE;
	bp->TopEdge = - AROUND_SPACE;
	if( window ) {
	    bp->FrontPen = fpen;
	    bp->BackPen = bpen;
	    bp->DrawMode = drawmode;
	}
	gp->GadgetType = BOOLGADGET;
	gp->GadgetRender = (APTR) bp;
	if( window ) {
	    if( window->Flags & GIMMEZEROZERO ) {
		gp->GadgetType |= GZZGADGET;
	    }
	}
	gp->GadgetID = id;
	gp->UserData = gadgmh;
	return( gp );
    ENDGUESS
    if( gadgmh ) {
	chainFreeMem( gadgmh );
    }
    return( NULL );
} /* gimmeBoolGadget */


struct Gadget *gimmeBoolImageGadget( window, id, left, top, depth, width,
					height, myflags, dep2, wid2, ht2 )
    struct Window   *window;
    USHORT	    id;
    SHORT	    left, top;
    SHORT	    depth, width, height;
    ULONG	    myflags;
    SHORT	    dep2, wid2, ht2;
{
    register struct Gadget  *gp;
    UBYTE   *spstr;
    void    *gadgmh = NULL;

    GUESS
	QUIF( !id );

	gp = chainAllocMem( &gadgmh, (ULONG)sizeof(struct Gadget),
				MEMF_CLEAR | MEMF_PUBLIC );
	QUIF( !gp );
	gp->GadgetRender = (APTR) gimmeImage( &gadgmh, depth, width, height );
	QUIF( !gp->GadgetRender );
	if( dep2 > 0 && wid2 > 0 && ht2 > 0 ) {
	    gp->SelectRender = (APTR) gimmeImage( &gadgmh, dep2, wid2, ht2 );
	    QUIF( !gp->SelectRender );
	    gp->Flags = GADGIMAGE | GADGHIMAGE;
	    gp->Activation = GADGIMMEDIATE | TOGGLESELECT;
	} else {
	    gp->Flags = GADGIMAGE | GADGHCOMP;
	    gp->Activation = RELVERIFY;
	}
	switch( myflags & GPT_XFLAGS ) {
	  case GPT_XCENTRE:
	    left -= width >> 1;
	    break;
	  case GPT_XRIGHT:
	    left -= width;
	  case GPT_XLEFT:
	  default:
	    break;
	} /* switch */
	switch( myflags & GPT_YFLAGS ) {
	  case GPT_YBOTTOM:
	  case GPT_YBASELINE:	    /* no "real" meaning, so use bottom */
	    top -= height;
	    break;
	  case GPT_YCENTRE:
	  case GPT_YCENTREBASE:     /* no "real" meaning, so use centre */
	    top -= height >> 1;
	    break;
	  case GPT_YTOP:
	  default:
	    break;
	} /* switch */
	gp->LeftEdge = left;
	gp->TopEdge = top;
	gp->Width = width;
	gp->Height = height;
	gp->GadgetType = BOOLGADGET;
	if( window && (window->Flags & GIMMEZEROZERO) ) {
	    gp->GadgetType |= GZZGADGET;
	}
	gp->GadgetID = id;
	gp->UserData = gadgmh;
	return( gp );
    ENDGUESS
    if( gadgmh ) {
	chainFreeMem( gadgmh );
    }
    return( NULL );
} /* gimmeBoolImageGadget */


struct Gadget *gimmePropGadget( window, id, left, top, xsize, ysize, label,
				textattr, activflags, propflags )
    struct Window   *window;
    USHORT	    id;
    SHORT	    left, top, xsize, ysize;
    UBYTE	    *label;
    struct TextAttr *textattr;
    ULONG	    activflags, propflags;
{
    register struct Gadget  *gp;
    SHORT   len;
    BYTE    fpen, bpen;
    void    *gadgmh = NULL;

    GUESS
	QUIF( !id );
	gp = chainAllocMem( &gadgmh, (ULONG)sizeof(struct Gadget),
				MEMF_CLEAR | MEMF_PUBLIC );
	QUIF( !gp );
	gp->SpecialInfo = (APTR) gimmePropInfo( &gadgmh, propflags );
	QUIF( !gp->SpecialInfo );
	gp->LeftEdge = left;
	gp->TopEdge = top;
	if( label ) {
	    gp->GadgetText = gimmeIntuiText( &gadgmh, label, textattr, 0 );
	    QUIF( !gp->GadgetText );
	    len = IntuiTextLength( gp->GadgetText ) + HORIZ_SPACE;
	    gp->GadgetText->LeftEdge = -len;
	    gp->LeftEdge += len;
	    gp->GadgetText->FrontPen = 1;
	    gp->GadgetText->BackPen = 0;
	    if( window ) {
		if( (fpen = window->RPort->FgPen) != (BYTE)(-1) ) {
		    gp->GadgetText->FrontPen = fpen;
		}
		if( (bpen = window->RPort->BgPen) != (BYTE)(-1) ) {
		    gp->GadgetText->BackPen = bpen;
		}
		gp->GadgetText->DrawMode = window->RPort->DrawMode;
	    }
	}
	gp->Width = xsize;
	gp->Height = ysize;
	gp->Flags = GADGHCOMP | GADGIMAGE;
	gp->Activation = RELVERIFY | activflags;
	gp->GadgetType = PROPGADGET;
	gp->GadgetRender = chainAllocMem( &gadgmh, (ULONG)sizeof(struct Image),
					    MEMF_CLEAR | MEMF_PUBLIC );
	QUIF( !gp->GadgetRender );
	if( window && (window->Flags & GIMMEZEROZERO) ) {
	    gp->GadgetType |= GZZGADGET;
	}
	gp->GadgetID = id;
	gp->UserData = gadgmh;
	return( gp );
    ENDGUESS
    if( gadgmh ) {
	chainFreeMem( gadgmh );
    }
    return( NULL );
} /* gimmePropGadget */


struct PropInfo *gimmePropInfo( mh, flags )
    void    **mh;
    ULONG   flags;
{
    register struct PropInfo	*pip;

    pip = chainAllocMem( mh, (ULONG)sizeof(struct PropInfo),
			    MEMF_PUBLIC | MEMF_CLEAR );
    if( pip ) {
	pip->Flags = AUTOKNOB | flags;
	pip->HorizBody = 1;
	pip->VertBody = 1;
    }
    return( pip );
} /* gimmePropInfo */


struct Gadget *gimmeStringGadget( window, id, left, top, width, maxbuf,
				    initstr, label, textattr, activflags )
    struct Window   *window;
    USHORT	    id;
    SHORT	    left, top, width;
    SHORT	    maxbuf;
    UBYTE	    *initstr, *label;
    struct TextAttr *textattr;
    ULONG	    activflags;
{
    register struct Gadget  *gp;
    struct Border   *bp;
    SHORT   xsize, ysize;
    SHORT   len;
    BYTE    fpen, bpen, drawmode, pad;
    void    *gadgmh = NULL;

    GUESS
	QUIF( !id );
	gp = chainAllocMem( &gadgmh, (ULONG)sizeof(struct Gadget),
				MEMF_CLEAR | MEMF_PUBLIC );
	QUIF( !gp );
	gp->SpecialInfo = (APTR) gimmeStringInfo( &gadgmh, maxbuf, initstr,
						    activflags );
	QUIF( !gp->SpecialInfo );
	if( window ) {
	    if( (fpen = window->RPort->FgPen) == (BYTE)(-1) ) {
		fpen = 1;
	    }
	    if( (bpen = window->RPort->BgPen) == (BYTE)(-1) ) {
		bpen = 0;
	    }
	    drawmode = window->RPort->DrawMode;
	}
	if( textattr ) {
	    ysize = textattr->ta_YSize;
	} else if( window ) {
	    ysize = window->WScreen->Font->ta_YSize;
	} else {
	    ysize = GfxBase->DefaultFont->tf_YSize;
	}
	ysize += VERT_SPACE << 1;
	gp->LeftEdge = left + HORIZ_SPACE;
	gp->TopEdge = top + VERT_SPACE;
	if( label ) {
	    gp->GadgetText = gimmeIntuiText( &gadgmh, label, textattr, 0 );
	    QUIF( !gp->GadgetText );
	    len = IntuiTextLength( gp->GadgetText ) + (HORIZ_SPACE << 1);
	    gp->GadgetText->LeftEdge = -len;
	    if( window ) {
		gp->GadgetText->FrontPen = fpen;
		gp->GadgetText->BackPen = bpen;
		gp->GadgetText->DrawMode = drawmode;
	    }
	    width -= len;
	    gp->LeftEdge += len - HORIZ_SPACE;
	}
	gp->Width = width - HORIZ_SPACE - 1;
	gp->Height = ysize - VERT_SPACE - 1;
	bp = gimmeBorder( &gadgmh, width, ysize );
	/* QUIF( !bp ); */
	bp->LeftEdge = - HORIZ_SPACE;
	bp->TopEdge = - VERT_SPACE;
	if( window ) {
	    bp->FrontPen = fpen;
	    bp->BackPen = bpen;
	    bp->DrawMode = drawmode;
	}
	gp->Flags = GADGHCOMP;
	gp->Activation = RELVERIFY | activflags;
	gp->GadgetType = STRGADGET;
	gp->GadgetRender = (APTR) bp;
	if( window && (window->Flags & GIMMEZEROZERO) ) {
	    gp->GadgetType |= GZZGADGET;
	}
	gp->GadgetID = id;
	gp->UserData = gadgmh;
	return( gp );
    ENDGUESS
    if( gadgmh ) {
	chainFreeMem( gadgmh );
    }
    return( NULL );
} /* gimmeStringGadget */


struct StringInfo *gimmeStringInfo( mh, bufsize, s, flags )
    void    **mh;
    SHORT   bufsize;
    UBYTE   *s;
    ULONG   flags;
{
    register struct StringInfo	*sip;
    UBYTE   tempchar;
    short   len;
    void    *mymh = NULL;

    GUESS
	sip = chainAllocMem( &mymh, (ULONG)sizeof(struct StringInfo),
				MEMF_PUBLIC | MEMF_CLEAR );
	QUIF( !sip );
	sip->Buffer = chainAllocMem( &mymh, (LONG) bufsize,
					MEMF_PUBLIC | MEMF_CLEAR );
	QUIF( !sip->Buffer );
	if( bufsize <= GIM_DFLT_UNDO_BUF_SIZE ) {
	    sip->UndoBuffer = defaultUndoBuffer;
	} else {
	    sip->UndoBuffer = chainAllocMem( &mymh, (LONG) bufsize,
					MEMF_PUBLIC | MEMF_CLEAR );
	    QUIF( !sip->UndoBuffer );
	}
	sip->MaxChars = bufsize--;
	len = strlen( s );
	--bufsize;
	if( len > bufsize ) {           /* make sure string not too long */
	    tempchar = s[bufsize];
	    s[bufsize] = '\0';
	}
	strcpy( sip->Buffer, s );
	if( len > bufsize ) {
	    s[bufsize] = tempchar;
	}
	if( flags & LONGINT ) {
	    sip->LongInt = atol( s );
	}
	linkChainMem( mh, mymh );
	return( sip );
    ENDGUESS
    if( mymh ) {
	chainFreeMem( mymh );
    }
    return( NULL );
} /* gimmeStringInfo */
SHAR_EOF
cat << \SHAR_EOF > gadgstuff.c
/*
 *  FILE: gadgstuff.c
 *  Support routines for dealing with gadgets.
 *
 *  Public Domain, but keep my name in it as the original author.
 *  31-Aug-88	Jan Sven Trabandt   first release version
 *  30-Sep-88	Jan Sven Trabandt   split from gadget.c (and improved)
 *				    renamed clearGadget to clearGadgets
 *  31-Oct-88	Jan Sven Trabandt   removed addGadgets, removeGadgets
 *				      since system AddGList, RemoveGList exists
 *				    changed order of clearGadgets parms to
 *				      match RefreshGadgets more closely
 *				    moved toggleBoolGadget from gadget.c
 */


#define I_AM_GADGSTUFF
#include "gimmelib/gimmefuncs.h"


short clearGadgets( gp, window, req, numgad )
    struct Gadget	*gp;
    struct Window	*window;
    struct Requester	*req;
    SHORT		numgad;
{
    register struct Image   *ip;
    struct RastPort	    *rp;
    APTR		    temp;
    register SHORT	    pick, onoff;    /* use as front/back as well */
    SHORT		    left, top;
    SHORT		    propborder;
    struct Image	    image;
    struct IntuiText	    itext;
    BYTE		    backpen;

#ifdef GIMME_WIMPY
    if( !window ) {
	return( -1 );
    }
#endif
    rp = window->RPort;
    if( gp && !(gp->GadgetType & REQGADGET) ) {
	req = NULL;
    }
    if( req ) {
	backpen = req->BackFill;
	if( req->ReqLayer && req->ReqLayer->rp ) {
	    rp = req->ReqLayer->rp;
	}
    } else if( (backpen = window->RPort->BgPen) == -1 ) {
	backpen = 0;
    }
    for( ; gp && numgad != 0; gp = gp->NextGadget, --numgad ) {
	left = gp->LeftEdge;
	if( gp->Flags & GRELRIGHT ) {
	    left += (req ? req->Width : window->Width) - 1;
	}
	top = gp->TopEdge;
	if( gp->Flags & GRELBOTTOM ) {
	    top += (req ? req->Height : window->Height) - 1;
	}
	propborder = 0;
	if( (gp->GadgetType & ~GADGETTYPE) == PROPGADGET ) {
	    if( !(((struct PropInfo *)gp->SpecialInfo)->Flags
					    & PROPBORDERLESS) ) {
		propborder = 1;
	    }
	}
	if( (gp->Flags & SELECTED) && (gp->Flags & GADGHIMAGE)
		&& gp->SelectRender ) {
	    (APTR) ip = gp->SelectRender;
	} else {
	    (APTR) ip = gp->GadgetRender;
	}
	if( gp->Flags & GADGIMAGE ) {
	    while( ip ) {
		if( propborder ) {
		    ip->LeftEdge += 4;
		    ip->TopEdge += 2;
		}
		pick = ip->PlanePick;
		onoff = ip->PlaneOnOff;
		ip->PlanePick = 0x0;
		ip->PlaneOnOff = backpen;
		temp = (APTR) ip->NextImage;
		ip->NextImage = NULL;
		DrawImage( rp, ip, (long) left, (long) top );
		ip->NextImage = (struct Image *) temp;
		ip->PlanePick = pick;
		ip->PlaneOnOff = onoff;
		if( propborder ) {
		    ip->LeftEdge -= 4;
		    ip->TopEdge -= 2;
		}
		ip = (struct Image *) temp;
	    } /* while */
	} else {			/* else it's a border */
	    while( (struct Border *) ip ) {
		if( propborder ) {
		    ((struct Border *)ip)->LeftEdge += 4;
		    ((struct Border *)ip)->TopEdge += 2;
		}
		pick = ((struct Border *)ip)->FrontPen;
		onoff = ((struct Border *)ip)->BackPen;
		((struct Border *)ip)->FrontPen = backpen;
		((struct Border *)ip)->BackPen = backpen;
		temp = (APTR) ((struct Border *)ip)->NextBorder;
		((struct Border *)ip)->NextBorder = NULL;
		DrawBorder( rp, (struct Border *) ip, (long) left, (long) top );
		((struct Border *)ip)->NextBorder = (struct Border *) temp;
		((struct Border *)ip)->FrontPen = pick;
		((struct Border *)ip)->BackPen = onoff;
		if( propborder ) {
		    ((struct Border *)ip)->LeftEdge -= 4;
		    ((struct Border *)ip)->TopEdge -= 2;
		}
		(struct Border *)ip = (struct Border *) temp;
	    } /* while */
	}
	(struct IntuiText *) ip = gp->GadgetText;
	while( (struct IntuiText *) ip ) {
	    pick = ((struct IntuiText *)ip)->FrontPen;
	    onoff = ((struct IntuiText *)ip)->BackPen;
	    ((struct IntuiText *)ip)->FrontPen = backpen;
	    ((struct IntuiText *)ip)->BackPen = backpen;
	    temp = (APTR) ((struct IntuiText *)ip)->NextText;
	    ((struct IntuiText *)ip)->NextText = NULL;
	    PrintIText( rp, (struct IntuiText *) ip, (long) left, (long) top );
	    ((struct IntuiText *)ip)->NextText = (struct IntuiText *) temp;
	    ((struct IntuiText *)ip)->FrontPen = pick;
	    ((struct IntuiText *)ip)->BackPen = onoff;
	    (struct IntuiText *)ip = (struct IntuiText *) temp;
	} /* while */
	    /* the actual strgadget string is rendered in the screen's font
	     * but initially using Screen->BarLayer->rp->Font
	     */
/*****
	if( (gp->GadgetType & ~GADGETTYPE) == STRGADGET ) {
	    sip = (struct StringInfo *) gp->SpecialInfo;
	    itext.BackPen = itext.FrontPen = backpen;
	    itext.DrawMode = JAM2;
	    itext.TopEdge = itext.LeftEdge = 0;
	    itext.ITextFont = window->WScreen->Font;
	    itext.IText = &sip->Buffer[sip->DispPos];
	    tempchar = itext.IText[sip->DispCount];
	    itext.IText[sip->DispCount] = '\0';
	    itext.NextText = NULL;
	    PrintIText( rp, &itext, (long) sip->CLeft, (long) sip->CTop );
	    itext.IText[sip->DispCount] = tempchar;
	}
*****/
	if( (gp->GadgetType & ~GADGETTYPE) == PROPGADGET
		|| (gp->GadgetType & ~GADGETTYPE) == STRGADGET ) {
	    image.LeftEdge = 0;
	    image.TopEdge = 0;
	    image.Width = gp->Width;
	    if( gp->Flags & GRELWIDTH ) {
		image.Width += req ? req->Width : window->Width;
	    }
	    image.Height = gp->Height;
	    if( gp->Flags & GRELHEIGHT ) {
		image.Height += req ? req->Height : window->Height;
	    }
	    image.Depth = 0;
	    image.ImageData = NULL;
	    image.PlanePick = 0;
	    image.PlaneOnOff = backpen;
	    image.NextImage = NULL;
	    DrawImage( rp, &image, (long) left, (long) top );
	}
    } /* for */
    return( 0 );
} /* clearGadgets */


short toggleBoolGadget( window, gp, req )
    struct Window	    *window;
    register struct Gadget  *gp;
    struct Requester	    *req;
{
    APTR	    temp;
    USHORT	    pos;
    SHORT	    pick, onoff;

#ifdef GIMME_WIMPY
    if( !window || !gp ) {
	return( -1 );
    }
#endif
    if( (gp->GadgetType & ~GADGETTYPE) != BOOLGADGET ) {
	return( 0 );
    }
    if( (pos = RemoveGadget(window, gp)) == (USHORT) -1 ) {
	return( -1 );
    }
    gp->NextGadget = NULL;
    if( gp->Flags & GADGIMAGE ) {
	clearGadgets( gp, window, req, 1 );
	temp = gp->GadgetRender;
	gp->GadgetRender = gp->SelectRender;
	gp->SelectRender = temp;
	gp->Width = ((struct Image *)gp->GadgetRender)->Width;
	gp->Height = ((struct Image *)gp->GadgetRender)->Height;
    } else {
	temp = (APTR) gp->GadgetText;
	gp->GadgetText = (struct IntuiText *) gp->SelectRender;
	gp->SelectRender = temp;
    }
    gp->Flags &= ~SELECTED;
    AddGList( window, gp, (long) pos, 1L, req );
    RefreshGList( gp, window, req, 1L );
    return( 0 );
} /* toggleBoolGadget */


struct Gadget *findGadget( gp, id )
    register struct Gadget  *gp;
    USHORT  id;
{
    for( ; gp; gp = gp->NextGadget ) {
	if( gp->GadgetID == id ) {
	    break;
	}
    } /* for */
    return( gp );
} /* findGadget */


struct Gadget *findMyFirstGadget( gp, id )
    register struct Gadget  *gp;
    USHORT  id;
{
    for( ; gp; gp = gp->NextGadget ) {
	if( gp->GadgetID > id ) {
	    break;
	}
    } /* for */
    return( gp );
} /* findMyFirstGadget */
SHAR_EOF
#	End of shell archive
exit 0
-- 
Bob Page, U of Lowell CS Dept.  page@swan.ulowell.edu  ulowell!page
Have five nice days.