Reverted removal of 'const' from TagItem arrays/pointers in r50147
[AROS.git] / workbench / demos / 2View / 2View.c
blob442ee3d8c4c63759bbb64d9f8b9e88f7a548ae90
1 /* Modified version for AROS - The AROS Research OS
2 ** $Id$
3 */
5 /***********************************************************************\
6 * 2View V1.50 *
7 * A simple, fast ILBM viewer, for use under AmigaOS V2.x. *
8 * Written and ©1991-1992 by Dave Schreiber. All Rights Reserved. *
9 * *
10 * Usage: *
11 * 2View FILE/A/M,FROM/K,SECS=SECONDS/K/N,TICKS/K/N,LOOP/S,PRINT *
12 * *
13 * Where the following arguments are defined as follows: *
14 * FILE - The name of one (or more) IFF ILBM files *
15 * FROM - A file containing a list of filenames. Used instead of FILE *
16 * SECS - Number of seconds to display a file *
17 * TICKS - Number of ticks (1/60ths of a second) *
18 * LOOP - When finished showing the last pictures, start over *
19 * PRINT - Print each picture as it is shown *
20 * *
21 * To compile (with SAS/C V5.10a): *
22 * lc -v 2View ARexx *
23 * lc -v -b0 Misc *
24 * asm 2ViewAsm.a *
25 * blink with 2View.lnk *
26 * *
27 * Version history: *
28 * 1.50 - Rewrote the subroutine that reads the ILBM from disk in *
29 * assembly language, for speed. Added support for SHAM and *
30 * Macro Paint images, and for color cycling (both *
31 * traditional (CRNG, i.e. continutout cycle ranges) and *
32 * DPaint-IV style cycling (DRNG, i.e. non-continuous cycle *
33 * ranges). A 'tick' (as used with the "TICK" keyword, above)*
34 * has been redefined as 1/60th of a second. Finally, the *
35 * source code in 2View.c has been split into two files *
36 * (2View.c and Misc.c). *
37 * Released 3/24/92 *
38 * *
39 * 1.11 - Improved error reporting (with this version, if the user *
40 * run 2View from Workbench and there's an error, a requester *
41 * is put up. Previously, the user was not notified at all *
42 * of the error). *
43 * Released 9/11/91 *
44 * *
45 * 1.10 - Added support for Workbench, ARexx, scrollable bitmaps, *
46 * and printing. Also, the user can now use CTRL-C to advance*
47 * to the next frame, and CTRL-D to abort a playlist. *
48 * Released 9/3/91 *
49 * *
50 * 1.00 - Original version. Released 7/24/91 *
51 * *
52 \************************************************************************/
55 unsigned long availBytes,curPos,bufSize;
57 /*Include files*/
59 #include <exec/types.h>
60 #include <libraries/iffparse.h>
61 #include <dos/dos.h>
62 #include <dos/dosasl.h>
63 #include <intuition/intuition.h>
64 #include <exec/memory.h>
65 #include <workbench/startup.h>
66 #include <graphics/gfxbase.h>
68 /*Prototypes*/
69 #include <proto/exec.h>
70 #include <proto/intuition.h>
71 #include <proto/dos.h>
72 #include <proto/graphics.h>
73 #include <proto/iffparse.h>
75 /*Other include files*/
76 #include "iff.h"
77 #include "2View.h"
78 /* #include "arexx.h" */
80 #include <stdlib.h>
81 #include <string.h>
83 /*Libraries we'll need*/
84 struct Library *IFFParseBase=NULL;
85 struct IntuitionBase *IntuitionBase=NULL;
86 struct GfxBase *GfxBase=NULL;
88 #ifdef __AROS__
89 #define __chip
90 #endif
92 /*Generic screen and window definitions. They will be used to define*/
93 /*the screen and window that the various pictures will be shown on*/
94 struct NewScreen newScreen=
96 0,0,0,0,0,1,0,0,CUSTOMSCREEN|SCREENBEHIND|AUTOSCROLL,NULL,NULL,NULL,
97 NULL
100 struct NewWindow newWindow =
102 0,0,0,0,0,1,IDCMP_MENUPICK|IDCMP_MOUSEBUTTONS|IDCMP_ACTIVEWINDOW|IDCMP_VANILLAKEY,
103 WFLG_RMBTRAP|WFLG_BORDERLESS|WFLG_NOCAREREFRESH,NULL,NULL,NULL,NULL,NULL,
104 0,0,640,400,CUSTOMSCREEN
107 struct Screen *screen=NULL;
108 struct Window *window=NULL;
110 UWORD *storage;
111 int counter;
113 /*A true here indicates the current ILBM file is compressed*/
114 BYTE Compression;
116 /*The version string. Do a 'version 2View' to display it*/
117 char *version="$VER: QView V1.50 (24.3.92)";
119 /*Just so that the © message is part of the actual program*/
120 char *copyRightMsg="Copyright 1991-1992 by Dave Schreiber. All Rights Reserved.";
122 BYTE ExitFlag=FALSE; /*'Exit now' flag*/
123 UWORD ticks=0; /*Delay requested by user.*/
125 /*The previous screen and window*/
126 struct Window *prevWindow=NULL;
127 struct Screen *prevScreen=NULL;
129 /*Data for a blank pointer*/
130 UWORD __chip fakePointerData[]={0,0,0,0,0};
132 struct IFFHandle *iff=NULL; /*IFF handle*/
133 BPTR pL=BNULL; /*Playlist file pointer*/
134 BOOL masking,print,toFront,printPics;
135 #ifdef __AROS__
136 struct WBStartup *WBenchMsg = NULL;
137 #else
138 extern struct WBStartup *WBenchMsg;
139 #endif
141 char *playListFilename=NULL;
143 /*Variables that have to be global so that ARexx.c can access them*/
144 ButtonTypes rexxAbort=none;
145 /* long arexxSigBit; */
146 UWORD ticksRemaining=0;
147 BOOL loop=FALSE;
148 BYTE specialModes;
150 char *picFilename;
151 char trashBuf[512]; /* A place to dump mask information */
152 char *buf=trashBuf;
154 struct TagItem TagList[]=
156 /* This defines what part of the displayed picture is shown. It's */
157 /* necessary to have a line like this in here in order to get */
158 /* 2.0 autoscrolling to work. */
159 {SA_Overscan,OSCAN_VIDEO},
160 {TAG_DONE,0}
163 char *about1="2View";
164 char *about2="Please";
166 extern struct EasyStruct erError1Line;
167 BOOL cycle=FALSE;
168 UBYTE numColors;
169 UWORD destMap[32];
170 UBYTE numCycleColors;
171 UBYTE rate;
173 /* The assembly-language reader routine */
174 extern int ReadILBM (struct IFFHandle * iff,
175 struct Window * window, ULONG width, ULONG height, UWORD Depth,
176 BOOL Compression, BOOL masking);
178 char **filenames;
179 UWORD numFilenames=0,numSlots;
181 int main(int argc, char ** argv)
183 UWORD c;
184 IPTR args[7] = { 0 };
185 char **filenames = NULL;
186 char curFilename[140];
187 BYTE playList = FALSE; /*True if a playlist is being used, false otherwise*/
189 /*Open the libraries*/
190 IFFParseBase=(struct Library *)OpenLibrary("iffparse.library",0L);
191 if(IFFParseBase==NULL)
193 cleanup();
194 exit(50);
197 IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",0L);
198 if(IntuitionBase==NULL)
200 cleanup();
201 exit(75);
204 GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",0L);
205 if(GfxBase==NULL)
207 cleanup();
208 exit(85);
211 /*Get the arguments*/
212 if(WBenchMsg==NULL)
214 ParseArgs(args);
216 /*If a playlist filename was provided, store it for later use*/
217 if((char *)args[4]!=NULL)
219 playListFilename=(char *)args[4];
220 playList=TRUE;
222 else /*Otherwise, read the filenames from the command line*/
223 playList=FALSE;
225 /*If a time was provided (in ticks), use it*/
226 if((ULONG *)args[1]!=NULL)
227 ticks=*(ULONG *)args[1]*50;
229 /*If a time was provided (in seconds), use it (overrides ticks)*/
230 if((ULONG *)args[2]!=NULL && *(ULONG *)args[2]!=0)
231 ticks=*(ULONG *)args[2];
233 /*If neither a picture filename, nor a playlist filename, was*/
234 /*specified, print an error and exit.*/
235 if((char **)args[0]==NULL && !playList)
237 printError("Please enter one or more filenames");
238 cleanup();
239 exit(45);
242 /*Determine if we should print the pictures we display or not*/
243 printPics=((BOOL *)args[5]!=NULL);
245 /*Get the pointer to the list of filename*/
246 filenames=(char **)args[0];
248 /*Will we loop back to the beginning once we finish displaying all*/
249 /*the pictures?*/
250 loop=((BOOL *)args[3]!=NULL);
252 else
253 if(WBenchMsg->sm_NumArgs==1)
255 EasyRequest(NULL,&erError1Line,NULL,
256 (IPTR) "2View V1.50 (March 24, 1992)",
257 (IPTR) "Written by Dave Schreiber");
258 cleanup();
259 exit(0);
263 #if 0
264 /* Initialize the ARexx port */
265 arexxSigBit=initRexxPort();
266 if(arexxSigBit==0)
268 cleanup();
269 exit(47);
271 #endif
273 /*Allocate the IFF structure*/
274 iff=AllocIFF();
276 /*If the allocation failed, abort*/
277 if(iff==NULL)
279 printError("Couldn't allocate necessary resources");
280 cleanup();
281 exit(100);
284 /*Run until we run out of filenames, or the user aborts*/
285 while(!ExitFlag)
287 picFilename=curFilename; /*Get a pointer to the filename buffer*/
289 /*Check to see if we're running from Workbench. If so, and the*/
290 /*user provided names of pictures to display (by clicking on their*/
291 /*icons), display those pictures*/
292 if(WBenchMsg!=NULL && WBenchMsg->sm_NumArgs>1)
294 CurrentDir(WBenchMsg->sm_ArgList[1].wa_Lock);
295 picFilename=WBenchMsg->sm_ArgList[1].wa_Name;
297 else if(playList) /*If a playlist is being used*/
299 pL=Open(playListFilename,MODE_OLDFILE); /*Open the playlist*/
301 if(pL==BNULL) /*If we couldn't open the playlist, abort*/
303 printError("Can't open playlist");
304 cleanup();
305 exit(199);
308 do /*Loop until we run out of playlist, or get a valid name*/
310 if(FGets(pL,picFilename,140)==NULL) /*If end-of-file*/
311 picFilename=NULL; /*Set as NULL as a flag*/
313 while(picFilename!=NULL && picFilename[0]==0x0A);
315 if(picFilename!=NULL) /*If not NULL, it's a valid filename*/
316 picFilename[strlen(picFilename)-1]='\0'; /*Remove the linefeed*/
318 else /*Otherwise, if a playlist isn't being used, get the current*/
319 picFilename=filenames[0]; /*filename*/
322 /*Loop while the user hasn't requested an abort, and while*/
323 /*there are still files to display*/
324 for(c=0;!ExitFlag && picFilename!=NULL;c++)
326 if((iff->iff_Stream=(IPTR)Open(picFilename,MODE_OLDFILE))==0)
327 { /*If the ILBM file can't be opened...*/
329 /*Print an error...*/
330 printError("Can't open: %s", picFilename);
332 cleanup();
333 exit(200);
336 InitIFFasDOS(iff); /*The IFF file will be read from disk*/
338 OpenIFF(iff,IFFF_READ); /*Make iffparse.library aware of the*/
339 /*ILBM file*/
341 /*Read in the file and display*/
342 ReadAndDisplay(picFilename,iff);
344 CloseIFF(iff); /*Release iffparse's hold on the file*/
346 Close((BPTR)iff->iff_Stream); /*Close the file*/
348 /*Get the next filename, either from Workbench,*/
349 if(WBenchMsg!=NULL)
351 if(WBenchMsg->sm_NumArgs > c+2)
353 CurrentDir(WBenchMsg->sm_ArgList[c+2].wa_Lock);
354 picFilename=WBenchMsg->sm_ArgList[c+2].wa_Name;
356 else
357 picFilename=NULL;
359 else if(playList) /*The playlist*/
363 if(FGets(pL,picFilename,140)==NULL)
364 picFilename=NULL;
366 while(picFilename!=NULL && picFilename[0]==0x0A);
368 if(picFilename!=NULL)
369 picFilename[strlen(picFilename)-1]='\0';
371 else /*or the command line*/
372 picFilename=filenames[c+1];
375 /*We're finished with this run of pictures*/
376 if(playList) /*Close playlist, if open*/
377 Close(pL);
378 pL=BNULL;
380 if(!loop && !printPics) /*If the loop flag wasn't given, exit*/
381 ExitFlag=TRUE;
384 /*Time to exit, so close stuff*/
386 cleanup();
387 exit(0); /*And exit*/
390 LONG ilbmprops[] = { ID_ILBM,ID_CMAP,ID_ILBM,ID_BMHD,ID_ILBM,ID_CAMG,
391 ID_ILBM,ID_CRNG,ID_ILBM,ID_DRNG,ID_ILBM,ID_SHAM,
392 ID_ILBM,ID_CTBL };
394 /*Read in an ILBM file and display it*/
395 void ReadAndDisplay(char *filename,struct IFFHandle *iff)
397 int error;
398 UBYTE *bodyBuffer = NULL; /*Pointer to buffer holding 'BODY' chunk info*/
399 ULONG ViewModes; /*Holds the viewmodes flags*/
400 UWORD c;
401 ButtonTypes button;
402 UBYTE cycleTable[32];
403 UBYTE countDown;
405 /*Structures required for IFF parsing*/
406 struct StoredProperty *bmhd,*cmap,*camg,*crng,*drng,*sham;
407 #if 0 /* for MacroPaint */
408 struct StoredProperty *ctbl;
409 #endif
410 struct ContextNode *bodyContext;
412 /*IntuiMessage...*/
413 struct IntuiMessage *mesg;
415 /*Indentify chunks that should be stored during parse*/
416 /*(in this case, CMAP, BMHD, CRNG, DRNG, CAMG, and SHAM)*/
417 error=PropChunks(iff,ilbmprops,7);
419 /*If there was an error, print a message and return*/
420 if(error!=0)
422 printError("Error in PropChunks() wile reading %s: %d\n",filename,error);
423 ExitFlag=TRUE;
424 return;
427 /*Tell iffparse to stop at a 'BODY' chunk*/
428 error=StopChunk(iff,ID_ILBM,ID_BODY);
430 /*Error handling yet again*/
431 if(error!=0 && error!=-1)
433 printError("Error in StopChunk() wile reading %s: %d\n",filename,error);
434 ExitFlag=TRUE;
435 return;
438 /*Do the actual parsing*/
439 error=ParseIFF(iff,IFFPARSE_SCAN);
441 /*Check for errors yet again*/
442 if(error!=0 && error !=-1)
444 printError("Error in ParseIFF() wile reading %s: %d\n",filename,error);
445 ExitFlag=TRUE;
446 return;
449 /*Get the chunks that were found in the file*/
450 bmhd = FindProp(iff,ID_ILBM,ID_BMHD); /*Bitmap information*/
451 cmap = FindProp(iff,ID_ILBM,ID_CMAP); /*Color map*/
452 camg = FindProp(iff,ID_ILBM,ID_CAMG); /*Amiga viewmode information*/
453 crng = FindProp(iff,ID_ILBM,ID_CRNG); /*Color-cycling ranges*/
454 drng = FindProp(iff,ID_ILBM,ID_DRNG); /*New (DPaint IV) color-cycling*/
455 sham = FindProp(iff,ID_ILBM,ID_SHAM); /*SHAM color tables*/
456 #if 0
457 ctbl = FindProp(iff,ID_ILBM,ID_CTBL); /*Macro Paint color table info*/
458 #endif
460 /*Get the descriptor for the BODY chunk*/
461 bodyContext=CurrentChunk(iff);
463 /*If there wasn't a BMHD, CMAP, or BODY chunk, abort*/
464 if (!bmhd | !cmap | !bodyContext)
466 printError ("%s is corrupted or is not in Amiga ILBM format. No %s%s%s%s%s found."
467 , filename
468 , bmhd ? "" : "BMHD"
469 , !bmhd && !cmap ? ", " : ""
470 , cmap ? "" : "CMAP"
471 , (!bmhd || !cmap) && !bodyContext ? ", " : ""
472 , bodyContext ? "" : "BODY"
474 ExitFlag=TRUE;
475 return;
478 /*Prepare to determine screen modes*/
479 newScreen.ViewModes=0;
481 /*If there was a CAMG chunk, use it to get the viewmodes*/
482 if(camg!=NULL)
484 ViewModes=( ((CAMG *)(camg->sp_Data))->viewmodes );
486 if(ViewModes & HAM)
487 newScreen.ViewModes|=HAM;
489 if(ViewModes & EXTRA_HALFBRITE)
490 newScreen.ViewModes|=EXTRA_HALFBRITE;
492 if(ViewModes & LACE)
493 newScreen.ViewModes|=LACE;
495 if(ViewModes & HIRES)
496 newScreen.ViewModes|=HIRES;
500 if(crng==NULL)
502 if(drng==NULL) /*No color cycling*/
503 numCycleColors=0;
504 else /* DPaint-IV--style color cycling*/
505 numCycleColors=interpretDRNG(cycleTable,(DRNG *)(drng->sp_Data),&rate);
506 } else /*DPaint I-III--style color cycling*/
507 numCycleColors=interpretCRNG( cycleTable,(CRNG *)(crng->sp_Data),&rate);
509 if(numCycleColors != 0)
510 cycle=TRUE; /*Start cycling if there are colors to cycle*/
511 else
512 cycle=FALSE;
514 /*Interpret the BMHD chunk*/
515 getBMHD(bmhd->sp_Data);
517 /*Don't open an interlace screen if the image is in SHAM mode*/
518 /*(the Amiga OS doesn't properly handle user copper lists on */
519 /*interlaced screens for some reason)*/
520 if(sham!=NULL)
521 newScreen.ViewModes&=~LACE;
523 /*Open a screen, defined by the BMHD and CAMG chunks*/
524 screen=OpenScreenTagList(&newScreen,TagList);
526 /*If the screen couldn't be opened, abort*/
527 if(screen==NULL)
529 printError("Cannot open screen!");
530 ExitFlag=TRUE;
531 return;
534 /*This more properly centers the screen, for some reason */
535 MoveScreen(screen,1,1);
536 MoveScreen(screen,-1,-1);
538 /*Set the window dimensions from the screen dimensions*/
539 newWindow.Screen=screen;
540 newWindow.Width=newScreen.Width;
541 newWindow.Height=newScreen.Height;
543 /*Open the window*/
544 window=OpenWindow(&newWindow);
546 /*Abort if the window couldn't be opened*/
547 if(window==NULL)
549 printError("Cannot open window!");
551 ExitFlag=TRUE;
552 return;
555 availBytes = bufSize;
556 curPos = bufSize;
558 /*Blank out the pointer*/
559 SetPointer(window,fakePointerData,1,16,0,0);
561 /*Set the screen colors to those provided in the CMAP chunk*/
562 setScreenColors(screen,cmap->sp_Data,newScreen.Depth,destMap,&numColors);
564 /*Uncompress an ILBM and copy it into the bitmap*/
565 if (!ReadILBM (iff, window, window->Width, window->Height,
566 newScreen.Depth,
567 Compression, masking))
569 printError ("Cannot read bitmap!");
571 ExitFlag=TRUE;
572 return;
575 /*Activate the window, and flush any IDCMP message*/
576 ActivateWindow(window);
577 while((mesg=(struct IntuiMessage *)GetMsg(window->UserPort))!=NULL)
578 ReplyMsg((struct Message *)mesg);
580 #if 0
581 /*If this is a SHAM image, setup the copper list appropriately*/
582 if(sham!=NULL)
584 specialModes=SHAM;
585 setupSHAM(screen,(UWORD *)(sham->sp_Data));
587 else
588 /*If this is a MacroPaint image, setup the copper list*/
589 if(ctbl!=NULL)
591 specialModes=MACROPAINT;
592 setupDynHires(screen,(UWORD *)(ctbl->sp_Data));
594 else
595 #endif
596 /* Otherwise, this is a normal ILBM*/
597 specialModes=NORMAL_MODE;
599 /*Bring the screen to the front*/
600 ScreenToFront(screen);
602 /*If the user used the 'print' flag on the command line, print*/
603 /*the picture (but not if this is a SHAM or MacroPaint image)*/
604 if(printPics && specialModes == NORMAL_MODE)
605 dumpRastPort(&(screen->RastPort),&(screen->ViewPort));
607 print=TRUE;
609 /*Close the previous window and screen*/
610 if(prevWindow!=NULL)
611 CloseWindow(prevWindow);
612 if(prevScreen!=NULL)
613 CloseScreen(prevScreen);
615 /*Free the buffer that holds the BODY chunk information*/
616 FreeMem(bodyBuffer,bufSize);
618 /*Store the current window & screen structures, so they can be*/
619 /*closed later*/
620 prevWindow=window;
621 prevScreen=screen;
623 screen=NULL;
624 window=NULL;
626 rexxAbort=none;
627 countDown=rate;
628 if(ticks==0) /*If ticks==0, this means that no delay was specified*/
629 { /*by the user. So just wait for him to click a button*/
630 #if 0
631 int prevTopEdge=prevScreen->TopEdge;
632 #endif
634 while((button=checkButton())==none && rexxAbort==none)
636 /*Wait for 1/60th of a second*/
637 Wait (1L << prevWindow->UserPort->mp_SigBit);
639 #if 0
640 /*Refresh the SHAM copper list if required*/
641 if(prevTopEdge!=prevScreen->TopEdge && sham!=NULL)
643 prevTopEdge=prevScreen->TopEdge;
644 setupSHAM(prevScreen,(UWORD *)(sham->sp_Data));
647 /*Refresh the MacroPaint copper list if required*/
648 if(prevTopEdge!=prevScreen->TopEdge && ctbl!=NULL)
650 prevTopEdge=prevScreen->TopEdge;
651 setupDynHires(prevScreen,(UWORD *)(ctbl->sp_Data));
653 #endif
655 /*If its time to cycle the colors, then cycle them*/
656 if(cycle && numCycleColors!=0 && --countDown==0)
658 cycleColors(cycleTable,destMap,numCycleColors,numColors);
659 countDown=rate;
662 #if 0
663 dispRexxPort();
664 #endif
667 /*Check to see if the user wants to abort*/
668 if(button==menu || rexxAbort==menu)
669 ExitFlag=TRUE;
671 else /*Otherwise, wait for the specified amount of time*/
673 for(c=0;c<ticks;c++)
675 /*Wait 1/60th of a second*/
676 WaitTOF();
678 /*Cycle colors if necessary*/
679 if(cycle && numCycleColors!=0 && --countDown==0)
681 cycleColors(cycleTable,destMap,numCycleColors,numColors);
682 countDown=rate;
685 #if 0
686 dispRexxPort(); /*Check ARexx port*/
687 #endif
689 button=checkButton(); /*After each 25 ticks, check to see if*/
690 if(button==menu || rexxAbort==menu) /*the user wants to abort*/
692 ExitFlag=TRUE;
693 return;
695 if(button==select || rexxAbort==select) /*Or advance prematurely*/
696 return;
701 /*End of 2View.c*/