/*
   ***************************************************************************
   *
   * Datei:
   *      RSysSaveWindow.c
   *
   * Inhalt:
   *
   *      --- Globale Routinen ---
   *
   *    void SaveWindows ( void );
   *
   *      --- Lokale  Routinen ---
   *
   *    static BYTE PutANNO ( IFFHANDLE *Handle );
   *    static BYTE PutBMHD ( IFFHANDLE *Handle , WINDOW *Window , UBYTE Compression );
   *    static BYTE PutBODY ( IFFHANDLE *Handle , BITMAP *BitMap , UBYTE Compression );
   *    static BYTE PutCAMG ( IFFHANDLE *Handle , VIEWPORT *VPort );
   *    static BYTE PutCMAP ( IFFHANDLE *Handle , VIEWPORT *VPort );
   *    static BYTE SaveWindow ( STRPTR Name , WINDOW *Window );
   *    static int OpenSaveAWindowWindow ( void );
   *    static LONG PackRow ( PLANEPTR *SourcePtr ,  PLANEPTR Destination , LONG RowSize );
   *    static PLANEPTR PutDump (  PLANEPTR Destination ,  LONG Count );
   *    static PLANEPTR PutRun (  PLANEPTR Destination , LONG Count , WORD Char );
   *    static void CreateWinList ( int count );
   *    static void ResetWinList ( void );
   *
   * Bemerkungen:
   *      Erzeugen einer IFF-Datei aus einem Window.
   *
   * Erstellungsdatum:
   *      07-Jan-93     Rolf Böhme
   *
   * Änderungen:
   *      07-Jan-93     Rolf Böhme        Erstellung
   *
   ***************************************************************************
 */

#include "RSys.h"
#include "protos.h"

 /*
  * Diese Routinen habe ich wieder mal aus der
  * "Quellen-Fundgrube" von TERM entnommen.  Danke Olaf!        Aber
  * einiges war leider falsch :-)
  */


 /* Local packer data. */

static LONG PackedBytes;
static BYTE Buffer[MAXDAT + 1];

 /* PutDump( PLANEPTR Destination, LONG Count):

  *     Output a byte dump.
  */

static PLANEPTR
PutDump (PLANEPTR Destination, LONG Count)
{
  PLANEPTR Source = (PLANEPTR) Buffer;

  *Destination++ = Count - 1;
  PackedBytes += Count + 1;

  while (Count--)
    *Destination++ = *Source++;

  return Destination;
}

 /* PutRun( PLANEPTR Destination,LONG Count,WORD Char):

  *     Output a byte run.
  */

static PLANEPTR
PutRun (PLANEPTR Destination, LONG Count, WORD Char)
{
  *Destination++ = -(Count - 1);
  *Destination++ = Char;
  PackedBytes += 2;

  return Destination;
}

 /* PackRow(PLANEPTR *SourcePtr, PLANEPTR Destination,LONG RowSize):

  *     Pack a row of bitmap data using ByteRun compression,
  *     based on the original "EA IFF 85" pack.c example code.
  */

static LONG
PackRow (PLANEPTR * SourcePtr, PLANEPTR Destination, LONG RowSize)
{
  PLANEPTR Source = *SourcePtr;

  WORD Buffered = 1, RunStart = 0;
  BYTE Mode = DUMP, LastChar, Char;

  PackedBytes = 0;

  Buffer[0] = LastChar = Char = *Source++;

  RowSize--;

  while (RowSize--)
    {
      Buffer[Buffered++] = Char = *Source++;

      if (Mode)
	{
	  if ((Char != LastChar) || (Buffered - RunStart > MAXRUN))
	    {
	      Destination = PutRun (Destination, Buffered - 1 - RunStart, LastChar);
	      Buffer[0] = Char;
	      Buffered = 1;
	      RunStart = 0;
	      Mode = DUMP;
	    }
	}
      else
	{
	  if (Buffered > MAXDAT)
	    {
	      Destination = PutDump (Destination, Buffered - 1);
	      Buffer[0] = Char;
	      Buffered = 1;
	      RunStart = 0;
	    }
	  else
	    {
	      if (Char == LastChar)
		{
		  if (Buffered - RunStart >= MINRUN)
		    {
		      if (RunStart)
			Destination = PutDump (Destination, (LONG) RunStart);

		      Mode = RUN;
		    }
		  else
		    {
		      if (!RunStart)
			Mode = RUN;
		    }
		}
	      else
		RunStart = Buffered - 1;
	    }
	}

      LastChar = Char;
    }

  if (Mode)
    PutRun (Destination, Buffered - RunStart, LastChar);
  else
    PutDump (Destination, (LONG) Buffered);

  *SourcePtr = Source;

  return PackedBytes;
}

 /* PutANNO(IFFHANDLE *Handle):

  *     Output `ANNO' chunk.
  */

static BYTE
PutANNO (IFFHANDLE * Handle)
{
  WORD Len;

  Len = strlen (&gmdv[1]);

  /* Push the `ANNO' chunk on the stack. */

  if (!PushChunk (Handle, 0, ID_ANNO, (long) Len))
    {
      /* Write the creator string. */

      if (WriteChunkBytes (Handle, &gmdv[1], (long) Len) == Len)
	{
	  /* Pop the `ANNO' chunk. */

	  if (!PopChunk (Handle))
	    return TRUE;
	}
    }

  return FALSE;
}

 /* PutBMHD():

  *     Output `BMHD' chunk.
  */

static BYTE
PutBMHD (IFFHANDLE * Handle, WINDOW * Window, UBYTE Compression)
{
  DISPLAYINFO DisplayInfo;

  /* Get the display aspect ratio. */

  if (GetDisplayInfoData (NULL,
			  (APTR) & DisplayInfo,
			  sizeof (DISPLAYINFO),
			  DTAG_DISP,
			  GetVPModeID (&Window->WScreen->ViewPort)))
    {
      RSYS_BitMapHeader Header;

      /* Fill in the bitmap header. */

      Header.w = Window->Width;
      Header.h = Window->Height;
      Header.pageWidth = Window /*-> WScreen*/ ->Width;
      Header.pageHeight = Window /*-> WScreen*/ ->Height;
      Header.x = Window->LeftEdge;
      Header.y = Window->TopEdge;
      Header.nPlanes = Window /*-> WScreen*/ ->RPort->BitMap->Depth;
      Header.masking = mskNone;
      Header.compression = Compression;
      Header.pad1 = 0;
      Header.transparentColor = 0;
      Header.xAspect = DisplayInfo.Resolution.x;
      Header.yAspect = DisplayInfo.Resolution.y;

      /* Push the `BMHD' chunk on the stack. */

      if (!PushChunk (Handle, 0, ID_BMHD, sizeof (RSYS_BitMapHeader)))
	{
	  /* Write the bitmap header. */

	  if (WriteChunkBytes (Handle, &Header, sizeof (RSYS_BitMapHeader)) == sizeof (RSYS_BitMapHeader))
	    {
	      /* Pop the `BMHD' chunk. */

	      if (!PopChunk (Handle))
		return TRUE;
	    }
	}
    }

  return FALSE;
}

 /* PutCMAP(IFFHANDLE *Handle,VIEWPORT *VPort):

  *     Output `CMAP' chunk, only 4-bit colour s
  *     are supported so far.
  */

static BYTE
PutCMAP (IFFHANDLE * Handle, VIEWPORT * VPort)
{
  /* Push the `CMAP' chunk on the stack. */

  if (!PushChunk (Handle, 0, ID_CMAP, 3 * VPort->ColorMap->Count))
    {
      RSYS_ColorRegister Colour;
      LONG i;
      ULONG Value, R, G, B;

      /* Read and convert all the
       * ColorMap entries (4 bit colour
       * components only).
       */

      for (i = 0; i < VPort->ColorMap->Count; i++)
	{
	  /* Read colour value. */

	  Value = GetRGB4 (VPort->ColorMap, i);

	  /* Split the value into components. */

	  R = (Value >> 8) & 0xF;
	  G = (Value >> 4) & 0xF;
	  B = (Value) & 0xF;

	  /* Store the colour components. */

	  Colour.red = (R << 4) | R;
	  Colour.green = (G << 4) | G;
	  Colour.blue = (B << 4) | B;

	  /* Write the colours. */

	  if (WriteChunkBytes (Handle, &Colour, 3) != 3)
	    return (FALSE);
	}

      /* Pop the `CMAP' chunk. */

      if (!PopChunk (Handle))
	return TRUE;
    }

  return FALSE;
}

 /* PutCAMG(IFFHANDLE *Handle,VIEWPORT *VPort):

  *     Output `CAMG' chunk.
  */

static BYTE
PutCAMG (IFFHANDLE * Handle, VIEWPORT * VPort)
{
  if (!PushChunk (Handle, 0, ID_CAMG, sizeof (ULONG)))
    {
      ULONG ViewModes = GetVPModeID (VPort), ulongsize = sizeof (ULONG);

      if (WriteChunkBytes (Handle, &ViewModes, ulongsize) == ulongsize)
	{
	  if (!PopChunk (Handle))
	    return TRUE;
	}
    }

  return FALSE;
}

 /* PutBODY(IFFHANDLE *Handle)

  *     Output `BODY' chunk.
  */

static BYTE
PutBODY (IFFHANDLE * Handle, BITMAP * BitMap, UBYTE Compression)
{
  BYTE Success = FALSE;

  PLANEPTR *Planes;

  /* Allocate temporary bitplane pointers. */

  if (Planes = (PLANEPTR *) MyAllocVec (BitMap->Depth * sizeof (PLANEPTR *), MEMF_ANY | MEMF_CLEAR, NO_KILL))
    {
      LONG i;

      /* Copy the bitplane pointers. */

      for (i = 0; i < BitMap->Depth; i++)
	Planes[i] = BitMap->Planes[i];

      /* Are we to compress the data? */

      if (Compression == cmpByteRun1)
	{
	  PLANEPTR PackBuffer;

	  /* Allocate line compression buffer. */

	  if (PackBuffer = (PLANEPTR) MyAllocVec (BitMap->BytesPerRow * 2, MEMF_ANY, NO_KILL))
	    {
	      /* Push the `BODY' chunk on the stack. */

	      if (!PushChunk (Handle, 0, ID_BODY, IFFSIZE_UNKNOWN))
		{
		  LONG PackedBytes, j;

		  /* So far, we are quite successful,
		   * any write access to fail will
		   * cause `Success' to drop to FALSE.
		   */

		  Success = TRUE;

		  /* Compress all the rows. */

		  for (i = 0; Success && i < BitMap->Rows; i++)
		    {
		      /* Compress all the planes. */

		      for (j = 0; Success && j < BitMap->Depth; j++)
			{
			  /* Do the compression. */

			  PackedBytes = PackRow (&Planes[j], PackBuffer, (LONG) BitMap->BytesPerRow);

			  /* Write the compressed data. */

			  if (WriteChunkBytes (Handle, PackBuffer, PackedBytes) != PackedBytes)
			    Success = FALSE;
			}
		    }

		  /* Pop the `BODY' chunk. */

		  if (PopChunk (Handle))
		    Success = FALSE;
		}

	      /* Free the line compression buffer. */

	      MyFreeVec (PackBuffer);
	    }
	}
      else
	{
	  /* Push the `BODY' chunk on the stack. */

	  if (!PushChunk (Handle, 0, ID_BODY, IFFSIZE_UNKNOWN))
	    {
	      LONG j;

	      /* So far, we are quite successful,
	       * any write access to fail will
	       * cause `Success' to drop to FALSE.
	       */

	      Success = TRUE;

	      /* Compress all the rows. */

	      for (i = 0; Success && i < BitMap->Rows; i++)
		{
		  /* Compress all the planes. */

		  for (j = 0; Success && j < BitMap->Depth; j++)
		    {
		      /* Write the row. */

		      if (WriteChunkBytes (Handle, Planes[j], (long) BitMap->BytesPerRow) != BitMap->BytesPerRow)
			Success = FALSE;
		      else
			Planes[j] += BitMap->BytesPerRow;
		    }
		}

	      /* Pop the `BODY' chunk. */

	      if (PopChunk (Handle))
		Success = FALSE;
	    }
	}

      /* Free the temporary bitplane pointers. */

      MyFreeVec (Planes);
    }

  /* Return the result. */

  return Success;
}

 /* SaveWindow(STRPTR Name,WINDOW *Window):

  *     Save the contents of a window to a file.
  */

static BYTE
SaveWindow (STRPTR Name, WINDOW * Window)
{
  RASTPORT *RPort;
  BYTE Success = FALSE, NewFile = FALSE;

  if (IFFParseBase = OpenLibrary ((STRPTR) "iffparse.library", 0))
    {
      /* Allocate a dummy rastport, we will need only
       * to copy the contents of the window into the
       * bitmap.
       */

      if (RPort = (RASTPORT *) MyAllocVec (sizeof (RASTPORT), MEMF_ANY, NO_KILL))
	{
	  BITMAP *BitMap;

	  /* Initialize the rastport with defaults. */

	  InitRastPort (RPort);

	  /* Allocate a bitmap. */

	  if (BitMap = (BITMAP *) MyAllocVec (sizeof (BITMAP), MEMF_ANY, NO_KILL))
	    {
	      WORD i;

	      /* Put it into the rastport. */

	      RPort->BitMap = BitMap;

	      /* Initialize it with the window dimensions. */

	      /*
	       * An dieser Stelle ist der RastPort des Fensters
	       * zu nehmen, NICHT der des Screens, zu dem das
	       * Fenster gehört!
	       */
	      InitBitMap (BitMap,
			  (long) Window->RPort->BitMap->Depth,
			  (long) (Window->Width),
			  (long) Window->Height);

	      /* Flag success so any allocation
	       * to fail in the bitplane allocation
	       * loop will indicate failure.
	       */

	      Success = TRUE;

	      /* Allocate all the bitplanes necessary. */

	      for (i = 0; Success && i < BitMap->Depth; i++)
		{
		  if (!(BitMap->Planes[i] = AllocRaster ((long) Window->Width, (long) Window->Height)))
		    Success = FALSE;
		}

	      /* Did we get all the planes we wanted? */

	      if (Success)
		{
		  IFFHANDLE *Handle;

		  /* Copy the window contents to the
		   * local bitmap.
		   */
		  if (NOT (Window->Flags & WFLG_BACKDROP))
		    WindowToFront (Window);

		  Delay (10);

		  /*
		   * ClipBlit() arbeitet nicht korrekt! Ich habe
		   * die Routine durch BltBitMap() ersetzt
		   */
		  /*
		   * ClipBlit(Window -> RPort,0,0,RPort,0,0,(long)Window -> Width,(long)Window -> Height,0xC0);
		   */

		  BltBitMap (Window->RPort->BitMap,
		    (long) Window->LeftEdge, (long) Window->TopEdge, BitMap,
			     0, 0, (long) Window->Width, (long) Window->Height, 0xC0, 0xFF, NULL);

		  /* Reset the success indicator. */

		  Success = FALSE;

		  /* Allocate an iff handle. */

		  if (Handle = AllocIFF ())
		    {
		      /* Open a file for write access. */

		      if (Handle->iff_Stream = Open (Name, MODE_NEWFILE))
			{
			  /* Remember that we succeeded
			   * in creating a new file.
			   */

			  NewFile = TRUE;

			  /* Tell iffparse.library that it's
			   * a plain AmigaDOS file handle.
			   */

			  InitIFFasDOS (Handle);

			  /* Open the file for writing. */

			  if (!OpenIFF (Handle, IFFF_WRITE))
			    {
			      /* Push parent chunk on the
			       * stack.
			       */

			      if (!PushChunk (Handle, ID_ILBM, ID_FORM, IFFSIZE_UNKNOWN))
				{
				  /* Output all the chunk data. */

				  if (PutANNO (Handle))
				    {
				      UBYTE Compression;

				      /* Don't compress the bitmap if
				       * isn't really worth it.
				       */
				      if (BitMap->BytesPerRow > 4)
					Compression = cmpByteRun1;
				      else
					Compression = cmpNone;

				      if (PutBMHD (Handle, Window, Compression))
					{
					  if (PutCMAP (Handle, &Window->WScreen->ViewPort))
					    {
					      if (PutCAMG (Handle, &Window->WScreen->ViewPort))
						{
						  if (PutBODY (Handle, BitMap, Compression))
						    {
						      /* Pop the parent chunk
						       * from the stack.
						       */

						      if (!PopChunk (Handle))
							Success = TRUE;
						    }
						}
					    }
					}
				    }
				}

			      /* Close the iff handle. */

			      CloseIFF (Handle);
			    }

			  /* Close the file. */

			  if (!Close (Handle->iff_Stream))
			    Success = FALSE;
			}

		      /* Free the iff handle. */

		      FreeIFF (Handle);
		    }
		}

	      /* Free all bitplanes. */

	      for (i = 0; i < BitMap->Depth; i++)
		{
		  if (BitMap->Planes[i])
		    FreeRaster (BitMap->Planes[i], (long) Window->Width, (long) Window->Height);
		}

	      /* Free the bitmap. */

	      MyFreeVec (BitMap);
	    }

	  /* Free the rastport. */

	  MyFreeVec (RPort);
	}

      /* If successful, clear the `executable' bit. */

      if (Success)
	SetProtection (Name, FIBF_EXECUTE);
      else
	{
	  /* Delete the remains of the file. */

	  if (NewFile)
	    DeleteFile (Name);
	}

      CloseLibrary (IFFParseBase);
    }
  else
    Success = FALSE;

  /* Return the result. */

  return Success;
}

RSYS_winlist *windows = NULL;

LIST WinList;

static WINDOW *SaveAWindowWnd = NULL;
static GADGET *SaveAWindowGList = NULL;
static GADGET *SaveAWindowGadgets[3];
static UWORD SaveAWindowLeft = 178;
static UWORD SaveAWindowTop = 38;
static UWORD SaveAWindowWidth = 258;
static UWORD SaveAWindowHeight = 121;
static UBYTE SaveAWindowWdt[100];	/*GMD */

static UWORD SaveAWindowGTypes[] =
{
  LISTVIEW_KIND,
  BUTTON_KIND,
  BUTTON_KIND
};

static NEWGADGET SaveAWindowNGad[] =
{
  8, 18, 241, 80, (UBYTE *) "Windows", NULL, GD_WindowsLVGad, PLACETEXT_ABOVE, NULL, NULL,
  8, 103, 113, 13, (UBYTE *) "IFF File", NULL, GD_SaveIFFGad, PLACETEXT_IN, NULL, NULL,
  128, 103, 121, 13, (UBYTE *) "Rescan windows", NULL, GD_ResetWinGad, PLACETEXT_IN, NULL, NULL
};

static ULONG *SaveAWindowGTags[] =
{
  (ULONG *) (GTLV_ShowSelected), (ULONG *) NULL, (ULONG *) (GTLV_Labels), (ULONG *) & WinList, (ULONG *) (TAG_DONE),
  (ULONG *) (TAG_DONE),
  (ULONG *) (TAG_DONE)
};

 /*
  * OpenSaveAWindowWindow() öffnet ein Fenster mit einem
  * ListView und zwei Gadgets zu Auswahl eines zu speichernden
  * Fensters
  */
static int
OpenSaveAWindowWindow (void)
{
  NEWGADGET ng;
  GADGET *g;
  UWORD lc, tc;
  UWORD wleft = SaveAWindowLeft, wtop = SaveAWindowTop, ww, wh;
  int gl[] =
  {GD_WindowsLVGad - GD_WindowsLVGad};

  AdjustWindowDimensions (Scr, SaveAWindowLeft, SaveAWindowTop, SaveAWindowWidth, SaveAWindowHeight,
			  &wleft, &wtop, &ww, &wh);

  if (!(g = CreateContext (&SaveAWindowGList)))
    return 1L;

  for (lc = 0, tc = 0; lc < SaveAWindow_CNT; lc++)
    {
      CopyMem ((char *) &SaveAWindowNGad[lc], (char *) &ng, (long) sizeof (NEWGADGET));

      ng.ng_VisualInfo = VisualInfo;
      ng.ng_TextAttr = Font;
      ng.ng_LeftEdge = OffX + ComputeX (ng.ng_LeftEdge);
      ng.ng_TopEdge = OffY + ComputeY (ng.ng_TopEdge);
      ng.ng_Width = ComputeX (ng.ng_Width);
      ng.ng_Height = ComputeY (ng.ng_Height);

      SaveAWindowGadgets[lc] = g = CreateGadgetA ((ULONG) SaveAWindowGTypes[lc], g, &ng, (TAGITEM *) & SaveAWindowGTags[tc]);

      makelabelvisible (SaveAWindowGadgets[lc]);

      while (SaveAWindowGTags[tc])
	tc += 2;
      tc++;

      if (NOT g)
	return 2L;
    }

  strcpy (SaveAWindowWdt, get_vers (" - Save window"));		/*GMD */

  if (!(SaveAWindowWnd = OpenWindowTags (NULL,
					 WA_Left, wleft,
					 WA_Top, wtop,
					 WA_Width, ww,
					 WA_Height, wh,
					 WA_IDCMP, LISTVIEWIDCMP |
					 BUTTONIDCMP |
					 IDCMP_CLOSEWINDOW |
					 IDCMP_VANILLAKEY |
					 IDCMP_REFRESHWINDOW,
					 WA_Flags, WFLG_DRAGBAR |
					 WFLG_DEPTHGADGET |
					 WFLG_CLOSEGADGET |
					 WFLG_SMART_REFRESH |
					 WFLG_ACTIVATE |
					 WFLG_RMBTRAP,
					 WA_Title, SaveAWindowWdt,
					 WA_PubScreenFallBack, TRUE,
					 WA_PubScreen, Scr,
					 TAG_DONE)))
    return 4L;

  RefreshRastPort (SaveAWindowWnd, SaveAWindowGadgets, gl, 1, FALSE, SaveAWindowGList);

  return NULL;
}

 /*
  * CreateWinList() erzeugt eine Liste von Fenstertiteln und
  * Adressen
  */
static void
CreateWinList (int count)
{
  ULONG lock;
  WINDOW *win;
  SCREEN *scr;
  char help[MAXFULLNAME];
  int i = 0;

  DPOS;
  MyFreeVec (windows);

  windows = (RSYS_winlist *) MyAllocVec (count * sizeof (RSYS_winlist),
					 MEMF_ANY | MEMF_CLEAR, KILL);

  lock = LockIBase (NULL);

  for (scr = IntuitionBase->FirstScreen; scr && (i < count); scr = scr->NextScreen)
    for (win = scr->FirstWindow; win && (i < count); win = win->NextWindow)
      {
	windows[i].node.ln_Name = windows[i].name;
	windows[i].node.ln_Type = NT_USER;

	windows[i].win = win;

	if ((char *) win->Title)
	  strncpy (help, (char *) win->Title, MAXFULLNAME - 1);
	else
	  help[0] = STRINGEND;

	sprintf (windows[i].name, "0x%08lX %s", windows[i].win, help);

	i++;
      }

  UnlockIBase (lock);

  for (i = 0; i < count; i++)
    AddTail (&WinList, &windows[i].node);

  return;
}

 /*
  * ResetWinList() erneuert die Window-Liste
  */
static void
ResetWinList (void)
{
  int cntwin;

  DPOS;
  InitListView (SaveAWindowWnd, SaveAWindowGadgets[GD_WindowsLVGad - GD_WindowsLVGad], NULL, 0);

  NewList (&WinList);

  cntwin = CountIntuiObjects ((int) WINDOWS);

  CreateWinList (cntwin);

  InitListView (SaveAWindowWnd, SaveAWindowGadgets[GD_WindowsLVGad - GD_WindowsLVGad], &WinList, 0);

  EnableGadget (SaveAWindowWnd, SaveAWindowGadgets[GD_SaveIFFGad - GD_WindowsLVGad], FALSE);

  return;
}

 /*
  * SaveWindows() bietet eine Benutzeroberfläche an und
  * verwaltet die Benutzereingaben
  */
void
SaveWindows (void)
{
  INTUIMESSAGE *message;
  ULONG class, code;
  APTR object;
  NODE *clickednode = NULL;
  WINDOW *printwin;
  int id;

  DPOS;

  HandleHelp (MN_SaveWindows);

  Flags.quit_sw = 0;

  NewList (&WinList);

  windows = NULL;

  if (OpenASysWindow (OpenSaveAWindowWindow, NO_KILL))
    {
      PrintInfo ("Save windows", SPEAK, 0);

      LockMainWindow (WIN_LOCK);

      ResetWinList ();

      do
	{
	  Wait (1L << SaveAWindowWnd->UserPort->mp_SigBit);

	  while ((message = (INTUIMESSAGE *) GT_GetIMsg (SaveAWindowWnd->UserPort)) != NULL)
	    {
	      class = message->Class;
	      code = message->Code;
	      object = message->IAddress;

	      GT_ReplyIMsg (message);

	      switch (class)
		{
		case IDCMP_CLOSEWINDOW:
		  Flags.quit_sw = 1;
		  break;

		case IDCMP_GADGETUP:
		  id = ((GADGET *) object)->GadgetID;

		  switch (id)
		    {
		    case GD_WindowsLVGad:
		      if (clickednode = GetNode (&WinList, code))
			EnableGadget (SaveAWindowWnd, SaveAWindowGadgets[GD_SaveIFFGad - GD_WindowsLVGad],
				      TRUE);

		      printwin = ((RSYS_winlist *) clickednode)->win;

		      if (NOT (CheckWindow (printwin)))
			{
			  ErrorHandle (clickednode->ln_Name, WINDOW_ERR, FIND_FAIL, NO_KILL);
			  clickednode = NULL;
			  ResetWinList ();
			}

		      break;

		    case GD_SaveIFFGad:
		      if (clickednode)
			{
			  if (GetFile (SaveAWindowWnd, "RAM:",
				       "RSys-Window.IFF", "#?.IFF",
				       "Select IFF-File for saving Window",
				       "Save"))
			    {
			      printwin = ((RSYS_winlist *) clickednode)->win;

			      if (CheckWindow (printwin))
				{
				  if (NOT (SaveWindow ((STRPTR) _fullpath, printwin)))
				    ErrorHandle (_fullpath, FILE_ERR, WRITE_FAIL, NO_KILL);
				}
			      else
				ErrorHandle (clickednode->ln_Name, WINDOW_ERR, FIND_FAIL, NO_KILL);

			      ResetWinList ();
			    }
			}
		      break;

		    case GD_ResetWinGad:
		      clickednode = NULL;
		      ResetWinList ();
		      break;
		    }
		  break;

		case IDCMP_VANILLAKEY:
		  if ((char) code == ESC)
		    Flags.quit_sw = 1;
		  break;
		}
	    }
	}
      while (NOT (Flags.quit_sw));

      CloseASysWindow (&SaveAWindowWnd, &SaveAWindowGList, NULL);

      MyFreeVec (windows);

      LockMainWindow (WIN_UNLOCK);
    }

  return;
}
