Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

463 lines
12 KiB

//
// snoop.cpp
//
// CSnoopWnd implementation.
//
#include "globals.h"
#include "snoop.h"
#include "case.h"
#include "editsess.h"
class CUpdateTextEditSession : public CEditSessionBase
{
public:
CUpdateTextEditSession(ITfContext *pContext, ITfRange *pRange, CSnoopWnd *pSnoopWnd) : CEditSessionBase(pContext)
{
_pSnoopWnd = pSnoopWnd;
_pRange = pRange;
if (_pRange != NULL)
{
_pRange->AddRef();
}
}
~CUpdateTextEditSession()
{
SafeRelease(_pRange);
}
// ITfEditSession
STDMETHODIMP DoEditSession(TfEditCookie ec);
private:
CSnoopWnd *_pSnoopWnd;
ITfRange *_pRange;
};
#define SNOOP_X_POS 0
#define SNOOP_Y_POS 0
#define SNOOP_WIDTH 300
#define SNOOP_HEIGHT (SNOOP_WIDTH / 3)
ATOM CSnoopWnd::_atomWndClass = 0;
//+---------------------------------------------------------------------------
//
// ctor
//
//----------------------------------------------------------------------------
CSnoopWnd::CSnoopWnd(CCaseTextService *pCase)
{
_pCase = pCase; // no AddRef because CSnoopWnd is contained in the
// pCase lifetime
_hWnd = NULL;
_cchText = 0;
}
//+---------------------------------------------------------------------------
//
// _InitClass
//
//----------------------------------------------------------------------------
/* static */
BOOL CSnoopWnd::_InitClass()
{
WNDCLASS wc;
wc.style = 0;
wc.lpfnWndProc = CSnoopWnd::_WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = g_hInst;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = TEXT("SnoopWndClass");
_atomWndClass = RegisterClass(&wc);
return (_atomWndClass != 0);
}
//+---------------------------------------------------------------------------
//
// _UninitClass
//
//----------------------------------------------------------------------------
/* static */
void CSnoopWnd::_UninitClass()
{
if (_atomWndClass != 0)
{
UnregisterClass((LPCTSTR)_atomWndClass, g_hInst);
}
}
//+---------------------------------------------------------------------------
//
// _Init
//
//----------------------------------------------------------------------------
BOOL CSnoopWnd::_Init()
{
// nb: on windows 2000, you can use WS_EX_NOACTIVATE to prevent windows
// from taking the foreground. We don't use that here for compatibility.
// Instead, we use WS_DISABLED, which can be burdensome for more complex
// ui.
_hWnd = CreateWindowEx(WS_EX_TOPMOST | WS_EX_TOOLWINDOW,
(LPCTSTR)_atomWndClass,
TEXT("Snoop Window"),
WS_BORDER | WS_DISABLED | WS_POPUP,
SNOOP_X_POS, SNOOP_Y_POS,
SNOOP_WIDTH, SNOOP_HEIGHT,
NULL,
NULL,
g_hInst,
this);
return (_hWnd != NULL);
}
//+---------------------------------------------------------------------------
//
// _Uninit
//
//----------------------------------------------------------------------------
void CSnoopWnd::_Uninit()
{
if (_hWnd != NULL)
{
DestroyWindow(_hWnd);
_hWnd = NULL;
}
}
//+---------------------------------------------------------------------------
//
// _Show
//
//----------------------------------------------------------------------------
void CSnoopWnd::_Show()
{
ShowWindow(_hWnd, SW_SHOWNA);
}
//+---------------------------------------------------------------------------
//
// _Hide
//
//----------------------------------------------------------------------------
void CSnoopWnd::_Hide()
{
ShowWindow(_hWnd, SW_HIDE);
}
//+---------------------------------------------------------------------------
//
// _UpdateText
//
//----------------------------------------------------------------------------
void CSnoopWnd::_UpdateText(ITfRange *pRange)
{
ITfDocumentMgr *pdmFocus;
ITfContext *pContext;
CUpdateTextEditSession *pEditSession;
HRESULT hr;
if (pRange == NULL)
{
// caller wants us to just use the selection in the focus doc
if (_pCase->_GetThreadMgr()->GetFocus(&pdmFocus) != S_OK)
return;
hr = pdmFocus->GetTop(&pContext);
pdmFocus->Release();
if (hr != S_OK)
return;
}
else if (pRange->GetContext(&pContext) != S_OK)
return;
if (pEditSession = new CUpdateTextEditSession(pContext, pRange, this))
{
// we need a document read lock to scan text
// the CUpdateTextEditSession will do all the work when the
// CUpdateTextEditSession::DoEditSession method is called by the context
pContext->RequestEditSession(_pCase->_GetClientId(), pEditSession, TF_ES_READ | TF_ES_ASYNCDONTCARE, &hr);
pEditSession->Release();
}
pContext->Release();
}
//+---------------------------------------------------------------------------
//
// DoEditSession
//
//----------------------------------------------------------------------------
STDAPI CUpdateTextEditSession::DoEditSession(TfEditCookie ec)
{
_pSnoopWnd->_UpdateText(ec, _pContext, _pRange);
return S_OK;
}
//+---------------------------------------------------------------------------
//
// _UpdateText
//
//----------------------------------------------------------------------------
void CSnoopWnd::_UpdateText(TfEditCookie ec, ITfContext *pContext, ITfRange *pRange)
{
LONG cchBefore;
LONG cchAfter;
TF_SELECTION tfSelection;
ULONG cFetched;
BOOL fReleaseRange = FALSE;
if (pRange == NULL)
{
// caller wants us to use the selection
if (pContext->GetSelection(ec, TS_DEFAULT_SELECTION, 1, &tfSelection, &cFetched) != S_OK ||
cFetched != 1)
{
return;
}
pRange = tfSelection.range; // no AddRef, take ownership of the pointer
fReleaseRange = TRUE;
}
// arbitrarily grab some text before and after the range start anchor
pRange->Collapse(ec, TF_ANCHOR_START);
pRange->ShiftStart(ec, -MAX_SNOOP_TEXT / 2, &cchBefore, NULL);
cchBefore = -cchBefore; // we shifted backwards, so make count a positive number
pRange->GetText(ec, 0, _achText, cchBefore, (ULONG *)&cchBefore);
pRange->Collapse(ec, TF_ANCHOR_END);
pRange->ShiftEnd(ec, MAX_SNOOP_TEXT - cchBefore, &cchAfter, NULL);
pRange->GetText(ec, 0, _achText + cchBefore, cchAfter, (ULONG *)&cchAfter);
_cchText = cchBefore + cchAfter;
// force a repaint
InvalidateRect(_hWnd, NULL, TRUE);
if (fReleaseRange)
{
pRange->Release();
}
}
//+---------------------------------------------------------------------------
//
// _WndProc
//
// Snoop window proc.
//----------------------------------------------------------------------------
/* static */
LRESULT CALLBACK CSnoopWnd::_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
switch (uMsg)
{
case WM_CREATE:
_SetThis(hWnd, lParam);
return 0;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
_GetThis(hWnd)->_OnPaint(hWnd, hdc);
EndPaint(hWnd, &ps);
return 0;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
//+---------------------------------------------------------------------------
//
// _OnPaint
//
// WM_PAINT handler for CSnoopWnd.
//----------------------------------------------------------------------------
void CSnoopWnd::_OnPaint(HWND hWnd, HDC hdc)
{
RECT rc;
// background
GetClientRect(hWnd, &rc);
FillRect(hdc, &rc, (HBRUSH)GetStockObject(LTGRAY_BRUSH));
// text
TextOutW(hdc, 0, 0, _achText, _cchText);
}
//+---------------------------------------------------------------------------
//
// _InitSnoopWnd
//
// Create and init the snoop window.
//----------------------------------------------------------------------------
BOOL CCaseTextService::_InitSnoopWnd()
{
BOOL fThreadfocus;
ITfSource *pSource = NULL;
// create a snoop window
if ((_pSnoopWnd = new CSnoopWnd(this)) == NULL)
return FALSE;
if (!_pSnoopWnd->_Init())
goto ExitError;
// we also need a thread focus sink
if (_pThreadMgr->QueryInterface(IID_ITfSource, (void **)&pSource) != S_OK)
{
pSource = NULL;
goto ExitError;
}
if (pSource->AdviseSink(IID_ITfThreadFocusSink, (ITfThreadFocusSink *)this, &_dwThreadFocusSinkCookie) != S_OK)
{
// make sure we don't try to Unadvise _dwThreadFocusSinkCookie later
_dwThreadFocusSinkCookie = TF_INVALID_COOKIE;
goto ExitError;
}
pSource->Release();
// we may need to display the snoop window right now
// our thread focus sink won't be called until something changes,
// so we need to check the current state.
if (_pThreadMgr->IsThreadFocus(&fThreadfocus) == S_OK && fThreadfocus)
{
OnSetThreadFocus();
}
return TRUE;
ExitError:
SafeRelease(pSource);
_UninitSnoopWnd();
return FALSE;
}
//+---------------------------------------------------------------------------
//
// _UninitSnoopWnd
//
// Uninit and free the snoop window, unadvise the thread focus sink.
//----------------------------------------------------------------------------
void CCaseTextService::_UninitSnoopWnd()
{
ITfSource *pSource;
if (_pSnoopWnd != NULL)
{
_pSnoopWnd->_Uninit();
delete _pSnoopWnd;
}
if (_dwThreadFocusSinkCookie != TF_INVALID_COOKIE)
{
if (_pThreadMgr->QueryInterface(IID_ITfSource, (void **)&pSource) == S_OK)
{
pSource->UnadviseSink(_dwThreadFocusSinkCookie);
pSource->Release();
}
_dwThreadFocusSinkCookie = TF_INVALID_COOKIE;
}
}
//+---------------------------------------------------------------------------
//
// _Menu_ShowSnoopWnd
//
// Show or hide the snoop window.
//----------------------------------------------------------------------------
void CCaseTextService::_Menu_ShowSnoopWnd(CCaseTextService *_this)
{
_this->_fShowSnoop = !_this->_fShowSnoop;
if (_this->_fShowSnoop)
{
_this->_pSnoopWnd->_Show();
}
else
{
_this->_pSnoopWnd->_Hide();
}
}
//+---------------------------------------------------------------------------
//
// OnSetThreadFocus
//
// Called by the system when the thread/appartment of this text service gains
// the ui focus.
//----------------------------------------------------------------------------
STDAPI CCaseTextService::OnSetThreadFocus()
{
if (_fShowSnoop)
{
_pSnoopWnd->_Show();
}
return S_OK;
}
//+---------------------------------------------------------------------------
//
// OnKillThreadFocus
//
// Called by the system when the thread/appartment of this text service loses
// the ui focus.
//----------------------------------------------------------------------------
STDAPI CCaseTextService::OnKillThreadFocus()
{
// only show our snoop window when our thread has the focus.
if (_fShowSnoop)
{
_pSnoopWnd->_Hide();
}
return S_OK;
}