#include <stdio.h>
#include <stdlib.h>
#include <intuition/intuition.h>
#include <proto/intuition.h>
#include <pragmas/intuition_pragmas.h>
#include <libraries/gadtools.h>
#include <proto/graphics.h>
#include <proto/gadtools.h>
#include <libraries/gadtools.h>
#include <pragmas/gadtools_pragmas.h>
#include <proto/exec.h>
#include <pragmas/exec_pragmas.h>
#include <intuition/gadgetclass.h>

#include "cell_gui.h"

#ifdef GERMAN
#define STR(a,b) a
#else
#define STR(a,b) b
#endif

#define MENU_ROTATE FULLMENUNUM(1,9,NOSUB)
#define MENU_MIRROR FULLMENUNUM(1,10,NOSUB)
#define MENU_PASTE  FULLMENUNUM(1,6,NOSUB)
#define MENU_INSERT FULLMENUNUM(1,7,NOSUB)

void WriteField(char *file),WritePaste(char *file);
void ReadField(char *file),ReadPaste(char *file);
void NextStep(void);
int AllocField(void);
void FreeField(void);
void ToggleField(long x,long y,short md);
void DrawBlock(long x,long y,short col);
void RefreshField(void);
void notify(struct Window *win,char *s,...);
int InitFReq(void);
void FreeFReq(void);
UBYTE *FileRequest(struct Window *,int);
void RefreshScroller(void);
void FreePaste(void);
int GetPaste(int),PushPaste(void),PopPaste(void);
void DoPaste(void);
void Rotate90(void);
void Rotate180(void);
void Rotate270(void);
void MirrorX(void);
void MirrorY(void);

static UWORD ComputeX(UWORD);
static UWORD ComputeY(UWORD);

struct IntuitionBase *IntuitionBase=NULL;
struct Library *GadToolsBase=NULL;
struct GfxBase *GfxBase=NULL;
struct Library *AslBase=NULL;

extern struct Window *CellWnd;
extern struct Window *PasteWnd;

extern UBYTE *Paste;

extern struct IntuiMessage CellMsg;
extern struct IntuiMessage PasteMsg;

#define GD_HScroll 0
#define GD_VScroll 1

#define STATE_STOP 0
#define STATE_RUN 1

void quit(char *);
int InitScroller(void);
void FreeScroller(void);

int xwin,ywin;

int left,top,width,height,XSize,YSize;
int xoff=0,yoff=0;
int penmode=0,speed=5,state=0;

int new=1;
int markstate=0,marked=0;
int mark_left=0,mark_top=0,mark_bottom=0,mark_right=0;

#define swap_int(x,y) {int __swap;__swap=x;x=y;y=__swap;}

ULONG WaitTimeout(ULONG,ULONG,ULONG);

main()
{
   int run=1;
   IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",37);
   GadToolsBase=OpenLibrary("gadtools.library",37);
   GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",37);
   AslBase=OpenLibrary("asl.library",37);

   if(!IntuitionBase) quit(STR("Kann intuition.library V37 nicht öffnen","Cannot open intuition V37"));
   if(!GadToolsBase) quit(STR("Kann gadtools.library V37 nicht öffnen","Cannot open gadtools library V37"));
   if(!GfxBase) quit(STR("Kann graphics.library V37 nicht öffnen","Cannot open graphics.library V37"));
   if(!AslBase) quit(STR("Kann asl.library V37 nicht öffnen","Cannot open asl.library V37"));

   if(SetupScreen()) quit(STR("Kann public-Screen nicht finden","Cannot find public screen"));

   if(OpenCellWindow()) quit(STR("Kann Window nicht öffnen","Cannot open window"));

   WindowLimits(CellWnd,CellWnd->Width,CellWnd->Height,~0,~0);

   if(InitScroller()) quit(STR("Kann Scroller nicht initialisieren","Cannot initialize scrollers"));

   if(InitFReq()) quit(STR("Kann Filerequester nicht initialisieren","Cannot initialize filerequester"));

   xwin=CellWnd->Width;
   ywin=CellWnd->Height;


   while(run) {
      ULONG waitmask,mask;

      waitmask=1<<CellWnd->UserPort->mp_SigBit;
      if(PasteWnd) waitmask|=1<<PasteWnd->UserPort->mp_SigBit;

      if(state==STATE_STOP || new) {
         mask=Wait(waitmask);
      } else {
         int micros=1000000/speed-1;
         while(!(mask=WaitTimeout(waitmask,0,micros))) NextStep();
      }

      if(PasteWnd && (mask & 1<<PasteWnd->UserPort->mp_SigBit)) {
         if(!HandlePasteIDCMP()) {
            ClosePasteWindow();
            FreePaste();
            OffMenu(CellWnd,MENU_ROTATE);
            OffMenu(CellWnd,MENU_MIRROR);
            OnMenu(CellWnd,MENU_PASTE);
            OnMenu(CellWnd,MENU_INSERT);
            GT_SetGadgetAttrs(CellGadgets[GDX_Bereich],CellWnd,NULL,GA_Disabled,FALSE,TAG_DONE);
            markstate=0;
            RefreshField();
         }
      }
      if(mask & 1<<CellWnd->UserPort->mp_SigBit) {
         run=HandleCellIDCMP();
      }
   }


   quit(NULL);
}
void quit(char *err)
{
   if(err) {
      if(IntuitionBase) {
         notify(CellWnd,"%s",err);
      } else {
         fprintf(stderr,"%s",err);
      }
   }

   FreePaste();
   FreeField();
   FreeFReq();
   FreeScroller();
   CloseCellWindow();
   ClosePasteWindow();
   CloseDownScreen();

   if(AslBase) CloseLibrary(AslBase);
   if(IntuitionBase) CloseLibrary((struct Library *)IntuitionBase);
   if(GadToolsBase) CloseLibrary(GadToolsBase);
   if(GfxBase) CloseLibrary((struct Library *)GfxBase);

   exit(0);
}
int Select(struct Window *win,char *buttons,char *s,...)
{
   static struct EasyStruct reqES = {
      sizeof (struct EasyStruct),
      0,
      NULL,
      NULL,
      NULL,
   };
   ULONG iflags=NULL;

   reqES.es_TextFormat=s;
   reqES.es_GadgetFormat=buttons;
   return(EasyRequestArgs(win,&reqES,&iflags,(APTR)(((ULONG)&s)+4)));
}
int SchrittClicked( void )
{
   /* routine when gadget "Schritt" is clicked. */
   if(!new) NextStep();
   return(1);
}
int FolgeClicked( void )
{
   /* routine when gadget "" is clicked. */
   state=CellMsg.Code;
   return(1);
}
int DrahtClicked( void )
{
   /* routine when gadget "" is clicked. */
   penmode=CellMsg.Code;
   return(1);
}
int SpeedClicked( void )
{
   /* routine when gadget "Geschw." is clicked. */
   speed=CellMsg.Code;
   return(1);
}
int HScrollClicked( void )
{
   /* routine when gadget "" is clicked. */
   xoff=CellMsg.Code;
   if(!new) RefreshField();
   return(1);
}
int VScrollClicked( void )
{
   /* routine when gadget "" is clicked. */
   yoff=CellMsg.Code;
   if(!new) RefreshField();
   return(1);
}
int BereichClicked( void )
{
   /* routine when gadget "Bereich" is clicked. */
   if(!new) {
      markstate=1;
      if(marked) {
         marked=0;
         RefreshField();
      }
      GT_SetGadgetAttrs(CellGadgets[GDX_Schritt],CellWnd,NULL,GA_Disabled,TRUE,TAG_DONE);
      GT_SetGadgetAttrs(CellGadgets[GDX_Folge],CellWnd,NULL,GA_Disabled,TRUE,TAG_DONE);
      GT_SetGadgetAttrs(CellGadgets[GDX_Draht],CellWnd,NULL,GA_Disabled,TRUE,TAG_DONE);
   }

   return(1);
}
int OKClicked( void )
{
   /* routine when gadget "OK" is clicked. */
   DoPaste();
   return(0);
}
int AbbruchClicked( void )
{
   /* routine when gadget "Abbruch" is clicked. */
   return(0);
}
int CellNeu( void )
{
   /* routine when (sub)item "Neu" is selected. */

   if(!Select(CellWnd,"Yes: Continue|No: Abort","Warning: Have you saved your work yet ?")) return(1);


   GT_SetGadgetAttrs(CellGadgets[GDX_Width],CellWnd,NULL,GA_Disabled,FALSE,TAG_DONE);
   GT_SetGadgetAttrs(CellGadgets[GDX_Height],CellWnd,NULL,GA_Disabled,FALSE,TAG_DONE);
   GT_SetGadgetAttrs(CellGadgets[GDX_Schritt],CellWnd,NULL,GA_Disabled,FALSE,TAG_DONE);
   GT_SetGadgetAttrs(CellGadgets[GDX_Folge],CellWnd,NULL,GA_Disabled,FALSE,TAG_DONE);
   GT_SetGadgetAttrs(CellGadgets[GDX_Draht],CellWnd,NULL,GA_Disabled,FALSE,TAG_DONE);
   FreeField();
   new=1;
   markstate=0;
   marked=0;
   return(1);
}
int CellLaden( void )
{
   /* routine when (sub)item "Laden" is selected. */
   UBYTE *n;
   n=FileRequest(CellWnd,0);
   if(n) ReadField(n);

   return(1);
}
int CellSpeichern( void )
{
   /* routine when (sub)item "Speichern" is selected. */
   char *n;

   n=FileRequest(CellWnd,1);
   if(n) WriteField(n);

   return(1);
}
int CellEnde( void )
{
   /* routine when (sub)item "Ende" is selected. */
   return(0);
}
int CellMLoeschen( void )
{
   /* routine when (sub)item "Markierung löschen" is selected. */
   if(marked==0) {
      notify(CellWnd,STR("Kein Bereich markiert","No mark set"));
      return(1);
   }
   marked=0;
   RefreshField();
   return(1);
}
int CellMCut( void )
{
   /* routine when (sub)item "Bereich ausschneiden" is selected. */
   if(marked==0) {
      notify(CellWnd,STR("Kein Bereich markiert","No mark set"));
      return(1);
   }
   if(GetPaste(1)) notify(CellWnd,STR("Nicht genügend Speicher für Clip","Not enough memory for clip"));
   if(PushPaste()) notify(CellWnd,STR("Fehler beim Schreiben ins Clipboard","Write error to clipboard"));
   FreePaste();
   marked=0;
   RefreshField();
   return(1);
}
int CellMCopy( void )
{
   /* routine when (sub)item "Bereich kopieren" is selected. */
   if(marked==0) {
      notify(CellWnd,"Kein Bereich markiert");
      return(1);
   }
   if(GetPaste(0)) notify(CellWnd,STR("Nicht genügend Speicher für Clip","Not enough memory for clip"));
   if(PushPaste()) notify(CellWnd,STR("Fehler beim Schreiben ins Clipboard","Write error to clipboard"));
   FreePaste();
   marked=0;
   RefreshField();
   return(1);
}
int CellMPaste( void )
{
   int err;
   static char *errmsg[]={STR("Kein Speicher","No memory"),
                          STR("Kein Cell-Clip","No cell-clip"),
                          STR("Lesefehler vom Clipboard","Read error from clipboard")};

   /* routine when (sub)item "Bereich einkleben" is selected. */
   if(marked) {
      marked=0;
      RefreshField();
      GT_SetGadgetAttrs(CellGadgets[GDX_Schritt],CellWnd,NULL,GA_Disabled,FALSE,TAG_DONE);
      GT_SetGadgetAttrs(CellGadgets[GDX_Folge],CellWnd,NULL,GA_Disabled,FALSE,TAG_DONE);
      GT_SetGadgetAttrs(CellGadgets[GDX_Draht],CellWnd,NULL,GA_Disabled,FALSE,TAG_DONE);
   }
   if(err=PopPaste()) {
      notify(CellWnd,errmsg[err-1]);
      return(1);
   }
   if(Paste) {
      if(new) {
         if(GetNumber(CellGadgets[GDX_Width])<10    ||
               GetNumber(CellGadgets[GDX_Width])>10000 ||
               GetNumber(CellGadgets[GDX_Height])<10    ||
               GetNumber(CellGadgets[GDX_Height])>10000) {
            notify(CellWnd,STR("Feldgröße muß zwischen 10*10\nund 10000*10000 liegen","Fieldsize must be bewtween\n 10*10 and 10000*10000"));
            return(1);
         }

         RefreshScroller();
         if(AllocField()==0) {
            GT_SetGadgetAttrs(CellGadgets[GDX_Width],CellWnd,NULL,GA_Disabled,TRUE,TAG_DONE);
            GT_SetGadgetAttrs(CellGadgets[GDX_Height],CellWnd,NULL,GA_Disabled,TRUE,TAG_DONE);
            new=0;
         } else {
            notify(CellWnd,STR("Nicht genügend Speicher\nfür Feld %ld*%ld","Not enough memory\n for fiels %ld*%ld"),
                           (long)GetNumber(CellGadgets[GDX_Width]),
                           (long)GetNumber(CellGadgets[GDX_Height]));
         }
      }
      GT_SetGadgetAttrs(CellGadgets[GDX_Bereich],CellWnd,NULL,GA_Disabled,TRUE,TAG_DONE);
      if(OpenPasteWindow()) {
         notify(CellWnd,STR("Nicht genügend Speicher","Not enough memory"));
      }
      OnMenu(CellWnd,MENU_ROTATE);
      OnMenu(CellWnd,MENU_MIRROR);
      OffMenu(CellWnd,MENU_INSERT);
      OffMenu(CellWnd,MENU_PASTE);
      markstate=-1;
      mark_left=mark_top=0;
      RefreshField();
   } else notify(CellWnd,STR("Kein Bereich selektiert","No mark set"));
   return(1);
}
int CellMSave( void )
{
   /* routine when (sub)item "Bereich speichern" is selected. */
   char *n;
   if(marked==0) {
      notify(CellWnd,STR("Kein Bereich markiert","No mark set"));
      return(1);
   }

   n=FileRequest(CellWnd,1);
   if(n) {
      if(GetPaste(0)) notify(CellWnd,STR("Nicht genügend Speicher für Clip","Not enough memory for clip"));
      WritePaste(n);
      FreePaste();
      marked=0;
      RefreshField();
   }
   return(1);
}
int CellMInsert( void )
{
   UBYTE *n;
   /* routine when (sub)item "Bereich einkleben" is selected. */

   n=FileRequest(CellWnd,0);
   if(n) ReadPaste(n); else return(1);

   if(marked) {
      marked=0;
      RefreshField();
      GT_SetGadgetAttrs(CellGadgets[GDX_Schritt],CellWnd,NULL,GA_Disabled,FALSE,TAG_DONE);
      GT_SetGadgetAttrs(CellGadgets[GDX_Folge],CellWnd,NULL,GA_Disabled,FALSE,TAG_DONE);
      GT_SetGadgetAttrs(CellGadgets[GDX_Draht],CellWnd,NULL,GA_Disabled,FALSE,TAG_DONE);
   }
   if(Paste) {
      if(new) {
         if(GetNumber(CellGadgets[GDX_Width])<10    ||
               GetNumber(CellGadgets[GDX_Width])>10000 ||
               GetNumber(CellGadgets[GDX_Height])<10    ||
               GetNumber(CellGadgets[GDX_Height])>10000) {
            notify(CellWnd,STR("Feldgröße muß zwischen 10*10\nund 10000*10000 liegen","Fieldsize must be betweed\n10*10 and 10000*10000"));
            return(1);
         }

         RefreshScroller();
         if(AllocField()==0) {
            GT_SetGadgetAttrs(CellGadgets[GDX_Width],CellWnd,NULL,GA_Disabled,TRUE,TAG_DONE);
            GT_SetGadgetAttrs(CellGadgets[GDX_Height],CellWnd,NULL,GA_Disabled,TRUE,TAG_DONE);
            new=0;
         } else {
            notify(CellWnd,STR("Nicht genügend Speicher\nfür Feld %ld*%ld","Not enough memory for field\n%ld*%ld"),
                           (long)GetNumber(CellGadgets[GDX_Width]),
                           (long)GetNumber(CellGadgets[GDX_Height]));
         }
      }
      GT_SetGadgetAttrs(CellGadgets[GDX_Bereich],CellWnd,NULL,GA_Disabled,TRUE,TAG_DONE);
      if(OpenPasteWindow()) {
         notify(CellWnd,STR("Nicht genügend Speicher","Not enough memory"));
      }
      OnMenu(CellWnd,MENU_ROTATE);
      OnMenu(CellWnd,MENU_MIRROR);
      OffMenu(CellWnd,MENU_PASTE);
      OffMenu(CellWnd,MENU_INSERT);
      markstate=-1;
      mark_left=mark_top=0;
      RefreshField();
   } else notify(CellWnd,STR("Kein Bereich selektiert","No mark set"));
   return(1);
}
int CellRot90( void )
{
   /* routine when (sub)item "+90°" is selected. */
   Rotate90();
   RefreshField();
   return(1);
}
int CellRot180( void )
{
   /* routine when (sub)item "+180°" is selected. */
   Rotate180();
   RefreshField();
   return(1);
}
int CellRot270( void )
{
   /* routine when (sub)item "-90°" is selected. */
   Rotate270();
   RefreshField();
   return(1);
}
int CellMirrorX( void )
{
   /* routine when (sub)item "X" is selected. */
   MirrorX();
   RefreshField();
   return(1);
}
int CellMirrorY( void )
{
   /* routine when (sub)item "Y" is selected. */
   MirrorY();
   RefreshField();
   return(1);
}
int CellCloseWindow( void )
{
   /* routine for "IDCMP_CLOSEWINDOW". */
   return(0);
}
int CellMouseButtons( void )
{
   USHORT x,y;
   /* routine for "IDCMP_MOUSEBUTTONS". */

   if(CellMsg.Code!=SELECTDOWN) return(1);

   x=CellMsg.MouseX;
   y=CellMsg.MouseY;

   if(markstate==0) {

      if(x>=left && x<left+width && y>=top && y<top+height) {
         if(new) {
            if(GetNumber(CellGadgets[GDX_Width])<10    ||
                  GetNumber(CellGadgets[GDX_Width])>10000 ||
                  GetNumber(CellGadgets[GDX_Height])<10    ||
                  GetNumber(CellGadgets[GDX_Height])>10000) {
               notify(CellWnd,STR("Feldgröße muß zwischen 10*10\nund 10000*10000 liegen","Fieldsize must be between\n10*10 and 10000*10000"));
               return(1);
            }

            RefreshScroller();
            if(AllocField()==0) {
               GT_SetGadgetAttrs(CellGadgets[GDX_Width],CellWnd,NULL,GA_Disabled,TRUE,TAG_DONE);
               GT_SetGadgetAttrs(CellGadgets[GDX_Height],CellWnd,NULL,GA_Disabled,TRUE,TAG_DONE);
               new=0;
            } else {
               notify(CellWnd,STR("Nicht genügend Speicher\nfür Feld %ld*%ld","Not enough memory for field\n%ld*%ld"),
                              (long)GetNumber(CellGadgets[GDX_Width]),
                              (long)GetNumber(CellGadgets[GDX_Height]));
            }
         }
         if(!new) ToggleField(((x-left)>>3)+xoff,((y-top)>>3)+yoff,penmode);
      }
   } else if(markstate==-1) {
      if(x>=left && x<left+width && y>=top && y<top+height) {
         mark_left=((x-left)>>3)+xoff;
         mark_top=((y-top)>>3)+yoff;
         if(!new) RefreshField();
      }
   } else if(markstate==1) {
      if(x>=left && x<left+width && y>=top && y<top+height) {
         mark_left=((x-left)>>3)+xoff;
         mark_top=((y-top)>>3)+yoff;
         markstate=2;
      }
   } else {
      if(x>=left && x<left+width && y>=top && y<top+height) {
         mark_right=((x-left)>>3)+xoff;
         mark_bottom=((y-top)>>3)+yoff;
         markstate=0;
         marked=1;
         GT_SetGadgetAttrs(CellGadgets[GDX_Schritt],CellWnd,NULL,GA_Disabled,FALSE,TAG_DONE);
         GT_SetGadgetAttrs(CellGadgets[GDX_Folge],CellWnd,NULL,GA_Disabled,FALSE,TAG_DONE);
         GT_SetGadgetAttrs(CellGadgets[GDX_Draht],CellWnd,NULL,GA_Disabled,FALSE,TAG_DONE);
         if(mark_left>mark_right) swap_int(mark_left,mark_right);
         if(mark_top>mark_bottom) swap_int(mark_top,mark_bottom);

         RefreshField();
      }
   }
   return(1);
}
int PasteRot90( void )
{
   /* routine when (sub)item "+90°" is selected. */
   Rotate90();
   RefreshField();
   return(1);
}
int PasteRot180( void )
{
   /* routine when (sub)item "+180°" is selected. */
   Rotate180();
   RefreshField();
   return(1);
}
int PasteRot270( void )
{
   /* routine when (sub)item "-90°" is selected. */
   Rotate270();
   RefreshField();
   return(1);
}
int PasteMirrorX( void )
{
   /* routine when (sub)item "X" is selected. */
   MirrorX();
   RefreshField();
   return(1);
}
int PasteMirrorY( void )
{
   /* routine when (sub)item "Y" is selected. */
   MirrorY();
   RefreshField();
   return(1);
}


struct NewGadget NScroll[] = {
   100, 178, 188, 13, NULL, NULL, GD_HScroll, 0, NULL, (APTR)HScrollClicked,
   264, 5, 17, 173, NULL, NULL, GD_VScroll, 0, NULL, (APTR)VScrollClicked,
};

ULONG ScrollTags[]={
   (GTSC_Arrows), 14, (PGA_Freedom), LORIENT_HORIZ, (GA_RelVerify), TRUE, (TAG_DONE),
   (GTSC_Arrows), 14, (PGA_Freedom), LORIENT_VERT, (GA_RelVerify), TRUE,  (TAG_DONE)
};

ULONG TagBegin[]={0,7};

extern UWORD CellLeft,CellTop,CellWidth,CellHeight;
extern APTR VisualInfo;
extern struct TextAttr *Font;
extern UWORD OffX,OffY;
extern UWORD FontX, FontY;

struct Gadget *ScrollGList = NULL;
struct Gadget *ScrollGadget[2];

int InitScroller(void)
{
   int a;
   static short inited=0;
   struct Gadget   *g;

   if(!inited) {
      inited=1;

      for(a=0;a<2;a++) {
         NScroll[a].ng_VisualInfo=VisualInfo;
         NScroll[a].ng_TextAttr   = Font;
      }

      NScroll[0].ng_Height     = ComputeY( NScroll[a].ng_Height);
      NScroll[0].ng_LeftEdge   = OffX +
                              ComputeX( CellNGad[GDX_Schritt].ng_LeftEdge)+
                              ComputeX( CellNGad[GDX_Schritt].ng_Width)+4;
      NScroll[0].ng_TopEdge    = CellWnd->Height-
                                     CellWnd->BorderBottom-
                                     NScroll[0].ng_Height -4;
      NScroll[0].ng_Width      = CellWnd->Width -
                                    NScroll[0].ng_LeftEdge -
                                    CellWnd->BorderRight-4;
      NScroll[1].ng_Width      = ComputeX( NScroll[1].ng_Width );
      NScroll[1].ng_LeftEdge   = CellWnd->Width-
                                    CellWnd->BorderRight-
                                    NScroll[1].ng_Width-4;
      NScroll[1].ng_TopEdge    = OffY + ComputeY( NScroll[1].ng_TopEdge );
      NScroll[1].ng_Height     = NScroll[0].ng_TopEdge-NScroll[1].ng_TopEdge-4;

   }

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


   for(a=0;a<2;a++) {
      ScrollGadget[a]=g=CreateGadgetA(SCROLLER_KIND,g,&NScroll[a],
                                (struct TagItem *)(&ScrollTags[TagBegin[a]]));

      if(!g) return(2);
   }

   AddGList(CellWnd,ScrollGList,~0,-1,NULL);
   RefreshGadgets(ScrollGList,CellWnd,NULL);
   GT_RefreshWindow( CellWnd, NULL );

   left=NScroll[0].ng_LeftEdge+2;
   top=NScroll[1].ng_TopEdge+2;
   width=(NScroll[1].ng_LeftEdge-left-8) & 0xfff8;
   height=(NScroll[1].ng_Height-4) & 0xfff8;

   XSize=width>>3;
   YSize=height>>3;

   if(XSize>GetNumber(CellGadgets[GDX_Width])) {
      XSize=GetNumber(CellGadgets[GDX_Width]);
      width=XSize<<3;
   }

   if(YSize>GetNumber(CellGadgets[GDX_Height])) {
      YSize=GetNumber(CellGadgets[GDX_Height]);
      height=YSize<<3;
   }

   DrawBevelBox(CellWnd->RPort,left-2,top-2,width+4,height+4,
                GT_VisualInfo,VisualInfo,TAG_DONE);

   if(xoff>GetNumber(CellGadgets[GDX_Width])-XSize) {
      xoff=GetNumber(CellGadgets[GDX_Width])-XSize;
      if(xoff<0) xoff=0;
   }

   if(yoff>GetNumber(CellGadgets[GDX_Height])-YSize) {
      yoff=GetNumber(CellGadgets[GDX_Height])-YSize;
      if(yoff<0) yoff=0;
   }

   GT_SetGadgetAttrs(ScrollGadget[GD_HScroll],CellWnd,NULL,
                     GTSC_Total,GetNumber(CellGadgets[GDX_Width]),
                     GTSC_Visible,(ULONG)XSize,
                     GTSC_Top,(ULONG)xoff,TAG_DONE);

   GT_SetGadgetAttrs(ScrollGadget[GD_VScroll],CellWnd,NULL,
                     GTSC_Total,GetNumber(CellGadgets[GDX_Height]),
                     GTSC_Visible,(ULONG)YSize,
                     GTSC_Top,(ULONG)yoff,TAG_DONE);

   return( 0L );
}
void FreeScroller(void)
{
   RemoveGList(CellWnd,ScrollGList,-1);
   FreeGadgets(ScrollGList);
   ScrollGList=NULL;
}
void RefreshScroller()
{
   FreeScroller();
   SetAPen(CellWnd->RPort,0);
   RectFill(CellWnd->RPort,
               ComputeX(CellNGad[GD_Schritt].ng_LeftEdge +
                                           CellNGad[GD_Schritt].ng_Width)+2,
               CellWnd->BorderTop,
               CellWnd->Width-1,
               CellWnd->Height-1);

   RefreshWindowFrame(CellWnd);
   if(InitScroller()) quit(STR("Fataler Fehler bei Resize","Fatal error on resizing"));
}

static UWORD ComputeX( UWORD value )
{
   return(( UWORD )((( FontX * value ) + 4 ) / 8 ));
}
static UWORD ComputeY( UWORD value )
{
   return(( UWORD )((( FontY * value ) + 4 ) / 8 ));
}

int CellNewSize( void )
{
/*   int owidth,oheight;

   owidth=xwin;
   oheight=ywin;      */

   NScroll[0].ng_Width+=CellWnd->Width-xwin;
   NScroll[0].ng_TopEdge+=CellWnd->Height-ywin;
   NScroll[1].ng_LeftEdge+=CellWnd->Width-xwin;
   NScroll[1].ng_Height+=CellWnd->Height-ywin;

   RefreshScroller();

   xwin=CellWnd->Width;
   ywin=CellWnd->Height;

/*   if(XSize>GetNumber(CellGadgets[GDX_Width]) ||
      YSize>GetNumber(CellGadgets[GDX_Height]))
            SizeWindow(CellWnd,owidth-CellWnd->Width,oheight-CellWnd->Height); */

   if(!new) RefreshField();
   return(1);
}
int WidthClicked( void )
{
   /* routine when gadget "X" is clicked. */

   if(GetNumber(CellGadgets[GDX_Width])<10) {
      notify(CellWnd,STR("Minimale Breite: 10","Minimal width: 10"));
      GT_SetGadgetAttrs(CellGadgets[GDX_Width],CellWnd,NULL,
            GTIN_Number,10,TAG_DONE);
   }
   if(GetNumber(CellGadgets[GDX_Width])>10000) {
      notify(CellWnd,STR("Maximale Breite: 10000","Maximal width: 10000"));
      GT_SetGadgetAttrs(CellGadgets[GDX_Width],CellWnd,NULL,
            GTIN_Number,10000,TAG_DONE);
   }

   RefreshScroller();

   return(1);
}
int HeightClicked( void )
{
   /* routine when gadget "Y" is clicked. */

   if(GetNumber(CellGadgets[GDX_Height])<10) {
      notify(CellWnd,STR("Minimale Höhe: 10","Minimal height: 10"));
      GT_SetGadgetAttrs(CellGadgets[GDX_Height],CellWnd,NULL,
            GTIN_Number,10,TAG_DONE);
   }
   if(GetNumber(CellGadgets[GDX_Height])>10000) {
      notify(CellWnd,STR("Maximale Höhe: 10000","Maximal height: 10000"));
      GT_SetGadgetAttrs(CellGadgets[GDX_Height],CellWnd,NULL,
            GTIN_Number,10000,TAG_DONE);
   }

   RefreshScroller();

   return(1);
}


