home *** CD-ROM | disk | FTP | other *** search
/ World of A1200 / World_Of_A1200.iso / programs / monitors / rsys / rsyssrc.lha / RSysSaveWindow.c < prev    next >
C/C++ Source or Header  |  1993-09-19  |  22KB  |  969 lines

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