Editor.cpp 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306
  1. //---------------------------------------------------------------------------
  2. #include <vcl.h>
  3. #pragma hdrstop
  4. #include <Common.h>
  5. #include "Editor.h"
  6. #include "TextsWin.h"
  7. #include "Tools.h"
  8. #include <CoreMain.h>
  9. #include "VCLCommon.h"
  10. #include "WinConfiguration.h"
  11. #include "HelpWin.h"
  12. //---------------------------------------------------------------------------
  13. #pragma package(smart_init)
  14. #pragma link "TB2Dock"
  15. #pragma link "TBX"
  16. #pragma link "TB2Item"
  17. #pragma link "TB2Toolbar"
  18. #pragma link "TBXStatusBars"
  19. #ifndef NO_RESOURCES
  20. #pragma resource "*.dfm"
  21. #endif
  22. //---------------------------------------------------------------------------
  23. TForm * __fastcall ShowEditorForm(const UnicodeString FileName, TCustomForm * ParentForm,
  24. TNotifyEvent OnFileChanged, TNotifyEvent OnFileReload, TFileClosedEvent OnClose,
  25. const UnicodeString Caption)
  26. {
  27. TEditorForm * Dialog = new TEditorForm(Application);
  28. try
  29. {
  30. Dialog->FileName = FileName;
  31. Dialog->ParentForm = ParentForm;
  32. Dialog->Caption = Caption.IsEmpty() ? FileName : Caption;
  33. Dialog->OnFileChanged = OnFileChanged;
  34. Dialog->OnFileReload = OnFileReload;
  35. // load before showing, so when loading failes,
  36. // we do not show an empty editor
  37. Dialog->LoadFile();
  38. Dialog->Show();
  39. // make sure editor closing is announced only if it was ever successfully shown
  40. // (at least current implementation of the events cannot handle that)
  41. Dialog->OnWindowClose = OnClose;
  42. }
  43. catch(...)
  44. {
  45. delete Dialog;
  46. throw;
  47. }
  48. return Dialog;
  49. }
  50. //---------------------------------------------------------------------------
  51. void __fastcall ReconfigureEditorForm(TForm * Form)
  52. {
  53. TEditorForm * Editor = dynamic_cast<TEditorForm *>(Form);
  54. assert(Editor != NULL);
  55. Editor->ApplyConfiguration();
  56. }
  57. //---------------------------------------------------------------------------
  58. class TRichEdit20 : public TRichEdit
  59. {
  60. public:
  61. virtual __fastcall TRichEdit20(TComponent * AOwner);
  62. void __fastcall LoadFromStream(TStream * Stream, TEncoding * Encoding);
  63. void __fastcall SetFormat(UnicodeString FontName, int FontHeight,
  64. TFontCharset FontCharset, TFontStyles FontStyles, unsigned int TabSize,
  65. bool AWordWrap);
  66. void __fastcall ResetFormat();
  67. int __fastcall FindText(const UnicodeString SearchStr, int StartPos, int Length,
  68. TSearchTypes Options, bool Down);
  69. void __fastcall Redo();
  70. __property bool SupportsUpSearch = { read = FVersion20 };
  71. __property bool CanRedo = { read = GetCanRedo };
  72. protected:
  73. friend unsigned long __stdcall StreamLoad(DWORD_PTR Cookie, unsigned char * Buff, long Read, long * WasRead);
  74. virtual void __fastcall CreateParams(TCreateParams & Params);
  75. virtual void __fastcall DestroyWnd();
  76. void __fastcall Dispatch(void * Message);
  77. bool __fastcall GetCanRedo();
  78. void __fastcall SetTabSize(unsigned int TabSize);
  79. void __fastcall WMPaste();
  80. void __fastcall EMStreamIn(TMessage & Message);
  81. bool __stdcall StreamLoad(TRichEditStreamInfo * StreamInfo,
  82. unsigned char * Buff, long Read, long & WasRead);
  83. private:
  84. HINSTANCE FLibrary;
  85. bool FVersion20;
  86. bool FWordWrap;
  87. unsigned int FTabSize;
  88. bool FInitialized;
  89. bool FStreamLoadEncodingError;
  90. };
  91. //---------------------------------------------------------------------------
  92. __fastcall TRichEdit20::TRichEdit20(TComponent * AOwner) :
  93. TRichEdit(AOwner),
  94. FLibrary(0),
  95. FVersion20(false),
  96. FTabSize(0),
  97. FWordWrap(true),
  98. FInitialized(false)
  99. {
  100. }
  101. //---------------------------------------------------------------------------
  102. void __fastcall TRichEdit20::SetFormat(UnicodeString FontName, int FontHeight,
  103. TFontCharset FontCharset, TFontStyles FontStyles, unsigned int TabSize,
  104. bool AWordWrap)
  105. {
  106. if (!FInitialized)
  107. {
  108. // for efficiency we should be creating handle here
  109. assert(!HandleAllocated());
  110. }
  111. // setting DefAttributes is noop if we do not have a handle
  112. // (btw code below would create one anyway)
  113. HandleNeeded();
  114. LockWindowUpdate(Handle);
  115. // setting DefAttributes may take quite time, even if the font attributes
  116. // do not change, so avoid that if not necessary
  117. if (!FInitialized ||
  118. (Font->Name != FontName) ||
  119. (Font->Height != FontHeight) ||
  120. (Font->Charset != FontCharset) ||
  121. (Font->Style != FontStyles))
  122. {
  123. Font->Name = FontName;
  124. Font->Height = FontHeight;
  125. Font->Charset = FontCharset;
  126. Font->Style = FontStyles;
  127. DefAttributes->Assign(Font);
  128. }
  129. if (!FInitialized ||
  130. (FTabSize != TabSize))
  131. {
  132. SetTabSize(TabSize);
  133. FTabSize = TabSize;
  134. }
  135. if (!FInitialized ||
  136. (FWordWrap != AWordWrap))
  137. {
  138. assert(HandleAllocated());
  139. // Undocumented usage of EM_SETTARGETDEVICE.
  140. // But note that it is used by MFC in CRichEditView::WrapChanged()
  141. SendMessage(Handle, EM_SETTARGETDEVICE, 0, (AWordWrap ? 0 : 1));
  142. FWordWrap = AWordWrap;
  143. }
  144. LockWindowUpdate(NULL);
  145. FInitialized = true;
  146. }
  147. //---------------------------------------------------------------------------
  148. void __fastcall TRichEdit20::ResetFormat()
  149. {
  150. // tabs are paragraph attributes, which default values cannot be set,
  151. // so we need to reapply them after loading file
  152. SetTabSize(FTabSize);
  153. }
  154. //---------------------------------------------------------------------------
  155. int __fastcall TRichEdit20::FindText(const UnicodeString SearchStr, int StartPos,
  156. int /*Length*/, TSearchTypes Options, bool Down)
  157. {
  158. int Result;
  159. if (FVersion20)
  160. {
  161. ::FINDTEXTEX Find;
  162. memset(&Find, 0, sizeof(Find));
  163. Find.chrg.cpMin = StartPos;
  164. Find.chrg.cpMax = -1;
  165. Find.lpstrText = UnicodeString(SearchStr).c_str();
  166. unsigned int Flags =
  167. FLAGMASK(Options.Contains(stWholeWord), FR_WHOLEWORD) |
  168. FLAGMASK(Options.Contains(stMatchCase), FR_MATCHCASE) |
  169. FLAGMASK(Down, FR_DOWN);
  170. Result = SendMessage(Handle, EM_FINDTEXTEX, Flags, (LPARAM)&Find);
  171. }
  172. else
  173. {
  174. assert(Down);
  175. Result = TRichEdit::FindText(SearchStr, StartPos, Text.Length(), Options);
  176. }
  177. return Result;
  178. }
  179. //---------------------------------------------------------------------------
  180. void __fastcall TRichEdit20::Redo()
  181. {
  182. assert(FVersion20);
  183. SendMessage(Handle, EM_REDO, 0, 0);
  184. }
  185. //---------------------------------------------------------------------------
  186. void __fastcall TRichEdit20::CreateParams(TCreateParams & Params)
  187. {
  188. const wchar_t RichEditModuleName[] = L"RICHED20.DLL";
  189. long int OldError;
  190. OldError = SetErrorMode(SEM_NOOPENFILEERRORBOX);
  191. FLibrary = LoadLibrary(RichEditModuleName);
  192. SetErrorMode(OldError);
  193. FVersion20 = (FLibrary != 0);
  194. if (!FVersion20)
  195. {
  196. // fallback to richedit 1.0
  197. TRichEdit::CreateParams(Params);
  198. }
  199. else
  200. {
  201. TCustomMemo::CreateParams(Params);
  202. CreateSubClass(Params, RICHEDIT_CLASS);
  203. Params.Style = Params.Style |
  204. (HideScrollBars ? 0 : ES_DISABLENOSCROLL) |
  205. (HideSelection ? 0 : ES_NOHIDESEL);
  206. Params.WindowClass.style = Params.WindowClass.style &
  207. ~(CS_HREDRAW | CS_VREDRAW);
  208. }
  209. }
  210. //---------------------------------------------------------------------------
  211. void __fastcall TRichEdit20::DestroyWnd()
  212. {
  213. TRichEdit::DestroyWnd();
  214. if (FLibrary != 0)
  215. {
  216. FreeLibrary(FLibrary);
  217. }
  218. }
  219. //---------------------------------------------------------------------------
  220. void __fastcall TRichEdit20::WMPaste()
  221. {
  222. // override default pasting to prevent inserting formatted text (RTF).
  223. const wchar_t * Text = NULL;
  224. HANDLE Handle = OpenTextFromClipboard(Text);
  225. if (Handle != NULL)
  226. {
  227. try
  228. {
  229. // replacement for EM_PASTESPECIAL,
  230. // which ignores trailing line end for some reason
  231. Perform(EM_REPLACESEL, true, reinterpret_cast<int>(Text));
  232. }
  233. __finally
  234. {
  235. CloseTextFromClipboard(Handle);
  236. }
  237. }
  238. }
  239. //---------------------------------------------------------------------------
  240. // Copy from Vcl.ComCtrls.pas
  241. static int __fastcall AdjustLineBreaks(unsigned char * Dest, const TBytes & Source, int Start, int Len)
  242. {
  243. unsigned char * P = Dest;
  244. int I = Start; // Position in Source
  245. while (I < (Len - 1))
  246. {
  247. if ((Source[I] == 10) && (Source[I + 1] == 0))
  248. {
  249. // Convert #10 to #13#10
  250. *P = 13;
  251. P++;
  252. *P = 0;
  253. P++;
  254. *P = 10;
  255. P++;
  256. *P = 0;
  257. P++;
  258. }
  259. else
  260. {
  261. *P = Source[I];
  262. P++;
  263. *P = Source[I + 1];
  264. P++;
  265. if ((Source[I] == 13) && (Source[I + 1] == 0))
  266. {
  267. // Convert #13 to #13#10
  268. *P = 10;
  269. P++;
  270. *P = 0;
  271. P++;
  272. // Skip #10 if preceeded by #13
  273. if ((Source[I + 2] == 10) && (Source[I + 3] == 0))
  274. {
  275. I += 2;
  276. }
  277. }
  278. }
  279. I += 2;
  280. }
  281. if (I == Len - 1)
  282. {
  283. *P = Source[I];
  284. P++;
  285. }
  286. return (P - Dest);
  287. }
  288. //---------------------------------------------------------------------------
  289. struct TStreamLoadInfo
  290. {
  291. TRichEditStreamInfo * StreamInfo;
  292. TRichEdit20 * RichEdit;
  293. };
  294. //---------------------------------------------------------------------------
  295. // Copy from Vcl.ComCtrls.pas,
  296. /// WORKAROUND for bug in BCB XE2 VCL
  297. // Fixes conversion from UTF-8, when read buffer ends in the middle of UTF-8 char
  298. static unsigned long __stdcall StreamLoad(DWORD_PTR Cookie, unsigned char * Buff, long Read, long * WasRead)
  299. {
  300. TStreamLoadInfo * LoadInfo = reinterpret_cast<TStreamLoadInfo *>(Cookie);
  301. return LoadInfo->RichEdit->StreamLoad(LoadInfo->StreamInfo, Buff, Read, *WasRead) ? 0 : 1;
  302. }
  303. //---------------------------------------------------------------------------
  304. void __fastcall TRichEdit20::EMStreamIn(TMessage & Message)
  305. {
  306. TEditStream * EditStream = reinterpret_cast<TEditStream *>(Message.LParam);
  307. EditStream->pfnCallback = &::StreamLoad;
  308. TStreamLoadInfo LoadInfo;
  309. LoadInfo.StreamInfo = reinterpret_cast<TRichEditStreamInfo *>(EditStream->dwCookie);
  310. LoadInfo.RichEdit = this;
  311. EditStream->dwCookie = reinterpret_cast<DWORD_PTR>(&LoadInfo);
  312. TRichEdit::Dispatch(&Message);
  313. }
  314. //---------------------------------------------------------------------------
  315. void __fastcall TRichEdit20::Dispatch(void * Message)
  316. {
  317. TMessage * M = static_cast<TMessage *>(Message);
  318. switch (M->Msg)
  319. {
  320. case WM_PASTE:
  321. WMPaste();
  322. break;
  323. case EM_STREAMIN:
  324. EMStreamIn(*M);
  325. break;
  326. default:
  327. TRichEdit::Dispatch(Message);
  328. break;
  329. }
  330. }
  331. //---------------------------------------------------------------------------
  332. bool __fastcall TRichEdit20::GetCanRedo()
  333. {
  334. return FVersion20 && (SendMessage(Handle, EM_CANREDO, 0, 0) != 0);
  335. }
  336. //---------------------------------------------------------------------------
  337. void __fastcall TRichEdit20::SetTabSize(unsigned int TabSize)
  338. {
  339. assert(TabSize > 0);
  340. HDC DC = GetDC(Handle);
  341. SaveDC(DC);
  342. SetMapMode(DC, MM_TEXT);
  343. SelectObject(DC, Font->Handle);
  344. int LogPixelsX = GetDeviceCaps(DC, LOGPIXELSX);
  345. SIZE Size;
  346. GetTextExtentPoint(DC, UnicodeString::StringOfChar(L'X', TabSize).c_str(),
  347. TabSize, &Size);
  348. RestoreDC(DC, -1);
  349. ReleaseDC(Handle, DC);
  350. unsigned int TabTwips = MulDiv(Size.cx, 1440, LogPixelsX);
  351. // save selection
  352. CHARRANGE CharRange;
  353. SendMessage(Handle, EM_EXGETSEL, 0, (LPARAM)&CharRange);
  354. CHARRANGE CharRangeAll;
  355. CharRangeAll.cpMin = 0;
  356. CharRangeAll.cpMax = -1;
  357. SendMessage(Handle, EM_EXSETSEL, 0, (LPARAM)&CharRangeAll);
  358. PARAFORMAT2 ParaFormat;
  359. ParaFormat.cbSize = sizeof(ParaFormat);
  360. ParaFormat.dwMask = PFM_TABSTOPS;
  361. ParaFormat.cTabCount = MAX_TAB_STOPS;
  362. for (int i = 0; i < ParaFormat.cTabCount; i++)
  363. {
  364. ParaFormat.rgxTabs[i] = (i + 1) * TabTwips;
  365. }
  366. SendMessage(Handle, EM_SETPARAFORMAT, 0, (LPARAM)&ParaFormat);
  367. // restore selection
  368. SendMessage(Handle, EM_EXSETSEL, 0, (LPARAM)&CharRange);
  369. }
  370. //---------------------------------------------------------------------------
  371. bool __stdcall TRichEdit20::StreamLoad(
  372. TRichEditStreamInfo * StreamInfo, unsigned char * Buff, long Read, long & WasRead)
  373. {
  374. WasRead = 0;
  375. try
  376. {
  377. if (StreamInfo->Converter != NULL)
  378. {
  379. TBytes Buffer;
  380. Buffer.Length = Read + 1;
  381. Read = Read / 2;
  382. if ((Read % 2) > 0)
  383. {
  384. Read--;
  385. }
  386. WasRead = StreamInfo->Converter->ConvertReadStream(StreamInfo->Stream, Buffer, Read);
  387. if (WasRead > 0)
  388. {
  389. Buffer[WasRead] = 0;
  390. if (Buffer[WasRead - 1] == 13)
  391. {
  392. Buffer[WasRead - 1] = 0;
  393. WasRead--;
  394. }
  395. int StartIndex = 0;
  396. // Convert from desired Encoding to Unicode
  397. if (StreamInfo->PlainText)
  398. {
  399. if (StreamInfo->Encoding == NULL)
  400. {
  401. Buffer = TEncoding::Convert(TEncoding::Default, TEncoding::Unicode, Buffer, 0, WasRead);
  402. WasRead = Buffer.Length;
  403. }
  404. else
  405. {
  406. if (!TEncoding::Unicode->Equals(StreamInfo->Encoding))
  407. {
  408. int MaxTries = StreamInfo->Encoding->GetMaxByteCount(1);
  409. while ((WasRead > 0) &&
  410. (StreamInfo->Encoding->GetCharCount(Buffer, 0, WasRead) == 0))
  411. {
  412. WasRead--;
  413. StreamInfo->Stream->Seek(-1, soFromCurrent);
  414. MaxTries--;
  415. if (MaxTries == 0)
  416. {
  417. FStreamLoadEncodingError = true;
  418. Abort();
  419. }
  420. }
  421. Buffer = TEncoding::Convert(StreamInfo->Encoding, TEncoding::Unicode, Buffer, 0, WasRead);
  422. WasRead = Buffer.Length;
  423. }
  424. // If Unicode preamble is present, set StartIndex to skip over it
  425. TBytes Preamble = TEncoding::Unicode->GetPreamble();
  426. if ((WasRead >= 2) && (Buffer[0] == Preamble[0]) && (Buffer[1] == Preamble[1]))
  427. {
  428. StartIndex = 2;
  429. }
  430. }
  431. }
  432. WasRead = AdjustLineBreaks(Buff, Buffer, StartIndex, WasRead);
  433. }
  434. }
  435. return true;
  436. }
  437. catch (...)
  438. {
  439. return false;
  440. }
  441. }
  442. //---------------------------------------------------------------------------
  443. void __fastcall TRichEdit20::LoadFromStream(TStream * Stream, TEncoding * Encoding)
  444. {
  445. FStreamLoadEncodingError = false;
  446. Lines->LoadFromStream(Stream, Encoding);
  447. // TODO Use FStreamLoadEncodingError to let user know
  448. }
  449. //---------------------------------------------------------------------------
  450. class TFindDialogEx : public TFindDialog
  451. {
  452. public:
  453. __fastcall virtual TFindDialogEx(TComponent * AOwner) : TFindDialog(AOwner)
  454. {
  455. FHelpMsg = RegisterWindowMessage(HELPMSGSTRING);
  456. }
  457. protected:
  458. unsigned int FHelpMsg;
  459. virtual bool __fastcall MessageHook(TMessage & Msg)
  460. {
  461. bool Result = false;
  462. if (Msg.Msg == FHelpMsg)
  463. {
  464. Application->HelpKeyword(HELP_EDITOR_FIND);
  465. Result = true;
  466. }
  467. if (!Result)
  468. {
  469. Result = TFindDialog::MessageHook(Msg);
  470. }
  471. return Result;
  472. }
  473. };
  474. //---------------------------------------------------------------------------
  475. class TReplaceDialogEx : public TReplaceDialog
  476. {
  477. public:
  478. __fastcall virtual TReplaceDialogEx(TComponent * AOwner) : TReplaceDialog(AOwner)
  479. {
  480. FHelpMsg = RegisterWindowMessage(HELPMSGSTRING);
  481. }
  482. protected:
  483. unsigned int FHelpMsg;
  484. virtual bool __fastcall MessageHook(TMessage & Msg)
  485. {
  486. bool Result = false;
  487. if (Msg.Msg == FHelpMsg)
  488. {
  489. Application->HelpKeyword(HELP_EDITOR_REPLACE);
  490. Result = true;
  491. }
  492. if (!Result)
  493. {
  494. Result = TReplaceDialog::MessageHook(Msg);
  495. }
  496. return Result;
  497. }
  498. };
  499. //---------------------------------------------------------------------------
  500. unsigned int TEditorForm::FInstances = 0;
  501. //---------------------------------------------------------------------------
  502. __fastcall TEditorForm::TEditorForm(TComponent* Owner)
  503. : TForm(Owner)
  504. {
  505. EditorMemo = new TRichEdit20(this);
  506. EditorMemo->Parent = this;
  507. EditorMemo->Align = alClient;
  508. EditorMemo->HideSelection = false;
  509. EditorMemo->PlainText = true;
  510. EditorMemo->PopupMenu = EditorPopup;
  511. EditorMemo->ScrollBars = ssBoth;
  512. EditorMemo->WantTabs = true;
  513. EditorMemo->OnChange = EditorMemoChange;
  514. EditorMemo->OnKeyUp = EditorMemoKeyUp;
  515. EditorMemo->OnMouseUp = EditorMemoMouseUp;
  516. FParentForm = NULL;
  517. FCaretPos = TPoint(-1, -1);
  518. FLastFindDialog = NULL;
  519. FCloseAnnounced = false;
  520. FShowStatusBarHint = false;
  521. ApplyConfiguration();
  522. FFindDialog = new TFindDialogEx(this);
  523. FFindDialog->OnFind = FindDialogFind;
  524. FReplaceDialog = new TReplaceDialogEx(this);
  525. FReplaceDialog->OnFind = FindDialogFind;
  526. FReplaceDialog->OnReplace = FindDialogFind;
  527. FEncoding = NULL;
  528. InitCodePage();
  529. UseSystemSettings(this);
  530. }
  531. //---------------------------------------------------------------------------
  532. __fastcall TEditorForm::~TEditorForm()
  533. {
  534. assert(FInstances > 0);
  535. FInstances--;
  536. if (FInstance == 0)
  537. {
  538. UnicodeString WindowParams = StoreForm(this);
  539. // this is particularly to prevent saving the form state
  540. // for the first time, keeping default positioning by a system
  541. if (!FWindowParams.IsEmpty() && (FWindowParams != WindowParams))
  542. {
  543. TEditorConfiguration EditorConfiguration = WinConfiguration->Editor;
  544. EditorConfiguration.WindowParams = StoreForm(this);
  545. WinConfiguration->Editor = EditorConfiguration;
  546. }
  547. }
  548. // see FormClose for explanation
  549. if (!FCloseAnnounced)
  550. {
  551. BackupSave();
  552. DoWindowClose(true);
  553. }
  554. if (Application->OnHint == ApplicationHint)
  555. {
  556. Application->OnHint = NULL;
  557. }
  558. }
  559. //---------------------------------------------------------------------------
  560. UnicodeString __fastcall TEditorForm::GetCodePageName(TEncoding * Encoding)
  561. {
  562. if (Encoding == TEncoding::UTF8)
  563. {
  564. return LoadStr(UTF8_NAME);
  565. }
  566. else
  567. {
  568. return DefaultEncodingName();
  569. }
  570. }
  571. //---------------------------------------------------------------------------
  572. void __fastcall TEditorForm::InitCodePage()
  573. {
  574. DefaultEncodingAction->Caption = DefaultEncodingName();
  575. DefaultEncodingAction->Hint = FORMAT(DefaultEncodingAction->Hint, (DefaultEncodingName()));
  576. }
  577. //---------------------------------------------------------------------------
  578. void __fastcall TEditorForm::SetFileName(const UnicodeString value)
  579. {
  580. if (value != FFileName)
  581. {
  582. FFileName = value;
  583. if (Visible)
  584. {
  585. LoadFile();
  586. }
  587. }
  588. }
  589. //---------------------------------------------------------------------------
  590. void __fastcall TEditorForm::SetParentForm(TCustomForm * value)
  591. {
  592. if (FParentForm != value)
  593. {
  594. FParentForm = value;
  595. if (value)
  596. {
  597. Width = value->BoundsRect.Width();
  598. Height = value->BoundsRect.Height();
  599. }
  600. }
  601. }
  602. //---------------------------------------------------------------------------
  603. void __fastcall TEditorForm::EditorActionsUpdate(TBasicAction *Action,
  604. bool &Handled)
  605. {
  606. Handled = true;
  607. if (Action == SaveAction)
  608. {
  609. SaveAction->Enabled = EditorMemo->Modified;
  610. }
  611. else if (Action == FindNextAction)
  612. {
  613. FindNextAction->Enabled =
  614. FLastFindDialog != NULL || !FFindDialog->FindText.IsEmpty();
  615. }
  616. else if (Action == EditRedo)
  617. {
  618. EditRedo->Enabled = EditorMemo->CanRedo;
  619. }
  620. else if (Action == PreferencesAction || Action == CloseAction ||
  621. Action == FindAction || Action == ReplaceAction || Action == GoToLineAction ||
  622. Action == HelpAction || Action == ReloadAction)
  623. {
  624. ((TAction *)Action)->Enabled = true;
  625. }
  626. else if (Action == DefaultEncodingAction)
  627. {
  628. DefaultEncodingAction->Enabled = true;
  629. DefaultEncodingAction->Checked = (FEncoding == TEncoding::Default);
  630. }
  631. else if (Action == UTF8EncodingAction)
  632. {
  633. UTF8EncodingAction->Enabled = true;
  634. UTF8EncodingAction->Checked = (FEncoding == TEncoding::UTF8);
  635. }
  636. else
  637. {
  638. Handled = false;
  639. }
  640. }
  641. //---------------------------------------------------------------------------
  642. void __fastcall TEditorForm::EditorActionsExecute(TBasicAction *Action,
  643. bool &Handled)
  644. {
  645. Handled = true;
  646. if (Action == SaveAction)
  647. {
  648. assert(!FFileName.IsEmpty());
  649. EditorMemo->Lines->SaveToFile(FFileName, FEncoding);
  650. if (FOnFileChanged)
  651. {
  652. FOnFileChanged(this);
  653. }
  654. EditorMemo->Modified = false;
  655. UpdateControls();
  656. }
  657. else if (Action == PreferencesAction)
  658. {
  659. DoPreferencesDialog(pmEditor);
  660. }
  661. else if (Action == CloseAction)
  662. {
  663. Close();
  664. }
  665. else if (Action == ReloadAction)
  666. {
  667. Reload();
  668. }
  669. else if (Action == FindAction || Action == ReplaceAction)
  670. {
  671. StartFind(Action == FindAction);
  672. }
  673. else if (Action == FindNextAction)
  674. {
  675. if (!FLastFindDialog)
  676. {
  677. FLastFindDialog = FFindDialog;
  678. }
  679. Find();
  680. }
  681. else if (Action == GoToLineAction)
  682. {
  683. GoToLine();
  684. }
  685. else if (Action == EditRedo)
  686. {
  687. EditorMemo->Redo();
  688. }
  689. else if (Action == HelpAction)
  690. {
  691. FormHelp(this);
  692. }
  693. else if (Action == DefaultEncodingAction)
  694. {
  695. ChangeEncoding(TEncoding::Default);
  696. }
  697. else if (Action == UTF8EncodingAction)
  698. {
  699. ChangeEncoding(TEncoding::UTF8);
  700. }
  701. else
  702. {
  703. Handled = false;
  704. }
  705. }
  706. //---------------------------------------------------------------------------
  707. void __fastcall TEditorForm::BackupSave()
  708. {
  709. if (EditorMemo->Modified)
  710. {
  711. int Uniq = 0;
  712. while (true)
  713. {
  714. UnicodeString FileName = FFileName + L".bak" + (Uniq == 0 ? UnicodeString() : IntToStr(Uniq));
  715. if (!FileExists(FileName))
  716. {
  717. EditorMemo->Lines->SaveToFile(FileName, FEncoding);
  718. break;
  719. }
  720. Uniq++;
  721. }
  722. }
  723. }
  724. //---------------------------------------------------------------------------
  725. void __fastcall TEditorForm::ChangeEncoding(TEncoding * Encoding)
  726. {
  727. if (FEncoding != Encoding)
  728. {
  729. if (!EditorMemo->Modified ||
  730. (MessageDialog(LoadStr(EDITOR_MODIFIED_ENCODING), qtConfirmation,
  731. qaOK | qaCancel) != qaCancel))
  732. {
  733. FEncoding = Encoding;
  734. LoadFile();
  735. }
  736. }
  737. }
  738. //---------------------------------------------------------------------------
  739. void __fastcall TEditorForm::FormCloseQuery(TObject * /*Sender*/,
  740. bool &CanClose)
  741. {
  742. if (EditorMemo->Modified)
  743. {
  744. SetFocus();
  745. unsigned int Answer = MessageDialog(LoadStr(SAVE_CHANGES), qtConfirmation,
  746. qaYes | qaNo | qaCancel);
  747. CanClose = (Answer != qaCancel);
  748. if (Answer == qaYes)
  749. {
  750. SaveAction->Execute();
  751. }
  752. }
  753. }
  754. //---------------------------------------------------------------------------
  755. void __fastcall TEditorForm::ApplyConfiguration()
  756. {
  757. bool PrevModified = EditorMemo->Modified;
  758. assert(Configuration);
  759. EditorMemo->SetFormat(WinConfiguration->Editor.FontName,
  760. WinConfiguration->Editor.FontHeight, (TFontCharset)WinConfiguration->Editor.FontCharset,
  761. IntToFontStyles(WinConfiguration->Editor.FontStyle), WinConfiguration->Editor.TabSize,
  762. WinConfiguration->Editor.WordWrap);
  763. EditorMemo->Modified = PrevModified;
  764. EditorMemo->ClearUndo();
  765. UpdateControls();
  766. }
  767. //---------------------------------------------------------------------------
  768. void __fastcall TEditorForm::UpdateControls()
  769. {
  770. if (FShowStatusBarHint)
  771. {
  772. StatusBar->SimplePanel = true;
  773. StatusBar->SimpleText = FStatusBarHint;
  774. FCaretPos = TPoint(-1, -1);
  775. }
  776. else
  777. {
  778. TPoint ACaretPos = EditorMemo->CaretPos;
  779. if (ACaretPos.x != FCaretPos.x || ACaretPos.y != FCaretPos.y)
  780. {
  781. FCaretPos = ACaretPos;
  782. int Count = EditorMemo->Lines->Count;
  783. StatusBar->Panels->Items[0]->Caption = FMTLOAD(EDITOR_LINE_STATUS,
  784. ((int)FCaretPos.y+1, Count));
  785. int Column = 0;
  786. UnicodeString Character;
  787. if (FCaretPos.y >= 0 && FCaretPos.y < EditorMemo->Lines->Count)
  788. {
  789. UnicodeString Line = EditorMemo->Lines->Strings[FCaretPos.y];
  790. int TabSize = WinConfiguration->Editor.TabSize;
  791. for (int Index = 1; Index <= FCaretPos.x + 1; Index++)
  792. {
  793. if ((Index - 1 >= 1) && (Index - 1 <= Line.Length()) && (Line[Index - 1] == L'\t') &&
  794. (TabSize > 0)) // sanity check
  795. {
  796. Column = (((Column / TabSize) + 1) * TabSize) + 1;
  797. }
  798. else
  799. {
  800. Column++;
  801. }
  802. }
  803. if (FCaretPos.x+1 <= Line.Length())
  804. {
  805. int Code;
  806. wchar_t Ch = Line[FCaretPos.x + 1];
  807. if (FEncoding == TEncoding::Default)
  808. {
  809. char Buf[10];
  810. BOOL UsedDefaultChar = FALSE;
  811. int Conversion =
  812. WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, &Ch, 1,
  813. Buf, sizeof(Buf), NULL, &UsedDefaultChar);
  814. // actually with multibyte encoding it may be > 1,
  815. if ((Conversion == 1) && !UsedDefaultChar)
  816. {
  817. Code = static_cast<int>(static_cast<unsigned char>(Buf[0]));
  818. }
  819. else
  820. {
  821. Code = -1;
  822. }
  823. }
  824. else
  825. {
  826. Code = static_cast<int>(Ch);
  827. }
  828. if (Code >= 0)
  829. {
  830. Character = FMTLOAD(EDITOR_CHARACTER_STATUS2, (Code, Code));
  831. }
  832. }
  833. }
  834. StatusBar->Panels->Items[1]->Caption =
  835. (Column > 0) ? FMTLOAD(EDITOR_COLUMN_STATUS, (Column)) : UnicodeString();
  836. StatusBar->Panels->Items[2]->Caption = Character;
  837. }
  838. StatusBar->Panels->Items[3]->Caption = FMTLOAD(EDITOR_ENCODING_STATUS, (FEncodingName));
  839. StatusBar->Panels->Items[4]->Caption =
  840. (EditorMemo->Modified ? LoadStr(EDITOR_MODIFIED) : UnicodeString(L""));
  841. StatusBar->SimplePanel = false;
  842. }
  843. EditorActions->UpdateAction(SaveAction);
  844. }
  845. //---------------------------------------------------------------------------
  846. void __fastcall TEditorForm::EditorMemoMouseUp(TObject * /*Sender*/,
  847. TMouseButton /*Button*/, TShiftState /*Shift*/, int /*X*/, int /*Y*/)
  848. {
  849. UpdateControls();
  850. }
  851. //---------------------------------------------------------------------------
  852. void __fastcall TEditorForm::EditorMemoKeyUp(TObject * /*Sender*/,
  853. WORD & /*Key*/, TShiftState /*Shift*/)
  854. {
  855. UpdateControls();
  856. }
  857. //---------------------------------------------------------------------------
  858. void __fastcall TEditorForm::EditorMemoChange(TObject * /*Sender*/)
  859. {
  860. UpdateControls();
  861. }
  862. //---------------------------------------------------------------------------
  863. void __fastcall TEditorForm::FindDialogFind(TObject * /*Sender*/)
  864. {
  865. Find();
  866. }
  867. //---------------------------------------------------------------------------
  868. void __fastcall TEditorForm::Find()
  869. {
  870. int NewPos;
  871. int Replacements = 0;
  872. do
  873. {
  874. assert(FLastFindDialog);
  875. TSearchTypes SearchTypes;
  876. // length condition is there to improve performance when large
  877. // block is selected in editor
  878. if (FLastFindDialog == FReplaceDialog &&
  879. (FReplaceDialog->Options.Contains(frReplace) ||
  880. FReplaceDialog->Options.Contains(frReplaceAll)) &&
  881. FReplaceDialog->FindText.Length() == EditorMemo->SelLength &&
  882. AnsiSameText(FReplaceDialog->FindText, EditorMemo->SelText))
  883. {
  884. EditorMemo->SelText = FReplaceDialog->ReplaceText;
  885. Replacements++;
  886. }
  887. TEditorConfiguration EditorConfiguration = WinConfiguration->Editor;
  888. EditorConfiguration.FindText = FLastFindDialog->FindText;
  889. EditorConfiguration.ReplaceText = FReplaceDialog->ReplaceText;
  890. EditorConfiguration.FindMatchCase = FLastFindDialog->Options.Contains(frMatchCase);
  891. EditorConfiguration.FindWholeWord = FLastFindDialog->Options.Contains(frWholeWord);
  892. EditorConfiguration.FindDown = FLastFindDialog->Options.Contains(frDown);
  893. WinConfiguration->Editor = EditorConfiguration;
  894. if (EditorConfiguration.FindMatchCase)
  895. {
  896. SearchTypes << stMatchCase;
  897. }
  898. if (EditorConfiguration.FindWholeWord)
  899. {
  900. SearchTypes << stWholeWord;
  901. }
  902. NewPos = EditorMemo->FindText(EditorConfiguration.FindText,
  903. EditorMemo->SelLength ? EditorMemo->SelStart+1 : EditorMemo->SelStart,
  904. EditorMemo->Text.Length(), SearchTypes, EditorConfiguration.FindDown);
  905. if (NewPos >= 0)
  906. {
  907. EditorMemo->SelStart = NewPos;
  908. EditorMemo->SelLength = EditorConfiguration.FindText.Length();
  909. }
  910. if (FLastFindDialog->Handle)
  911. {
  912. PositionFindDialog(true);
  913. }
  914. if (NewPos < 0)
  915. {
  916. if ((Replacements == 0) || FReplaceDialog->Options.Contains(frReplaceAll))
  917. {
  918. // now Screen->ActiveForm can be NULL when other form was meanwhile
  919. // activated and then focus was returned back to "find" dialog
  920. // (non VCL form)
  921. if (Screen->ActiveForm != this)
  922. {
  923. SetFocus();
  924. FLastFindDialog->Execute();
  925. }
  926. if (Replacements == 0)
  927. {
  928. MessageDialog(FMTLOAD(EDITOR_FIND_END, (EditorConfiguration.FindText)), qtInformation, qaOK, HELP_NONE);
  929. }
  930. else if (FReplaceDialog->Options.Contains(frReplaceAll))
  931. {
  932. MessageDialog(FMTLOAD(EDITOR_REPLACE_END, (Replacements)), qtInformation, qaOK, HELP_NONE);
  933. }
  934. }
  935. }
  936. }
  937. while (NewPos >= 0 && FLastFindDialog == FReplaceDialog &&
  938. FReplaceDialog->Options.Contains(frReplaceAll));
  939. }
  940. //---------------------------------------------------------------------------
  941. void __fastcall TEditorForm::FormShow(TObject * /*Sender*/)
  942. {
  943. CutFormToDesktop(this);
  944. assert(FWindowParams.IsEmpty());
  945. if (FWindowParams.IsEmpty())
  946. {
  947. FWindowParams = StoreForm(this);
  948. }
  949. }
  950. //---------------------------------------------------------------------------
  951. // copy from ComCtrls.pas
  952. bool __fastcall TEditorForm::ContainsPreamble(TStream * Stream, const TBytes & Signature)
  953. {
  954. bool Result;
  955. TBytes Buffer;
  956. int LBufLen;
  957. int LSignatureLen = Signature.Length;
  958. __int64 LPosition = Stream->Position;
  959. try
  960. {
  961. Buffer.Length = LSignatureLen;
  962. LBufLen = Stream->Read(&Buffer[0], LSignatureLen);
  963. }
  964. __finally
  965. {
  966. Stream->Position = LPosition;
  967. }
  968. if (LBufLen == LSignatureLen)
  969. {
  970. Result = true;
  971. for (int I = 1; I <= LSignatureLen; I++)
  972. {
  973. if (Buffer[I - 1] != Signature[I - 1])
  974. {
  975. Result = false;
  976. break;
  977. }
  978. }
  979. }
  980. else
  981. {
  982. Result = false;
  983. }
  984. return Result;
  985. }
  986. //---------------------------------------------------------------------------
  987. void __fastcall TEditorForm::LoadFromFile()
  988. {
  989. TStream * Stream = new TFileStream(FFileName, fmOpenRead | fmShareDenyWrite);
  990. try
  991. {
  992. if (FEncoding == NULL)
  993. {
  994. int Encoding;
  995. if (ContainsPreamble(Stream, TEncoding::UTF8->GetPreamble()))
  996. {
  997. Encoding = CP_UTF8;
  998. }
  999. else
  1000. {
  1001. Encoding = WinConfiguration->Editor.Encoding;
  1002. }
  1003. switch (Encoding)
  1004. {
  1005. case CP_UTF8:
  1006. FEncoding = TEncoding::UTF8;
  1007. break;
  1008. default:
  1009. FAIL;
  1010. // fallthru
  1011. case CP_ACP:
  1012. FEncoding = TEncoding::Default;
  1013. break;
  1014. }
  1015. }
  1016. FEncodingName = GetCodePageName(FEncoding);
  1017. EditorMemo->LoadFromStream(Stream, FEncoding);
  1018. }
  1019. __finally
  1020. {
  1021. delete Stream;
  1022. }
  1023. SendMessage(EditorMemo->Handle, EM_EXLIMITTEXT, 0, 0x7FFFFFF0);
  1024. }
  1025. //---------------------------------------------------------------------------
  1026. void __fastcall TEditorForm::LoadFile()
  1027. {
  1028. HandleNeeded();
  1029. LoadFromFile();
  1030. EditorMemo->ResetFormat();
  1031. EditorMemo->Modified = false;
  1032. FCaretPos.x = -1;
  1033. // this is important particularly after reload
  1034. UpdateControls();
  1035. }
  1036. //---------------------------------------------------------------------------
  1037. bool __fastcall TEditorForm::CursorInUpperPart()
  1038. {
  1039. HFONT OldFont;
  1040. HDC DC;
  1041. TTextMetric TM;
  1042. TRect Rect;
  1043. DC = GetDC(EditorMemo->Handle);
  1044. OldFont = (HFONT)SelectObject(DC, EditorMemo->Font->Handle);
  1045. try
  1046. {
  1047. GetTextMetrics(DC, &TM);
  1048. EditorMemo->Perform(EM_GETRECT, 0, ((int)&Rect));
  1049. }
  1050. __finally
  1051. {
  1052. SelectObject(DC, OldFont);
  1053. ReleaseDC(EditorMemo->Handle, DC);
  1054. }
  1055. int VisibleLines = (Rect.Bottom - Rect.Top) / (TM.tmHeight + TM.tmExternalLeading);
  1056. int FirstLine = SendMessage(EditorMemo->Handle, EM_GETFIRSTVISIBLELINE, 0, 0);
  1057. TPoint CaretPos = EditorMemo->CaretPos;
  1058. return (CaretPos.y - FirstLine) < VisibleLines / 2;
  1059. }
  1060. //---------------------------------------------------------------------------
  1061. void __fastcall TEditorForm::PositionFindDialog(bool VerticalOnly)
  1062. {
  1063. assert(FLastFindDialog);
  1064. if (!VerticalOnly)
  1065. {
  1066. FLastFindDialog->Left = Left + EditorMemo->Left + EditorMemo->Width / 2 - 100;
  1067. }
  1068. FLastFindDialog->Top = Top + EditorMemo->Top + (EditorMemo->Height / 4) +
  1069. (CursorInUpperPart() ? (EditorMemo->Height / 2) : 0) - 40;
  1070. }
  1071. //---------------------------------------------------------------------------
  1072. void __fastcall TEditorForm::StartFind(bool Find)
  1073. {
  1074. UnicodeString Text = EditorMemo->SelText;
  1075. TFindOptions Options;
  1076. Options << frShowHelp;
  1077. if (Text.IsEmpty())
  1078. {
  1079. Text = WinConfiguration->Editor.FindText;
  1080. }
  1081. TFindDialog * Dialog = Find ? FFindDialog : FReplaceDialog;
  1082. if (FLastFindDialog && Dialog != FLastFindDialog && FLastFindDialog->Handle)
  1083. {
  1084. FLastFindDialog->CloseDialog();
  1085. }
  1086. FLastFindDialog = Dialog;
  1087. if (!Text.IsEmpty())
  1088. {
  1089. FLastFindDialog->FindText = Text;
  1090. }
  1091. FReplaceDialog->ReplaceText = WinConfiguration->Editor.ReplaceText;
  1092. if (WinConfiguration->Editor.FindMatchCase)
  1093. {
  1094. Options << frMatchCase;
  1095. }
  1096. if (WinConfiguration->Editor.FindWholeWord)
  1097. {
  1098. Options << frWholeWord;
  1099. }
  1100. if (EditorMemo->SupportsUpSearch)
  1101. {
  1102. if (WinConfiguration->Editor.FindDown)
  1103. {
  1104. Options << frDown;
  1105. }
  1106. }
  1107. else
  1108. {
  1109. Options << frHideUpDown; // not implemented
  1110. Options << frDown;
  1111. }
  1112. FLastFindDialog->Options = Options;
  1113. if (!FLastFindDialog->Handle)
  1114. {
  1115. PositionFindDialog(false);
  1116. }
  1117. FLastFindDialog->Execute();
  1118. }
  1119. //---------------------------------------------------------------------------
  1120. void __fastcall TEditorForm::GoToLine()
  1121. {
  1122. UnicodeString Str;
  1123. if (InputDialog(LoadStr(EDITOR_GO_TO_LINE), LoadStr(EDITOR_LINE_NUMBER), Str))
  1124. {
  1125. int Line = StrToIntDef(Str, -1);
  1126. if (Line <= 0 || Line > EditorMemo->Lines->Count)
  1127. {
  1128. throw Exception(LoadStr(EDITOR_INVALID_LINE));
  1129. }
  1130. else
  1131. {
  1132. EditorMemo->CaretPos = TPoint(0, Line-1);
  1133. }
  1134. }
  1135. }
  1136. //---------------------------------------------------------------------------
  1137. void __fastcall TEditorForm::FormClose(TObject * /*Sender*/,
  1138. TCloseAction & Action)
  1139. {
  1140. // Preferably announce closure here as this is called from within TForm::Close(),
  1141. // so the annoucement will be synchronous (and editor manager thus
  1142. // will consider the form to be really closed and will not block
  1143. // application closure).
  1144. // However FormClose is not called when form is closed due to
  1145. // application exit, so there is last resort call from destructor.
  1146. DoWindowClose(false);
  1147. FCloseAnnounced = true;
  1148. Action = caFree;
  1149. }
  1150. //---------------------------------------------------------------------------
  1151. void __fastcall TEditorForm::DoWindowClose(bool Forced)
  1152. {
  1153. if (FOnWindowClose != NULL)
  1154. {
  1155. try
  1156. {
  1157. FOnWindowClose(this, Forced);
  1158. }
  1159. catch(Exception & E)
  1160. {
  1161. ShowExtendedException(&E);
  1162. }
  1163. }
  1164. }
  1165. //---------------------------------------------------------------------------
  1166. void __fastcall TEditorForm::CreateParams(TCreateParams & Params)
  1167. {
  1168. // this is called for the first time from parent's constructor.
  1169. // FFormRestored is set to false implicitly
  1170. if (!FFormRestored)
  1171. {
  1172. FInstance = FInstances;
  1173. FInstances++;
  1174. FFormRestored = true;
  1175. UnicodeString WindowParams = WinConfiguration->Editor.WindowParams;
  1176. if ((FInstance == 0) && !WindowParams.IsEmpty())
  1177. {
  1178. RestoreForm(WindowParams, this);
  1179. }
  1180. }
  1181. TForm::CreateParams(Params);
  1182. Params.WndParent = GetDesktopWindow();
  1183. }
  1184. //---------------------------------------------------------------------------
  1185. void __fastcall TEditorForm::Reload()
  1186. {
  1187. if (!EditorMemo->Modified ||
  1188. (MessageDialog(LoadStr(EDITOR_MODIFIED_RELOAD), qtConfirmation,
  1189. qaOK | qaCancel) != qaCancel))
  1190. {
  1191. if (FOnFileReload)
  1192. {
  1193. FOnFileReload(this);
  1194. }
  1195. LoadFile();
  1196. }
  1197. }
  1198. //---------------------------------------------------------------------------
  1199. void __fastcall TEditorForm::ApplicationHint(TObject * /*Sender*/)
  1200. {
  1201. assert(Application);
  1202. UnicodeString AHint = GetLongHint(Application->Hint);
  1203. FShowStatusBarHint = Active && !AHint.IsEmpty();
  1204. if (FShowStatusBarHint)
  1205. {
  1206. FStatusBarHint = AHint != L"E" ? AHint : UnicodeString(L"");
  1207. }
  1208. else
  1209. {
  1210. FStatusBarHint = L"";
  1211. }
  1212. UpdateControls();
  1213. }
  1214. //---------------------------------------------------------------------------
  1215. void __fastcall TEditorForm::FormActivate(TObject * /*Sender*/)
  1216. {
  1217. Application->OnHint = ApplicationHint;
  1218. }
  1219. //---------------------------------------------------------------------------