page@swan.ulowell.edu (Bob Page) (12/02/88)
Submitted-by: oscvax!jan@uunet.UU.NET (Jan Sven Trabandt) Posting-number: Volume 2, Issue 79 Archive-name: libraries/gimme.6 # 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: # picture.c # postext.c # requester.c # screen.c # scrollbar.c # sound.c # stdstuff.c # subtask.c # subtinit.c # timer.c # timerstuff.c # window.c # This archive created: Thu Dec 1 19:52:33 1988 cat << \SHAR_EOF > picture.c /* * FILE: picture.c * Support routines for reading IFF/ILBM files. * * Public Domain, but keep our names in it as the original authors. * 08-Dec-87 Rico Mariani original code (modified by JST) * 31-Aug-88 Jan Sven Trabandt first release version */ #define I_AM_PICTURE #include "gimmelib/gimmefuncs.h" #include "gimmelib/picture.h" #include "gimmelib/postext.h" #include "gimmelib/minterm.h" #include <stdio.h> #define GET(iffile) getc( iffile ) #define getId getLong #define getLen getLong #define getByte GET #define skip(len, file) fseek(file, (long)(len), 1) #define getBMH(bmh, file) fread(bmh, sizeof(BitMapHeader), 1, file) /* requires an existent variable 'char *errmsg' and a label 'failure_return' */ #define fail_and_return(msg) {errmsg = msg; goto failure_return;} /* forward declarations */ static LONG getLong(); static WORD getWord(); static ULONG makeBM(); static char noMemMsg[] = "insufficient memory\n"; static char badFileMsg[] = "corrupt or incomplete file\n"; PICTURE *gimmePicture( filename, myflags ) UBYTE *filename; ULONG myflags; { LONG len, id; PICTURE *pic = NULL; BYTE *p; void *mh = NULL; FILE *file = NULL; char *errmsg = " "; SHORT i; if( !(file = fopen(filename, "r")) ) { fail_and_return( "unable to open iff picture file for read\n" ); } if( getId(file) != ID_FORM ) { fail_and_return( "not IFF format\n" ); } getLen( file ); if( getId(file) != ID_ILBM ) { fail_and_return( "not ILBM format\n" ); } for( ;; ) { getChunk( &id, &len, file ); if( ferror(file) || feof(file) ) { fail_and_return( badFileMsg ); } switch( id ) { case ID_BMHD: pic = chainAllocMem( &mh, (ULONG)sizeof(PICTURE), MEMF_PUBLIC | MEMF_CLEAR ); if( !pic ) { fail_and_return( noMemMsg ); } getBMH( &pic->bmh, file ); if( len & 1 ) { GET(file); } break; case ID_CMAP: if( getLut(pic, len, file) ) { fail_and_return( "unable to get color table\n" ); } break; case ID_BODY: if( !pic ) { fail_and_return( "didn't find BMHD chunk\n" ); return( NULL ); } switch( pic->bmh.masking ) { case mskNone: case mskLasso: case mskHasTranCol: break; default: printf("Error, unsupported masking type\n"); return( NULL ); } /* switch */ pic->xsize = pic->bmh.w; if( (pic->myflags = makeBM(pic, myflags)) == GBP_ERROR ) { return( NULL ); } switch( pic->bmh.compression ) { case cmpNone: if( getBody(pic->bm, pic->myflags, file) ) { fail_and_return( "error in uncompressed body\n" ); } break; case cmpByteRun1: if( getCmpBody(pic->bm, file) ) { fail_and_return( "error in compressed body\n" ); } break; default: fail_and_return( "unknown compression form\n" ); return( NULL ); } /* switch */ if( ferror(file) ) { fail_and_return( badFileMsg ); } pic->memhead = mh; fclose( file ); return( pic ); break; case ID_DEST: case ID_SPRT: case ID_CAMG: case ID_CRNG: case ID_CCRT: default: /* unimplemented chunk type */ skip( EVEN(len), file ); break; } /* switch */ } /* for */ failure_return: {} if( Output() ) { Write( Output(), errmsg, (ULONG)strlen(errmsg) ); } if( mh ) { chainFreeMem( mh ); } if( file ) { fclose( file ); } return( NULL ); } /* gimmePicture */ static ULONG makeBM( pic, myflags ) register PICTURE *pic; ULONG myflags; { UBYTE *plane; if( !(pic->bm = AllocMem((ULONG)sizeof(struct BitMap), MEMF_PUBLIC)) ) { return( GBP_ERROR ); } InitBitMap( pic->bm, (long) pic->bmh.nPlanes, (long) pic->bmh.w, (long) pic->bmh.h ); return( gimmeBitPlanes(pic->bm, myflags) ); } /* makeBM */ short getRidOfPicture( picture ) PICTURE *picture; { #ifdef GIMME_WIMPY if( picture ) { return( -1 ); } #endif if( picture->colormap.ColorTable ) { FreeMem( picture->colormap.ColorTable, (ULONG) picture->colormap.Count * sizeof(USHORT) ); } if( picture->bm ) { getRidOfBitPlanes( picture->bm, picture->myflags ); FreeMem( picture->bm, (ULONG)sizeof(struct BitMap) ); } chainFreeMem( picture->memhead ); return( 0 ); } /* getRidOfPicture */ short positionPicture( rp, myflags, pic, minterm, x, y ) struct RastPort *rp; ULONG myflags; PICTURE *pic; SHORT minterm; register SHORT x, y; { SHORT left, top; SHORT width, height; SHORT temp; struct BitMap *bm; #ifdef GIMME_WIMPY if( !pic || !rp ) { return( -1 ); } #endif left = top = 0; width = pic->bmh.w; height = pic->bmh.h; bm = rp->BitMap; switch( myflags & GPT_XFLAGS ) { case GPT_XCENTRE: x -= width >> 1; break; case GPT_XRIGHT: x -= width; break; case GPT_XLEFT: default: break; } /* switch */ switch( myflags & GPT_YFLAGS ) { case GPT_YBOTTOM: case GPT_YBASELINE: y -= height; break; case GPT_YCENTRE: case GPT_YCENTREBASE: y -= height >> 1; break; case GPT_YTOP: default: break; } /* switch */ if( minterm != GIM_MINTERM_DEST ) { if( x < 0 ) { width += x; left -= x; x = 0; } else if( (temp = x + width - (bm->BytesPerRow << 3)) > 0 ) { width -= temp; } if( y < 0 ) { height += y; top -= y; y = 0; } else if( (temp = y + height - bm->Rows) > 0 ) { height -= temp; } if( width > 0 && height > 0 ) { BltBitMapRastPort( pic->bm, (long) left, (long) top, rp, (long) x, (long) y, (long) width, (long) height, (long) minterm ); } } return( 0 ); } /* positionPicture */ short usePictureColors( pic, screen ) register PICTURE *pic; struct Screen *screen; { #ifdef GIMME_WIMPY if( !pic || !screen ) { return( -1 ); } #endif return( setColors(screen, pic->colormap.ColorTable, (SHORT) pic->colormap.Count) ); } /* usePictureColors */ /* read an IFF Id */ static LONG getLong( file ) FILE *file; { register UBYTE p[4]; p[0] = GET(file); p[1] = GET(file); p[2] = GET(file); p[3] = GET(file); return( (LONG) Mk(p[0],p[1],p[2],p[3]) ); } /* getLong */ /* read an IFF chunk header */ static getChunk( id, len, file ) LONG *id, *len; FILE *file; { *id = getId( file ); *len = getLen( file ); } /* getChunk */ /* get len bytes from the file and put them into memory */ static memget( p, len, file ) UBYTE *p; LONG len; FILE *file; { for( ; len > 0L; len -= 0x07fffL, p += 0x07fffL ) { fread( p, (int) (len & 0x07fffL), 1, file ); } /* for */ } /* memget */ /* get a word */ static WORD getWord( file ) FILE *file; { WORD v; v = GET(file) << 8; return( v | GET(file) ); } /* getWord */ static int getCmpBody( bm, file ) struct BitMap *bm; FILE *file; { register short x; short y, pl; UBYTE *plane; UBYTE run_len, verb_len, run_byte; BYTE v; register BYTE mybyte; verb_len = run_len = 0; /* note: the bit-planes should be clear already */ for( y = 0; y < bm->Rows; ++y ) { for( pl = 0; pl < bm->Depth; ++pl ) { plane = bm->Planes[pl] + y * bm->BytesPerRow; for( x = 0; x < bm->BytesPerRow; ++x ) { if( run_len ) { --run_len; mybyte = run_byte; } else if( verb_len ) { --verb_len; mybyte = GET(file); } else if( (v = GET(file)) >= 0 ) { verb_len = v; mybyte = GET(file); } else { run_len = -v; mybyte = run_byte = GET(file); } plane[x] = mybyte; } /* for */ } /* for */ } /* for */ return( 0 ); } /* getCmpBody */ static int getBody( bm, flags, file ) register struct BitMap *bm; ULONG flags; FILE *file; { register short i; if( flags & GBP_CONTIGUOUS ) { memget( bm->Planes[0], (ULONG)(bm->Depth) * bm->Rows * bm->BytesPerRow, file ); } else { for( i = 0; i < bm->Depth; ++i ) { memget( bm->Planes[i], (ULONG)(bm->Rows) * bm->BytesPerRow, file ); } /* for */ } return( 0 ); } /* getBody */ static int getLut( pic, len, file ) PICTURE *pic; LONG len; FILE *file; { SHORT i, ncols; USHORT red, green, blue; USHORT *lut; pic->colormap.Flags = pic->colormap.Type = 0; ncols = len / 3; lut = (USHORT *) AllocMem( (ULONG) ncols * sizeof(USHORT), MEMF_PUBLIC ); if( !lut ) { return( -1 ); } for( i = 0; i < ncols; ++i ) { red = GET(file) >> 4; green = GET(file) >> 4; blue = GET(file) >> 4; lut[i] = (red << 8) | (green << 4) | blue; } /* for */ if( len & 1 ) { GET(file); } pic->colormap.Count = ncols; pic->colormap.ColorTable = (APTR) lut; return( 0 ); } /* getLut */ SHAR_EOF cat << \SHAR_EOF > postext.c /* * FILE: postext.c * Support routines for writing text (or a number) in a rastport, * with flexible text location specification (eg any corner, centre). * * Public Domain, but keep my name in it as the original author. * 31-Aug-88 Jan Sven Trabandt first release version */ #define I_AM_POSTEXT #include "gimmelib/gimmefuncs.h" #include "gimmelib/postext.h" SHORT positionText( rp, myflags, s, num, x, y ) register struct RastPort *rp; register ULONG myflags; UBYTE *s; LONG num; SHORT x, y; { register SHORT i, j; SHORT len, rastlen, maxrastlen; SHORT maxbit, lowi; SHORT dest, temp; SHORT height, baseline; struct RastPort myrp; UBYTE buf[12]; /* big enough for max ULONG + '\0' */ #ifdef GIMME_WIMPY if( !rp ) { return( -1 ); } #endif if( s ) { len = strlen( s ); } else { len = sprintf( buf, "%1ld", num ); s = buf; } maxrastlen = len * (rp->TxWidth + rp->TxSpacing); rastlen = TextLength( rp, s, (long) len ); if( myflags & (GPT_YUPWARDS | GPT_YDOWNWARDS) ) { myrp = *rp; /* copy struct */ myrp.BitMap = gimmeBitMap( rp->BitMap->Depth, rastlen, myrp.TxHeight ); if( !myrp.BitMap ) { return( -1 ); } myrp.Layer = NULL; /* make sure no layer else trouble */ myrp.GelsInfo = NULL; Move( &myrp, 0L, (long) myrp.TxBaseline ); Text( &myrp, s, (long) len ); maxbit = rastlen - 1; switch( myflags & GPT_XFLAGS ) { case GPT_XRIGHT: if( myflags & GPT_YDOWNWARDS ) { y -= maxbit; } break; case GPT_XCENTRE: y -= rastlen >> 1; break; case GPT_XLEFT: default: if( myflags & GPT_YUPWARDS ) { y -= maxbit; } break; } /* switch */ if( myflags & GPT_XTHICKEN ) { /* if double thickness */ height = (myrp.TxHeight << 1) - 1; baseline = (myrp.TxBaseline << 1); } else { height = myrp.TxHeight - 1; baseline = myrp.TxBaseline; } switch( myflags & GPT_YFLAGS ) { /* make x top of char */ case GPT_YBOTTOM: if( myflags & GPT_YUPWARDS ) { x -= height; } break; case GPT_YCENTRE: /* skew to top of char */ if( myflags & GPT_YDOWNWARDS ) { /* x += (height >> 1) - height; */ x -= (height + 1) >> 1; } else { x -= height >> 1; } break; case GPT_YCENTREBASE: /* skew to bottom of char */ if( myflags & GPT_YDOWNWARDS ) { x += ((baseline + 1) >> 1) - height; } else { x -= (baseline + 1) >> 1; } break; case GPT_YTOP: if( myflags & GPT_YDOWNWARDS ) { x -= height; } break; case GPT_YBASELINE: default: if( myflags & GPT_YDOWNWARDS ) { x += baseline - height; } else { x -= baseline; } break; } /* switch */ if( y < 0 ) { rastlen += y; y = 0; } lowi = rastlen - rp->BitMap->Rows; if( lowi > 0 ) { rastlen -= lowi; } else { lowi = 0; } maxbit = rastlen - 1; if( myflags & GPT_YDOWNWARDS ) { if( lowi ) { maxbit -= lowi; lowi = 0; } temp = x + height; for( j = myrp.TxHeight - 1; j >= 0; --j ) { if( GPT_XTHICKEN ) { dest = temp - (j << 1) - 1; } else { dest = temp - j; } for( i = maxbit; i >= lowi; --i ) { /* if no error and not background colour */ if( ReadPixel(&myrp, (long) i, (long) j) > 0L ) { WritePixel( rp, (long) dest, (long) y + i ); if( myflags & GPT_XTHICKEN ) { WritePixel( rp, (long) dest + 1, (long) y + i ); } } } /* for */ } /* for */ } else { /* else upwards */ for( i = maxbit; i >= lowi; --i ) { dest = y + maxbit - i; for( j = myrp.TxHeight - 1; j >= 0; --j ) { /* if no error and not background colour */ if( ReadPixel(&myrp, (long) i, (long) j) > 0L ) { if( myflags & GPT_XTHICKEN ) { temp = j << 1; WritePixel( rp, (long) x + temp + 1, (long) dest ); WritePixel( rp, (long) x + temp, (long) dest ); } else { WritePixel( rp, (long) x + j, (long) dest ); } } } /* for */ } /* for */ } getRidOfBitMap( myrp.BitMap ); } else { switch( myflags & GPT_XFLAGS ) { case GPT_XRIGHT: x -= rastlen - 1; break; case GPT_XCENTRE: x -= rastlen >> 1; break; case GPT_XLEFT: default: break; } /* switch */ switch( myflags & GPT_YFLAGS ) { /* make y top of char */ case GPT_YBOTTOM: y -= rp->TxHeight - 1; break; case GPT_YCENTRE: y -= (rp->TxHeight - 1) >> 1; /* skew to top of char */ break; case GPT_YCENTREBASE: y -= (rp->TxBaseline + 1) >> 1; /* skew to bottom of char */ break; case GPT_YTOP: break; case GPT_YBASELINE: default: y -= rp->TxBaseline; break; } /* switch */ y += rp->TxBaseline; /* adjust top to baseline for Text() */ /* note rp's TxBaseline is offset from top pixel of character */ Move( rp, (long) x, (long) y ); Text( rp, s, (long) len ); } return( maxrastlen ); } /* positionText */ SHAR_EOF cat << \SHAR_EOF > requester.c /* * FILE: requester.c * Support routines for putting up an Auto Request or creating a Requester. * * Public Domain, but keep my name in it as the original author. * 31-Aug-88 Jan Sven Trabandt first release version * 31-Oct-88 Jan Sven Trabandt added more functionality to gimmeRequester */ #define I_AM_REQUESTER #include <clib/macros.h> #include "gimmelib/gimmefuncs.h" #include "gimmelib/requester.h" #include "gimmelib/macros.h" extern struct GfxBase *GfxBase; SHORT gimmeAutoRequest( window, s, textattr ) struct Window *window; UBYTE *s; struct TextAttr *textattr; { struct IntuiText itext, ptext, ntext; SHORT xsize, ysize, width; if( !s ) { s = (UBYTE *) GAR_DUMMY_TEXT; } itext.FrontPen = AUTOFRONTPEN; itext.BackPen = AUTOBACKPEN; itext.DrawMode = AUTODRAWMODE; itext.LeftEdge = AUTOLEFTEDGE; itext.TopEdge = AUTOTOPEDGE; itext.ITextFont = textattr; itext.IText = s; itext.NextText = AUTONEXTTEXT; ptext = itext; /* struct copy */ ntext = itext; /* struct copy */ ptext.IText = gimAutReqPostext; ntext.IText = gimAutReqNegtext; xsize = 0; if( textattr ) { ysize = textattr->ta_YSize; } else if( window ) { ysize = window->RPort->TxHeight; xsize = window->RPort->TxWidth; } else { ysize = GfxBase->DefaultFont->tf_YSize; } if( !xsize ) { xsize = GfxBase->DefaultFont->tf_XSize; } width = MAX(IntuiTextLength(&itext), IntuiTextLength(&ptext) + IntuiTextLength(&ntext) + 3*xsize); return ( AutoRequest( window, &itext, &ptext, &ntext, ENDGADGET, ENDGADGET, (ULONG) width + xsize * GAR_BORDER_WIDTH, (ULONG) ysize * GAR_HEIGHT ) ); } /* gimmeAutoRequest */ #define XLEEWAY 8 /* border space */ #define YLEEWAY 4 #define MIN_WIDTH 50 /* minimum dimensions if calculating dimension(s) */ #define MIN_HEIGHT 20 /* not counting y leeways */ struct Requester *gimmeRequester( mh, left, top, width, height, backfill, gp, s, textattr, flags ) void **mh; SHORT left, top; SHORT width, height; UBYTE backfill; struct Gadget *gp; UBYTE *s; struct TextAttr *textattr; ULONG flags; { register struct Requester *req; register struct Border *bp; struct Gadget *gadg; SHORT len, extra; void *mymh = NULL; GUESS QUIF( !mh ); req = chainAllocMem( &mymh, (ULONG)sizeof(struct Requester), MEMF_PUBLIC | MEMF_CLEAR ); QUIF( !req ); if( flags & POINTREL ) { req->RelLeft = left; req->RelTop = top; } req->LeftEdge = left; req->TopEdge = top; req->ReqGadget = gp; req->ReqText = gimmeIntuiText( &mymh, s != NULL ? s : (UBYTE *)"", textattr, 0 ); QUIF( !req->ReqText ); req->ReqText->TopEdge = YLEEWAY; req->ReqText->LeftEdge = XLEEWAY; req->ReqText->BackPen = backfill; req->Flags = flags; req->BackFill = backfill; if( width <= 0 ) { width = IntuiTextLength( req->ReqText ); extra = 0; for( gadg = gp; gadg; gadg = gadg->NextGadget ) { if( gadg->Flags & GRELRIGHT ) { len = -gadg->LeftEdge; } else { len = gadg->LeftEdge; } if( !(gadg->Flags & GRELWIDTH) ) { len += gadg->Width; } if( len > width ) { width = len; } else if( gadg->Activation & (RIGHTBORDER | LEFTBORDER) ) { if( len > extra ) { extra = gadg->Width; } } } /* for */ width += extra + XLEEWAY; if( width <= 0 ) { width = MIN_WIDTH; } } req->Width = width; if( height <= 0 ) { if( textattr ) { height = textattr->ta_YSize; } else { height = MIN_HEIGHT; } extra = 0; for( gadg = gp; gadg; gadg = gadg->NextGadget ) { if( gadg->Flags & GRELBOTTOM ) { len = -gadg->TopEdge; } else { len = gadg->TopEdge; } if( !(gadg->Flags & GRELHEIGHT) ) { len += gadg->Height; } if( len > height ) { height = len; } else if( gadg->Activation & (BOTTOMBORDER | TOPBORDER) ) { if( len > extra ) { extra = gadg->Height; } } } /* for */ height += extra + YLEEWAY; } req->Height = height; bp = gimmeBorder( &mymh, width - 4, height - 2 ); if( bp ) { bp->LeftEdge = 2; bp->TopEdge = 1; bp->FrontPen = ~backfill; req->ReqBorder = bp; /* double thickness vertical lines */ bp = gimmeBorder( &mymh, width - 6, height - 2 ); if( bp ) { bp->LeftEdge = 3; bp->TopEdge = 1; bp->FrontPen = ~backfill; req->ReqBorder->NextBorder = bp; } } linkChainMem( mh, mymh ); return( req ); ENDGUESS if( mymh ) { chainFreeMem( mymh ); } return( NULL ); } /* gimmeRequester */ SHAR_EOF cat << \SHAR_EOF > screen.c /* * FILE: screen.c * Support for Intuition screen stuff. * * Public Domain, but keep our names in it as the original authors. * 31-Aug-88 Jan Sven Trabandt first release version * 30-Sep-88 Jan Sven Trabandt gimmeNewScreen checks width more closely */ #define I_AM_SCREEN #include "gimmelib/gimmefuncs.h" #include "gimmelib/window.h" #include "gimmelib/globals.h" extern struct GfxBase *GfxBase; struct NewScreen *gimmeNewScreen( modes, type, depth, title, textattr ) ULONG modes, type; SHORT depth; UBYTE *title; struct TextAttr *textattr; { register struct NewScreen *ns; #ifdef GIMME_WIMPY if( depth < 1 || depth > 8 ) { return( NULL ); } #endif ns = (struct NewScreen *) AllocMem( (ULONG)sizeof(struct NewScreen), MEMF_PUBLIC | MEMF_CLEAR ); if( ns ) { ns->Width = GfxBase->NormalDisplayColumns; if( modes & HIRES ) { if( ns->Width <= 350 ) { ns->Width <<= 1; } } else { if( ns->Width > 350 ) { ns->Width >>= 1; } } ns->Height = STDSCREENHEIGHT; ns->Depth = depth; ns->BlockPen = 1; ns->ViewModes = modes; ns->Type = type; ns->Font = textattr; ns->DefaultTitle = title; } return( ns ); } /* gimmeNewScreen */ short getRidOfNewScreen( ns ) struct NewScreen *ns; { #ifdef GIMME_WIMPY if( !ns ) { return( -1 ); } #endif FreeMem( ns, (ULONG)sizeof(struct NewScreen) ); return( 0 ); } /* getRidOfNewScreen */ struct Screen *gimmeScreen( ns, winptr, depth, IDCMPflags, winflags ) struct NewScreen *ns; struct Window **winptr; SHORT depth; ULONG IDCMPflags, winflags; { struct Screen *screen; struct NewWindow *nw; struct NewScreen *myns; if( !(myns = ns) ) { ns = gimmeNewScreen( HIRES, CUSTOMSCREEN, depth, NULL, &gimMyFont ); } if( ns ) { screen = OpenScreen( ns ); if( screen && winptr ) { nw = gimmeNewWindow( NULL, screen, 0, 1, IDCMPflags, winflags ); if( !nw ) { *winptr = NULL; } else { *winptr = gimmeWindow( nw, 0, 0, 0 ); getRidOfNewWindow( nw ); if( !*winptr ) { getRidOfScreen( screen, NULL ); screen = NULL; } else { ShowTitle( screen, FALSE ); /* hide screen title */ } } } } if( !myns && ns ) { getRidOfNewScreen( ns ); } return( screen ); } /* gimmeScreen */ struct Screen *gimmeScreenLazy( ns, winptr, depth ) struct NewScreen *ns; struct Window **winptr; SHORT depth; { return( gimmeScreen(ns, winptr, depth, IDCMP_DEFAULT, FLAGS_DEFAULT) ); } /* gimmeScreenLazy */ short getRidOfScreen( screen, window ) struct Screen *screen; struct Window *window; { if( window ) { getRidOfWindow( window ); } if( screen ) { CloseScreen( screen ); } return( 0 ); } /* getRidOfScreen */ short lowerScreen( screen, toheight ) struct Screen *screen; SHORT toheight; { register SHORT i; #ifdef GIMME_WIMPY if( !screen ) { return( -1 ); } #endif for( i = screen->TopEdge | 1; i < toheight; i += 2 ) { MoveScreen( screen, 0L, 2L ); } /* for */ return( 0 ); } /* lowerScreen */ short raiseScreen( screen, toheight ) struct Screen *screen; SHORT toheight; { register SHORT i; #ifdef GIMME_WIMPY if( !screen ) { return( -1 ); } #endif for( i = screen->TopEdge & (~1); i >= toheight; i -= 2 ) { MoveScreen( screen, 0L, -2L ); } /* for */ return( 0 ); } /* raiseScreen */ SHAR_EOF cat << \SHAR_EOF > scrollbar.c /* * FILE: scrollbar.c * Support routines for making scroll-bar and -button 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 keep up with changes to gadget.c */ #define I_AM_SCROLLBAR #include "gimmelib/gimmefuncs.h" #include "gimmelib/scrollbar.h" #include "gimmelib/macros.h" struct Gadget *gimmeOneScroll( window, id, dirflags, myflags ) struct Window *window; USHORT id; ULONG dirflags, myflags; { register struct Gadget *gp; void *gadgmh = NULL; USHORT *data; USHORT *imagedata; GUESS QUIF( !id ); gp = chainAllocMem( &gadgmh, (ULONG)sizeof(struct Gadget), MEMF_CLEAR | MEMF_PUBLIC ); QUIF( !gp ); gp->GadgetType = BOOLGADGET; gp->GadgetRender = (APTR) gimmeImage( &gadgmh, GOS_BITDEPTH, GOS_BITWIDTH, GOS_BITHEIGHT ); QUIF( !gp->GadgetRender ); if( dirflags & FREEVERT ) { gp->LeftEdge = -(GOS_BITWIDTH -1); gp->Width = GOS_BITWIDTH; gp->Height = GOS_BITHEIGHT; if( myflags & GOS_TOP ) { if( window ) { gp->TopEdge = window->BorderTop - 1; } else { gp->TopEdge = GIM_DFLT_TBHEIGHT; } gp->Flags = GADGIMAGE | GADGHCOMP | GRELRIGHT; imagedata = gimDataOneScrollUp; } else { gp->TopEdge = -GIM_SZHEIGHT - (GOS_BITHEIGHT -1); gp->Flags = GADGIMAGE | GADGHCOMP | GRELRIGHT | GRELBOTTOM; imagedata = gimDataOneScrollDown; } gp->Activation = RELVERIFY | RIGHTBORDER; } else { /* otherwise we have FREEHORIZ */ gp->TopEdge = -(GOS_BITHEIGHT -1); gp->Width = GOS_BITWIDTH; gp->Height = GOS_BITHEIGHT; if( myflags & GOS_LEFT ) { gp->LeftEdge = 0; gp->Flags = GADGIMAGE | GADGHCOMP | GRELBOTTOM; imagedata = gimDataOneScrollLeft; } else { gp->LeftEdge = -GIM_SZWIDTH - (GOS_BITWIDTH - 1); gp->Flags = GADGIMAGE | GADGHCOMP | GRELBOTTOM | GRELRIGHT; imagedata = gimDataOneScrollRight; } gp->Activation = RELVERIFY | BOTTOMBORDER; } copyDataImage( imagedata, (struct Image *) gp->GadgetRender ); if( window ) { if( window->Flags & GIMMEZEROZERO ) { gp->GadgetType |= GZZGADGET; } } gp->GadgetID = id; gp->UserData = gadgmh; return( gp ); ENDGUESS if( gadgmh ) { chainFreeMem( gadgmh ); return( NULL ); } } /* gimmeOneScroll */ struct Gadget *gimmeScrollBar( window, id, propflags, myflags ) struct Window *window; USHORT id; ULONG propflags, myflags; { register struct Gadget *gp; SHORT ones_size = 0; SHORT left, top, width, height; ULONG gadgflags, activation; void *gadgmh = NULL; GUESS QUIF( !id ); if( propflags & FREEVERT ) { propflags &= ~FREEHORIZ; if( myflags & GSB_ONE_SCROLL ) { ones_size = GOS_BITHEIGHT; } left = - (GOS_BITWIDTH -1); top = ones_size; if( !(myflags & GSB_NO_TITLEBAR) ) { if( window ) { top += window->BorderTop - 1; } else { top += GIM_DFLT_TBHEIGHT; } } width = GOS_BITWIDTH; height = -top - ones_size - GIM_SZHEIGHT; gadgflags = GADGHCOMP | GADGIMAGE | GRELRIGHT | GRELHEIGHT; activation = RELVERIFY | RIGHTBORDER; } else { /* otherwise we have FREEHORIZ */ propflags &= ~FREEVERT; if( myflags & GSB_ONE_SCROLL ) { ones_size = GOS_BITWIDTH; } left = ones_size; top = - (GOS_BITHEIGHT -1); width = -GIM_SZWIDTH - (ones_size<<1); height = GOS_BITHEIGHT; gadgflags = GADGHCOMP | GADGIMAGE | GRELBOTTOM | GRELWIDTH; activation = RELVERIFY | BOTTOMBORDER; } gp = gimmePropGadget( window, id, left, top, width, height, NULL, NULL, activation, propflags ); QUIF( !gp ); gp->Flags = gadgflags; if( window ) { ((struct PropInfo *)gp->SpecialInfo)->VertBody = 0x0FFFFL * window->Height / window->MaxHeight; ((struct PropInfo *)gp->SpecialInfo)->HorizBody = 0x0FFFFL * window->Width / window->MaxWidth; } linkChainMem( &gp->UserData, gadgmh ); return( gp ); ENDGUESS if( gadgmh ) { chainFreeMem( gadgmh ); return( NULL ); } } /* gimmeScrollBar */ struct Gadget *gimmeFullScrollBar( window, id, propflags, myflags, id1, id2 ) struct Window *window; USHORT id; ULONG propflags, myflags; USHORT id1, id2; { register struct Gadget *gp; GUESS QUIF( !id ); gp = gimmeScrollBar( window, id, propflags, myflags | GSB_ONE_SCROLL ); QUIF( !gp ); /* top or left one-scroll */ gp->NextGadget = gimmeOneScroll( window, id1, propflags, GOS_TOP | GOS_LEFT ); QUIF( !gp->NextGadget ); /* bottom or right one-scroll */ gp->NextGadget->NextGadget = gimmeOneScroll( window, id2, propflags, GOS_BOT | GOS_RIGHT ); QUIF( !gp->NextGadget->NextGadget ); return( gp ); ENDGUESS if( gp ) { getRidOfGadgets( gp ); } return( NULL ); } /* gimmeFullScrollBar */ SHAR_EOF cat << \SHAR_EOF > sound.c /* * FILE: sound.c * Support routines for reading IFF/8SVX files. * * Public Domain, but keep our names in it as the original authors. * 09-Dec-87 Rico Mariani original code (modified by JST) * 31-Aug-88 Jan Sven Trabandt first release version */ #define I_AM_SOUND #include "gimmelib/gimmefuncs.h" #include "gimmelib/sound.h" #include <stdio.h> #define GET(iffile) getc( iffile ) #define getId getLong #define getLen getLong #define getByte GET #define skip(len, file) fseek(file, (long)(len), 1) #define getV8H(v8h, file) fread(v8h, sizeof(Voice8Header), 1, file) /* requires an existent variable 'char *errmsg' and a label 'failure_return' */ #define fail_and_return(msg) {errmsg = msg; goto failure_return;} /* forward declarations */ static LONG getLong(); static WORD getWord(); static char noMemMsg[] = "insufficient memory\n"; static char badFileMsg[] = "corrupt or incomplete file\n"; SOUND *gimmeSound( filename ) UBYTE *filename; { LONG len, id; SOUND *snd = NULL; BYTE *p; void *mh = NULL; FILE *file = NULL; char *errmsg = " "; SHORT i; if( !(file = fopen(filename, "r")) ) { fail_and_return( "unable to open iff sound file for read\n" ); } if( getId(file) != ID_FORM ) { fail_and_return( "not IFF format\n" ); } getLen( file ); if( getId(file) != ID_8SVX ) { fail_and_return( "not 8SVX format\n" ); } for( ;; ) { getChunk( &id, &len, file ); if( ferror(file) || feof(file) ) { fail_and_return( badFileMsg ); } switch( id ) { case ID_VHDR: snd = chainAllocMem( &mh, (ULONG)sizeof(SOUND), MEMF_PUBLIC | MEMF_CLEAR ); if( !snd ) { fail_and_return( noMemMsg ); } getV8H( &snd->vh, file ); if( len & 1 ) { GET(file); } break; case ID_BODY: if( !snd ) { fail_and_return( "didn't find VHDR chunk\n" ); } switch( snd->vh.sCompression ) { case sCmpNone: snd->bodylen = len; snd->body = chainAllocMem( &mh, len, MEMF_CHIP ); if( !snd->body ) { fail_and_return( noMemMsg ); } memget( snd->body, len, file ); break; case sCmpFibDelta: snd->bodylen = len << 1; snd->body = chainAllocMem( &mh, (ULONG) snd->bodylen, MEMF_CHIP ); if( !snd->body ) { fail_and_return( noMemMsg ); } p = AllocMem( len, MEMF_PUBLIC ); if( !p ) { fail_and_return( noMemMsg ); } memget( p, len, file ); DUnpack( p, len, snd->body ); FreeMem( p, len ); break; default: fail_and_return( "unknown compression form\n" ); break; } /* switch */ if( len & 1 ) { GET(file); } if( ferror(file) ) { fail_and_return( badFileMsg ); } snd->memhead = mh; fclose( file ); return( snd ); break; case ID_NAME: case ID_AUTH: case ID_COPY: case ID_ANNO: case ID_ATAK: case ID_RLSE: default: /* unimplemented chunk type */ skip( EVEN(len), file ); break; } /* switch */ } /* for */ failure_return: {} if( Output() ) { Write( Output(), errmsg, (ULONG)strlen(errmsg) ); } if( mh ) { chainFreeMem( mh ); } if( file ) { fclose( file ); } return( NULL ); } /* gimmeSound */ short getRidOfSound( sound ) SOUND *sound; { #ifdef GIMME_WIMPY if( !sound ) { return( -1 ); } #endif chainFreeMem( sound->memhead ); return( 0 ); } /* getRidOfSound */ /* read an IFF Id */ static LONG getLong( file ) FILE *file; { register UBYTE p[4]; p[0] = GET(file); p[1] = GET(file); p[2] = GET(file); p[3] = GET(file); return( (LONG) Mk(p[0],p[1],p[2],p[3]) ); } /* getLong */ /* read an IFF chunk header */ static getChunk( id, len, file ) LONG *id, *len; FILE *file; { *id = getId( file ); *len = getLen( file ); } /* getChunk */ /* get len bytes from the file and put them into memory */ static memget( p, len, file ) UBYTE *p; LONG len; FILE *file; { for( ; len > 0L; len -= 0x07fffL, p += 0x07fffL ) { fread( p, (int) (len & 0x07fffL), 1, file ); } /* for */ } /* memget */ /* get a word */ static WORD getWord( file ) FILE *file; { WORD v; v = GET(file) << 8; return( v | GET(file) ); } /* getWord */ /* get the EGPoint info */ static getEGPoint( pnt, file ) EGPoint *pnt; FILE *file; { pnt->duration = getWord( file ); pnt->dest = getLong( file ); } /* getEGPoint */ static BYTE codeToDelta[] = {-34,-21,-13,-8,-5,-3,-2,-1,0,1,2,3,5,8,13,21}; /* unpack a part of a fibonacci delta encoded sound sample */ static BYTE D1Unpack( source, n, dest, x ) BYTE *source; LONG n; BYTE *dest; BYTE x; { UBYTE d; LONG i, lim; lim = n << 1; for( i = 0; i < lim; ++i ) { d = source[i>>1]; if( i & 1 ) { d &= 0xf; } else { d >>= 4; } x += codeToDelta[d]; dest[i] = x; } /* for */ return( x ); /* return last data value */ } /* D1Unpack */ /* unpack a fibonacci delta encoded sound sample */ static DUnpack( source, n, dest ) BYTE *source; LONG n; BYTE *dest; { D1Unpack( source + 2, n - 2, dest, source[1] ); } /* DUnpack */ SHAR_EOF cat << \SHAR_EOF > stdstuff.c /* * FILE: stdstuff.c * Support routines for creating and dealing with standard libraries * and devices. * * Public Domain, but keep my name in it as the original author. * 30-Sep-88 Jan Sven Trabandt added to gimme.lib * 31-Oct-88 Jan Sven Trabandt added new options * made getRidOfStdStuff more controllable */ #define I_AM_STDSTUFF #include "gimmelib/gimmefuncs.h" #include "gimmelib/stdstuff.h" #ifdef AZTEC_C extern int Enable_Abort; #endif AZTEC_C struct IntuitionBase *IntuitionBase = NULL; struct GfxBase *GfxBase = NULL; struct DiskfontBase *DiskfontBase = NULL; struct Device *TimerBase = NULL; struct MsgPort *gimTimerPort = NULL; struct timerequest *gimMasterTR = NULL; struct timerequest *gimSlaveTR = NULL; struct MsgPort *gimMainPort = NULL; SHORT gimSubTasks = 0; void *gimChainMem = NULL; ULONG gimmeStdStuff( myflags, rev ) ULONG myflags; SHORT rev; { if( myflags & GSS_DISABLEABORT ) { #ifdef AZTEC_C Enable_Abort = 0; #endif } if( myflags & GSS_INTUITION ) { if( !(IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library", (long) rev)) ) { return( GSS_INTUITION ); } } if( myflags & GSS_GFX ) { if( !(GfxBase = (struct GfxBase *) OpenLibrary("graphics.library", (long) rev)) ) { return( GSS_GFX ); } } if( myflags & GSS_CLOSEWBENCH ) { if( CloseWorkBench() ) { return( GSS_CLOSEWBENCH ); } } if( myflags & GSS_DISKFONT ) { if( !(DiskfontBase = (struct DiskfontBase *) OpenLibrary("diskfont.library", (long) rev)) ) { return( GSS_DISKFONT ); } } if( myflags & GSS_TIMER ) { if( !(gimMasterTR = accessTimer(UNIT_MICROHZ, &gimTimerPort)) ) { return( GSS_TIMER ); } if( !(gimSlaveTR = gimmeTimeRequest(gimMasterTR)) ) { return( GSS_TIMER ); } } if( myflags & GSS_SUBTASK ) { if( initSubTasker(&gimSubTasks, &gimMainPort) ) { return( GSS_SUBTASK ); } } return( 0L ); } /* gimmeStdStuff */ ULONG getRidOfStdStuff( myflags ) ULONG myflags; { if( myflags & GSS_MEMCHAIN ) { if( gimChainMem ) { chainFreeMem( gimChainMem ); gimChainMem = NULL; } } if( myflags & GSS_SUBTASK ) { if( gimMainPort ) { handleSpecialSubTaskMsg( &gimSubTasks, &gimMainPort ); if( doneSubTasker(&gimSubTasks, &gimMainPort) && !(myflags & GSS_RUTHLESS) ) { return( GSS_SUBTASK ); } gimSubTasks = 0; gimMainPort = NULL; } } if( myflags & GSS_TIMER ) { if( gimSlaveTR ) { if( getRidOfTimeRequest(gimSlaveTR) && !(myflags & GSS_RUTHLESS) ) { return( GSS_TIMER ); } gimSlaveTR = NULL; } if( gimMasterTR ) { if( releaseTimer(gimMasterTR, NULL) && !(myflags & GSS_RUTHLESS) ) { return( GSS_TIMER ); } gimMasterTR = NULL; gimTimerPort = NULL; } } if( myflags & GSS_DISKFONT ) { if( DiskfontBase ) { CloseLibrary( DiskfontBase ); DiskfontBase = NULL; } } if( myflags & GSS_OPENWBENCH ) { if( OpenWorkBench() && !(myflags & GSS_RUTHLESS) ) { return( GSS_OPENWBENCH ); } } if( myflags & GSS_GFX ) { if( GfxBase ) { CloseLibrary( GfxBase ); GfxBase = NULL; } } if( myflags & GSS_INTUITION ) { if( IntuitionBase ) { CloseLibrary( IntuitionBase ); IntuitionBase = NULL; } } if( myflags & GSS_ENABLEABORT ) { #ifdef AZTEC_C Enable_Abort = 1; #endif } return( 0L ); } /* getRidOfStdStuff */ SHAR_EOF cat << \SHAR_EOF > subtask.c /* * FILE: subtask.c * Support routines for spawning subtasks (not processes). * This means the subtask shares the same memory space as its parent task. * * Note: this "library" is re-entrant, so any task can spawn and keep track * of its own subtasks independantly of other users of this "library". * * Public Domain, but keep my name in it as the original author. * 31-Aug-88 Jan Sven Trabandt first release version * 31-Oct-88 Jan Sven Trabandt (de)initialize routines moved to subtinit.c * so that minimal routines need to be * linked in when using stdstuff.c * renamed getRidOfSubTask to killSubTask */ #define I_AM_SUBTASK #include "gimmelib/gimmefuncs.h" #define MIN_STACK 100L #define MIN_COUNT 2 #define MAX_EXTRA 2 typedef struct { struct Message msg; ULONG flags; APTR ptr; } DONEMSG; #define DONEFLAG ((1L << 31) + 1857329L) /* internal use only!! * * NAME: a4get, a4put * * SYNOPSIS: a4value = a4get(); * a4put( a4value ); * LONG a4value; * * DESCRIPTION: Get or put a value into register A4. MANX specific!!!! * These two functions are support routines for task creation. * BECAUSE A4 GETS CLEARED IN THE SUBTASK * and Manx needs it as a base pointer in small-code model. * Manx's geta4() won't work if its code is too far away, * so this ensures a4 is set up. * I'm not sure if this is only in small code and/or small data. * static LONG a4get(); static VOID a4put(); #asm cseg _a4get: move.l a4,d0 rts _a4put: move.l 4(a7),a4 rts #endasm struct Task *gimmeSubTask( countptr, portptr, stack_size, data_size, myportptr ) SHORT *countptr; struct MsgPort **portptr; LONG stack_size, data_size; struct MsgPort **myportptr; { struct Task *task; DONEMSG *msg = NULL; struct MemList *mymemlist; struct myneeds { struct MemList mn_head; /* 1 MemEntry in the head */ struct MemEntry mn_body[MIN_COUNT+MAX_EXTRA-1]; } myneeds; UWORD count = 0; myneeds.mn_head.ml_Node.ln_Type = NT_MEMORY; myneeds.mn_head.ml_Node.ln_Pri = 0; myneeds.mn_head.ml_Node.ln_Name = NULL; if( data_size > 0L ) { myneeds.mn_head.ml_me[count].me_Reqs = MEMF_PUBLIC | MEMF_CLEAR; myneeds.mn_head.ml_me[count].me_Length = data_size; ++count; } if( myportptr && portptr ) { myneeds.mn_head.ml_me[count].me_Reqs = MEMF_PUBLIC | MEMF_CLEAR; myneeds.mn_head.ml_me[count].me_Length = (LONG) sizeof(DONEMSG); ++count; } /* leave stack and struct Task as last two memory blocks */ if( stack_size < MIN_STACK ) { stack_size = MIN_STACK; } myneeds.mn_head.ml_me[count].me_Reqs = MEMF_PUBLIC; myneeds.mn_head.ml_me[count].me_Length = stack_size; ++count; myneeds.mn_head.ml_me[count].me_Reqs = MEMF_PUBLIC | MEMF_CLEAR; myneeds.mn_head.ml_me[count].me_Length = (LONG) sizeof(struct Task); ++count; myneeds.mn_head.ml_NumEntries = count; mymemlist = (struct MemList *) AllocEntry( &myneeds ); if( (ULONG)(mymemlist) & (1L<<31) ) { return( NULL ); } --count; task = (struct Task *) mymemlist->ml_me[count].me_Addr; NewList( &task->tc_MemEntry ); AddTail( &task->tc_MemEntry, mymemlist ); --count; task->tc_SPLower = mymemlist->ml_me[count].me_Addr; /* stack */ task->tc_SPUpper = (APTR) (stack_size + (ULONG) task->tc_SPLower); task->tc_SPReg = task->tc_SPUpper; task->tc_Node.ln_Type = NT_TASK; if( myportptr && portptr ) { --count; msg = (DONEMSG *) mymemlist->ml_me[count].me_Addr; msg->msg.mn_Length = mymemlist->ml_me[count].me_Length; msg->msg.mn_Node.ln_Type = NT_MESSAGE; msg->ptr = (APTR) *portptr; /* save subtask monitoring port */ msg->flags = DONEFLAG; } /* endif */ pushTaskStack( task, msg ); if( data_size > 0L ) { --count; task->tc_UserData = mymemlist->ml_me[count].me_Addr; } pushTaskStack( task, task->tc_UserData ); pushTaskStack( task, myportptr ); pushTaskStack( task, countptr ); return( task ); } /* gimmeSubTask */ /* internal use only!! * * pushTaskStack : push a long value onto the subtask's stack * task struct and stack must already be initialized, * task must not have been started yet. static pushTaskStack( task, val ) struct Task *task; LONG val; { --((LONG *)task->tc_SPReg); *((LONG *)task->tc_SPReg) = val; } /* pushTaskStack */ /* internal use only!! * * popTaskStack : pop a long value off the subtask's stack * task struct and stack must already be initialized, * task must not have been started yet. static LONG popTaskStack( task ) struct Task *task; { return( *((LONG *)task->tc_SPReg)++ ); } /* popTaskStack */ VOID undoGimmeSubTask( task ) struct Task *task; { if( task ) { FreeEntry( task->tc_MemEntry.lh_Head ); } } /* undoGimmeSubTask */ VOID killSubTask( countptr, portptr, task ) SHORT *countptr; struct MsgPort **portptr; struct Task *task; { struct MsgPort *myport; if( portptr && (myport = *portptr) ) { *portptr = NULL; DeletePort( myport ); } /* It is permissible to do a Forbid() and RemTask(NULL) [kill myself] * even though the following Permit() statement would not get executed * since the OS will take care of things just fine. */ Forbid(); if( countptr ) { --(*countptr); } RemTask( task ); Permit(); } /* killSubTask */ /* internal use only!! * * getRidOfMyself * what's actually on the stack: * func a4 countptr myport data msg -> see bridgeSubTask * what getRidOfMyself thinks is there: * ret-addr dum [countptr] [myport] [data] [msg] * note it doesn't actually know about data, msg and port. * thus countptr is 1 long past dum, etc. static VOID getRidOfMyself( dum ) LONG dum; { LONG *parm; DONEMSG *msg; struct MsgPort *mp, *myport; parm = &dum; msg = (DONEMSG *) *(parm + 4); if( msg && (myport = (struct MsgPort *) *(parm + 2)) ) { mp = (struct MsgPort *) msg->ptr; msg->ptr = (APTR) FindTask( NULL ); msg->msg.mn_ReplyPort = myport; PutMsg( mp, msg ); for( ;; ) { WaitPort( myport ); while ( msg = (DONEMSG *) GetMsg(myport) ) { if( msg->msg.mn_Node.ln_Type != NT_REPLYMSG ) { ReplyMsg( msg ); } else if( msg->flags == DONEFLAG ) { goto gromyself_done; } } /* while */ } /* for */ } gromyself_done: killSubTask( *(parm + 1), parm + 2, NULL ); } /* getRidOfMyself */ /* internal use only!! * * bridgeSubTask * Used as the actual initialPC for the subtask, it gets a message port * if necessary and calls the real subtask routine. * Also increments the subtask counter!!!! * Also changes portptr on the stack to port (ie a pointer to a port, not * a pointer to a pointer) so things are kosher for getRidOfMyself. * startSubTask does the set-up so that the new subtask starts executing * with this routine. static VOID bridgeSubTask( func, a4, countptr, myportptr, data, msg ) long (*func)(); LONG a4; SHORT *countptr; struct MsgPort **myportptr; APTR data; DONEMSG *msg; { a4put( a4 ); if( countptr ) { Forbid(); ++(*countptr); Permit(); } if( myportptr ) { *myportptr = CreatePort( NULL, 0L ); if( !*myportptr ) { return; } *((struct MsgPort **)&myportptr) = *myportptr; } func( data ); } /* bridgeSubTask */ short startSubTask( task, name, pri, initialpc, finalpc ) struct Task *task; char *name; BYTE pri; void (*initialpc)(), (*finalpc)(); { if( !task || !initialpc ) { return( -1 ); } task->tc_Node.ln_Name = name; task->tc_Node.ln_Pri = pri; pushTaskStack( task, a4get() ); pushTaskStack( task, initialpc ); if( !finalpc ) { (APTR) finalpc = (APTR) getRidOfMyself; } AddTask( task, bridgeSubTask, finalpc ); return( 0 ); } /* startSubTask */ SHAR_EOF cat << \SHAR_EOF > subtinit.c /* * FILE: subtinit.c * Support routines for spawning subtasks (not processes). * This means the subtask shares the same memory space as its parent task. * * Note: this "library" is re-entrant, so any task can spawn and keep track * of its own subtasks independantly of other users of this "library". * * Public Domain, but keep my name in it as the original author. * 31-Oct-88 Jan Sven Trabandt split from subtask.c */ #define I_AM_SUBTINIT #include "gimmelib/gimmefuncs.h" #define GIM_BUILTIN #include "gimmelib/macros.h" short initSubTasker( countptr, portptr ) SHORT *countptr; struct MsgPort **portptr; { if( countptr ) { *countptr = 0; } if( portptr ) { *portptr = CreatePort( NULL, 0L ); if( !*portptr ) { return( -1 ); } } return( 0 ); } /* initSubTasker */ short doneSubTasker( countptr, portptr ) SHORT *countptr; struct MsgPort **portptr; { struct MsgPort *myport; if( countptr && *countptr ) { return( -1 ); } if( portptr && (myport = *portptr) ) { *portptr = NULL; DeletePort( myport ); } return( 0 ); } /* doneSubTasker */ /****************************************************************/ /* routines to handle printing messages from subtasks to Output() extern struct Message *gimmeMessage(); struct print_msg { struct Message msg; ULONG flags; UBYTE buf[164]; }; typedef struct print_msg PRINTMSG; #define PRINTMSG_FLAG 218572L short doPrintf( port, replyport, s, p1, p2, p3, p4 ) struct MsgPort *port, *replyport; UBYTE *s; LONG p1, p2; double p3, p4; { PRINTMSG *pmsg; if( !port || !s ) { return( -1 ); } pmsg = (PRINTMSG *) gimmeMessage( (ULONG)sizeof(PRINTMSG), replyport ); if( !pmsg ) { return( -1 ); } pmsg->flags = PRINTMSG_FLAG; sprintf( pmsg->buf, s, p1, p2, p3, p4 ); PutMsg( port, pmsg ); if( replyport ) { WaitPort( replyport ); pmsg = (PRINTMSG *) GetMsg( port ); /*** if( pmsg->msg.mn_Node.ln_Type != NT_REPLYMSG || pmsg->flags != PRINTMSG_FLAG ) { } ***/ getRidOfMessage( pmsg ); } /* endif */ return( 0 ); } /* doPrintf */ SHORT handleSpecialSubTaskMsg( countptr, portptr ) SHORT *countptr; struct MsgPort **portptr; { PRINTMSG *msg; SHORT died = 0; if( !portptr || !*portptr ) { return( died ); } while( msg = (PRINTMSG *) GetMsg(*portptr) ) { if( msg->flags == PRINTMSG_FLAG ) { if( Output() ) { Forbid(); Write( Output(), msg->buf, (ULONG)strlen(msg->buf) ); Permit(); } if( !msg->msg.mn_ReplyPort ) { getRidOfMessage( msg ); } else { ReplyMsg( msg ); } } else { /* otherwise its a DONEMSG (see subtask.c) */ ReplyMsg( msg ); ++died; } /* endif */ } /* while */ return( died ); } /* handleSpecialSubTaskMsg */ SHAR_EOF cat << \SHAR_EOF > timer.c /* * FILE: timer.c * Support routines for dealing with the timer device. * * Public Domain, but keep my name in it as the original author. * 31-Aug-88 Jan Sven Trabandt first release version * 31-Oct-88 Jan Sven Trabandt most routines moved to timerstuff.c * so that minimal routines need to be * linked in when using stdstuff.c */ #define I_AM_TIMER #include "gimmelib/gimmefuncs.h" extern struct Device *TimerBase; struct timerequest *accessTimer( unit, portptr ) ULONG unit; struct MsgPort **portptr; { struct MsgPort *timerport = NULL; struct timerequest *tr; #ifdef GIMME_WIMPY if( unit != UNIT_VBLANK && unit != UNIT_MICROHZ ) { return( NULL ); } #endif if( portptr && *portptr ) { timerport = *portptr; } else { timerport = CreatePort( NULL, 0L ); if( portptr ) { *portptr = timerport; } } if( !timerport ) { return( NULL ); } tr = CreateExtIO( timerport, (ULONG)sizeof(struct timerequest) ); if( !tr ) { DeletePort( timerport ); } else { if( OpenDevice(TIMERNAME, unit, tr, 0L) ) { DeleteExtIO( tr, (ULONG)sizeof(struct timerequest) ); DeletePort( timerport ); return( NULL ); } } TimerBase = tr->tr_node.io_Device; tr->tr_node.io_Message.mn_Node.ln_Type = NT_FREEMSG; return( tr ); } /* accessTimer */ LONG releaseTimer( tr, saveport ) register struct timerequest *tr; struct MsgPort *saveport; { struct MsgPort *tport; LONG err; #ifdef GIMME_WIMPY if( !tr ) { return( 0L ); } #endif tport = tr->tr_node.io_Message.mn_ReplyPort; if( tr->tr_node.io_Message.mn_Node.ln_Type == NT_MESSAGE ) { if( err = AbortIO(tr) ) { return( err ); } Remove( tr ); } CloseDevice( tr ); DeleteExtIO( tr, (ULONG)sizeof(struct timerequest) ); if( !saveport && tport ) { DeletePort( tport ); } return( 0L ); } /* releaseTimer */ struct timerequest *gimmeTimeRequest( trmaster ) struct timerequest *trmaster; { register struct timerequest *tr; #ifdef GIMME_WIMPY if( !trmaster ) { return( NULL ); } #endif tr = CreateExtIO( trmaster->tr_node.io_Message.mn_ReplyPort, (ULONG)sizeof(struct timerequest) ); if( tr ) { tr->tr_node.io_Device = trmaster->tr_node.io_Device; tr->tr_node.io_Unit = trmaster->tr_node.io_Unit; tr->tr_node.io_Message.mn_Node.ln_Type = NT_FREEMSG; } return( tr ); } /* gimmeTimeRequest */ LONG getRidOfTimeRequest( tr ) register struct timerequest *tr; { LONG err; #ifdef GIMME_WIMPY if( !tr ) { return( 0L ); } #endif Forbid(); tr->tr_node.io_Message.mn_ReplyPort = NULL; if( tr->tr_node.io_Message.mn_Node.ln_Type == NT_MESSAGE ) { if( err = AbortIO(tr) ) { Permit(); return( err ); } Remove( tr ); tr->tr_node.io_Message.mn_Node.ln_Type = NT_FREEMSG; } Permit(); DeleteExtIO( tr, (ULONG)sizeof(struct timerequest) ); return( 0L ); } /* getRidOfTimeRequest */ SHAR_EOF cat << \SHAR_EOF > timerstuff.c /* * FILE: timerstuff.c * Support routines for dealing with timerequests and additional timer support. * * Public Domain, but keep my name in it as the original author. * 31-Oct-88 Jan Sven Trabandt split from timer.c */ #define I_AM_TIMERSTUFF #include "gimmelib/gimmefuncs.h" extern struct Device *TimerBase; LONG timeDelay( secs, micros, unit, mytr ) ULONG secs, micros; ULONG unit; struct timerequest *mytr; { register struct timerequest *tr; LONG err; if( !secs && !micros ) { return( 0L ); /* so we don't crash, return right away */ } if( mytr ) { tr = mytr; } else { #ifdef GIMME_WIMPY if( unit != UNIT_VBLANK && unit != UNIT_MICROHZ ) { return( -1L ); } #endif if( !secs ) { unit = UNIT_MICROHZ; /* force more efficient method */ } if( !(tr = accessTimer(unit, NULL)) ) { return( -1L ); } } tr->tr_node.io_Command = TR_ADDREQUEST; tr->tr_time.tv_secs = secs; tr->tr_time.tv_micro = micros; err = DoIO( tr ); tr->tr_node.io_Message.mn_Node.ln_Type = NT_FREEMSG; if( !mytr ) { releaseTimer( tr, NULL ); } return( err ); } /* timeDelay */ struct timerequest *timeDelayAsync( secs, micros, unit, tr ) ULONG secs, micros; ULONG unit; register struct timerequest *tr; { if( !tr ) { #ifdef GIMME_WIMPY if( unit != UNIT_VBLANK && unit != UNIT_MICROHZ ) { return( NULL ); } #endif if( !secs ) { unit = UNIT_MICROHZ; /* force more efficient method */ } if( !(tr = accessTimer(unit, NULL)) ) { return( NULL ); } } if( !secs && !micros ) { micros = 1L; /* so we don't crash on zero-delay */ } tr->tr_node.io_Command = TR_ADDREQUEST; tr->tr_time.tv_secs = secs; tr->tr_time.tv_micro = micros; SendIO( tr ); return( tr ); } /* timeDelayAsync */ LONG waitTimer( tr ) struct timerequest *tr; { LONG err = 0L; #ifdef GIMME_WIMPY if( !tr ) { return( err ); } #endif err = WaitIO( tr ); tr->tr_node.io_Message.mn_Node.ln_Type = NT_FREEMSG; return( err ); } /* waitTimer */ LONG killTimeDelay( tr ) register struct timerequest *tr; { LONG err; #ifdef GIMME_WIMPY if( !tr ) { return( 0L ); } #endif Forbid(); if( tr->tr_node.io_Message.mn_Node.ln_Type == NT_MESSAGE ) { if( err = AbortIO(tr) ) { Permit(); return( err ); } Remove( tr ); tr->tr_node.io_Message.mn_Node.ln_Type = NT_FREEMSG; } Permit(); return( 0L ); } /* killTimeDelay */ short getSysTime( secs, micros, mytr ) ULONG *secs, *micros; struct timerequest *mytr; { register struct timerequest *tr; if( mytr ) { tr = mytr; } else { if( !(tr = accessTimer(UNIT_MICROHZ, NULL)) ) { return( -1 ); } } tr->tr_node.io_Command = TR_GETSYSTIME; DoIO( tr ); tr->tr_node.io_Message.mn_Node.ln_Type = NT_FREEMSG; if( secs ) { *secs = tr->tr_time.tv_secs; } if( micros ) { *micros = tr->tr_time.tv_micro; } if( !mytr ) { releaseTimer( tr, NULL ); } return( 0 ); } /* getSysTime */ short setSysTime( secs, micros, mytr ) ULONG secs, micros; struct timerequest *mytr; { register struct timerequest *tr; if( mytr ) { tr = mytr; } else { if( !(tr = accessTimer(UNIT_MICROHZ, NULL)) ) { return( -1 ); } } tr->tr_node.io_Command = TR_SETSYSTIME; tr->tr_time.tv_secs = secs; tr->tr_time.tv_micro = micros; DoIO( tr ); tr->tr_node.io_Message.mn_Node.ln_Type = NT_FREEMSG; if( !mytr ) { releaseTimer( tr, NULL ); } return( 0 ); } /* setSysTime */ SHAR_EOF cat << \SHAR_EOF > window.c /* * FILE: window.c * Support routines for dynamic (de)allocation of (new)windows. * * Public Domain, but keep my name in it as the original author. * 31-Aug-88 Jan Sven Trabandt first release version */ #define I_AM_WINDOW #include "gimmelib/gimmefuncs.h" #include "gimmelib/window.h" #include <graphics/gfxbase.h> extern struct GfxBase *GfxBase; struct NewWindow *gimmeNewWindow( title, screen, leftedge, topedge, IDCMPflags, flags ) UBYTE *title; struct Screen *screen; SHORT leftedge, topedge; ULONG IDCMPflags, flags; { register struct NewWindow *nw; nw = (struct NewWindow *) AllocMem( (ULONG)sizeof(struct NewWindow), MEMF_PUBLIC | MEMF_CLEAR ); if( !nw ) { return( NULL ); } nw->DetailPen = GNW_DETAIL_PEN; nw->BlockPen = GNW_BLOCK_PEN; nw->IDCMPFlags= IDCMPflags; nw->Flags = flags; nw->Title = title; nw->MinWidth = GNW_MIN_WIDTH; nw->MinHeight = GNW_MIN_HEIGHT; nw->LeftEdge = leftedge; nw->TopEdge = topedge; if( screen ) { nw->Type = CUSTOMSCREEN; nw->Screen = screen; nw->MaxWidth = screen->Width; nw->MaxHeight = screen->Height; } else { nw->Type = WBENCHSCREEN; nw->MaxWidth = GfxBase->NormalDisplayColumns; nw->MaxHeight = GfxBase->NormalDisplayRows; } nw->Width = nw->MaxWidth - nw->LeftEdge; nw->Height = nw->MaxHeight - nw->TopEdge; return( nw ); } /* gimmeNewWindow */ short getRidOfNewWindow( nw ) struct NewWindow *nw; { #ifdef GIMME_WIMPY if( !nw ) { return( -1 ); } #endif FreeMem( nw, (ULONG)sizeof(struct NewWindow) ); return( 0 ); } /* getRidOfNewWindow */ struct Window *gimmeWindow( nw, depth, width, height ) struct NewWindow *nw; SHORT depth, width, height; { struct Window *window; struct NewWindow *mynw; if( !(mynw = nw) ) { nw = gimmeNewWindow( NULL, NULL, 0, 1, IDCMP_DEFAULT, FLAGS_DEFAULT ); } for( ;; ) { /* dummy loop with break at end */ if( nw ) { if( nw->Flags & SUPER_BITMAP ) { if( !(nw->BitMap = gimmeBitMap(depth, width, height)) ) { break; } } window = OpenWindow( nw ); if( !window ) { if( nw->Flags & SUPER_BITMAP ) { getRidOfBitMap( nw->BitMap ); } } else { window->UserData = (BYTE *) nw->BitMap; } } break; } /* for */ if( !mynw && nw ) { getRidOfNewWindow( nw ); } return( window ); } /* gimmeWindow */ short getRidOfWindow( window ) struct Window *window; { struct BitMap *bm = NULL; struct IntuiMessage *imsg; #ifdef GIMME_WIMPY if( !window ) { return( -1 ); } #endif if( window->Flags & SUPER_BITMAP ) { bm = (struct BitMap *) window->UserData; } if( window->MenuStrip ) { ClearMenuStrip( window ); } while( imsg = (struct IntuiMessage *) GetMsg(window->UserPort) ) { ReplyMsg( imsg ); } /* while */ CloseWindow( window ); if( bm ) { getRidOfBitMap( bm ); } } /* getRidOfWindow */ 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.