{$I OVC.INC}

{$B-} {Complete Boolean Evaluation}
{$I+} {Input/Output-Checking}
{$P+} {Open Parameters}
{$T-} {Typed @ Operator}
{$W-} {Windows Stack Frame}
{$X+} {Extended Syntax}
{$R-} {Range-Checking}
{$S-} {Stack-Overflow Checking}

{$IFNDEF Win32}
{$G+} {286 Instructions}
{$N+} {Numeric Coprocessor}
{$C MOVEABLE,DEMANDLOAD,DISCARDABLE}
{$ENDIF}

{*********************************************************}
{*                  OVCEDITP.PA2 2.00                    *}
{*     Copyright (c) TurboPower Software Co 1995-96      *}
{*                 All rights reserved.                  *}
{*********************************************************}

unit OvcEditP;
  {-editor paragraph list and undo buffer classes}

interface

uses
  Controls, Forms, SysUtils,
  OvcData, OvcEditN, OvcEditU;

{.Z+}
type
  TUndoBuffer = class;

  TParaList = class(TObject)
  public
    Owner      : TOvcEditBase; {original owner of this object}
    Head       : TParaNode;    {start of list}
    Tail       : TParaNode;    {end of list}
    LastNode   : TParaNode;    {last node found}
    LastP      : LongInt;      {last paragraph found}
    LastN      : LongInt;      {last line found}
    LastO      : Integer;      {lastO is line offset into LastNode for LastN}
    ParaCount  : LongInt;      {total number of paragraphs}
    ByteCount  : LongInt;      {total number of bytes}
    LineCount  : LongInt;      {total number of lines}
    MaxParas   : LongInt;      {max number of paragraphs}
    MaxBytes   : LongInt;      {max number of bytes}
    MaxParaLen : Integer;      {max paragraph length}
    WordWrap   : Boolean;      {if True, word wrap is on}
    WrapColumn : Integer;      {column for word wrap}
    TabSize    : Byte;         {size for tab stops}
    Modified   : Boolean;      {if True, text stream has been modified}
    FixMarkers : Boolean;      {should markers be adjusted yet?}
    Markers    : TMarkerArray; {position markers}
    UndoBuffer : TUndoBuffer;  {buffer of insertions/deletions}
    InUndo     : Boolean;      {are we in the Undo routine?}
    FLine      : LongInt;      {first changed line}
    LLine      : LongInt;      {last changed line}

    constructor Init(AOwner : TOvcEditBase; UndoSize : Word; Wrap : Boolean);
      virtual;
      {-initialize the paragraph list; POwner is original owner of list}
    destructor Destroy;
      override;
      {-destroy the paragraph list}

    {undo facility}
    procedure MakeUndoRec(UT : UndoType; P : LongInt; Pos : Integer;
                          S : PAnsiChar; Len : Word);
      {-create an undo record}
    procedure MakeReplaceUndoRec(P : LongInt; Pos : Integer;
                                 S : PAnsiChar; Len : Word;
                                 R : PAnsiChar; RLen : Word);
      {-create an undo record for a replace operation}
    procedure Undo(Editor : TOvcEditBase; var P : LongInt; var Pos : Integer);
      {-undo last insertion/deletion/replacement}
    procedure Redo(Editor : TOvcEditBase; var P : LongInt; var Pos : Integer);
      {-redo last undone operation}
    procedure SetUndoSize(Size : Word);
      {-set size of undo buffer}

    {adding and deleting nodes}
    procedure Insert(PPN : TParaNode);
      {-insert element PPN at beginning of list}
    procedure Append(PPN : TParaNode);
      {-add a node to the end of the list}
    procedure Place(PPN, LPN : TParaNode);
      {-place element PPN into list after existing element LPN}
    procedure PlaceBefore(PPN, LPN : TParaNode);
      {-place element PPN into list before existing element LPN}

    {finding lines/paragraphs}
    procedure SetLastNode(PPN : TParaNode; P, N : LongInt; O : Integer);
      {-set LastNode to PPN, LastP to P, LastN to N, LastO to O}
    function  NthPara(P : LongInt) : TParaNode;
      {-return pointer to Nth paragraph}
    function  NthLine(N : LongInt; var S : PAnsiChar; var Len : Word) : TParaNode;
      {-return pointer to Nth line and its length}
    function  FindParaByLine(N : LongInt; var LinePos : Integer) : LongInt;
      {-return the index of the paragraph containing line N}
    function  FindLineByPara(P : LongInt; Pos : Integer;
                             var Col : Integer) : LongInt;
      {-return the Line,Col corresponding to paragraph P, position Pos}

    {settings}
    procedure ResetPositionInfo;
      {-tell all editors to reset their position info}
    procedure Recalculate;
      {-recalculate number of lines}
    function  GetWrapColumn : Integer;
      {-get the column for word wrap}
    procedure SetWrapColumn(Value : Integer);
      {-set the column for word wrap}
    procedure SetTabSize(Value : Byte);
      {-set the tab size}
    procedure SetByteLimit(Value : LongInt);
      {-set limit on total bytes}
    procedure SetParaLimit(Value : LongInt);
      {-set limit on total paragraphs}
    procedure SetWordWrap(Value : Boolean);
      {-turn word wrap on or off}

    {effective columns to actual columns, etc.}
    function  ParaLength(Value : LongInt) : Integer;
      {-return length of paragraph P}
    function  LineLength(Value : LongInt) : Integer;
      {-return length of line N}
    function  EffStrLen(S : PAnsiChar; Len : Word) : Word;
      {-compute effective length of S}
    function  EffLen(N : LongInt) : Word;
      {-compute effective length of line N}
    function  EffCol(S : PAnsiChar; Len, Col : Word) : Word;
      {-compute effective column}
    function  ActualCol(S : PAnsiChar; Len, Col : Word) : Word;
      {-given an effective column #, return an actual column #}

    {inserting and deleting text}
    function  OkToInsert(P : LongInt; Paras, Bytes : Word) : Word;
      {-is it OK to insert Bytes characters into paragraph P?}
    function  AppendParaEof(S : PAnsiChar; SLen : Word; Trim : Boolean) : Word;
      {-create a new paragraph from S and append to end of file}
    procedure InsertParaNode(Editor : TOvcEditBase; P : LongInt; NPN : TParaNode);
      {-insert a new paragraph before paragraph P}
    function  InsertParaPrim(Editor : TOvcEditBase; P : LongInt;
                             S : PAnsiChar; Len : Word) : Word;
      {-create a new paragraph with text from S^ and insert before paragraph P}
    procedure PlaceParaNode(Editor : TOvcEditBase; P : LongInt; NPN : TParaNode);
      {-place a new paragraph after paragraph P}
    function PlaceParaPrim(Editor : TOvcEditBase; P : LongInt;
                           S : PAnsiChar; Len : Word) : Word;
      {-create a new paragraph with text from S^ and place it after paragraph P}
    function  InsertTextPrim(Editor : TOvcEditBase; P : LongInt; Pos : Integer;
                             S : PAnsiChar; SLen : Word) : Word;
      {-insert SLen characters from S^ in paragraph P at Pos}
    function  InsertBlock(Editor : TOvcEditBase; var P : LongInt;
                          var Pos : Integer; S : PAnsiChar) : Word;
      {-insert a block of text}
    procedure DeletePara(Editor : TOvcEditBase; P : LongInt);
      {-delete paragraph P}
    procedure DeleteText(Editor : TOvcEditBase; P : LongInt; Pos, Count : Integer);
      {-delete Count characters from paragraph P at Pos}
    procedure DeleteBlock(Editor : TOvcEditBase; Para1 : LongInt; Pos1 : Integer;
                          Para2 : LongInt; Pos2 : Integer);
      {-delete the block from Para1,Pos1 to Para2,Pos2}
    function  JoinWithNext(Editor : TOvcEditBase; P : LongInt; Pos : Integer) : Word;
      {-join paragraph P with the following paragraph at Pos}
    function  BreakPara(Editor : TOvcEditBase; P : LongInt; Pos, TabSz : Integer;
                        var Indent : Integer; Trim : Boolean) : Word;
      {-break paragraph P at Pos and indent the new paragraph}
    function  ReplaceText(Editor : TOvcEditBase; P : LongInt;
                          Pos, Count : Integer;
                          St : PAnsiChar; StLen : Integer) : Word;
      {-replace the next Count characters at P,Pos with text of St^}

    {text markers}
    procedure SetMarker(N : Byte; Para : LongInt; Pos : Integer);
    procedure SetMarkerAt(N : Byte; Line : LongInt; Col : Integer);
    procedure FixMarkerInsertedPara(var M : TMarker; N : LongInt; Pos, Indent : Integer);
    procedure FixMarkersInsertedPara(Editor : TOvcEditBase; N : LongInt; Pos, Indent : Integer);
    procedure FixMarkerInsertedText(var M : TMarker; N : LongInt; Pos, Count : Integer);
    procedure FixMarkersInsertedText(Editor : TOvcEditBase; N : LongInt; Pos, Count : Integer);
    procedure FixMarkDeletedPara(var M : TMarker; N : LongInt);
    procedure FixMarkerDeletedPara(var M : TMarker; N : LongInt);
    procedure FixMarkersDeletedPara(Editor : TOvcEditBase; N : LongInt);
    procedure FixMarkDeletedText(var M : TMarker; N : LongInt; Pos, Count : Integer);
    procedure FixMarkerDeletedText(var M : TMarker; N : LongInt; Pos, Count : Integer);
    procedure FixMarkersDeletedText(Editor : TOvcEditBase; N : LongInt; Pos, Count : Integer);
    procedure FixMarkerJoinedParas(var M : TMarker; N : LongInt; Pos : Integer);
    procedure FixMarkersJoinedParas(Editor : TOvcEditBase; N : LongInt; Pos : Integer);
  end;

  TUndoBuffer = class(TObject)
  public
    Owner    : TParaList;
    Buffer   : Pointer;   {pointer to the undo/redo buffer}
    BufSize  : Word;      {size of the undo/redo buffer}
    BufAvail : Word;      {free space in the buffer}
    Last     : PUndoRec;  {points to the last TUndoRec in the buffer}
    Undos    : Word;      {number of undo entries}
    Redos    : Word;      {number of redo entries}
    CurLink  : Byte;
    Linking  : Boolean;
    Error    : Boolean;
    GUN      : TUndoNode; {general undo node object}

    constructor Init(ParaList : TParaList; Size : Word);
      virtual;
    destructor Destroy;
      override;

    procedure Flush;
    function  CheckSize(Bytes : LongInt) : Boolean;
    function  SameOperation(UT : UndoType; var Before : Boolean; P : LongInt;
                            Pos : Integer; DLen : Word) : Boolean;
    procedure Append(D : PAnsiChar; DLen : Word);
    procedure Prepend(D : PAnsiChar; DLen : Word);
    procedure AppendReplace(D : PAnsiChar; DLen : Word; R : PAnsiChar; RLen : Word);
    procedure Push(UT : UndoType; MF : Boolean; P : LongInt; Pos : Integer;
                   D : PAnsiChar; DLen : Word);
    procedure PushReplace(MF : Boolean; P : LongInt; Pos : Integer;
                          D : PAnsiChar; DLen : Word;
                          R : PAnsiChar; RLen : Word);
    procedure GetUndo(var UT : UndoType; var Link : Byte; var MF : Boolean;
                      var P : LongInt; var Pos : Integer;
                      var D : PAnsiChar; var DLen : Word);
    procedure GetRedo(var UT : UndoType; var Link : Byte; var MF : Boolean;
                      var P : LongInt; var Pos : Integer;
                      var D : PAnsiChar; var DLen : Word);
    procedure PeekUndoLink(var Link : Byte);
    procedure PeekRedoLink(var Link : Byte);
    function  NthRec(N : Integer) : PUndoRec;
    procedure SetModified;
    procedure BeginComplexOp(var SaveLinking : Boolean);
    procedure EndComplexOp(SaveLinking : Boolean);
  end;
{.Z-}


implementation
