/*ProfiPacket - packet radio terminal program
  Copyright (C) 1999  Alexander Feigl

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

  Author:

  Alexander Feigl
  Burachstraße 51

  D-88250 Weingarten

  Mail : Alexander.Feigl@gmx.de
*/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#define __near
#define __far
#define MAKE_ANSIDEFAULT
#define MAKE_ANSIDEFAULT_OP

#define Class_Name "Editor.mcc"
#define Class_IDString "$VER: Editor.mcc 16.3 (05.08.97) ©1997 Alexander Feigl\015\012"
#define Class_Version 16
#define Class_Revision 3

#define Class_SuperClass "Area.mui"

#include <libraries/mui.h>


#include "Editor.h"
#include "EditorCommon.h"
#include "EditorPrivate.h"                                                                 

extern Object *PrefDataspace;

#include <graphics/scale.h>
#include <exec/memory.h>


#include <clib/muimaster_protos.h>
#include <clib/alib_protos.h>
#include <clib/utility_protos.h>
#include <clib/graphics_protos.h>
#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>


#ifdef __GNUC__


extern void *SysBase;
extern void *IntuitionBase;
extern void *UtilityBase;
extern void *GfxBase;
extern void *MUIMasterBase;

#define NO_INLINE_STDARG
#include <inline/muimaster.h>
#include <inline/exec.h>
#include <inline/intuition.h>
#include <inline/utility.h>
#include <inline/graphics.h>
#undef MUI_CreateCustomClass
#endif

#include <devices/inputevent.h>

#include <exec/memory.h>



void memcpyfast(void *Source,void *Destination,unsigned long Bytes);


ULONG _New(struct IClass *cl, Object *obj,struct opSet *msg);
ULONG _Dispose(struct IClass *cl, Object *obj, Msg msg);
ULONG _Set(struct IClass *cl,Object *obj,Msg msg);
static ULONG _Get(struct IClass *cl,Object *obj,Msg msg);
static ULONG _Setup(struct IClass *cl,Object *obj, struct MUIP_Setup *msg);
static ULONG _Cleanup(struct IClass *cl,Object *obj,Msg msg);
static ULONG _Show(struct IClass *cl,Object *obj, struct MUIP_Setup *msg);
static ULONG _Hide(struct IClass *cl,Object *obj,Msg msg);
ULONG _AskMinMax(struct IClass *cl,Object *obj,struct MUIP_AskMinMax *msg);
ULONG _Draw(struct IClass *cl,Object *obj, struct MUIP_Draw *msg);
ULONG _HandleEvent(struct IClass *cl,Object *obj, struct MUIP_HandleInput *msg);


unsigned int WrapEditor(struct Class_Data *data,unsigned long WrapLine,
                        unsigned long WrapColumn);

void DoRefresh(struct IClass *cl,Object *obj,struct Class_Data *data);


extern void *Dispatcher_Entry();
ULONG ClassDispatcher(struct IClass *cl,Object *obj,Msg msg);

int MCCEditor_Init(void)
{
 EditorClass=MUI_CreateCustomClass(NULL,Class_SuperClass,NULL,
                                   sizeof(struct Class_Data),Dispatcher_Entry);
 if (EditorClass==NULL) return(FALSE);
 EditorClass->mcc_Class->cl_UserData=(ULONG) ClassDispatcher;
 return(TRUE);
}

void DoRefresh(struct IClass *cl,Object *obj,struct Class_Data *data)
 {
  struct EditorBuffer *tedit;
  unsigned long i;
  unsigned int firstx;
  unsigned long endx;

  if (data->Refresh==0) return;  

  if (data->ScrollLines!=0)

    {

     if (data->ScrollLines>0)
      {
       SetBPen(data->GfxRPort,MUIPEN(data->ANSIPens[0]));
       ScrollRaster(data->GfxRPort,0,-(data->ScrollLines*data->FontYSize),
                    data->GfxLeft,data->GfxTop,data->GfxRight,
                    data->GfxTop+(data->GfxLines*data->FontYSize)-1);
      }

     if (data->ScrollLines<0)
      {
       SetBPen(data->GfxRPort,MUIPEN(data->ANSIPens[0]));
       ScrollRaster(data->GfxRPort,0,-(data->ScrollLines*data->FontYSize),
                    data->GfxLeft,data->GfxTop,data->GfxRight,
                    data->GfxTop+(data->GfxLines*data->FontYSize)-1);
      }
    }

  tedit = data->Buffers[data->DisplayPage];
  if (data->Refresh==3)
   {


    if (!data->SolidBackground) DoSuperMethod(cl,obj,MUIM_DrawBackground,
                              data->GfxLeft,
                              data->GfxTop,
                              data->GfxWidth,
                              data->GfxHeight,
                              data->GfxPOffsetX,
                              data->GfxPOffsetY,
                              0);
   
    data->Refresh=2;
   }
 
  for (i=0;i<data->GfxLines;++i)
   {
    struct LineInfo linf;
    unsigned long LineY;

    firstx=(data->Refresh!=2)?TRUE:FALSE;

    endx=data->GfxLeft;

    if (data->RefreshLine[i]==-1) continue;

    if ( (data->CursorIsDisplay==TRUE) &&
         (data->CursorIsY==i) &&
         (data->CursorIsX>=data->RefreshLine[i]) )
     {
      data->CursorIsDisplay=FALSE;
     }

    LineY=(i*data->FontYSize)+data->GfxTop;

    if (tedit->BufferLineCache<=(i+tedit->HeadLine)) 
     {
      data->RefreshLine[i]=-1;
      if (data->SolidBackground)
       {
        SetAPen(data->GfxRPort,MUIPEN(data->ANSIPens[0]));
        RectFill(data->GfxRPort,data->GfxLeft,LineY,
                                data->GfxWidth+data->GfxLeft-1,
                                data->FontYSize-1+LineY);
        continue;
       }
      if (data->Refresh==2) continue;
      DoSuperMethod(cl,obj,MUIM_DrawBackground,
                           data->GfxLeft,
                           LineY,
                           data->GfxWidth,
                           data->FontYSize,
                           data->GfxPOffsetX,
                           data->GfxPOffsetY+LineY-data->GfxTop,
                           0);
      continue;
     }

    if ( (GetLineInfo(data,&linf,i+tedit->HeadLine)) == FALSE)
     {
      DisplayBeep(NULL);
      continue;
     }
    
    data->DisplayStart=data->RefreshLine[i];
    data->DisplayStop=5000;
    data->DisplayOffset=tedit->HeadColumn;
    data->DisplayXMax=data->GfxWidth;

    while ( FillDisplayCache(data,&linf) != 0 )
     {
      if (firstx==TRUE)
       {
        if (!data->SolidBackground) DoSuperMethod(cl,obj,MUIM_DrawBackground,
                               data->GfxLeft+data->DisplayX,
                               LineY,
                               data->GfxWidth-data->DisplayX,
                               data->FontYSize,
                               data->GfxPOffsetX+data->DisplayX,
                               data->GfxPOffsetY+LineY-data->GfxTop,
                               0);
        firstx=FALSE;
       }
      SetFont(data->GfxRPort,data->GfxFont);
      SetAPen(data->GfxRPort,data->DisplayAPen);
      SetBPen(data->GfxRPort,data->DisplayBPen);
      SetDrMd(data->GfxRPort,data->DisplayDrMd);
      SetSoftStyle(data->GfxRPort,0x7,data->DisplayStyle);
      Move(data->GfxRPort,data->GfxLeft+data->DisplayX,
                          LineY+data->FontBaseline);
      Text(data->GfxRPort,data->DisplayCache,data->DisplayLength);
      endx=data->DisplayX+data->GfxLeft+data->DisplayXSize;
     }


    if ( (firstx==TRUE) )
     {
      data->DisplayX=ColumnToOffset(data,&linf,data->RefreshLine[i]);
      if (data->DisplayX>=tedit->HeadColumn)
       {
        data->DisplayX-=tedit->HeadColumn;
        if (data->DisplayX<data->GfxWidth)
         {
          if (!data->SolidBackground)
                  DoSuperMethod(cl,obj,MUIM_DrawBackground,
                           data->GfxLeft+data->DisplayX,
                           LineY,
                           data->GfxWidth-data->DisplayX,
                           data->FontYSize,
                           data->GfxPOffsetX+data->DisplayX,
                           data->GfxPOffsetY+LineY-data->GfxTop,
                           0);
            else
             {
              SetAPen(data->GfxRPort,MUIPEN(data->ANSIPens[0] ));
              RectFill(data->GfxRPort,data->GfxLeft+data->DisplayX,
                       LineY,data->GfxWidth+data->GfxLeft-1,
                       LineY+data->FontYSize-1);
             }
         }
       }
     }
     else
     {
      if (data->SolidBackground)
       {
        SetAPen(data->GfxRPort,MUIPEN(data->ANSIPens[0]));
        RectFill(data->GfxRPort,endx,LineY,data->GfxWidth+data->GfxLeft-1,
                 LineY+data->FontYSize-1);
       }
     }


    data->RefreshLine[i]=-1;
   }
  

   
  while (
         (data->CursorWantDisplay!=data->CursorIsDisplay) ||
         (data->CursorRefresh==TRUE) ||
         ( (data->CursorIsDisplay==TRUE) &&
           (
            (data->CursorIsY!=(tedit->CursorLine-tedit->HeadLine)) ||
            (data->CursorIsX!=(tedit->CursorColumn))
           )
         )
        )
   {
    struct LineInfo linf;
    unsigned long LineY;
    signed long DisplayLine;
    signed long DisplayX;
    signed long DisplayY;
    signed long DisplayWidth;
    signed long DisplayHeight;
    unsigned short CType;


    if (data->CursorIsDisplay==TRUE)
     { 
      data->CursorIsDisplay=FALSE;

      /* Please blank cursor */

      if (data->CursorIsReal==FALSE) 
       {
        continue;
       }
      if ( (GetLineInfo(data,&linf,data->CursorIsY+tedit->HeadLine)) == FALSE)
       {
        DisplayBeep(NULL);
        continue;
       }

      LineY=(data->CursorIsY*data->FontYSize)+data->GfxTop;
      data->DisplayStart=data->CursorIsX;
      data->DisplayStop=data->DisplayStart;
      data->DisplayOffset=tedit->HeadColumn;
      data->DisplayXMax=data->GfxWidth-1;

      if ( FillDisplayCache(data,&linf) != 0 )
       {
        if (!data->SolidBackground)
                DoSuperMethod(cl,obj,MUIM_DrawBackground,
                      data->GfxLeft+data->DisplayX,
                      LineY,
                      data->DisplayXSize,
                      data->FontYSize,
                      data->GfxPOffsetX+data->DisplayX,
                      data->GfxPOffsetY+LineY-data->GfxTop,
                      0);
        SetFont(data->GfxRPort,data->GfxFont);
        SetAPen(data->GfxRPort,data->DisplayAPen);
        SetBPen(data->GfxRPort,data->DisplayBPen);
        SetDrMd(data->GfxRPort,data->DisplayDrMd);
        SetSoftStyle(data->GfxRPort,0x7,data->DisplayStyle);
        Move(data->GfxRPort,data->GfxLeft+data->DisplayX,
                            LineY+data->FontBaseline);
        Text(data->GfxRPort,data->DisplayCache,data->DisplayLength);
       }
       else
       {
        data->DisplayX=ColumnToOffset(data,&linf,data->CursorIsX);
        data->DisplayXSize=ColumnXSize(data,&linf,data->CursorIsX);        
        if (data->DisplayX<tedit->HeadColumn)
         {
          continue;
         }
        data->DisplayX-=tedit->HeadColumn;
        if (!data->SolidBackground)
             {  DoSuperMethod(cl,obj,MUIM_DrawBackground,
                      data->GfxLeft+data->DisplayX,
                      LineY,
                      data->DisplayXSize,
                      data->FontYSize,
                      data->GfxPOffsetX+data->DisplayX,
                      data->GfxPOffsetY+LineY-data->GfxTop,
                      0);
             }
             else
             {
              SetAPen(data->GfxRPort,MUIPEN(data->ANSIPens[0]));
              RectFill(data->GfxRPort,data->GfxLeft+data->DisplayX,
                       LineY,data->DisplayXSize+data->GfxLeft+
                       data->DisplayX-1,data->FontYSize+LineY-1);
             }
       }


  
      continue;
     }
  
    /* Please set cursor */
    
    CType=(data->InsertMode)?data->CursorInsert:data->CursorOverwr;
    DisplayLine=tedit->CursorLine-tedit->HeadLine;
    data->CursorIsX=tedit->CursorColumn;
    data->CursorIsY=DisplayLine;
    data->CursorIsDisplay=TRUE;
    data->CursorIsReal=FALSE;
    data->CursorRefresh=FALSE;
    if ( (DisplayLine<0) || (DisplayLine>=data->GfxLines) )
     {
      continue;
     };
    if ( (GetLineInfo(data,&linf,tedit->CursorLine)) == FALSE)
     {
      DisplayBeep(NULL);
      continue;
     }


    if (CType==1)
     {
        /* Non inversid h-line cursor*/

        DisplayX=ColumnToOffset(data,&linf,tedit->CursorColumn);
        DisplayWidth=ColumnXSize(data,&linf,tedit->CursorColumn);
        if (DisplayX<tedit->HeadColumn)
         {
          continue;
         }
        DisplayX-=tedit->HeadColumn;

        if ( (DisplayX+DisplayWidth) >= (data->GfxWidth) )
         {
          continue;
         }

        DisplayY=DisplayLine*data->FontYSize;
        DisplayHeight=data->FontYSize-data->FontBaseline;
        DisplayY+=data->FontBaseline;
        if (DisplayHeight==0)
         {
          DisplayHeight+=2;
          DisplayY-=2;
         } 
        DisplayX+=data->GfxLeft;
        DisplayY+=data->GfxTop;
        SetDrMd(data->GfxRPort,JAM1);
        SetAPen(data->GfxRPort,MUIPEN(data->CursorPen));
        RectFill(data->GfxRPort,DisplayX,DisplayY,DisplayX+DisplayWidth-1,
                  DisplayY+DisplayHeight-1);
        data->CursorIsReal=TRUE;

     }

    if (CType==0)
     {
        /* Inversid block cursor*/

      if ( (GetLineInfo(data,&linf,data->CursorIsY+tedit->HeadLine)) == FALSE)
       {
        DisplayBeep(NULL);
        continue;
       }

      LineY=(data->CursorIsY*data->FontYSize)+data->GfxTop;
      data->DisplayStart=data->CursorIsX;
      data->DisplayStop=data->DisplayStart;
      data->DisplayOffset=tedit->HeadColumn;
      data->DisplayXMax=data->GfxWidth-1;

      if ( FillDisplayCache(data,&linf) != 0 )
       {
        if (!data->SolidBackground)
               {DoSuperMethod(cl,obj,MUIM_DrawBackground,
                      data->GfxLeft+data->DisplayX,
                      LineY,
                      data->DisplayXSize,
                      data->FontYSize,
                      data->GfxPOffsetX+data->DisplayX,
                      data->GfxPOffsetY+LineY-data->GfxTop,
                      0);
               }

        SetFont(data->GfxRPort,data->GfxFont);
        SetBPen(data->GfxRPort,data->DisplayAPen);
        SetAPen(data->GfxRPort,data->DisplayBPen);
        SetDrMd(data->GfxRPort,JAM2);
        SetSoftStyle(data->GfxRPort,0x7,data->DisplayStyle);
        Move(data->GfxRPort,data->GfxLeft+data->DisplayX,
                            LineY+data->FontBaseline);
        Text(data->GfxRPort,data->DisplayCache,data->DisplayLength);
       }
       else
       {
        data->DisplayX=ColumnToOffset(data,&linf,data->CursorIsX);
        data->DisplayXSize=ColumnXSize(data,&linf,data->CursorIsX);
        if (data->DisplayX<tedit->HeadColumn)
         {
          continue;
         }
        data->DisplayX-=tedit->HeadColumn;
        SetAPen(data->GfxRPort,MUIPEN(data->CursorPen));
        SetDrMd(data->GfxRPort,JAM1);
        RectFill(data->GfxRPort,data->GfxLeft+data->DisplayX,LineY,
                                data->GfxLeft+data->DisplayX+data->DisplayXSize-1,
                                LineY+data->FontYSize-1);
       }
      data->CursorIsReal=TRUE;
     }

    if (CType==2)
     {
        /* Non inversid v-line cursor*/

        DisplayX=ColumnToOffset(data,&linf,tedit->CursorColumn);
        DisplayWidth=(data->FontYSize/3)+1;
        if (DisplayX<tedit->HeadColumn)
         {
          continue;
         }
        DisplayX-=tedit->HeadColumn;

        if ( (DisplayX+DisplayWidth) >= (data->GfxWidth) )
         {
          continue;
         }

        DisplayY=DisplayLine*data->FontYSize;
        DisplayHeight=data->FontYSize;
        if (DisplayHeight==0)
         {
          DisplayHeight+=2;
          DisplayY-=2;
         }
        DisplayX+=data->GfxLeft;
        DisplayY+=data->GfxTop;
        SetDrMd(data->GfxRPort,JAM1);
        SetAPen(data->GfxRPort,MUIPEN(data->CursorPen));
        RectFill(data->GfxRPort,DisplayX,DisplayY,DisplayX+DisplayWidth-1,
                  DisplayY+DisplayHeight-1);
        data->CursorIsReal=TRUE;


     }
   }
  data->Refresh=0;
  data->ScrollLines=0;
 }


void CompleteRefresh(struct Class_Data *data)
{
 unsigned long i;
 data->CursorIsDisplay=FALSE;
 for (i=0;i<128;++i)
  {
   data->RefreshLine[i]=0;
  }
 data->Refresh=3;

}


ULONG _New(struct IClass *cl, Object *obj,struct opSet *msg)
{
        struct Class_Data *data;

        if (!(obj = (Object *)DoSuperMethodA(cl, obj, (APTR ) msg)))
                return(0);

        /*** init data ***/
        data = INST_DATA(cl, obj);
        data->RootObject= (void *) obj;

        data->JobStack=NULL;


        /*** set default values ***/
       
        data->AltAsciiStatus=-1; 

        data->ValidDisplay=FALSE;
        data->CachedLine=-1;
        data->MarkStartX=-1;
        data->MarkStartY=-1;

        {
         unsigned long i;
         for (i=0;i<128;++i) data->Buffers[i]=NULL;
         for (i=0;i<128;++i)
          {
           data->RefreshLine[i]=-1;
          }

        data->Refresh=0;
        data->ScrollLines=0;

        }
        
        data->CursorIsDisplay=FALSE;
        data->CursorWantDisplay=TRUE;
        data->CursorFollow=FALSE;
        data->CursorRefresh=FALSE;

        /*** Set arguments ***/

        data->BufferSize= GetTagData(MUIA_Editor_BufferSize,4096,msg->ops_AttrList);
        data->Pages= GetTagData(MUIA_Editor_Pages,1,msg->ops_AttrList);
        data->Type=GetTagData(MUIA_Editor_EditorType,0,msg->ops_AttrList);
        data->DisplayPage=GetTagData(MUIA_Editor_ActivePage,0,msg->ops_AttrList);


        data->Markable=GetTagData(MUIA_Editor_EditorMarkable,TRUE,msg->ops_AttrList);
        data->NumLockStatus=GetTagData(MUIA_Editor_NumLockStatus,FALSE,msg->ops_AttrList);
        data->NumLock= GetTagData(MUIA_Editor_NumLock,TRUE,msg->ops_AttrList);
        data->AltAscii=GetTagData(MUIA_Editor_AltAscii,TRUE,msg->ops_AttrList);
        data->InsertMode=GetTagData(MUIA_Editor_InsertMode,TRUE,msg->ops_AttrList);
        data->FreeMoving=GetTagData(MUIA_Editor_FreeMoving,FALSE,msg->ops_AttrList);
        data->Interactive=GetTagData(MUIA_Editor_Interactive,FALSE,msg->ops_AttrList);
        data->AskInputStream=GetTagData(MUIA_Editor_AskInputStream,FALSE,msg->ops_AttrList);
        data->AskInputANSI=GetTagData(MUIA_Editor_AskInputANSI,FALSE,msg->ops_AttrList);
        data->PCFontKey=GetTagData(MUIA_Editor_PCFontKeymap,FALSE,msg->ops_AttrList);
        data->NotifyPrPa=GetTagData(MUIA_Editor_NotifyPrPa,FALSE,msg->ops_AttrList);
        

        data->MaxLines=GetTagData(MUIA_Editor_MaxLines,0,msg->ops_AttrList);
        data->Unprintable=GetTagData(MUIA_Editor_Unprintable,0xffffffff,msg->ops_AttrList);
        data->InputMask=GetTagData(MUIA_Editor_InputMask,3847,msg->ops_AttrList);


        data->LineWrap=GetTagData(MUIA_Editor_LineWrap,TRUE,msg->ops_AttrList);
        data->WordWrap=GetTagData(MUIA_Editor_WordWrap,0,msg->ops_AttrList);
        data->GarbageEditor=GetTagData(MUIA_Editor_GarbageEditor,FALSE,msg->ops_AttrList);

        data->DisableRedraw=GetTagData(MUIA_Editor_DisableRedraw,FALSE,msg->ops_AttrList);

        if (FindTagItem(MUIA_Editor_SolidBackground,msg->ops_AttrList)!=NULL)
         {
          data->SolidBackgroundForce=TRUE;
          data->SolidBackground=GetTagData(MUIA_Editor_SolidBackground,FALSE,msg->ops_AttrList);
         }
         else
         {
          data->SolidBackground=Standard_SolidBackground;
          data->SolidBackgroundForce=FALSE;
         }

        /* Handle exclusive settings */

        /* Interactive no linewrap,no wordwrap, no freemoving */

        if (data->Interactive!=FALSE)
         {
          data->FreeMoving=FALSE;
          data->LineWrap=FALSE;
          data->WordWrap=FALSE;
         }


        if ( (data->BufferSize < 1024) || (data->Pages < 1) || 
             (data->Pages > 512) || (data->Type >2))
           {
            CoerceMethod(cl,obj,OM_DISPOSE);
            return (0);
           }

        while (1)
         {
          struct EditorBuffer *edbuf;
          unsigned long i;
          unsigned short allocerror;
          allocerror=FALSE;
          for (i=0;i<data->Pages;++i)
           {
            if ( (edbuf=
                        AllocVec(sizeof(struct EditorBuffer)+
                                 data->BufferSize,
                                 MEMF_PUBLIC) ) ==NULL )
             {
              allocerror=TRUE;
              break;
             }

            data->Buffers[i]=edbuf;  
            edbuf->EditorMem=(void *) (edbuf+1);
            edbuf->BufferSize=data->BufferSize;
           
            /* Clear buffer */
          
            ClearBuffer(edbuf);
           
           }

          if (allocerror==TRUE)
           {
            if (data->BufferSize>4096)
             {
              data->BufferSize=4096;
              for (i=0;i<data->Pages;++i)
               {
                if (data->Buffers[i]!=NULL)
                 {
                  FreeVec(data->Buffers[i]);
                  data->Buffers[i]=NULL;
                 }               
               }
              continue;
             }
             else
             {
              CoerceMethod(cl,obj,OM_DISPOSE);
              return(0);            
             }
           
           } 
          break;
         }

 return ( (ULONG) (obj) );
}



ULONG _Dispose(struct IClass *cl, Object *obj, Msg msg)
{
 struct Class_Data *data = INST_DATA(cl, obj);
 struct ANSIJob *FreeJobs;
 unsigned long i;
 for (i=0;i<128;++i)
  {
   if (data->Buffers[i]!=NULL)
    {
     FreeVec(data->Buffers[i]);
     data->Buffers[i]=NULL;
    }
  }

 while (data->JobStack!=NULL)
  {
   FreeJobs=data->JobStack;
   data->JobStack=(data->JobStack->next);
   FreeVec(FreeJobs);
  }
 data->JobStack=NULL;
 return(DoSuperMethodA(cl,obj,msg));
}



ULONG _Set(struct IClass *cl,Object *obj,Msg msg)
{
        struct Class_Data *data = INST_DATA(cl, obj);
        struct TagItem *tags,*tag;

        for(tags=((struct opSet *)msg)->ops_AttrList; (tag=NextTagItem(&tags))!=NULL;)
        {
                switch(tag->ti_Tag)
                {
                 case MUIA_Editor_AltAscii:
                   if (tag->ti_Data==data->AltAscii) tag->ti_Tag=TAG_SKIP;
                   data->AltAscii=tag->ti_Data;
                   break;               
                 case MUIA_Editor_InputMask:
                   if (tag->ti_Data==data->InputMask) tag->ti_Tag=TAG_SKIP;
                   data->InputMask=tag->ti_Data;
                   break;
                 case MUIA_Editor_NumLock: 
                   if (tag->ti_Data==data->NumLock) tag->ti_Tag=TAG_SKIP;
                   data->NumLock=tag->ti_Data;
                   break;
                 case MUIA_Editor_NumLockStatus:
                   if (tag->ti_Data==data->NumLockStatus) tag->ti_Tag=TAG_SKIP;
                   data->NumLockStatus=tag->ti_Data;
                   break;
                 case MUIA_Editor_InsertMode:
                   if (tag->ti_Data==data->InsertMode)
                     {
                      tag->ti_Tag=TAG_SKIP;
                      break;
                     }
                   data->InsertMode=tag->ti_Data;
                   data->CursorRefresh=TRUE;
                   if (data->Refresh==0) data->Refresh=1;
                   MUI_Redraw(obj,MADF_DRAWUPDATE);

                   break;
                 case MUIA_Editor_AskInputStream:
                   if (tag->ti_Data==data->AskInputStream) tag->ti_Tag=TAG_SKIP;
                   data->AskInputStream=tag->ti_Data;
                   break;
                 case MUIA_Editor_AskInputANSI:
                   if (tag->ti_Data==data->AskInputANSI) tag->ti_Tag=TAG_SKIP;
                   data->AskInputANSI=tag->ti_Data;
                   break;
                 case MUIA_Editor_PCFontKeymap:
                   if (tag->ti_Data==data->PCFontKey) tag->ti_Tag=TAG_SKIP;
                   data->PCFontKey=tag->ti_Data;
                   break;
                 case MUIA_Editor_WordWrap:
                   if (tag->ti_Data==data->WordWrap) tag->ti_Tag=TAG_SKIP;
                   data->WordWrap=tag->ti_Data;
                   break;
                 case MUIA_Editor_ActivePage:
                   {
                    if ( (tag->ti_Data==data->DisplayPage) || 
                         (tag->ti_Data>=data->Pages) ||
                         (tag->ti_Data<0) )
                     {
                      tag->ti_Tag=TAG_SKIP;              
                     }
                     else
                     {
                      if (CacheClear(data)==FALSE)
                       {
                        DisplayBeep(NULL);
                        break;
                       }
                      StopMark(data);
                      data->AltAsciiStatus=-1;
                      data->DisplayPage=tag->ti_Data;
                      CompleteRefresh(data);
                     }                    
                    break;
                   }
                 case MUIA_Editor_DisableRedraw:
                   if (tag->ti_Data==data->DisableRedraw)
                       {
                        tag->ti_Tag=TAG_SKIP;
                       }
                   data->DisableRedraw=tag->ti_Data;
                   if (data->DisableRedraw==FALSE)
                    {

                    }
                   break;

                }
        }

        if (data->Refresh)
        {
         MUI_Redraw (obj,MADF_DRAWUPDATE);
        }

        return(DoSuperMethodA(cl, obj, msg));
}


static ULONG _Get(struct IClass *cl,Object *obj,Msg msg)
{
        struct Class_Data *data = INST_DATA(cl, obj);
        ULONG *store = ((struct opGet *)msg)->opg_Storage;

        switch( ((struct opGet *)msg)->opg_AttrID ) 
        {
         case MUIA_Editor_AltAscii:
           *store=data->AltAscii;
           break;
         case MUIA_Editor_AltAsciiMode:
           *store= (data->AltAsciiStatus==-1)?FALSE:TRUE;
           break;
         case MUIA_Editor_InputMask:
           *store=data->InputMask;
           break;
         case MUIA_Editor_NumLock:
           *store=data->NumLock;
           break;
         case MUIA_Editor_NumLockStatus:
           *store=data->NumLockStatus;
           break;
         case MUIA_Editor_InsertMode:
           *store=data->InsertMode;
           break;
         case MUIA_Editor_AskInputStream:
           *store=data->AskInputStream;
           break;
         case MUIA_Editor_AskInputANSI:
           *store=data->AskInputANSI;
           break;
         case MUIA_Editor_PCFontKeymap:
           *store=data->PCFontKey;
           break;
         case MUIA_Editor_ActivePage:
           *store=data->DisplayPage;
           break;
         case MUIA_Editor_BufferSize:
           *store=data->BufferSize;
           break;
         case MUIA_Editor_Pages: 
           *store=data->Pages;
           break;
         case MUIA_Editor_EditorType:
           *store=data->Type;
           break;
         case MUIA_Editor_FreeMoving:
           *store=data->FreeMoving;
           break;
         case MUIA_Editor_LineWrap:
           *store=data->LineWrap;
           break;
         case MUIA_Editor_WordWrap:
           *store=data->WordWrap;
           break;
         case MUIA_Editor_GarbageEditor:
           *store=data->GarbageEditor;
           break;
         case MUIA_Editor_Interactive:
           *store=data->Interactive;
           break;
        }

        return(DoSuperMethodA(cl, obj, msg));
}


static ULONG _Setup(struct IClass *cl,Object *obj, struct MUIP_Setup *msg)
{
        struct Class_Data *data = INST_DATA(cl, obj);

        void *CPointer;

        unsigned long xival;


        if(!(DoSuperMethodA(cl,obj,(Msg)msg)))
                return(FALSE);

        data->mri = msg->RenderInfo;
        data->ValidDisplay=FALSE;
        if (data->AltAsciiStatus!=-1) 
          SetAttrs(obj,MUIA_Editor_AltAsciiMode,FALSE,TAG_DONE);
                                 
        /* Initialize font data */

        {
         struct TextFont *tfo;
         tfo=_font(obj);
         data->FontYSize=tfo->tf_YSize;
         data->FontNominalX=tfo->tf_XSize;
         data->FontBaseline=tfo->tf_Baseline;
        }
        if (
            (CPointer = (void *) (DoMethod(PrefDataspace, 
                          MUIM_Dataspace_Find, MUICFG_Editor_ANSIPens)))
            !=NULL)
        
         {
          CopyMem(CPointer,data->ANSISpecs,8*sizeof(struct MUI_PenSpec));
         }
         else
         {
          Init_ANSISpecs(data->ANSISpecs);
         }
        {
         unsigned long i;
         for (i=0;i<8;++i)
          {
           data->ANSIPens[i]=
           MUI_ObtainPen(data->mri,&data->ANSISpecs[i],0);
          }
        }
        
        xival=(data->Type==0)?MUICFG_Editor_CursEditorPen:
                              MUICFG_Editor_CursScrollPen;

        if (
            (CPointer = (void *) (DoMethod(PrefDataspace,
                          MUIM_Dataspace_Find, xival)))
            !=NULL)

         {
          CopyMem(CPointer,&data->CursorSpec,sizeof(struct MUI_PenSpec));
         }
         else
         {
          if (data->Type==0)
           {
            Init_CursEditorPen(&data->CursorSpec);
           }
           else
           {
            Init_CursScrollPen(&data->CursorSpec);
           }
         }

        data->CursorPen=
           MUI_ObtainPen(data->mri,&data->CursorSpec,0);

        xival=(data->Type==0)?MUICFG_Editor_BlinkEditor:
                              MUICFG_Editor_BlinkScroller;

        if (
            (CPointer = (void *) (DoMethod(PrefDataspace,
                          MUIM_Dataspace_Find, xival)))
            !=NULL)

         {
          CopyMem(CPointer,&data->BlinkCursor,sizeof(long));
         }
         else
         {
          if (data->Type==0)
           {
            data->BlinkCursor=Standard_BlinkEditor;
           }
           else
           {
            data->BlinkCursor=Standard_BlinkScroller;
           }
         }

        if (
            (CPointer = (void *) (DoMethod(PrefDataspace,
                          MUIM_Dataspace_Find, MUICFG_Editor_CursorInsert)))
            !=NULL)

         {
          CopyMem(CPointer,&data->CursorInsert,sizeof(long));
         }
         else
         {
          data->CursorInsert=Standard_CursorInsert;
         }

        if (
            (CPointer = (void *) (DoMethod(PrefDataspace,
                          MUIM_Dataspace_Find, MUICFG_Editor_CursorOverwr)))
            !=NULL)

         {
          CopyMem(CPointer,&data->CursorOverwr,sizeof(long));
         }
         else
         {
          data->CursorOverwr=Standard_CursorOverwrite;
         }


        if (
            (CPointer = (void *) (DoMethod(PrefDataspace,
                          MUIM_Dataspace_Find, MUICFG_Editor_BlinkFrequency)))
            !=NULL)

         {
          CopyMem(CPointer,&data->BlinkFrequency,sizeof(long));
         }
         else
         {
          data->BlinkFrequency=Standard_BlinkFrequency;
         }


        if (!data->SolidBackgroundForce)
        {
        if (
            (CPointer = (void *) (DoMethod(PrefDataspace,
                          MUIM_Dataspace_Find, MUICFG_Editor_SolidBackground)))
            !=NULL)

         {
          CopyMem(CPointer,&data->SolidBackground,sizeof(long));
         }
        }







        return(TRUE);
}


static ULONG _Cleanup(struct IClass *cl,Object *obj,Msg msg)
{
        struct Class_Data *data = INST_DATA(cl, obj);

        {
         unsigned long i;
         for (i=0;i<8;++i)
          {
           MUI_ReleasePen(data->mri,data->ANSIPens[i]);
          }
        }

        data->mri = NULL;
        data->ValidDisplay=FALSE;

        if (data->AltAsciiStatus!=-1) 
          SetAttrs(obj,MUIA_Editor_AltAsciiMode,FALSE,TAG_DONE);


        return(DoSuperMethodA(cl,obj,msg));
}

static ULONG _Show(struct IClass *cl,Object *obj, struct MUIP_Setup *msg)
{
        struct Class_Data *data = INST_DATA(cl, obj);

        if(!(DoSuperMethodA(cl,obj,(Msg)msg)))
                return(FALSE);

        data->ValidDisplay=FALSE;

        {
         struct TextFont *tfo,*tfoo;
         unsigned long i;
         unsigned char ic;
         tfo=_font(obj);
         tfoo=_rp(obj)->Font;
         SetFont(_rp(obj),tfo);
         for (i=0;i<256;++i)
          {
           ic=i;
           data->FontXSize[i]=TextLength(_rp(obj),&ic,1);
          }
         SetFont(_rp(obj),tfoo);
        }

        
        if (data->BlinkCursor==1)
         {
          data->CursorTimer.ihn_Object=obj;
          data->CursorTimer.ihn_Millis=20*data->BlinkFrequency;
          data->CursorTimer.ihn_Flags=MUIIHNF_TIMER;
          data->CursorTimer.ihn_Method=MUIM_Editor_BlinkCursor;
        
          DoMethod(_app(obj),MUIM_Application_AddInputHandler,&data->CursorTimer);
         }
         else
         {
          data->CursorWantDisplay=TRUE;
         }

        data->MainEventHandler.ehn_Priority=10-(10*data->Type);
        data->MainEventHandler.ehn_Flags=0;
        data->MainEventHandler.ehn_Events=IDCMP_RAWKEY|IDCMP_MOUSEBUTTONS|
                                          IDCMP_INACTIVEWINDOW;
        data->MainEventHandler.ehn_Object=obj;
        data->MainEventHandler.ehn_Class=cl;
       
        DoMethod(_win(obj),MUIM_Window_AddEventHandler,&data->MainEventHandler);

        data->AuxEventHandler.ehn_Priority=0;
        data->AuxEventHandler.ehn_Flags=0;
        data->AuxEventHandler.ehn_Events=IDCMP_MOUSEMOVE|IDCMP_INTUITICKS;
        data->AuxEventHandler.ehn_Object=obj;
        data->AuxEventHandler.ehn_Class=cl;
       
        data->AuxEventActive=FALSE;        

        if (data->AltAsciiStatus!=-1) 
          SetAttrs(obj,MUIA_Editor_AltAsciiMode,FALSE,TAG_DONE);

        data->CursorFollow=1234;

        return(TRUE);
}


static ULONG _Hide(struct IClass *cl,Object *obj,Msg msg)
{
        struct Class_Data *data = INST_DATA(cl, obj);

        data->ValidDisplay=FALSE;

        if (data->BlinkCursor==1)
         {
          DoMethod(_app(obj),MUIM_Application_RemInputHandler,&data->CursorTimer);
         }

        DoMethod(_win(obj),MUIM_Window_RemEventHandler,&data->MainEventHandler);
 
        if (data->AuxEventActive!=FALSE)
         {
          DoMethod(_win(obj),MUIM_Window_RemEventHandler,&data->AuxEventHandler);
          data->AuxEventActive=FALSE;
         }

        StopMark(data);

        if (CacheClear(data)==FALSE)
         {
          DisplayBeep(NULL);
         }

        if (data->AltAsciiStatus!=-1) 
          SetAttrs(obj,MUIA_Editor_AltAsciiMode,FALSE,TAG_DONE);


        return(DoSuperMethodA(cl,obj,msg));
}


ULONG _AskMinMax(struct IClass *cl,Object *obj,struct MUIP_AskMinMax *msg)
{

        struct Class_Data *data = INST_DATA(cl, obj);

        DoSuperMethodA(cl, obj, (Msg)msg);

        msg->MinMaxInfo->MinWidth  += (data->FontNominalX*5)+20;
        msg->MinMaxInfo->DefWidth  += (data->FontNominalX*50)+20;
        msg->MinMaxInfo->MaxWidth  += MUI_MAXMAX;

        msg->MinMaxInfo->MinHeight += (data->FontYSize)*2;
        msg->MinMaxInfo->DefHeight += (data->FontYSize)*8;
        msg->MinMaxInfo->MaxHeight += MUI_MAXMAX;

        return(0);
}


void ScrollEditor(struct Class_Data *data,signed long lines)
{
 unsigned long i,xlines;
 if (lines==0) return;
 if ( (data->ValidDisplay==FALSE) || (data->SolidBackground==FALSE))
  {
   CompleteRefresh(data);
   return;
  }
 if (lines>0)
  {
   if (lines>=data->GfxLines)
    {
     CompleteRefresh(data);
     return;
    }
   for (i=(data->GfxLines-1);i>=lines;--i)
    {
     data->RefreshLine[i-lines]=data->RefreshLine[i];
    }
   for (i=0;i<lines;++i)
    {
     data->RefreshLine[i]=0;
    }
   if (data->Refresh==0) data->Refresh=1;
   data->ScrollLines+=lines;
  }
 if (lines<0)
  {
   xlines=-lines;
   if (xlines>=data->GfxLines)
    {
     CompleteRefresh(data);
     return;
    }
   data->ScrollLines+=lines;
   for (i=0;i<(data->GfxLines-lines);++i)
    {
     data->RefreshLine[i+lines]=data->RefreshLine[i];
    }
   for (i=(data->GfxLines-lines);i<data->GfxLines;++i)
    {
     data->RefreshLine[i]=0;
    }
   if (data->Refresh==0) data->Refresh=1;
  }
 if ( (data->CursorIsDisplay) && (data->CursorIsReal))
  {
   data->CursorIsY+=lines;
   if (data->CursorIsY>=data->GfxLines)
    {
     data->CursorIsReal=FALSE;
    }
  }
}

ULONG _Draw(struct IClass *cl,Object *obj, struct MUIP_Draw *msg)
{
        struct Class_Data *data = INST_DATA(cl, obj);

        /*** first draw the superclass ***/
        DoSuperMethodA(cl, obj, (Msg)msg);

        data->ValidDisplay=TRUE;
        data->GfxRPort=_rp(obj);
        data->GfxWindow=_window(obj);
        data->GfxFont=_font(obj);
        data->GfxLeft=_mleft(obj)+1;
        data->GfxRight=_mright(obj)-1;
        data->GfxTop=_mtop(obj);
        data->GfxBottom=_mbottom(obj);
        data->GfxWidth=_mwidth(obj)-2;;
        data->GfxHeight=_mheight(obj);
        data->GfxPOffsetX=data->GfxLeft;
        data->GfxPOffsetY=data->GfxTop;

        data->GfxLines=data->GfxHeight / data->FontYSize;

        memcpyfast (data->GfxRPort,&data->CloneRastport,sizeof(struct RastPort));
        
        data->GfxRPort=&data->CloneRastport;

        if (data->CursorFollow==1234)
         {          
          unsigned long i;
          signed long diffline;        
          struct EditorBuffer *edbuf;
          data->CursorFollow=FALSE;
          for (i=0;i<data->Pages;++i)
           {
            edbuf=data->Buffers[i];
            diffline=edbuf->CursorLine-edbuf->HeadLine;
            diffline=data->GfxLines-1-diffline;
            if (edbuf->HeadLine>=diffline) edbuf->HeadLine-=diffline;            
           }           
         }



        if (data->CursorFollow==TRUE)
         {
          struct EditorBuffer *tedit;
          struct LineInfo linf;
          unsigned long XPos;
          unsigned long XSize;

          data->CursorFollow=FALSE;
          tedit = data->Buffers[data->DisplayPage];
          if (tedit->HeadLine>tedit->CursorLine)
           {
            ScrollEditor(data,tedit->HeadLine-tedit->CursorLine);
            tedit->HeadLine=tedit->CursorLine;
           }
          if ((tedit->HeadLine+data->GfxLines)<=tedit->CursorLine)
           {
            ScrollEditor(data,tedit->HeadLine-(tedit->CursorLine-
                        data->GfxLines+1));
            tedit->HeadLine=tedit->CursorLine-data->GfxLines+1;

           }
          if ( (GetLineInfo(data,&linf,tedit->CursorLine)) == FALSE)
           {
            DisplayBeep(NULL);
            linf.Chars=NULL;
           }
          XPos=0;
          XSize=0;
          if (linf.Chars!=NULL) XPos=ColumnToOffset(data,&linf,tedit->CursorColumn);
          if (linf.Chars!=NULL) XSize=ColumnXSize(data,&linf,tedit->CursorColumn);

          if ((XPos+XSize)>=(data->GfxWidth+tedit->HeadColumn))
           {
            tedit->HeadColumn=XPos+XSize-(data->GfxWidth/2);
            CompleteRefresh(data);
           }
          if (XPos<tedit->HeadColumn)
           {
            if (XPos>(data->GfxWidth/2))
             {
              tedit->HeadColumn=XPos-(data->GfxWidth/2);
             }
             else
             {
              tedit->HeadColumn=0;
             }
            CompleteRefresh(data);
           }
         }

        if (data->DisableRedraw)
         {
          CompleteRefresh(data);
          return(0);
         }


        if(msg->flags & MADF_DRAWUPDATE)
        {
         DoRefresh(cl,obj,data);
        }
        else if(msg->flags & MADF_DRAWOBJECT)
        {
         CompleteRefresh(data);
         data->Refresh=2;
         DoRefresh(cl,obj,data);
        }

        return(0);
}

unsigned int BackwrapEditor(struct Class_Data *data,struct EditorBuffer *edbuf)
{
 struct LineInfo linf;
 if (CacheClear(data)==FALSE)
  {
   DisplayBeep(NULL);
   return(FALSE);
  }
 if (edbuf->CursorLine==0) return(FALSE);
 if (CacheSet(data,edbuf->CursorLine-1)==FALSE)
  {
   DisplayBeep(NULL);
   return(FALSE);
  }
 if (GetLineInfo(data,&linf,edbuf->CursorLine)==FALSE)
     {
      DisplayBeep(NULL);
      return (FALSE);
     }

  {
   unsigned long charappend;
   unsigned long currentchar;
   unsigned long gluesize;
   unsigned char *captr;
   unsigned char *glueptr;
   struct StyleInfo *gluesty;
   struct StyleInfo *appsty;
   unsigned long gstsize;
   unsigned long styleappend;
   unsigned long currentstyle;

   glueptr=linf.Chars;
   gluesize=linf.CharLen;
   charappend=data->CachedTextLen;
   captr=data->CachedChar+charappend;
   currentchar=charappend;
   while ( (currentchar<4096) && (gluesize>0))
    {
     *(captr++)=*(glueptr++);
     ++data->CachedTextLen;
     currentchar++;
     gluesize--;
    }

   gluesty=linf.Styles;
   gstsize=linf.StyleLen;
   styleappend=data->CachedStyleInfo;
   appsty=data->CachedStyle+styleappend;
   currentstyle=styleappend;

   while ( (currentstyle<128) && (gstsize>0))
    {
     if ( (styleappend>0) && (gstsize==linf.StyleLen) &&
          ( (appsty-1)->ForegroundColor==gluesty->ForegroundColor) &&
          ( (appsty-1)->BackgroundColor==gluesty->BackgroundColor) &&
          ( (appsty-1)->TextStyle==gluesty->TextStyle) )
       {
        gluesty++;
        gstsize--;
        continue;
       }

     if ( (styleappend>0) && (gstsize==linf.StyleLen) &&
          ( (appsty-1)->StartColumn==(gluesty->StartColumn+charappend)))
       {
        data->CachedStyleInfo--;
        currentstyle--;
        appsty--;
       }



     appsty->ForegroundColor=gluesty->ForegroundColor;
     appsty->BackgroundColor=gluesty->BackgroundColor;
     appsty->TextStyle=gluesty->TextStyle;
     appsty->Pad1=0;
     appsty->StartColumn=gluesty->StartColumn+charappend;
     data->CachedStyleInfo++;
     currentstyle++;
     appsty++;
     gluesty++;
     gstsize--;
    }

   edbuf->CursorLine--;
   edbuf->CursorColumn=charappend;
  }

 if (CacheClear(data)==FALSE)
  {
   DisplayBeep(NULL);
   return(FALSE);
  }


 if (DeleteLine(data,edbuf->CursorLine+1)==FALSE)
  {
   DisplayBeep(NULL);
   return(FALSE);
  }
 return(TRUE);
}

unsigned int WrapEditor(struct Class_Data *data,unsigned long WrapLine,
                        unsigned long WrapColumn)
 {
  struct LineInfo linf;
  signed long i;
  unsigned char *schr;
  unsigned char *dchr;
  struct StyleInfo *ssty;
  struct StyleInfo *dsty;
  struct EditorBuffer *edbuf;
  signed long XWrapLine;

  XWrapLine=WrapLine;

  edbuf=data->Buffers[data->DisplayPage];


  if ( (data->MaxLines!=0) &&
       (XWrapLine>=data->MaxLines) ) return(FALSE);

  data->GarbagedLines=0;
  
  if (CacheClear(data)==FALSE)
     {
      DisplayBeep(NULL);
      return(FALSE);
     }
  
  XWrapLine=WrapLine-data->GarbagedLines;
  if (XWrapLine<0) return (FALSE);

  if (InsertLine(data,edbuf,XWrapLine+1)==FALSE)
     {
      DisplayBeep(NULL);
      return(FALSE);
     }

  XWrapLine=WrapLine-data->GarbagedLines;
  if (XWrapLine<0) return (FALSE);

  if (CacheSet(data,XWrapLine+1)==FALSE)
     {
      DisplayBeep(NULL);
      return(FALSE);
     }

  XWrapLine=WrapLine-data->GarbagedLines;
  if (XWrapLine<0) return (FALSE);

 
  if (GetLineInfo(data,&linf,XWrapLine)==FALSE)
     {
      DisplayBeep(NULL);
      return (FALSE);
     }

  XWrapLine=WrapLine-data->GarbagedLines;
  if (XWrapLine<0) return (FALSE);


  data->CachedTextLen=0;
  schr=linf.Chars+WrapColumn;
  dchr=data->CachedChar;
  for (i=WrapColumn;i<linf.CharLen;++i)
    {
     *(dchr++)=*(schr++);
     data->CachedTextLen++;
    }

  data->CachedStyleInfo=0;
  dsty=data->CachedStyle;
  ssty=linf.Styles;
  for (i=0;i<linf.StyleLen;++i,++ssty)
   {
    if ( ( (i+1) < linf.StyleLen) && (  (ssty+1)->StartColumn <=WrapColumn) )
     {
      continue;
     }
    *(dsty)=*(ssty);
    if (dsty->StartColumn<WrapColumn)
     {
      dsty->StartColumn=0;
     }
     else
     {
      dsty->StartColumn-=WrapColumn;
     }
    dsty++;
    data->CachedStyleInfo++;
   }

  if (CacheClear(data)==FALSE)
     {
      DisplayBeep(NULL);
      return(FALSE);
     }

  XWrapLine=WrapLine-data->GarbagedLines;
  if (XWrapLine<0) return (FALSE);


  if (CacheSet(data,XWrapLine)==FALSE)
     {
      DisplayBeep(NULL);
      return(FALSE);
     }

  XWrapLine=WrapLine-data->GarbagedLines;
  if (XWrapLine<0) return (FALSE);

  
  data->CachedTextLen=WrapColumn;
  ssty=data->CachedStyle;
  for (i=0;i<data->CachedStyleInfo;++i,++ssty)
   {
    if (ssty->StartColumn>WrapColumn)
     {
      data->CachedStyleInfo=i;
      break;
     }
   }

  if (CacheClear(data)==FALSE)
     {
      DisplayBeep(NULL);
      return(FALSE);
     }

  XWrapLine=WrapLine-data->GarbagedLines;
  if (XWrapLine<0) return (FALSE);

 
  {
   unsigned long MaxLine;

   MaxLine=127;
   if (data->ValidDisplay!=FALSE) MaxLine=data->GfxLines-1;

   if (edbuf->HeadLine<=XWrapLine)
    {
     i=XWrapLine-edbuf->HeadLine;
     if ( (i<=MaxLine) && (i>=0) )
      {
       if ( (data->RefreshLine[i]==-1) || 
            (data->RefreshLine[i]>WrapColumn) )
         {
          data->RefreshLine[i]=WrapColumn;
         }      
      }
    }

   if (edbuf->HeadLine+MaxLine>XWrapLine)
    {
     signed long RedisLine;
     RedisLine=XWrapLine+1-edbuf->HeadLine;
     if (RedisLine<0) RedisLine=0;
     while (RedisLine<=MaxLine)
      {
       data->RefreshLine[RedisLine]=0;
       ++RedisLine;
      }
    }   
      

  }

  if (data->Refresh==0) data->Refresh=1;
 
  return(TRUE);

 }

void ClearBuffer(struct EditorBuffer *edbuf)
 {
  edbuf->BufferFilled=0;
  edbuf->BufferLineCache=0;
  edbuf->HeadLine=0;
  edbuf->HeadColumn=0;
  edbuf->CursorLine=0;
  edbuf->CursorColumn=0;
  edbuf->InputLine=-1;
  edbuf->InputColumn=-1;
  edbuf->MarkStartLine=-1;
  edbuf->MarkStartColumn=-1;
  edbuf->MarkStopLine=-1;
  edbuf->MarkStopColumn=-1;
  edbuf->ANSIInput.ANSICmdState=0;    
  edbuf->ANSIInput.ForegroundColor=1;
  edbuf->ANSIInput.BackgroundColor=0;
  edbuf->ANSIInput.TextStyle=0;
  edbuf->ImportMode=MUIV_Editor_ImExMode_LF|MUIV_Editor_ImExMode_AmChar;

 }


static ULONG _BlinkCursor(struct IClass *cl,Object *obj,Msg msg)
{
        struct Class_Data *data = INST_DATA(cl, obj);

        data->CursorWantDisplay^=1;
        if (data->Refresh==0) data->Refresh=1;
        MUI_Redraw(obj,MADF_DRAWUPDATE);

        return(0);
}


ULONG ClassDispatcher(struct IClass *cl,Object *obj,Msg msg)
{
        switch(msg->MethodID)
        {
                case MUIM_Editor_BlinkCursor : return(_BlinkCursor    (cl,obj,(APTR)msg));
                case OM_NEW        : return(_New      (cl,obj,(struct opSet *)msg));
                case OM_DISPOSE    : return(_Dispose  (cl,obj,(APTR)msg));
                case OM_SET        : return(_Set      (cl,obj,(APTR)msg));
                case OM_GET        : return(_Get      (cl,obj,(APTR)msg));
                case MUIM_Setup    : return(_Setup    (cl,obj,(APTR)msg));
                case MUIM_Cleanup  : return(_Cleanup  (cl,obj,(APTR)msg));
                case MUIM_Show     : return(_Show     (cl,obj,(APTR)msg));
                case MUIM_Hide     : return(_Hide     (cl,obj,(APTR)msg));
                case MUIM_AskMinMax: return(_AskMinMax(cl,obj,(APTR)msg));
                case MUIM_Draw     : return(_Draw     (cl,obj,(APTR)msg));
                case MUIM_HandleEvent: return(_HandleEvent (cl,obj,(APTR)msg));
                case MUIM_Editor_WriteANSI: return(_WriteANSI (cl,obj,(APTR)msg));
                case MUIM_Editor_WriteStream: return(_WriteStream (cl,obj,(APTR)msg));
                case MUIM_Editor_ANSIToStream: return(_ANSIToStream (cl,obj,(APTR)msg));
                case MUIM_Editor_StreamToANSI: return(_StreamToANSI (cl,obj,(APTR)msg));
                case MUIM_Editor_PutStorage: return(_PutStorage (cl,obj,(APTR)msg));
                case MUIM_Editor_GetStorage: return(_GetStorage (cl,obj,(APTR)msg));
                case MUIM_Editor_ExportPage: return(_ExportPage (cl,obj,(APTR)msg));
                case MUIM_Editor_ImportPage: return(_ImportPage (cl,obj,(APTR)msg));
                case MUIM_Editor_ClearPage: return(_ClearPage (cl,obj,(APTR)msg));
                case MUIM_Editor_ExportStream: return(_ExportStream(cl,obj,(APTR)msg));
                case MUIM_Editor_ImportStream: return(_ImportStream(cl,obj,(APTR)msg));
        }

        return(DoSuperMethodA(cl,obj,msg));
}




