1 {
2     This file is part of the Free Pascal Integrated Development Environment
3     Copyright (c) 1998-2000 by Berczi Gabor
4 
5     Code editor template objects
6 
7     See the file COPYING.FPC, included in this distribution,
8     for details about the copyright.
9 
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 
14  **********************************************************************}
15 {$i globdir.inc}
16 unit WCEdit;
17 
18 interface
19 
20 uses Objects,Drivers,Views,
21      WUtils,WEditor;
22 
23 type
24     PCodeEditor = ^TCodeEditor;
25 
26     PIndicator = ^TIndicator;
27     TIndicator = object(TView)
28       Location: TPoint;
29       Modified : Boolean;
30       CodeOwner : PCodeEditor;
31 {$ifdef debug}
32       StoreUndo : Boolean;
33       SyntaxComplete : boolean;
34       UseTabs : Boolean;
35 {$endif debug}
36       constructor Init(var Bounds: TRect);
37       procedure   Draw; virtual;
GetPalettenull38       function    GetPalette: PPalette; virtual;
39       procedure   SetState(AState: Word; Enable: Boolean); virtual;
40       procedure   SetValue(ALocation: TPoint; AModified: Boolean);
41     end;
42 
43     PLine = ^TLine;
44     TLine = object(TCustomLine)
45     public { internal use only! }
46       Text        : PString;
47       DefaultEditorInfo : PEditorLineInfo;
48       EditorInfos : PEditorLineInfoCollection;
49       Flags       : longint;
50       Owner       : PCustomCodeEditorCore;
51       procedure AddEditorInfo(Index: sw_integer; AEditor: PCustomCodeEditor); virtual;
52       procedure RemoveEditorInfo(AEditor: PCustomCodeEditor); virtual;
53     public
54       constructor Init(AOwner: PCustomCodeEditorCore; const AText: string; AFlags: longint);
GetTextnull55       function    GetText: string; virtual;
56       procedure   SetText(const AText: string); virtual;
GetEditorInfonull57       function    GetEditorInfo(Editor: PCustomCodeEditor): PEditorLineInfo; virtual;
GetFlagsnull58       function    GetFlags: longint; virtual;
59       procedure   SetFlags(AFlags: longint); virtual;
60       destructor  Done; virtual;
61     end;
62 
63     PCodeEditorCore = ^TCodeEditorCore;
64     TCodeEditorCore = object(TCustomCodeEditorCore)
65     protected
66       Lines      : PLineCollection;
67       CanUndo    : Boolean;
68       StoreUndo  : boolean;
69       Modified   : Boolean;
70       ReadOnly   : Boolean;
71       TabSize    : integer;
72       IndentSize  : integer;
73       ModifiedTime : cardinal;
74     public
75       UndoList   : PEditorActionCollection;
76       RedoList   : PEditorActionCollection;
77       constructor Init;
78       destructor  Done; virtual;
79       procedure   ChangeLinesTo(ALines : PLineCollection); virtual;
GetModifiednull80       function    GetModified: boolean; virtual;
81       procedure   SetModified(AModified: boolean); virtual;
GetModifyTimenull82       function    GetModifyTime: cardinal; virtual;
GetTabSizenull83       function    GetTabSize: integer; virtual;
84       procedure   SetTabSize(ATabSize: integer); virtual;
GetIndentSizenull85       function    GetIndentSize: integer; virtual;
86       procedure   SetIndentSize(AIndentSize: integer); virtual;
GetStoreUndonull87       function    GetStoreUndo: boolean; virtual;
88       procedure   SetStoreUndo(AStore: boolean); virtual;
GetSyntaxCompletednull89       function    GetSyntaxCompleted: boolean; virtual;
90       procedure   SetSyntaxCompleted(SC : boolean); virtual;
GetLastSyntaxedLinenull91       function    GetLastSyntaxedLine: sw_integer; virtual;
92       procedure   SetLastSyntaxedLine(ALine: sw_integer); virtual;
93       { Storage }
94     protected
95       { Text & info storage abstraction }
96       procedure   ISetLineFlagState(Binding: PEditorBinding; LineNo: sw_integer; Flag: longint; ASet: boolean); virtual;
97       procedure   IGetDisplayTextFormat(Binding: PEditorBinding; LineNo: sw_integer;var DT,DF:string); virtual;
IGetLineFormatnull98       function    IGetLineFormat(Binding: PEditorBinding; LineNo: sw_integer): string; virtual;
99       procedure   ISetLineFormat(Binding: PEditorBinding; LineNo: sw_integer;const S: string); virtual;
100     public
101       { Text & info storage abstraction }
GetLineCountnull102       function    GetLineCount: sw_integer; virtual;
GetLinenull103       function    GetLine(LineNo: sw_integer): PCustomLine; virtual;
GetLineTextnull104       function    GetLineText(LineNo: sw_integer): string; virtual;
105       procedure   SetDisplayText(I: sw_integer;const S: string); virtual;
GetDisplayTextnull106       function    GetDisplayText(I: sw_integer): string; virtual;
107       procedure   SetLineText(I: sw_integer;const S: string); virtual;
108       procedure   DeleteAllLines; virtual;
109       procedure   DeleteLine(I: sw_integer); virtual;
InsertLinenull110       function    InsertLine(LineNo: sw_integer; const S: string): PCustomLine; virtual;
111       procedure   AddLine(const S: string); virtual;
112       procedure   GetContent(ALines: PUnsortedStringCollection); virtual;
113       procedure   SetContent(ALines: PUnsortedStringCollection); virtual;
114    public
115      { Undo info storage }
116       procedure   AddAction(AAction: byte; AStartPos, AEndPos: TPoint; AText: string;AFlags : longint); virtual;
117       procedure   AddGroupedAction(AAction : byte); virtual;
118       procedure   CloseGroupedAction(AAction : byte); virtual;
GetUndoActionCountnull119       function    GetUndoActionCount: sw_integer; virtual;
GetRedoActionCountnull120       function    GetRedoActionCount: sw_integer; virtual;
121     private
122       OnDiskLoadTime : cardinal;
123       SystemLoadTime : cardinal;
124       procedure LinesInsert(Idx: sw_integer; Line: PLine);
125     end;
126 
127     TCodeEditor = object(TCustomCodeEditor)
128       Core       : PCodeEditorCore;
129       Flags      : longint;
130       Indicator  : PIndicator;
131       HighlightRow: sw_integer;
132       DebuggerRow: sw_integer;
133       CodeCompleteFrag: PString;
134       CodeCompleteWord: PString;
135       ReadOnly   : boolean;
136       CompleteState: TCompleteState;
137       ErrorMessage: PString;
138       IndicatorDrawCalled  : boolean;
139       Folds      : PFoldCollection;
140       MaxFoldLevel: sw_integer;
141       constructor Init(var Bounds: TRect; AHScrollBar, AVScrollBar:
142           PScrollBar; AIndicator: PIndicator; ACore: PCodeEditorCore);
143     public
144       procedure   DrawIndicator; virtual;
145     public
GetFlagsnull146       function    GetFlags: longint; virtual;
147       procedure   SetFlags(AFlags: longint); virtual;
GetModifiednull148       function    GetModified: boolean; virtual;
149       procedure   SetModified(AModified: boolean); virtual;
GetStoreUndonull150       function    GetStoreUndo: boolean; virtual;
151       procedure   SetStoreUndo(AStore: boolean); virtual;
152       procedure   ClearUndoList;
GetSyntaxCompletednull153       function    GetSyntaxCompleted: boolean; virtual;
154       procedure   SetSyntaxCompleted(SC : boolean); virtual;
GetLastSyntaxedLinenull155       function    GetLastSyntaxedLine: sw_integer; virtual;
156       procedure   SetLastSyntaxedLine(ALine: sw_integer); virtual;
GetTabSizenull157       function    GetTabSize: integer; virtual;
158       procedure   SetTabSize(ATabSize: integer); virtual;
GetIndentSizenull159       function    GetIndentSize: integer; virtual;
160       procedure   SetIndentSize(AIndentSize: integer); virtual;
IsReadOnlynull161       function    IsReadOnly: boolean; virtual;
162     public
163       procedure   UpdateIndicator; virtual;
164       procedure   ModifiedChanged; virtual;
165       procedure   PositionChanged; virtual;
166       procedure   LimitsChanged; virtual;
IsClipboardnull167       function    IsClipboard: Boolean; virtual;
LoadFromStreamnull168       function    LoadFromStream(Stream: PFastBufStream): boolean; virtual;
SaveToStreamnull169       function    SaveToStream(Stream: PStream): boolean; virtual;
SaveAreaToStreamnull170       function    SaveAreaToStream(Stream: PStream; StartP,EndP: TPoint): boolean;virtual;
171       destructor  Done; virtual;
172     public
173 {      ChangedLine : sw_integer;}
174       { Text & info storage abstraction }
GetLineCountnull175       function    GetLineCount: sw_integer; virtual;
GetLinenull176       function    GetLine(LineNo: sw_integer): PCustomLine; virtual;
CharIdxToLinePosnull177       function    CharIdxToLinePos(Line,CharIdx: sw_integer): sw_integer; virtual;
LinePosToCharIdxnull178       function    LinePosToCharIdx(Line,X: sw_integer): sw_integer; virtual;
GetLineTextnull179       function    GetLineText(I: sw_integer): string; virtual;
180       procedure   SetDisplayText(I: sw_integer;const S: string); virtual;
GetDisplayTextnull181       function    GetDisplayText(I: sw_integer): string; virtual;
182       procedure   SetLineText(I: sw_integer;const S: string); virtual;
183       procedure   GetDisplayTextFormat(I: sw_integer;var DT,DF:string); virtual;
GetLineFormatnull184       function    GetLineFormat(I: sw_integer): string; virtual;
185       procedure   SetLineFormat(I: sw_integer;const S: string); virtual;
186       procedure   DeleteAllLines; virtual;
187       procedure   DeleteLine(I: sw_integer); virtual;
InsertLinenull188       function    InsertLine(LineNo: sw_integer; const S: string): PCustomLine; virtual;
189       procedure   AddLine(const S: string); virtual;
GetErrorMessagenull190       function    GetErrorMessage: string; virtual;
191       procedure   SetErrorMessage(const S: string); virtual;
192       procedure   GetContent(ALines: PUnsortedStringCollection); virtual;
193       procedure   SetContent(ALines: PUnsortedStringCollection); virtual;
194       procedure   Lock; virtual;
195       procedure   UnLock; virtual;
196     public
197      { CodeComplete support }
GetCodeCompleteWordnull198       function    GetCodeCompleteWord: string; virtual;
199       procedure   SetCodeCompleteWord(const S: string); virtual;
GetCodeCompleteFragnull200       function    GetCodeCompleteFrag: string; virtual;
201       procedure   SetCodeCompleteFrag(const S: string); virtual;
GetCompleteStatenull202       function    GetCompleteState: TCompleteState; virtual;
203       procedure   SetCompleteState(AState: TCompleteState); virtual;
204    public
205       { Syntax highlight }
UpdateAttrsnull206    {a}function    UpdateAttrs(FromLine: sw_integer; Attrs: byte): sw_integer; virtual;
UpdateAttrsRangenull207    {a}function    UpdateAttrsRange(FromLine, ToLine: sw_integer; Attrs: byte): sw_integer; virtual;
208    public
209      { Undo info storage }
210       procedure   AddAction(AAction: byte; AStartPos, AEndPos: TPoint; AText: string;AFlags : longint); virtual;
211       procedure   AddGroupedAction(AAction : byte); virtual;
212       procedure   CloseGroupedAction(AAction : byte); virtual;
GetUndoActionCountnull213       function    GetUndoActionCount: sw_integer; virtual;
GetRedoActionCountnull214       function    GetRedoActionCount: sw_integer; virtual;
215       procedure   JumpToLastCursorPos; virtual;
216       procedure   Undo; virtual;
217       procedure   Redo; virtual;
218      { Fold support }
GetMaxFoldLevelnull219       function    GetMaxFoldLevel: sw_integer; virtual;
GetFoldCountnull220       function    GetFoldCount: sw_integer; virtual;
GetFoldnull221       function    GetFold(Index: sw_integer): PFold; virtual;
222       procedure   RegisterFold(AFold: PFold); virtual;
223       procedure   UnRegisterFold(AFold: PFold); virtual;
224     end;
225 
226     PFileEditor = ^TFileEditor;
227     TFileEditor = object(TCodeEditor)
228       FileName: string;
229       constructor Init(var Bounds: TRect; AHScrollBar, AVScrollBar:
230           PScrollBar; AIndicator: PIndicator; ACore: PCodeEditorCore; const AFileName: string);
Savenull231       function    Save: Boolean; virtual;
SaveAsnull232       function    SaveAs: Boolean; virtual;
SaveAsknull233       function    SaveAsk(Force: boolean): Boolean; virtual;
LoadFilenull234       function    LoadFile: boolean; virtual;
ReloadFilenull235       function    ReloadFile: boolean; virtual;
SaveFilenull236       function    SaveFile: boolean; virtual;
Validnull237       function    Valid(Command: Word): Boolean; virtual;
238       procedure   HandleEvent(var Event: TEvent); virtual;
ShouldSavenull239       function    ShouldSave: boolean; virtual;
IsChangedOnDisknull240       function    IsChangedOnDisk : boolean;
241     public
242       procedure   BindingsChanged; virtual;
243     end;
244 
DefUseSyntaxHighlightnull245 function DefUseSyntaxHighlight(Editor: PFileEditor): boolean;
DefUseTabsPatternnull246 function DefUseTabsPattern(Editor: PFileEditor): boolean;
247 
248 const
249      DefaultCodeEditorFlags : longint =
250        efBackupFiles+efInsertMode+efAutoIndent+efPersistentBlocks+
251        {efUseTabCharacters+}efBackSpaceUnindents+efSyntaxHighlight+
252        efExpandAllTabs+efCodeComplete{+efFolds};
253      DefaultTabSize     : integer = 8;
254      DefaultIndentSize   : integer = 1;
ditornull255      UseSyntaxHighlight : function(Editor: PFileEditor): boolean = {$ifdef fpc}@{$endif}DefUseSyntaxHighlight;
ditornull256      UseTabsPattern     : function(Editor: PFileEditor): boolean = {$ifdef fpc}@{$endif}DefUseTabsPattern;
257 
258 procedure RegisterWCEdit;
259 
260 implementation
261 
262 uses Dos,
263      WConsts,
264      FVConsts,
265      App,WViews;
266 
267 {$ifndef NOOBJREG}
268 const
269   RIndicator: TStreamRec = (
270      ObjType: 1100;
271      VmtLink: Ofs(TypeOf(TIndicator)^);
272      Load:    @TIndicator.Load;
273      Store:   @TIndicator.Store
274   );
275   RCodeEditor: TStreamRec = (
276      ObjType: 1101;
277      VmtLink: Ofs(TypeOf(TCodeEditor)^);
278      Load:    @TCodeEditor.Load;
279      Store:   @TCodeEditor.Store
280   );
281   RFileEditor: TStreamRec = (
282      ObjType: 1102;
283      VmtLink: Ofs(TypeOf(TFileEditor)^);
284      Load:    @TFileEditor.Load;
285      Store:   @TFileEditor.Store
286   );
287 {$endif}
288 
289 constructor TLine.Init(AOwner: PCustomCodeEditorCore; const AText: string; AFlags: longint);
290 begin
291   inherited Init(AText,AFlags);
292   // New(EditorInfos, Init(10,10));
293   Owner:=AOwner;
294 end;
295 
296 procedure TLine.AddEditorInfo(Index: sw_integer; AEditor: PCustomCodeEditor);
297 begin
298   if Index=0 then
299     begin
300       DefaultEditorInfo:=New(PEditorLineInfo, Init(AEditor));
301       exit;
302     end;
303   if not assigned(EditorInfos) then
304     begin
305       New(EditorInfos, Init(10,10));
306       EditorInfos^.AtInsert(0,DefaultEditorInfo);
307       DefaultEditorInfo:=nil;
308     end;
309   EditorInfos^.AtInsert(Index,New(PEditorLineInfo, Init(AEditor)));
310 end;
311 
312 procedure TLine.RemoveEditorInfo(AEditor: PCustomCodeEditor);
313 var E: PEditorLineInfo;
314 begin
315   E:=GetEditorInfo(AEditor);
316   if Assigned(EditorInfos) then
317     EditorInfos^.Free(E);
318 end;
319 
TLine.GetTextnull320 function TLine.GetText: string;
321 begin
322   GetText:=GetStr(Text);
323 end;
324 
325 procedure TLine.SetText(const AText: string);
326 begin
327   SetStr(Text,AText);
328 end;
329 
GetEditorInfonull330 function TLine.GetEditorInfo(Editor: PCustomCodeEditor): PEditorLineInfo;
Matchnull331 function Match(P: PEditorLineInfo): boolean;
332 begin
333   Match:=P^.Editor=Editor;
334 end;
335 begin
336   if not assigned(EditorInfos) then
337     GetEditorInfo:=DefaultEditorInfo
338   else
339     GetEditorInfo:=EditorInfos^.FirstThat(@Match);
340 end;
341 
GetFlagsnull342 function TLine.GetFlags: longint;
343 begin
344   GetFlags:=Flags;
345 end;
346 
347 procedure TLine.SetFlags(AFlags: longint);
348 begin
349   Flags:=AFlags;
350   if Assigned(Owner) then
351     Owner^.ContentsChanged;
352 end;
353 
354 destructor TLine.Done;
355 begin
356   if Assigned(Text) then
357     DisposeStr(Text);
358   Text:=nil;
359   if Assigned(EditorInfos) then
360     Dispose(EditorInfos, Done);
361   EditorInfos:=nil;
362   if Assigned(DefaultEditorInfo) then
363     Dispose(DefaultEditorInfo, Done);
364   DefaultEditorInfo:=nil;
365   inherited Done;
366 end;
367 
368 constructor TCodeEditorCore.Init;
369 begin
370   inherited Init;
371   StoreUndo:=true;
372   new(UndoList,init(500,1000));
373   new(RedoList,init(500,1000));
374   New(Lines, Init(500,1000));
375   TabSize:=DefaultTabSize;
376   IndentSize:=DefaultIndentSize;
377   OnDiskLoadTime:=0;
378   SystemLoadTime:=0;
379 end;
380 
381 procedure TCodeEditorCore.ChangeLinesTo(ALines : PLineCollection);
382 begin
383   if assigned(lines) then
384     Dispose(Lines,Done);
385   Lines:=ALines;
386 end;
387 
TCodeEditorCore.GetLineCountnull388 function TCodeEditorCore.GetLineCount: sw_integer;
389 begin
390   GetLineCount:=Lines^.Count;
391 end;
392 
GetLinenull393 function TCodeEditorCore.GetLine(LineNo: sw_integer): PCustomLine;
394 begin
395   GetLine:=Lines^.At(LineNo);
396 end;
397 
TCodeEditorCore.GetModifiednull398 function TCodeEditorCore.GetModified: boolean;
399 begin
400   GetModified:=Modified;
401 end;
402 
TCodeEditorCore.GetModifyTimenull403 function TCodeEditorCore.GetModifyTime: cardinal;
404 begin
405   GetModifyTime:=ModifiedTime;
406 end;
407 
408 procedure TCodeEditorCore.SetModified(AModified: boolean);
409 begin
410   if AModified<>Modified then
411   begin
412     Modified:=AModified;
413     ModifiedChanged;
414   end;
415   ModifiedTime:=cardinal(Now);
416 end;
417 
TCodeEditorCore.GetStoreUndonull418 function TCodeEditorCore.GetStoreUndo: boolean;
419 begin
420   GetStoreUndo:=StoreUndo;
421 end;
422 
423 procedure TCodeEditorCore.SetStoreUndo(AStore: boolean);
424 begin
425   if StoreUndo<>AStore then
426   begin
427     StoreUndo:=AStore;
428     StoreUndoChanged;
429   end;
430 end;
431 
TCodeEditorCore.GetSyntaxCompletednull432 function TCodeEditorCore.GetSyntaxCompleted: boolean;
433 begin
434 {$ifdef TEST_PARTIAL_SYNTAX}
435   GetSyntaxCompleted:=SyntaxComplete;
436 {$else}
437   GetSyntaxCompleted:=true;
438 {$endif}
439 end;
440 
441 procedure TCodeEditorCore.SetSyntaxCompleted(SC: boolean);
442 begin
443 {$ifdef TEST_PARTIAL_SYNTAX}
444   if SC<>SyntaxComplete then
445     begin
446       SyntaxComplete:=SC;
447     end;
448 {$endif}
449 end;
GetLastSyntaxedLinenull450 function TCodeEditorCore.GetLastSyntaxedLine: sw_integer;
451 begin
452   GetLastSyntaxedLine:=LastSyntaxedLine;
453 end;
454 
455 procedure TCodeEditorCore.SetLastSyntaxedLine(ALine: sw_integer);
456 begin
457   LastSyntaxedLine:=ALine;
458 end;
459 
460 
461 procedure TCodeEditorCore.ISetLineFlagState(Binding: PEditorBinding; LineNo: sw_integer; Flag: longint; ASet: boolean);
462 var P: PCustomLine;
463 begin
464   if LineNo<GetLineCount then
465   begin
466     P:=GetLine(LineNo);
467     if assigned(P) then
468       P^.SetFlagState(Flag,ASet);
469   end;
470 end;
471 
472 procedure TCodeEditorCore.GetContent(ALines: PUnsortedStringCollection);
473 procedure AddIt(P: PCustomLine);
474 begin
475   if Assigned(P) then
476     ALines^.Insert(NewStr(P^.GetText));
477 end;
478 begin
479   if Assigned(Lines) then
480     Lines^.ForEach(@AddIt);
481 end;
482 
483 procedure TCodeEditorCore.SetContent(ALines: PUnsortedStringCollection);
484 procedure AddIt(P: PString);
485 begin
486   AddLine(GetStr(P));
487 end;
488 begin
489   DeleteAllLines;
490   if Assigned(ALines) then
491     ALines^.ForEach(@AddIt);
492   LimitsChanged;
493 end;
494 
TCodeEditorCore.GetTabSizenull495 function TCodeEditorCore.GetTabSize: integer;
496 begin
497   GetTabSize:=TabSize;
498 end;
499 
500 procedure TCodeEditorCore.SetTabSize(ATabSize: integer);
501 begin
502   if ATabSize<>TabSize then
503   begin
504     TabSize:=ATabSize;
505     TabSizeChanged;
506   end;
507 end;
508 
GetIndentSizenull509 function TCodeEditorCore.GetIndentSize: integer;
510 begin
511   GetIndentSize:=IndentSize;
512 end;
513 
514 procedure TCodeEditorCore.SetIndentSize(AIndentSize: integer);
515 begin
516   if AIndentSize<>IndentSize then
517   begin
518     IndentSize:=AIndentSize;
519   end;
520 end;
521 
GetLineTextnull522 function TCodeEditorCore.GetLineText(LineNo: sw_integer): string;
523 var
524   L : PCustomLine;
525 begin
526   GetLineText:='';
527   if LineNo<Lines^.Count then
528    begin
529      L:=Lines^.At(LineNo);
530      GetLineText:=L^.GetText;
531    end;
532 end;
533 
534 procedure TCodeEditorCore.LinesInsert(Idx: sw_integer; Line: PLine);
535 var I: sw_integer;
536 procedure RegLine(P: PEditorBinding);
537 begin
538   Line^.AddEditorInfo(I,P^.Editor);
539   Inc(I);
540 end;
541 begin
542   if Idx=-1 then Idx:=Lines^.Count;
543   I:=0;
544   Bindings^.ForEach(@RegLine);
545   Lines^.AtInsert(Idx,Line);
546 end;
547 
548 procedure TCodeEditorCore.SetLineText(I: sw_integer;const S: string);
549 var
550   L : PCustomLine;
551   AddCount : Sw_Integer;
552 begin
553   AddCount:=0;
554   while (Lines^.Count<I+1) do
555    begin
556      LinesInsert(-1,New(PLine, Init(@Self,'',0)));
557      Inc(AddCount);
558    end;
559   if AddCount>0 then
560    LimitsChanged;
561   L:=Lines^.At(I);
562   L^.SetText(S);
563   ContentsChanged;
564 end;
565 
GetDisplayTextnull566 function TCodeEditorCore.GetDisplayText(I: sw_integer): string;
567 begin
568   GetDisplayText:=ExtractTabs(GetLineText(I),GetTabSize);
569 end;
570 
571 procedure TCodeEditorCore.SetDisplayText(I: sw_integer;const S: string);
572 begin
573   { I disagree here
574     I don't want the editor to change the position of the tabs
575     in my makefiles !! PM
576   if FlagSet(efUseTabCharacters) and (TabSize>0) then
577    SetLineText(I,CompressUsingTabs(S,TabSize))
578   else                  }
579   { ... then you better make this optional - Gabor }
580    SetLineText(I,S);
581 end;
582 
583 procedure TCodeEditorCore.IGetDisplayTextFormat(Binding: PEditorBinding; LineNo: sw_integer;var DT,DF:string);
584 var
585   L : PCustomLine;
586   P,PAdd : SW_Integer;
587 begin
588   DF:='';
589   DT:='';
590   if (0<=LineNo) and (LineNo<GetLineCount) then
591    begin
592      L:=GetLine(LineNo);
593      if not assigned(L) then
594        exit;
595      DF:=IGetLineFormat(Binding,LineNo);
596      DT:=L^.GetText;
597      p:=0;
598      while p<length(DT) do
599       begin
600         inc(p);
601         if DT[p]=#9 then
602          begin
603            PAdd:=TabSize-((p-1) mod TabSize);
604            if DF<>'' then
605             DF:=copy(DF,1,P-1)+CharStr(DF[p],PAdd)+copy(DF,P+1,High(DF));
606            DT:=copy(DT,1,P-1)+CharStr(' ',PAdd)+copy(DT,P+1,High(DF));
607            inc(P,PAdd-1);
608          end;
609       end;
610    end;
611 end;
612 
TCodeEditorCore.IGetLineFormatnull613 function TCodeEditorCore.IGetLineFormat(Binding: PEditorBinding; LineNo: sw_integer): string;
614 var P: PCustomLine;
615     LI: PEditorLineInfo;
616     S: string;
617 begin
618   if (0<=LineNo) and (LineNo<GetLineCount) then
619     P:=GetLine(LineNo)
620   else
621     P:=nil;
622   if P=nil then LI:=nil else
623     LI:=P^.GetEditorInfo(Binding^.Editor);
624   if LI=nil then S:='' else S:=LI^.GetFormat;
625   IGetLineFormat:=S;
626 end;
627 
628 procedure TCodeEditorCore.ISetLineFormat(Binding: PEditorBinding; LineNo: sw_integer;const S: string);
629 var P: PCustomLine;
630     LI: PEditorLineInfo;
631 begin
632   if (LineNo<GetLineCount) then
633   begin
634     P:=GetLine(LineNo);
635     if P=nil then LI:=nil else LI:=P^.GetEditorInfo(Binding^.Editor);
636     if Assigned(LI) then LI^.SetFormat(S);
637   end;
638 end;
639 
640 procedure TCodeEditorCore.DeleteAllLines;
641 begin
642   if Assigned(Lines) then
643     Lines^.FreeAll;
644 end;
645 
646 procedure TCodeEditorCore.DeleteLine(I: sw_integer);
647 var
648  CP : Tpoint;
649 begin
650   if I<Lines^.Count then
651     begin
652       if StoreUndo then
653         begin
654           CP.X:=0;CP.Y:=I;
655           AddAction(eaDeleteLine,CP,CP,GetLineText(I),0);
656        end;
657       Lines^.AtFree(I);
658     end;
659 end;
660 
InsertLinenull661 function TCodeEditorCore.InsertLine(LineNo: sw_integer; const S: string): PCustomLine;
662 var L: PLine;
663 begin
664   L:=New(PLine, Init(@Self,S,0));
665   LinesInsert(LineNo, L);
666   InsertLine:=L;
667 end;
668 
669 procedure TCodeEditorCore.AddLine(const S: string);
670 begin
671   LinesInsert(-1,New(PLine, Init(@Self,S,0)));
672 end;
673 
674 procedure TCodeEditorCore.AddAction(AAction: byte; AStartPos, AEndPos: TPoint; AText: string;AFlags : longint);
675 var
676   ActionIntegrated : boolean;
677   pa : PEditorAction;
678   S : String;
679 begin
680   if (UndoList=nil) or (not StoreUndo) then Exit;
681   ActionIntegrated:=false;
682   if UndoList^.count>0 then
683     begin
684       pa:=UndoList^.At(UndoList^.count-1);
685       if (pa^.action=AAction) and
686          (pa^.EndPos.X=AStartPos.X) and
687          (pa^.EndPos.Y=AStartPos.Y) and
688          { do not group InsertLine and DeleteLine !! }
689          ((AAction=eaMoveCursor) or
690           (AAction=eaInsertText) or
691           (AAction=eaOverwriteText) or
692           (AAction=eaDeleteText)) and
693          { do not group if a new grouped_action started }
694           (not assigned(UndoList^.CurrentGroupedAction) or
695            (UndoList^.CurrentGroupedAction^.ActionCount>0))
696          then
697         begin
698           pa^.EndPos:=AEndPos;
699           S:=GetStr(pa^.text);
700           if S<>'' then
701            DisposeStr(pa^.text);
702           if (AAction=eaDeleteText) and
703              (AStartPos.X>AEndPos.X) then
704             pa^.text:=NewStr(AText+S)
705           else
706             pa^.text:=NewStr(S+AText);
707           ActionIntegrated:=true;
708         end;
709     end;
710   if not ActionIntegrated then
711     begin
712       UndoList^.Insert(New(PEditorAction,Init(AAction,AStartPos,AEndPos,AText,AFlags)));
713       if assigned(UndoList^.CurrentGroupedAction) then
714         Inc(UndoList^.CurrentGroupedAction^.actionCount);
715       UpdateUndoRedo(cmUndo,AAction);
716     end;
717   if UndoList^.count>0 then
718   begin
719     UpdateUndoRedo(cmRedo,0);
720     RedoList^.FreeAll;
721   end;
722 end;
723 
724 procedure TCodeEditorCore.AddGroupedAction(AAction : byte);
725 begin
726   if (UndoList=nil) or (not StoreUndo) then Exit;
727   if Assigned(UndoList^.CurrentGroupedAction) then
728     inc(UndoList^.GroupLevel)
729   else
730     begin
731       UndoList^.CurrentGroupedAction:=New(PEditorAction,Init_group(AAction));
732       UndoList^.GroupLevel:=1;
733     end;
734 end;
735 
736 procedure TCodeEditorCore.CloseGroupedAction(AAction : byte);
737 begin
738   if (UndoList=nil) or (not StoreUndo) then Exit;
739   dec(UndoList^.GroupLevel);
740   if UndoList^.GroupLevel=0 then
741     begin
742       UndoList^.CurrentGroupedAction^.TimeStamp:=now;
743       UndoList^.Insert(UndoList^.CurrentGroupedAction);
744       UndoList^.CurrentGroupedAction:=nil;
745       UpdateUndoRedo(cmUndo,AAction);
746     end;
747 end;
748 
TCodeEditorCore.GetUndoActionCountnull749 function TCodeEditorCore.GetUndoActionCount: sw_integer;
750 begin
751   GetUndoActionCount:=UndoList^.Count;
752 end;
753 
TCodeEditorCore.GetRedoActionCountnull754 function TCodeEditorCore.GetRedoActionCount: sw_integer;
755 begin
756   GetRedoActionCount:=RedoList^.Count;
757 end;
758 
759 destructor TCodeEditorCore.Done;
760 begin
761   inherited Done;
762   if Assigned(Lines) then Dispose(Lines, Done); Lines:=nil;
763   if Assigned(RedoList) then Dispose(RedoList, Done); RedoList:=nil;
764   if Assigned(UndoList) then Dispose(UndoList, Done); UndoList:=nil;
765 end;
766 
767 constructor TIndicator.Init(var Bounds: TRect);
768 begin
769   inherited Init(Bounds);
770   GrowMode := gfGrowLoY + gfGrowHiY;
771 end;
772 
773 procedure TIndicator.Draw;
774 var
775   Color: Byte;
776   Frame: Char;
777   L: array[0..1] of PtrInt;
778   S: String[15];
779   B: TDrawBuffer;
780 begin
781   if assigned(CodeOwner) and
782      (CodeOwner^.ELockFlag>0) then
783     begin
784       CodeOwner^.IndicatorDrawCalled:=true;
785       exit;
786     end;
787   if (State and sfDragging = 0) and (State and sfActive <> 0) then
788    begin
789      Color := GetColor(1);
790      Frame := #205;
791    end
792   else
793    begin
794      if (State and sfDragging)<>0 then
795       Color := GetColor(2)
796      else
797       Color := GetColor(3);
798      Frame := #196;
799    end;
800   MoveChar(B, Frame, Color, Size.X);
801   if State and sfActive<>0 then
802    begin
803      if Modified then
804        WordRec (B[0]).Lo := ord('*');
805 {$ifdef debug}
806      if StoreUndo then
807        WordRec (B[1]).Lo := ord('S');
808      if SyntaxComplete then
809        WordRec(B[2]).lo := ord('C');
810      if UseTabs then
811        WordRec(B[3]).lo := ord('T');
812 {$endif debug}
813      L[0] := Location.Y + 1;
814      L[1] := Location.X + 1;
815      FormatStr(S, ' %d:%d ', L);
816      MoveStr(B[8 - Pos(':', S)], S, Color);
817    end;
818   WriteBuf(0, 0, Size.X, 1, B);
819 end;
820 
GetPalettenull821 function TIndicator.GetPalette: PPalette;
822 const
823   P: string[Length(CIndicator)] = CIndicator;
824 begin
825   GetPalette := @P;
826 end;
827 
828 procedure TIndicator.SetState(AState: Word; Enable: Boolean);
829 begin
830   inherited SetState(AState, Enable);
831   if (AState = sfDragging) or (AState=sfActive) then
832    DrawView;
833 end;
834 
835 procedure TIndicator.SetValue(ALocation: TPoint; AModified: Boolean);
836 begin
837   if (Location.X<>ALocation.X) or
838      (Location.Y<>ALocation.Y) or
839      (Modified <> AModified) then
840   begin
841     Location := ALocation;
842     Modified := AModified;
843     DrawView;
844   end;
845 end;
846 
847 {constructor TIndicator.Load(var S: TStream);
848 begin
849   inherited Load(S);
850   S.Read(Location,SizeOf(Location));
851   S.Read(Modified,SizeOf(Modified));
852 end;
853 
854 procedure TIndicator.Store(var S: TStream);
855 begin
856   inherited Store(S);
857   S.Write(Location,SizeOf(Location));
858   S.Write(Modified,SizeOf(Modified));
859 end;}
860 
861 {*****************************************************************************
862                 TCodeEditor
863 *****************************************************************************}
864 
865 constructor TCodeEditor.Init(var Bounds: TRect; AHScrollBar, AVScrollBar:
866           PScrollBar; AIndicator: PIndicator; ACore: PCodeEditorCore);
867 begin
868   inherited Init(Bounds,AHScrollBar,AVScrollBar);
869   New(Folds, Init(100,100));
870   if ACore=nil then ACore:=New(PCodeEditorCore, Init);
871   Core:=ACore;
872   Core^.BindEditor(@Self);
873   SetState(sfCursorVis,true);
874   SetFlags(DefaultCodeEditorFlags);
875   SetCurPtr(0,0);
876   Indicator:=AIndicator;
877   if assigned(Indicator) then
878     Indicator^.CodeOwner:=@Self;
879   UpdateIndicator;
880   LimitsChanged;
881 end;
882 
GetFlagsnull883 function TCodeEditor.GetFlags: longint;
884 begin
885   GetFlags:=Flags;
886 end;
887 
888 procedure TCodeEditor.SetFlags(AFlags: longint);
889 var OFlags: longint;
890 begin
891   if AFlags<>Flags then
892   begin
893     OFlags:=Flags;
894     Flags:=AFlags;
895     FlagsChanged(OFlags);
896   end;
897 end;
898 
TCodeEditor.GetModifiednull899 function TCodeEditor.GetModified: boolean;
900 begin
901   GetModified:=Core^.GetModified;
902 end;
903 
904 procedure TCodeEditor.SetModified(AModified: boolean);
905 begin
906   Core^.SetModified(AModified);
907 end;
908 
TCodeEditor.GetStoreUndonull909 function TCodeEditor.GetStoreUndo: boolean;
910 begin
911   GetStoreUndo:=Core^.GetStoreUndo;
912 end;
913 
914 procedure TCodeEditor.SetStoreUndo(AStore: boolean);
915 begin
916   Core^.SetStoreUndo(AStore);
917 end;
918 
919 procedure TCodeEditor.ClearUndoList;
920 begin
921   Core^.UndoList^.FreeAll;
922   Core^.RedoList^.FreeAll;
923 end;
924 
GetSyntaxCompletednull925 function TCodeEditor.GetSyntaxCompleted: boolean;
926 begin
927   GetSyntaxCompleted:=Core^.GetSyntaxCompleted;
928 end;
929 
930 procedure TCodeEditor.SetSyntaxCompleted(SC : boolean);
931 begin
932   Core^.SetSyntaxCompleted(SC);
933   UpdateIndicator;
934 end;
935 
GetLastSyntaxedLinenull936 function TCodeEditor.GetLastSyntaxedLine: sw_integer;
937 begin
938   GetLastSyntaxedLine:=Core^.GetLastSyntaxedLine;
939 end;
940 
941 procedure TCodeEditor.SetLastSyntaxedLine(ALine: sw_integer);
942 begin
943   Core^.SetLastSyntaxedLine(ALine);
944 end;
945 
GetTabSizenull946 function TCodeEditor.GetTabSize: integer;
947 begin
948   GetTabSize:=Core^.GetTabSize;
949 end;
950 
951 procedure TCodeEditor.SetTabSize(ATabSize: integer);
952 begin
953   Core^.SetTabSize(ATabSize);
954 end;
955 
TCodeEditor.GetIndentSizenull956 function TCodeEditor.GetIndentSize: integer;
957 begin
958   GetIndentSize:=Core^.GetIndentSize;
959 end;
960 
961 procedure TCodeEditor.SetIndentSize(AIndentSize: integer);
962 begin
963   Core^.SetIndentSize(AIndentSize);
964 end;
965 
TCodeEditor.IsReadOnlynull966 function TCodeEditor.IsReadOnly: boolean;
967 begin
968   IsReadOnly:=ReadOnly or (Core^.ReadOnly);
969 end;
970 
TCodeEditor.IsClipboardnull971 function TCodeEditor.IsClipboard: Boolean;
972 begin
973   IsClipboard:=Core^.IsClipboard;
974 end;
975 
TCodeEditor.GetErrorMessagenull976 function TCodeEditor.GetErrorMessage: string;
977 begin
978   GetErrorMessage:=GetStr(ErrorMessage);
979 end;
980 
981 procedure TCodeEditor.SetErrorMessage(const S: string);
982 begin
983   SetStr(ErrorMessage,S);
984   DrawView;
985 end;
986 
TCodeEditor.GetLineCountnull987 function TCodeEditor.GetLineCount: sw_integer;
988 begin
989   GetLineCount:=Core^.GetLineCount;
990 end;
991 
GetLinenull992 function TCodeEditor.GetLine(LineNo: sw_integer): PCustomLine;
993 begin
994   GetLine:=Core^.GetLine(LineNo);
995 end;
996 
CharIdxToLinePosnull997 function TCodeEditor.CharIdxToLinePos(Line,CharIdx: sw_integer): sw_integer;
998 begin
999   CharIdxToLinePos:=Core^.CharIdxToLinePos(Line,CharIdx);
1000 end;
1001 
TCodeEditor.LinePosToCharIdxnull1002 function TCodeEditor.LinePosToCharIdx(Line,X: sw_integer): sw_integer;
1003 begin
1004   LinePosToCharIdx:=Core^.LinePosToCharIdx(Line,X);
1005 end;
1006 
TCodeEditor.GetLineTextnull1007 function TCodeEditor.GetLineText(I: sw_integer): string;
1008 begin
1009   GetLineText:=Core^.GetLineText(I);
1010 end;
1011 
1012 procedure TCodeEditor.SetDisplayText(I: sw_integer;const S: string);
1013 begin
1014   Core^.SetDisplayText(I,S);
1015 end;
1016 
GetDisplayTextnull1017 function TCodeEditor.GetDisplayText(I: sw_integer): string;
1018 begin
1019   GetDisplayText:=Core^.GetDisplayText(I);
1020 end;
1021 
1022 procedure TCodeEditor.SetLineText(I: sw_integer;const S: string);
1023 begin
1024   Core^.SetLineText(I,S);
1025 end;
1026 
1027 procedure TCodeEditor.GetDisplayTextFormat(I: sw_integer;var DT,DF:string);
1028 begin
1029   Core^.GetDisplayTextFormat(@Self,I,DT,DF);
1030 end;
1031 
GetLineFormatnull1032 function TCodeEditor.GetLineFormat(I: sw_integer): string;
1033 begin
1034   GetLineFormat:=Core^.GetLineFormat(@Self,I);
1035 end;
1036 
1037 procedure TCodeEditor.SetLineFormat(I: sw_integer;const S: string);
1038 begin
1039   Core^.SetLineFormat(@Self,I,S);
1040 end;
1041 
1042 procedure TCodeEditor.DeleteAllLines;
1043 begin
1044   Core^.DeleteAllLines;
1045 end;
1046 
1047 procedure TCodeEditor.DeleteLine(I: sw_integer);
1048 begin
1049   Core^.DeleteLine(I);
1050 end;
1051 
TCodeEditor.InsertLinenull1052 function TCodeEditor.InsertLine(LineNo: sw_integer; const S: string): PCustomLine;
1053 begin
1054   InsertLine:=Core^.InsertLine(LineNo,S);
1055 end;
1056 
1057 procedure TCodeEditor.AddLine(const S: string);
1058 begin
1059   Core^.AddLine(S);
1060 end;
1061 
TCodeEditor.GetMaxFoldLevelnull1062 function TCodeEditor.GetMaxFoldLevel: sw_integer;
1063 begin
1064   GetMaxFoldLevel:=MaxFoldLevel;
1065 end;
1066 
1067 procedure TCodeEditor.RegisterFold(AFold: PFold);
1068 var L: sw_integer;
1069 begin
1070   if Assigned(Folds) then
1071   begin
1072     Folds^.Insert(AFold);
1073     L:=AFold^.GetLevel+1;
1074     if L>MaxFoldLevel then MaxFoldLevel:=L;
1075   end;
1076 end;
1077 
1078 procedure TCodeEditor.UnRegisterFold(AFold: PFold);
1079 begin
1080   if Assigned(Folds) then
1081   begin
1082     Folds^.Delete(AFold);
1083     if Folds^.Count=0 then
1084       MaxFoldLevel:=0
1085     else
1086       MaxFoldLevel:=inherited GetMaxFoldLevel+1;
1087   end;
1088 end;
1089 
GetFoldCountnull1090 function TCodeEditor.GetFoldCount: sw_integer;
1091 begin
1092   GetFoldCount:=Folds^.Count;
1093 end;
1094 
TCodeEditor.GetFoldnull1095 function TCodeEditor.GetFold(Index: sw_integer): PFold;
1096 begin
1097   GetFold:=Folds^.At(Index);
1098 end;
1099 
1100 {function TCodeEditor.GetLineTextPos(Line,X: integer): integer;
1101 var
1102   S: string;
1103   rx,i : Sw_integer;
1104 begin
1105   S:=GetLineText(Line);
1106   i:=0; rx:=0;
1107   while (RX<X) and (i<Length(s)) do
1108    begin
1109      inc(i);
1110      inc(rx);
1111      if s[i]=#9 then
1112       inc(rx,TabSize-(rx mod tabsize));
1113    end;
1114   if RX<X then Inc(I,X-RX);
1115   GetLineTextPos:=i;
1116 end;
1117 
GetDisplayTextPosnull1118 function TCodeEditor.GetDisplayTextPos(Line,X: integer): integer;
1119 var
1120   S: string;
1121   L: PCustomLine;
1122   rx,i : Sw_integer;
1123 begin
1124   S:='';
1125   if Line<Lines^.Count then
1126    begin
1127      L:=Lines^.At(Line);
1128      if assigned(L^.Text) then
1129       S:=L^.Text^;
1130    end;
1131   i:=0;
1132   rx:=0;
1133   while (i<X) and (i<Length(s)) do
1134    begin
1135      inc(i);
1136      inc(rx);
1137      if s[i]=#9 then
1138 
1139 
1140       inc(rx,TabSize-(rx mod tabsize));
1141    end;
1142   GetDisplayTextPos:=rx;
1143 end;}
1144 
1145 procedure TCodeEditor.GetContent(ALines: PUnsortedStringCollection);
1146 begin
1147   Core^.GetContent(ALines);
1148 end;
1149 
1150 procedure TCodeEditor.SetContent(ALines: PUnsortedStringCollection);
1151 begin
1152   Lock;
1153   TextStart; HideSelect;
1154   Core^.SetContent(ALines);
1155   LimitsChanged;
1156   if IsFlagSet(efSyntaxHighlight) then
1157     Core^.UpdateAttrsRange(0,Min(Delta.Y+Size.Y,GetLineCount-1),
1158       attrAll
1159 {$ifndef TEST_PARTIAL_SYNTAX}
1160       +attrForceFull
1161 {$endif TEST_PARTIAL_SYNTAX}
1162       );
1163   TextStart;
1164   UnLock;
1165 end;
1166 
TCodeEditor.GetCodeCompleteFragnull1167 function TCodeEditor.GetCodeCompleteFrag: string;
1168 begin
1169   GetCodeCompleteFrag:=GetStr(CodeCompleteFrag);
1170 end;
1171 
1172 procedure TCodeEditor.SetCodeCompleteFrag(const S: string);
1173 begin
1174   SetStr(CodeCompleteFrag,S);
1175 end;
1176 
GetCompleteStatenull1177 function TCodeEditor.GetCompleteState: TCompleteState;
1178 begin
1179   GetCompleteState:=CompleteState;
1180 end;
1181 
1182 procedure TCodeEditor.SetCompleteState(AState: TCompleteState);
1183 begin
1184   if AState<>CompleteState then
1185   begin
1186     CompleteState:=AState;
1187     if CompleteState<>csOffering then
1188       ClearCodeCompleteWord;
1189   end;
1190 end;
1191 
TCodeEditor.GetCodeCompleteWordnull1192 function TCodeEditor.GetCodeCompleteWord: string;
1193 begin
1194   GetCodeCompleteWord:=GetStr(CodeCompleteWord);
1195 end;
1196 
1197 procedure TCodeEditor.SetCodeCompleteWord(const S: string);
1198 begin
1199   if Assigned(CodeCompleteWord) then DisposeStr(CodeCompleteWord);
1200   CodeCompleteWord:=NewStr(S);
1201   inherited SetCodeCompleteWord(S);
1202 end;
1203 
1204 procedure TCodeEditor.DrawIndicator;
1205 begin
1206   if Assigned(Indicator) then
1207     Indicator^.DrawView;
1208 end;
1209 
1210 procedure TCodeEditor.Lock;
1211 begin
1212   inherited Lock;
1213   Core^.Lock(@Self);
1214 end;
1215 
1216 procedure TCodeEditor.UnLock;
1217 begin
1218   Core^.UnLock(@Self);
1219   inherited UnLock;
1220   If (ELockFlag=0) and IndicatorDrawCalled then
1221     begin
1222       DrawIndicator;
1223       IndicatorDrawCalled:=false;
1224     end;
1225 end;
1226 
1227 procedure TCodeEditor.UpdateIndicator;
1228 begin
1229   if Indicator<>nil then
1230   begin
1231     Indicator^.Location:=CurPos;
1232     Indicator^.Modified:=GetModified;
1233 {$ifdef debug}
1234     Indicator^.StoreUndo:=GetStoreUndo;
1235 {$ifdef TEST_PARTIAL_SYNTAX}
1236     Indicator^.SyntaxComplete:=GetSyntaxCompleted and IsFlagSet(efSyntaxHighlight);
1237 {$endif TEST_PARTIAL_SYNTAX}
1238     Indicator^.UseTabs:=IsFlagSet(efUseTabCharacters);
1239 {$endif debug}
1240     if Elockflag>0 then
1241       IndicatorDrawCalled:=true
1242     else
1243       Indicator^.DrawView;
1244   end;
1245 end;
1246 
1247 procedure TCodeEditor.LimitsChanged;
1248 begin
1249   Core^.LimitsChanged;
1250 end;
1251 
1252 procedure TCodeEditor.ModifiedChanged;
1253 begin
1254   UpdateIndicator;
1255 end;
1256 
1257 procedure TCodeEditor.PositionChanged;
1258 begin
1259   UpdateIndicator;
1260 end;
1261 
1262 procedure TCodeEditor.JumpToLastCursorPos;
1263 var
1264   pa : PEditorAction;
1265 begin
1266   if (Core^.UndoList^.count>0) and (Core^.RedoList^.count=0) then
1267     begin
1268       { Or should we just call Undo ?? PM }
1269       pa:=Core^.UndoList^.At(Core^.UndoList^.count-1);
1270       if (pa^.action=eaMoveCursor) then
1271         SetCurPtr(pa^.StartPos.X,pa^.StartPos.Y);
1272     end;
1273 end;
1274 
1275 procedure TCodeEditor.Undo;
1276 var
1277   Temp,Idx,Last,Count : Longint;
1278   StoredFlags : longint;
1279   UndoTime : longint;
1280   WasInserting,IsGrouped,HadefNoIndent : boolean;
1281   MaxY,MinY : sw_integer;
1282   Line : String;
1283 
1284   procedure SetMinMax(y : sw_integer);
1285     begin
1286       if MinY=-1 then
1287         MinY:=Y;
1288       if Y<MinY then
1289         MinY:=Y;
1290       if MaxY=-1 then
1291         MaxY:=Y;
1292       if Y>MaxY then
1293         MaxY:=Y;
1294     end;
1295 begin
1296   Core^.SetStoreUndo(False);
1297   Lock;
1298   MinY:=-1;
1299   MaxY:=-1;
1300   if Core^.UndoList^.count > 0 then
1301   begin
1302     Last:=Core^.UndoList^.count-1;
1303     if Core^.UndoList^.At(Last)^.Is_grouped_action then
1304       begin
1305         Count:=Core^.UndoList^.At(Last)^.ActionCount;
1306         UndoTime:=Core^.UndoList^.At(Last)^.TimeStamp;
1307         Dec(Last);
1308         IsGrouped:=true;
1309       end
1310     else
1311       begin
1312         Count:=1;
1313         IsGrouped:=false;
1314       end;
1315     for Idx:=Last downto Last-Count+1 do
1316       with Core^.UndoList^.At(Idx)^ do
1317         begin
1318           if not IsGrouped then
1319             UndoTime:=TimeStamp;
1320           case action of
1321             eaMoveCursor :
1322               begin
1323                 { move cursor back to original position }
1324                 SetCurPtr(startpos.x,startpos.y);
1325               end;
1326             eaInsertText :
1327               begin
1328                 SetCurPtr(StartPos.X,StartPos.Y);
1329                 if assigned(text) then
1330                   for Temp := 1 to length(Text^) do
1331                     DelChar;
1332                 SetMinMax(StartPos.Y);
1333               end;
1334             eaDeleteText :
1335               begin
1336                 { reinsert deleted text }
1337                 SetCurPtr(EndPos.X,EndPos.Y);
1338                 WasInserting:=GetInsertMode;
1339                 SetInsertMode(true);
1340                 if assigned(text) then
1341                   for Temp := 1 to length(Text^) do
1342                     AddChar(Text^[Temp]);
1343                 SetInsertMode(WasInserting);
1344                 SetMinMax(EndPos.Y);
1345                 SetCurPtr(StartPos.X,StartPos.Y);
1346               end;
1347             eaOverwriteText :
1348               begin
1349                 SetCurPtr(StartPos.X,StartPos.Y);
1350                 Line:=GetDisplayText(StartPos.Y);
1351                 WasInserting:=GetInsertMode;
1352                 SetInsertMode(false);
1353                 if assigned(text) then
1354                   for Temp := 1 to length(Text^) do
1355                     begin
1356                       AddChar(Text^[Temp]);
1357                       if StartPos.X+Temp>Length(Line) then
1358                         Text^[Temp]:=' '
1359                       else
1360                         Text^[Temp]:=Line[StartPos.X+Temp];
1361                     end;
1362                 SetInsertMode(WasInserting);
1363                 SetMinMax(EndPos.Y);
1364                 SetCurPtr(StartPos.X,StartPos.Y);
1365               end;
1366             eaInsertLine :
1367               begin
1368                 SetCurPtr(EndPos.X,EndPos.Y);
1369                 Line:=Copy(GetDisplayText(StartPos.Y),1,StartPos.X);
1370                 If Length(Line)<StartPos.X then
1371                   Line:=Line+CharStr(' ',StartPos.X-length(Line))+GetStr(Text);
1372                 SetDisplayText(StartPos.Y,Line+Copy(GetDisplayText(EndPos.Y),EndPos.X+1,255));
1373                 SetMinMax(EndPos.Y);
1374                 SetCurPtr(0,EndPos.Y);
1375                 DeleteLine(EndPos.Y);
1376                 SetCurPtr(StartPos.X,StartPos.Y);
1377                 SetMinMax(StartPos.Y);
1378               end;
1379             eaDeleteLine :
1380               begin
1381                 HadefNoIndent:=(GetFlags and efNoIndent)<>0;
1382                 WasInserting:=GetInsertMode;
1383                 SetInsertMode(true);
1384                 SetFlags(GetFlags or efNoIndent);
1385                 InsertLine(StartPos.Y,GetStr(Text));
1386                 SetInsertMode(WasInserting);
1387                 if not HadefNoIndent then
1388                   SetFlags(GetFlags and not efNoIndent);
1389                 {DelEnd; wrong for eaCut at least }
1390                 SetCurPtr(StartPos.X,StartPos.Y);
1391                 if StartPos.Y > EndPos.Y then
1392                    SetLineText(EndPos.Y,Copy(GetDisplayText(EndPos.Y),1,EndPos.X));
1393                 SetMinMax(StartPos.Y);
1394               end;
1395             eaSelectionChanged :
1396               begin
1397                 { move cursor to end of last set selection }
1398               end;
1399           else
1400             { what the 'ell's an undefined action doing round 'ere mate! }
1401             ;
1402           end; { once this lot is done paste into redo and modify to suit needs }
1403           { move item to redo stack }
1404           Core^.RedoList^.Insert(Core^.UndoList^.At(Idx));
1405           UpdateUndoRedo(cmRedo,Core^.UndoList^.At(Idx)^.Action);
1406           Core^.UndoList^.atDelete(Idx);
1407           If Idx>0 then
1408             UpdateUndoRedo(cmUndo,Core^.UndoList^.At(Idx-1)^.Action)
1409           else
1410             UpdateUndoRedo(cmUndo,0);
1411         end;{Idx loop for grouped actions }
1412       if IsGrouped then
1413         begin
1414           Idx:=Core^.UndoList^.Count-1;
1415           Core^.RedoList^.Insert(Core^.UndoList^.At(Idx));
1416           UpdateUndoRedo(cmRedo,Core^.UndoList^.At(Idx)^.Action);
1417           Core^.UndoList^.atDelete(Idx);
1418           If Idx>0 then
1419             UpdateUndoRedo(cmUndo,Core^.UndoList^.At(Idx-1)^.Action)
1420           else
1421             UpdateUndoRedo(cmUndo,0);
1422         end;
1423       if Core^.UndoList^.count=0 then
1424         SetCmdState(UndoCmd,false);
1425       if (Core^.UndoList^.count=0) or
1426          ((Core^.UndoList^.count=1) and
1427           (Core^.UndoList^.At(0)^.Action=eaMoveCursor)) then
1428         begin
1429           SetCmdState(UndoCmd,false);
1430           if (UndoTime>=Core^.SystemLoadTime) or (Core^.SystemLoadTime=0) then
1431             SetModified(false);
1432         end;
1433       SetCmdState(RedoCmd,true);
1434       Message(Application,evBroadcast,cmCommandSetChanged,nil);
1435       if MinY<>-1 then
1436         UpdateAttrsRange(MinY,MaxY,attrAll);
1437       DrawView;
1438     end;
1439   Core^.SetStoreUndo(True);
1440   Unlock;
1441 end;
1442 
1443 procedure TCodeEditor.Redo;
1444 var
1445   Temp,Idx,i,Last,Count : Longint;
1446   StoredFlags : longint;
1447   WasInserting,IsGrouped,ShouldInsertText : boolean;
1448   Line : String;
1449   MaxY,MinY : sw_integer;
1450   procedure SetMinMax(y : sw_integer);
1451     begin
1452       if MinY=-1 then
1453         MinY:=Y;
1454       if Y<MinY then
1455         MinY:=Y;
1456       if MaxY=-1 then
1457         MaxY:=Y;
1458       if Y>MaxY then
1459         MaxY:=Y;
1460     end;
1461 begin
1462   Core^.SetStoreUndo(False);
1463   Lock;
1464   MinY:=-1;
1465   MaxY:=-1;
1466   if Core^.RedoList^.count <> 0 then
1467    begin
1468     Last:=Core^.RedoList^.count-1;
1469     if Core^.RedoList^.At(Last)^.Is_grouped_action then
1470       begin
1471         Count:=Core^.RedoList^.At(Last)^.ActionCount;
1472         Dec(Last);
1473         IsGrouped:=true;
1474       end
1475     else
1476       begin
1477         Count:=1;
1478         IsGrouped:=false;
1479       end;
1480     for Idx:=Last downto Last-Count+1 do
1481     with Core^.RedoList^.At(Idx)^ do
1482     begin
1483       case action of
1484         eaMoveCursor :
1485           begin
1486             { move cursor back to original position }
1487             SetCurPtr(EndPos.X,EndPos.Y);
1488           end;
1489         eaInsertText :
1490           begin
1491             SetCurPtr(startpos.x,startpos.y);
1492             InsertText(GetStr(Text));
1493             SetMinMax(StartPos.Y);
1494           end;
1495         eaDeleteText :
1496           begin
1497             SetCurPtr(EndPos.X,EndPos.Y);
1498             for Temp := 1 to length(GetStr(Text)) do
1499               DelChar;
1500             SetMinMax(EndPos.Y);
1501           end;
1502         eaOverwriteText :
1503           begin
1504             SetCurPtr(StartPos.X,StartPos.Y);
1505             Line:=GetDisplayText(StartPos.Y);
1506             WasInserting:=GetInsertMode;
1507             SetInsertMode(false);
1508             if assigned(text) then
1509               for Temp := 1 to length(Text^) do
1510                 begin
1511                   AddChar(Text^[Temp]);
1512                   if StartPos.X+Temp>Length(Line) then
1513                     Text^[Temp]:=' '
1514                   else
1515                     Text^[Temp]:=Line[StartPos.X+Temp];
1516                 end;
1517             SetInsertMode(WasInserting);
1518             SetCurPtr(EndPos.X,EndPos.Y);
1519             SetMinMax(StartPos.Y);
1520           end;
1521         eaInsertLine :
1522           begin
1523             SetCurPtr(StartPos.X,StartPos.Y);
1524             StoredFlags:=GetFlags;
1525             SetFlags(Flags);
1526             InsertNewLine;
1527             SetCurPtr(0,EndPos.Y);
1528             Line:=GetStr(Text);
1529             ShouldInsertText:=false;
1530             for I:=1 to Length(Line) do
1531               if Line[I]<>' ' then
1532                 ShouldInsertText:=true;
1533             If ShouldInsertText then
1534               InsertText(Line);
1535             SetFlags(StoredFlags);
1536             SetCurPtr(EndPos.X,EndPos.Y);
1537             SetMinMax(StartPos.Y);
1538           end;
1539         eaDeleteLine :
1540           begin
1541             SetCurPtr(StartPos.X,StartPos.Y);
1542             DeleteLine(StartPos.Y);
1543             SetCurPtr(EndPos.X,EndPos.Y);
1544             if EndPos.Y=StartPos.Y-1 then
1545             SetDisplayText(EndPos.Y,RExpand(
1546               copy(GetDisplayText(EndPos.Y),1,EndPos.X),EndPos.X)
1547               +GetStr(Text));
1548             SetCurPtr(EndPos.X,EndPos.Y);
1549             SetMinMax(StartPos.Y);
1550             SetMinMax(EndPos.Y);
1551           end;
1552         eaSelectionChanged :
1553           begin
1554             { move cursor to end of last set test selection }
1555           end;
1556       else
1557         { what the 'ell's an undefined action doing round 'ere mate! }
1558         ;
1559       end; { once this lot is done paste back into undo and modify to suit needs }
1560     { move item to undo stack }
1561       Core^.UndoList^.Insert(Core^.RedoList^.At(Idx));
1562       UpdateUndoRedo(cmUndo,Core^.RedoList^.At(Idx)^.Action);
1563       If Idx>0 then
1564         UpdateUndoRedo(cmRedo,Core^.RedoList^.At(Idx-1)^.Action)
1565       else
1566         UpdateUndoRedo(cmRedo,0);
1567       Core^.RedoList^.atDelete(Idx);
1568       end;{ Idx loop for grouped action }
1569       If IsGrouped then
1570         begin
1571           Idx:=Core^.RedoList^.count-1;
1572           Core^.UndoList^.Insert(Core^.RedoList^.At(Idx));
1573           UpdateUndoRedo(cmUndo,Core^.RedoList^.At(Idx)^.Action);
1574           If Idx>0 then
1575             UpdateUndoRedo(cmRedo,Core^.RedoList^.At(Idx-1)^.Action)
1576           else
1577             UpdateUndoRedo(cmRedo,0);
1578           Core^.RedoList^.atDelete(Idx);
1579         end;
1580       if Core^.RedoList^.count=0 then
1581         SetCmdState(RedoCmd,false);
1582       SetCmdState(UndoCmd,true);
1583       Message(Application,evBroadcast,cmCommandSetChanged,nil);
1584       if MinY<>-1 then
1585         UpdateAttrsRange(MinY,MaxY,attrAll);
1586       DrawView;
1587     end;
1588   Core^.SetStoreUndo(True);
1589   Unlock;
1590 end;
1591 
1592 (*constructor TCodeEditor.Load(var S: TStream);
1593 var TS: PSubStream;
1594     TSize: longint;
1595 begin
1596   inherited Load(S);
1597 
1598   New(UndoList,init(500,1000));
1599   New(RedoList,init(500,1000));
1600 
1601   New(Lines, Init(500,1000));
1602   { we have always need at least 1 line }
1603   LinesInsert(New(PLine, Init('',0)));
1604 
1605   GetPeerViewPtr(S,Indicator);
1606   S.Read(Flags,SizeOf(Flags));
1607   S.Read(TabSize,SizeOf(TabSize));
1608 
1609   if IsFlagSet(efStoreContent) then
1610     begin
1611       S.Read(TSize,SizeOf(TSize));
1612       New(TS, Init(@S,S.GetPos,TSize));
1613 {$ifdef TEST_PARTIAL_SYNTAX}
1614       Core^.SearchBinding(Editor)^.SyntaxComplete:=false;
1615       { Idle necessary }
1616       EventMask:=EventMask or evIdle;
1617 {$endif TEST_PARTIAL_SYNTAX}
1618       LoadFromStream(TS);
1619       Dispose(TS, Done);
1620     end;
1621 
1622   S.Read(SelStart,SizeOf(SelStart));
1623   S.Read(SelEnd,SizeOf(SelEnd));
1624   S.Read(Highlight,SizeOf(Highlight));
1625   S.Read(CurPos,SizeOf(CurPos));
1626   S.Read(StoreUndo,SizeOf(StoreUndo));
1627   S.Read(IsReadOnly,SizeOf(IsReadOnly));
1628   S.Read(NoSelect,SizeOf(NoSelect));
1629   S.Read(HighlightRow,SizeOf(HighlightRow));
1630   SetDebuggerRow(-1);
1631 
1632   LimitsChanged;
1633   SelectionChanged; HighlightChanged;
1634   UpdateIndicator;
1635 end;
1636 
1637 procedure TCodeEditor.Store(var S: TStream);
1638 var {NS: TNulStream;}
1639     TSizePos,TSize,EndPos: longint;
1640 begin
1641   inherited Store(S);
1642 
1643   PutPeerViewPtr(S,Indicator);
1644   S.Write(Flags,SizeOf(Flags));
1645   S.Write(TabSize,SizeOf(TabSize));
1646 
1647   if IsFlagSet(efStoreContent) then
1648     begin
1649       { NS.Init;
1650       SaveToStream(@NS);
1651       TSize:=NS.GetSize;
1652       NS.Done;
1653         This is waste of time PM
1654         use Seek instead !! }
1655       { yep. and this won't work for serial streams. - Gabor }
1656       TSize:=0;
1657       TSizePos:=S.GetPos;
1658       S.Write(TSize,SizeOf(TSize));
1659       SaveToStream(@S);
1660       EndPos:=S.GetPos;
1661       TSize:=EndPos-TSizePos-SizeOf(TSize);
1662       S.Seek(TSizePos);
1663       S.Write(TSize,SizeOf(TSize));
1664       S.Seek(EndPos);
1665     end;
1666 
1667   S.Write(SelStart,SizeOf(SelStart));
1668   S.Write(SelEnd,SizeOf(SelEnd));
1669   S.Write(Highlight,SizeOf(Highlight));
1670   S.Write(CurPos,SizeOf(CurPos));
1671   S.Write(StoreUndo,SizeOf(StoreUndo));
1672   S.Write(IsReadOnly,SizeOf(IsReadOnly));
1673   S.Write(NoSelect,SizeOf(NoSelect));
1674   S.Write(HighlightRow,SizeOf(HighlightRow));
1675 end;*)
1676 
TCodeEditor.LoadFromStreamnull1677 function TCodeEditor.LoadFromStream(Stream: PFastBufStream): boolean;
1678 var OK: boolean;
1679 begin
1680   OK:=Core^.LoadFromStream(@Self,Stream);
1681   if IsFlagSet(efSyntaxHighlight) then
1682     UpdateAttrsRange(0,Min(Delta.Y+Size.Y,GetLineCount-1),
1683       attrAll
1684 {$ifndef TEST_PARTIAL_SYNTAX}
1685       +attrForceFull
1686 {$endif TEST_PARTIAL_SYNTAX}
1687       );
1688   TextStart;
1689   LoadFromStream:=OK;
1690 end;
1691 
SaveToStreamnull1692 function TCodeEditor.SaveToStream(Stream: PStream): boolean;
1693 begin
1694   SaveToStream:=Core^.SaveToStream(@Self,Stream);
1695 end;
1696 
SaveAreaToStreamnull1697 function TCodeEditor.SaveAreaToStream(Stream: PStream; StartP,EndP: TPoint): boolean;
1698 begin
1699   SaveAreaToStream:=Core^.SaveAreaToStream(@Self,Stream,StartP,EndP);
1700 end;
1701 
TCodeEditor.UpdateAttrsnull1702 function TCodeEditor.UpdateAttrs(FromLine: sw_integer; Attrs: byte): sw_integer;
1703 begin
1704   UpdateAttrs:=Core^.UpdateAttrs(FromLine,Attrs);
1705 end;
1706 
UpdateAttrsRangenull1707 function TCodeEditor.UpdateAttrsRange(FromLine, ToLine: sw_integer; Attrs: byte): sw_integer;
1708 begin
1709   UpdateAttrsRange:=Core^.UpdateAttrsRange(FromLine,ToLine,Attrs);
1710 end;
1711 
1712 procedure TCodeEditor.AddAction(AAction: byte; AStartPos, AEndPos: TPoint; AText: string;AFlags : longint);
1713 begin
1714   Core^.AddAction(AAction,AStartPos,AEndPos,AText,AFlags);
1715 end;
1716 
1717 procedure TCodeEditor.AddGroupedAction(AAction : byte);
1718 begin
1719   Core^.AddGroupedAction(AAction);
1720 end;
1721 
1722 procedure TCodeEditor.CloseGroupedAction(AAction : byte);
1723 begin
1724   Core^.CloseGroupedAction(AAction);
1725 end;
1726 
GetUndoActionCountnull1727 function TCodeEditor.GetUndoActionCount: sw_integer;
1728 begin
1729   GetUndoActionCount:=Core^.GetUndoActionCount;
1730 end;
1731 
TCodeEditor.GetRedoActionCountnull1732 function TCodeEditor.GetRedoActionCount: sw_integer;
1733 begin
1734   GetRedoActionCount:=Core^.GetRedoActionCount;
1735 end;
1736 
1737 destructor TCodeEditor.Done;
1738 begin
1739   inherited Done;
1740   if Assigned(Core) then
1741   begin
1742     Core^.UnBindEditor(@Self);
1743     if Core^.CanDispose then
1744       Dispose(Core, Done);
1745   end;
1746   Core:=nil;
1747   if Assigned(CodeCompleteFrag) then
1748     DisposeStr(CodeCompleteFrag);
1749   if Assigned(CodeCompleteWord) then
1750     DisposeStr(CodeCompleteWord);
1751   if Assigned(ErrorMessage) then
1752     DisposeStr(ErrorMessage);
1753   if Assigned(Folds) then
1754     Dispose(Folds, Done);
1755   Folds:=nil;
1756 end;
1757 
1758 constructor TFileEditor.Init(var Bounds: TRect; AHScrollBar, AVScrollBar:
1759        PScrollBar; AIndicator: PIndicator;ACore: PCodeEditorCore; const AFileName: string);
1760 begin
1761   inherited Init(Bounds,AHScrollBAr,AVScrollBAr,AIndicator,ACore);
1762   FileName:=AFileName;
1763   UpdateIndicator;
1764   Message(@Self,evBroadcast,cmFileNameChanged,@Self);
1765 end;
1766 
LoadFilenull1767 function TFileEditor.LoadFile: boolean;
1768 var OK: boolean;
1769     PA : Array[1..2] of pointer;
1770 begin
1771   OK:=LoadFromFile(FileName);
1772   if GetModified and (Core^.GetBindingCount=1) then
1773     begin
1774       PA[1]:=@FileName;
1775       Ptrint(PA[2]):=Core^.GetChangedLine;
1776       EditorDialog(edChangedOnloading,@PA);
1777     end;
1778   Core^.OnDiskLoadTime:=Cardinal(GetFileTime(FileName));
1779   Core^.SystemLoadTime:=Core^.OnDiskLoadTime;
1780   LoadFile:=OK;
1781 end;
1782 
TFileEditor.IsChangedOnDisknull1783 function TFileEditor.IsChangedOnDisk : boolean;
1784 begin
1785   IsChangedOnDisk:=(Core^.OnDiskLoadTime<>Cardinal(GetFileTime(FileName))) and
1786     (Core^.OnDiskLoadTime<>0);
1787 end;
1788 
SaveFilenull1789 function TFileEditor.SaveFile: boolean;
1790 var OK: boolean;
1791     BAKName: string;
1792     f: text;
1793     SaveTime : cardinal;
1794 begin
1795   If IsChangedOnDisk then
1796     begin
1797       if EditorDialog(edFileOnDiskChanged, @FileName) <> cmYes then
1798         begin
1799           SaveFile:=false;
1800           exit;
1801         end;
1802     end;
1803 {$I-}
1804   if IsFlagSet(efBackupFiles) and ExistsFile(FileName) then
1805   begin
1806      BAKName:=DirAndNameOf(FileName)+'.bak';
1807      Assign(f,BAKName);
1808      Erase(f);
1809      EatIO;
1810      Assign(f,FileName);
1811      Rename(F,BAKName);
1812      EatIO;
1813   end;
1814 {$I+}
1815   SaveTime:=cardinal(now);
1816   OK:=SaveToFile(FileName);
1817   if OK then
1818     SetModified(false)
1819   { Restore the original }
1820   else if IsFlagSet(efBackupFiles) and ExistsFile(BakName) then
1821     begin
1822 {$I-}
1823      Assign(f,BakName);
1824      Rename(F,FileName);
1825      EatIO;
1826 {$I+}
1827     end;
1828   { don't forget to update the OnDiskLoadTime value }
1829   if OK then
1830     begin
1831       Core^.OnDiskLoadTime:=Cardinal(GetFileTime(FileName));
1832       Core^.SystemLoadTime:=SaveTime;
1833     end;
1834   if not OK then
1835     EditorDialog(edSaveError,@FileName);
1836   SaveFile:=OK;
1837 end;
1838 
ReloadFilenull1839 function TFileEditor.ReloadFile: boolean;
1840 var OK,WasModified: boolean;
1841     BAKName: string;
1842     f: text;
1843 begin
1844   If not IsChangedOnDisk then
1845     begin
1846       ReloadFile:=false;
1847       exit;
1848     end;
1849   WasModified:=GetModified;
1850   if not WasModified then
1851     OK:=EditorDialog(edreloaddiskmodifiedfile, @FileName)=cmYes
1852   else
1853     OK:=EditorDialog(edreloaddiskandidemodifiedfile, @FileName)=cmYes;
1854   if not OK then
1855     begin
1856       ReloadFile:=false;
1857       exit;
1858     end;
1859   { avoid wrong message }
1860   if WasModified then
1861     SetModified(false);
1862   OK:=LoadFile;
1863   if OK then
1864     begin
1865       SetModified(false);
1866       ClearUndoList;
1867       { don't forget to update the OnDiskLoadTime value }
1868       Core^.OnDiskLoadTime:=Cardinal(GetFileTime(FileName));
1869       Core^.SystemLoadTime:=Core^.OnDiskLoadTime;
1870       DrawView;
1871     end
1872   else
1873     begin
1874       if WasModified then
1875         SetModified(true);
1876       EditorDialog(edReadError,@FileName);
1877     end;
1878   ReloadFile:=OK;
1879 end;
1880 
TFileEditor.ShouldSavenull1881 function TFileEditor.ShouldSave: boolean;
1882 begin
1883   ShouldSave:=GetModified{ or (FileName='')};
1884 end;
1885 
TFileEditor.Savenull1886 function TFileEditor.Save: Boolean;
1887 begin
1888   if ShouldSave=false then begin Save:=true; Exit; end;
1889   if FileName = '' then Save := SaveAs else Save := SaveFile;
1890 end;
1891 
TFileEditor.SaveAsnull1892 function TFileEditor.SaveAs: Boolean;
1893 var
1894   SavedName : String;
1895   SavedDiskLoadTime : cardinal;
1896 begin
1897   SaveAs := False;
1898   SavedName:=FileName;
1899   SavedDiskLoadTime:=Core^.OnDiskLoadTime;
1900   if EditorDialog(edSaveAs, @FileName) <> cmCancel then
1901   begin
1902     FileName:=FExpand(FileName);
1903     Message(Owner, evBroadcast, cmUpdateTitle, @Self);
1904     { if we rename the file the OnDiskLoadTime is wrong so we reset it }
1905     Core^.OnDiskLoadTime:=0;
1906     if SaveFile then
1907       begin
1908         SaveAs := true;
1909       end
1910     else
1911       begin
1912         FileName:=SavedName;
1913         Core^.OnDiskLoadTime:=SavedDiskLoadTime;
1914         Message(Owner, evBroadcast, cmUpdateTitle, @Self);
1915       end;
1916     if IsClipboard then FileName := '';
1917     Message(Application,evBroadcast,cmFileNameChanged,@Self);
1918   end;
1919 end;
1920 
SaveAsknull1921 function TFileEditor.SaveAsk(Force: boolean): boolean;
1922 var OK: boolean;
1923     D: Sw_integer;
1924 begin
1925   if Force then
1926    begin
1927      if GetModified then
1928       OK:=Save
1929      else
1930       OK:=true;
1931    end
1932   else
1933    begin
1934      OK:=(GetModified=false);
1935      if (OK=false) and (Core^.GetBindingCount>1) then
1936       OK:=true;
1937      if OK=false then
1938       begin
1939         if FileName = '' then D := edSaveUntitled else D := edSaveModify;
1940         case EditorDialog(D, @FileName) of
1941           cmYes    : OK := Save;
1942           cmNo     : begin
1943                      { the file should be still marked as modified! (FK) }
1944                      {   SetModified(False);                               }
1945                      OK:=true;
1946                     end;
1947          cmCancel : begin
1948                       OK := False;
1949                       Message(Application,evBroadcast,cmSaveCancelled,@Self);
1950                     end;
1951         end;
1952       end;
1953    end;
1954   SaveAsk:=OK;
1955 end;
1956 
1957 procedure TFileEditor.BindingsChanged;
1958 begin
1959   Message(Application,evBroadcast,cmUpdateTitle,@Self);
1960 end;
1961 
1962 procedure TFileEditor.HandleEvent(var Event: TEvent);
1963 var SH,B: boolean;
1964 begin
1965   case Event.What of
1966     evBroadcast :
1967       case Event.Command of
1968    cmFileNameChanged :
1969      if (Event.InfoPtr=nil) or (Event.InfoPtr=@Self) then
1970      begin
1971        B:=IsFlagSet(efSyntaxHighlight);
1972        SH:=UseSyntaxHighlight(@Self);
1973        if SH<>B then
1974          if SH then
1975            SetFlags(Flags or efSyntaxHighlight)
1976          else
1977            SetFlags(Flags and not efSyntaxHighlight);
1978        if UseTabsPattern(@Self) then
1979          SetFlags(Flags or efUseTabCharacters);
1980      end;
1981       end;
1982   end;
1983   inherited HandleEvent(Event);
1984 end;
1985 
TFileEditor.Validnull1986 function TFileEditor.Valid(Command: Word): Boolean;
1987 var OK: boolean;
1988 begin
1989   OK:=inherited Valid(Command);
1990   if OK and (Command=cmClose) then
1991     if IsClipboard=false then
1992       OK:=SaveAsk(false);
1993   Valid:=OK;
1994 end;
1995 
1996 (* constructor TFileEditor.Load(var S: TStream);
1997 var P: PString;
1998     SSP,SEP,CP,DP: TPoint;
1999     HR: TRect;
2000     PA : Array[1..2] of pointer;
2001     HoldUndo : boolean;
2002 begin
2003   inherited Load(S);
2004   HoldUndo:=GetStoreUndo;
2005   SetStoreUndo(False);
2006   P:=S.ReadStr;
2007   FileName:=GetStr(P);
2008   if P<>nil then DisposeStr(P);
2009 
2010   UpdateIndicator;
2011 {  Message(@Self,evBroadcast,cmFileNameChanged,@Self);}
2012 
2013   SSP:=SelStart; SEP:=SelEnd;
2014   CP:=CurPos;
2015   HR:=Highlight;
2016   DP:=Delta;
2017 
2018   if FileName<>'' then
2019     LoadFile;
2020 
2021 {  if GetModified then
2022     begin
2023       PA[1]:=@FileName;
2024       longint(PA[2]):=ChangedLine;
2025       EditorDialog(edChangedOnloading,@PA);
2026     end;}
2027 
2028   SetHighlight(HR.A,HR.B);
2029   SetSelection(SSP,SEP);
2030   SetCurPtr(CP.X,CP.Y);
2031   ScrollTo(DP.X,DP.Y);
2032   SetModified(false);
2033 
2034   LimitsChanged;
2035   SetStoreUndo(HoldUndo);
2036 end;
2037 
2038 procedure TFileEditor.Store(var S: TStream);
2039 begin
2040   inherited Store(S);
2041   S.WriteStr(@FileName);
2042 end;
2043 *)
2044 
DefUseSyntaxHighlightnull2045 function DefUseSyntaxHighlight(Editor: PFileEditor): boolean;
2046 begin
2047   DefUseSyntaxHighlight:=Editor^.IsFlagSet(efSyntaxHighlight);
2048 end;
2049 
DefUseTabsPatternnull2050 function DefUseTabsPattern(Editor: PFileEditor): boolean;
2051 begin
2052   DefUseTabsPattern:=Editor^.IsFlagSet(efUseTabCharacters);
2053 end;
2054 
2055 procedure RegisterWCEdit;
2056 begin
2057 {$ifndef NOOBJREG}
2058   RegisterType(RIndicator);
2059   RegisterType(RCodeEditor);
2060   RegisterType(RFileEditor);
2061 {$endif}
2062 end;
2063 
2064 end.
2065