Browse Source

+ Gabor patch to add support for multiple windows
of same file
weditor has been splitted into weditor and wcedit units

pierre 25 years ago
parent
commit
58c1b8a0be
2 changed files with 5370 additions and 3338 deletions
  1. 1724 0
      ide/text/wcedit.pas
  2. 3646 3338
      ide/text/weditor.pas

+ 1724 - 0
ide/text/wcedit.pas

@@ -0,0 +1,1724 @@
+{
+    $Id$
+    This file is part of the Free Pascal Integrated Development Environment
+    Copyright (c) 1998-2000 by Berczi Gabor
+
+    Code editor template objects
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    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.
+
+ **********************************************************************}
+{$i globdir.inc}
+unit WCEdit;
+
+interface
+
+uses Objects,Drivers,Views,
+     { necessary for ExistsFile }FPUtils,
+     WUtils,WEditor;
+
+type
+    PIndicator = ^TIndicator;
+    TIndicator = object(TView)
+      Location: TPoint;
+      Modified : Boolean;
+{$ifdef debug}
+      StoreUndo : Boolean;
+      SyntaxComplete : boolean;
+      UseTabs : Boolean;
+{$endif debug}
+      constructor Init(var Bounds: TRect);
+      procedure   Draw; virtual;
+      function    GetPalette: PPalette; virtual;
+      procedure   SetState(AState: Word; Enable: Boolean); virtual;
+      procedure   SetValue(ALocation: TPoint; AModified: Boolean);
+    end;
+
+    PLine = ^TLine;
+    TLine = object(TCustomLine)
+    public { internal use only! }
+      Text        : PString;
+      EditorInfos : PEditorLineInfoCollection;
+      Flags       : longint;
+      procedure AddEditorInfo(Index: sw_integer; AEditor: PCustomCodeEditor); virtual;
+      procedure RemoveEditorInfo(AEditor: PCustomCodeEditor); virtual;
+    public
+      constructor Init(const AText: string; AFlags: longint);
+      function    GetText: string; virtual;
+      procedure   SetText(const AText: string); virtual;
+      function    GetEditorInfo(Editor: PCustomCodeEditor): PEditorLineInfo; virtual;
+      function    GetFlags: longint; virtual;
+      procedure   SetFlags(AFlags: longint); virtual;
+      destructor  Done; virtual;
+    end;
+
+    PCodeEditorCore = ^TCodeEditorCore;
+    TCodeEditorCore = object(TCustomCodeEditorCore)
+    {$ifdef TP}public{$else}protected{$endif}
+      Lines      : PLineCollection;
+      CanUndo    : Boolean;
+      StoreUndo  : boolean;
+      Modified   : Boolean;
+      ReadOnly   : Boolean;
+      TabSize    : integer;
+    {$ifdef UNDO}public{$endif}
+      UndoList   : PEditorActionCollection;
+      RedoList   : PEditorActionCollection;
+    public
+      constructor Init;
+      destructor  Done; virtual;
+    public
+      function    GetModified: boolean; virtual;
+      procedure   SetModified(AModified: boolean); virtual;
+      function    GetTabSize: integer; virtual;
+      procedure   SetTabSize(ATabSize: integer); virtual;
+      function    GetStoreUndo: boolean; virtual;
+      procedure   SetStoreUndo(AStore: boolean); virtual;
+      function    GetSyntaxCompleted: boolean; virtual;
+      procedure   SetSyntaxCompleted(SC : boolean); virtual;
+      function    GetLastSyntaxedLine: sw_integer; virtual;
+      procedure   SetLastSyntaxedLine(ALine: sw_integer); virtual;
+    public
+      { Storage }
+    {$ifdef TP}public{$else}protected{$endif}
+      { Text & info storage abstraction }
+      procedure   ISetLineFlagState(Binding: PEditorBinding; LineNo: sw_integer; Flag: longint; ASet: boolean); virtual;
+      procedure   IGetDisplayTextFormat(Binding: PEditorBinding; LineNo: sw_integer;var DT,DF:string); virtual;
+      function    IGetLineFormat(Binding: PEditorBinding; LineNo: sw_integer): string; virtual;
+      procedure   ISetLineFormat(Binding: PEditorBinding; LineNo: sw_integer;const S: string); virtual;
+    public
+      { Text & info storage abstraction }
+      function    GetLineCount: sw_integer; virtual;
+      function    GetLine(LineNo: sw_integer): PCustomLine; virtual;
+      function    GetLineText(LineNo: sw_integer): string; virtual;
+      procedure   SetDisplayText(I: sw_integer;const S: string); virtual;
+      function    GetDisplayText(I: sw_integer): string; virtual;
+      procedure   SetLineText(I: sw_integer;const S: string); virtual;
+      procedure   DeleteAllLines; virtual;
+      procedure   DeleteLine(I: sw_integer); virtual;
+      procedure   InsertLine(LineNo: sw_integer; const S: string); virtual;
+      procedure   AddLine(const S: string); virtual;
+      procedure   GetContent(ALines: PUnsortedStringCollection); virtual;
+      procedure   SetContent(ALines: PUnsortedStringCollection); virtual;
+   public
+     { Undo info storage }
+      procedure   AddAction(AAction: byte; AStartPos, AEndPos: TPoint; AText: string); virtual;
+      procedure   AddGroupedAction(AAction : byte); virtual;
+      procedure   CloseGroupedAction(AAction : byte); virtual;
+      function    GetUndoActionCount: sw_integer; virtual;
+      function    GetRedoActionCount: sw_integer; virtual;
+    private
+      procedure LinesInsert(Idx: sw_integer; Line: PLine);
+    end;
+
+    PCodeEditor = ^TCodeEditor;
+    TCodeEditor = object(TCustomCodeEditor)
+      Core       : PCodeEditorCore;
+      Flags      : longint;
+      Indicator  : PIndicator;
+      HighlightRow: sw_integer;
+      DebuggerRow: sw_integer;
+      CodeCompleteFrag: PString;
+      CodeCompleteWord: PString;
+      ReadOnly   : boolean;
+      CompleteState: TCompleteState;
+      ErrorMessage: PString;
+      IndicatorDrawCalled  : boolean;
+      constructor Init(var Bounds: TRect; AHScrollBar, AVScrollBar:
+          PScrollBar; AIndicator: PIndicator; ACore: PCodeEditorCore);
+    public
+      procedure   DrawIndicator; virtual;
+    public
+      function    GetFlags: longint; virtual;
+      procedure   SetFlags(AFlags: longint); virtual;
+      function    GetModified: boolean; virtual;
+      procedure   SetModified(AModified: boolean); virtual;
+      function    GetStoreUndo: boolean; virtual;
+      procedure   SetStoreUndo(AStore: boolean); virtual;
+      function    GetSyntaxCompleted: boolean; virtual;
+      procedure   SetSyntaxCompleted(SC : boolean); virtual;
+      function    GetLastSyntaxedLine: sw_integer; virtual;
+      procedure   SetLastSyntaxedLine(ALine: sw_integer); virtual;
+      function    GetTabSize: integer; virtual;
+      procedure   SetTabSize(ATabSize: integer); virtual;
+      function    IsReadOnly: boolean; virtual;
+    public
+      procedure   UpdateIndicator; virtual;
+      procedure   ModifiedChanged; virtual;
+      procedure   LimitsChanged; virtual;
+      function    IsClipboard: Boolean; virtual;
+      function    LoadFromStream(Stream: PStream): boolean; virtual;
+      function    SaveToStream(Stream: PStream): boolean; virtual;
+      function    SaveAreaToStream(Stream: PStream; StartP,EndP: TPoint): boolean;
+      destructor  Done; virtual;
+    public
+{      ChangedLine : sw_integer;}
+      { Text & info storage abstraction }
+      function    GetLineCount: sw_integer; virtual;
+      function    GetLine(LineNo: sw_integer): PCustomLine; virtual;
+      function    CharIdxToLinePos(Line,CharIdx: sw_integer): sw_integer; virtual;
+      function    LinePosToCharIdx(Line,X: sw_integer): sw_integer; virtual;
+      function    GetLineText(I: sw_integer): string; virtual;
+      procedure   SetDisplayText(I: sw_integer;const S: string); virtual;
+      function    GetDisplayText(I: sw_integer): string; virtual;
+      procedure   SetLineText(I: sw_integer;const S: string); virtual;
+      procedure   GetDisplayTextFormat(I: sw_integer;var DT,DF:string); virtual;
+      function    GetLineFormat(I: sw_integer): string; virtual;
+      procedure   SetLineFormat(I: sw_integer;const S: string); virtual;
+      procedure   DeleteAllLines; virtual;
+      procedure   DeleteLine(I: sw_integer); virtual;
+      procedure   InsertLine(LineNo: sw_integer; const S: string); virtual;
+      procedure   AddLine(const S: string); virtual;
+      function    GetErrorMessage: string; virtual;
+      procedure   SetErrorMessage(const S: string); virtual;
+      procedure   GetContent(ALines: PUnsortedStringCollection); virtual;
+      procedure   SetContent(ALines: PUnsortedStringCollection); virtual;
+      procedure   Lock; virtual;
+      procedure   UnLock; virtual;
+    public
+     { CodeComplete support }
+      function    GetCodeCompleteWord: string; virtual;
+      procedure   SetCodeCompleteWord(const S: string); virtual;
+      function    GetCodeCompleteFrag: string; virtual;
+      procedure   SetCodeCompleteFrag(const S: string); virtual;
+      function    GetCompleteState: TCompleteState; virtual;
+      procedure   SetCompleteState(AState: TCompleteState); virtual;
+   public
+      { Syntax highlight }
+   {a}function    UpdateAttrs(FromLine: sw_integer; Attrs: byte): sw_integer; virtual;
+   {a}function    UpdateAttrsRange(FromLine, ToLine: sw_integer; Attrs: byte): sw_integer; virtual;
+   public
+     { Undo info storage }
+      procedure   AddAction(AAction: byte; AStartPos, AEndPos: TPoint; AText: string); virtual;
+      procedure   AddGroupedAction(AAction : byte); virtual;
+      procedure   CloseGroupedAction(AAction : byte); virtual;
+      function    GetUndoActionCount: sw_integer; virtual;
+      function    GetRedoActionCount: sw_integer; virtual;
+      procedure   JumpToLastCursorPos; virtual;
+      procedure   Undo; virtual;
+      procedure   Redo; virtual;
+    end;
+
+    PFileEditor = ^TFileEditor;
+    TFileEditor = object(TCodeEditor)
+      FileName: string;
+      constructor Init(var Bounds: TRect; AHScrollBar, AVScrollBar:
+          PScrollBar; AIndicator: PIndicator; ACore: PCodeEditorCore; const AFileName: string);
+      function    Save: Boolean; virtual;
+      function    SaveAs: Boolean; virtual;
+      function    SaveAsk: Boolean; virtual;
+      function    LoadFile: boolean; virtual;
+      function    SaveFile: boolean; virtual;
+      function    Valid(Command: Word): Boolean; virtual;
+      procedure   HandleEvent(var Event: TEvent); virtual;
+      function    ShouldSave: boolean; virtual;
+      function    IsChangedOnDisk : boolean;
+    public
+      procedure   BindingsChanged; virtual;
+    private
+      OnDiskLoadTime : longint;
+    end;
+
+function DefUseSyntaxHighlight(Editor: PFileEditor): boolean;
+function DefUseTabsPattern(Editor: PFileEditor): boolean;
+
+const
+     DefaultCodeEditorFlags : longint =
+       efBackupFiles+efInsertMode+efAutoIndent+efPersistentBlocks+
+       {efUseTabCharacters+}efBackSpaceUnindents+efSyntaxHighlight+
+       efExpandAllTabs+efCodeComplete;
+     DefaultTabSize     : integer = 8;
+     UseSyntaxHighlight : function(Editor: PFileEditor): boolean = DefUseSyntaxHighlight;
+     UseTabsPattern     : function(Editor: PFileEditor): boolean = DefUseTabsPattern;
+
+procedure RegisterWCEdit;
+
+implementation
+
+uses Dos,
+     Commands,App,WViews;
+
+{$ifndef NOOBJREG}
+const
+  RIndicator: TStreamRec = (
+     ObjType: 1100;
+     VmtLink: Ofs(TypeOf(TIndicator)^);
+     Load:    @TIndicator.Load;
+     Store:   @TIndicator.Store
+  );
+  RCodeEditor: TStreamRec = (
+     ObjType: 1101;
+     VmtLink: Ofs(TypeOf(TCodeEditor)^);
+     Load:    @TCodeEditor.Load;
+     Store:   @TCodeEditor.Store
+  );
+  RFileEditor: TStreamRec = (
+     ObjType: 1102;
+     VmtLink: Ofs(TypeOf(TFileEditor)^);
+     Load:    @TFileEditor.Load;
+     Store:   @TFileEditor.Store
+  );
+{$endif}
+
+constructor TLine.Init(const AText: string; AFlags: longint);
+begin
+  inherited Init(AText,AFlags);
+  New(EditorInfos, Init(10,10));
+end;
+
+procedure TLine.AddEditorInfo(Index: sw_integer; AEditor: PCustomCodeEditor);
+begin
+  EditorInfos^.AtInsert(Index,New(PEditorLineInfo, Init(AEditor)));
+end;
+
+procedure TLine.RemoveEditorInfo(AEditor: PCustomCodeEditor);
+var E: PEditorLineInfo;
+begin
+  E:=GetEditorInfo(AEditor);
+  EditorInfos^.Free(E);
+end;
+
+function TLine.GetText: string;
+begin
+  GetText:=GetStr(Text);
+end;
+
+procedure TLine.SetText(const AText: string);
+begin
+  SetStr(Text,AText);
+end;
+
+function TLine.GetEditorInfo(Editor: PCustomCodeEditor): PEditorLineInfo;
+function Match(P: PEditorLineInfo): boolean; {$ifdef TP}far;{$endif}
+begin
+  Match:=P^.Editor=Editor;
+end;
+begin
+  GetEditorInfo:=EditorInfos^.FirstThat(@Match);
+end;
+
+function TLine.GetFlags: longint;
+begin
+  GetFlags:=Flags;
+end;
+
+procedure TLine.SetFlags(AFlags: longint);
+begin
+  Flags:=AFlags;
+end;
+
+destructor TLine.Done;
+begin
+  if Assigned(Text) then DisposeStr(Text); Text:=nil;
+  if Assigned(EditorInfos) then Dispose(EditorInfos, Done); EditorInfos:=nil;
+  inherited Done;
+end;
+
+constructor TCodeEditorCore.Init;
+begin
+  inherited Init;
+{$ifndef Undo}
+  StoreUndo:=false;
+{$else Undo}
+  StoreUndo:=true;
+{$endif def Undo}
+  new(UndoList,init(500,1000));
+  new(RedoList,init(500,1000));
+  New(Lines, Init(500,1000));
+  TabSize:=DefaultTabSize;
+end;
+
+function TCodeEditorCore.GetLineCount: sw_integer;
+begin
+  GetLineCount:=Lines^.Count;
+end;
+
+function TCodeEditorCore.GetLine(LineNo: sw_integer): PCustomLine;
+begin
+  GetLine:=Lines^.At(LineNo);
+end;
+
+function TCodeEditorCore.GetModified: boolean;
+begin
+  GetModified:=Modified;
+end;
+
+procedure TCodeEditorCore.SetModified(AModified: boolean);
+begin
+  if AModified<>Modified then
+  begin
+    Modified:=AModified;
+    ModifiedChanged;
+  end;
+end;
+
+function TCodeEditorCore.GetStoreUndo: boolean;
+begin
+  GetStoreUndo:=StoreUndo;
+end;
+
+procedure TCodeEditorCore.SetStoreUndo(AStore: boolean);
+begin
+  if StoreUndo<>AStore then
+  begin
+    StoreUndo:=AStore;
+    StoreUndoChanged;
+  end;
+end;
+
+function TCodeEditorCore.GetSyntaxCompleted: boolean;
+begin
+{$ifdef TEST_PARTIAL_SYNTAX}
+  GetSyntaxCompleted:=SyntaxComplete;
+{$else}
+  GetSyntaxCompleted:=true;
+{$endif}
+end;
+
+procedure TCodeEditorCore.SetSyntaxCompleted(SC: boolean);
+begin
+{$ifdef TEST_PARTIAL_SYNTAX}
+  if SC<>SyntaxComplete then
+    begin
+      SyntaxComplete:=SC;
+    end;
+{$endif}
+end;
+function TCodeEditorCore.GetLastSyntaxedLine: sw_integer;
+begin
+  GetLastSyntaxedLine:=LastSyntaxedLine;
+end;
+
+procedure TCodeEditorCore.SetLastSyntaxedLine(ALine: sw_integer);
+begin
+  LastSyntaxedLine:=ALine;
+end;
+
+
+procedure TCodeEditorCore.ISetLineFlagState(Binding: PEditorBinding; LineNo: sw_integer; Flag: longint; ASet: boolean);
+var P: PCustomLine;
+begin
+  if LineNo<GetLineCount then
+  begin
+    P:=GetLine(LineNo);
+    P^.SetFlagState(Flag,ASet);
+  end;
+end;
+
+procedure TCodeEditorCore.GetContent(ALines: PUnsortedStringCollection);
+procedure AddIt(P: PCustomLine); {$ifndef FPC}far;{$endif}
+begin
+  if Assigned(P) then
+    ALines^.Insert(NewStr(P^.GetText));
+end;
+begin
+  if Assigned(Lines) then
+    Lines^.ForEach(@AddIt);
+end;
+
+procedure TCodeEditorCore.SetContent(ALines: PUnsortedStringCollection);
+procedure AddIt(P: PString); {$ifndef FPC}far;{$endif}
+begin
+  AddLine(GetStr(P));
+end;
+begin
+  DeleteAllLines;
+  if Assigned(ALines) then
+    ALines^.ForEach(@AddIt);
+  LimitsChanged;
+end;
+
+function TCodeEditorCore.GetTabSize: integer;
+begin
+  GetTabSize:=TabSize;
+end;
+
+procedure TCodeEditorCore.SetTabSize(ATabSize: integer);
+begin
+  if ATabSize<>TabSize then
+  begin
+    TabSize:=ATabSize;
+    TabSizeChanged;
+  end;
+end;
+
+function TCodeEditorCore.GetLineText(LineNo: sw_integer): string;
+var
+  L : PCustomLine;
+begin
+  GetLineText:='';
+  if LineNo<Lines^.Count then
+   begin
+     L:=Lines^.At(LineNo);
+     GetLineText:=L^.GetText;
+   end;
+end;
+
+procedure TCodeEditorCore.LinesInsert(Idx: sw_integer; Line: PLine);
+var I: sw_integer;
+procedure RegLine(P: PEditorBinding); {$ifndef FPC}far;{$endif}
+begin
+  Line^.AddEditorInfo(I,P^.Editor);
+  Inc(I);
+end;
+begin
+  if Idx=-1 then Idx:=Lines^.Count;
+  I:=0;
+  Bindings^.ForEach(@RegLine);
+  Lines^.AtInsert(Idx,Line);
+end;
+
+procedure TCodeEditorCore.SetLineText(I: sw_integer;const S: string);
+var
+  L : PCustomLine;
+  AddCount : Sw_Integer;
+begin
+  AddCount:=0;
+  while (Lines^.Count<I+1) do
+   begin
+     LinesInsert(-1,New(PLine, Init('',0)));
+     Inc(AddCount);
+   end;
+  if AddCount>0 then
+   LimitsChanged;
+  L:=Lines^.At(I);
+  L^.SetText(S);
+  ContentsChanged;
+end;
+
+function TCodeEditorCore.GetDisplayText(I: sw_integer): string;
+begin
+  GetDisplayText:=ExtractTabs(GetLineText(I),GetTabSize);
+end;
+
+procedure TCodeEditorCore.SetDisplayText(I: sw_integer;const S: string);
+begin
+  { I disagree here
+    I don't want the editor to change the position of the tabs
+    in my makefiles !! PM
+  if FlagSet(efUseTabCharacters) and (TabSize>0) then
+   SetLineText(I,CompressUsingTabs(S,TabSize))
+  else                  }
+  { ... then you better make this optional - Gabor }
+   SetLineText(I,S);
+end;
+
+procedure TCodeEditorCore.IGetDisplayTextFormat(Binding: PEditorBinding; LineNo: sw_integer;var DT,DF:string);
+var
+  L : PCustomLine;
+  P,PAdd : SW_Integer;
+begin
+  DF:='';
+  DT:='';
+  if LineNo<GetLineCount then
+   begin
+     L:=GetLine(LineNo);
+     DF:=IGetLineFormat(Binding,LineNo);
+     DT:=L^.GetText;
+     p:=0;
+     while p<length(DT) do
+      begin
+        inc(p);
+        if DT[p]=#9 then
+         begin
+           PAdd:=TabSize-((p-1) mod TabSize);
+           if DF<>'' then
+            DF:=copy(DF,1,P-1)+CharStr(DF[p],PAdd)+copy(DF,P+1,255);
+           DT:=copy(DT,1,P-1)+CharStr(' ',PAdd)+copy(DT,P+1,255);
+           inc(P,PAdd-1);
+         end;
+      end;
+   end;
+end;
+
+function TCodeEditorCore.IGetLineFormat(Binding: PEditorBinding; LineNo: sw_integer): string;
+var P: PCustomLine;
+    LI: PEditorLineInfo;
+    S: string;
+begin
+  if LineNo<GetLineCount then P:=GetLine(LineNo) else P:=nil;
+  if P=nil then LI:=nil else
+    LI:=P^.GetEditorInfo(Binding^.Editor);
+  if LI=nil then S:='' else S:=LI^.GetFormat;
+  IGetLineFormat:=S;
+end;
+
+procedure TCodeEditorCore.ISetLineFormat(Binding: PEditorBinding; LineNo: sw_integer;const S: string);
+var P: PCustomLine;
+    LI: PEditorLineInfo;
+begin
+  if LineNo<GetLineCount then
+  begin
+    P:=GetLine(LineNo);
+    if P=nil then LI:=nil else LI:=P^.GetEditorInfo(Binding^.Editor);
+    if Assigned(LI) then LI^.SetFormat(S);
+  end;
+end;
+
+procedure TCodeEditorCore.DeleteAllLines;
+begin
+  if Assigned(Lines) then
+    Lines^.FreeAll;
+end;
+
+procedure TCodeEditorCore.DeleteLine(I: sw_integer);
+var
+ CP : Tpoint;
+begin
+  if I<Lines^.Count then
+    begin
+      if StoreUndo then
+        begin
+          CP.X:=0;CP.Y:=I;
+          AddAction(eaDeleteLine,CP,CP,GetLineText(I));
+       end;
+      Lines^.AtFree(I);
+    end;
+end;
+
+procedure TCodeEditorCore.InsertLine(LineNo: sw_integer; const S: string);
+begin
+  LinesInsert(LineNo, New(PLine, Init(S,0)));
+end;
+
+procedure TCodeEditorCore.AddLine(const S: string);
+begin
+  LinesInsert(-1,New(PLine, Init(S,0)));
+end;
+
+procedure TCodeEditorCore.AddAction(AAction: byte; AStartPos, AEndPos: TPoint; AText: string);
+{$ifdef Undo}
+var
+  ActionIntegrated : boolean;
+  pa : PEditorAction;
+  S : String;
+{$endif Undo}
+begin
+{$ifdef Undo}
+  if (UndoList=nil) or (not StoreUndo) then Exit;
+  ActionIntegrated:=false;
+  if UndoList^.count>0 then
+    begin
+      pa:=UndoList^.At(UndoList^.count-1);
+      if (pa^.action=AAction) and
+         (pa^.EndPos.X=AStartPos.X) and
+         (pa^.EndPos.Y=AStartPos.Y) and
+         { do not group InsertLine and DeleteLine !! }
+         ((AAction=eaMoveCursor) or
+          (AAction=eaInsertText) or
+          (AAction=eaDeleteText))
+         then
+        begin
+          pa^.EndPos:=AEndPos;
+          S:=GetStr(pa^.text);
+          if S<>'' then
+           DisposeStr(pa^.text);
+          if (AAction=eaDeleteText) and
+             (AStartPos.X>AEndPos.X) then
+            pa^.text:=NewStr(AText+S)
+          else
+            pa^.text:=NewStr(S+AText);
+          ActionIntegrated:=true;
+        end;
+    end;
+  if not ActionIntegrated then
+    begin
+      UndoList^.Insert(New(PEditorAction,Init(AAction,AStartPos,AEndPos,AText)));
+      if assigned(UndoList^.CurrentGroupedAction) then
+        Inc(UndoList^.CurrentGroupedAction^.actionCount);
+      UpdateUndoRedo(cmUndo,AAction);
+    end;
+  if UndoList^.count>0 then
+  begin
+    UpdateUndoRedo(cmRedo,0);
+    RedoList^.FreeAll;
+  end;
+{$endif Undo}
+end;
+
+procedure TCodeEditorCore.AddGroupedAction(AAction : byte);
+begin
+{$ifdef Undo}
+  UndoList^.CurrentGroupedAction:=New(PEditorAction,Init_group(AAction));
+{$endif Undo}
+end;
+
+procedure TCodeEditorCore.CloseGroupedAction(AAction : byte);
+begin
+{$ifdef Undo}
+  UndoList^.Insert(UndoList^.CurrentGroupedAction);
+  UndoList^.CurrentGroupedAction:=nil;
+  UpdateUndoRedo(cmUndo,AAction);
+{$endif Undo}
+end;
+
+function TCodeEditorCore.GetUndoActionCount: sw_integer;
+begin
+  GetUndoActionCount:=UndoList^.Count;
+end;
+
+function TCodeEditorCore.GetRedoActionCount: sw_integer;
+begin
+  GetRedoActionCount:=RedoList^.Count;
+end;
+
+destructor TCodeEditorCore.Done;
+begin
+  inherited Done;
+  if Assigned(Lines) then Dispose(Lines, Done); Lines:=nil;
+  if Assigned(RedoList) then Dispose(RedoList, Done); RedoList:=nil;
+  if Assigned(UndoList) then Dispose(UndoList, Done); UndoList:=nil;
+end;
+
+constructor TIndicator.Init(var Bounds: TRect);
+begin
+  inherited Init(Bounds);
+  GrowMode := gfGrowLoY + gfGrowHiY;
+end;
+
+procedure TIndicator.Draw;
+var
+  Color: Byte;
+  Frame: Char;
+  L: array[0..1] of Longint;
+  S: String[15];
+  B: TDrawBuffer;
+begin
+  if (State and sfDragging = 0) and (State and sfActive <> 0) then
+   begin
+     Color := GetColor(1);
+     Frame := #205;
+   end
+  else
+   begin
+     if (State and sfDragging)<>0 then
+      Color := GetColor(2)
+     else
+      Color := GetColor(3);
+     Frame := #196;
+   end;
+  MoveChar(B, Frame, Color, Size.X);
+  if State and sfActive<>0 then
+   begin
+     if Modified then
+       WordRec (B[0]).Lo := ord('*');
+{$ifdef debug}
+     if StoreUndo then
+       WordRec (B[1]).Lo := ord('S');
+     if SyntaxComplete then
+       WordRec(B[2]).lo := ord('C');
+     if UseTabs then
+       WordRec(B[3]).lo := ord('T');
+{$endif debug}
+     L[0] := Location.Y + 1;
+     L[1] := Location.X + 1;
+     FormatStr(S, '%d:%d ', L);
+     MoveStr(B[8 - Pos(':', S)], S, Color);
+   end;
+  WriteBuf(0, 0, Size.X, 1, B);
+end;
+
+function TIndicator.GetPalette: PPalette;
+const
+  P: string[Length(CIndicator)] = CIndicator;
+begin
+  GetPalette := @P;
+end;
+
+procedure TIndicator.SetState(AState: Word; Enable: Boolean);
+begin
+  inherited SetState(AState, Enable);
+  if (AState = sfDragging) or (AState=sfActive) then
+   DrawView;
+end;
+
+procedure TIndicator.SetValue(ALocation: TPoint; AModified: Boolean);
+begin
+  if (Location.X<>ALocation.X) or
+     (Location.Y<>ALocation.Y) or
+     (Modified <> AModified) then
+  begin
+    Location := ALocation;
+    Modified := AModified;
+    DrawView;
+  end;
+end;
+
+{constructor TIndicator.Load(var S: TStream);
+begin
+  inherited Load(S);
+  S.Read(Location,SizeOf(Location));
+  S.Read(Modified,SizeOf(Modified));
+end;
+
+procedure TIndicator.Store(var S: TStream);
+begin
+  inherited Store(S);
+  S.Write(Location,SizeOf(Location));
+  S.Write(Modified,SizeOf(Modified));
+end;}
+
+{*****************************************************************************
+                TCodeEditor
+*****************************************************************************}
+
+constructor TCodeEditor.Init(var Bounds: TRect; AHScrollBar, AVScrollBar:
+          PScrollBar; AIndicator: PIndicator; ACore: PCodeEditorCore);
+begin
+  inherited Init(Bounds,AHScrollBar,AVScrollBar);
+  if ACore=nil then ACore:=New(PCodeEditorCore, Init);
+  Core:=ACore;
+  Core^.BindEditor(@Self);
+  SetState(sfCursorVis,true);
+  SetFlags(DefaultCodeEditorFlags);
+  SetCurPtr(0,0);
+  Indicator:=AIndicator;
+  UpdateIndicator;
+  LimitsChanged;
+end;
+
+function TCodeEditor.GetFlags: longint;
+begin
+  GetFlags:=Flags;
+end;
+
+procedure TCodeEditor.SetFlags(AFlags: longint);
+var OFlags: longint;
+begin
+  if AFlags<>Flags then
+  begin
+    OFlags:=Flags;
+    Flags:=AFlags;
+    FlagsChanged(OFlags);
+  end;
+end;
+
+function TCodeEditor.GetModified: boolean;
+begin
+  GetModified:=Core^.GetModified;
+end;
+
+procedure TCodeEditor.SetModified(AModified: boolean);
+begin
+  Core^.SetModified(AModified);
+end;
+
+function TCodeEditor.GetStoreUndo: boolean;
+begin
+  GetStoreUndo:=Core^.GetStoreUndo;
+end;
+
+procedure TCodeEditor.SetStoreUndo(AStore: boolean);
+begin
+  Core^.SetStoreUndo(AStore);
+end;
+
+function TCodeEditor.GetSyntaxCompleted: boolean;
+begin
+  GetSyntaxCompleted:=Core^.GetSyntaxCompleted;
+end;
+
+procedure TCodeEditor.SetSyntaxCompleted(SC : boolean);
+begin
+  Core^.SetSyntaxCompleted(SC);
+end;
+
+function TCodeEditor.GetLastSyntaxedLine: sw_integer;
+begin
+  GetLastSyntaxedLine:=Core^.GetLastSyntaxedLine;
+end;
+
+procedure TCodeEditor.SetLastSyntaxedLine(ALine: sw_integer);
+begin
+  Core^.SetLastSyntaxedLine(ALine);
+end;
+
+function TCodeEditor.GetTabSize: integer;
+begin
+  GetTabSize:=Core^.GetTabSize;
+end;
+
+procedure TCodeEditor.SetTabSize(ATabSize: integer);
+begin
+  Core^.SetTabSize(ATabSize);
+end;
+
+function TCodeEditor.IsReadOnly: boolean;
+begin
+  IsReadOnly:=ReadOnly or (Core^.ReadOnly);
+end;
+
+function TCodeEditor.IsClipboard: Boolean;
+begin
+  IsClipboard:=Core^.IsClipboard;
+end;
+
+function TCodeEditor.GetErrorMessage: string;
+begin
+  GetErrorMessage:=GetStr(ErrorMessage);
+end;
+
+procedure TCodeEditor.SetErrorMessage(const S: string);
+begin
+  SetStr(ErrorMessage,S);
+  DrawView;
+end;
+
+function TCodeEditor.GetLineCount: sw_integer;
+begin
+  GetLineCount:=Core^.GetLineCount;
+end;
+
+function TCodeEditor.GetLine(LineNo: sw_integer): PCustomLine;
+begin
+  GetLine:=Core^.GetLine(LineNo);
+end;
+
+function TCodeEditor.CharIdxToLinePos(Line,CharIdx: sw_integer): sw_integer;
+begin
+  CharIdxToLinePos:=Core^.CharIdxToLinePos(Line,CharIdx);
+end;
+
+function TCodeEditor.LinePosToCharIdx(Line,X: sw_integer): sw_integer;
+begin
+  LinePosToCharIdx:=Core^.LinePosToCharIdx(Line,X);
+end;
+
+function TCodeEditor.GetLineText(I: sw_integer): string;
+begin
+  GetLineText:=Core^.GetLineText(I);
+end;
+
+procedure TCodeEditor.SetDisplayText(I: sw_integer;const S: string);
+begin
+  Core^.SetDisplayText(I,S);
+end;
+
+function TCodeEditor.GetDisplayText(I: sw_integer): string;
+begin
+  GetDisplayText:=Core^.GetDisplayText(I);
+end;
+
+procedure TCodeEditor.SetLineText(I: sw_integer;const S: string);
+begin
+  Core^.SetLineText(I,S);
+end;
+
+procedure TCodeEditor.GetDisplayTextFormat(I: sw_integer;var DT,DF:string);
+begin
+  Core^.GetDisplayTextFormat(@Self,I,DT,DF);
+end;
+
+function TCodeEditor.GetLineFormat(I: sw_integer): string;
+begin
+  GetLineFormat:=Core^.GetLineFormat(@Self,I);
+end;
+
+procedure TCodeEditor.SetLineFormat(I: sw_integer;const S: string);
+begin
+  Core^.SetLineFormat(@Self,I,S);
+end;
+
+procedure TCodeEditor.DeleteAllLines;
+begin
+  Core^.DeleteAllLines;
+end;
+
+procedure TCodeEditor.DeleteLine(I: sw_integer);
+begin
+  Core^.DeleteLine(I);
+end;
+
+procedure TCodeEditor.InsertLine(LineNo: sw_integer; const S: string);
+begin
+  Core^.InsertLine(LineNo,S);
+end;
+
+procedure TCodeEditor.AddLine(const S: string);
+begin
+  Core^.AddLine(S);
+end;
+
+{function TCodeEditor.GetLineTextPos(Line,X: integer): integer;
+var
+  S: string;
+  rx,i : Sw_integer;
+begin
+  S:=GetLineText(Line);
+  i:=0; rx:=0;
+  while (RX<X) and (i<Length(s)) do
+   begin
+     inc(i);
+     inc(rx);
+     if s[i]=#9 then
+      inc(rx,TabSize-(rx mod tabsize));
+   end;
+  if RX<X then Inc(I,X-RX);
+  GetLineTextPos:=i;
+end;
+
+function TCodeEditor.GetDisplayTextPos(Line,X: integer): integer;
+var
+  S: string;
+  L: PCustomLine;
+  rx,i : Sw_integer;
+begin
+  S:='';
+  if Line<Lines^.Count then
+   begin
+     L:=Lines^.At(Line);
+     if assigned(L^.Text) then
+      S:=L^.Text^;
+   end;
+  i:=0;
+  rx:=0;
+  while (i<X) and (i<Length(s)) do
+   begin
+     inc(i);
+     inc(rx);
+     if s[i]=#9 then
+      inc(rx,TabSize-(rx mod tabsize));
+   end;
+  GetDisplayTextPos:=rx;
+end;}
+
+procedure TCodeEditor.GetContent(ALines: PUnsortedStringCollection);
+begin
+  Core^.GetContent(ALines);
+end;
+
+procedure TCodeEditor.SetContent(ALines: PUnsortedStringCollection);
+begin
+  Lock;
+  TextStart; HideSelect;
+  Core^.SetContent(ALines);
+  LimitsChanged;
+  if IsFlagSet(efSyntaxHighlight) then
+    Core^.UpdateAttrsRange(0,Min(Delta.Y+Size.Y,GetLineCount-1),
+      attrAll
+{$ifndef TEST_PARTIAL_SYNTAX}
+      +attrForceFull
+{$endif TEST_PARTIAL_SYNTAX}
+      );
+  TextStart;
+  UnLock;
+end;
+
+function TCodeEditor.GetCodeCompleteFrag: string;
+begin
+  GetCodeCompleteFrag:=GetStr(CodeCompleteFrag);
+end;
+
+procedure TCodeEditor.SetCodeCompleteFrag(const S: string);
+begin
+  SetStr(CodeCompleteFrag,S);
+end;
+
+function TCodeEditor.GetCompleteState: TCompleteState;
+begin
+  GetCompleteState:=CompleteState;
+end;
+
+procedure TCodeEditor.SetCompleteState(AState: TCompleteState);
+begin
+  if AState<>CompleteState then
+  begin
+    CompleteState:=AState;
+    if CompleteState<>csOffering then
+      ClearCodeCompleteWord;
+  end;
+end;
+
+function TCodeEditor.GetCodeCompleteWord: string;
+begin
+  GetCodeCompleteWord:=GetStr(CodeCompleteWord);
+end;
+
+procedure TCodeEditor.SetCodeCompleteWord(const S: string);
+begin
+  if Assigned(CodeCompleteWord) then DisposeStr(CodeCompleteWord);
+  CodeCompleteWord:=NewStr(S);
+  inherited SetCodeCompleteWord(S);
+end;
+
+procedure TCodeEditor.DrawIndicator;
+begin
+  if Assigned(Indicator) then
+    Indicator^.DrawView;
+end;
+
+procedure TCodeEditor.Lock;
+begin
+  inherited Lock;
+  Core^.Lock(@Self);
+end;
+
+procedure TCodeEditor.UnLock;
+begin
+  Core^.UnLock(@Self);
+  inherited UnLock;
+  If IndicatorDrawCalled then
+    begin
+      DrawIndicator;
+      IndicatorDrawCalled:=false;
+    end;
+end;
+
+procedure TCodeEditor.UpdateIndicator;
+begin
+  if Indicator<>nil then
+  begin
+    Indicator^.Location:=CurPos;
+    Indicator^.Modified:=GetModified;
+{$ifdef debug}
+    Indicator^.StoreUndo:=GetStoreUndo;
+{$ifdef TEST_PARTIAL_SYNTAX}
+    Indicator^.SyntaxComplete:=GetSyntaxCompleted and IsFlagSet(efSyntaxHighlight);
+{$endif TEST_PARTIAL_SYNTAX}
+    Indicator^.UseTabs:=IsFlagSet(efUseTabCharacters);
+{$endif debug}
+    if lockflag>0 then
+      IndicatorDrawCalled:=true
+    else
+      Indicator^.DrawView;
+  end;
+end;
+
+procedure TCodeEditor.LimitsChanged;
+begin
+  Core^.LimitsChanged;
+end;
+
+procedure TCodeEditor.ModifiedChanged;
+begin
+  UpdateIndicator;
+end;
+
+procedure TCodeEditor.JumpToLastCursorPos;
+{$ifdef Undo}
+var
+  pa : PEditorAction;
+{$endif Undo}
+begin
+{$ifdef Undo}
+  if (Core^.UndoList^.count>0) and (Core^.RedoList^.count=0) then
+    begin
+      { Or should we just call Undo ?? PM }
+      pa:=Core^.UndoList^.At(Core^.UndoList^.count-1);
+      if (pa^.action=eaMoveCursor) then
+        SetCurPtr(pa^.StartPos.X,pa^.StartPos.Y);
+    end;
+{$else not Undo}
+  NotImplemented;
+{$endif Undo}
+end;
+
+procedure TCodeEditor.Undo;
+{$ifdef Undo}
+var
+  Temp,Idx,Last,Count : Longint;
+  Is_grouped : boolean;
+{$endif Undo}
+begin
+{$ifdef Undo}
+  Core^.SetStoreUndo(False);
+  Lock;
+  if Core^.UndoList^.count > 0 then
+  begin
+    Last:=Core^.UndoList^.count-1;
+    if Core^.UndoList^.At(Last)^.Is_grouped_action then
+      begin
+        Count:=Core^.UndoList^.At(Last)^.ActionCount;
+        Dec(Last);
+        Is_grouped:=true;
+      end
+    else
+      begin
+        Count:=1;
+        Is_grouped:=false;
+      end;
+    for Idx:=Last downto Last-Count+1 do
+      with Core^.UndoList^.At(Idx)^ do
+        begin
+          case action of
+            eaMoveCursor :
+              begin
+                { move cursor back to original position }
+                SetCurPtr(startpos.x,startpos.y);
+              end;
+            eaInsertText :
+              begin
+                SetCurPtr(StartPos.X,StartPos.Y);
+                if assigned(text) then
+                  for Temp := 1 to length(Text^) do
+                    DelChar;
+              end;
+            eaDeleteText :
+              begin
+                { reinsert deleted text }
+                SetCurPtr(EndPos.X,EndPos.Y);
+                if assigned(text) then
+                  for Temp := 1 to length(Text^) do
+                    AddChar(Text^[Temp]);
+                SetCurPtr(StartPos.X,StartPos.Y);
+              end;
+            eaInsertLine :
+              begin
+                SetCurPtr(EndPos.X,EndPos.Y);
+                SetDisplayText(EndPos.Y,Copy(GetDisplayText(EndPos.Y),EndPos.X+1,255));
+                BackSpace;
+                SetCurPtr(StartPos.X,StartPos.Y);
+              end;
+            eaDeleteLine :
+              begin
+                SetCurPtr(EndPos.X,EndPos.Y);
+                DelEnd;
+                InsertNewLine;
+                SetCurPtr(StartPos.X,StartPos.Y);
+                SetLineText(StartPos.Y,GetStr(Text));
+              end;
+            eaSelectionChanged :
+              begin
+                { move cursor to end of last set selection }
+              end;
+          else
+            { what the 'ell's an undefined action doing round 'ere mate! }
+          end; { once this lot is done paste into redo and modify to suit needs }
+          { move item to redo stack }
+          Core^.RedoList^.Insert(Core^.UndoList^.At(Idx));
+          UpdateUndoRedo(cmRedo,Core^.UndoList^.At(Idx)^.Action);
+          Core^.UndoList^.atDelete(Idx);
+          If Idx>0 then
+            UpdateUndoRedo(cmUndo,Core^.UndoList^.At(Idx-1)^.Action)
+          else
+            UpdateUndoRedo(cmUndo,0);
+        end;{Idx loop for grouped actions }
+      if is_grouped then
+        begin
+          Idx:=Core^.UndoList^.Count-1;
+          Core^.RedoList^.Insert(Core^.UndoList^.At(Idx));
+          UpdateUndoRedo(cmRedo,Core^.UndoList^.At(Idx)^.Action);
+          Core^.UndoList^.atDelete(Idx);
+          If Idx>0 then
+            UpdateUndoRedo(cmUndo,Core^.UndoList^.At(Idx-1)^.Action)
+          else
+            UpdateUndoRedo(cmUndo,0);
+        end;
+      if Core^.UndoList^.count=0 then
+        SetCmdState(UndoCmd,false);
+      SetCmdState(RedoCmd,true);
+      Message(Application,evBroadcast,cmCommandSetChanged,nil);
+      DrawView;
+    end;
+  Core^.SetStoreUndo(True);
+  Unlock;
+{$else}
+  NotImplemented; Exit;
+{$endif Undo}
+end;
+
+procedure TCodeEditor.Redo;
+{$ifdef Undo}
+var
+  Temp,Idx,Last,Count : Longint;
+  Is_grouped : boolean;
+{$endif Undo}
+begin
+{$ifdef Undo}
+  Core^.SetStoreUndo(False);
+  Lock;
+  if Core^.RedoList^.count <> 0 then
+   begin
+    Last:=Core^.RedoList^.count-1;
+    if Core^.RedoList^.At(Last)^.Is_grouped_action then
+      begin
+        Count:=Core^.RedoList^.At(Last)^.ActionCount;
+        Dec(Last);
+        Is_grouped:=true;
+      end
+    else
+      begin
+        Count:=1;
+        Is_grouped:=false;
+      end;
+    for Idx:=Last downto Last-Count+1 do
+    with Core^.RedoList^.At(Idx)^ do
+    begin
+      case action of
+        eaMoveCursor :
+          begin
+            { move cursor back to original position }
+            SetCurPtr(EndPos.X,EndPos.Y);
+          end;
+        eaInsertText :
+          begin
+            SetCurPtr(startpos.x,startpos.y);
+            InsertText(GetStr(Text));
+          end;
+        eaDeleteText :
+          begin
+            SetCurPtr(EndPos.X,EndPos.Y);
+            for Temp := 1 to length(GetStr(Text)) do
+              DelChar;
+          end;
+        eaInsertLine :
+          begin
+            SetCurPtr(StartPos.X,StartPos.Y);
+            InsertNewLine;
+            SetCurPtr(StartPos.X,StartPos.Y);
+            InsertText(GetStr(Text));
+            SetCurPtr(EndPos.X,EndPos.Y);
+          end;
+        eaDeleteLine :
+          begin
+            SetCurPtr(StartPos.X,StartPos.Y);
+            DeleteLine(StartPos.Y);
+            { SetCurPtr(EndPos.X,EndPos.Y);
+            for Temp := 1 to length(GetStr(Text)) do
+              DelChar;}
+            SetCurPtr(EndPos.X,EndPos.Y);
+          end;
+        eaSelectionChanged :
+          begin
+            { move cursor to end of last set test selection }
+          end;
+      else
+        { what the 'ell's an undefined action doing round 'ere mate! }
+      end; { once this lot is done paste back into undo and modify to suit needs }
+    { move item to undo stack }
+      Core^.UndoList^.Insert(Core^.RedoList^.At(Idx));
+      UpdateUndoRedo(cmUndo,Core^.RedoList^.At(Idx)^.Action);
+      If Idx>0 then
+        UpdateUndoRedo(cmRedo,Core^.RedoList^.At(Idx-1)^.Action)
+      else
+        UpdateUndoRedo(cmRedo,0);
+      Core^.RedoList^.atDelete(Idx);
+      end;{ Idx loop for grouped action }
+      If is_grouped then
+        begin
+          Idx:=Core^.RedoList^.count-1;
+          Core^.UndoList^.Insert(Core^.RedoList^.At(Idx));
+          UpdateUndoRedo(cmUndo,Core^.RedoList^.At(Idx)^.Action);
+          If Idx>0 then
+            UpdateUndoRedo(cmRedo,Core^.RedoList^.At(Idx-1)^.Action)
+          else
+            UpdateUndoRedo(cmRedo,0);
+          Core^.RedoList^.atDelete(Idx);
+        end;
+      if Core^.RedoList^.count=0 then
+        SetCmdState(RedoCmd,false);
+      SetCmdState(UndoCmd,true);
+      DrawView;
+      Message(Application,evBroadcast,cmCommandSetChanged,nil);
+    end;
+  Core^.SetStoreUndo(True);
+  Unlock;
+{$else}
+  NotImplemented; Exit;
+{$endif Undo}
+end;
+
+(*constructor TCodeEditor.Load(var S: TStream);
+var TS: PSubStream;
+    TSize: longint;
+begin
+  inherited Load(S);
+
+  New(UndoList,init(500,1000));
+  New(RedoList,init(500,1000));
+
+  New(Lines, Init(500,1000));
+  { we have always need at least 1 line }
+  LinesInsert(New(PLine, Init('',0)));
+
+  GetPeerViewPtr(S,Indicator);
+  S.Read(Flags,SizeOf(Flags));
+  S.Read(TabSize,SizeOf(TabSize));
+
+  if IsFlagSet(efStoreContent) then
+    begin
+      S.Read(TSize,SizeOf(TSize));
+      New(TS, Init(@S,S.GetPos,TSize));
+{$ifdef TEST_PARTIAL_SYNTAX}
+      Core^.SearchBinding(Editor)^.SyntaxComplete:=false;
+      { Idle necessary }
+      EventMask:=EventMask or evIdle;
+{$endif TEST_PARTIAL_SYNTAX}
+      LoadFromStream(TS);
+      Dispose(TS, Done);
+    end;
+
+  S.Read(SelStart,SizeOf(SelStart));
+  S.Read(SelEnd,SizeOf(SelEnd));
+  S.Read(Highlight,SizeOf(Highlight));
+  S.Read(CurPos,SizeOf(CurPos));
+  S.Read(StoreUndo,SizeOf(StoreUndo));
+  S.Read(IsReadOnly,SizeOf(IsReadOnly));
+  S.Read(NoSelect,SizeOf(NoSelect));
+  S.Read(HighlightRow,SizeOf(HighlightRow));
+  SetDebuggerRow(-1);
+
+  LimitsChanged;
+  SelectionChanged; HighlightChanged;
+  UpdateIndicator;
+end;
+
+procedure TCodeEditor.Store(var S: TStream);
+var {NS: TNulStream;}
+    TSizePos,TSize,EndPos: longint;
+begin
+  inherited Store(S);
+
+  PutPeerViewPtr(S,Indicator);
+  S.Write(Flags,SizeOf(Flags));
+  S.Write(TabSize,SizeOf(TabSize));
+
+  if IsFlagSet(efStoreContent) then
+    begin
+      { NS.Init;
+      SaveToStream(@NS);
+      TSize:=NS.GetSize;
+      NS.Done;
+        This is waste of time PM
+        use Seek instead !! }
+      { yep. and this won't work for serial streams. - Gabor }
+      TSize:=0;
+      TSizePos:=S.GetPos;
+      S.Write(TSize,SizeOf(TSize));
+      SaveToStream(@S);
+      EndPos:=S.GetPos;
+      TSize:=EndPos-TSizePos-SizeOf(TSize);
+      S.Seek(TSizePos);
+      S.Write(TSize,SizeOf(TSize));
+      S.Seek(EndPos);
+    end;
+
+  S.Write(SelStart,SizeOf(SelStart));
+  S.Write(SelEnd,SizeOf(SelEnd));
+  S.Write(Highlight,SizeOf(Highlight));
+  S.Write(CurPos,SizeOf(CurPos));
+  S.Write(StoreUndo,SizeOf(StoreUndo));
+  S.Write(IsReadOnly,SizeOf(IsReadOnly));
+  S.Write(NoSelect,SizeOf(NoSelect));
+  S.Write(HighlightRow,SizeOf(HighlightRow));
+end;*)
+
+function TCodeEditor.LoadFromStream(Stream: PStream): boolean;
+var OK: boolean;
+begin
+  OK:=Core^.LoadFromStream(@Self,Stream);
+  if IsFlagSet(efSyntaxHighlight) then
+    UpdateAttrsRange(0,Min(Delta.Y+Size.Y,GetLineCount-1),
+      attrAll
+{$ifndef TEST_PARTIAL_SYNTAX}
+      +attrForceFull
+{$endif TEST_PARTIAL_SYNTAX}
+      );
+  TextStart;
+  LoadFromStream:=OK;
+end;
+
+function TCodeEditor.SaveToStream(Stream: PStream): boolean;
+begin
+  SaveToStream:=Core^.SaveToStream(@Self,Stream);
+end;
+
+function TCodeEditor.SaveAreaToStream(Stream: PStream; StartP,EndP: TPoint): boolean;
+begin
+  SaveAreaToStream:=Core^.SaveAreaToStream(@Self,Stream,StartP,EndP);
+end;
+
+function TCodeEditor.UpdateAttrs(FromLine: sw_integer; Attrs: byte): sw_integer;
+begin
+  UpdateAttrs:=Core^.UpdateAttrs(FromLine,Attrs);
+end;
+
+function TCodeEditor.UpdateAttrsRange(FromLine, ToLine: sw_integer; Attrs: byte): sw_integer;
+begin
+  UpdateAttrsRange:=Core^.UpdateAttrsRange(FromLine,ToLine,Attrs);
+end;
+
+procedure TCodeEditor.AddAction(AAction: byte; AStartPos, AEndPos: TPoint; AText: string);
+begin
+  Core^.AddAction(AAction,AStartPos,AEndPos,AText);
+end;
+
+procedure TCodeEditor.AddGroupedAction(AAction : byte);
+begin
+  Core^.AddGroupedAction(AAction);
+end;
+
+procedure TCodeEditor.CloseGroupedAction(AAction : byte);
+begin
+  Core^.CloseGroupedAction(AAction);
+end;
+
+function TCodeEditor.GetUndoActionCount: sw_integer;
+begin
+  GetUndoActionCount:=Core^.GetUndoActionCount;
+end;
+
+function TCodeEditor.GetRedoActionCount: sw_integer;
+begin
+  GetRedoActionCount:=Core^.GetRedoActionCount;
+end;
+
+destructor TCodeEditor.Done;
+begin
+  inherited Done;
+  if Assigned(Core) then
+  begin
+    Core^.UnBindEditor(@Self);
+    if Core^.CanDispose then
+      Dispose(Core, Done);
+  end;
+  Core:=nil;
+  if Assigned(CodeCompleteFrag) then
+    DisposeStr(CodeCompleteFrag);
+  if Assigned(CodeCompleteWord) then
+    DisposeStr(CodeCompleteWord);
+end;
+
+constructor TFileEditor.Init(var Bounds: TRect; AHScrollBar, AVScrollBar:
+       PScrollBar; AIndicator: PIndicator;ACore: PCodeEditorCore; const AFileName: string);
+begin
+  inherited Init(Bounds,AHScrollBAr,AVScrollBAr,AIndicator,ACore);
+  FileName:=AFileName;
+  UpdateIndicator;
+  Message(@Self,evBroadcast,cmFileNameChanged,@Self);
+  OnDiskLoadTime:=-1;
+end;
+
+function TFileEditor.LoadFile: boolean;
+var S: PBufStream;
+    OK: boolean;
+begin
+  New(S, Init(FileName,stOpenRead,EditorTextBufSize));
+  OK:=Assigned(S);
+{$ifdef TEST_PARTIAL_SYNTAX}
+  SetSyntaxCompleted(false);
+  { Idle necessary }
+  EventMask:=EventMask or evIdle;
+{$endif TEST_PARTIAL_SYNTAX}
+  if OK then OK:=LoadFromStream(S);
+  if Assigned(S) then Dispose(S, Done);
+  OnDiskLoadTime:=GetFileTime(FileName);
+  LoadFile:=OK;
+end;
+
+function TFileEditor.IsChangedOnDisk : boolean;
+begin
+  IsChangedOnDisk:=(OnDiskLoadTime<>GetFileTime(FileName)) and (OnDiskLoadTime<>-1);
+end;
+
+function TFileEditor.SaveFile: boolean;
+var OK: boolean;
+    BAKName: string;
+    S: PBufStream;
+    f: text;
+begin
+  If IsChangedOnDisk then
+    begin
+      if EditorDialog(edFileOnDiskChanged, @FileName) <> cmYes then
+        begin
+          SaveFile:=false;
+          exit;
+        end;
+    end;
+{$I-}
+  if IsFlagSet(efBackupFiles) and ExistsFile(FileName) then
+  begin
+     BAKName:=DirAndNameOf(FileName)+'.bak';
+     Assign(f,BAKName);
+     Erase(f);
+     EatIO;
+     Assign(f,FileName);
+     Rename(F,BAKName);
+     EatIO;
+  end;
+{$I+}
+  New(S, Init(FileName,stCreate,EditorTextBufSize));
+  OK:=Assigned(S) and (S^.Status=stOK);
+  if OK then OK:=SaveToStream(S);
+  if Assigned(S) then Dispose(S, Done);
+  if OK then
+    SetModified(false)
+  { Restore the original }
+  else if IsFlagSet(efBackupFiles) and ExistsFile(BakName) then
+    begin
+{$I-}
+     Assign(f,BakName);
+     Rename(F,FileName);
+     EatIO;
+{$I+}
+    end;
+  { don't forget to update the OnDiskLoadTime value }
+  if OK then
+    OnDiskLoadTime:=GetFileTime(FileName);
+  if not OK then
+    EditorDialog(edSaveError,@FileName);
+  SaveFile:=OK;
+end;
+
+function TFileEditor.ShouldSave: boolean;
+begin
+  ShouldSave:=GetModified{ or (FileName='')};
+end;
+
+function TFileEditor.Save: Boolean;
+begin
+  if ShouldSave=false then begin Save:=true; Exit; end;
+  if FileName = '' then Save := SaveAs else Save := SaveFile;
+end;
+
+function TFileEditor.SaveAs: Boolean;
+begin
+  SaveAs := False;
+  if EditorDialog(edSaveAs, @FileName) <> cmCancel then
+  begin
+    FileName := FExpand(FileName);
+    Message(Owner, evBroadcast, cmUpdateTitle, @Self);
+    { if we rename the file the OnDiskLoadTime is wrong so we reset it }
+    OnDiskLoadTime:=-1;
+    SaveAs := SaveFile;
+    if IsClipboard then FileName := '';
+    Message(Application,evBroadcast,cmFileNameChanged,@Self);
+  end;
+end;
+
+function TFileEditor.SaveAsk: boolean;
+var OK: boolean;
+    D: Sw_integer;
+begin
+  OK:=GetModified=false;
+  if (OK=false) and (Core^.GetBindingCount>1) then
+    OK:=true;
+  if OK=false then
+  begin
+    if FileName = '' then D := edSaveUntitled else D := edSaveModify;
+    case EditorDialog(D, @FileName) of
+      cmYes    : OK := Save;
+      cmNo     : begin SetModified(False); OK:=true; end;
+      cmCancel : begin
+                   OK := False;
+                   Message(Application,evBroadcast,cmSaveCancelled,@Self);
+                 end;
+    end;
+  end;
+  SaveAsk:=OK;
+end;
+
+procedure TFileEditor.BindingsChanged;
+begin
+  Message(Application,evBroadcast,cmUpdateTitle,@Self);
+end;
+
+procedure TFileEditor.HandleEvent(var Event: TEvent);
+var SH,B: boolean;
+begin
+  case Event.What of
+    evBroadcast :
+      case Event.Command of
+   cmFileNameChanged :
+     if (Event.InfoPtr=nil) or (Event.InfoPtr=@Self) then
+     begin
+       B:=IsFlagSet(efSyntaxHighlight);
+       SH:=UseSyntaxHighlight(@Self);
+       if SH<>B then
+         if SH then
+           SetFlags(Flags or efSyntaxHighlight)
+         else
+           SetFlags(Flags and not efSyntaxHighlight);
+       if UseTabsPattern(@Self) then
+         SetFlags(Flags or efUseTabCharacters);
+     end;
+      end;
+  end;
+  inherited HandleEvent(Event);
+end;
+
+function TFileEditor.Valid(Command: Word): Boolean;
+var OK: boolean;
+begin
+  OK:=inherited Valid(Command);
+  if OK and ((Command=cmClose) or (Command=cmQuit)) then
+     if IsClipboard=false then
+    OK:=SaveAsk;
+  Valid:=OK;
+end;
+
+(*constructor TFileEditor.Load(var S: TStream);
+var P: PString;
+    SSP,SEP,CP,DP: TPoint;
+    HR: TRect;
+    PA : Array[1..2] of pointer;
+    HoldUndo : boolean;
+begin
+  inherited Load(S);
+  HoldUndo:=GetStoreUndo;
+  SetStoreUndo(False);
+  P:=S.ReadStr;
+  FileName:=GetStr(P);
+  if P<>nil then DisposeStr(P);
+
+  UpdateIndicator;
+{  Message(@Self,evBroadcast,cmFileNameChanged,@Self);}
+
+  SSP:=SelStart; SEP:=SelEnd;
+  CP:=CurPos;
+  HR:=Highlight;
+  DP:=Delta;
+
+  if FileName<>'' then
+    LoadFile;
+
+{  if GetModified then
+    begin
+      PA[1]:=@FileName;
+      longint(PA[2]):=ChangedLine;
+      EditorDialog(edChangedOnloading,@PA);
+    end;}
+
+  SetHighlight(HR.A,HR.B);
+  SetSelection(SSP,SEP);
+  SetCurPtr(CP.X,CP.Y);
+  ScrollTo(DP.X,DP.Y);
+  SetModified(false);
+
+  LimitsChanged;
+  SetStoreUndo(HoldUndo);
+end;
+
+procedure TFileEditor.Store(var S: TStream);
+begin
+  inherited Store(S);
+  S.WriteStr(@FileName);
+end;
+*)
+
+function DefUseSyntaxHighlight(Editor: PFileEditor): boolean;
+begin
+  DefUseSyntaxHighlight:=Editor^.IsFlagSet(efSyntaxHighlight);
+end;
+
+function DefUseTabsPattern(Editor: PFileEditor): boolean;
+begin
+  DefUseTabsPattern:=Editor^.IsFlagSet(efUseTabCharacters);
+end;
+
+procedure RegisterWCEdit;
+begin
+{$ifndef NOOBJREG}
+  RegisterType(RIndicator);
+  RegisterType(RCodeEditor);
+  RegisterType(RFileEditor);
+{$endif}
+end;
+
+
+END.

File diff suppressed because it is too large
+ 3646 - 3338
ide/text/weditor.pas


Some files were not shown because too many files changed in this diff