/* $Revision Header * Header built automatically - do not edit! ************* * * (C) Copyright 1990 by MXM * * Name .....: LoadImage.c * Created ..: Saturday 23-Sep-90 12:30 * Revision .: 11 * * Date Author Comment * ========= ======== ==================== * 11-May-90 Olsen New routines * 01-May-90 Olsen Rework for Aztec 5.0 release * 23-Sep-89 Olsen Created this file! * * $Revision Header ********************************************************/ /* Arp user interface stuff. */ char *CLI_Template = "INFO/S,NOMODE/S,LACE/S,CYCLE/S,Files,,,,,,"; char *CLI_Help = "\nUsage: LoadImage [INFO] [NOMODE] [LACE] [CYCLE] Files1 ... FileN\n\n NOMODE and LACE are mutually exclusive.\n"; /* Argument vector offsets. */ #define ARG_INFO 1 #define ARG_NOMODE 2 #define ARG_LACE 3 #define ARG_CYCLE 4 #define ARG_FILES 5 /* The cycling code needs this to be defined externally. */ CRange CycleRange[6]; /* Some more fontdata for the Requester soon to come. */ struct TextAttr StandardFont[3] = { {(UBYTE *)"topaz.font",8,FS_NORMAL ,FPF_ROMFONT}, {(UBYTE *)"topaz.font",8,FSF_BOLD ,FPF_ROMFONT}, {(UBYTE *)"topaz.font",8,FSF_ITALIC,FPF_ROMFONT} }; /* Menu text definitions. */ struct IntuiText MenuIntTxt[10] = { {0,0,0,2,1,&StandardFont[0],(UBYTE *)"About LoadImage...", NULL}, {0,0,0,0,0,&StandardFont[1],(UBYTE *)"________________________",NULL}, {0,0,0,2,1,&StandardFont[0],(UBYTE *)"Title bar", NULL}, {0,0,0,2,1,&StandardFont[0],(UBYTE *)"Cycling", NULL}, {0,0,0,0,0,&StandardFont[1],(UBYTE *)"________________________",NULL}, {0,0,0,2,1,&StandardFont[0],(UBYTE *)"Print Standard", NULL}, {0,0,0,2,1,&StandardFont[0],(UBYTE *)" Enlarged", NULL}, {0,0,0,0,0,&StandardFont[1],(UBYTE *)"________________________",NULL}, {0,0,0,2,1,&StandardFont[0],(UBYTE *)"Next Image", NULL}, {0,0,0,2,1,&StandardFont[0],(UBYTE *)"Quit LoadImage", NULL} }; /* A chain of menu items. */ struct MenuItem MenuItem[10] = { {&MenuItem[1], 1, 0,196,10, 86,0,(APTR)&MenuIntTxt[0],NULL,'?',NULL,NULL}, {&MenuItem[2], 3, 4,192, 8,210,0,(APTR)&MenuIntTxt[1],NULL, 0,NULL,NULL}, {&MenuItem[3], 1,13,196,10, 86,0,(APTR)&MenuIntTxt[2],NULL,'T',NULL,NULL}, {&MenuItem[4], 1,23,196,10, 86,0,(APTR)&MenuIntTxt[3],NULL,'C',NULL,NULL}, {&MenuItem[5], 3,27,192, 8,210,0,(APTR)&MenuIntTxt[4],NULL, 0,NULL,NULL}, {&MenuItem[6], 1,36,196,10, 86,0,(APTR)&MenuIntTxt[5],NULL,'S',NULL,NULL}, {&MenuItem[7], 1,46,196,10, 86,0,(APTR)&MenuIntTxt[6],NULL,'E',NULL,NULL}, {&MenuItem[8], 3,50,192, 8,210,0,(APTR)&MenuIntTxt[7],NULL, 0,NULL,NULL}, {&MenuItem[9], 1,59,196,10, 86,0,(APTR)&MenuIntTxt[8],NULL,'N',NULL,NULL}, {NULL, 1,69,196,10, 86,0,(APTR)&MenuIntTxt[9],NULL,'Q',NULL,NULL} }; /* Our only menu. */ struct Menu Menu = { NULL,1,0,120,0,257,"LoadImage 1.11",&MenuItem[0] }; /* Requester text definitions. */ struct IntuiText ReqIntTxt[] = { {0,0,0, 76, 4,&StandardFont[0],(UBYTE *)"Understood", NULL}, {0,0,0, 94, 6,&StandardFont[1],(UBYTE *)"LoadImage 1.11", &ReqIntTxt[2]}, {0,0,0, 34, 18,&StandardFont[0],(UBYTE *)"Was written by Olaf 'Olsen'", &ReqIntTxt[3]}, {0,0,0, 34, 26,&StandardFont[0],(UBYTE *)"Barthel of MXM. This version", &ReqIntTxt[4]}, {0,0,0, 34, 34,&StandardFont[0],(UBYTE *)"supports EHB & HAM pictures,", &ReqIntTxt[5]}, {0,0,0, 34, 42,&StandardFont[0],(UBYTE *)"will also take care of", &ReqIntTxt[6]}, {0,0,0, 34, 50,&StandardFont[0],(UBYTE *)"oversized pictures which", &ReqIntTxt[7]}, {0,0,0, 34, 58,&StandardFont[0],(UBYTE *)"require 1M of chip ram and", &ReqIntTxt[8]}, {0,0,0, 46, 66,&StandardFont[0],(UBYTE *)"features an Arp interface.", &ReqIntTxt[9]}, {0,0,0, 34, 82,&StandardFont[0],(UBYTE *)"Press the left mouse button", &ReqIntTxt[10]}, {0,0,0, 34, 90,&StandardFont[0],(UBYTE *)"and move the pointer towards", &ReqIntTxt[11]}, {0,0,0, 34, 98,&StandardFont[0],(UBYTE *)"the borders of the screen to", &ReqIntTxt[12]}, {0,0,0, 34,106,&StandardFont[0],(UBYTE *)"scroll around in overscanned", &ReqIntTxt[13]}, {0,0,0,122,114,&StandardFont[0],(UBYTE *)"images.", &ReqIntTxt[14]}, {0,0,0, 58,130,&StandardFont[2],(UBYTE *)"© Copyright 1990 by MXM", NULL} }; /* Requester border coordinates. */ SHORT ReqBrdDat[] = { -3,-2,234,-2,234, 17,-3, 17,-3,-2, -6,-4,237,-4,237, 19,-6, 19,-6,-4, 0, 0,293, 0,293,172, 0,172, 0, 0, 0, 0,295, 0,295,172, 0,172, 0, 0 }; /* Requester border definitions. */ struct Border ReqBrd[] = { {0,0,0,0,0,5,&ReqBrdDat[ 0],&ReqBrd[1]}, {0,0,0,0,0,5,&ReqBrdDat[10],NULL}, {3,1,0,0,0,5,&ReqBrdDat[20],&ReqBrd[3]}, {2,1,0,0,0,5,&ReqBrdDat[30],NULL} }; /* The only gadget employed by the Requester. */ struct Gadget ReqGad = {NULL,34,149,232,16,0,3,4097,(APTR)&ReqBrd[0],NULL,&ReqIntTxt[0],NULL,NULL,0,NULL}; /* Our only Requester. */ struct Requester Req; /* Yes... we will open a CUSTOMBITMAP screen. */ struct BitMap ScreenMap; /* If the picture is smaller than the screen. */ struct BitMap TinyBitMap; /* Must be defined externally since three routines need it. * There could have been an easier way to do this, but it was * me who programmed it and not a "reentrant-code-fanatic". */ BitMapHeader InfoHeader; /* Empty colour information. */ UWORD BlackIsBlack[32] = { 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0 }; /* Wait and see what this will be! */ struct NewScreen NewScreen = { 0,0,0,0,0, /* Gets filled in later. */ 0,1, /* Pens. */ NULL, /* ViewModes, get filled in later. */ CUSTOMSCREEN | SCREENBEHIND | CUSTOMBITMAP, &StandardFont[0], /* Just insure that the menu looks cute. */ (STRPTR)"LoadImage 1.11", /* Some title text. */ NULL, /* No gagdets. */ &ScreenMap /* Custom bitmap! */ }; /* What do we need this window for? We've got a menu and * screens don't like menus very much... */ struct NewWindow NewWindow = { 0,0, /* These get filled in later. */ 0,0, 0,1, /* Pens. */ GADGETUP | MOUSEBUTTONS | MENUPICK | MENUVERIFY | MOUSEMOVE | RAWKEY, /* We want to know about this. */ BACKDROP | BORDERLESS | RMBTRAP, /* This is how it should look like. */ (struct Gadget *)NULL, /* Don't need a gadget. */ (struct Image *)NULL, /* Don't need a checkmark either. */ (STRPTR)NULL, /* Don't need a title. */ (struct Screen *)NULL, /* This gets filled in later. */ (struct BitMap *)NULL, /* Don't need it, really. */ 0,0, /* Minimum dimensions. */ 0,0, /* Maximum dimensions. */ CUSTOMSCREEN /* No Workbench, this is MY window. */ }; /* External symbols the linker wants. */ extern struct IntuitionBase *IntuitionBase; extern struct GfxBase *GfxBase; extern struct ExecBase *SysBase; struct Screen *Screen; struct Window *Window; /* Check for ^C signal. */ #define BreakCheck() (SetSignal(0,0) & SIGBREAKF_CTRL_C) /* Macro expressions to set the pointer for our window. */ #define SetPoint(wind) SetPointer(wind,PointData,7,16,-4,-3) #define SetSnooze(wind) SetPointer(wind,Snooze,22,16,-9,-13) #define SetSize(wind) SetPointer(wind,SizeData,13,16,-4,-3) /* Sprite dump for the pointer image. */ USHORT PointData[(2 + 7) * 2] = { 0x0000,0x0000, 0x0000,0x1000, 0x1000,0x0000, 0x1000,0x1000, 0x6C00,0xAA00, 0x1000,0x1000, 0x1000,0x0000, 0x0000,0x1000, 0x0000,0x0000 }; /* Sprite dump for the Workbench balloon. */ USHORT Snooze[(2 + 22) * 2] = { 0x0000,0x0000, 0x0700,0x0000, 0x0FA0,0x0700, 0x3FF0,0x0FA0, 0x70F8,0x3FF0, 0x7DFC,0x3FF8, 0xFBFC,0x7FF8, 0x70FC,0x3FF8, 0x7FFE,0x3FFC, 0x7F0E,0x3FFC, 0x3FDF,0x1FFE, 0x7FBE,0x3FFC, 0x3F0E,0x1FFC, 0x1FFC,0x07F8, 0x07F8,0x01E0, 0x01E0,0x0080, 0x07C0,0x0340, 0x0FE0,0x07C0, 0x0740,0x0200, 0x0000,0x0000, 0x0070,0x0020, 0x0078,0x0038, 0x0038,0x0010, 0x0000,0x0000 }; USHORT SizeData[(2 + 13) * 2] = { 0x0000,0x0000, 0x0000,0x1000, 0x1000,0x0000, 0x1000,0x1000, 0x6C00,0xAA00, 0x1000,0x1000, 0x1000,0x0000, 0x0000,0x1000, 0x0000,0x0000, 0x0D77,0x0D77, 0x1114,0x1114, 0x1D27,0x1D27, 0x0544,0x0544, 0x1977,0x1977, 0x0000,0x0000 }; /* This is where the colours go when the About item is * selected. */ UWORD PrefColours[32]; struct Preferences StandardPrefs; /* MakeID(IDString) : * * Transforms a string into a chunk ID. How can we do this * in a macro expression? Just don't know. */ ULONG MakeID(char *IDString) { ULONG LongID; LongID = (IDString[0] << 24) | (IDString[1] << 16) | (IDString[2] << 8) | (IDString[3]); return(LongID); } /* FindChunk(ChunkName,FilePointer) : * * Will try to find a chunk ID somewhere in the * file. If it doesn't find any it returns FALSE. * This routine was somewhat inspired by the * Chunk-reader to be found on the disk distributed * along with the FutureSound sound sampling hardware. * Some months later I through the 'crap' out. Instead * of years this will take you only some moments to * load now. */ LONG FindChunk(char *ChunkName,FILE *FilePointer) { IFF_Chunk Chunk; LONG OldPosition,FormType,WeWant; /* Set up the chunk type. */ WeWant = MakeID(ChunkName); /* Remember the initial file position. */ OldPosition = ftell(FilePointer); /* Reset the form type. */ FormType = 0; for(;;) { /* Try to read the chunk. */ if(fread(&Chunk,sizeof(Chunk),1,FilePointer) != 1) { /* If it went wrong, reset the * file position. */ fseek(FilePointer,OldPosition,0); return(0); } /* If this is supposed to be a FORM chunk, * try to figure out the form type. */ if(OldPosition == 0 && FormType == 0 && Chunk . IFF_Type == MakeID("FORM")) { fread(&FormType,sizeof(LONG),1,FilePointer); /* Is it the type we want? */ if(FormType == WeWant) return(Chunk . IFF_Length); continue; } /* Is this what we want? */ if(Chunk . IFF_Type == WeWant) return(Chunk . IFF_Length); /* Else, skip the length information. */ fseek(FilePointer,Chunk . IFF_Length,1); } } /* LoadHeader(FileName,BMHeader) : * * Does two jobs for us: Initializes the BitMapHeader * and tries to figure out the Amiga ViewModes this * file needs. Returns -1 on failure, not NULL. */ LONG LoadHeader(char *FileName,BitMapHeader *BMHeader) { FILE *ImageFile; LONG ViewModes = NULL; /* No such file? */ if(!(ImageFile = fopen(FileName,"r"))) return(-1); /* No BMHD-Chunk? */ if(!FindChunk("BMHD",ImageFile)) { fclose(ImageFile); return(-1); } /* Read the header. */ fread(BMHeader,sizeof(BitMapHeader),1,ImageFile); /* Strange values, probably not a picture but a * "mistake", or even a CMAP. */ if(BMHeader -> nPlanes < 1 || BMHeader -> nPlanes > 8) { fclose(ImageFile); return(-1); } /* If we don't find a CAMG chunk in the file * we will have to guess the right * ViewModes. This line takes care of the * interlaced display mode. */ if(BMHeader -> pageHeight > GfxBase -> NormalDisplayRows) ViewModes |= LACE; /* Could it be HIRES? */ if(BMHeader -> pageWidth >= 640) ViewModes |= HIRES; /* It is still much more likely to encounter a * HAM picture than an EHB picture. If we are * wrong with this assumption, the CAMG chunk * will tell us (hope so). */ if(BMHeader -> nPlanes == 6) ViewModes |= HAM; /* Hello out there, got any CAMG chunk? */ if(!FindChunk("CAMG",ImageFile)) { fclose(ImageFile); return(ViewModes); } /* Read it then. */ fread(&ViewModes,sizeof(LONG),1,ImageFile); /* Mask out all unwanted bits (thanks, Carolyn!). */ ViewModes &= (~(SPRITES | VP_HIDE | GENLOCK_AUDIO | GENLOCK_VIDEO) | 0xFFFF); /* Finish it. */ fclose(ImageFile); return(ViewModes); } /* LoadCMAP(FileName,ColourMap,MaxCol,BMHeader) : * * Will load an unsigned word array with the * colours to be found in the CMAP chunk. */ LONG LoadCMAP(char *FileName,UWORD *ColourMap,LONG MaxCol,BitMapHeader *BMHeader) { LONG i; FILE *ColFile; LONG R,G,B; /* Are you there? */ if(!(ColFile = fopen(FileName,"r"))) return(0); /* Black 'n white or colour TV? */ if(!FindChunk("CMAP",ColFile)) { fclose(ColFile); return(0); } /* Correct it before the reader believes it! */ if(MaxCol < 2) MaxCol = 1 << BMHeader -> nPlanes; /* A bit too large, innit? */ if(MaxCol > 32) MaxCol = 32; /* Read those colours. */ for(i = 0 ; i < MaxCol ; i++) { R = fgetc(ColFile) >> 4; G = fgetc(ColFile) >> 4; B = fgetc(ColFile) >> 4; /* The transformation. */ ColourMap[i] = (R << 8) | (G << 4) | (B); } /* Finish it. */ fclose(ColFile); return(MaxCol); } /* LoadRaster(FileName,BitPlanes,BMHeader) : * * Will decompress the interleaved bitmap data * into a set of bitplanes. */ UBYTE LoadRaster(char *FileName,PLANEPTR *BitPlanes,BitMapHeader *BMHeader) { LONG i,j,k; UBYTE Value,SoFar,Compr,Depth; BYTE ChkVal; LONG Height,Width; PLANEPTR Planes[9]; /* 9 for possible bitmask. */ FILE *PicFile; BYTE *AuxBuff; /* Decompress in memory buffer. */ BYTE *AuxBuff2; LONG AuxLength; /* Clear the planes. */ for(i = 0 ; i < 9 ; i++) Planes[i] = NULL; /* Set up the working copies. */ Width = LineBytes(BMHeader -> w); Height = BMHeader -> h; Depth = BMHeader -> nPlanes; Compr = BMHeader -> compression; /* Is there something wrong in paradise? */ if(Compr > 1 || !BitPlanes) return(FALSE); /* Can we read it, please? */ if(!(PicFile = fopen(FileName,"r"))) return(FALSE); /* No BODY? What is this? */ if(!(AuxLength = FindChunk("BODY",PicFile))) { fclose(PicFile); return(FALSE); } /* Copy the bitmap pointers since their * contents will get changed. */ for(i = 0 ; i < Depth ; i++) Planes[i] = BitPlanes[i]; /* Very well, nobody told me that DPaint and Aegis Images * are allowed to save their own home-brewn BODY chunks * if the transparent colour is nonzero or the * stencil/behind function is used. In this case the * interleaved plane data is immediately followed by * a bitmask which is to clear out all unwanted pixels * after the image is drawn. To support this attitude * we increment the depth of the image to give the * reader access to a blank pointer the bitmask will * be sent to. */ if(BMHeader -> masking == 1) Depth++; /* If we can allocate the memory buffer, we will * decompress the image in memory rather than * while reading it from disk. */ if(AuxBuff = (BYTE *)AllocMem(AuxLength,MEMF_PUBLIC)) { /* Read the data. */ fread(AuxBuff,AuxLength,1,PicFile); /* Remember the buffer address. */ AuxBuff2 = AuxBuff; /* No compression? */ if(Compr == 0) { for(k = 0 ; k < Height ; k++) { for(j = 0 ; j < Depth ; j++) { if(Planes[j]) { CopyMem(AuxBuff,Planes[j],Width); Planes[j] += Width; } AuxBuff += Width; } } } /* ByteRun compression? */ if(Compr == 1) { for(k = 0 ; k < Height ; k++) { for(j = 0 ; j < Depth ; j++) { for(SoFar = 0 ; SoFar < Width ; ) { ChkVal = *AuxBuff; AuxBuff++; if(ChkVal > 0) { if(Planes[j]) { CopyMem(AuxBuff,Planes[j],ChkVal + 1); Planes[j] += ChkVal + 1; } AuxBuff += ChkVal + 1; SoFar += ChkVal + 1; } else { if(ChkVal != -128) { Value = *AuxBuff; AuxBuff++; for(i = 0 ; i <= -ChkVal ; i++) { if(Planes[j]) { *Planes[j] = Value; Planes[j]++; } SoFar++; } } } } } } } /* Free the auxilary buffer. */ FreeMem(AuxBuff2,AuxLength); goto Quit; } /* No compression, take the data as is. */ if(Compr == 0) { for(k = 0 ; k < Height ; k++) { for(j = 0 ; j < Depth ; j++) { if(Planes[j]) { fread(Planes[j],Width,1,PicFile); Planes[j] += Width; } else fseek(PicFile,Width,1); } } } /* ByteRun1 compression, efficient but tricky. */ if(Compr == 1) { for(k = 0 ; k < Height ; k++) { for(j = 0 ; j < Depth ; j++) { for(SoFar = 0 ; SoFar < Width ; ) { ChkVal = fgetc(PicFile); /* Read the next bytes. */ if(ChkVal > 0) { if(Planes[j]) { fread(Planes[j],ChkVal + 1,1,PicFile); Planes[j] += ChkVal + 1; } else fseek(PicFile,ChkVal + 1,1); SoFar += ChkVal + 1; } else { /* Set the memory to this * value. */ if(ChkVal != -128) { Value = fgetc(PicFile); for(i = 0 ; i <= -ChkVal ; i++) { if(Planes[j]) { *Planes[j] = Value; Planes[j]++; } SoFar++; } } } } } } } /* Finish it up. */ Quit: fclose(PicFile); return(TRUE); } /* FadeTo(): * * Fades a palette into a different palette or colour. */ VOID FadeTo(struct ViewPort *VPort,UWORD *From,UWORD *To,LONG NumColours,LONG ToCol,LONG FromCol) { UWORD FromTemp[32]; UWORD ToTemp[32]; SHORT i,j,R1,G1,B1,R2,G2,B2; /* A bit too large? */ if(NumColours > 32) NumColours = 32; /* Do we have a source palette? */ if(From) CopyMem(&From[0],&FromTemp[0],sizeof(UWORD) * 32); else memset(&FromTemp[0],FromCol,sizeof(UWORD) * 32); /* Do we have a destination palette? */ if(To) CopyMem(&To[0],&ToTemp[0],sizeof(UWORD) * 32); else memset(&ToTemp[0],ToCol,sizeof(UWORD) * 32); /* Let's get into action. */ for(j = 0 ; j < 16 ; j++) { for(i = 0 ; i < NumColours ; i++) { /* Split the source colour. */ R1 = (FromTemp[i] >> 8) & 0xF; G1 = (FromTemp[i] >> 4) & 0xF; B1 = (FromTemp[i]) & 0xF; /* Split the destination colour. */ R2 = (ToTemp[i] >> 8) & 0xF; G2 = (ToTemp[i] >> 4) & 0xF; B2 = (ToTemp[i]) & 0xF; /* Adjust the colours. */ if(R1 > R2) R1--; if(G1 > G2) G1--; if(B1 > B2) B1--; /* Adjust the colours. */ if(R1 < R2) R1++; if(G1 < G2) G1++; if(B1 < B2) B1++; /* Put it together again. */ FromTemp[i] = (R1 << 8) | (G1 << 4) | B1; } /* Wait a bit. */ Delay(2); /* Load the new map. */ LoadRGB4(VPort,FromTemp,NumColours); } } /* InitTinyBitMap() : * * If the picture to be loaded is smaller than the * screen it is to appear on, a custom bitmap is * initialized to receive the image data. */ UBYTE InitTinyBitMap() { SHORT i; /* So the Blitter won't be confused. */ InitBitMap(&TinyBitMap,InfoHeader . nPlanes,InfoHeader . w,InfoHeader . h); /* Try to steal some memory for the tiny bitmap. */ for(i = 0 ; i < InfoHeader . nPlanes ; i++) if(!(TinyBitMap . Planes[i] = (PLANEPTR)AllocRaster(InfoHeader . w,InfoHeader . h))) return(FALSE); InitBitMap(&ScreenMap,InfoHeader . nPlanes,NewScreen . Width,NewScreen . Height); /* Try to steal some memory for the bitplanes. */ for(i = 0 ; i < InfoHeader . nPlanes ; i++) if(!(ScreenMap . Planes[i] = (PLANEPTR)AllocRaster(NewScreen . Width,NewScreen . Height))) return(FALSE); return(TRUE); } /* CleanExit() : * * Closes the libraries and exits. */ VOID CleanExit(LONG ExitCode) { /* Take care of external signals. */ SetSignal(0,SIGBREAKF_CTRL_C); /* Return the control to DOS. See what it's doing with * it. */ exit(ExitCode); } /* CloseDisplay() : * * Closes anything that we have opened but the * libraries. */ VOID CloseDisplay() { SHORT i; /* Canst thou hear me? Finish what you have started. */ ClearCycleCode(); /* A window! */ if(Window) { /* Hide the menu. */ Window -> Flags |= RMBTRAP; /* We don't need the menu any more. */ ClearMenuStrip(Window); CloseWindow(Window); Window = NULL; } /* Is there a screen anywhere? */ if(Screen) { CloseScreen(Screen); Screen = NULL; } /* Get rid of the planes. */ for(i = 0 ; i < ScreenMap . Depth ; i++) { if(TinyBitMap . Planes[i]) { FreeRaster(TinyBitMap . Planes[i],InfoHeader . w,InfoHeader . h); TinyBitMap . Planes[i] = NULL; if(ScreenMap . Planes[i]) { FreeRaster(ScreenMap . Planes[i],NewScreen . Width,NewScreen . Height); ScreenMap . Planes[i] = NULL; } continue; } if(ScreenMap . Planes[i]) { FreeRaster(ScreenMap . Planes[i],InfoHeader . w,InfoHeader . h); ScreenMap . Planes[i] = NULL; } } } /* PrintScreen(Large): * * Sends the current LoadImage screen to the printer. */ VOID PrintScreen(UBYTE Large) { struct IODRPReq *PrinterDump; struct MsgPort *PrinterPort; struct IntuiMessage *Massage; ULONG Class; USHORT Code; UBYTE HasTitle = (Screen -> Flags & SHOWTITLE) ? TRUE : FALSE; UBYTE Cycling = IsCycling(); LONG StartX,StartY,Width,Height; volatile LONG OldX = -1,OldY = -1,TempX,TempY,X,Y; SetSnooze(Window); /* IO Replyport. */ if(PrinterPort = (struct MsgPort *)CreatePort(NULL,0)) { /* Custom RastPort dump structure. */ if(PrinterDump = (struct IODRPReq *)CreateExtIO(PrinterPort,sizeof(struct IODRPReq))) { /* Try to open the device. */ if(!OpenDevice("printer.device",0,PrinterDump,0)) { SetSize(Window); SetDrMd(Window -> RPort,COMPLEMENT); /* Don't let anyone disturb the * LoadImage screen bitmap. */ Window -> Flags |= RMBTRAP; if(HasTitle) ShowTitle(Screen,FALSE); if(Cycling) ToggleCycleCode(); /* Let the user set the initial * point. */ FOREVER { WaitPort(Window -> UserPort); if(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort)) { Class = Massage -> Class; Code = Massage -> Code; ReplyMsg(Massage); } if((Class == MOUSEBUTTONS && Code == MENUDOWN) || Class == RAWKEY) { DisplayBeep(Screen); goto HitAndQuit; } if(Class == MOUSEBUTTONS && Code == SELECTDOWN) { X = Window -> MouseX; Y = Window -> MouseY; break; } } /* Now let him resize the rubber box * to the right dimensions. */ ReportMouse(TRUE,Window); FOREVER { USHORT Qualifier; TempX = Window -> MouseX; TempY = Window -> MouseY; if(TempX < 0) TempX = 0; if(TempY < 0) TempY = 0; if(TempX > Window -> Width - 1) TempX = Window -> Width - 1; if(OldX >= 0 && OldY >= 0) { Move(Window -> RPort,X,Y); Draw(Window -> RPort,OldX,Y); Draw(Window -> RPort,OldX,OldY); Draw(Window -> RPort,X,OldY); Draw(Window -> RPort,X,(OldY >= Y) ? Y + 1 : Y - 1); } else OldX = OldY = 0; Move(Window -> RPort,X,Y); Draw(Window -> RPort,TempX,Y); Draw(Window -> RPort,TempX,TempY); Draw(Window -> RPort,X,TempY); Draw(Window -> RPort,X,(TempY >= Y) ? Y + 1 : Y - 1); OldX = TempX; OldY = TempY; WaitLoop: WaitPort(Window -> UserPort); if(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort)) { Class = Massage -> Class; Code = Massage -> Code; Qualifier = Massage -> Qualifier; ReplyMsg(Massage); } if((Class == MOUSEBUTTONS && Code == MENUDOWN) || Class == RAWKEY) { DisplayBeep(Screen); Move(Window -> RPort,X,Y); Draw(Window -> RPort,TempX,Y); Draw(Window -> RPort,TempX,TempY); Draw(Window -> RPort,X,TempY); Draw(Window -> RPort,X,(TempY >= Y) ? Y + 1 : Y - 1); goto HitAndQuit; } if(Class == MOUSEBUTTONS && Code == SELECTUP) { Move(Window -> RPort,X,Y); Draw(Window -> RPort,TempX,Y); Draw(Window -> RPort,TempX,TempY); Draw(Window -> RPort,X,TempY); Draw(Window -> RPort,X,(TempY >= Y) ? Y + 1 : Y - 1); StartX = (X < TempX) ? X : TempX; StartY = (Y < TempY) ? Y : TempY; Width = ABS(TempX - X) + 1; Height = ABS(TempY - Y) + 1; if(Width < 2 || Height < 2) goto HitAndQuit; break; } } /* Initialize the IO Request for * a RastPort dump. */ PrinterDump -> io_Command = PRD_DUMPRPORT; PrinterDump -> io_RastPort = &Screen -> RastPort; PrinterDump -> io_ColorMap = Screen -> ViewPort . ColorMap; PrinterDump -> io_Modes = Screen -> ViewPort . Modes; PrinterDump -> io_SrcWidth = Width; PrinterDump -> io_SrcHeight = Height; PrinterDump -> io_SrcX = StartX; PrinterDump -> io_SrcY = StartY; /* Print it as large as possible? */ if(Large) { PrinterDump -> io_DestCols = 0; PrinterDump -> io_Special = SPECIAL_FULLCOLS | SPECIAL_ASPECT; } else { PrinterDump -> io_DestCols = Width; PrinterDump -> io_Special = SPECIAL_MILCOLS | SPECIAL_ASPECT; } SetSnooze(Window); /* Try the dump. */ if(DoIO(PrinterDump)) DisplayBeep(Screen); /* Re-enable the window. */ HitAndQuit: Window -> Flags &= ~RMBTRAP; SetPoint(Window); /* If set, re-enable the screen title. */ if(HasTitle) ShowTitle(Screen,TRUE); if(Cycling) ToggleCycleCode(); ReportMouse(FALSE,Window); CloseDevice(PrinterDump); } else DisplayBeep(Screen); DeleteExtIO(PrinterDump); } else DisplayBeep(Screen); DeletePort(PrinterPort); } else DisplayBeep(Screen); SetPoint(Window); } /* GetRealName(): * * Looks for a file and returns its real name. */ VOID GetRealName(char *FullName,char *RealName) { struct FileInfoBlock *FileInfo; BPTR FileLock; if(FileLock = Lock(FullName,ACCESS_READ)) { if(FileInfo = (struct FileInfoBlock *)AllocMem(sizeof(struct FileInfoBlock),MEMF_PUBLIC)) { if(Examine(FileLock,FileInfo)) strcpy(RealName,FileInfo -> fib_FileName); FreeMem(FileInfo,sizeof(struct FileInfoBlock)); } UnLock(FileLock); } } /* LoadImage(): * * Will finally load and display an image file. */ LONG LoadImage(char *FileName,UBYTE ForceScroll,UBYTE ForceLace,UBYTE CycleOnStartup,UBYTE LastOne) { UWORD Colours[32]; /* Colour buffer (yes I'm British!) */ LONG ViewModes; WORD ColourNumber; /* Number of colours. */ SHORT MaxOffsetX,MaxOffsetY; /* Some scrolling stuff. */ volatile SHORT StartOffsetX,StartOffsetY; SHORT Width,Height; /* Size of the ViewPort */ SHORT JumpY = 1,JumpX = 1; /* Scrolljump steps */ UBYTE WeAreScrolling = FALSE; UBYTE RemakeTheView; USHORT MenuNum; struct MenuItem *Item; UBYTE IsMouse; /* Scrollmode. */ UBYTE WasCycling; /* What happened? */ UBYTE ChangedColours = FALSE; UBYTE IsTiny = FALSE; /* Image smaller than screen? */ LONG TinyX,TinyY; /* Image offsets for tiny bitmap. */ struct IntuiMessage *Massage; ULONG Class; USHORT Code; SHORT i; /* Loop counters. */ volatile UBYTE *RightMouse = (UBYTE *)0xDFF016; char RealName[108]; GetRealName(FileName,RealName); /* Is it the last picture? */ if(LastOne) MenuItem[8] . Flags &= ~ITEMENABLED; else MenuItem[8] . Flags |= ITEMENABLED; /* Try to load the header. */ if((ViewModes = LoadHeader(FileName,&InfoHeader)) == -1) return(ERR_NOIFF); /* Are there any colours out there? */ if(!(ColourNumber = LoadCMAP(FileName,Colours,32,&InfoHeader))) return(ERR_NOCOLMAP); /* Take care of the size of the ViewPort. */ Width = InfoHeader . pageWidth; Height = InfoHeader . pageHeight; /* Forced scrolling? */ if(ForceScroll) ViewModes &= ~(HIRES | LACE); /* Forced interlaced display mode? */ if(ForceLace) ViewModes |= LACE; /* Take care of exotic screen sizes. */ if(InfoHeader . h > Height) Height = InfoHeader . h; if(InfoHeader . w > Width) Width = InfoHeader . w; /* Hires or lores? */ if(ViewModes & HIRES) { Width = 640; JumpX = 2; } else Width = 320; /* Interlaced or not? This may get funny since * it is possible to scroll the image in steps * of one pixel. In doing so one copper list * (either shortframe or longframe) is ignored * and only half of the image is displayed * correctly. To avoid this the scroll jump * is set to two pixels. */ if(ViewModes & LACE) JumpY = 2; if(Height > GfxBase -> NormalDisplayRows * JumpY) Height = GfxBase -> NormalDisplayRows * JumpY; /* Adjust the information. */ NewScreen . Width = Width; NewScreen . Height = Height; NewScreen . Depth = InfoHeader . nPlanes; NewScreen . ViewModes = ViewModes; /* And don't forget the window. */ NewWindow . Width = Width; NewWindow . Height = Height; /* Anything wrong with the picture? */ if(InfoHeader . w < InfoHeader . pageWidth || InfoHeader . h < InfoHeader . pageHeight) { if(!InitTinyBitMap()) return(ERR_NOMEM); IsTiny = TRUE; } else { /* Initialize the bitmap for future use. */ InitBitMap(&ScreenMap,InfoHeader . nPlanes,InfoHeader . w,InfoHeader . h); /* Try to steal some memory for the bitplanes. */ for(i = 0 ; i < InfoHeader . nPlanes ; i++) { if(!(ScreenMap . Planes[i] = (PLANEPTR)AllocRaster(InfoHeader . w,InfoHeader . h))) return(ERR_NOMEM); IsTiny = FALSE; } } /* Open the screen. */ if(!(Screen = (struct Screen *)OpenScreen(&NewScreen))) return(ERR_NOMEM); /* Hide the title bar and prepare the window. */ ShowTitle(Screen,FALSE); NewWindow . Screen = Screen; /* Try to open the window. */ if(!(Window = (struct Window *)OpenWindow(&NewWindow))) return(ERR_NOMEM); SetSnooze(Window); SetWindowTitles(Window,(STRPTR)-1,(STRPTR)RealName); /* Set up the alternate colour palette. */ for(i = 0 ; i < 32 ; i++) { PrefColours[i] = Colours[i]; if(i >= (1 << NewScreen . Depth)) PrefColours[i] = Colours[i] = GetRGB4(Screen -> ViewPort . ColorMap,i); } PrefColours[0] = StandardPrefs . color0; PrefColours[1] = StandardPrefs . color1; PrefColours[2] = StandardPrefs . color2; PrefColours[3] = StandardPrefs . color3; /* Load the colours. */ LoadRGB4(&Screen -> ViewPort,Colours,ColourNumber); /* Just in case we will have to restore it. */ StartOffsetX = Screen -> ViewPort . RasInfo -> RxOffset; StartOffsetY = Screen -> ViewPort . RasInfo -> RyOffset; /* Play it safe --- keep the maximum scroll offset * in reasonable dimensions. */ if((MaxOffsetX = InfoHeader . w - Width) < 0) MaxOffsetX = 0; if((MaxOffsetY = InfoHeader . h - Height) < 0) MaxOffsetY = 0; /* Absolute maximum limit. */ MaxOffsetX += StartOffsetX; MaxOffsetY += StartOffsetY; /* "Here comes the sun..." */ if(IsTiny) { if(!LoadRaster(FileName,TinyBitMap . Planes,&InfoHeader)) return(ERR_DOS); } else { if(!LoadRaster(FileName,ScreenMap . Planes,&InfoHeader)) return(ERR_DOS); } /* Do we allow colour cycling? */ if(LoadCycleRange(FileName,CycleRange,6)) InitCycleCode(&Screen -> ViewPort,Colours,ColourNumber,CycleRange,6); /* Install the menu and the pointer. */ SetMenuStrip(Window,&Menu); SetPoint(Window); /* And - if necessary - print the tiny image. */ if(IsTiny) { if(InfoHeader . x + InfoHeader . w <= Screen -> Width) TinyX = InfoHeader . x; else TinyX = (NewScreen . Width - InfoHeader . w) >> 1; if(InfoHeader . y + InfoHeader . h <= Screen -> Height) TinyY = InfoHeader . y; else TinyY = (NewScreen . Height - InfoHeader . h) >> 1; BltBitMap(&TinyBitMap,0,0,Screen -> RastPort . BitMap,TinyX,TinyY,InfoHeader . w,InfoHeader . h,0xC0,0xFF,NULL); } /* Paint the screen black (for the effect). */ if(!(ViewModes & HAM)) LoadRGB4(&Screen -> ViewPort,BlackIsBlack,ColourNumber); /* Bring the screen to the front. */ ScreenToFront(Screen); ActivateWindow(Window); FreeSprite(0); /* Fade the colours in. */ if(!(ViewModes & HAM)) FadeTo(&Screen -> ViewPort,NULL,Colours,ColourNumber,0,0); /* Allow the menu to be selected. */ Window -> Flags &= ~RMBTRAP; /* If we are to cycle... */ if(CycleOnStartup) ToggleCycleCode(); /* "Ewig währt am längsten." : Kurt Schwitters (1887 - 1948). * * Kurt Schwitters was a famous * Hanoverian Dada artist. */ FOREVER { /* Let's be nice and wait for reactions. */ WaitPort(Window -> UserPort); /* Massage the userport. */ if(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort)) { Class = Massage -> Class; Code = Massage -> Code; /* If the user presses the menu button * the menu appears. There is nothing * wrong with this, but it might be * possible that the user does not * see the menu because of the raster * offset. So we reposition the ViewPort * before Intuition renders the menu bar. * To keep the menu visible we adjust * the colours if the right mouse * button is pressed. This is done * because of the fact that the * keyboard shortcuts generate the * same MENUVERIFY event. If there is * anyone who doesn't like it this * way he can try to test the keyboard * matrix by tickling the hardware. * I have chosen the easier way. */ if(Class == MENUVERIFY && !(*RightMouse & 4)) { if(WasCycling = IsCycling()) ToggleCycleCode(); LoadRGB4(&Screen -> ViewPort,PrefColours,32); ChangedColours = TRUE; /* Reset the offsets. */ Screen -> ViewPort . RasInfo -> RxOffset = StartOffsetX; Screen -> ViewPort . RasInfo -> RyOffset = StartOffsetY; /* Remake the copper list. */ MakeScreen(Screen); RethinkDisplay(); } ReplyMsg(Massage); } /* If the user presses the select button * we'll assume that he wants to scroll * around in the picture. */ if(Class == MOUSEBUTTONS && Code == SELECTDOWN) { FreeSprite(0); if(ChangedColours) { LoadRGB4(&Screen -> ViewPort,Colours,ColourNumber); ChangedColours = FALSE; if(WasCycling) ToggleCycleCode(); WasCycling = FALSE; } WeAreScrolling = TRUE; IsMouse = TRUE; } /* User pressed the cursor keys and wants * to scroll around in the picture. */ if(Class == RAWKEY && (Code & ~IECODE_UP_PREFIX) >= CURSORUP && (Code & ~IECODE_UP_PREFIX) <= CURSORLEFT) { FreeSprite(0); WeAreScrolling = TRUE; IsMouse = FALSE; } /* User didn't like the menu shortcut * and pressed the Tab key (is he a * DPaint fanatic?). */ if(Class == RAWKEY && Code == 0x42) { FreeSprite(0); ToggleCycleCode(); } /* The user picked a menu item. */ if(Class == MENUPICK) { if(ChangedColours) { LoadRGB4(&Screen -> ViewPort,Colours,ColourNumber); if(WasCycling) ToggleCycleCode(); ChangedColours = FALSE; WasCycling = FALSE; } MenuNum = Code; /* Until the last event is traced. */ while(MenuNum != MENUNULL) { if(MENUNUM(MenuNum) == 0) { switch(ITEMNUM(MenuNum)) { /* About... */ case 0: if(WasCycling = IsCycling()) ToggleCycleCode(); LoadRGB4(&Screen -> ViewPort,PrefColours,32); /* Reset the offsets. */ Screen -> ViewPort . RasInfo -> RxOffset = StartOffsetX; Screen -> ViewPort . RasInfo -> RyOffset = StartOffsetY; /* Remake the copper list. */ MakeScreen(Screen); RethinkDisplay(); InitRequester(&Req); Req . Width = 300; Req . Height = 175; Req . LeftEdge = (Window -> Width - Req . Width) / 2; Req . TopEdge = (Window -> Height - Req . Height) / 2; Req . BackFill = 1; Req . Flags = NOISYREQ | SIMPLEREQ; Req . ReqGadget = &ReqGad; Req . ReqBorder = &ReqBrd[2]; Req . ReqText = &ReqIntTxt[1]; if(Request(&Req,Window)) { FOREVER { WaitPort(Window -> UserPort); while(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort)) { Class = Massage -> Class; ReplyMsg(Massage); if(Class == GADGETUP || Class == RAWKEY) { EndRequest(&Req,Window); goto EndReq; } } } } EndReq: SetPoint(Window); LoadRGB4(&Screen -> ViewPort,Colours,ColourNumber); if(WasCycling) ToggleCycleCode(); FreeSprite(0); break; /* Toggle the presence of the screen title. */ case 2: FreeSprite(0); if(Screen -> Flags & SHOWTITLE) ShowTitle(Screen,FALSE); else ShowTitle(Screen,TRUE); break; /* Toggle cycling. */ case 3: FreeSprite(0); ToggleCycleCode(); break; /* Print screen (standard size). */ case 5: Screen -> ViewPort . RasInfo -> RxOffset = StartOffsetX; Screen -> ViewPort . RasInfo -> RyOffset = StartOffsetY; /* Remake the copper list. */ MakeScreen(Screen); RethinkDisplay(); PrintScreen(FALSE); break; /* Print screen (enlarged). */ case 6: Screen -> ViewPort . RasInfo -> RxOffset = StartOffsetX; Screen -> ViewPort . RasInfo -> RyOffset = StartOffsetY; /* Remake the copper list. */ MakeScreen(Screen); RethinkDisplay(); PrintScreen(TRUE); break; /* Next picture. */ case 8: if(IsCycling()) ToggleCycleCode(); WasCycling = FALSE; if(!(ViewModes & HAM)) FadeTo(&Screen -> ViewPort,Colours,NULL,ColourNumber,0,0); ScreenToBack(Screen); CloseDisplay(); return(0); /* Quit LoadImage. */ case 9: if(IsCycling()) ToggleCycleCode(); WasCycling = FALSE; if(!(ViewModes & HAM)) FadeTo(&Screen -> ViewPort,Colours,NULL,ColourNumber,0,0); ScreenToBack(Screen); CloseDisplay(); return(-1); } } /* See if there is another * menu item around. */ Item = (struct MenuItem *)ItemAddress(&Menu,MenuNum); MenuNum = Item -> NextSelect; } } /* No chance to scroll anywhere, so we'll block * it. */ if(MaxOffsetX == StartOffsetX && MaxOffsetY == StartOffsetY) WeAreScrolling = FALSE; /* This loop will run until the select button * or the cursor key is released. */ while(WeAreScrolling) { if(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort)) { Class = Massage -> Class; Code = Massage -> Code; ReplyMsg(Massage); } /* User doesn't want to scroll anymore? */ if(Code & IECODE_UP_PREFIX) { FreeSprite(0); WeAreScrolling = FALSE; } /* Nothing happened. */ RemakeTheView = FALSE; /* Left border, scroll left. */ if(((Window -> MouseX == 0 && IsMouse) || (Code == CURSORLEFT && !IsMouse)) && (Screen -> ViewPort . RasInfo -> RxOffset - JumpX >= StartOffsetX)) { Screen -> ViewPort . RasInfo -> RxOffset -= JumpX; RemakeTheView = TRUE; } /* Top border, scroll up. */ if(((Window -> MouseY == 0 && IsMouse) || (Code == CURSORUP && !IsMouse)) && (Screen -> ViewPort . RasInfo -> RyOffset - JumpY >= StartOffsetY)) { Screen -> ViewPort . RasInfo -> RyOffset -= JumpY; RemakeTheView = TRUE; } /* Right border, scroll right. */ if(((Window -> MouseX == Window -> Width - 1 && IsMouse) || (Code == CURSORRIGHT && !IsMouse)) && (Screen -> ViewPort . RasInfo -> RxOffset + JumpX <= MaxOffsetX)) { Screen -> ViewPort . RasInfo -> RxOffset += JumpX; RemakeTheView = TRUE; } /* Bottom border, scroll down. */ if(((Window -> MouseY == Window -> Height - 1 && IsMouse) || (Code == CURSORDOWN && !IsMouse)) && (Screen -> ViewPort . RasInfo -> RyOffset + JumpY <= MaxOffsetY)) { Screen -> ViewPort . RasInfo -> RyOffset += JumpY; RemakeTheView = TRUE; } /* Are we to scroll the ViewPort? */ if(RemakeTheView) { MakeScreen(Screen); RethinkDisplay(); } } } } /* QuickSort(av,n) : * * Quicksort routine borrowed from Steve Drew's revision * of Matt Dillon's Shell. Please don't ask me how it * works, I forgot it some moments after my Pascal teacher * had explained it to me in detail. */ VOID QuickSort(char **av,LONG n) { LONG b; if(n > 0) { b = QSplit(av,n); QuickSort(av,b); QuickSort(av + b + 1,n - b - 1); } } /* QSplit(av,n) : * * Quicksort subroutine to save stack space. */ LONG QSplit(char **av,LONG n) { LONG i,b; char *element,*scr; element = av[0]; for(b = 0,i = 1 ; i < n ; i++) { if(Strcmp(av[i],element) < 0) { b++; scr = av[i]; av[i] = av[b]; av[b] = scr; } } scr = av[0]; av[0] = av[b]; av[b] = scr; return(b); } /* Chk_Abort() : * * The system calls this during I/O. Returns 0 to tell * it that there is no CTRL-C around. */ LONG Chk_Abort(VOID) { return(0); } /* _wb_parse(CurrentProcess,WBMsg) : * * Modified Workbench tool parsing routine. This one * always opens a standard output window if the program * has been started from Workbench. Original version * Copyright (C) 1986,1987 by Manx Software Systems, Inc. */ void _wb_parse(struct Process *CurrentProcess,struct WBStartup *WBMsg) { struct FileHandle *FileHandlePtr; /* Window pointer. */ BPTR FileWindow; /* BCPL window pointer. */ static char WindowTitle[40 + 18]; /* Title buffer. */ SHORT i = 0,j = 0; /* Counters. */ if(WBMsg -> sm_NumArgs == 1) return; /* Set up the window title. */ strcpy(WindowTitle,"CON:0/11/640/80/"); /* Find the end of the window title string. */ while(WindowTitle[i]) i++; /* Append the tool name. */ while((WindowTitle[i++] = WBMsg -> sm_ArgList -> wa_Name[j++]) && j != 40); /* Window title null termination. */ WindowTitle[40 + 17] = 0; /* Open the window. */ if(FileWindow = Open(WindowTitle, MODE_OLDFILE)) { /* Convert BPTR to window pointer. */ FileHandlePtr = (struct FileHandle *)BADDR(FileWindow); CurrentProcess -> pr_ConsoleTask = (APTR)FileHandlePtr -> fh_Type; /* Set up console IO streams. */ CurrentProcess -> pr_CIS = FileWindow; CurrentProcess -> pr_COS = Open("*", MODE_OLDFILE); /* Setup for exit to close these if we succeeded. */ _devtab[0] . mode &= ~O_STDIO; _devtab[1] . mode &= ~O_STDIO; } } VOID main(int argc,char **argv) { struct FileRequester *Request; SHORT i,NumItems,Error; char TempName[DSIZE * 10 + FCHARS]; /* Setup the standard colours for later use. */ GetPrefs(&StandardPrefs,sizeof(struct Preferences)); /* Workbench startup? */ if(!argc) { extern struct WBStartup *WBenchMsg; struct WBArg *WArg; char FullPath[DSIZE * 10]; /* Didn't select any project icons? */ if((NumItems = WBenchMsg -> sm_NumArgs - 1) < 1) { if(Request = ArpAllocFreq()) { Request -> fr_Hail = "Select file to display"; FOREVER { if(FileRequest(Request)) { strcpy(TempName,Request -> fr_Dir); TackOn(TempName,Request -> fr_File); if(LoadImage(TempName,FALSE,FALSE,FALSE,FALSE) > 0) DisplayBeep(NULL); } else break; } } CleanExit(RETURN_OK); } /* Take the first argument. */ WArg = WBenchMsg -> sm_ArgList; WArg++; /* Scan the list... */ for(i = 0 ; i < NumItems ; i++) { /* Build image file name. */ PathName(WArg -> wa_Lock,FullPath,DSIZE * 10); TackOn(FullPath,WArg -> wa_Name); WArg++; Printf("Picture \33[33mNº %03ld\33[31m, \33[1m\"%s\"\33[0m loading... ",i + 1,FullPath); if((Error = LoadImage(FullPath,FALSE,FALSE,TRUE,(i == NumItems - 1))) < 0 || BreakCheck()) { if(BreakCheck()) Puts("*** aborted.\a"); else Puts(""); break; } switch(Error) { case ERR_NOIFF: Printf("\33[33mNot an IFF-ILBM file.\33[31m\a"); break; case ERR_NOCOLMAP: Printf("\33[33mNo colour map.\33[31m\a"); break; case ERR_NOMEM: Printf("\33[33mNot enough memory.\33[31m\a"); break; case ERR_DOS: Printf("\33[33mError while reading.\33[31m\a"); break; default: Printf("Done."); break; } Puts(""); } Printf("\nPlease press \33[1mRETURN\33[0m."); Read(Input(),FullPath,1); CleanExit(RETURN_OK); } else { UBYTE ForceScroll = FALSE,ForceLace = FALSE,Cycle = FALSE; SHORT Offset = 1,NumFiles,j; char *FileArray[256],*Pat; /* User wants information? */ if(argv[ARG_INFO]) { Printf("\n \33[1m\33[33mLoadImage\33[31m\33[0m © Copyright 1990 by MXM\n\n"); Printf(" Usage is: \33[1mLoadImage\33[0m [INFO] [NOMODE]/[LACE] [CYCLE] Files1 ... FileN\n"); Printf(" \33[33mAmigaDOS\33[31m wildcards are supported!\n\n"); Printf(" \33[1mINFO\33[0m \33[33m»\33[31m Displays this page.\n"); Printf(" \33[1mNOMODE\33[0m \33[33m»\33[31m Force scrollmode (ignore Hi-Res & Interlace flags).\n"); Printf(" \33[1mLACE\33[0m \33[33m»\33[31m Force interlaced display mode.\n"); Printf(" \33[1mCYCLE\33[0m \33[33m»\33[31m Force colour cycling on startup.\n\n"); Printf(" Note that \33[1mNOMODE\33[0m and \33[1mLACE\33[0m are \33[4mmutually exclusive\33[0m.\n\n"); Printf(" If you wish to come in contact with \33[1mme\33[0m, here's my address:\n\n"); Printf("\tOlaf 'Olsen' Barthel\n"); Printf("\tBrabeckstrasse 35\n"); Printf("\tD-3000 Hannover 71\n\n"); Printf("\t\33[1mFederal Republic of Germany\33[0m\n\n"); Printf(" Have \33[4mfun\33[0m with the code ... \33[3mOlsen\33[0m\n\n"); CleanExit(0); } /* Both modes selected? */ if(argv[ARG_NOMODE] && argv[ARG_LACE]) { Puts(CLI_Help); CleanExit(RETURN_WARN); } /* Force scrolling? */ if(argv[ARG_NOMODE]) { ForceScroll = TRUE; Offset++; } /* Interlaced display mode? */ if(argv[ARG_LACE]) { ForceLace = TRUE; Offset++; } /* Cycle on startup? */ if(argv[ARG_CYCLE]) { Cycle = TRUE; Offset++; } /* No file names given? Show the file requester. */ if(!argv[ARG_FILES]) { if(Request = ArpAllocFreq()) { Request -> fr_Hail = "Select file to display"; FOREVER { if(FileRequest(Request)) { strcpy(TempName,Request -> fr_Dir); TackOn(TempName,Request -> fr_File); if((Error = LoadImage(TempName,ForceScroll,ForceLace,Cycle,FALSE)) < 0 || BreakCheck()) { if(BreakCheck()) Puts("*** aborted.\a"); else Puts(""); break; } switch(Error) { case ERR_NOIFF: Printf("\33[33mNot an IFF-ILBM file.\33[31m\a"); break; case ERR_NOCOLMAP: Printf("\33[33mNo colour map.\33[31m\a"); break; case ERR_NOMEM: Printf("\33[33mNot enough memory.\33[31m\a"); break; case ERR_DOS: Printf("\33[33mError while reading.\33[31m\a"); break; default: Printf("Done."); break; } Puts(""); } } } CleanExit(RETURN_OK); } NumItems = argc - Offset; /* Scan the argument list. */ for(i = 0 ; i < NumItems ; i++) { if(PreParse(argv[ARG_FILES + i],TempName)) { NumFiles = 0; while((Pat = scdir(argv[ARG_FILES + i])) && NumFiles < 255) { if(!(FileArray[NumFiles] = (char *)malloc(strlen(Pat) + 1))) break; strcpy(FileArray[NumFiles++],Pat); if(NumFiles == 2) Printf("\n\33[3mScanning directory for \33[0m\33[1m%s\33[0m...\n\n",BaseName(argv[ARG_FILES + i])); } if(NumFiles > 1) QuickSort(FileArray,NumFiles); for(j = 0 ; j < NumFiles ; j++) { if(!FileArray[j] || !FileArray[j][0]) continue; Printf("Picture \33[33mNº %03ld\33[31m, \33[1m\"%s\"\33[0m loading... ",j + 1,BaseName(FileArray[j])); if((Error = LoadImage(FileArray[j],ForceScroll,ForceLace,Cycle,(i == NumFiles - 1))) < 0 || BreakCheck()) { if(BreakCheck()) Puts("*** aborted.\a"); else Puts(""); break; } switch(Error) { case ERR_NOIFF: Printf("\33[33mNot an IFF-ILBM file.\33[31m\a"); break; case ERR_NOCOLMAP: Printf("\33[33mNo colour map.\33[31m\a"); break; case ERR_NOMEM: Printf("\33[33mNot enough memory.\33[31m\a"); break; case ERR_DOS: Printf("\33[33mError while reading.\33[31m\a"); break; default: Printf("Done."); break; } Puts(""); } for(j = 0 ; j < NumFiles ; j++) free(FileArray[j]); } else { Printf("Picture \33[33mNº %03ld\33[31m, \33[1m\"%s\"\33[0m loading... ",i + 1,argv[ARG_FILES + i]); if((Error = LoadImage(argv[ARG_FILES + i],ForceScroll,ForceLace,Cycle,(i == NumItems - 1))) < 0 || BreakCheck()) { if(BreakCheck()) Puts("*** aborted.\a"); else Puts(""); break; } switch(Error) { case ERR_NOIFF: Printf("\33[33mNot an IFF-ILBM file.\33[31m\a"); break; case ERR_NOCOLMAP: Printf("\33[33mNo colour map.\33[31m\a"); break; case ERR_NOMEM: Printf("\33[33mNot enough memory.\33[31m\a"); break; case ERR_DOS: Printf("\33[33mError while reading.\33[31m\a"); break; default: Printf("Done."); break; } Puts(""); } } } CleanExit(RETURN_OK); }