Path: utzoo!utgpu!jarvis.csri.toronto.edu!clyde.concordia.ca!uunet!lll-winken!uwm.edu!dogie.macc.wisc.edu!uakari.primate.wisc.edu!xanth!cs.odu.edu!Amiga-Request From: Amiga-Request@cs.odu.edu (Amiga Sources/Binaries Moderator) Newsgroups: comp.sources.amiga Subject: v90i010: plplot 2.6 - C library for making scientific plots, Part09/12 Message-ID: <10982@xanth.cs.odu.edu> Date: 14 Jan 90 23:33:18 GMT Sender: tadguy@cs.odu.edu Reply-To: Anthony M. Richardson Lines: 998 Approved: tadguy@cs.odu.edu (Tad Guy) Submitted-by: Anthony M. Richardson Posting-number: Volume 90, Issue 010 Archive-name: applications/plplot-2.6/part09 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh 'Amiga/plsupport.c' <<'END_OF_FILE' X#include "plplot.h" X#include "plamiga.h" X#include X#ifdef LATTICE_50 X #include X #include X#else X extern char *calloc(); X extern void free(); X /* Psuedo-ANSI compatibility for AZTEC */ X #define memset(ptr,val,len) setmem(ptr,len,val) X#endif X#include X Xextern FILE *PlotFile; Xextern short fbuffer; X X/* I borrowed most of the IFF and preferences stuff from Tom Rokicki */ Xstatic union printerIO { X struct IOStdReq ios; X struct IODRPReq iodrp; X struct IOPrtCmdReq iopc; X} *printerIO; X Xstatic struct PrinterData *PD; Xstatic struct PrinterExtendedData *PED; Xstatic struct MsgPort *replyport; Xstatic struct RastPort rastport; Xstatic struct BitMap Bitmap; Xstatic short dummycolors[] = { 0x0000, 0x0fff }; Xstatic struct ColorMap dummyColorMap = { NULL, NULL, 2, (APTR)&dummycolors }; X X Xstatic void doio() X{ X register struct IODRPReq *ioreq; X X ioreq = &printerIO->iodrp; X SendIO((struct IORequest *)ioreq); X while(1) { X if(GetMsg(replyport) == NULL) X Wait(1L << replyport->mp_SigBit); X else X break; X } X} X Xvoid dmpport(flags, x, y) Xlong flags; Xint x, y; X{ X register struct IODRPReq *ioreq; X X ioreq = &printerIO->iodrp; X ioreq->io_Command = PRD_DUMPRPORT; X ioreq->io_RastPort = &rastport; X ioreq->io_ColorMap = &dummyColorMap; X ioreq->io_Modes = 0; X ioreq->io_SrcX = 0; X ioreq->io_SrcY = 0; X ioreq->io_SrcWidth = x; X ioreq->io_SrcHeight = y; X ioreq->io_DestCols = x; X ioreq->io_DestRows = y; X ioreq->io_Special = flags | SPECIAL_TRUSTME ; X doio(); X} X Xstatic long bitmapx, bitmapy, wordsperrow; Xstatic short *bitmap; X Xint mapinit(bmapx, bmapy) Xlong bmapx, bmapy; X{ X bitmapx = bmapx; X bitmapy = bmapy; X wordsperrow = (bmapx+15)/16; X Bitmap.BytesPerRow = wordsperrow * 2; X Bitmap.Rows = bmapy; X /* Allocate memory for bitmap */ X if((bitmap = (short *)calloc(wordsperrow * 2, (int)bmapy)) == NULL) { X fprintf(stderr,"\nCan't allocate memory for bitmap dump.\n"); X return(1); X } X Bitmap.Planes[0] = (PLANEPTR)bitmap; X return(0); X} X Xvoid mapfree() X{ X free((VOID *)bitmap); X} X Xvoid mapclear() X{ X memset((char *)bitmap,'\0',(int)(wordsperrow * (long)bitmapy * 2)); X} X X/* Function to draw the line in the bitmap */ Xvoid mapline(x1,y1,x2,y2) Xregister int x1,y1,x2,y2; X{ X register short *p ; X register unsigned int b ; X register int t ; X int d ; X int nextrow ; X X /* we always want to go left to right. */ X if (x1 > x2) { X t = x1 ; x1 = x2 ; x2 = t ; X t = y1 ; y1 = y2 ; y2 = t ; X } X p = bitmap + y1 * wordsperrow ; X /* we always want to go `up'. */ X if (y2 > y1) X nextrow = wordsperrow ; X else { X y2 = y1 * 2 - y2 ; X nextrow = - wordsperrow ; X } X b = 1L << (15 - (x1 & 15)) ; X p += (x1 >> 4) ; X x2 -= x1 ; X y2 -= y1 ; X /* two routines, one for major in x, one for major in y */ X if (y2 > x2) { X d = y2 ; X t = x2 / 2 ; X y1 = y2 ; X while (y1 >= 0) { X *p |= b ; X p += nextrow ; X t += x2 ; X if (t >= d) { X t -= d ; X b >>= 1 ; X if (b == 0) { X b = 0x8000 ; X p++ ; X } X } X y1-- ; X } X } else { X d = x2 ; X t = y2 / 2 ; X x1 = x2 ; X while (x1 >= 0) { X *p |= b ; X b >>= 1 ; X if (b == 0) { X b = 0x8000 ; X p++ ; X } X t += y2 ; X if (t >= d) { X t -= d ; X p += nextrow ; X } X x1-- ; X } X } X} X Xint openprinter() X{ X replyport = (struct MsgPort *)CreatePort("PLPlot.PIO",0L); X if(replyport == NULL){ X fprintf(stderr,"Couldn't open reply port for printer dump.\n"); X return(1); X } X X printerIO = (union printerIO *) X AllocMem((long)sizeof(union printerIO), X (long)(MEMF_CLEAR | MEMF_PUBLIC)); X if(printerIO == NULL) { X DeletePort(replyport); X fprintf(stderr,"Couldn't create IO request block for printer dump.\n"); X return(1); X } X printerIO->ios.io_Message.mn_Node.ln_Type = NT_MESSAGE; X printerIO->ios.io_Message.mn_Length = sizeof(union printerIO); X printerIO->ios.io_Message.mn_ReplyPort = replyport; X X if(OpenDevice("printer.device",0L,(struct IORequest *)printerIO,0L)!=NULL) { X FreeMem((VOID *)printerIO,(long)sizeof(union printerIO)); X DeletePort(replyport); X fprintf(stderr,"Error opening printer device.\n"); X return(1); X } X X PD = (struct PrinterData *)printerIO->iodrp.io_Device; X PED = &PD->pd_SegmentData->ps_PED; X return(0); X} X Xvoid closeprinter() X{ X CloseDevice((struct IORequest *)printerIO); X FreeMem((VOID *)printerIO,(long)sizeof(union printerIO)); X DeletePort(replyport); X} X Xint queryprint(bmapx, bmapy, bmapxmax, bmapymax, xdpi, ydpi) Xlong *bmapx, *bmapy, *bmapxmax, *bmapymax, *xdpi, *ydpi; X{ X int mode; X Bitmap.BytesPerRow = 0; X Bitmap.Rows = 0; X Bitmap.Depth = 1; X rastport.BitMap = &Bitmap; X dmpport((long)(SPECIAL_NOPRINT), 0, 0); X X *bmapxmax = PED->ped_MaxXDots; X *bmapymax = 95*PED->ped_YDotsInch/10; /* 9.5" to prevent problems */ X X *xdpi = PED->ped_XDotsInch; X *ydpi = PED->ped_YDotsInch; X X if(PD->pd_Preferences.PrintFlags & BOUNDED_DIMENSIONS) { X *bmapx = PD->pd_Preferences.PrintMaxWidth*PED->ped_XDotsInch/10; X *bmapy = PD->pd_Preferences.PrintMaxHeight*PED->ped_YDotsInch/10; X mode = 1; X } X else if(PD->pd_Preferences.PrintFlags & ABSOLUTE_DIMENSIONS) { X *bmapx = PD->pd_Preferences.PrintMaxWidth*PED->ped_XDotsInch/10; X *bmapy = PD->pd_Preferences.PrintMaxHeight*PED->ped_YDotsInch/10; X mode = 0; X } X else if(PD->pd_Preferences.PrintFlags & PIXEL_DIMENSIONS) { X *bmapx = PD->pd_Preferences.PrintMaxWidth; X *bmapy = PD->pd_Preferences.PrintMaxHeight; X mode = 0; X } X else { X *bmapx = *bmapxmax; X *bmapy = *bmapymax; X mode = 1; X } X X PD->pd_Preferences.PrintImage = IMAGE_NEGATIVE; X PD->pd_Preferences.PrintShade = SHADE_BW; X PD->pd_Preferences.PrintThreshold = 7; X PD->pd_Preferences.PrintAspect = ASPECT_HORIZ; X PD->pd_Preferences.PrintFlags = INTEGER_SCALING; X return(mode); X} X Xvoid ejectpage() X{ X printerIO->ios.io_Command = PRD_RAWWRITE; X printerIO->ios.io_Data = (APTR)"\014" ; X printerIO->ios.io_Length = 1 ; X doio() ; X} X X/* If type = 0 dump the plplot window to the printer with full preferences X support, i.e. color, shading, threshold, etc. Otherwise we override many X of the preferences selections, create a full page black and white X bitmap and dump it to the printer. */ Xvoid screendump(type) XPLINT type; X{ X register struct IODRPReq *ioreq; X long bmapx, bmapy; X long cxy, x1, y1; X long dwidth, dheight, xlas, ylas, xnew, ynew; X int penwid=1; X X if(type != 0 && fbuffer == 0) X return; X if(openprinter()) /* return if error */ X return; X X ioreq = &printerIO->iodrp; X X if(type == 0) { X ioreq->io_Command = PRD_DUMPRPORT; X ioreq->io_RastPort = PLWRPort; X ioreq->io_ColorMap = PLScreen->ViewPort.ColorMap; X ioreq->io_Modes = PLScreen->ViewPort.Modes; X ioreq->io_SrcX = XOffset; X ioreq->io_SrcY = YOffset; X ioreq->io_SrcWidth = PLWidth; X ioreq->io_SrcHeight = PLHeight; X ioreq->io_DestCols = 0; X ioreq->io_DestRows = 0; X ioreq->io_Special = SPECIAL_FULLROWS | SPECIAL_FULLCOLS | X SPECIAL_TRUSTME ; X doio(); X } X else { X /* get bmapx and bmapy (the others are dummy variables) */ X queryprint(&bmapx,&bmapy,&dwidth,&dheight,&dwidth, &dheight); X X /* Set up map */ X if(mapinit(bmapx,bmapy)) { X closeprinter(); X return; X } X X prepupdate(); X X dwidth = bmapx - 2; X dheight = bmapy - 2; X while(!getpoint(&cxy, &x1, &y1)) { X if(cxy == PENU) { X if(type == 1) { X xlas = ((long)dheight*(long)x1)/InitPLWidth; X ylas = ((long)dwidth*(long)y1)/InitPLHeight; X } X else { X xlas = ((long)dwidth*(long)x1)/InitPLWidth; X ylas = ((long)dheight*(long)y1)/InitPLHeight; X } X } X else if(cxy == PEND) { X if(type == 1) { X xnew = ((long)dheight*(long)x1)/InitPLWidth; X ynew = ((long)dwidth*(long)y1)/InitPLHeight; X switch (penwid) { X case 3: X mapline(ylas,xlas,ynew,xnew); X case 2: X mapline(ylas+2,xlas+2,ynew+2,xnew+2); X case 1: X default: X mapline(ylas+1,xlas+1,ynew+1,xnew+1); X } X } X else { X xnew = ((long)dwidth*(long)x1)/InitPLWidth; X ynew = ((long)dheight*(long)y1)/InitPLHeight; X switch (penwid) { X case 3: X mapline(xlas,dheight-ylas,xnew,dheight-ynew); X case 2: X mapline(xlas+2,dheight-ylas+2,xnew+1,dheight-ynew+2); X case 1: X default: X mapline(xlas+1,dheight-ylas+1,xnew+1,dheight-ynew+1); X } X } X xlas = xnew; X ylas = ynew; X } X else if(cxy == SPEN) { X ; X } X else if(cxy == PWID) { X penwid = x1; X } X } X finiupdate(); X X dmpport(0L, bmapx, bmapy); X mapfree(); X } X closeprinter(); X} X X/* prepupdate() flushes and rewinds the plot buffer file. This should always X be called before attempting to read the buffer file. */ Xvoid prepupdate() X{ X if(fbuffer) { X fflush(PlotFile); X rewind(PlotFile); X } X} X X/* Use getpoint to read the next command in the plot buffer file. */ X/* Returns 0 if okay or 1 if end of file. */ Xint getpoint(com, x, y) Xlong *com, *x, *y; X{ X short csh, xsh, ysh; X X if(!fread((char *)&csh,sizeof(short),1,PlotFile)) X return(1); X X *com = csh; X if(csh == PENU || csh == PEND) { X fread((char *)&xsh,sizeof(short),1,PlotFile); X fread((char *)&ysh,sizeof(short),1,PlotFile); X *x = xsh; X *y = ysh; X } X else if(csh == SPEN || csh == PWID) { X fread((char *)&xsh,sizeof(short),1,PlotFile); X *x = xsh; X } X X return(0); X} X Xvoid finiupdate() X{ X fseek(PlotFile,0L,2); X} X Xstatic long iffpos ; Xstatic short curbyte ; Xstatic short curcount ; Xstatic short runcount ; Xstatic FILE *OutFile; X Xstruct BitMapHeader { X UWORD w, h; X WORD x, y; X UBYTE nPlanes; X UBYTE masking; X UBYTE compression; X UBYTE pad1; X UWORD transparentColor; X UBYTE xAspect, yAspect; X WORD pageWidth, pageHeight; X} bmhd; X Xstatic void iffobyte(b) Xregister int b ; X{ X putc(b, OutFile) ; X iffpos++ ; X} Xchar outchunk[256] ; X Xstatic void iffoutbyte(b) Xregister int b ; X{ X register int i ; X X if (b == curbyte && runcount < 125) { X runcount++ ; X } else { X if (runcount > 2) { X if (curcount > 0) { X iffobyte(curcount-1) ; X for (i=0; i 0) { X outchunk[curcount++] = curbyte ; X runcount-- ; X } X if (curcount > 110) { X iffobyte(curcount-1) ; X for (i=0; i 0) { X outchunk[curcount++] = curbyte ; X runcount-- ; X } X } X if (curcount > 0) { X iffobyte(curcount-1) ; X for (i=0; i 0) { X iffobyte(256 - runcount + 1) ; X iffobyte(curbyte) ; X curbyte = -1 ; X runcount = 0 ; X } X} X X#define BADFLAGS (SPRITES|VP_HIDE|GENLOCK_AUDIO|GENLOCK_VIDEO) X#define FLAGMASK (~BADFLAGS) X#define CAMGMASK (FLAGMASK & 0x0000FFFFL) X X/* Routine to write out color bitmap. */ Xvoid saveiff() X{ X long int formlen=0, formpos, bmhdlen, camglen, camgbod; X long int bodylen=0, bodypos, cmaplen; X long int numcolors, rowlen, rowoff, coloff; X short int i, j, k; X UWORD *coltable; X UBYTE *byteptr, rgb[3]; X struct BitMap *PLBitMap; X char *filename; X FILE *IFFFile; X char *plfilereq(); X X filename = plfilereq(); X if(!filename) X return; X X if((IFFFile = fopen(filename,"w+"))==NULL) { X fprintf(stderr,"Can't open %s\n",filename); X return; X } X X iffpos = 0; X curbyte = -1; X curcount = 0; X runcount = 0; X OutFile = IFFFile; X X bmhdlen = sizeof(struct BitMapHeader); X camglen = 4; X PLBitMap = &PLScreen->BitMap; X X fwrite("FORM",sizeof(char),4,IFFFile); X formpos = ftell(IFFFile); X fwrite((char *)&formlen,sizeof(long),1,IFFFile); X X fwrite("ILBM",sizeof(char),4,IFFFile); X formlen += 4; X X fwrite("BMHD",sizeof(char),4,IFFFile); X formlen += 4; X fwrite((char *)&bmhdlen,sizeof(long),1,IFFFile); X formlen += 4; X bmhd.w = 16*((PLWidth+15)/16); X bmhd.h = PLHeight; X bmhd.x = PLWindow->LeftEdge + XOffset; X bmhd.y = PLWindow->TopEdge + YOffset; X bmhd.nPlanes = PLBitMap->Depth; X bmhd.masking = 0; X bmhd.compression = 1; X bmhd.pad1 = 0; X bmhd.transparentColor = 0; X bmhd.xAspect = 10; X bmhd.yAspect = 11; X bmhd.pageWidth = PLScreen->Width; X bmhd.pageHeight = PLScreen->Height; X fwrite((char *)&bmhd,bmhdlen,1,IFFFile); X formlen += bmhdlen; X X fwrite("CAMG",sizeof(char),4,IFFFile); X formlen += 4; X fwrite((char *)&camglen,sizeof(long),1,IFFFile); X formlen += 4; X camgbod = PLScreen->ViewPort.Modes & CAMGMASK; X fwrite((char *)&camgbod,sizeof(long),1,IFFFile); X formlen += 4; X X fwrite("CMAP",sizeof(char),4,IFFFile); X formlen += 4; X numcolors = 1; X for(i=PLBitMap->Depth; i>0; i--) X numcolors *= 2; X cmaplen = numcolors*3; X fwrite((char *)&cmaplen,sizeof(long),1,IFFFile); X formlen += 4; X coltable = (UWORD *)PLCMap->ColorTable; X for(i=0; i> 4) & 0xf0; X rgb[1] = *coltable & 0xf0; X rgb[2] = (*coltable << 4) & 0xf0; X fwrite((char *)rgb,sizeof(UBYTE),3,IFFFile); X formlen += 3; X coltable++; X } X X fwrite("BODY",sizeof(char),4,IFFFile); X formlen += 4; X bodypos = ftell(IFFFile); X fwrite((char *)&bodylen,sizeof(long),1,IFFFile); X formlen += 4; X rowlen = ((PLWidth+15)/16); X rowlen *= 2; X rowoff = (PLWindow->TopEdge + YOffset)*PLBitMap->BytesPerRow; X coloff = (PLWindow->LeftEdge+ XOffset)/8; X for(i=0; iDepth; j++) { X byteptr = (UBYTE *)PLBitMap->Planes[j] + rowoff + coloff; X for(k=0; kBytesPerRow; X } X if(iffpos & 1) X iffobyte(0); X bodylen = iffpos; X formlen += iffpos; X fflush(IFFFile); X fseek(IFFFile,formpos,0); X fwrite((char *)&formlen,sizeof(long),1,IFFFile); X fseek(IFFFile,bodypos,0); X fwrite((char *)&bodylen,sizeof(long),1,IFFFile); X fclose(IFFFile); X} X X/* X * Code we steal to write a black and white IFF file. X */ Xstatic struct iffhead { X char formname[4] ; X long formlen ; /* fill me in */ X char ilbmname[4] ; X char bmhdname[4] ; X long bmhdlen ; X short w, h ; /* fill me in */ X long dummy0 ; X char numplanes, masking, compression, pad1 ; X short tc ; X char xas, yas ; X short pw, ph ; X char cmapname[4] ; X long cmaplen ; X char r0, g0, b0, r1, g1, b1 ; X char bodyname[4] ; X long bodylen ; /* fill me in */ X} iffhead = { {'F','O','R','M'}, 0, {'I','L','B','M'}, {'B','M','H','D'}, 20, X 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 320, 200, {'C','M','A','P'}, 6, 240, 240, X 240, 0, 0, 0, {'B','O','D','Y'}, 0 } ; X X/* X * Finally we get into the nitty gritty of writing the stupid file. X */ Xvoid iffwritefile(xdpi, ydpi, File) XPLINT xdpi, ydpi; XFILE *File; X{ X register int i, j ; X register short *p; X X p = bitmap; X OutFile = File; X fwrite((char *)&iffhead, 1, sizeof(struct iffhead), OutFile) ; X iffpos = 0 ; X curbyte = -1; X curcount = 0; X runcount = 0; X for (j=0; j> 8) & 255) ; X iffoutbyte(*p & 255) ; X } X finishrow() ; X } X if (iffpos & 1) X iffobyte(0) ; X fseek(OutFile, 0L, 0) ; X iffhead.w = bitmapx ; X iffhead.h = bitmapy ; X iffhead.pw = bitmapx ; X iffhead.ph = bitmapy ; X iffhead.formlen = iffpos + sizeof(struct iffhead) - 8 ; X iffhead.bodylen = iffpos ; X iffhead.xas = xdpi ; X iffhead.yas = ydpi ; X fwrite((char *)&iffhead, 1, sizeof(struct iffhead), OutFile) ; X} X X/* Use 1.3 palette program to set colors. */ Xvoid plcolreq() X{ X short i; X extern PLINT MaxColors; X struct FileLock *lock; X struct Process *thisproc; X APTR winptr; X X /* This ensures that a requester won't appear for tools: or sys: X if they don't exist */ X thisproc = (struct Process *)FindTask(0); X winptr = thisproc->pr_WindowPtr; X thisproc->pr_WindowPtr = (APTR)-1; /* No window */ X X /* Check to see if palette is in tools: or sys:tools */ X if(lock = (struct FileLock *)Lock("tools:palette",ACCESS_READ)) { X Execute("tools:palette",0,0); X UnLock((BPTR)lock); X } X else if(lock = (struct FileLock *)Lock("sys:tools/palette",ACCESS_READ)) { X Execute("sys:tools/palette",0,0); X UnLock((BPTR)lock); X } X /* Can't find palette so just return */ X else { X thisproc->pr_WindowPtr = winptr; X return; X } X X /* Restore window pointer */ X thisproc->pr_WindowPtr = winptr; X X /* Save new colors in PLCurPrefs. */ X for(i=0; iIDCMPFlags; X ModifyIDCMP(PLWindow,GADGETUP); X Request(&PLFileReq,PLWindow); X Wait(1<UserPort->mp_SigBit); X message = (struct IntuiMessage *)GetMsg(PLWindow->UserPort); X gadid = ((struct Gadget *)message->IAddress)->GadgetID; X ReplyMsg((struct Message *)message); X switch(gadid) { X case PLOKGAD: X if(Gadget3SIBuff[0] == NULL) X file = NULL; X else X file = (char *)Gadget3SIBuff; X break; X case PLCAGAD: X file = NULL; X break; X case PLSTGAD: X if(Gadget3SIBuff[0] == NULL) X file = NULL; X else X file = (char *)Gadget3SIBuff; X break; X default: X break; X } X ModifyIDCMP(PLWindow,oldFlags); X return(file); X} X X/* This routine disables all the gadgets attached to PLWindow. X It's useful when saving the window as an IFF file or when dumping it X to the printer. (We don't want the user moving the window around or X resizing it during those periods.). We always disable the window sizing X and close gadgets. If flag is zero we disable the dragging gadget also. */ Xvoid disablegads(flag) XPLINT flag; X{ X int type; X struct Gadget *gadget; X X gadget = PLWindow->FirstGadget; X while(gadget) { X type = gadget->GadgetType & 0x00ff; X if(type == SIZING || type == CLOSE || (type == WDRAGGING && !flag)) X OffGadget(gadget,PLWindow,0); X gadget = gadget->NextGadget; X } X} X Xvoid enablegads() X{ X struct Gadget *gadget; X X gadget = PLWindow->FirstGadget; X while(gadget) { X OnGadget(gadget,PLWindow,0); X gadget = gadget->NextGadget; X } X RefreshWindowFrame(PLWindow); X} X END_OF_FILE if test 26014 -ne `wc -c <'Amiga/plsupport.c'`; then echo shar: \"'Amiga/plsupport.c'\" unpacked with wrong size! fi # end of 'Amiga/plsupport.c' fi echo shar: End of archive 9 \(of 12\). cp /dev/null ark9isdone MISSING="" for I in 1 2 3 4 5 6 7 8 9 10 11 12 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 12 archives. rm -f ark[1-9]isdone ark[1-9][0-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0 -- Submissions to comp.sources.amiga and comp.binaries.amiga should be sent to: amiga@cs.odu.edu or amiga@xanth.cs.odu.edu ( obsolescent mailers may need this address ) or ...!uunet!xanth!amiga ( very obsolescent mailers need this address ) Comments, questions, and suggestions s should be addressed to ``amiga-request'' (only use ``amiga'' for submissions) at the above addresses.