home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / Programming / DOpus4-GPL / Program / iffload.c < prev    next >
C/C++ Source or Header  |  2000-01-27  |  51KB  |  1,964 lines

  1. /*
  2.  
  3. Directory Opus 4
  4. Original GPL release version 4.12
  5. Copyright 1993-2000 Jonathan Potter
  6.  
  7. This program is free software; you can redistribute it and/or
  8. modify it under the terms of the GNU General Public License
  9. as published by the Free Software Foundation; either version 2
  10. of the License, or (at your option) any later version.
  11.  
  12. This program is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. GNU General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with this program; if not, write to the Free Software
  19. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  20.  
  21. All users of Directory Opus 4 (including versions distributed
  22. under the GPL) are entitled to upgrade to the latest version of
  23. Directory Opus version 5 at a reduced price. Please see
  24. http://www.gpsoft.com.au for more information.
  25.  
  26. The release of Directory Opus 4 under the GPL in NO WAY affects
  27. the existing commercial status of Directory Opus 5.
  28.  
  29. */
  30.  
  31. #include "DOpus.h"
  32. #include "ppdata.h"
  33.  
  34. enum {
  35.     PRINT_ASPECT,
  36.     PRINT_IMAGE,
  37.     PRINT_SHADE,
  38.     PRINT_PLACE,
  39.     PRINT_FORMFD,
  40.     PRINT_TITLE,
  41.     PRINT_OKAY,
  42.     PRINT_CANCEL,
  43.     PRINT_ABORT};
  44.  
  45. static ULONG *colourtable_8=NULL,ctsize;
  46. static UWORD *copperlist,*colourtable_4=NULL,colourlist[4];
  47. static struct View *view;
  48. static struct ViewPort *ivp;
  49. static char *picbuffer,*picturename;
  50. static unsigned char *bodyptr;
  51. static CRange cyclerange[6];
  52. static ULONG buffersize,bufferpos;
  53. static int
  54.     numcolours,currange,copperheight,viewmode,
  55.     screenwidth,screenheight,
  56.     imagewidth,imageheight,
  57.     bitmapwidth,bitmapheight,
  58.     minwidth,minheight,maxwidth,maxheight,depth,coppersize,
  59.     viewflags;
  60. static char specialformat;
  61. static BitMapHeader bmhead;
  62. static struct BitMap *iffbm[2];
  63. static struct Window *iffwindow;
  64. static struct DOpusRemember *iffkey;
  65.  
  66. #ifdef DO_DBUF
  67. static struct DBufInfo *dbufinfo;
  68. static struct MsgPort *dbufport;
  69. #endif
  70.  
  71. char iffscreenname[34]="";
  72.  
  73. struct AnimFrame {
  74.     struct AnimFrame *next;
  75.     AnimHdr *animheader;
  76.     unsigned char *delta;
  77.     unsigned char *cmap;
  78.     int cmapsize;
  79. };
  80.  
  81. static struct TagItem
  82.     loresscreentags[3]={
  83.         {SA_DisplayID,LORES_KEY},
  84.         {SA_Pens,(ULONG)scr_drawinfo},
  85.         {0,0}};
  86.  
  87. static struct ExtNewScreen
  88.     printscreen={
  89.         0,0,320,0,2,
  90.         0,1,0,
  91.         CUSTOMSCREEN|SCREENQUIET|SCREENBEHIND|NS_EXTENDED,
  92.         &screen_attr,NULL,NULL,NULL,loresscreentags};
  93.  
  94. static struct NewWindow
  95.     iffwin={
  96.         0,0,0,0,
  97.         255,255,
  98.         IDCMP_MOUSEBUTTONS|IDCMP_RAWKEY|IDCMP_INTUITICKS|IDCMP_INACTIVEWINDOW,
  99.         WFLG_RMBTRAP|WFLG_BORDERLESS|WFLG_SIMPLE_REFRESH|WFLG_NOCAREREFRESH,
  100.         NULL,NULL,NULL,NULL,NULL,
  101.         0,0,0,0,CUSTOMSCREEN},
  102.     printwin={
  103.         0,0,320,0,0,0,
  104.         IDCMP_GADGETUP|IDCMP_VANILLAKEY,
  105.         WFLG_RMBTRAP|WFLG_BORDERLESS,
  106.         NULL,NULL,NULL,NULL,NULL,
  107.         0,0,0,0,CUSTOMSCREEN};
  108.  
  109. static struct Image
  110.     printcheckimage={7,2,13,7,1,NULL,1,0,NULL},
  111.     printnullcheckimage={7,2,13,7,1,NULL,0,0,NULL},
  112.     animframeimage;
  113.  
  114. static struct Gadget
  115.     printgadgets[8]={
  116.         {&printgadgets[1],142,104,123,14,GFLG_GADGHCOMP,GACT_RELVERIFY,GTYP_BOOLGADGET,
  117.         NULL,NULL,NULL,GAD_CYCLE,NULL,PRINT_ASPECT,NULL},
  118.         {&printgadgets[2],142,120,123,14,GFLG_GADGHCOMP,GACT_RELVERIFY,GTYP_BOOLGADGET,
  119.         NULL,NULL,NULL,GAD_CYCLE,NULL,PRINT_IMAGE,NULL},
  120.         {&printgadgets[3],142,136,123,14,GFLG_GADGHCOMP,GACT_RELVERIFY,GTYP_BOOLGADGET,
  121.         NULL,NULL,NULL,GAD_CYCLE,NULL,PRINT_SHADE,NULL},
  122.         {&printgadgets[4],142,152,123,14,GFLG_GADGHCOMP,GACT_RELVERIFY,GTYP_BOOLGADGET,
  123.         NULL,NULL,NULL,GAD_CYCLE,NULL,PRINT_PLACE,NULL},
  124.         {&printgadgets[5],18,168,26,11,GFLG_GADGIMAGE|GFLG_GADGHIMAGE|GFLG_SELECTED,GACT_RELVERIFY|GACT_TOGGLESELECT,GTYP_BOOLGADGET,
  125.         (APTR)&printnullcheckimage,(APTR)&printcheckimage,NULL,GAD_CHECK,NULL,PRINT_FORMFD,NULL},
  126.         {&printgadgets[6],142,168,26,11,GFLG_GADGIMAGE|GFLG_GADGHIMAGE,GACT_RELVERIFY|GACT_TOGGLESELECT,GTYP_BOOLGADGET,
  127.         (APTR)&printnullcheckimage,(APTR)&printcheckimage,NULL,GAD_CHECK,NULL,PRINT_TITLE,NULL},
  128.         {&printgadgets[7],20,186,100,12,GFLG_GADGHCOMP,GACT_RELVERIFY,GTYP_BOOLGADGET,
  129.         NULL,NULL,NULL,0,NULL,PRINT_OKAY,NULL},
  130.         {NULL,196,186,100,12,GFLG_GADGHCOMP,GACT_RELVERIFY,GTYP_BOOLGADGET,
  131.         NULL,NULL,NULL,0,NULL,PRINT_CANCEL,NULL}},
  132.     abortprintgad={
  133.         NULL,60,0,200,80,GFLG_GADGHCOMP,GACT_RELVERIFY,GTYP_BOOLGADGET,
  134.         NULL,NULL,NULL,0,NULL,PRINT_ABORT,NULL};
  135.  
  136. char
  137.     *printgadtxt[9],
  138.     *printabortgadtxt[2]={NULL,NULL},
  139.     *print_aspect_txt[2],
  140.     *print_image_txt[2],
  141.     *print_shade_txt[3],
  142.     *print_placement_txt[2],
  143.  
  144.     **print_gads_txt[4]={
  145.         print_aspect_txt,
  146.         print_image_txt,
  147.         print_shade_txt,
  148.         print_placement_txt};
  149.  
  150. static char
  151.     print_gads_sel[4]={0,0,0,0},
  152.     print_gads_max[4]={1,1,2,1};
  153.  
  154. static struct AnimFrame
  155.     *first_anim_frame,*current_anim_frame,*last_anim_frame,
  156.     initial_anim_cmap;
  157. static int framecount,framenum,framedisp;
  158. static char doublebuffer;
  159. static int animspeed,framespersec,animrestart;
  160. static struct BitMap *animframe_bm[2],*initialframe_bm;
  161. static USHORT basepalette[4]={0xaaa,0x000,0xfff,0x679};
  162. static union printerIO *print_request; /* IO request for Print operation */
  163. static int palette32,got_dpan;
  164. static int animtype;
  165. static struct PCHGHeader *pchghead;
  166. static char *sham;
  167.  
  168. LoadPic(name)
  169. char *name;
  170. {
  171.     int
  172.         retcode,a,gotbody,brush,scroll,mp=1,isanim,extflag=0,
  173.         colourptr,coloursize,maxframes;
  174.     ULONG chunkid,chunksize,chunkbuf[3];
  175.     struct DimensionInfo *dimension;
  176.     DisplayInfoHandle *handle;
  177.     char dimbuf[256],*ptr;
  178.     DPAnimChunk dpan;
  179.     struct AnimFrame *cur_frame=NULL,*frame;
  180.  
  181.     picturename=name;
  182.     if (readfile(name,&picbuffer,(int *)&buffersize)) return(0);
  183.  
  184.     viewmode=-1; copperlist=NULL; iffwindow=NULL;
  185.     iffscreen=NULL; iffscreenname[0]=0;
  186.     copperheight=currange=gotbody=brush=0; scroll=1;
  187.     colourptr=-1; doublebuffer=0; animspeed=50000;
  188.     bodyptr=NULL; bufferpos=isanim=0; iffkey=NULL; first_anim_frame=NULL;
  189.     framecount=0; framespersec=20; maxframes=65535; specialformat=0;
  190.     initialframe_bm=NULL; palette32=0;
  191.     last_anim_frame=NULL; initial_anim_cmap.cmap=NULL;
  192.     got_dpan=0; animtype=0;
  193.     pchghead=NULL; sham=NULL;
  194.  
  195.     for (a=0;a<2;a++) {
  196.         iffbm[a]=NULL;
  197.         animframe_bm[a]=NULL;
  198.     }
  199.  
  200. #ifdef DO_DBUF
  201.     dbufinfo=NULL; dbufport=NULL;
  202. #endif
  203.  
  204.     if (!chunkread(chunkbuf,sizeof(ULONG)*3) ||
  205.         chunkbuf[0]!=ID_FORM ||
  206.         (chunkbuf[2]!=ID_ANIM && chunkbuf[2]!=ID_ILBM)) {
  207.         retcode=IFFERR_NOTILBM;
  208.         goto endiff;
  209.     }
  210.     if (chunkbuf[2]==ID_ANIM) isanim=1;
  211.  
  212.     while (bufferpos<=buffersize) {
  213.         if (!chunkread(&chunkid,sizeof(int)) ||
  214.             !chunkread(&chunksize,sizeof(int)) ||
  215.             ((bufferpos+chunksize)>buffersize)) break;
  216.         switch (chunkid) {
  217.             case ID_FORM:
  218.                 bufferpos+=4;
  219.                 continue;
  220.             case ID_DPAN:
  221.                 if (!isanim) break;
  222.                 if (!(chunkread(&dpan,sizeof(DPAnimChunk)))) {
  223.                     retcode=IFFERR_BADIFF;
  224.                     goto endiff;
  225.                 }
  226.                 chunksize=0;
  227.                 maxframes=dpan.nframes;
  228.                 if ((framespersec=dpan.framespersecond)>0)
  229.                     animspeed=1000000/dpan.framespersecond;
  230.                 got_dpan=1;
  231.                 break;
  232.             case ID_ANHD:
  233.                 if (isanim && framecount<maxframes &&
  234.                     (frame=LAllocRemember(&iffkey,sizeof(struct AnimFrame),MEMF_CLEAR))) {
  235.                     frame->animheader=(AnimHdr *)(picbuffer+bufferpos);
  236.                     if (frame->animheader->interleave!=1) doublebuffer=1;
  237.                     if (!animtype) animtype=frame->animheader->operation;
  238.  
  239.                     if (cur_frame) cur_frame->next=frame;
  240.                     else first_anim_frame=frame;
  241.                     cur_frame=frame;
  242.                 }
  243.                 break;
  244.             case ID_DLTA:
  245.                 if (isanim && framecount<maxframes && cur_frame) {
  246.                     cur_frame->delta=picbuffer+bufferpos;
  247.                     ++framecount;
  248.                 }
  249.                 break;
  250.             case ID_BMHD:
  251.                 if (!chunkread(&bmhead,sizeof(BitMapHeader))) {
  252.                     retcode=IFFERR_BADIFF;
  253.                     goto endiff;
  254.                 }
  255.                 chunksize=0;
  256.                 break;
  257.             case ID_CMAP:
  258.                 if (colourptr==-1) {
  259.                     colourptr=bufferpos; coloursize=chunksize;
  260.                     initial_anim_cmap.cmap=(unsigned char *)&picbuffer[bufferpos];
  261.                     initial_anim_cmap.cmapsize=chunksize;
  262.                 }
  263.                 else if (isanim && framecount<maxframes && cur_frame) {
  264.                     cur_frame->cmap=(unsigned char *)&picbuffer[bufferpos];
  265.                     cur_frame->cmapsize=chunksize;
  266.                 }
  267.                 break;
  268.             case ID_GRAB:
  269.                 brush=1;
  270.                 break;
  271.             case ID_CAMG:
  272.                 if (!chunkread(&viewmode,sizeof(int))) {
  273.                     retcode=IFFERR_BADIFF;
  274.                     goto endiff;
  275.                 }
  276.                 chunksize=0;
  277.                 break;
  278.             case ID_CTBL:
  279.                 if (copperlist=LAllocRemember(&iffkey,chunksize,MEMF_CLEAR)) {
  280.                     coppersize=chunksize;
  281.                     copperheight=chunksize/32;
  282.                     CopyMem((char *)&picbuffer[bufferpos],(char *)copperlist,chunksize);
  283.                     CopyMem((char *)&picbuffer[bufferpos],(char *)colourlist,8);
  284.                 }
  285.                 break;
  286.             case ID_DYCP:
  287.                 mp=0;
  288.                 break;
  289.             case ID_SHAM:
  290.                 if (!(pchghead=PCHG_SHAM2PCHG((UWORD *)&picbuffer[bufferpos],chunksize,(viewmode&LACE)?2:1))) {
  291.                     retcode=IFFERR_NOMEM;
  292.                     goto endiff;
  293.                 }
  294.                 sham=&picbuffer[bufferpos];
  295.                 specialformat=1;
  296.                 break;
  297.             case ID_PCHG:
  298.                 pchghead=(struct PCHGHeader *)&picbuffer[bufferpos];
  299.                 specialformat=1;
  300.                 break;
  301.             case ID_CRNG:
  302.                 if (currange<6) {
  303.                     CopyMem((char *)&picbuffer[bufferpos],(char *)&cyclerange[currange],sizeof(CRange));
  304.                     if (cyclerange[currange].rate<=CRNG_NORATE ||
  305.                         cyclerange[currange].low==cyclerange[currange].high)
  306.                         cyclerange[currange].active=0;
  307.                     if (cyclerange[currange].rate>CRNG_NORATE)
  308.                         cyclerange[currange].rate=16384/cyclerange[currange].rate;
  309.                     else cyclerange[currange].rate=0;
  310.                     ++currange;
  311.                 }
  312.                 break;
  313.             case ID_BODY:
  314.                 if (!gotbody) {
  315.                     gotbody=1;
  316.                     bodyptr=picbuffer+bufferpos;
  317.                 }
  318.                 break;
  319.         }
  320.         if (chunksize) {
  321.             bufferpos+=chunksize;
  322.             if (chunksize&1) ++bufferpos;
  323.         }
  324.     }
  325.  
  326.     if (!gotbody) {
  327.         retcode=IFFERR_BADIFF;
  328.         goto endiff;
  329.     }
  330.  
  331.     if (copperlist) specialformat=1;
  332.  
  333.     depth=bmhead.nPlanes;
  334.  
  335.     if (colourptr>-1) {
  336.         numcolours=coloursize/3;
  337.  
  338.         if (system_version2>=OSVER_39 && !specialformat)
  339.             colourtable_8=LAllocRemember(&iffkey,(coloursize+2)*4,MEMF_CLEAR);
  340.  
  341.         colourtable_4=LAllocRemember(&iffkey,numcolours*sizeof(UWORD),MEMF_CLEAR);
  342.     }
  343.  
  344.     if (!colourtable_8 && !colourtable_4) {
  345.         retcode=IFFERR_BADIFF;
  346.         goto endiff;
  347.     }
  348.  
  349.     if ((config->viewbits&VIEWBITS_8BITSPERGUN || bmhead.flags&BMHF_CMAPOK) &&
  350.         colourtable_8) palette32=1;
  351.  
  352.     build_palettes(&picbuffer[colourptr],coloursize,colourtable_4,colourtable_8);
  353.  
  354.     imagewidth=bmhead.w;
  355.     imageheight=bmhead.h;
  356.     screenwidth=bmhead.w;
  357.     screenheight=bmhead.h;
  358.  
  359.     minwidth=320;
  360.     minheight=200;
  361.  
  362.     maxwidth=368;
  363.     if (scrdata_is_pal) maxheight=281;
  364.     else maxheight=241;
  365.  
  366.     if (viewmode==-1 || brush) {
  367.         viewflags=viewmode; viewmode=0;
  368.         if (bmhead.pageWidth>maxwidth) viewmode|=HIRES;
  369.         if (bmhead.pageHeight>maxheight) viewmode|=LACE;
  370.         if (system_version2<OSVER_39) {
  371.             if (depth>6) {
  372.                 retcode=IFFERR_BADMODE;
  373.                 goto endiff;
  374.             }
  375.             if (depth==6) {
  376.                 if (viewflags==-1 || viewflags&HAM) viewmode|=HAM;
  377.                 else viewmode|=EXTRA_HALFBRITE;
  378.             }
  379.         }
  380.         viewflags=0;
  381.     }
  382.  
  383.     if (system_version2) {
  384.         if (viewmode&0xfffe000) {
  385.             if (!(ModeNotAvailable(viewmode))) extflag=1;
  386.             else if ((handle=FindDisplayInfo(viewmode)) &&
  387.                 (GetDisplayInfoData(handle,dimbuf,256,DTAG_NAME,0)))
  388.                 extflag=1;
  389.         }
  390.     }
  391.  
  392.     if (extflag) {
  393.         if (ModeNotAvailable(viewmode)) {
  394.             if (system_version2<OSVER_39) {
  395.                 retcode=IFFERR_BADMODE;
  396.                 goto endiff;
  397.             }
  398.             else viewmode=-1;
  399.         }
  400.  
  401.         if (system_version2>=OSVER_39 &&
  402.             (viewmode==-1 || config->viewbits&VIEWBITS_BESTMODEID)) {
  403.  
  404.             ULONG newmode;
  405.  
  406.             if (!(ModeNotAvailable((newmode=
  407.                 BestModeID(
  408.                     BIDTAG_NominalWidth,imagewidth,
  409.                     BIDTAG_NominalHeight,imageheight,
  410.                     BIDTAG_Depth,depth,
  411.                     BIDTAG_SourceID,viewmode,
  412.                     BIDTAG_MonitorID,(GetVPModeID(&Window->WScreen->ViewPort)&MONITOR_ID_MASK),
  413.                     TAG_END))))) viewmode=newmode;
  414.         }
  415.  
  416.         if (handle=FindDisplayInfo(viewmode)) {
  417.             if (!(a=GetDisplayInfoData(handle,dimbuf,256,DTAG_NAME,0))) {
  418.                 DisplayInfoHandle *temphandle;
  419.                 ULONG tempviewmode;
  420.  
  421.                 tempviewmode=viewmode;
  422.                 tempviewmode&=~(HAM_KEY|EXTRAHALFBRITE_KEY);
  423.  
  424.                 if ((temphandle=FindDisplayInfo(tempviewmode)))
  425.                     a=GetDisplayInfoData(temphandle,dimbuf,256,DTAG_NAME,0);
  426.             }
  427.             if (a && (((struct NameInfo *)dimbuf)->Name)) {
  428.                 strcpy(iffscreenname,((struct NameInfo *)dimbuf)->Name);
  429.                 if ((ptr=strchr(iffscreenname,':'))) strcpy(iffscreenname,ptr+1);
  430.             }
  431.             GetDisplayInfoData(handle,dimbuf,256,DTAG_DIMS,0);
  432.             dimension=(struct DimensionInfo *)dimbuf;
  433.             maxwidth=(dimension->StdOScan.MaxX-dimension->StdOScan.MinX)+1;
  434.             maxheight=(dimension->StdOScan.MaxY-dimension->StdOScan.MinY)+1;
  435.             if (depth>dimension->MaxDepth) {
  436.                 retcode=IFFERR_BADMODE;
  437.                 goto endiff;
  438.             }
  439.         }
  440.         else extflag=0;
  441.         viewflags=0;
  442.         if ((viewmode&SUPER_KEY)==SUPER_KEY) viewflags|=SUPERHIRES|HIRES;
  443.         else if (viewmode&HIRES_KEY) viewflags|=HIRES;
  444.         if (viewmode&LORESLACE_KEY) viewflags|=LACE;
  445.         if (viewmode&HAM_KEY) viewflags|=HAM;
  446.         if (viewmode&EXTRAHALFBRITE_KEY) viewflags|=EXTRA_HALFBRITE;
  447.         if (!extflag) viewmode=viewflags;
  448.     }
  449.  
  450.     if (!extflag) {
  451.         viewmode&=0x0000ffff;
  452.         viewmode&=~(SPRITES|GENLOCK_AUDIO|GENLOCK_VIDEO|VP_HIDE|DUALPF|PFBA|EXTENDED_MODE);
  453.         viewflags=viewmode;
  454.  
  455.         if (viewflags&HIRES) {
  456.             if (viewflags&SUPERHIRES) maxwidth*=4;
  457.             else maxwidth*=2;
  458.             minwidth*=2;
  459.         }
  460.     }
  461.  
  462.     if (screenwidth<minwidth) screenwidth=minwidth;
  463.     else if (screenwidth>maxwidth) screenwidth=maxwidth;
  464.  
  465.     if (!extflag && viewflags&LACE) {
  466.         maxheight*=2;
  467.         minheight*=2;
  468.     }
  469.     if (screenheight<minheight) screenheight=minheight;
  470.     else if (screenheight>maxheight) screenheight=maxheight;
  471.  
  472.     if (imagewidth<screenwidth) bitmapwidth=screenwidth;
  473.     else bitmapwidth=imagewidth;
  474.     if (imageheight<screenheight) bitmapheight=screenheight;
  475.     else bitmapheight=imageheight;
  476.  
  477.     if (bitmapwidth>screenwidth || bitmapheight>screenheight) scroll=3;
  478.     dotitle();
  479.  
  480.     if (isanim && first_anim_frame) {
  481.         if (!(animframe_bm[0]=getbitmap(bitmapwidth,bitmapheight,bmhead.nPlanes))) {
  482.             retcode=IFFERR_NOMEM;
  483.             goto endiff;
  484.         }
  485.         if (doublebuffer) {
  486.             if ((animframe_bm[1]=getbitmap(bitmapwidth,bitmapheight,bmhead.nPlanes))) {
  487.                 initialframe_bm=getbitmap(bitmapwidth,bitmapheight,bmhead.nPlanes);
  488. #ifdef DO_DBUF
  489.                 if (system_version2>=OSVER_39 &&
  490.                     (dbufinfo=AllocDBufInfo(ivp))) {
  491.                     if (dbufport=LCreatePort(NULL,0)) {
  492.                         dbufinfo->dbi_SafeMessage.mn_ReplyPort=dbufport;
  493.                         dbufinfo->dbi_SafeMessage.mn_Length=sizeof(struct Message);
  494.                     }
  495.                 }
  496. #endif
  497.             }
  498.         }
  499.     }
  500.  
  501.     if (doublebuffer) {
  502.         for (a=0;a<2;a++) {
  503.             if (animframe_bm[a]) {
  504.                 if (!(iffbm[a]=LAllocRemember(&iffkey,sizeof(struct BitMap),MEMF_CLEAR))) {
  505.                     retcode=IFFERR_NOMEMORY;
  506.                     goto endiff;
  507.                 }
  508.                 CopyMem((char *)animframe_bm[a],(char *)iffbm[a],sizeof(struct BitMap));
  509.             }
  510.         }
  511.     }
  512.     else if (!(iffbm[0]=getbitmap(bitmapwidth,bitmapheight,depth))) {
  513.         retcode=IFFERR_NOMEMORY;
  514.         goto endiff;
  515.     }
  516.  
  517.     if (system_version2) {
  518.         struct TagItem iffscr_tags[10];
  519.         ULONG err=0;
  520.  
  521.         iffscr_tags[0].ti_Tag=SA_Width;
  522.         iffscr_tags[0].ti_Data=bitmapwidth;
  523.         iffscr_tags[1].ti_Tag=SA_Height;
  524.         iffscr_tags[1].ti_Data=bitmapheight;
  525.         iffscr_tags[2].ti_Tag=SA_Depth;
  526.         iffscr_tags[2].ti_Data=depth;
  527.         iffscr_tags[3].ti_Tag=SA_BitMap;
  528.         iffscr_tags[3].ti_Data=(ULONG)iffbm[0];
  529.         iffscr_tags[4].ti_Tag=SA_Behind;
  530.         iffscr_tags[4].ti_Data=TRUE;
  531.         iffscr_tags[5].ti_Tag=SA_DisplayID;
  532.         iffscr_tags[5].ti_Data=viewmode;
  533.         iffscr_tags[6].ti_Tag=SA_AutoScroll;
  534.         iffscr_tags[6].ti_Data=TRUE;
  535.         iffscr_tags[7].ti_Tag=SA_Overscan;
  536.         iffscr_tags[7].ti_Data=OSCAN_MAX;
  537.         iffscr_tags[8].ti_Tag=SA_ErrorCode;
  538.         iffscr_tags[8].ti_Data=(ULONG)&err;
  539.         iffscr_tags[9].ti_Tag=TAG_END;
  540.         iffscr_tags[9].ti_Data=0;
  541.  
  542.         iffscreen=OpenScreenTagList(NULL,iffscr_tags);
  543.     }
  544.     else {
  545.         struct NewScreen iffscr;
  546.  
  547.         iffscr.LeftEdge=0;
  548.         iffscr.TopEdge=0;
  549.         iffscr.Width=screenwidth;
  550.         iffscr.Height=screenheight;
  551.         iffscr.Depth=depth;
  552.         iffscr.DetailPen=0;
  553.         iffscr.BlockPen=0;
  554.         iffscr.ViewModes=viewflags;
  555.         iffscr.Type=CUSTOMSCREEN|SCREENBEHIND|CUSTOMBITMAP;
  556.         iffscr.Font=NULL;
  557.         iffscr.DefaultTitle=NULL;
  558.         iffscr.Gadgets=NULL;
  559.         iffscr.CustomBitMap=iffbm[0];
  560.  
  561.         iffscreen=OpenScreen(&iffscr);
  562.     }
  563.  
  564.     if (!iffscreen) {
  565.         retcode=IFFERR_NOSCREEN;
  566.         goto endiff;
  567.     }
  568.  
  569.     ivp=&(iffscreen->ViewPort);
  570.     LoadRGB4(ivp,nullpalette,1<<depth);
  571.  
  572.     iffwin.Screen=iffscreen;
  573.     iffwin.Width=iffscreen->Width;
  574.     iffwin.Height=iffscreen->Height;
  575.  
  576.     if (!(iffwindow=OpenWindow(&iffwin))) {
  577.         retcode=IFFERR_NOSCREEN;
  578.         goto endiff;
  579.     }
  580.  
  581.     setnullpointer(iffwindow);
  582.  
  583.     if (isanim && first_anim_frame) {
  584.         framenum=1;
  585.         framedisp=animrestart=0;
  586.         current_anim_frame=first_anim_frame;
  587.  
  588.         rletobuffer(bodyptr,bmhead.w,bmhead.h,animframe_bm[0],bmhead.masking,bmhead.compression);
  589.  
  590.         if (doublebuffer) {
  591.             if (animframe_bm[1]) {
  592.                 BltBitMap(animframe_bm[0],0,0,animframe_bm[1],0,0,bmhead.w,bmhead.h,0xc0,0xff,NULL);
  593.                 if (initialframe_bm)
  594.                     BltBitMap(animframe_bm[0],0,0,initialframe_bm,0,0,bmhead.w,bmhead.h,0xc0,0xff,NULL);
  595.                 WaitBlit();
  596.             }
  597.         }
  598.         else {
  599.             animframeimage.LeftEdge=(bitmapwidth-bmhead.w)/2;
  600.             animframeimage.TopEdge=(bitmapheight-bmhead.h)/2;
  601.             doanimframe();
  602.         }
  603.     }
  604.     else readpic(&bmhead,bodyptr,iffbm[0]);
  605.  
  606.     if (numcolours>ivp->ColorMap->Count) numcolours=ivp->ColorMap->Count;
  607.  
  608.     if (!copperlist) {
  609.         if (!system_version2) {
  610.             int x,y;
  611.  
  612.             if (viewflags&HIRES) x=(scrdata_norm_width-screenwidth)/2;
  613.             else x=((scrdata_norm_width/2)-screenwidth)/2;
  614.             if (viewflags&LACE) y=((scrdata_norm_height*2)-screenheight)/2;
  615.             else y=(scrdata_norm_height-screenheight)/2;
  616.             ivp->DxOffset=x;
  617.             ivp->DyOffset=y;
  618.             MakeScreen(iffscreen);
  619.         }
  620.         if (viewflags&HAM || pchghead) {
  621.             if (palette32) LoadRGB32(ivp,colourtable_8);
  622.             else LoadRGB4(ivp,colourtable_4,numcolours);
  623.         }
  624.     }
  625.  
  626.     if (pchghead) {
  627.         if (sham) PCHG_SetUserCopList(0,0,ivp,pchghead,&pchghead[1],sham);
  628.         else PCHG_ParsePCHG(pchghead,ivp);
  629.     }
  630.  
  631.     ActivateWindow(iffwindow);
  632.     ScreenToFront(iffscreen);
  633.  
  634.     if (copperlist) {
  635.         view=ViewAddress();
  636.         if ((copperheight>>1)>scrdata_norm_height) view->DyOffset=14+(system_version2?8:0);
  637.         if (mp) LoadRGB4(ivp,colourlist,4);
  638.         if (!InitDHIRES(mp)) {
  639.             retcode=IFFERR_NOMEMORY;
  640.             goto endiff;
  641.         }
  642.     }
  643.     else if (!specialformat && !(viewflags&HAM)) {
  644.         if (palette32) FadeRGB32(iffscreen,&colourtable_8[1],numcolours,1,config->fadetime);
  645.         else FadeRGB4(iffscreen,colourtable_4,numcolours,1,config->fadetime);
  646.     }
  647.  
  648.     if (currange) initcycle(ivp,colourtable_4,numcolours,cyclerange,currange);
  649.  
  650.     if (!(a=WaitForMouseClick(scroll,iffwindow))) retcode=1;
  651.     else retcode=-1;
  652.  
  653.     if (checkcycling()) togglecycle();
  654.     stopcycle();
  655.  
  656.     if (specialformat) {
  657.         ScreenToBack(iffscreen);
  658.         FreeVPortCopLists(ivp);
  659.     }
  660.     else if (a!=-3 && !(viewflags&HAM)) {
  661.         if (palette32) FadeRGB32(iffscreen,&colourtable_8[1],numcolours,-1,config->fadetime);
  662.         else FadeRGB4(iffscreen,colourtable_4,numcolours,-1,config->fadetime);
  663.     }
  664.     
  665. endiff:
  666. #ifdef DO_DBUF
  667.     if (dbufinfo) FreeDBufInfo(dbufinfo);
  668.     if (dbufport) LDeletePort(dbufport);
  669. #endif
  670.     cleanupbitmap();
  671.     ActivateWindow(Window);
  672.     if (pchghead && sham) {
  673.         FreeMem(pchghead,sizeof(struct PCHGHeader)+((pchghead->LineCount+31)/32)*4);
  674.     }
  675.     LFreeRemember(&iffkey);
  676.     if (picbuffer) FreeMem(picbuffer,buffersize);
  677.     first_anim_frame=NULL;
  678.     colourtable_8=NULL; colourtable_4=NULL;
  679.     return(retcode);
  680. }
  681.  
  682. struct BitMap *getbitmap(width,height,depth)
  683. int width,height,depth;
  684. {
  685.     struct BitMap *bm;
  686.     int a;
  687.  
  688.     if (system_version2>=OSVER_39) {
  689.         return((AllocBitMap(width,height,depth,BMF_DISPLAYABLE|BMF_CLEAR,NULL)));
  690.     }
  691.     if (!(bm=AllocMem(sizeof(struct BitMap),MEMF_CLEAR))) return(NULL);
  692.     InitBitMap(bm,depth,width,height);
  693.     for (a=0;a<8;a++) bm->Planes[a]=NULL;
  694.     for (a=0;a<depth;a++) {
  695.         if (!(bm->Planes[a]=AllocRaster(width,height))) {
  696.             freebitmap(bm,width,height);
  697.             return(NULL);
  698.         }
  699.     }
  700.     return(bm);
  701. }
  702.  
  703. void freebitmap(bm,width,height)
  704. struct BitMap *bm;
  705. {
  706.     int a;
  707.  
  708.     if (bm) {
  709.         if (system_version2>=OSVER_39) FreeBitMap(bm);
  710.         else {
  711.             for (a=0;a<8;a++) if (bm->Planes[a]) FreeRaster(bm->Planes[a],width,height);
  712.             FreeMem(bm,sizeof(struct BitMap));
  713.         }
  714.     }
  715. }
  716.  
  717. void cleanupbitmap()
  718. {
  719.     int num;
  720.  
  721.     if (blankscreen) ScreenToFront(blankscreen);
  722.     else ScreenToFront(Window->WScreen);
  723.     if (iffwindow) {
  724.         CloseWindow(iffwindow);
  725.         iffwindow=NULL;
  726.     }
  727.     if (iffscreen) {
  728.         CloseScreen(iffscreen);
  729.         iffscreen=NULL;
  730.     }
  731.     if (iffbm[0] && !doublebuffer) freebitmap(iffbm[0],bitmapwidth,bitmapheight);
  732.     for (num=0;num<2;num++) {
  733.         if (animframe_bm[num]) freebitmap(animframe_bm[num],bitmapwidth,bitmapheight);
  734.     }
  735.     if (initialframe_bm) freebitmap(initialframe_bm,bitmapwidth,bitmapheight);
  736. }
  737.  
  738. void rletobuffer(source,sourcewidth,sourceheight,dest,mask,comp)
  739. unsigned char *source;
  740. int sourcewidth,sourceheight;
  741. struct BitMap *dest;
  742. char mask,comp;
  743. {
  744.     struct RLEinfo picinfo;
  745.  
  746.     picinfo.sourceptr=source;
  747.     picinfo.destplanes=dest->Planes;
  748.     picinfo.imagebpr=((sourcewidth+15)/16)*2;
  749.     picinfo.imageheight=sourceheight;
  750.     picinfo.imagedepth=dest->Depth;
  751.     picinfo.destbpr=dest->BytesPerRow;
  752.     picinfo.destheight=dest->Rows;
  753.     picinfo.destdepth=dest->Depth;
  754.     picinfo.masking=mask;
  755.     picinfo.compression=comp;
  756.     picinfo.offset=0;
  757.  
  758.     decoderle(&picinfo);
  759. }
  760.  
  761. void readpic(bmhead,source,bmap)
  762. BitMapHeader *bmhead;
  763. unsigned char *source;
  764. struct BitMap *bmap;
  765. {
  766.     int rowbytes,bmrbytes,rows;
  767.     int byteoff=0;
  768.     struct RLEinfo picinfo;
  769.  
  770.     rowbytes=((bmhead->w+15)/16)*2;
  771.     if (system_version2>=OSVER_39) bmrbytes=((GetBitMapAttr(bmap,BMA_WIDTH)+15)/16)*2;
  772.     else bmrbytes=bmap->BytesPerRow;
  773.  
  774.     if ((rows=bmhead->h)>bmap->Rows) rows=bmap->Rows;
  775.  
  776.     if (!system_version2) {
  777.         if (rowbytes<bmrbytes) byteoff=(bmrbytes-rowbytes)/2;
  778.         else byteoff=0;
  779.         if (rows<bmap->Rows) byteoff+=((bmap->Rows-rows)/2)*bmrbytes;
  780.     }
  781.  
  782.     picinfo.sourceptr=source;
  783.     picinfo.destplanes=bmap->Planes;
  784.     picinfo.imagebpr=rowbytes;
  785.     picinfo.imageheight=rows;
  786.     picinfo.imagedepth=bmhead->nPlanes;
  787.     picinfo.destbpr=bmrbytes;
  788.     picinfo.destheight=bmap->Rows;
  789.     picinfo.destdepth=bmap->Depth;
  790.     picinfo.masking=bmhead->masking;
  791.     picinfo.compression=bmhead->compression;
  792.     picinfo.offset=byteoff;
  793.  
  794.     decoderle(&picinfo);
  795. }
  796.  
  797. void decoderle(rleinfo)
  798. struct RLEinfo *rleinfo;
  799. {
  800.     register char *source,*dest;
  801.     register int copy,col;
  802.     register char count;
  803.     int plane,row,bmoffset,planes;
  804.  
  805.     planes=rleinfo->imagedepth;
  806.     if (rleinfo->masking==1) ++planes;
  807.     source=rleinfo->sourceptr;
  808.  
  809.     switch (rleinfo->compression) {
  810.         case 1:
  811.             bmoffset=rleinfo->offset;
  812.             for (row=0;row<rleinfo->imageheight;row++) {
  813.                 for (plane=0;plane<planes;plane++) {
  814.                     if (plane<rleinfo->destdepth && rleinfo->destplanes[plane])
  815.                         dest=(char *)(rleinfo->destplanes[plane]+bmoffset);
  816.                     else dest=NULL;
  817.  
  818.                     for (col=0;col<rleinfo->imagebpr;) {
  819.                         if ((count=*source++)>=0) {
  820.                             copy=count+1;
  821.                             col+=copy;
  822.                             if (dest) {
  823.                                 while (copy--) *dest++=*source++;
  824.                             }
  825.                             else source+=copy;
  826.                         }
  827.                         else if (count!=-128) {
  828.                             copy=1-count;
  829.                             col+=copy;
  830.                             if (dest) {
  831.                                 while (copy--) *dest++=*source;
  832.                             }
  833.                             ++source;
  834.                         }
  835.                     }
  836.                 }
  837.                 bmoffset+=rleinfo->destbpr;
  838.             }
  839.             break;
  840.         case 0:
  841.             bmoffset=rleinfo->offset;
  842.             for (row=0;row<rleinfo->imageheight;row++) {
  843.                 for (plane=0;plane<planes;plane++) {
  844.                     if (plane<rleinfo->destdepth)
  845.                         CopyMem(source,(char *)rleinfo->destplanes[plane]+bmoffset,rleinfo->imagebpr);
  846.                     source+=rleinfo->imagebpr;
  847.                 }
  848.                 bmoffset+=rleinfo->destbpr;
  849.             }
  850.             break;
  851.     }
  852. }
  853.  
  854. void doanimframe()
  855. {
  856.     struct AnimFrame *frame;
  857.  
  858.     if (last_anim_frame) {
  859.         frame=last_anim_frame;
  860.         last_anim_frame=last_anim_frame->next;
  861.     }
  862.     else {
  863.         frame=&initial_anim_cmap;
  864.         last_anim_frame=first_anim_frame;
  865.     }
  866.  
  867.     if (frame->cmap) {
  868.         build_palettes(frame->cmap,frame->cmapsize,colourtable_4,colourtable_8);
  869.         if (palette32) LoadRGB32(ivp,colourtable_8);
  870.         else LoadRGB4(ivp,colourtable_4,numcolours);
  871.     }
  872.  
  873.     if (doublebuffer && iffbm[1]) {
  874. #ifdef DO_DBUF
  875.         if (dbufport) {
  876.             ChangeVPBitMap(ivp,iffbm[framedisp],dbufinfo);
  877.             WaitPort(dbufport);
  878.             GetMsg(dbufport);
  879.         }
  880.         else {
  881.             iffscreen->RastPort.BitMap=iffbm[framedisp];
  882.             iffscreen->ViewPort.RasInfo->BitMap=iffbm[framedisp];
  883.             MakeScreen(iffscreen);
  884.             RethinkDisplay();
  885.         }
  886. #else
  887.         iffscreen->RastPort.BitMap=iffbm[framedisp];
  888.         iffscreen->ViewPort.RasInfo->BitMap=iffbm[framedisp];
  889.         MakeScreen(iffscreen);
  890.         RethinkDisplay();
  891. #endif
  892.     }
  893.     else {
  894.         BltBitMap(animframe_bm[framedisp],0,0,
  895.             iffwindow->RPort->BitMap,animframeimage.LeftEdge,animframeimage.TopEdge,
  896.             bmhead.w,bmhead.h,0xc0,0xff,NULL);
  897.         WaitBlit();
  898.     }
  899.     if (animframe_bm[1]) framedisp=1-framedisp;
  900.  
  901.     if (!current_anim_frame) {
  902.         if (animframe_bm[1]) {
  903.             if (initialframe_bm) {
  904.                 BltBitMap(initialframe_bm,0,0,
  905.                     animframe_bm[framedisp],0,0,
  906.                     bmhead.w,bmhead.h,0xc0,0xff,NULL);
  907.                 WaitBlit();
  908.             }
  909.             else rletobuffer(bodyptr,bmhead.w,bmhead.h,
  910.                 animframe_bm[framedisp],bmhead.masking,bmhead.compression);
  911.         }
  912.         if (got_dpan || framenum==0) {
  913.             current_anim_frame=first_anim_frame;
  914.             last_anim_frame=first_anim_frame;
  915.             framenum=1;
  916.         }
  917.         else framenum=0;
  918.     }
  919.  
  920.     if (framenum>0) {
  921.         switch (current_anim_frame->animheader->operation) {
  922.             case 0:
  923.                 if (current_anim_frame->delta)
  924.                     rletobuffer(current_anim_frame->delta,bmhead.w,bmhead.h,
  925.                         animframe_bm[framedisp],bmhead.masking,bmhead.compression);
  926.                 break;
  927.             case 5:
  928.                 doriff(current_anim_frame->delta,animframe_bm[framedisp],
  929.                     (current_anim_frame->animheader->bits&2 || !animframe_bm[1]),bmhead.w,0);
  930.                 break;
  931.             case 7:
  932.                 doriff7(current_anim_frame->delta,animframe_bm[framedisp],
  933.                     bmhead.w,(current_anim_frame->animheader->bits&1)?2:1);
  934.                 break;
  935.             case 8:
  936.                 doriff(current_anim_frame->delta,animframe_bm[framedisp],
  937.                     1,bmhead.w,(current_anim_frame->animheader->bits&1)?2:1);
  938.                 break;
  939.         }
  940.         ++framenum;
  941.         current_anim_frame=current_anim_frame->next;
  942.     }
  943. }
  944.  
  945. void doriff(delta,image,xor,sourcewidth,size)
  946. unsigned char *delta;
  947. struct BitMap *image;
  948. int xor,sourcewidth,size;
  949. {
  950.     int plane,*dptr;
  951.     unsigned char *data;
  952.  
  953.     sourcewidth=((sourcewidth+15)/16)*2;
  954.  
  955.     if ((dptr=(int *)delta)) {
  956.         for (plane=0;plane<image->Depth;plane++) {
  957.             if (dptr[plane]) {
  958.                 data=(unsigned char *)delta+dptr[plane];
  959.                 if (size==0) {
  960.                     if (xor) decode_riff_xor(data,image->Planes[plane],image->BytesPerRow,sourcewidth);
  961.                     else decode_riff_set(data,image->Planes[plane],image->BytesPerRow,sourcewidth);
  962.                 }
  963.                 else if (size==1)
  964.                     decode_riff_short((USHORT *)data,image->Planes[plane],image->BytesPerRow,sourcewidth);
  965.                 else decode_riff_long((ULONG *)data,image->Planes[plane],image->BytesPerRow,sourcewidth);
  966.             }
  967.         }
  968.     }
  969. }
  970.  
  971. void doriff7(delta,image,sourcewidth,size)
  972. unsigned char *delta;
  973. struct BitMap *image;
  974. int sourcewidth,size;
  975. {
  976.     int plane,*dptr;
  977.     unsigned char *data;
  978.     unsigned char *opcode;
  979.  
  980.     sourcewidth=((sourcewidth+15)/16)*2;
  981.  
  982.     if ((dptr=(int *)delta)) {
  983.         for (plane=0;plane<image->Depth;plane++) {
  984.             if (dptr[plane] && dptr[plane+8]) {
  985.                 opcode=(unsigned char *)delta+dptr[plane];
  986.                 data=(unsigned char *)delta+dptr[plane+8];
  987.                 if (size==1)
  988.                     decode_riff7_short((USHORT *)data,opcode,image->Planes[plane],image->BytesPerRow,sourcewidth);
  989.                 else decode_riff7_long((ULONG *)data,opcode,image->Planes[plane],image->BytesPerRow,sourcewidth);
  990.             }
  991.         }
  992.     }
  993. }
  994.  
  995. void decode_riff_xor(delta,image,rowbytes,sourcebytes)
  996. unsigned char *delta;
  997. char *image;
  998. int rowbytes,sourcebytes;
  999. {
  1000.     int column,opcount;
  1001.     unsigned char *data,ch;
  1002.  
  1003.     for (column=0;column<sourcebytes;column++) {
  1004.         data=image+column;
  1005.         opcount=*delta++;
  1006.         while (opcount--) {
  1007.             ch=*delta++;
  1008.             if (ch) {
  1009.                 if (!(ch&128)) data+=rowbytes*ch;
  1010.                 else {
  1011.                     ch&=127;
  1012.                     while (ch--) {
  1013.                         *data^=*delta++;
  1014.                         data+=rowbytes;
  1015.                     }
  1016.                 }
  1017.             }
  1018.             else {
  1019.                 ch=*delta++;
  1020.                 while (ch--) {
  1021.                     *data^=*delta;
  1022.                     data+=rowbytes;
  1023.                 }
  1024.                 ++delta;
  1025.             }
  1026.         }
  1027.     }
  1028. }
  1029.  
  1030. void decode_riff_set(delta,image,rowbytes,sourcebytes)
  1031. unsigned char *delta;
  1032. char *image;
  1033. int rowbytes,sourcebytes;
  1034. {
  1035.     int column,opcount;
  1036.     unsigned char *data,ch;
  1037.  
  1038.     for (column=0;column<sourcebytes;column++) {
  1039.         data=image+column;
  1040.         opcount=*delta++;
  1041.         while (opcount--) {
  1042.             ch=*delta++;
  1043.             if (ch) {
  1044.                 if (!(ch&128)) data+=rowbytes*ch;
  1045.                 else {
  1046.                     ch&=127;
  1047.                     while (ch--) {
  1048.                         *data=*delta++;
  1049.                         data+=rowbytes;
  1050.                     }
  1051.                 }
  1052.             }
  1053.             else {
  1054.                 ch=*delta++;
  1055.                 while (ch--) {
  1056.                     *data=*delta;
  1057.                     data+=rowbytes;
  1058.                 }
  1059.                 ++delta;
  1060.             }
  1061.         }
  1062.     }
  1063. }
  1064.  
  1065. void decode_riff_short(delta,image,rowbytes,sourcebytes)
  1066. USHORT *delta;
  1067. unsigned char *image;
  1068. int rowbytes,sourcebytes;
  1069. {
  1070.     int column,opcount;
  1071.     unsigned char *data;
  1072.     USHORT ch;
  1073.  
  1074.     sourcebytes/=2;
  1075.  
  1076.     for (column=0;column<sourcebytes;column++) {
  1077.         data=(unsigned char *)(image+(column*2));
  1078.         opcount=*delta++;
  1079.         while (opcount--) {
  1080.             ch=*delta++;
  1081.             if (ch) {
  1082.                 if (!(ch&0x8000)) data+=rowbytes*ch;
  1083.                 else {
  1084.                     ch&=0x7fff;
  1085.                     while (ch--) {
  1086.                         *(USHORT *)data=*delta++;
  1087.                         data+=rowbytes;
  1088.                     }
  1089.                 }
  1090.             }
  1091.             else {
  1092.                 ch=*delta++;
  1093.                 while (ch--) {
  1094.                     *(USHORT *)data=*delta;
  1095.                     data+=rowbytes;
  1096.                 }
  1097.                 ++delta;
  1098.             }
  1099.         }
  1100.     }
  1101. }
  1102.  
  1103. void decode_riff_long(delta,image,rowbytes,sourcebytes)
  1104. ULONG *delta;
  1105. unsigned char *image;
  1106. int rowbytes,sourcebytes;
  1107. {
  1108.     int column,opcount;
  1109.     unsigned char *data;
  1110.     ULONG ch;
  1111.  
  1112.     sourcebytes/=4;
  1113.  
  1114.     for (column=0;column<sourcebytes;column++) {
  1115.         data=(unsigned char *)(image+(column*4));
  1116.         opcount=*delta++;
  1117.         while (opcount--) {
  1118.             ch=*delta++;
  1119.             if (ch) {
  1120.                 if (!(ch&0x80000000)) data+=rowbytes*ch;
  1121.                 else {
  1122.                     ch&=0x7fffffff;
  1123.                     while (ch--) {
  1124.                         *(ULONG *)data=*delta++;
  1125.                         data+=rowbytes;
  1126.                     }
  1127.                 }
  1128.             }
  1129.             else {
  1130.                 ch=*delta++;
  1131.                 while (ch--) {
  1132.                     *(ULONG *)data=*delta;
  1133.                     data+=rowbytes;
  1134.                 }
  1135.                 ++delta;
  1136.             }
  1137.         }
  1138.     }
  1139. }
  1140.  
  1141. void decode_riff7_short(delta,opcode,image,rowbytes,sourcebytes)
  1142. USHORT *delta;
  1143. unsigned char *opcode;
  1144. unsigned char *image;
  1145. int rowbytes,sourcebytes;
  1146. {
  1147.     int column,opcount;
  1148.     unsigned char *data,ch;
  1149.  
  1150.     sourcebytes/=2;
  1151.  
  1152.     for (column=0;column<sourcebytes;column++) {
  1153.         data=(unsigned char *)(image+(column*2));
  1154.         opcount=*opcode++;
  1155.         while (opcount--) {
  1156.             ch=*opcode++;
  1157.             if (ch) {
  1158.                 if (!(ch&0x80)) data+=rowbytes*ch;
  1159.                 else {
  1160.                     ch&=0x7f;
  1161.                     while (ch--) {
  1162.                         *(USHORT *)data=*delta++;
  1163.                         data+=rowbytes;
  1164.                     }
  1165.                 }
  1166.             }
  1167.             else {
  1168.                 ch=*opcode++;
  1169.                 while (ch--) {
  1170.                     *(USHORT *)data=*delta;
  1171.                     data+=rowbytes;
  1172.                 }
  1173.                 ++delta;
  1174.             }
  1175.         }
  1176.     }
  1177. }
  1178.  
  1179. void decode_riff7_long(delta,opcode,image,rowbytes,sourcebytes)
  1180. ULONG *delta;
  1181. unsigned char *opcode;
  1182. unsigned char *image;
  1183. int rowbytes,sourcebytes;
  1184. {
  1185.     int column,opcount;
  1186.     unsigned char *data,ch;
  1187.  
  1188.     sourcebytes/=4;
  1189.  
  1190.     for (column=0;column<sourcebytes;column++) {
  1191.         data=(unsigned char *)(image+(column*4));
  1192.         opcount=*opcode++;
  1193.         while (opcount--) {
  1194.             ch=*opcode++;
  1195.             if (ch) {
  1196.                 if (!(ch&0x80)) data+=rowbytes*ch;
  1197.                 else {
  1198.                     ch&=0x7f;
  1199.                     while (ch--) {
  1200.                         *(ULONG *)data=*delta++;
  1201.                         data+=rowbytes;
  1202.                     }
  1203.                 }
  1204.             }
  1205.             else {
  1206.                 ch=*opcode++;
  1207.                 while (ch--) {
  1208.                     *(ULONG *)data=*delta;
  1209.                     data+=rowbytes;
  1210.                 }
  1211.                 ++delta;
  1212.             }
  1213.         }
  1214.     }
  1215. }
  1216.  
  1217. WaitForMouseClick(tits,wind)
  1218. int tits;
  1219. struct Window *wind;
  1220. {
  1221.     struct IntuiMessage *msg;
  1222.     ULONG class;
  1223.     USHORT code,qual;
  1224.     int ticks,waitfor=0,pon=0,waitbits,retcode=1,gottimer=0,origspeed,anim,delta;
  1225.     struct timerequest treq;
  1226.  
  1227.     while (msg=(struct IntuiMessage *) GetMsg(wind->UserPort))
  1228.         ReplyMsg((struct Message *)msg);
  1229.     if (!first_anim_frame && config->showdelay>0) {
  1230.         waitfor=config->showdelay*10; ticks=0;
  1231.     }
  1232.  
  1233.     origspeed=animspeed;
  1234.  
  1235.     waitbits=1<<wind->UserPort->mp_SigBit;
  1236.     if (first_anim_frame) {
  1237.         if (!(OpenDevice(TIMERNAME,UNIT_VBLANK,&treq.tr_node,0))) {
  1238.             treq.tr_node.io_Message.mn_ReplyPort=general_port;
  1239.             treq.tr_node.io_Command=TR_ADDREQUEST;
  1240.             treq.tr_node.io_Flags=0;
  1241.             treq.tr_time.tv_secs=0;
  1242.             treq.tr_time.tv_micro=10;
  1243.             SendIO(&treq.tr_node);
  1244.             waitbits|=1<<general_port->mp_SigBit;
  1245.             gottimer=1;
  1246.         }
  1247.         if (!(anim=(!(config->viewbits&VIEWBITS_PAUSEANIMS))) && doublebuffer)
  1248.             doanimframe();
  1249.     }
  1250.  
  1251.     FOREVER {
  1252.         if (first_anim_frame) {
  1253.             while (GetMsg(general_port));
  1254.             if (CheckIO(&treq.tr_node)) {
  1255.                 WaitIO(&treq.tr_node);
  1256.                 treq.tr_time.tv_secs=0;
  1257.                 treq.tr_time.tv_micro=animspeed;
  1258.                 SendIO(&treq.tr_node);
  1259.                 if (anim) doanimframe();
  1260.             }
  1261.         }
  1262.         while (msg=(struct IntuiMessage *) GetMsg(wind->UserPort)) {
  1263.             class=msg->Class; code=msg->Code; qual=msg->Qualifier;
  1264.             ReplyMsg((struct Message *) msg);
  1265.             switch (class) {
  1266.                 case IDCMP_INTUITICKS:
  1267.                     if (waitfor && (++ticks)>=waitfor) retcode=0;
  1268.                     break;
  1269.                 case IDCMP_RAWKEY:
  1270.                     if (code>=0x50 && code<=0x59) {
  1271.                         code-=0x50;
  1272.                         animspeed=(code*10000)+10;
  1273.                         break;
  1274.                     }
  1275.                     switch (code) {
  1276.                         case 0x0b:
  1277.                             if ((animspeed+=10000)>1000000) animspeed=1000000;
  1278.                             break;
  1279.                         case 0x0c:
  1280.                             if ((animspeed-=10000)<10) animspeed=10;
  1281.                             break;
  1282.                         case 0x0d:
  1283.                             animspeed=origspeed;
  1284.                             break;
  1285.                         case 0x21:
  1286.                             anim=1-anim;
  1287.                             break;
  1288.                         case 0x36:
  1289.                             if (first_anim_frame) {
  1290.                                 anim=0;
  1291.                                 doanimframe();
  1292.                             }
  1293.                             break;
  1294.                         case CURSOR_LEFT:
  1295.                         case 0x2d:
  1296.                         case CURSOR_RIGHT:
  1297.                         case 0x2f:
  1298.                             if (tits!=3) break;
  1299.                             if (qual&IEQUALIFIER_CONTROL) delta=-bitmapwidth;
  1300.                             else if (qual&IEQUALIFIER_ANYSHIFT) delta=-(screenwidth-20);
  1301.                             else delta=-2;
  1302.                             if (code==CURSOR_RIGHT || code==0x2f) delta=-delta;
  1303.                             if (system_version2) MoveScreen(wind->WScreen,-delta,0);
  1304.                             else {
  1305.                                 ivp->RasInfo->RxOffset+=delta;
  1306.                                 docheckrasscroll(wind->WScreen);
  1307.                             }
  1308.                             break;
  1309.                         case CURSOR_UP:
  1310.                         case 0x3e:
  1311.                         case CURSOR_DOWN:
  1312.                         case 0x1e:
  1313.                             if (tits!=3) break;
  1314.                             if (qual&IEQUALIFIER_CONTROL) delta=bitmapheight;
  1315.                             else if (qual&IEQUALIFIER_ANYSHIFT) delta=screenheight-20;
  1316.                             else delta=2;
  1317.                             if (code==CURSOR_UP || code==0x3e) {
  1318.                                 delta=-delta;
  1319.                                 if (system_version2) {
  1320.                                     if (wind->WScreen->TopEdge-delta>0)
  1321.                                         delta=wind->WScreen->TopEdge;
  1322.                                 }
  1323.                             }
  1324.                             if (system_version2) MoveScreen(wind->WScreen,0,-delta);
  1325.                             else {
  1326.                                 ivp->RasInfo->RyOffset+=delta;
  1327.                                 docheckrasscroll(wind->WScreen);
  1328.                             }
  1329.                             break;
  1330.                         case 0x44:
  1331.                             if (tits==2) retcode=-2;
  1332.                             else retcode=0;
  1333.                             break;
  1334.                         case 0x45:
  1335.                             retcode=-1;
  1336.                             break;
  1337.                         case 0x10:
  1338.                             if (!(qual&IEQUALIFIER_REPEAT)) retcode=0;
  1339.                             break;
  1340.                         case 0x42:
  1341.                             if (tits&1 && currange) togglecycle();
  1342.                             break;
  1343.                         case 0x5f:
  1344.                         case 0x19:
  1345.                         case 0x40:
  1346.                             if (!(qual&IEQUALIFIER_REPEAT)) {
  1347.                                 ModifyIDCMP(wind,(wind->IDCMPFlags&~IDCMP_INACTIVEWINDOW)|IDCMP_ACTIVEWINDOW);
  1348.                                 if (tits&1) gfxprint(wind,&iffscreen->RastPort,0,0,bitmapwidth,bitmapheight,1);
  1349.                                 else gfxprint(wind,wind->RPort,0,0,wind->Width,wind->Height,0);
  1350.                             }
  1351.                             break;
  1352.                         case 0x39:
  1353.                             if (pon) setnullpointer(wind);
  1354.                             else ClearPointer(wind);
  1355.                             pon^=1;
  1356.                             break;
  1357.                         case 0x1a:
  1358.                             if (colourtable_4 && !specialformat)
  1359.                                 LoadRGB4(ivp,colourtable_4,numcolours);
  1360.                             break;
  1361.                         case 0x1b:
  1362.                             if (colourtable_8 && !specialformat)
  1363.                                 LoadRGB32(ivp,colourtable_8);
  1364.                             break;
  1365.                     }
  1366.                     break;
  1367.                 case IDCMP_ACTIVEWINDOW:
  1368.                     ModifyIDCMP(wind,(wind->IDCMPFlags&~IDCMP_ACTIVEWINDOW)|IDCMP_INACTIVEWINDOW);
  1369.                     break;
  1370.                 case IDCMP_INACTIVEWINDOW:
  1371.                     if (IntuitionBase->ActiveScreen!=wind->WScreen) {
  1372.                         retcode=-3;
  1373.                         break;
  1374.                     }
  1375.                     code=SELECTDOWN;
  1376.                 case IDCMP_MOUSEBUTTONS:
  1377.                     if (code==SELECTDOWN) retcode=0;
  1378.                     else if (code==MENUDOWN) retcode=-1;
  1379.                     break;
  1380.             }
  1381.             if (retcode!=1) break;
  1382.         }
  1383.         if (retcode!=1) break;
  1384.         Wait(waitbits);
  1385.     }
  1386.     if (first_anim_frame && gottimer) {
  1387.         if (!(CheckIO(&treq.tr_node)))
  1388.             AbortIO(&treq.tr_node);
  1389.         WaitIO(&treq.tr_node);
  1390.         CloseDevice(&treq.tr_node);
  1391.         while (GetMsg(general_port));
  1392.     }
  1393.     return(retcode);
  1394. }
  1395.  
  1396. chunkread(buf,nbytes)
  1397. void *buf;
  1398. ULONG nbytes;
  1399. {
  1400.     if (bufferpos+nbytes>buffersize) return(0);
  1401.     CopyMem((char *)&picbuffer[bufferpos],(char *)buf,nbytes);
  1402.     bufferpos+=nbytes;
  1403.     return(1);
  1404. }
  1405.  
  1406. void getcolstring(str)
  1407. char *str;
  1408. {
  1409.     if (viewflags&HAM || specialformat) {
  1410.         if (bmhead.nPlanes==8) strcpy(str,"256K");
  1411.         else strcpy(str,"4096");
  1412.     }
  1413.     else lsprintf(str,"%ld",1<<bmhead.nPlanes);
  1414. }
  1415.  
  1416. void dotitle()
  1417. {
  1418.     char title[100],modes[140],cols[30];
  1419.  
  1420.     getcolstring(cols);
  1421.     getviewmodes(modes);
  1422.     lsprintf(title,"%ld x %ld x %ld (page %ld x %ld) %s cols (%s)",
  1423.         bmhead.w,bmhead.h,bmhead.nPlanes,bmhead.pageWidth,bmhead.pageHeight,
  1424.         cols,modes);
  1425.     dostatustext(title);
  1426. }
  1427.  
  1428. void gfxprint(wind,rast,x,y,w,h,iff)
  1429. struct Window *wind;
  1430. struct RastPort *rast;
  1431. int x,y,w,h,iff;
  1432. {
  1433.     struct IntuiMessage *msg;
  1434.     struct Window *pwin;
  1435.     struct Screen *pscr;
  1436.     struct RastPort *prp;
  1437.     ULONG class;
  1438.     USHORT code,gadgetid,qual;
  1439.     struct PrinterData *pd;
  1440.     struct Preferences *prefs;
  1441.     int a,b,abort=0,goff,fnum;
  1442.     char buf[200],modes[140],*ptr,pactcode[6],cols[30],title[120];
  1443.     APTR save;
  1444.     struct DOpusRemember *pkey=NULL;
  1445.     static char firsttime;
  1446.  
  1447.     if (scrdata_is_pal) {
  1448.         printscreen.Height=printwin.Height=256;
  1449.         goff=28;
  1450.     }
  1451.     else {
  1452.         printscreen.Height=printwin.Height=200;
  1453.         goff=0;
  1454.     }
  1455.  
  1456.     for (a=0;a<7;a++) {
  1457.         if (a==5) printgadtxt[a]=globstring[STR_PRINTTITLE];
  1458.         else if (a==6) printgadtxt[a]=globstring[STR_PRINT];
  1459.         else printgadtxt[a]=globstring[STR_ASPECT+a];
  1460.         if (a<6) {
  1461.             for (b=0;;b++) {
  1462.                 if (!printgadtxt[a][b]) break;
  1463.                 if (printgadtxt[a][b]=='_') {
  1464.                     pactcode[a]=tolower(printgadtxt[a][b+1]);
  1465.                     break;
  1466.                 }
  1467.             }
  1468.         }
  1469.     }
  1470.  
  1471.     printgadtxt[7]=str_cancelstring;
  1472.     printgadtxt[8]=NULL;
  1473.     printabortgadtxt[0]=globstring[STR_ABORT_PRINT];
  1474.     for (a=0;a<2;a++) {
  1475.         print_aspect_txt[a]=globstring[STR_PORTRAIT+a];
  1476.         print_image_txt[a]=globstring[STR_POSITIVE+a];
  1477.         print_placement_txt[a]=globstring[STR_CENTER+a];
  1478.     }
  1479.     for (a=0;a<3;a++) print_shade_txt[a]=globstring[STR_BLACK_WHITE+a];
  1480.  
  1481.     if (!(pscr=OpenScreen((struct NewScreen *)&printscreen))) return;
  1482.     LoadRGB4(&(pscr->ViewPort),basepalette,4);
  1483.     printwin.Screen=pscr;
  1484.     if (!(pwin=OpenWindow(&printwin))) {
  1485.         CloseScreen(pscr);
  1486.         return;
  1487.     }
  1488.     prp=pwin->RPort;
  1489.     SetFont(prp,scr_font[FONT_GENERAL]);
  1490.     SetAPen(prp,1);
  1491.     Do3DFrame(prp,0,4+goff,320,88,globstring[STR_DESCRIPTION],2,1);
  1492.     Do3DFrame(prp,0,98+goff,320,86,globstring[STR_PRINT_CONTROL],2,1);
  1493.  
  1494.     if (iff) {
  1495.         ptr=BaseName(picturename);
  1496.         getcolstring(cols);
  1497.         lsprintf(buf,"%12s : %s",
  1498.             globstring[STR_FILE],
  1499.             ptr);
  1500.         iffinfotxt(prp,buf,7,19+goff);
  1501.  
  1502.         lsprintf(buf,"%12s : %ld x %ld",
  1503.             globstring[STR_IMAGE_SIZE],
  1504.             bmhead.w,
  1505.             bmhead.h);
  1506.         iffinfotxt(prp,buf,7,35+goff);
  1507.  
  1508.         if (first_anim_frame) {
  1509.             if (framenum<2) fnum=1;
  1510.             else fnum=framenum-1;
  1511.             lsprintf(buf,"%12s : %ld %s %ld @ %ld/sec",
  1512.                 globstring[STR_NUM_FRAMES],
  1513.                 fnum,
  1514.                 globstring[STR_OF],
  1515.                 framecount+(1-got_dpan),
  1516.                 framespersec);
  1517.             iffinfotxt(prp,buf,7,43+goff);
  1518.  
  1519.             lsprintf(buf,"%12s : ANIM Op %ld",
  1520.                 globstring[STR_ANIM_TYPE],
  1521.                 animtype);
  1522.             iffinfotxt(prp,buf,7,51+goff);
  1523.  
  1524.             lsprintf(title,"IFF ANIM : %s   %s %ld %s %ld   %ld x %ld x %s\n\n",
  1525.                 ptr,
  1526.                 globstring[STR_FRAME],
  1527.                 fnum,
  1528.                 globstring[STR_OF],
  1529.                 framecount+1,
  1530.                 bmhead.w,
  1531.                 bmhead.h,
  1532.                 cols);
  1533.         }
  1534.         else {
  1535.             lsprintf(buf,"%12s : %ld x %ld",
  1536.                 globstring[STR_PAGE_SIZE],
  1537.                 bmhead.pageWidth,
  1538.                 bmhead.pageHeight);
  1539.             iffinfotxt(prp,buf,7,43+goff);
  1540.  
  1541.             lsprintf(buf,"%12s : %ld x %ld",
  1542.                 globstring[STR_SCREEN_SIZE],
  1543.                 iffscreen->Width,
  1544.                 iffscreen->Height);
  1545.             iffinfotxt(prp,buf,7,51+goff);
  1546.  
  1547.             lsprintf(title,"IFF ILBM : %s   %ld x %ld x %s\n\n",
  1548.                 ptr,
  1549.                 bmhead.w,
  1550.                 bmhead.h,
  1551.                 cols);
  1552.         }
  1553.         lsprintf(buf,"%12s : %ld",
  1554.             globstring[STR_DEPTH],
  1555.             bmhead.nPlanes);
  1556.         iffinfotxt(prp,buf,7,67+goff);
  1557.  
  1558.         lsprintf(buf,"%12s : %s",
  1559.             globstring[STR_COLOURS],
  1560.             cols);
  1561.         iffinfotxt(prp,buf,7,75+goff);
  1562.  
  1563.         getviewmodes(modes);
  1564.         lsprintf(buf,"%12s : %s",
  1565.             globstring[STR_SCREEN_MODES],
  1566.             modes);
  1567.         iffinfotxt(prp,buf,7,83+goff);
  1568.     }
  1569.     else if (show_global_font) {
  1570.         char fontname[40],*ptr;
  1571.  
  1572.         strcpy(fontname,show_global_font->tf_Message.mn_Node.ln_Name);
  1573.         if (ptr=strstri(fontname,".font")) *ptr=0;
  1574.  
  1575.         lsprintf(buf,"%12s : %s",
  1576.             globstring[STR_FONT],
  1577.             fontname);
  1578.         iffinfotxt(prp,buf,7,19+goff);
  1579.  
  1580.         lsprintf(buf,"%12s : %ld",
  1581.             globstring[STR_FONT_SIZE],
  1582.             show_global_font->tf_YSize);
  1583.         iffinfotxt(prp,buf,7,35+goff);
  1584.  
  1585.         lsprintf(buf,"%12s : %ld (%ld - %ld)",
  1586.             globstring[STR_NUM_CHARS],
  1587.             (show_global_font->tf_HiChar-show_global_font->tf_LoChar)+1,
  1588.             show_global_font->tf_LoChar,
  1589.             show_global_font->tf_HiChar);
  1590.         iffinfotxt(prp,buf,7,51+goff);
  1591.  
  1592.         lsprintf(buf,"%12s :",
  1593.             globstring[STR_FONT_STYLE]);
  1594.         if ((show_global_font->tf_Style&15)==0) strcat(buf," NORMAL");
  1595.         else {
  1596.             if (show_global_font->tf_Style&FSF_UNDERLINED) strcat(buf," ULINED");
  1597.             if (show_global_font->tf_Style&FSF_BOLD) strcat(buf," BOLD");
  1598.             if (show_global_font->tf_Style&FSF_ITALIC) strcat(buf," ITALIC");
  1599.             if (show_global_font->tf_Style&FSF_EXTENDED) strcat(buf," EXTEND");
  1600.         }
  1601.         iffinfotxt(prp,buf,7,67+goff);
  1602.  
  1603.         lsprintf(buf,"%12s :",globstring[STR_FONT_FLAGS]);
  1604.         if (show_global_font->tf_Flags&FPF_TALLDOT) strcat(buf," TALL");
  1605.         if (show_global_font->tf_Flags&FPF_WIDEDOT) strcat(buf," WIDE");
  1606.         if (show_global_font->tf_Flags&FPF_PROPORTIONAL)
  1607.             strcat(buf," PROP");
  1608.         iffinfotxt(prp,buf,7,75+goff);
  1609.  
  1610.         lsprintf(title,"Font : %s/%ld   %ld chars (%ld - %ld)\n\n",
  1611.             fontname,show_global_font->tf_YSize,
  1612.             (show_global_font->tf_HiChar-show_global_font->tf_LoChar)+1,
  1613.             show_global_font->tf_LoChar,
  1614.             show_global_font->tf_HiChar);
  1615.     }
  1616.     else if (show_global_icon) {
  1617.         lsprintf(buf,"%12s : %s",
  1618.             globstring[STR_ICON],
  1619.             show_global_icon_name);
  1620.         iffinfotxt(prp,buf,7,27+goff);
  1621.  
  1622.         lsprintf(buf,"%12s : %s",
  1623.             globstring[STR_ICON_TYPE],
  1624.             icon_type_names[show_global_icon->do_Type-1]);
  1625.         iffinfotxt(prp,buf,7,43+goff);
  1626.  
  1627.         lsprintf(buf,"%12s : %s",
  1628.             globstring[STR_ICON_ALTERNATE],
  1629.             (show_global_icon->do_Gadget.Flags&GFLG_GADGHIMAGE)?
  1630.             globstring[STR_YES]:globstring[STR_NO]);
  1631.         iffinfotxt(prp,buf,7,59+goff);
  1632.  
  1633.         if (show_global_icon->do_DefaultTool) {
  1634.             lsprintf(buf,"%12s : %s",
  1635.                 globstring[STR_ICON_DEFAULTTOOL],
  1636.                 show_global_icon->do_DefaultTool);
  1637.             iffinfotxt(prp,buf,7,75+goff);
  1638.         }
  1639.         lsprintf(title,"Workbench %s : %s\n\n",
  1640.             globstring[STR_ICON],
  1641.             show_global_icon_name);
  1642.     }
  1643.  
  1644.     for (a=0;a<8;a++) printgadgets[a].TopEdge+=goff;
  1645.     printcheckimage.ImageData=(USHORT *)DOpusBase->pdb_check;
  1646.     AddGadgetBorders(&pkey,printgadgets,4,2,1);
  1647.     AddGadgetBorders(&pkey,&printgadgets[PRINT_OKAY],2,2,1);
  1648.     AddGadgets(pwin,printgadgets,printgadtxt,8,2,1,1);
  1649.  
  1650.     if (!firsttime) {
  1651.         struct Preferences prefs;
  1652.  
  1653.         GetPrefs(&prefs,sizeof(struct Preferences));
  1654.         print_gads_sel[PRINT_ASPECT]=prefs.PrintAspect;
  1655.         print_gads_sel[PRINT_IMAGE]=prefs.PrintImage;
  1656.         print_gads_sel[PRINT_SHADE]=prefs.PrintShade;
  1657.  
  1658.         firsttime=1;
  1659.     }
  1660.  
  1661.     for (a=0;a<4;a++) {
  1662.         DoCycleGadget(&printgadgets[a],
  1663.             pwin,
  1664.             print_gads_txt[a],
  1665.             print_gads_sel[a]);
  1666.     }
  1667.  
  1668.     ScreenToFront(pscr);
  1669.     ActivateWindow(pwin);
  1670.     save=main_proc->pr_WindowPtr;
  1671.     main_proc->pr_WindowPtr=(APTR)pwin;
  1672.  
  1673.     FOREVER {
  1674.         Wait(1<<pwin->UserPort->mp_SigBit);
  1675.         while (msg=(struct IntuiMessage *) GetMsg(pwin->UserPort)) {
  1676.             class=msg->Class; code=msg->Code; qual=msg->Qualifier;
  1677.             if (class==IDCMP_GADGETUP)
  1678.                 gadgetid=((struct Gadget *)msg->IAddress)->GadgetID;
  1679.             ReplyMsg((struct Message *) msg);
  1680.             switch (class) {
  1681.                 case IDCMP_VANILLAKEY:
  1682.                     if (qual&IEQUALIFIER_REPEAT) break;
  1683.                     for (a=0;a<6;a++) {
  1684.                         if (code==pactcode[a] || code==toupper(pactcode[a])) {
  1685.                             if (a<4) {
  1686.                                 if (code==toupper(pactcode[a])) qual|=IEQUALIFIER_LSHIFT;
  1687.                                 SelectGadget(pwin,&printgadgets[a]);
  1688.                                 gadgetid=a;
  1689.                                 goto docyclegads;
  1690.                             }
  1691.                             else if (a==4) {
  1692.                                 printgadgets[4].Flags^=GFLG_SELECTED;
  1693.                                 RefreshGList(&printgadgets[4],pwin,NULL,1);
  1694.                             }
  1695.                             else if (a==5) {
  1696.                                 printgadgets[5].Flags^=GFLG_SELECTED;
  1697.                                 RefreshGList(&printgadgets[5],pwin,NULL,1);
  1698.                             }
  1699.                         }
  1700.                     }
  1701.                     if (code==globstring[STR_PRINT][0]) {
  1702.                         SelectGadget(pwin,&printgadgets[6]);
  1703.                         goto doprint;
  1704.                     }
  1705.                     else if (code=='' || code==' ' || code==tolower(str_cancelstring[0])) {
  1706.                         SelectGadget(pwin,&printgadgets[7]);
  1707.                         goto endprint;
  1708.                     }
  1709.                     break;
  1710.  
  1711.                 case IDCMP_GADGETUP:
  1712.                     if (gadgetid<PRINT_FORMFD) {
  1713. docyclegads:
  1714.                         if (qual&IEQUALIFIER_ANYSHIFT) {
  1715.                             if ((--print_gads_sel[gadgetid])<0)
  1716.                                 print_gads_sel[gadgetid]=print_gads_max[gadgetid];
  1717.                         }
  1718.                         else {
  1719.                             if ((++print_gads_sel[gadgetid])>print_gads_max[gadgetid])
  1720.                                 print_gads_sel[gadgetid]=0;
  1721.                         }
  1722.                         DoCycleGadget(&printgadgets[gadgetid],
  1723.                             pwin,
  1724.                             print_gads_txt[gadgetid],
  1725.                             print_gads_sel[gadgetid]);
  1726.                     }
  1727.                     else switch (gadgetid) {
  1728.                         case PRINT_CANCEL:
  1729.                             goto endprint;
  1730.                         case PRINT_OKAY:
  1731.                             goto doprint;
  1732.                     }
  1733.                     break;
  1734.             }
  1735.         }
  1736.     }
  1737. doprint:
  1738.     RemoveGList(pwin,printgadgets,-1);
  1739.     SetAPen(prp,0);
  1740.     RectFill(prp,0,0,319,pwin->Height-1);
  1741.     SetAPen(prp,1);
  1742.     abortprintgad.TopEdge=(pwin->Height-80)/2;
  1743.     AddGadgetBorders(&pkey,&abortprintgad,1,2,1);
  1744.     AddGadgets(pwin,&abortprintgad,printabortgadtxt,1,2,1,1);
  1745.     SetBusyPointer(pwin);
  1746.     if (print_request=(union printerIO *) LCreateExtIO(general_port,sizeof(union printerIO))) {
  1747.         if (!(OpenDevice("printer.device",0,(struct IORequest *)print_request,0))) {
  1748.             pd=(struct PrinterData *)print_request->iodrp.io_Device;
  1749.             prefs=&pd->pd_Preferences;
  1750.             prefs->PrintAspect=print_gads_sel[PRINT_ASPECT];
  1751.             prefs->PrintImage=print_gads_sel[PRINT_IMAGE];
  1752.             prefs->PrintShade=print_gads_sel[PRINT_SHADE];
  1753.             prefs->PrintXOffset=0;
  1754.  
  1755.             print_request->ios.io_Command=CMD_WRITE;
  1756.             print_request->ios.io_Data="\033#1";
  1757.             print_request->ios.io_Length=-1;
  1758.             while (DoIO((struct IORequest *)print_request)) {
  1759.                 reqoverride=pwin;
  1760.                 a=simplerequest(globstring[STR_ERROR_INITIALISING_PRINTER],
  1761.                     globstring[STR_TRY_AGAIN],str_cancelstring,NULL);
  1762.                 reqoverride=NULL;
  1763.                 if (!a) goto closeprinter;
  1764.             }
  1765.  
  1766.             if (printgadgets[5].Flags&GFLG_SELECTED) {
  1767.                 print_request->ios.io_Command=CMD_WRITE;
  1768.                 print_request->ios.io_Data=title;
  1769.                 print_request->ios.io_Length=-1;
  1770.                 if (DoIO((struct IORequest *)print_request)) goto closeprinter;
  1771.             }
  1772.  
  1773.             print_request->iodrp.io_Command=PRD_DUMPRPORT;
  1774.             print_request->iodrp.io_RastPort=rast;
  1775.             print_request->iodrp.io_ColorMap=wind->WScreen->ViewPort.ColorMap;
  1776.             if (system_version2) {
  1777.                 print_request->iodrp.io_Modes=GetVPModeID(&(wind->WScreen->ViewPort));
  1778.             }
  1779.             else {
  1780.                 print_request->iodrp.io_Modes=wind->WScreen->ViewPort.Modes;
  1781.             }
  1782.             print_request->iodrp.io_SrcX=x;
  1783.             print_request->iodrp.io_SrcY=y;
  1784.             print_request->iodrp.io_SrcWidth=w;
  1785.             print_request->iodrp.io_SrcHeight=h;
  1786.             print_request->iodrp.io_Special=SPECIAL_FULLCOLS|SPECIAL_ASPECT|SPECIAL_NOFORMFEED;
  1787.             if (!print_gads_sel[PRINT_PLACE])
  1788.                 print_request->iodrp.io_Special|=SPECIAL_CENTER;
  1789.             if (!(printgadgets[4].Flags&GFLG_SELECTED))
  1790.                 print_request->iodrp.io_Special|=SPECIAL_NOFORMFEED;
  1791.  
  1792.             SendIO((struct IORequest *)print_request);
  1793.             FOREVER {
  1794.                 Wait(1<<pwin->UserPort->mp_SigBit|1<<general_port->mp_SigBit);
  1795.                 while (GetMsg(general_port));
  1796.                 while (msg=(struct IntuiMessage *) GetMsg(pwin->UserPort)) {
  1797.                     class=msg->Class;
  1798.                     if (class==IDCMP_GADGETUP)
  1799.                         gadgetid=((struct Gadget *)msg->IAddress)->GadgetID;
  1800.                     ReplyMsg((struct Message *) msg);
  1801.                     if (class==IDCMP_GADGETUP && gadgetid==PRINT_ABORT) {
  1802.                         reqoverride=pwin;
  1803.                         abort=simplerequest(globstring[STR_REALLY_ABORT_PRINT],
  1804.                             globstring[STR_ABORT],globstring[STR_CONTINUE],NULL);
  1805.                         reqoverride=NULL;
  1806.                         if (abort) AbortIO((struct IORequest *)print_request);
  1807.                         break;
  1808.                     }
  1809.                 }
  1810.                 if (abort || (CheckIO((struct IORequest *)print_request))) break;
  1811.             }
  1812.             WaitIO((struct IORequest *)print_request);
  1813.             if (!abort && printgadgets[4].Flags&GFLG_SELECTED) {
  1814.                 print_request->ios.io_Command=CMD_WRITE;
  1815.                 print_request->ios.io_Data="\f";
  1816.                 print_request->ios.io_Length=-1;
  1817.                 DoIO((struct IORequest *)print_request);
  1818.             }
  1819. closeprinter:
  1820.             CloseDevice((struct IORequest *)print_request);
  1821.         }
  1822.         LDeleteExtIO((struct IORequest *)print_request);
  1823.     }
  1824. endprint:
  1825.     for (a=0;a<8;a++) printgadgets[a].TopEdge-=goff;
  1826.     main_proc->pr_WindowPtr=save;
  1827.     ActivateWindow(iffwindow);
  1828.     ScreenToBack(pscr);
  1829.     CloseWindow(pwin);
  1830.     CloseScreen(pscr);
  1831.     LFreeRemember(&pkey);
  1832. }
  1833.  
  1834. InitDHIRES(mp)
  1835. int mp;
  1836. {
  1837.     int line,creg,top,oscan,lace;
  1838.     struct UCopList *ucop;
  1839.  
  1840.     if (!(ucop=(struct UCopList *)AllocMem(sizeof(struct UCopList),MEMF_CLEAR)))
  1841.         return(0);
  1842.  
  1843.     lace=(viewflags&LACE)?1:0;
  1844.     top=copperheight;
  1845.     if (lace) top/=2;
  1846.  
  1847.     if (mp) {
  1848.         if (screenwidth>640) oscan=14;
  1849.         else oscan=16;
  1850.         CINIT(ucop,top*13);
  1851.         for (line=0;line<top;line++) {
  1852.             CWAIT(ucop,(line-1)<<lace,112);
  1853.             for (creg=4;creg<oscan;creg++) {
  1854.                 CMove(ucop,(long *)(0xdff180+(creg*2)),copperlist[(line<<(4+lace))+creg]);
  1855.                 CBump(ucop);
  1856.             }
  1857.         }
  1858.     }
  1859.     else {
  1860.         CINIT(ucop,copperheight*17);
  1861.         for (line=0;line<copperheight;line++) {
  1862.             CWAIT(ucop,line-1,122);
  1863.             for (creg=4;creg<16;creg++) {
  1864.                 CMove(ucop,(long *)(0xdff180+(creg*2)),copperlist[(line<<4)+creg]);
  1865.                 CBump(ucop);
  1866.             }
  1867.         }
  1868.     }
  1869.  
  1870.     CEND(ucop);
  1871.     Forbid();
  1872.     ivp->UCopIns=ucop;
  1873.     Permit();
  1874.     RethinkDisplay();
  1875.     return(1);
  1876. }
  1877.  
  1878. void getviewmodes(modes)
  1879. char *modes;
  1880. {
  1881.     if (iffscreenname[0]) strcpy(modes,iffscreenname);
  1882.     else {
  1883.         if (viewflags&SUPERHIRES) {
  1884.             strcpy(modes,"SUPERHIRES");
  1885.             if (bmhead.w>1280) strcat(modes," OSCAN");
  1886.         }
  1887.         else if (viewflags&HIRES) {
  1888.             strcpy(modes,"HIRES");
  1889.             if (bmhead.w>640) strcat(modes," OSCAN");
  1890.         }
  1891.         else {
  1892.             strcpy(modes,"LORES");
  1893.             if (bmhead.w>320) strcat(modes," OSCAN");
  1894.         }
  1895.         if (viewflags&LACE) strcat(modes," LACE");
  1896.     }
  1897.     if (copperlist) strcat(modes," DHIRES");
  1898.     else if (pchghead) {
  1899.         if (sham) strcat(modes," SHAM");
  1900.         else strcat(modes," PCHG");
  1901.     }
  1902.     else {
  1903.         if (viewflags&HAM) strcat(modes," HAM");
  1904.         else if (viewflags&EXTRA_HALFBRITE) strcat(modes," EHB");
  1905.     }
  1906. }
  1907.  
  1908. void docheckrasscroll(scr)
  1909. struct Screen *scr;
  1910. {
  1911.     if (ivp->RasInfo->RxOffset+screenwidth>bitmapwidth)
  1912.         ivp->RasInfo->RxOffset=bitmapwidth-ivp->DWidth;
  1913.     if (ivp->RasInfo->RxOffset<0) ivp->RasInfo->RxOffset=0;
  1914.     if (ivp->RasInfo->RyOffset+screenheight>bitmapheight)
  1915.         ivp->RasInfo->RyOffset=bitmapheight-ivp->DHeight;
  1916.     if (ivp->RasInfo->RyOffset<0) ivp->RasInfo->RyOffset=0;
  1917.     MakeScreen(scr);
  1918.     RethinkDisplay();
  1919. }
  1920.  
  1921. void iffinfotxt(r,buf,x,y)
  1922. struct RastPort *r;
  1923. char *buf;
  1924. int x,y;
  1925. {
  1926.     int a,l;
  1927.  
  1928.     a=strlen(buf); l=(316-x)/8;
  1929.     Move(r,x,y);
  1930.     Text(r,buf,(a>l)?l:a);
  1931. }
  1932.  
  1933. void build_palettes(colourdata,coloursize,ctable4,ctable8)
  1934. unsigned char *colourdata;
  1935. int coloursize;
  1936. UWORD *ctable4;
  1937. ULONG *ctable8;
  1938. {
  1939.     int a,b;
  1940.     unsigned int rgb[3];
  1941.  
  1942.     if (ctable8) {
  1943.         for (a=0,b=1;a<coloursize;a++,b++)
  1944. /*
  1945.             ctable8[b]=(colourdata[a]<<24)|0x00ffffff;
  1946. */
  1947.             ctable8[b]=
  1948.                 ((colourdata[a]<<24)&0xff000000)|
  1949.                 ((colourdata[a]<<16)&0x00ff0000)|
  1950.                 ((colourdata[a]<<8)&0x0000ff00)|
  1951.                 ((colourdata[a]&0x000000ff));
  1952.  
  1953.         ctable8[0]=numcolours<<16;
  1954.         ctable8[(numcolours*3)+1]=0;
  1955.     }
  1956.  
  1957.     if (ctable4) {
  1958.         for (a=0;a<numcolours;a++) {
  1959.             for (b=0;b<3;b++) rgb[b]=(unsigned int)(((unsigned char)(*(colourdata++)))>>4);
  1960.             ctable4[a]=(rgb[0]<<8)+(rgb[1]<<4)+rgb[2];
  1961.         }
  1962.     }
  1963. }
  1964.