#ifndef INTUITION_IMAGECLASS_H
#include <intuition/imageclass.h>
#endif

#ifndef INTUITION_GADGETCLASS_H
#include <intuition/gadgetclass.h>
#endif

#ifndef LIBRARIES_IFFPARSE_H
#include <libraries/iffparse.h>
#endif

#ifndef INTUITION_ICCLASS_H
#include <intuition/icclass.h>
#endif

#include <proto/layers.h>
#include <proto/gadtools.h>

#define MYLIB_BOOPSI

#include "xmris.h"
#include "Errors.h"
#include "ConfigScreen.h"

#include "Catalog.h"

/************************************************************************/

#define BUTTON_LEFT		0
#define BUTTON_RIGHT		1
#define BUTTON_UP		2
#define BUTTON_DOWN		3
#define SCROLLER_HORIZONTAL	4
#define SCROLLER_VERTICAL	5

/************************************************************************/

struct Line
{
  struct MinNode Node;
  /* followed by '\0'-terminated text */
};

/************************************************************************/

struct Window *ErrorWindow;
int ErrorFlag;

/************************************************************************/

static struct MinList Lines=
{
  (struct MinNode *)&Lines.mlh_Tail,NULL,(struct MinNode *)&Lines.mlh_Head
};
static WORD MaxWidth;
static UWORD LineCount;

static struct DrawInfo *DrawInfo;

static struct Gadget *Gadgets;
static struct Gadget *VerticalScroller, *HorizontalScroller;

static int UnlockScreen;

/************************************************************************/

static struct TagItem WindowTags[]=
{
  {WA_MinWidth, 0},			/* 0 */
  {WA_MinHeight, 0},			/* 1 */
  {WA_MaxWidth, ~0},			/* 2 */
  {WA_MaxHeight, ~0},			/* 3 */
  {WA_CustomScreen, (ULONG)NULL},	/* 4 */
  {WA_Width, 0},			/* 5 */
  {WA_Height, 0},			/* 6 */
  {WA_Left, ~0},			/* 7 */
  {WA_Top, ~0},				/* 8 */
  {WA_Flags, WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_CLOSEGADGET | WFLG_SIZEGADGET | WFLG_SIMPLE_REFRESH | WFLG_NEWLOOKMENUS | WFLG_SIZEBBOTTOM | WFLG_SIZEBRIGHT},
  {TAG_DONE}
};

/************************************************************************/

void CloseErrorWindow()

{
  if ((struct Screen *)WindowTags[4].ti_Data!=NULL)
    {
      if (DrawInfo!=NULL)
	{
	  if (Gadgets!=NULL)
	    {
	      if (ErrorWindow!=NULL)
		{
		  struct Menu *Menustrip;

		  if ((Menustrip=ErrorWindow->MenuStrip)!=NULL)
		    {
		      ClearMenuStrip(ErrorWindow);
		      FreeVisualInfo(GTMENU_USERDATA(Menustrip));
		      FreeMenus(Menustrip);
		    }
		  GS_WindowWakeup(ErrorWindow);
		  assert(WindowTags[5].ti_Tag==WA_Width);
		  assert(WindowTags[6].ti_Tag==WA_Height);
		  LockLayerInfo(ErrorWindow->WLayer->LayerInfo);
		  WindowTags[5].ti_Data=ErrorWindow->Width;
		  WindowTags[6].ti_Data=ErrorWindow->Height;
		  WindowTags[7].ti_Data=ErrorWindow->LeftEdge;
		  WindowTags[8].ti_Data=ErrorWindow->TopEdge;
		  UnlockLayerInfo(ErrorWindow->WLayer->LayerInfo);
		  CloseWindowSafely(ErrorWindow);
		  ErrorWindow=NULL;
		}
	      while (Gadgets!=NULL)
		{
		  struct Gadget *Next;

		  DisposeObject(Gadgets->UserData);
		  Next=Gadgets->NextGadget;
		  DisposeObject(Gadgets);
		  Gadgets=Next;
		}
	    }
	  FreeScreenDrawInfo((struct Screen *)WindowTags[4].ti_Data,DrawInfo);
	}
      if (UnlockScreen)
	{
	  UnlockPubScreen(NULL,(struct Screen *)WindowTags[4].ti_Data);
	}
      WindowTags[4].ti_Data=(ULONG)NULL;
    }
}

/************************************************************************/
/*									*/
/* Measure width of all text lines, to find maximum width		*/
/*									*/
/************************************************************************/

static void CalcMaxWidth(void)

{
  struct Line *Line;

  for (Line=(struct Line *)Lines.mlh_Head; Line->Node.mln_Succ!=NULL; Line=(struct Line *)Line->Node.mln_Succ)
    {
      WORD Width;

      Width=TextLength(ErrorWindow->RPort,(char *)(Line+1),strlen((char *)(Line+1)));
      if (Width>MaxWidth)
	{
	  MaxWidth=Width;
	}
    }
}

/************************************************************************/
/*									*/
/* Create & install the clipping region					*/
/*									*/
/************************************************************************/

static int InstallClipping(void)

{
  struct Region *Region;

  if ((Region=NewRegion())!=NULL)
    {
      struct Rectangle Rectangle;

      Rectangle.MinX=ErrorWindow->BorderLeft+ErrorWindow->RPort->TxHeight;
      Rectangle.MaxX=ErrorWindow->Width-ErrorWindow->BorderRight-ErrorWindow->RPort->TxHeight-1;
      Rectangle.MinY=ErrorWindow->BorderTop+ErrorWindow->RPort->TxHeight/2;
      Rectangle.MaxY=ErrorWindow->Height-ErrorWindow->BorderBottom-ErrorWindow->RPort->TxHeight/2-1;
      if (OrRectRegion(Region,&Rectangle))
	{
	  InstallClipRegion(ErrorWindow->WLayer,Region);
	  return TRUE;
	}
      DisposeRegion(Region);
    }
  return FALSE;
}

/************************************************************************/

static void RemoveClipping(void)

{
  DisposeRegion(InstallClipRegion(ErrorWindow->WLayer,NULL));
}

/************************************************************************/
/*									*/
/* Redraw the full window.						*/
/* This just does the rendering, no clipping!				*/
/*									*/
/************************************************************************/

static void DrawWindow(void)

{
  WORD Y, YMax, X, XMax;
  struct RastPort *RastPort;
  struct Line *Current;

  RastPort=ErrorWindow->RPort;
  YMax=ErrorWindow->Height-ErrorWindow->BorderBottom-RastPort->TxHeight/2;
  SetABPenDrMd(RastPort,DrawInfo->dri_Pens[TEXTPEN],DrawInfo->dri_Pens[BACKGROUNDPEN],JAM2);
  YMax=ErrorWindow->Height-ErrorWindow->BorderBottom-RastPort->TxHeight/2;
  Y=ErrorWindow->BorderTop+RastPort->TxHeight/2-AttrGet((Object *)VerticalScroller,PGA_Top);
  Current=(struct Line *)Lines.mlh_Head;
  while (Y<0)
    {
      assert(Current->Node.mln_Succ!=NULL);
      Current=(struct Line *)Current->Node.mln_Succ;
      Y+=RastPort->TxHeight;
    }
  X=ErrorWindow->BorderLeft+RastPort->TxHeight-AttrGet((Object *)HorizontalScroller,PGA_Top);
  XMax=ErrorWindow->Width-ErrorWindow->BorderRight-RastPort->TxHeight;
  while (Current->Node.mln_Succ!=NULL && Y<=YMax)
    {
      Move(RastPort,X,Y+RastPort->TxBaseline);
      Text(RastPort,(char *)(Current+1),strlen((char *)(Current+1)));
      if (RastPort->cp_x<=XMax)
	{
	  SetAPen(RastPort,DrawInfo->dri_Pens[BACKGROUNDPEN]);
	  RectFill(RastPort,RastPort->cp_x,Y,XMax,Y+RastPort->TxHeight-1);
	  SetAPen(RastPort,DrawInfo->dri_Pens[TEXTPEN]);
	}
      Y+=RastPort->TxHeight;
      Current=(struct Line *)Current->Node.mln_Succ;
    }
}

/************************************************************************/

static void RedrawWindow(void)

{
  LockLayer(0,ErrorWindow->WLayer);
  if (InstallClipping())
    {
      DrawWindow();
      RemoveClipping();
    }
  UnlockLayer(ErrorWindow->WLayer);
}

/************************************************************************/

static INLINE void MakeMenu(void)

{
  static struct NewMenu NewMenu[]=
    {
      {NM_TITLE,(STRPTR)MSG_GAME_MENU,NULL,0,0,NULL},
      {NM_ITEM,(STRPTR)MSG_GAME_FLUSHERRORS_MENU,NULL,0,0,(APTR)MSG_GAME_FLUSHERRORS_MENU},
      {NM_ITEM,NM_BARLABEL,NULL,0,0,NULL},
      {NM_ITEM,(STRPTR)MSG_GAME_QUIT_MENU,NULL,0,0,(APTR)MSG_GAME_QUIT_MENU},
      {NM_TITLE,(STRPTR)MSG_CONFIG_MENU,NULL,0,0,NULL},
      {NM_ITEM,(STRPTR)MSG_CONFIG_DISPLAY_SCREEN_MENU,NULL,0,0,(APTR)MSG_CONFIG_DISPLAY_SCREEN_MENU},
      {NM_END}
    };
  struct Menu *Menustrip;

  if ((Menustrip=CreateMenustrip(NewMenu))!=NULL)
    {
      APTR VisualInfo;

      assert(WindowTags[4].ti_Tag==WA_CustomScreen);
      if ((VisualInfo=GetVisualInfoA((struct Screen *)WindowTags[4].ti_Data,NULL))!=NULL)
	{
	  static struct TagItem TagList[]=
	    {
	      {GTMN_NewLookMenus, TRUE},
	      {TAG_DONE}
	    };

	  if (LayoutMenusA(Menustrip,VisualInfo,TagList))
	    {
	      SetMenuStrip(ErrorWindow,Menustrip);
	      GTMENU_USERDATA(Menustrip)=VisualInfo;
	      return;
	    }
	  FreeVisualInfo(VisualInfo);
	}
      FreeMenus(Menustrip);
    }
}

/************************************************************************/

static struct Image *MakeImage(struct Screen *Screen, ULONG Type)

{
  return (struct Image *)NewObject(NULL,BOOPSI_sysiclass,
				   SYSIA_Which, Type,
				   SYSIA_DrawInfo, DrawInfo,
				   SYSIA_Size, (Screen->Flags & SCREENHIRES) ? SYSISIZE_MEDRES : SYSISIZE_LOWRES,
				   TAG_DONE);
}

/************************************************************************/

static void UpdateScrollers(void)

{
  SetGadgetAttrs(VerticalScroller,ErrorWindow,NULL,
		 PGA_Total, LineCount*ErrorWindow->RPort->TxHeight,
		 PGA_Visible, ErrorWindow->Height-ErrorWindow->BorderTop-ErrorWindow->BorderBottom-2*(ErrorWindow->RPort->TxHeight/2),
		 TAG_DONE);
  SetGadgetAttrs(HorizontalScroller,ErrorWindow,NULL,
		 PGA_Total, MaxWidth,
		 PGA_Visible, ErrorWindow->Width-ErrorWindow->BorderLeft-ErrorWindow->BorderRight-2*ErrorWindow->RPort->TxHeight,
		 TAG_DONE);
}

/************************************************************************/

void OpenErrorWindow(void)

{
  if (ErrorWindow==NULL)
    {
      struct Screen *Screen;

      if (display.Screen!=NULL)
	{
	  Screen=display.Screen->Screen;
	  UnlockScreen=FALSE;
	}
      else
	{
	  Screen=LockPubScreen(NULL);
	  UnlockScreen=TRUE;
	}
      assert(WindowTags[4].ti_Tag==WA_CustomScreen);
      WindowTags[4].ti_Data=(ULONG)Screen;
      if (Screen!=NULL)
	{
	  if ((DrawInfo=GetScreenDrawInfo(Screen))!=NULL)
	    {
	      struct Image *Image;

	      if ((Image=MakeImage(Screen,SIZEIMAGE))!=NULL)
		{
		  WORD SizingWidth, SizingHeight;

		  SizingWidth=Image->Width;
		  SizingHeight=Image->Height;
		  DisposeObject(Image);
		  if ((Image=MakeImage(Screen,RIGHTIMAGE))!=NULL)
		    {
		      struct Gadget *Gadget;

		      Gadgets=Gadget=NewObject(NULL,BOOPSI_buttongclass,
					       GA_RelRight, 1-(SizingWidth+Image->Width),
					       GA_RelBottom, 1-Image->Height,
					       GA_BottomBorder, TRUE,
					       GA_Image, Image,
					       GA_UserData, Image,
					       ICA_TARGET, ICTARGET_IDCMP,
					       GA_ID, BUTTON_RIGHT,
					       TAG_DONE);
		      if (Gadget!=NULL && (Image=MakeImage(Screen,LEFTIMAGE))!=NULL)
			{
			  Gadget=NewObject(NULL,BOOPSI_buttongclass,
					   GA_Previous, Gadget,
					   GA_RelRight, Gadget->LeftEdge-Image->Width,
					   GA_RelBottom, Gadget->TopEdge,
					   GA_BottomBorder, TRUE,
					   GA_Image, Image,
					   GA_UserData, Image,
					   ICA_TARGET, ICTARGET_IDCMP,
					   GA_ID, BUTTON_LEFT,
					   TAG_DONE);
			  if (Gadget!=NULL)
			    {
			      Image=NULL;
			      Gadget=NewObject(NULL,BOOPSI_propgclass,
					       GA_Previous, Gadget,
					       PGA_Freedom, FREEHORIZ,
					       PGA_NewLook, TRUE,
					       PGA_Borderless, TRUE,
					       GA_Left, Screen->WBorLeft,
					       GA_RelBottom, -SizingHeight+Screen->WBorBottom/2+2,
					       GA_RelWidth, Gadget->LeftEdge-Screen->WBorLeft-1,
					       GA_Height, SizingHeight-Screen->WBorBottom-2,
					       GA_BottomBorder, TRUE,
					       GA_UserData, NULL,
					       ICA_TARGET, ICTARGET_IDCMP,
					       GA_ID, SCROLLER_HORIZONTAL,
					       TAG_DONE);
			      HorizontalScroller=Gadget;
			      if (Gadget!=NULL && (Image=MakeImage(Screen,DOWNIMAGE))!=NULL)
				{
				  Gadget=NewObject(NULL,BOOPSI_buttongclass,
						   GA_Previous, Gadget,
						   GA_RelRight, 1-Image->Width,
						   GA_RelBottom, 1-(SizingHeight+Image->Height),
						   GA_RightBorder, TRUE,
						   GA_Image, Image,
						   GA_UserData, Image,
						   ICA_TARGET, ICTARGET_IDCMP,
						   GA_ID, BUTTON_DOWN,
						   TAG_DONE);
				  if (Gadget!=NULL && (Image=MakeImage(Screen,UPIMAGE))!=NULL)
				    {
				      Gadget=NewObject(NULL,BOOPSI_buttongclass,
						       GA_Previous, Gadget,
						       GA_RelRight, Gadget->LeftEdge,
						       GA_RelBottom, Gadget->TopEdge-Image->Height,
						       GA_RightBorder, TRUE,
						       GA_Image, Image,
						       GA_UserData, Image,
						       ICA_TARGET, ICTARGET_IDCMP,
						       GA_ID, BUTTON_UP,
						       TAG_DONE);
				      if (Gadget!=NULL)
					{
					  WORD TopBorder;

					  Image=NULL;
					  TopBorder=Screen->WBorTop+DrawInfo->dri_Font->tf_YSize+1;
					  Gadget=NewObject(NULL,BOOPSI_propgclass,
							   GA_Previous, Gadget,
							   PGA_NewLook, TRUE,
							   PGA_Borderless, TRUE,
							   PGA_Top, MAX_WORD,
							   GA_Top, TopBorder,
							   GA_RelRight, Screen->WBorRight/2+2-SizingWidth,
							   GA_RelHeight, Gadget->TopEdge-TopBorder-1,
							   GA_Width, SizingWidth-Screen->WBorRight-2,
							   GA_RightBorder, TRUE,
							   GA_UserData, NULL,
							   GA_ID, SCROLLER_VERTICAL,
							   ICA_TARGET, ICTARGET_IDCMP,
							   TAG_DONE);
					  VerticalScroller=Gadget;
					  if (Gadget!=NULL)
					    {
					      assert(WindowTags[0].ti_Tag==WA_MinWidth);
					      WindowTags[0].ti_Data=10*DrawInfo->dri_Font->tf_YSize-HorizontalScroller->Width;
					      assert(WindowTags[1].ti_Tag==WA_MinHeight);
					      WindowTags[1].ti_Data=DrawInfo->dri_Font->tf_YSize-VerticalScroller->Height;
					      if (WindowTags[1].ti_Data<3*DrawInfo->dri_Font->tf_YSize)
						{
						  WindowTags[1].ti_Data=3*DrawInfo->dri_Font->tf_YSize;
						}
					      assert(WindowTags[5].ti_Tag==WA_Width);
					      if (WindowTags[5].ti_Data<WindowTags[0].ti_Data)
						{
						  WindowTags[5].ti_Data=WindowTags[0].ti_Data+15*DrawInfo->dri_Font->tf_YSize;
						}
					      assert(WindowTags[6].ti_Tag==WA_Height);
					      if (WindowTags[6].ti_Data<WindowTags[1].ti_Data)
						{
						  WindowTags[6].ti_Data=WindowTags[1].ti_Data;
						}
					      assert(WindowTags[7].ti_Tag==WA_Left);
					      assert(WindowTags[8].ti_Tag==WA_Top);
					      if (WindowTags[7].ti_Data==~0)
						{
						  ULONG IntuiLock;

						  IntuiLock=LockIBase(0);
						  WindowTags[7].ti_Data=Screen->MouseX;
						  WindowTags[8].ti_Data=Screen->MouseY;
						  UnlockIBase(IntuiLock);
						  WindowTags[7].ti_Data-=WindowTags[5].ti_Data/2;
						  WindowTags[8].ti_Data-=WindowTags[6].ti_Data/2;
						}
					      ErrorWindow=OpenWindowTags(NULL,
									 WA_Title, GetString(MSG_ERRORS_TITLE),
									 WA_Gadgets, Gadgets,
									 TAG_MORE, WindowTags);
					      if (ErrorWindow!=NULL)
						{
						  SetFont(ErrorWindow->RPort,DrawInfo->dri_Font);
						  ErrorWindow->UserPort=&WindowPort;
						  if (ModifyIDCMP(ErrorWindow,(IDCMP_REFRESHWINDOW |
									       IDCMP_CLOSEWINDOW |
									       IDCMP_IDCMPUPDATE |
									       IDCMP_MENUPICK |
									       IDCMP_NEWSIZE)))
						    {
						      MakeMenu();
						      CalcMaxWidth();
						      LockLayer(0,ErrorWindow->WLayer);
						      if (InstallClipping())
							{
							  UpdateScrollers();
							  DrawWindow();
							  RemoveClipping();
							}
						      UnlockLayer(ErrorWindow->WLayer);
						      if (MiscState.Sleep)
							{
							  GS_WindowSleep(ErrorWindow);
							}
						      return;
						    }
						}
					    }
					}
				    }
				}
			    }
			}
		    }
		  DisposeObject(Image);
		}
	    }
	  CloseErrorWindow();
	}
    }
}

/************************************************************************/

void DisplayError(LONG TemplateID, ...)

{
  char String[ERRORSTRING_LENGTH];
  char *Error;
  ULONG Length;

  if (TemplateID!=0)
    {
      Error=GS_FormatString(GetString(TemplateID),(&TemplateID)+1,&Length,Locale);
    }
  else
    {
      Error=ErrorString(String,*(&TemplateID+1));
      Length=strlen(Error);
    }
  if (Error!=NULL)
    {
      struct Line *Line;

      if ((Line=GS_MemoryAlloc(sizeof(*Line)+Length+1))!=NULL)
	{
	  strcpy((char *)(Line+1),Error);
	  AddTail((struct List *)&Lines,(struct Node *)&Line->Node);
	  LineCount++;
	  if (ErrorWindow!=NULL)
	    {
	      if (LineCount*ErrorWindow->RPort->TxHeight+2*(ErrorWindow->RPort->TxHeight/2)+ErrorWindow->BorderTop+ErrorWindow->BorderBottom>MAX_WORD)
		{
		  GS_MemoryFree(RemHead((struct List *)&Lines));
		  CalcMaxWidth();
		}
	      else
		{
		  WORD Width;

		  Width=TextLength(ErrorWindow->RPort,(char *)(Line+1),Length);
		  if (Width>MaxWidth)
		    {
		      MaxWidth=Width;
		    }
		}
	      UpdateScrollers();
	    }
	  if (ErrorWindow!=NULL)
	    {
	      SetGadgetAttrs(VerticalScroller,ErrorWindow,NULL,PGA_Top,MAX_WORD,TAG_DONE);
	      SetGadgetAttrs(HorizontalScroller,ErrorWindow,NULL,PGA_Top,0,TAG_DONE);
	      RedrawWindow();
	    }
	  else
	    {
	      OpenErrorWindow();
	    }
	  ErrorFlag=TRUE;
	}
      if (TemplateID!=0)
	{
	  GS_MemoryFree(Error);
	}
    }
}

/************************************************************************/

void FreeErrors(void)

{
  struct Line *Line;

  while ((Line=(struct Line *)RemHead((struct List *)&Lines))!=NULL)
    {
      GS_MemoryFree(Line);
    }
}

/************************************************************************/
/*									*/
/* Currently the DOS error codes (ERROR_#?), IFF error codes		*/
/* (IFFERR_#?) and screen error codes (OSERR_#?) are supported.		*/
/*									*/
/************************************************************************/

char *ErrorString(char *String, LONG ErrorCode)

{
  if (ErrorCode<0)
    {
      /* IFF error */

      switch (ErrorCode)
	{
	case IFFERR_NOTIFF:
	  return GetString(MSG_IFFERR_NOTIFF);

	case IFFERR_NOSCOPE:
	case IFFERR_MANGLED:
	case IFFERR_SYNTAX:
	  return GetString(MSG_IFFERR_INVALIDIFF);

	case IFFERR_NOMEM:
	  ErrorCode=ERROR_NO_FREE_STORE;
	  break;

	case IFFERR_READ:
	  return GetString(MSG_IFFERR_READ);

	case IFFERR_WRITE:
	  return GetString(MSG_IFFERR_WRITE);

	case IFFERR_SEEK:
	  return GetString(MSG_IFFERR_SEEK);
	}
    }

  if (ErrorCode<100)
    {
      /* screen error code */

      switch (ErrorCode)
	{
	case OSERR_NOMEM:
	  ErrorCode=ERROR_NO_FREE_STORE;
	  break;

	case OSERR_NOCHIPMEM:
	  return GetString(MSG_OSERR_NOCHIPMEM);

	case OSERR_NOMONITOR:
	case OSERR_NOCHIPS:
	case OSERR_UNKNOWNMODE:
	case OSERR_NOTAVAILABLE:
	  return GetString(MSG_OSERR_INVALIDMODE);

#ifdef DEBUG
	case OSERR_PUBNOTUNIQUE:
	  assert(FALSE);
	  break;
#endif

	case OSERR_TOODEEP:
	  return GetString(MSG_OSERR_TOODEEP);
	}
    }

  if (ErrorCode==ERROR_UNKNOWN || ErrorCode==0)
    {
      return GetString(MSG_ERROR_UNKNOWN);
    }

  /* DOS error code */
  Fault(ErrorCode,NULL,String,ERRORSTRING_LENGTH);
  return String;
}

/************************************************************************/

void ProcessErrorWindow(struct IntuiMessage *Message)

{
  switch (Message->Class)
    {
    case IDCMP_CLOSEWINDOW:
      ReplyMsg(&Message->ExecMessage);
      CloseErrorWindow();
      return;

    case IDCMP_MENUPICK:
      {
	UWORD Selection;

	Selection=Message->Code;
	while (Selection!=MENUNULL && !global.quit)
	  {
	    struct MenuItem *Item;

	    Item=ItemAddress(ErrorWindow->MenuStrip,Selection);
	    switch ((ULONG)GTMENUITEM_USERDATA(Item))
	      {
	      case MSG_GAME_QUIT_MENU:
		global.quit=TRUE;
		break;

	      case MSG_CONFIG_DISPLAY_SCREEN_MENU:
		OpenConfigScreen();
		break;

	      case MSG_GAME_FLUSHERRORS_MENU:
		FreeErrors();
		goto Redraw;
	      }
	    Selection=Item->NextSelect;
	  }
      }
      break;

    case IDCMP_REFRESHWINDOW:
      LockLayerInfo(ErrorWindow->WLayer->LayerInfo);
      if (InstallClipping())
	{
	  BeginRefresh(ErrorWindow);
	  DrawWindow();
	  EndRefresh(ErrorWindow,TRUE);
	  RemoveClipping();
	}
      UnlockLayerInfo(ErrorWindow->WLayer->LayerInfo);
      break;

    case IDCMP_NEWSIZE:
    Redraw:
      LockLayer(0,ErrorWindow->WLayer);
      SetABPenDrMd(ErrorWindow->RPort,DrawInfo->dri_Pens[BACKGROUNDPEN],0,JAM1);
      RectFill(ErrorWindow->RPort,
	       ErrorWindow->BorderLeft,
	       ErrorWindow->BorderTop,
	       ErrorWindow->Width-ErrorWindow->BorderRight-1,
	       ErrorWindow->Height-ErrorWindow->BorderBottom-1);
      if (InstallClipping())
	{
	  UpdateScrollers();
	  DrawWindow();
	  RemoveClipping();
	}
      UnlockLayer(ErrorWindow->WLayer);
      break;

    case IDCMP_IDCMPUPDATE:
      switch (GetTagData(GA_ID,0,(struct TagItem *)Message->IAddress))
	{
	case SCROLLER_HORIZONTAL:
	case SCROLLER_VERTICAL:
	  RedrawWindow();
	  break;

	case BUTTON_LEFT:
	  {
	    WORD Top;

	    if ((Top=(WORD)AttrGet((Object *)HorizontalScroller,PGA_Top))>0)
	      {
		SetGadgetAttrs(HorizontalScroller,ErrorWindow,NULL,PGA_Top,Top-1,TAG_DONE);
		RedrawWindow();
	      }
	  }
	  break;

	case BUTTON_RIGHT:
	  SetGadgetAttrs(HorizontalScroller,ErrorWindow,NULL,PGA_Top,AttrGet((Object *)HorizontalScroller,PGA_Top)+1,TAG_DONE);
	  RedrawWindow();
	  break;

	case BUTTON_UP:
	  {
	    WORD Top;

	    if ((Top=(WORD)AttrGet((Object *)VerticalScroller,PGA_Top))>0)
	      {
		SetGadgetAttrs(VerticalScroller,ErrorWindow,NULL,PGA_Top,Top-1,TAG_DONE);
		RedrawWindow();
	      }
	  }
	  break;

	case BUTTON_DOWN:
	  SetGadgetAttrs(VerticalScroller,ErrorWindow,NULL,PGA_Top,AttrGet((Object *)VerticalScroller,PGA_Top)+1,TAG_DONE);
	  RedrawWindow();
	  break;
	}
      break;
    }
  ReplyMsg(&Message->ExecMessage);
}
