wcedit.pas 56 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115
  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. WUtils,WEditor;
  17. type
  18. PCodeEditor = ^TCodeEditor;
  19. PIndicator = ^TIndicator;
  20. TIndicator = object(TView)
  21. Location: TPoint;
  22. Modified : Boolean;
  23. CodeOwner : PCodeEditor;
  24. {$ifdef debug}
  25. StoreUndo : Boolean;
  26. SyntaxComplete : boolean;
  27. UseTabs : Boolean;
  28. {$endif debug}
  29. constructor Init(var Bounds: TRect);
  30. procedure Draw; virtual;
  31. function GetPalette: PPalette; virtual;
  32. procedure SetState(AState: Word; Enable: Boolean); virtual;
  33. procedure SetValue(ALocation: TPoint; AModified: Boolean);
  34. end;
  35. PLine = ^TLine;
  36. TLine = object(TCustomLine)
  37. public { internal use only! }
  38. Text : PString;
  39. DefaultEditorInfo : PEditorLineInfo;
  40. EditorInfos : PEditorLineInfoCollection;
  41. Flags : longint;
  42. Owner : PCustomCodeEditorCore;
  43. procedure AddEditorInfo(Index: sw_integer; AEditor: PCustomCodeEditor); virtual;
  44. procedure RemoveEditorInfo(AEditor: PCustomCodeEditor); virtual;
  45. public
  46. constructor Init(AOwner: PCustomCodeEditorCore; const AText: string; AFlags: longint);
  47. function GetText: string; virtual;
  48. procedure SetText(const AText: string); virtual;
  49. function GetEditorInfo(Editor: PCustomCodeEditor): PEditorLineInfo; virtual;
  50. function GetFlags: longint; virtual;
  51. procedure SetFlags(AFlags: longint); virtual;
  52. destructor Done; virtual;
  53. end;
  54. PCodeEditorCore = ^TCodeEditorCore;
  55. TCodeEditorCore = object(TCustomCodeEditorCore)
  56. {$ifdef TP}public{$else}protected{$endif}
  57. Lines : PLineCollection;
  58. CanUndo : Boolean;
  59. StoreUndo : boolean;
  60. Modified : Boolean;
  61. ReadOnly : Boolean;
  62. TabSize : integer;
  63. IndentSize : integer;
  64. ModifiedTime : cardinal;
  65. public
  66. UndoList : PEditorActionCollection;
  67. RedoList : PEditorActionCollection;
  68. constructor Init;
  69. destructor Done; virtual;
  70. procedure ChangeLinesTo(ALines : PLineCollection); virtual;
  71. function GetModified: boolean; virtual;
  72. procedure SetModified(AModified: boolean); virtual;
  73. function GetModifyTime: cardinal; virtual;
  74. function GetTabSize: integer; virtual;
  75. procedure SetTabSize(ATabSize: integer); virtual;
  76. function GetIndentSize: integer; virtual;
  77. procedure SetIndentSize(AIndentSize: integer); virtual;
  78. function GetStoreUndo: boolean; virtual;
  79. procedure SetStoreUndo(AStore: boolean); virtual;
  80. function GetSyntaxCompleted: boolean; virtual;
  81. procedure SetSyntaxCompleted(SC : boolean); virtual;
  82. function GetLastSyntaxedLine: sw_integer; virtual;
  83. procedure SetLastSyntaxedLine(ALine: sw_integer); virtual;
  84. { Storage }
  85. {$ifdef TP}public{$else}protected{$endif}
  86. { Text & info storage abstraction }
  87. procedure ISetLineFlagState(Binding: PEditorBinding; LineNo: sw_integer; Flag: longint; ASet: boolean); virtual;
  88. procedure IGetDisplayTextFormat(Binding: PEditorBinding; LineNo: sw_integer;var DT,DF:string); virtual;
  89. function IGetLineFormat(Binding: PEditorBinding; LineNo: sw_integer): string; virtual;
  90. procedure ISetLineFormat(Binding: PEditorBinding; LineNo: sw_integer;const S: string); virtual;
  91. public
  92. { Text & info storage abstraction }
  93. function GetLineCount: sw_integer; virtual;
  94. function GetLine(LineNo: sw_integer): PCustomLine; virtual;
  95. function GetLineText(LineNo: sw_integer): string; virtual;
  96. procedure SetDisplayText(I: sw_integer;const S: string); virtual;
  97. function GetDisplayText(I: sw_integer): string; virtual;
  98. procedure SetLineText(I: sw_integer;const S: string); virtual;
  99. procedure DeleteAllLines; virtual;
  100. procedure DeleteLine(I: sw_integer); virtual;
  101. function InsertLine(LineNo: sw_integer; const S: string): PCustomLine; virtual;
  102. procedure AddLine(const S: string); virtual;
  103. procedure GetContent(ALines: PUnsortedStringCollection); virtual;
  104. procedure SetContent(ALines: PUnsortedStringCollection); virtual;
  105. public
  106. { Undo info storage }
  107. procedure AddAction(AAction: byte; AStartPos, AEndPos: TPoint; AText: string); virtual;
  108. procedure AddGroupedAction(AAction : byte); virtual;
  109. procedure CloseGroupedAction(AAction : byte); virtual;
  110. function GetUndoActionCount: sw_integer; virtual;
  111. function GetRedoActionCount: sw_integer; virtual;
  112. private
  113. procedure LinesInsert(Idx: sw_integer; Line: PLine);
  114. end;
  115. TCodeEditor = object(TCustomCodeEditor)
  116. Core : PCodeEditorCore;
  117. Flags : longint;
  118. Indicator : PIndicator;
  119. HighlightRow: sw_integer;
  120. DebuggerRow: sw_integer;
  121. CodeCompleteFrag: PString;
  122. CodeCompleteWord: PString;
  123. ReadOnly : boolean;
  124. CompleteState: TCompleteState;
  125. ErrorMessage: PString;
  126. IndicatorDrawCalled : boolean;
  127. Folds : PFoldCollection;
  128. MaxFoldLevel: sw_integer;
  129. constructor Init(var Bounds: TRect; AHScrollBar, AVScrollBar:
  130. PScrollBar; AIndicator: PIndicator; ACore: PCodeEditorCore);
  131. public
  132. procedure DrawIndicator; virtual;
  133. public
  134. function GetFlags: longint; virtual;
  135. procedure SetFlags(AFlags: longint); virtual;
  136. function GetModified: boolean; virtual;
  137. procedure SetModified(AModified: boolean); virtual;
  138. function GetStoreUndo: boolean; virtual;
  139. procedure SetStoreUndo(AStore: boolean); virtual;
  140. procedure ClearUndoList;
  141. function GetSyntaxCompleted: boolean; virtual;
  142. procedure SetSyntaxCompleted(SC : boolean); virtual;
  143. function GetLastSyntaxedLine: sw_integer; virtual;
  144. procedure SetLastSyntaxedLine(ALine: sw_integer); virtual;
  145. function GetTabSize: integer; virtual;
  146. procedure SetTabSize(ATabSize: integer); virtual;
  147. function GetIndentSize: integer; virtual;
  148. procedure SetIndentSize(AIndentSize: integer); virtual;
  149. function IsReadOnly: boolean; virtual;
  150. public
  151. procedure UpdateIndicator; virtual;
  152. procedure ModifiedChanged; virtual;
  153. procedure PositionChanged; virtual;
  154. procedure LimitsChanged; virtual;
  155. function IsClipboard: Boolean; virtual;
  156. function LoadFromStream(Stream: PStream): boolean; virtual;
  157. function SaveToStream(Stream: PStream): boolean; virtual;
  158. function SaveAreaToStream(Stream: PStream; StartP,EndP: TPoint): boolean;virtual;
  159. destructor Done; virtual;
  160. public
  161. { ChangedLine : sw_integer;}
  162. { Text & info storage abstraction }
  163. function GetLineCount: sw_integer; virtual;
  164. function GetLine(LineNo: sw_integer): PCustomLine; virtual;
  165. function CharIdxToLinePos(Line,CharIdx: sw_integer): sw_integer; virtual;
  166. function LinePosToCharIdx(Line,X: sw_integer): sw_integer; virtual;
  167. function GetLineText(I: sw_integer): string; virtual;
  168. procedure SetDisplayText(I: sw_integer;const S: string); virtual;
  169. function GetDisplayText(I: sw_integer): string; virtual;
  170. procedure SetLineText(I: sw_integer;const S: string); virtual;
  171. procedure GetDisplayTextFormat(I: sw_integer;var DT,DF:string); virtual;
  172. function GetLineFormat(I: sw_integer): string; virtual;
  173. procedure SetLineFormat(I: sw_integer;const S: string); virtual;
  174. procedure DeleteAllLines; virtual;
  175. procedure DeleteLine(I: sw_integer); virtual;
  176. function InsertLine(LineNo: sw_integer; const S: string): PCustomLine; virtual;
  177. procedure AddLine(const S: string); virtual;
  178. function GetErrorMessage: string; virtual;
  179. procedure SetErrorMessage(const S: string); virtual;
  180. procedure GetContent(ALines: PUnsortedStringCollection); virtual;
  181. procedure SetContent(ALines: PUnsortedStringCollection); virtual;
  182. procedure Lock; virtual;
  183. procedure UnLock; virtual;
  184. public
  185. { CodeComplete support }
  186. function GetCodeCompleteWord: string; virtual;
  187. procedure SetCodeCompleteWord(const S: string); virtual;
  188. function GetCodeCompleteFrag: string; virtual;
  189. procedure SetCodeCompleteFrag(const S: string); virtual;
  190. function GetCompleteState: TCompleteState; virtual;
  191. procedure SetCompleteState(AState: TCompleteState); virtual;
  192. public
  193. { Syntax highlight }
  194. {a}function UpdateAttrs(FromLine: sw_integer; Attrs: byte): sw_integer; virtual;
  195. {a}function UpdateAttrsRange(FromLine, ToLine: sw_integer; Attrs: byte): sw_integer; virtual;
  196. public
  197. { Undo info storage }
  198. procedure AddAction(AAction: byte; AStartPos, AEndPos: TPoint; AText: string); virtual;
  199. procedure AddGroupedAction(AAction : byte); virtual;
  200. procedure CloseGroupedAction(AAction : byte); virtual;
  201. function GetUndoActionCount: sw_integer; virtual;
  202. function GetRedoActionCount: sw_integer; virtual;
  203. procedure JumpToLastCursorPos; virtual;
  204. procedure Undo; virtual;
  205. procedure Redo; virtual;
  206. { Fold support }
  207. function GetMaxFoldLevel: sw_integer; virtual;
  208. function GetFoldCount: sw_integer; virtual;
  209. function GetFold(Index: sw_integer): PFold; virtual;
  210. procedure RegisterFold(AFold: PFold); virtual;
  211. procedure UnRegisterFold(AFold: PFold); virtual;
  212. end;
  213. PFileEditor = ^TFileEditor;
  214. TFileEditor = object(TCodeEditor)
  215. FileName: string;
  216. constructor Init(var Bounds: TRect; AHScrollBar, AVScrollBar:
  217. PScrollBar; AIndicator: PIndicator; ACore: PCodeEditorCore; const AFileName: string);
  218. function Save: Boolean; virtual;
  219. function SaveAs: Boolean; virtual;
  220. function SaveAsk(Force: boolean): Boolean; virtual;
  221. function LoadFile: boolean; virtual;
  222. function ReloadFile: boolean; virtual;
  223. function SaveFile: boolean; virtual;
  224. function Valid(Command: Word): Boolean; virtual;
  225. procedure HandleEvent(var Event: TEvent); virtual;
  226. function ShouldSave: boolean; virtual;
  227. function IsChangedOnDisk : boolean;
  228. public
  229. procedure BindingsChanged; virtual;
  230. private
  231. OnDiskLoadTime : longint;
  232. end;
  233. function DefUseSyntaxHighlight(Editor: PFileEditor): boolean;
  234. function DefUseTabsPattern(Editor: PFileEditor): boolean;
  235. const
  236. DefaultCodeEditorFlags : longint =
  237. efBackupFiles+efInsertMode+efAutoIndent+efPersistentBlocks+
  238. {efUseTabCharacters+}efBackSpaceUnindents+efSyntaxHighlight+
  239. efExpandAllTabs+efCodeComplete{+efFolds};
  240. DefaultTabSize : integer = 8;
  241. DefaultIndentSize : integer = 1;
  242. UseSyntaxHighlight : function(Editor: PFileEditor): boolean = {$ifdef fpc}@{$endif}DefUseSyntaxHighlight;
  243. UseTabsPattern : function(Editor: PFileEditor): boolean = {$ifdef fpc}@{$endif}DefUseTabsPattern;
  244. procedure RegisterWCEdit;
  245. implementation
  246. uses Dos,
  247. WConsts,
  248. {$ifdef FVISION}
  249. FVConsts,
  250. {$else}
  251. Commands,
  252. {$endif}
  253. App,WViews;
  254. {$ifndef NOOBJREG}
  255. const
  256. RIndicator: TStreamRec = (
  257. ObjType: 1100;
  258. VmtLink: Ofs(TypeOf(TIndicator)^);
  259. Load: @TIndicator.Load;
  260. Store: @TIndicator.Store
  261. );
  262. RCodeEditor: TStreamRec = (
  263. ObjType: 1101;
  264. VmtLink: Ofs(TypeOf(TCodeEditor)^);
  265. Load: @TCodeEditor.Load;
  266. Store: @TCodeEditor.Store
  267. );
  268. RFileEditor: TStreamRec = (
  269. ObjType: 1102;
  270. VmtLink: Ofs(TypeOf(TFileEditor)^);
  271. Load: @TFileEditor.Load;
  272. Store: @TFileEditor.Store
  273. );
  274. {$endif}
  275. constructor TLine.Init(AOwner: PCustomCodeEditorCore; const AText: string; AFlags: longint);
  276. begin
  277. inherited Init(AText,AFlags);
  278. // New(EditorInfos, Init(10,10));
  279. Owner:=AOwner;
  280. end;
  281. procedure TLine.AddEditorInfo(Index: sw_integer; AEditor: PCustomCodeEditor);
  282. begin
  283. if Index=0 then
  284. begin
  285. DefaultEditorInfo:=New(PEditorLineInfo, Init(AEditor));
  286. exit;
  287. end;
  288. if not assigned(EditorInfos) then
  289. begin
  290. New(EditorInfos, Init(10,10));
  291. EditorInfos^.AtInsert(0,DefaultEditorInfo);
  292. DefaultEditorInfo:=nil;
  293. end;
  294. EditorInfos^.AtInsert(Index,New(PEditorLineInfo, Init(AEditor)));
  295. end;
  296. procedure TLine.RemoveEditorInfo(AEditor: PCustomCodeEditor);
  297. var E: PEditorLineInfo;
  298. begin
  299. E:=GetEditorInfo(AEditor);
  300. if Assigned(EditorInfos) then
  301. EditorInfos^.Free(E);
  302. end;
  303. function TLine.GetText: string;
  304. begin
  305. GetText:=GetStr(Text);
  306. end;
  307. procedure TLine.SetText(const AText: string);
  308. begin
  309. SetStr(Text,AText);
  310. end;
  311. function TLine.GetEditorInfo(Editor: PCustomCodeEditor): PEditorLineInfo;
  312. function Match(P: PEditorLineInfo): boolean; {$ifdef TP}far;{$endif}
  313. begin
  314. Match:=P^.Editor=Editor;
  315. end;
  316. begin
  317. if not assigned(EditorInfos) then
  318. GetEditorInfo:=DefaultEditorInfo
  319. else
  320. GetEditorInfo:=EditorInfos^.FirstThat(@Match);
  321. end;
  322. function TLine.GetFlags: longint;
  323. begin
  324. GetFlags:=Flags;
  325. end;
  326. procedure TLine.SetFlags(AFlags: longint);
  327. begin
  328. Flags:=AFlags;
  329. if Assigned(Owner) then
  330. Owner^.ContentsChanged;
  331. end;
  332. destructor TLine.Done;
  333. begin
  334. if Assigned(Text) then
  335. DisposeStr(Text);
  336. Text:=nil;
  337. if Assigned(EditorInfos) then
  338. Dispose(EditorInfos, Done);
  339. EditorInfos:=nil;
  340. if Assigned(DefaultEditorInfo) then
  341. Dispose(DefaultEditorInfo, Done);
  342. DefaultEditorInfo:=nil;
  343. inherited Done;
  344. end;
  345. constructor TCodeEditorCore.Init;
  346. begin
  347. inherited Init;
  348. StoreUndo:=true;
  349. new(UndoList,init(500,1000));
  350. new(RedoList,init(500,1000));
  351. New(Lines, Init(500,1000));
  352. TabSize:=DefaultTabSize;
  353. IndentSize:=DefaultIndentSize;
  354. end;
  355. procedure TCodeEditorCore.ChangeLinesTo(ALines : PLineCollection);
  356. begin
  357. if assigned(lines) then
  358. Dispose(Lines,Done);
  359. Lines:=ALines;
  360. end;
  361. function TCodeEditorCore.GetLineCount: sw_integer;
  362. begin
  363. GetLineCount:=Lines^.Count;
  364. end;
  365. function TCodeEditorCore.GetLine(LineNo: sw_integer): PCustomLine;
  366. begin
  367. GetLine:=Lines^.At(LineNo);
  368. end;
  369. function TCodeEditorCore.GetModified: boolean;
  370. begin
  371. GetModified:=Modified;
  372. end;
  373. function TCodeEditorCore.GetModifyTime: cardinal;
  374. begin
  375. GetModifyTime:=ModifiedTime;
  376. end;
  377. procedure TCodeEditorCore.SetModified(AModified: boolean);
  378. begin
  379. if AModified<>Modified then
  380. begin
  381. Modified:=AModified;
  382. ModifiedChanged;
  383. end;
  384. ModifiedTime:=cardinal(Now);
  385. end;
  386. function TCodeEditorCore.GetStoreUndo: boolean;
  387. begin
  388. GetStoreUndo:=StoreUndo;
  389. end;
  390. procedure TCodeEditorCore.SetStoreUndo(AStore: boolean);
  391. begin
  392. if StoreUndo<>AStore then
  393. begin
  394. StoreUndo:=AStore;
  395. StoreUndoChanged;
  396. end;
  397. end;
  398. function TCodeEditorCore.GetSyntaxCompleted: boolean;
  399. begin
  400. {$ifdef TEST_PARTIAL_SYNTAX}
  401. GetSyntaxCompleted:=SyntaxComplete;
  402. {$else}
  403. GetSyntaxCompleted:=true;
  404. {$endif}
  405. end;
  406. procedure TCodeEditorCore.SetSyntaxCompleted(SC: boolean);
  407. begin
  408. {$ifdef TEST_PARTIAL_SYNTAX}
  409. if SC<>SyntaxComplete then
  410. begin
  411. SyntaxComplete:=SC;
  412. end;
  413. {$endif}
  414. end;
  415. function TCodeEditorCore.GetLastSyntaxedLine: sw_integer;
  416. begin
  417. GetLastSyntaxedLine:=LastSyntaxedLine;
  418. end;
  419. procedure TCodeEditorCore.SetLastSyntaxedLine(ALine: sw_integer);
  420. begin
  421. LastSyntaxedLine:=ALine;
  422. end;
  423. procedure TCodeEditorCore.ISetLineFlagState(Binding: PEditorBinding; LineNo: sw_integer; Flag: longint; ASet: boolean);
  424. var P: PCustomLine;
  425. begin
  426. if LineNo<GetLineCount then
  427. begin
  428. P:=GetLine(LineNo);
  429. if assigned(P) then
  430. P^.SetFlagState(Flag,ASet);
  431. end;
  432. end;
  433. procedure TCodeEditorCore.GetContent(ALines: PUnsortedStringCollection);
  434. procedure AddIt(P: PCustomLine); {$ifndef FPC}far;{$endif}
  435. begin
  436. if Assigned(P) then
  437. ALines^.Insert(NewStr(P^.GetText));
  438. end;
  439. begin
  440. if Assigned(Lines) then
  441. Lines^.ForEach(@AddIt);
  442. end;
  443. procedure TCodeEditorCore.SetContent(ALines: PUnsortedStringCollection);
  444. procedure AddIt(P: PString); {$ifndef FPC}far;{$endif}
  445. begin
  446. AddLine(GetStr(P));
  447. end;
  448. begin
  449. DeleteAllLines;
  450. if Assigned(ALines) then
  451. ALines^.ForEach(@AddIt);
  452. LimitsChanged;
  453. end;
  454. function TCodeEditorCore.GetTabSize: integer;
  455. begin
  456. GetTabSize:=TabSize;
  457. end;
  458. procedure TCodeEditorCore.SetTabSize(ATabSize: integer);
  459. begin
  460. if ATabSize<>TabSize then
  461. begin
  462. TabSize:=ATabSize;
  463. TabSizeChanged;
  464. end;
  465. end;
  466. function TCodeEditorCore.GetIndentSize: integer;
  467. begin
  468. GetIndentSize:=IndentSize;
  469. end;
  470. procedure TCodeEditorCore.SetIndentSize(AIndentSize: integer);
  471. begin
  472. if AIndentSize<>IndentSize then
  473. begin
  474. IndentSize:=AIndentSize;
  475. end;
  476. end;
  477. function TCodeEditorCore.GetLineText(LineNo: sw_integer): string;
  478. var
  479. L : PCustomLine;
  480. begin
  481. GetLineText:='';
  482. if LineNo<Lines^.Count then
  483. begin
  484. L:=Lines^.At(LineNo);
  485. GetLineText:=L^.GetText;
  486. end;
  487. end;
  488. procedure TCodeEditorCore.LinesInsert(Idx: sw_integer; Line: PLine);
  489. var I: sw_integer;
  490. procedure RegLine(P: PEditorBinding); {$ifndef FPC}far;{$endif}
  491. begin
  492. Line^.AddEditorInfo(I,P^.Editor);
  493. Inc(I);
  494. end;
  495. begin
  496. if Idx=-1 then Idx:=Lines^.Count;
  497. I:=0;
  498. Bindings^.ForEach(@RegLine);
  499. Lines^.AtInsert(Idx,Line);
  500. end;
  501. procedure TCodeEditorCore.SetLineText(I: sw_integer;const S: string);
  502. var
  503. L : PCustomLine;
  504. AddCount : Sw_Integer;
  505. begin
  506. AddCount:=0;
  507. while (Lines^.Count<I+1) do
  508. begin
  509. LinesInsert(-1,New(PLine, Init(@Self,'',0)));
  510. Inc(AddCount);
  511. end;
  512. if AddCount>0 then
  513. LimitsChanged;
  514. L:=Lines^.At(I);
  515. L^.SetText(S);
  516. ContentsChanged;
  517. end;
  518. function TCodeEditorCore.GetDisplayText(I: sw_integer): string;
  519. begin
  520. GetDisplayText:=ExtractTabs(GetLineText(I),GetTabSize);
  521. end;
  522. procedure TCodeEditorCore.SetDisplayText(I: sw_integer;const S: string);
  523. begin
  524. { I disagree here
  525. I don't want the editor to change the position of the tabs
  526. in my makefiles !! PM
  527. if FlagSet(efUseTabCharacters) and (TabSize>0) then
  528. SetLineText(I,CompressUsingTabs(S,TabSize))
  529. else }
  530. { ... then you better make this optional - Gabor }
  531. SetLineText(I,S);
  532. end;
  533. procedure TCodeEditorCore.IGetDisplayTextFormat(Binding: PEditorBinding; LineNo: sw_integer;var DT,DF:string);
  534. var
  535. L : PCustomLine;
  536. P,PAdd : SW_Integer;
  537. begin
  538. DF:='';
  539. DT:='';
  540. if (0<=LineNo) and (LineNo<GetLineCount) then
  541. begin
  542. L:=GetLine(LineNo);
  543. if not assigned(L) then
  544. exit;
  545. DF:=IGetLineFormat(Binding,LineNo);
  546. DT:=L^.GetText;
  547. p:=0;
  548. while p<length(DT) do
  549. begin
  550. inc(p);
  551. if DT[p]=#9 then
  552. begin
  553. PAdd:=TabSize-((p-1) mod TabSize);
  554. if DF<>'' then
  555. DF:=copy(DF,1,P-1)+CharStr(DF[p],PAdd)+copy(DF,P+1,High(DF));
  556. DT:=copy(DT,1,P-1)+CharStr(' ',PAdd)+copy(DT,P+1,High(DF));
  557. inc(P,PAdd-1);
  558. end;
  559. end;
  560. end;
  561. end;
  562. function TCodeEditorCore.IGetLineFormat(Binding: PEditorBinding; LineNo: sw_integer): string;
  563. var P: PCustomLine;
  564. LI: PEditorLineInfo;
  565. S: string;
  566. begin
  567. if (0<=LineNo) and (LineNo<GetLineCount) then
  568. P:=GetLine(LineNo)
  569. else
  570. P:=nil;
  571. if P=nil then LI:=nil else
  572. LI:=P^.GetEditorInfo(Binding^.Editor);
  573. if LI=nil then S:='' else S:=LI^.GetFormat;
  574. IGetLineFormat:=S;
  575. end;
  576. procedure TCodeEditorCore.ISetLineFormat(Binding: PEditorBinding; LineNo: sw_integer;const S: string);
  577. var P: PCustomLine;
  578. LI: PEditorLineInfo;
  579. begin
  580. if (LineNo<GetLineCount) then
  581. begin
  582. P:=GetLine(LineNo);
  583. if P=nil then LI:=nil else LI:=P^.GetEditorInfo(Binding^.Editor);
  584. if Assigned(LI) then LI^.SetFormat(S);
  585. end;
  586. end;
  587. procedure TCodeEditorCore.DeleteAllLines;
  588. begin
  589. if Assigned(Lines) then
  590. Lines^.FreeAll;
  591. end;
  592. procedure TCodeEditorCore.DeleteLine(I: sw_integer);
  593. var
  594. CP : Tpoint;
  595. begin
  596. if I<Lines^.Count then
  597. begin
  598. if StoreUndo then
  599. begin
  600. CP.X:=0;CP.Y:=I;
  601. AddAction(eaDeleteLine,CP,CP,GetLineText(I));
  602. end;
  603. Lines^.AtFree(I);
  604. end;
  605. end;
  606. function TCodeEditorCore.InsertLine(LineNo: sw_integer; const S: string): PCustomLine;
  607. var L: PLine;
  608. begin
  609. L:=New(PLine, Init(@Self,S,0));
  610. LinesInsert(LineNo, L);
  611. InsertLine:=L;
  612. end;
  613. procedure TCodeEditorCore.AddLine(const S: string);
  614. begin
  615. LinesInsert(-1,New(PLine, Init(@Self,S,0)));
  616. end;
  617. procedure TCodeEditorCore.AddAction(AAction: byte; AStartPos, AEndPos: TPoint; AText: string);
  618. var
  619. ActionIntegrated : boolean;
  620. pa : PEditorAction;
  621. S : String;
  622. begin
  623. if (UndoList=nil) or (not StoreUndo) then Exit;
  624. ActionIntegrated:=false;
  625. if UndoList^.count>0 then
  626. begin
  627. pa:=UndoList^.At(UndoList^.count-1);
  628. if (pa^.action=AAction) and
  629. (pa^.EndPos.X=AStartPos.X) and
  630. (pa^.EndPos.Y=AStartPos.Y) and
  631. { do not group InsertLine and DeleteLine !! }
  632. ((AAction=eaMoveCursor) or
  633. (AAction=eaInsertText) or
  634. (AAction=eaOverwriteText) or
  635. (AAction=eaDeleteText)) and
  636. { do not group if a new grouped_action started }
  637. (not assigned(UndoList^.CurrentGroupedAction) or
  638. (UndoList^.CurrentGroupedAction^.ActionCount>0))
  639. then
  640. begin
  641. pa^.EndPos:=AEndPos;
  642. S:=GetStr(pa^.text);
  643. if S<>'' then
  644. DisposeStr(pa^.text);
  645. if (AAction=eaDeleteText) and
  646. (AStartPos.X>AEndPos.X) then
  647. pa^.text:=NewStr(AText+S)
  648. else
  649. pa^.text:=NewStr(S+AText);
  650. ActionIntegrated:=true;
  651. end;
  652. end;
  653. if not ActionIntegrated then
  654. begin
  655. UndoList^.Insert(New(PEditorAction,Init(AAction,AStartPos,AEndPos,AText)));
  656. if assigned(UndoList^.CurrentGroupedAction) then
  657. Inc(UndoList^.CurrentGroupedAction^.actionCount);
  658. UpdateUndoRedo(cmUndo,AAction);
  659. end;
  660. if UndoList^.count>0 then
  661. begin
  662. UpdateUndoRedo(cmRedo,0);
  663. RedoList^.FreeAll;
  664. end;
  665. end;
  666. procedure TCodeEditorCore.AddGroupedAction(AAction : byte);
  667. begin
  668. if Assigned(UndoList^.CurrentGroupedAction) then
  669. inc(UndoList^.GroupLevel)
  670. else
  671. begin
  672. UndoList^.CurrentGroupedAction:=New(PEditorAction,Init_group(AAction));
  673. UndoList^.GroupLevel:=1;
  674. end;
  675. end;
  676. procedure TCodeEditorCore.CloseGroupedAction(AAction : byte);
  677. begin
  678. dec(UndoList^.GroupLevel);
  679. if UndoList^.GroupLevel=0 then
  680. begin
  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. WasInserting,Is_grouped,Had_efNoIndent : boolean;
  1145. MaxY,MinY : sw_integer;
  1146. Line : String;
  1147. procedure SetMinMax(y : sw_integer);
  1148. begin
  1149. if MinY=-1 then
  1150. MinY:=Y;
  1151. if Y<MinY then
  1152. MinY:=Y;
  1153. if MaxY=-1 then
  1154. MaxY:=Y;
  1155. if Y>MaxY then
  1156. MaxY:=Y;
  1157. end;
  1158. begin
  1159. Core^.SetStoreUndo(False);
  1160. Lock;
  1161. MinY:=-1;
  1162. MaxY:=-1;
  1163. if Core^.UndoList^.count > 0 then
  1164. begin
  1165. Last:=Core^.UndoList^.count-1;
  1166. if Core^.UndoList^.At(Last)^.Is_grouped_action then
  1167. begin
  1168. Count:=Core^.UndoList^.At(Last)^.ActionCount;
  1169. Dec(Last);
  1170. Is_grouped:=true;
  1171. end
  1172. else
  1173. begin
  1174. Count:=1;
  1175. Is_grouped:=false;
  1176. end;
  1177. for Idx:=Last downto Last-Count+1 do
  1178. with Core^.UndoList^.At(Idx)^ do
  1179. begin
  1180. case action of
  1181. eaMoveCursor :
  1182. begin
  1183. { move cursor back to original position }
  1184. SetCurPtr(startpos.x,startpos.y);
  1185. end;
  1186. eaInsertText :
  1187. begin
  1188. SetCurPtr(StartPos.X,StartPos.Y);
  1189. if assigned(text) then
  1190. for Temp := 1 to length(Text^) do
  1191. DelChar;
  1192. SetMinMax(StartPos.Y);
  1193. end;
  1194. eaDeleteText :
  1195. begin
  1196. { reinsert deleted text }
  1197. SetCurPtr(EndPos.X,EndPos.Y);
  1198. if assigned(text) then
  1199. for Temp := 1 to length(Text^) do
  1200. AddChar(Text^[Temp]);
  1201. SetMinMax(EndPos.Y);
  1202. SetCurPtr(StartPos.X,StartPos.Y);
  1203. end;
  1204. eaOverwriteText :
  1205. begin
  1206. SetCurPtr(StartPos.X,StartPos.Y);
  1207. Line:=GetDisplayText(StartPos.Y);
  1208. WasInserting:=GetInsertMode;
  1209. SetInsertMode(false);
  1210. if assigned(text) then
  1211. for Temp := 1 to length(Text^) do
  1212. begin
  1213. AddChar(Text^[Temp]);
  1214. if StartPos.X+Temp>Length(Line) then
  1215. Text^[Temp]:=' '
  1216. else
  1217. Text^[Temp]:=Line[StartPos.X+Temp];
  1218. end;
  1219. SetInsertMode(WasInserting);
  1220. SetMinMax(EndPos.Y);
  1221. SetCurPtr(StartPos.X,StartPos.Y);
  1222. end;
  1223. eaInsertLine :
  1224. begin
  1225. SetCurPtr(EndPos.X,EndPos.Y);
  1226. SetDisplayText(EndPos.Y,Copy(GetDisplayText(EndPos.Y),EndPos.X+1,255));
  1227. SetMinMax(EndPos.Y);
  1228. SetCurPtr(0,EndPos.Y);
  1229. BackSpace;
  1230. SetCurPtr(StartPos.X,StartPos.Y);
  1231. SetMinMax(StartPos.Y);
  1232. end;
  1233. eaDeleteLine :
  1234. begin
  1235. SetCurPtr(EndPos.X,EndPos.Y);
  1236. SetMinMax(EndPos.Y);
  1237. Had_efNoIndent:=(GetFlags and efNoIndent)<>0;
  1238. WasInserting:=GetInsertMode;
  1239. SetInsertMode(true);
  1240. SetFlags(GetFlags or efNoIndent);
  1241. InsertNewLine;
  1242. SetInsertMode(WasInserting);
  1243. if not Had_efNoIndent then
  1244. SetFlags(GetFlags and not efNoIndent);
  1245. {DelEnd; wrong for eaCut at least }
  1246. SetCurPtr(StartPos.X,StartPos.Y);
  1247. SetLineText(StartPos.Y,Copy(GetDisplayText(StartPos.Y),1,StartPos.X)+GetStr(Text));
  1248. SetMinMax(StartPos.Y);
  1249. end;
  1250. eaSelectionChanged :
  1251. begin
  1252. { move cursor to end of last set selection }
  1253. end;
  1254. else
  1255. { what the 'ell's an undefined action doing round 'ere mate! }
  1256. ;
  1257. end; { once this lot is done paste into redo and modify to suit needs }
  1258. { move item to redo stack }
  1259. Core^.RedoList^.Insert(Core^.UndoList^.At(Idx));
  1260. UpdateUndoRedo(cmRedo,Core^.UndoList^.At(Idx)^.Action);
  1261. Core^.UndoList^.atDelete(Idx);
  1262. If Idx>0 then
  1263. UpdateUndoRedo(cmUndo,Core^.UndoList^.At(Idx-1)^.Action)
  1264. else
  1265. UpdateUndoRedo(cmUndo,0);
  1266. end;{Idx loop for grouped actions }
  1267. if is_grouped then
  1268. begin
  1269. Idx:=Core^.UndoList^.Count-1;
  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;
  1278. if Core^.UndoList^.count=0 then
  1279. SetCmdState(UndoCmd,false);
  1280. SetCmdState(RedoCmd,true);
  1281. Message(Application,evBroadcast,cmCommandSetChanged,nil);
  1282. if MinY<>-1 then
  1283. UpdateAttrsRange(MinY,MaxY,attrAll);
  1284. DrawView;
  1285. end;
  1286. Core^.SetStoreUndo(True);
  1287. Unlock;
  1288. end;
  1289. procedure TCodeEditor.Redo;
  1290. var
  1291. Temp,Idx,Last,Count : Longint;
  1292. WasInserting,Is_grouped,Had_efNoIndent : boolean;
  1293. Line : String;
  1294. MaxY,MinY : sw_integer;
  1295. procedure SetMinMax(y : sw_integer);
  1296. begin
  1297. if MinY=-1 then
  1298. MinY:=Y;
  1299. if Y<MinY then
  1300. MinY:=Y;
  1301. if MaxY=-1 then
  1302. MaxY:=Y;
  1303. if Y>MaxY then
  1304. MaxY:=Y;
  1305. end;
  1306. begin
  1307. Core^.SetStoreUndo(False);
  1308. Lock;
  1309. MinY:=-1;
  1310. MaxY:=-1;
  1311. if Core^.RedoList^.count <> 0 then
  1312. begin
  1313. Last:=Core^.RedoList^.count-1;
  1314. if Core^.RedoList^.At(Last)^.Is_grouped_action then
  1315. begin
  1316. Count:=Core^.RedoList^.At(Last)^.ActionCount;
  1317. Dec(Last);
  1318. Is_grouped:=true;
  1319. end
  1320. else
  1321. begin
  1322. Count:=1;
  1323. Is_grouped:=false;
  1324. end;
  1325. for Idx:=Last downto Last-Count+1 do
  1326. with Core^.RedoList^.At(Idx)^ do
  1327. begin
  1328. case action of
  1329. eaMoveCursor :
  1330. begin
  1331. { move cursor back to original position }
  1332. SetCurPtr(EndPos.X,EndPos.Y);
  1333. end;
  1334. eaInsertText :
  1335. begin
  1336. SetCurPtr(startpos.x,startpos.y);
  1337. InsertText(GetStr(Text));
  1338. SetMinMax(StartPos.Y);
  1339. end;
  1340. eaDeleteText :
  1341. begin
  1342. SetCurPtr(EndPos.X,EndPos.Y);
  1343. for Temp := 1 to length(GetStr(Text)) do
  1344. DelChar;
  1345. SetMinMax(EndPos.Y);
  1346. end;
  1347. eaOverwriteText :
  1348. begin
  1349. SetCurPtr(StartPos.X,StartPos.Y);
  1350. Line:=GetDisplayText(StartPos.Y);
  1351. WasInserting:=GetInsertMode;
  1352. SetInsertMode(false);
  1353. if assigned(text) then
  1354. for Temp := 1 to length(Text^) do
  1355. begin
  1356. AddChar(Text^[Temp]);
  1357. if StartPos.X+Temp>Length(Line) then
  1358. Text^[Temp]:=' '
  1359. else
  1360. Text^[Temp]:=Line[StartPos.X+Temp];
  1361. end;
  1362. SetInsertMode(WasInserting);
  1363. SetCurPtr(EndPos.X,EndPos.Y);
  1364. SetMinMax(StartPos.Y);
  1365. end;
  1366. eaInsertLine :
  1367. begin
  1368. SetCurPtr(StartPos.X,StartPos.Y);
  1369. Had_efNoIndent:=(GetFlags and efNoIndent)<>0;
  1370. SetFlags(GetFlags or efNoIndent);
  1371. WasInserting:=GetInsertMode;
  1372. SetInsertMode(false);
  1373. InsertNewLine;
  1374. SetInsertMode(WasInserting);
  1375. SetCurPtr(StartPos.X,StartPos.Y);
  1376. InsertText(GetStr(Text));
  1377. if not Had_efNoIndent then
  1378. SetFlags(GetFlags and not efNoIndent);
  1379. SetCurPtr(EndPos.X,EndPos.Y);
  1380. SetMinMax(StartPos.Y);
  1381. end;
  1382. eaDeleteLine :
  1383. begin
  1384. SetCurPtr(StartPos.X,StartPos.Y);
  1385. DeleteLine(StartPos.Y);
  1386. SetCurPtr(EndPos.X,EndPos.Y);
  1387. if EndPos.Y=StartPos.Y-1 then
  1388. SetDisplayText(EndPos.Y,RExpand(
  1389. copy(GetDisplayText(EndPos.Y),1,EndPos.X),EndPos.X)
  1390. +GetStr(Text));
  1391. SetCurPtr(EndPos.X,EndPos.Y);
  1392. SetMinMax(StartPos.Y);
  1393. SetMinMax(EndPos.Y);
  1394. end;
  1395. eaSelectionChanged :
  1396. begin
  1397. { move cursor to end of last set test selection }
  1398. end;
  1399. else
  1400. { what the 'ell's an undefined action doing round 'ere mate! }
  1401. ;
  1402. end; { once this lot is done paste back into undo and modify to suit needs }
  1403. { move item to undo stack }
  1404. Core^.UndoList^.Insert(Core^.RedoList^.At(Idx));
  1405. UpdateUndoRedo(cmUndo,Core^.RedoList^.At(Idx)^.Action);
  1406. If Idx>0 then
  1407. UpdateUndoRedo(cmRedo,Core^.RedoList^.At(Idx-1)^.Action)
  1408. else
  1409. UpdateUndoRedo(cmRedo,0);
  1410. Core^.RedoList^.atDelete(Idx);
  1411. end;{ Idx loop for grouped action }
  1412. If is_grouped then
  1413. begin
  1414. Idx:=Core^.RedoList^.count-1;
  1415. Core^.UndoList^.Insert(Core^.RedoList^.At(Idx));
  1416. UpdateUndoRedo(cmUndo,Core^.RedoList^.At(Idx)^.Action);
  1417. If Idx>0 then
  1418. UpdateUndoRedo(cmRedo,Core^.RedoList^.At(Idx-1)^.Action)
  1419. else
  1420. UpdateUndoRedo(cmRedo,0);
  1421. Core^.RedoList^.atDelete(Idx);
  1422. end;
  1423. if Core^.RedoList^.count=0 then
  1424. SetCmdState(RedoCmd,false);
  1425. SetCmdState(UndoCmd,true);
  1426. Message(Application,evBroadcast,cmCommandSetChanged,nil);
  1427. if MinY<>-1 then
  1428. UpdateAttrsRange(MinY,MaxY,attrAll);
  1429. DrawView;
  1430. end;
  1431. Core^.SetStoreUndo(True);
  1432. Unlock;
  1433. end;
  1434. (*constructor TCodeEditor.Load(var S: TStream);
  1435. var TS: PSubStream;
  1436. TSize: longint;
  1437. begin
  1438. inherited Load(S);
  1439. New(UndoList,init(500,1000));
  1440. New(RedoList,init(500,1000));
  1441. New(Lines, Init(500,1000));
  1442. { we have always need at least 1 line }
  1443. LinesInsert(New(PLine, Init('',0)));
  1444. GetPeerViewPtr(S,Indicator);
  1445. S.Read(Flags,SizeOf(Flags));
  1446. S.Read(TabSize,SizeOf(TabSize));
  1447. if IsFlagSet(efStoreContent) then
  1448. begin
  1449. S.Read(TSize,SizeOf(TSize));
  1450. New(TS, Init(@S,S.GetPos,TSize));
  1451. {$ifdef TEST_PARTIAL_SYNTAX}
  1452. Core^.SearchBinding(Editor)^.SyntaxComplete:=false;
  1453. { Idle necessary }
  1454. EventMask:=EventMask or evIdle;
  1455. {$endif TEST_PARTIAL_SYNTAX}
  1456. LoadFromStream(TS);
  1457. Dispose(TS, Done);
  1458. end;
  1459. S.Read(SelStart,SizeOf(SelStart));
  1460. S.Read(SelEnd,SizeOf(SelEnd));
  1461. S.Read(Highlight,SizeOf(Highlight));
  1462. S.Read(CurPos,SizeOf(CurPos));
  1463. S.Read(StoreUndo,SizeOf(StoreUndo));
  1464. S.Read(IsReadOnly,SizeOf(IsReadOnly));
  1465. S.Read(NoSelect,SizeOf(NoSelect));
  1466. S.Read(HighlightRow,SizeOf(HighlightRow));
  1467. SetDebuggerRow(-1);
  1468. LimitsChanged;
  1469. SelectionChanged; HighlightChanged;
  1470. UpdateIndicator;
  1471. end;
  1472. procedure TCodeEditor.Store(var S: TStream);
  1473. var {NS: TNulStream;}
  1474. TSizePos,TSize,EndPos: longint;
  1475. begin
  1476. inherited Store(S);
  1477. PutPeerViewPtr(S,Indicator);
  1478. S.Write(Flags,SizeOf(Flags));
  1479. S.Write(TabSize,SizeOf(TabSize));
  1480. if IsFlagSet(efStoreContent) then
  1481. begin
  1482. { NS.Init;
  1483. SaveToStream(@NS);
  1484. TSize:=NS.GetSize;
  1485. NS.Done;
  1486. This is waste of time PM
  1487. use Seek instead !! }
  1488. { yep. and this won't work for serial streams. - Gabor }
  1489. TSize:=0;
  1490. TSizePos:=S.GetPos;
  1491. S.Write(TSize,SizeOf(TSize));
  1492. SaveToStream(@S);
  1493. EndPos:=S.GetPos;
  1494. TSize:=EndPos-TSizePos-SizeOf(TSize);
  1495. S.Seek(TSizePos);
  1496. S.Write(TSize,SizeOf(TSize));
  1497. S.Seek(EndPos);
  1498. end;
  1499. S.Write(SelStart,SizeOf(SelStart));
  1500. S.Write(SelEnd,SizeOf(SelEnd));
  1501. S.Write(Highlight,SizeOf(Highlight));
  1502. S.Write(CurPos,SizeOf(CurPos));
  1503. S.Write(StoreUndo,SizeOf(StoreUndo));
  1504. S.Write(IsReadOnly,SizeOf(IsReadOnly));
  1505. S.Write(NoSelect,SizeOf(NoSelect));
  1506. S.Write(HighlightRow,SizeOf(HighlightRow));
  1507. end;*)
  1508. function TCodeEditor.LoadFromStream(Stream: PStream): boolean;
  1509. var OK: boolean;
  1510. begin
  1511. OK:=Core^.LoadFromStream(@Self,Stream);
  1512. if IsFlagSet(efSyntaxHighlight) then
  1513. UpdateAttrsRange(0,Min(Delta.Y+Size.Y,GetLineCount-1),
  1514. attrAll
  1515. {$ifndef TEST_PARTIAL_SYNTAX}
  1516. +attrForceFull
  1517. {$endif TEST_PARTIAL_SYNTAX}
  1518. );
  1519. TextStart;
  1520. LoadFromStream:=OK;
  1521. end;
  1522. function TCodeEditor.SaveToStream(Stream: PStream): boolean;
  1523. begin
  1524. SaveToStream:=Core^.SaveToStream(@Self,Stream);
  1525. end;
  1526. function TCodeEditor.SaveAreaToStream(Stream: PStream; StartP,EndP: TPoint): boolean;
  1527. begin
  1528. SaveAreaToStream:=Core^.SaveAreaToStream(@Self,Stream,StartP,EndP);
  1529. end;
  1530. function TCodeEditor.UpdateAttrs(FromLine: sw_integer; Attrs: byte): sw_integer;
  1531. begin
  1532. UpdateAttrs:=Core^.UpdateAttrs(FromLine,Attrs);
  1533. end;
  1534. function TCodeEditor.UpdateAttrsRange(FromLine, ToLine: sw_integer; Attrs: byte): sw_integer;
  1535. begin
  1536. UpdateAttrsRange:=Core^.UpdateAttrsRange(FromLine,ToLine,Attrs);
  1537. end;
  1538. procedure TCodeEditor.AddAction(AAction: byte; AStartPos, AEndPos: TPoint; AText: string);
  1539. begin
  1540. Core^.AddAction(AAction,AStartPos,AEndPos,AText);
  1541. end;
  1542. procedure TCodeEditor.AddGroupedAction(AAction : byte);
  1543. begin
  1544. Core^.AddGroupedAction(AAction);
  1545. end;
  1546. procedure TCodeEditor.CloseGroupedAction(AAction : byte);
  1547. begin
  1548. Core^.CloseGroupedAction(AAction);
  1549. end;
  1550. function TCodeEditor.GetUndoActionCount: sw_integer;
  1551. begin
  1552. GetUndoActionCount:=Core^.GetUndoActionCount;
  1553. end;
  1554. function TCodeEditor.GetRedoActionCount: sw_integer;
  1555. begin
  1556. GetRedoActionCount:=Core^.GetRedoActionCount;
  1557. end;
  1558. destructor TCodeEditor.Done;
  1559. begin
  1560. inherited Done;
  1561. if Assigned(Core) then
  1562. begin
  1563. Core^.UnBindEditor(@Self);
  1564. if Core^.CanDispose then
  1565. Dispose(Core, Done);
  1566. end;
  1567. Core:=nil;
  1568. if Assigned(CodeCompleteFrag) then
  1569. DisposeStr(CodeCompleteFrag);
  1570. if Assigned(CodeCompleteWord) then
  1571. DisposeStr(CodeCompleteWord);
  1572. if Assigned(ErrorMessage) then
  1573. DisposeStr(ErrorMessage);
  1574. if Assigned(Folds) then
  1575. Dispose(Folds, Done);
  1576. Folds:=nil;
  1577. end;
  1578. constructor TFileEditor.Init(var Bounds: TRect; AHScrollBar, AVScrollBar:
  1579. PScrollBar; AIndicator: PIndicator;ACore: PCodeEditorCore; const AFileName: string);
  1580. begin
  1581. inherited Init(Bounds,AHScrollBAr,AVScrollBAr,AIndicator,ACore);
  1582. FileName:=AFileName;
  1583. UpdateIndicator;
  1584. Message(@Self,evBroadcast,cmFileNameChanged,@Self);
  1585. OnDiskLoadTime:=-1;
  1586. end;
  1587. function TFileEditor.LoadFile: boolean;
  1588. var OK: boolean;
  1589. PA : Array[1..2] of pointer;
  1590. begin
  1591. OK:=LoadFromFile(FileName);
  1592. if GetModified and (Core^.GetBindingCount=1) then
  1593. begin
  1594. PA[1]:=@FileName;
  1595. longint(PA[2]):=Core^.GetChangedLine;
  1596. EditorDialog(edChangedOnloading,@PA);
  1597. end;
  1598. OnDiskLoadTime:=GetFileTime(FileName);
  1599. LoadFile:=OK;
  1600. end;
  1601. function TFileEditor.IsChangedOnDisk : boolean;
  1602. begin
  1603. IsChangedOnDisk:=(OnDiskLoadTime<>GetFileTime(FileName)) and (OnDiskLoadTime<>-1);
  1604. end;
  1605. function TFileEditor.SaveFile: boolean;
  1606. var OK: boolean;
  1607. BAKName: string;
  1608. f: text;
  1609. begin
  1610. If IsChangedOnDisk then
  1611. begin
  1612. if EditorDialog(edFileOnDiskChanged, @FileName) <> cmYes then
  1613. begin
  1614. SaveFile:=false;
  1615. exit;
  1616. end;
  1617. end;
  1618. {$I-}
  1619. if IsFlagSet(efBackupFiles) and ExistsFile(FileName) then
  1620. begin
  1621. BAKName:=DirAndNameOf(FileName)+'.bak';
  1622. Assign(f,BAKName);
  1623. Erase(f);
  1624. EatIO;
  1625. Assign(f,FileName);
  1626. Rename(F,BAKName);
  1627. EatIO;
  1628. end;
  1629. {$I+}
  1630. OK:=SaveToFile(FileName);
  1631. if OK then
  1632. SetModified(false)
  1633. { Restore the original }
  1634. else if IsFlagSet(efBackupFiles) and ExistsFile(BakName) then
  1635. begin
  1636. {$I-}
  1637. Assign(f,BakName);
  1638. Rename(F,FileName);
  1639. EatIO;
  1640. {$I+}
  1641. end;
  1642. { don't forget to update the OnDiskLoadTime value }
  1643. if OK then
  1644. OnDiskLoadTime:=GetFileTime(FileName);
  1645. if not OK then
  1646. EditorDialog(edSaveError,@FileName);
  1647. SaveFile:=OK;
  1648. end;
  1649. function TFileEditor.ReloadFile: boolean;
  1650. var OK,WasModified: boolean;
  1651. BAKName: string;
  1652. f: text;
  1653. begin
  1654. If not IsChangedOnDisk then
  1655. begin
  1656. ReloadFile:=false;
  1657. exit;
  1658. end;
  1659. WasModified:=GetModified;
  1660. if not WasModified then
  1661. OK:=EditorDialog(edreloaddiskmodifiedfile, @FileName)=cmYes
  1662. else
  1663. OK:=EditorDialog(edreloaddiskandidemodifiedfile, @FileName)=cmYes;
  1664. if not OK then
  1665. begin
  1666. ReloadFile:=false;
  1667. exit;
  1668. end;
  1669. { avoid wrong message }
  1670. if WasModified then
  1671. SetModified(false);
  1672. OK:=LoadFile;
  1673. if OK then
  1674. begin
  1675. SetModified(false);
  1676. ClearUndoList;
  1677. { don't forget to update the OnDiskLoadTime value }
  1678. OnDiskLoadTime:=GetFileTime(FileName);
  1679. DrawView;
  1680. end
  1681. else
  1682. begin
  1683. if WasModified then
  1684. SetModified(true);
  1685. EditorDialog(edReadError,@FileName);
  1686. end;
  1687. ReloadFile:=OK;
  1688. end;
  1689. function TFileEditor.ShouldSave: boolean;
  1690. begin
  1691. ShouldSave:=GetModified{ or (FileName='')};
  1692. end;
  1693. function TFileEditor.Save: Boolean;
  1694. begin
  1695. if ShouldSave=false then begin Save:=true; Exit; end;
  1696. if FileName = '' then Save := SaveAs else Save := SaveFile;
  1697. end;
  1698. function TFileEditor.SaveAs: Boolean;
  1699. var
  1700. SavedName : String;
  1701. SavedDiskLoadTime : longint;
  1702. begin
  1703. SaveAs := False;
  1704. SavedName:=FileName;
  1705. SavedDiskLoadTime:=OnDiskLoadTime;
  1706. if EditorDialog(edSaveAs, @FileName) <> cmCancel then
  1707. begin
  1708. FileName:=FExpand(FileName);
  1709. Message(Owner, evBroadcast, cmUpdateTitle, @Self);
  1710. { if we rename the file the OnDiskLoadTime is wrong so we reset it }
  1711. OnDiskLoadTime:=-1;
  1712. if SaveFile then
  1713. begin
  1714. SaveAs := true;
  1715. end
  1716. else
  1717. begin
  1718. FileName:=SavedName;
  1719. OnDiskLoadTime:=SavedDiskLoadTime;
  1720. Message(Owner, evBroadcast, cmUpdateTitle, @Self);
  1721. end;
  1722. if IsClipboard then FileName := '';
  1723. Message(Application,evBroadcast,cmFileNameChanged,@Self);
  1724. end;
  1725. end;
  1726. function TFileEditor.SaveAsk(Force: boolean): boolean;
  1727. var OK: boolean;
  1728. D: Sw_integer;
  1729. begin
  1730. if Force then
  1731. begin
  1732. if GetModified then
  1733. OK:=Save
  1734. else
  1735. OK:=true;
  1736. end
  1737. else
  1738. begin
  1739. OK:=(GetModified=false);
  1740. if (OK=false) and (Core^.GetBindingCount>1) then
  1741. OK:=true;
  1742. if OK=false then
  1743. begin
  1744. if FileName = '' then D := edSaveUntitled else D := edSaveModify;
  1745. case EditorDialog(D, @FileName) of
  1746. cmYes : OK := Save;
  1747. cmNo : begin
  1748. { the file should be still marked as modified! (FK) }
  1749. { SetModified(False); }
  1750. OK:=true;
  1751. end;
  1752. cmCancel : begin
  1753. OK := False;
  1754. Message(Application,evBroadcast,cmSaveCancelled,@Self);
  1755. end;
  1756. end;
  1757. end;
  1758. end;
  1759. SaveAsk:=OK;
  1760. end;
  1761. procedure TFileEditor.BindingsChanged;
  1762. begin
  1763. Message(Application,evBroadcast,cmUpdateTitle,@Self);
  1764. end;
  1765. procedure TFileEditor.HandleEvent(var Event: TEvent);
  1766. var SH,B: boolean;
  1767. begin
  1768. case Event.What of
  1769. evBroadcast :
  1770. case Event.Command of
  1771. cmFileNameChanged :
  1772. if (Event.InfoPtr=nil) or (Event.InfoPtr=@Self) then
  1773. begin
  1774. B:=IsFlagSet(efSyntaxHighlight);
  1775. SH:=UseSyntaxHighlight(@Self);
  1776. if SH<>B then
  1777. if SH then
  1778. SetFlags(Flags or efSyntaxHighlight)
  1779. else
  1780. SetFlags(Flags and not efSyntaxHighlight);
  1781. if UseTabsPattern(@Self) then
  1782. SetFlags(Flags or efUseTabCharacters);
  1783. end;
  1784. end;
  1785. end;
  1786. inherited HandleEvent(Event);
  1787. end;
  1788. function TFileEditor.Valid(Command: Word): Boolean;
  1789. var OK: boolean;
  1790. begin
  1791. OK:=inherited Valid(Command);
  1792. if OK and (Command=cmClose) then
  1793. if IsClipboard=false then
  1794. OK:=SaveAsk(false);
  1795. Valid:=OK;
  1796. end;
  1797. (* constructor TFileEditor.Load(var S: TStream);
  1798. var P: PString;
  1799. SSP,SEP,CP,DP: TPoint;
  1800. HR: TRect;
  1801. PA : Array[1..2] of pointer;
  1802. HoldUndo : boolean;
  1803. begin
  1804. inherited Load(S);
  1805. HoldUndo:=GetStoreUndo;
  1806. SetStoreUndo(False);
  1807. P:=S.ReadStr;
  1808. FileName:=GetStr(P);
  1809. if P<>nil then DisposeStr(P);
  1810. UpdateIndicator;
  1811. { Message(@Self,evBroadcast,cmFileNameChanged,@Self);}
  1812. SSP:=SelStart; SEP:=SelEnd;
  1813. CP:=CurPos;
  1814. HR:=Highlight;
  1815. DP:=Delta;
  1816. if FileName<>'' then
  1817. LoadFile;
  1818. { if GetModified then
  1819. begin
  1820. PA[1]:=@FileName;
  1821. longint(PA[2]):=ChangedLine;
  1822. EditorDialog(edChangedOnloading,@PA);
  1823. end;}
  1824. SetHighlight(HR.A,HR.B);
  1825. SetSelection(SSP,SEP);
  1826. SetCurPtr(CP.X,CP.Y);
  1827. ScrollTo(DP.X,DP.Y);
  1828. SetModified(false);
  1829. LimitsChanged;
  1830. SetStoreUndo(HoldUndo);
  1831. end;
  1832. procedure TFileEditor.Store(var S: TStream);
  1833. begin
  1834. inherited Store(S);
  1835. S.WriteStr(@FileName);
  1836. end;
  1837. *)
  1838. function DefUseSyntaxHighlight(Editor: PFileEditor): boolean;
  1839. begin
  1840. DefUseSyntaxHighlight:=Editor^.IsFlagSet(efSyntaxHighlight);
  1841. end;
  1842. function DefUseTabsPattern(Editor: PFileEditor): boolean;
  1843. begin
  1844. DefUseTabsPattern:=Editor^.IsFlagSet(efUseTabCharacters);
  1845. end;
  1846. procedure RegisterWCEdit;
  1847. begin
  1848. {$ifndef NOOBJREG}
  1849. RegisterType(RIndicator);
  1850. RegisterType(RCodeEditor);
  1851. RegisterType(RFileEditor);
  1852. {$endif}
  1853. end;
  1854. END.
  1855. {
  1856. $Log$
  1857. Revision 1.7 2002-01-25 14:15:35 pierre
  1858. * fix bug 1774
  1859. Revision 1.6 2001/10/10 23:34:54 pierre
  1860. * fix bug 1632
  1861. Revision 1.5 2001/09/27 22:32:24 pierre
  1862. * avoid to get unnecessary warnings about modified files if file already open
  1863. Revision 1.4 2001/09/14 23:47:08 pierre
  1864. + more regexp, options now in Find/Replace dialogs
  1865. Revision 1.3 2001/09/14 16:33:06 pierre
  1866. * several small changes
  1867. Revision 1.2 2001/08/05 02:01:48 peter
  1868. * FVISION define to compile with fvision units
  1869. Revision 1.1 2001/08/04 11:30:25 peter
  1870. * ide works now with both compiler versions
  1871. Revision 1.1.2.20 2001/06/07 16:41:12 jonas
  1872. * updated for stricter checking of @ for procvars
  1873. Revision 1.1.2.19 2001/03/20 00:20:43 pierre
  1874. * fix some memory leaks + several small enhancements
  1875. Revision 1.1.2.18 2001/03/12 17:34:57 pierre
  1876. + Disassembly window started
  1877. Revision 1.1.2.17 2001/03/06 22:04:53 pierre
  1878. * Avoid cursor updates when editor window is locked
  1879. Revision 1.1.2.16 2001/02/19 10:40:51 pierre
  1880. * Check for changed files after Running tool or shell
  1881. Revision 1.1.2.15 2001/02/13 16:04:00 pierre
  1882. * fixes for bugs 1280
  1883. Revision 1.1.2.14 2001/02/05 12:58:26 pierre
  1884. * fix several Undo bugs
  1885. Revision 1.1.2.13 2000/12/30 22:44:37 peter
  1886. * autosave editor files fixed
  1887. Revision 1.1.2.12 2000/12/23 23:08:42 florian
  1888. * better message for unsaved files
  1889. Revision 1.1.2.11 2000/12/09 17:41:20 florian
  1890. * IndentSize is stored in the .INI file now
  1891. Revision 1.1.2.10 2000/11/29 12:04:37 pierre
  1892. * remove unwanted Indicator changes
  1893. Revision 1.1.2.9 2000/11/29 11:26:01 pierre
  1894. + TFPDlgWindow that handles cmSearchWindow
  1895. Revision 1.1.2.8 2000/11/27 12:06:50 pierre
  1896. New bunch of Gabor fixes
  1897. Revision 1.1.2.7 2000/11/14 23:41:32 pierre
  1898. * fix for bug 1234
  1899. Revision 1.1.2.6 2000/11/03 15:49:26 pierre
  1900. * more Undo fixes
  1901. Revision 1.1.2.5 2000/11/03 13:31:33 pierre
  1902. + more Undo stuff and smarter indent/unindent
  1903. Revision 1.1.2.4 2000/10/24 23:06:30 pierre
  1904. * some Undo/redo fixes
  1905. Revision 1.1.2.3 2000/09/18 13:20:55 pierre
  1906. New bunch of Gabor changes
  1907. }