home *** CD-ROM | disk | FTP | other *** search
/ World of A1200 / World_Of_A1200.iso / programs / monitors / rsys / source.lha / src / rsyssavewindow.c < prev    next >
C/C++ Source or Header  |  1995-01-09  |  24KB  |  1,053 lines

  1. /*
  2. ***************************************************************************
  3. *
  4. * Datei:
  5. *    RSysSaveWindow.c
  6. *
  7. * Inhalt:
  8. *    void SaveWindows(void);
  9. *
  10. * Bemerkungen:
  11. *    Erzeugen einer IFF-Datei aus einem Window.
  12. *
  13. * Erstellungsdatum:
  14. *    07-Jan-93    Rolf Böhme
  15. *
  16. * Änderungen:
  17. *    07-Jan-93    Rolf Böhme    Erstellung
  18. *
  19. ***************************************************************************
  20. */
  21.  
  22. #include "RSysDebug.h"
  23. #include "RSysFunc.h"
  24.  
  25.    /*
  26.     * Diese Routinen habe ich wieder mal aus der
  27.     * "Quellen-Fundgrube" von TERM entnommen.  Danke Olaf!  Aber
  28.     * einiges war leider falsch :-)
  29.     */
  30.  
  31.     /* Current compression mode. */
  32.  
  33. #define DUMP        0
  34. #define RUN        1
  35.  
  36.     /* ByteRun compression data. */
  37.  
  38. #define MINRUN        3
  39. #define MAXRUN        128
  40. #define MAXDAT        128
  41.  
  42.     /* Chunk types. */
  43.  
  44. #define ID_ILBM        MAKE_ID('I','L','B','M')
  45. #define ID_ANNO        MAKE_ID('A','N','N','O')
  46. #define ID_BMHD        MAKE_ID('B','M','H','D')
  47. #define ID_CMAP        MAKE_ID('C','M','A','P')
  48. #define ID_CAMG        MAKE_ID('C','A','M','G')
  49. #define ID_BODY        MAKE_ID('B','O','D','Y')
  50.  
  51.     /* Masking technique. */
  52.  
  53. #define mskNone        0
  54.  
  55.     /* Compression techniques. */
  56.  
  57. #define cmpNone        0
  58. #define cmpByteRun1    1
  59.  
  60.     /* A bitmap header. */
  61.  
  62. typedef struct
  63. {
  64.     UWORD        w,h;            /* raster width & height in pixels */
  65.     WORD        x,y;            /* position for this image */
  66.     UBYTE        nPlanes;        /* # source bitplanes */
  67.     UBYTE        masking;        /* masking technique */
  68.     UBYTE        compression;        /* compression algorithm */
  69.     UBYTE        pad1;            /* UNUSED.  For consistency, put 0 here.*/
  70.     UWORD        transparentColor;    /* transparent "color number" */
  71.     UBYTE        xAspect,yAspect;    /* aspect ratio, a rational number x/y */
  72.     WORD        pageWidth,pageHeight;    /* source "page" size in pixels */
  73. } BitMapHeader;
  74.  
  75.     /* A single 8-bit colour register. */
  76.  
  77. typedef struct
  78. {
  79.     UBYTE        red,            /* red component, 0..255 */
  80.             green,            /* green component, 0..255 */
  81.             blue;            /* blue component, 0..255 */
  82. } ColorRegister;
  83.  
  84.  
  85.     /* Local packer data. */
  86.  
  87. static LONG        PackedBytes;
  88. static BYTE        Buffer[MAXDAT + 1];
  89.  
  90.     /* PutDump(register PLANEPTR Destination,register LONG Count):
  91.      *
  92.      *    Output a byte dump.
  93.      */
  94.  
  95. static PLANEPTR
  96. PutDump(register PLANEPTR Destination,register LONG Count)
  97. {
  98.     register PLANEPTR Source = (PLANEPTR)Buffer;
  99.  
  100.     *Destination++     = Count - 1;
  101.      PackedBytes    += Count + 1;
  102.  
  103.     while(Count--)
  104.         *Destination++ = *Source++;
  105.  
  106.     return(Destination);
  107. }
  108.  
  109.     /* PutRun(register PLANEPTR Destination,LONG Count,WORD Char):
  110.      *
  111.      *    Output a byte run.
  112.      */
  113.  
  114. static PLANEPTR
  115. PutRun(register PLANEPTR Destination,LONG Count,WORD Char)
  116. {
  117.     *Destination++     = -(Count - 1);
  118.     *Destination++     = Char;
  119.      PackedBytes    += 2;
  120.  
  121.     return(Destination);
  122. }
  123.  
  124.     /* PackRow(PLANEPTR *SourcePtr,register PLANEPTR Destination,LONG RowSize):
  125.      *
  126.      *    Pack a row of bitmap data using ByteRun compression,
  127.      *    based on the original "EA IFF 85" pack.c example code.
  128.      */
  129.  
  130. static LONG
  131. PackRow(PLANEPTR *SourcePtr,register PLANEPTR Destination,LONG RowSize)
  132. {
  133.     register PLANEPTR Source = *SourcePtr;
  134.  
  135.     WORD    Buffered    = 1,
  136.         RunStart    = 0;
  137.     BYTE    Mode        = DUMP,
  138.         LastChar,
  139.         Char;
  140.  
  141.     PackedBytes = 0;
  142.  
  143.     Buffer[0] = LastChar = Char = *Source++;
  144.  
  145.     RowSize--;
  146.  
  147.     while(RowSize--)
  148.     {
  149.         Buffer[Buffered++] = Char = *Source++;
  150.  
  151.         if(Mode)
  152.         {
  153.             if((Char != LastChar) || (Buffered - RunStart > MAXRUN))
  154.             {
  155.                 Destination    = PutRun(Destination,Buffered - 1 - RunStart,LastChar);
  156.                 Buffer[0]    = Char;
  157.                 Buffered    = 1;
  158.                 RunStart    = 0;
  159.                 Mode        = DUMP;
  160.             }
  161.         }
  162.         else
  163.         {
  164.             if(Buffered > MAXDAT)
  165.             {
  166.                 Destination    = PutDump(Destination,Buffered - 1);
  167.                 Buffer[0]    = Char;
  168.                 Buffered    = 1;
  169.                 RunStart    = 0;
  170.             }
  171.             else
  172.             {
  173.                 if(Char == LastChar)
  174.                 {
  175.                     if(Buffered - RunStart >= MINRUN)
  176.                     {
  177.                         if(RunStart)
  178.                             Destination = PutDump(Destination,(LONG)RunStart);
  179.  
  180.                         Mode = RUN;
  181.                     }
  182.                     else
  183.                     {
  184.                         if(!RunStart)
  185.                             Mode = RUN;
  186.                     }
  187.                 }
  188.                 else
  189.                     RunStart = Buffered - 1;
  190.             }
  191.         }
  192.  
  193.         LastChar = Char;
  194.     }
  195.  
  196.     if(Mode)
  197.         PutRun(Destination,Buffered - RunStart,LastChar);
  198.     else
  199.         PutDump(Destination,(LONG)Buffered);
  200.  
  201.     *SourcePtr = Source;
  202.  
  203.     return(PackedBytes);
  204. }
  205.  
  206.     /* PutANNO(struct IFFHandle *Handle):
  207.      *
  208.      *    Output `ANNO' chunk.
  209.      */
  210.  
  211. static BYTE
  212. PutANNO(struct IFFHandle *Handle)
  213. {
  214.    extern char *v;
  215.         WORD    Len;
  216.  
  217.     Len = strlen(&v[1]);
  218.  
  219.         /* Push the `ANNO' chunk on the stack. */
  220.  
  221.     if(!PushChunk(Handle,0,ID_ANNO,(long)Len))
  222.     {
  223.             /* Write the creator string. */
  224.  
  225.         if(WriteChunkBytes(Handle,&v[1],(long)Len) == Len)
  226.         {
  227.                 /* Pop the `ANNO' chunk. */
  228.  
  229.             if(!PopChunk(Handle))
  230.                 return(TRUE);
  231.         }
  232.     }
  233.  
  234.     return(FALSE);
  235. }
  236.  
  237.     /* PutBMHD():
  238.      *
  239.      *    Output `BMHD' chunk.
  240.      */
  241.  
  242. static BYTE
  243. PutBMHD(struct IFFHandle *Handle,struct Window *Window,UBYTE Compression)
  244. {
  245.     struct DisplayInfo DisplayInfo;
  246.  
  247.         /* Get the display aspect ratio. */
  248.  
  249.     if(GetDisplayInfoData(NULL,
  250.                          (APTR)&DisplayInfo,
  251.                          sizeof(struct DisplayInfo),
  252.                          DTAG_DISP,
  253.                          GetVPModeID(&Window -> WScreen -> ViewPort)))
  254.     {
  255.         BitMapHeader Header;
  256.  
  257.             /* Fill in the bitmap header. */
  258.  
  259.         Header . w            = Window -> Width;
  260.         Header . h            = Window -> Height;
  261.         Header . pageWidth        = Window /*-> WScreen*/ -> Width;
  262.         Header . pageHeight        = Window /*-> WScreen*/ -> Height;
  263.         Header . x            = Window -> LeftEdge;
  264.         Header . y            = Window -> TopEdge;
  265.         Header . nPlanes        = Window /*-> WScreen*/ -> RPort -> BitMap -> Depth;
  266.         Header . masking        = mskNone;
  267.         Header . compression        = Compression;
  268.         Header . pad1            = 0;
  269.         Header . transparentColor    = 0;
  270.         Header . xAspect        = DisplayInfo . Resolution . x;
  271.         Header . yAspect        = DisplayInfo . Resolution . y;
  272.  
  273.             /* Push the `BMHD' chunk on the stack. */
  274.  
  275.         if(!PushChunk(Handle,0,ID_BMHD,sizeof(BitMapHeader)))
  276.         {
  277.                 /* Write the bitmap header. */
  278.  
  279.             if(WriteChunkBytes(Handle,&Header,sizeof(BitMapHeader)) == sizeof(BitMapHeader))
  280.             {
  281.                     /* Pop the `BMHD' chunk. */
  282.  
  283.                 if(!PopChunk(Handle))
  284.                     return(TRUE);
  285.             }
  286.         }
  287.     }
  288.  
  289.     return(FALSE);
  290. }
  291.  
  292.     /* PutCMAP(struct IFFHandle *Handle,struct ViewPort *VPort):
  293.      *
  294.      *    Output `CMAP' chunk, only 4-bit colour registers
  295.      *    are supported so far.
  296.      */
  297.  
  298. static BYTE
  299. PutCMAP(struct IFFHandle *Handle,struct ViewPort *VPort)
  300. {
  301.         /* Push the `CMAP' chunk on the stack. */
  302.  
  303.     if(!PushChunk(Handle,0,ID_CMAP,3 * VPort -> ColorMap -> Count))
  304.     {
  305.         ColorRegister    Colour;
  306.         LONG        i;
  307.         ULONG        Value,
  308.                 R,G,B;
  309.  
  310.             /* Read and convert all the
  311.              * ColorMap entries (4 bit colour
  312.              * components only).
  313.              */
  314.  
  315.         for(i = 0 ; i < VPort -> ColorMap -> Count ; i++)
  316.         {
  317.                 /* Read colour value. */
  318.  
  319.             Value = GetRGB4(VPort -> ColorMap,i);
  320.  
  321.                 /* Split the value into components. */
  322.  
  323.             R = (Value >> 8) & 0xF;
  324.             G = (Value >> 4) & 0xF;
  325.             B = (Value     ) & 0xF;
  326.  
  327.                 /* Store the colour components. */
  328.  
  329.             Colour . red    = (R << 4) | R;
  330.             Colour . green    = (G << 4) | G;
  331.             Colour . blue    = (B << 4) | B;
  332.  
  333.                 /* Write the colours. */
  334.  
  335.             if(WriteChunkBytes(Handle,&Colour,3) != 3)
  336.                 return(FALSE);
  337.         }
  338.  
  339.             /* Pop the `CMAP' chunk. */
  340.  
  341.         if(!PopChunk(Handle))
  342.             return(TRUE);
  343.     }
  344.  
  345.     return(FALSE);
  346. }
  347.  
  348.     /* PutCAMG(struct IFFHandle *Handle,struct ViewPort *VPort):
  349.      *
  350.      *    Output `CAMG' chunk.
  351.      */
  352.  
  353. static BYTE
  354. PutCAMG(struct IFFHandle *Handle,struct ViewPort *VPort)
  355. {
  356.     if(!PushChunk(Handle,0,ID_CAMG,sizeof(ULONG)))
  357.     {
  358.         ULONG ViewModes = GetVPModeID(VPort),ulongsize = sizeof(ULONG);
  359.  
  360.         if(WriteChunkBytes(Handle,&ViewModes,ulongsize) == ulongsize)
  361.         {
  362.             if(!PopChunk(Handle))
  363.                 return(TRUE);
  364.         }
  365.     }
  366.  
  367.     return(FALSE);
  368. }
  369.  
  370.     /* PutBODY(struct IFFHandle *Handle)
  371.      *
  372.      *    Output `BODY' chunk.
  373.      */
  374.  
  375. static BYTE
  376. PutBODY(struct IFFHandle *Handle,struct BitMap *BitMap,UBYTE Compression)
  377. {
  378.     BYTE Success = FALSE;
  379.  
  380.     PLANEPTR *Planes;
  381.  
  382.         /* Allocate temporary bitplane pointers. */
  383.  
  384.     if(Planes = (PLANEPTR *)MyAllocVec(BitMap -> Depth * sizeof(PLANEPTR *),MEMF_ANY | MEMF_CLEAR, NO_KILL))
  385.     {
  386.         register LONG i;
  387.  
  388.             /* Copy the bitplane pointers. */
  389.  
  390.         for(i = 0 ; i < BitMap -> Depth ; i++)
  391.             Planes[i] = BitMap -> Planes[i];
  392.  
  393.             /* Are we to compress the data? */
  394.  
  395.         if(Compression == cmpByteRun1)
  396.         {
  397.             PLANEPTR PackBuffer;
  398.  
  399.                 /* Allocate line compression buffer. */
  400.  
  401.             if(PackBuffer = (PLANEPTR)MyAllocVec(BitMap -> BytesPerRow * 2,MEMF_ANY, NO_KILL))
  402.             {
  403.                     /* Push the `BODY' chunk on the stack. */
  404.  
  405.                 if(!PushChunk(Handle,0,ID_BODY,IFFSIZE_UNKNOWN))
  406.                 {
  407.                     register LONG    PackedBytes,
  408.                             j;
  409.  
  410.                         /* So far, we are quite successful,
  411.                          * any write access to fail will
  412.                          * cause `Success' to drop to FALSE.
  413.                          */
  414.  
  415.                     Success = TRUE;
  416.  
  417.                         /* Compress all the rows. */
  418.  
  419.                     for(i = 0 ; Success && i < BitMap -> Rows ; i++)
  420.                     {
  421.                             /* Compress all the planes. */
  422.  
  423.                         for(j = 0 ; Success && j < BitMap -> Depth ; j++)
  424.                         {
  425.                                 /* Do the compression. */
  426.  
  427.                             PackedBytes = PackRow(&Planes[j],PackBuffer,(LONG)BitMap -> BytesPerRow);
  428.  
  429.                                 /* Write the compressed data. */
  430.  
  431.                             if(WriteChunkBytes(Handle,PackBuffer,PackedBytes) != PackedBytes)
  432.                                 Success = FALSE;
  433.                         }
  434.                     }
  435.  
  436.                         /* Pop the `BODY' chunk. */
  437.  
  438.                     if(PopChunk(Handle))
  439.                         Success = FALSE;
  440.                 }
  441.  
  442.                     /* Free the line compression buffer. */
  443.  
  444.                 MyFreeVec(PackBuffer);
  445.             }
  446.         }
  447.         else
  448.         {
  449.                 /* Push the `BODY' chunk on the stack. */
  450.  
  451.             if(!PushChunk(Handle,0,ID_BODY,IFFSIZE_UNKNOWN))
  452.             {
  453.                 register LONG j;
  454.  
  455.                     /* So far, we are quite successful,
  456.                      * any write access to fail will
  457.                      * cause `Success' to drop to FALSE.
  458.                      */
  459.  
  460.                 Success = TRUE;
  461.  
  462.                     /* Compress all the rows. */
  463.  
  464.                 for(i = 0 ; Success && i < BitMap -> Rows ; i++)
  465.                 {
  466.                         /* Compress all the planes. */
  467.  
  468.                     for(j = 0 ; Success && j < BitMap -> Depth ; j++)
  469.                     {
  470.                             /* Write the row. */
  471.  
  472.                         if(WriteChunkBytes(Handle,Planes[j],(long)BitMap -> BytesPerRow) != BitMap -> BytesPerRow)
  473.                             Success = FALSE;
  474.                         else
  475.                             Planes[j] += BitMap -> BytesPerRow;
  476.                     }
  477.                 }
  478.  
  479.                     /* Pop the `BODY' chunk. */
  480.  
  481.                 if(PopChunk(Handle))
  482.                     Success = FALSE;
  483.             }
  484.         }
  485.  
  486.             /* Free the temporary bitplane pointers. */
  487.  
  488.         MyFreeVec(Planes);
  489.     }
  490.  
  491.         /* Return the result. */
  492.  
  493.     return(Success);
  494. }
  495.  
  496.     /* SaveWindow(STRPTR Name,struct Window *Window):
  497.      *
  498.      *    Save the contents of a window to a file.
  499.      */
  500.  
  501. static BYTE
  502. SaveWindow(STRPTR Name,struct Window *Window)
  503. {
  504.     struct RastPort        *RPort;
  505.     BYTE             Success = FALSE,
  506.                  NewFile = FALSE;
  507.  
  508.     if(IFFParseBase = OpenLibrary((STRPTR)"iffparse.library",0))
  509.    {
  510.            /* Allocate a dummy rastport, we will need only
  511.             * to copy the contents of the window into the
  512.             * bitmap.
  513.             */
  514.  
  515.        if(RPort = (struct RastPort *)MyAllocVec(sizeof(struct RastPort),MEMF_ANY, NO_KILL))
  516.        {
  517.            struct BitMap *BitMap;
  518.  
  519.                /* Initialize the rastport with defaults. */
  520.  
  521.            InitRastPort(RPort);
  522.  
  523.                /* Allocate a bitmap. */
  524.  
  525.            if(BitMap = (struct BitMap *)MyAllocVec(sizeof(struct BitMap),MEMF_ANY, NO_KILL))
  526.            {
  527.                WORD i;
  528.  
  529.                    /* Put it into the rastport. */
  530.  
  531.                RPort -> BitMap = BitMap;
  532.  
  533.                    /* Initialize it with the window dimensions. */
  534.  
  535.                /*
  536.                 * An dieser Stelle ist der RastPort des Fensters
  537.                 * zu nehmen, NICHT der des Screens, zu dem das
  538.                 * Fenster gehört!
  539.                 */
  540.                InitBitMap(BitMap,
  541. /*                       (long)Window -> WScreen -> RastPort . BitMap -> Depth,*/
  542.                        (long)Window -> RPort -> BitMap -> Depth,
  543.                        (long)(Window -> Width),
  544.                        (long)Window -> Height);
  545.  
  546.                    /* Flag success so any allocation
  547.                     * to fail in the bitplane allocation
  548.                     * loop will indicate failure.
  549.                     */
  550.  
  551.                Success = TRUE;
  552.  
  553.                    /* Allocate all the bitplanes necessary. */
  554.  
  555.                for(i = 0 ; Success && i < BitMap -> Depth ; i++)
  556.                {
  557.                    if(!(BitMap -> Planes[i] = AllocRaster((long)Window -> Width,(long)Window -> Height)))
  558.                        Success = FALSE;
  559.                }
  560.  
  561.                    /* Did we get all the planes we wanted? */
  562.  
  563.                if(Success)
  564.                {
  565.                    struct IFFHandle *Handle;
  566.  
  567.                        /* Copy the window contents to the
  568.                         * local bitmap.
  569.                         */
  570.                if(NOT(Window->Flags & WFLG_BACKDROP))
  571.                   WindowToFront(Window);
  572.  
  573.                Delay(10);
  574.  
  575.                   /*
  576.                    * ClipBlit() arbeitet nicht korrekt! Ich habe
  577.                    * die Routine durch BltBitMap() ersetzt
  578.                    */
  579.                /*
  580.                 * ClipBlit(Window -> RPort,0,0,RPort,0,0,(long)Window -> Width,(long)Window -> Height,0xC0);
  581.                 */
  582.  
  583.                BltBitMap(Window->RPort->BitMap,
  584.                          (long)Window -> LeftEdge,(long)Window -> TopEdge,BitMap,
  585.                          0,0,(long)Window -> Width,(long)Window -> Height,0xC0,0xFF,NULL);
  586.  
  587.                        /* Reset the success indicator. */
  588.  
  589.                    Success = FALSE;
  590.  
  591.                        /* Allocate an iff handle. */
  592.  
  593.                    if(Handle = AllocIFF())
  594.                    {
  595.                            /* Open a file for write access. */
  596.  
  597.                        if(Handle -> iff_Stream = Open(Name,MODE_NEWFILE))
  598.                        {
  599.                                /* Remember that we succeeded
  600.                                 * in creating a new file.
  601.                                 */
  602.  
  603.                            NewFile = TRUE;
  604.  
  605.                                /* Tell iffparse.library that it's
  606.                                 * a plain AmigaDOS file handle.
  607.                                 */
  608.  
  609.                            InitIFFasDOS(Handle);
  610.  
  611.                                /* Open the file for writing. */
  612.  
  613.                            if(!OpenIFF(Handle,IFFF_WRITE))
  614.                            {
  615.                                    /* Push parent chunk on the
  616.                                     * stack.
  617.                                     */
  618.  
  619.                                if(!PushChunk(Handle,ID_ILBM,ID_FORM,IFFSIZE_UNKNOWN))
  620.                                {
  621.                                        /* Output all the chunk data. */
  622.  
  623.                                    if(PutANNO(Handle))
  624.                                    {
  625.                                        UBYTE Compression;
  626.  
  627.                                            /* Don't compress the bitmap if
  628.                                             * isn't really worth it.
  629.                                             */
  630.                                        if(BitMap -> BytesPerRow > 4)
  631.                                            Compression = cmpByteRun1;
  632.                                        else
  633.                                            Compression = cmpNone;
  634.  
  635.                                        if(PutBMHD(Handle,Window,Compression))
  636.                                        {
  637.                                            if(PutCMAP(Handle,&Window -> WScreen -> ViewPort))
  638.                                            {
  639.                                                if(PutCAMG(Handle,&Window -> WScreen -> ViewPort))
  640.                                                {
  641.                                                    if(PutBODY(Handle,BitMap,Compression))
  642.                                                    {
  643.                                                            /* Pop the parent chunk
  644.                                                             * from the stack.
  645.                                                             */
  646.  
  647.                                                        if(!PopChunk(Handle))
  648.                                                            Success = TRUE;
  649.                                                    }
  650.                                                }
  651.                                            }
  652.                                        }
  653.                                    }
  654.                                }
  655.  
  656.                                    /* Close the iff handle. */
  657.  
  658.                                CloseIFF(Handle);
  659.                            }
  660.  
  661.                                /* Close the file. */
  662.  
  663.                            if(!Close(Handle -> iff_Stream))
  664.                                Success = FALSE;
  665.                        }
  666.  
  667.                            /* Free the iff handle. */
  668.  
  669.                        FreeIFF(Handle);
  670.                    }
  671.                }
  672.  
  673.                    /* Free all bitplanes. */
  674.  
  675.                for(i = 0 ; i < BitMap -> Depth ; i++)
  676.                {
  677.                    if(BitMap -> Planes[i])
  678.                        FreeRaster(BitMap -> Planes[i],(long)Window -> Width,(long)Window -> Height);
  679.                }
  680.  
  681.                    /* Free the bitmap. */
  682.  
  683.                MyFreeVec(BitMap);
  684.            }
  685.  
  686.                /* Free the rastport. */
  687.  
  688.            MyFreeVec(RPort);
  689.        }
  690.  
  691.            /* If successful, clear the `executable' bit. */
  692.  
  693.        if(Success)
  694.            SetProtection(Name,FIBF_EXECUTE);
  695.        else
  696.        {
  697.                /* Delete the remains of the file. */
  698.  
  699.            if(NewFile)
  700.                DeleteFile(Name);
  701.        }
  702.  
  703.       CloseLibrary(IFFParseBase);
  704.    }
  705.    else
  706.       Success = FALSE;
  707.  
  708.         /* Return the result. */
  709.  
  710.     return(Success);
  711. }
  712.  
  713. struct winlist
  714. {
  715.    struct Node node;
  716.    struct Window *win;
  717.    char name[MAXFULLNAME];
  718. } *windows = NULL;
  719.  
  720. struct List WinList;
  721.  
  722. enum
  723. {
  724.    GD_WindowsLVGad,
  725.    GD_SaveIFFGad,
  726.    GD_ResetWinGad
  727. };
  728.  
  729. #define SaveAWindow_CNT 3
  730.  
  731. static struct Window         *SaveAWindowWnd = NULL;
  732. static struct Gadget         *SaveAWindowGList = NULL;
  733. static struct Gadget         *SaveAWindowGadgets[3];
  734. static UWORD                  SaveAWindowLeft = 178;
  735. static UWORD                  SaveAWindowTop = 38;
  736. static UWORD                  SaveAWindowWidth = 258;
  737. static UWORD                  SaveAWindowHeight = 121;
  738. static UBYTE                 *SaveAWindowWdt = (UBYTE *)NAME " " VERSION " - Save window";
  739.  
  740. static UWORD SaveAWindowGTypes[] = {
  741.     LISTVIEW_KIND,
  742.     BUTTON_KIND,
  743.     BUTTON_KIND
  744. };
  745.  
  746. static struct NewGadget SaveAWindowNGad[] = {
  747.     8, 18, 241, 80, (UBYTE *)"Windows", NULL, GD_WindowsLVGad, PLACETEXT_ABOVE, NULL, NULL,
  748.     8, 103, 113, 13, (UBYTE *)"IFF File", NULL, GD_SaveIFFGad, PLACETEXT_IN, NULL, NULL,
  749.     128, 103, 121, 13, (UBYTE *)"Rescan windows", NULL, GD_ResetWinGad, PLACETEXT_IN, NULL, NULL
  750. };
  751.  
  752. static ULONG *SaveAWindowGTags[] = {
  753.     (ULONG *)(GTLV_ShowSelected), (ULONG *)NULL,(ULONG *)(GTLV_Labels), (ULONG *)&WinList, (ULONG *)(TAG_DONE),
  754.     (ULONG *)(TAG_DONE),
  755.     (ULONG *)(TAG_DONE)
  756. };
  757.  
  758.    /*
  759.     * OpenSaveAWindowWindow() öffnet ein Fenster mit einem
  760.     * ListView und zwei Gadgets zu Auswahl eines zu speichernden
  761.     * Fensters
  762.     */
  763. static int
  764. OpenSaveAWindowWindow( void )
  765. {
  766.     struct NewGadget    ng;
  767.     struct Gadget    *g;
  768.     UWORD        lc, tc;
  769.     UWORD        wleft = SaveAWindowLeft, wtop = SaveAWindowTop, ww, wh;
  770.    int gl[] = {GD_WindowsLVGad};
  771.  
  772.     ComputeFont( Scr,SaveAWindowWidth, SaveAWindowHeight );
  773.  
  774.     ww = ComputeX( SaveAWindowWidth );
  775.     wh = ComputeY( SaveAWindowHeight );
  776.  
  777.     if (( wleft + ww + OffX + Scr->WBorRight ) > Scr->Width )
  778.       wleft = Scr->Width - ww;
  779.     if (( wtop + wh + OffY + Scr->WBorBottom ) > Scr->Height )
  780.       wtop = Scr->Height - wh;
  781.  
  782.    ww = compute((UWORD) (OffX + Scr->WBorRight), FontX, (int)SaveAWindowWidth);
  783.    wh = compute((UWORD) (OffY + Scr->WBorBottom), FontY, (int)SaveAWindowHeight);
  784.  
  785.    CenterWindow(Scr, &wtop, &wleft, ww, wh);
  786.  
  787.     if ( ! ( g = CreateContext( &SaveAWindowGList )))
  788.         return( 1L );
  789.  
  790.     for( lc = 0, tc = 0; lc < SaveAWindow_CNT; lc++ ) {
  791.  
  792.         CopyMem((char * )&SaveAWindowNGad[ lc ], (char * )&ng, (long)sizeof( struct NewGadget ));
  793.  
  794.         ng.ng_VisualInfo = VisualInfo;
  795.         ng.ng_TextAttr   = Font;
  796.         ng.ng_LeftEdge   = OffX + ComputeX( ng.ng_LeftEdge );
  797.         ng.ng_TopEdge    = OffY + ComputeY( ng.ng_TopEdge );
  798.         ng.ng_Width      = ComputeX( ng.ng_Width );
  799.         ng.ng_Height     = ComputeY( ng.ng_Height);
  800.  
  801.         SaveAWindowGadgets[ lc ] = g = CreateGadgetA((ULONG)SaveAWindowGTypes[ lc ], g, &ng, ( struct TagItem * )&SaveAWindowGTags[ tc ] );
  802.  
  803.       makelabelvisible(SaveAWindowGadgets[lc]);
  804.  
  805.         while( SaveAWindowGTags[ tc ] ) tc += 2;
  806.         tc++;
  807.  
  808.         if ( NOT g )
  809.             return( 2L );
  810.     }
  811.  
  812.     if ( ! ( SaveAWindowWnd = OpenWindowTags( NULL,
  813.                 WA_Left,    wleft,
  814.                 WA_Top,        wtop,
  815.                 WA_Width,    ww,
  816.                 WA_Height,    wh,
  817.                 WA_IDCMP,    LISTVIEWIDCMP|
  818.             BUTTONIDCMP|
  819.             IDCMP_CLOSEWINDOW|
  820.             IDCMP_VANILLAKEY|
  821.             IDCMP_REFRESHWINDOW,
  822.                 WA_Flags,    WFLG_DRAGBAR|
  823.             WFLG_DEPTHGADGET|
  824.             WFLG_CLOSEGADGET|
  825.             WFLG_SMART_REFRESH|
  826.             WFLG_ACTIVATE|
  827.             WFLG_RMBTRAP,
  828.                 WA_Gadgets,    SaveAWindowGList,
  829.                 WA_Title,    SaveAWindowWdt,
  830.             WA_PubScreenFallBack,TRUE,
  831.             WA_PubScreen, Scr,
  832.                 TAG_DONE )))
  833.     return( 4L );
  834.  
  835.    RefreshRastPort(SaveAWindowWnd,SaveAWindowGadgets,gl, 1);
  836.  
  837.    if(Flags.autofront)
  838.    {
  839.       WindowToFront(SaveAWindowWnd);
  840.       ActivateWindow(SaveAWindowWnd);
  841.    }
  842.  
  843.     return( 0L );
  844. }
  845.  
  846.    /*
  847.     * CreateWinList() erzeugt eine Liste von Fenstertiteln und
  848.     * Adressen
  849.     */
  850. static void
  851. CreateWinList(int count)
  852. {
  853.    ULONG lock;
  854.    struct Window *win;
  855.    struct Screen *scr;
  856.    char help[MAXFULLNAME];
  857.    int   i = 0;
  858.  
  859.    DPOS;
  860.    MyFreeVec(windows);
  861.  
  862.    DPOS;
  863.    windows = (struct winlist *) MyAllocVec(count * sizeof(struct winlist),
  864.                                            MEMF_ANY | MEMF_CLEAR, KILL);
  865.  
  866.    DPOS;
  867.    lock = LockIBase(NULL);
  868.  
  869.    for (scr = IntuitionBase->FirstScreen; scr && (i < count);
  870.         scr = scr->NextScreen)
  871.       for (win = scr->FirstWindow; win && (i < count);
  872.            win = win->NextWindow)
  873.       {
  874.          windows[i].node.ln_Name = windows[i].name;
  875.          windows[i].node.ln_Type = NT_USER;
  876.  
  877.          windows[i].win = win;
  878.  
  879.          if ((char *)win->Title)
  880.             strncpy(help,(char *)win->Title, MAXFULLNAME - 1);
  881.          else
  882.             help[0] = STRINGEND;
  883.  
  884.          sprintf(windows[i].name,"0x%08lx %s",windows[i].win,help);
  885.  
  886.          i++;
  887.       }
  888.  
  889.    UnlockIBase(lock);
  890.  
  891.    DPOS;
  892.    for (i = 0; i < count; i++)
  893.       AddTail(&WinList, &windows[i].node);
  894.  
  895.    return;
  896. }
  897.  
  898.    /*
  899.     * ResetWinList() erneuert die Window-Liste
  900.     */
  901. static void
  902. ResetWinList(void)
  903. {
  904.    register int cntwin;
  905.  
  906.    DPOS;
  907.    InitListView(SaveAWindowWnd,SaveAWindowGadgets[GD_WindowsLVGad],NULL,0);
  908.  
  909.    NewList(&WinList);
  910.  
  911.    cntwin = CountIntuiObjects((int)WINDOWS);
  912.    DPOS;
  913.    CreateWinList(cntwin);
  914.  
  915.    DPOS;
  916.    InitListView(SaveAWindowWnd,SaveAWindowGadgets[GD_WindowsLVGad],&WinList,0);
  917.  
  918.    DPOS;
  919.    EnableGadget(SaveAWindowWnd,SaveAWindowGadgets[GD_SaveIFFGad],FALSE);
  920.  
  921.    return;
  922. }
  923.  
  924.    /*
  925.     * SaveWindows() bietet eine Benutzeroberfläche an und
  926.     * verwaltet die Benutzereingaben
  927.     */
  928. void
  929. SaveWindows(void)
  930. {
  931.    struct IntuiMessage *message;
  932.    ULONG class,
  933.          code;
  934.    APTR  object;
  935.    struct Node *clickednode = NULL;
  936.    struct Window *printwin;
  937.    APTR  req;
  938.    int id;
  939.  
  940.    DPOS;
  941.  
  942.    Flags.quit_sw = 0;
  943.  
  944.    NewList(&WinList);
  945.  
  946.    windows = NULL;
  947.  
  948.    if (OpenASysWindow(OpenSaveAWindowWindow,NO_KILL))
  949.    {
  950.       PrintInfo("Save windows", SPEAK, 0);
  951.  
  952.       if (SysWnd)
  953.          req = LockWindow(SysWnd);
  954.  
  955.    DPOS;
  956.       ResetWinList();
  957.  
  958.    DPOS;
  959.       do
  960.       {
  961.          Wait(1L << SaveAWindowWnd->UserPort->mp_SigBit);
  962.  
  963.          while ((message = (struct IntuiMessage *)
  964.                  GT_GetIMsg(SaveAWindowWnd->UserPort)) != NULL)
  965.          {
  966.             class = message->Class;
  967.             code = message->Code;
  968.             object = message->IAddress;
  969.  
  970.             GT_ReplyIMsg(message);
  971.  
  972.             switch(class)
  973.             {
  974.                case IDCMP_CLOSEWINDOW:
  975.                   Flags.quit_sw = 1;
  976.                   break;
  977.  
  978.                case IDCMP_GADGETUP:
  979.                   id = ((struct Gadget *)object)->GadgetID;
  980.  
  981.                   switch(id)
  982.                   {
  983.                      case GD_WindowsLVGad:
  984.                         if(clickednode = GetNode(&WinList,code))
  985.                            EnableGadget(SaveAWindowWnd,SaveAWindowGadgets[GD_SaveIFFGad],
  986.                                         TRUE);
  987.  
  988.                         printwin = ((struct winlist *)clickednode)->win;
  989.  
  990.                         if(NOT(CheckWindow(printwin)))
  991.                         {
  992.                            ErrorHandle(WINDOW_ERR, FIND_FAIL, NO_KILL);
  993.                            clickednode = NULL;
  994.                            ResetWinList();
  995.                         }
  996.  
  997.                         break;
  998.  
  999.                      case GD_SaveIFFGad:
  1000.                         if(clickednode)
  1001.                         {
  1002.                            if (GetFile(SaveAWindowWnd,"RAM:",
  1003.                                        "RSys-Window.IFF","#?.IFF",
  1004.                                        "Select IFF-File for saving Window",
  1005.                                        "Save"))
  1006.                            {
  1007.                               printwin = ((struct winlist *)clickednode)->win;
  1008.  
  1009.                               if(CheckWindow(printwin))
  1010.                               {
  1011.                                  if(NOT(SaveWindow((STRPTR)_fullpath,
  1012.                                                    printwin)))
  1013.                                     ErrorHandle(FILE_ERR, WRITE_FAIL,NO_KILL);
  1014.                               }
  1015.                               else
  1016.                                  ErrorHandle(WINDOW_ERR, FIND_FAIL, NO_KILL);
  1017.  
  1018.                               ResetWinList();
  1019.                            }
  1020.                         }
  1021.                         break;
  1022.  
  1023.                      case GD_ResetWinGad:
  1024.                         clickednode = NULL;
  1025.                         ResetWinList();
  1026.                         break;
  1027.                   }
  1028.                   break;
  1029.  
  1030.                case IDCMP_VANILLAKEY:
  1031.                   if((char)code == ESC)
  1032.                      Flags.quit_sw = 1;
  1033.                   break;
  1034.             }
  1035.          }
  1036.       }
  1037.       while (NOT(Flags.quit_sw));
  1038.  
  1039.       CloseASysWindow(&SaveAWindowWnd, &SaveAWindowGList, NULL);
  1040.  
  1041.       MyFreeVec(windows);
  1042.  
  1043.       if (SysWnd)
  1044.       {
  1045.          UnlockWindow(req);
  1046.          RefreshMainWindowPattern();
  1047.          RefreshList(LastID);
  1048.       }
  1049.    }
  1050.  
  1051.    return;
  1052. }
  1053.