wcedit.pas 55 KB

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