home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frozen Fish 1: Amiga
/
FrozenFish-Apr94.iso
/
bbs
/
alib
/
d5xx
/
d546
/
2view.lha
/
2View
/
Source
/
2View.c
next >
Wrap
C/C++ Source or Header
|
1991-09-19
|
26KB
|
938 lines
/***********************************************************************\
* 2View V1.11 *
* A simple, fast ILBM viewer, for use under AmigaOS V2.x. *
* Written and ©1991 by Dave Schreiber. All Rights Reserved. *
* *
* Usage: *
* 2View FILE/A/M,FROM/K,SECS=SECONDS/K/N,TICKS/K/N,LOOP/S,PRINT *
* *
* Where the following arguments are defined as follows: *
* FILE - The name of one (or more) IFF ILBM files *
* FROM - A file containing a list of filenames. Used instead of FILE *
* SECS - Number of seconds to display a file *
* TICKS - Number of ticks (1/50ths of a second) *
* LOOP - When finished showing the last pictures, start over *
* PRINT - Print each picture as it is shown *
* *
* To compile (with SAS/C V5.10a): *
* lc -v 2View ARexx *
* blink with 2View.lnk *
* *
* Version history: *
* 1.11 - Improved error reporting (with this version, if the user *
* run 2View from Workbench and there's an error, a requester *
* is put up. Previously, the user was not notified at all *
* of the error). *
* Released 9/11/91 *
* *
* 1.10 - Added support for Workbench, ARexx, scrollable bitmaps, *
* and printing. Also, the user can now use CTRL-C to advance*
* to the next frame, and CTRL-D to abort a playlist. *
* Released 9/3/91 *
* *
* 1.00 - Original version. Released 7/24/91 *
* *
\************************************************************************/
unsigned long availBytes,curPos,bufSize;
/*Include files*/
#include <exec/types.h>
#include <libraries/iffparse.h>
#include <dos/dos.h>
#include <intuition/screens.h>
#include <intuition/intuition.h>
#include <dos/rdargs.h>
#include <exec/memory.h>
#include <devices/printer.h>
#include <devices/prtgfx.h>
#include <workbench/startup.h>
/*Prototypes*/
#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/graphics_protos.h>
#include <clib/iffparse_protos.h>
#include <clib/dos_protos.h>
#include <clib/alib_protos.h>
/*Pragmas*/
#include <pragmas/exec_pragmas.h>
#include <pragmas/intuition_pragmas.h>
#include <pragmas/graphics_pragmas.h>
#include <pragmas/iffparse_pragmas.h>
#include <pragmas/dos_pragmas.h>
/*Other include files*/
#include "iff.h"
#include "2View.h"
#include "arexx.h"
/*Libraries we'll need*/
struct Library *IFFParseBase=NULL;
struct Library *IntuitionBase=NULL;
struct Library *GfxBase=NULL;
/*Provided by the compiler*/
extern struct Library *SysBase;
extern struct Library *DOSBase;
/*Generic screen and window definitions. They will be used to define*/
/*the screen and window that the various pictures will be shown on*/
struct NewScreen newScreen=
{
0,0,0,0,0,1,0,NULL,CUSTOMSCREEN|SCREENBEHIND|AUTOSCROLL,NULL,NULL,NULL,
NULL
};
struct NewWindow newWindow =
{
0,0,0,0,0,1,MENUDOWN|SELECTDOWN|ACTIVEWINDOW|VANILLAKEY,
RMBTRAP|BORDERLESS|NOCAREREFRESH|ACTIVATE,NULL,NULL,NULL,NULL,NULL,
0,0,640,400,CUSTOMSCREEN
};
struct Screen *screen=NULL;
struct Window *window=NULL;
/*A true here indicates the current ILBM file is compressed*/
BYTE Compression;
/*An error message that used in various places*/
char *errorMsg="An error occured while reading";
/*The version string. Do a 'version 2View' to display it*/
char *version="$VER: QView V1.11 (11.9.91)";
/*Just so that the © message is part of the actual program*/
char *copyRightMsg="Copyright 1991 by Dave Schreiber. All Rights Reserved.";
BYTE ExitFlag=FALSE; /*'Exit now' flag*/
UWORD ticks=0; /*Delay requested by user.*/
/*The previous screen and window*/
struct Window *prevWindow=NULL;
struct Screen *prevScreen=NULL;
/*Data for a blank pointer*/
UWORD chip fakePointerData[]={0,0,0,0,0};
BPTR StdErr=NULL; /*'Standard error' for AmigaDOS IO functions*/
struct IFFHandle *iff=NULL; /*IFF handle*/
BPTR pL=NULL; /*Playlist file pointer*/
BOOL masking,print,toFront,printPics;
extern struct WBStartup *WBenchMsg;
char *playListFilename=NULL;
/*Variables that have to be global so that ARexx.c can access them*/
ButtonTypes rexxAbort=none;
extern void dispRexxPort(void);
extern void dnRexxPort();
long arexxSigBit;
UWORD ticksRemaining=0;
BOOL loop=FALSE;
char *picFilename;
char buf[512]; /* A place to dump mask information */
void _main();
struct TagItem TagList[]=
{
/* This defines what part of the displayed picture is shown. It's */
/* necessary to have a line like this in here in order to get */
/* 2.0 autoscrolling to work. */
{SA_Overscan,OSCAN_VIDEO},
{TAG_DONE,NULL}
};
char *about1="2View";
char *about2="Please";
void _main()
{
UWORD c;
LONG args[7];
char **filenames;
char curFilename[140];
BYTE playList; /*True if a playlist is being used, false otherwise*/
/*Initialize the argument buffers to NULL*/
for(c=0;c<7;c++)
args[c]=NULL;
/*Open the libraries*/
IFFParseBase=(struct Library *)OpenLibrary("iffparse.library",0L);
if(IFFParseBase==NULL)
{
cleanup();
exit(50);
}
IntuitionBase=(struct Library *)OpenLibrary("intuition.library",0L);
if(IntuitionBase==NULL)
{
cleanup();
exit(75);
}
GfxBase=(struct Library *)OpenLibrary("graphics.library",0L);
if(GfxBase==NULL)
{
cleanup();
exit(85);
}
/*Get the arguments*/
if(WBenchMsg==NULL)
{
ParseArgs(args);
/*If a playlist filename was provided, store it for later use*/
if(args[4]!=NULL)
{
playListFilename=(char *)args[4];
playList=TRUE;
}
else /*Otherwise, read the filenames from the command line*/
playList=FALSE;
/*If a time was provided (in ticks), use it*/
if(args[1]!=NULL)
ticks=*(ULONG *)args[1]*50;
/*If a time was provided (in seconds), use it (overrides ticks)*/
if(args[2]!=NULL && *(ULONG *)args[2]!=0)
ticks=*(ULONG *)args[2];
/*If neither a picture filename, nor a playlist filename, was*/
/*specified, print an error and exit.*/
if(args[0]==NULL && !playList)
{
printError("Please enter one or more filenames","");
cleanup();
exit(45);
}
/*Determine if we should print the pictures we display or not*/
printPics=(args[5]!=NULL);
/*Get the pointer to the list of filename*/
filenames=(char **)args[0];
/*Will we loop back to the beginning once we finish displaying all*/
/*the pictures?*/
loop=(args[3]!=NULL);
}
else
if(WBenchMsg->sm_NumArgs==1)
{
EasyRequest(NULL,&erError1Line,NULL,
"2View V1.11 (September 11, 1991)",
"Written by Dave Schreiber");
cleanup();
exit(0);
}
/* Initialize the ARexx port */
arexxSigBit=initRexxPort();
if(arexxSigBit==0)
{
cleanup();
exit(47);
}
/*Allocate the IFF structure*/
iff=AllocIFF();
/*If the allocation failed, abort*/
if(iff==NULL)
{
printError("Couldn't allocate necessary resources","");
cleanup();
exit(100);
}
/*Run until we run out of filenames, or the user aborts*/
while(!ExitFlag)
{
picFilename=curFilename; /*Get a pointer to the filename buffer*/
/*Check to see if we're running from Workbench. If so, and the*/
/*user provided names of pictures to display (by clicking on their*/
/*icons), display those pictures*/
if(WBenchMsg!=NULL && WBenchMsg->sm_NumArgs>1)
{
CurrentDir(WBenchMsg->sm_ArgList[1].wa_Lock);
picFilename=WBenchMsg->sm_ArgList[1].wa_Name;
}
else if(playList) /*If a playlist is being used*/
{
pL=Open(playListFilename,MODE_OLDFILE); /*Open the playlist*/
if(pL==NULL) /*If we couldn't open the playlist, abort*/
{
printError("Can't open playlist","");
cleanup();
exit(199);
}
do /*Loop until we run out of playlist, or get a valid name*/
{
if(FGets(pL,picFilename,140)==NULL) /*If end-of-file*/
picFilename=NULL; /*Set as NULL as a flag*/
}
while(picFilename!=NULL && picFilename[0]==0x0A);
if(picFilename!=NULL) /*If not NULL, it's a valid filename*/
picFilename[strlen(picFilename)-1]=NULL; /*Remove the linefeed*/
}
else /*Otherwise, if a playlist isn't being used, get the current*/
picFilename=filenames[0]; /*filename*/
/*Loop while the user hasn't requested an abort, and while*/
/*there are still files to display*/
for(c=0;!ExitFlag && picFilename!=NULL;c++)
{
if((iff->iff_Stream=Open(picFilename,MODE_OLDFILE))==NULL)
{ /*If the ILBM file can't be opened...*/
/*Print an error...*/
printError("Can't open: ", picFilename);
cleanup();
exit(200);
}
InitIFFasDOS(iff); /*The IFF file will be read from disk*/
OpenIFF(iff,IFFF_READ); /*Make iffparse.library aware of the*/
/*ILBM file*/
/*Read in the file and display*/
ReadAndDisplay(picFilename,iff);
CloseIFF(iff); /*Release iffparse's hold on the file*/
Close(iff->iff_Stream); /*Close the file*/
/*Get the next filename, either from Workbench,*/
if(WBenchMsg!=NULL)
{
if(WBenchMsg->sm_NumArgs > c+2)
{
CurrentDir(WBenchMsg->sm_ArgList[c+2].wa_Lock);
picFilename=WBenchMsg->sm_ArgList[c+2].wa_Name;
}
else
picFilename=NULL;
}
else if(playList) /*The playlist,*/
{
do
{
if(FGets(pL,picFilename,140)==NULL)
picFilename=NULL;
}
while(picFilename!=NULL && picFilename[0]==0x0A);
if(picFilename!=NULL)
picFilename[strlen(picFilename)-1]=NULL;
}
else /*or the command line*/
picFilename=filenames[c+1];
}
/*We're finished with this run of pictures*/
if(playList) /*Close playlist, if open*/
Close(pL);
pL=NULL;
if(!loop && !printPics) /*If the loop flag wasn't given, exit*/
ExitFlag=TRUE;
}
/*Time to exit, so close stuff*/
cleanup();
exit(0); /*And exit*/
}
LONG ilbmprops[] = { ID_ILBM,ID_CMAP,ID_ILBM,ID_BMHD,ID_ILBM,ID_CAMG };
/*Read in an ILBM file and display it*/
void ReadAndDisplay(char *filename,struct IFFHandle *iff)
{
int error;
UBYTE *bodyBuffer; /*Pointer to buffer holding 'BODY' chunk info*/
ULONG ViewModes; /*Holds the viewmodes flags*/
UWORD c;
ButtonTypes button;
/*Structures required for IFF parsing*/
struct StoredProperty *bmhd,*cmap,*camg;
struct ContextNode *bodyContext;
/*IntuiMessage...*/
struct IntuiMessage *mesg;
/*Indentify chunks that should be stored during parse*/
/*(in this case, CMAP, BMHD, and CAMG)*/
error=PropChunks(iff,ilbmprops,3);
/*If there was an error, print a message and return*/
if(error!=0)
{
printError(errorMsg,filename);
ExitFlag=TRUE;
return;
}
/*Tell iffparse to stop at a 'BODY' chunk*/
error=StopChunk(iff,ID_ILBM,ID_BODY);
/*Error handling yet again*/
if(error!=0 && error!=-1)
{
printError(errorMsg,filename);
ExitFlag=TRUE;
return;
}
/*Do the actual parsing*/
error=ParseIFF(iff,IFFPARSE_SCAN);
/*Check for errors yet again*/
if(error!=0 && error !=-1)
{
printError(errorMsg,filename);
ExitFlag=TRUE;
return;
}
/*Get the BMHD, CMAP, and CAMG chunks that were read from the file*/
bmhd = FindProp(iff,ID_ILBM,ID_BMHD);
cmap = FindProp(iff,ID_ILBM,ID_CMAP);
camg = FindProp(iff,ID_ILBM,ID_CAMG);
/*Get the descriptor for the BODY chunk*/
bodyContext=CurrentChunk(iff);
/*If there wasn't a BMHD, CMAP, or BODY chunk, abort*/
if(!bmhd | !cmap | !bodyContext)
{
printError(filename,"is corrupted or is not in Amiga ILBM format");
ExitFlag=TRUE;
return;
}
/*Prepare to determine screen modes*/
newScreen.ViewModes=NULL;
/*If there was a CAMG chunk, use it to get the viewmodes*/
if(camg!=NULL)
{
ViewModes=( ((CAMG *)(camg->sp_Data))->viewmodes );
if(ViewModes & HAM)
newScreen.ViewModes|=HAM;
if(ViewModes & EXTRA_HALFBRITE)
newScreen.ViewModes|=EXTRA_HALFBRITE;
if(ViewModes & LACE)
newScreen.ViewModes|=LACE;
if(ViewModes & HIRES)
newScreen.ViewModes|=HIRES;
}
/*Interpret the BMHD chunk*/
getBMHD((struct BitMapHeader *)bmhd->sp_Data);
/*Open a screen, defined by the BMHD and CAMG chunks*/
screen=OpenScreenTagList(&newScreen,TagList);
/*If the screen couldn't be opened, abort*/
if(screen==NULL)
{
printError("Cannot open screen!","");
ExitFlag=TRUE;
return;
}
/*Set the window dimensions from the screen dimensions*/
newWindow.Screen=screen;
newWindow.Width=newScreen.Width;
newWindow.Height=newScreen.Height;
/*Open the window*/
window=OpenWindow(&newWindow);
/*Abort if the window couldn't be opened*/
if(window==NULL)
{
printError("Cannot open window!","");
ExitFlag=TRUE;
return;
}
/*Allocate enough memory to hold the BODY data*/
/*We want to find out what the biggest block of memory is. If*/
/*we have enough memory to hold the entire body chunk, we'll load*/
/*the whole thing into memory and decompress from there. If not,*/
/*we'll load as much as we can and refill the buffer when it*/
/*empties*/
/*We do a Forbid() to keep anyone from allocating memory between*/
/*the AvailMem() and AllocMem() calls. This way, we're guaranteed*/
/*that a memory block of the size given by Availmem() can be */
/*allocated. For this reason, we don't need to check the result*/
/*of the AllocMem(); we're guaranteed that it worked*/
Forbid();
bufSize=AvailMem(MEMF_LARGEST);
bufSize=MIN(bufSize,bodyContext->cn_Size+1);
if(bufSize==0) /*It'll never happen, but just in case...*/
{
Permit();
ExitFlag=TRUE;
return;
}
bodyBuffer=AllocMem(bufSize,0L);
Permit();
availBytes = bufSize;
curPos = bufSize;
/*Blank out the pointer*/
SetPointer(window,fakePointerData,1,16,0,0);
/*Set the screen colors to those provided in the CMAP chunk*/
setScreenColors(screen,cmap->sp_Data,newScreen.Depth);
/*Put the BODY chunk information into the bitmap*/
ReadBodyIntoBitmap(&(screen->BitMap),bodyBuffer,bufSize);
/*Activate the window, and flush any IDCMP message*/
ActivateWindow(window);
while((mesg=(struct IntuiMessage *)GetMsg(window->UserPort))!=NULL)
ReplyMsg((struct Message *)mesg);
/*Bring the screen to the front*/
ScreenToFront(screen);
/*If the user used the 'print' flag on the command line, print*/
/*the picture*/
if(printPics)
dumpRastPort(&(screen->RastPort),&(screen->ViewPort));
print=TRUE;
/*Close the previous window and screen*/
if(prevWindow!=NULL)
CloseWindow(prevWindow);
if(prevScreen!=NULL)
CloseScreen(prevScreen);
/*Free the buffer that holds the BODY chunk information*/
FreeMem(bodyBuffer,bufSize);
/*Store the current window & screen structures, so they can be*/
/*closed later*/
prevWindow=window;
prevScreen=screen;
screen=NULL;
window=NULL;
rexxAbort=none;
if(ticks==0) /*If ticks==0, this means that no delay was specified*/
{ /*by the user. So just wait for him to click a button*/
while((button=checkButton())==none && rexxAbort==none)
{
Wait((1<<prevWindow->UserPort->mp_SigBit) | arexxSigBit);
dispRexxPort();
}
if(button==menu || rexxAbort==menu)
ExitFlag=TRUE;
}
else /*Otherwise, wait for the specified amount of time*/
{
for(c=0;c<ticks;c+=25)
{
ticksRemaining=ticks-c;
Delay((ticksRemaining < 25) ? ticksRemaining : 25);
dispRexxPort(); /*Check ARexx port*/
button=checkButton(); /*After each 25 ticks, check to see if*/
if(button==menu || rexxAbort==menu) /*the user wants to abort*/
{
ExitFlag=TRUE;
return;
}
if(button==select || rexxAbort==select) /*Or advance prematurely*/
return;
}
}
}
/*Convert the CMAP information into a color map, then set the colors*/
/*of the screen according to that colormap*/
void setScreenColors(struct Screen *scr, UBYTE *colorMap, UBYTE depth)
{
int i,numColors;
numColors=1<<depth; /*Get the number of colors (generally 2^depth)*/
if(newScreen.ViewModes & HAM) /*There are, of course, 2 exceptions*/
numColors=16;
if(newScreen.ViewModes & EXTRA_HALFBRITE)
numColors=32;
/*For each color, convert it from CMAP to Amiga form and*/
/*install it*/
for(i=0;i<numColors;i++)
SetRGB4(&(scr->ViewPort),i,colorMap[i*3]>>4,colorMap[i*3+1]>>4,
colorMap[i*3+2]>>4);
return;
}
/*Transform the information in the BODY chunk into a displayable picture,*/
/*decompressing if necessary*/
void ReadBodyIntoBitmap(struct BitMap *bm,UBYTE *buffer,ULONG bufferSize)
{
register int d;
register int repl;
register UBYTE toRepl;
BYTE *src,*dest;
register int depth,rows;
register int bytesInRow;
register int reqDepth;
src=buffer;
bytesInRow=((newScreen.Width+15)/8) & (~1);
/*If there's a mask plane, we have an extra bitplane to read in*/
reqDepth=(masking) ? newScreen.Depth+1 : newScreen.Depth;
/*Loop once for each row*/
for(rows=0;rows<newScreen.Height;rows++)
/*Loop once for each in plane in each row*/
for(depth=0;depth<reqDepth;depth++)
{
/*If we've read all the valid bitplane information and are*/
/*now about to get to the mask, point the destination*/
/*buffer pointer at an unused buffer (a bit bucket)*/
if(masking && depth==reqDepth-1)
dest=buf;
else
dest=&(bm->Planes[depth][bytesInRow*rows]);
if(Compression==1) /*If the file is compressed, decompress*/
{
/*Loop for each byte in the destination row*/
for(d=0;d<bytesInRow;)
{
/*If the compression buffer is full, read more data from*/
/*the disk*/
if(curPos >= availBytes)
{
ReadChunkBytes(iff,src,bufSize);
curPos=0;
}
/*Note: n = the value in the current byte. [n]+1 = the*/
/*value in the next byte*/
/*If 128>n>=0, copy the next n+1 bytes literally*/
if(src[curPos]>=0 && src[curPos]<128)
{
repl=src[curPos++]+1;
/*If there aren't n+1 bytes in the buffer, transfer what */
/*is there to the bitmap, then refill the buffer*/
if(curPos+repl > bufSize)
{
repl-=(bufSize-curPos);
CopyMem(&src[curPos],&dest[d],bufSize-curPos);
d+=(bufSize-curPos);
ReadChunkBytes(iff,src,bufSize);
curPos=0;
}
CopyMem(&src[curPos],&dest[d],repl);
curPos+=repl;
d+=repl;
}
else if(src[curPos] < 0) /*If n < 0, the next -n+1 bytes*/
{ /*are to be set equal to [n]+1*/
repl=-src[curPos++]+1+d;
if(curPos >= availBytes)
{
ReadChunkBytes(iff,src,bufSize);
curPos=0;
}
toRepl=src[curPos++];
for(;d<repl;d++)
dest[d]=toRepl;
}
else /*Otherwise (n==128), just skip that byte*/
curPos++;
}
}
else /*Otherwise, the source buffer isn't compressed, so just*/
{ /*copy the bytes*/
repl=bytesInRow;
d=0;
/*Again, if the buffer doesn't contain all the data we need,*/
/*transfer what's there and then refill the buffer*/
if(curPos+repl > bufSize)
{
repl-=(bufSize-curPos);
CopyMem(&src[curPos],&dest[d],bufSize-curPos);
d+=(bufSize-curPos);
ReadChunkBytes(iff,src,bufSize);
curPos=0;
}
CopyMem(&src[curPos],&dest[d],repl);
curPos+=repl;
}
}
return;
}
/*Make a newScreen structure using the BMHD chunk*/
void getBMHD(struct BitMapHeader *bmhd)
{
if(bmhd->w > 400 && bmhd->w <=704) /*Define the screen as hires*/
newScreen.ViewModes|=HIRES; /*If wider than 400 pixels*/
if(bmhd->h > 300 && bmhd->h <=512) /*Define the screen as interlaced*/
newScreen.ViewModes|=LACE; /*if the height is > 300 pixels*/
newScreen.Width=bmhd->w; /*Store the rest of the values*/
newScreen.Height=bmhd->h;
newScreen.LeftEdge=bmhd->x;
newScreen.TopEdge=bmhd->y;
newScreen.Depth=bmhd->nplanes;
masking=(bmhd->Masking == 1);
Compression=bmhd->Compression; /*Compression flag. Store for*/
/*later use*/
return;
}
/*Data structures for ReadArgs()*/
struct RDArgs ra=
{
{NULL,0,0},
NULL,
buf,
512,
"FILE/A/M,SECS=SECONDS/K/N,TICKS/K/N,LOOP/S,FROM/K,PRINT/S"
};
/*Parse the argument list, using ReadArgs()*/
void ParseArgs(ULONG *args)
{
ReadArgs("FILE/A/M,SECS=SECONDS/K/N,TICKS/K/N,LOOP/S,FROM/K,PRINT/S",
args,&ra);
return;
}
/*Check to see which mouse buttons have been pressed*/
ButtonTypes checkButton(void)
{
struct IntuiMessage *mesg;
ButtonTypes Button=none;
static justActivated=FALSE;
/*This function disregards a select (left) mouse button click*/
/*if the window's just been activated. This is so that a user*/
/*can click on another window, then make this one active again,*/
/*without advancing to the next picture*/
/*While there are messages to be read...*/
while((mesg=(struct IntuiMessage *)GetMsg(prevWindow->UserPort))!=NULL)
{
/*Interpret them*/
switch(mesg->Class)
{
case ACTIVEWINDOW: /*Set the appropriate flag if the window*/
justActivated=TRUE; /*was just activated*/
break;
case VANILLAKEY:
switch(mesg->Code)
{
case 16: /*CTRL-P - Print (if this picture hasn't been*/
if(print) /*printed; this is designed in case the user*/
{ /*holds down CTRL-P: we don't want 10-20 */
/*print requests to get queued up */
dumpRastPort(&(prevScreen->RastPort),
&(prevScreen->ViewPort));
print=FALSE;
}
break;
case 4: /*CTRL-D - Abort everything*/
Button=menu;
break;
case 3:
Button=select; /*CTRL-C - Advance to next picture*/
break;
}
break;
case MOUSEBUTTONS: /*Interpret a button click*/
if(mesg->Code==SELECTDOWN) /*If the left button was pushed,*/
if(justActivated) /*and not so as to activate the*/
{ /*window, advance to the next*/
justActivated=FALSE; /*screen*/
break;
}
else
Button=select;
else if(mesg->Code == MENUDOWN) /*If the right button was*/
Button=menu; /*pushed, we'll want to*/
break; /*abort*/
}
ReplyMsg((struct Message *)mesg); /*Reply to the message*/
}
return(Button); /*Return the results*/
}
/*This prints an error to the console, if we were run from the CLI*/
/*This is done instead of using Output() so as to get around any redirection*/
/*that may be in place (just like the standard C stderr)*/
/*If we can't open a StdErr or 2View was run from Workbench, a requester */
/*is put up*/
void printError(char *error1,char *error2)
{
if(StdErr==NULL)
StdErr=Open("CONSOLE:",MODE_OLDFILE);
/* If we can't open StdErr, or Output()==NULL (meaning we're running */
/* Workbench), put up a requester */
if(StdErr==NULL || Output()==NULL)
{
if(error2==NULL || error2[0]==NULL)
EasyRequest(NULL,&erError1Line,NULL,error1,"Exiting...");
else
EasyRequest(NULL,&erError2Line,NULL,error1,error2,"Exiting...");
}
else
{
FPuts(StdErr,error1);
FPuts(StdErr,error2);
FPuts(StdErr,"\nExiting\n");
}
return;
}
/*Free allocated resources in anticipation of quitting*/
void cleanup()
{
/*Close the ARexx port*/
dnRexxPort();
/*Close the standard-error file if opened*/
if(StdErr!=NULL)
Close(StdErr);
/*Close a previous screen and window, if open*/
if(prevWindow!=NULL)
CloseWindow(prevWindow);
if(prevScreen!=NULL)
CloseScreen(prevScreen);
/*Close a current screen and window, if open*/
if(window!=NULL)
CloseWindow(window);
if(screen!=NULL)
CloseScreen(screen);
if(iff!=NULL)
FreeIFF(iff);
if(pL!=NULL)
Close(pL);
if(IFFParseBase!=NULL)
CloseLibrary(IFFParseBase);
if(IntuitionBase!=NULL)
CloseLibrary(IntuitionBase);
if(GfxBase!=NULL)
CloseLibrary(GfxBase);
}
/*Print the specified RastPort (whose ViewPort is pointed to by vp*/
BOOL dumpRastPort(struct RastPort *rp,struct ViewPort *vp)
{
struct IODRPReq *printerMsg;
struct MsgPort *printerPort;
static BOOL ableToPrint=TRUE;
if(ableToPrint)
{
ableToPrint=FALSE;
printerPort=CreatePort("2View.print.port",0);
if(printerPort!=NULL)
{
printerMsg=(struct IORequest *)CreateExtIO(printerPort,
(long)sizeof(struct IODRPReq));
if(printerMsg != NULL)
{
/*Open the printer device*/
if(OpenDevice("printer.device",0,printerMsg,0)==0)
{
/*Set up the IODRPReq structure*/
printerMsg->io_Command=PRD_DUMPRPORT;
printerMsg->io_RastPort=rp;
printerMsg->io_ColorMap=vp->ColorMap;
printerMsg->io_Modes=vp->Modes;
printerMsg->io_SrcX=0;
printerMsg->io_SrcY=0;
printerMsg->io_SrcWidth=vp->DWidth;
printerMsg->io_SrcHeight=vp->DHeight;
printerMsg->io_Special=SPECIAL_ASPECT|SPECIAL_FULLROWS|
SPECIAL_FULLCOLS;
/*Do it*/
if(DoIO(printerMsg)==0)
ableToPrint=TRUE;
CloseDevice(printerMsg);
}
DeleteExtIO(printerMsg);
}
DeletePort(printerPort);
}
return(ableToPrint);
}
}
/*End of 2View.c*/