LogMemo.cpp 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. //---------------------------------------------------------------------------
  2. #include <vcl.h>
  3. #pragma hdrstop
  4. #include <Common.h>
  5. #include "LogMemo.h"
  6. #pragma package(smart_init)
  7. //---------------------------------------------------------------------------
  8. // ValidCtrCheck is used to assure that the components created do not have
  9. // any pure virtual functions.
  10. static inline void ValidCtrCheck(TLogMemo *)
  11. {
  12. new TLogMemo(NULL);
  13. }
  14. //---------------------------------------------------------------------------
  15. namespace Logmemo
  16. {
  17. void __fastcall PACKAGE Register()
  18. {
  19. TComponentClass classes[1] = {__classid(TLogMemo)};
  20. RegisterComponents("Scp", classes, 0);
  21. }
  22. }
  23. //---------------------------------------------------------------------------
  24. __fastcall TLogMemo::TLogMemo(TComponent* Owner)
  25. : TCustomRichEdit(Owner)
  26. {
  27. FIndexes = new TList();
  28. FWantScrollToEnd = false;
  29. FUpdating = false;
  30. FNeedsRepaint = false;
  31. FShowTypes = DEFAULT_LOGMEMO_SHOWTYPES;
  32. ReadOnly = true;
  33. Font->Name = DEFAULT_LOGMEMO_FONT;
  34. WantReturns = false;
  35. WordWrap = false;
  36. ScrollBars = ssBoth;
  37. }
  38. //---------------------------------------------------------------------------
  39. __fastcall TLogMemo::~TLogMemo()
  40. {
  41. delete FIndexes;
  42. }
  43. //---------------------------------------------------------------------------
  44. void __fastcall TLogMemo::WMSetFocus(TWMSetFocus & Message)
  45. {
  46. try
  47. {
  48. TCustomRichEdit::Dispatch(&Message);
  49. }
  50. __finally
  51. {
  52. HideCaret(Handle);
  53. }
  54. }
  55. //---------------------------------------------------------------------------
  56. bool __fastcall TLogMemo::IsFontStored()
  57. {
  58. return
  59. (Font->Name != DEFAULT_LOGMEMO_FONT) ||
  60. (Font->Charset != DEFAULT_CHARSET) ||
  61. (Font->Color != clWindowText) ||
  62. (Font->Height != -11) ||
  63. (Font->Pitch != fpDefault) ||
  64. (Font->Size != 8) ||
  65. (Font->Style != TFontStyles());
  66. }
  67. //---------------------------------------------------------------------------
  68. #ifndef DESIGN_ONLY
  69. void __fastcall TLogMemo::SetSessionLog(TSessionLog * value)
  70. {
  71. if (FSessionLog != value)
  72. {
  73. if (SessionLog && (SessionLog->OnChange == SessionLogChange))
  74. {
  75. SessionLog->OnChange = NULL;
  76. }
  77. FSessionLog = value;
  78. if (SessionLog)
  79. {
  80. SessionLog->OnChange = SessionLogChange;
  81. }
  82. ReloadFromLog();
  83. }
  84. }
  85. #endif
  86. //---------------------------------------------------------------------------
  87. void __fastcall TLogMemo::SessionLogChange(TObject * Sender)
  88. {
  89. #ifndef DESIGN_ONLY
  90. USEDPARAM(Sender);
  91. assert(Sender && (Sender == SessionLog));
  92. #endif
  93. UpdateFromLog();
  94. }
  95. //---------------------------------------------------------------------------
  96. void __fastcall TLogMemo::UpdateFromLog()
  97. {
  98. #ifndef DESIGN_ONLY
  99. if (SessionLog && Parent && !Application->Terminated)
  100. {
  101. assert(FIndexes->Count == Lines->Count);
  102. FUpdating = true;
  103. try
  104. {
  105. ScrollToEnd();
  106. if (Lines->Count && (Indexes[0] < SessionLog->TopIndex))
  107. {
  108. try
  109. {
  110. SendMessage(Handle, WM_SETREDRAW, false, 0);
  111. FNeedsRepaint = true;
  112. while (Lines->Count && (Indexes[0] < SessionLog->TopIndex))
  113. {
  114. FIndexes->Delete(0);
  115. if (Parent) Lines->Delete(0);
  116. }
  117. }
  118. __finally
  119. {
  120. SendMessage(Handle, WM_SETREDRAW, true, 0);
  121. }
  122. }
  123. if (SessionLog->Count)
  124. {
  125. int LastIndex;
  126. if (Lines->Count)
  127. {
  128. LastIndex = Indexes[Lines->Count-1] + 1;
  129. }
  130. else
  131. {
  132. LastIndex = SessionLog->TopIndex;
  133. }
  134. while (Parent && LastIndex <= SessionLog->BottomIndex)
  135. {
  136. if (Parent && ShowTypes.Contains(SessionLog->Type[LastIndex]))
  137. {
  138. SelLength = 0;
  139. SelStart = Lines->Text.Length();
  140. if (Parent) SelAttributes->Color = SessionLog->Color[LastIndex];
  141. FIndexes->Add((void*) LastIndex);
  142. try
  143. {
  144. // this usually fails when log window is closed while
  145. // new line is being added (control has no parent)
  146. if (Parent)
  147. {
  148. if (SessionLog->Line[LastIndex].Pos("\r"))
  149. {
  150. Lines->Add(StringReplace(SessionLog->Line[LastIndex], "\r", "",
  151. TReplaceFlags() << rfReplaceAll));
  152. }
  153. else
  154. {
  155. Lines->Add(SessionLog->Line[LastIndex]);
  156. }
  157. }
  158. }
  159. catch(...)
  160. {
  161. }
  162. }
  163. LastIndex++;
  164. }
  165. }
  166. if (Parent)
  167. {
  168. ScrollToEnd();
  169. if (FNeedsRepaint)
  170. {
  171. FNeedsRepaint = false;
  172. Invalidate();
  173. }
  174. }
  175. assert(!Parent || FIndexes->Count == Lines->Count);
  176. }
  177. __finally
  178. {
  179. FUpdating = false;
  180. }
  181. }
  182. #endif
  183. }
  184. //---------------------------------------------------------------------------
  185. void __fastcall TLogMemo::ReloadFromLog()
  186. {
  187. if (Parent)
  188. {
  189. Lines->BeginUpdate();
  190. try
  191. {
  192. Clear();
  193. FIndexes->Clear();
  194. UpdateFromLog();
  195. }
  196. __finally
  197. {
  198. Lines->EndUpdate();
  199. }
  200. }
  201. }
  202. //---------------------------------------------------------------------------
  203. int __fastcall TLogMemo::GetIndexes(int Index)
  204. {
  205. assert((Index >= 0) && (Index < Lines->Count) && (FIndexes->Count == Lines->Count));
  206. return ((int)FIndexes->Items[Index]);
  207. }
  208. //---------------------------------------------------------------------------
  209. void __fastcall TLogMemo::SetShowTypes(TLogLineTypes value)
  210. {
  211. if (ShowTypes != value)
  212. {
  213. FShowTypes = value;
  214. ReloadFromLog();
  215. }
  216. }
  217. //---------------------------------------------------------------------------
  218. bool __fastcall TLogMemo::StoreShowTypes()
  219. {
  220. return (ShowTypes != DEFAULT_LOGMEMO_SHOWTYPES);
  221. }
  222. //---------------------------------------------------------------------------
  223. void __fastcall TLogMemo::ScrollToEnd()
  224. {
  225. TCharRange Selection;
  226. Selection.cpMin = Lines->Text.Length();
  227. Selection.cpMax = Selection.cpMin;
  228. Perform(EM_EXSETSEL, 0, ((long)&Selection));
  229. Perform(EM_SCROLLCARET, 0, 0);
  230. }
  231. //---------------------------------------------------------------------------
  232. void TLogMemo::CMVisibleChanged(TMessage & Message)
  233. {
  234. try
  235. {
  236. TCustomRichEdit::Dispatch(&Message);
  237. }
  238. __finally
  239. {
  240. ScrollToEnd();
  241. }
  242. }
  243. //---------------------------------------------------------------------------
  244. void __fastcall TLogMemo::MouseDown(TMouseButton Button, TShiftState Shift, int X, int Y)
  245. {
  246. try
  247. {
  248. TCustomRichEdit::MouseDown(Button, Shift, X, Y);
  249. }
  250. __finally
  251. {
  252. HideCaret(Handle);
  253. }
  254. }
  255. //---------------------------------------------------------------------------
  256. void __fastcall TLogMemo::CMShowingChanged(TMessage & Message)
  257. {
  258. bool VShowing = Showing;
  259. try
  260. {
  261. TCustomRichEdit::Dispatch(&Message);
  262. }
  263. __finally
  264. {
  265. if (VShowing)
  266. {
  267. FWantScrollToEnd = true;
  268. }
  269. HideCaret(Handle);
  270. }
  271. }
  272. //---------------------------------------------------------------------------
  273. void __fastcall TLogMemo::KeyDown(Word & Key, TShiftState Shift)
  274. {
  275. if ((Key == VK_UP) || (Key == VK_DOWN))
  276. {
  277. SendMessage(Handle, EM_LINESCROLL, 0, ( Key == VK_UP ? -1 : 1));
  278. Key = 0;
  279. }
  280. else
  281. {
  282. TCustomRichEdit::KeyDown(Key, Shift);
  283. }
  284. }
  285. //---------------------------------------------------------------------------
  286. void __fastcall TLogMemo::WMKeyDown(TWMKeyDown & Message)
  287. {
  288. try
  289. {
  290. TCustomRichEdit::Dispatch(&Message);
  291. }
  292. __finally
  293. {
  294. HideCaret(Handle);
  295. }
  296. }
  297. //---------------------------------------------------------------------------
  298. void __fastcall TLogMemo::WMPaint(TWMPaint & Message)
  299. {
  300. try
  301. {
  302. TCustomRichEdit::Dispatch(&Message);
  303. }
  304. __finally
  305. {
  306. if (FWantScrollToEnd)
  307. {
  308. FWantScrollToEnd = false;
  309. SelLength = 0;
  310. SelStart = Lines->Text.Length();
  311. SendMessage(Handle, EM_LINESCROLL, 0, Lines->Count);
  312. //SendMessage(Handle, EM_LINESCROLL, 0, -LinesVisible+1);
  313. }
  314. HideCaret(Handle);
  315. }
  316. }
  317. //---------------------------------------------------------------------------
  318. int __fastcall TLogMemo::GetLinesVisible()
  319. {
  320. HFONT OldFont;
  321. void *DC;
  322. TTextMetric TM;
  323. TRect Rect;
  324. DC = GetDC(Handle);
  325. OldFont = SelectObject(DC, Font->Handle);
  326. try
  327. {
  328. GetTextMetrics(DC, &TM);
  329. Perform(EM_GETRECT, 0, ((int)&Rect));
  330. }
  331. __finally
  332. {
  333. SelectObject(DC, OldFont);
  334. ReleaseDC(Handle, DC);
  335. }
  336. return (Rect.Bottom - Rect.Top) / (TM.tmHeight + TM.tmExternalLeading);
  337. }
  338. //---------------------------------------------------------------------------
  339. void __fastcall TLogMemo::SetParent(TWinControl * AParent)
  340. {
  341. TCustomRichEdit::SetParent(AParent);
  342. if (AParent) UpdateFromLog();
  343. }
  344. //---------------------------------------------------------------------------
  345. void __fastcall TLogMemo::InitiateAction()
  346. {
  347. TCustomRichEdit::InitiateAction();
  348. /*if (FNeedsRepaint)
  349. {
  350. FNeedsRepaint = false;
  351. Refresh();
  352. } */
  353. }
  354. //---------------------------------------------------------------------------
  355. void __fastcall TLogMemo::Change()
  356. {
  357. if (Parent && Visible && !Application->Terminated)
  358. {
  359. TCustomRichEdit::Change();
  360. }
  361. }