wcedit.pas 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758
  1. {
  2. $Id$
  3. This file is part of the Free Pascal Integrated Development Environment
  4. Copyright (c) 1998-2000 by Berczi Gabor
  5. Code editor template objects
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. {$i globdir.inc}
  13. unit WCEdit;
  14. interface
  15. uses Objects,Drivers,Views,
  16. { necessary for ExistsFile }FPUtils,
  17. WUtils,WEditor;
  18. type
  19. PIndicator = ^TIndicator;
  20. TIndicator = object(TView)
  21. Location: TPoint;
  22. Modified : Boolean;
  23. {$ifdef debug}
  24. StoreUndo : Boolean;
  25. SyntaxComplete : boolean;
  26. UseTabs : Boolean;
  27. {$endif debug}
  28. constructor Init(var Bounds: TRect);
  29. procedure Draw; virtual;
  30. function GetPalette: PPalette; virtual;
  31. procedure SetState(AState: Word; Enable: Boolean); virtual;
  32. procedure SetValue(ALocation: TPoint; AModified: Boolean);
  33. end;
  34. PLine = ^TLine;
  35. TLine = object(TCustomLine)
  36. public { internal use only! }
  37. Text : PString;
  38. EditorInfos : PEditorLineInfoCollection;
  39. Flags : longint;
  40. Owner : PCustomCodeEditorCore;
  41. procedure AddEditorInfo(Index: sw_integer; AEditor: PCustomCodeEditor); virtual;
  42. procedure RemoveEditorInfo(AEditor: PCustomCodeEditor); virtual;
  43. public
  44. constructor Init(AOwner: PCustomCodeEditorCore; const AText: string; AFlags: longint);
  45. function GetText: string; virtual;
  46. procedure SetText(const AText: string); virtual;
  47. function GetEditorInfo(Editor: PCustomCodeEditor): PEditorLineInfo; virtual;
  48. function GetFlags: longint; virtual;
  49. procedure SetFlags(AFlags: longint); virtual;
  50. destructor Done; virtual;
  51. end;
  52. PCodeEditorCore = ^TCodeEditorCore;
  53. TCodeEditorCore = object(TCustomCodeEditorCore)
  54. {$ifdef TP}public{$else}protected{$endif}
  55. Lines : PLineCollection;
  56. CanUndo : Boolean;
  57. StoreUndo : boolean;
  58. Modified : Boolean;
  59. ReadOnly : Boolean;
  60. TabSize : integer;
  61. {$ifdef UNDO}public{$endif}
  62. UndoList : PEditorActionCollection;
  63. RedoList : PEditorActionCollection;
  64. public
  65. constructor Init;
  66. destructor Done; virtual;
  67. public
  68. function GetModified: boolean; virtual;
  69. procedure SetModified(AModified: boolean); virtual;
  70. function GetTabSize: integer; virtual;
  71. procedure SetTabSize(ATabSize: integer); virtual;
  72. function GetStoreUndo: boolean; virtual;
  73. procedure SetStoreUndo(AStore: boolean); virtual;
  74. function GetSyntaxCompleted: boolean; virtual;
  75. procedure SetSyntaxCompleted(SC : boolean); virtual;
  76. function GetLastSyntaxedLine: sw_integer; virtual;
  77. procedure SetLastSyntaxedLine(ALine: sw_integer); virtual;
  78. public
  79. { Storage }
  80. {$ifdef TP}public{$else}protected{$endif}
  81. { Text & info storage abstraction }
  82. procedure ISetLineFlagState(Binding: PEditorBinding; LineNo: sw_integer; Flag: longint; ASet: boolean); virtual;
  83. procedure IGetDisplayTextFormat(Binding: PEditorBinding; LineNo: sw_integer;var DT,DF:string); virtual;
  84. function IGetLineFormat(Binding: PEditorBinding; LineNo: sw_integer): string; virtual;
  85. procedure ISetLineFormat(Binding: PEditorBinding; LineNo: sw_integer;const S: string); virtual;
  86. public
  87. { Text & info storage abstraction }
  88. function GetLineCount: sw_integer; virtual;
  89. function GetLine(LineNo: sw_integer): PCustomLine; virtual;
  90. function GetLineText(LineNo: sw_integer): string; virtual;
  91. procedure SetDisplayText(I: sw_integer;const S: string); virtual;
  92. function GetDisplayText(I: sw_integer): string; virtual;
  93. procedure SetLineText(I: sw_integer;const S: string); virtual;
  94. procedure DeleteAllLines; virtual;
  95. procedure DeleteLine(I: sw_integer); virtual;
  96. procedure InsertLine(LineNo: sw_integer; const S: string); virtual;
  97. procedure AddLine(const S: string); virtual;
  98. procedure GetContent(ALines: PUnsortedStringCollection); virtual;
  99. procedure SetContent(ALines: PUnsortedStringCollection); virtual;
  100. public
  101. { Undo info storage }
  102. procedure AddAction(AAction: byte; AStartPos, AEndPos: TPoint; AText: string); virtual;
  103. procedure AddGroupedAction(AAction : byte); virtual;
  104. procedure CloseGroupedAction(AAction : byte); virtual;
  105. function GetUndoActionCount: sw_integer; virtual;
  106. function GetRedoActionCount: sw_integer; virtual;
  107. private
  108. procedure LinesInsert(Idx: sw_integer; Line: PLine);
  109. end;
  110. PCodeEditor = ^TCodeEditor;
  111. TCodeEditor = object(TCustomCodeEditor)
  112. Core : PCodeEditorCore;
  113. Flags : longint;
  114. Indicator : PIndicator;
  115. HighlightRow: sw_integer;
  116. DebuggerRow: sw_integer;
  117. CodeCompleteFrag: PString;
  118. CodeCompleteWord: PString;
  119. ReadOnly : boolean;
  120. CompleteState: TCompleteState;
  121. ErrorMessage: PString;
  122. IndicatorDrawCalled : boolean;
  123. constructor Init(var Bounds: TRect; AHScrollBar, AVScrollBar:
  124. PScrollBar; AIndicator: PIndicator; ACore: PCodeEditorCore);
  125. public
  126. procedure DrawIndicator; virtual;
  127. public
  128. function GetFlags: longint; virtual;
  129. procedure SetFlags(AFlags: longint); virtual;
  130. function GetModified: boolean; virtual;
  131. procedure SetModified(AModified: boolean); virtual;
  132. function GetStoreUndo: boolean; virtual;
  133. procedure SetStoreUndo(AStore: boolean); virtual;
  134. function GetSyntaxCompleted: boolean; virtual;
  135. procedure SetSyntaxCompleted(SC : boolean); virtual;
  136. function GetLastSyntaxedLine: sw_integer; virtual;
  137. procedure SetLastSyntaxedLine(ALine: sw_integer); virtual;
  138. function GetTabSize: integer; virtual;
  139. procedure SetTabSize(ATabSize: integer); virtual;
  140. function IsReadOnly: boolean; virtual;
  141. public
  142. procedure UpdateIndicator; virtual;
  143. procedure ModifiedChanged; virtual;
  144. procedure PositionChanged; virtual;
  145. procedure LimitsChanged; virtual;
  146. function IsClipboard: Boolean; virtual;
  147. function LoadFromStream(Stream: PStream): boolean; virtual;
  148. function SaveToStream(Stream: PStream): boolean; virtual;
  149. function SaveAreaToStream(Stream: PStream; StartP,EndP: TPoint): boolean;virtual;
  150. destructor Done; virtual;
  151. public
  152. { ChangedLine : sw_integer;}
  153. { Text & info storage abstraction }
  154. function GetLineCount: sw_integer; virtual;
  155. function GetLine(LineNo: sw_integer): PCustomLine; virtual;
  156. function CharIdxToLinePos(Line,CharIdx: sw_integer): sw_integer; virtual;
  157. function LinePosToCharIdx(Line,X: sw_integer): sw_integer; virtual;
  158. function GetLineText(I: sw_integer): string; virtual;
  159. procedure SetDisplayText(I: sw_integer;const S: string); virtual;
  160. function GetDisplayText(I: sw_integer): string; virtual;
  161. procedure SetLineText(I: sw_integer;const S: string); virtual;
  162. procedure GetDisplayTextFormat(I: sw_integer;var DT,DF:string); virtual;
  163. function GetLineFormat(I: sw_integer): string; virtual;
  164. procedure SetLineFormat(I: sw_integer;const S: string); virtual;
  165. procedure DeleteAllLines; virtual;
  166. procedure DeleteLine(I: sw_integer); virtual;
  167. procedure InsertLine(LineNo: sw_integer; const S: string); virtual;
  168. procedure AddLine(const S: string); virtual;
  169. function GetErrorMessage: string; virtual;
  170. procedure SetErrorMessage(const S: string); virtual;
  171. procedure GetContent(ALines: PUnsortedStringCollection); virtual;
  172. procedure SetContent(ALines: PUnsortedStringCollection); virtual;
  173. procedure Lock; virtual;
  174. procedure UnLock; virtual;
  175. public
  176. { CodeComplete support }
  177. function GetCodeCompleteWord: string; virtual;
  178. procedure SetCodeCompleteWord(const S: string); virtual;
  179. function GetCodeCompleteFrag: string; virtual;
  180. procedure SetCodeCompleteFrag(const S: string); virtual;
  181. function GetCompleteState: TCompleteState; virtual;
  182. procedure SetCompleteState(AState: TCompleteState); virtual;
  183. public
  184. { Syntax highlight }
  185. {a}function UpdateAttrs(FromLine: sw_integer; Attrs: byte): sw_integer; virtual;
  186. {a}function UpdateAttrsRange(FromLine, ToLine: sw_integer; Attrs: byte): sw_integer; virtual;
  187. public
  188. { Undo info storage }
  189. procedure AddAction(AAction: byte; AStartPos, AEndPos: TPoint; AText: string); virtual;
  190. procedure AddGroupedAction(AAction : byte); virtual;
  191. procedure CloseGroupedAction(AAction : byte); virtual;
  192. function GetUndoActionCount: sw_integer; virtual;
  193. function GetRedoActionCount: sw_integer; virtual;
  194. procedure JumpToLastCursorPos; virtual;
  195. procedure Undo; virtual;
  196. procedure Redo; virtual;
  197. end;
  198. PFileEditor = ^TFileEditor;
  199. TFileEditor = object(TCodeEditor)
  200. FileName: string;
  201. constructor Init(var Bounds: TRect; AHScrollBar, AVScrollBar:
  202. PScrollBar; AIndicator: PIndicator; ACore: PCodeEditorCore; const AFileName: string);
  203. function Save: Boolean; virtual;
  204. function SaveAs: Boolean; virtual;
  205. function SaveAsk(Force: boolean): Boolean; virtual;
  206. function LoadFile: boolean; virtual;
  207. function SaveFile: boolean; virtual;
  208. function Valid(Command: Word): Boolean; virtual;
  209. procedure HandleEvent(var Event: TEvent); virtual;
  210. function ShouldSave: boolean; virtual;
  211. function IsChangedOnDisk : boolean;
  212. public
  213. procedure BindingsChanged; virtual;
  214. private
  215. OnDiskLoadTime : longint;
  216. end;
  217. function DefUseSyntaxHighlight(Editor: PFileEditor): boolean;
  218. function DefUseTabsPattern(Editor: PFileEditor): boolean;
  219. const
  220. DefaultCodeEditorFlags : longint =
  221. efBackupFiles+efInsertMode+efAutoIndent+efPersistentBlocks+
  222. {efUseTabCharacters+}efBackSpaceUnindents+efSyntaxHighlight+
  223. efExpandAllTabs+efCodeComplete;
  224. DefaultTabSize : integer = 8;
  225. UseSyntaxHighlight : function(Editor: PFileEditor): boolean = DefUseSyntaxHighlight;
  226. UseTabsPattern : function(Editor: PFileEditor): boolean = DefUseTabsPattern;
  227. procedure RegisterWCEdit;
  228. implementation
  229. uses Dos,
  230. Commands,App,WViews;
  231. {$ifndef NOOBJREG}
  232. const
  233. RIndicator: TStreamRec = (
  234. ObjType: 1100;
  235. VmtLink: Ofs(TypeOf(TIndicator)^);
  236. Load: @TIndicator.Load;
  237. Store: @TIndicator.Store
  238. );
  239. RCodeEditor: TStreamRec = (
  240. ObjType: 1101;
  241. VmtLink: Ofs(TypeOf(TCodeEditor)^);
  242. Load: @TCodeEditor.Load;
  243. Store: @TCodeEditor.Store
  244. );
  245. RFileEditor: TStreamRec = (
  246. ObjType: 1102;
  247. VmtLink: Ofs(TypeOf(TFileEditor)^);
  248. Load: @TFileEditor.Load;
  249. Store: @TFileEditor.Store
  250. );
  251. {$endif}
  252. constructor TLine.Init(AOwner: PCustomCodeEditorCore; const AText: string; AFlags: longint);
  253. begin
  254. inherited Init(AText,AFlags);
  255. New(EditorInfos, Init(10,10));
  256. Owner:=AOwner;
  257. end;
  258. procedure TLine.AddEditorInfo(Index: sw_integer; AEditor: PCustomCodeEditor);
  259. begin
  260. EditorInfos^.AtInsert(Index,New(PEditorLineInfo, Init(AEditor)));
  261. end;
  262. procedure TLine.RemoveEditorInfo(AEditor: PCustomCodeEditor);
  263. var E: PEditorLineInfo;
  264. begin
  265. E:=GetEditorInfo(AEditor);
  266. EditorInfos^.Free(E);
  267. end;
  268. function TLine.GetText: string;
  269. begin
  270. GetText:=GetStr(Text);
  271. end;
  272. procedure TLine.SetText(const AText: string);
  273. begin
  274. SetStr(Text,AText);
  275. end;
  276. function TLine.GetEditorInfo(Editor: PCustomCodeEditor): PEditorLineInfo;
  277. function Match(P: PEditorLineInfo): boolean; {$ifdef TP}far;{$endif}
  278. begin
  279. Match:=P^.Editor=Editor;
  280. end;
  281. begin
  282. GetEditorInfo:=EditorInfos^.FirstThat(@Match);
  283. end;
  284. function TLine.GetFlags: longint;
  285. begin
  286. GetFlags:=Flags;
  287. end;
  288. procedure TLine.SetFlags(AFlags: longint);
  289. begin
  290. Flags:=AFlags;
  291. if Assigned(Owner) then
  292. Owner^.ContentsChanged;
  293. end;
  294. destructor TLine.Done;
  295. begin
  296. if Assigned(Text) then DisposeStr(Text); Text:=nil;
  297. if Assigned(EditorInfos) then Dispose(EditorInfos, Done); EditorInfos:=nil;
  298. inherited Done;
  299. end;
  300. constructor TCodeEditorCore.Init;
  301. begin
  302. inherited Init;
  303. {$ifndef Undo}
  304. StoreUndo:=false;
  305. {$else Undo}
  306. StoreUndo:=true;
  307. {$endif def Undo}
  308. new(UndoList,init(500,1000));
  309. new(RedoList,init(500,1000));
  310. New(Lines, Init(500,1000));
  311. TabSize:=DefaultTabSize;
  312. end;
  313. function TCodeEditorCore.GetLineCount: sw_integer;
  314. begin
  315. GetLineCount:=Lines^.Count;
  316. end;
  317. function TCodeEditorCore.GetLine(LineNo: sw_integer): PCustomLine;
  318. begin
  319. GetLine:=Lines^.At(LineNo);
  320. end;
  321. function TCodeEditorCore.GetModified: boolean;
  322. begin
  323. GetModified:=Modified;
  324. end;
  325. procedure TCodeEditorCore.SetModified(AModified: boolean);
  326. begin
  327. if AModified<>Modified then
  328. begin
  329. Modified:=AModified;
  330. ModifiedChanged;
  331. end;
  332. end;
  333. function TCodeEditorCore.GetStoreUndo: boolean;
  334. begin
  335. GetStoreUndo:=StoreUndo;
  336. end;
  337. procedure TCodeEditorCore.SetStoreUndo(AStore: boolean);
  338. begin
  339. if StoreUndo<>AStore then
  340. begin
  341. StoreUndo:=AStore;
  342. StoreUndoChanged;
  343. end;
  344. end;
  345. function TCodeEditorCore.GetSyntaxCompleted: boolean;
  346. begin
  347. {$ifdef TEST_PARTIAL_SYNTAX}
  348. GetSyntaxCompleted:=SyntaxComplete;
  349. {$else}
  350. GetSyntaxCompleted:=true;
  351. {$endif}
  352. end;
  353. procedure TCodeEditorCore.SetSyntaxCompleted(SC: boolean);
  354. begin
  355. {$ifdef TEST_PARTIAL_SYNTAX}
  356. if SC<>SyntaxComplete then
  357. begin
  358. SyntaxComplete:=SC;
  359. end;
  360. {$endif}
  361. end;
  362. function TCodeEditorCore.GetLastSyntaxedLine: sw_integer;
  363. begin
  364. GetLastSyntaxedLine:=LastSyntaxedLine;
  365. end;
  366. procedure TCodeEditorCore.SetLastSyntaxedLine(ALine: sw_integer);
  367. begin
  368. LastSyntaxedLine:=ALine;
  369. end;
  370. procedure TCodeEditorCore.ISetLineFlagState(Binding: PEditorBinding; LineNo: sw_integer; Flag: longint; ASet: boolean);
  371. var P: PCustomLine;
  372. begin
  373. if LineNo<GetLineCount then
  374. begin
  375. P:=GetLine(LineNo);
  376. P^.SetFlagState(Flag,ASet);
  377. end;
  378. end;
  379. procedure TCodeEditorCore.GetContent(ALines: PUnsortedStringCollection);
  380. procedure AddIt(P: PCustomLine); {$ifndef FPC}far;{$endif}
  381. begin
  382. if Assigned(P) then
  383. ALines^.Insert(NewStr(P^.GetText));
  384. end;
  385. begin
  386. if Assigned(Lines) then
  387. Lines^.ForEach(@AddIt);
  388. end;
  389. procedure TCodeEditorCore.SetContent(ALines: PUnsortedStringCollection);
  390. procedure AddIt(P: PString); {$ifndef FPC}far;{$endif}
  391. begin
  392. AddLine(GetStr(P));
  393. end;
  394. begin
  395. DeleteAllLines;
  396. if Assigned(ALines) then
  397. ALines^.ForEach(@AddIt);
  398. LimitsChanged;
  399. end;
  400. function TCodeEditorCore.GetTabSize: integer;
  401. begin
  402. GetTabSize:=TabSize;
  403. end;
  404. procedure TCodeEditorCore.SetTabSize(ATabSize: integer);
  405. begin
  406. if ATabSize<>TabSize then
  407. begin
  408. TabSize:=ATabSize;
  409. TabSizeChanged;
  410. end;
  411. end;
  412. function TCodeEditorCore.GetLineText(LineNo: sw_integer): string;
  413. var
  414. L : PCustomLine;
  415. begin
  416. GetLineText:='';
  417. if LineNo<Lines^.Count then
  418. begin
  419. L:=Lines^.At(LineNo);
  420. GetLineText:=L^.GetText;
  421. end;
  422. end;
  423. procedure TCodeEditorCore.LinesInsert(Idx: sw_integer; Line: PLine);
  424. var I: sw_integer;
  425. procedure RegLine(P: PEditorBinding); {$ifndef FPC}far;{$endif}
  426. begin
  427. Line^.AddEditorInfo(I,P^.Editor);
  428. Inc(I);
  429. end;
  430. begin
  431. if Idx=-1 then Idx:=Lines^.Count;
  432. I:=0;
  433. Bindings^.ForEach(@RegLine);
  434. Lines^.AtInsert(Idx,Line);
  435. end;
  436. procedure TCodeEditorCore.SetLineText(I: sw_integer;const S: string);
  437. var
  438. L : PCustomLine;
  439. AddCount : Sw_Integer;
  440. begin
  441. AddCount:=0;
  442. while (Lines^.Count<I+1) do
  443. begin
  444. LinesInsert(-1,New(PLine, Init(@Self,'',0)));
  445. Inc(AddCount);
  446. end;
  447. if AddCount>0 then
  448. LimitsChanged;
  449. L:=Lines^.At(I);
  450. L^.SetText(S);
  451. ContentsChanged;
  452. end;
  453. function TCodeEditorCore.GetDisplayText(I: sw_integer): string;
  454. begin
  455. GetDisplayText:=ExtractTabs(GetLineText(I),GetTabSize);
  456. end;
  457. procedure TCodeEditorCore.SetDisplayText(I: sw_integer;const S: string);
  458. begin
  459. { I disagree here
  460. I don't want the editor to change the position of the tabs
  461. in my makefiles !! PM
  462. if FlagSet(efUseTabCharacters) and (TabSize>0) then
  463. SetLineText(I,CompressUsingTabs(S,TabSize))
  464. else }
  465. { ... then you better make this optional - Gabor }
  466. SetLineText(I,S);
  467. end;
  468. procedure TCodeEditorCore.IGetDisplayTextFormat(Binding: PEditorBinding; LineNo: sw_integer;var DT,DF:string);
  469. var
  470. L : PCustomLine;
  471. P,PAdd : SW_Integer;
  472. begin
  473. DF:='';
  474. DT:='';
  475. if LineNo<GetLineCount then
  476. begin
  477. L:=GetLine(LineNo);
  478. DF:=IGetLineFormat(Binding,LineNo);
  479. DT:=L^.GetText;
  480. p:=0;
  481. while p<length(DT) do
  482. begin
  483. inc(p);
  484. if DT[p]=#9 then
  485. begin
  486. PAdd:=TabSize-((p-1) mod TabSize);
  487. if DF<>'' then
  488. DF:=copy(DF,1,P-1)+CharStr(DF[p],PAdd)+copy(DF,P+1,High(DF));
  489. DT:=copy(DT,1,P-1)+CharStr(' ',PAdd)+copy(DT,P+1,High(DF));
  490. inc(P,PAdd-1);
  491. end;
  492. end;
  493. end;
  494. end;
  495. function TCodeEditorCore.IGetLineFormat(Binding: PEditorBinding; LineNo: sw_integer): string;
  496. var P: PCustomLine;
  497. LI: PEditorLineInfo;
  498. S: string;
  499. begin
  500. if LineNo<GetLineCount then P:=GetLine(LineNo) else P:=nil;
  501. if P=nil then LI:=nil else
  502. LI:=P^.GetEditorInfo(Binding^.Editor);
  503. if LI=nil then S:='' else S:=LI^.GetFormat;
  504. IGetLineFormat:=S;
  505. end;
  506. procedure TCodeEditorCore.ISetLineFormat(Binding: PEditorBinding; LineNo: sw_integer;const S: string);
  507. var P: PCustomLine;
  508. LI: PEditorLineInfo;
  509. begin
  510. if LineNo<GetLineCount then
  511. begin
  512. P:=GetLine(LineNo);
  513. if P=nil then LI:=nil else LI:=P^.GetEditorInfo(Binding^.Editor);
  514. if Assigned(LI) then LI^.SetFormat(S);
  515. end;
  516. end;
  517. procedure TCodeEditorCore.DeleteAllLines;
  518. begin
  519. if Assigned(Lines) then
  520. Lines^.FreeAll;
  521. end;
  522. procedure TCodeEditorCore.DeleteLine(I: sw_integer);
  523. var
  524. CP : Tpoint;
  525. begin
  526. if I<Lines^.Count then
  527. begin
  528. if StoreUndo then
  529. begin
  530. CP.X:=0;CP.Y:=I;
  531. AddAction(eaDeleteLine,CP,CP,GetLineText(I));
  532. end;
  533. Lines^.AtFree(I);
  534. end;
  535. end;
  536. procedure TCodeEditorCore.InsertLine(LineNo: sw_integer; const S: string);
  537. begin
  538. LinesInsert(LineNo, New(PLine, Init(@Self,S,0)));
  539. end;
  540. procedure TCodeEditorCore.AddLine(const S: string);
  541. begin
  542. LinesInsert(-1,New(PLine, Init(@Self,S,0)));
  543. end;
  544. procedure TCodeEditorCore.AddAction(AAction: byte; AStartPos, AEndPos: TPoint; AText: string);
  545. {$ifdef Undo}
  546. var
  547. ActionIntegrated : boolean;
  548. pa : PEditorAction;
  549. S : String;
  550. {$endif Undo}
  551. begin
  552. {$ifdef Undo}
  553. if (UndoList=nil) or (not StoreUndo) then Exit;
  554. ActionIntegrated:=false;
  555. if UndoList^.count>0 then
  556. begin
  557. pa:=UndoList^.At(UndoList^.count-1);
  558. if (pa^.action=AAction) and
  559. (pa^.EndPos.X=AStartPos.X) and
  560. (pa^.EndPos.Y=AStartPos.Y) and
  561. { do not group InsertLine and DeleteLine !! }
  562. ((AAction=eaMoveCursor) or
  563. (AAction=eaInsertText) or
  564. (AAction=eaDeleteText))
  565. then
  566. begin
  567. pa^.EndPos:=AEndPos;
  568. S:=GetStr(pa^.text);
  569. if S<>'' then
  570. DisposeStr(pa^.text);
  571. if (AAction=eaDeleteText) and
  572. (AStartPos.X>AEndPos.X) then
  573. pa^.text:=NewStr(AText+S)
  574. else
  575. pa^.text:=NewStr(S+AText);
  576. ActionIntegrated:=true;
  577. end;
  578. end;
  579. if not ActionIntegrated then
  580. begin
  581. UndoList^.Insert(New(PEditorAction,Init(AAction,AStartPos,AEndPos,AText)));
  582. if assigned(UndoList^.CurrentGroupedAction) then
  583. Inc(UndoList^.CurrentGroupedAction^.actionCount);
  584. UpdateUndoRedo(cmUndo,AAction);
  585. end;
  586. if UndoList^.count>0 then
  587. begin
  588. UpdateUndoRedo(cmRedo,0);
  589. RedoList^.FreeAll;
  590. end;
  591. {$endif Undo}
  592. end;
  593. procedure TCodeEditorCore.AddGroupedAction(AAction : byte);
  594. begin
  595. {$ifdef Undo}
  596. UndoList^.CurrentGroupedAction:=New(PEditorAction,Init_group(AAction));
  597. {$endif Undo}
  598. end;
  599. procedure TCodeEditorCore.CloseGroupedAction(AAction : byte);
  600. begin
  601. {$ifdef Undo}
  602. UndoList^.Insert(UndoList^.CurrentGroupedAction);
  603. UndoList^.CurrentGroupedAction:=nil;
  604. UpdateUndoRedo(cmUndo,AAction);
  605. {$endif Undo}
  606. end;
  607. function TCodeEditorCore.GetUndoActionCount: sw_integer;
  608. begin
  609. GetUndoActionCount:=UndoList^.Count;
  610. end;
  611. function TCodeEditorCore.GetRedoActionCount: sw_integer;
  612. begin
  613. GetRedoActionCount:=RedoList^.Count;
  614. end;
  615. destructor TCodeEditorCore.Done;
  616. begin
  617. inherited Done;
  618. if Assigned(Lines) then Dispose(Lines, Done); Lines:=nil;
  619. if Assigned(RedoList) then Dispose(RedoList, Done); RedoList:=nil;
  620. if Assigned(UndoList) then Dispose(UndoList, Done); UndoList:=nil;
  621. end;
  622. constructor TIndicator.Init(var Bounds: TRect);
  623. begin
  624. inherited Init(Bounds);
  625. GrowMode := gfGrowLoY + gfGrowHiY;
  626. end;
  627. procedure TIndicator.Draw;
  628. var
  629. Color: Byte;
  630. Frame: Char;
  631. L: array[0..1] of Longint;
  632. S: String[15];
  633. B: TDrawBuffer;
  634. begin
  635. if (State and sfDragging = 0) and (State and sfActive <> 0) then
  636. begin
  637. Color := GetColor(1);
  638. Frame := #205;
  639. end
  640. else
  641. begin
  642. if (State and sfDragging)<>0 then
  643. Color := GetColor(2)
  644. else
  645. Color := GetColor(3);
  646. Frame := #196;
  647. end;
  648. MoveChar(B, Frame, Color, Size.X);
  649. if State and sfActive<>0 then
  650. begin
  651. if Modified then
  652. WordRec (B[0]).Lo := ord('*');
  653. {$ifdef debug}
  654. if StoreUndo then
  655. WordRec (B[1]).Lo := ord('S');
  656. if SyntaxComplete then
  657. WordRec(B[2]).lo := ord('C');
  658. if UseTabs then
  659. WordRec(B[3]).lo := ord('T');
  660. {$endif debug}
  661. L[0] := Location.Y + 1;
  662. L[1] := Location.X + 1;
  663. FormatStr(S, '%d:%d ', L);
  664. MoveStr(B[8 - Pos(':', S)], S, Color);
  665. end;
  666. WriteBuf(0, 0, Size.X, 1, B);
  667. end;
  668. function TIndicator.GetPalette: PPalette;
  669. const
  670. P: string[Length(CIndicator)] = CIndicator;
  671. begin
  672. GetPalette := @P;
  673. end;
  674. procedure TIndicator.SetState(AState: Word; Enable: Boolean);
  675. begin
  676. inherited SetState(AState, Enable);
  677. if (AState = sfDragging) or (AState=sfActive) then
  678. DrawView;
  679. end;
  680. procedure TIndicator.SetValue(ALocation: TPoint; AModified: Boolean);
  681. begin
  682. if (Location.X<>ALocation.X) or
  683. (Location.Y<>ALocation.Y) or
  684. (Modified <> AModified) then
  685. begin
  686. Location := ALocation;
  687. Modified := AModified;
  688. DrawView;
  689. end;
  690. end;
  691. {constructor TIndicator.Load(var S: TStream);
  692. begin
  693. inherited Load(S);
  694. S.Read(Location,SizeOf(Location));
  695. S.Read(Modified,SizeOf(Modified));
  696. end;
  697. procedure TIndicator.Store(var S: TStream);
  698. begin
  699. inherited Store(S);
  700. S.Write(Location,SizeOf(Location));
  701. S.Write(Modified,SizeOf(Modified));
  702. end;}
  703. {*****************************************************************************
  704. TCodeEditor
  705. *****************************************************************************}
  706. constructor TCodeEditor.Init(var Bounds: TRect; AHScrollBar, AVScrollBar:
  707. PScrollBar; AIndicator: PIndicator; ACore: PCodeEditorCore);
  708. begin
  709. inherited Init(Bounds,AHScrollBar,AVScrollBar);
  710. if ACore=nil then ACore:=New(PCodeEditorCore, Init);
  711. Core:=ACore;
  712. Core^.BindEditor(@Self);
  713. SetState(sfCursorVis,true);
  714. SetFlags(DefaultCodeEditorFlags);
  715. SetCurPtr(0,0);
  716. Indicator:=AIndicator;
  717. UpdateIndicator;
  718. LimitsChanged;
  719. end;
  720. function TCodeEditor.GetFlags: longint;
  721. begin
  722. GetFlags:=Flags;
  723. end;
  724. procedure TCodeEditor.SetFlags(AFlags: longint);
  725. var OFlags: longint;
  726. begin
  727. if AFlags<>Flags then
  728. begin
  729. OFlags:=Flags;
  730. Flags:=AFlags;
  731. FlagsChanged(OFlags);
  732. end;
  733. end;
  734. function TCodeEditor.GetModified: boolean;
  735. begin
  736. GetModified:=Core^.GetModified;
  737. end;
  738. procedure TCodeEditor.SetModified(AModified: boolean);
  739. begin
  740. Core^.SetModified(AModified);
  741. end;
  742. function TCodeEditor.GetStoreUndo: boolean;
  743. begin
  744. GetStoreUndo:=Core^.GetStoreUndo;
  745. end;
  746. procedure TCodeEditor.SetStoreUndo(AStore: boolean);
  747. begin
  748. Core^.SetStoreUndo(AStore);
  749. end;
  750. function TCodeEditor.GetSyntaxCompleted: boolean;
  751. begin
  752. GetSyntaxCompleted:=Core^.GetSyntaxCompleted;
  753. end;
  754. procedure TCodeEditor.SetSyntaxCompleted(SC : boolean);
  755. begin
  756. Core^.SetSyntaxCompleted(SC);
  757. end;
  758. function TCodeEditor.GetLastSyntaxedLine: sw_integer;
  759. begin
  760. GetLastSyntaxedLine:=Core^.GetLastSyntaxedLine;
  761. end;
  762. procedure TCodeEditor.SetLastSyntaxedLine(ALine: sw_integer);
  763. begin
  764. Core^.SetLastSyntaxedLine(ALine);
  765. end;
  766. function TCodeEditor.GetTabSize: integer;
  767. begin
  768. GetTabSize:=Core^.GetTabSize;
  769. end;
  770. procedure TCodeEditor.SetTabSize(ATabSize: integer);
  771. begin
  772. Core^.SetTabSize(ATabSize);
  773. end;
  774. function TCodeEditor.IsReadOnly: boolean;
  775. begin
  776. IsReadOnly:=ReadOnly or (Core^.ReadOnly);
  777. end;
  778. function TCodeEditor.IsClipboard: Boolean;
  779. begin
  780. IsClipboard:=Core^.IsClipboard;
  781. end;
  782. function TCodeEditor.GetErrorMessage: string;
  783. begin
  784. GetErrorMessage:=GetStr(ErrorMessage);
  785. end;
  786. procedure TCodeEditor.SetErrorMessage(const S: string);
  787. begin
  788. SetStr(ErrorMessage,S);
  789. DrawView;
  790. end;
  791. function TCodeEditor.GetLineCount: sw_integer;
  792. begin
  793. GetLineCount:=Core^.GetLineCount;
  794. end;
  795. function TCodeEditor.GetLine(LineNo: sw_integer): PCustomLine;
  796. begin
  797. GetLine:=Core^.GetLine(LineNo);
  798. end;
  799. function TCodeEditor.CharIdxToLinePos(Line,CharIdx: sw_integer): sw_integer;
  800. begin
  801. CharIdxToLinePos:=Core^.CharIdxToLinePos(Line,CharIdx);
  802. end;
  803. function TCodeEditor.LinePosToCharIdx(Line,X: sw_integer): sw_integer;
  804. begin
  805. LinePosToCharIdx:=Core^.LinePosToCharIdx(Line,X);
  806. end;
  807. function TCodeEditor.GetLineText(I: sw_integer): string;
  808. begin
  809. GetLineText:=Core^.GetLineText(I);
  810. end;
  811. procedure TCodeEditor.SetDisplayText(I: sw_integer;const S: string);
  812. begin
  813. Core^.SetDisplayText(I,S);
  814. end;
  815. function TCodeEditor.GetDisplayText(I: sw_integer): string;
  816. begin
  817. GetDisplayText:=Core^.GetDisplayText(I);
  818. end;
  819. procedure TCodeEditor.SetLineText(I: sw_integer;const S: string);
  820. begin
  821. Core^.SetLineText(I,S);
  822. end;
  823. procedure TCodeEditor.GetDisplayTextFormat(I: sw_integer;var DT,DF:string);
  824. begin
  825. Core^.GetDisplayTextFormat(@Self,I,DT,DF);
  826. end;
  827. function TCodeEditor.GetLineFormat(I: sw_integer): string;
  828. begin
  829. GetLineFormat:=Core^.GetLineFormat(@Self,I);
  830. end;
  831. procedure TCodeEditor.SetLineFormat(I: sw_integer;const S: string);
  832. begin
  833. Core^.SetLineFormat(@Self,I,S);
  834. end;
  835. procedure TCodeEditor.DeleteAllLines;
  836. begin
  837. Core^.DeleteAllLines;
  838. end;
  839. procedure TCodeEditor.DeleteLine(I: sw_integer);
  840. begin
  841. Core^.DeleteLine(I);
  842. end;
  843. procedure TCodeEditor.InsertLine(LineNo: sw_integer; const S: string);
  844. begin
  845. Core^.InsertLine(LineNo,S);
  846. end;
  847. procedure TCodeEditor.AddLine(const S: string);
  848. begin
  849. Core^.AddLine(S);
  850. end;
  851. {function TCodeEditor.GetLineTextPos(Line,X: integer): integer;
  852. var
  853. S: string;
  854. rx,i : Sw_integer;
  855. begin
  856. S:=GetLineText(Line);
  857. i:=0; rx:=0;
  858. while (RX<X) and (i<Length(s)) do
  859. begin
  860. inc(i);
  861. inc(rx);
  862. if s[i]=#9 then
  863. inc(rx,TabSize-(rx mod tabsize));
  864. end;
  865. if RX<X then Inc(I,X-RX);
  866. GetLineTextPos:=i;
  867. end;
  868. function TCodeEditor.GetDisplayTextPos(Line,X: integer): integer;
  869. var
  870. S: string;
  871. L: PCustomLine;
  872. rx,i : Sw_integer;
  873. begin
  874. S:='';
  875. if Line<Lines^.Count then
  876. begin
  877. L:=Lines^.At(Line);
  878. if assigned(L^.Text) then
  879. S:=L^.Text^;
  880. end;
  881. i:=0;
  882. rx:=0;
  883. while (i<X) and (i<Length(s)) do
  884. begin
  885. inc(i);
  886. inc(rx);
  887. if s[i]=#9 then
  888. inc(rx,TabSize-(rx mod tabsize));
  889. end;
  890. GetDisplayTextPos:=rx;
  891. end;}
  892. procedure TCodeEditor.GetContent(ALines: PUnsortedStringCollection);
  893. begin
  894. Core^.GetContent(ALines);
  895. end;
  896. procedure TCodeEditor.SetContent(ALines: PUnsortedStringCollection);
  897. begin
  898. Lock;
  899. TextStart; HideSelect;
  900. Core^.SetContent(ALines);
  901. LimitsChanged;
  902. if IsFlagSet(efSyntaxHighlight) then
  903. Core^.UpdateAttrsRange(0,Min(Delta.Y+Size.Y,GetLineCount-1),
  904. attrAll
  905. {$ifndef TEST_PARTIAL_SYNTAX}
  906. +attrForceFull
  907. {$endif TEST_PARTIAL_SYNTAX}
  908. );
  909. TextStart;
  910. UnLock;
  911. end;
  912. function TCodeEditor.GetCodeCompleteFrag: string;
  913. begin
  914. GetCodeCompleteFrag:=GetStr(CodeCompleteFrag);
  915. end;
  916. procedure TCodeEditor.SetCodeCompleteFrag(const S: string);
  917. begin
  918. SetStr(CodeCompleteFrag,S);
  919. end;
  920. function TCodeEditor.GetCompleteState: TCompleteState;
  921. begin
  922. GetCompleteState:=CompleteState;
  923. end;
  924. procedure TCodeEditor.SetCompleteState(AState: TCompleteState);
  925. begin
  926. if AState<>CompleteState then
  927. begin
  928. CompleteState:=AState;
  929. if CompleteState<>csOffering then
  930. ClearCodeCompleteWord;
  931. end;
  932. end;
  933. function TCodeEditor.GetCodeCompleteWord: string;
  934. begin
  935. GetCodeCompleteWord:=GetStr(CodeCompleteWord);
  936. end;
  937. procedure TCodeEditor.SetCodeCompleteWord(const S: string);
  938. begin
  939. if Assigned(CodeCompleteWord) then DisposeStr(CodeCompleteWord);
  940. CodeCompleteWord:=NewStr(S);
  941. inherited SetCodeCompleteWord(S);
  942. end;
  943. procedure TCodeEditor.DrawIndicator;
  944. begin
  945. if Assigned(Indicator) then
  946. Indicator^.DrawView;
  947. end;
  948. procedure TCodeEditor.Lock;
  949. begin
  950. inherited Lock;
  951. Core^.Lock(@Self);
  952. end;
  953. procedure TCodeEditor.UnLock;
  954. begin
  955. Core^.UnLock(@Self);
  956. inherited UnLock;
  957. If IndicatorDrawCalled then
  958. begin
  959. DrawIndicator;
  960. IndicatorDrawCalled:=false;
  961. end;
  962. end;
  963. procedure TCodeEditor.UpdateIndicator;
  964. begin
  965. if Indicator<>nil then
  966. begin
  967. Indicator^.Location:=CurPos;
  968. Indicator^.Modified:=GetModified;
  969. {$ifdef debug}
  970. Indicator^.StoreUndo:=GetStoreUndo;
  971. {$ifdef TEST_PARTIAL_SYNTAX}
  972. Indicator^.SyntaxComplete:=GetSyntaxCompleted and IsFlagSet(efSyntaxHighlight);
  973. {$endif TEST_PARTIAL_SYNTAX}
  974. Indicator^.UseTabs:=IsFlagSet(efUseTabCharacters);
  975. {$endif debug}
  976. if lockflag>0 then
  977. IndicatorDrawCalled:=true
  978. else
  979. Indicator^.DrawView;
  980. end;
  981. end;
  982. procedure TCodeEditor.LimitsChanged;
  983. begin
  984. Core^.LimitsChanged;
  985. end;
  986. procedure TCodeEditor.ModifiedChanged;
  987. begin
  988. UpdateIndicator;
  989. end;
  990. procedure TCodeEditor.PositionChanged;
  991. begin
  992. UpdateIndicator;
  993. end;
  994. procedure TCodeEditor.JumpToLastCursorPos;
  995. {$ifdef Undo}
  996. var
  997. pa : PEditorAction;
  998. {$endif Undo}
  999. begin
  1000. {$ifdef Undo}
  1001. if (Core^.UndoList^.count>0) and (Core^.RedoList^.count=0) then
  1002. begin
  1003. { Or should we just call Undo ?? PM }
  1004. pa:=Core^.UndoList^.At(Core^.UndoList^.count-1);
  1005. if (pa^.action=eaMoveCursor) then
  1006. SetCurPtr(pa^.StartPos.X,pa^.StartPos.Y);
  1007. end;
  1008. {$else not Undo}
  1009. NotImplemented;
  1010. {$endif Undo}
  1011. end;
  1012. procedure TCodeEditor.Undo;
  1013. {$ifdef Undo}
  1014. var
  1015. Temp,Idx,Last,Count : Longint;
  1016. Is_grouped : boolean;
  1017. MaxY,MinY : sw_integer;
  1018. procedure SetMinMax(y : sw_integer);
  1019. begin
  1020. if MinY=-1 then
  1021. MinY:=Y;
  1022. if Y<MinY then
  1023. MinY:=Y;
  1024. if MaxY=-1 then
  1025. MaxY:=Y;
  1026. if Y>MaxY then
  1027. MaxY:=Y;
  1028. end;
  1029. {$endif Undo}
  1030. begin
  1031. {$ifdef Undo}
  1032. Core^.SetStoreUndo(False);
  1033. Lock;
  1034. MinY:=-1;
  1035. MaxY:=-1;
  1036. if Core^.UndoList^.count > 0 then
  1037. begin
  1038. Last:=Core^.UndoList^.count-1;
  1039. if Core^.UndoList^.At(Last)^.Is_grouped_action then
  1040. begin
  1041. Count:=Core^.UndoList^.At(Last)^.ActionCount;
  1042. Dec(Last);
  1043. Is_grouped:=true;
  1044. end
  1045. else
  1046. begin
  1047. Count:=1;
  1048. Is_grouped:=false;
  1049. end;
  1050. for Idx:=Last downto Last-Count+1 do
  1051. with Core^.UndoList^.At(Idx)^ do
  1052. begin
  1053. case action of
  1054. eaMoveCursor :
  1055. begin
  1056. { move cursor back to original position }
  1057. SetCurPtr(startpos.x,startpos.y);
  1058. end;
  1059. eaInsertText :
  1060. begin
  1061. SetCurPtr(StartPos.X,StartPos.Y);
  1062. if assigned(text) then
  1063. for Temp := 1 to length(Text^) do
  1064. DelChar;
  1065. SetMinMax(StartPos.Y);
  1066. end;
  1067. eaDeleteText :
  1068. begin
  1069. { reinsert deleted text }
  1070. SetCurPtr(EndPos.X,EndPos.Y);
  1071. if assigned(text) then
  1072. for Temp := 1 to length(Text^) do
  1073. AddChar(Text^[Temp]);
  1074. SetMinMax(EndPos.Y);
  1075. SetCurPtr(StartPos.X,StartPos.Y);
  1076. end;
  1077. eaInsertLine :
  1078. begin
  1079. SetCurPtr(EndPos.X,EndPos.Y);
  1080. SetDisplayText(EndPos.Y,Copy(GetDisplayText(EndPos.Y),EndPos.X+1,255));
  1081. SetMinMax(EndPos.Y);
  1082. BackSpace;
  1083. SetCurPtr(StartPos.X,StartPos.Y);
  1084. SetMinMax(StartPos.Y);
  1085. end;
  1086. eaDeleteLine :
  1087. begin
  1088. SetCurPtr(EndPos.X,EndPos.Y);
  1089. DelEnd;{ wrong for eaCut at least }
  1090. InsertNewLine;
  1091. SetCurPtr(StartPos.X,StartPos.Y);
  1092. SetLineText(StartPos.Y,Copy(GetDisplayText(StartPos.Y),1,StartPos.X)+GetStr(Text));
  1093. SetMinMax(StartPos.Y);
  1094. end;
  1095. eaSelectionChanged :
  1096. begin
  1097. { move cursor to end of last set selection }
  1098. end;
  1099. else
  1100. { what the 'ell's an undefined action doing round 'ere mate! }
  1101. ;
  1102. end; { once this lot is done paste into redo and modify to suit needs }
  1103. { move item to redo stack }
  1104. Core^.RedoList^.Insert(Core^.UndoList^.At(Idx));
  1105. UpdateUndoRedo(cmRedo,Core^.UndoList^.At(Idx)^.Action);
  1106. Core^.UndoList^.atDelete(Idx);
  1107. If Idx>0 then
  1108. UpdateUndoRedo(cmUndo,Core^.UndoList^.At(Idx-1)^.Action)
  1109. else
  1110. UpdateUndoRedo(cmUndo,0);
  1111. end;{Idx loop for grouped actions }
  1112. if is_grouped then
  1113. begin
  1114. Idx:=Core^.UndoList^.Count-1;
  1115. Core^.RedoList^.Insert(Core^.UndoList^.At(Idx));
  1116. UpdateUndoRedo(cmRedo,Core^.UndoList^.At(Idx)^.Action);
  1117. Core^.UndoList^.atDelete(Idx);
  1118. If Idx>0 then
  1119. UpdateUndoRedo(cmUndo,Core^.UndoList^.At(Idx-1)^.Action)
  1120. else
  1121. UpdateUndoRedo(cmUndo,0);
  1122. end;
  1123. if Core^.UndoList^.count=0 then
  1124. SetCmdState(UndoCmd,false);
  1125. SetCmdState(RedoCmd,true);
  1126. Message(Application,evBroadcast,cmCommandSetChanged,nil);
  1127. if MinY<>-1 then
  1128. UpdateAttrsRange(MinY,MaxY,attrAll);
  1129. DrawView;
  1130. end;
  1131. Core^.SetStoreUndo(True);
  1132. Unlock;
  1133. {$else}
  1134. NotImplemented; Exit;
  1135. {$endif Undo}
  1136. end;
  1137. procedure TCodeEditor.Redo;
  1138. {$ifdef Undo}
  1139. var
  1140. Temp,Idx,Last,Count : Longint;
  1141. Is_grouped : boolean;
  1142. {$endif Undo}
  1143. begin
  1144. {$ifdef Undo}
  1145. Core^.SetStoreUndo(False);
  1146. Lock;
  1147. if Core^.RedoList^.count <> 0 then
  1148. begin
  1149. Last:=Core^.RedoList^.count-1;
  1150. if Core^.RedoList^.At(Last)^.Is_grouped_action then
  1151. begin
  1152. Count:=Core^.RedoList^.At(Last)^.ActionCount;
  1153. Dec(Last);
  1154. Is_grouped:=true;
  1155. end
  1156. else
  1157. begin
  1158. Count:=1;
  1159. Is_grouped:=false;
  1160. end;
  1161. for Idx:=Last downto Last-Count+1 do
  1162. with Core^.RedoList^.At(Idx)^ do
  1163. begin
  1164. case action of
  1165. eaMoveCursor :
  1166. begin
  1167. { move cursor back to original position }
  1168. SetCurPtr(EndPos.X,EndPos.Y);
  1169. end;
  1170. eaInsertText :
  1171. begin
  1172. SetCurPtr(startpos.x,startpos.y);
  1173. InsertText(GetStr(Text));
  1174. end;
  1175. eaDeleteText :
  1176. begin
  1177. SetCurPtr(EndPos.X,EndPos.Y);
  1178. for Temp := 1 to length(GetStr(Text)) do
  1179. DelChar;
  1180. end;
  1181. eaInsertLine :
  1182. begin
  1183. SetCurPtr(StartPos.X,StartPos.Y);
  1184. InsertNewLine;
  1185. SetCurPtr(StartPos.X,StartPos.Y);
  1186. InsertText(GetStr(Text));
  1187. SetCurPtr(EndPos.X,EndPos.Y);
  1188. end;
  1189. eaDeleteLine :
  1190. begin
  1191. SetCurPtr(StartPos.X,StartPos.Y);
  1192. DeleteLine(StartPos.Y);
  1193. SetCurPtr(EndPos.X,EndPos.Y);
  1194. SetDisplayText(StartPos.Y,RExpand(
  1195. copy(GetDisplayText(StartPos.Y),1,StartPos.X),StartPos.X)
  1196. +GetStr(Text));
  1197. SetCurPtr(EndPos.X,EndPos.Y);
  1198. end;
  1199. eaSelectionChanged :
  1200. begin
  1201. { move cursor to end of last set test selection }
  1202. end;
  1203. else
  1204. { what the 'ell's an undefined action doing round 'ere mate! }
  1205. ;
  1206. end; { once this lot is done paste back into undo and modify to suit needs }
  1207. { move item to undo stack }
  1208. Core^.UndoList^.Insert(Core^.RedoList^.At(Idx));
  1209. UpdateUndoRedo(cmUndo,Core^.RedoList^.At(Idx)^.Action);
  1210. If Idx>0 then
  1211. UpdateUndoRedo(cmRedo,Core^.RedoList^.At(Idx-1)^.Action)
  1212. else
  1213. UpdateUndoRedo(cmRedo,0);
  1214. Core^.RedoList^.atDelete(Idx);
  1215. end;{ Idx loop for grouped action }
  1216. If is_grouped then
  1217. begin
  1218. Idx:=Core^.RedoList^.count-1;
  1219. Core^.UndoList^.Insert(Core^.RedoList^.At(Idx));
  1220. UpdateUndoRedo(cmUndo,Core^.RedoList^.At(Idx)^.Action);
  1221. If Idx>0 then
  1222. UpdateUndoRedo(cmRedo,Core^.RedoList^.At(Idx-1)^.Action)
  1223. else
  1224. UpdateUndoRedo(cmRedo,0);
  1225. Core^.RedoList^.atDelete(Idx);
  1226. end;
  1227. if Core^.RedoList^.count=0 then
  1228. SetCmdState(RedoCmd,false);
  1229. SetCmdState(UndoCmd,true);
  1230. DrawView;
  1231. Message(Application,evBroadcast,cmCommandSetChanged,nil);
  1232. end;
  1233. Core^.SetStoreUndo(True);
  1234. Unlock;
  1235. {$else}
  1236. NotImplemented; Exit;
  1237. {$endif Undo}
  1238. end;
  1239. (*constructor TCodeEditor.Load(var S: TStream);
  1240. var TS: PSubStream;
  1241. TSize: longint;
  1242. begin
  1243. inherited Load(S);
  1244. New(UndoList,init(500,1000));
  1245. New(RedoList,init(500,1000));
  1246. New(Lines, Init(500,1000));
  1247. { we have always need at least 1 line }
  1248. LinesInsert(New(PLine, Init('',0)));
  1249. GetPeerViewPtr(S,Indicator);
  1250. S.Read(Flags,SizeOf(Flags));
  1251. S.Read(TabSize,SizeOf(TabSize));
  1252. if IsFlagSet(efStoreContent) then
  1253. begin
  1254. S.Read(TSize,SizeOf(TSize));
  1255. New(TS, Init(@S,S.GetPos,TSize));
  1256. {$ifdef TEST_PARTIAL_SYNTAX}
  1257. Core^.SearchBinding(Editor)^.SyntaxComplete:=false;
  1258. { Idle necessary }
  1259. EventMask:=EventMask or evIdle;
  1260. {$endif TEST_PARTIAL_SYNTAX}
  1261. LoadFromStream(TS);
  1262. Dispose(TS, Done);
  1263. end;
  1264. S.Read(SelStart,SizeOf(SelStart));
  1265. S.Read(SelEnd,SizeOf(SelEnd));
  1266. S.Read(Highlight,SizeOf(Highlight));
  1267. S.Read(CurPos,SizeOf(CurPos));
  1268. S.Read(StoreUndo,SizeOf(StoreUndo));
  1269. S.Read(IsReadOnly,SizeOf(IsReadOnly));
  1270. S.Read(NoSelect,SizeOf(NoSelect));
  1271. S.Read(HighlightRow,SizeOf(HighlightRow));
  1272. SetDebuggerRow(-1);
  1273. LimitsChanged;
  1274. SelectionChanged; HighlightChanged;
  1275. UpdateIndicator;
  1276. end;
  1277. procedure TCodeEditor.Store(var S: TStream);
  1278. var {NS: TNulStream;}
  1279. TSizePos,TSize,EndPos: longint;
  1280. begin
  1281. inherited Store(S);
  1282. PutPeerViewPtr(S,Indicator);
  1283. S.Write(Flags,SizeOf(Flags));
  1284. S.Write(TabSize,SizeOf(TabSize));
  1285. if IsFlagSet(efStoreContent) then
  1286. begin
  1287. { NS.Init;
  1288. SaveToStream(@NS);
  1289. TSize:=NS.GetSize;
  1290. NS.Done;
  1291. This is waste of time PM
  1292. use Seek instead !! }
  1293. { yep. and this won't work for serial streams. - Gabor }
  1294. TSize:=0;
  1295. TSizePos:=S.GetPos;
  1296. S.Write(TSize,SizeOf(TSize));
  1297. SaveToStream(@S);
  1298. EndPos:=S.GetPos;
  1299. TSize:=EndPos-TSizePos-SizeOf(TSize);
  1300. S.Seek(TSizePos);
  1301. S.Write(TSize,SizeOf(TSize));
  1302. S.Seek(EndPos);
  1303. end;
  1304. S.Write(SelStart,SizeOf(SelStart));
  1305. S.Write(SelEnd,SizeOf(SelEnd));
  1306. S.Write(Highlight,SizeOf(Highlight));
  1307. S.Write(CurPos,SizeOf(CurPos));
  1308. S.Write(StoreUndo,SizeOf(StoreUndo));
  1309. S.Write(IsReadOnly,SizeOf(IsReadOnly));
  1310. S.Write(NoSelect,SizeOf(NoSelect));
  1311. S.Write(HighlightRow,SizeOf(HighlightRow));
  1312. end;*)
  1313. function TCodeEditor.LoadFromStream(Stream: PStream): boolean;
  1314. var OK: boolean;
  1315. begin
  1316. OK:=Core^.LoadFromStream(@Self,Stream);
  1317. if IsFlagSet(efSyntaxHighlight) then
  1318. UpdateAttrsRange(0,Min(Delta.Y+Size.Y,GetLineCount-1),
  1319. attrAll
  1320. {$ifndef TEST_PARTIAL_SYNTAX}
  1321. +attrForceFull
  1322. {$endif TEST_PARTIAL_SYNTAX}
  1323. );
  1324. TextStart;
  1325. LoadFromStream:=OK;
  1326. end;
  1327. function TCodeEditor.SaveToStream(Stream: PStream): boolean;
  1328. begin
  1329. SaveToStream:=Core^.SaveToStream(@Self,Stream);
  1330. end;
  1331. function TCodeEditor.SaveAreaToStream(Stream: PStream; StartP,EndP: TPoint): boolean;
  1332. begin
  1333. SaveAreaToStream:=Core^.SaveAreaToStream(@Self,Stream,StartP,EndP);
  1334. end;
  1335. function TCodeEditor.UpdateAttrs(FromLine: sw_integer; Attrs: byte): sw_integer;
  1336. begin
  1337. UpdateAttrs:=Core^.UpdateAttrs(FromLine,Attrs);
  1338. end;
  1339. function TCodeEditor.UpdateAttrsRange(FromLine, ToLine: sw_integer; Attrs: byte): sw_integer;
  1340. begin
  1341. UpdateAttrsRange:=Core^.UpdateAttrsRange(FromLine,ToLine,Attrs);
  1342. end;
  1343. procedure TCodeEditor.AddAction(AAction: byte; AStartPos, AEndPos: TPoint; AText: string);
  1344. begin
  1345. Core^.AddAction(AAction,AStartPos,AEndPos,AText);
  1346. end;
  1347. procedure TCodeEditor.AddGroupedAction(AAction : byte);
  1348. begin
  1349. Core^.AddGroupedAction(AAction);
  1350. end;
  1351. procedure TCodeEditor.CloseGroupedAction(AAction : byte);
  1352. begin
  1353. Core^.CloseGroupedAction(AAction);
  1354. end;
  1355. function TCodeEditor.GetUndoActionCount: sw_integer;
  1356. begin
  1357. GetUndoActionCount:=Core^.GetUndoActionCount;
  1358. end;
  1359. function TCodeEditor.GetRedoActionCount: sw_integer;
  1360. begin
  1361. GetRedoActionCount:=Core^.GetRedoActionCount;
  1362. end;
  1363. destructor TCodeEditor.Done;
  1364. begin
  1365. inherited Done;
  1366. if Assigned(Core) then
  1367. begin
  1368. Core^.UnBindEditor(@Self);
  1369. if Core^.CanDispose then
  1370. Dispose(Core, Done);
  1371. end;
  1372. Core:=nil;
  1373. if Assigned(CodeCompleteFrag) then
  1374. DisposeStr(CodeCompleteFrag);
  1375. if Assigned(CodeCompleteWord) then
  1376. DisposeStr(CodeCompleteWord);
  1377. end;
  1378. constructor TFileEditor.Init(var Bounds: TRect; AHScrollBar, AVScrollBar:
  1379. PScrollBar; AIndicator: PIndicator;ACore: PCodeEditorCore; const AFileName: string);
  1380. begin
  1381. inherited Init(Bounds,AHScrollBAr,AVScrollBAr,AIndicator,ACore);
  1382. FileName:=AFileName;
  1383. UpdateIndicator;
  1384. Message(@Self,evBroadcast,cmFileNameChanged,@Self);
  1385. OnDiskLoadTime:=-1;
  1386. end;
  1387. function TFileEditor.LoadFile: boolean;
  1388. var OK: boolean;
  1389. PA : Array[1..2] of pointer;
  1390. begin
  1391. OK:=LoadFromFile(FileName);
  1392. if GetModified then
  1393. begin
  1394. PA[1]:=@FileName;
  1395. longint(PA[2]):=Core^.GetChangedLine;
  1396. EditorDialog(edChangedOnloading,@PA);
  1397. end;
  1398. OnDiskLoadTime:=GetFileTime(FileName);
  1399. LoadFile:=OK;
  1400. end;
  1401. function TFileEditor.IsChangedOnDisk : boolean;
  1402. begin
  1403. IsChangedOnDisk:=(OnDiskLoadTime<>GetFileTime(FileName)) and (OnDiskLoadTime<>-1);
  1404. end;
  1405. function TFileEditor.SaveFile: boolean;
  1406. var OK: boolean;
  1407. BAKName: string;
  1408. f: text;
  1409. begin
  1410. If IsChangedOnDisk then
  1411. begin
  1412. if EditorDialog(edFileOnDiskChanged, @FileName) <> cmYes then
  1413. begin
  1414. SaveFile:=false;
  1415. exit;
  1416. end;
  1417. end;
  1418. {$I-}
  1419. if IsFlagSet(efBackupFiles) and ExistsFile(FileName) then
  1420. begin
  1421. BAKName:=DirAndNameOf(FileName)+'.bak';
  1422. Assign(f,BAKName);
  1423. Erase(f);
  1424. EatIO;
  1425. Assign(f,FileName);
  1426. Rename(F,BAKName);
  1427. EatIO;
  1428. end;
  1429. {$I+}
  1430. OK:=SaveToFile(FileName);
  1431. if OK then
  1432. SetModified(false)
  1433. { Restore the original }
  1434. else if IsFlagSet(efBackupFiles) and ExistsFile(BakName) then
  1435. begin
  1436. {$I-}
  1437. Assign(f,BakName);
  1438. Rename(F,FileName);
  1439. EatIO;
  1440. {$I+}
  1441. end;
  1442. { don't forget to update the OnDiskLoadTime value }
  1443. if OK then
  1444. OnDiskLoadTime:=GetFileTime(FileName);
  1445. if not OK then
  1446. EditorDialog(edSaveError,@FileName);
  1447. SaveFile:=OK;
  1448. end;
  1449. function TFileEditor.ShouldSave: boolean;
  1450. begin
  1451. ShouldSave:=GetModified{ or (FileName='')};
  1452. end;
  1453. function TFileEditor.Save: Boolean;
  1454. begin
  1455. if ShouldSave=false then begin Save:=true; Exit; end;
  1456. if FileName = '' then Save := SaveAs else Save := SaveFile;
  1457. end;
  1458. function TFileEditor.SaveAs: Boolean;
  1459. begin
  1460. SaveAs := False;
  1461. if EditorDialog(edSaveAs, @FileName) <> cmCancel then
  1462. begin
  1463. FileName := FExpand(FileName);
  1464. Message(Owner, evBroadcast, cmUpdateTitle, @Self);
  1465. { if we rename the file the OnDiskLoadTime is wrong so we reset it }
  1466. OnDiskLoadTime:=-1;
  1467. SaveAs := SaveFile;
  1468. if IsClipboard then FileName := '';
  1469. Message(Application,evBroadcast,cmFileNameChanged,@Self);
  1470. end;
  1471. end;
  1472. function TFileEditor.SaveAsk(Force: boolean): boolean;
  1473. var OK: boolean;
  1474. D: Sw_integer;
  1475. begin
  1476. OK:=GetModified=false;
  1477. if Force=false then
  1478. if (OK=false) and (Core^.GetBindingCount>1) then
  1479. OK:=true;
  1480. if OK=false then
  1481. begin
  1482. if FileName = '' then D := edSaveUntitled else D := edSaveModify;
  1483. case EditorDialog(D, @FileName) of
  1484. cmYes : OK := Save;
  1485. cmNo : begin SetModified(False); OK:=true; end;
  1486. cmCancel : begin
  1487. OK := False;
  1488. Message(Application,evBroadcast,cmSaveCancelled,@Self);
  1489. end;
  1490. end;
  1491. end;
  1492. SaveAsk:=OK;
  1493. end;
  1494. procedure TFileEditor.BindingsChanged;
  1495. begin
  1496. Message(Application,evBroadcast,cmUpdateTitle,@Self);
  1497. end;
  1498. procedure TFileEditor.HandleEvent(var Event: TEvent);
  1499. var SH,B: boolean;
  1500. begin
  1501. case Event.What of
  1502. evBroadcast :
  1503. case Event.Command of
  1504. cmFileNameChanged :
  1505. if (Event.InfoPtr=nil) or (Event.InfoPtr=@Self) then
  1506. begin
  1507. B:=IsFlagSet(efSyntaxHighlight);
  1508. SH:=UseSyntaxHighlight(@Self);
  1509. if SH<>B then
  1510. if SH then
  1511. SetFlags(Flags or efSyntaxHighlight)
  1512. else
  1513. SetFlags(Flags and not efSyntaxHighlight);
  1514. if UseTabsPattern(@Self) then
  1515. SetFlags(Flags or efUseTabCharacters);
  1516. end;
  1517. end;
  1518. end;
  1519. inherited HandleEvent(Event);
  1520. end;
  1521. function TFileEditor.Valid(Command: Word): Boolean;
  1522. var OK: boolean;
  1523. begin
  1524. OK:=inherited Valid(Command);
  1525. if OK and ((Command=cmClose) or (Command=cmQuit)) then
  1526. if IsClipboard=false then
  1527. OK:=SaveAsk(Command=cmQuit);
  1528. Valid:=OK;
  1529. end;
  1530. (* constructor TFileEditor.Load(var S: TStream);
  1531. var P: PString;
  1532. SSP,SEP,CP,DP: TPoint;
  1533. HR: TRect;
  1534. PA : Array[1..2] of pointer;
  1535. HoldUndo : boolean;
  1536. begin
  1537. inherited Load(S);
  1538. HoldUndo:=GetStoreUndo;
  1539. SetStoreUndo(False);
  1540. P:=S.ReadStr;
  1541. FileName:=GetStr(P);
  1542. if P<>nil then DisposeStr(P);
  1543. UpdateIndicator;
  1544. { Message(@Self,evBroadcast,cmFileNameChanged,@Self);}
  1545. SSP:=SelStart; SEP:=SelEnd;
  1546. CP:=CurPos;
  1547. HR:=Highlight;
  1548. DP:=Delta;
  1549. if FileName<>'' then
  1550. LoadFile;
  1551. { if GetModified then
  1552. begin
  1553. PA[1]:=@FileName;
  1554. longint(PA[2]):=ChangedLine;
  1555. EditorDialog(edChangedOnloading,@PA);
  1556. end;}
  1557. SetHighlight(HR.A,HR.B);
  1558. SetSelection(SSP,SEP);
  1559. SetCurPtr(CP.X,CP.Y);
  1560. ScrollTo(DP.X,DP.Y);
  1561. SetModified(false);
  1562. LimitsChanged;
  1563. SetStoreUndo(HoldUndo);
  1564. end;
  1565. procedure TFileEditor.Store(var S: TStream);
  1566. begin
  1567. inherited Store(S);
  1568. S.WriteStr(@FileName);
  1569. end;
  1570. *)
  1571. function DefUseSyntaxHighlight(Editor: PFileEditor): boolean;
  1572. begin
  1573. DefUseSyntaxHighlight:=Editor^.IsFlagSet(efSyntaxHighlight);
  1574. end;
  1575. function DefUseTabsPattern(Editor: PFileEditor): boolean;
  1576. begin
  1577. DefUseTabsPattern:=Editor^.IsFlagSet(efUseTabCharacters);
  1578. end;
  1579. procedure RegisterWCEdit;
  1580. begin
  1581. {$ifndef NOOBJREG}
  1582. RegisterType(RIndicator);
  1583. RegisterType(RCodeEditor);
  1584. RegisterType(RFileEditor);
  1585. {$endif}
  1586. end;
  1587. END.
  1588. {
  1589. $Log $
  1590. }