page@swan.ulowell.edu (Bob Page) (12/02/88)
Submitted-by: oscvax!jan@uunet.UU.NET (Jan Sven Trabandt) Posting-number: Volume 2, Issue 78 Archive-name: libraries/gimme.5 # 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: # globals.c # graph.c # inputhand.c # intuistuff.c # keyboard.c # memchain.c # menu.c # menustuff.c # message.c # This archive created: Thu Dec 1 19:52:10 1988 cat << \SHAR_EOF > globals.c /* * FILE: globals.c * Some global declarations. * This allows inclusion of <gimmelib/gimmeall.h> without linking in entire * files containing global variables unnecessarily. * * Public Domain, but keep my name in it as the original author. * 31-Aug-88 Jan Sven Trabandt first release version */ #define I_AM_GIM_GLOBALS #include "gimmelib/requester.h" #include "gimmelib/scrollbar.h" /* generally usefull stuff */ struct TextAttr gimMyFont = { (STRPTR) "topaz.font", TOPAZ_EIGHTY, FS_NORMAL, FPF_ROMFONT }; /* for requester.c */ UBYTE *gimAutReqPostext = (UBYTE *) GAR_POSTEXT; UBYTE *gimAutReqNegtext = (UBYTE *) GAR_NEGTEXT; /* for scrollbar.c */ USHORT gimDataOneScrollUp[] = { 0xffff, 0xffff, 0xfe7f, 0xfdbf, 0xfbdf, 0xf7ef, 0xeff7, 0xdffb, 0xffff }; USHORT gimDataOneScrollDown[] = { 0xffff, 0xdffb, 0xeff7, 0xf7ef, 0xfbdf, 0xfdbf, 0xfe7f, 0xffff, 0xffff }; USHORT gimDataOneScrollLeft[] = { 0xffff, 0xffcf, 0xff3f, 0xfcff, 0xf3ff, 0xfcff, 0xff3f, 0xffcf, 0xffff }; USHORT gimDataOneScrollRight[] = { 0xffff, 0xf3ff, 0xfcff, 0xff3f, 0xffcf, 0xff3f, 0xfcff, 0xf3ff, 0xffff }; SHAR_EOF cat << \SHAR_EOF > graph.c /* * FILE: graph.c * Support routines for creating and manipulating graphs. * * Public Domain, but keep my name in it as the original author. * 31-Oct-88 Jan Sven Trabandt added to gimme.lib */ #define I_AM_GRAPH #include "gimmelib/gimmefuncs.h" #include "gimmelib/graph.h" #include "gimmelib/postext.h" #include <clib/macros.h> /* macros for internal scaling */ #define SCALEUP(x) ((long)(x) << SCALE) /* x * 2^SCALE */ #define SCALEDN(x) ((long)(x) >> SCALE) /* x / 2^SCALE */ /* macros to translate pixel offset from origin to pixel offset in rastport */ #define TRANSX(gr,off) ((short)((gr)->X.origin + (off))) #define TRANSY(gr,off) ((short)((gr)->Y.origin - (off))) /* leeways for titles */ #define XLEEWAY 4 #define YLEEWAY 3 #define TOLERANCE 2 /* pixel tolerance for fancy auto label */ /* internal flags for graphWriteLabel */ #define GWL_RESERVED_VAL (0x0000ffffL) /* lower short reserved for value */ #define GWL_NO_HIGH (1L << 16) /* for internal use only!! */ /* forward declarations */ static SHORT coordToOffset(); static SHORT offsetToCoord(); static VOID initAxis(); static SHORT updateCoord(); static VOID doBlock(); GRAPH *gimmeGraph( newgr, bm, areainfo, tmpras ) register NEWGRAPH *newgr; struct BitMap *bm; struct AreaInfo *areainfo; struct TmpRas *tmpras; { register GRAPH *gr; void *mymh = NULL; UBYTE *raster; SHORT width, height; #ifdef GIMME_WIMPY if( !newgr ) { return( NULL ); } #endif if( !bm && (!newgr->rp || !newgr->rp->BitMap) ) { return( NULL ); } gr = (GRAPH *) chainAllocMem( &mymh, (ULONG)sizeof(GRAPH), MEMF_PUBLIC | MEMF_CLEAR ); if( !gr ) { return( NULL ); } if( !newgr->rp ) { InitRastPort( &gr->rp ); } else { gr->rp = *newgr->rp; /* copy struct */ if( newgr->rp->Layer ) { gr->rp.Layer = chainAllocMem( &mymh, (ULONG)sizeof(struct Layer), MEMF_PUBLIC | MEMF_CLEAR ); if( !gr->rp.Layer ) { chainFreeMem( mymh ); return( NULL ); } *gr->rp.Layer = *newgr->rp->Layer; /* copy struct */ gr->rp.Layer->rp = &gr->rp; /* make this layer come back */ } } if( bm ) { gr->rp.BitMap = bm; } gr->title = newgr->title; gr->xtitle = newgr->xtitle; gr->ytitle = newgr->ytitle; gr->FPen = newgr->FPen; gr->BPen = newgr->BPen; gr->AxesPen = newgr->AxesPen; gr->XlabPen = gr->YlabPen = gr->AxesPen; gr->TitlePen = newgr->TitlePen; gr->XtitlePen = gr->YtitlePen = gr->TitlePen; gr->flags = newgr->flags; gr->ctlflags = newgr->ctlflags; if( newgr->titleta ) { gr->titletf = gimmeFont( newgr->titleta ); } if( newgr->xta ) { gr->xlabtf = gr->xtf = gimmeFont( newgr->xta ); } if( newgr->yta ) { gr->ylabtf = gr->ytf = gimmeFont( newgr->yta ); } if( !(gr->ctlflags & GGR_NOCLEARSTART) ) { SetRast( &gr->rp, (long) gr->BPen ); } initAxis( gr, &gr->X, &newgr->X ); initAxis( gr, &gr->Y, &newgr->Y ); SetAPen( &gr->rp, (long) gr->FPen ); SetBPen( &gr->rp, (long) gr->BPen ); SetDrMd( &gr->rp, (ULONG) JAM1 ); if( newgr->flags & (GGR_FILLTOX | GGR_FILLTOY) ) { if( areainfo ) { gr->rp.AreaInfo = areainfo; } else if( !gr->rp.AreaInfo ) { gr->rp.AreaInfo = chainAllocMem( &mymh, (ULONG)sizeof(struct AreaInfo) + 5 * 2 * sizeof(LONG), MEMF_PUBLIC | MEMF_CLEAR ); if( !gr->rp.AreaInfo ) { chainFreeMem( mymh ); return( NULL ); } InitArea( gr->rp.AreaInfo, (SHORT *)(gr->rp.AreaInfo + 1), 5L ); } if( tmpras ) { gr->rp.TmpRas = tmpras; } else if( !gr->rp.TmpRas ) { gr->rp.TmpRas = chainAllocMem( &mymh, (ULONG)sizeof(struct TmpRas), MEMF_PUBLIC | MEMF_CLEAR ); if( !gr->rp.TmpRas ) { chainFreeMem( mymh ); return( NULL ); } width = gr->rp.BitMap->BytesPerRow << 3; height = gr->rp.BitMap->Rows; raster = chainAllocMem( &mymh, (long)RASSIZE((long)width, (long)height), MEMF_CHIP | MEMF_CLEAR ); if( !raster ) { chainFreeMem( mymh ); return( NULL ); } InitTmpRas( gr->rp.TmpRas, raster, (long)RASSIZE((long)width, (long)height) ); } } if( !(gr->ctlflags & GGR_NOLABELS) ) { drawGraphAxes( gr ); } if( gr->ctlflags & (GGR_INITPOINT | GGR_INITORIGIN) ) { gr->points = 1; } else { gr->points = 0; } gr->memhead = mymh; return( gr ); } /* gimmeGraph */ short getRidOfGraph( gr ) GRAPH *gr; { #ifdef GIMME_WIMPY if( !gr ) { return( -1 ); } #endif if( gr->ctlflags & GGR_CLEARONEND ) { clearGraph( gr ); } if( gr->ytf ) { getRidOfFont( gr->ytf ); } if( gr->xtf ) { getRidOfFont( gr->xtf ); } if( gr->titletf ) { getRidOfFont( gr->titletf ); } chainFreeMem( gr->memhead ); return( 0 ); } /* getRidOfGraph */ VOID clearGraph( gr ) register GRAPH *gr; { BYTE fpen, bpen, axespen, titlepen; BYTE xlabpen, ylabpen, xtitlepen, ytitlepen; if( !(gr->ctlflags & GGR_NOCLEARSTART) ) { SetRast( &gr->rp, (long) gr->BPen ); } else { fpen = gr->FPen; bpen = gr->BPen; axespen = gr->AxesPen; titlepen = gr->TitlePen; xlabpen = gr->XlabPen; ylabpen = gr->YlabPen; xtitlepen = gr->XtitlePen; ytitlepen = gr->YtitlePen; gr->FPen = bpen; gr->AxesPen = bpen; gr->TitlePen = bpen; gr->XlabPen = bpen; gr->YlabPen = bpen; gr->XtitlePen = bpen; gr->YtitlePen = bpen; SetAPen( &gr->rp, (long) bpen ); RectFill( &gr->rp, (long) TRANSX(gr,1), (long) TRANSY(gr,gr->Y.size), (long) TRANSX(gr,gr->X.size), (long) TRANSY(gr,1) ); if( !(gr->ctlflags & GGR_NOLABELS) ) { drawGraphAxes( gr ); } gr->FPen = fpen; gr->AxesPen = axespen; gr->TitlePen = titlepen; gr->XlabPen = xlabpen; gr->YlabPen = ylabpen; gr->XtitlePen = xtitlepen; gr->YtitlePen = ytitlepen; } } /* clearGraph */ VOID resetGraph( gr ) register GRAPH *gr; { clearGraph( gr ); gr->X.low = gr->X.flow; gr->X.high = gr->X.fhigh; gr->X.lastdata = gr->X.fdata; gr->X.lastoff = gr->X.foff; gr->Y.low = gr->Y.flow; gr->Y.high = gr->Y.fhigh; gr->Y.lastdata = gr->Y.fdata; gr->Y.lastoff = gr->Y.foff; if( gr->ctlflags & (GGR_INITPOINT | GGR_INITORIGIN) ) { gr->points = 1; } else { gr->points = 0; } if( !(gr->ctlflags & GGR_NOLABELS) ) { drawGraphAxes( gr ); } } /* resetGraph */ VOID drawGraphAxesOnly( gr ) register GRAPH *gr; { SHORT maxrastlen, maxlen; SetAPen( &gr->rp, (long) gr->AxesPen ); Move( &gr->rp, (long) TRANSX(gr,0), (long) TRANSY(gr,gr->Y.size) ); Draw( &gr->rp, (long) TRANSX(gr,0), (long) TRANSY(gr,0) ); Draw( &gr->rp, (long) TRANSX(gr,gr->X.size), (long) TRANSY(gr,0) ); SetAPen( &gr->rp, (long) gr->FPen ); } /* drawGraphAxesOnly */ SHORT drawGraphAxes( gr ) register GRAPH *gr; { SHORT maxrastlen, maxlen; SHORT yoff; ULONG flags; drawGraphAxesOnly( gr ); maxrastlen = graphWriteLabel( gr, GWL_XAXIS, gr->X.low, gr->X.high, gr->X.step ); maxlen = graphWriteLabel( gr, GWL_YAXIS, gr->Y.low, gr->Y.high, gr->Y.step ); drawGraphTitle( gr, gr->X.size >> 1, gr->Y.size + YLEEWAY, GPT_XCENTRE | GPT_YBOTTOM ); yoff = - (YLEEWAY << 1); if( !(gr->ctlflags & GGR_NOLABELS) ) { yoff -= (gr->xlabtf ? gr->xlabtf->tf_YSize : gr->rp.TxHeight); } drawGraphXtitle( gr, gr->X.size >> 1, yoff, GPT_XCENTRE | GPT_YTOP ); flags = GPT_XCENTRE | GPT_YBOTTOM | GPT_YUPWARDS; if( (gr->ctlflags & GGR_HIRES) && !(gr->ctlflags & GGR_INTERLACE) ) { flags |= GPT_XTHICKEN; } drawGraphYtitle( gr, -maxlen - XLEEWAY*2, gr->Y.size >> 1, flags ); if( maxlen > maxrastlen ) { maxrastlen = maxlen; } return( maxrastlen ); } /* drawGraphAxes */ VOID drawGraphTitle( gr, xoff, yoff, myflags ) register GRAPH *gr; SHORT xoff, yoff; ULONG myflags; { struct TextFont *tf; if( gr->title ) { tf = gr->rp.Font; if( gr->titletf ) { SetFont( &gr->rp, gr->titletf ); } SetAPen( &gr->rp, (long) gr->TitlePen ); positionText( &gr->rp, myflags, gr->title, 0L, TRANSX(gr,xoff), TRANSY(gr,yoff) ); SetAPen( &gr->rp, (long) gr->FPen ); if( gr->titletf && tf ) { SetFont( &gr->rp, tf ); } } } /* drawGraphTitle */ VOID drawGraphXtitle( gr, xoff, yoff, myflags ) register GRAPH *gr; SHORT xoff, yoff; ULONG myflags; { struct TextFont *tf; if( gr->xtitle ) { tf = gr->rp.Font; if( gr->xtf ) { SetFont( &gr->rp, gr->xtf ); } SetAPen( &gr->rp, (long) gr->XtitlePen ); positionText( &gr->rp, myflags, gr->xtitle, 0L, TRANSX(gr,xoff), TRANSY(gr,yoff) ); SetAPen( &gr->rp, (long) gr->FPen ); if( gr->xtf && tf ) { SetFont( &gr->rp, tf ); } } } /* drawGraphXtitle */ VOID drawGraphYtitle( gr, xoff, yoff, myflags ) register GRAPH *gr; SHORT xoff, yoff; ULONG myflags; { SHORT destx, desty; struct TextFont *tf; if( gr->ytitle ) { tf = gr->rp.Font; if( gr->ytf ) { SetFont( &gr->rp, gr->ytf ); } SetAPen( &gr->rp, (long) gr->YtitlePen ); positionText( &gr->rp, myflags, gr->ytitle, 0L, TRANSX(gr,xoff), TRANSY(gr,yoff) ); SetAPen( &gr->rp, (long) gr->FPen ); if( gr->ytf && tf ) { SetFont( &gr->rp, tf ); } } } /* drawGraphYtitle */ static SHORT coordToOffset( axis, coord ) register AXIS *axis; SHORT coord; { if( axis->scale <= 0 ) { return( SCALEUP(coord - axis->low) / -axis->scale ); } else { return( SCALEDN((coord - axis->low) * axis->scale) ); } } /* coordToOffset */ static SHORT offsetToCoord( axis, offset ) register AXIS *axis; SHORT offset; { SHORT coord; if( axis->scale <= 0 ) { coord = SCALEDN(offset * -axis->scale); } else { /* offset in "window" belongs to next higher coordinate */ coord = (SCALEUP(offset) + axis->scale - 1) / axis->scale; } return( axis->low + coord ); } /* offsetToCoord */ /* internal use only!! * initialize a graph's axis given a new axis structure static VOID initAxis( gr, axis, nax ) GRAPH *gr; register AXIS *axis; register NEWAXIS *nax; { SHORT temp; SHORT amt; ULONG flags; if( axis == &gr->X ) { flags = gr->flags & GGR_X_FLAGS; } else { flags = gr->flags & GGR_Y_FLAGS; } axis->origin = nax->origin; axis->size = nax->size; axis->flow = axis->low = nax->low; axis->step = nax->step; axis->labnum = nax->labnum; if( !nax->labdenom ) { /* to avoid divide by zero!! */ axis->labnum = 1; axis->labdenom = 1; } else { axis->labdenom = nax->labdenom; } amt = nax->amt; if( flags & (GGR_X_SPACING | GGR_Y_SPACING) ) { if( !amt ) { ++amt; } axis->scale = SCALEUP(amt); temp = axis->size; do { axis->high = offsetToCoord( axis, temp ); axis->usesize = coordToOffset( axis, axis->high ); } while( axis->usesize > temp-- ); } else { if( flags & (GGR_X_INTERVALS | GGR_Y_INTERVALS) ) { if( amt <= 0 ) { amt = 5; } axis->high = axis->low + amt; } else { /* if( flags & (GGR_X_MAX | GGR_Y_MAX) ) */ if( amt < axis->low ) { amt = axis->low + 5; } axis->high = amt; } temp = axis->high - axis->low; if( temp >= nax->size ) { axis->scale = - ( SCALEUP(temp) / axis->size ); temp = SCALE - 1; while( (axis->usesize = coordToOffset(axis, axis->high)) > axis->size ) { if( temp < 0 ) break; axis->scale -= SCALEUP(5) >> temp; --temp; } /* while */ if( flags & (GGR_X_INTEGRAL | GGR_DELTAX | GGR_Y_INTEGRAL | GGR_DELTAY) ) { if( (temp = SCALEUP(SCALEDN(-axis->scale))) < -axis->scale ) { axis->scale = -SCALEUP( SCALEDN(-axis->scale) + 1 ); } else { axis->scale = -temp; } } } else { axis->scale = SCALEUP(axis->size) / temp; if( flags & (GGR_X_INTEGRAL | GGR_DELTAX | GGR_Y_INTEGRAL | GGR_DELTAY) ) { axis->scale = SCALEUP( SCALEDN(axis->scale) ); } axis->usesize = coordToOffset( axis, axis->high ); } } axis->fhigh = axis->high; if( gr->ctlflags & GGR_INITPOINT ) { axis->lastdata = nax->initpt; axis->lastoff = coordToOffset( axis, axis->lastdata ); } else { /* if( gr->ctlflags & GGR_INITORIGIN ) */ axis->lastdata = axis->low; axis->lastoff = 1; } axis->fdata = axis->lastdata; axis->foff = axis->lastoff; if( !axis->scale ) { axis->scale = 1; /* to avoid divide by zero!! */ } } /* initAxis */ SHORT graphWriteLabel( gr, myflags, first, last, step ) register GRAPH *gr; ULONG myflags; SHORT first, last; SHORT step; { AXIS *axis; SHORT full, spacing; SHORT low, high; SHORT maxrlen = 0, len; SHORT coord, loop; SHORT x, y; struct TextFont *tf; BYTE xpen, ypen; BYTE bpen, dmode; if( !(myflags & GWL_NO_HIGH) ) { if( myflags & (GWL_CLEAR_OLD | GWL_CLEAR_ONLY) ) { if( myflags & GWL_XAXIS ) { xpen = gr->XlabPen; gr->XlabPen = gr->BPen; } else { ypen = gr->YlabPen; gr->YlabPen = gr->BPen; } maxrlen = graphWriteLabel( gr, myflags & ~(GWL_CLEAR_OLD | GWL_CLEAR_ONLY), first, last, step ); if( myflags & GWL_XAXIS ) { gr->XlabPen = xpen; } else { gr->YlabPen = ypen; } if( myflags & GWL_CLEAR_ONLY ) { return( maxrlen ); } } tf = gr->rp.Font; bpen = gr->rp.BgPen; dmode = gr->rp.DrawMode; if( myflags & GWL_XAXIS ) { SetAPen( &gr->rp, (long) gr->XlabPen ); if( gr->xlabtf ) { SetFont( &gr->rp, gr->xlabtf ); } } else { /* else YAXIS */ SetAPen( &gr->rp, (long) gr->YlabPen ); if( gr->ylabtf ) { SetFont( &gr->rp, gr->ylabtf ); } } } if( step > 0 ) { /* if we want even-spaced labels */ for( loop = first; loop <= last; loop += step ) { if( myflags & GWL_YAXIS) { y = coordToOffset(&gr->Y, loop); WritePixel( &gr->rp, (long)TRANSX(gr,-1), (long)TRANSY(gr,y) ); len = positionText( &gr->rp, GPT_XRIGHT | GPT_YCENTREBASE, NULL, (long) (loop) * gr->Y.labnum / gr->Y.labdenom, TRANSX(gr,-XLEEWAY), TRANSY(gr,y) ); } else { /* x-axis */ x = coordToOffset(&gr->X, loop); WritePixel( &gr->rp, (long)TRANSX(gr,x), (long)TRANSY(gr,-1) ); len = positionText( &gr->rp, GPT_XCENTRE | GPT_YTOP, NULL, (long) (loop) * gr->X.labnum / gr->X.labdenom, TRANSX(gr,x), TRANSY(gr,-YLEEWAY) ); } maxrlen = MAX(maxrlen, len); } /* for */ } else { if( myflags & GWL_YAXIS) { high = coordToOffset(&gr->Y, last); if( !(myflags & GWL_NO_HIGH) ) { WritePixel( &gr->rp, (long)TRANSX(gr,-1), (long)TRANSY(gr,high) ); maxrlen = positionText(&gr->rp, GPT_XRIGHT | GPT_YCENTREBASE, NULL, (long) (last) * gr->Y.labnum / gr->Y.labdenom, TRANSX(gr,-XLEEWAY), TRANSY(gr,high) ); } low = coordToOffset(&gr->Y, first); WritePixel( &gr->rp, (long)TRANSX(gr,-1), (long)TRANSY(gr,low) ); positionText( &gr->rp, GPT_XRIGHT | GPT_YCENTREBASE, NULL, (long) (first) * gr->Y.labnum / gr->Y.labdenom, TRANSX(gr,-XLEEWAY), TRANSY(gr,low) ); full = gr->rp.TxHeight; axis = &gr->Y; } else { /* x-axis */ high = coordToOffset(&gr->X, last); if( !(myflags & GWL_NO_HIGH) ) { WritePixel( &gr->rp, (long)TRANSX(gr,high), (long)TRANSY(gr,-1) ); maxrlen = positionText( &gr->rp, GPT_XCENTRE| GPT_YTOP, NULL, (long) (last) * gr->X.labnum / gr->X.labdenom, TRANSX(gr,high), TRANSY(gr,-YLEEWAY) ); full = maxrlen; myflags = (myflags & ~0xFFFFL) | full; } else { full = myflags & 0xFFFFL; } low = coordToOffset(&gr->X, first); WritePixel( &gr->rp, (long)TRANSX(gr,low), (long)TRANSY(gr,-1) ); positionText( &gr->rp, GPT_XCENTRE | GPT_YTOP, NULL, (long) (first) * gr->X.labnum / gr->X.labdenom, TRANSX(gr,low), TRANSY(gr,-YLEEWAY) ); axis = &gr->X; } spacing = full << 1; low += spacing; coord = offsetToCoord( axis, low ); low = coordToOffset( axis, coord ); if( high - low >= spacing - TOLERANCE ) { graphWriteLabel( gr, myflags | GWL_NO_HIGH, coord, last, step ); } } if( !(myflags & GWL_NO_HIGH) ) { SetAPen( &gr->rp, (long) gr->FPen ); if( tf ) { SetFont( &gr->rp, tf ); } } return( maxrlen ); } /* graphWriteLabel */ VOID addToGraph( gr, x, y ) register GRAPH *gr; SHORT x, y; { SHORT amt; SHORT newX, newY; newX = updateCoord( gr, &gr->X, x ); newY = updateCoord( gr, &gr->Y, y ); SetAPen( &gr->rp, (long) gr->FPen ); if( !(gr->ctlflags & GGR_NOCONNECTLINE) ) { Move( &gr->rp, (long) TRANSX(gr,gr->X.lastoff), (long) TRANSY(gr,gr->Y.lastoff) ); Draw( &gr->rp, (long)TRANSX(gr,newX), (long)TRANSY(gr,newY) ); } else { Move( &gr->rp, (long)TRANSX(gr,newX), (long)TRANSY(gr,newY) ); } if( gr->flags & GGR_LINETOX ) { Move( &gr->rp, (long)TRANSX(gr,newX), (long)TRANSY(gr,newY) ); Draw( &gr->rp, (long)TRANSX(gr,newX), (long)TRANSY(gr,1) ); } if( gr->flags & GGR_LINETOY ) { Move( &gr->rp, (long)TRANSX(gr,newX), (long)TRANSY(gr,newY) ); Draw( &gr->rp, (long)TRANSX(gr,1), (long)TRANSY(gr,newY) ); } if( gr->flags & GGR_FILLTOX ) { doBlock( &gr->rp, TRANSX(gr, gr->X.lastoff), TRANSY(gr, 1), TRANSX(gr, gr->X.lastoff), TRANSY(gr, gr->Y.lastoff), TRANSX(gr, newX), TRANSY(gr, newY), TRANSX(gr, newX), TRANSY(gr, 1) ); } if( gr->flags & GGR_FILLTOY ) { doBlock( &gr->rp, TRANSX(gr, 1), TRANSY(gr, gr->Y.lastoff), TRANSX(gr,gr->X.lastoff), TRANSY(gr, gr->Y.lastoff), TRANSX(gr, newX), TRANSY(gr, newY), TRANSX(gr, 1), TRANSY(gr, newY) ); } if( gr->flags & GGR_BLACKTOX ) { SetAPen( &gr->rp, (long) gr->BPen ); Move( &gr->rp, (long) TRANSX(gr, gr->X.lastoff),(long)TRANSY(gr, 1) ); Draw( &gr->rp, (long) TRANSX(gr, gr->X.lastoff), (long) TRANSY(gr, gr->Y.lastoff) ); SetAPen( &gr->rp, (long) gr->FPen ); } if( gr->flags & GGR_BLACKTOY ) { SetAPen( &gr->rp, (long) gr->BPen ); Move(&gr->rp, (long) TRANSX(gr, 1),(long)TRANSY(gr, gr->Y.lastoff) ); Draw(&gr->rp, (long) TRANSX(gr, gr->X.lastoff), (long) TRANSY(gr, gr->Y.lastoff) ); SetAPen( &gr->rp, (long) gr->FPen ); } gr->X.lastoff = newX; gr->Y.lastoff = newY; ++gr->points; } /* addToGraph */ /* internal use only!! * add a coordinate to an axis, doing the actual scrolling if necessary * and updating some AXIS fields * * note: truncates to the rectangle defined by the origin and the axis' size. * * returns the standard pixel offset for the coordinate static SHORT updateCoord( gr, axis, coord ) GRAPH *gr; register AXIS *axis; SHORT coord; { SHORT offset; SHORT amt; LONG Xamt, Yamt; ULONG flags, awlflags; if( axis == &gr->X ) { flags = gr->flags & GGR_X_FLAGS; } else { flags = gr->flags & GGR_Y_FLAGS; } if( flags & (GGR_DELTAX | GGR_DELTAY) ) { axis->lastdata += coord; offset = coordToOffset( axis, axis->lastdata ); if( offset > axis->usesize ) { if( axis == &gr->X ) { Xamt = amt = offset - axis->lastoff; Yamt = 0L; } else { Xamt = 0L; Yamt = amt = offset - axis->lastoff; } ScrollRaster( &gr->rp, (long) Xamt, (long) Yamt, (long) TRANSX(gr,1), (long) TRANSY(gr,gr->Y.size), (long) TRANSX(gr,axis->size), (long) TRANSY(gr,1) ); awlflags = (axis == &gr->X) ? GWL_XAXIS : GWL_YAXIS; if( !(gr->ctlflags & GGR_NOLABELS) ) { graphWriteLabel( gr, awlflags | GWL_CLEAR_ONLY, axis->low, axis->high, axis->step ); } axis->low += coord; axis->high += coord; /* drawGraphAxesOnly( gr ); */ if( !(gr->ctlflags & GGR_NOLABELS) ) { graphWriteLabel( gr, awlflags, axis->low, axis->high, axis->step ); } offset = axis->lastoff; axis->lastoff -= amt; } } else { offset = coordToOffset( axis, coord ); if( offset < 0 ) { offset = 0; } else if( offset > axis->size ) { offset = axis->size; } axis->lastdata = coord; } return( offset ); } /* updateCoord */ /* internal use only!! * do an area fill on the 4 pairs of coordinates, * clipped to the rastport's bitmap size * NOTE: the TmpRas should be (at least) the same size as this bitmap static VOID doBlock( rp, x1, y1, x2, y2, x3, y3, x4, y4 ) register struct RastPort *rp; SHORT x1, y1, x2, y2, x3, y3, x4, y4; { SHORT width, height; width = rp->BitMap->BytesPerRow << 3; height = rp->BitMap->Rows; if( x1 < 0 ) x1 = 0; else if( x1 > width ) x1 = width; if( x2 < 0 ) x2 = 0; else if( x2 > width ) x2 = width; if( x3 < 0 ) x3 = 0; else if( x3 > width ) x3 = width; if( x4 < 0 ) x4 = 0; else if( x4 > width ) x4 = width; if( x1 == x3 ) return; if( y1 < 0 ) y1 = 0; else if( y1 > height ) y1 = height; if( y2 < 0 ) y2 = 0; else if( y2 > height ) y2 = height; if( y3 < 0 ) y3 = 0; else if( y3 > height ) y3 = height; if( y4 < 0 ) y4 = 0; else if( y4 > height ) y4 = height; if( y1 == y3 ) return; AreaMove( rp, (long) x1, (long) y1 ); AreaDraw( rp, (long) x2, (long) y2 ); AreaDraw( rp, (long) x3, (long) y3 ); AreaDraw( rp, (long) x4, (long) y4 ); AreaEnd( rp ); } /* doBlock */ SHAR_EOF cat << \SHAR_EOF > inputhand.c /* * FILE: inputhand.c * Support routines for installing/removing an input handler. * * Public Domain, but keep my name in it as the original author. * 31-Oct-88 Jan Sven Trabandt added to gimme.lib */ #define I_AM_INPUTHAND #include "gimmelib/gimmefuncs.h" struct IOStdReq *addInputHandler( handler, data, pri, name ) void (*handler)(); APTR data; BYTE pri; UBYTE *name; { struct MsgPort *port; struct IOStdReq *ioreq; struct Interrupt *handint; #ifdef GIMME_WIMPY if( !handler ) { return( NULL ); } #endif if( !(port = CreatePort(NULL, 0L)) ) { return( NULL ); } if( !(ioreq = CreateStdIO(port)) ) { DeletePort( port ); return( NULL ); } if( !(handint = AllocMem((ULONG)sizeof(struct Interrupt), MEMF_PUBLIC | MEMF_CLEAR)) ) { DeleteStdIO( ioreq ); DeletePort( port ); return( NULL ); } handint->is_Data = data; handint->is_Code = handler; handint->is_Node.ln_Type = NT_MESSAGE; handint->is_Node.ln_Pri = pri; handint->is_Node.ln_Name = (char *) name; if( OpenDevice("input.device", 0L, ioreq, 0L) ) { FreeMem( handint, (ULONG)sizeof(struct Interrupt) ); DeleteStdIO( ioreq ); DeletePort( port ); return( NULL ); } ioreq->io_Command = IND_ADDHANDLER; ioreq->io_Data = (APTR) handint; ioreq->io_Length = sizeof(struct Interrupt); if( DoIO(ioreq) ) { CloseDevice( ioreq ); FreeMem( handint, (ULONG)sizeof(struct Interrupt) ); DeleteStdIO( ioreq ); DeletePort( port ); return( NULL ); } return( ioreq ); } /* addInputHandler */ short removeInputHandler( ioreq ) struct IOStdReq *ioreq; { #ifdef GIMME_WIMPY if( !ioreq ) { return( -1 ); } #endif ioreq->io_Command = IND_REMHANDLER; ioreq->io_Message.mn_Node.ln_Type = NT_MESSAGE; if( DoIO(ioreq) ) { return( -1 ); } CloseDevice( ioreq ); FreeMem( ioreq->io_Data, (ULONG)sizeof(struct Interrupt) ); DeletePort( ioreq->io_Message.mn_ReplyPort ); DeleteStdIO( ioreq ); return( 0 ); } /* removeInputHandler */ SHAR_EOF cat << \SHAR_EOF > intuistuff.c /* * FILE: intuistuff.c * Support routines for creating some useful intuition-type structures. * * 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 made gimmeBorder more flexible/efficient */ #define I_AM_INTUISTUFF #include "gimmelib/gimmefuncs.h" #include "gimmelib/intuistuff.h" #include "gimmelib/macros.h" /* WSL-type construct */ #define GUESS do { #define QUIF( cond ) if( cond ) break; #define ENDGUESS } while( 0 ); struct Border *gimmeBorder( mh, xsize, ysize ) void **mh; SHORT xsize, ysize; { register struct Border *bp; register SHORT *r; ULONG size; void *mymh = NULL; void **mhdr = &mymh; GUESS size = sizeof(struct Border); if( !mh ) { r = AllocMem( (ULONG)sizeof(SHORT) * 2 * 5, MEMF_PUBLIC ); QUIF( !r ); mhdr = NULL; } else { if( xsize > 0 && ysize > 0 ) { /* need room for 5 pairs of shorts as well */ size = sizeof(struct Border) + sizeof(SHORT) * 2 * 5; r = NULL; } } bp = chainAllocMem( mhdr, (ULONG) size, MEMF_CLEAR | MEMF_PUBLIC ); QUIF( !bp ); bp->FrontPen = 1; bp->DrawMode = JAM1; if( xsize > 0 && ysize > 0 ) { if( !r ) { r = (SHORT *) (bp + 1); } bp->XY = r; r[2] = r[4] = xsize - 1; r[5] = r[7] = ysize - 1; bp->Count = 5; } linkChainMem( mh, mymh ); return( bp ); ENDGUESS if( mhdr ) { chainFreeMem( mymh ); } else { if( r ) { FreeMem( r, (ULONG) sizeof(SHORT) * 2 * 5 ); } } return( NULL ); } /* gimmeBorder */ struct Image *gimmeImage( mh, depth, width, height ) void **mh; SHORT depth, width, height; { register struct Image *ip; ULONG size; /* image datasize (bytes) for allocation */ void *mymh = NULL; void **mhdr = &mymh; UBYTE planepick; GUESS if( !mh ) { mhdr = NULL; } ip = chainAllocMem( mhdr, (ULONG)sizeof(struct Image), MEMF_CLEAR | MEMF_PUBLIC ); QUIF( !ip ); ip->Width = width; ip->Height = height; ip->Depth = depth; if( depth > 0 && width > 0 && height > 0 ) { size = GIM_IMAGESIZE(depth, width, height); ip->ImageData = chainAllocMem( mhdr, size, MEMF_CLEAR|MEMF_CHIP ); QUIF( !ip->ImageData ); planepick = 1; while( --depth > 0 ) { planepick = (planepick << 1) + 1; } /* while */ ip->PlanePick = planepick; } linkChainMem( mh, mymh ); return( ip ); ENDGUESS if( mhdr ) { chainFreeMem( mymh ); } else { if( ip ) { FreeMem( ip, (ULONG)sizeof(struct Image) ); } } return( NULL ); } /* gimmeImage */ struct IntuiText *gimmeIntuiText( mh, s, textattr, width ) void **mh; UBYTE *s; struct TextAttr *textattr; SHORT width; { register struct IntuiText *itp; GUESS itp = chainAllocMem( mh, (ULONG)sizeof(struct IntuiText), MEMF_CLEAR | MEMF_PUBLIC ); QUIF( !itp ); itp->FrontPen = 1; itp->DrawMode = JAM2; itp->ITextFont = textattr; itp->IText = s; if( width > 0 ) { /* if width given, centre text */ itp->LeftEdge = (width - IntuiTextLength(itp)) >> 1; } return( itp ); ENDGUESS return( NULL ); } /* gimmeIntuiText */ SHAR_EOF cat << \SHAR_EOF > keyboard.c /* * FILE: keyboard.c * Support routines for "cooking" raw input. * * 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 deadKeyConvert( imsg, buf, bufsize, keymap ) struct IntuiMessage *imsg; UBYTE *buf; USHORT bufsize; struct KeyMap *keymap; { struct InputEvent ievent; #ifdef GIMME_WIMPY if( !imsg || !buf || bufsize < 0 ) { return( -3 ); } #endif if( imsg->Class != RAWKEY ) { return( -2 ); } ievent.ie_NextEvent = NULL; ievent.ie_Class = IECLASS_RAWKEY; ievent.ie_Code = imsg->Code; ievent.ie_Qualifier = imsg->Qualifier; ievent.ie_position.ie_addr = *((APTR *)imsg->IAddress); return( RawKeyConvert(&ievent, buf, (ULONG)bufsize, keymap) ); } /* deadKeyConvert */ SHAR_EOF cat << \SHAR_EOF > memchain.c /* * FILE: memchain.c * Support routines for chaining memory, anchored to a head which * points to the latest chunk of memory allocated. * * 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 chainAllocMem acts like normal AllocMem * if no memory-chain pointer given * parameters checked in all these functions */ #include "gimmelib/gimmefuncs.h" struct memnode { struct memnode *next; ULONG size; }; void *chainAllocMem( headptr, size, type ) struct memnode **headptr; ULONG size; ULONG type; { register struct memnode *p; if( !headptr ) { p = AllocMem( size, type ); } else { size += sizeof(struct memnode); if( p = AllocMem(size, type) ) { p->size = size; p->next = *headptr; *headptr = p; ++p; /* make p point to user's memory */ } } return( p ); } /* chainAllocMem */ VOID chainFreeMem( head ) register struct memnode *head; { struct memnode *p; while( head ) { p = head->next; FreeMem( head, head->size ); head = p; } } /* chainFreeMem */ short linkChainMem( headptr, head ) struct memnode **headptr; struct memnode *head; { register struct memnode *p; if( headptr && head ) { p = head; if( *headptr ) { for( ; p->next; p = p->next ) { } /* for */ p->next = *headptr; } *headptr = head; } return( 0 ); } /* linkChainMem */ short pluckChainMem( headptr, mem ) struct memnode **headptr; void *mem; { register struct memnode *p; struct memnode *mine; if( !headptr ) { return( -1 ); } if( mem && *headptr ) { mine = (struct memnode *)( ((UBYTE *) mem) - (ULONG)sizeof(struct memnode) ); if( mine == *headptr ) { *headptr = mine->next; } else { for( p = *headptr; p->next != mine; p = p->next ) { if( !p->next ) { return( -1 ); /* not in this chain */ } } /* for */ p->next = mine->next; } FreeMem( mine, mine->size ); } return( 0 ); } /* pluckChainMem */ SHAR_EOF cat << \SHAR_EOF > menu.c /* * FILE: menu.c * Support routines for creating menu and menu item structures. * * Public Domain, but keep my name in it as the original author. * 31-Oct-88 Jan Sven Trabandt added to gimme.lib */ #define I_AM_MENU #include "gimmelib/gimmefuncs.h" #define GIM_BUILTIN #include "gimmelib/macros.h" extern struct GfxBase *GfxBase; #define XLEEWAY 10 /* make menu item a little visually appealing */ struct Menu *gimmeMenu( mhptr, left, width, name, flags ) void **mhptr; SHORT left, width; UBYTE *name; ULONG flags; { register struct Menu *menu; if( menu = chainAllocMem(mhptr, (ULONG)sizeof(struct Menu), MEMF_PUBLIC | MEMF_CLEAR) ) { menu->LeftEdge = left; if( width >= 0 ) { menu->Width = width; } else { menu->Width = 9 * strlen( name ); } menu->Height = 9; /* currently ignored by Intuition */ menu->Flags = flags; menu->MenuName = (BYTE *) name; } return( menu ); } /* gimmeMenu */ struct MenuItem *gimmeMenuItem( mhptr, left, width, height, command, name, textattr, flags ) void **mhptr; SHORT left; SHORT width, height; BYTE command; UBYTE *name; struct TextAttr *textattr; ULONG flags; { register struct MenuItem *item; SHORT temp; void *mymh = NULL; GUESS QUIF( !mhptr ); item = chainAllocMem( &mymh, (ULONG)sizeof(struct MenuItem), MEMF_PUBLIC | MEMF_CLEAR ); QUIF( !item ); if( flags & ITEMTEXT ) { item->ItemFill = (APTR) gimmeIntuiText( &mymh, name, textattr, 0 ); QUIF( !item->ItemFill ); ((struct IntuiText *)item->ItemFill)->DrawMode |= INVERSVID; if( width < 0 ) { width = IntuiTextLength( item->ItemFill ) + XLEEWAY; } if( height < 0 ) { if( textattr ) { height = textattr->ta_YSize; } else { height = GfxBase->DefaultFont->tf_YSize; } } } else { item->ItemFill = (APTR) name; if( flags & HIGHIMAGE ) { item->SelectFill = (APTR) textattr; } if( width < 0 ) { if( (struct Image *) name ) { width = ((struct Image *)name)->Width; } if( (struct Image *) item->SelectFill ) { temp = ((struct Image *)item->SelectFill)->Width; if( temp > width ) { width = temp; } } } if( height < 0 ) { if( (struct Image *) name ) { height = ((struct Image *)name)->Height; } if( (struct Image *) item->SelectFill ) { temp = ((struct Image *)item->SelectFill)->Height; if( temp > height ) { height = temp; } } } } if( flags & CHECKIT ) { width += CHECKWIDTH; } if( flags & COMMSEQ ) { width += COMMWIDTH + 4; /* separate text/image from commseq */ } item->LeftEdge = left; item->Width = width; item->Height = height; item->Flags = flags; item->Command = command; linkChainMem( mhptr, mymh ); return( item ); ENDGUESS if( mymh ) { chainFreeMem( mymh ); } return( NULL ); } /* gimmeMenuItem */ SHAR_EOF cat << \SHAR_EOF > menustuff.c /* * FILE: menustuff.c * Support routines for dealing with menus and menuitems. * * NOTE: these routines should only be used on a menustrip that is * not attached to a window or guaranteed not to be actively used by * Intuition (eg. by using the MENUVERIFY flag). * * Public Domain, but keep my name in it as the original author. * 31-Oct-88 Jan Sven Trabandt added to gimme.lib */ #define I_AM_MENUSTUFF #include "gimmelib/gimmefuncs.h" #include "gimmelib/menustuff.h" /* internal flags: must stay within defined GMI_RESERVED bits */ #define GMI_SUBITEM (1L << 30) /* process subitem, not item */ #define GMI_DO_TOP (1L << 29) /* modify top edge */ #define GMI_DO_ME (1L << 28) /* modify mutual exclude */ #define GMI_SNEAKY (1L << 27) /* sneaky -- don't modify too much */ #define GMI_ADJUST (GMI_FIXUP | GMI_SHUFFLE) #define GMI_ADJUSTME (GMI_FIXUPME | GMI_SHUFFLEME) ULONG addMenuItem( menu, item, positem, possub, numitem, myflags ) struct Menu *menu; struct MenuItem *item; SHORT positem, possub, numitem; ULONG myflags; { register struct MenuItem *temp, **old; struct MenuItem *save, *savelast; SHORT pos, sub; SHORT top, topedge; if( !menu || !item || !numitem ) { return( MENUNULL ); } if( myflags & GMI_SUBITEM ) { old = &((struct MenuItem *)menu)->SubItem; } else { old = &menu->FirstItem; } if( myflags & GMI_ADDSUBITEM ) { if( !*old ) { /* if no items, can't put subitem */ return( MENUNULL ); } } else { /* find last item in list to be added and truncate list appropriately */ for( temp = item; temp->NextItem; temp = temp->NextItem ) { if( --numitem == 0 ) { temp->NextItem = NULL; break; } } /* for */ savelast = temp; /* save pointer to last item to be added */ if( positem == 0 || !*old ) { /* add as first (sub)item */ savelast->NextItem = *old; *old = item; if( *old && (myflags & (GMI_ADJUST|GMI_ADJUSTME|GMI_APPEAREND)) ) { pos = 0; save = item; myflags |= GMI_SNEAKY; /* careful handling */ goto calculate_adjustment_mi; } adjustMenuItems( item, savelast->NextItem, 0, 0, myflags ); return( SHIFTITEM(0) | SHIFTSUB(NOSUB) ); } } /* find the item preceding where to insert, and position# for new item */ pos = 1; for( temp = *old; temp->NextItem; temp = temp->NextItem ) { if( --positem == 0 ) { break; } ++pos; } /* for */ if( myflags & GMI_ADDSUBITEM ) { sub = ITEMNUM( addMenuItem(temp, item, possub, 0, numitem, (myflags | GMI_SUBITEM) & ~GMI_ADDSUBITEM) ); } else { savelast->NextItem = temp->NextItem; save = temp; /* save ptr to item after which to add */ if( myflags & (GMI_ADJUST | GMI_ADJUSTME) ) { calculate_adjustment_mi: {} /* calculate top edge for new item */ topedge = 0; for( temp = *old; temp; temp = temp->NextItem ) { top = temp->TopEdge + temp->Height; if( temp == save ) { if( !(myflags & GMI_SNEAKY) ) { save->NextItem = item; if( top > topedge ) { topedge = top; } } if( !(myflags & GMI_APPEAREND) ) { break; /* exit for loop */ } temp = savelast; /* skip over what we added */ } if( top > topedge ) { topedge = top; } } /* for */ adjustMenuItems( item, savelast->NextItem, topedge, pos, myflags ); } else { save->NextItem = item; } sub = NOSUB; } return( SHIFTITEM(pos) | SHIFTSUB(sub) ); } /* addMenuItem */ ULONG addMenu( menuptr, menu, posmenu, nummenu, myflags ) struct Menu **menuptr; struct Menu *menu; SHORT posmenu, nummenu; ULONG myflags; { register struct Menu *temp, **old; struct Menu *save, *savelast; SHORT pos; SHORT left, leftedge; if( !nummenu || !menuptr || !menu ) { return( MENUNULL ); } old = menuptr; /* find last menu in list to be added and truncate list appropriately */ for( temp = menu; temp->NextMenu; temp = temp->NextMenu ) { if( --nummenu == 0 ) { temp->NextMenu = NULL; break; } } /* for */ savelast = temp; /* save pointer to last menu to be added */ if( posmenu == 0 || !*old ) { /* add to front of menu strip */ savelast->NextMenu = *old; *old = menu; if( *old && (myflags & (GMI_ADJUST | GMI_APPEAREND)) ) { pos = 0; save = menu; myflags |= GMI_SNEAKY; /* careful handling */ goto calculate_adjustment_m; } adjustMenuLefts( menu, savelast->NextMenu, 0, myflags ); return( SHIFTMENU(0) | SHIFTITEM(NOITEM) | SHIFTSUB(NOSUB) ); } /* find the menu preceding where to insert, and position# for new menu */ pos = 1; for( temp = *old; temp->NextMenu; temp = temp->NextMenu ) { if( --posmenu == 0 ) { break; } ++pos; } /* for */ savelast->NextMenu = temp->NextMenu; save = temp; /* save ptr to menu after which to add */ if( myflags & (GMI_ADJUST | GMI_ADJUSTME) ) { calculate_adjustment_m: {} /* calculate left edge for new menu */ leftedge = 0; for( temp = *old; temp; temp = temp->NextMenu ) { left = temp->LeftEdge + temp->Width; if( temp == save ) { if( !(myflags & GMI_SNEAKY) ) { save->NextMenu = menu; if( left > leftedge ) { leftedge = left; } } if( !(myflags & GMI_APPEAREND) ) { break; /* exit for loop */ } temp = savelast; /* skip over what we added */ } if( left > leftedge ) { leftedge = left; } } /* for */ adjustMenuLefts( menu, savelast->NextMenu, leftedge, myflags ); } else { save->NextMenu = menu; } return( SHIFTMENU(pos) | SHIFTITEM(NOITEM) | SHIFTSUB(NOSUB) ); } /* addMenu */ struct MenuItem *removeMenuItem( menu, item, positem, possub, numitem, myflags ) struct Menu *menu; struct MenuItem *item; SHORT positem, possub, numitem; ULONG myflags; { register struct MenuItem *temp, **old; struct MenuItem *save; SHORT pos; /* position for mutual exclude */ if( !menu ) { return( NULL ); } if( myflags & GMI_SUBITEM ) { old = &((struct MenuItem *)menu)->SubItem; } else { old = &menu->FirstItem; } if( !*old || !numitem ) { /* if no menu items */ return( NULL ); } if( myflags & GMI_REMSUBITEM ) { save = item; /* don't want to check item address yet */ item = NULL; } else { if( item ) { positem = -1; } } pos = 0; temp = *old; if( temp != item && positem != 0 && temp->NextItem ) { /* find the "item" preceding where to remove */ for( ; temp->NextItem && --positem != 0; ) { ++pos; if( temp->NextItem == item ) { /* found the item */ break; } temp = temp->NextItem; /* next in loop */ if( !temp->NextItem ) { /* no more to follow so stop */ break; } } /* for */ old = &temp->NextItem; } /* now old points to a MenuItem pointer to item to be removed */ if( item && *old != item ) { /* if its not the right item */ return( NULL ); } if( myflags & GMI_REMSUBITEM ) { item = removeMenuItem( temp, save, possub, 0, numitem, (myflags | GMI_SUBITEM) & ~GMI_REMSUBITEM ); } else { if( !item ) { item = *old; } if( myflags & GMI_ADDRONLY ) { return( item ); } /* find last one to be removed */ for( temp = item; temp->NextItem; temp = temp->NextItem ) { if( --numitem == 0 ) { break; } } /* for */ *old = temp->NextItem; temp->NextItem = NULL; myflags &= ~(GMI_FIXUP | GMI_FIXUPME); if( myflags & GMI_SHUFFLE ) { myflags |= GMI_FIXUP; } if( myflags & GMI_SHUFFLEME ) { myflags |= GMI_FIXUPME; } adjustMenuItems( *old, NULL, item->TopEdge, pos, myflags ); } return( item ); } /* removeMenuItem */ struct Menu *removeMenu( menuptr, menu, posmenu, nummenu, myflags ) struct Menu **menuptr; struct Menu *menu; SHORT posmenu, nummenu; ULONG myflags; { register struct Menu *temp, **old; if( !nummenu || !menuptr || !*menuptr ) { return( NULL ); } old = menuptr; if( menu ) { posmenu = -1; } temp = *old; if( temp != menu && posmenu != 0 && temp->NextMenu ) { /* find the menu preceding where to remove */ for( ; temp->NextMenu && --posmenu != 0; ) { if( temp->NextMenu == menu ) { /* found the menu */ break; } temp = temp->NextMenu; /* next in loop */ if( !temp->NextMenu ) { /* no more to follow so stop */ break; } } /* for */ old = &temp->NextMenu; } /* now old points to a Menu pointer to menu to be removed */ if( menu && *old != menu ) { /* if its not the right menu */ return( NULL ); } if( !menu ) { menu = *old; } if( myflags & GMI_ADDRONLY ) { return( menu ); } /* find last one to be removed */ for( temp = menu; temp->NextMenu; temp = temp->NextMenu ) { if( --nummenu == 0 ) { break; } } /* for */ *old = temp->NextMenu; temp->NextMenu = NULL; adjustMenuLefts( *old, NULL, menu->LeftEdge, myflags ); return( menu ); } /* removeMenu */ short adjustMenuItems( item, stop, topedge, meposition, myflags ) struct MenuItem *item, *stop; SHORT topedge, meposition; register ULONG myflags; { register struct MenuItem *temp; if( !(myflags & (GMI_ADJUST | GMI_ADJUSTME)) ) { return( -1 ); } if( myflags & GMI_FIXUP ) { myflags |= GMI_DO_TOP; } if( myflags & GMI_FIXUPME ) { myflags |= GMI_DO_ME; } for( temp = item; temp; temp = temp->NextItem ) { if( temp == stop ) { if( !(myflags & (GMI_SHUFFLE | GMI_SHUFFLEME)) ) { break; } myflags &= ~(GMI_DO_TOP | GMI_DO_ME); if( (myflags & GMI_SHUFFLE) && !(myflags & GMI_APPEAREND) ) { myflags |= GMI_DO_TOP; } if( myflags & GMI_SHUFFLEME ) { myflags |= GMI_DO_ME; } } if( myflags & GMI_DO_TOP ) { temp->TopEdge = topedge; } topedge += temp->Height; if( myflags & GMI_DO_ME ) { temp->MutualExclude = ~(1L << meposition); } ++meposition; } /* for */ return( 0 ); } /* adjustMenuItems */ short adjustMenuLefts( menu, stop, leftedge, myflags ) struct Menu *menu, *stop; register SHORT leftedge; ULONG myflags; { register struct Menu *temp; if( !(myflags & (GMI_ADJUST)) ) { return( -1 ); } for( temp = menu; temp; temp = temp->NextMenu ) { if( !(myflags & GMI_SHUFFLE) && temp == stop ) { break; } temp->LeftEdge = leftedge; leftedge += temp->Width; } /* for */ return( 0 ); } /* adjustMenuLefts */ SHAR_EOF cat << \SHAR_EOF > message.c /* * FILE: message.c * Support routines for dynamic (de)allocation of [extended] message structs * * 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 Message *gimmeMessage( size, replyport ) ULONG size; struct MsgPort *replyport; { struct Message *msg; #ifdef GIMME_WIMPY if( size > 0x0FFFFL ) { return( NULL ); } #endif msg = (struct Message *) AllocMem( size, MEMF_PUBLIC ); if( msg ) { msg->mn_Node.ln_Type = NT_FREEMSG; msg->mn_Node.ln_Pri = 0; msg->mn_Node.ln_Name = NULL; msg->mn_ReplyPort = replyport; msg->mn_Length = size; } return( msg ); } /* gimmeMessage */ short getRidOfMessage( msg ) struct Message *msg; { #ifdef GIMME_WIMPY if( !msg || !msg->mn_Length > 0 ) { return( -1 ); } #endif FreeMem( msg, (ULONG) msg->mn_Length ); } /* getRidOfMessage */ 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.