~ubuntu-branches/debian/lenny/fpc/lenny

« back to all changes in this revision

Viewing changes to fpcsrc/ide/weditor.pas

  • Committer: Bazaar Package Importer
  • Author(s): Mazen Neifer, Torsten Werner, Mazen Neifer
  • Date: 2008-05-17 17:12:11 UTC
  • mfrom: (3.1.9 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080517171211-9qi33xhd9evfa0kg
Tags: 2.2.0-dfsg1-9
[ Torsten Werner ]
* Add Mazen Neifer to Uploaders field.

[ Mazen Neifer ]
* Moved FPC sources into a version dependent directory from /usr/share/fpcsrc
  to /usr/share/fpcsrc/${FPCVERSION}. This allow installing more than on FPC
  release.
* Fixed far call issue in compiler preventing building huge binearies.
  (closes: #477743)
* Updated building dependencies, recomennded and suggested packages.
* Moved fppkg to fp-utils as it is just a helper tool and is not required by
  compiler.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
{
 
2
    This file is part of the Free Pascal Integrated Development Environment
 
3
    Copyright (c) 1998 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
{$ifdef TP}{$L-}{$endif}
 
17
unit WEditor;
 
18
 
 
19
interface
 
20
{tes}
 
21
uses
 
22
  Dos,Objects,Drivers,Views,Dialogs,Menus,
 
23
  FVConsts,
 
24
  WUtils,WViews;
 
25
 
 
26
const
 
27
      cmFileNameChanged      = 51234;
 
28
      cmASCIIChar            = 51235;
 
29
      cmClearLineHighlights  = 51236;
 
30
      cmSaveCancelled        = 51237;
 
31
      cmBreakLine            = 51238;
 
32
      cmSelStart             = 51239;
 
33
      cmSelEnd               = 51240;
 
34
      cmLastCursorPos        = 51241;
 
35
      cmIndentBlock          = 51242;
 
36
      cmUnIndentBlock        = 51243;
 
37
      cmSelectLine           = 51244;
 
38
      cmWriteBlock           = 51245;
 
39
      cmReadBlock            = 51246;
 
40
      cmPrintBlock           = 51247;
 
41
      cmResetDebuggerRow     = 51248;
 
42
      cmAddChar              = 51249;
 
43
      cmExpandCodeTemplate   = 51250;
 
44
      cmUpperCase            = 51251;
 
45
      cmLowerCase            = 51252;
 
46
      cmWindowStart          = 51253;
 
47
      cmWindowEnd            = 51254;
 
48
      cmFindMatchingDelimiter= 51255;
 
49
      cmFindMatchingDelimiterBack=51256;
 
50
      cmActivateMenu         = 51257;
 
51
      cmWordLowerCase        = 51258;
 
52
      cmWordUpperCase        = 51259;
 
53
      cmOpenAtCursor         = 51260;
 
54
      cmBrowseAtCursor       = 51261;
 
55
      cmInsertOptions        = 51262;
 
56
      cmToggleCase           = 51263;
 
57
      cmCreateFold           = 51264;
 
58
      cmToggleFold           = 51265;
 
59
      cmCollapseFold         = 51266;
 
60
      cmExpandFold           = 51267;
 
61
      cmDelToEndOfWord       = 51268;
 
62
 
 
63
      EditorTextBufSize = {$ifdef FPC}32768{$else} 4096{$endif};
 
64
      MaxLineLength     = 255;
 
65
      MaxLineCount      = {$ifdef FPC}2000000{$else}16380{$endif};
 
66
 
 
67
 
 
68
      CodeTemplateCursorChar = '|'; { char to signal cursor pos in templates }
 
69
 
 
70
      efBackupFiles         = $00000001;
 
71
      efInsertMode          = $00000002;
 
72
      efAutoIndent          = $00000004;
 
73
      efUseTabCharacters    = $00000008;
 
74
      efBackSpaceUnindents  = $00000010;
 
75
      efPersistentBlocks    = $00000020;
 
76
      efSyntaxHighlight     = $00000040;
 
77
      efBlockInsCursor      = $00000080;
 
78
      efVerticalBlocks      = $00000100;
 
79
      efHighlightColumn     = $00000200;
 
80
      efHighlightRow        = $00000400;
 
81
      efAutoBrackets        = $00000800;
 
82
      efExpandAllTabs       = $00001000;
 
83
      efKeepTrailingSpaces  = $00002000;
 
84
      efCodeComplete        = $00004000;
 
85
      efFolds               = $00008000;
 
86
      efNoIndent            = $00010000;
 
87
      efKeepLineAttr        = $00020000;
 
88
      efStoreContent        = $80000000;
 
89
 
 
90
      attrAsm       = 1;
 
91
      attrComment   = 2;
 
92
      attrForceFull = 128;
 
93
      attrAll       = attrAsm+attrComment;
 
94
 
 
95
      edOutOfMemory   = 0;
 
96
      edReadError     = 1;
 
97
      edWriteError    = 2;
 
98
      edCreateError   = 3;
 
99
      edSaveModify    = 4;
 
100
      edSaveUntitled  = 5;
 
101
      edSaveAs        = 6;
 
102
      edFind          = 7;
 
103
      edSearchFailed  = 8;
 
104
      edReplace       = 9;
 
105
      edReplacePrompt = 10;
 
106
      edTooManyLines  = 11;
 
107
      edGotoLine      = 12;
 
108
      edReplaceFile   = 13;
 
109
      edWriteBlock    = 14;
 
110
      edReadBlock     = 15;
 
111
      edFileOnDiskChanged = 16;
 
112
      edChangedOnloading = 17;
 
113
      edSaveError     = 18;
 
114
      edReloadDiskmodifiedFile = 19;
 
115
      edReloadDiskAndIDEModifiedFile = 20;
 
116
 
 
117
      ffmOptions      = $0007; ffsOptions     = 0;
 
118
      ffmDirection    = $0008; ffsDirection   = 3;
 
119
      ffmScope        = $0010; ffsScope       = 4;
 
120
      ffmOrigin       = $0020; ffsOrigin      = 5;
 
121
      ffDoReplace     = $0040;
 
122
      ffReplaceAll    = $0080;
 
123
 
 
124
 
 
125
      ffCaseSensitive    = $0001;
 
126
      ffWholeWordsOnly   = $0002;
 
127
      ffPromptOnReplace  = $0004;
 
128
 
 
129
      ffForward          = $0000;
 
130
      ffBackward         = $0008;
 
131
 
 
132
      ffGlobal           = $0000;
 
133
      ffSelectedText     = $0010;
 
134
 
 
135
      ffFromCursor       = $0000;
 
136
      ffEntireScope      = $0020;
 
137
 
 
138
{$ifdef TEST_REGEXP}
 
139
      ffUseRegExp        = $0100;
 
140
      ffmUseRegExpFind   = $0004;
 
141
      ffmOptionsFind     = $0003;
 
142
      ffsUseRegExpFind   = 8 - 2;
 
143
      ffmUseRegExpReplace = $0008;
 
144
      ffsUseRegExpReplace = 8 - 3;
 
145
{$endif TEST_REGEXP}
 
146
 
 
147
      coTextColor         = 0;
 
148
      coWhiteSpaceColor   = 1;
 
149
      coCommentColor      = 2;
 
150
      coReservedWordColor = 3;
 
151
      coIdentifierColor   = 4;
 
152
      coStringColor       = 5;
 
153
      coNumberColor       = 6;
 
154
      coAssemblerColor    = 7;
 
155
      coSymbolColor       = 8;
 
156
      coDirectiveColor    = 9;
 
157
      coHexNumberColor    = 10;
 
158
      coTabColor          = 11;
 
159
      coAsmReservedColor  = 12;
 
160
      coBreakColor        = 13;
 
161
      coFirstColor        = 0;
 
162
      coLastColor         = coBreakColor;
 
163
 
 
164
      lfBreakpoint        = $0001;
 
165
      lfHighlightRow      = $0002;
 
166
      lfDebuggerRow       = $0004;
 
167
      lfSpecialRow        = $0008;
 
168
 
 
169
      eaMoveCursor        = 1;
 
170
      eaInsertLine        = 2;
 
171
      eaInsertText        = 3;
 
172
      eaDeleteLine        = 4;
 
173
      eaDeleteText        = 5;
 
174
      eaSelectionChanged  = 6;
 
175
      eaCut               = 7;
 
176
      eaPaste             = 8;
 
177
      eaPasteWin          = 9;
 
178
      eaDelChar           = 10;
 
179
      eaClear             = 11;
 
180
      eaCopyBlock         = 12;
 
181
      eaMoveBlock         = 13;
 
182
      eaDelBlock          = 14;
 
183
      eaReadBlock         = 15;
 
184
      eaIndentBlock       = 16;
 
185
      eaUnindentBlock     = 17;
 
186
      eaOverwriteText     = 18;
 
187
      eaUpperCase         = 19;
 
188
      eaLowerCase         = 20;
 
189
      eaToggleCase        = 21;
 
190
      eaDummy             = 22;
 
191
      LastAction          = eaDummy;
 
192
 
 
193
      ActionString : array [0..LastAction-1] of string[13] =
 
194
        ('','Move','InsLine','InsText','DelLine','DelText',
 
195
         'SelChange','Cut','Paste','PasteWin','DelChar','Clear',
 
196
         'CopyBlock','MoveBlock','DelBlock',
 
197
         'ReadBlock','IndentBlock','UnindentBlock','Overwrite',
 
198
         'UpperCase','LowerCase','ToggleCase');
 
199
 
 
200
      CIndicator    = #2#3#1;
 
201
      CEditor       = #33#34#35#36#37#38#39#40#41#42#43#44#45#46#47#48#49#50;
 
202
 
 
203
      TAB      = #9;
 
204
      FindStrSize = 79;
 
205
 
 
206
 
 
207
type
 
208
    Tcentre = (do_not_centre,do_centre);
 
209
 
 
210
    PCustomCodeEditor = ^TCustomCodeEditor;
 
211
    PEditorLineInfo = ^TEditorLineInfo;
 
212
    PFoldCollection = ^TFoldCollection;
 
213
 
 
214
    PFold = ^TFold;
 
215
    TFold = object(TObject)
 
216
      constructor Init(AEditor: PCustomCodeEditor; AParentFold: PFold; ACollapsed: boolean);
 
217
      procedure   AddReference(P: PObject);
 
218
      procedure   RemoveReference(P: PObject);
 
219
      procedure   AddLineReference(Line: PEditorLineInfo);
 
220
      procedure   RemoveLineReference(Line: PEditorLineInfo);
 
221
      procedure   AddChildReference(Fold: PFold);
 
222
      procedure   RemoveChildReference(Fold: PFold);
 
223
      function    CanDispose: boolean;
 
224
      function    IsCollapsed: boolean;
 
225
      function    IsParent(AFold: PFold): boolean;
 
226
      function    GetLineCount: sw_integer;
 
227
      procedure   Collapse(ACollapse: boolean);
 
228
      procedure   Changed;
 
229
      function    GetLevel: sw_integer;
 
230
      destructor  Done; virtual;
 
231
    public
 
232
      ParentFold: PFold;
 
233
      Collapsed_: boolean;
 
234
      ReferenceCount: sw_integer;
 
235
      Editor: PCustomCodeEditor;
 
236
      LineCount_: sw_integer;
 
237
      Childs: PFoldCollection;
 
238
    end;
 
239
 
 
240
    TFoldCollection = object(TCollection)
 
241
      function At(Index: sw_Integer): PFold;
 
242
    end;
 
243
 
 
244
    TEditorLineInfo = object(TObject)
 
245
      Editor: PCustomCodeEditor;
 
246
      Format : PString;
 
247
      BeginsWithAsm,
 
248
      EndsWithAsm   : boolean;
 
249
      BeginsWithComment,
 
250
      EndsInSingleLineComment,
 
251
      EndsWithComment : boolean;
 
252
      BeginsWithDirective,
 
253
      EndsWithDirective : boolean;
 
254
      BeginCommentType,EndCommentType : byte;
 
255
      Fold: PFold;
 
256
      constructor Init(AEditor: PCustomCodeEditor);
 
257
      destructor  Done; virtual;
 
258
      function    GetFormat: string;
 
259
      procedure   SetFormat(const AFormat: string);
 
260
      procedure   SetFold(AFold: PFold);
 
261
      { Syntax information is now generated separately for each editor instance.
 
262
        This is not neccessary for a one-language IDE, but this unit contains
 
263
        a _generic_ editor object, which should be (and is) as flexible as
 
264
        possible.
 
265
        The overhead caused by generating the same syntax info for ex.
 
266
        twice isn't so much...   - Gabor }
 
267
    end;
 
268
 
 
269
    PEditorLineInfoCollection = ^TEditorLineInfoCollection;
 
270
    TEditorLineInfoCollection = object(TCollection)
 
271
      function At(Index: sw_Integer): PEditorLineInfo;
 
272
    end;
 
273
 
 
274
    PCustomLine = ^TCustomLine;
 
275
    TCustomLine = object(TObject)
 
276
      constructor Init(const AText: string; AFlags: longint);
 
277
   {a}function    GetText: string; virtual;
 
278
   {a}procedure   SetText(const AText: string); virtual;
 
279
   {a}function    GetEditorInfo(Editor: PCustomCodeEditor): PEditorLineInfo; virtual;
 
280
   {a}function    GetFlags: longint; virtual;
 
281
   {a}procedure   SetFlags(AFlags: longint); virtual;
 
282
      function    IsFlagSet(AFlag: longint): boolean; {$ifdef USEINLINE}inline;{$endif}
 
283
      procedure   SetFlagState(AFlag: longint; ASet: boolean);
 
284
      destructor  Done; virtual;
 
285
    public { internal use only! }
 
286
   {a}procedure AddEditorInfo(Index: sw_integer; AEditor: PCustomCodeEditor); virtual;
 
287
   {a}procedure RemoveEditorInfo(AEditor: PCustomCodeEditor); virtual;
 
288
    end;
 
289
 
 
290
    PLineCollection = ^TLineCollection;
 
291
    TLineCollection = object(TCollection)
 
292
      function  At(Index: sw_Integer): PCustomLine;
 
293
    end;
 
294
 
 
295
    PEditorAction = ^TEditorAction;
 
296
    TEditorAction = object(TObject)
 
297
      StartPos  : TPoint;
 
298
      EndPos    : TPoint;
 
299
      Text      : PString;
 
300
      ActionCount : longint;
 
301
      Flags : longint;
 
302
      Action    : byte;
 
303
      IsGrouped : boolean;
 
304
      TimeStamp : longint; { this is needed to keep track of line number &
 
305
                             position changes (for ex. for symbol browser)
 
306
                             the line&pos references (eg. symbol info) should
 
307
                             also contain such a timestamp. this will enable
 
308
                             to determine which changes have been made since
 
309
                             storage of the information and thus calculate
 
310
                             the (probably) changed line & position information,
 
311
                             so, we can still jump to the right position in the
 
312
                             editor even when it is heavily modified - Gabor }
 
313
      constructor init(act:byte; StartP,EndP:TPoint;Txt:String;AFlags : longint);
 
314
      constructor init_group(act:byte);
 
315
      function is_grouped_action : boolean;
 
316
      destructor done; virtual;
 
317
    end;
 
318
 
 
319
    PEditorActionCollection = ^TEditorActionCollection;
 
320
    TEditorActionCollection = object(TCollection)
 
321
      CurrentGroupedAction : PEditorAction;
 
322
      GroupLevel           : longint;
 
323
      function At(Idx : sw_integer) : PEditorAction;
 
324
    end;
 
325
 
 
326
    TSpecSymbolClass =
 
327
      (ssCommentPrefix,ssCommentSingleLinePrefix,ssCommentSuffix,ssStringPrefix,ssStringSuffix,
 
328
       ssDirectivePrefix,ssDirectiveSuffix,ssAsmPrefix,ssAsmSuffix);
 
329
 
 
330
    TEditorBookMark = record
 
331
      Valid  : boolean;
 
332
      Pos    : TPoint;
 
333
    end;
 
334
 
 
335
    TCompleteState = (csInactive,csOffering,csDenied);
 
336
 
 
337
    PEditorBinding = ^TEditorBinding;
 
338
 
 
339
    PEditorBindingCollection = ^TEditorBindingCollection;
 
340
    TEditorBindingCollection = object(TCollection)
 
341
      function At(Index: sw_Integer): PEditorBinding;
 
342
    end;
 
343
 
 
344
    TEditorBinding = object(TObject)
 
345
      Editor : PCustomCodeEditor;
 
346
      constructor Init(AEditor: PCustomCodeEditor);
 
347
      destructor  Done; virtual;
 
348
    end;
 
349
 
 
350
    PCustomCodeEditorCore = ^TCustomCodeEditorCore;
 
351
    TCustomCodeEditorCore = object(TObject)
 
352
    {$ifdef TP}public{$else}protected{$endif}
 
353
      Bindings    : PEditorBindingCollection;
 
354
      LockFlag    : sw_integer;
 
355
      ChangedLine : sw_integer;
 
356
      ContentsChangedCalled : boolean;
 
357
      LimitsChangedCalled : boolean;
 
358
      ModifiedChangedCalled : boolean;
 
359
      TabSizeChangedCalled : boolean;
 
360
      StoreUndoChangedCalled : boolean;
 
361
{$ifdef TEST_PARTIAL_SYNTAX}
 
362
      LastSyntaxedLine : sw_integer;
 
363
      SyntaxComplete   : boolean;
 
364
{$endif TEST_PARTIAL_SYNTAX}
 
365
    public
 
366
      constructor Init;
 
367
      procedure   BindEditor(AEditor: PCustomCodeEditor);
 
368
      procedure   UnBindEditor(AEditor: PCustomCodeEditor);
 
369
      function    IsEditorBound(AEditor: PCustomCodeEditor): boolean;
 
370
      function    GetBindingCount: sw_integer;
 
371
      function    GetBindingIndex(AEditor: PCustomCodeEditor): sw_integer;
 
372
      function    SearchBinding(AEditor: PCustomCodeEditor): PEditorBinding;
 
373
      function    CanDispose: boolean;
 
374
      destructor  Done; virtual;
 
375
    public
 
376
   {a}function    GetModified: boolean; virtual;
 
377
      function    GetChangedLine: sw_integer;
 
378
   {a}procedure   SetModified(AModified: boolean); virtual;
 
379
   {a}function    GetStoreUndo: boolean; virtual;
 
380
   {a}procedure   SetStoreUndo(AStore: boolean); virtual;
 
381
   {a}function    GetSyntaxCompleted: boolean; virtual;
 
382
   {a}procedure   SetSyntaxCompleted(SC: boolean); virtual;
 
383
   {a}function    GetTabSize: integer; virtual;
 
384
   {a}procedure   SetTabSize(ATabSize: integer); virtual;
 
385
   {a}function    GetIndentSize: integer; virtual;
 
386
   {a}procedure   SetIndentSize(AIndentSize: integer); virtual;
 
387
      function    IsClipboard: Boolean;
 
388
    public
 
389
      { Notifications }
 
390
      procedure   BindingsChanged;
 
391
      procedure   ContentsChanged;
 
392
      procedure   LimitsChanged;
 
393
      procedure   ModifiedChanged;
 
394
      procedure   TabSizeChanged;
 
395
      procedure   StoreUndoChanged;
 
396
   {a}procedure   DoContentsChanged; virtual;
 
397
   {a}procedure   DoLimitsChanged; virtual;
 
398
   {a}procedure   DoModifiedChanged; virtual;
 
399
   {a}procedure   DoTabSizeChanged; virtual;
 
400
   {a}procedure   DoStoreUndoChanged; virtual;
 
401
   {a}procedure   DoSyntaxStateChanged; virtual;
 
402
      function    GetLastVisibleLine : sw_integer;
 
403
    public
 
404
      { Storage }
 
405
      function    LoadFromStream(Editor: PCustomCodeEditor; Stream: PFastBufStream): boolean; virtual;
 
406
      function    SaveToStream(Editor: PCustomCodeEditor; Stream: PStream): boolean; virtual;
 
407
      function    SaveAreaToStream(Editor: PCustomCodeEditor; Stream: PStream; StartP,EndP: TPoint): boolean; virtual;
 
408
    {$ifdef TP}public{$else}protected{$endif}
 
409
      { Text & info storage abstraction }
 
410
   {a}procedure   ISetLineFlagState(Binding: PEditorBinding; LineNo: sw_integer; Flag: longint; ASet: boolean); virtual;
 
411
   {a}procedure   IGetDisplayTextFormat(Binding: PEditorBinding; LineNo: sw_integer;var DT,DF:string); virtual;
 
412
   {a}function    IGetLineFormat(Binding: PEditorBinding; LineNo: sw_integer): string; virtual;
 
413
   {a}procedure   ISetLineFormat(Binding: PEditorBinding; LineNo: sw_integer;const S: string); virtual;
 
414
    public
 
415
      { Text & info storage abstraction }
 
416
      function    CharIdxToLinePos(Line,CharIdx: sw_integer): sw_integer;
 
417
      function    LinePosToCharIdx(Line,X: sw_integer): sw_integer;
 
418
   {a}function    GetLineCount: sw_integer; virtual;
 
419
   {a}function    GetLine(LineNo: sw_integer): PCustomLine; virtual;
 
420
   {a}function    GetLineText(LineNo: sw_integer): string; virtual;
 
421
   {a}procedure   SetDisplayText(I: sw_integer;const S: string); virtual;
 
422
   {a}function    GetDisplayText(I: sw_integer): string; virtual;
 
423
   {a}procedure   SetLineText(I: sw_integer;const S: string); virtual;
 
424
      procedure   GetDisplayTextFormat(Editor: PCustomCodeEditor; I: sw_integer;var DT,DF:string); virtual;
 
425
      function    GetLineFormat(Editor: PCustomCodeEditor; I: sw_integer): string; virtual;
 
426
      procedure   SetLineFormat(Editor: PCustomCodeEditor; I: sw_integer;const S: string); virtual;
 
427
   {a}procedure   DeleteAllLines; virtual;
 
428
   {a}procedure   DeleteLine(I: sw_integer); virtual;
 
429
   {a}function    InsertLine(LineNo: sw_integer; const S: string): PCustomLine; virtual;
 
430
   {a}procedure   AddLine(const S: string); virtual;
 
431
   {a}procedure   GetContent(ALines: PUnsortedStringCollection); virtual;
 
432
   {a}procedure   SetContent(ALines: PUnsortedStringCollection); virtual;
 
433
   public
 
434
      procedure   Lock(AEditor: PCustomCodeEditor);
 
435
      procedure   UnLock(AEditor: PCustomCodeEditor);
 
436
      function    Locked: boolean;
 
437
   public
 
438
      { Syntax highlight }
 
439
      function    UpdateAttrs(FromLine: sw_integer; Attrs: byte): sw_integer; virtual;
 
440
      function    UpdateAttrsRange(FromLine, ToLine: sw_integer; Attrs: byte): sw_integer; virtual;
 
441
      function    DoUpdateAttrs(Editor: PCustomCodeEditor; FromLine: sw_integer; Attrs: byte): sw_integer; virtual;
 
442
      function    DoUpdateAttrsRange(Editor: PCustomCodeEditor; FromLine, ToLine: sw_integer;
 
443
                  Attrs: byte): sw_integer; virtual;
 
444
   public
 
445
     { Undo info storage }
 
446
   {a}procedure   AddAction(AAction: byte; AStartPos, AEndPos: TPoint; AText: string;AFlags : longint); virtual;
 
447
   {a}procedure   AddGroupedAction(AAction : byte); virtual;
 
448
   {a}procedure   CloseGroupedAction(AAction : byte); virtual;
 
449
   {a}function    GetUndoActionCount: sw_integer; virtual;
 
450
   {a}function    GetRedoActionCount: sw_integer; virtual;
 
451
      procedure   UpdateUndoRedo(cm : word; action : byte);virtual;
 
452
    end;
 
453
 
 
454
    TCaseAction = (caToLowerCase,caToUpperCase,caToggleCase);
 
455
 
 
456
    TCustomCodeEditor = object(TScroller)
 
457
      SelStart   : TPoint;
 
458
      SelEnd     : TPoint;
 
459
      Highlight  : TRect;
 
460
      CurPos     : TPoint;
 
461
      ELockFlag   : integer;
 
462
      NoSelect   : Boolean;
 
463
      AlwaysShowScrollBars: boolean;
 
464
   public
 
465
{      constructor Load(var S: TStream);
 
466
      procedure   Store(var S: TStream);}
 
467
      procedure   ConvertEvent(var Event: TEvent); virtual;
 
468
      procedure   HandleEvent(var Event: TEvent); virtual;
 
469
      procedure   SetState(AState: Word; Enable: Boolean); virtual;
 
470
      procedure   LocalMenu(P: TPoint); virtual;
 
471
      function    GetLocalMenu: PMenu; virtual;
 
472
      function    GetCommandTarget: PView; virtual;
 
473
      function    CreateLocalMenuView(var Bounds: TRect; M: PMenu): PMenuPopup; virtual;
 
474
      function    GetPalette: PPalette; virtual;
 
475
    public
 
476
      procedure   Draw; virtual;
 
477
      procedure   DrawCursor; virtual;
 
478
      { this is the only way I found to avoid
 
479
        having the cursor being updated if lock is on PM }
 
480
      procedure   ResetCursor; virtual;
 
481
      procedure   DrawIndicator; virtual;
 
482
    public
 
483
   {a}function    GetFlags: longint; virtual;
 
484
   {a}procedure   SetFlags(AFlags: longint); virtual;
 
485
   {a}function    GetModified: boolean; virtual;
 
486
   {a}procedure   SetModified(AModified: boolean); virtual;
 
487
   {a}function    GetStoreUndo: boolean; virtual;
 
488
   {a}procedure   SetStoreUndo(AStore: boolean); virtual;
 
489
   {a}function    GetSyntaxCompleted: boolean; virtual;
 
490
   {a}procedure   SetSyntaxCompleted(SC: boolean); virtual;
 
491
   {a}function    GetLastSyntaxedLine: sw_integer; virtual;
 
492
   {a}procedure   SetLastSyntaxedLine(ALine: sw_integer); virtual;
 
493
      function    IsFlagSet(AFlag: longint): boolean;{$ifdef USEINLINE}inline;{$endif}
 
494
      function    GetReservedColCount: sw_integer; virtual;
 
495
   {a}function    GetTabSize: integer; virtual;
 
496
   {a}procedure   SetTabSize(ATabSize: integer); virtual;
 
497
   {a}function    GetIndentSize: integer; virtual;
 
498
   {a}procedure   SetIndentSize(AIndentSize: integer); virtual;
 
499
   {a}function    IsReadOnly: boolean; virtual;
 
500
   {a}function    IsClipboard: Boolean; virtual;
 
501
   {a}function    GetInsertMode: boolean; virtual;
 
502
   {a}procedure   SetInsertMode(InsertMode: boolean); virtual;
 
503
      procedure   SetCurPtr(X,Y: sw_integer); virtual;
 
504
      procedure   GetSelectionArea(var StartP,EndP: TPoint); virtual;
 
505
      procedure   SetSelection(A, B: TPoint); virtual;
 
506
      procedure   SetHighlight(A, B: TPoint); virtual;
 
507
      procedure   ChangeCaseArea(StartP,EndP: TPoint; CaseAction: TCaseAction); virtual;
 
508
      procedure   SetLineFlagState(LineNo: sw_integer; Flags: longint; ASet: boolean);
 
509
      procedure   SetLineFlagExclusive(Flags: longint; LineNo: sw_integer);
 
510
      procedure   Update; virtual;
 
511
      procedure   ScrollTo(X, Y: sw_Integer);
 
512
      procedure   TrackCursor(centre:Tcentre); virtual;
 
513
      procedure   Lock; virtual;
 
514
      procedure   UnLock; virtual;
 
515
    public
 
516
      { Text & info storage abstraction }
 
517
   {a}function    GetLineCount: sw_integer; virtual;
 
518
   {a}function    GetLine(LineNo: sw_integer): PCustomLine; virtual;
 
519
   {a}function    CharIdxToLinePos(Line,CharIdx: sw_integer): sw_integer; virtual;
 
520
   {a}function    LinePosToCharIdx(Line,X: sw_integer): sw_integer; virtual;
 
521
   {a}function    GetLineText(I: sw_integer): string; virtual;
 
522
   {a}procedure   SetDisplayText(I: sw_integer;const S: string); virtual;
 
523
   {a}function    GetDisplayText(I: sw_integer): string; virtual;
 
524
   {a}procedure   SetLineText(I: sw_integer;const S: string); virtual;
 
525
   {a}procedure   GetDisplayTextFormat(I: sw_integer;var DT,DF:string); virtual;
 
526
   {a}function    GetLineFormat(I: sw_integer): string; virtual;
 
527
   {a}procedure   SetLineFormat(I: sw_integer;const S: string); virtual;
 
528
   {a}procedure   DeleteAllLines; virtual;
 
529
   {a}procedure   DeleteLine(I: sw_integer); virtual;
 
530
   {a}function    InsertLine(LineNo: sw_integer; const S: string): PCustomLine; virtual;
 
531
   {a}procedure   AddLine(const S: string); virtual;
 
532
   {a}function    GetErrorMessage: string; virtual;
 
533
   {a}procedure   SetErrorMessage(const S: string); virtual;
 
534
   {a}procedure   AdjustSelection(DeltaX, DeltaY: sw_integer);
 
535
   {a}procedure   AdjustSelectionBefore(DeltaX, DeltaY: sw_integer);
 
536
   {a}procedure   AdjustSelectionPos(OldCurPosX, OldCurPosY: sw_integer; DeltaX, DeltaY: sw_integer);
 
537
   {a}procedure   GetContent(ALines: PUnsortedStringCollection); virtual;
 
538
   {a}procedure   SetContent(ALines: PUnsortedStringCollection); virtual;
 
539
   {a}function    LoadFromStream(Stream: PFastBufStream): boolean; virtual;
 
540
   {a}function    SaveToStream(Stream: PStream): boolean; virtual;
 
541
   {a}function    SaveAreaToStream(Stream: PStream; StartP,EndP: TPoint): boolean;virtual;
 
542
      function    LoadFromFile(const AFileName: string): boolean; virtual;
 
543
      function    SaveToFile(const AFileName: string): boolean; virtual;
 
544
    public
 
545
   {a}function    InsertFrom(Editor: PCustomCodeEditor): Boolean; virtual;
 
546
   {a}function    InsertText(const S: string): Boolean; virtual;
 
547
    public
 
548
      procedure   FlagsChanged(OldFlags: longint); virtual;
 
549
   {a}procedure   BindingsChanged; virtual;
 
550
      procedure   ContentsChanged; virtual;
 
551
      procedure   LimitsChanged; virtual;
 
552
      procedure   ModifiedChanged; virtual;
 
553
      procedure   PositionChanged; virtual;
 
554
      procedure   TabSizeChanged; virtual;
 
555
      procedure   SyntaxStateChanged; virtual;
 
556
      procedure   StoreUndoChanged; virtual;
 
557
      procedure   SelectionChanged; virtual;
 
558
      procedure   HighlightChanged; virtual;
 
559
   {a}procedure   DoLimitsChanged; virtual;
 
560
    public
 
561
     { Syntax highlight support }
 
562
   {a}function    GetSpecSymbolCount(SpecClass: TSpecSymbolClass): integer; virtual;
 
563
   {a}function    GetSpecSymbol(SpecClass: TSpecSymbolClass; Index: integer): pstring; virtual;
 
564
   {a}function    IsReservedWord(const S: string): boolean; virtual;
 
565
   {a}function    IsAsmReservedWord(const S: string): boolean; virtual;
 
566
    public
 
567
     { CodeTemplate support }
 
568
   {a}function    TranslateCodeTemplate(var Shortcut: string; ALines: PUnsortedStringCollection): boolean; virtual;
 
569
      function    SelectCodeTemplate(var ShortCut: string): boolean; virtual;
 
570
     { CodeComplete support }
 
571
   {a}function    CompleteCodeWord(const WordS: string; var Text: string): boolean; virtual;
 
572
   {a}function    GetCodeCompleteWord: string; virtual;
 
573
   {a}procedure   SetCodeCompleteWord(const S: string); virtual;
 
574
   {a}function    GetCodeCompleteFrag: string; virtual;
 
575
   {a}procedure   SetCodeCompleteFrag(const S: string); virtual;
 
576
      function    GetCompleteState: TCompleteState; virtual;
 
577
      procedure   SetCompleteState(AState: TCompleteState); virtual;
 
578
      procedure   ClearCodeCompleteWord; virtual;
 
579
     { Fold support }
 
580
      function    GetMaxFoldLevel: sw_integer; virtual;
 
581
      function    GetFoldStringWidth: sw_integer; virtual;
 
582
      procedure   GetFoldStrings(EditorLine: sw_integer; var Prefix, Suffix: openstring); virtual;
 
583
   {a}function    GetFoldCount: sw_integer; virtual;
 
584
   {a}function    GetFold(Index: sw_integer): PFold; virtual;
 
585
   {a}procedure   RegisterFold(AFold: PFold); virtual;
 
586
   {a}procedure   UnRegisterFold(AFold: PFold); virtual;
 
587
      function    ViewToEditorLine(ViewLine: sw_integer): sw_integer;
 
588
      function    EditorToViewLine(EditorLine: sw_integer): sw_integer;
 
589
      procedure   ViewToEditorPoint(P: TPoint; var NP: TPoint);
 
590
      procedure   EditorToViewPoint(P: TPoint; var NP: TPoint);
 
591
     { Fold support }
 
592
      function    CreateFold(StartY,EndY: sw_integer; Collapsed: boolean): boolean; virtual;
 
593
      procedure   FoldChanged(Fold: PFold); virtual;
 
594
      procedure   RemoveAllFolds; virtual;
 
595
   public
 
596
      { Syntax highlight }
 
597
   {a}function    UpdateAttrs(FromLine: sw_integer; Attrs: byte): sw_integer; virtual;
 
598
   {a}function    UpdateAttrsRange(FromLine, ToLine: sw_integer; Attrs: byte): sw_integer; virtual;
 
599
    public
 
600
     { Undo info storage }
 
601
   {a}procedure   AddAction(AAction: byte; AStartPos, AEndPos: TPoint; AText: string;AFlags : longint); virtual;
 
602
   {a}procedure   AddGroupedAction(AAction : byte); virtual;
 
603
   {a}procedure   CloseGroupedAction(AAction : byte); virtual;
 
604
   {a}function    GetUndoActionCount: sw_integer; virtual;
 
605
   {a}function    GetRedoActionCount: sw_integer; virtual;
 
606
    {$ifdef TP}public{$else}protected{$endif}
 
607
      LastLocalCmd: word;
 
608
      KeyState    : Integer;
 
609
      Bookmarks   : array[0..9] of TEditorBookmark;
 
610
      DrawCalled,
 
611
      DrawCursorCalled: boolean;
 
612
      CurEvent    : PEvent;
 
613
      procedure   DrawLines(FirstLine: sw_integer);
 
614
      function    Overwrite: boolean;
 
615
      function    IsModal: boolean;
 
616
      procedure   CheckSels;
 
617
      procedure   CodeCompleteCheck;
 
618
      procedure   CodeCompleteApply;
 
619
      procedure   CodeCompleteCancel;
 
620
      procedure   UpdateUndoRedo(cm : word; action : byte);
 
621
      procedure   HideHighlight;
 
622
      function    ShouldExtend: boolean;
 
623
      function    ValidBlock: boolean;
 
624
      function    GetLineFold(EditorLine: sw_integer): PFold;
 
625
      function    IsLineVisible(EditorLine: sw_integer): boolean; virtual;
 
626
      function    NextVisibleLine(StartLine: sw_integer; Down: boolean): sw_integer;
 
627
      procedure   PushInfo(Const st : string);virtual;
 
628
      procedure   PopInfo;virtual;
 
629
    public
 
630
      { Editor primitives }
 
631
      procedure   SelectAll(Enable: boolean); virtual;
 
632
    public
 
633
      { Editor commands }
 
634
      SearchRunCount: integer;
 
635
      InASCIIMode: boolean;
 
636
      procedure Indent; virtual;
 
637
      procedure CharLeft; virtual;
 
638
      procedure CharRight; virtual;
 
639
      procedure WordLeft; virtual;
 
640
      procedure WordRight; virtual;
 
641
      procedure LineStart; virtual;
 
642
      procedure LineEnd; virtual;
 
643
      procedure LineUp; virtual;
 
644
      procedure LineDown; virtual;
 
645
      procedure PageUp; virtual;
 
646
      procedure PageDown; virtual;
 
647
      procedure TextStart; virtual;
 
648
      procedure TextEnd; virtual;
 
649
      procedure WindowStart; virtual;
 
650
      procedure WindowEnd; virtual;
 
651
      procedure JumpSelStart; virtual;
 
652
      procedure JumpSelEnd; virtual;
 
653
      procedure JumpMark(MarkIdx: integer); virtual;
 
654
      procedure DefineMark(MarkIdx: integer); virtual;
 
655
      procedure JumpToLastCursorPos; virtual;
 
656
      procedure FindMatchingDelimiter(ScanForward: boolean); virtual;
 
657
      procedure CreateFoldFromBlock; virtual;
 
658
      procedure ToggleFold; virtual;
 
659
      procedure CollapseFold; virtual;
 
660
      procedure ExpandFold; virtual;
 
661
      procedure UpperCase; virtual;
 
662
      procedure LowerCase; virtual;
 
663
      procedure WordLowerCase; virtual;
 
664
      procedure WordUpperCase; virtual;
 
665
      procedure InsertOptions; virtual;
 
666
      procedure ToggleCase; virtual;
 
667
      function  InsertNewLine: Sw_integer; virtual;
 
668
      procedure BreakLine; virtual;
 
669
      procedure BackSpace; virtual;
 
670
      procedure DelChar; virtual;
 
671
      procedure DelWord; virtual;
 
672
      procedure DelToEndOfWord; virtual;
 
673
      procedure DelStart; virtual;
 
674
      procedure DelEnd; virtual;
 
675
      procedure DelLine; virtual;
 
676
      procedure InsMode; virtual;
 
677
      procedure StartSelect; virtual;
 
678
      procedure EndSelect; virtual;
 
679
      procedure DelSelect; virtual;
 
680
      procedure HideSelect; virtual;
 
681
      procedure CopyBlock; virtual;
 
682
      procedure MoveBlock; virtual;
 
683
      procedure IndentBlock; virtual;
 
684
      procedure UnindentBlock; virtual;
 
685
      procedure SelectWord; virtual;
 
686
      procedure SelectLine; virtual;
 
687
      procedure WriteBlock; virtual;
 
688
      procedure ReadBlock; virtual;
 
689
      procedure PrintBlock; virtual;
 
690
      procedure ExpandCodeTemplate; virtual;
 
691
      procedure AddChar(C: char); virtual;
 
692
{$ifdef WinClipSupported}
 
693
      function  ClipCopyWin: Boolean; virtual;
 
694
      function  ClipPasteWin: Boolean; virtual;
 
695
{$endif WinClipSupported}
 
696
      function  ClipCopy: Boolean; virtual;
 
697
      procedure ClipCut; virtual;
 
698
      procedure ClipPaste; virtual;
 
699
      function  GetCurrentWord : string;
 
700
      function  GetCurrentWordArea(var StartP,EndP: TPoint): boolean;
 
701
      procedure Undo; virtual;
 
702
      procedure Redo; virtual;
 
703
      procedure Find; virtual;
 
704
      procedure Replace; virtual;
 
705
      procedure DoSearchReplace; virtual;
 
706
      procedure GotoLine; virtual;
 
707
    end;
 
708
 
 
709
    TCodeEditorDialog = function(Dialog: Integer; Info: Pointer): Word;
 
710
 
 
711
    TEditorInputLine = object(TInputLine)
 
712
      Procedure   HandleEvent(var Event : TEvent);virtual;
 
713
    end;
 
714
    PEditorInputLine = ^TEditorInputLine;
 
715
 
 
716
 
 
717
const
 
718
     { used for ShiftDel and ShiftIns to avoid
 
719
       GetShiftState to be considered for extending
 
720
       selection (PM) }
 
721
     DontConsiderShiftState: boolean  = false;
 
722
 
 
723
     CodeCompleteMinLen : byte = 4; { minimum length of text to try to complete }
 
724
 
 
725
     ToClipCmds         : TCommandSet = ([cmCut,cmCopy,cmCopyWin,
 
726
       { cmUnselect should because like cut, copy, copywin:
 
727
         if there is a selection, it is active, else it isn't }
 
728
       cmUnselect]);
 
729
     FromClipCmds       : TCommandSet = ([cmPaste]);
 
730
     NulClipCmds        : TCommandSet = ([cmClear]);
 
731
     UndoCmd            : TCommandSet = ([cmUndo]);
 
732
     RedoCmd            : TCommandSet = ([cmRedo]);
 
733
 
 
734
function ExtractTabs(S: string; TabSize: Sw_integer): string;
 
735
 
 
736
function StdEditorDialog(Dialog: Integer; Info: Pointer): word;
 
737
 
 
738
const
 
739
     DefaultSaveExt     : string[12] = '.pas';
 
740
     FileDir            : DirStr = '';
 
741
 
 
742
     EditorDialog       : TCodeEditorDialog = {$ifdef fpc}@{$endif}StdEditorDialog;
 
743
     Clipboard          : PCustomCodeEditor = nil;
 
744
     FindStr            : String[FindStrSize] = '';
 
745
     ReplaceStr         : String[FindStrSize] = '';
 
746
     FindReplaceEditor  : PCustomCodeEditor = nil;
 
747
     FindFlags          : word = ffPromptOnReplace;
 
748
{$ifndef NO_UNTYPEDSET}
 
749
  {$define USE_UNTYPEDSET}
 
750
{$endif ndef NO_UNTYPEDSET}
 
751
     WhiteSpaceChars    {$ifdef USE_UNTYPEDSET}: set of char {$endif} = [#0,#32,#255];
 
752
     TabChars           {$ifdef USE_UNTYPEDSET}: set of char {$endif} = [#9];
 
753
     HashChars          {$ifdef USE_UNTYPEDSET}: set of char {$endif} = ['#'];
 
754
     AlphaChars         {$ifdef USE_UNTYPEDSET}: set of char {$endif} = ['A'..'Z','a'..'z','_'];
 
755
     NumberChars        {$ifdef USE_UNTYPEDSET}: set of char {$endif} = ['0'..'9'];
 
756
     HexNumberChars     {$ifdef USE_UNTYPEDSET}: set of char {$endif} = ['0'..'9','A'..'F','a'..'f'];
 
757
     RealNumberChars    {$ifdef USE_UNTYPEDSET}: set of char {$endif} = ['E','e','.'{,'+','-'}];
 
758
 
 
759
procedure RegisterWEditor;
 
760
 
 
761
implementation
 
762
 
 
763
uses
 
764
  Strings,Video,MsgBox,App,StdDlg,Validate,
 
765
{$ifdef WinClipSupported}
 
766
  WinClip,
 
767
{$endif WinClipSupported}
 
768
{$ifdef TEST_REGEXP}
 
769
  regexpr,
 
770
{$endif TEST_REGEXP}
 
771
  WConsts,WCEdit;
 
772
 
 
773
type
 
774
    RecordWord = sw_word;
 
775
 
 
776
     TFindDialogRec = packed record
 
777
       Find     : String[FindStrSize];
 
778
       Options  : RecordWord{longint};
 
779
       { checkboxes need 32  bits PM  }
 
780
       { reverted to word in dialogs.TCluster for TP compatibility (PM) }
 
781
       { anyhow its complete nonsense : you can only have 16 fields
 
782
         but use a longint to store it !! }
 
783
       Direction: RecordWord;{ and tcluster has word size }
 
784
       Scope    : RecordWord;
 
785
       Origin   : RecordWord;
 
786
     end;
 
787
 
 
788
     TReplaceDialogRec = packed record
 
789
       Find     : String[FindStrSize];
 
790
       Replace  : String[FindStrSize];
 
791
       Options  : RecordWord{longint};
 
792
       Direction: RecordWord;
 
793
       Scope    : RecordWord;
 
794
       Origin   : RecordWord;
 
795
     end;
 
796
 
 
797
     TGotoLineDialogRec = packed record
 
798
       LineNo  : string[5];
 
799
       Lines   : sw_integer;
 
800
     end;
 
801
 
 
802
const
 
803
     kbShift = kbLeftShift+kbRightShift;
 
804
 
 
805
const
 
806
  FirstKeyCount = 46;
 
807
  FirstKeys: array[0..FirstKeyCount * 2] of Word = (FirstKeyCount,
 
808
    Ord(^A), cmWordLeft, Ord(^B), cmJumpLine, Ord(^C), cmPageDown,
 
809
    Ord(^D), cmCharRight, Ord(^E), cmLineUp,
 
810
    Ord(^F), cmWordRight, Ord(^G), cmDelChar,
 
811
    Ord(^H), cmBackSpace, Ord(^J), cmExpandCodeTemplate,
 
812
    Ord(^K), $FF02, Ord(^L), cmSearchAgain,
 
813
    Ord(^M), cmNewLine, Ord(^N), cmBreakLine,
 
814
    Ord(^O), $FF03,
 
815
    Ord(^P), cmASCIIChar, Ord(^Q), $FF01,
 
816
    Ord(^R), cmPageUp, Ord(^S), cmCharLeft,
 
817
    Ord(^T), cmDelToEndOfWord, Ord(^U), cmUndo,
 
818
    Ord(^V), cmInsMode, Ord(^X), cmLineDown,
 
819
    Ord(^Y), cmDelLine, kbLeft, cmCharLeft,
 
820
    kbRight, cmCharRight, kbCtrlLeft, cmWordLeft,
 
821
    kbCtrlRight, cmWordRight, kbHome, cmLineStart,
 
822
    kbCtrlHome, cmWindowStart, kbCtrlEnd, cmWindowEnd,
 
823
    kbEnd, cmLineEnd, kbUp, cmLineUp,
 
824
    kbDown, cmLineDown, kbPgUp, cmPageUp,
 
825
    kbPgDn, cmPageDown, kbCtrlPgUp, cmTextStart,
 
826
    kbCtrlPgDn, cmTextEnd, kbIns, cmInsMode,
 
827
    kbDel, cmDelChar, kbShiftIns, cmPaste,
 
828
    kbShiftDel, cmCut, kbCtrlIns, cmCopy,
 
829
    kbCtrlDel, cmClear,
 
830
    kbCtrlGrayMul, cmToggleFold, kbCtrlGrayMinus, cmCollapseFold, kbCtrlGrayPlus, cmExpandFold);
 
831
  QuickKeyCount = 29;
 
832
  QuickKeys: array[0..QuickKeyCount * 2] of Word = (QuickKeyCount,
 
833
    Ord('A'), cmReplace, Ord('C'), cmTextEnd,
 
834
    Ord('D'), cmLineEnd, Ord('F'), cmFind,
 
835
    Ord('H'), cmDelStart, Ord('R'), cmTextStart,
 
836
    Ord('S'), cmLineStart, Ord('Y'), cmDelEnd,
 
837
    Ord('G'), cmJumpLine, Ord('A'), cmReplace,
 
838
    Ord('B'), cmSelStart, Ord('K'), cmSelEnd,
 
839
    Ord('P'), cmLastCursorPos,
 
840
    Ord('E'), cmWindowStart, Ord('T'), cmWindowStart,
 
841
    Ord('U'), cmWindowEnd, Ord('X'), cmWindowEnd,
 
842
    Ord('['), cmFindMatchingDelimiter, Ord(']'), cmFindMatchingDelimiterBack,
 
843
    Ord('0'), cmJumpMark0, Ord('1'), cmJumpMark1, Ord('2'), cmJumpMark2,
 
844
    Ord('3'), cmJumpMark3, Ord('4'), cmJumpMark4, Ord('5'), cmJumpMark5,
 
845
    Ord('6'), cmJumpMark6, Ord('7'), cmJumpMark7, Ord('8'), cmJumpMark8,
 
846
    Ord('9'), cmJumpMark9);
 
847
  BlockKeyCount = 30;
 
848
  BlockKeys: array[0..BlockKeyCount * 2] of Word = (BlockKeyCount,
 
849
    Ord('B'), cmStartSelect, Ord('C'), cmCopyBlock,
 
850
    Ord('H'), cmHideSelect, Ord('K'), cmEndSelect,
 
851
    Ord('Y'), cmDelSelect, Ord('V'), cmMoveBlock,
 
852
    Ord('I'), cmIndentBlock, Ord('U'), cmUnindentBlock,
 
853
    Ord('T'), cmSelectWord, Ord('L'), cmSelectLine,
 
854
    Ord('W'), cmWriteBlock, Ord('R'), cmReadBlock,
 
855
    Ord('P'), cmPrintBlock,
 
856
    Ord('N'), cmUpperCase, Ord('O'), cmLowerCase,
 
857
    Ord('D'), cmActivateMenu,
 
858
    Ord('E'), cmWordLowerCase, Ord('F'), cmWordUpperCase,
 
859
    Ord('S'), cmSave, Ord('A'), cmCreateFold,
 
860
    Ord('0'), cmSetMark0, Ord('1'), cmSetMark1, Ord('2'), cmSetMark2,
 
861
    Ord('3'), cmSetMark3, Ord('4'), cmSetMark4, Ord('5'), cmSetMark5,
 
862
    Ord('6'), cmSetMark6, Ord('7'), cmSetMark7, Ord('8'), cmSetMark8,
 
863
    Ord('9'), cmSetMark9);
 
864
  MiscKeyCount = 6;
 
865
  MiscKeys: array[0..MiscKeyCount * 2] of Word = (MiscKeyCount,
 
866
    Ord('A'), cmOpenAtCursor, Ord('B'), cmBrowseAtCursor,
 
867
    Ord('G'), cmJumpLine, Ord('O'), cmInsertOptions,
 
868
    Ord('U'), cmToggleCase, Ord('L'), cmSelectLine);
 
869
  KeyMap: array[0..3] of Pointer = (@FirstKeys, @QuickKeys, @BlockKeys, @MiscKeys);
 
870
 
 
871
function ScanKeyMap(KeyMap: Pointer; KeyCode: Word): Word;
 
872
type
 
873
  pword = ^word;
 
874
var
 
875
  p : pword;
 
876
  count : sw_word;
 
877
begin
 
878
  p:=keymap;
 
879
  count:=p^;
 
880
  inc(p);
 
881
  while (count>0) do
 
882
   begin
 
883
     if (lo(p^)=lo(keycode)) and
 
884
        ((hi(p^)=0) or (hi(p^)=hi(keycode))) then
 
885
      begin
 
886
        inc(p);
 
887
        scankeymap:=p^;
 
888
        Exit;
 
889
      end;
 
890
     inc(p,2);
 
891
     dec(count);
 
892
   end;
 
893
  scankeymap:=0;
 
894
end;
 
895
 
 
896
function IsWordSeparator(C: char): boolean;
 
897
begin
 
898
  IsWordSeparator:=C in
 
899
      [' ',#0,#255,':','=','''','"',
 
900
      '.',',','/',';','$','#',
 
901
      '(',')','<','>','^','*',
 
902
      '+','-','?','&','[',']',
 
903
      '{','}','@','~','%','\',
 
904
      '!'];
 
905
end;
 
906
 
 
907
{function IsSpace(C: char): boolean;
 
908
begin
 
909
  IsSpace:=C in[' ',#0,#255];
 
910
end;}
 
911
 
 
912
function LTrim(S: string): string;
 
913
begin
 
914
  while (length(S)>0) and (S[1] in [#0,TAB,#32]) do
 
915
    Delete(S,1,1);
 
916
  LTrim:=S;
 
917
end;
 
918
 
 
919
{ TAB are not same as spaces if UseTabs is set PM }
 
920
function RTrim(S: string;cut_tabs : boolean): string;
 
921
begin
 
922
  while (length(S)>0) and
 
923
    ((S[length(S)] in [#0,#32]) or
 
924
    ((S[Length(S)]=TAB) and cut_tabs)) do
 
925
    Delete(S,length(S),1);
 
926
  RTrim:=S;
 
927
end;
 
928
 
 
929
function Trim(S: string): string;
 
930
begin
 
931
  Trim:=RTrim(LTrim(S),true);
 
932
end;
 
933
 
 
934
function EatIO: integer;
 
935
begin
 
936
  EatIO:=IOResult;
 
937
end;
 
938
 
 
939
function ExistsFile(const FileName: string): boolean;
 
940
var f: file;
 
941
    Exists: boolean;
 
942
begin
 
943
  if FileName='' then Exists:=false else
 
944
 begin
 
945
  {$I-}
 
946
  Assign(f,FileName);
 
947
  Reset(f,1);
 
948
  Exists:=EatIO=0;
 
949
  Close(f);
 
950
  EatIO;
 
951
  {$I+}
 
952
 end;
 
953
  ExistsFile:=Exists;
 
954
end;
 
955
 
 
956
function StrToInt(const S: string): longint;
 
957
var L: longint;
 
958
    C: integer;
 
959
begin
 
960
  Val(S,L,C); if C<>0 then L:=-1;
 
961
  StrToInt:=L;
 
962
end;
 
963
 
 
964
function RExpand(const S: string; MinLen: byte): string;
 
965
begin
 
966
  if length(S)<MinLen then
 
967
   RExpand:=S+CharStr(' ',MinLen-length(S))
 
968
  else
 
969
   RExpand:=S;
 
970
end;
 
971
 
 
972
{
 
973
function upper(const s : string) : string;
 
974
var
 
975
  i  : Sw_word;
 
976
begin
 
977
  for i:=1 to length(s) do
 
978
   if s[i] in ['a'..'z'] then
 
979
    upper[i]:=char(byte(s[i])-32)
 
980
   else
 
981
    upper[i]:=s[i];
 
982
  upper[0]:=s[0];
 
983
end;
 
984
}
 
985
type TPosOfs = {$ifdef TP}longint{$endif}{$ifdef FPC}int64{$endif};
 
986
 
 
987
function PosToOfs(const X,Y: sw_integer): TPosOfs;
 
988
begin
 
989
  PosToOfs:=TPosOfs(y) shl (sizeof(sw_integer)*8) or x;
 
990
end;
 
991
 
 
992
function PosToOfsP(const P: TPoint): TPosOfs;
 
993
begin
 
994
  PosToOfsP:=PosToOfs(P.X,P.Y);
 
995
end;
 
996
 
 
997
function PointOfs(P: TPoint): TPosOfs;
 
998
begin
 
999
  PointOfs:={longint(P.Y)*MaxLineLength+P.X}PosToOfsP(P);
 
1000
end;
 
1001
 
 
1002
 
 
1003
function ExtractTabs(S: string; TabSize: Sw_integer): string;
 
1004
var
 
1005
  P,PAdd: Sw_integer;
 
1006
begin
 
1007
  p:=0;
 
1008
  while p<length(s) do
 
1009
   begin
 
1010
     inc(p);
 
1011
     if s[p]=TAB then
 
1012
      begin
 
1013
        PAdd:=TabSize-((p-1) mod TabSize);
 
1014
        s:=copy(S,1,P-1)+CharStr(' ',PAdd)+copy(S,P+1,High(s));
 
1015
        inc(P,PAdd-1);
 
1016
      end;
 
1017
   end;
 
1018
  ExtractTabs:=S;
 
1019
end;
 
1020
 
 
1021
{function CompressUsingTabs(S: string; TabSize: byte): string;
 
1022
var TabS: string;
 
1023
    P: byte;
 
1024
begin
 
1025
  TabS:=CharStr(' ',TabSize);
 
1026
  repeat
 
1027
    P:=Pos(TabS,S);
 
1028
    if P>0 then
 
1029
      S:=copy(S,1,P-1)+TAB+copy(S,P+TabSize,High(S));
 
1030
  until P=0;
 
1031
  CompressUsingTabs:=S;
 
1032
end;}
 
1033
 
 
1034
 
 
1035
{*****************************************************************************
 
1036
                           Forward/Backward Scanning
 
1037
*****************************************************************************}
 
1038
 
 
1039
Const
 
1040
{$ifndef FPC}
 
1041
  MaxBufLength   = $7f00;
 
1042
  NotFoundValue  = -1;
 
1043
{$else}
 
1044
  MaxBufLength   = $7fffff00;
 
1045
  NotFoundValue  = -1;
 
1046
{$endif}
 
1047
 
 
1048
Type
 
1049
  Btable = Array[0..255] of Byte;
 
1050
Procedure BMFMakeTable(const s:string; Var t : Btable);
 
1051
Var
 
1052
  x : sw_integer;
 
1053
begin
 
1054
  FillChar(t,sizeof(t),length(s));
 
1055
  For x := length(s) downto 1 do
 
1056
   if (t[ord(s[x])] = length(s)) then
 
1057
    t[ord(s[x])] := length(s) - x;
 
1058
end;
 
1059
 
 
1060
 
 
1061
function BMFScan(var Block; Size: Sw_Word;const Str: String;const bt:BTable): Sw_Integer;
 
1062
Var
 
1063
  buffer : Array[0..MaxBufLength-1] of Byte Absolute block;
 
1064
  s2     : String;
 
1065
  len,
 
1066
  numb   : Sw_Word;
 
1067
  found  : Boolean;
 
1068
begin
 
1069
  len:=length(str);
 
1070
  if len>size then
 
1071
   begin
 
1072
     BMFScan := NotFoundValue;
 
1073
     exit;
 
1074
   end;
 
1075
  s2[0]:=chr(len);       { sets the length to that of the search String }
 
1076
  found:=False;
 
1077
  numb:=pred(len);
 
1078
  While (not found) and (numb<size) do
 
1079
   begin
 
1080
     { partial match }
 
1081
     if buffer[numb] = ord(str[len]) then
 
1082
      begin
 
1083
        { less partial! }
 
1084
        if buffer[numb-pred(len)] = ord(str[1]) then
 
1085
         begin
 
1086
           move(buffer[numb-pred(len)],s2[1],len);
 
1087
           if (str=s2) then
 
1088
            begin
 
1089
              found:=true;
 
1090
              break;
 
1091
            end;
 
1092
         end;
 
1093
        inc(numb);
 
1094
     end
 
1095
    else
 
1096
     inc(numb,Bt[buffer[numb]]);
 
1097
  end;
 
1098
  if not found then
 
1099
    BMFScan := NotFoundValue
 
1100
  else
 
1101
    BMFScan := numb - pred(len);
 
1102
end;
 
1103
 
 
1104
 
 
1105
function BMFIScan(var Block; Size: Sw_Word;const Str: String;const bt:BTable): Sw_Integer;
 
1106
Var
 
1107
  buffer : Array[0..MaxBufLength-1] of Char Absolute block;
 
1108
  len,
 
1109
  numb,
 
1110
  x      : Sw_Word;
 
1111
  found  : Boolean;
 
1112
  p      : pchar;
 
1113
  c      : char;
 
1114
begin
 
1115
  len:=length(str);
 
1116
  if (len=0) or (len>size) then
 
1117
   begin
 
1118
     BMFIScan := NotFoundValue;
 
1119
     exit;
 
1120
   end;
 
1121
  found:=False;
 
1122
  numb:=pred(len);
 
1123
  While (not found) and (numb<size) do
 
1124
   begin
 
1125
     { partial match }
 
1126
     c:=buffer[numb];
 
1127
     if c in ['a'..'z'] then
 
1128
      c:=chr(ord(c)-32);
 
1129
     if (c=str[len]) then
 
1130
      begin
 
1131
        { less partial! }
 
1132
        p:=@buffer[numb-pred(len)];
 
1133
        x:=1;
 
1134
        while (x<=len) do
 
1135
         begin
 
1136
           if not(((p^ in ['a'..'z']) and (chr(ord(p^)-32)=str[x])) or
 
1137
             (p^=str[x])) then
 
1138
            break;
 
1139
           inc(p);
 
1140
           inc(x);
 
1141
         end;
 
1142
        if (x>len) then
 
1143
         begin
 
1144
           found:=true;
 
1145
           break;
 
1146
         end;
 
1147
        inc(numb);
 
1148
      end
 
1149
     else
 
1150
      inc(numb,Bt[ord(c)]);
 
1151
   end;
 
1152
  if not found then
 
1153
    BMFIScan := NotFoundValue
 
1154
  else
 
1155
    BMFIScan := numb - pred(len);
 
1156
end;
 
1157
 
 
1158
 
 
1159
Procedure BMBMakeTable(const s:string; Var t : Btable);
 
1160
Var
 
1161
  x : sw_integer;
 
1162
begin
 
1163
  FillChar(t,sizeof(t),length(s));
 
1164
  For x := 1 to length(s)do
 
1165
   if (t[ord(s[x])] = length(s)) then
 
1166
    t[ord(s[x])] := x-1;
 
1167
end;
 
1168
 
 
1169
 
 
1170
function BMBScan(var Block; Size: Sw_Word;const Str: String;const bt:BTable): Sw_Integer;
 
1171
Var
 
1172
  buffer : Array[0..MaxBufLength-1] of Byte Absolute block;
 
1173
  s2     : String;
 
1174
  len    : Sw_Word;
 
1175
  numb   : Sw_Integer;
 
1176
  found  : Boolean;
 
1177
begin
 
1178
  len:=length(str);
 
1179
  if len>size then
 
1180
   begin
 
1181
     BMBScan := NotFoundValue;
 
1182
     exit;
 
1183
   end;
 
1184
  s2[0]:=chr(len);       { sets the length to that of the search String }
 
1185
  found:=False;
 
1186
  numb:=size-len;
 
1187
  While (not found) and (numb>=0) do
 
1188
   begin
 
1189
     { partial match }
 
1190
     if buffer[numb] = ord(str[1]) then
 
1191
      begin
 
1192
        { less partial! }
 
1193
        if buffer[numb+pred(len)] = ord(str[len]) then
 
1194
         begin
 
1195
           move(buffer[numb],s2[1],len);
 
1196
           if (str=s2) then
 
1197
            begin
 
1198
              found:=true;
 
1199
              break;
 
1200
            end;
 
1201
         end;
 
1202
        dec(numb);
 
1203
     end
 
1204
    else
 
1205
     dec(numb,Bt[buffer[numb]]);
 
1206
  end;
 
1207
  if not found then
 
1208
    BMBScan := NotFoundValue
 
1209
  else
 
1210
    BMBScan := numb;
 
1211
end;
 
1212
 
 
1213
 
 
1214
function BMBIScan(var Block; Size: Sw_Word;const Str: String;const bt:BTable): Sw_Integer;
 
1215
Var
 
1216
  buffer : Array[0..MaxBufLength-1] of Char Absolute block;
 
1217
  len,
 
1218
  x      : Sw_Word;
 
1219
  numb   : Sw_Integer;
 
1220
  found  : Boolean;
 
1221
  p      : pchar;
 
1222
  c      : char;
 
1223
begin
 
1224
  len:=length(str);
 
1225
  if (len=0) or (len>size) then
 
1226
   begin
 
1227
     BMBIScan := NotFoundValue;
 
1228
     exit;
 
1229
   end;
 
1230
  found:=False;
 
1231
  numb:=size-len;
 
1232
  While (not found) and (numb>=0) do
 
1233
   begin
 
1234
     { partial match }
 
1235
     c:=buffer[numb];
 
1236
     if c in ['a'..'z'] then
 
1237
      c:=chr(ord(c)-32);
 
1238
     if (c=str[1]) then
 
1239
      begin
 
1240
        { less partial! }
 
1241
        p:=@buffer[numb];
 
1242
        x:=1;
 
1243
        while (x<=len) do
 
1244
         begin
 
1245
           if not(((p^ in ['a'..'z']) and (chr(ord(p^)-32)=str[x])) or
 
1246
             (p^=str[x])) then
 
1247
            break;
 
1248
           inc(p);
 
1249
           inc(x);
 
1250
         end;
 
1251
        if (x>len) then
 
1252
         begin
 
1253
           found:=true;
 
1254
           break;
 
1255
         end;
 
1256
        dec(numb);
 
1257
      end
 
1258
     else
 
1259
      dec(numb,Bt[ord(c)]);
 
1260
   end;
 
1261
  if not found then
 
1262
    BMBIScan := NotFoundValue
 
1263
  else
 
1264
    BMBIScan := numb;
 
1265
end;
 
1266
 
 
1267
 
 
1268
{*****************************************************************************
 
1269
                            PLine,TLineCollection
 
1270
*****************************************************************************}
 
1271
 
 
1272
constructor TCustomLine.Init(const AText: string; AFlags: longint);
 
1273
begin
 
1274
  inherited Init;
 
1275
  SetText(AText);
 
1276
end;
 
1277
 
 
1278
function TCustomLine.GetText: string;
 
1279
begin
 
1280
  Abstract;GetText:='';
 
1281
end;
 
1282
 
 
1283
procedure TCustomLine.SetText(const AText: string);
 
1284
begin
 
1285
  Abstract;
 
1286
end;
 
1287
 
 
1288
function TCustomLine.GetEditorInfo(Editor: PCustomCodeEditor): PEditorLineInfo;
 
1289
begin
 
1290
  Abstract;
 
1291
  GetEditorInfo:=nil;
 
1292
end;
 
1293
 
 
1294
function TCustomLine.GetFlags: longint;
 
1295
begin
 
1296
  Abstract;
 
1297
  GetFlags:=0;
 
1298
end;
 
1299
 
 
1300
procedure TCustomLine.SetFlags(AFlags: longint);
 
1301
begin
 
1302
  Abstract;
 
1303
end;
 
1304
 
 
1305
function TCustomLine.IsFlagSet(AFlag: longint): boolean;{$ifdef USEINLINE}inline;{$endif}
 
1306
begin
 
1307
  IsFlagSet:=(GetFlags and AFlag)=AFlag;
 
1308
end;
 
1309
 
 
1310
procedure TCustomLine.SetFlagState(AFlag: longint; ASet: boolean);
 
1311
var N,O: longint;
 
1312
begin
 
1313
  O:=GetFlags; N:=O;
 
1314
  if ASet then
 
1315
    N:=N or AFlag
 
1316
  else
 
1317
    N:=N and (not AFlag);
 
1318
  if N<>O then
 
1319
    SetFlags(N);
 
1320
end;
 
1321
 
 
1322
procedure TCustomLine.AddEditorInfo(Index: sw_integer; AEditor: PCustomCodeEditor);
 
1323
begin
 
1324
  { Abstract }
 
1325
end;
 
1326
 
 
1327
procedure TCustomLine.RemoveEditorInfo(AEditor: PCustomCodeEditor);
 
1328
begin
 
1329
  { Abstract }
 
1330
end;
 
1331
 
 
1332
destructor TCustomLine.Done;
 
1333
begin
 
1334
  inherited Done;
 
1335
end;
 
1336
 
 
1337
function TLineCollection.At(Index: sw_Integer): PCustomLine;
 
1338
begin
 
1339
  At:=inherited At(Index);
 
1340
end;
 
1341
 
 
1342
constructor TFold.Init(AEditor: PCustomCodeEditor; AParentFold: PFold; ACollapsed: boolean);
 
1343
begin
 
1344
  inherited Init;
 
1345
  New(Childs, Init(10,10));
 
1346
  Editor:=AEditor;
 
1347
  ParentFold:=AParentFold;
 
1348
  if Assigned(ParentFold) then
 
1349
    ParentFold^.AddChildReference(@Self);
 
1350
  Collapsed_:=ACollapsed;
 
1351
  if Assigned(AEditor) then
 
1352
    Editor^.RegisterFold(@Self);
 
1353
end;
 
1354
 
 
1355
procedure TFold.AddReference(P: PObject);
 
1356
begin
 
1357
  Inc(ReferenceCount);
 
1358
end;
 
1359
 
 
1360
procedure TFold.RemoveReference(P: PObject);
 
1361
begin
 
1362
  Dec(ReferenceCount);
 
1363
  if CanDispose then
 
1364
    Free;
 
1365
end;
 
1366
 
 
1367
procedure TFold.AddLineReference(Line: PEditorLineInfo);
 
1368
begin
 
1369
  Inc(LineCount_);
 
1370
  AddReference(Line);
 
1371
end;
 
1372
 
 
1373
procedure TFold.RemoveLineReference(Line: PEditorLineInfo);
 
1374
begin
 
1375
  Dec(LineCount_);
 
1376
  RemoveReference(Line);
 
1377
end;
 
1378
 
 
1379
procedure TFold.AddChildReference(Fold: PFold);
 
1380
begin
 
1381
  Childs^.Insert(Fold);
 
1382
  AddReference(Fold);
 
1383
end;
 
1384
 
 
1385
procedure TFold.RemoveChildReference(Fold: PFold);
 
1386
begin
 
1387
  Childs^.Delete(Fold);
 
1388
  RemoveReference(Fold);
 
1389
end;
 
1390
 
 
1391
function TFold.CanDispose: boolean;
 
1392
begin
 
1393
  CanDispose:=ReferenceCount<=0;
 
1394
end;
 
1395
 
 
1396
function TFold.IsCollapsed: boolean;
 
1397
var C: boolean;
 
1398
begin
 
1399
  C:=Collapsed_;
 
1400
  if Assigned(ParentFold) then C:=C or ParentFold^.IsCollapsed;
 
1401
  IsCollapsed:=C;
 
1402
end;
 
1403
 
 
1404
function TFold.IsParent(AFold: PFold): boolean;
 
1405
var P: boolean;
 
1406
begin
 
1407
  P:=(ParentFold=AFold);
 
1408
  if Assigned(ParentFold) then P:=P or ParentFold^.IsParent(AFold);
 
1409
  IsParent:=P;
 
1410
end;
 
1411
 
 
1412
function TFold.GetLineCount: sw_integer;
 
1413
var Count: sw_integer;
 
1414
procedure AddIt(P: PFold); {$ifndef FPC}far;{$endif}
 
1415
begin
 
1416
  Inc(Count,P^.GetLineCount);
 
1417
end;
 
1418
begin
 
1419
  Count:=LineCount_;
 
1420
  if assigned(Childs) then Childs^.ForEach(@AddIt);
 
1421
  GetLineCount:=Count;
 
1422
end;
 
1423
 
 
1424
procedure TFold.Collapse(ACollapse: boolean);
 
1425
begin
 
1426
  if ACollapse<>Collapsed_ then
 
1427
  begin
 
1428
    Collapsed_:=ACollapse;
 
1429
    if (not Collapsed_) and Assigned(ParentFold) then
 
1430
      ParentFold^.Collapse(false);
 
1431
    Changed;
 
1432
  end;
 
1433
end;
 
1434
 
 
1435
procedure TFold.Changed;
 
1436
begin
 
1437
  if Assigned(Editor) then
 
1438
    Editor^.FoldChanged(@Self);
 
1439
end;
 
1440
 
 
1441
function TFold.GetLevel: sw_integer;
 
1442
var Level: sw_integer;
 
1443
begin
 
1444
  Level:=0;
 
1445
  if Assigned(ParentFold) then
 
1446
    Inc(Level,1+ParentFold^.GetLevel);
 
1447
  GetLevel:=Level;
 
1448
end;
 
1449
 
 
1450
destructor TFold.Done;
 
1451
begin
 
1452
  if Assigned(ParentFold) then
 
1453
    ParentFold^.RemoveChildReference(@Self);
 
1454
  if Assigned(Editor) then
 
1455
    Editor^.UnRegisterFold(@Self);
 
1456
  Childs^.DeleteAll; Dispose(Childs, Done);
 
1457
  inherited Done;
 
1458
end;
 
1459
 
 
1460
function TFoldCollection.At(Index: sw_Integer): PFold;
 
1461
begin
 
1462
  At:=inherited At(Index);
 
1463
end;
 
1464
 
 
1465
constructor TEditorLineInfo.Init(AEditor: PCustomCodeEditor);
 
1466
begin
 
1467
  inherited Init;
 
1468
  Editor:=AEditor;
 
1469
end;
 
1470
 
 
1471
function TEditorLineInfo.GetFormat: string;
 
1472
begin
 
1473
  GetFormat:=GetStr(Format);
 
1474
end;
 
1475
 
 
1476
procedure TEditorLineInfo.SetFormat(const AFormat: string);
 
1477
begin
 
1478
  SetStr(Format,AFormat);
 
1479
end;
 
1480
 
 
1481
procedure TEditorLineInfo.SetFold(AFold: PFold);
 
1482
begin
 
1483
  if Assigned(Fold) then
 
1484
    Fold^.RemoveLineReference(@Self);
 
1485
  Fold:=AFold;
 
1486
  if Assigned(Fold) then
 
1487
    Fold^.AddLineReference(@Self);
 
1488
end;
 
1489
 
 
1490
destructor TEditorLineInfo.Done;
 
1491
begin
 
1492
  if Format<>nil then
 
1493
    DisposeStr(Format);
 
1494
  Format:=nil;
 
1495
  SetFold(nil);
 
1496
  inherited Done;
 
1497
end;
 
1498
 
 
1499
function TEditorLineInfoCollection.At(Index: sw_Integer): PEditorLineInfo;
 
1500
begin
 
1501
  At:=inherited At(Index);
 
1502
end;
 
1503
 
 
1504
function TEditorBindingCollection.At(Index: sw_Integer): PEditorBinding;
 
1505
begin
 
1506
  At:=inherited At(Index);
 
1507
end;
 
1508
 
 
1509
constructor TEditorBinding.Init(AEditor: PCustomCodeEditor);
 
1510
begin
 
1511
  inherited Init;
 
1512
  Editor:=AEditor;
 
1513
end;
 
1514
 
 
1515
destructor TEditorBinding.Done;
 
1516
begin
 
1517
  inherited Done;
 
1518
end;
 
1519
 
 
1520
constructor TCustomCodeEditorCore.Init;
 
1521
begin
 
1522
  inherited Init;
 
1523
  New(Bindings, Init(10,10));
 
1524
end;
 
1525
 
 
1526
procedure TCustomCodeEditorCore.BindEditor(AEditor: PCustomCodeEditor);
 
1527
var B: PEditorBinding;
 
1528
    Count,I,Idx: sw_integer;
 
1529
    L: PCustomLine;
 
1530
begin
 
1531
  assert(Aeditor<>nil);
 
1532
  New(B, Init(AEditor));
 
1533
  Bindings^.Insert(B);
 
1534
  Idx:=Bindings^.IndexOf(B);
 
1535
  Count:=GetLineCount;
 
1536
  for I:=0 to Count-1 do
 
1537
  begin
 
1538
    L:=GetLine(I);
 
1539
    if Assigned(L) then
 
1540
      L^.AddEditorInfo(Idx,AEditor);
 
1541
  end;
 
1542
 
 
1543
  BindingsChanged;
 
1544
end;
 
1545
 
 
1546
procedure TCustomCodeEditorCore.UnBindEditor(AEditor: PCustomCodeEditor);
 
1547
var B: PEditorBinding;
 
1548
    Count,I: sw_integer;
 
1549
    L: PCustomLine;
 
1550
begin
 
1551
  assert(Aeditor<>nil);
 
1552
  B:=SearchBinding(AEditor);
 
1553
  if Assigned(B) then
 
1554
  begin
 
1555
    Count:=GetLineCount;
 
1556
    for I:=0 to Count-1 do
 
1557
    begin
 
1558
      L:=GetLine(I);
 
1559
      if Assigned(L) then
 
1560
        L^.RemoveEditorInfo(AEditor);
 
1561
    end;
 
1562
    Bindings^.Free(B);
 
1563
 
 
1564
    BindingsChanged;
 
1565
  end;
 
1566
end;
 
1567
 
 
1568
function TCustomCodeEditorCore.IsEditorBound(AEditor: PCustomCodeEditor): boolean;
 
1569
begin
 
1570
  IsEditorBound:=SearchBinding(AEditor)<>nil;
 
1571
end;
 
1572
 
 
1573
function TCustomCodeEditorCore.GetBindingCount: sw_integer;
 
1574
begin
 
1575
  GetBindingCount:=Bindings^.Count;
 
1576
end;
 
1577
 
 
1578
function TCustomCodeEditorCore.GetBindingIndex(AEditor: PCustomCodeEditor): sw_integer;
 
1579
var B: PEditorBinding;
 
1580
begin
 
1581
  B:=SearchBinding(AEditor);
 
1582
  GetBindingIndex:=Bindings^.IndexOf(B);
 
1583
end;
 
1584
 
 
1585
function TCustomCodeEditorCore.SearchBinding(AEditor: PCustomCodeEditor): PEditorBinding;
 
1586
function SearchEditor(P: PEditorBinding): boolean; {$ifndef FPC}far;{$endif}
 
1587
begin
 
1588
  SearchEditor:=P^.Editor=AEditor;
 
1589
end;
 
1590
begin
 
1591
  SearchBinding:=Bindings^.FirstThat(@SearchEditor);
 
1592
end;
 
1593
 
 
1594
function TCustomCodeEditorCore.CanDispose: boolean;
 
1595
begin
 
1596
  CanDispose:=Assigned(Bindings) and (Bindings^.Count=0);
 
1597
end;
 
1598
 
 
1599
function TCustomCodeEditorCore.GetModified: boolean;
 
1600
begin
 
1601
  Abstract;
 
1602
  GetModified:=true;
 
1603
end;
 
1604
function TCustomCodeEditorCore.GetChangedLine: sw_integer;
 
1605
begin
 
1606
  GetChangedLine:=ChangedLine;
 
1607
end;
 
1608
 
 
1609
procedure TCustomCodeEditorCore.SetModified(AModified: boolean);
 
1610
begin
 
1611
  Abstract;
 
1612
end;
 
1613
 
 
1614
function TCustomCodeEditorCore.GetStoreUndo: boolean;
 
1615
begin
 
1616
  Abstract;
 
1617
  GetStoreUndo:=false;
 
1618
end;
 
1619
 
 
1620
procedure TCustomCodeEditorCore.SetStoreUndo(AStore: boolean);
 
1621
begin
 
1622
  Abstract;
 
1623
end;
 
1624
 
 
1625
function TCustomCodeEditorCore.GetSyntaxCompleted: boolean;
 
1626
begin
 
1627
  Abstract;
 
1628
  GetSyntaxCompleted:=true;
 
1629
end;
 
1630
 
 
1631
procedure TCustomCodeEditorCore.SetSyntaxCompleted(SC : boolean);
 
1632
begin
 
1633
  Abstract;
 
1634
end;
 
1635
 
 
1636
 
 
1637
function TCustomCodeEditorCore.IsClipboard: Boolean;
 
1638
function IsClip(P: PEditorBinding): boolean; {$ifndef FPC}far;{$endif}
 
1639
begin
 
1640
  IsClip:=(P^.Editor=Clipboard);
 
1641
end;
 
1642
begin
 
1643
  IsClipBoard:=Bindings^.FirstThat(@IsClip)<>nil;
 
1644
end;
 
1645
 
 
1646
function TCustomCodeEditorCore.GetTabSize: integer;
 
1647
begin
 
1648
  Abstract;
 
1649
  GetTabSize:=0;
 
1650
end;
 
1651
 
 
1652
procedure TCustomCodeEditorCore.SetTabSize(ATabSize: integer);
 
1653
begin
 
1654
  Abstract;
 
1655
end;
 
1656
 
 
1657
function TCustomCodeEditorCore.GetIndentSize: integer;
 
1658
begin
 
1659
  Abstract;
 
1660
  GetIndentSize:=0;
 
1661
end;
 
1662
 
 
1663
procedure TCustomCodeEditorCore.SetIndentSize(AIndentSize: integer);
 
1664
begin
 
1665
  Abstract;
 
1666
end;
 
1667
 
 
1668
procedure TCustomCodeEditorCore.LimitsChanged;
 
1669
begin
 
1670
  if Locked then
 
1671
    LimitsChangedCalled:=true
 
1672
  else
 
1673
    DoLimitsChanged;
 
1674
end;
 
1675
 
 
1676
procedure TCustomCodeEditorCore.ContentsChanged;
 
1677
begin
 
1678
  if Locked then
 
1679
    ContentsChangedCalled:=true
 
1680
  else
 
1681
    DoContentsChanged;
 
1682
end;
 
1683
 
 
1684
procedure TCustomCodeEditorCore.ModifiedChanged;
 
1685
begin
 
1686
  if Locked then
 
1687
    ModifiedChangedCalled:=true
 
1688
  else
 
1689
    DoModifiedChanged;
 
1690
end;
 
1691
 
 
1692
procedure TCustomCodeEditorCore.TabSizeChanged;
 
1693
begin
 
1694
  if Locked then
 
1695
    TabSizeChangedCalled:=true
 
1696
  else
 
1697
    DoTabSizeChanged;
 
1698
end;
 
1699
 
 
1700
procedure TCustomCodeEditorCore.StoreUndoChanged;
 
1701
begin
 
1702
  if Locked then
 
1703
    StoreUndoChangedCalled:=true
 
1704
  else
 
1705
    DoStoreUndoChanged;
 
1706
end;
 
1707
 
 
1708
 
 
1709
procedure TCustomCodeEditorCore.BindingsChanged;
 
1710
procedure CallIt(P: PEditorBinding); {$ifndef FPC}far;{$endif}
 
1711
begin
 
1712
  P^.Editor^.BindingsChanged;
 
1713
end;
 
1714
begin
 
1715
  Bindings^.ForEach(@CallIt);
 
1716
end;
 
1717
 
 
1718
procedure TCustomCodeEditorCore.DoLimitsChanged;
 
1719
procedure CallIt(P: PEditorBinding); {$ifndef FPC}far;{$endif}
 
1720
begin
 
1721
  P^.Editor^.DoLimitsChanged;
 
1722
end;
 
1723
begin
 
1724
  Bindings^.ForEach(@CallIt);
 
1725
end;
 
1726
 
 
1727
procedure TCustomCodeEditorCore.DoContentsChanged;
 
1728
procedure CallIt(P: PEditorBinding); {$ifndef FPC}far;{$endif}
 
1729
begin
 
1730
  P^.Editor^.ContentsChanged;
 
1731
end;
 
1732
begin
 
1733
  Bindings^.ForEach(@CallIt);
 
1734
end;
 
1735
 
 
1736
procedure TCustomCodeEditorCore.DoModifiedChanged;
 
1737
procedure CallIt(P: PEditorBinding); {$ifndef FPC}far;{$endif}
 
1738
begin
 
1739
  P^.Editor^.ModifiedChanged;
 
1740
end;
 
1741
begin
 
1742
  Bindings^.ForEach(@CallIt);
 
1743
end;
 
1744
 
 
1745
procedure TCustomCodeEditorCore.DoTabSizeChanged;
 
1746
procedure CallIt(P: PEditorBinding); {$ifndef FPC}far;{$endif}
 
1747
begin
 
1748
  P^.Editor^.TabSizeChanged;
 
1749
end;
 
1750
begin
 
1751
  Bindings^.ForEach(@CallIt);
 
1752
end;
 
1753
 
 
1754
procedure TCustomCodeEditorCore.UpdateUndoRedo(cm : word; action : byte);
 
1755
procedure CallIt(P: PEditorBinding); {$ifndef FPC}far;{$endif}
 
1756
begin
 
1757
  if (P^.Editor^.State and sfActive)<>0 then
 
1758
    begin
 
1759
      P^.Editor^.UpdateUndoRedo(cm,action);
 
1760
    if cm=cmUndo then
 
1761
      begin
 
1762
        P^.Editor^.SetCmdState(UndoCmd,true);
 
1763
        P^.Editor^.SetCmdState(RedoCmd,false);
 
1764
        Message(Application,evBroadcast,cmCommandSetChanged,nil);
 
1765
      end;
 
1766
    end;
 
1767
end;
 
1768
begin
 
1769
  Bindings^.ForEach(@CallIt);
 
1770
end;
 
1771
 
 
1772
 
 
1773
procedure TCustomCodeEditorCore.DoStoreUndoChanged;
 
1774
procedure CallIt(P: PEditorBinding); {$ifndef FPC}far;{$endif}
 
1775
begin
 
1776
  P^.Editor^.StoreUndoChanged;
 
1777
end;
 
1778
begin
 
1779
  Bindings^.ForEach(@CallIt);
 
1780
end;
 
1781
procedure   TCustomCodeEditorCore.DoSyntaxStateChanged;
 
1782
procedure CallIt(P: PEditorBinding); {$ifndef FPC}far;{$endif}
 
1783
begin
 
1784
  P^.Editor^.SyntaxStateChanged;
 
1785
end;
 
1786
begin
 
1787
  Bindings^.ForEach(@CallIt);
 
1788
end;
 
1789
 
 
1790
function TCustomCodeEditorCore.GetLastVisibleLine : sw_integer;
 
1791
var
 
1792
  y : sw_integer;
 
1793
procedure CallIt(P: PEditorBinding); {$ifndef FPC}far;{$endif}
 
1794
begin
 
1795
  if y < P^.Editor^.Delta.Y+P^.Editor^.Size.Y then
 
1796
    y:=P^.Editor^.Delta.Y+P^.Editor^.Size.Y;
 
1797
end;
 
1798
begin
 
1799
  y:=0;
 
1800
  Bindings^.ForEach(@CallIt);
 
1801
  GetLastVisibleLine:=y;
 
1802
end;
 
1803
 
 
1804
function TCustomCodeEditorCore.SaveToStream(Editor: PCustomCodeEditor; Stream: PStream): boolean;
 
1805
var A,B: TPoint;
 
1806
begin
 
1807
  A.Y:=0; A.X:=0;
 
1808
  B.Y:=GetLineCount-1;
 
1809
  if GetLineCount>0 then
 
1810
    B.X:=length(GetDisplayText(B.Y))
 
1811
  else
 
1812
    B.X:=0;
 
1813
  SaveToStream:=SaveAreaToStream(Editor,Stream,A,B);
 
1814
end;
 
1815
 
 
1816
procedure TCustomCodeEditorCore.ISetLineFlagState(Binding: PEditorBinding; LineNo: sw_integer; Flag: longint; ASet: boolean);
 
1817
begin
 
1818
  Abstract;
 
1819
end;
 
1820
 
 
1821
procedure TCustomCodeEditorCore.IGetDisplayTextFormat(Binding: PEditorBinding; LineNo: sw_integer;var DT,DF:string);
 
1822
begin
 
1823
  Abstract;
 
1824
end;
 
1825
 
 
1826
function TCustomCodeEditorCore.IGetLineFormat(Binding: PEditorBinding; LineNo: sw_integer): string;
 
1827
begin
 
1828
  Abstract;
 
1829
  IGetLineFormat:='';
 
1830
end;
 
1831
 
 
1832
procedure TCustomCodeEditorCore.ISetLineFormat(Binding: PEditorBinding; LineNo: sw_integer;const S: string);
 
1833
begin
 
1834
  Abstract;
 
1835
end;
 
1836
 
 
1837
function TCustomCodeEditorCore.CharIdxToLinePos(Line,CharIdx: sw_integer): sw_integer;
 
1838
var S: string;
 
1839
    TabSize,CP,RX,NextInc: sw_integer;
 
1840
begin
 
1841
  S:=GetLineText(Line);
 
1842
  (* this would fasten the code
 
1843
    but UseTabCharacters is set for Editor not for EditorCore
 
1844
    objects,which is dangerous anyway and should be changed ... PM
 
1845
  if not IsFlagSet(efUseTabCharacters) then
 
1846
    begin
 
1847
     if CharIdx<=Length(S) then
 
1848
       CharIdxToLinePos:=CharIdx-1
 
1849
     else
 
1850
       CharIdxToLinePos:=Length(S)-1;
 
1851
     exit;
 
1852
    end; *)
 
1853
 
 
1854
  TabSize:=GetTabSize;
 
1855
  CP:=1; RX:=0;
 
1856
  NextInc:=0;
 
1857
  while {(CP<=length(S)) and }(CP<=CharIdx) do
 
1858
   begin
 
1859
     if NextInc>0 then
 
1860
       Inc(RX,NextInc);
 
1861
     if (CP<=length(S)) and (S[CP]=TAB) then
 
1862
       NextInc:=TabSize-(RX mod TabSize) -1
 
1863
     else
 
1864
       NextInc:=0;
 
1865
     Inc(RX);
 
1866
     Inc(CP);
 
1867
   end;
 
1868
  CharIdxToLinePos:=RX-1;
 
1869
end;
 
1870
 
 
1871
function TCustomCodeEditorCore.LinePosToCharIdx(Line,X: sw_integer): sw_integer;
 
1872
var S: string;
 
1873
    TabSize,CP,RX: sw_integer;
 
1874
begin
 
1875
  TabSize:=GetTabSize;
 
1876
  S:=GetLineText(Line);
 
1877
  (*
 
1878
  if not IsFlagSet(efUseTabCharacters) then
 
1879
    begin
 
1880
      if S='' then
 
1881
        CP:=0
 
1882
      else if (Line<Length(S)) then
 
1883
        LinePosToCharIdx:=Line+1
 
1884
      else
 
1885
        LinePosToCharIdx:=Length(S);
 
1886
      exit;
 
1887
    end; *)
 
1888
  if S='' then
 
1889
    CP:=0
 
1890
  else
 
1891
    begin
 
1892
     CP:=0; RX:=0;
 
1893
     while (RX<=X) and (CP<=length(S)) do
 
1894
      begin
 
1895
        Inc(CP);
 
1896
        if (CP<=length(S)) and
 
1897
           (S[CP]=TAB) then
 
1898
          Inc(RX,TabSize-(RX mod TabSize))
 
1899
        else
 
1900
          Inc(RX);
 
1901
      end;
 
1902
    end;
 
1903
  LinePosToCharIdx:=CP;
 
1904
end;
 
1905
 
 
1906
function TCustomCodeEditorCore.GetLineCount: sw_integer;
 
1907
begin
 
1908
  Abstract;
 
1909
  GetLineCount:=0;
 
1910
end;
 
1911
 
 
1912
function TCustomCodeEditorCore.GetLine(LineNo: sw_integer): PCustomLine;
 
1913
begin
 
1914
  Abstract;
 
1915
  GetLine:=nil;
 
1916
end;
 
1917
 
 
1918
function TCustomCodeEditorCore.GetLineText(LineNo: sw_integer): string;
 
1919
begin
 
1920
  Abstract;
 
1921
  GetLineText:='';
 
1922
end;
 
1923
 
 
1924
procedure TCustomCodeEditorCore.SetDisplayText(I: sw_integer;const S: string);
 
1925
begin
 
1926
  Abstract;
 
1927
end;
 
1928
 
 
1929
function TCustomCodeEditorCore.GetDisplayText(I: sw_integer): string;
 
1930
begin
 
1931
  Abstract;
 
1932
  GetDisplayText:='';
 
1933
end;
 
1934
 
 
1935
procedure TCustomCodeEditorCore.SetLineText(I: sw_integer;const S: string);
 
1936
begin
 
1937
  Abstract;
 
1938
end;
 
1939
 
 
1940
procedure TCustomCodeEditorCore.GetDisplayTextFormat(Editor: PCustomCodeEditor; I: sw_integer;var DT,DF:string);
 
1941
begin
 
1942
  IGetDisplayTextFormat(SearchBinding(Editor),I,DT,DF);
 
1943
end;
 
1944
 
 
1945
function TCustomCodeEditorCore.GetLineFormat(Editor: PCustomCodeEditor; I: sw_integer): string;
 
1946
begin
 
1947
  GetLineFormat:=IGetLineFormat(SearchBinding(Editor),I);
 
1948
end;
 
1949
 
 
1950
procedure TCustomCodeEditorCore.SetLineFormat(Editor: PCustomCodeEditor; I: sw_integer; const S: string);
 
1951
begin
 
1952
  ISetLineFormat(SearchBinding(Editor),I,S);
 
1953
end;
 
1954
 
 
1955
procedure TCustomCodeEditorCore.DeleteAllLines;
 
1956
begin
 
1957
  Abstract;
 
1958
end;
 
1959
 
 
1960
procedure TCustomCodeEditorCore.DeleteLine(I: sw_integer);
 
1961
begin
 
1962
  Abstract;
 
1963
end;
 
1964
 
 
1965
function TCustomCodeEditorCore.InsertLine(LineNo: sw_integer; const S: string): PCustomLine;
 
1966
begin
 
1967
  Abstract;
 
1968
  InsertLine:=nil; { eliminate compiler warning }
 
1969
end;
 
1970
 
 
1971
procedure TCustomCodeEditorCore.AddLine(const S: string);
 
1972
begin
 
1973
  Abstract;
 
1974
end;
 
1975
 
 
1976
procedure TCustomCodeEditorCore.GetContent(ALines: PUnsortedStringCollection);
 
1977
begin
 
1978
  Abstract;
 
1979
end;
 
1980
 
 
1981
procedure TCustomCodeEditorCore.SetContent(ALines: PUnsortedStringCollection);
 
1982
begin
 
1983
  Abstract;
 
1984
end;
 
1985
 
 
1986
function TCustomCodeEditorCore.Locked: boolean;
 
1987
begin
 
1988
  Locked:=LockFlag>0;
 
1989
end;
 
1990
 
 
1991
procedure TCustomCodeEditorCore.Lock(AEditor: PCustomCodeEditor);
 
1992
begin
 
1993
  Inc(LockFlag);
 
1994
end;
 
1995
 
 
1996
procedure TCustomCodeEditorCore.UnLock(AEditor: PCustomCodeEditor);
 
1997
begin
 
1998
{$ifdef DEBUG}
 
1999
  if LockFlag=0 then
 
2000
    Bug('negative lockflag',nil)
 
2001
  else
 
2002
{$endif DEBUG}
 
2003
    Dec(LockFlag);
 
2004
  if (LockFlag>0) then
 
2005
    Exit;
 
2006
 
 
2007
  if LimitsChangedCalled then
 
2008
    begin
 
2009
      DoLimitsChanged;
 
2010
      LimitsChangedCalled:=false;
 
2011
    end;
 
2012
 
 
2013
  if ModifiedChangedCalled then
 
2014
    begin
 
2015
      DoModifiedChanged;
 
2016
      ModifiedChangedCalled:=false;
 
2017
    end;
 
2018
 
 
2019
  if TabSizeChangedCalled then
 
2020
    begin
 
2021
      DoTabSizeChanged;
 
2022
      TabSizeChangedCalled:=false;
 
2023
    end;
 
2024
 
 
2025
  if StoreUndoChangedCalled then
 
2026
    begin
 
2027
      DoStoreUndoChanged;
 
2028
      StoreUndoChangedCalled:=false;
 
2029
    end;
 
2030
 
 
2031
  if ContentsChangedCalled then
 
2032
    begin
 
2033
      DoContentsChanged;
 
2034
      ContentsChangedCalled:=false;
 
2035
    end;
 
2036
 
 
2037
end;
 
2038
 
 
2039
function TCustomCodeEditorCore.UpdateAttrs(FromLine: sw_integer; Attrs: byte): sw_integer;
 
2040
var MinLine: sw_integer;
 
2041
procedure CallIt(P: PEditorBinding); {$ifndef FPC}far;{$endif}
 
2042
var I: sw_integer;
 
2043
begin
 
2044
  I:=DoUpdateAttrs(P^.Editor,FromLine,Attrs);
 
2045
  if (I<MinLine) or (MinLine=-1) then MinLine:=I;
 
2046
end;
 
2047
begin
 
2048
  MinLine:=-1;
 
2049
  Bindings^.ForEach(@CallIt);
 
2050
  UpdateAttrs:=MinLine;
 
2051
end;
 
2052
 
 
2053
function TCustomCodeEditorCore.UpdateAttrsRange(FromLine, ToLine: sw_integer; Attrs: byte): sw_integer;
 
2054
var MinLine: sw_integer;
 
2055
procedure CallIt(P: PEditorBinding); {$ifndef FPC}far;{$endif}
 
2056
var I: sw_integer;
 
2057
begin
 
2058
  I:=DoUpdateAttrsRange(P^.Editor,FromLine,ToLine,Attrs);
 
2059
  if (I<MinLine) or (MinLine=-1) then MinLine:=I;
 
2060
end;
 
2061
begin
 
2062
  MinLine:=-1;
 
2063
  Bindings^.ForEach(@CallIt);
 
2064
  UpdateAttrsRange:=MinLine;
 
2065
end;
 
2066
 
 
2067
function TCustomCodeEditorCore.DoUpdateAttrs(Editor: PCustomCodeEditor; FromLine: sw_integer; Attrs: byte): sw_integer;
 
2068
type
 
2069
    TCharClass = (ccWhiteSpace,ccTab,ccAlpha,
 
2070
      ccNumber,ccHexNumber,ccRealNumber,
 
2071
      ccHash,ccSymbol);
 
2072
var
 
2073
  SymbolIndex: Sw_integer;
 
2074
  CurrentCommentType : Byte;
 
2075
  FirstCC,LastCC: TCharClass;
 
2076
  InAsm,InComment,InSingleLineComment,InDirective,InString: boolean;
 
2077
  X,ClassStart: Sw_integer;
 
2078
  SymbolConcat: string;
 
2079
  LineText,Format: string;
 
2080
 
 
2081
  function MatchSymbol(const What, S: string): boolean;
 
2082
  var Match: boolean;
 
2083
  begin
 
2084
    Match:=false;
 
2085
    if length(What)>=length(S) then
 
2086
      if copy(What,1+length(What)-length(S),length(S))=S then
 
2087
    Match:=true;
 
2088
    MatchSymbol:=Match;
 
2089
  end;
 
2090
 
 
2091
  var MatchedSymbol: boolean;
 
2092
      MatchingSymbol: string;
 
2093
  type TPartialType = (pmNone,pmLeft,pmRight,pmAny);
 
2094
 
 
2095
  function MatchesAnySpecSymbol(SClass: TSpecSymbolClass; PartialMatch: TPartialType): boolean;
 
2096
  var S: pstring;
 
2097
      I: Sw_integer;
 
2098
      Match,Found: boolean;
 
2099
  begin
 
2100
    Found:=false;
 
2101
    if SymbolConcat<>'' then
 
2102
    for I:=1 to Editor^.GetSpecSymbolCount(SClass) do
 
2103
    begin
 
2104
      SymbolIndex:=I;
 
2105
      S:=Editor^.GetSpecSymbol(SClass,I-1);
 
2106
      if (length(SymbolConcat)<length(S^)) or
 
2107
         ((PartialMatch=pmNone) and (length(S^)<>length(SymbolConcat)))
 
2108
          then
 
2109
        Match:=false
 
2110
      else
 
2111
        begin
 
2112
          case PartialMatch of
 
2113
            pmNone : Match:=SymbolConcat=S^;
 
2114
            pmRight:
 
2115
              Match:=copy(SymbolConcat,length(SymbolConcat)-length(S^)+1,length(S^))=S^;
 
2116
          else Match:=MatchSymbol(SymbolConcat,S^);
 
2117
          end;
 
2118
        end;
 
2119
      if Match then
 
2120
      begin
 
2121
        MatchingSymbol:=S^; Found:=true; Break;
 
2122
      end;
 
2123
    end;
 
2124
    MatchedSymbol:=MatchedSymbol or Found;
 
2125
    MatchesAnySpecSymbol:=Found;
 
2126
  end;
 
2127
 
 
2128
  function MatchesAsmSpecSymbol(Const OrigWhat: string; SClass: TSpecSymbolClass): boolean;
 
2129
  var What : String;
 
2130
      S: pstring;
 
2131
      I: Sw_integer;
 
2132
      Match,Found: boolean;
 
2133
  begin
 
2134
    Found:=false;
 
2135
    What:=UpcaseStr(OrigWhat);
 
2136
    if What<>'' then
 
2137
    for I:=1 to Editor^.GetSpecSymbolCount(SClass) do
 
2138
    begin
 
2139
      SymbolIndex:=I;
 
2140
      S:=Editor^.GetSpecSymbol(SClass,I-1);
 
2141
      if (length(S^)<>length(What)) then
 
2142
        Match:=false
 
2143
      else
 
2144
        begin
 
2145
          {if CaseInsensitive then
 
2146
            S:=UpcaseStr(S); asm symbols need to be uppercased PM }
 
2147
          {case PartialMatch of
 
2148
            pmNone : }
 
2149
          Match:=What=S^;
 
2150
          {  pmRight:
 
2151
              Match:=copy(What,length(What)-length(S)+1,length(S))=S;
 
2152
          else Match:=MatchSymbol(What,S);
 
2153
          end;  }
 
2154
        end;
 
2155
      if Match then
 
2156
      begin
 
2157
        MatchingSymbol:=S^;
 
2158
        Found:=true;
 
2159
        Break;
 
2160
      end;
 
2161
    end;
 
2162
    // MatchedSymbol:=MatchedSymbol or Found;
 
2163
    MatchesAsmSpecSymbol:=Found;
 
2164
  end;
 
2165
 
 
2166
  function IsCommentPrefix: boolean;
 
2167
  begin
 
2168
    IsCommentPrefix:=MatchesAnySpecSymbol(ssCommentPrefix,pmLeft);
 
2169
  end;
 
2170
                              {** **}
 
2171
  function IsSingleLineCommentPrefix: boolean;
 
2172
  begin
 
2173
    IsSingleLineCommentPrefix:=MatchesAnySpecSymbol(ssCommentSingleLinePrefix,pmLeft);
 
2174
  end;
 
2175
 
 
2176
  function IsCommentSuffix: boolean;
 
2177
  begin
 
2178
    IsCommentSuffix:=(MatchesAnySpecSymbol(ssCommentSuffix,pmRight))
 
2179
      and (CurrentCommentType=SymbolIndex);
 
2180
  end;
 
2181
 
 
2182
  function IsStringPrefix: boolean;
 
2183
  begin
 
2184
    IsStringPrefix:=MatchesAnySpecSymbol(ssStringPrefix,pmLeft);
 
2185
  end;
 
2186
 
 
2187
  function IsStringSuffix: boolean;
 
2188
  begin
 
2189
    IsStringSuffix:=MatchesAnySpecSymbol(ssStringSuffix,pmRight);
 
2190
  end;
 
2191
 
 
2192
  function IsDirectivePrefix: boolean;
 
2193
  begin
 
2194
    IsDirectivePrefix:=MatchesAnySpecSymbol(ssDirectivePrefix,pmLeft);
 
2195
  end;
 
2196
 
 
2197
  function IsDirectiveSuffix: boolean;
 
2198
  begin
 
2199
    IsDirectiveSuffix:=MatchesAnySpecSymbol(ssDirectiveSuffix,pmRight);
 
2200
  end;
 
2201
 
 
2202
  function IsAsmPrefix(const WordS: string): boolean;
 
2203
  { var
 
2204
     StoredMatchedSymbol : boolean;}
 
2205
  begin
 
2206
    {StoredMatchedSymbol:=MatchedSymbol;}
 
2207
    IsAsmPrefix:=MatchesAsmSpecSymbol(WordS,ssAsmPrefix);
 
2208
    {MatchedSymbol:=StoredMatchedSymbol;}
 
2209
  end;
 
2210
 
 
2211
  function IsAsmSuffix(const WordS: string): boolean;
 
2212
  {var
 
2213
    StoredMatchedSymbol : boolean;}
 
2214
  begin
 
2215
    {StoredMatchedSymbol:=MatchedSymbol;}
 
2216
    IsAsmSuffix:=MatchesAsmSpecSymbol(WordS,ssAsmSuffix);
 
2217
    {MatchedSymbol:=StoredMatchedSymbol;}
 
2218
  end;
 
2219
 
 
2220
  function GetCharClass(C: char): TCharClass;
 
2221
  var CC: TCharClass;
 
2222
  begin
 
2223
  (*
 
2224
     WhiteSpaceChars    {$ifdef USE_UNTYPEDSET}: set of char {$endif} = [#0,#32,#255];
 
2225
     TabChars           {$ifdef USE_UNTYPEDSET}: set of char {$endif} = [#9];
 
2226
     HashChars          {$ifdef USE_UNTYPEDSET}: set of char {$endif} = ['#'];
 
2227
     AlphaChars         {$ifdef USE_UNTYPEDSET}: set of char {$endif} = ['A'..'Z','a'..'z','_'];
 
2228
     NumberChars        {$ifdef USE_UNTYPEDSET}: set of char {$endif} = ['0'..'9'];
 
2229
     HexNumberChars     {$ifdef USE_UNTYPEDSET}: set of char {$endif} = ['0'..'9','A'..'F','a'..'f'];
 
2230
     RealNumberChars    {$ifdef USE_UNTYPEDSET}: set of char {$endif} = ['E','e','.'{,'+','-'}];
 
2231
  *)
 
2232
    if C in {$ifdef USE_UNTYPEDSET}[#0,#32,#255]{$else}WhiteSpaceChars{$endif} then
 
2233
      CC:=ccWhiteSpace
 
2234
    else if C in {$ifdef USE_UNTYPEDSET}[#9]{$else}TabChars{$endif} then
 
2235
      CC:=ccTab
 
2236
    else if C in {$ifdef USE_UNTYPEDSET}['#']{$else}HashChars{$endif} then
 
2237
      CC:=ccHash
 
2238
    else if (LastCC=ccHexNumber) and (C in {$ifdef USE_UNTYPEDSET}['0'..'9','A'..'F','a'..'f']{$else}HexNumberChars{$endif}) then
 
2239
      CC:=ccHexNumber
 
2240
    else if C in {$ifdef USE_UNTYPEDSET}['0'..'9']{$else}NumberChars{$endif} then
 
2241
      CC:=ccNumber
 
2242
    else if (LastCC=ccNumber) and (C in {$ifdef USE_UNTYPEDSET}['E','e','.']{$else}RealNumberChars{$endif}) then
 
2243
      begin
 
2244
        if (C='.') then
 
2245
          begin
 
2246
            if (X>=length(LineText)) or
 
2247
               (LineText[X+1]='.') then
 
2248
              cc:=ccSymbol
 
2249
            else
 
2250
              cc:=ccRealNumber;
 
2251
          end
 
2252
        else {'E','e'}
 
2253
          begin
 
2254
            if (X>=length(LineText)) or
 
2255
               (LineText[X+1]in ['+','-','0'..'9']) then
 
2256
              cc:=ccRealNumber
 
2257
            else
 
2258
              cc:=ccAlpha
 
2259
          end;
 
2260
      end
 
2261
    else if C in {$ifdef USE_UNTYPEDSET}['A'..'Z','a'..'z','_']{$else}AlphaChars{$endif} then CC:=ccAlpha else
 
2262
      CC:=ccSymbol;
 
2263
    GetCharClass:=CC;
 
2264
  end;
 
2265
 
 
2266
  procedure FormatWord(SClass: TCharClass; StartX:Sw_integer;EndX: Sw_integer);
 
2267
  var
 
2268
      C: byte;
 
2269
      WordS: string;
 
2270
  begin
 
2271
    C:=0;
 
2272
    WordS:=copy(LineText,StartX,EndX-StartX+1);
 
2273
    if (InAsm=true) and (InComment=false) and (InString=false) and
 
2274
        (InDirective=false) and (SClass=ccAlpha) and IsAsmSuffix(WordS) then InAsm:=false;
 
2275
    if InDirective then C:=coDirectiveColor else
 
2276
    if InComment then C:=coCommentColor else
 
2277
    if InString then C:=coStringColor else
 
2278
    if InAsm then
 
2279
      begin
 
2280
          if (SClass=ccAlpha) and Editor^.IsAsmReservedWord(WordS) then
 
2281
            C:=coReservedWordColor
 
2282
          else
 
2283
            C:=coAssemblerColor;
 
2284
      end
 
2285
    else
 
2286
    case SClass of
 
2287
      ccWhiteSpace :
 
2288
        C:=coWhiteSpaceColor;
 
2289
      ccTab :
 
2290
        C:=coTabColor;
 
2291
      ccHexNumber:
 
2292
        C:=coHexNumberColor;
 
2293
      ccNumber,
 
2294
      ccRealNumber :
 
2295
        C:=coNumberColor;
 
2296
      ccHash :
 
2297
        C:=coStringColor;
 
2298
      ccSymbol :
 
2299
        C:=coSymbolColor;
 
2300
      ccAlpha :
 
2301
        begin
 
2302
          if Editor^.IsReservedWord(WordS) then
 
2303
            C:=coReservedWordColor
 
2304
          else
 
2305
            C:=coIdentifierColor;
 
2306
        end;
 
2307
    end;
 
2308
    if EndX+1>=StartX then
 
2309
      FillChar(Format[StartX],EndX+1-StartX,C);
 
2310
    if (InString=false) and (InAsm=false) and (InComment=false) and
 
2311
       (InDirective=false) and (SClass=ccAlpha) and IsAsmPrefix(WordS) then
 
2312
      InAsm:=true;
 
2313
  end;
 
2314
 
 
2315
  procedure ProcessChar(C: char);
 
2316
  var CC: TCharClass;
 
2317
      EX: Sw_integer;
 
2318
      EndComment: pstring;
 
2319
  begin
 
2320
    CC:=GetCharClass(C);
 
2321
    if ClassStart=X then
 
2322
      FirstCC:=CC;
 
2323
    if ( (CC<>LastCC) and
 
2324
        (
 
2325
         ((FirstCC=ccNumber) and (CC<>ccRealNumber) {and (CC<>ccNumber)}) or
 
2326
        (((CC<>ccAlpha) or (LastCC<>ccNumber) ) and
 
2327
          ( (CC<>ccNumber) or (LastCC<>ccAlpha) ) and
 
2328
          ( (CC<>ccNumber) or (LastCC<>ccHash) ) and
 
2329
          ( (CC<>ccRealNumber) or (LastCC<>ccNumber))
 
2330
         ))) or
 
2331
 
 
2332
       (X>length(LineText)) or (CC=ccSymbol) then
 
2333
      begin
 
2334
        MatchedSymbol:=false;
 
2335
        EX:=X-1;
 
2336
        if (CC=ccSymbol) then
 
2337
         begin
 
2338
           if length(SymbolConcat)>=High(SymbolConcat) then
 
2339
             Delete(SymbolConcat,1,1);
 
2340
           SymbolConcat:=SymbolConcat+C;
 
2341
           if  InComment and IsCommentSuffix then
 
2342
              Inc(EX) else
 
2343
           if InString and IsStringSuffix  then
 
2344
              Inc(EX) else
 
2345
           if InDirective and IsDirectiveSuffix then
 
2346
              Inc(EX);
 
2347
         end;
 
2348
        if CC=ccRealNumber then
 
2349
          Inc(EX);
 
2350
        if (C='$') and (MatchedSymbol=false) and (IsDirectivePrefix=false) then
 
2351
          CC:=ccHexNumber;
 
2352
        if CC<>ccSymbol then SymbolConcat:='';
 
2353
        FormatWord(LastCC,ClassStart,EX);
 
2354
        ClassStart:=EX+1;
 
2355
        if ClassStart=X then
 
2356
          FirstCC:=CC;
 
2357
        case CC of
 
2358
          ccAlpha  : ;
 
2359
          ccNumber :
 
2360
            if (LastCC<>ccAlpha) then;
 
2361
          ccSymbol :
 
2362
              if (InComment=true) and (CurrentCommentType=1) and
 
2363
                 (InDirective=false)  and IsDirectivePrefix then
 
2364
                begin
 
2365
                  InDirective:=true;
 
2366
                  InComment:=false;
 
2367
                  Dec(ClassStart,length(MatchingSymbol)-1);
 
2368
                end
 
2369
              else if (InComment=false) and
 
2370
                 (InDirective=true) and IsDirectiveSuffix then
 
2371
                 InDirective:=false
 
2372
              else if (InComment=false) and
 
2373
                 (InString=false) and (InDirective=false) and IsCommentPrefix then
 
2374
                begin
 
2375
                  InComment:=true;
 
2376
                  CurrentCommentType:=SymbolIndex;
 
2377
                  InSingleLineComment:=IsSingleLineCommentPrefix;
 
2378
                  {InString:=false; }
 
2379
                  Dec(ClassStart,length(MatchingSymbol)-1);
 
2380
                  { Remove (* from SymbolConcat to avoid problem with (*) PM }
 
2381
                  { fixes part of bug 1617 }
 
2382
                  { but removed proper directive prefix detection ... }
 
2383
                  EndComment:=Editor^.GetSpecSymbol(ssCommentSuffix,SymbolIndex);
 
2384
                  if MatchingSymbol[length(MatchingSymbol)]=EndComment^[1] then
 
2385
                    Delete(SymbolConcat,1,length(MatchingSymbol));
 
2386
                end
 
2387
              else if InComment and IsCommentSuffix then
 
2388
                begin
 
2389
                  InComment:=false;
 
2390
                  InString:=false;
 
2391
                end
 
2392
              else if (InComment=false) and (InString=false) and IsStringPrefix then
 
2393
                begin
 
2394
                  InString:=true;
 
2395
                  Dec(ClassStart,length(MatchingSymbol)-1);
 
2396
                end
 
2397
              else if (InComment=false) and (InString=true) and IsStringSuffix then
 
2398
               InString:=false;
 
2399
        end;
 
2400
        if MatchedSymbol and (InComment=false) then
 
2401
          SymbolConcat:='';
 
2402
        LastCC:=CC;
 
2403
      end;
 
2404
  end;
 
2405
 
 
2406
var CurLineNr: Sw_integer;
 
2407
    Line,NextLine,PrevLine{,OldLine}: PCustomLine;
 
2408
    PrevLI,LI,nextLI: PEditorLineInfo;
 
2409
begin
 
2410
  if (not Editor^.IsFlagSet(efSyntaxHighlight)) or (FromLine>=GetLineCount) then
 
2411
  begin
 
2412
    SetLineFormat(Editor,FromLine,'');
 
2413
    DoUpdateAttrs:=GetLineCount;
 
2414
{$ifdef TEST_PARTIAL_SYNTAX}
 
2415
    LastSyntaxedLine:=GetLineCount;
 
2416
    if not SyntaxComplete then
 
2417
      begin
 
2418
        SyntaxComplete:=true;
 
2419
        DoSyntaxStateChanged;
 
2420
      end;
 
2421
(*    { no Idle necessary }
 
2422
    EventMask:=EventMask and not evIdle;*)
 
2423
{$endif TEST_PARTIAL_SYNTAX}
 
2424
    Editor^.SyntaxStateChanged;
 
2425
    Exit;
 
2426
  end;
 
2427
{$ifdef TEST_PARTIAL_SYNTAX}
 
2428
  If Editor^.IsFlagSet(efSyntaxHighlight) and (LastSyntaxedLine<FromLine)
 
2429
     and (FromLine<GetLineCount) then
 
2430
    CurLineNr:=LastSyntaxedLine
 
2431
  else
 
2432
{$endif TEST_PARTIAL_SYNTAX}
 
2433
    CurLineNr:=FromLine;
 
2434
  if CurLineNr>0 then
 
2435
    PrevLine:=GetLine(CurLineNr-1)
 
2436
  else
 
2437
    PrevLine:=nil;
 
2438
  repeat
 
2439
    Line:=GetLine(CurLineNr);
 
2440
    if Assigned(PrevLine) then PrevLI:=PrevLine^.GetEditorInfo(Editor) else PrevLI:=nil;
 
2441
    if Assigned(Line) then LI:=Line^.GetEditorInfo(Editor) else LI:=nil;
 
2442
    InSingleLineComment:=false;
 
2443
    if PrevLI<>nil then
 
2444
     begin
 
2445
       InAsm:=PrevLI^.EndsWithAsm;
 
2446
       InComment:=PrevLI^.EndsWithComment and not PrevLI^.EndsInSingleLineComment;
 
2447
       CurrentCommentType:=PrevLI^.EndCommentType;
 
2448
       InDirective:=PrevLI^.EndsWithDirective;
 
2449
     end
 
2450
    else
 
2451
     begin
 
2452
       InAsm:=false;
 
2453
       InComment:=false;
 
2454
       CurrentCommentType:=0;
 
2455
       InDirective:=false;
 
2456
     end;
 
2457
{    OldLine:=Line;}
 
2458
    if (not Editor^.IsFlagSet(efKeepLineAttr)) then
 
2459
      begin
 
2460
        LI^.BeginsWithAsm:=InAsm;
 
2461
        LI^.BeginsWithComment:=InComment;
 
2462
        LI^.BeginsWithDirective:=InDirective;
 
2463
        LI^.BeginCommentType:=CurrentCommentType;
 
2464
      end
 
2465
    else
 
2466
      begin
 
2467
        InAsm:=LI^.BeginsWithAsm;
 
2468
        InComment:=LI^.BeginsWithComment;
 
2469
        InDirective:=LI^.BeginsWithDirective;
 
2470
        CurrentCommentType:=LI^.BeginCommentType;
 
2471
      end;
 
2472
    LineText:=GetLineText(CurLineNr);
 
2473
    Format:=CharStr(chr(coTextColor),length(LineText));
 
2474
    LastCC:=ccWhiteSpace;
 
2475
    ClassStart:=1;
 
2476
    SymbolConcat:='';
 
2477
    InString:=false;
 
2478
    if LineText<>'' then
 
2479
     begin
 
2480
       for X:=1 to length(LineText) do
 
2481
         ProcessChar(LineText[X]);
 
2482
       Inc(X);
 
2483
       ProcessChar(' ');
 
2484
     end;
 
2485
    SetLineFormat(Editor,CurLineNr,Format);
 
2486
    LI^.EndsWithAsm:=InAsm;
 
2487
    LI^.EndsWithComment:=InComment;
 
2488
    LI^.EndsInSingleLineComment:=InSingleLineComment;
 
2489
    LI^.EndCommentType:=CurrentCommentType;
 
2490
    LI^.EndsWithDirective:=InDirective;
 
2491
    Inc(CurLineNr);
 
2492
    if CurLineNr>=GetLineCount then
 
2493
     Break;
 
2494
    NextLine:=GetLine(CurLineNr);
 
2495
    if Assigned(NextLine) then NextLI:=NextLine^.GetEditorInfo(Editor) else NextLI:=nil;
 
2496
    if ((Attrs and attrForceFull)=0) then
 
2497
      if (*  Why should we go
 
2498
         (InAsm=false) and (NextLI^.BeginsWithAsm=false) and
 
2499
         (InComment=false) and (NextLI^.BeginsWithComment=false) and
 
2500
         (InDirective=false) and (NextLI^.BeginsWithDirective=false) and
 
2501
{          OldLine = Line so this is nonsense}
 
2502
         (PrevLI^.EndsWithComment=LI^.EndsWithComment) and
 
2503
         (PrevLI^.EndsWithAsm=LI^.EndsWithAsm) and
 
2504
         (PrevLI^.EndsWithDirective=LI^.EndsWithDirective) and *)
 
2505
{$ifdef TEST_PARTIAL_SYNTAX}
 
2506
         (CurLineNr>FromLine) and
 
2507
{$endif TEST_PARTIAL_SYNTAX}
 
2508
         (NextLI^.BeginsWithAsm=LI^.EndsWithAsm) and
 
2509
         (NextLI^.BeginsWithComment=LI^.EndsWithComment) and
 
2510
         (NextLI^.BeginsWithDirective=LI^.EndsWithDirective) and
 
2511
         (NextLI^.BeginCommentType=LI^.EndCommentType) and
 
2512
         (NextLI^.Format<>nil) then
 
2513
       Break;
 
2514
{$ifdef TEST_PARTIAL_SYNTAX}
 
2515
    if (CurLineNr<GetLineCount) and
 
2516
       (CurLineNr>FromLine) and
 
2517
       ((Attrs and attrForceFull)=0) and
 
2518
       (CurLineNr>GetLastVisibleLine) then
 
2519
      begin
 
2520
        If SyntaxComplete then
 
2521
          begin
 
2522
            SyntaxComplete:=false;
 
2523
            DoSyntaxStateChanged;
 
2524
          end;
 
2525
        LastSyntaxedLine:=CurLineNr-1;
 
2526
        break;
 
2527
      end;
 
2528
{$endif TEST_PARTIAL_SYNTAX}
 
2529
    PrevLine:=Line;
 
2530
  until false;
 
2531
  DoUpdateAttrs:=CurLineNr;
 
2532
{$ifdef TEST_PARTIAL_SYNTAX}
 
2533
  If LastSyntaxedLine<CurLineNr-1 then
 
2534
    LastSyntaxedLine:=CurLineNr-1;
 
2535
  if CurLineNr=GetLineCount then
 
2536
    begin
 
2537
      SyntaxComplete:=true;
 
2538
      DoSyntaxStateChanged;
 
2539
    end;
 
2540
{$endif TEST_PARTIAL_SYNTAX}
 
2541
end;
 
2542
 
 
2543
function TCustomCodeEditorCore.DoUpdateAttrsRange(Editor: PCustomCodeEditor; FromLine, ToLine: sw_integer;
 
2544
         Attrs: byte): sw_integer;
 
2545
var Line: Sw_integer;
 
2546
begin
 
2547
  Lock(Editor);
 
2548
  Line:=FromLine;
 
2549
  repeat
 
2550
    Line:=DoUpdateAttrs(Editor,Line,Attrs);
 
2551
  until (Line>=GetLineCount) or (Line>ToLine);
 
2552
  DoUpdateAttrsRange:=Line;
 
2553
  Unlock(Editor);
 
2554
end;
 
2555
 
 
2556
procedure TCustomCodeEditorCore.AddAction(AAction: byte; AStartPos, AEndPos: TPoint; AText: string;AFlags : longint);
 
2557
begin
 
2558
  Abstract;
 
2559
end;
 
2560
 
 
2561
procedure TCustomCodeEditorCore.AddGroupedAction(AAction : byte);
 
2562
begin
 
2563
  Abstract;
 
2564
end;
 
2565
 
 
2566
procedure TCustomCodeEditorCore.CloseGroupedAction(AAction : byte);
 
2567
begin
 
2568
  Abstract;
 
2569
end;
 
2570
 
 
2571
function TCustomCodeEditorCore.GetUndoActionCount: sw_integer;
 
2572
begin
 
2573
  Abstract;
 
2574
  GetUndoActionCount:=0;
 
2575
end;
 
2576
 
 
2577
function TCustomCodeEditorCore.GetRedoActionCount: sw_integer;
 
2578
begin
 
2579
  Abstract;
 
2580
  GetRedoActionCount:=0;
 
2581
end;
 
2582
 
 
2583
destructor TCustomCodeEditorCore.Done;
 
2584
begin
 
2585
{$ifdef DEBUG}
 
2586
  if Bindings^.Count>0 then
 
2587
    ErrorBox('Internal error: there are still '+IntToStr(Bindings^.Count)+' editors '+
 
2588
      'registered at TCodeEditorCode.Done!!!',nil);
 
2589
{$endif}
 
2590
  if Assigned(Bindings) then Dispose(Bindings, Done); Bindings:=nil;
 
2591
  inherited Done;
 
2592
end;
 
2593
 
 
2594
procedure TCustomCodeEditor.Lock;
 
2595
begin
 
2596
  Inc(ELockFlag);
 
2597
  LockScreenUpdate;
 
2598
end;
 
2599
 
 
2600
procedure TCustomCodeEditor.UnLock;
 
2601
begin
 
2602
{$ifdef DEBUG}
 
2603
  if Elockflag=0 then
 
2604
    Bug('negative lockflag',nil)
 
2605
  else
 
2606
{$endif DEBUG}
 
2607
  UnlockScreenUpdate;
 
2608
  Dec(ELockFlag);
 
2609
  if (ELockFlag>0) then
 
2610
    Exit;
 
2611
 
 
2612
  if DrawCalled then
 
2613
    DrawView;
 
2614
 
 
2615
  If DrawCursorCalled then
 
2616
    Begin
 
2617
      DrawCursor;
 
2618
      DrawCursorCalled:=false;
 
2619
    End;
 
2620
end;
 
2621
 
 
2622
procedure TCustomCodeEditor.DrawIndicator;
 
2623
begin
 
2624
  { Abstract }
 
2625
end;
 
2626
 
 
2627
procedure TCustomCodeEditor.AdjustSelectionPos(OldCurPosX, OldCurPosY: sw_integer; DeltaX, DeltaY: sw_integer);
 
2628
var CP: TPoint;
 
2629
begin
 
2630
  if ValidBlock=false then Exit;
 
2631
 
 
2632
  CP.X:=OldCurPosX; CP.Y:=OldCurPosY;
 
2633
  if (PosToOfsP(SelStart)<=PosToOfsP(CP)) and (PosToOfsP(CP)<PosToOfsP(SelEnd)) then
 
2634
    begin
 
2635
      { OldCurPos is IN selection }
 
2636
      if (CP.Y=SelEnd.Y) then
 
2637
        begin
 
2638
          if ((SelStart.Y<>SelEnd.Y) or (SelStart.X<=CP.X)) and
 
2639
             (CP.X<=SelEnd.X) then
 
2640
            Inc(SelEnd.X,DeltaX);
 
2641
        end
 
2642
      else if (CP.Y=SelEnd.Y+DeltaY) then
 
2643
        Inc(SelEnd.X,DeltaX);
 
2644
      Inc(SelEnd.Y,DeltaY);
 
2645
      SelectionChanged;
 
2646
    end
 
2647
  else
 
2648
  if (PosToOfsP(CP)<=PosToOfsP(SelStart)) then
 
2649
    begin
 
2650
      { OldCurPos is BEFORE selection }
 
2651
      if (CP.Y=SelStart.Y) and (CP.Y=SelEnd.Y) and (DeltaY<0) then
 
2652
        begin
 
2653
          SelStart:=CurPos; SelEnd:=CurPos;
 
2654
        end
 
2655
      else
 
2656
      if (CP.Y=SelStart.Y) then
 
2657
        begin
 
2658
          if CP.X<SelStart.X then
 
2659
            Inc(SelStart.X,DeltaX);
 
2660
        end;
 
2661
{      else}
 
2662
        begin
 
2663
          Inc(SelStart.Y,DeltaY);
 
2664
          Inc(SelEnd.Y,DeltaY);
 
2665
        end;
 
2666
      if SelEnd.Y=CurPos.Y then Inc(SelEnd.X,DeltaX);
 
2667
      SelectionChanged;
 
2668
    end
 
2669
  else
 
2670
    begin
 
2671
      { OldCurPos is AFTER selection }
 
2672
      { actually we don't have to do anything here }
 
2673
    end;
 
2674
end;
 
2675
 
 
2676
function TCustomCodeEditor.GetFlags: longint;
 
2677
begin
 
2678
  { Abstract }
 
2679
  GetFlags:=0;
 
2680
end;
 
2681
 
 
2682
procedure TCustomCodeEditor.SetFlags(AFlags: longint);
 
2683
begin
 
2684
  { Abstract }
 
2685
end;
 
2686
 
 
2687
function TCustomCodeEditor.GetModified: boolean;
 
2688
begin
 
2689
  { Abstract }
 
2690
  GetModified:=true;
 
2691
end;
 
2692
 
 
2693
procedure TCustomCodeEditor.SetModified(AModified: boolean);
 
2694
begin
 
2695
  { Abstract }
 
2696
end;
 
2697
 
 
2698
function TCustomCodeEditor.GetStoreUndo: boolean;
 
2699
begin
 
2700
  { Abstract }
 
2701
  GetStoreUndo:=false;
 
2702
end;
 
2703
 
 
2704
procedure TCustomCodeEditor.SetStoreUndo(AStore: boolean);
 
2705
begin
 
2706
  { Abstract }
 
2707
end;
 
2708
 
 
2709
function TCustomCodeEditor.GetSyntaxCompleted: boolean;
 
2710
begin
 
2711
  { Abstract }
 
2712
  GetSyntaxCompleted:=true;
 
2713
end;
 
2714
 
 
2715
procedure TCustomCodeEditor.SetSyntaxCompleted(SC : boolean);
 
2716
begin
 
2717
  { Abstract }
 
2718
end;
 
2719
 
 
2720
function  TCustomCodeEditor.GetLastSyntaxedLine: sw_integer;
 
2721
begin
 
2722
  Abstract;
 
2723
  GetLastSyntaxedLine:=0;
 
2724
end;
 
2725
 
 
2726
procedure   TCustomCodeEditor.SetLastSyntaxedLine(ALine: sw_integer);
 
2727
begin
 
2728
  Abstract;
 
2729
end;
 
2730
 
 
2731
function TCustomCodeEditor.IsFlagSet(AFlag: longint): boolean;{$ifdef USEINLINE}inline;{$endif}
 
2732
begin
 
2733
  IsFlagSet:=(GetFlags and AFlag)=AFlag;
 
2734
end;
 
2735
 
 
2736
function TCustomCodeEditor.GetTabSize: integer;
 
2737
begin
 
2738
  { Abstract }
 
2739
  GetTabSize:=5;
 
2740
end;
 
2741
 
 
2742
procedure TCustomCodeEditor.SetTabSize(ATabSize: integer);
 
2743
begin
 
2744
  { Abstract }
 
2745
end;
 
2746
 
 
2747
function TCustomCodeEditor.GetIndentSize: integer;
 
2748
begin
 
2749
  { Abstract }
 
2750
  GetIndentSize:=1;
 
2751
end;
 
2752
 
 
2753
procedure TCustomCodeEditor.SetIndentSize(AIndentSize: integer);
 
2754
begin
 
2755
  { Abstract }
 
2756
end;
 
2757
 
 
2758
function TCustomCodeEditor.IsReadOnly: boolean;
 
2759
begin
 
2760
  { Abstract }
 
2761
  IsReadOnly:=false;
 
2762
end;
 
2763
 
 
2764
function TCustomCodeEditor.IsClipboard: Boolean;
 
2765
begin
 
2766
  { Abstract }
 
2767
  IsClipboard:=false;
 
2768
end;
 
2769
 
 
2770
function TCustomCodeEditor.GetLineCount: sw_integer;
 
2771
begin
 
2772
  Abstract;
 
2773
  GetLineCount:=0;
 
2774
end;
 
2775
 
 
2776
function TCustomCodeEditor.GetLine(LineNo: sw_integer): PCustomLine;
 
2777
begin
 
2778
  Abstract;
 
2779
  GetLine:=nil;
 
2780
end;
 
2781
 
 
2782
function TCustomCodeEditor.CharIdxToLinePos(Line,CharIdx: sw_integer): sw_integer;
 
2783
begin
 
2784
  Abstract;
 
2785
  CharIdxToLinePos:=0;
 
2786
end;
 
2787
 
 
2788
function TCustomCodeEditor.LinePosToCharIdx(Line,X: sw_integer): sw_integer;
 
2789
begin
 
2790
  Abstract;
 
2791
  LinePosToCharIdx:=0;
 
2792
end;
 
2793
 
 
2794
function TCustomCodeEditor.GetLineText(I: sw_integer): string;
 
2795
begin
 
2796
  Abstract;
 
2797
  GetLineText:='';
 
2798
end;
 
2799
 
 
2800
procedure TCustomCodeEditor.SetDisplayText(I: sw_integer;const S: string);
 
2801
begin
 
2802
  Abstract;
 
2803
end;
 
2804
 
 
2805
function TCustomCodeEditor.GetDisplayText(I: sw_integer): string;
 
2806
begin
 
2807
  Abstract;
 
2808
  GetDisplayText:='';
 
2809
end;
 
2810
 
 
2811
procedure TCustomCodeEditor.SetLineText(I: sw_integer;const S: string);
 
2812
begin
 
2813
  Abstract;
 
2814
end;
 
2815
 
 
2816
procedure TCustomCodeEditor.GetDisplayTextFormat(I: sw_integer;var DT,DF:string);
 
2817
begin
 
2818
  Abstract;
 
2819
end;
 
2820
 
 
2821
function TCustomCodeEditor.GetLineFormat(I: sw_integer): string;
 
2822
begin
 
2823
  { Abstract }
 
2824
  GetLineFormat:='';
 
2825
end;
 
2826
 
 
2827
procedure TCustomCodeEditor.SetLineFormat(I: sw_integer;const S: string);
 
2828
begin
 
2829
  { Abstract }
 
2830
end;
 
2831
 
 
2832
procedure TCustomCodeEditor.DeleteAllLines;
 
2833
begin
 
2834
  Abstract;
 
2835
end;
 
2836
 
 
2837
procedure TCustomCodeEditor.DeleteLine(I: sw_integer);
 
2838
begin
 
2839
  Abstract;
 
2840
end;
 
2841
 
 
2842
function TCustomCodeEditor.InsertLine(LineNo: sw_integer; const S: string): PCustomLine;
 
2843
begin
 
2844
  Abstract;
 
2845
  InsertLine:=nil; { eliminate compiler warning }
 
2846
end;
 
2847
 
 
2848
procedure TCustomCodeEditor.AddLine(const S: string);
 
2849
begin
 
2850
  Abstract;
 
2851
end;
 
2852
 
 
2853
function TCustomCodeEditor.GetErrorMessage: string;
 
2854
begin
 
2855
  Abstract;
 
2856
  GetErrorMessage:='';
 
2857
end;
 
2858
 
 
2859
procedure TCustomCodeEditor.SetErrorMessage(const S: string);
 
2860
begin
 
2861
  Abstract;
 
2862
end;
 
2863
 
 
2864
procedure TCustomCodeEditor.GetContent(ALines: PUnsortedStringCollection);
 
2865
begin
 
2866
  Abstract;
 
2867
end;
 
2868
 
 
2869
procedure TCustomCodeEditor.SetContent(ALines: PUnsortedStringCollection);
 
2870
begin
 
2871
  Abstract;
 
2872
end;
 
2873
 
 
2874
function TCustomCodeEditor.LoadFromStream(Stream: PFastBufStream): boolean;
 
2875
begin
 
2876
  Abstract;
 
2877
  LoadFromStream:=false;
 
2878
end;
 
2879
 
 
2880
function TCustomCodeEditor.SaveToStream(Stream: PStream): boolean;
 
2881
var A,B: TPoint;
 
2882
begin
 
2883
  A.Y:=0; A.X:=0;
 
2884
  B.Y:=GetLineCount-1;
 
2885
  if GetLineCount>0 then
 
2886
    B.X:=length(GetDisplayText(B.Y))
 
2887
  else
 
2888
    B.X:=0;
 
2889
  SaveToStream:=SaveAreaToStream(Stream,A,B);
 
2890
end;
 
2891
 
 
2892
function TCustomCodeEditor.SaveAreaToStream(Stream: PStream; StartP,EndP: TPoint): boolean;
 
2893
begin
 
2894
  Abstract;
 
2895
  SaveAreaToStream:=false;
 
2896
end;
 
2897
 
 
2898
function TCustomCodeEditor.LoadFromFile(const AFileName: string): boolean;
 
2899
var S: PFastBufStream;
 
2900
    OK: boolean;
 
2901
begin
 
2902
  New(S, Init(AFileName,stOpenRead,EditorTextBufSize));
 
2903
  OK:=Assigned(S);
 
2904
{$ifdef TEST_PARTIAL_SYNTAX}
 
2905
  SetSyntaxCompleted(false);
 
2906
  { Idle necessary }
 
2907
  EventMask:=EventMask or evIdle;
 
2908
{$endif TEST_PARTIAL_SYNTAX}
 
2909
  if OK then OK:=LoadFromStream(S);
 
2910
  if Assigned(S) then Dispose(S, Done);
 
2911
  LoadFromFile:=OK;
 
2912
end;
 
2913
 
 
2914
function TCustomCodeEditor.SaveToFile(const AFileName: string): boolean;
 
2915
var OK: boolean;
 
2916
    S: PBufStream;
 
2917
begin
 
2918
  New(S, Init(AFileName,stCreate,EditorTextBufSize));
 
2919
  OK:=Assigned(S) and (S^.Status=stOK);
 
2920
  if OK then OK:=SaveToStream(S);
 
2921
  if Assigned(S) then Dispose(S, Done);
 
2922
  SaveToFile:=OK;
 
2923
end;
 
2924
 
 
2925
 
 
2926
function TCustomCodeEditor.InsertFrom(Editor: PCustomCodeEditor): Boolean;
 
2927
var OK: boolean;
 
2928
    CP,RX,RSX,LineDelta,LineCount: Sw_integer;
 
2929
    StartPos,DestPos,BPos,EPos: TPoint;
 
2930
    LineStartX,LineEndX: Sw_integer;
 
2931
    TabSize,CharIdxStart,CharIdxEnd: Sw_integer;
 
2932
    S,DS,BeforeS,OrigS,AfterS: string;
 
2933
    VerticalBlock: boolean;
 
2934
    SEnd: TPoint;
 
2935
begin
 
2936
  if Editor^.IsFlagSet(efVerticalBlocks) then
 
2937
    begin
 
2938
      NotImplemented;
 
2939
      Exit;
 
2940
    end;
 
2941
  Lock;
 
2942
 
 
2943
  { every data in the clipboard gets a new line }
 
2944
  if (Clipboard=@Self) and (CurPos.X>0) then
 
2945
    InsertNewLine;
 
2946
 
 
2947
  OK:=(Editor^.SelStart.X<>Editor^.SelEnd.X) or (Editor^.SelStart.Y<>Editor^.SelEnd.Y);
 
2948
  if OK then
 
2949
  begin
 
2950
    StartPos:=CurPos; DestPos:=CurPos;
 
2951
    EPos:=CurPos;
 
2952
    VerticalBlock:=Editor^.IsFlagSet(efVerticalBlocks);
 
2953
    LineDelta:=0; LineCount:=(Editor^.SelEnd.Y-Editor^.SelStart.Y)+1;
 
2954
    OK:=GetLineCount<MaxLineCount;
 
2955
    OrigS:=GetLineText(DestPos.Y);
 
2956
    BeforeS:=Copy(OrigS,1,LinePosToCharIdx(DestPos.Y,DestPos.X-1));
 
2957
    { we might need to add some spaces here,
 
2958
      but how many ? }
 
2959
    TabSize:=GetTabSize;
 
2960
    CP:=1; RX:=0;
 
2961
    while (CP<=length(BeforeS)) do
 
2962
      begin
 
2963
        if (BeforeS[CP]=TAB) then
 
2964
          Inc(RX,TabSize-(RX mod TabSize))
 
2965
        else
 
2966
          Inc(RX);
 
2967
        Inc(CP);
 
2968
      end;
 
2969
    BeforeS:=BeforeS+CharStr(' ',DestPos.X-RX);
 
2970
    AfterS:=Copy(OrigS,LinePosToCharIdx(DestPos.Y,DestPos.X),High(OrigS));
 
2971
    BPos:=CurPos;
 
2972
    while OK and (LineDelta<LineCount) do
 
2973
    begin
 
2974
      if (LineDelta>0) and (VerticalBlock=false) then
 
2975
        begin
 
2976
          InsertLine(DestPos.Y,'');
 
2977
          EPOS.X:=0;EPos.Y:=DestPos.Y;
 
2978
          AddAction(eaInsertLine,BPos,EPos,'',GetFlags);
 
2979
          LimitsChanged;
 
2980
        end;
 
2981
 
 
2982
      If LineDelta>0 then
 
2983
        BeforeS:='';
 
2984
      if (LineDelta=0) or VerticalBlock then
 
2985
        LineStartX:=Editor^.SelStart.X
 
2986
      else
 
2987
        LineStartX:=0;
 
2988
 
 
2989
      if (LineDelta=LineCount-1) or VerticalBlock then
 
2990
        LineEndX:=Editor^.SelEnd.X-1
 
2991
      else
 
2992
        LineEndX:=High(S);
 
2993
 
 
2994
      CharIdxStart:=Editor^.LinePosToCharIdx(Editor^.SelStart.Y+LineDelta,LineStartX);
 
2995
      CharIdxEnd:=Editor^.LinePosToCharIdx(Editor^.SelStart.Y+LineDelta,LineEndX);
 
2996
      if LineEndX<LineStartX then
 
2997
        S:=''
 
2998
      else if VerticalBlock then
 
2999
        S:=RExpand(copy(Editor^.GetLineText(Editor^.SelStart.Y+LineDelta),CharIdxStart,CharIdxEnd-CharIdxStart+1),
 
3000
                   Min(CharIdxEnd-CharIdxStart+1,High(S)))
 
3001
      else
 
3002
        S:=copy(Editor^.GetLineText(Editor^.SelStart.Y+LineDelta),CharIdxStart,CharIdxEnd-CharIdxStart+1);
 
3003
      if VerticalBlock=false then
 
3004
        begin
 
3005
          DS:=BeforeS+S;
 
3006
          CP:=1; RX:=0;
 
3007
          RSX :=0;
 
3008
          while (CP<=length(DS)) do
 
3009
            begin
 
3010
              if (DS[CP]=TAB) then
 
3011
                Inc(RX,TabSize-(RX mod TabSize))
 
3012
              else
 
3013
                Inc(RX);
 
3014
              if CP=length(BeforeS) then
 
3015
                RSX:=RX;
 
3016
              Inc(CP);
 
3017
            end;
 
3018
 
 
3019
          if LineDelta=LineCount-1 then
 
3020
            begin
 
3021
              SetLineText(DestPos.Y,DS+AfterS);
 
3022
              BPos.X:=DestPos.X;BPos.Y:=DestPos.Y;
 
3023
              EPOS.X:=DestPos.X+RX-RSX;EPos.Y:=DestPos.Y;
 
3024
              AddAction(eaInsertText,BPos,EPos,S,GetFlags);
 
3025
            end
 
3026
          else
 
3027
            begin
 
3028
              SetLineText(DestPos.Y,DS);
 
3029
              BPos.X:=DestPos.X;BPos.Y:=DestPos.Y;
 
3030
              EPOS.X:=DestPos.X+RX-RSX;EPos.Y:=DestPos.Y;
 
3031
              AddAction(eaInsertText,BPos,EPos,S,GetFlags);
 
3032
            end;
 
3033
          BPos.X:=EPos.X;
 
3034
          if LineDelta=LineCount-1 then
 
3035
            begin
 
3036
              SEnd.Y:=DestPos.Y;
 
3037
              SEnd.X:=DestPos.X+RX-RSX;
 
3038
            end
 
3039
          else
 
3040
           begin
 
3041
             Inc(DestPos.Y);
 
3042
             DestPos.X:=0;
 
3043
           end;
 
3044
        end
 
3045
      else { if VerticalBlock=false then .. else }
 
3046
        begin
 
3047
          { this is not yet implemented !! PM }
 
3048
          S:=RExpand(S,LineEndX-LineStartX+1);
 
3049
        end;
 
3050
      Inc(LineDelta);
 
3051
      OK:=GetLineCount<MaxLineCount;
 
3052
    end;
 
3053
    if not OK then EditorDialog(edTooManyLines,nil);
 
3054
    { mainly to force eaMove insertion }
 
3055
    if not IsClipboard then
 
3056
      SetCurPtr(EPos.X,EPos.Y);
 
3057
    SetCurPtr(StartPos.X,StartPos.Y);
 
3058
    UpdateAttrs(StartPos.Y,attrAll);
 
3059
    SetModified(true);
 
3060
    LimitsChanged;
 
3061
    SetSelection(CurPos,SEnd);
 
3062
    if IsClipboard then
 
3063
     begin
 
3064
       Inc(DestPos.X,length(S));
 
3065
       SetCurPtr(DestPos.X,DestPos.Y);
 
3066
     end;
 
3067
    DrawView;
 
3068
  end;
 
3069
  UnLock;
 
3070
  InsertFrom:=OK;
 
3071
end;
 
3072
 
 
3073
function TCustomCodeEditor.InsertText(const S: string): Boolean;
 
3074
var I: sw_integer;
 
3075
    OldPos: TPoint;
 
3076
    HoldUndo : boolean;
 
3077
begin
 
3078
  Lock;
 
3079
  OldPos:=CurPos;
 
3080
  HoldUndo:=GetStoreUndo;
 
3081
  SetStoreUndo(false);
 
3082
  for I:=1 to length(S) do
 
3083
    AddChar(S[I]);
 
3084
  InsertText:=true;
 
3085
  SetStoreUndo(HoldUndo);
 
3086
  AddAction(eaInsertText,OldPos,CurPos,S,GetFlags);
 
3087
  UnLock;
 
3088
end;
 
3089
 
 
3090
procedure TCustomCodeEditor.ModifiedChanged;
 
3091
begin
 
3092
  { Abstract }
 
3093
end;
 
3094
 
 
3095
procedure TCustomCodeEditor.PositionChanged;
 
3096
begin
 
3097
  { Abstract }
 
3098
end;
 
3099
 
 
3100
procedure TCustomCodeEditor.TabSizeChanged;
 
3101
begin
 
3102
  { Abstract }
 
3103
end;
 
3104
 
 
3105
procedure TCustomCodeEditor.SyntaxStateChanged;
 
3106
begin
 
3107
  { Abstract }
 
3108
end;
 
3109
 
 
3110
procedure TCustomCodeEditor.StoreUndoChanged;
 
3111
begin
 
3112
  { Abstract }
 
3113
end;
 
3114
 
 
3115
function TCustomCodeEditor.GetSpecSymbolCount(SpecClass: TSpecSymbolClass): integer;
 
3116
begin
 
3117
  { Abstract }
 
3118
  GetSpecSymbolCount:=0;
 
3119
end;
 
3120
 
 
3121
function TCustomCodeEditor.GetSpecSymbol(SpecClass: TSpecSymbolClass; Index: integer): pstring;
 
3122
begin
 
3123
  Abstract;
 
3124
  GetSpecSymbol:=nil;
 
3125
end;
 
3126
 
 
3127
function TCustomCodeEditor.IsReservedWord(const S: string): boolean;
 
3128
begin
 
3129
  { Abstract }
 
3130
  IsReservedWord:=false;
 
3131
end;
 
3132
 
 
3133
function TCustomCodeEditor.IsAsmReservedWord(const S: string): boolean;
 
3134
begin
 
3135
  { Abstract }
 
3136
  IsAsmReservedWord:=false;
 
3137
end;
 
3138
 
 
3139
function TCustomCodeEditor.TranslateCodeTemplate(var Shortcut: string; ALines: PUnsortedStringCollection): boolean;
 
3140
begin
 
3141
  { Abstract }
 
3142
  TranslateCodeTemplate:=false;
 
3143
end;
 
3144
 
 
3145
function TCustomCodeEditor.CompleteCodeWord(const WordS: string; var Text: string): boolean;
 
3146
begin
 
3147
  { Abstract }
 
3148
  Text:='';
 
3149
  CompleteCodeWord:=false;
 
3150
end;
 
3151
 
 
3152
function TCustomCodeEditor.GetCodeCompleteWord: string;
 
3153
begin
 
3154
  { Abstract }
 
3155
  GetCodeCompleteWord:='';
 
3156
end;
 
3157
 
 
3158
function TCustomCodeEditor.CreateFold(StartY,EndY: sw_integer; Collapsed: boolean): boolean;
 
3159
var F,ParentF: PFold;
 
3160
    L: PCustomLine;
 
3161
    EI: PEditorLineInfo;
 
3162
    Y: sw_integer;
 
3163
    OK: boolean;
 
3164
begin
 
3165
  OK:=true;
 
3166
  Lock;
 
3167
  for Y:=StartY to EndY do
 
3168
  begin
 
3169
    L:=GetLine(Y);
 
3170
    if assigned(L) then
 
3171
      EI:=L^.GetEditorInfo(@Self)
 
3172
    else
 
3173
      begin
 
3174
        CreateFold:=False;
 
3175
        exit;
 
3176
      end;
 
3177
    if Y=StartY then
 
3178
      ParentF:=EI^.Fold
 
3179
    else
 
3180
      OK:=OK and (EI^.Fold=ParentF);
 
3181
    if not OK then
 
3182
      Break;
 
3183
  end;
 
3184
  if OK then
 
3185
  begin
 
3186
    New(F, Init(@Self,ParentF,Collapsed));
 
3187
    for Y:=StartY to EndY do
 
3188
      GetLine(Y)^.GetEditorInfo(@Self)^.SetFold(F);
 
3189
    DrawView;
 
3190
  end;
 
3191
  UnLock;
 
3192
  CreateFold:=OK;
 
3193
end;
 
3194
 
 
3195
procedure TCustomCodeEditor.FoldChanged(Fold: PFold);
 
3196
var F: PFold;
 
3197
    I: sw_integer;
 
3198
begin
 
3199
  for I:=0 to GetFoldCount-1 do
 
3200
  begin
 
3201
    F:=GetFold(I);
 
3202
    if F^.ParentFold=Fold then
 
3203
      FoldChanged(F);
 
3204
  end;
 
3205
  if Fold^.IsCollapsed then
 
3206
  begin
 
3207
    F:=GetLineFold(CurPos.Y); I:=CurPos.Y;
 
3208
    if F=Fold then
 
3209
    begin
 
3210
     while GetLineFold(I-1)=Fold do
 
3211
       Dec(I);
 
3212
     if I<>CurPos.Y then
 
3213
       SetCurPtr(CurPos.X,I);
 
3214
    end;
 
3215
  end;
 
3216
  DrawView;
 
3217
end;
 
3218
 
 
3219
procedure TCustomCodeEditor.RemoveAllFolds;
 
3220
var I: sw_integer;
 
3221
    L: PCustomLine;
 
3222
begin
 
3223
 
 
3224
  for I:=0 to GetLineCount-1 do
 
3225
    begin
 
3226
      L:=GetLine(I);
 
3227
      if not assigned(L) then exit;
 
3228
      with L^ do
 
3229
        with GetEditorInfo(@Self)^ do
 
3230
          SetFold(nil);
 
3231
    end;
 
3232
  DrawView;
 
3233
end;
 
3234
 
 
3235
{ to be called if CurPos has already been changed }
 
3236
 
 
3237
procedure TCustomCodeEditor.AdjustSelection(DeltaX, DeltaY: sw_integer);
 
3238
begin
 
3239
  AdjustSelectionPos(CurPos.X-DeltaX,CurPos.Y-DeltaY,DeltaX,DeltaY);
 
3240
end;
 
3241
 
 
3242
{ to be called if CurPos has not yet been changed }
 
3243
 
 
3244
procedure TCustomCodeEditor.AdjustSelectionBefore(DeltaX, DeltaY: sw_integer);
 
3245
begin
 
3246
  AdjustSelectionPos(CurPos.X,CurPos.Y,DeltaX,DeltaY);
 
3247
end;
 
3248
 
 
3249
procedure TCustomCodeEditor.TrackCursor(centre:Tcentre);
 
3250
var D,CP: TPoint;
 
3251
begin
 
3252
  D:=Delta;
 
3253
  EditorToViewPoint(D,D); EditorToViewPoint(CurPos,CP);
 
3254
  if CP.Y<Delta.Y then D.Y:=CP.Y else
 
3255
   if CP.Y>Delta.Y+Size.Y-1 then D.Y:=CP.Y-Size.Y+1;
 
3256
  if CP.X<Delta.X then D.X:=CP.X else
 
3257
   if CP.X>Delta.X+Size.X-1 then D.X:=CP.X-Size.X+1;
 
3258
  if {((Delta.X<>D.X) or (Delta.Y<>D.Y)) and }centre=do_centre then
 
3259
  begin
 
3260
     { loose centering for debugger PM }
 
3261
     while (CP.Y-D.Y)<(Size.Y div 3) do Dec(D.Y);
 
3262
     while (CP.Y-D.Y)>2*(Size.Y div 3) do Inc(D.Y);
 
3263
  end;
 
3264
  ViewToEditorPoint(D,D);
 
3265
  if (Delta.X<>D.X) or (Delta.Y<>D.Y) then
 
3266
    ScrollTo(D.X,D.Y);
 
3267
  DrawCursor;
 
3268
end;
 
3269
 
 
3270
procedure TCustomCodeEditor.ScrollTo(X, Y: sw_Integer);
 
3271
begin
 
3272
  inherited ScrollTo(X,Y);
 
3273
  if (HScrollBar=nil) or (VScrollBar=nil) then
 
3274
     begin Delta.X:=X; Delta.Y:=Y; end;
 
3275
  DrawView;
 
3276
end;
 
3277
 
 
3278
function TCustomCodeEditor.IsModal: boolean;
 
3279
var IsM: boolean;
 
3280
begin
 
3281
  IsM:=GetState(sfModal);
 
3282
  if Assigned(Owner) then
 
3283
    IsM:=IsM or Owner^.GetState(sfModal);
 
3284
  IsModal:=IsM;
 
3285
end;
 
3286
 
 
3287
procedure TCustomCodeEditor.FlagsChanged(OldFlags: longint);
 
3288
var I: sw_integer;
 
3289
begin
 
3290
  Lock;
 
3291
  if ((OldFlags xor GetFlags) and efCodeComplete)<>0 then
 
3292
    ClearCodeCompleteWord;
 
3293
  SetInsertMode(IsFlagSet(efInsertMode));
 
3294
  if ((OldFlags xor GetFlags) and efFolds)<>0 then
 
3295
    if not IsFlagSet(efFolds) then
 
3296
      RemoveAllFolds;
 
3297
  if IsFlagSet(efSyntaxHighlight) then
 
3298
    UpdateAttrs(0,attrAll) else
 
3299
  for I:=0 to GetLineCount-1 do
 
3300
    SetLineFormat(I,'');
 
3301
  DrawView;
 
3302
  UnLock;
 
3303
end;
 
3304
 
 
3305
procedure TCustomCodeEditor.LimitsChanged;
 
3306
begin
 
3307
  Abstract;
 
3308
end;
 
3309
 
 
3310
procedure TCustomCodeEditor.DoLimitsChanged;
 
3311
begin
 
3312
  SetLimit(MaxLineLength+1,EditorToViewLine(GetLineCount));
 
3313
end;
 
3314
 
 
3315
procedure TCustomCodeEditor.BindingsChanged;
 
3316
begin
 
3317
  { Abstract }
 
3318
end;
 
3319
 
 
3320
procedure TCustomCodeEditor.ContentsChanged;
 
3321
begin
 
3322
  DrawView;
 
3323
end;
 
3324
 
 
3325
procedure TCustomCodeEditor.ConvertEvent(var Event: TEvent);
 
3326
var
 
3327
  Key: Word;
 
3328
begin
 
3329
  if Event.What = evKeyDown then
 
3330
  begin
 
3331
    if (Event.KeyShift and kbShift <> 0) and
 
3332
      (Event.ScanCode >= $47) and (Event.ScanCode <= $51) then
 
3333
      Event.CharCode := #0;
 
3334
    Key := Event.KeyCode;
 
3335
    if KeyState <> 0 then
 
3336
    begin
 
3337
      if (Lo(Key) >= $01) and (Lo(Key) <= $1A) then Inc(Key, $40);
 
3338
      if (Lo(Key) >= $61) and (Lo(Key) <= $7A) then Dec(Key, $20);
 
3339
    end;
 
3340
    Key := ScanKeyMap(KeyMap[KeyState], Key);
 
3341
    if (KeyState<>0) and (Key=0) then
 
3342
      ClearEvent(Event); { eat second key if unrecognized after ^Q or ^K }
 
3343
    KeyState := 0;
 
3344
    if Key <> 0 then
 
3345
      if Hi(Key) = $FF then
 
3346
        begin
 
3347
          KeyState := Lo(Key);
 
3348
          ClearEvent(Event);
 
3349
        end
 
3350
      else
 
3351
        begin
 
3352
          Event.What := evCommand;
 
3353
          Event.Command := Key;
 
3354
        end;
 
3355
  end;
 
3356
end;
 
3357
 
 
3358
procedure TCustomCodeEditor.SetLineFlagState(LineNo: sw_integer; Flags: longint; ASet: boolean);
 
3359
var L: PCustomLine;
 
3360
begin
 
3361
  { Avoid crashes if file was shorten for instance }
 
3362
  if LineNo>=GetLineCount then
 
3363
    exit;
 
3364
  L:=GetLine(LineNo);
 
3365
  if Assigned(L) then
 
3366
    with L^ do
 
3367
      if ASet then
 
3368
        SetFlags(GetFlags or Flags)
 
3369
      else
 
3370
        SetFlags(GetFlags and not Flags);
 
3371
end;
 
3372
 
 
3373
procedure TCustomCodeEditor.SetLineFlagExclusive(Flags: longint; LineNo: sw_integer);
 
3374
var I,Count: sw_integer;
 
3375
    L: PCustomLine;
 
3376
begin
 
3377
  Lock;
 
3378
  Count:=GetLineCount;
 
3379
  for I:=0 to Count-1 do
 
3380
  begin
 
3381
    L:=GetLine(I);
 
3382
    if not assigned(L) then break;
 
3383
    if I=LineNo then
 
3384
      L^.SetFlags(L^.GetFlags or Flags)
 
3385
    else
 
3386
      L^.SetFlags(L^.GetFlags and (not Flags));
 
3387
  end;
 
3388
  UnLock;
 
3389
end;
 
3390
 
 
3391
procedure TCustomCodeEditor.HandleEvent(var Event: TEvent);
 
3392
var DontClear : boolean;
 
3393
 
 
3394
  procedure CheckScrollBar(P: PScrollBar; var D: Sw_Integer);
 
3395
  begin
 
3396
    if (Event.InfoPtr = P) and (P^.Value <> D) then
 
3397
    begin
 
3398
      D := P^.Value;
 
3399
      DrawView;
 
3400
    end;
 
3401
  end;
 
3402
 
 
3403
  procedure GetMousePos(var P: TPoint);
 
3404
  begin
 
3405
    MakeLocal(Event.Where,P);
 
3406
    Inc(P.X,Delta.X); Inc(P.Y,Delta.Y);
 
3407
    Dec(P.X,GetReservedColCount);
 
3408
    if P.X<0 then P.X:=0;
 
3409
    if P.Y<0 then P.Y:=0;
 
3410
  end;
 
3411
type TCCAction = (ccCheck,ccClear,ccDontCare);
 
3412
var
 
3413
  StartP,P: TPoint;
 
3414
  E: TEvent;
 
3415
  OldEvent : PEvent;
 
3416
  CCAction: TCCAction;
 
3417
begin
 
3418
  CCAction:=ccClear;
 
3419
  E:=Event;
 
3420
  OldEvent:=CurEvent;
 
3421
  if (E.What and (evMouse or evKeyboard))<>0 then
 
3422
    CurEvent:=@E;
 
3423
  if (InASCIIMode=false) or (Event.What<>evKeyDown) then
 
3424
   if (Event.What<>evKeyDown) or (Event.KeyCode<>kbEnter) or (IsReadOnly=false) then
 
3425
   if (Event.What<>evKeyDown) or
 
3426
      ((Event.KeyCode<>kbEnter) and (Event.KeyCode<>kbEsc)) or
 
3427
      (GetCompleteState<>csOffering) then
 
3428
    ConvertEvent(Event);
 
3429
  case Event.What of
 
3430
    evMouseDown :
 
3431
      if MouseInView(Event.Where) then
 
3432
       if (Event.Buttons=mbRightButton) then
 
3433
         begin
 
3434
           MakeLocal(Event.Where,P); Inc(P.X); Inc(P.Y);
 
3435
           LocalMenu(P);
 
3436
           ClearEvent(Event);
 
3437
         end else
 
3438
       if Event.Buttons=mbLeftButton then
 
3439
        begin
 
3440
          GetMousePos(P);
 
3441
          StartP:=P;
 
3442
          SetCurPtr(P.X,P.Y);
 
3443
          repeat
 
3444
            GetMousePos(P);
 
3445
            if PointOfs(P)<PointOfs(StartP)
 
3446
               then SetSelection(P,StartP)
 
3447
               else SetSelection(StartP,P);
 
3448
            SetCurPtr(P.X,P.Y);
 
3449
            DrawView;
 
3450
          until not MouseEvent(Event, evMouseMove+evMouseAuto);
 
3451
          DrawView;
 
3452
        end;
 
3453
    evKeyDown :
 
3454
      begin
 
3455
        { Scancode is almost never zero PM }
 
3456
        { this is supposed to enable entering of ASCII chars below 32,
 
3457
          which are normally interpreted as control chars. So, when you enter
 
3458
          Alt+24 (on the numeric pad) then this will normally move the cursor
 
3459
          one line down, but if you do it in ASCII mode (also after Ctrl+B)
 
3460
          then this will insert the ASCII #24 char (upper arrow) in the
 
3461
          source code. - Gabor }
 
3462
        if InASCIIMode {and (Event.CharCode<>0)} then
 
3463
          begin
 
3464
            AddChar(Event.CharCode);
 
3465
            if (GetCompleteState<>csDenied) or (Event.CharCode=#32) then
 
3466
              CCAction:=ccCheck
 
3467
            else
 
3468
              CCAction:=ccClear;
 
3469
          end
 
3470
        else
 
3471
          begin
 
3472
           DontClear:=false;
 
3473
           case Event.KeyCode of
 
3474
             kbAltF10 :
 
3475
               Message(@Self,evCommand,cmLocalMenu,@Self);
 
3476
             kbEnter  :
 
3477
               if IsReadOnly then
 
3478
                 DontClear:=true else
 
3479
               if GetCompleteState=csOffering then
 
3480
                 CodeCompleteApply
 
3481
               else
 
3482
                 Message(@Self,evCommand,cmNewLine,nil);
 
3483
             kbEsc :
 
3484
               if GetCompleteState=csOffering then
 
3485
                 CodeCompleteCancel else
 
3486
                if IsModal then
 
3487
                  DontClear:=true;
 
3488
           else
 
3489
            case Event.CharCode of
 
3490
             #9,#32..#255 :
 
3491
               if (Event.CharCode=#9) and IsModal then
 
3492
                 DontClear:=true
 
3493
               else
 
3494
                 begin
 
3495
                   NoSelect:=true;
 
3496
                   AddChar(Event.CharCode);
 
3497
                   NoSelect:=false;
 
3498
                   if (GetCompleteState<>csDenied) or (Event.CharCode=#32) then
 
3499
                     CCAction:=ccCheck
 
3500
                   else
 
3501
                     CCAction:=ccClear;
 
3502
                 end;
 
3503
            else
 
3504
              DontClear:=true;
 
3505
            end; { case Event.CharCode .. }
 
3506
           end; { case Event.KeyCode .. }
 
3507
            if not DontClear then
 
3508
             ClearEvent(Event);
 
3509
          end;
 
3510
        InASCIIMode:=false;
 
3511
      end;
 
3512
    evCommand :
 
3513
      begin
 
3514
        DontClear:=false;
 
3515
        case Event.Command of
 
3516
          cmASCIIChar   : InASCIIMode:=not InASCIIMode;
 
3517
          cmAddChar     : AddChar(chr(longint(Event.InfoPtr)));
 
3518
          cmCharLeft    : CharLeft;
 
3519
          cmCharRight   : CharRight;
 
3520
          cmWordLeft    : WordLeft;
 
3521
          cmWordRight   : WordRight;
 
3522
          cmLineStart   : LineStart;
 
3523
          cmLineEnd     : LineEnd;
 
3524
          cmLineUp      : LineUp;
 
3525
          cmLineDown    : LineDown;
 
3526
          cmPageUp      : PageUp;
 
3527
          cmPageDown    : PageDown;
 
3528
          cmTextStart   : TextStart;
 
3529
          cmTextEnd     : TextEnd;
 
3530
          cmWindowStart : WindowStart;
 
3531
          cmWindowEnd   : WindowEnd;
 
3532
          cmNewLine     : begin
 
3533
                            InsertNewLine;
 
3534
                            TrackCursor(do_not_centre);
 
3535
                          end;
 
3536
          cmBreakLine   : BreakLine;
 
3537
          cmBackSpace   : BackSpace;
 
3538
          cmDelChar     : DelChar;
 
3539
          cmDelWord     : DelWord;
 
3540
       cmDelToEndOfWord : DelToEndOfWord;
 
3541
          cmDelStart    : DelStart;
 
3542
          cmDelEnd      : DelEnd;
 
3543
          cmDelLine     : DelLine;
 
3544
          cmInsMode     : InsMode;
 
3545
          cmStartSelect : StartSelect;
 
3546
          cmHideSelect  : HideSelect;
 
3547
          cmUpdateTitle : ;
 
3548
          cmEndSelect   : EndSelect;
 
3549
          cmDelSelect   : DelSelect;
 
3550
          cmCopyBlock   : CopyBlock;
 
3551
          cmMoveBlock   : MoveBlock;
 
3552
          cmIndentBlock   : IndentBlock;
 
3553
          cmUnindentBlock : UnindentBlock;
 
3554
          cmSelStart    : JumpSelStart;
 
3555
          cmSelEnd      : JumpSelEnd;
 
3556
          cmLastCursorPos : JumpToLastCursorPos;
 
3557
          cmFindMatchingDelimiter : FindMatchingDelimiter(true);
 
3558
          cmFindMatchingDelimiterBack : FindMatchingDelimiter(false);
 
3559
          cmUpperCase     : UpperCase;
 
3560
          cmLowerCase     : LowerCase;
 
3561
          cmWordLowerCase : WordLowerCase;
 
3562
          cmWordUpperCase : WordUpperCase;
 
3563
          cmInsertOptions : InsertOptions;
 
3564
          cmToggleCase    : ToggleCase;
 
3565
          cmCreateFold    : CreateFoldFromBlock;
 
3566
          cmToggleFold    : ToggleFold;
 
3567
          cmExpandFold    : ExpandFold;
 
3568
          cmCollapseFold  : CollapseFold;
 
3569
          cmJumpMark0..cmJumpMark9 : JumpMark(Event.Command-cmJumpMark0);
 
3570
          cmSetMark0..cmSetMark9 : DefineMark(Event.Command-cmSetMark0);
 
3571
          cmSelectWord  : SelectWord;
 
3572
          cmSelectLine  : SelectLine;
 
3573
          cmWriteBlock  : WriteBlock;
 
3574
          cmReadBlock   : ReadBlock;
 
3575
          cmPrintBlock  : PrintBlock;
 
3576
        { ------ }
 
3577
          cmFind        : Find;
 
3578
          cmReplace     : Replace;
 
3579
          cmSearchAgain : DoSearchReplace;
 
3580
          cmJumpLine    : GotoLine;
 
3581
        { ------ }
 
3582
          cmCut         : ClipCut;
 
3583
          cmCopy        : ClipCopy;
 
3584
          cmPaste       : ClipPaste;
 
3585
 
 
3586
          cmSelectAll   : SelectAll(true);
 
3587
          cmUnselect    : SelectAll(false);
 
3588
{$ifdef WinClipSupported}
 
3589
          cmCopyWin     : ClipCopyWin;
 
3590
          cmPasteWin    : ClipPasteWin;
 
3591
{$endif WinClipSupported}
 
3592
          cmUndo        : Undo;
 
3593
          cmRedo        : Redo;
 
3594
          cmClear       : DelSelect;
 
3595
          cmExpandCodeTemplate: ExpandCodeTemplate;
 
3596
          cmLocalMenu :
 
3597
            begin
 
3598
              P:=CurPos; Inc(P.X); Inc(P.Y);
 
3599
              LocalMenu(P);
 
3600
            end;
 
3601
          cmActivateMenu :
 
3602
            Message(Application,evCommand,cmMenu,nil);
 
3603
        else
 
3604
          begin
 
3605
            DontClear:=true;
 
3606
            CCAction:=ccDontCare;
 
3607
          end;
 
3608
        end;
 
3609
        if DontClear=false then
 
3610
          ClearEvent(Event);
 
3611
      end;
 
3612
{$ifdef TEST_PARTIAL_SYNTAX}
 
3613
    evIdle :
 
3614
      begin
 
3615
        CCAction:=ccDontCare;
 
3616
        { Complete syntax by 20 lines increment }
 
3617
        { could already be quite lengthy on slow systems }
 
3618
        if not GetSyntaxCompleted then
 
3619
          UpdateAttrsRange(GetLastSyntaxedLine,GetLastSyntaxedLine+20,AttrAll);
 
3620
      end;
 
3621
{$endif TEST_PARTIAL_SYNTAX}
 
3622
    evBroadcast :
 
3623
      begin
 
3624
        CCAction:=ccDontCare;
 
3625
        case Event.Command of
 
3626
          cmUpdate :
 
3627
            Update;
 
3628
          cmClearLineHighlights :
 
3629
            SetLineFlagExclusive(lfHighlightRow,-1);
 
3630
          cmResetDebuggerRow :
 
3631
            SetLineFlagExclusive(lfDebuggerRow,-1);
 
3632
          cmScrollBarChanged:
 
3633
            if (Event.InfoPtr = HScrollBar) or
 
3634
               (Event.InfoPtr = VScrollBar) then
 
3635
              begin
 
3636
                CheckScrollBar(HScrollBar, Delta.X);
 
3637
                CheckScrollBar(VScrollBar, Delta.Y);
 
3638
              end;
 
3639
        end;
 
3640
      end;
 
3641
  else CCAction:=ccDontCare;
 
3642
  end;
 
3643
  inherited HandleEvent(Event);
 
3644
  CurEvent:=OldEvent;
 
3645
  case CCAction of
 
3646
    ccCheck : CodeCompleteCheck;
 
3647
    ccClear : ClearCodeCompleteWord;
 
3648
  end;
 
3649
end;
 
3650
 
 
3651
procedure TCustomCodeEditor.UpdateUndoRedo(cm : word; action : byte);
 
3652
var UndoMenu : PMenuItem;
 
3653
begin
 
3654
  UndoMenu:=PAdvancedMenuBar(MenuBar)^.GetMenuItem(cm);
 
3655
  if assigned(UndoMenu) then
 
3656
    begin
 
3657
      If assigned(UndoMenu^.Param) then
 
3658
        DisposeStr(UndoMenu^.Param);
 
3659
      if action<lastaction then
 
3660
        UndoMenu^.Param:=NewStr(ActionString[action]);
 
3661
    end;
 
3662
end;
 
3663
 
 
3664
 
 
3665
procedure TCustomCodeEditor.Update;
 
3666
begin
 
3667
  Lock;
 
3668
  LimitsChanged;
 
3669
  SelectionChanged;
 
3670
  HighlightChanged;
 
3671
  UnLock;
 
3672
end;
 
3673
 
 
3674
function TCustomCodeEditor.GetLocalMenu: PMenu;
 
3675
begin
 
3676
  GetLocalMenu:=nil;
 
3677
end;
 
3678
 
 
3679
function TCustomCodeEditor.GetCommandTarget: PView;
 
3680
begin
 
3681
  GetCommandTarget:=@Self;
 
3682
end;
 
3683
 
 
3684
function TCustomCodeEditor.CreateLocalMenuView(var Bounds: TRect; M: PMenu): PMenuPopup;
 
3685
var MV: PMenuPopup;
 
3686
begin
 
3687
  New(MV, Init(Bounds, M));
 
3688
  CreateLocalMenuView:=MV;
 
3689
end;
 
3690
 
 
3691
procedure TCustomCodeEditor.LocalMenu(P: TPoint);
 
3692
var M: PMenu;
 
3693
    MV: PMenuPopUp;
 
3694
    R: TRect;
 
3695
    Re: word;
 
3696
begin
 
3697
  M:=GetLocalMenu;
 
3698
  if M=nil then Exit;
 
3699
  if LastLocalCmd<>0 then
 
3700
     M^.Default:=SearchMenuItem(M,LastLocalCmd);
 
3701
  Desktop^.GetExtent(R);
 
3702
  MakeGlobal(P,R.A); {Desktop^.MakeLocal(R.A,R.A);}
 
3703
  MV:=CreateLocalMenuView(R,M);
 
3704
  Re:=Application^.ExecView(MV);
 
3705
  if M^.Default=nil then LastLocalCmd:=0
 
3706
     else LastLocalCmd:=M^.Default^.Command;
 
3707
  Dispose(MV, Done);
 
3708
  if Re<>0 then
 
3709
    Message(GetCommandTarget,evCommand,Re,@Self);
 
3710
end;
 
3711
 
 
3712
function TCustomCodeEditor.GetReservedColCount: sw_integer;
 
3713
var LSX: sw_integer;
 
3714
begin
 
3715
  if IsFlagSet(efFolds) then LSX:=GetFoldStringWidth else LSX:=0;
 
3716
  GetReservedColCount:=LSX;
 
3717
end;
 
3718
 
 
3719
procedure TCustomCodeEditor.Draw;
 
3720
function GetEIFold(EI: PEditorLineInfo): PFold;
 
3721
begin
 
3722
  if Assigned(EI) then GetEIFold:=EI^.Fold else GetEIFold:=nil;
 
3723
end;
 
3724
var SelectColor,
 
3725
    HighlightColColor,
 
3726
    HighlightRowColor,
 
3727
    ErrorMessageColor  : word;
 
3728
    B: TDrawBuffer;
 
3729
    X,Y,AX,AY,MaxX,LSX: sw_integer;
 
3730
    PX: TPoint;
 
3731
    LineCount: sw_integer;
 
3732
    Line: PCustomLine;
 
3733
    LineText,Format: string;
 
3734
    isBreak : boolean;
 
3735
    C: char;
 
3736
    FreeFormat: array[0..MaxLineLength] of boolean;
 
3737
    Color: word;
 
3738
    ColorTab: array[coFirstColor..coLastColor] of word;
 
3739
    ErrorLine: integer;
 
3740
    ErrorMsg: string[MaxViewWidth];
 
3741
function CombineColors(Orig,Modifier: byte): byte;
 
3742
var Color: byte;
 
3743
begin
 
3744
  if (Modifier and $0f)=0 then
 
3745
    Color:=(Orig and $0f) or (Modifier and $f0)
 
3746
  else
 
3747
    Color:=(Orig and $f0) or (Modifier and $0f);
 
3748
  { do not allow invisible }
 
3749
  { use white as foreground in this case }
 
3750
  if (Color and $f) = ((Color div $10) and $7) then
 
3751
    Color:=(Color and $F0) or $F;
 
3752
  CombineColors:=Color;
 
3753
end;
 
3754
var
 
3755
    FoldPrefix,FoldSuffix: string;
 
3756
{    SkipLine: boolean;}
 
3757
{    FoldStartLine: sw_integer;}
 
3758
begin
 
3759
  if ELockFlag>0 then
 
3760
    begin
 
3761
      DrawCalled:=true;
 
3762
      Exit;
 
3763
    end;
 
3764
  DrawCalled:=false;
 
3765
 
 
3766
  ErrorMsg:=copy(GetErrorMessage,1,MaxViewWidth);
 
3767
  if ErrorMsg='' then ErrorLine:=-1 else
 
3768
  if (CurPos.Y-Delta.Y)<(Size.Y div 2) then ErrorLine:=Size.Y-1
 
3769
     else ErrorLine:=0;
 
3770
  LineCount:=GetLineCount;
 
3771
  ColorTab[coTextColor]:=GetColor(1);
 
3772
  ColorTab[coWhiteSpaceColor]:=GetColor(2);
 
3773
  ColorTab[coCommentColor]:=GetColor(3);
 
3774
  ColorTab[coReservedWordColor]:=GetColor(4);
 
3775
  ColorTab[coIdentifierColor]:=GetColor(5);
 
3776
  ColorTab[coStringColor]:=GetColor(6);
 
3777
  ColorTab[coNumberColor]:=GetColor(7);
 
3778
  ColorTab[coAssemblerColor]:=GetColor(8);
 
3779
  ColorTab[coSymbolColor]:=GetColor(9);
 
3780
  ColorTab[coDirectiveColor]:=GetColor(13);
 
3781
  ColorTab[coHexNumberColor]:=GetColor(14);
 
3782
  ColorTab[coTabColor]:=GetColor(15);
 
3783
  { break same as error }
 
3784
  ColorTab[coBreakColor]:=GetColor(16);
 
3785
  ColorTab[coAsmReservedColor]:=GetColor(17);
 
3786
  SelectColor:=GetColor(10);
 
3787
  HighlightColColor:=GetColor(11);
 
3788
  HighlightRowColor:=GetColor(12);
 
3789
  ErrorMessageColor:=GetColor(16);
 
3790
{$ifdef TEST_PARTIAL_SYNTAX}
 
3791
  If (not GetSyntaxCompleted) and (GetLastSyntaxedLine<Delta.Y+Size.Y) then
 
3792
    UpdateAttrsRange(GetLastSyntaxedLine,Delta.Y+Size.Y,AttrAll);
 
3793
{$endif TEST_PARTIAL_SYNTAX}
 
3794
  LSX:=GetReservedColCount;
 
3795
  Y:=0; AY:=Delta.Y;
 
3796
  for Y:=0 to Size.Y-1 do
 
3797
  begin
 
3798
    if Y=ErrorLine then
 
3799
      begin
 
3800
        MoveChar(B,' ',ErrorMessageColor,Size.X);
 
3801
        MoveStr(B,ErrorMsg,ErrorMessageColor);
 
3802
        WriteLine(0,Y,Size.X,1,B);
 
3803
      end
 
3804
    else
 
3805
      begin
 
3806
        AY:=ViewToEditorLine(Delta.Y+Y);
 
3807
        if (0<=AY) and (AY<LineCount) then
 
3808
          begin
 
3809
            Line:=GetLine(AY);
 
3810
            if assigned(Line) then
 
3811
              begin
 
3812
                IsBreak:=Line^.IsFlagSet(lfBreakpoint);
 
3813
              end
 
3814
            else
 
3815
              begin
 
3816
                IsBreak:=false;
 
3817
              end;
 
3818
          end
 
3819
        else
 
3820
          begin
 
3821
            Line:=nil;
 
3822
            IsBreak:=false;
 
3823
          end;
 
3824
 
 
3825
        begin
 
3826
          Color:=ColorTab[coTextColor];
 
3827
          FillChar(FreeFormat,SizeOf(FreeFormat),1);
 
3828
          MoveChar(B,' ',Color,Size.X);
 
3829
          GetDisplayTextFormat(AY,LineText,Format);
 
3830
 
 
3831
      {    if FlagSet(efSyntaxHighlight) then MaxX:=length(LineText)+1
 
3832
             else }MaxX:=Size.X+Delta.X;
 
3833
          for X:=1 to Min(MaxX,High(LineText)) do
 
3834
          begin
 
3835
            AX:=Delta.X+X-1;
 
3836
            if X<=length(LineText) then C:=LineText[X] else C:=' ';
 
3837
 
 
3838
            PX.X:=AX-Delta.X; PX.Y:=AY;
 
3839
            if (Highlight.A.X<>Highlight.B.X) or (Highlight.A.Y<>Highlight.B.Y) then
 
3840
             { there's a highlight }
 
3841
              begin
 
3842
                if (PointOfs(Highlight.A)<=PointOfs(PX)) and (PointOfs(PX)<PointOfs(Highlight.B)) then
 
3843
                  begin
 
3844
                    Color:=SelectColor;
 
3845
                    FreeFormat[X]:=false;
 
3846
                  end;
 
3847
              end
 
3848
            else
 
3849
             { no highlight }
 
3850
              begin
 
3851
                if IsFlagSet(efVerticalBlocks) then
 
3852
                  begin
 
3853
                    if (SelStart.X<=AX) and (AX<=SelEnd.X) and
 
3854
                       (SelStart.Y<=AY) and (AY<=SelEnd.Y) then
 
3855
                      begin
 
3856
                        Color:=SelectColor; FreeFormat[X]:=false;
 
3857
                      end;
 
3858
                  end
 
3859
                else
 
3860
                  if PointOfs(SelStart)<>PointOfs(SelEnd) then
 
3861
                   if (PointOfs(SelStart)<=PointOfs(PX)) and (PointOfs(PX)<PointOfs(SelEnd)) then
 
3862
                    begin
 
3863
                      Color:=SelectColor; FreeFormat[X]:=false;
 
3864
                    end;
 
3865
              end; { no highlight }
 
3866
            if FreeFormat[X] then
 
3867
             if X<=length(Format) then
 
3868
               {Color:=ColorTab[ord(Format[X])] else Color:=ColorTab[coTextColor];
 
3869
                 this give BoundsCheckError with -Cr quite often PM }
 
3870
               Color:=ColorTab[ord(Format[X]) mod (coLastColor + 1)] else Color:=ColorTab[coTextColor];
 
3871
 
 
3872
            if IsFlagSet(efHighlightRow) and
 
3873
               (PX.Y=CurPos.Y) then
 
3874
              begin
 
3875
                Color:=CombineColors(Color,HighlightRowColor);
 
3876
                FreeFormat[X]:=false;
 
3877
              end;
 
3878
            if IsFlagSet(efHighlightColumn) and (PX.X=CurPos.X) then
 
3879
              begin
 
3880
                Color:=CombineColors(Color,HighlightColColor);
 
3881
                FreeFormat[X]:=false;
 
3882
              end;
 
3883
 
 
3884
            if Assigned(Line) and Line^.IsFlagSet(lfHighlightRow) then
 
3885
              begin
 
3886
                Color:=CombineColors(Color,HighlightRowColor);
 
3887
                FreeFormat[X]:=false;
 
3888
              end;
 
3889
            if isbreak then
 
3890
              begin
 
3891
                Color:=ColorTab[coBreakColor];
 
3892
                FreeFormat[X]:=false;
 
3893
              end;
 
3894
            if Assigned(Line) and Line^.isFlagSet(lfDebuggerRow) then
 
3895
              begin
 
3896
                Color:=CombineColors(Color,HighlightRowColor);
 
3897
                FreeFormat[X]:=false;
 
3898
              end;
 
3899
 
 
3900
            if (0<=LSX+X-1-Delta.X) and (LSX+X-1-Delta.X<MaxViewWidth) then
 
3901
              MoveChar(B[LSX+X-1-Delta.X],C,Color,1);
 
3902
          end; { for X:=1 to ... }
 
3903
          if IsFlagSet(efFolds) then
 
3904
          begin
 
3905
            GetFoldStrings(AY,FoldPrefix,FoldSuffix);
 
3906
            MoveStr(B[0],FoldPrefix,ColorTab[coTextColor]);
 
3907
            if FoldSuffix<>'' then
 
3908
              MoveStr(B[Size.X-1-length(FoldSuffix)],FoldSuffix,ColorTab[coTextColor]);
 
3909
          end;
 
3910
          WriteLine(0,Y,Size.X,1,B);
 
3911
        end; { if not SkipLine ... }
 
3912
      end; { not errorline }
 
3913
  end; { while (Y<Size.Y) ... }
 
3914
  DrawCursor;
 
3915
end;
 
3916
 
 
3917
procedure TCustomCodeEditor.DrawCursor;
 
3918
begin
 
3919
  if Elockflag>0 then
 
3920
    DrawCursorCalled:=true
 
3921
  else
 
3922
    begin
 
3923
      SetCursor(GetReservedColCount+CurPos.X-Delta.X,EditorToViewLine(CurPos.Y)-Delta.Y);
 
3924
      SetState(sfCursorIns,Overwrite);
 
3925
    end;
 
3926
end;
 
3927
 
 
3928
procedure TCustomCodeEditor.ResetCursor;
 
3929
begin
 
3930
  if Elockflag>0 then
 
3931
    begin
 
3932
      DrawCursorCalled:=true;
 
3933
      exit;
 
3934
    end
 
3935
  else
 
3936
    inherited ResetCursor;
 
3937
end;
 
3938
 
 
3939
function TCustomCodeEditor.Overwrite: boolean;
 
3940
begin
 
3941
  Overwrite:=not IsFlagSet(efInsertMode);
 
3942
end;
 
3943
 
 
3944
procedure TCustomCodeEditor.SetCodeCompleteWord(const S: string);
 
3945
begin
 
3946
  if S<>'' then
 
3947
    SetCompleteState(csOffering)
 
3948
  else
 
3949
    SetCompleteState(csInactive);
 
3950
end;
 
3951
 
 
3952
procedure TCustomCodeEditor.ClearCodeCompleteWord;
 
3953
begin
 
3954
  SetCodeCompleteWord('');
 
3955
  SetCompleteState(csInactive);
 
3956
end;
 
3957
 
 
3958
function TCustomCodeEditor.GetCompleteState: TCompleteState;
 
3959
begin
 
3960
  { Abstract }
 
3961
  GetCompleteState:=csInactive;
 
3962
end;
 
3963
 
 
3964
procedure TCustomCodeEditor.SetCompleteState(AState: TCompleteState);
 
3965
begin
 
3966
  { Abstract }
 
3967
end;
 
3968
 
 
3969
function TCustomCodeEditor.UpdateAttrs(FromLine: sw_integer; Attrs: byte): sw_integer;
 
3970
begin
 
3971
  Abstract;
 
3972
  UpdateAttrs:=-1;
 
3973
end;
 
3974
 
 
3975
function TCustomCodeEditor.UpdateAttrsRange(FromLine, ToLine: sw_integer; Attrs: byte): sw_integer;
 
3976
begin
 
3977
  Abstract;
 
3978
  UpdateAttrsRange:=-1;
 
3979
end;
 
3980
 
 
3981
procedure TCustomCodeEditor.AddAction(AAction: byte; AStartPos, AEndPos: TPoint; AText: string;AFlags : longint);
 
3982
begin
 
3983
  { Abstract }
 
3984
end;
 
3985
 
 
3986
procedure TCustomCodeEditor.AddGroupedAction(AAction : byte);
 
3987
begin
 
3988
  { Abstract }
 
3989
end;
 
3990
 
 
3991
procedure TCustomCodeEditor.CloseGroupedAction(AAction : byte);
 
3992
begin
 
3993
  { Abstract }
 
3994
end;
 
3995
 
 
3996
function TCustomCodeEditor.GetUndoActionCount: sw_integer;
 
3997
begin
 
3998
  { Abstract }
 
3999
  GetUndoActionCount:=0;
 
4000
end;
 
4001
 
 
4002
function TCustomCodeEditor.GetRedoActionCount: sw_integer;
 
4003
begin
 
4004
  { Abstract }
 
4005
  GetRedoActionCount:=0;
 
4006
end;
 
4007
 
 
4008
function TCustomCodeEditor.GetMaxFoldLevel: sw_integer;
 
4009
var Max,L,I: sw_integer;
 
4010
begin
 
4011
  Max:=0;
 
4012
  for I:=0 to GetFoldCount-1 do
 
4013
  begin
 
4014
    L:=GetFold(I)^.GetLevel;
 
4015
    if L>Max then Max:=L;
 
4016
  end;
 
4017
  GetMaxFoldLevel:=Max;
 
4018
end;
 
4019
 
 
4020
function TCustomCodeEditor.GetFoldStringWidth: sw_integer;
 
4021
begin
 
4022
  GetFoldStringWidth:=GetMaxFoldLevel;
 
4023
end;
 
4024
 
 
4025
procedure TCustomCodeEditor.GetFoldStrings(EditorLine: sw_integer; var Prefix, Suffix: openstring);
 
4026
var F: PFold;
 
4027
    C: char;
 
4028
begin
 
4029
  Prefix:=CharStr(' ',GetFoldStringWidth); Suffix:='';
 
4030
  F:=GetLineFold(EditorLine);
 
4031
  if Assigned(F) then
 
4032
  begin
 
4033
    if F^.Collapsed_ then C:=#27 else C:=#26;
 
4034
    Prefix[1+F^.GetLevel]:=C;
 
4035
    if F^.Collapsed_ then
 
4036
      Suffix:='('+IntToStr(F^.GetLineCount)+')';
 
4037
  end;
 
4038
end;
 
4039
 
 
4040
function TCustomCodeEditor.GetFoldCount: sw_integer;
 
4041
begin
 
4042
  GetFoldCount:=0;
 
4043
end;
 
4044
 
 
4045
function TCustomCodeEditor.GetFold(Index: sw_integer): PFold;
 
4046
begin
 
4047
  GetFold:=nil;
 
4048
end;
 
4049
 
 
4050
procedure TCustomCodeEditor.RegisterFold(AFold: PFold);
 
4051
begin
 
4052
  Abstract;
 
4053
end;
 
4054
 
 
4055
procedure TCustomCodeEditor.UnRegisterFold(AFold: PFold);
 
4056
begin
 
4057
  Abstract;
 
4058
end;
 
4059
 
 
4060
procedure TCustomCodeEditor.Indent;
 
4061
var S, PreS: string;
 
4062
    Shift: integer;
 
4063
begin
 
4064
  S:=GetLineText(CurPos.Y);
 
4065
  if CurPos.Y>0 then
 
4066
    PreS:=RTrim(GetLineText(CurPos.Y-1),not IsFlagSet(efUseTabCharacters))
 
4067
  else
 
4068
    PreS:='';
 
4069
  if CurPos.X>=length(PreS) then
 
4070
    Shift:=GetTabSize
 
4071
  else
 
4072
    begin
 
4073
      Shift:=1;
 
4074
      while (CurPos.X+Shift<length(PreS)) and (PreS[CurPos.X+Shift]<>' ') do
 
4075
       Inc(Shift);
 
4076
    end;
 
4077
  SetLineText(CurPos.Y,RExpand(copy(S,1,CurPos.X+1),CurPos.X+1)+CharStr(' ',Shift)+copy(S,CurPos.X+2,High(S)));
 
4078
  SetCurPtr(CurPos.X+Shift,CurPos.Y);
 
4079
  UpdateAttrs(CurPos.Y,attrAll);
 
4080
  DrawLines(CurPos.Y);
 
4081
  SetModified(true);
 
4082
end;
 
4083
 
 
4084
procedure TCustomCodeEditor.CharLeft;
 
4085
begin
 
4086
  if CurPos.X=0 then Exit;
 
4087
 
 
4088
  SetCurPtr(CurPos.X-1,CurPos.Y);
 
4089
end;
 
4090
 
 
4091
procedure TCustomCodeEditor.CharRight;
 
4092
begin
 
4093
  if CurPos.X>=MaxLineLength then
 
4094
    Exit;
 
4095
  SetCurPtr(CurPos.X+1,CurPos.Y);
 
4096
end;
 
4097
 
 
4098
procedure TCustomCodeEditor.WordLeft;
 
4099
var X, Y: sw_integer;
 
4100
    Line: string;
 
4101
    GotIt,FoundNonSeparator: boolean;
 
4102
begin
 
4103
  X:=CurPos.X;
 
4104
  Y:=CurPos.Y;
 
4105
  GotIt:=false;
 
4106
  FoundNonSeparator:=false;
 
4107
  while (Y>=0) do
 
4108
   begin
 
4109
     if Y=CurPos.Y then
 
4110
      begin
 
4111
   X:=length(GetDisplayText(Y));
 
4112
   if CurPos.X<X then
 
4113
     X:=CurPos.X; Dec(X);
 
4114
   if (X=-1) then
 
4115
     begin
 
4116
       Dec(Y);
 
4117
       if Y>=0 then
 
4118
        X:=length(GetDisplayText(Y));
 
4119
       Break;
 
4120
     end;
 
4121
      end
 
4122
     else
 
4123
      X:=length(GetDisplayText(Y))-1;
 
4124
     Line:=GetDisplayText(Y);
 
4125
     while (X>=0) and (GotIt=false) do
 
4126
      begin
 
4127
   if FoundNonSeparator then
 
4128
    begin
 
4129
      if IsWordSeparator(Line[X+1]) then
 
4130
       begin
 
4131
         Inc(X);
 
4132
         GotIt:=true;
 
4133
         Break;
 
4134
       end;
 
4135
    end
 
4136
   else
 
4137
    if not IsWordSeparator(Line[X+1]) then
 
4138
     FoundNonSeparator:=true;
 
4139
   Dec(X);
 
4140
   if (X=0) and (IsWordSeparator(Line[1])=false) then
 
4141
    begin
 
4142
      GotIt:=true;
 
4143
      Break;
 
4144
    end;
 
4145
      end;
 
4146
     if GotIt then
 
4147
      Break;
 
4148
     X:=0;
 
4149
     Dec(Y);
 
4150
     if Y>=0 then
 
4151
      begin
 
4152
   X:=length(GetDisplayText(Y));
 
4153
   Break;
 
4154
      end;
 
4155
   end;
 
4156
  if Y<0 then Y:=0; if X<0 then X:=0;
 
4157
  SetCurPtr(X,Y);
 
4158
end;
 
4159
 
 
4160
procedure TCustomCodeEditor.WordRight;
 
4161
var X, Y: sw_integer;
 
4162
    Line: string;
 
4163
    GotIt: boolean;
 
4164
begin
 
4165
  X:=CurPos.X; Y:=CurPos.Y; GotIt:=false;
 
4166
  while (Y<GetLineCount) do
 
4167
  begin
 
4168
    if Y=CurPos.Y then
 
4169
       begin
 
4170
    X:=CurPos.X; Inc(X);
 
4171
    if (X>length(GetDisplayText(Y))-1) then
 
4172
       begin Inc(Y); X:=0; end;
 
4173
       end else X:=0;
 
4174
    Line:=GetDisplayText(Y);
 
4175
    while (X<=length(Line)+1) and (GotIt=false) and (Line<>'') do
 
4176
    begin
 
4177
      if X=length(Line)+1 then begin GotIt:=true; Dec(X); Break end;
 
4178
      if IsWordSeparator(Line[X]) then
 
4179
    begin
 
4180
      while (Y<GetLineCount) and
 
4181
       (X<=length(Line)) and (IsWordSeparator(Line[X])) do
 
4182
       begin
 
4183
         Inc(X);
 
4184
         if X>=length(Line) then
 
4185
            begin GotIt:=true; Dec(X); Break; end;
 
4186
       end;
 
4187
      if (GotIt=false) and (X<length(Line)) then
 
4188
      begin
 
4189
        Dec(X);
 
4190
        GotIt:=true;
 
4191
        Break;
 
4192
      end;
 
4193
    end;
 
4194
      Inc(X);
 
4195
    end;
 
4196
    if GotIt then Break;
 
4197
    X:=0;
 
4198
    Inc(Y);
 
4199
    if (Y<GetLineCount) then
 
4200
    begin
 
4201
      Line:=GetDisplayText(Y);
 
4202
      if (Line<>'') and (IsWordSeparator(Line[1])=false) then Break;
 
4203
    end;
 
4204
  end;
 
4205
  if Y=GetLineCount then Y:=GetLineCount-1;
 
4206
  SetCurPtr(X,Y);
 
4207
end;
 
4208
 
 
4209
procedure TCustomCodeEditor.LineStart;
 
4210
begin
 
4211
  SetCurPtr(0,CurPos.Y);
 
4212
end;
 
4213
 
 
4214
procedure TCustomCodeEditor.LineEnd;
 
4215
var
 
4216
  s : string;
 
4217
  i : longint;
 
4218
begin
 
4219
  if CurPos.Y<GetLineCount then
 
4220
    begin
 
4221
      s:=GetDisplayText(CurPos.Y);
 
4222
      i:=length(s);
 
4223
      while (i>0) and (s[i]=' ') do
 
4224
        dec(i);
 
4225
      SetCurPtr(i,CurPos.Y);
 
4226
    end
 
4227
  else
 
4228
    SetCurPtr(0,CurPos.Y);
 
4229
end;
 
4230
 
 
4231
function TCustomCodeEditor.NextVisibleLine(StartLine: sw_integer; Down: boolean): sw_integer;
 
4232
var Count,NL: sw_integer;
 
4233
begin
 
4234
  if Down then
 
4235
    begin
 
4236
      Count:=GetLineCount;
 
4237
      NL:=StartLine;
 
4238
      while (NL<Count-1) and not IsLineVisible(NL) do
 
4239
        Inc(NL);
 
4240
      if NL>=Count then
 
4241
        NL:=-1;
 
4242
    end
 
4243
  else
 
4244
    begin
 
4245
      NL:=StartLine;
 
4246
      while (NL>0) and not IsLineVisible(NL) do
 
4247
        Dec(NL);
 
4248
    end;
 
4249
  if not IsLineVisible(NL) then
 
4250
    NL:=-1;
 
4251
  NextVisibleLine:=NL;
 
4252
end;
 
4253
 
 
4254
procedure TCustomCodeEditor.LineUp;
 
4255
var NL: sw_integer;
 
4256
begin
 
4257
  NL:=NextVisibleLine(CurPos.Y-1,false);
 
4258
  if NL<>-1 then
 
4259
    SetCurPtr(CurPos.X,NL);
 
4260
end;
 
4261
 
 
4262
procedure TCustomCodeEditor.LineDown;
 
4263
var NL: sw_integer;
 
4264
begin
 
4265
  NL:=NextVisibleLine(CurPos.Y+1,true);
 
4266
  if NL<>-1 then
 
4267
    SetCurPtr(CurPos.X,NL);
 
4268
end;
 
4269
 
 
4270
procedure TCustomCodeEditor.PageUp;
 
4271
var NL: sw_integer;
 
4272
begin
 
4273
  ScrollTo(Delta.X,Max(Delta.Y-Size.Y,0));
 
4274
  NL:=Max(CurPos.Y-(Size.Y),0);
 
4275
  if not IsLineVisible(NL) then
 
4276
    NL:=NextVisibleLine(NL,false);
 
4277
  if NL>=0 then
 
4278
    SetCurPtr(CurPos.X,Max(0,NL));
 
4279
end;
 
4280
 
 
4281
procedure TCustomCodeEditor.PageDown;
 
4282
var NL: sw_integer;
 
4283
begin
 
4284
  ScrollTo(Delta.X,Min(Delta.Y+Size.Y,GetLineCount-1));
 
4285
  NL:=Min(CurPos.Y+(Size.Y{-1}),GetLineCount-1);
 
4286
  if not IsLineVisible(NL) then
 
4287
    NL:=NextVisibleLine(NL,true);
 
4288
  if NL>=0 then
 
4289
    SetCurPtr(CurPos.X,Min(GetLineCount-1,NL));
 
4290
end;
 
4291
 
 
4292
procedure TCustomCodeEditor.TextStart;
 
4293
begin
 
4294
  SetCurPtr(0,0);
 
4295
end;
 
4296
 
 
4297
procedure TCustomCodeEditor.TextEnd;
 
4298
var s : string;
 
4299
    i : longint;
 
4300
begin
 
4301
  s:=GetDisplayText(GetLineCount-1);
 
4302
  i:=length(s);
 
4303
  while (i>0) and (s[i]=' ') do
 
4304
    dec(i);
 
4305
  SetCurPtr(i,GetLineCount-1);
 
4306
end;
 
4307
 
 
4308
procedure TCustomCodeEditor.WindowStart;
 
4309
begin
 
4310
  SetCurPtr(CurPos.X,Delta.Y);
 
4311
end;
 
4312
 
 
4313
procedure TCustomCodeEditor.WindowEnd;
 
4314
begin
 
4315
  SetCurPtr(CurPos.X,Delta.Y+Size.Y-1);
 
4316
end;
 
4317
 
 
4318
procedure TCustomCodeEditor.JumpSelStart;
 
4319
begin
 
4320
  if ValidBlock then
 
4321
    SetCurPtr(SelStart.X,SelStart.Y);
 
4322
end;
 
4323
 
 
4324
procedure TCustomCodeEditor.JumpSelEnd;
 
4325
begin
 
4326
  if ValidBlock then
 
4327
  SetCurPtr(SelEnd.X,SelEnd.Y);
 
4328
end;
 
4329
 
 
4330
procedure TCustomCodeEditor.JumpMark(MarkIdx: integer);
 
4331
begin
 
4332
  DontConsiderShiftState:=true;
 
4333
  if (MarkIdx<Low(Bookmarks)) or (MarkIdx>High(Bookmarks)) then
 
4334
    begin ErrorBox(FormatStrInt(msg_invalidmarkindex,MarkIdx),nil); Exit; end;
 
4335
 
 
4336
  with Bookmarks[MarkIdx] do
 
4337
  if Valid=false then
 
4338
    InformationBox(FormatStrInt(msg_marknotset,MarkIdx),nil)
 
4339
  else
 
4340
    SetCurPtr(Pos.X,Pos.Y);
 
4341
  DontConsiderShiftState:=false;
 
4342
end;
 
4343
 
 
4344
procedure TCustomCodeEditor.DefineMark(MarkIdx: integer);
 
4345
begin
 
4346
  if (MarkIdx<Low(Bookmarks)) or (MarkIdx>High(Bookmarks)) then
 
4347
    begin
 
4348
      ErrorBox(FormatStrInt(msg_invalidmarkindex,MarkIdx),nil);
 
4349
      Exit;
 
4350
    end;
 
4351
  with Bookmarks[MarkIdx] do
 
4352
   begin
 
4353
     Pos:=CurPos;
 
4354
     Valid:=true;
 
4355
   end;
 
4356
end;
 
4357
 
 
4358
procedure TCustomCodeEditor.JumpToLastCursorPos;
 
4359
begin
 
4360
  NotImplemented;
 
4361
end;
 
4362
 
 
4363
procedure TCustomCodeEditor.UpperCase;
 
4364
var StartP,EndP: TPoint;
 
4365
begin
 
4366
  if ValidBlock=false then Exit;
 
4367
  GetSelectionArea(StartP,EndP);
 
4368
  AddGroupedAction(eaUpperCase);
 
4369
  ChangeCaseArea(StartP,EndP,caToUpperCase);
 
4370
  CloseGroupedAction(eaUpperCase);
 
4371
end;
 
4372
 
 
4373
procedure TCustomCodeEditor.LowerCase;
 
4374
var StartP,EndP: TPoint;
 
4375
begin
 
4376
  if ValidBlock=false then Exit;
 
4377
  GetSelectionArea(StartP,EndP);
 
4378
  AddGroupedAction(eaLowerCase);
 
4379
  ChangeCaseArea(StartP,EndP,caToLowerCase);
 
4380
  CloseGroupedAction(eaLowerCase);
 
4381
end;
 
4382
 
 
4383
procedure TCustomCodeEditor.ToggleCase;
 
4384
var StartP,EndP: TPoint;
 
4385
begin
 
4386
  if ValidBlock=false then Exit;
 
4387
  GetSelectionArea(StartP,EndP);
 
4388
  AddGroupedAction(eaToggleCase);
 
4389
  ChangeCaseArea(StartP,EndP,caToggleCase);
 
4390
  CloseGroupedAction(eaToggleCase);
 
4391
end;
 
4392
 
 
4393
procedure TCustomCodeEditor.WordLowerCase;
 
4394
var StartP,EndP: TPoint;
 
4395
begin
 
4396
  if GetCurrentWordArea(StartP,EndP)=false then Exit;
 
4397
  AddGroupedAction(eaLowerCase);
 
4398
  ChangeCaseArea(StartP,EndP,caToLowerCase);
 
4399
  CloseGroupedAction(eaLowerCase);
 
4400
end;
 
4401
 
 
4402
procedure TCustomCodeEditor.WordUpperCase;
 
4403
var StartP,EndP: TPoint;
 
4404
begin
 
4405
  if GetCurrentWordArea(StartP,EndP)=false then Exit;
 
4406
  AddGroupedAction(eaUpperCase);
 
4407
  ChangeCaseArea(StartP,EndP,caToUpperCase);
 
4408
  CloseGroupedAction(eaUpperCase);
 
4409
end;
 
4410
 
 
4411
procedure TCustomCodeEditor.CreateFoldFromBlock;
 
4412
var StartY,EndY: sw_integer;
 
4413
begin
 
4414
  if not IsFlagSet(efFolds) then Exit;
 
4415
  if not ValidBlock then Exit;
 
4416
  StartY:=SelStart.Y; EndY:=SelEnd.Y;
 
4417
  if SelEnd.X=0 then Dec(EndY);
 
4418
  if CreateFold(StartY,EndY,false)=false then
 
4419
    ErrorBox(msg_foldboundsarenotvalid,nil);
 
4420
end;
 
4421
 
 
4422
procedure TCustomCodeEditor.ToggleFold;
 
4423
var F: PFold;
 
4424
begin
 
4425
  if not IsFlagSet(efFolds) then Exit;
 
4426
  F:=GetLineFold(CurPos.Y);
 
4427
  if Assigned(F) then
 
4428
    F^.Collapse(not F^.Collapsed_);
 
4429
end;
 
4430
 
 
4431
procedure TCustomCodeEditor.ExpandFold;
 
4432
var F: PFold;
 
4433
begin
 
4434
  if not IsFlagSet(efFolds) then Exit;
 
4435
  F:=GetLineFold(CurPos.Y);
 
4436
  if Assigned(F) then
 
4437
    F^.Collapse(false);
 
4438
end;
 
4439
 
 
4440
procedure TCustomCodeEditor.CollapseFold;
 
4441
var F: PFold;
 
4442
begin
 
4443
  if not IsFlagSet(efFolds) then Exit;
 
4444
  F:=GetLineFold(CurPos.Y);
 
4445
  if Assigned(F) then
 
4446
    F^.Collapse(true);
 
4447
end;
 
4448
 
 
4449
procedure TCustomCodeEditor.ChangeCaseArea(StartP,EndP: TPoint; CaseAction: TCaseAction);
 
4450
var Y,X: sw_integer;
 
4451
    X1,X2: sw_integer;
 
4452
    S: string;
 
4453
    C: char;
 
4454
    StartPos : TPoint;
 
4455
    HoldUndo : boolean;
 
4456
begin
 
4457
  Lock;
 
4458
  HoldUndo:=GetStoreUndo;
 
4459
  SetStoreUndo(false);
 
4460
  for Y:=StartP.Y to EndP.Y do
 
4461
  begin
 
4462
    S:=GetDisplayText(Y);
 
4463
    { Pierre, please implement undo here! Gabor }
 
4464
    X1:=0; X2:=length(S)-1;
 
4465
    if Y=StartP.Y then X1:=StartP.X;
 
4466
    if Y=EndP.Y then X2:=EndP.X;
 
4467
    SetStoreUndo(HoldUndo);
 
4468
    StartPos.X:=X1;
 
4469
    StartPos.Y:=Y;
 
4470
    { the only drawback is that we keep
 
4471
      the original text even if Toggle where
 
4472
      it is not really necessary PM }
 
4473
    Addaction(eaOverwriteText,StartPos,StartPos,Copy(S,X1+1,X2-X1+1),GetFlags);
 
4474
    SetStoreUndo(false);
 
4475
    for X:=X1 to X2 do
 
4476
    begin
 
4477
      C:=S[X+1];
 
4478
      case CaseAction of
 
4479
        caToLowerCase : C:=LowCase(C);
 
4480
        caToUpperCase : C:=UpCase(C);
 
4481
        caToggleCase  : if C in['a'..'z'] then
 
4482
                          C:=Upcase(C)
 
4483
                        else
 
4484
                          C:=LowCase(C);
 
4485
       end;
 
4486
      S[X+1]:=C;
 
4487
    end;
 
4488
    SetDisplayText(Y,S);
 
4489
  end;
 
4490
  UpdateAttrsRange(StartP.Y,EndP.Y,attrAll);
 
4491
  DrawLines(CurPos.Y);
 
4492
  SetModified(true);
 
4493
  Addaction(eaMoveCursor,StartPos,CurPos,'',GetFlags);
 
4494
  SetStoreUndo(HoldUndo);
 
4495
  UnLock;
 
4496
end;
 
4497
 
 
4498
procedure  TCustomCodeEditor.PushInfo(Const st : string);
 
4499
begin
 
4500
  { Dummies }
 
4501
end;
 
4502
 
 
4503
procedure  TCustomCodeEditor.PopInfo;
 
4504
begin
 
4505
  { Dummies }
 
4506
end;
 
4507
 
 
4508
 
 
4509
procedure TCustomCodeEditor.InsertOptions;
 
4510
begin
 
4511
  { Abstract }
 
4512
  NotImplemented;
 
4513
end;
 
4514
 
 
4515
function TCustomCodeEditor.GetLineFold(EditorLine: sw_integer): PFold;
 
4516
var L: PCustomLine;
 
4517
    LI: PEditorLineInfo;
 
4518
    F: PFold;
 
4519
begin
 
4520
  F:=nil;
 
4521
  if IsFlagSet(efFolds) then
 
4522
  if (0<=EditorLine) and (EditorLine<GetLineCount) then
 
4523
  begin
 
4524
    L:=GetLine(EditorLine);
 
4525
    if Assigned(L) then
 
4526
      LI:=L^.GetEditorInfo(@Self)
 
4527
    else
 
4528
      LI:=nil;
 
4529
    if Assigned(LI) then
 
4530
      F:=LI^.Fold;
 
4531
  end;
 
4532
  GetLineFold:=F;
 
4533
end;
 
4534
 
 
4535
function TCustomCodeEditor.IsLineVisible(EditorLine: sw_integer): boolean;
 
4536
var V: boolean;
 
4537
    F,PrevF: PFold;
 
4538
    FoldHeadline: boolean;
 
4539
begin
 
4540
  V:=true;
 
4541
  if IsFlagSet(efFolds) then
 
4542
    begin
 
4543
      F:=GetLineFold(EditorLine);
 
4544
      if Assigned(F) then
 
4545
      begin
 
4546
        PrevF:=GetLineFold(EditorLine-1);
 
4547
        FoldHeadline:=false;
 
4548
        if (PrevF<>F) and ((PrevF=nil) or (not PrevF^.IsParent(F))) then
 
4549
          FoldHeadline:=true;
 
4550
        if FoldHeadline then
 
4551
          begin
 
4552
            if Assigned(F^.ParentFold) and (F^.ParentFold^.IsCollapsed) then
 
4553
              V:=false;
 
4554
          end
 
4555
        else
 
4556
          if F^.IsCollapsed then
 
4557
            V:=false;
 
4558
      end;
 
4559
    end;
 
4560
  IsLineVisible:=V;
 
4561
end;
 
4562
 
 
4563
function TCustomCodeEditor.ViewToEditorLine(ViewLine: sw_integer): sw_integer;
 
4564
var I,Line,Count: sw_integer;
 
4565
begin
 
4566
  if not IsFlagSet(efFolds) then
 
4567
    Line:=ViewLine
 
4568
  else
 
4569
    begin
 
4570
      Count:=GetLineCount;
 
4571
      I:=0; Line:=-1;
 
4572
      while (Line<ViewLine) and (I<Count) do
 
4573
      begin
 
4574
        if IsLineVisible(I) then
 
4575
          Inc(Line);
 
4576
        Inc(I);
 
4577
      end;
 
4578
      if Line<>ViewLine then
 
4579
        Line:=-1
 
4580
      else
 
4581
        Line:=I-1;
 
4582
    end;
 
4583
  ViewToEditorLine:=Line;
 
4584
end;
 
4585
 
 
4586
function TCustomCodeEditor.EditorToViewLine(EditorLine: sw_integer): sw_integer;
 
4587
var I,Line: sw_integer;
 
4588
begin
 
4589
  if not IsFlagSet(efFolds) then
 
4590
    Line:=EditorLine
 
4591
  else
 
4592
    begin
 
4593
      Line:=-1;
 
4594
      for I:=0 to EditorLine do
 
4595
        if IsLineVisible(I) then
 
4596
          Inc(Line);
 
4597
    end;
 
4598
  EditorToViewLine:=Line;
 
4599
end;
 
4600
 
 
4601
procedure TCustomCodeEditor.ViewToEditorPoint(P: TPoint; var NP: TPoint);
 
4602
begin
 
4603
  NP.X:=P.X-GetReservedColCount;
 
4604
  NP.Y:=ViewToEditorLine(P.Y);
 
4605
end;
 
4606
 
 
4607
procedure TCustomCodeEditor.EditorToViewPoint(P: TPoint; var NP: TPoint);
 
4608
begin
 
4609
  NP.X:=P.X+GetReservedColCount;
 
4610
  NP.Y:=EditorToViewLine(P.Y);
 
4611
end;
 
4612
 
 
4613
procedure TCustomCodeEditor.FindMatchingDelimiter(ScanForward: boolean);
 
4614
const OpenSymbols  : string[6] = '[{(<''"';
 
4615
      CloseSymbols : string[6] = ']})>''"';
 
4616
var SymIdx: integer;
 
4617
    LineText,LineAttr: string;
 
4618
    CurChar: char;
 
4619
    X,Y: sw_integer;
 
4620
    LineCount: sw_integer;
 
4621
    JumpPos: TPoint;
 
4622
    BracketLevel: integer;
 
4623
begin
 
4624
  JumpPos.X:=-1; JumpPos.Y:=-1;
 
4625
  LineText:=GetDisplayText(CurPos.Y);
 
4626
  LineText:=copy(LineText,CurPos.X+1,1);
 
4627
  if LineText='' then Exit;
 
4628
  CurChar:=LineText[1];
 
4629
  Y:=CurPos.Y; X:=CurPos.X; LineCount:=0;
 
4630
  BracketLevel:=1;
 
4631
  if ScanForward then
 
4632
    begin
 
4633
      SymIdx:=Pos(CurChar,OpenSymbols);
 
4634
      if SymIdx=0 then Exit;
 
4635
      repeat
 
4636
        Inc(LineCount);
 
4637
        GetDisplayTextFormat(Y,LineText,LineAttr);
 
4638
        if LineCount<>1 then X:=-1;
 
4639
        repeat
 
4640
          Inc(X);
 
4641
          if X<length(LineText) then
 
4642
           if copy(LineAttr,X+1,1)<>chr(attrComment) then
 
4643
             if (LineText[X+1]=CloseSymbols[SymIdx]) and (BracketLevel=1) then
 
4644
               begin
 
4645
                 JumpPos.X:=X; JumpPos.Y:=Y;
 
4646
               end
 
4647
             else
 
4648
               if LineText[X+1]=OpenSymbols[SymIdx] then
 
4649
                 Inc(BracketLevel)
 
4650
               else
 
4651
               if LineText[X+1]=CloseSymbols[SymIdx] then
 
4652
                 if BracketLevel>1 then
 
4653
                   Dec(BracketLevel);
 
4654
        until (X>=length(LineText)) or (JumpPos.X<>-1);
 
4655
        Inc(Y);
 
4656
      until (Y>=GetLineCount) or (JumpPos.X<>-1);
 
4657
    end
 
4658
  else
 
4659
    begin
 
4660
      SymIdx:=Pos(CurChar,CloseSymbols);
 
4661
      if SymIdx=0 then Exit;
 
4662
      repeat
 
4663
        Inc(LineCount);
 
4664
        GetDisplayTextFormat(Y,LineText,LineAttr);
 
4665
        if LineCount<>1 then X:=length(LineText);
 
4666
        repeat
 
4667
          Dec(X);
 
4668
          if X>0 then
 
4669
           if copy(LineAttr,X+1,1)<>chr(attrComment) then
 
4670
             if (LineText[X+1]=OpenSymbols[SymIdx]) and (BracketLevel=1) then
 
4671
               begin
 
4672
                 JumpPos.X:=X; JumpPos.Y:=Y;
 
4673
               end
 
4674
             else
 
4675
               if LineText[X+1]=CloseSymbols[SymIdx] then
 
4676
                 Inc(BracketLevel)
 
4677
               else
 
4678
               if LineText[X+1]=OpenSymbols[SymIdx] then
 
4679
                 if BracketLevel>1 then
 
4680
                   Dec(BracketLevel);
 
4681
        until (X<0) or (JumpPos.X<>-1);
 
4682
        Dec(Y);
 
4683
      until (Y<0) or (JumpPos.X<>-1);
 
4684
    end;
 
4685
  if JumpPos.X<>-1 then
 
4686
  begin
 
4687
    SetCurPtr(JumpPos.X,JumpPos.Y);
 
4688
    TrackCursor(do_centre);
 
4689
  end;
 
4690
end;
 
4691
 
 
4692
function TCustomCodeEditor.InsertNewLine: Sw_integer;
 
4693
var i,Ind: Sw_integer;
 
4694
    S,IndentStr: string;
 
4695
procedure CalcIndent(LineOver: Sw_integer);
 
4696
begin
 
4697
  if (LineOver<0) or (LineOver>GetLineCount) or ((GetFlags and efNoIndent)<>0) then
 
4698
    Ind:=0 else
 
4699
  begin
 
4700
    repeat
 
4701
      IndentStr:=GetDisplayText(LineOver);
 
4702
      Dec(LineOver);
 
4703
    until (LineOver<0) or (IndentStr<>'');
 
4704
    Ind:=0;
 
4705
    while (Ind<length(IndentStr)) and (IndentStr[Ind+1]=' ') do
 
4706
     Inc(Ind);
 
4707
  end;
 
4708
  IndentStr:=CharStr(' ',Ind);
 
4709
end;
 
4710
var {SelBack: sw_integer;}
 
4711
    SCP: TPoint;
 
4712
    CI : sw_integer;
 
4713
    HoldUndo : Boolean;
 
4714
    L,NewL: PCustomLine;
 
4715
    EI,NewEI: PEditorLineInfo;
 
4716
begin
 
4717
  if IsReadOnly then begin InsertNewLine:=-1; Exit; end;
 
4718
  Lock;
 
4719
  SCP:=CurPos;
 
4720
  HoldUndo:=GetStoreUndo;
 
4721
  SetStoreUndo(false);
 
4722
  if CurPos.Y<GetLineCount then S:=GetLineText(CurPos.Y) else S:='';
 
4723
  if Overwrite=false then
 
4724
  begin
 
4725
    if CurPos.Y<GetLineCount then
 
4726
      begin
 
4727
        L:=GetLine(CurPos.Y);
 
4728
        if not assigned(L) then
 
4729
          EI:=nil
 
4730
        else
 
4731
          EI:=L^.GetEditorInfo(@Self);
 
4732
      end
 
4733
    else
 
4734
      EI:=nil;
 
4735
{    SelBack:=0;}
 
4736
    CI:=LinePosToCharIdx(CurPos.Y,CurPos.X);
 
4737
    if GetLineCount>0 then
 
4738
    begin
 
4739
      S:=GetLineText(CurPos.Y);
 
4740
{      SelBack:=length(S)-SelEnd.X;}
 
4741
      SetLineText(CurPos.Y,RTrim(S,not IsFlagSet(efUseTabCharacters)));
 
4742
    end;
 
4743
    SetLineText(CurPos.Y,copy(S,1,CI-1));
 
4744
    CalcIndent(CurPos.Y);
 
4745
    S:=copy(S,CI,High(S));
 
4746
    i:=1;
 
4747
    while (i<=length(s)) and (i<=length(IndentStr)) and (s[i]=' ') do
 
4748
      inc(i);
 
4749
    if i>1 then
 
4750
      Delete(IndentStr,1,i-1);
 
4751
    NewL:=InsertLine(CurPos.Y+1,IndentStr+S);
 
4752
    LimitsChanged;
 
4753
(*    if PointOfs(SelStart)<>PointOfs(SelEnd) then { !!! check it - it's buggy !!! }
 
4754
      begin SelEnd.Y:=CurPos.Y+1; SelEnd.X:=length(GetLineText(CurPos.Y+1))-SelBack; end;*)
 
4755
    UpdateAttrs(CurPos.Y,attrAll);
 
4756
    SetCurPtr(Ind,CurPos.Y+1);
 
4757
    NewEI:=NewL^.GetEditorInfo(@Self);
 
4758
    if Assigned(EI) and Assigned(NewEI) then
 
4759
    begin
 
4760
      NewEI^.SetFold(EI^.Fold);
 
4761
      if Assigned(EI^.Fold) then
 
4762
        if EI^.Fold^.IsCollapsed then
 
4763
          EI^.Fold^.Collapse(false);
 
4764
    end;
 
4765
     SetStoreUndo(HoldUndo);
 
4766
     { obsolete IndentStr is taken care of by the Flags PM }
 
4767
     Addaction(eaInsertLine,SCP,CurPos,CharStr(' ',i-1){IndentStr},GetFlags);
 
4768
     SetStoreUndo(false);
 
4769
     AdjustSelectionPos(SCP.X,SCP.Y,CurPos.X-SCP.X,CurPos.Y-SCP.Y);
 
4770
  end else
 
4771
  begin
 
4772
    CalcIndent(CurPos.Y);
 
4773
    if CurPos.Y=GetLineCount-1 then
 
4774
    begin
 
4775
      AddLine(IndentStr);
 
4776
      AdjustSelectionBefore(0,1);
 
4777
      LimitsChanged;
 
4778
      SetStoreUndo(HoldUndo);
 
4779
      UpdateAttrs(CurPos.Y,attrAll);
 
4780
      SetCurPtr(Ind,CurPos.Y+1);
 
4781
      { obsolete IndentStr is taken care of by the Flags PM }
 
4782
      Addaction(eaInsertLine,SCP,CurPos,''{IndentStr},GetFlags);
 
4783
      SetStoreUndo(false);
 
4784
    end
 
4785
    else
 
4786
    begin
 
4787
      UpdateAttrs(CurPos.Y,attrAll);
 
4788
      SetStoreUndo(HoldUndo);
 
4789
      SetCurPtr(Ind,CurPos.Y+1);
 
4790
      AddAction(eaMoveCursor,SCP,CurPos,'',GetFlags);
 
4791
      SetStoreUndo(false);
 
4792
    end;
 
4793
  end;
 
4794
  DrawLines(CurPos.Y);
 
4795
  SetStoreUndo(HoldUndo);
 
4796
  SetModified(true);
 
4797
  Unlock;
 
4798
end;
 
4799
 
 
4800
procedure TCustomCodeEditor.BreakLine;
 
4801
begin
 
4802
  NotImplemented; Exit;
 
4803
end;
 
4804
 
 
4805
procedure TCustomCodeEditor.BackSpace;
 
4806
var S,PreS: string;
 
4807
    OI,CI,CP,Y,TX: Sw_integer;
 
4808
    SCP,SC1 : TPoint;
 
4809
    HoldUndo : Boolean;
 
4810
begin
 
4811
  if IsReadOnly then Exit;
 
4812
  Lock;
 
4813
  SCP:=CurPos;
 
4814
  HoldUndo:=GetStoreUndo;
 
4815
  SetStoreUndo(false);
 
4816
  if CurPos.X=0 then
 
4817
   begin
 
4818
     if CurPos.Y>0 then
 
4819
      begin
 
4820
        CI:=Length(GetDisplayText(CurPos.Y-1));
 
4821
        S:=GetLineText(CurPos.Y-1);
 
4822
        SetLineText(CurPos.Y-1,S+GetLineText(CurPos.Y));
 
4823
        SC1.X:=Length(S);SC1.Y:=CurPOS.Y-1;
 
4824
        SetStoreUndo(HoldUndo);
 
4825
        AddAction(eaDeleteLine,SCP,SC1,GetLineText(CurPos.Y),GetFlags);
 
4826
        SetStoreUndo(false);
 
4827
        DeleteLine(CurPos.Y);
 
4828
        LimitsChanged;
 
4829
        SetCurPtr(CI,CurPos.Y-1);
 
4830
        AdjustSelectionPos(Ci,CurPos.Y,CurPos.X-SCP.X,CurPos.Y-SCP.Y);
 
4831
      end;
 
4832
   end
 
4833
  else
 
4834
   begin
 
4835
     CP:=CurPos.X-1;
 
4836
     S:=GetLineText(CurPos.Y);
 
4837
     CI:=LinePosToCharIdx(CurPos.Y,CP);
 
4838
     if (s[ci]=TAB) and (CharIdxToLinePos(Curpos.y,ci)=cp) then
 
4839
      CP:=CharIdxToLinePos(CurPos.Y,CI-1)+1;
 
4840
     if IsFlagSet(efBackspaceUnindents) then
 
4841
      begin
 
4842
        S:=GetDisplayText(CurPos.Y);
 
4843
        if Trim(copy(S,1,CP+1))='' then
 
4844
         begin
 
4845
           Y:=CurPos.Y;
 
4846
           while (Y>0) do
 
4847
            begin
 
4848
              Dec(Y);
 
4849
              PreS:=GetDisplayText(Y);
 
4850
              if Trim(copy(PreS,1,CP+1))<>'' then Break;
 
4851
            end;
 
4852
           if Y<0 then PreS:='';
 
4853
           TX:=0;
 
4854
           while (TX<length(PreS)) and (PreS[TX+1]=' ') do
 
4855
            Inc(TX);
 
4856
           if TX<CP then CP:=TX;
 
4857
         end;
 
4858
      end;
 
4859
     S:=GetLineText(CurPos.Y);
 
4860
     OI:=LinePosToCharIdx(CurPos.Y,CurPos.X);
 
4861
     CI:=LinePosToCharIdx(CurPos.Y,CP);
 
4862
     SetLineText(CurPos.Y,copy(S,1,CI-1)+copy(S,OI,High(S)));
 
4863
     SetCurPtr(CP,CurPos.Y);
 
4864
     SetStoreUndo(HoldUndo);
 
4865
     Addaction(eaDeleteText,SCP,CurPos,Copy(S,CI,OI-CI),GetFlags);
 
4866
     SetStoreUndo(false);
 
4867
     AdjustSelectionPos(SCP.X-1,SCP.Y,CurPos.X-SCP.X,CurPos.Y-SCP.Y);
 
4868
   end;
 
4869
  UpdateAttrs(CurPos.Y,attrAll);
 
4870
  DrawLines(CurPos.Y);
 
4871
  SetStoreUndo(HoldUndo);
 
4872
  SetModified(true);
 
4873
  Unlock;
 
4874
end;
 
4875
 
 
4876
procedure TCustomCodeEditor.DelChar;
 
4877
var S: string;
 
4878
    SDX,SDY,CI : sw_integer;
 
4879
    HoldUndo : boolean;
 
4880
    SCP : TPoint;
 
4881
begin
 
4882
  if IsReadOnly then Exit;
 
4883
  Lock;
 
4884
  HoldUndo:=GetStoreUndo;
 
4885
  SetStoreUndo(false);
 
4886
  S:=GetLineText(CurPos.Y);
 
4887
  CI:=LinePosToCharIdx(CurPos.Y,CurPos.X);
 
4888
  if (CI>length(S)) or (S='') then
 
4889
   begin
 
4890
     if CurPos.Y<GetLineCount-1 then
 
4891
      begin
 
4892
        SetLineText(CurPos.Y,S+CharStr(' ',CurPOS.X-Length(S))+GetLineText(CurPos.Y+1));
 
4893
        SDX:=CurPos.X;
 
4894
        SetStoreUndo(HoldUndo);
 
4895
        SCP.X:=0;SCP.Y:=CurPos.Y+1;
 
4896
        AddGroupedAction(eaDelChar);
 
4897
        AddAction(eaMoveCursor,CurPos,SCP,'',GetFlags);
 
4898
        S:=GetLineText(CurPos.Y+1);
 
4899
        AddAction(eaDeleteLine,SCP,CurPos,S,GetFlags);
 
4900
        CloseGroupedAction(eaDelChar);
 
4901
        SetStoreUndo(false);
 
4902
        DeleteLine(CurPos.Y+1);
 
4903
        LimitsChanged;
 
4904
        SDY:=-1;
 
4905
        SetCurPtr(CurPos.X,CurPos.Y);
 
4906
        UpdateAttrs(CurPos.Y,attrAll);
 
4907
        AdjustSelectionPos(CurPos.X,CurPos.Y,SDX,SDY);
 
4908
      end;
 
4909
   end
 
4910
  else
 
4911
   begin
 
4912
     SCP:=CurPos;
 
4913
     { Problem if S[CurPos.X+1]=TAB !! PM }
 
4914
     if S[CI]=TAB then
 
4915
       begin
 
4916
         { we want to remove the tab if we are at the first place
 
4917
           of the tab, but the following test was true for the last position
 
4918
           in tab
 
4919
         if CharIdxToLinePos(Curpos.y,ci)=Curpos.x then }
 
4920
         if CharIdxToLinePos(Curpos.y,ci-1)=Curpos.x-1 then
 
4921
            Delete(S,Ci,1)
 
4922
         else
 
4923
          S:=Copy(S,1,CI-1)+CharStr(' ',GetTabSize-1)+Copy(S,CI+1,High(S));
 
4924
         SetStoreUndo(HoldUndo);
 
4925
         Addaction(eaDeleteText,CurPos,CurPos,#9,GetFlags);
 
4926
         SDX:=-1;
 
4927
         SetStoreUndo(false);
 
4928
       end
 
4929
     else
 
4930
       begin
 
4931
         SetStoreUndo(HoldUndo);
 
4932
         Addaction(eaDeleteText,CurPos,CurPos,S[CI],GetFlags);
 
4933
         SetStoreUndo(false);
 
4934
         SDX:=-1;
 
4935
         Delete(S,CI,1);
 
4936
       end;
 
4937
     SetLineText(CurPos.Y,S);
 
4938
     SDY:=0;
 
4939
     SetCurPtr(CurPos.X,CurPos.Y);
 
4940
     UpdateAttrs(CurPos.Y,attrAll);
 
4941
     AdjustSelectionPos(SCP.X,SCP.Y,SDX,SDY);
 
4942
   end;
 
4943
  DrawLines(CurPos.Y);
 
4944
  SetStoreUndo(HoldUndo);
 
4945
  SetModified(true);
 
4946
  Unlock;
 
4947
end;
 
4948
 
 
4949
procedure TCustomCodeEditor.DelWord;
 
4950
var
 
4951
  SP,EP : TPoint;
 
4952
  SelSize : sw_integer;
 
4953
begin
 
4954
  if IsReadOnly then Exit;
 
4955
  Lock;
 
4956
  SP:=SelStart;
 
4957
  EP:=SelEnd;
 
4958
  SetSelection(SelStart,SelStart);
 
4959
  SelectWord;
 
4960
  SelSize:=SelEnd.X-SelStart.X;
 
4961
  DelSelect;
 
4962
  SetSelection(SP,EP);
 
4963
  AdjustSelectionPos(CurPos.X,CurPos.Y,-SelSize,0);
 
4964
  if SelSize>0 then
 
4965
    SetModified(true);
 
4966
  Unlock;
 
4967
end;
 
4968
 
 
4969
procedure TCustomCodeEditor.DelToEndOfWord;
 
4970
var
 
4971
  SP,EP : TPoint;
 
4972
  S : String;
 
4973
  SelSize : sw_integer;
 
4974
begin
 
4975
  if IsReadOnly then Exit;
 
4976
  Lock;
 
4977
  SP:=SelStart;
 
4978
  EP:=SelEnd;
 
4979
  SetSelection(SelStart,SelStart);
 
4980
  SelectWord;
 
4981
  S:=GetDisplayText(CurPos.Y);
 
4982
  if ((SelStart.X=SelEnd.X) and (SelStart.Y=SelEnd.Y)) then
 
4983
    begin
 
4984
      if (Length(S) <= CurPos.X) then
 
4985
        begin
 
4986
          SetSelection(SP,EP);
 
4987
          DelChar;
 
4988
          Unlock;
 
4989
          exit;
 
4990
        end
 
4991
      else
 
4992
        begin
 
4993
          SelEnd.X:=CurPos.X+1;
 
4994
          SelEnd.Y:=CurPos.Y;
 
4995
        end;
 
4996
    end;
 
4997
  while (length(S)>= SelEnd.X+1) and
 
4998
        ((S[SelEnd.X+1]=' ') or (S[SelEnd.X+1]=TAB))  do
 
4999
    inc(SelEnd.X);
 
5000
  SetSelection(CurPos,SelEnd);
 
5001
  SelSize:=SelEnd.X-SelStart.X;
 
5002
  DelSelect;
 
5003
  SetSelection(SP,EP);
 
5004
  AdjustSelectionPos(CurPos.X,CurPos.Y,-SelSize,0);
 
5005
  if SelSize>0 then
 
5006
    SetModified(true);
 
5007
  Unlock;
 
5008
end;
 
5009
 
 
5010
procedure TCustomCodeEditor.DelStart;
 
5011
var S: string;
 
5012
begin
 
5013
  if IsReadOnly then Exit;
 
5014
  Lock;
 
5015
  S:=GetLineText(CurPos.Y);
 
5016
  if (S<>'') and (CurPos.X<>0) then
 
5017
  begin
 
5018
    SetLineText(CurPos.Y,copy(S,LinePosToCharIdx(CurPos.Y,CurPos.X),High(S)));
 
5019
    SetCurPtr(0,CurPos.Y);
 
5020
    UpdateAttrs(CurPos.Y,attrAll);
 
5021
    DrawLines(CurPos.Y);
 
5022
    SetModified(true);
 
5023
  end;
 
5024
  Unlock;
 
5025
end;
 
5026
 
 
5027
procedure TCustomCodeEditor.DelEnd;
 
5028
var S: string;
 
5029
begin
 
5030
  if IsReadOnly then Exit;
 
5031
  Lock;
 
5032
  S:=GetLineText(CurPos.Y);
 
5033
  if (S<>'') and (CurPos.X<>length(S)) then
 
5034
  begin
 
5035
    SetLineText(CurPos.Y,copy(S,1,LinePosToCharIdx(CurPos.Y,CurPos.X)-1));
 
5036
    SetCurPtr(CurPos.X,CurPos.Y);
 
5037
    UpdateAttrs(CurPos.Y,attrAll);
 
5038
    DrawLines(CurPos.Y);
 
5039
    SetModified(true);
 
5040
  end;
 
5041
  Unlock;
 
5042
end;
 
5043
 
 
5044
procedure TCustomCodeEditor.DelLine;
 
5045
var
 
5046
  HoldUndo : boolean;
 
5047
  SP : TPoint;
 
5048
  S : String;
 
5049
begin
 
5050
  if IsReadOnly then Exit;
 
5051
  Lock;
 
5052
  if GetLineCount>0 then
 
5053
  begin
 
5054
    SP:=CurPos;
 
5055
    S:=GetLineText(CurPos.Y);
 
5056
    HoldUndo:=GetStoreUndo;
 
5057
    SetStoreUndo(false);
 
5058
    DeleteLine(CurPos.Y);
 
5059
    LimitsChanged;
 
5060
    AdjustSelectionBefore(0,-1);
 
5061
    SetCurPtr(0,CurPos.Y);
 
5062
    UpdateAttrs(Max(0,CurPos.Y-1),attrAll);
 
5063
    DrawLines(CurPos.Y);
 
5064
    SetStoreUndo(HoldUndo);
 
5065
    AddAction(eaDeleteLine,SP,CurPos,S,GetFlags);
 
5066
    SetModified(true);
 
5067
  end;
 
5068
  Unlock;
 
5069
end;
 
5070
 
 
5071
procedure TCustomCodeEditor.InsMode;
 
5072
begin
 
5073
  SetInsertMode(Overwrite);
 
5074
end;
 
5075
 
 
5076
function TCustomCodeEditor.GetCurrentWordArea(var StartP,EndP: TPoint): boolean;
 
5077
const WordChars = ['A'..'Z','a'..'z','0'..'9','_'];
 
5078
var P : TPoint;
 
5079
    S : String;
 
5080
    StartPos,EndPos : byte;
 
5081
    OK: boolean;
 
5082
begin
 
5083
  P:=CurPos;
 
5084
  S:=GetLineText(P.Y);
 
5085
  StartPos:=P.X+1;
 
5086
  EndPos:=StartPos;
 
5087
  OK:=(S[StartPos] in WordChars);
 
5088
  if OK then
 
5089
    begin
 
5090
       While (StartPos>0) and (S[StartPos-1] in WordChars) do
 
5091
         Dec(StartPos);
 
5092
       While (EndPos<Length(S)) and (S[EndPos+1] in WordChars) do
 
5093
         Inc(EndPos);
 
5094
       StartP.X:=StartPos-1; StartP.Y:=CurPos.Y;
 
5095
       EndP.X:=EndPos-1; EndP.Y:=CurPos.Y;
 
5096
    end;
 
5097
  GetCurrentWordArea:=OK;
 
5098
end;
 
5099
 
 
5100
function  TCustomCodeEditor.GetCurrentWord : string;
 
5101
var S: string;
 
5102
    StartP,EndP: TPoint;
 
5103
begin
 
5104
  if GetCurrentWordArea(StartP,EndP)=false then
 
5105
    S:=''
 
5106
  else
 
5107
    begin
 
5108
      S:=GetLineText(StartP.Y);
 
5109
      S:=copy(S,StartP.X+1,EndP.X-StartP.X+1);
 
5110
    end;
 
5111
  GetCurrentWord:=S;
 
5112
end;
 
5113
 
 
5114
procedure TCustomCodeEditor.StartSelect;
 
5115
var P1,P2: TPoint;
 
5116
begin
 
5117
  if ValidBlock=false then
 
5118
    begin
 
5119
{      SetSelection(SelStart,Limit);}
 
5120
      P1:=CurPos; P1.X:=0; P2:=CurPos; {P2.X:=length(GetLineText(P2.Y))+1;}
 
5121
      SetSelection(P1,P2);
 
5122
    end
 
5123
  else
 
5124
    SetSelection(CurPos,SelEnd);
 
5125
  if PointOfs(SelEnd)<PointOfs(SelStart) then
 
5126
     SetSelection(SelStart,SelStart);
 
5127
  CheckSels;
 
5128
  DrawView;
 
5129
end;
 
5130
 
 
5131
procedure TCustomCodeEditor.EndSelect;
 
5132
var P: TPoint;
 
5133
    LS: sw_integer;
 
5134
begin
 
5135
  P:=CurPos;
 
5136
{  P.X:=Min(SelEnd.X,length(GetLineText(SelEnd.Y)));}
 
5137
  LS:=length(GetLineText(SelEnd.Y));
 
5138
  if LS<P.X then P.X:=LS;
 
5139
  CheckSels;
 
5140
  SetSelection(SelStart,P);
 
5141
  DrawView;
 
5142
end;
 
5143
 
 
5144
procedure TCustomCodeEditor.DelSelect;
 
5145
var LineDelta, LineCount, CurLine: Sw_integer;
 
5146
    StartX,EndX,LastX: Sw_integer;
 
5147
    S: string;
 
5148
    SPos : TPoint;
 
5149
begin
 
5150
  if IsReadOnly or (ValidBlock=false) then Exit;
 
5151
 
 
5152
  Lock;
 
5153
  AddGroupedAction(eaDelBlock);
 
5154
  LineCount:=(SelEnd.Y-SelStart.Y)+1;
 
5155
  LineDelta:=0; LastX:=CurPos.X;
 
5156
  CurLine:=SelStart.Y;
 
5157
  { single line : easy }
 
5158
  if LineCount=1 then
 
5159
    begin
 
5160
      S:=GetDisplayText(CurLine);
 
5161
      StartX:=SelStart.X;
 
5162
      EndX:=SelEnd.X;
 
5163
      SetDisplayText(CurLine,RExpand(copy(S,1,StartX),StartX)
 
5164
        +copy(S,EndX+1,High(S)));
 
5165
      if GetStoreUndo then
 
5166
        begin
 
5167
          SPos.X:=StartX;
 
5168
          SPos.Y:=CurLine;
 
5169
          AddAction(eaDeleteText,SPos,SPos,Copy(S,StartX+1,EndX-StartX),GetFlags);
 
5170
        end;
 
5171
      Inc(CurLine);
 
5172
      LastX:=SelStart.X;
 
5173
    end
 
5174
  { several lines : a bit less easy }
 
5175
  else
 
5176
    begin
 
5177
      S:=GetDisplayText(CurLine);
 
5178
      StartX:=SelStart.X;
 
5179
      EndX:=SelEnd.X;
 
5180
      SetDisplayText(CurLine,RExpand(copy(S,1,StartX),StartX)
 
5181
        +copy(GetDisplayText(CurLine+LineCount-1),EndX+1,High(S)));
 
5182
      if GetStoreUndo then
 
5183
        begin
 
5184
          SPos.X:=StartX;
 
5185
          SPos.Y:=CurLine;
 
5186
          AddAction(eaDeleteText,SPos,SPos,Copy(S,StartX+1,High(S)),GetFlags);
 
5187
          S:=GetDisplayText(CurLine+LineCount-1);
 
5188
        end;
 
5189
      Inc(CurLine);
 
5190
      Inc(LineDelta);
 
5191
      LastX:=SelStart.X;
 
5192
      while (LineDelta<LineCount) do
 
5193
        begin
 
5194
        { delete the complete line }
 
5195
          DeleteLine(CurLine);
 
5196
          Inc(LineDelta);
 
5197
        end;
 
5198
      if GetStoreUndo then
 
5199
        begin
 
5200
          AddAction(eaInsertText,SPos,SPos,Copy(S,EndX+1,High(S)),GetFlags);
 
5201
        end;
 
5202
    end;
 
5203
  HideSelect;
 
5204
  SetCurPtr(LastX,CurLine-1);
 
5205
  UpdateAttrs(CurPos.Y,attrAll);
 
5206
  DrawLines(CurPos.Y);
 
5207
  SetModified(true);
 
5208
  CloseGroupedAction(eaDelBlock);
 
5209
  UnLock;
 
5210
end;
 
5211
 
 
5212
procedure TCustomCodeEditor.HideSelect;
 
5213
begin
 
5214
  SetSelection(CurPos,CurPos);
 
5215
  DrawLines(Delta.Y);
 
5216
end;
 
5217
 
 
5218
procedure TCustomCodeEditor.CopyBlock;
 
5219
var Temp: PCodeEditor;
 
5220
    R: TRect;
 
5221
begin
 
5222
  if IsReadOnly or (ValidBlock=false) then Exit;
 
5223
 
 
5224
  Lock;
 
5225
  GetExtent(R);
 
5226
  AddGroupedAction(eaCopyBlock);
 
5227
  New(Temp, Init(R, nil, nil, nil,nil));
 
5228
  Temp^.InsertFrom(@Self);
 
5229
(*  Temp^.SelectAll(true);
 
5230
  { this selects one line too much because
 
5231
    we have a empty line at creation to avoid
 
5232
    negative line problems so we need to decrease SelEnd.Y }
 
5233
  Dec(Temp^.SelEnd.Y);*)
 
5234
 
 
5235
 
 
5236
  InsertFrom(Temp);
 
5237
  Dispose(Temp, Done);
 
5238
  CloseGroupedAction(eaCopyBlock);
 
5239
  UnLock;
 
5240
end;
 
5241
 
 
5242
procedure TCustomCodeEditor.MoveBlock;
 
5243
var Temp: PCodeEditor;
 
5244
    R: TRect;
 
5245
    OldPos: TPoint;
 
5246
begin
 
5247
  if IsReadOnly then Exit;
 
5248
  if (SelStart.X=SelEnd.X) and (SelStart.Y=SelEnd.Y) then Exit;
 
5249
  Lock;
 
5250
  AddGroupedAction(eaMoveBlock);
 
5251
  GetExtent(R);
 
5252
  New(Temp, Init(R, nil, nil, nil,nil));
 
5253
  Temp^.InsertFrom(@Self);
 
5254
  OldPos:=CurPos;
 
5255
  if CurPos.Y>SelStart.Y then
 
5256
    Dec(OldPos.Y,Temp^.GetLineCount-1);
 
5257
  DelSelect;
 
5258
  SetCurPtr(OldPos.X,OldPos.Y);
 
5259
  InsertFrom(Temp);
 
5260
  Dispose(Temp, Done);
 
5261
  CloseGroupedAction(eaMoveBlock);
 
5262
  UnLock;
 
5263
end;
 
5264
 
 
5265
procedure TCustomCodeEditor.IndentBlock;
 
5266
var
 
5267
  ey,i{,indlen} : Sw_integer;
 
5268
  S,Ind : String;
 
5269
  Pos : Tpoint;
 
5270
begin
 
5271
  if IsReadOnly then Exit;
 
5272
  if (SelStart.X=SelEnd.X) and (SelStart.Y=SelEnd.Y) then Exit;
 
5273
  Lock;
 
5274
  AddGroupedAction(eaIndentBlock);
 
5275
  ey:=selend.y;
 
5276
  if selend.x=0 then
 
5277
   dec(ey);
 
5278
  S:='';
 
5279
  { If AutoIndent try to align first line to
 
5280
    last line before selection }
 
5281
  { DISABLED created problems PM
 
5282
  if IsFlagSet(efAutoIndent) and (SelStart.Y>0) then
 
5283
    begin
 
5284
      i:=SelStart.Y-1;
 
5285
      while (S='') and (i>=0) do
 
5286
        begin
 
5287
          S:=GetDisplayText(i);
 
5288
          dec(i);
 
5289
        end;
 
5290
      if (S='') or (S[1]<>' ') then
 
5291
        Ind:=' '
 
5292
      else
 
5293
        begin
 
5294
          i:=1;
 
5295
          while (i<=Length(S)) and (S[i]=' ') do
 
5296
           inc(i);
 
5297
          indlen:=i;
 
5298
          S:=GetDisplayText(SelStart.Y);
 
5299
          i:=1;
 
5300
          while (i<=Length(S)) and (S[i]=' ') do
 
5301
            inc(i);
 
5302
          indlen:=indlen-i;
 
5303
          if indlen<=0 then
 
5304
            indlen:=1;
 
5305
          Ind:=CharStr(' ',indlen);
 
5306
        end;
 
5307
    end
 
5308
  else
 
5309
   Ind:=' ';}
 
5310
  Ind:=CharStr(' ',GetIndentSize);
 
5311
  for i:=selstart.y to ey do
 
5312
   begin
 
5313
     S:=GetLineText(i);
 
5314
     SetLineText(i,Ind+S);
 
5315
     Pos.X:=0;Pos.Y:=i;
 
5316
     AddAction(eaInsertText,Pos,Pos,Ind,GetFlags);
 
5317
   end;
 
5318
  SetCurPtr(CurPos.X,CurPos.Y);
 
5319
  { must be added manually here PM }
 
5320
  AddAction(eaMoveCursor,Pos,CurPos,'',GetFlags);
 
5321
  UpdateAttrsRange(SelStart.Y,SelEnd.Y,attrAll);
 
5322
  DrawLines(CurPos.Y);
 
5323
  SetModified(true);
 
5324
  CloseGroupedAction(eaIndentBlock);
 
5325
  UnLock;
 
5326
end;
 
5327
 
 
5328
procedure TCustomCodeEditor.UnindentBlock;
 
5329
var
 
5330
  ey,i,j,k,indlen : Sw_integer;
 
5331
  S : String;
 
5332
  Pos : TPoint;
 
5333
begin
 
5334
  if IsReadOnly then Exit;
 
5335
  if (SelStart.X=SelEnd.X) and (SelStart.Y=SelEnd.Y) then Exit;
 
5336
  Lock;
 
5337
  AddGroupedAction(eaUnindentBlock);
 
5338
  ey:=selend.y;
 
5339
  if selend.x=0 then
 
5340
   dec(ey);
 
5341
  { If AutoIndent try to align first line to
 
5342
    last line before selection }
 
5343
  { Disabled created problems
 
5344
  if IsFlagSet(efAutoIndent) and (SelStart.Y>0) then
 
5345
    begin
 
5346
      S:=GetDisplayText(SelStart.Y);
 
5347
      i:=1;
 
5348
      while (i<=Length(S)) and (S[i]=' ') do
 
5349
        inc(i);
 
5350
      indlen:=i-1;
 
5351
      i:=SelStart.Y-1;
 
5352
      S:='';
 
5353
      while (S='') and (i>=0) do
 
5354
        begin
 
5355
          if Trim(Copy(GetDisplayText(i),1,indlen))='' then
 
5356
            S:=''
 
5357
          else
 
5358
            S:=GetDisplayText(i);
 
5359
          dec(i);
 
5360
        end;
 
5361
      if (S='') then
 
5362
        Indlen:=1
 
5363
      else
 
5364
        begin
 
5365
          i:=1;
 
5366
          while (i<=Length(S)) and (S[i]=' ') do
 
5367
           inc(i);
 
5368
          indlen:=indlen-i+1;
 
5369
          if indlen<=0 then
 
5370
            indlen:=1;
 
5371
        end;
 
5372
    end
 
5373
  else
 
5374
   Indlen:=1;}
 
5375
  Indlen:=GetIndentSize;
 
5376
  for i:=selstart.y to ey do
 
5377
   begin
 
5378
     S:=GetLineText(i);
 
5379
     k:=0;
 
5380
     for j:=1 to indlen do
 
5381
       if (length(s)>1) and (S[1]=' ') then
 
5382
         begin
 
5383
           Delete(s,1,1);
 
5384
           inc(k);
 
5385
         end;
 
5386
     SetLineText(i,S);
 
5387
     if k>0 then
 
5388
       begin
 
5389
         Pos.Y:=i;
 
5390
         Pos.X:=0;
 
5391
         AddAction(eaDeleteText,Pos,Pos,CharStr(' ',k),GetFlags);
 
5392
       end;
 
5393
   end;
 
5394
  SetCurPtr(CurPos.X,CurPos.Y);
 
5395
  UpdateAttrsRange(SelStart.Y,SelEnd.Y,attrAll);
 
5396
  DrawLines(CurPos.Y);
 
5397
  SetModified(true);
 
5398
  CloseGroupedAction(eaUnindentBlock);
 
5399
  UnLock;
 
5400
end;
 
5401
 
 
5402
procedure TCustomCodeEditor.SelectWord;
 
5403
const WordChars = ['A'..'Z','a'..'z','0'..'9','_'];
 
5404
var S : String;
 
5405
    StartPos,EndPos : byte;
 
5406
    A,B: TPoint;
 
5407
begin
 
5408
  A:=CurPos;
 
5409
  B:=CurPos;
 
5410
  S:=GetDisplayText(A.Y);
 
5411
  StartPos:=A.X+1;
 
5412
  EndPos:=StartPos;
 
5413
  if not (S[StartPos] in WordChars) then
 
5414
    exit
 
5415
  else
 
5416
    begin
 
5417
       While (StartPos>0) and (S[StartPos-1] in WordChars) do
 
5418
         Dec(StartPos);
 
5419
       While (EndPos<Length(S)) and (S[EndPos+1] in WordChars) do
 
5420
         Inc(EndPos);
 
5421
       A.X:=StartPos-1;
 
5422
       B.X:=EndPos;
 
5423
       SetSelection(A,B);
 
5424
    end;
 
5425
end;
 
5426
 
 
5427
procedure TCustomCodeEditor.SelectLine;
 
5428
var A,B: TPoint;
 
5429
begin
 
5430
  if CurPos.Y<GetLineCount then
 
5431
    begin
 
5432
      A.Y:=CurPos.Y; A.X:=0;
 
5433
      B.Y:=CurPos.Y+1; B.X:=0;
 
5434
      SetSelection(A,B);
 
5435
    end;
 
5436
end;
 
5437
 
 
5438
procedure TCustomCodeEditor.WriteBlock;
 
5439
var FileName: string;
 
5440
    S: PBufStream;
 
5441
begin
 
5442
  if ValidBlock=false then Exit;
 
5443
 
 
5444
  FileName:='';
 
5445
  if EditorDialog(edWriteBlock, @FileName) <> cmCancel then
 
5446
  begin
 
5447
    FileName := FExpand(FileName);
 
5448
 
 
5449
    New(S, Init(FileName, stCreate, 4096));
 
5450
    if (S=nil) or (S^.Status<>stOK) then
 
5451
      EditorDialog(edCreateError,@FileName)
 
5452
    else
 
5453
      if SaveAreaToStream(S,SelStart,SelEnd)=false then
 
5454
        EditorDialog(edWriteError,@FileName);
 
5455
    if Assigned(S) then Dispose(S, Done);
 
5456
  end;
 
5457
end;
 
5458
 
 
5459
procedure TCustomCodeEditor.ReadBlock;
 
5460
var FileName: string;
 
5461
    S: PFastBufStream;
 
5462
    E: PCodeEditor;
 
5463
    R: TRect;
 
5464
begin
 
5465
  if IsReadOnly then Exit;
 
5466
  FileName:='';
 
5467
  if EditorDialog(edReadBlock, @FileName) <> cmCancel then
 
5468
  begin
 
5469
    FileName := FExpand(FileName);
 
5470
 
 
5471
    New(S, Init(FileName, stOpenRead, 4096));
 
5472
    if (S=nil) or (S^.Status<>stOK) then
 
5473
      EditorDialog(edReadError,@FileName)
 
5474
    else
 
5475
      begin
 
5476
        R.Assign(0,0,0,0);
 
5477
        New(E, Init(R,nil,nil,nil,nil));
 
5478
        AddGroupedAction(eaReadBlock);
 
5479
        if E^.LoadFromStream(S)=false then
 
5480
          EditorDialog(edReadError,@FileName)
 
5481
        else
 
5482
          begin
 
5483
            E^.SelectAll(true);
 
5484
            Self.InsertFrom(E);
 
5485
          end;
 
5486
        CloseGroupedAction(eaReadBlock);
 
5487
        Dispose(E, Done);
 
5488
      end;
 
5489
    if Assigned(S) then Dispose(S, Done);
 
5490
  end;
 
5491
end;
 
5492
 
 
5493
procedure TCustomCodeEditor.PrintBlock;
 
5494
begin
 
5495
  NotImplemented; Exit;
 
5496
end;
 
5497
 
 
5498
function TCustomCodeEditor.SelectCodeTemplate(var ShortCut: string): boolean;
 
5499
begin
 
5500
  { Abstract }
 
5501
  SelectCodeTemplate:=false;
 
5502
end;
 
5503
 
 
5504
procedure TCustomCodeEditor.ExpandCodeTemplate;
 
5505
var Line,ShortCutInEditor,ShortCut: string;
 
5506
    X,Y,I,LineIndent: sw_integer;
 
5507
    CodeLines: PUnsortedStringCollection;
 
5508
    CanJump: boolean;
 
5509
    CP: TPoint;
 
5510
begin
 
5511
  {
 
5512
    The usage of editing primitives in this routine make it pretty slow, but
 
5513
    its speed is still acceptable and they make the implementation of Undo
 
5514
    much easier... - Gabor
 
5515
  }
 
5516
  if IsReadOnly then Exit;
 
5517
 
 
5518
  Lock;
 
5519
 
 
5520
  CP.X:=-1; CP.Y:=-1;
 
5521
  Line:=GetDisplayText(CurPos.Y);
 
5522
  X:=CurPos.X; ShortCut:='';
 
5523
  if X<=length(Line) then
 
5524
  while (X>0) and (Line[X] in (NumberChars+AlphaChars)) do
 
5525
  begin
 
5526
    ShortCut:=Line[X]+ShortCut;
 
5527
    Dec(X);
 
5528
  end;
 
5529
  ShortCutInEditor:=ShortCut;
 
5530
 
 
5531
  New(CodeLines, Init(10,10));
 
5532
  if (ShortCut='') or (not TranslateCodeTemplate(ShortCut,CodeLines)) then
 
5533
   if SelectCodeTemplate(ShortCut) then
 
5534
     TranslateCodeTemplate(ShortCut,CodeLines);
 
5535
 
 
5536
  if CodeLines^.Count>0 then
 
5537
  begin
 
5538
    LineIndent:=X;
 
5539
    SetCurPtr(X,CurPos.Y);
 
5540
    if Copy(ShortCut,1,length(ShortCutInEditor))=ShortCutInEditor then
 
5541
      begin
 
5542
        for I:=1 to length(ShortCutInEditor) do
 
5543
          DelChar;
 
5544
      end
 
5545
    else
 
5546
      { restore correct position }
 
5547
      SetCurPtr(X+Length(ShortCutInEditor),CurPos.Y);
 
5548
    for Y:=0 to CodeLines^.Count-1 do
 
5549
    begin
 
5550
      Line:=GetStr(CodeLines^.At(Y));
 
5551
      CanJump:=false;
 
5552
      if (Y>0) then
 
5553
        begin
 
5554
           CanJump:=Trim(GetLineText(CurPos.Y))='';
 
5555
           if CanJump=false then
 
5556
             begin
 
5557
(*                 for X:=1 to LineIndent do  { indent template lines to align }
 
5558
                 AddChar(' ');            { them to the first line         }*)
 
5559
               InsertText(CharStr(' ',LineIndent));
 
5560
             end
 
5561
           else
 
5562
            SetCurPtr(CurPos.X+LineIndent,CurPos.Y);
 
5563
        end;
 
5564
      I:=Pos(CodeTemplateCursorChar,Line);
 
5565
      if I>0 then
 
5566
        begin
 
5567
          Delete(Line,I,1);
 
5568
          CP.X:=CurPos.X+I-1;
 
5569
          CP.Y:=CurPos.Y;
 
5570
        end;
 
5571
      InsertText(Line);
 
5572
      if Y<CodeLines^.Count-1 then
 
5573
        begin
 
5574
          InsertNewLine;               { line break }
 
5575
          if CanJump=false then
 
5576
            begin
 
5577
              while CurPos.X>0 do       { unindent }
 
5578
              begin
 
5579
                SetCurPtr(CurPos.X-1,CurPos.Y);
 
5580
                DelChar;
 
5581
              end;
 
5582
            end
 
5583
          else
 
5584
            SetCurPtr(0,CurPos.Y);
 
5585
        end;
 
5586
    end;
 
5587
  end;
 
5588
  Dispose(CodeLines, Done);
 
5589
 
 
5590
  if (CP.X<>-1) and (CP.Y<>-1) then
 
5591
    SetCurPtr(CP.X,CP.Y);
 
5592
 
 
5593
  UnLock;
 
5594
end;
 
5595
 
 
5596
procedure TCustomCodeEditor.AddChar(C: char);
 
5597
const OpenBrackets  : string[10] = '[({';
 
5598
      CloseBrackets : string[10] = '])}';
 
5599
var S,SC,TabS: string;
 
5600
    BI: byte;
 
5601
    CI,TabStart,LocTabSize : Sw_integer;
 
5602
    SP: TPoint;
 
5603
    HoldUndo : boolean;
 
5604
begin
 
5605
  if IsReadOnly then Exit;
 
5606
 
 
5607
  Lock;
 
5608
  SP:=CurPos;
 
5609
  HoldUndo:=GetStoreUndo;
 
5610
  SetStoreUndo(false);
 
5611
  if (C<>TAB) or IsFlagSet(efUseTabCharacters) then
 
5612
    SC:=C
 
5613
  else
 
5614
    begin
 
5615
      LocTabSize:=GetTabSize - (CurPos.X mod GetTabSize);
 
5616
      if (CurPos.Y<=1) or not IsFlagSet(efAutoIndent) then
 
5617
        SC:=CharStr(' ',LocTabSize)
 
5618
      else
 
5619
        begin
 
5620
          S:=GetLineText(CurPos.Y-1);
 
5621
          BI:=CurPos.X+1;
 
5622
          while (BI<=Length(S)) and (S[BI]=' ') do
 
5623
            inc(BI);
 
5624
          if (BI=CurPos.X+1) or (BI>Length(S)) then
 
5625
            SC:=CharStr(' ',LocTabSize)
 
5626
          else
 
5627
            SC:=CharStr(' ',BI-CurPos.X-1);
 
5628
        end;
 
5629
    end;
 
5630
  S:=GetLineText(CurPos.Y);
 
5631
  if CharIdxToLinePos(CurPos.Y,length(S))<CurPos.X then
 
5632
    begin
 
5633
      S:=S+CharStr(' ',CurPos.X-CharIdxToLinePos(CurPos.Y,length(S)){-1});
 
5634
      SetLineText(CurPos.Y,S);
 
5635
    end;
 
5636
  CI:=LinePosToCharIdx(CurPos.Y,CurPos.X);
 
5637
  if CI>High(S) then
 
5638
    begin
 
5639
      Unlock;
 
5640
      exit;
 
5641
    end;
 
5642
  if (CI>0) and (S[CI]=TAB) and not IsFlagSet(efUseTabCharacters) then
 
5643
    begin
 
5644
      if CI=1 then
 
5645
        TabStart:=0
 
5646
      else
 
5647
        TabStart:=CharIdxToLinePos(CurPos.Y,CI-1)+1;
 
5648
      if SC=Tab then TabS:=Tab else
 
5649
        TabS:=CharStr(' ',CurPos.X-TabStart);
 
5650
      SetLineText(CurPos.Y,copy(S,1,CI-1)+TabS+SC+copy(S,CI+1,High(S)));
 
5651
      SetCurPtr(CharIdxToLinePos(CurPos.Y,CI+length(TabS)+length(SC)),CurPos.Y);
 
5652
    end
 
5653
  else
 
5654
    begin
 
5655
      if Overwrite and (CI<=length(S)) then
 
5656
        begin
 
5657
          SetLineText(CurPos.Y,copy(S,1,CI-1)+SC+copy(S,CI+length(SC),High(S)));
 
5658
        end
 
5659
      else
 
5660
        SetLineText(CurPos.Y,copy(S,1,CI-1)+SC+copy(S,CI,High(S)));
 
5661
      SetCurPtr(CharIdxToLinePos(CurPos.Y,CI+length(SC)),CurPos.Y);
 
5662
    end;
 
5663
 { must be before CloseBrackets !! }
 
5664
  SetStoreUndo(HoldUndo);
 
5665
  if Overwrite then
 
5666
    Addaction(eaOverwriteText,SP,CurPos,Copy(S,CI,length(SC)),GetFlags)
 
5667
  else
 
5668
    Addaction(eaInsertText,SP,CurPos,SC,GetFlags);
 
5669
  SetStoreUndo(false);
 
5670
  if IsFlagSet(efAutoBrackets) then
 
5671
    begin
 
5672
      BI:=Pos(C,OpenBrackets);
 
5673
      if (BI>0) then
 
5674
        begin
 
5675
          SetStoreUndo(HoldUndo);
 
5676
          AddChar(CloseBrackets[BI]);
 
5677
          SetStoreUndo(false);
 
5678
          SetCurPtr(CurPos.X-1,CurPos.Y);
 
5679
        end;
 
5680
    end;
 
5681
  UpdateAttrs(CurPos.Y,attrAll);
 
5682
  if GetInsertMode then
 
5683
    AdjustSelection(CurPos.X-SP.X,CurPos.Y-SP.Y);
 
5684
  DrawLines(CurPos.Y);
 
5685
  SetStoreUndo(HoldUndo);
 
5686
  SetModified(true);
 
5687
  UnLock;
 
5688
end;
 
5689
 
 
5690
{$ifdef WinClipSupported}
 
5691
function TCustomCodeEditor.ClipPasteWin: Boolean;
 
5692
var OK: boolean;
 
5693
    l,i : longint;
 
5694
    p,p10,p2,p13 : pchar;
 
5695
    s : string;
 
5696
    BPos,EPos,StorePos : TPoint;
 
5697
    first : boolean;
 
5698
begin
 
5699
  Lock;
 
5700
  OK:=WinClipboardSupported;
 
5701
  if OK then
 
5702
    begin
 
5703
      first:=true;
 
5704
      StorePos:=CurPos;
 
5705
      i:=CurPos.Y;
 
5706
      l:=GetTextWinClipboardSize;
 
5707
      if l=0 then
 
5708
        OK:=false
 
5709
      else
 
5710
        OK:=GetTextWinClipBoardData(p,l);
 
5711
      if OK then
 
5712
        begin
 
5713
          if l>500 then
 
5714
            PushInfo(msg_readingwinclipboard);
 
5715
          AddGroupedAction(eaPasteWin);
 
5716
          p2:=p;
 
5717
          p13:=strpos(p,#13);
 
5718
          p10:=strpos(p,#10);
 
5719
          while assigned(p10) do
 
5720
            begin
 
5721
              if p13+1=p10 then
 
5722
                p13[0]:=#0
 
5723
              else
 
5724
                p10[0]:=#0;
 
5725
              s:=strpas(p2);
 
5726
              if first then
 
5727
                begin
 
5728
                  { we need to cut the line in two
 
5729
                    if not at end of line PM }
 
5730
                  InsertNewLine;
 
5731
                  SetCurPtr(StorePos.X,StorePos.Y);
 
5732
                  InsertText(s);
 
5733
                  first:=false;
 
5734
                end
 
5735
              else
 
5736
                begin
 
5737
                  Inc(i);
 
5738
                  InsertLine(i,s);
 
5739
                  BPos.X:=0;BPos.Y:=i;
 
5740
                  EPOS.X:=Length(s);EPos.Y:=i;
 
5741
                  AddAction(eaInsertLine,BPos,EPos,GetDisplayText(i),GetFlags);
 
5742
                end;
 
5743
              if p13+1=p10 then
 
5744
                p13[0]:=#13
 
5745
              else
 
5746
                p10[0]:=#10;
 
5747
              p2:=@p10[1];
 
5748
              p13:=strpos(p2,#13);
 
5749
              p10:=strpos(p2,#10);
 
5750
            end;
 
5751
          if strlen(p2)>0 then
 
5752
            begin
 
5753
              s:=strpas(p2);
 
5754
              if not first then
 
5755
                SetCurPtr(0,i+1);
 
5756
              InsertText(s);
 
5757
            end;
 
5758
          SetCurPtr(StorePos.X,StorePos.Y);
 
5759
          SetModified(true);
 
5760
          UpdateAttrs(StorePos.Y,attrAll);
 
5761
          CloseGroupedAction(eaPasteWin);
 
5762
          Update;
 
5763
          if l>500 then
 
5764
            PopInfo;
 
5765
          { we must free the allocated memory }
 
5766
          freemem(p,l);
 
5767
          DrawView;
 
5768
        end;
 
5769
    end;
 
5770
  ClipPasteWin:=OK;
 
5771
  UnLock;
 
5772
end;
 
5773
 
 
5774
function TCustomCodeEditor.ClipCopyWin: Boolean;
 
5775
var OK,ShowInfo: boolean;
 
5776
    p,p2 : pchar;
 
5777
    s : string;
 
5778
    i,str_begin,str_end,NumLines,PcLength : longint;
 
5779
begin
 
5780
  NumLines:=SelEnd.Y-SelStart.Y;
 
5781
  if (NumLines>0) or (SelEnd.X>SelStart.X) then
 
5782
    Inc(NumLines);
 
5783
  if NumLines=0 then
 
5784
    exit;
 
5785
  Lock;
 
5786
  ShowInfo:=SelEnd.Y-SelStart.Y>50;
 
5787
  if ShowInfo then
 
5788
    PushInfo(msg_copyingwinclipboard);
 
5789
  { First calculate needed size }
 
5790
  { for newlines first + 1 for terminal #0 }
 
5791
  PcLength:=Length(EOL)*(NumLines-1)+1;
 
5792
 
 
5793
  { overestimated but can not be that big PM }
 
5794
  for i:=SelStart.Y to SelEnd.Y do
 
5795
    PCLength:=PCLength+Length(GetLineText(i));
 
5796
  getmem(p,PCLength);
 
5797
  i:=SelStart.Y;
 
5798
  s:=GetLineText(i);
 
5799
  str_begin:=LinePosToCharIdx(i,SelStart.X);
 
5800
  if SelEnd.Y>SelStart.Y then
 
5801
    str_end:=High(S)
 
5802
  else
 
5803
    str_end:=LinePosToCharIdx(i,SelEnd.X)-1;
 
5804
  s:=copy(s,str_begin,str_end-str_begin+1);
 
5805
  strpcopy(p,s);
 
5806
  p2:=strend(p);
 
5807
  inc(i);
 
5808
  while i<SelEnd.Y do
 
5809
    begin
 
5810
      strpcopy(p2,EOL+GetLineText(i));
 
5811
      p2:=strend(p2);
 
5812
      Inc(i);
 
5813
    end;
 
5814
  if SelEnd.Y>SelStart.Y then
 
5815
    begin
 
5816
      s:=copy(GetLineText(i),1,LinePosToCharIdx(i,SelEnd.X)-1);
 
5817
      strpcopy(p2,EOL+s);
 
5818
    end;
 
5819
  OK:=WinClipboardSupported;
 
5820
  if OK then
 
5821
    begin
 
5822
      OK:=SetTextWinClipBoardData(p,strlen(p));
 
5823
    end;
 
5824
  ClipCopyWin:=OK;
 
5825
  if ShowInfo then
 
5826
    PopInfo;
 
5827
  Freemem(p,PCLength);
 
5828
  UnLock;
 
5829
end;
 
5830
{$endif WinClipSupported}
 
5831
 
 
5832
function TCustomCodeEditor.ClipCopy: Boolean;
 
5833
 
 
5834
var ShowInfo,CanPaste: boolean;
 
5835
 
 
5836
begin
 
5837
  Lock;
 
5838
  {AddGroupedAction(eaCopy);
 
5839
   can we undo a copy ??
 
5840
   maybe as an Undo Paste in Clipboard !! }
 
5841
  clipcopy:=false;
 
5842
  showinfo:=false;
 
5843
  if (clipboard<>nil) and (clipboard<>@self) then
 
5844
    begin
 
5845
      ShowInfo:=SelEnd.Y-SelStart.Y>50;
 
5846
      if ShowInfo then
 
5847
        PushInfo(msg_copyingclipboard);
 
5848
      clipcopy:=Clipboard^.InsertFrom(@Self);
 
5849
      if ShowInfo then
 
5850
        PopInfo;
 
5851
      {Enable paste command.}
 
5852
      CanPaste:=((Clipboard^.SelStart.X<>Clipboard^.SelEnd.X) or
 
5853
                (Clipboard^.SelStart.Y<>Clipboard^.SelEnd.Y));
 
5854
      SetCmdState(FromClipCmds,CanPaste);
 
5855
    end;
 
5856
  UnLock;
 
5857
end;
 
5858
 
 
5859
procedure TCustomCodeEditor.ClipCut;
 
5860
var
 
5861
  ShowInfo,CanPaste : boolean;
 
5862
begin
 
5863
  if IsReadOnly then Exit;
 
5864
  Lock;
 
5865
  AddGroupedAction(eaCut);
 
5866
  DontConsiderShiftState:=true;
 
5867
  if (clipboard<>nil) and (clipboard<>@self) then
 
5868
   begin
 
5869
     ShowInfo:=SelEnd.Y-SelStart.Y>50;
 
5870
     if ShowInfo then
 
5871
       PushInfo(msg_cutting);
 
5872
     if Clipboard^.InsertFrom(@Self) then
 
5873
      begin
 
5874
        if not IsClipBoard then
 
5875
         DelSelect;
 
5876
        SetModified(true);
 
5877
      end;
 
5878
     if ShowInfo then
 
5879
       PopInfo;
 
5880
     CanPaste:=((Clipboard^.SelStart.X<>Clipboard^.SelEnd.X) or
 
5881
               (Clipboard^.SelStart.Y<>Clipboard^.SelEnd.Y));
 
5882
     SetCmdState(FromClipCmds,CanPaste);
 
5883
   end;
 
5884
  CloseGroupedAction(eaCut);
 
5885
  UnLock;
 
5886
  DontConsiderShiftState:=false;
 
5887
end;
 
5888
 
 
5889
procedure TCustomCodeEditor.ClipPaste;
 
5890
var
 
5891
  ShowInfo : boolean;
 
5892
begin
 
5893
  if IsReadOnly then Exit;
 
5894
  DontConsiderShiftState:=true;
 
5895
  Lock;
 
5896
  AddGroupedAction(eaPaste);
 
5897
  if Clipboard<>nil then
 
5898
   begin
 
5899
     ShowInfo:=Clipboard^.SelEnd.Y-Clipboard^.SelStart.Y>50;
 
5900
     if ShowInfo then
 
5901
       PushInfo(msg_pastingclipboard);
 
5902
     InsertFrom(Clipboard);
 
5903
     if ShowInfo then
 
5904
       PopInfo;
 
5905
     SetModified(true);
 
5906
   end;
 
5907
  CloseGroupedAction(eaPaste);
 
5908
  UnLock;
 
5909
  DontConsiderShiftState:=false;
 
5910
end;
 
5911
 
 
5912
procedure TCustomCodeEditor.Undo;
 
5913
begin
 
5914
  NotImplemented; Exit;
 
5915
end;
 
5916
 
 
5917
procedure TCustomCodeEditor.Redo;
 
5918
begin
 
5919
  NotImplemented; Exit;
 
5920
end;
 
5921
 
 
5922
procedure TCustomCodeEditor.GotoLine;
 
5923
var
 
5924
  GotoRec: TGotoLineDialogRec;
 
5925
begin
 
5926
  with GotoRec do
 
5927
  begin
 
5928
    LineNo:='1';
 
5929
    Lines:=GetLineCount;
 
5930
    {Linecount can be 0, but in that case there still is a cursor blinking in top
 
5931
     of the window, which will become line 1 as soon as sometype hits a key.}
 
5932
    if lines=0 then
 
5933
      lines:=1;
 
5934
    if EditorDialog(edGotoLine, @GotoRec) <> cmCancel then
 
5935
    begin
 
5936
      Lock;
 
5937
      SetCurPtr(0,StrToInt(LineNo)-1);
 
5938
      TrackCursor(do_centre);
 
5939
      UnLock;
 
5940
    end;
 
5941
  end;
 
5942
end;
 
5943
 
 
5944
procedure TCustomCodeEditor.Find;
 
5945
var
 
5946
  FindRec: TFindDialogRec;
 
5947
  DoConf: boolean;
 
5948
begin
 
5949
  with FindRec do
 
5950
  begin
 
5951
    Find := FindStr;
 
5952
    if GetCurrentWord<>'' then
 
5953
      Find:=GetCurrentWord;
 
5954
{$ifdef TEST_REGEXP}
 
5955
    Options := ((FindFlags and ffmOptionsFind) shr ffsOptions) or
 
5956
               ((FindFlags and ffUseRegExp) shr ffsUseRegExpFind);
 
5957
{$else not TEST_REGEXP}
 
5958
    Options := (FindFlags and ffmOptions) shr ffsOptions;
 
5959
{$endif TEST_REGEXP}
 
5960
    Direction := (FindFlags and ffmDirection) shr ffsDirection;
 
5961
    Scope := (FindFlags and ffmScope) shr ffsScope;
 
5962
    Origin := (FindFlags and ffmOrigin) shr ffsOrigin;
 
5963
    DoConf:= (FindFlags and ffPromptOnReplace)<>0;
 
5964
    FindReplaceEditor:=@self;
 
5965
    if EditorDialog(edFind, @FindRec) <> cmCancel then
 
5966
    begin
 
5967
      FindStr := Find;
 
5968
{$ifdef TEST_REGEXP}
 
5969
      FindFlags := ((Options and ffmOptionsFind) shl ffsOptions) or (Direction shl ffsDirection) or
 
5970
         ((Options and ffmUseRegExpFind) shl ffsUseRegExpFind) or
 
5971
         (Scope shl ffsScope) or (Origin shl ffsOrigin);
 
5972
{$else : not TEST_REGEXP}
 
5973
      FindFlags := ((Options and ffmOptions) shl ffsOptions) or (Direction shl ffsDirection) or
 
5974
         (Scope shl ffsScope) or (Origin shl ffsOrigin);
 
5975
{$endif TEST_REGEXP}
 
5976
      FindFlags := FindFlags and not ffDoReplace;
 
5977
      if DoConf then
 
5978
        FindFlags := (FindFlags or ffPromptOnReplace);
 
5979
      SearchRunCount:=0;
 
5980
      if FindStr<>'' then
 
5981
        DoSearchReplace
 
5982
      else
 
5983
        EditorDialog(edSearchFailed,nil);
 
5984
    end;
 
5985
    FindReplaceEditor:=nil;
 
5986
  end;
 
5987
end;
 
5988
 
 
5989
procedure TCustomCodeEditor.Replace;
 
5990
var
 
5991
  ReplaceRec: TReplaceDialogRec;
 
5992
  Re: word;
 
5993
begin
 
5994
  if IsReadOnly then Exit;
 
5995
  with ReplaceRec do
 
5996
  begin
 
5997
    Find := FindStr;
 
5998
    if GetCurrentWord<>'' then
 
5999
      Find:=GetCurrentWord;
 
6000
    Replace := ReplaceStr;
 
6001
{$ifdef TEST_REGEXP}
 
6002
    Options := (FindFlags and ffmOptions) shr ffsOptions or
 
6003
               (FindFlags and ffUseRegExp) shr ffsUseRegExpReplace;
 
6004
{$else not TEST_REGEXP}
 
6005
    Options := (FindFlags and ffmOptions) shr ffsOptions;
 
6006
{$endif TEST_REGEXP}
 
6007
    Direction := (FindFlags and ffmDirection) shr ffsDirection;
 
6008
    Scope := (FindFlags and ffmScope) shr ffsScope;
 
6009
    Origin := (FindFlags and ffmOrigin) shr ffsOrigin;
 
6010
    FindReplaceEditor:=@self;
 
6011
    Re:=EditorDialog(edReplace, @ReplaceRec);
 
6012
    FindReplaceEditor:=nil;
 
6013
    if Re <> cmCancel then
 
6014
    begin
 
6015
      FindStr := Find;
 
6016
      ReplaceStr := Replace;
 
6017
      FindFlags := (Options shl ffsOptions) or (Direction shl ffsDirection) or
 
6018
{$ifdef TEST_REGEXP}
 
6019
         ((Options and ffmUseRegExpReplace) shl ffsUseRegExpReplace) or
 
6020
{$endif TEST_REGEXP}
 
6021
         (Scope shl ffsScope) or (Origin shl ffsOrigin);
 
6022
      FindFlags := FindFlags or ffDoReplace;
 
6023
      if Re = cmYes then
 
6024
        FindFlags := FindFlags or ffReplaceAll;
 
6025
      SearchRunCount:=0;
 
6026
      if FindStr<>'' then
 
6027
        DoSearchReplace
 
6028
      else
 
6029
        EditorDialog(edSearchFailed,nil);
 
6030
    end;
 
6031
  end;
 
6032
end;
 
6033
 
 
6034
procedure TCustomCodeEditor.DoSearchReplace;
 
6035
var S: string;
 
6036
    DX,DY,P,Y,X: sw_integer;
 
6037
    Count: sw_integer;
 
6038
    Found,CanExit: boolean;
 
6039
    SForward,DoReplace,DoReplaceAll: boolean;
 
6040
{$ifdef TEST_REGEXP}
 
6041
    UseRegExp : boolean;
 
6042
    RegExpEngine : TRegExprEngine;
 
6043
    RegExpFlags : tregexprflags;
 
6044
    regexpindex,regexplen : longint;
 
6045
    findstrpchar : pchar;
 
6046
{$endif TEST_REGEXP}
 
6047
    LeftOK,RightOK: boolean;
 
6048
    FoundCount: sw_integer;
 
6049
    A,B: TPoint;
 
6050
    AreaStart,AreaEnd: TPoint;
 
6051
    CanReplace,Confirm: boolean;
 
6052
    Re: word;
 
6053
    IFindStr : string;
 
6054
    BT : BTable;
 
6055
 
 
6056
  function ContainsText(const SubS:string;var S: string; Start: Sw_integer): Sw_integer;
 
6057
  var
 
6058
    P: Sw_Integer;
 
6059
  begin
 
6060
    if Start<=0 then
 
6061
     P:=0
 
6062
    else
 
6063
     begin
 
6064
       if SForward then
 
6065
        begin
 
6066
          if Start>length(s) then
 
6067
           P:=0
 
6068
          else if FindFlags and ffCaseSensitive<>0 then
 
6069
           P:=BMFScan(S[Start],length(s)+1-Start,FindStr,Bt)+1
 
6070
          else
 
6071
           P:=BMFIScan(S[Start],length(s)+1-Start,IFindStr,Bt)+1;
 
6072
          if P>0 then
 
6073
           Inc(P,Start-1);
 
6074
        end
 
6075
       else
 
6076
        begin
 
6077
          if start>length(s) then
 
6078
           start:=length(s);
 
6079
          if FindFlags and ffCaseSensitive<>0 then
 
6080
           P:=BMBScan(S[1],Start,FindStr,Bt)+1
 
6081
          else
 
6082
           P:=BMBIScan(S[1],Start,IFindStr,Bt)+1;
 
6083
        end;
 
6084
     end;
 
6085
    ContainsText:=P;
 
6086
  end;
 
6087
 
 
6088
  function InArea(X,Y: sw_integer): boolean;
 
6089
  begin
 
6090
    InArea:=((AreaStart.Y=Y) and (AreaStart.X<=X)) or
 
6091
       ((AreaStart.Y<Y) and (Y<AreaEnd.Y)) or
 
6092
       ((AreaEnd.Y=Y) and (X<=AreaEnd.X));
 
6093
  end;
 
6094
var CurDY: sw_integer;
 
6095
begin
 
6096
  if FindStr='' then
 
6097
    begin
 
6098
      Find;
 
6099
      { Find will call DoFindReplace at end again
 
6100
        so we need to exit directly now PM }
 
6101
      exit;
 
6102
    end;
 
6103
  Inc(SearchRunCount);
 
6104
 
 
6105
  SForward:=(FindFlags and ffmDirection)=ffForward;
 
6106
  DoReplace:=(FindFlags and ffDoReplace)<>0;
 
6107
  Confirm:=(FindFlags and ffPromptOnReplace)<>0;
 
6108
  DoReplaceAll:=(FindFlags and ffReplaceAll)<>0;
 
6109
{$ifdef TEST_REGEXP}
 
6110
  UseRegExp:=(FindFlags and ffUseRegExp)<>0;
 
6111
  if UseRegExp then
 
6112
    begin
 
6113
      if FindFlags and ffCaseSensitive<>0 then
 
6114
        RegExpFlags:=[ref_caseinsensitive]
 
6115
      else
 
6116
        RegExpFlags:=[];
 
6117
      getmem(findstrpchar,length(findstr)+1);
 
6118
      strpcopy(findstrpchar,findstr);
 
6119
      RegExpEngine:=GenerateRegExprEngine(findstrpchar,RegExpFlags);
 
6120
      strdispose(findstrpchar);
 
6121
    end;
 
6122
{$endif TEST_REGEXP}
 
6123
  Count:=GetLineCount;
 
6124
  FoundCount:=0;
 
6125
  { Empty file ? }
 
6126
  if Count=0 then
 
6127
   begin
 
6128
     EditorDialog(edSearchFailed,nil);
 
6129
     exit;
 
6130
   end;
 
6131
 
 
6132
  if SForward then
 
6133
    DY:=1
 
6134
  else
 
6135
    DY:=-1;
 
6136
  DX:=DY;
 
6137
 
 
6138
  if FindStr<>'' then
 
6139
    PushInfo('Looking for "'+FindStr+'"');
 
6140
  if (FindFlags and ffmScope)=ffGlobal then
 
6141
   begin
 
6142
     AreaStart.X:=0;
 
6143
     AreaStart.Y:=0;
 
6144
     AreaEnd.X:=length(GetDisplayText(Count-1));
 
6145
     AreaEnd.Y:=Count-1;
 
6146
   end
 
6147
  else
 
6148
   begin
 
6149
     AreaStart:=SelStart;
 
6150
     AreaEnd:=SelEnd;
 
6151
   end;
 
6152
 
 
6153
  X:=CurPos.X-DX;
 
6154
  Y:=CurPos.Y;;
 
6155
  if SearchRunCount=1 then
 
6156
    if (FindFlags and ffmOrigin)=ffEntireScope then
 
6157
      if SForward then
 
6158
        begin
 
6159
          X:=AreaStart.X-1;
 
6160
          Y:=AreaStart.Y;
 
6161
        end
 
6162
       else
 
6163
        begin
 
6164
          X:=AreaEnd.X+1;
 
6165
          Y:=AreaEnd.Y;
 
6166
        end;
 
6167
 
 
6168
  if FindFlags and ffCaseSensitive<>0 then
 
6169
   begin
 
6170
     if SForward then
 
6171
      BMFMakeTable(FindStr,bt)
 
6172
     else
 
6173
      BMBMakeTable(FindStr,bt);
 
6174
   end
 
6175
  else
 
6176
   begin
 
6177
     IFindStr:=upcase(FindStr);
 
6178
     if SForward then
 
6179
      BMFMakeTable(IFindStr,bt)
 
6180
     else
 
6181
      BMBMakeTable(IFindStr,bt);
 
6182
   end;
 
6183
 
 
6184
  inc(X,DX);
 
6185
  CanExit:=false;
 
6186
  if not DoReplace or (not Confirm and (Owner<>nil)) then
 
6187
    Owner^.Lock;
 
6188
  if InArea(X,Y) then
 
6189
  repeat
 
6190
    CurDY:=DY;
 
6191
    S:=GetDisplayText(Y);
 
6192
{$ifdef TEST_REGEXP}
 
6193
    if UseRegExp then
 
6194
       begin
 
6195
         getmem(findstrpchar,length(Copy(S,X+1,high(S)))+1);
 
6196
         strpcopy(findstrpchar,Copy(S,X+1,high(S)));
 
6197
         { If start of line is required do check other positions PM }
 
6198
         if (FindStr[1]='^') and (X<>0) then
 
6199
           Found:=false
 
6200
         else
 
6201
           Found:=RegExprPos(RegExpEngine,findstrpchar,regexpindex,regexplen);
 
6202
         strdispose(findstrpchar);
 
6203
         P:=regexpindex+X+1;
 
6204
       end
 
6205
    else
 
6206
{$endif TEST_REGEXP}
 
6207
      begin
 
6208
        P:=ContainsText(FindStr,S,X+1);
 
6209
        Found:=P<>0;
 
6210
      end;
 
6211
    if Found then
 
6212
      begin
 
6213
        A.X:=P-1;
 
6214
        A.Y:=Y;
 
6215
        B.Y:=Y;
 
6216
{$ifdef TEST_REGEXP}
 
6217
        if UseRegExp then
 
6218
          B.X:=A.X+regexplen
 
6219
        else
 
6220
{$endif TEST_REGEXP}
 
6221
          B.X:=A.X+length(FindStr);
 
6222
      end;
 
6223
    Found:=Found and InArea(A.X,A.Y);
 
6224
 
 
6225
    if Found and ((FindFlags and ffWholeWordsOnly)<>0) then
 
6226
     begin
 
6227
       LeftOK:=(A.X<=0) or (not( (S[A.X] in AlphaChars) or (S[A.X] in NumberChars) ));
 
6228
       RightOK:=(B.X>=length(S)) or (not( (S[B.X+1] in AlphaChars) or (S[B.X+1] in NumberChars) ));
 
6229
       Found:=LeftOK and RightOK;
 
6230
       if not Found then
 
6231
         begin
 
6232
           CurDY:=0;
 
6233
           X:=B.X+1;
 
6234
         end;
 
6235
     end;
 
6236
 
 
6237
    if Found then
 
6238
      begin
 
6239
        Inc(FoundCount);
 
6240
        Lock;
 
6241
        if SForward then
 
6242
         SetCurPtr(B.X,B.Y)
 
6243
        else
 
6244
         SetCurPtr(A.X,A.Y);
 
6245
        TrackCursor(do_centre);
 
6246
        SetHighlight(A,B);
 
6247
        UnLock;
 
6248
        CurDY:=0;
 
6249
        if not DoReplace then
 
6250
          begin
 
6251
            CanExit:=true;
 
6252
            If SForward then
 
6253
              begin
 
6254
                X:=B.X;
 
6255
                Y:=B.Y;
 
6256
              end
 
6257
            else
 
6258
              begin
 
6259
                X:=A.X;
 
6260
                Y:=A.Y;
 
6261
              end;
 
6262
          end
 
6263
        else
 
6264
          begin
 
6265
            if not confirm then
 
6266
              CanReplace:=true
 
6267
            else
 
6268
              begin
 
6269
                Re:=EditorDialog(edReplacePrompt,@CurPos);
 
6270
                case Re of
 
6271
                  cmYes :
 
6272
                    CanReplace:=true;
 
6273
                  cmNo :
 
6274
                    CanReplace:=false;
 
6275
                  else {cmCancel}
 
6276
                    begin
 
6277
                      CanReplace:=false;
 
6278
                      CanExit:=true;
 
6279
                    end;
 
6280
                end;
 
6281
              end;
 
6282
            if CanReplace then
 
6283
              begin
 
6284
                Lock;
 
6285
                SetSelection(A,B);
 
6286
                DelSelect;
 
6287
                InsertText(ReplaceStr);
 
6288
                if SForward then
 
6289
                  begin
 
6290
                    X:=CurPos.X;
 
6291
                    Y:=CurPos.Y;
 
6292
                  end
 
6293
                else
 
6294
                  begin
 
6295
                    X:=A.X;
 
6296
                    Y:=A.Y;
 
6297
                  end;
 
6298
                UnLock;
 
6299
              end
 
6300
            else
 
6301
              begin
 
6302
                If SForward then
 
6303
                  begin
 
6304
                    X:=B.X;
 
6305
                    Y:=B.Y;
 
6306
                  end
 
6307
                else
 
6308
                  begin
 
6309
                    X:=A.X;
 
6310
                    Y:=A.Y;
 
6311
                  end;
 
6312
              end;
 
6313
            if (DoReplaceAll=false) then
 
6314
              CanExit:=true;
 
6315
          end;
 
6316
      end;
 
6317
 
 
6318
    if (CanExit=false) and (CurDY<>0) then
 
6319
      begin
 
6320
        inc(Y,CurDY);
 
6321
        if SForward then
 
6322
          X:=0
 
6323
        else
 
6324
          X:=254;
 
6325
        CanExit:=(Y>=Count) or (Y<0);
 
6326
      end;
 
6327
    if not CanExit then
 
6328
      CanExit:=not InArea(X,Y);
 
6329
  until CanExit;
 
6330
  if (FoundCount=0) or (DoReplace) then
 
6331
    SetHighlight(CurPos,CurPos);
 
6332
  if (DoReplace=false) or ((Confirm=false) and (Owner<>nil)) then
 
6333
    Owner^.UnLock;
 
6334
  {if (DoReplace=false) or (Confirm=false) then
 
6335
    UnLock;}
 
6336
  if (FoundCount=0) then
 
6337
    EditorDialog(edSearchFailed,nil);
 
6338
  if FindStr<>'' then
 
6339
    PopInfo;
 
6340
{$ifdef TEST_REGEXP}
 
6341
  if UseRegExp then
 
6342
    DestroyRegExprEngine(RegExpEngine);
 
6343
{$endif TEST_REGEXP}
 
6344
  if (FindFlags and ffmScope)=ffSelectedText then
 
6345
    { restore selection PM }
 
6346
    begin
 
6347
      SetSelection(AreaStart,AreaEnd);
 
6348
    end;
 
6349
end;
 
6350
 
 
6351
function TCustomCodeEditor.GetInsertMode: boolean;
 
6352
begin
 
6353
  GetInsertMode:=(GetFlags and efInsertMode)<>0;
 
6354
end;
 
6355
 
 
6356
procedure TCustomCodeEditor.SetInsertMode(InsertMode: boolean);
 
6357
begin
 
6358
  if InsertMode then
 
6359
    SetFlags(GetFlags or efInsertMode)
 
6360
  else
 
6361
    SetFlags(GetFlags and (not efInsertMode));
 
6362
  DrawCursor;
 
6363
end;
 
6364
 
 
6365
{ there is a problem with ShiftDel here
 
6366
  because GetShitState tells to extend the
 
6367
  selection which gives wrong results (PM) }
 
6368
 
 
6369
function TCustomCodeEditor.ShouldExtend: boolean;
 
6370
var ShiftInEvent: boolean;
 
6371
begin
 
6372
  ShiftInEvent:=false;
 
6373
  if Assigned(CurEvent) then
 
6374
    if CurEvent^.What=evKeyDown then
 
6375
      ShiftInEvent:=((CurEvent^.KeyShift and kbShift)<>0);
 
6376
  ShouldExtend:=ShiftInEvent and
 
6377
    not DontConsiderShiftState;
 
6378
end;
 
6379
 
 
6380
procedure TCustomCodeEditor.SetCurPtr(X,Y: sw_integer);
 
6381
var OldPos{,OldSEnd,OldSStart}: TPoint;
 
6382
    Extended: boolean;
 
6383
    F: PFold;
 
6384
begin
 
6385
  Lock;
 
6386
  X:=Max(0,Min(MaxLineLength+1,X));
 
6387
  Y:=Max(0,Min(GetLineCount-1,Y));
 
6388
  OldPos:=CurPos;
 
6389
{  OldSEnd:=SelEnd;
 
6390
  OldSStart:=SelStart;}
 
6391
  CurPos.X:=X;
 
6392
  CurPos.Y:=Y;
 
6393
  TrackCursor(do_not_centre);
 
6394
  if not IsLineVisible(CurPos.Y) then
 
6395
  begin
 
6396
    F:=GetLineFold(CurPos.Y);
 
6397
    if Assigned(F) then
 
6398
      F^.Collapse(false);
 
6399
  end;
 
6400
  if not NoSelect and ShouldExtend then
 
6401
    begin
 
6402
      CheckSels;
 
6403
      Extended:=false;
 
6404
      if PointOfs(OldPos)=PointOfs(SelStart) then
 
6405
        begin
 
6406
          SetSelection(CurPos,SelEnd);
 
6407
          Extended:=true;
 
6408
        end;
 
6409
      CheckSels;
 
6410
      if Extended=false then
 
6411
       if PointOfs(OldPos)=PointOfs(SelEnd) then
 
6412
         begin
 
6413
           if not ValidBlock then
 
6414
             SetSelection(CurPos,CurPos);
 
6415
           SetSelection(SelStart,CurPos); Extended:=true;
 
6416
         end;
 
6417
      CheckSels;
 
6418
      if not Extended then
 
6419
         if PointOfs(OldPos)<=PointOfs(CurPos) then
 
6420
           begin
 
6421
             SetSelection(OldPos,CurPos);
 
6422
             Extended:=true;
 
6423
           end
 
6424
         else
 
6425
           begin
 
6426
             SetSelection(CurPos,OldPos);
 
6427
             Extended:=true;
 
6428
           end;
 
6429
      DrawView;
 
6430
    end
 
6431
  else if not IsFlagSet(efPersistentBlocks) then
 
6432
      begin
 
6433
        HideSelect;
 
6434
        DrawView;
 
6435
      end;
 
6436
{  if PointOfs(SelStart)=PointOfs(SelEnd) then
 
6437
     SetSelection(CurPos,CurPos);}
 
6438
  if (GetFlags and (efHighlightColumn+efHighlightRow))<>0 then
 
6439
     DrawView;
 
6440
  if ((CurPos.X<>OldPos.X) or (CurPos.Y<>OldPos.Y)) and
 
6441
     ((Highlight.A.X<>HighLight.B.X) or (Highlight.A.Y<>HighLight.B.Y)) then
 
6442
     HideHighlight;
 
6443
  if (OldPos.Y<>CurPos.Y) and (0<=OldPos.Y) and (OldPos.Y<GetLineCount) then
 
6444
     SetLineText(OldPos.Y,RTrim(GetLineText(OldPos.Y),not IsFlagSet(efUseTabCharacters)));
 
6445
  if ((CurPos.X<>OldPos.X) or (CurPos.Y<>OldPos.Y)) and (GetErrorMessage<>'') then
 
6446
    SetErrorMessage('');
 
6447
{  if ((CurPos.X<>OldPos.X) or (CurPos.Y<>OldPos.Y)) and (HighlightRow<>-1) then
 
6448
    SetHighlightRow(-1);}
 
6449
  if ((CurPos.X<>OldPos.X) or (CurPos.Y<>OldPos.Y)) then
 
6450
    AddAction(eaMoveCursor,OldPos,CurPos,'',GetFlags);
 
6451
  if ((CurPos.X<>OldPos.X) or (CurPos.Y<>OldPos.Y)) then
 
6452
    PositionChanged;{UpdateIndicator;}
 
6453
  UnLock;
 
6454
end;
 
6455
 
 
6456
procedure TCustomCodeEditor.CheckSels;
 
6457
begin
 
6458
  if (SelStart.Y>SelEnd.Y) or
 
6459
     ( (SelStart.Y=SelEnd.Y) and (SelStart.X>SelEnd.X) ) then
 
6460
       SetSelection(SelEnd,SelStart);
 
6461
end;
 
6462
 
 
6463
procedure TCustomCodeEditor.CodeCompleteApply;
 
6464
var S: string;
 
6465
    FragLen,
 
6466
    I: integer;
 
6467
begin
 
6468
  Lock;
 
6469
 
 
6470
  { here should be some kind or "mark" or "break" inserted in the Undo
 
6471
    information, so activating it "undoes" only the completition first and
 
6472
    doesn't delete the complete word at once... - Gabor }
 
6473
 
 
6474
  FragLen:=Length(GetCodeCompleteFrag);
 
6475
  S:=GetCodeCompleteWord;
 
6476
  for I:=FragLen+1 to length(S) do
 
6477
    AddChar(S[I]);
 
6478
 
 
6479
  UnLock;
 
6480
  SetCompleteState(csInactive);
 
6481
end;
 
6482
 
 
6483
procedure TCustomCodeEditor.CodeCompleteCancel;
 
6484
begin
 
6485
  SetCompleteState(csDenied);
 
6486
end;
 
6487
 
 
6488
procedure TCustomCodeEditor.CodeCompleteCheck;
 
6489
var Line: string;
 
6490
    X: sw_integer;
 
6491
    CurWord,NewWord: string;
 
6492
begin
 
6493
  SetCodeCompleteFrag('');
 
6494
  if (not IsFlagSet(efCodeComplete)) or (IsReadOnly=true) then Exit;
 
6495
 
 
6496
  Lock;
 
6497
 
 
6498
  Line:=GetDisplayText(CurPos.Y);
 
6499
  X:=CurPos.X; CurWord:='';
 
6500
  if X<=length(Line) then
 
6501
  while (X>0) and (Line[X] in (NumberChars+AlphaChars)) do
 
6502
  begin
 
6503
    CurWord:=Line[X]+CurWord;
 
6504
    Dec(X);
 
6505
  end;
 
6506
 
 
6507
  if (length(CurWord)>=CodeCompleteMinLen) and CompleteCodeWord(CurWord,NewWord) then
 
6508
    begin
 
6509
      SetCodeCompleteFrag(CurWord);
 
6510
      SetCodeCompleteWord(NewWord);
 
6511
    end
 
6512
  else
 
6513
    ClearCodeCompleteWord;
 
6514
 
 
6515
  UnLock;
 
6516
end;
 
6517
 
 
6518
function TCustomCodeEditor.GetCodeCompleteFrag: string;
 
6519
begin
 
6520
  { Abstract }
 
6521
  GetCodeCompleteFrag:='';
 
6522
end;
 
6523
 
 
6524
procedure TCustomCodeEditor.SetCodeCompleteFrag(const S: string);
 
6525
begin
 
6526
  { Abstract }
 
6527
end;
 
6528
 
 
6529
procedure TCustomCodeEditor.DrawLines(FirstLine: sw_integer);
 
6530
begin
 
6531
  if FirstLine>=(Delta.Y+Size.Y) then Exit; { falls outside of the screen }
 
6532
  DrawView;
 
6533
end;
 
6534
 
 
6535
procedure TCustomCodeEditor.HideHighlight;
 
6536
begin
 
6537
  SetHighlight(CurPos,CurPos);
 
6538
end;
 
6539
 
 
6540
procedure TCustomCodeEditor.GetSelectionArea(var StartP,EndP: TPoint);
 
6541
begin
 
6542
  StartP:=SelStart; EndP:=SelEnd;
 
6543
  if EndP.X=0 then
 
6544
    begin
 
6545
      Dec(EndP.Y);
 
6546
      EndP.X:=length(GetDisplayText(EndP.Y))-1;
 
6547
    end
 
6548
  else
 
6549
   Dec(EndP.X);
 
6550
end;
 
6551
 
 
6552
function TCustomCodeEditor.ValidBlock: boolean;
 
6553
begin
 
6554
  ValidBlock:=(SelStart.X<>SelEnd.X) or (SelStart.Y<>SelEnd.Y);
 
6555
end;
 
6556
 
 
6557
procedure TCustomCodeEditor.SetSelection(A, B: TPoint);
 
6558
var WV: boolean;
 
6559
    OS,OE: TPoint;
 
6560
begin
 
6561
  WV:=ValidBlock;
 
6562
  OS:=SelStart; OE:=SelEnd;
 
6563
  SelStart:=A; SelEnd:=B;
 
6564
  if (WV=false) and (ValidBlock=false) then { do nothing } else
 
6565
    if (OS.X<>SelStart.X) or (OS.Y<>SelStart.Y) or
 
6566
       (OE.X<>SelEnd.X) or (OE.Y<>SelEnd.Y) then
 
6567
     SelectionChanged;
 
6568
end;
 
6569
 
 
6570
procedure TCustomCodeEditor.SetHighlight(A, B: TPoint);
 
6571
begin
 
6572
  Highlight.A:=A; Highlight.B:=B;
 
6573
  HighlightChanged;
 
6574
end;
 
6575
 
 
6576
{procedure TCustomCodeEditor.SetHighlightRow(Row: sw_integer);
 
6577
begin
 
6578
  HighlightRow:=Row;
 
6579
  DrawView;
 
6580
end;}
 
6581
 
 
6582
{procedure TCodeEditor.SetDebuggerRow(Row: sw_integer);
 
6583
begin
 
6584
  DebuggerRow:=Row;
 
6585
  DrawView;
 
6586
end;}
 
6587
 
 
6588
procedure TCustomCodeEditor.SelectAll(Enable: boolean);
 
6589
var A,B: TPoint;
 
6590
begin
 
6591
  if (Enable=false) or (GetLineCount=0) then
 
6592
     begin A:=CurPos; B:=CurPos end
 
6593
  else
 
6594
     begin
 
6595
       A.X:=0; A.Y:=0;
 
6596
{       B.Y:=GetLineCount-1;
 
6597
       B.X:=length(GetLineText(B.Y));}
 
6598
       B.Y:=GetLineCount; B.X:=0;
 
6599
     end;
 
6600
  SetSelection(A,B);
 
6601
  DrawView;
 
6602
end;
 
6603
 
 
6604
procedure TCustomCodeEditor.SelectionChanged;
 
6605
var Enable,CanPaste: boolean;
 
6606
begin
 
6607
  if GetLineCount=0 then
 
6608
    begin
 
6609
      SelStart.X:=0; SelStart.Y:=0; SelEnd:=SelStart;
 
6610
    end
 
6611
  else
 
6612
    if SelEnd.Y>GetLineCount-1 then
 
6613
     if (SelEnd.Y<>GetLineCount) or (SelEnd.X<>0) then
 
6614
      begin
 
6615
        SelEnd.Y:=GetLineCount-1;
 
6616
        SelEnd.X:=length(GetDisplayText(SelEnd.Y));
 
6617
      end;
 
6618
 
 
6619
  { we change the CurCommandSet, but only if we are top view }
 
6620
  if ((State and sfFocused)<>0) then
 
6621
    begin
 
6622
      Enable:=((SelStart.X<>SelEnd.X) or (SelStart.Y<>SelEnd.Y)) and (Clipboard<>nil);
 
6623
      SetCmdState(ToClipCmds,Enable and (Clipboard<>@Self));
 
6624
      SetCmdState(NulClipCmds,Enable);
 
6625
      CanPaste:=(Clipboard<>nil) and ((Clipboard^.SelStart.X<>Clipboard^.SelEnd.X) or
 
6626
           (Clipboard^.SelStart.Y<>Clipboard^.SelEnd.Y));
 
6627
      SetCmdState(FromClipCmds,CanPaste  and (Clipboard<>@Self));
 
6628
      SetCmdState(UndoCmd,(GetUndoActionCount>0));
 
6629
      SetCmdState(RedoCmd,(GetRedoActionCount>0));
 
6630
      Message(Application,evBroadcast,cmCommandSetChanged,nil);
 
6631
    end;
 
6632
  DrawView;
 
6633
end;
 
6634
 
 
6635
procedure TCustomCodeEditor.HighlightChanged;
 
6636
begin
 
6637
  DrawView;
 
6638
end;
 
6639
 
 
6640
procedure TCustomCodeEditor.SetState(AState: Word; Enable: Boolean);
 
6641
  procedure ShowSBar(SBar: PScrollBar);
 
6642
  begin
 
6643
    if Assigned(SBar) and (SBar^.GetState(sfVisible)=false) then
 
6644
        SBar^.Show;
 
6645
  end;
 
6646
begin
 
6647
  inherited SetState(AState,Enable);
 
6648
 
 
6649
  if AlwaysShowScrollBars then
 
6650
   begin
 
6651
     ShowSBar(HScrollBar);
 
6652
     ShowSBar(VScrollBar);
 
6653
   end;
 
6654
 
 
6655
  if (AState and (sfActive+sfSelected+sfFocused))<>0 then
 
6656
    begin
 
6657
      SelectionChanged;
 
6658
      if ((State and sfFocused)=0) and (GetCompleteState=csOffering) then
 
6659
        ClearCodeCompleteWord;
 
6660
    end;
 
6661
end;
 
6662
 
 
6663
function TCustomCodeEditor.GetPalette: PPalette;
 
6664
const P: string[length(CEditor)] = CEditor;
 
6665
begin
 
6666
  GetPalette:=@P;
 
6667
end;
 
6668
 
 
6669
function TCustomCodeEditorCore.LoadFromStream(Editor: PCustomCodeEditor; Stream: PFastBufStream): boolean;
 
6670
var S: string;
 
6671
    AllLinesComplete,LineComplete,hasCR,OK: boolean;
 
6672
begin
 
6673
  DeleteAllLines;
 
6674
  ChangedLine:=-1;
 
6675
  AllLinesComplete:=true;
 
6676
  OK:=(Stream^.Status=stOK);
 
6677
  if eofstream(Stream) then
 
6678
   AddLine('')
 
6679
  else
 
6680
   begin
 
6681
     while OK and (eofstream(Stream)=false) and (GetLineCount<MaxLineCount) do
 
6682
       begin
 
6683
         if not UseOldBufStreamMethod then
 
6684
           Stream^.Readline(S,LineComplete,hasCR)
 
6685
         else
 
6686
           ReadlnFromStream(Stream,S,LineComplete,hasCR);
 
6687
         AllLinesComplete:=AllLinesComplete and LineComplete;
 
6688
         OK:=OK and (Stream^.Status=stOK);
 
6689
         if OK then AddLine(S);
 
6690
         if not LineComplete and (ChangedLine=-1) then
 
6691
           ChangedLine:=GetLineCount;
 
6692
       end;
 
6693
     { Do not remove the final newline if it exists PM }
 
6694
     if hasCR then
 
6695
       AddLine('');
 
6696
    end;
 
6697
  LimitsChanged;
 
6698
  if not AllLinesComplete then
 
6699
    SetModified(true);
 
6700
  if (GetLineCount=MaxLineCount) and not eofstream(stream) then
 
6701
    EditorDialog(edTooManyLines,nil);
 
6702
  LoadFromStream:=OK;
 
6703
end;
 
6704
 
 
6705
function TCustomCodeEditorCore.SaveAreaToStream(Editor: PCustomCodeEditor; Stream: PStream; StartP,EndP: TPoint): boolean;
 
6706
var S: string;
 
6707
    OK: boolean;
 
6708
    Line: Sw_integer;
 
6709
begin
 
6710
  if EndP.X=0 then
 
6711
    begin
 
6712
      if EndP.Y>0 then
 
6713
        begin
 
6714
          EndP.X:=length(GetDisplayText(EndP.Y));
 
6715
        end
 
6716
      else
 
6717
        EndP.X:=0;
 
6718
    end
 
6719
  else
 
6720
    Dec(EndP.X);
 
6721
  OK:=(Stream^.Status=stOK); Line:=StartP.Y;
 
6722
  while OK and (Line<=EndP.Y) and (Line<GetLineCount) do
 
6723
  begin
 
6724
    S:=GetLineText(Line);
 
6725
    { Remove all traling spaces PM }
 
6726
    if not Editor^.IsFlagSet(efKeepTrailingSpaces) then
 
6727
      While (Length(S)>0) and (S[Length(S)]=' ') do
 
6728
       Dec(S[0]);
 
6729
    { if FlagSet(efUseTabCharacters) then
 
6730
      S:=CompressUsingTabs(S,TabSize);
 
6731
      }
 
6732
    if Line=EndP.Y then S:=copy(S,1,LinePosToCharIdx(Line,EndP.X));
 
6733
    if Line=StartP.Y then S:=copy(S,LinePosToCharIdx(Line,StartP.X),High(S));
 
6734
    Stream^.Write(S[1],length(S));
 
6735
    if Line<EndP.Y then
 
6736
      Stream^.Write(EOL[1],length(EOL));
 
6737
    Inc(Line);
 
6738
    OK:=OK and (Stream^.Status=stOK);
 
6739
  end;
 
6740
  SaveAreaToStream:=OK;
 
6741
end;
 
6742
 
 
6743
 
 
6744
constructor TEditorAction.init(act:byte; StartP,EndP:TPoint;Txt:String;AFlags : longint);
 
6745
begin
 
6746
  Action:=act;
 
6747
  StartPos:=StartP;
 
6748
  EndPos:=EndP;
 
6749
  Text:=NewStr(txt);
 
6750
  ActionCount:=0;
 
6751
  Flags:=AFlags;
 
6752
  TimeStamp:=Now;
 
6753
  IsGrouped:=false;
 
6754
end;
 
6755
 
 
6756
constructor TEditorAction.init_group(act:byte);
 
6757
begin
 
6758
  Action:=act;
 
6759
  ActionCount:=0;
 
6760
  Flags:=0;
 
6761
  IsGrouped:=true;
 
6762
end;
 
6763
 
 
6764
function TEditorAction.Is_grouped_action : boolean;
 
6765
begin
 
6766
  Is_grouped_action:=IsGrouped;
 
6767
end;
 
6768
 
 
6769
destructor TEditorAction.done;
 
6770
begin
 
6771
  DisposeStr(Text);
 
6772
  inherited done;
 
6773
end;
 
6774
 
 
6775
 
 
6776
function TEditorActionCollection.At(Idx : sw_integer) : PEditorAction;
 
6777
begin
 
6778
  At:=PEditorAction(Inherited At(Idx));
 
6779
end;
 
6780
 
 
6781
procedure TEditorInputLine.HandleEvent(var Event : TEvent);
 
6782
var
 
6783
  s,s2 : string;
 
6784
  i : longint;
 
6785
begin
 
6786
     If (Event.What=evKeyDown) then
 
6787
       begin
 
6788
         if (Event.KeyCode=kbRight) and
 
6789
            (CurPos = Length(Data^)) and
 
6790
            Assigned(FindReplaceEditor) then
 
6791
           Begin
 
6792
             s:=FindReplaceEditor^.GetDisplayText(FindReplaceEditor^.CurPos.Y);
 
6793
             s:=Copy(s,FindReplaceEditor^.CurPos.X + 1 -length(Data^),high(s));
 
6794
             i:=pos(Data^,s);
 
6795
             if i>0 then
 
6796
               begin
 
6797
                 s:=Data^+s[i+length(Data^)];
 
6798
                 If not assigned(validator) or
 
6799
                    Validator^.IsValidInput(s,False)  then
 
6800
                   Begin
 
6801
                     Event.CharCode:=s[length(s)];
 
6802
                     Event.Scancode:=0;
 
6803
                     Inherited HandleEvent(Event);
 
6804
                   End;
 
6805
               end;
 
6806
             ClearEvent(Event);
 
6807
           End
 
6808
         else if (Event.KeyCode=kbShiftIns)  and
 
6809
                 Assigned(Clipboard) and (Clipboard^.ValidBlock) then
 
6810
           { paste from clipboard }
 
6811
           begin
 
6812
             i:=Clipboard^.SelStart.Y;
 
6813
             s:=Clipboard^.GetDisplayText(i);
 
6814
             i:=Clipboard^.SelStart.X;
 
6815
             if i>0 then
 
6816
              s:=copy(s,i+1,high(s));
 
6817
             if (Clipboard^.SelStart.Y=Clipboard^.SelEnd.Y) then
 
6818
               begin
 
6819
                 i:=Clipboard^.SelEnd.X-i;
 
6820
                 s:=copy(s,1,i);
 
6821
               end;
 
6822
             for i:=1 to length(s) do
 
6823
               begin
 
6824
                 s2:=Data^+s[i];
 
6825
                 If not assigned(validator) or
 
6826
                    Validator^.IsValidInput(s2,False)  then
 
6827
                   Begin
 
6828
                     Event.What:=evKeyDown;
 
6829
                     Event.CharCode:=s[i];
 
6830
                     Event.Scancode:=0;
 
6831
                     Inherited HandleEvent(Event);
 
6832
                   End;
 
6833
               end;
 
6834
             ClearEvent(Event);
 
6835
           end
 
6836
         else if (Event.KeyCode=kbCtrlIns)  and
 
6837
                 Assigned(Clipboard) then
 
6838
           { Copy to clipboard }
 
6839
           begin
 
6840
             s:=GetStr(Data);
 
6841
             s:=copy(s,selstart+1,selend-selstart);
 
6842
             Clipboard^.SelStart:=Clipboard^.CurPos;
 
6843
             Clipboard^.InsertText(s);
 
6844
             Clipboard^.SelEnd:=Clipboard^.CurPos;
 
6845
             ClearEvent(Event);
 
6846
           end
 
6847
         else if (Event.KeyCode=kbShiftDel)  and
 
6848
                 Assigned(Clipboard) then
 
6849
           { Cut to clipboard }
 
6850
           begin
 
6851
             s:=GetStr(Data);
 
6852
             s:=copy(s,selstart+1,selend-selstart);
 
6853
             Clipboard^.SelStart:=Clipboard^.CurPos;
 
6854
             Clipboard^.InsertText(s);
 
6855
             Clipboard^.SelEnd:=Clipboard^.CurPos;
 
6856
             s2:=GetStr(Data);
 
6857
             { now remove the selected part }
 
6858
             Event.keyCode:=kbDel;
 
6859
             inherited HandleEvent(Event);
 
6860
             ClearEvent(Event);
 
6861
           end
 
6862
         else
 
6863
           Inherited HandleEvent(Event);
 
6864
       End
 
6865
     else
 
6866
       Inherited HandleEvent(Event);
 
6867
end;
 
6868
 
 
6869
function CreateFindDialog: PDialog;
 
6870
var R,R1,R2: TRect;
 
6871
    D: PDialog;
 
6872
    IL1: PEditorInputLine;
 
6873
    Control : PView;
 
6874
    CB1: PCheckBoxes;
 
6875
    RB1,RB2,RB3: PRadioButtons;
 
6876
begin
 
6877
  R.Assign(0,0,56,15);
 
6878
  New(D, Init(R, dialog_find));
 
6879
  with D^ do
 
6880
  begin
 
6881
    Options:=Options or ofCentered;
 
6882
    GetExtent(R); R.Grow(-3,-2);
 
6883
    R1.Copy(R); R1.B.X:=17; R1.B.Y:=R1.A.Y+1;
 
6884
    R2.Copy(R); R2.B.X:=R2.B.X-3;R2.A.X:=17; R2.B.Y:=R2.A.Y+1;
 
6885
    New(IL1, Init(R2, FindStrSize));
 
6886
    IL1^.Data^:=FindStr;
 
6887
    Insert(IL1);
 
6888
    Insert(New(PLabel, Init(R1, label_find_texttofind, IL1)));
 
6889
    R1.Assign(R2.B.X, R2.A.Y, R2.B.X+3, R2.B.Y);
 
6890
    Control := New(PHistory, Init(R1, IL1, TextFindId));
 
6891
    Insert(Control);
 
6892
 
 
6893
    R1.Copy(R); Inc(R1.A.Y,2); R1.B.Y:=R1.A.Y+1; R1.B.X:=R1.A.X+(R1.B.X-R1.A.X) div 2-1;
 
6894
    R2.Copy(R1); R2.Move(0,1);
 
6895
    R2.B.Y:=R2.A.Y+{$ifdef TEST_REGEXP}3{$else}2{$endif};
 
6896
    New(CB1, Init(R2,
 
6897
      NewSItem(label_find_casesensitive,
 
6898
      NewSItem(label_find_wholewordsonly,
 
6899
{$ifdef TEST_REGEXP}
 
6900
      NewSItem(label_find_useregexp,
 
6901
{$endif TEST_REGEXP}
 
6902
      nil)))){$ifdef TEST_REGEXP}){$endif TEST_REGEXP};
 
6903
    Insert(CB1);
 
6904
    Insert(New(PLabel, Init(R1, label_find_options, CB1)));
 
6905
 
 
6906
    R1.Copy(R); Inc(R1.A.Y,2); R1.B.Y:=R1.A.Y+1; R1.A.X:=R1.B.X-(R1.B.X-R1.A.X) div 2+1;
 
6907
    R2.Copy(R1); R2.Move(0,1); R2.B.Y:=R2.A.Y+2;
 
6908
    New(RB1, Init(R2,
 
6909
      NewSItem(label_find_forward,
 
6910
      NewSItem(label_find_backward,
 
6911
      nil))));
 
6912
    Insert(RB1);
 
6913
    Insert(New(PLabel, Init(R1, label_find_direction, RB1)));
 
6914
 
 
6915
    R1.Copy(R); Inc(R1.A.Y,6); R1.B.Y:=R1.A.Y+1; R1.B.X:=R1.A.X+(R1.B.X-R1.A.X) div 2-1;
 
6916
    R2.Copy(R1); R2.Move(0,1); R2.B.Y:=R2.A.Y+2;
 
6917
    New(RB2, Init(R2,
 
6918
      NewSItem(label_find_global,
 
6919
      NewSItem(label_find_selectedtext,
 
6920
      nil))));
 
6921
    Insert(RB2);
 
6922
    Insert(New(PLabel, Init(R1, label_find_scope, RB2)));
 
6923
 
 
6924
    R1.Copy(R); Inc(R1.A.Y,6); R1.B.Y:=R1.A.Y+1; R1.A.X:=R1.B.X-(R1.B.X-R1.A.X) div 2+1;
 
6925
    R2.Copy(R1); R2.Move(0,1); R2.B.Y:=R2.A.Y+2;
 
6926
    New(RB3, Init(R2,
 
6927
      NewSItem(label_find_fromcursor,
 
6928
      NewSItem(label_find_entirescope,
 
6929
      nil))));
 
6930
    Insert(RB3);
 
6931
    Insert(New(PLabel, Init(R1, label_find_origin, RB3)));
 
6932
 
 
6933
    GetExtent(R); R.Grow(-13,-1); R.A.Y:=R.B.Y-2; R.B.X:=R.A.X+10;
 
6934
    Insert(New(PButton, Init(R, btn_OK, cmOK, bfDefault)));
 
6935
    R.Move(19,0);
 
6936
    Insert(New(PButton, Init(R, btn_Cancel, cmCancel, bfNormal)));
 
6937
  end;
 
6938
  IL1^.Select;
 
6939
  CreateFindDialog := D;
 
6940
end;
 
6941
 
 
6942
function CreateReplaceDialog: PDialog;
 
6943
var R,R1,R2: TRect;
 
6944
    D: PDialog;
 
6945
    Control : PView;
 
6946
    IL1: PEditorInputLine;
 
6947
    IL2: PEditorInputLine;
 
6948
    CB1: PCheckBoxes;
 
6949
    RB1,RB2,RB3: PRadioButtons;
 
6950
begin
 
6951
  R.Assign(0,0,56,18);
 
6952
  New(D, Init(R, dialog_replace));
 
6953
  with D^ do
 
6954
  begin
 
6955
    Options:=Options or ofCentered;
 
6956
    GetExtent(R); R.Grow(-3,-2);
 
6957
    R1.Copy(R); R1.B.X:=17; R1.B.Y:=R1.A.Y+1;
 
6958
    R2.Copy(R); R2.B.X:=R2.B.X-3;R2.A.X:=17; R2.B.Y:=R2.A.Y+1;
 
6959
    New(IL1, Init(R2, FindStrSize));
 
6960
    IL1^.Data^:=FindStr;
 
6961
    Insert(IL1);
 
6962
    Insert(New(PLabel, Init(R1, label_replace_texttofind, IL1)));
 
6963
    R1.Assign(R2.B.X, R2.A.Y, R2.B.X+3, R2.B.Y);
 
6964
    Control := New(PHistory, Init(R1, IL1, TextFindId));
 
6965
    Insert(Control);
 
6966
 
 
6967
    R1.Copy(R); R1.Move(0,2); R1.B.X:=17; R1.B.Y:=R1.A.Y+1;
 
6968
    R2.Copy(R); R2.Move(0,2);R2.B.X:=R2.B.X-3;
 
6969
    R2.A.X:=17; R2.B.Y:=R2.A.Y+1;
 
6970
    New(IL2, Init(R2, FindStrSize));
 
6971
    IL2^.Data^:=ReplaceStr;
 
6972
    Insert(IL2);
 
6973
    Insert(New(PLabel, Init(R1, label_replace_newtext, IL2)));
 
6974
    R1.Assign(R2.B.X, R2.A.Y, R2.B.X+3, R2.B.Y);
 
6975
    Control := New(PHistory, Init(R1, IL2, TextReplaceId));
 
6976
    Insert(Control);
 
6977
 
 
6978
    R1.Copy(R); Inc(R1.A.Y,4); R1.B.Y:=R1.A.Y+1; R1.B.X:=R1.A.X+(R1.B.X-R1.A.X) div 2-1;
 
6979
    R2.Copy(R1); R2.Move(0,1);
 
6980
    R2.B.Y:=R2.A.Y+{$ifdef TEST_REGEXP}4{$else}3{$endif};
 
6981
    New(CB1, Init(R2,
 
6982
      NewSItem(label_replace_casesensitive,
 
6983
      NewSItem(label_replace_wholewordsonly,
 
6984
      NewSItem(label_replace_promptonreplace,
 
6985
{$ifdef TEST_REGEXP}
 
6986
      NewSItem(label_find_useregexp,
 
6987
{$endif TEST_REGEXP}
 
6988
      nil))))){$ifdef TEST_REGEXP}){$endif TEST_REGEXP};
 
6989
    Insert(CB1);
 
6990
    Insert(New(PLabel, Init(R1, label_replace_options, CB1)));
 
6991
 
 
6992
    R1.Copy(R); Inc(R1.A.Y,4); R1.B.Y:=R1.A.Y+1; R1.A.X:=R1.B.X-(R1.B.X-R1.A.X) div 2+1;
 
6993
    R2.Copy(R1); R2.Move(0,1); R2.B.Y:=R2.A.Y+2;
 
6994
    New(RB1, Init(R2,
 
6995
      NewSItem(label_replace_forward,
 
6996
      NewSItem(label_replace_backward,
 
6997
      nil))));
 
6998
    Insert(RB1);
 
6999
    Insert(New(PLabel, Init(R1, label_replace_direction, RB1)));
 
7000
 
 
7001
    R1.Copy(R); Inc(R1.A.Y,9); R1.B.Y:=R1.A.Y+1; R1.B.X:=R1.A.X+(R1.B.X-R1.A.X) div 2-1;
 
7002
    R2.Copy(R1); R2.Move(0,1); R2.B.Y:=R2.A.Y+2;
 
7003
    New(RB2, Init(R2,
 
7004
      NewSItem(label_replace_global,
 
7005
      NewSItem(label_replace_selectedtext,
 
7006
      nil))));
 
7007
    Insert(RB2);
 
7008
    Insert(New(PLabel, Init(R1, label_replace_scope, RB2)));
 
7009
 
 
7010
    R1.Copy(R); Inc(R1.A.Y,9); R1.B.Y:=R1.A.Y+1; R1.A.X:=R1.B.X-(R1.B.X-R1.A.X) div 2+1;
 
7011
    R2.Copy(R1); R2.Move(0,1); R2.B.Y:=R2.A.Y+2;
 
7012
    New(RB3, Init(R2,
 
7013
      NewSItem(label_replace_fromcursor,
 
7014
      NewSItem(label_replace_entirescope,
 
7015
      nil))));
 
7016
    Insert(RB3);
 
7017
    Insert(New(PLabel, Init(R1, label_replace_origin, RB3)));
 
7018
 
 
7019
    GetExtent(R); R.Grow(-13,-1); R.A.Y:=R.B.Y-2; R.B.X:=R.A.X+10; R.Move(-10,0);
 
7020
    Insert(New(PButton, Init(R, btn_OK, cmOK, bfDefault)));
 
7021
    R.Move(11,0); R.B.X:=R.A.X+14;
 
7022
    Insert(New(PButton, Init(R, btn_replace_changeall, cmYes, bfNormal)));
 
7023
    R.Move(15,0); R.B.X:=R.A.X+10;
 
7024
    Insert(New(PButton, Init(R, btn_Cancel, cmCancel, bfNormal)));
 
7025
  end;
 
7026
  IL1^.Select;
 
7027
  CreateReplaceDialog := D;
 
7028
end;
 
7029
 
 
7030
function CreateGotoLineDialog(Info: pointer): PDialog;
 
7031
var D: PDialog;
 
7032
    R,R1,R2: TRect;
 
7033
    Control : PView;
 
7034
    IL: PEditorInputLine;
 
7035
begin
 
7036
  R.Assign(0,0,40,7);
 
7037
  New(D, Init(R, dialog_gotoline));
 
7038
  with D^ do
 
7039
  begin
 
7040
    Options:=Options or ofCentered;
 
7041
    GetExtent(R); R.Grow(-3,-2); R.B.Y:=R.A.Y+1;
 
7042
    R1.Copy(R); R1.B.X:=27; R2.Copy(R);
 
7043
    R2.B.X:=R2.B.X-3;R2.A.X:=27;
 
7044
    New(IL, Init(R2,5));
 
7045
    with TGotoLineDialogRec(Info^) do
 
7046
    IL^.SetValidator(New(PRangeValidator, Init(1, Lines)));
 
7047
    Insert(IL);
 
7048
    Insert(New(PLabel, Init(R1, label_gotoline_linenumber, IL)));
 
7049
    R1.Assign(R2.B.X, R2.A.Y, R2.B.X+3, R2.B.Y);
 
7050
    Control := New(PHistory, Init(R1, IL, GotoId));
 
7051
    Insert(Control);
 
7052
 
 
7053
    GetExtent(R); R.Grow(-8,-1); R.A.Y:=R.B.Y-2; R.B.X:=R.A.X+10;
 
7054
    Insert(New(PButton, Init(R, btn_OK, cmOK, bfDefault)));
 
7055
    R.Move(15,0);
 
7056
    Insert(New(PButton, Init(R, btn_Cancel, cmCancel, bfNormal)));
 
7057
  end;
 
7058
  IL^.Select;
 
7059
  CreateGotoLineDialog:=D;
 
7060
end;
 
7061
 
 
7062
function StdEditorDialog(Dialog: Integer; Info: Pointer): Word;
 
7063
var
 
7064
  R: TRect;
 
7065
  T: TPoint;
 
7066
  Re: word;
 
7067
  Name: string;
 
7068
  DriveNumber : byte;
 
7069
  StoreDir,StoreDir2 : DirStr;
 
7070
  Title,DefExt: string;
 
7071
  AskOW: boolean;
 
7072
begin
 
7073
  case Dialog of
 
7074
    edOutOfMemory:
 
7075
      StdEditorDialog := AdvMessageBox(msg_notenoughmemoryforthisoperation,
 
7076
   nil, mfInsertInApp+ mfError + mfOkButton);
 
7077
    edReadError:
 
7078
      StdEditorDialog := AdvMessageBox(msg_errorreadingfile,
 
7079
   @Info, mfInsertInApp+ mfError + mfOkButton);
 
7080
    edWriteError:
 
7081
      StdEditorDialog := AdvMessageBox(msg_errorwritingfile,
 
7082
   @Info, mfInsertInApp+ mfError + mfOkButton);
 
7083
    edSaveError:
 
7084
      StdEditorDialog := AdvMessageBox(msg_errorsavingfile,
 
7085
   @Info, mfInsertInApp+ mfError + mfOkButton);
 
7086
    edCreateError:
 
7087
      StdEditorDialog := AdvMessageBox(msg_errorcreatingfile,
 
7088
   @Info, mfInsertInApp+ mfError + mfOkButton);
 
7089
    edSaveModify:
 
7090
      StdEditorDialog := AdvMessageBox(msg_filehasbeenmodifiedsave,
 
7091
   @Info, mfInsertInApp+ mfInformation + mfYesNoCancel);
 
7092
    edSaveUntitled:
 
7093
      StdEditorDialog := AdvMessageBox(msg_saveuntitledfile,
 
7094
   nil, mfInsertInApp+ mfInformation + mfYesNoCancel);
 
7095
    edChangedOnloading:
 
7096
      StdEditorDialog := AdvMessageBox(msg_filehadtoolonglines,
 
7097
   Info, mfInsertInApp+ mfOKButton + mfInformation);
 
7098
    edFileOnDiskChanged:
 
7099
      StdEditorDialog := AdvMessageBox(msg_filewasmodified,
 
7100
   @info, mfInsertInApp+ mfInformation + mfYesNoCancel);
 
7101
    edReloadDiskmodifiedFile:
 
7102
      StdEditorDialog := AdvMessageBox(msg_reloaddiskmodifiedfile,
 
7103
   @info, mfInsertInApp+ mfInformation + mfYesNoCancel);
 
7104
    edReloadDiskAndIDEModifiedFile:
 
7105
      StdEditorDialog := AdvMessageBox(msg_reloaddiskandidemodifiedfile,
 
7106
   @info, mfInsertInApp+ mfInformation + mfYesNoCancel);
 
7107
    edSaveAs,edWriteBlock,edReadBlock:
 
7108
      begin
 
7109
        Name:=PString(Info)^;
 
7110
        GetDir(0,StoreDir);
 
7111
        DriveNumber:=0;
 
7112
        if (Length(FileDir)>1) and (FileDir[2]=':') then
 
7113
          begin
 
7114
            { does not assume that lowercase are greater then uppercase ! }
 
7115
            if (FileDir[1]>='a') and (FileDir[1]<='z') then
 
7116
              DriveNumber:=Ord(FileDir[1])-ord('a')+1
 
7117
            else
 
7118
              DriveNumber:=Ord(FileDir[1])-ord('A')+1;
 
7119
            GetDir(DriveNumber,StoreDir2);
 
7120
            {$I-}
 
7121
            ChDir(Copy(FileDir,1,2));
 
7122
            EatIO;
 
7123
            {$I+}
 
7124
          end;
 
7125
        if FileDir<>'' then
 
7126
          begin
 
7127
            {$I-}
 
7128
            ChDir(TrimEndSlash(FileDir));
 
7129
            EatIO;
 
7130
            {$I+}
 
7131
          end;
 
7132
        case Dialog of
 
7133
          edSaveAs     :
 
7134
            begin
 
7135
              Title:=dialog_savefileas;
 
7136
              DefExt:='*'+DefaultSaveExt;
 
7137
            end;
 
7138
          edWriteBlock :
 
7139
            begin
 
7140
              Title:=dialog_writeblocktofile;
 
7141
              DefExt:='*.*';
 
7142
            end;
 
7143
          edReadBlock  :
 
7144
            begin
 
7145
              Title:=dialog_readblockfromfile;
 
7146
              DefExt:='*.*';
 
7147
            end;
 
7148
        else begin Title:='???'; DefExt:=''; end;
 
7149
        end;
 
7150
        Re:=Application^.ExecuteDialog(New(PFileDialog, Init(DefExt,
 
7151
          Title, label_name, fdOkButton, FileId)), @Name);
 
7152
        case Dialog of
 
7153
          edSaveAs     :
 
7154
            begin
 
7155
              if ExtOf(Name)='' then
 
7156
                Name:=Name+DefaultSaveExt;
 
7157
              AskOW:=(Name<>PString(Info)^);
 
7158
            end;
 
7159
          edWriteBlock :
 
7160
            begin
 
7161
              if ExtOf(Name)='' then
 
7162
                Name:=Name+DefaultSaveExt;
 
7163
              AskOW:=true;
 
7164
            end;
 
7165
          edReadBlock  : AskOW:=false;
 
7166
        else AskOW:=true;
 
7167
        end;
 
7168
        if (Re<>cmCancel) and AskOW then
 
7169
          begin
 
7170
            FileDir:=DirOf(FExpand(Name));
 
7171
            if ExistsFile(Name) then
 
7172
              if EditorDialog(edReplaceFile,@Name)<>cmYes then
 
7173
                Re:=cmCancel;
 
7174
          end;
 
7175
        if DriveNumber<>0 then
 
7176
          ChDir(StoreDir2);
 
7177
{$ifndef FPC}
 
7178
        if (Length(StoreDir)>1) and (StoreDir[2]=':') then
 
7179
          ChDir(Copy(StoreDir,1,2));
 
7180
{$endif not FPC}
 
7181
        if StoreDir<>'' then
 
7182
          ChDir(TrimEndSlash(StoreDir));
 
7183
 
 
7184
        if Re<>cmCancel then
 
7185
          PString(Info)^:=Name;
 
7186
        StdEditorDialog := Re;
 
7187
      end;
 
7188
    edGotoLine:
 
7189
      StdEditorDialog :=
 
7190
   Application^.ExecuteDialog(CreateGotoLineDialog(Info), Info);
 
7191
    edFind:
 
7192
      StdEditorDialog :=
 
7193
   Application^.ExecuteDialog(CreateFindDialog, Info);
 
7194
    edSearchFailed:
 
7195
      StdEditorDialog := AdvMessageBox(msg_searchstringnotfound,
 
7196
   nil, mfInsertInApp+ mfError + mfOkButton);
 
7197
    edReplace:
 
7198
      StdEditorDialog :=
 
7199
   Application^.ExecuteDialog(CreateReplaceDialog, Info);
 
7200
    edReplacePrompt:
 
7201
      begin
 
7202
   { Avoid placing the dialog on the same line as the cursor }
 
7203
   R.Assign(0, 1, 40, 8);
 
7204
   R.Move((Desktop^.Size.X - R.B.X) div 2, 0);
 
7205
   Desktop^.MakeGlobal(R.B, T);
 
7206
   Inc(T.Y);
 
7207
   if PPoint(Info)^.Y <= T.Y then
 
7208
     R.Move(0, Desktop^.Size.Y - R.B.Y - 2);
 
7209
   StdEditorDialog := AdvMessageBoxRect(R, msg_replacethisoccourence,
 
7210
     nil, mfInsertInApp+ mfYesNoCancel + mfInformation);
 
7211
      end;
 
7212
    edReplaceFile :
 
7213
      StdEditorDialog :=
 
7214
   AdvMessageBox(msg_fileexistsoverwrite,@Info,mfInsertInApp+mfConfirmation+
 
7215
     mfYesButton+mfNoButton);
 
7216
  end;
 
7217
end;
 
7218
 
 
7219
procedure RegisterWEditor;
 
7220
begin
 
7221
{$ifndef NOOBJREG}
 
7222
{$endif}
 
7223
end;
 
7224
 
 
7225
END.