123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414 |
- //---------------------------------------------------------------------------
- #include <vcl.h>
- #pragma hdrstop
- #include <Common.h>
- #include "LogMemo.h"
- #include <StrUtils.hpp>
- #pragma package(smart_init)
- //---------------------------------------------------------------------------
- #ifndef DESIGN_ONLY
- const TColor LogLineColors[] =
- {clGreen, clRed, clMaroon, clBlue, clGray};
- #endif
- //---------------------------------------------------------------------------
- // ValidCtrCheck is used to assure that the components created do not have
- // any pure virtual functions.
- static inline void ValidCtrCheck(TLogMemo *)
- {
- new TLogMemo(NULL);
- }
- //---------------------------------------------------------------------------
- namespace Logmemo
- {
- void __fastcall PACKAGE Register()
- {
- TComponentClass classes[1] = {__classid(TLogMemo)};
- RegisterComponents(L"Scp", classes, 0);
- }
- }
- //---------------------------------------------------------------------------
- __fastcall TLogMemo::TLogMemo(TComponent* Owner)
- : TCustomRichEdit(Owner)
- {
- FIndexes = new TList();
- FWantScrollToEnd = false;
- FUpdating = false;
- FNeedsRepaint = false;
- FLastUpdate = 0;
- FShowTypes = DEFAULT_LOGMEMO_SHOWTYPES;
- ReadOnly = true;
- Font->Name = DEFAULT_LOGMEMO_FONT;
- WantReturns = false;
- WordWrap = false;
- ScrollBars = ssBoth;
- FThread = GetCurrentThreadId();
- }
- //---------------------------------------------------------------------------
- __fastcall TLogMemo::~TLogMemo()
- {
- #ifndef DESIGN_ONLY
- // deassociate us from session log change handler
- SessionLog = NULL;
- #endif
- delete FIndexes;
- }
- //---------------------------------------------------------------------------
- void __fastcall TLogMemo::WMSetFocus(TWMSetFocus & Message)
- {
- try
- {
- TCustomRichEdit::Dispatch(&Message);
- }
- __finally
- {
- HideCaret(Handle);
- }
- }
- //---------------------------------------------------------------------------
- bool __fastcall TLogMemo::IsFontStored()
- {
- return
- (Font->Name != DEFAULT_LOGMEMO_FONT) ||
- (Font->Charset != DEFAULT_CHARSET) ||
- (Font->Color != clWindowText) ||
- (Font->Height != -11) ||
- (Font->Pitch != TFontPitch::fpDefault) ||
- (Font->Size != 8) ||
- (Font->Style != TFontStyles());
- }
- //---------------------------------------------------------------------------
- #ifndef DESIGN_ONLY
- void __fastcall TLogMemo::SetSessionLog(TSessionLog * value)
- {
- if (FSessionLog != value)
- {
- if (SessionLog && (SessionLog->OnChange == SessionLogChange))
- {
- SessionLog->OnChange = NULL;
- }
- FSessionLog = value;
- if (SessionLog)
- {
- SessionLog->OnChange = SessionLogChange;
- }
- ReloadFromLog();
- }
- }
- #endif
- //---------------------------------------------------------------------------
- void __fastcall TLogMemo::SessionLogChange(TObject * Sender)
- {
- USEDPARAM(Sender);
- #ifndef DESIGN_ONLY
- assert(Sender && (Sender == (TObject*)SessionLog));
- #endif
- if (HandleAllocated())
- {
- unsigned int Ticks = GetTickCount();
- if (((FLastUpdate == 0) || (Ticks < FLastUpdate) || (Ticks - FLastUpdate > 200)) &&
- (FThread == GetCurrentThreadId()))
- {
- // forced update
- UpdateFromLog();
- }
- else
- {
- // update later, once idle
- PostMessage(Handle, WM_LOG_UPDATE, 0, 0);
- }
- }
- }
- //---------------------------------------------------------------------------
- void __fastcall TLogMemo::UpdateFromLog()
- {
- #ifndef DESIGN_ONLY
- if (SessionLog && Parent && !Application->Terminated)
- {
- assert(FIndexes->Count == Lines->Count);
- FUpdating = true;
- bool Updated = false;
- SessionLog->Lock();
- try
- {
- ScrollToEnd();
- if (Lines->Count && (Indexes[0] < SessionLog->TopIndex))
- {
- try
- {
- SendMessage(Handle, WM_SETREDRAW, false, 0);
- FNeedsRepaint = true;
- while (Lines->Count && (Indexes[0] < SessionLog->TopIndex))
- {
- FIndexes->Delete(0);
- if (Parent)
- {
- Lines->Delete(0);
- Updated = true;
- }
- }
- }
- __finally
- {
- SendMessage(Handle, WM_SETREDRAW, true, 0);
- }
- }
- if (SessionLog->Count)
- {
- int LastIndex;
- if (Lines->Count)
- {
- LastIndex = Indexes[Lines->Count-1] + 1;
- }
- else
- {
- LastIndex = SessionLog->TopIndex;
- }
- while (Parent && LastIndex <= SessionLog->BottomIndex)
- {
- if (Parent && ShowTypes.Contains(SessionLog->Type[LastIndex]))
- {
- SelLength = 0;
- SelStart = Lines->Text.Length();
- if (Parent) SelAttributes->Color = LogLineColors[SessionLog->Type[LastIndex]];
- FIndexes->Add((void*) LastIndex);
- try
- {
- // this usually fails when log window is closed while
- // new line is being added (control has no parent)
- if (Parent)
- {
- if (SessionLog->Line[LastIndex].Pos(L"\r"))
- {
- Lines->Add(ReplaceStr(SessionLog->Line[LastIndex], L"\r", L""));
- }
- else
- {
- Lines->Add(SessionLog->Line[LastIndex]);
- }
- Updated = true;
- }
- }
- catch(...)
- {
- if (Lines->Count < FIndexes->Count)
- {
- FIndexes->Delete(FIndexes->Count - 1);
- }
- assert(FIndexes->Count == Lines->Count);
- // LastIndex is strangely reset to 0 when exception is caught
- LastIndex = Indexes[Lines->Count-1];
- }
- }
- LastIndex++;
- }
- }
- if (Parent)
- {
- ScrollToEnd();
- if (FNeedsRepaint)
- {
- FNeedsRepaint = false;
- Invalidate();
- }
- }
- assert(!Parent || FIndexes->Count == Lines->Count);
- FLastUpdate = GetTickCount();
- }
- __finally
- {
- SessionLog->Unlock();
- FUpdating = false;
- }
- if (Updated)
- {
- Change();
- }
- }
- #endif
- }
- //---------------------------------------------------------------------------
- void __fastcall TLogMemo::ReloadFromLog()
- {
- if (Parent)
- {
- Lines->BeginUpdate();
- try
- {
- Clear();
- FIndexes->Clear();
- UpdateFromLog();
- }
- __finally
- {
- Lines->EndUpdate();
- }
- }
- }
- //---------------------------------------------------------------------------
- int __fastcall TLogMemo::GetIndexes(int Index)
- {
- assert((Index >= 0) && (Index < Lines->Count) && (FIndexes->Count == Lines->Count));
- return ((int)FIndexes->Items[Index]);
- }
- //---------------------------------------------------------------------------
- void __fastcall TLogMemo::SetShowTypes(TLogLineTypes value)
- {
- if (ShowTypes != value)
- {
- FShowTypes = value;
- ReloadFromLog();
- }
- }
- //---------------------------------------------------------------------------
- bool __fastcall TLogMemo::StoreShowTypes()
- {
- return (ShowTypes != DEFAULT_LOGMEMO_SHOWTYPES);
- }
- //---------------------------------------------------------------------------
- void __fastcall TLogMemo::ScrollToEnd()
- {
- TCharRange Selection;
- Selection.cpMin = Lines->Text.Length();
- Selection.cpMax = Selection.cpMin;
- Perform(EM_EXSETSEL, 0, ((long)&Selection));
- Perform(EM_SCROLLCARET, 0, 0);
- }
- //---------------------------------------------------------------------------
- void TLogMemo::WMLogUpdate(TMessage & /*Message*/)
- {
- UpdateFromLog();
- }
- //---------------------------------------------------------------------------
- void TLogMemo::CMVisibleChanged(TMessage & Message)
- {
- try
- {
- TCustomRichEdit::Dispatch(&Message);
- }
- __finally
- {
- ScrollToEnd();
- }
- }
- //---------------------------------------------------------------------------
- void __fastcall TLogMemo::MouseDown(TMouseButton Button, TShiftState Shift, int X, int Y)
- {
- try
- {
- TCustomRichEdit::MouseDown(Button, Shift, X, Y);
- }
- __finally
- {
- HideCaret(Handle);
- }
- }
- //---------------------------------------------------------------------------
- void __fastcall TLogMemo::CMShowingChanged(TMessage & Message)
- {
- bool VShowing = Showing;
- try
- {
- TCustomRichEdit::Dispatch(&Message);
- }
- __finally
- {
- if (VShowing)
- {
- FWantScrollToEnd = true;
- }
- HideCaret(Handle);
- }
- }
- //---------------------------------------------------------------------------
- void __fastcall TLogMemo::KeyDown(Word & Key, TShiftState Shift)
- {
- if ((Key == VK_UP) || (Key == VK_DOWN))
- {
- SendMessage(Handle, EM_LINESCROLL, 0, ( Key == VK_UP ? -1 : 1));
- Key = 0;
- }
- else
- {
- TCustomRichEdit::KeyDown(Key, Shift);
- }
- }
- //---------------------------------------------------------------------------
- void __fastcall TLogMemo::WMKeyDown(TWMKeyDown & Message)
- {
- try
- {
- TCustomRichEdit::Dispatch(&Message);
- }
- __finally
- {
- HideCaret(Handle);
- }
- }
- //---------------------------------------------------------------------------
- void __fastcall TLogMemo::WMPaint(TWMPaint & Message)
- {
- try
- {
- TCustomRichEdit::Dispatch(&Message);
- }
- __finally
- {
- if (FWantScrollToEnd)
- {
- FWantScrollToEnd = false;
- SelLength = 0;
- SelStart = Lines->Text.Length();
- SendMessage(Handle, EM_LINESCROLL, 0, Lines->Count);
- }
- HideCaret(Handle);
- }
- }
- //---------------------------------------------------------------------------
- int __fastcall TLogMemo::GetLinesVisible()
- {
- HFONT OldFont;
- HDC DC;
- TTextMetricW TM;
- TRect Rect;
- DC = GetDC((HWND)Handle);
- OldFont = (HFONT)SelectObject(DC, (HWND)Font->Handle);
- try
- {
- GetTextMetrics(DC, &TM);
- Perform(EM_GETRECT, 0, ((int)&Rect));
- }
- __finally
- {
- SelectObject(DC, OldFont);
- ReleaseDC(Handle, DC);
- }
- return (Rect.Bottom - Rect.Top) / (TM.tmHeight + TM.tmExternalLeading);
- }
- //---------------------------------------------------------------------------
- void __fastcall TLogMemo::SetParent(TWinControl * AParent)
- {
- TCustomRichEdit::SetParent(AParent);
- if (AParent) UpdateFromLog();
- }
- //---------------------------------------------------------------------------
- void __fastcall TLogMemo::Change()
- {
- if (Parent && Visible && !Application->Terminated && !FUpdating)
- {
- TCustomRichEdit::Change();
- }
- }
|