1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/widget/tests/TestWinTSF.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,3194 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 + 1.10 +/* This tests Mozilla's Text Services Framework implementation (bug #88831) 1.11 + * 1.12 + * The Mozilla implementation interacts with the TSF system through a 1.13 + * system-provided COM interface, ITfThreadMgr. This tests works by swapping 1.14 + * the system version of the interface with a custom version implemented in 1.15 + * here. This way the Mozilla implementation thinks it's interacting with the 1.16 + * system but in fact is interacting with this test program. This allows the 1.17 + * test program to access and test every aspect of the Mozilla implementation. 1.18 + */ 1.19 + 1.20 +#include <ole2.h> 1.21 +#include <msctf.h> 1.22 +#include <textstor.h> 1.23 +#include <richedit.h> 1.24 + 1.25 +#include "TestHarness.h" 1.26 +#include <algorithm> 1.27 + 1.28 +#define WM_USER_TSF_TEXTCHANGE (WM_USER + 0x100) 1.29 + 1.30 +#ifndef MOZILLA_INTERNAL_API 1.31 +// some of the includes make use of internal string types 1.32 +#define nsAString_h___ 1.33 +#define nsString_h___ 1.34 +#define nsStringFwd_h___ 1.35 +#define nsReadableUtils_h___ 1.36 +class nsACString; 1.37 +class nsAString; 1.38 +class nsAFlatString; 1.39 +class nsAFlatCString; 1.40 +class nsAdoptingString; 1.41 +class nsAdoptingCString; 1.42 +class nsXPIDLString; 1.43 +template<class T> class nsReadingIterator; 1.44 +#endif 1.45 + 1.46 +#include "nscore.h" 1.47 +#include "nsWeakReference.h" 1.48 +#include "nsIAppShell.h" 1.49 +#include "nsWidgetsCID.h" 1.50 +#include "nsIAppShellService.h" 1.51 +#include "nsAppShellCID.h" 1.52 +#include "nsNetUtil.h" 1.53 +#include "nsIWebBrowserChrome.h" 1.54 +#include "nsIXULWindow.h" 1.55 +#include "nsIBaseWindow.h" 1.56 +#include "nsIDOMWindow.h" 1.57 +#include "nsIDocShell.h" 1.58 +#include "nsIWidget.h" 1.59 +#include "nsIPresShell.h" 1.60 +#include "nsPresContext.h" 1.61 +#include "nsIFrame.h" 1.62 +#include "nsIWebProgress.h" 1.63 +#include "nsIWebProgressListener.h" 1.64 +#include "nsIInterfaceRequestorUtils.h" 1.65 +#include "nsIDOMHTMLDocument.h" 1.66 +#include "mozilla/dom/HTMLBodyElement.h" 1.67 +#include "nsIDOMHTMLElement.h" 1.68 +#include "nsIDOMHTMLInputElement.h" 1.69 +#include "nsIDOMHTMLTextAreaElement.h" 1.70 +#include "nsIDOMElement.h" 1.71 +#include "nsISelectionController.h" 1.72 +#include "nsViewManager.h" 1.73 +#include "nsTArray.h" 1.74 + 1.75 +#ifndef MOZILLA_INTERNAL_API 1.76 +#undef nsString_h___ 1.77 +#undef nsAString_h___ 1.78 +#undef nsReadableUtils_h___ 1.79 +#endif 1.80 + 1.81 +static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID); 1.82 + 1.83 +class TSFMgrImpl; 1.84 +class TSFDocumentMgrImpl; 1.85 +class TSFContextImpl; 1.86 +class TSFRangeImpl; 1.87 +class TSFEnumRangeImpl; 1.88 +class TSFAttrPropImpl; 1.89 + 1.90 +class TestApp : public nsIWebProgressListener, public nsSupportsWeakReference 1.91 +{ 1.92 +public: 1.93 + NS_DECL_ISUPPORTS 1.94 + NS_DECL_NSIWEBPROGRESSLISTENER 1.95 + 1.96 + TestApp() : mFailed(false) {} 1.97 + ~TestApp() {} 1.98 + 1.99 + nsresult Run(void); 1.100 + bool CheckFailed(void); 1.101 + 1.102 + typedef bool (TestApp::*test_type)(void); 1.103 + 1.104 +protected: 1.105 + nsresult Init(void); 1.106 + nsresult Term(void); 1.107 + bool RunTest(test_type aTest, bool aLock = true); 1.108 + 1.109 + bool TestFocus(void); 1.110 + bool TestClustering(void); 1.111 + bool TestSelection(void); 1.112 + bool TestText(void); 1.113 + bool TestExtents(void); 1.114 + bool TestComposition(void); 1.115 + bool TestNotification(void); 1.116 + bool TestEditMessages(void); 1.117 + bool TestScrollMessages(void); 1.118 + 1.119 + bool TestSelectionInternal(char* aTestName, 1.120 + LONG aStart, 1.121 + LONG aEnd, 1.122 + TsActiveSelEnd aSelEnd); 1.123 + bool TestCompositionSelectionAndText(char* aTestName, 1.124 + LONG aExpectedSelStart, 1.125 + LONG aExpectedSelEnd, 1.126 + nsString& aReferenceString); 1.127 + bool TestNotificationTextChange(nsIWidget* aWidget, 1.128 + uint32_t aCode, 1.129 + const nsAString& aCharacter, 1.130 + LONG aStart, 1.131 + LONG aOldEnd, 1.132 + LONG aNewEnd); 1.133 + nsresult GetSelCon(nsISelectionController** aSelCon); 1.134 + 1.135 + bool GetWidget(nsIWidget** aWidget); 1.136 + 1.137 + bool mFailed; 1.138 + nsString mTestString; 1.139 + nsRefPtr<TSFMgrImpl> mMgr; 1.140 + nsCOMPtr<nsIAppShell> mAppShell; 1.141 + nsCOMPtr<nsIXULWindow> mWindow; 1.142 + nsCOMPtr<nsIDOMNode> mCurrentNode; 1.143 + nsCOMPtr<nsIDOMHTMLInputElement> mInput; 1.144 + nsCOMPtr<nsIDOMHTMLTextAreaElement> mTextArea; 1.145 + nsCOMPtr<nsIDOMHTMLInputElement> mButton; 1.146 +}; 1.147 + 1.148 +NS_IMETHODIMP 1.149 +TestApp::OnProgressChange(nsIWebProgress *aWebProgress, 1.150 + nsIRequest *aRequest, 1.151 + int32_t aCurSelfProgress, 1.152 + int32_t aMaxSelfProgress, 1.153 + int32_t aCurTotalProgress, 1.154 + int32_t aMaxTotalProgress) 1.155 +{ 1.156 + return NS_OK; 1.157 +} 1.158 + 1.159 +NS_IMETHODIMP 1.160 +TestApp::OnLocationChange(nsIWebProgress *aWebProgress, 1.161 + nsIRequest *aRequest, 1.162 + nsIURI *aLocation, 1.163 + uint32_t aFlags) 1.164 +{ 1.165 + return NS_OK; 1.166 +} 1.167 + 1.168 +NS_IMETHODIMP 1.169 +TestApp::OnStatusChange(nsIWebProgress *aWebProgress, 1.170 + nsIRequest *aRequest, 1.171 + nsresult aStatus, 1.172 + const char16_t *aMessage) 1.173 +{ 1.174 + return NS_OK; 1.175 +} 1.176 + 1.177 +NS_IMETHODIMP 1.178 +TestApp::OnSecurityChange(nsIWebProgress *aWebProgress, 1.179 + nsIRequest *aRequest, 1.180 + uint32_t aState) 1.181 +{ 1.182 + return NS_OK; 1.183 +} 1.184 + 1.185 +static HRESULT 1.186 +GetRegularExtent(ITfRange *aRange, LONG &aStart, LONG &aEnd) 1.187 +{ 1.188 + NS_ENSURE_TRUE(aRange, E_INVALIDARG); 1.189 + nsRefPtr<ITfRangeACP> rangeACP; 1.190 + HRESULT hr = aRange->QueryInterface(IID_ITfRangeACP, 1.191 + getter_AddRefs(rangeACP)); 1.192 + NS_ENSURE_TRUE(SUCCEEDED(hr) && rangeACP, E_FAIL); 1.193 + 1.194 + LONG start, length; 1.195 + hr = rangeACP->GetExtent(&start, &length); 1.196 + NS_ENSURE_TRUE(SUCCEEDED(hr), hr); 1.197 + if (length >= 0) { 1.198 + aStart = start; 1.199 + aEnd = start + length; 1.200 + } else { 1.201 + aEnd = start; 1.202 + aStart = start + length; 1.203 + } 1.204 + return S_OK; 1.205 +} 1.206 + 1.207 +// {3B2DFDF5-2485-4858-8185-5C6B4EFD38F5} 1.208 +static const GUID GUID_COMPOSING_SELECTION_ATTR = 1.209 + { 0x3b2dfdf5, 0x2485, 0x4858, 1.210 + { 0x81, 0x85, 0x5c, 0x6b, 0x4e, 0xfd, 0x38, 0xf5 } }; 1.211 +#define GUID_ATOM_COMPOSING_SELECTION_ATTR \ 1.212 + (static_cast<TfGuidAtom>(0x3b2dfdf5)) 1.213 + 1.214 +/****************************************************************************** 1.215 + * TSFRangeImpl 1.216 + ******************************************************************************/ 1.217 + 1.218 +class TSFRangeImpl : public ITfRangeACP 1.219 +{ 1.220 +private: 1.221 + ULONG mRefCnt; 1.222 + 1.223 +public: 1.224 + LONG mStart; 1.225 + LONG mLength; 1.226 + 1.227 + TSFRangeImpl(LONG aStart = 0, LONG aLength = 0) : 1.228 + mRefCnt(0), mStart(aStart), mLength(aLength) 1.229 + { 1.230 + } 1.231 + 1.232 + ~TSFRangeImpl() 1.233 + { 1.234 + } 1.235 + 1.236 +public: // IUnknown 1.237 + 1.238 + STDMETHODIMP QueryInterface(REFIID riid, void** ppUnk) 1.239 + { 1.240 + *ppUnk = nullptr; 1.241 + if (IID_IUnknown == riid || IID_ITfRange == riid || IID_ITfRangeACP == riid) 1.242 + *ppUnk = static_cast<ITfRangeACP*>(this); 1.243 + if (*ppUnk) 1.244 + AddRef(); 1.245 + return *ppUnk ? S_OK : E_NOINTERFACE; 1.246 + } 1.247 + 1.248 + STDMETHODIMP_(ULONG) AddRef(void) 1.249 + { 1.250 + return ++mRefCnt; 1.251 + } 1.252 + 1.253 + STDMETHODIMP_(ULONG) Release(void) 1.254 + { 1.255 + if (--mRefCnt) return mRefCnt; 1.256 + delete this; 1.257 + return 0; 1.258 + } 1.259 + 1.260 +public: // ITfRange 1.261 + 1.262 + STDMETHODIMP GetText(TfEditCookie ec, DWORD dwFlags, WCHAR *pchText, 1.263 + ULONG cchMax, ULONG *pcch) 1.264 + { 1.265 + NS_NOTREACHED("ITfRange::GetText"); 1.266 + return E_NOTIMPL; 1.267 + } 1.268 + 1.269 + STDMETHODIMP SetText(TfEditCookie ec, DWORD dwFlags, const WCHAR *pchText, 1.270 + LONG cch) 1.271 + { 1.272 + NS_NOTREACHED("ITfRange::SetText"); 1.273 + return E_NOTIMPL; 1.274 + } 1.275 + 1.276 + STDMETHODIMP GetFormattedText(TfEditCookie ec, IDataObject **ppDataObject) 1.277 + { 1.278 + NS_NOTREACHED("ITfRange::GetFormattedText"); 1.279 + return E_NOTIMPL; 1.280 + } 1.281 + 1.282 + STDMETHODIMP GetEmbedded(TfEditCookie ec, REFGUID rguidService, REFIID riid, 1.283 + IUnknown **ppunk) 1.284 + { 1.285 + NS_NOTREACHED("ITfRange::GetEmbedded"); 1.286 + return E_NOTIMPL; 1.287 + } 1.288 + 1.289 + STDMETHODIMP InsertEmbedded(TfEditCookie ec, DWORD dwFlags, 1.290 + IDataObject *pDataObject) 1.291 + { 1.292 + NS_NOTREACHED("ITfRange::InsertEmbedded"); 1.293 + return E_NOTIMPL; 1.294 + } 1.295 + 1.296 + STDMETHODIMP ShiftStart(TfEditCookie ec, LONG cchReq, LONG *pcch, 1.297 + const TF_HALTCOND *pHalt) 1.298 + { 1.299 + NS_NOTREACHED("ITfRange::ShiftStart"); 1.300 + return E_NOTIMPL; 1.301 + } 1.302 + 1.303 + STDMETHODIMP ShiftEnd(TfEditCookie ec, LONG cchReq, LONG *pcch, 1.304 + const TF_HALTCOND *pHalt) 1.305 + { 1.306 + NS_NOTREACHED("ITfRange::ShiftEnd"); 1.307 + return E_NOTIMPL; 1.308 + } 1.309 + 1.310 + STDMETHODIMP ShiftStartToRange(TfEditCookie ec, ITfRange *pRange, 1.311 + TfAnchor aPos) 1.312 + { 1.313 + NS_NOTREACHED("ITfRange::ShiftStartToRange"); 1.314 + return E_NOTIMPL; 1.315 + } 1.316 + 1.317 + STDMETHODIMP ShiftEndToRange(TfEditCookie ec, ITfRange *pRange, TfAnchor aPos) 1.318 + { 1.319 + NS_NOTREACHED("ITfRange::ShiftEndToRange"); 1.320 + return E_NOTIMPL; 1.321 + } 1.322 + 1.323 + STDMETHODIMP ShiftStartRegion(TfEditCookie ec, TfShiftDir dir, 1.324 + BOOL *pfNoRegion) 1.325 + { 1.326 + NS_NOTREACHED("ITfRange::ShiftStartRegion"); 1.327 + return E_NOTIMPL; 1.328 + } 1.329 + 1.330 + STDMETHODIMP ShiftEndRegion(TfEditCookie ec, TfShiftDir dir, BOOL *pfNoRegion) 1.331 + { 1.332 + NS_NOTREACHED("ITfRange::ShiftEndRegion"); 1.333 + return E_NOTIMPL; 1.334 + } 1.335 + 1.336 + STDMETHODIMP IsEmpty(TfEditCookie ec, BOOL *pfEmpty) 1.337 + { 1.338 + NS_NOTREACHED("ITfRange::IsEmpty"); 1.339 + return E_NOTIMPL; 1.340 + } 1.341 + 1.342 + STDMETHODIMP Collapse(TfEditCookie ec, TfAnchor aPos) 1.343 + { 1.344 + NS_NOTREACHED("ITfRange::Collapse"); 1.345 + return E_NOTIMPL; 1.346 + } 1.347 + 1.348 + STDMETHODIMP IsEqualStart(TfEditCookie ec, ITfRange *pWith, TfAnchor aPos, 1.349 + BOOL *pfEqual) 1.350 + { 1.351 + NS_NOTREACHED("ITfRange::IsEqualStart"); 1.352 + return E_NOTIMPL; 1.353 + } 1.354 + 1.355 + STDMETHODIMP IsEqualEnd(TfEditCookie ec, ITfRange *pWith, TfAnchor aPos, 1.356 + BOOL *pfEqual) 1.357 + { 1.358 + NS_NOTREACHED("ITfRange::IsEqualEnd"); 1.359 + return E_NOTIMPL; 1.360 + } 1.361 + 1.362 + STDMETHODIMP CompareStart(TfEditCookie ec, ITfRange *pWith, TfAnchor aPos, 1.363 + LONG *plResult) 1.364 + { 1.365 + NS_NOTREACHED("ITfRange::CompareStart"); 1.366 + return E_NOTIMPL; 1.367 + } 1.368 + 1.369 + STDMETHODIMP CompareEnd(TfEditCookie ec, ITfRange *pWith, TfAnchor aPos, 1.370 + LONG *plResult) 1.371 + { 1.372 + NS_NOTREACHED("ITfRange::CompareEnd"); 1.373 + return E_NOTIMPL; 1.374 + } 1.375 + 1.376 + STDMETHODIMP AdjustForInsert(TfEditCookie ec, ULONG cchInsert, 1.377 + BOOL *pfInsertOk) 1.378 + { 1.379 + NS_NOTREACHED("ITfRange::AdjustForInsert"); 1.380 + return E_NOTIMPL; 1.381 + } 1.382 + 1.383 + STDMETHODIMP GetGravity(TfGravity *pgStart, TfGravity *pgEnd) 1.384 + { 1.385 + NS_NOTREACHED("ITfRange::GetGravity"); 1.386 + return E_NOTIMPL; 1.387 + } 1.388 + 1.389 + STDMETHODIMP SetGravity(TfEditCookie ec, TfGravity gStart, TfGravity gEnd) 1.390 + { 1.391 + NS_NOTREACHED("ITfRange::SetGravity"); 1.392 + return E_NOTIMPL; 1.393 + } 1.394 + 1.395 + STDMETHODIMP Clone(ITfRange **ppClone) 1.396 + { 1.397 + NS_NOTREACHED("ITfRange::Clone"); 1.398 + return E_NOTIMPL; 1.399 + } 1.400 + 1.401 + STDMETHODIMP GetContext(ITfContext **ppContext) 1.402 + { 1.403 + NS_NOTREACHED("ITfRange::GetContext"); 1.404 + return E_NOTIMPL; 1.405 + } 1.406 + 1.407 +public: // ITfRangeACP 1.408 + 1.409 + STDMETHODIMP GetExtent(LONG *pacpAnchor, LONG *pcch) 1.410 + { 1.411 + NS_ENSURE_TRUE(pacpAnchor, E_FAIL); 1.412 + NS_ENSURE_TRUE(pcch, E_FAIL); 1.413 + *pacpAnchor = mStart; 1.414 + *pcch = mLength; 1.415 + return S_OK; 1.416 + } 1.417 + 1.418 + STDMETHODIMP SetExtent(LONG acpAnchor, LONG cch) 1.419 + { 1.420 + mStart = acpAnchor; 1.421 + mLength = cch; 1.422 + return S_OK; 1.423 + } 1.424 +}; 1.425 + 1.426 +/****************************************************************************** 1.427 + * TSFEnumRangeImpl 1.428 + ******************************************************************************/ 1.429 + 1.430 +class TSFEnumRangeImpl : public IEnumTfRanges 1.431 +{ 1.432 +private: 1.433 + ULONG mRefCnt; 1.434 + uint32_t mCurrentIndex; 1.435 + 1.436 +public: 1.437 + nsTArray<nsRefPtr<TSFRangeImpl> > mRanges; 1.438 + 1.439 + TSFEnumRangeImpl() : 1.440 + mRefCnt(0), mCurrentIndex(0) 1.441 + { 1.442 + } 1.443 + 1.444 + ~TSFEnumRangeImpl() 1.445 + { 1.446 + } 1.447 + 1.448 +public: // IUnknown 1.449 + 1.450 + STDMETHODIMP QueryInterface(REFIID riid, void** ppUnk) 1.451 + { 1.452 + *ppUnk = nullptr; 1.453 + if (IID_IUnknown == riid || IID_IEnumTfRanges == riid) 1.454 + *ppUnk = static_cast<IEnumTfRanges*>(this); 1.455 + if (*ppUnk) 1.456 + AddRef(); 1.457 + return *ppUnk ? S_OK : E_NOINTERFACE; 1.458 + } 1.459 + 1.460 + STDMETHODIMP_(ULONG) AddRef(void) 1.461 + { 1.462 + return ++mRefCnt; 1.463 + } 1.464 + 1.465 + STDMETHODIMP_(ULONG) Release(void) 1.466 + { 1.467 + if (--mRefCnt) return mRefCnt; 1.468 + delete this; 1.469 + return 0; 1.470 + } 1.471 + 1.472 +public: // IEnumTfRanges 1.473 + 1.474 + STDMETHODIMP Clone(IEnumTfRanges **ppEnum) 1.475 + { 1.476 + NS_NOTREACHED("IEnumTfRanges::Clone"); 1.477 + return E_NOTIMPL; 1.478 + } 1.479 + 1.480 + STDMETHODIMP Next(ULONG ulCount, ITfRange **ppRange, ULONG *pcFetched) 1.481 + { 1.482 + NS_ENSURE_TRUE(ppRange, E_FAIL); 1.483 + if (pcFetched) 1.484 + *pcFetched = 0; 1.485 + if (mCurrentIndex + ulCount - 1 >= mRanges.Length()) 1.486 + return E_FAIL; 1.487 + for (uint32_t i = 0; i < ulCount; i++) { 1.488 + ppRange[i] = mRanges[mCurrentIndex++]; 1.489 + ppRange[i]->AddRef(); 1.490 + if (pcFetched) 1.491 + (*pcFetched)++; 1.492 + } 1.493 + return S_OK; 1.494 + } 1.495 + 1.496 + STDMETHODIMP Reset() 1.497 + { 1.498 + mCurrentIndex = 0; 1.499 + return S_OK; 1.500 + } 1.501 + 1.502 + STDMETHODIMP Skip(ULONG ulCount) 1.503 + { 1.504 + mCurrentIndex += ulCount; 1.505 + return S_OK; 1.506 + } 1.507 +}; 1.508 + 1.509 +/****************************************************************************** 1.510 + * TSFDispAttrInfoImpl 1.511 + ******************************************************************************/ 1.512 + 1.513 +class TSFDispAttrInfoImpl : public ITfDisplayAttributeInfo 1.514 +{ 1.515 +private: 1.516 + ULONG mRefCnt; 1.517 + TF_DISPLAYATTRIBUTE mAttr; 1.518 + 1.519 +public: 1.520 + 1.521 + TSFDispAttrInfoImpl(REFGUID aGUID) : 1.522 + mRefCnt(0) 1.523 + { 1.524 + if (aGUID == GUID_COMPOSING_SELECTION_ATTR) { 1.525 + mAttr.crText.type = TF_CT_NONE; 1.526 + mAttr.crBk.type = TF_CT_NONE; 1.527 + mAttr.lsStyle = TF_LS_SQUIGGLE; 1.528 + mAttr.fBoldLine = FALSE; 1.529 + mAttr.crLine.type = TF_CT_NONE; 1.530 + mAttr.bAttr = TF_ATTR_INPUT; 1.531 + } else { 1.532 + NS_NOTREACHED("TSFDispAttrInfoImpl::TSFDispAttrInfoImpl"); 1.533 + } 1.534 + } 1.535 + 1.536 + ~TSFDispAttrInfoImpl() 1.537 + { 1.538 + } 1.539 + 1.540 +public: // IUnknown 1.541 + 1.542 + STDMETHODIMP QueryInterface(REFIID riid, void** ppUnk) 1.543 + { 1.544 + *ppUnk = nullptr; 1.545 + if (IID_IUnknown == riid || IID_ITfDisplayAttributeInfo == riid) 1.546 + *ppUnk = static_cast<ITfDisplayAttributeInfo*>(this); 1.547 + if (*ppUnk) 1.548 + AddRef(); 1.549 + return *ppUnk ? S_OK : E_NOINTERFACE; 1.550 + } 1.551 + 1.552 + STDMETHODIMP_(ULONG) AddRef(void) 1.553 + { 1.554 + return ++mRefCnt; 1.555 + } 1.556 + 1.557 + STDMETHODIMP_(ULONG) Release(void) 1.558 + { 1.559 + if (--mRefCnt) return mRefCnt; 1.560 + delete this; 1.561 + return 0; 1.562 + } 1.563 + 1.564 +public: // ITfDisplayAttributeInfo 1.565 + 1.566 + STDMETHODIMP GetGUID(GUID *pguid) 1.567 + { 1.568 + NS_NOTREACHED("ITfDisplayAttributeInfo::GetGUID"); 1.569 + return E_NOTIMPL; 1.570 + } 1.571 + 1.572 + STDMETHODIMP GetDescription(BSTR *pbstrDesc) 1.573 + { 1.574 + NS_NOTREACHED("ITfDisplayAttributeInfo::GetDescription"); 1.575 + return E_NOTIMPL; 1.576 + } 1.577 + 1.578 + STDMETHODIMP GetAttributeInfo(TF_DISPLAYATTRIBUTE *pda) 1.579 + { 1.580 + NS_ENSURE_TRUE(pda, E_INVALIDARG); 1.581 + *pda = mAttr; 1.582 + return S_OK; 1.583 + } 1.584 + 1.585 + STDMETHODIMP SetAttributeInfo(const TF_DISPLAYATTRIBUTE *pda) 1.586 + { 1.587 + NS_NOTREACHED("ITfDisplayAttributeInfo::SetAttributeInfo"); 1.588 + return E_NOTIMPL; 1.589 + } 1.590 + 1.591 + STDMETHODIMP Reset() 1.592 + { 1.593 + NS_NOTREACHED("ITfDisplayAttributeInfo::Reset"); 1.594 + return E_NOTIMPL; 1.595 + } 1.596 +}; 1.597 + 1.598 +/****************************************************************************** 1.599 + * TSFAttrPropImpl 1.600 + ******************************************************************************/ 1.601 + 1.602 +class TSFAttrPropImpl : public ITfProperty 1.603 +{ 1.604 +private: 1.605 + ULONG mRefCnt; 1.606 + 1.607 +public: 1.608 + nsTArray<nsRefPtr<TSFRangeImpl> > mRanges; 1.609 + 1.610 + TSFAttrPropImpl() : 1.611 + mRefCnt(0) 1.612 + { 1.613 + } 1.614 + 1.615 + ~TSFAttrPropImpl() 1.616 + { 1.617 + } 1.618 + 1.619 +public: // IUnknown 1.620 + 1.621 + STDMETHODIMP QueryInterface(REFIID riid, void** ppUnk) 1.622 + { 1.623 + *ppUnk = nullptr; 1.624 + if (IID_IUnknown == riid || IID_ITfProperty == riid || 1.625 + IID_ITfReadOnlyProperty == riid) 1.626 + *ppUnk = static_cast<ITfProperty*>(this); 1.627 + if (*ppUnk) 1.628 + AddRef(); 1.629 + return *ppUnk ? S_OK : E_NOINTERFACE; 1.630 + } 1.631 + 1.632 + STDMETHODIMP_(ULONG) AddRef(void) 1.633 + { 1.634 + return ++mRefCnt; 1.635 + } 1.636 + 1.637 + STDMETHODIMP_(ULONG) Release(void) 1.638 + { 1.639 + if (--mRefCnt) return mRefCnt; 1.640 + delete this; 1.641 + return 0; 1.642 + } 1.643 + 1.644 +public: // ITfProperty 1.645 + 1.646 + STDMETHODIMP FindRange(TfEditCookie ec, ITfRange *pRange, ITfRange **ppRange, 1.647 + TfAnchor aPos) 1.648 + { 1.649 + NS_NOTREACHED("ITfProperty::FindRange"); 1.650 + return E_NOTIMPL; 1.651 + } 1.652 + 1.653 + STDMETHODIMP SetValueStore(TfEditCookie ec, ITfRange *pRange, 1.654 + ITfPropertyStore *pPropStore) 1.655 + { 1.656 + NS_NOTREACHED("ITfProperty::SetValueStore"); 1.657 + return E_NOTIMPL; 1.658 + } 1.659 + 1.660 + STDMETHODIMP SetValue(TfEditCookie ec, ITfRange *pRange, 1.661 + const VARIANT *pvarValue) 1.662 + { 1.663 + NS_NOTREACHED("ITfProperty::SetValue"); 1.664 + return E_NOTIMPL; 1.665 + } 1.666 + 1.667 + STDMETHODIMP Clear(TfEditCookie ec, ITfRange *pRange) 1.668 + { 1.669 + NS_NOTREACHED("ITfProperty::Clear"); 1.670 + return E_NOTIMPL; 1.671 + } 1.672 + 1.673 +public: // ITfReadOnlyProperty 1.674 + 1.675 + STDMETHODIMP GetType(GUID *pguid) 1.676 + { 1.677 + NS_NOTREACHED("ITfReadOnlyProperty::GetType"); 1.678 + return E_NOTIMPL; 1.679 + } 1.680 + 1.681 + STDMETHODIMP EnumRanges(TfEditCookie ec, IEnumTfRanges **ppEnum, 1.682 + ITfRange *pTargetRange) 1.683 + { 1.684 + NS_ENSURE_TRUE(ppEnum, E_INVALIDARG); 1.685 + NS_ENSURE_TRUE(pTargetRange, E_INVALIDARG); 1.686 + 1.687 + // XXX ec checking is not implemented yet. 1.688 + 1.689 + LONG targetStart = 0, targetEnd = 0; 1.690 + if (pTargetRange) { 1.691 + HRESULT hr = GetRegularExtent(pTargetRange, targetStart, targetEnd); 1.692 + NS_ENSURE_TRUE(SUCCEEDED(hr), hr); 1.693 + } 1.694 + nsRefPtr<TSFEnumRangeImpl> er = new TSFEnumRangeImpl(); 1.695 + NS_ENSURE_TRUE(er, E_OUTOFMEMORY); 1.696 + for (uint32_t i = 0; i < mRanges.Length(); i++) { 1.697 + LONG start, end; 1.698 + HRESULT hr = GetRegularExtent(mRanges[i], start, end); 1.699 + NS_ENSURE_TRUE(SUCCEEDED(hr), hr); 1.700 + if (pTargetRange) { 1.701 + // If pTargetRange is not null and the current range is not overlapped 1.702 + // with it, we don't need to add range. 1.703 + if (targetStart > end || targetEnd < start) 1.704 + continue; 1.705 + // Otherwise, shrink to the target range. 1.706 + start = std::max(targetStart, start); 1.707 + end = std::min(targetEnd, end); 1.708 + } 1.709 + nsRefPtr<TSFRangeImpl> range = new TSFRangeImpl(start, end - start); 1.710 + NS_ENSURE_TRUE(range, E_OUTOFMEMORY); 1.711 + er->mRanges.AppendElement(range); 1.712 + } 1.713 + *ppEnum = er; 1.714 + (*ppEnum)->AddRef(); 1.715 + return S_OK; 1.716 + } 1.717 + 1.718 + STDMETHODIMP GetValue(TfEditCookie ec, ITfRange *pRange, VARIANT *pvarValue) 1.719 + { 1.720 + NS_ENSURE_TRUE(pvarValue, E_INVALIDARG); 1.721 + 1.722 + LONG givenStart, givenEnd; 1.723 + HRESULT hr = GetRegularExtent(pRange, givenStart, givenEnd); 1.724 + NS_ENSURE_TRUE(SUCCEEDED(hr), hr); 1.725 + for (uint32_t i = 0; i < mRanges.Length(); i++) { 1.726 + LONG start, end; 1.727 + HRESULT hr = GetRegularExtent(mRanges[i], start, end); 1.728 + NS_ENSURE_TRUE(SUCCEEDED(hr), hr); 1.729 + // pRange must be same as (or included in) a range of mRanges. 1.730 + if (givenStart > start || givenEnd < end) 1.731 + continue; 1.732 + pvarValue->vt = VT_I4; 1.733 + pvarValue->lVal = static_cast<DWORD>(GUID_ATOM_COMPOSING_SELECTION_ATTR); 1.734 + return S_OK; 1.735 + } 1.736 + return E_FAIL; 1.737 + } 1.738 + 1.739 + STDMETHODIMP GetContext(ITfContext **ppContext) 1.740 + { 1.741 + NS_NOTREACHED("ITfReadOnlyProperty::GetContext"); 1.742 + return E_NOTIMPL; 1.743 + } 1.744 +}; 1.745 + 1.746 +/****************************************************************************** 1.747 + * TSFContextImpl 1.748 + ******************************************************************************/ 1.749 + 1.750 +class TSFContextImpl : public ITfContext, 1.751 + public ITfCompositionView, public ITextStoreACPSink 1.752 +{ 1.753 +private: 1.754 + ULONG mRefCnt; 1.755 + 1.756 +public: 1.757 + nsRefPtr<TSFAttrPropImpl> mAttrProp; 1.758 + nsRefPtr<TSFDocumentMgrImpl> mDocMgr; 1.759 + bool mTextChanged; 1.760 + bool mSelChanged; 1.761 + TS_TEXTCHANGE mTextChangeData; 1.762 + 1.763 +public: 1.764 + TSFContextImpl(TSFDocumentMgrImpl* aDocMgr) : 1.765 + mDocMgr(aDocMgr), mRefCnt(0), mTextChanged(false), 1.766 + mSelChanged(false) 1.767 + { 1.768 + mAttrProp = new TSFAttrPropImpl(); 1.769 + if (!mAttrProp) { 1.770 + NS_NOTREACHED("TSFContextImpl::TSFContextImpl (OOM)"); 1.771 + return; 1.772 + } 1.773 + } 1.774 + 1.775 + ~TSFContextImpl() 1.776 + { 1.777 + } 1.778 + 1.779 +public: // IUnknown 1.780 + 1.781 + STDMETHODIMP QueryInterface(REFIID riid, void** ppUnk) 1.782 + { 1.783 + *ppUnk = nullptr; 1.784 + if (IID_IUnknown == riid || IID_ITfContext == riid) 1.785 + *ppUnk = static_cast<ITfContext*>(this); 1.786 + else if (IID_ITextStoreACPSink == riid) 1.787 + *ppUnk = static_cast<ITextStoreACPSink*>(this); 1.788 + if (*ppUnk) 1.789 + AddRef(); 1.790 + return *ppUnk ? S_OK : E_NOINTERFACE; 1.791 + } 1.792 + 1.793 + STDMETHODIMP_(ULONG) AddRef(void) 1.794 + { 1.795 + return ++mRefCnt; 1.796 + } 1.797 + 1.798 + STDMETHODIMP_(ULONG) Release(void) 1.799 + { 1.800 + if (--mRefCnt) return mRefCnt; 1.801 + delete this; 1.802 + return 0; 1.803 + } 1.804 + 1.805 +public: // ITfContext 1.806 + 1.807 + STDMETHODIMP RequestEditSession(TfClientId tid, ITfEditSession *pes, 1.808 + DWORD dwFlags, HRESULT *phrSession) 1.809 + { 1.810 + NS_NOTREACHED("ITfContext::RequestEditSession"); 1.811 + return E_NOTIMPL; 1.812 + } 1.813 + 1.814 + STDMETHODIMP InWriteSession(TfClientId tid, BOOL *pfWriteSession) 1.815 + { 1.816 + NS_NOTREACHED("ITfContext::InWriteSession"); 1.817 + return E_NOTIMPL; 1.818 + } 1.819 + 1.820 + STDMETHODIMP GetSelection(TfEditCookie ec, ULONG ulIndex, ULONG ulCount, 1.821 + TF_SELECTION *pSelection, ULONG *pcFetched) 1.822 + { 1.823 + NS_NOTREACHED("ITfContext::GetSelection"); 1.824 + return E_NOTIMPL; 1.825 + } 1.826 + 1.827 + STDMETHODIMP SetSelection(TfEditCookie ec, ULONG ulCount, 1.828 + const TF_SELECTION *pSelection) 1.829 + { 1.830 + NS_NOTREACHED("ITfContext::SetSelection"); 1.831 + return E_NOTIMPL; 1.832 + } 1.833 + 1.834 + STDMETHODIMP GetStart(TfEditCookie ec, ITfRange **ppStart) 1.835 + { 1.836 + NS_NOTREACHED("ITfContext::GetStart"); 1.837 + return E_NOTIMPL; 1.838 + } 1.839 + 1.840 + STDMETHODIMP GetEnd(TfEditCookie ec, ITfRange **ppEnd) 1.841 + { 1.842 + NS_NOTREACHED("ITfContext::GetEnd"); 1.843 + return E_NOTIMPL; 1.844 + } 1.845 + 1.846 + STDMETHODIMP GetActiveView(ITfContextView **ppView) 1.847 + { 1.848 + NS_NOTREACHED("ITfContext::GetActiveView"); 1.849 + return E_NOTIMPL; 1.850 + } 1.851 + 1.852 + STDMETHODIMP EnumViews(IEnumTfContextViews **ppEnum) 1.853 + { 1.854 + NS_NOTREACHED("ITfContext::EnumViews"); 1.855 + return E_NOTIMPL; 1.856 + } 1.857 + 1.858 + STDMETHODIMP GetStatus(TF_STATUS *pdcs) 1.859 + { 1.860 + NS_NOTREACHED("ITfContext::GetStatus"); 1.861 + return E_NOTIMPL; 1.862 + } 1.863 + 1.864 + STDMETHODIMP GetProperty(REFGUID guidProp, ITfProperty **ppProp) 1.865 + { 1.866 + NS_ENSURE_TRUE(ppProp, E_INVALIDARG); 1.867 + if (guidProp == GUID_PROP_ATTRIBUTE) { 1.868 + (*ppProp) = mAttrProp; 1.869 + (*ppProp)->AddRef(); 1.870 + return S_OK; 1.871 + } 1.872 + NS_NOTREACHED("ITfContext::GetProperty"); 1.873 + return E_NOTIMPL; 1.874 + } 1.875 + 1.876 + STDMETHODIMP GetAppProperty(REFGUID guidProp, ITfReadOnlyProperty **ppProp) 1.877 + { 1.878 + NS_NOTREACHED("ITfContext::GetAppProperty"); 1.879 + return E_NOTIMPL; 1.880 + } 1.881 + 1.882 + STDMETHODIMP TrackProperties(const GUID **prgProp, ULONG cProp, 1.883 + const GUID **prgAppProp, ULONG cAppProp, 1.884 + ITfReadOnlyProperty **ppProperty) 1.885 + { 1.886 + NS_NOTREACHED("ITfContext::TrackProperties"); 1.887 + return E_NOTIMPL; 1.888 + } 1.889 + 1.890 + STDMETHODIMP EnumProperties(IEnumTfProperties **ppEnum) 1.891 + { 1.892 + NS_NOTREACHED("ITfContext::EnumProperties"); 1.893 + return E_NOTIMPL; 1.894 + } 1.895 + 1.896 + STDMETHODIMP GetDocumentMgr(ITfDocumentMgr **ppDm) 1.897 + { 1.898 + NS_NOTREACHED("ITfContext::GetDocumentMgr"); 1.899 + return E_NOTIMPL; 1.900 + } 1.901 + 1.902 + STDMETHODIMP CreateRangeBackup(TfEditCookie ec, ITfRange *pRange, 1.903 + ITfRangeBackup **ppBackup) 1.904 + { 1.905 + NS_NOTREACHED("ITfContext::CreateRangeBackup"); 1.906 + return E_NOTIMPL; 1.907 + } 1.908 + 1.909 +public: // ITfCompositionView 1.910 + 1.911 + STDMETHODIMP GetOwnerClsid(CLSID* pclsid) 1.912 + { 1.913 + NS_NOTREACHED("ITfCompositionView::GetOwnerClsid"); 1.914 + return E_NOTIMPL; 1.915 + } 1.916 + 1.917 + STDMETHODIMP GetRange(ITfRange** ppRange) 1.918 + { 1.919 + NS_ENSURE_TRUE(ppRange, E_INVALIDARG); 1.920 + NS_ENSURE_TRUE(mAttrProp->mRanges.Length() > 0, E_FAIL); 1.921 + LONG start = LONG_MAX, end = 0; 1.922 + for (uint32_t i = 0; i < mAttrProp->mRanges.Length(); i++) { 1.923 + LONG tmpStart, tmpEnd; 1.924 + HRESULT hr = GetRegularExtent(mAttrProp->mRanges[i], tmpStart, tmpEnd); 1.925 + NS_ENSURE_TRUE(SUCCEEDED(hr), hr); 1.926 + start = std::min(start, tmpStart); 1.927 + end = std::max(end, tmpEnd); 1.928 + } 1.929 + nsRefPtr<TSFRangeImpl> range = new TSFRangeImpl(); 1.930 + NS_ENSURE_TRUE(range, E_OUTOFMEMORY); 1.931 + HRESULT hr = range->SetExtent(start, end - start); 1.932 + NS_ENSURE_TRUE(SUCCEEDED(hr), hr); 1.933 + (*ppRange) = range; 1.934 + (*ppRange)->AddRef(); 1.935 + return S_OK; 1.936 + } 1.937 + 1.938 +public: // ITextStoreACPSink 1.939 + 1.940 + STDMETHODIMP OnTextChange(DWORD dwFlags, const TS_TEXTCHANGE *pChange) 1.941 + { 1.942 + mTextChanged = true; 1.943 + mTextChangeData = *pChange; 1.944 + return S_OK; 1.945 + } 1.946 + 1.947 + STDMETHODIMP OnSelectionChange(void) 1.948 + { 1.949 + mSelChanged = true; 1.950 + return S_OK; 1.951 + } 1.952 + 1.953 + STDMETHODIMP OnLayoutChange(TsLayoutCode lcode, TsViewCookie vcView) 1.954 + { 1.955 + return S_OK; 1.956 + } 1.957 + 1.958 + STDMETHODIMP OnStatusChange(DWORD dwFlags) 1.959 + { 1.960 + return S_OK; 1.961 + } 1.962 + 1.963 + STDMETHODIMP OnAttrsChange(LONG acpStart, LONG acpEnd, ULONG cAttrs, 1.964 + const TS_ATTRID *paAttrs) 1.965 + { 1.966 + return S_OK; 1.967 + } 1.968 + 1.969 + STDMETHODIMP OnLockGranted(DWORD dwLockFlags); 1.970 + 1.971 + STDMETHODIMP OnStartEditTransaction(void) 1.972 + { 1.973 + return S_OK; 1.974 + } 1.975 + 1.976 + STDMETHODIMP OnEndEditTransaction(void) 1.977 + { 1.978 + return S_OK; 1.979 + } 1.980 +}; 1.981 + 1.982 +/****************************************************************************** 1.983 + * TSFDocumentMgrImpl 1.984 + ******************************************************************************/ 1.985 + 1.986 +class TSFDocumentMgrImpl : public ITfDocumentMgr 1.987 +{ 1.988 +private: 1.989 + ULONG mRefCnt; 1.990 + 1.991 +public: 1.992 + nsRefPtr<TSFMgrImpl> mMgr; 1.993 + nsRefPtr<ITextStoreACP> mStore; 1.994 + nsRefPtr<TSFContextImpl> mContextBase; 1.995 + nsRefPtr<TSFContextImpl> mContextTop; // XXX currently, we don't support this. 1.996 + 1.997 +public: 1.998 + TSFDocumentMgrImpl(TSFMgrImpl* aMgr) : 1.999 + mRefCnt(0), mMgr(aMgr) 1.1000 + { 1.1001 + } 1.1002 + 1.1003 + ~TSFDocumentMgrImpl() 1.1004 + { 1.1005 + } 1.1006 + 1.1007 +public: // IUnknown 1.1008 + 1.1009 + STDMETHODIMP QueryInterface(REFIID riid, void** ppUnk) 1.1010 + { 1.1011 + *ppUnk = nullptr; 1.1012 + if (IID_IUnknown == riid || IID_ITfDocumentMgr == riid) 1.1013 + *ppUnk = static_cast<ITfDocumentMgr*>(this); 1.1014 + if (*ppUnk) 1.1015 + AddRef(); 1.1016 + return *ppUnk ? S_OK : E_NOINTERFACE; 1.1017 + } 1.1018 + 1.1019 + STDMETHODIMP_(ULONG) AddRef(void) 1.1020 + { 1.1021 + return ++mRefCnt; 1.1022 + } 1.1023 + 1.1024 + STDMETHODIMP_(ULONG) Release(void); 1.1025 + 1.1026 +public: // ITfDocumentMgr 1.1027 + 1.1028 + STDMETHODIMP CreateContext(TfClientId tidOwner, DWORD dwFlags, 1.1029 + IUnknown *punk, ITfContext **ppic, 1.1030 + TfEditCookie *pecTextStore) 1.1031 + { 1.1032 + nsRefPtr<TSFContextImpl> context = new TSFContextImpl(this); 1.1033 + punk->QueryInterface(IID_ITextStoreACP, getter_AddRefs(mStore)); 1.1034 + NS_ENSURE_TRUE(mStore, E_FAIL); 1.1035 + HRESULT hr = 1.1036 + mStore->AdviseSink(IID_ITextStoreACPSink, 1.1037 + static_cast<ITextStoreACPSink*>(context.get()), 1.1038 + TS_AS_ALL_SINKS); 1.1039 + if (FAILED(hr)) mStore = nullptr; 1.1040 + NS_ENSURE_TRUE(SUCCEEDED(hr), E_FAIL); 1.1041 + (*ppic) = context; 1.1042 + (*ppic)->AddRef(); 1.1043 + *pecTextStore = 1; 1.1044 + return S_OK; 1.1045 + } 1.1046 + 1.1047 + STDMETHODIMP Push(ITfContext *pic) 1.1048 + { 1.1049 + if (mContextTop) { 1.1050 + NS_NOTREACHED("TSFDocumentMgrImpl::Push stack is already full"); 1.1051 + return E_FAIL; 1.1052 + } 1.1053 + if (mContextBase) { 1.1054 + NS_WARNING("TSFDocumentMgrImpl::Push additional context is pushed, but we don't support that yet."); 1.1055 + if (mContextBase == pic) { 1.1056 + NS_NOTREACHED("TSFDocumentMgrImpl::Push same context is pused again"); 1.1057 + return E_FAIL; 1.1058 + } 1.1059 + mContextTop = static_cast<TSFContextImpl*>(pic); 1.1060 + return S_OK; 1.1061 + } 1.1062 + mContextBase = static_cast<TSFContextImpl*>(pic); 1.1063 + return S_OK; 1.1064 + } 1.1065 + 1.1066 + STDMETHODIMP Pop(DWORD dwFlags) 1.1067 + { 1.1068 + if (!mStore) 1.1069 + return E_FAIL; 1.1070 + if (dwFlags == TF_POPF_ALL) { 1.1071 + NS_ENSURE_TRUE(mContextBase, E_FAIL); 1.1072 + mStore->UnadviseSink(static_cast<ITextStoreACPSink*>(mContextBase.get())); 1.1073 + mStore = nullptr; 1.1074 + mContextBase = nullptr; 1.1075 + mContextTop = nullptr; 1.1076 + return S_OK; 1.1077 + } 1.1078 + if (dwFlags == 0) { 1.1079 + if (!mContextTop) { 1.1080 + NS_NOTREACHED("TSFDocumentMgrImpl::Pop there is non-base context"); 1.1081 + return E_FAIL; 1.1082 + } 1.1083 + mContextTop = nullptr; 1.1084 + return S_OK; 1.1085 + } 1.1086 + NS_NOTREACHED("TSFDocumentMgrImpl::Pop invalid flag"); 1.1087 + return E_FAIL; 1.1088 + } 1.1089 + 1.1090 + STDMETHODIMP GetTop(ITfContext **ppic) 1.1091 + { 1.1092 + (*ppic) = mContextTop ? mContextTop : mContextBase; 1.1093 + if (*ppic) (*ppic)->AddRef(); 1.1094 + return S_OK; 1.1095 + } 1.1096 + 1.1097 + STDMETHODIMP GetBase(ITfContext **ppic) 1.1098 + { 1.1099 + (*ppic) = mContextBase; 1.1100 + if (*ppic) (*ppic)->AddRef(); 1.1101 + return S_OK; 1.1102 + } 1.1103 + 1.1104 + STDMETHODIMP EnumContexts(IEnumTfContexts **ppEnum) 1.1105 + { 1.1106 + NS_NOTREACHED("ITfDocumentMgr::EnumContexts"); 1.1107 + return E_NOTIMPL; 1.1108 + } 1.1109 + 1.1110 +}; 1.1111 + 1.1112 +/****************************************************************************** 1.1113 + * TSFMgrImpl 1.1114 + ******************************************************************************/ 1.1115 + 1.1116 +class TSFMgrImpl : public ITfThreadMgr, 1.1117 + public ITfDisplayAttributeMgr, public ITfCategoryMgr 1.1118 +{ 1.1119 +private: 1.1120 + ULONG mRefCnt; 1.1121 + 1.1122 +public: 1.1123 + nsRefPtr<TestApp> mTestApp; 1.1124 + TestApp::test_type mTest; 1.1125 + bool mDeactivated; 1.1126 + TSFDocumentMgrImpl* mFocusedDocument; // Must be raw pointer, but strong. 1.1127 + int32_t mFocusCount; 1.1128 + 1.1129 + TSFMgrImpl(TestApp* test) : mTestApp(test), mTest(nullptr), mRefCnt(0), 1.1130 + mDeactivated(false), mFocusedDocument(nullptr), mFocusCount(0) 1.1131 + { 1.1132 + } 1.1133 + 1.1134 + ~TSFMgrImpl() 1.1135 + { 1.1136 + } 1.1137 + 1.1138 +public: // IUnknown 1.1139 + 1.1140 + STDMETHODIMP QueryInterface(REFIID riid, void** ppUnk) 1.1141 + { 1.1142 + *ppUnk = nullptr; 1.1143 + if (IID_IUnknown == riid || IID_ITfThreadMgr == riid) 1.1144 + *ppUnk = static_cast<ITfThreadMgr*>(this); 1.1145 + else if (IID_ITfDisplayAttributeMgr == riid) 1.1146 + *ppUnk = static_cast<ITfDisplayAttributeMgr*>(this); 1.1147 + else if (IID_ITfCategoryMgr == riid) 1.1148 + *ppUnk = static_cast<ITfCategoryMgr*>(this); 1.1149 + if (*ppUnk) 1.1150 + AddRef(); 1.1151 + return *ppUnk ? S_OK : E_NOINTERFACE; 1.1152 + } 1.1153 + 1.1154 + STDMETHODIMP_(ULONG) AddRef(void) 1.1155 + { 1.1156 + return ++mRefCnt; 1.1157 + } 1.1158 + 1.1159 + STDMETHODIMP_(ULONG) Release(void) 1.1160 + { 1.1161 + if (--mRefCnt) return mRefCnt; 1.1162 + delete this; 1.1163 + return 0; 1.1164 + } 1.1165 + 1.1166 +public: // ITfThreadMgr 1.1167 + 1.1168 + STDMETHODIMP Activate(TfClientId *ptid) 1.1169 + { 1.1170 + *ptid = 1; 1.1171 + return S_OK; 1.1172 + } 1.1173 + 1.1174 + STDMETHODIMP Deactivate(void) 1.1175 + { 1.1176 + mDeactivated = true; 1.1177 + return S_OK; 1.1178 + } 1.1179 + 1.1180 + STDMETHODIMP CreateDocumentMgr(ITfDocumentMgr **ppdim) 1.1181 + { 1.1182 + nsRefPtr<TSFDocumentMgrImpl> docMgr = new TSFDocumentMgrImpl(this); 1.1183 + if (!docMgr) { 1.1184 + NS_NOTREACHED("TSFMgrImpl::CreateDocumentMgr (OOM)"); 1.1185 + return E_OUTOFMEMORY; 1.1186 + } 1.1187 + (*ppdim) = docMgr; 1.1188 + (*ppdim)->AddRef(); 1.1189 + return S_OK; 1.1190 + } 1.1191 + 1.1192 + STDMETHODIMP EnumDocumentMgrs(IEnumTfDocumentMgrs **ppEnum) 1.1193 + { 1.1194 + NS_NOTREACHED("ITfThreadMgr::EnumDocumentMgrs"); 1.1195 + return E_NOTIMPL; 1.1196 + } 1.1197 + 1.1198 + STDMETHODIMP GetFocus(ITfDocumentMgr **ppdimFocus) 1.1199 + { 1.1200 + (*ppdimFocus) = mFocusedDocument; 1.1201 + if (*ppdimFocus) (*ppdimFocus)->AddRef(); 1.1202 + return S_OK; 1.1203 + } 1.1204 + 1.1205 + STDMETHODIMP SetFocus(ITfDocumentMgr *pdimFocus) 1.1206 + { 1.1207 + if (!pdimFocus) { 1.1208 + NS_NOTREACHED("ITfThreadMgr::SetFocus must not be called with NULL"); 1.1209 + return E_FAIL; 1.1210 + } 1.1211 + mFocusCount++; 1.1212 + if (mFocusedDocument == pdimFocus) { 1.1213 + return S_OK; 1.1214 + } 1.1215 + mFocusedDocument = static_cast<TSFDocumentMgrImpl*>(pdimFocus); 1.1216 + mFocusedDocument->AddRef(); 1.1217 + return S_OK; 1.1218 + } 1.1219 + 1.1220 + STDMETHODIMP AssociateFocus(HWND hwnd, ITfDocumentMgr *pdimNew, 1.1221 + ITfDocumentMgr **ppdimPrev) 1.1222 + { 1.1223 + NS_NOTREACHED("ITfThreadMgr::AssociateFocus"); 1.1224 + return E_NOTIMPL; 1.1225 + } 1.1226 + 1.1227 + STDMETHODIMP IsThreadFocus(BOOL *pfThreadFocus) 1.1228 + { 1.1229 + *pfThreadFocus = TRUE; 1.1230 + return S_OK; 1.1231 + } 1.1232 + 1.1233 + STDMETHODIMP GetFunctionProvider(REFCLSID clsid, 1.1234 + ITfFunctionProvider **ppFuncProv) 1.1235 + { 1.1236 + NS_NOTREACHED("ITfThreadMgr::GetFunctionProvider"); 1.1237 + return E_NOTIMPL; 1.1238 + } 1.1239 + 1.1240 + STDMETHODIMP EnumFunctionProviders(IEnumTfFunctionProviders **ppEnum) 1.1241 + { 1.1242 + NS_NOTREACHED("ITfThreadMgr::EnumFunctionProviders"); 1.1243 + return E_NOTIMPL; 1.1244 + } 1.1245 + 1.1246 + STDMETHODIMP GetGlobalCompartment(ITfCompartmentMgr **ppCompMgr) 1.1247 + { 1.1248 + NS_NOTREACHED("ITfThreadMgr::GetGlobalCompartment"); 1.1249 + return E_NOTIMPL; 1.1250 + } 1.1251 + 1.1252 +public: // ITfCategoryMgr 1.1253 + 1.1254 + STDMETHODIMP RegisterCategory(REFCLSID rclsid, REFGUID rcatid, REFGUID rguid) 1.1255 + { 1.1256 + NS_NOTREACHED("ITfCategoryMgr::RegisterCategory"); 1.1257 + return E_NOTIMPL; 1.1258 + } 1.1259 + 1.1260 + STDMETHODIMP UnregisterCategory(REFCLSID rclsid, REFGUID rcatid, REFGUID rguid) 1.1261 + { 1.1262 + NS_NOTREACHED("ITfCategoryMgr::UnregisterCategory"); 1.1263 + return E_NOTIMPL; 1.1264 + } 1.1265 + 1.1266 + STDMETHODIMP EnumCategoriesInItem(REFGUID rguid, IEnumGUID **ppEnum) 1.1267 + { 1.1268 + NS_NOTREACHED("ITfCategoryMgr::EnumCategoriesInItem"); 1.1269 + return E_NOTIMPL; 1.1270 + } 1.1271 + 1.1272 + STDMETHODIMP EnumItemsInCategory(REFGUID rcatid, IEnumGUID **ppEnum) 1.1273 + { 1.1274 + NS_NOTREACHED("ITfCategoryMgr::EnumItemsInCategory"); 1.1275 + return E_NOTIMPL; 1.1276 + } 1.1277 + 1.1278 + STDMETHODIMP FindClosestCategory(REFGUID rguid, GUID *pcatid, 1.1279 + const GUID **ppcatidList, ULONG ulCount) 1.1280 + { 1.1281 + NS_NOTREACHED("ITfCategoryMgr::FindClosestCategory"); 1.1282 + return E_NOTIMPL; 1.1283 + } 1.1284 + 1.1285 + STDMETHODIMP RegisterGUIDDescription(REFCLSID rclsid, REFGUID rguid, 1.1286 + const WCHAR *pchDesc, ULONG cch) 1.1287 + { 1.1288 + NS_NOTREACHED("ITfCategoryMgr::RegisterGUIDDescription"); 1.1289 + return E_NOTIMPL; 1.1290 + } 1.1291 + 1.1292 + STDMETHODIMP UnregisterGUIDDescription(REFCLSID rclsid, REFGUID rguid) 1.1293 + { 1.1294 + NS_NOTREACHED("ITfCategoryMgr::UnregisterGUIDDescription"); 1.1295 + return E_NOTIMPL; 1.1296 + } 1.1297 + 1.1298 + STDMETHODIMP GetGUIDDescription(REFGUID rguid, BSTR *pbstrDesc) 1.1299 + { 1.1300 + NS_NOTREACHED("ITfCategoryMgr::GetGUIDDescription"); 1.1301 + return E_NOTIMPL; 1.1302 + } 1.1303 + 1.1304 + STDMETHODIMP RegisterGUIDDWORD(REFCLSID rclsid, REFGUID rguid, DWORD dw) 1.1305 + { 1.1306 + NS_NOTREACHED("ITfCategoryMgr::RegisterGUIDDWORD"); 1.1307 + return E_NOTIMPL; 1.1308 + } 1.1309 + 1.1310 + STDMETHODIMP UnregisterGUIDDWORD(REFCLSID rclsid, REFGUID rguid) 1.1311 + { 1.1312 + NS_NOTREACHED("ITfCategoryMgr::UnregisterGUIDDWORD"); 1.1313 + return E_NOTIMPL; 1.1314 + } 1.1315 + 1.1316 + STDMETHODIMP GetGUIDDWORD(REFGUID rguid, DWORD *pdw) 1.1317 + { 1.1318 + NS_NOTREACHED("ITfCategoryMgr::GetGUIDDWORD"); 1.1319 + return E_NOTIMPL; 1.1320 + } 1.1321 + 1.1322 + STDMETHODIMP RegisterGUID(REFGUID rguid, TfGuidAtom *pguidatom) 1.1323 + { 1.1324 + NS_NOTREACHED("ITfCategoryMgr::RegisterGUID"); 1.1325 + return E_NOTIMPL; 1.1326 + } 1.1327 + 1.1328 + STDMETHODIMP GetGUID(TfGuidAtom guidatom, GUID *pguid) 1.1329 + { 1.1330 + if (guidatom == GUID_ATOM_COMPOSING_SELECTION_ATTR) { 1.1331 + *pguid = GUID_COMPOSING_SELECTION_ATTR; 1.1332 + return S_OK; 1.1333 + } 1.1334 + NS_NOTREACHED("ITfCategoryMgr::GetGUID"); 1.1335 + return E_FAIL; 1.1336 + } 1.1337 + 1.1338 + STDMETHODIMP IsEqualTfGuidAtom(TfGuidAtom guidatom, REFGUID rguid, 1.1339 + BOOL *pfEqual) 1.1340 + { 1.1341 + NS_NOTREACHED("ITfCategoryMgr::IsEqualTfGuidAtom"); 1.1342 + return E_NOTIMPL; 1.1343 + } 1.1344 + 1.1345 +public: // ITfDisplayAttributeMgr 1.1346 + 1.1347 + STDMETHODIMP OnUpdateInfo() 1.1348 + { 1.1349 + NS_NOTREACHED("ITfDisplayAttributeMgr::OnUpdateInfo"); 1.1350 + return E_NOTIMPL; 1.1351 + } 1.1352 + 1.1353 + STDMETHODIMP EnumDisplayAttributeInfo(IEnumTfDisplayAttributeInfo **ppEnum) 1.1354 + { 1.1355 + NS_NOTREACHED("ITfDisplayAttributeMgr::EnumDisplayAttributeInfo"); 1.1356 + return E_NOTIMPL; 1.1357 + } 1.1358 + 1.1359 + STDMETHODIMP GetDisplayAttributeInfo(REFGUID guid, 1.1360 + ITfDisplayAttributeInfo **ppInfo, 1.1361 + CLSID *pclsidOwner) 1.1362 + { 1.1363 + NS_ENSURE_TRUE(ppInfo, E_INVALIDARG); 1.1364 + NS_ENSURE_TRUE(!pclsidOwner, E_INVALIDARG); 1.1365 + if (guid == GUID_COMPOSING_SELECTION_ATTR) { 1.1366 + (*ppInfo) = new TSFDispAttrInfoImpl(guid); 1.1367 + (*ppInfo)->AddRef(); 1.1368 + return S_OK; 1.1369 + } 1.1370 + NS_NOTREACHED("ITfDisplayAttributeMgr::GetDisplayAttributeInfo"); 1.1371 + return E_FAIL; 1.1372 + } 1.1373 + 1.1374 +public: 1.1375 + 1.1376 + ITextStoreACP* GetFocusedStore() 1.1377 + { 1.1378 + return mFocusedDocument ? mFocusedDocument->mStore : nullptr; 1.1379 + } 1.1380 + 1.1381 + TSFContextImpl* GetFocusedContext() 1.1382 + { 1.1383 + return mFocusedDocument ? mFocusedDocument->mContextBase : nullptr; 1.1384 + } 1.1385 + 1.1386 + TSFAttrPropImpl* GetFocusedAttrProp() 1.1387 + { 1.1388 + TSFContextImpl* context = GetFocusedContext(); 1.1389 + return context ? context->mAttrProp : nullptr; 1.1390 + } 1.1391 + 1.1392 +}; 1.1393 + 1.1394 +STDMETHODIMP 1.1395 +TSFContextImpl::OnLockGranted(DWORD dwLockFlags) 1.1396 +{ 1.1397 + // If we have a test, run it 1.1398 + if (mDocMgr->mMgr->mTest && 1.1399 + !((*mDocMgr->mMgr->mTestApp).*(mDocMgr->mMgr->mTest))()) 1.1400 + return S_FALSE; 1.1401 + return S_OK; 1.1402 +} 1.1403 + 1.1404 + 1.1405 +STDMETHODIMP_(ULONG) 1.1406 +TSFDocumentMgrImpl::Release(void) 1.1407 +{ 1.1408 + --mRefCnt; 1.1409 + if (mRefCnt == 1 && mMgr->mFocusedDocument == this) { 1.1410 + mMgr->mFocusedDocument = nullptr; 1.1411 + --mRefCnt; 1.1412 + } 1.1413 + if (mRefCnt) return mRefCnt; 1.1414 + delete this; 1.1415 + return 0; 1.1416 +} 1.1417 + 1.1418 +NS_IMPL_ISUPPORTS(TestApp, nsIWebProgressListener, 1.1419 + nsISupportsWeakReference) 1.1420 + 1.1421 +nsresult 1.1422 +TestApp::Run(void) 1.1423 +{ 1.1424 + // Create a test window 1.1425 + // We need a full-fledged window to test for TSF functionality 1.1426 + nsresult rv; 1.1427 + mAppShell = do_GetService(kAppShellCID); 1.1428 + NS_ENSURE_TRUE(mAppShell, NS_ERROR_UNEXPECTED); 1.1429 + 1.1430 + nsCOMPtr<nsIAppShellService> appShellService( 1.1431 + do_GetService(NS_APPSHELLSERVICE_CONTRACTID)); 1.1432 + NS_ENSURE_TRUE(appShellService, NS_ERROR_UNEXPECTED); 1.1433 + 1.1434 + nsCOMPtr<nsIURI> uri; 1.1435 + rv = NS_NewURI(getter_AddRefs(uri), "about:blank", nullptr); 1.1436 + NS_ENSURE_SUCCESS(rv, rv); 1.1437 + 1.1438 + rv = appShellService->CreateTopLevelWindow(nullptr, uri, 1.1439 + nsIWebBrowserChrome::CHROME_DEFAULT, 1.1440 + 800 /*nsIAppShellService::SIZE_TO_CONTENT*/, 1.1441 + 600 /*nsIAppShellService::SIZE_TO_CONTENT*/, 1.1442 + getter_AddRefs(mWindow)); 1.1443 + NS_ENSURE_SUCCESS(rv, rv); 1.1444 + 1.1445 + nsCOMPtr<nsIDocShell> docShell; 1.1446 + rv = mWindow->GetDocShell(getter_AddRefs(docShell)); 1.1447 + NS_ENSURE_TRUE(docShell, NS_ERROR_UNEXPECTED); 1.1448 + nsCOMPtr<nsIWebProgress> progress(do_GetInterface(docShell)); 1.1449 + NS_ENSURE_TRUE(progress, NS_ERROR_UNEXPECTED); 1.1450 + rv = progress->AddProgressListener(this, 1.1451 + nsIWebProgress::NOTIFY_STATE_WINDOW | 1.1452 + nsIWebProgress::NOTIFY_STATUS); 1.1453 + NS_ENSURE_SUCCESS(rv, rv); 1.1454 + 1.1455 + mAppShell->Run(); 1.1456 + return NS_OK; 1.1457 +} 1.1458 + 1.1459 +bool 1.1460 +TestApp::CheckFailed(void) 1.1461 +{ 1.1462 + // All windows should be closed by now 1.1463 + if (mMgr && !mMgr->mDeactivated) { 1.1464 + fail("TSF not terminated properly"); 1.1465 + mFailed = true; 1.1466 + } 1.1467 + mMgr = nullptr; 1.1468 + return mFailed; 1.1469 +} 1.1470 + 1.1471 +nsresult 1.1472 +TestApp::Init(void) 1.1473 +{ 1.1474 + // Replace TSF manager pointer, category manager pointer and display 1.1475 + // attribute manager pointer. 1.1476 + nsCOMPtr<nsIBaseWindow> baseWindow(do_QueryInterface(mWindow)); 1.1477 + NS_ENSURE_TRUE(baseWindow, NS_ERROR_UNEXPECTED); 1.1478 + nsCOMPtr<nsIWidget> widget; 1.1479 + nsresult rv = baseWindow->GetMainWidget(getter_AddRefs(widget)); 1.1480 + NS_ENSURE_TRUE(widget, NS_ERROR_UNEXPECTED); 1.1481 + 1.1482 + ITfThreadMgr **threadMgr = reinterpret_cast<ITfThreadMgr**>( 1.1483 + widget->GetNativeData(NS_NATIVE_TSF_THREAD_MGR)); 1.1484 + if (!threadMgr) { 1.1485 + fail("nsIWidget::GetNativeData(NS_NATIVE_TSF_THREAD_MGR) not supported"); 1.1486 + return NS_ERROR_FAILURE; 1.1487 + } 1.1488 + if (*threadMgr) { 1.1489 + (*threadMgr)->Deactivate(); 1.1490 + (*threadMgr)->Release(); 1.1491 + (*threadMgr) = nullptr; 1.1492 + } else { 1.1493 + // This is only for information. The test does not need TSF to run. 1.1494 + printf("TSF not initialized properly (TSF is not enabled/installed?)\n"); 1.1495 + } 1.1496 + 1.1497 + ITfCategoryMgr **catMgr = reinterpret_cast<ITfCategoryMgr**>( 1.1498 + widget->GetNativeData(NS_NATIVE_TSF_CATEGORY_MGR)); 1.1499 + if (*catMgr) { 1.1500 + (*catMgr)->Release(); 1.1501 + (*catMgr) = nullptr; 1.1502 + } 1.1503 + ITfDisplayAttributeMgr **daMgr = reinterpret_cast<ITfDisplayAttributeMgr**>( 1.1504 + widget->GetNativeData(NS_NATIVE_TSF_DISPLAY_ATTR_MGR)); 1.1505 + if (*daMgr) { 1.1506 + (*daMgr)->Release(); 1.1507 + (*daMgr) = nullptr; 1.1508 + } 1.1509 + 1.1510 + mMgr = new TSFMgrImpl(this); 1.1511 + if (!mMgr) { 1.1512 + return NS_ERROR_OUT_OF_MEMORY; 1.1513 + } 1.1514 + (*threadMgr) = mMgr; 1.1515 + (*threadMgr)->AddRef(); 1.1516 + (*catMgr) = mMgr; 1.1517 + (*catMgr)->AddRef(); 1.1518 + (*daMgr) = mMgr; 1.1519 + (*daMgr)->AddRef(); 1.1520 + 1.1521 + // Apply the change 1.1522 + reinterpret_cast<ITfThreadMgr**>( 1.1523 + widget->GetNativeData(NS_NATIVE_TSF_THREAD_MGR)); 1.1524 + 1.1525 + // Create a couple of text boxes for testing 1.1526 + nsCOMPtr<nsIDOMWindow> win(do_GetInterface(mWindow)); 1.1527 + NS_ENSURE_TRUE(win, NS_ERROR_UNEXPECTED); 1.1528 + nsCOMPtr<nsIDOMDocument> document; 1.1529 + rv = win->GetDocument(getter_AddRefs(document)); 1.1530 + NS_ENSURE_TRUE(document, NS_ERROR_UNEXPECTED); 1.1531 + nsCOMPtr<nsIDOMHTMLDocument> htmlDoc(do_QueryInterface(document)); 1.1532 + NS_ENSURE_TRUE(htmlDoc, NS_ERROR_UNEXPECTED); 1.1533 + nsCOMPtr<nsIDOMHTMLElement> htmlBody; 1.1534 + rv = htmlDoc->GetBody(getter_AddRefs(htmlBody)); 1.1535 + NS_ENSURE_TRUE(htmlBody, NS_ERROR_UNEXPECTED); 1.1536 + 1.1537 + nsCOMPtr<nsIDOMElement> form; 1.1538 + rv = htmlDoc->CreateElementNS( 1.1539 + NS_LITERAL_STRING("http://www.w3.org/1999/xhtml"), 1.1540 + NS_LITERAL_STRING("form"), 1.1541 + getter_AddRefs(form)); 1.1542 + nsCOMPtr<nsIDOMElement> elem; 1.1543 + rv = htmlDoc->CreateElementNS( 1.1544 + NS_LITERAL_STRING("http://www.w3.org/1999/xhtml"), 1.1545 + NS_LITERAL_STRING("input"), 1.1546 + getter_AddRefs(elem)); 1.1547 + NS_ENSURE_SUCCESS(rv, rv); 1.1548 + elem->SetAttribute(NS_LITERAL_STRING("type"), 1.1549 + NS_LITERAL_STRING("text")); 1.1550 + mInput = do_QueryInterface(elem); 1.1551 + NS_ENSURE_TRUE(mInput, NS_ERROR_UNEXPECTED); 1.1552 + rv = htmlDoc->CreateElementNS( 1.1553 + NS_LITERAL_STRING("http://www.w3.org/1999/xhtml"), 1.1554 + NS_LITERAL_STRING("textarea"), 1.1555 + getter_AddRefs(elem)); 1.1556 + NS_ENSURE_SUCCESS(rv, rv); 1.1557 + mTextArea = do_QueryInterface(elem); 1.1558 + NS_ENSURE_TRUE(mTextArea, NS_ERROR_UNEXPECTED); 1.1559 + rv = htmlDoc->CreateElementNS( 1.1560 + NS_LITERAL_STRING("http://www.w3.org/1999/xhtml"), 1.1561 + NS_LITERAL_STRING("input"), 1.1562 + getter_AddRefs(elem)); 1.1563 + NS_ENSURE_SUCCESS(rv, rv); 1.1564 + elem->SetAttribute(NS_LITERAL_STRING("type"), 1.1565 + NS_LITERAL_STRING("button")); 1.1566 + mButton = do_QueryInterface(elem); 1.1567 + NS_ENSURE_TRUE(mButton, NS_ERROR_UNEXPECTED); 1.1568 + 1.1569 + nsCOMPtr<nsIDOMNode> node; 1.1570 + rv = form->AppendChild(mInput, getter_AddRefs(node)); 1.1571 + NS_ENSURE_SUCCESS(rv, rv); 1.1572 + rv = form->AppendChild(mTextArea, getter_AddRefs(node)); 1.1573 + NS_ENSURE_SUCCESS(rv, rv); 1.1574 + rv = form->AppendChild(mButton, getter_AddRefs(node)); 1.1575 + NS_ENSURE_SUCCESS(rv, rv); 1.1576 + rv = htmlBody->AppendChild(form, getter_AddRefs(node)); 1.1577 + NS_ENSURE_SUCCESS(rv, rv); 1.1578 + 1.1579 + // set a background color manually, 1.1580 + // otherwise the window might be transparent 1.1581 + static_cast<HTMLBodyElement*>(htmlBody)-> 1.1582 + SetBgColor(NS_LITERAL_STRING("white")); 1.1583 + 1.1584 + widget->Show(true); 1.1585 + widget->SetFocus(); 1.1586 + return NS_OK; 1.1587 +} 1.1588 + 1.1589 +nsresult 1.1590 +TestApp::Term(void) 1.1591 +{ 1.1592 + mCurrentNode = nullptr; 1.1593 + mInput = nullptr; 1.1594 + mTextArea = nullptr; 1.1595 + mButton = nullptr; 1.1596 + 1.1597 + nsCOMPtr<nsIDOMWindow> win(do_GetInterface(mWindow)); 1.1598 + if (win) 1.1599 + win->Close(); 1.1600 + win = nullptr; 1.1601 + mWindow = nullptr; 1.1602 + 1.1603 + if (mAppShell) 1.1604 + mAppShell->Exit(); 1.1605 + mAppShell = nullptr; 1.1606 + return NS_OK; 1.1607 +} 1.1608 + 1.1609 +bool 1.1610 +TestApp::RunTest(test_type aTest, bool aLock) 1.1611 +{ 1.1612 + bool succeeded; 1.1613 + if (aLock && mMgr && mMgr->GetFocusedStore()) { 1.1614 + mMgr->mTest = aTest; 1.1615 + HRESULT hr = E_FAIL; 1.1616 + mMgr->GetFocusedStore()->RequestLock(TS_LF_READWRITE | TS_LF_SYNC, &hr); 1.1617 + succeeded = hr == S_OK; 1.1618 + } else { 1.1619 + succeeded = (this->*aTest)(); 1.1620 + } 1.1621 + mFailed |= !succeeded; 1.1622 + return succeeded; 1.1623 +} 1.1624 + 1.1625 +NS_IMETHODIMP 1.1626 +TestApp::OnStateChange(nsIWebProgress *aWebProgress, 1.1627 + nsIRequest *aRequest, 1.1628 + uint32_t aStateFlags, 1.1629 + nsresult aStatus) 1.1630 +{ 1.1631 + NS_ASSERTION(aStateFlags & nsIWebProgressListener::STATE_IS_WINDOW && 1.1632 + aStateFlags & nsIWebProgressListener::STATE_STOP, "wrong state"); 1.1633 + if (NS_SUCCEEDED(Init())) { 1.1634 + mCurrentNode = mTextArea; 1.1635 + mTextArea->Focus(); 1.1636 + 1.1637 + if (RunTest(&TestApp::TestEditMessages)) 1.1638 + passed("TestEditMessages"); 1.1639 + if (RunTest(&TestApp::TestScrollMessages)) 1.1640 + passed("TestScrollMessages"); 1.1641 + 1.1642 + if (RunTest(&TestApp::TestFocus, false)) 1.1643 + passed("TestFocus"); 1.1644 + 1.1645 + mCurrentNode = mInput; 1.1646 + mInput->Focus(); 1.1647 + if (mMgr->GetFocusedStore()) { 1.1648 + if (RunTest(&TestApp::TestClustering)) 1.1649 + passed("TestClustering"); 1.1650 + } else { 1.1651 + fail("no text store (clustering)"); 1.1652 + mFailed = true; 1.1653 + } 1.1654 + 1.1655 + printf("Testing TSF support in text input element...\n"); 1.1656 + mCurrentNode = mInput; 1.1657 + mTestString = NS_LITERAL_STRING( 1.1658 + "This is a test of the Text Services Framework implementation."); 1.1659 + mInput->SetValue(mTestString); 1.1660 + mInput->Focus(); 1.1661 + if (mMgr->GetFocusedStore()) { 1.1662 + if (RunTest(&TestApp::TestSelection)) 1.1663 + passed("TestSelection (input)"); 1.1664 + if (RunTest(&TestApp::TestText)) 1.1665 + passed("TestText (input)"); 1.1666 + if (RunTest(&TestApp::TestExtents)) 1.1667 + passed("TestExtents (input)"); 1.1668 + if (RunTest(&TestApp::TestComposition)) 1.1669 + passed("TestComposition (input)"); 1.1670 + if (RunTest(&TestApp::TestNotification, false)) 1.1671 + passed("TestNotification (input)"); 1.1672 + } else { 1.1673 + fail("no text store (input)"); 1.1674 + mFailed = true; 1.1675 + } 1.1676 + 1.1677 + printf("Testing TSF support in textarea element...\n"); 1.1678 + mCurrentNode = mTextArea; 1.1679 + mTestString = NS_LITERAL_STRING( 1.1680 + "This is a test of the\r\nText Services Framework\r\nimplementation."); 1.1681 + mTextArea->SetValue(mTestString); 1.1682 + mTextArea->Focus(); 1.1683 + if (mMgr->GetFocusedStore()) { 1.1684 + if (RunTest(&TestApp::TestSelection)) 1.1685 + passed("TestSelection (textarea)"); 1.1686 + if (RunTest(&TestApp::TestText)) 1.1687 + passed("TestText (textarea)"); 1.1688 + if (RunTest(&TestApp::TestExtents)) 1.1689 + passed("TestExtents (textarea)"); 1.1690 + if (RunTest(&TestApp::TestComposition)) 1.1691 + passed("TestComposition (textarea)"); 1.1692 + if (RunTest(&TestApp::TestNotification, false)) 1.1693 + passed("TestNotification (textarea)"); 1.1694 + } else { 1.1695 + fail("no text store (textarea)"); 1.1696 + mFailed = true; 1.1697 + } 1.1698 + } else { 1.1699 + fail("initialization"); 1.1700 + mFailed = true; 1.1701 + } 1.1702 + Term(); 1.1703 + return NS_OK; 1.1704 +} 1.1705 + 1.1706 +bool 1.1707 +TestApp::TestFocus(void) 1.1708 +{ 1.1709 + uint32_t focus = mMgr->mFocusCount; 1.1710 + nsresult rv; 1.1711 + 1.1712 + /* If these fail the cause is probably one or more of: 1.1713 + * - nsIMEStateManager::OnTextStateFocus not called by nsEventStateManager 1.1714 + * - nsIMEStateManager::OnTextStateBlur not called by nsEventStateManager 1.1715 + * - nsWindow::OnIMEFocusChange (nsIWidget) not called by nsIMEStateManager 1.1716 + * - nsTextStore::Create/Focus/Destroy not called by nsWindow 1.1717 + * - ITfThreadMgr::CreateDocumentMgr/SetFocus not called by nsTextStore 1.1718 + * - ITfDocumentMgr::CreateContext/Push not called by nsTextStore 1.1719 + */ 1.1720 + 1.1721 + rv = mInput->Focus(); 1.1722 + if (!(NS_SUCCEEDED(rv) && 1.1723 + mMgr->mFocusedDocument && 1.1724 + mMgr->mFocusCount - focus == 1 && 1.1725 + mMgr->GetFocusedStore())) { 1.1726 + fail("TestFocus: document focus was not set"); 1.1727 + return false; 1.1728 + } 1.1729 + 1.1730 + rv = mTextArea->Focus(); 1.1731 + if (!(NS_SUCCEEDED(rv) && 1.1732 + mMgr->mFocusedDocument && 1.1733 + mMgr->mFocusCount - focus == 2 && 1.1734 + mMgr->GetFocusedStore())) { 1.1735 + fail("TestFocus: document focus was not changed"); 1.1736 + return false; 1.1737 + } 1.1738 + 1.1739 + rv = mButton->Focus(); 1.1740 + if (!(NS_SUCCEEDED(rv) && 1.1741 + !mMgr->mFocusedDocument && 1.1742 + mMgr->mFocusCount - focus == 2 && 1.1743 + !mMgr->GetFocusedStore())) { 1.1744 + fail("TestFocus: document focus was changed"); 1.1745 + return false; 1.1746 + } 1.1747 + return true; 1.1748 +} 1.1749 + 1.1750 +bool 1.1751 +TestApp::TestClustering(void) 1.1752 +{ 1.1753 + // Text for testing 1.1754 + const uint32_t STRING_LENGTH = 2; 1.1755 + char16_t string[3]; 1.1756 + string[0] = 'e'; 1.1757 + string[1] = 0x0301; // U+0301 'acute accent' 1.1758 + string[2] = nullptr; 1.1759 + 1.1760 + if (!mMgr->GetFocusedStore()) { 1.1761 + fail("TestClustering: GetFocusedStore returns null #1"); 1.1762 + return false; 1.1763 + } 1.1764 + 1.1765 + // Replace entire string with our string 1.1766 + TS_TEXTCHANGE textChange; 1.1767 + HRESULT hr = 1.1768 + mMgr->GetFocusedStore()->SetText(0, 0, -1, string, STRING_LENGTH, 1.1769 + &textChange); 1.1770 + if (!(SUCCEEDED(hr) && 1.1771 + 0 == textChange.acpStart && 1.1772 + STRING_LENGTH == textChange.acpNewEnd)) { 1.1773 + fail("TestClustering: SetText"); 1.1774 + return false; 1.1775 + } 1.1776 + 1.1777 + TsViewCookie view; 1.1778 + RECT rectLetter, rectAccent, rectWhole, rectCombined; 1.1779 + BOOL clipped, nonEmpty; 1.1780 + 1.1781 + if (!mMgr->GetFocusedStore()) { 1.1782 + fail("TestClustering: GetFocusedStore returns null #2"); 1.1783 + return false; 1.1784 + } 1.1785 + 1.1786 + hr = mMgr->GetFocusedStore()->GetActiveView(&view); 1.1787 + if (!(SUCCEEDED(hr))) { 1.1788 + fail("TestClustering: GetActiveView"); 1.1789 + return false; 1.1790 + } 1.1791 + 1.1792 + if (!mMgr->GetFocusedStore()) { 1.1793 + fail("TestClustering: GetFocusedStore returns null #3"); 1.1794 + return false; 1.1795 + } 1.1796 + 1.1797 + // Get rect of first char (the letter) 1.1798 + hr = mMgr->GetFocusedStore()->GetTextExt(view, 0, STRING_LENGTH / 2, 1.1799 + &rectLetter, &clipped); 1.1800 + if (!(SUCCEEDED(hr))) { 1.1801 + fail("TestClustering: GetTextExt (letter)"); 1.1802 + return false; 1.1803 + } 1.1804 + 1.1805 + if (!mMgr->GetFocusedStore()) { 1.1806 + fail("TestClustering: GetFocusedStore returns null #4"); 1.1807 + return false; 1.1808 + } 1.1809 + 1.1810 + // Get rect of second char (the accent) 1.1811 + hr = mMgr->GetFocusedStore()->GetTextExt(view, STRING_LENGTH / 2, 1.1812 + STRING_LENGTH, 1.1813 + &rectAccent, &clipped); 1.1814 + if (!(SUCCEEDED(hr))) { 1.1815 + fail("TestClustering: GetTextExt (accent)"); 1.1816 + return false; 1.1817 + } 1.1818 + 1.1819 + if (!mMgr->GetFocusedStore()) { 1.1820 + fail("TestClustering: GetFocusedStore returns null #5"); 1.1821 + return false; 1.1822 + } 1.1823 + 1.1824 + // Get rect of combined char 1.1825 + hr = mMgr->GetFocusedStore()->GetTextExt(view, 0, STRING_LENGTH, 1.1826 + &rectWhole, &clipped); 1.1827 + if (!(SUCCEEDED(hr))) { 1.1828 + fail("TestClustering: GetTextExt (whole)"); 1.1829 + return false; 1.1830 + } 1.1831 + 1.1832 + nonEmpty = ::UnionRect(&rectCombined, &rectLetter, &rectAccent); 1.1833 + if (!(nonEmpty && 1.1834 + ::EqualRect(&rectCombined, &rectWhole))) { 1.1835 + fail("TestClustering: unexpected combined rect"); 1.1836 + return false; 1.1837 + } 1.1838 + return true; 1.1839 +} 1.1840 + 1.1841 +bool 1.1842 +TestApp::TestSelectionInternal(char* aTestName, 1.1843 + LONG aStart, 1.1844 + LONG aEnd, 1.1845 + TsActiveSelEnd aSelEnd) 1.1846 +{ 1.1847 + bool succeeded = true, continueTest = true; 1.1848 + TS_SELECTION_ACP sel, testSel; 1.1849 + ULONG selFetched; 1.1850 + 1.1851 + if (!mMgr->GetFocusedStore()) { 1.1852 + fail("TestSelectionInternal: GetFocusedStore returns null #1"); 1.1853 + return false; 1.1854 + } 1.1855 + 1.1856 + sel.acpStart = aStart; 1.1857 + sel.acpEnd = aEnd; 1.1858 + sel.style.ase = aSelEnd; 1.1859 + sel.style.fInterimChar = FALSE; 1.1860 + HRESULT hr = mMgr->GetFocusedStore()->SetSelection(1, &sel); 1.1861 + if (!(SUCCEEDED(hr))) { 1.1862 + fail("TestSelection: SetSelection (%s)", aTestName); 1.1863 + continueTest = succeeded = false; 1.1864 + } 1.1865 + 1.1866 + if (continueTest) { 1.1867 + if (!mMgr->GetFocusedStore()) { 1.1868 + fail("TestSelectionInternal: GetFocusedStore returns null #2"); 1.1869 + return false; 1.1870 + } 1.1871 + 1.1872 + hr = mMgr->GetFocusedStore()->GetSelection(TS_DEFAULT_SELECTION, 1, 1.1873 + &testSel, &selFetched); 1.1874 + if (!(SUCCEEDED(hr) && 1.1875 + selFetched == 1 && 1.1876 + !memcmp(&sel, &testSel, sizeof(sel)))) { 1.1877 + fail("TestSelection: unexpected GetSelection result (%s)", aTestName); 1.1878 + succeeded = false; 1.1879 + } 1.1880 + } 1.1881 + return succeeded; 1.1882 +} 1.1883 + 1.1884 +bool 1.1885 +TestApp::TestSelection(void) 1.1886 +{ 1.1887 + bool succeeded = true; 1.1888 + 1.1889 + /* If these fail the cause is probably one or more of: 1.1890 + * nsTextStore::GetSelection not sending NS_QUERY_SELECTED_TEXT 1.1891 + * NS_QUERY_SELECTED_TEXT not handled by ContentEventHandler 1.1892 + * Bug in NS_QUERY_SELECTED_TEXT handler 1.1893 + * nsTextStore::SetSelection not sending NS_SELECTION_SET 1.1894 + * NS_SELECTION_SET not handled by ContentEventHandler 1.1895 + * Bug in NS_SELECTION_SET handler 1.1896 + */ 1.1897 + 1.1898 + TS_SELECTION_ACP testSel; 1.1899 + ULONG selFetched; 1.1900 + 1.1901 + if (!mMgr->GetFocusedStore()) { 1.1902 + fail("TestSelection: GetFocusedStore returns null"); 1.1903 + return false; 1.1904 + } 1.1905 + 1.1906 + HRESULT hr = 1.1907 + mMgr->GetFocusedStore()->GetSelection(0, 1, &testSel, &selFetched); 1.1908 + if (!(SUCCEEDED(hr) && 1.1909 + selFetched == 1)) { 1.1910 + fail("TestSelection: GetSelection"); 1.1911 + succeeded = false; 1.1912 + } 1.1913 + 1.1914 + const LONG SELECTION1_START = 0; 1.1915 + const LONG SELECTION1_END = mTestString.Length(); 1.1916 + const TsActiveSelEnd SELECTION1_SELEND = TS_AE_END; 1.1917 + 1.1918 + if (!TestSelectionInternal("normal", 1.1919 + SELECTION1_START, 1.1920 + SELECTION1_END, 1.1921 + SELECTION1_SELEND)) { 1.1922 + succeeded = false; 1.1923 + } 1.1924 + 1.1925 + const LONG SELECTION2_START = mTestString.Length() / 2; 1.1926 + const LONG SELECTION2_END = SELECTION2_START; 1.1927 + const TsActiveSelEnd SELECTION2_SELEND = TS_AE_END; 1.1928 + 1.1929 + if (!TestSelectionInternal("collapsed", 1.1930 + SELECTION2_START, 1.1931 + SELECTION2_END, 1.1932 + SELECTION2_SELEND)) { 1.1933 + succeeded = false; 1.1934 + } 1.1935 + 1.1936 + const LONG SELECTION3_START = 12; 1.1937 + const LONG SELECTION3_END = mTestString.Length() - 20; 1.1938 + const TsActiveSelEnd SELECTION3_SELEND = TS_AE_START; 1.1939 + 1.1940 + if (!TestSelectionInternal("reversed", 1.1941 + SELECTION3_START, 1.1942 + SELECTION3_END, 1.1943 + SELECTION3_SELEND)) { 1.1944 + succeeded = false; 1.1945 + } 1.1946 + return succeeded; 1.1947 +} 1.1948 + 1.1949 +bool 1.1950 +TestApp::TestText(void) 1.1951 +{ 1.1952 + const uint32_t BUFFER_SIZE = (0x100); 1.1953 + const uint32_t RUNINFO_SIZE = (0x10); 1.1954 + 1.1955 + bool succeeded = true, continueTest; 1.1956 + char16_t buffer[BUFFER_SIZE]; 1.1957 + TS_RUNINFO runInfo[RUNINFO_SIZE]; 1.1958 + ULONG bufferRet, runInfoRet; 1.1959 + LONG acpRet, acpCurrent; 1.1960 + TS_TEXTCHANGE textChange; 1.1961 + HRESULT hr; 1.1962 + 1.1963 + /* If these fail the cause is probably one or more of: 1.1964 + * nsTextStore::GetText not sending NS_QUERY_TEXT_CONTENT 1.1965 + * NS_QUERY_TEXT_CONTENT not handled by ContentEventHandler 1.1966 + * Bug in NS_QUERY_TEXT_CONTENT handler 1.1967 + * nsTextStore::SetText not calling SetSelection or InsertTextAtSelection 1.1968 + * Bug in SetSelection or InsertTextAtSelection 1.1969 + * NS_SELECTION_SET bug or NS_COMPOSITION_* / NS_TEXT_TEXT bug 1.1970 + */ 1.1971 + 1.1972 + if (!mMgr->GetFocusedStore()) { 1.1973 + fail("TestText: GetFocusedStore returns null #1"); 1.1974 + return false; 1.1975 + } 1.1976 + 1.1977 + // Get all text 1.1978 + hr = mMgr->GetFocusedStore()->GetText(0, -1, buffer, BUFFER_SIZE, &bufferRet, 1.1979 + runInfo, RUNINFO_SIZE, &runInfoRet, 1.1980 + &acpRet); 1.1981 + if (!(SUCCEEDED(hr) && 1.1982 + bufferRet <= mTestString.Length() && 1.1983 + !wcsncmp(mTestString.get(), buffer, bufferRet) && 1.1984 + acpRet == LONG(bufferRet) && 1.1985 + runInfoRet > 0)) { 1.1986 + fail("TestText: GetText 1"); 1.1987 + succeeded = false; 1.1988 + } 1.1989 + 1.1990 + 1.1991 + if (!mMgr->GetFocusedStore()) { 1.1992 + fail("TestText: GetFocusedStore returns null #2"); 1.1993 + return false; 1.1994 + } 1.1995 + 1.1996 + // Get text from GETTEXT2_START to GETTEXT2_END 1.1997 + const uint32_t GETTEXT2_START = (18); 1.1998 + const uint32_t GETTEXT2_END = (mTestString.Length() - 16); 1.1999 + const uint32_t GETTEXT2_BUFFER_SIZE = (0x10); 1.2000 + 1.2001 + hr = mMgr->GetFocusedStore()->GetText(GETTEXT2_START, GETTEXT2_END, 1.2002 + buffer, GETTEXT2_BUFFER_SIZE, 1.2003 + &bufferRet, runInfo, RUNINFO_SIZE, 1.2004 + &runInfoRet, &acpRet); 1.2005 + if (!(SUCCEEDED(hr) && 1.2006 + bufferRet <= GETTEXT2_BUFFER_SIZE && 1.2007 + !wcsncmp(mTestString.get() + GETTEXT2_START, buffer, bufferRet) && 1.2008 + acpRet == LONG(bufferRet) + GETTEXT2_START && 1.2009 + runInfoRet > 0)) { 1.2010 + fail("TestText: GetText 2"); 1.2011 + succeeded = false; 1.2012 + } 1.2013 + 1.2014 + 1.2015 + if (!mMgr->GetFocusedStore()) { 1.2016 + fail("TestText: GetFocusedStore returns null #3"); 1.2017 + return false; 1.2018 + } 1.2019 + 1.2020 + // Replace text from SETTEXT1_START to SETTEXT1_END with insertString 1.2021 + const uint32_t SETTEXT1_START = (8); 1.2022 + const uint32_t SETTEXT1_TAIL_LENGTH = (40); 1.2023 + const uint32_t SETTEXT1_END = (mTestString.Length() - 1.2024 + SETTEXT1_TAIL_LENGTH); 1.2025 + NS_NAMED_LITERAL_STRING(insertString, "(Inserted string)"); 1.2026 + 1.2027 + continueTest = true; 1.2028 + hr = mMgr->GetFocusedStore()->SetText(0, SETTEXT1_START, SETTEXT1_END, 1.2029 + insertString.get(), 1.2030 + insertString.Length(), &textChange); 1.2031 + if (!(SUCCEEDED(hr) && 1.2032 + textChange.acpStart == SETTEXT1_START && 1.2033 + textChange.acpOldEnd == LONG(SETTEXT1_END) && 1.2034 + textChange.acpNewEnd == LONG(SETTEXT1_START + 1.2035 + insertString.Length()))) { 1.2036 + fail("TestText: SetText 1"); 1.2037 + continueTest = succeeded = false; 1.2038 + } 1.2039 + 1.2040 + const uint32_t SETTEXT1_FINAL_LENGTH = (SETTEXT1_START + 1.2041 + SETTEXT1_TAIL_LENGTH + 1.2042 + insertString.Length()); 1.2043 + 1.2044 + if (continueTest) { 1.2045 + acpCurrent = 0; 1.2046 + while (acpCurrent < LONG(SETTEXT1_FINAL_LENGTH)) { 1.2047 + if (!mMgr->GetFocusedStore()) { 1.2048 + fail("TestText: GetFocusedStore returns null #4"); 1.2049 + return false; 1.2050 + } 1.2051 + 1.2052 + hr = mMgr->GetFocusedStore()->GetText(acpCurrent, -1, &buffer[acpCurrent], 1.2053 + BUFFER_SIZE, &bufferRet, runInfo, 1.2054 + RUNINFO_SIZE, &runInfoRet, &acpRet); 1.2055 + if (!(SUCCEEDED(hr) && 1.2056 + acpRet > acpCurrent && 1.2057 + bufferRet <= SETTEXT1_FINAL_LENGTH && 1.2058 + runInfoRet > 0)) { 1.2059 + fail("TestText: GetText failed after SetTest 1"); 1.2060 + continueTest = succeeded = false; 1.2061 + break; 1.2062 + } 1.2063 + acpCurrent = acpRet; 1.2064 + } 1.2065 + } 1.2066 + 1.2067 + if (continueTest) { 1.2068 + if (!(acpCurrent == LONG(SETTEXT1_FINAL_LENGTH) && 1.2069 + !wcsncmp(buffer, mTestString.get(), SETTEXT1_START) && 1.2070 + !wcsncmp(&buffer[SETTEXT1_START], insertString.get(), 1.2071 + insertString.Length()) && 1.2072 + !wcsncmp(&buffer[SETTEXT1_START + insertString.Length()], 1.2073 + mTestString.get() + SETTEXT1_END, SETTEXT1_TAIL_LENGTH))) { 1.2074 + fail("TestText: unexpected GetText result after SetText 1"); 1.2075 + succeeded = false; 1.2076 + } 1.2077 + } 1.2078 + 1.2079 + 1.2080 + if (!mMgr->GetFocusedStore()) { 1.2081 + fail("TestText: GetFocusedStore returns null #5"); 1.2082 + return false; 1.2083 + } 1.2084 + 1.2085 + // Restore entire text to original text (mTestString) 1.2086 + continueTest = true; 1.2087 + hr = mMgr->GetFocusedStore()->SetText(0, 0, -1, mTestString.get(), 1.2088 + mTestString.Length(), &textChange); 1.2089 + if (!(SUCCEEDED(hr) && 1.2090 + textChange.acpStart == 0 && 1.2091 + textChange.acpOldEnd == LONG(SETTEXT1_FINAL_LENGTH) && 1.2092 + textChange.acpNewEnd == LONG(mTestString.Length()))) { 1.2093 + fail("TestText: SetText 2"); 1.2094 + continueTest = succeeded = false; 1.2095 + } 1.2096 + 1.2097 + if (continueTest) { 1.2098 + acpCurrent = 0; 1.2099 + while (acpCurrent < LONG(mTestString.Length())) { 1.2100 + if (!mMgr->GetFocusedStore()) { 1.2101 + fail("TestText: GetFocusedStore returns null #6"); 1.2102 + return false; 1.2103 + } 1.2104 + 1.2105 + hr = mMgr->GetFocusedStore()->GetText(acpCurrent, -1, &buffer[acpCurrent], 1.2106 + BUFFER_SIZE, &bufferRet, runInfo, 1.2107 + RUNINFO_SIZE, &runInfoRet, &acpRet); 1.2108 + if (!(SUCCEEDED(hr) && 1.2109 + acpRet > acpCurrent && 1.2110 + bufferRet <= mTestString.Length() && 1.2111 + runInfoRet > 0)) { 1.2112 + fail("TestText: GetText failed after SetText 2"); 1.2113 + continueTest = succeeded = false; 1.2114 + break; 1.2115 + } 1.2116 + acpCurrent = acpRet; 1.2117 + } 1.2118 + } 1.2119 + 1.2120 + if (continueTest) { 1.2121 + if (!(acpCurrent == LONG(mTestString.Length()) && 1.2122 + !wcsncmp(buffer, mTestString.get(), mTestString.Length()))) { 1.2123 + fail("TestText: unexpected GetText result after SetText 2"); 1.2124 + succeeded = false; 1.2125 + } 1.2126 + } 1.2127 + return succeeded; 1.2128 +} 1.2129 + 1.2130 +bool 1.2131 +TestApp::TestExtents(void) 1.2132 +{ 1.2133 + if (!mMgr->GetFocusedStore()) { 1.2134 + fail("TestExtents: GetFocusedStore returns null #1"); 1.2135 + return false; 1.2136 + } 1.2137 + 1.2138 + TS_SELECTION_ACP sel; 1.2139 + sel.acpStart = 0; 1.2140 + sel.acpEnd = 0; 1.2141 + sel.style.ase = TS_AE_END; 1.2142 + sel.style.fInterimChar = FALSE; 1.2143 + mMgr->GetFocusedStore()->SetSelection(1, &sel); 1.2144 + 1.2145 + nsCOMPtr<nsISelectionController> selCon; 1.2146 + if (!(NS_SUCCEEDED(GetSelCon(getter_AddRefs(selCon))) && selCon)) { 1.2147 + fail("TestExtents: get nsISelectionController"); 1.2148 + return false; 1.2149 + } 1.2150 + selCon->ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL, 1.2151 + nsISelectionController::SELECTION_FOCUS_REGION, true); 1.2152 + 1.2153 + nsCOMPtr<nsIDOMWindow> window(do_GetInterface(mWindow)); 1.2154 + if (!window) { 1.2155 + fail("TestExtents: get nsIDOMWindow"); 1.2156 + return false; 1.2157 + } 1.2158 + RECT windowRect, screenRect, textRect1, textRect2; 1.2159 + BOOL clipped; 1.2160 + int32_t val; 1.2161 + TsViewCookie view; 1.2162 + HRESULT hr; 1.2163 + 1.2164 + nsresult nsr = window->GetScreenX(&val); 1.2165 + windowRect.left = val; 1.2166 + nsr |= window->GetScreenY(&val); 1.2167 + windowRect.top = val; 1.2168 + nsr |= window->GetOuterWidth(&val); 1.2169 + windowRect.right = windowRect.left + val; 1.2170 + nsr |= window->GetOuterHeight(&val); 1.2171 + windowRect.bottom = windowRect.top + val; 1.2172 + if (!(NS_SUCCEEDED(nsr))) { 1.2173 + fail("TestExtents: get window rect failed"); 1.2174 + return false; 1.2175 + } 1.2176 + 1.2177 + if (!mMgr->GetFocusedStore()) { 1.2178 + fail("TestExtents: GetFocusedStore returns null #2"); 1.2179 + return false; 1.2180 + } 1.2181 + 1.2182 + hr = mMgr->GetFocusedStore()->GetActiveView(&view); 1.2183 + if (!(SUCCEEDED(hr))) { 1.2184 + fail("TestExtents: GetActiveView"); 1.2185 + return false; 1.2186 + } 1.2187 + 1.2188 + if (!mMgr->GetFocusedStore()) { 1.2189 + fail("TestExtents: GetFocusedStore returns null #3"); 1.2190 + return false; 1.2191 + } 1.2192 + 1.2193 + bool succeeded = true; 1.2194 + HWND hwnd; 1.2195 + hr = mMgr->GetFocusedStore()->GetWnd(view, &hwnd); 1.2196 + if (!(SUCCEEDED(hr) && 1.2197 + ::IsWindow(hwnd))) { 1.2198 + fail("TestExtents: GetWnd"); 1.2199 + succeeded = false; 1.2200 + } 1.2201 + 1.2202 + ::SetRectEmpty(&screenRect); 1.2203 + 1.2204 + if (!mMgr->GetFocusedStore()) { 1.2205 + fail("TestExtents: GetFocusedStore returns null #4"); 1.2206 + return false; 1.2207 + } 1.2208 + 1.2209 + hr = mMgr->GetFocusedStore()->GetScreenExt(view, &screenRect); 1.2210 + if (!(SUCCEEDED(hr) && 1.2211 + screenRect.left > windowRect.left && 1.2212 + screenRect.top > windowRect.top && 1.2213 + screenRect.right > screenRect.left && 1.2214 + screenRect.bottom > screenRect.top && 1.2215 + screenRect.right < windowRect.right && 1.2216 + screenRect.bottom < windowRect.bottom)) { 1.2217 + fail("TestExtents: GetScreenExt"); 1.2218 + succeeded = false; 1.2219 + } 1.2220 + 1.2221 + const LONG GETTEXTEXT1_START = 0; 1.2222 + const LONG GETTEXTEXT1_END = 0; 1.2223 + 1.2224 + ::SetRectEmpty(&textRect1); 1.2225 + 1.2226 + if (!mMgr->GetFocusedStore()) { 1.2227 + fail("TestExtents: GetFocusedStore returns null #5"); 1.2228 + return false; 1.2229 + } 1.2230 + 1.2231 + hr = mMgr->GetFocusedStore()->GetTextExt(view, GETTEXTEXT1_START, 1.2232 + GETTEXTEXT1_END, &textRect1, 1.2233 + &clipped); 1.2234 + if (!(SUCCEEDED(hr) && 1.2235 + textRect1.left >= screenRect.left && 1.2236 + textRect1.top >= screenRect.top && 1.2237 + textRect1.right < screenRect.right && 1.2238 + textRect1.bottom <= screenRect.bottom && 1.2239 + textRect1.right >= textRect1.left && 1.2240 + textRect1.bottom > textRect1.top)) { 1.2241 + fail("TestExtents: GetTextExt (offset %ld to %ld)", 1.2242 + GETTEXTEXT1_START, GETTEXTEXT1_END); 1.2243 + succeeded = false; 1.2244 + } 1.2245 + 1.2246 + const LONG GETTEXTEXT2_START = 10; 1.2247 + const LONG GETTEXTEXT2_END = 25; 1.2248 + 1.2249 + ::SetRectEmpty(&textRect2); 1.2250 + 1.2251 + if (!mMgr->GetFocusedStore()) { 1.2252 + fail("TestExtents: GetFocusedStore returns null #6"); 1.2253 + return false; 1.2254 + } 1.2255 + 1.2256 + hr = mMgr->GetFocusedStore()->GetTextExt(view, GETTEXTEXT2_START, 1.2257 + GETTEXTEXT2_END, &textRect2, 1.2258 + &clipped); 1.2259 + if (!(SUCCEEDED(hr) && 1.2260 + textRect2.left >= screenRect.left && 1.2261 + textRect2.top >= screenRect.top && 1.2262 + textRect2.right <= screenRect.right && 1.2263 + textRect2.bottom <= screenRect.bottom && 1.2264 + textRect2.right > textRect2.left && 1.2265 + textRect2.bottom > textRect2.top)) { 1.2266 + fail("TestExtents: GetTextExt (offset %ld to %ld)", 1.2267 + GETTEXTEXT2_START, GETTEXTEXT2_END); 1.2268 + succeeded = false; 1.2269 + } 1.2270 + 1.2271 + // Offsets must be between GETTEXTEXT2_START and GETTEXTEXT2_END 1.2272 + const LONG GETTEXTEXT3_START = 23; 1.2273 + const LONG GETTEXTEXT3_END = 23; 1.2274 + 1.2275 + ::SetRectEmpty(&textRect1); 1.2276 + 1.2277 + if (!mMgr->GetFocusedStore()) { 1.2278 + fail("TestExtents: GetFocusedStore returns null #7"); 1.2279 + return false; 1.2280 + } 1.2281 + 1.2282 + hr = mMgr->GetFocusedStore()->GetTextExt(view, GETTEXTEXT3_START, 1.2283 + GETTEXTEXT3_END, &textRect1, 1.2284 + &clipped); 1.2285 + // Rectangle must be entirely inside the previous rectangle, 1.2286 + // since GETTEXTEXT3_START and GETTEXTEXT3_END are between 1.2287 + // GETTEXTEXT2_START and GETTEXTEXT2_START 1.2288 + if (!(SUCCEEDED(hr) && ::IsRectEmpty(&textRect1) || 1.2289 + (textRect1.left >= textRect2.left && 1.2290 + textRect1.top >= textRect2.top && 1.2291 + textRect1.right <= textRect2.right && 1.2292 + textRect1.bottom <= textRect2.bottom && 1.2293 + textRect1.right >= textRect1.left && 1.2294 + textRect1.bottom > textRect1.top))) { 1.2295 + fail("TestExtents: GetTextExt (offset %ld to %ld)", 1.2296 + GETTEXTEXT3_START, GETTEXTEXT3_END); 1.2297 + succeeded = false; 1.2298 + } 1.2299 + return succeeded; 1.2300 +} 1.2301 + 1.2302 +bool 1.2303 +TestApp::TestCompositionSelectionAndText(char* aTestName, 1.2304 + LONG aExpectedSelStart, 1.2305 + LONG aExpectedSelEnd, 1.2306 + nsString& aReferenceString) 1.2307 +{ 1.2308 + if (!mMgr->GetFocusedStore()) { 1.2309 + fail("TestCompositionSelectionAndText: GetFocusedStore returns null #1"); 1.2310 + return false; 1.2311 + } 1.2312 + 1.2313 + TS_SELECTION_ACP currentSel; 1.2314 + ULONG selFetched = 0; 1.2315 + HRESULT hr = mMgr->GetFocusedStore()->GetSelection(TF_DEFAULT_SELECTION, 1, 1.2316 + ¤tSel, &selFetched); 1.2317 + if (!(SUCCEEDED(hr) && 1.2318 + 1 == selFetched && 1.2319 + currentSel.acpStart == aExpectedSelStart && 1.2320 + currentSel.acpEnd == aExpectedSelEnd)) { 1.2321 + fail("TestComposition: GetSelection (%s)", aTestName); 1.2322 + return false; 1.2323 + } 1.2324 + 1.2325 + const uint32_t bufferSize = 0x100, runInfoSize = 0x10; 1.2326 + char16_t buffer[bufferSize]; 1.2327 + TS_RUNINFO runInfo[runInfoSize]; 1.2328 + ULONG bufferRet, runInfoRet; 1.2329 + LONG acpRet, acpCurrent = 0; 1.2330 + while (acpCurrent < LONG(aReferenceString.Length())) { 1.2331 + if (!mMgr->GetFocusedStore()) { 1.2332 + fail("TestCompositionSelectionAndText: GetFocusedStore returns null #2"); 1.2333 + return false; 1.2334 + } 1.2335 + 1.2336 + hr = mMgr->GetFocusedStore()->GetText(acpCurrent, aReferenceString.Length(), 1.2337 + &buffer[acpCurrent], bufferSize, 1.2338 + &bufferRet, runInfo, runInfoSize, 1.2339 + &runInfoRet, &acpRet); 1.2340 + if (!(SUCCEEDED(hr) && 1.2341 + acpRet > acpCurrent && 1.2342 + bufferRet <= aReferenceString.Length() && 1.2343 + runInfoRet > 0)) { 1.2344 + fail("TestComposition: GetText (%s)", aTestName); 1.2345 + return false; 1.2346 + } 1.2347 + acpCurrent = acpRet; 1.2348 + } 1.2349 + if (!(acpCurrent == aReferenceString.Length() && 1.2350 + !wcsncmp(buffer, aReferenceString.get(), aReferenceString.Length()))) { 1.2351 + fail("TestComposition: unexpected GetText result (%s)", aTestName); 1.2352 + return false; 1.2353 + } 1.2354 + return true; 1.2355 +} 1.2356 + 1.2357 +bool 1.2358 +TestApp::TestComposition(void) 1.2359 +{ 1.2360 + if (!mMgr->GetFocusedStore()) { 1.2361 + fail("TestComposition: GetFocusedStore returns null #1"); 1.2362 + return false; 1.2363 + } 1.2364 + 1.2365 + nsRefPtr<ITfContextOwnerCompositionSink> sink; 1.2366 + HRESULT hr = 1.2367 + mMgr->GetFocusedStore()->QueryInterface(IID_ITfContextOwnerCompositionSink, 1.2368 + getter_AddRefs(sink)); 1.2369 + if (!(SUCCEEDED(hr))) { 1.2370 + fail("TestComposition: QueryInterface"); 1.2371 + return false; 1.2372 + } 1.2373 + 1.2374 + const LONG PRECOMPOSITION_SEL_START = 2; 1.2375 + const LONG PRECOMPOSITION_SEL_END = PRECOMPOSITION_SEL_START; 1.2376 + const TsActiveSelEnd PRECOMPOSITION_SEL_SELEND = TS_AE_END; 1.2377 + 1.2378 + TS_SELECTION_ACP sel; 1.2379 + sel.acpStart = PRECOMPOSITION_SEL_START; 1.2380 + sel.acpEnd = PRECOMPOSITION_SEL_END; 1.2381 + sel.style.ase = PRECOMPOSITION_SEL_SELEND; 1.2382 + sel.style.fInterimChar = FALSE; 1.2383 + hr = mMgr->GetFocusedStore()->SetSelection(1, &sel); 1.2384 + if (!(SUCCEEDED(hr))) { 1.2385 + fail("TestComposition: SetSelection (pre-composition)"); 1.2386 + return false; 1.2387 + } 1.2388 + 1.2389 + if (!mMgr->GetFocusedStore()) { 1.2390 + fail("TestComposition: GetFocusedStore returns null #2"); 1.2391 + return false; 1.2392 + } 1.2393 + 1.2394 + TS_TEXTCHANGE textChange; 1.2395 + NS_NAMED_LITERAL_STRING(insertString1, "Compo1"); 1.2396 + hr = mMgr->GetFocusedStore()->InsertTextAtSelection(TF_IAS_NOQUERY, 1.2397 + insertString1.get(), 1.2398 + insertString1.Length(), 1.2399 + nullptr, nullptr, 1.2400 + &textChange); 1.2401 + if (!(SUCCEEDED(hr) && 1.2402 + sel.acpEnd == textChange.acpStart && 1.2403 + sel.acpEnd == textChange.acpOldEnd && 1.2404 + sel.acpEnd + insertString1.Length() == textChange.acpNewEnd)) { 1.2405 + fail("TestComposition: InsertTextAtSelection"); 1.2406 + return false; 1.2407 + } 1.2408 + sel.acpEnd = textChange.acpNewEnd; 1.2409 + 1.2410 + if (!mMgr->GetFocusedAttrProp()) { 1.2411 + fail("TestComposition: GetFocusedAttrProp returns null #1"); 1.2412 + return false; 1.2413 + } 1.2414 + mMgr->GetFocusedAttrProp()->mRanges.Clear(); 1.2415 + nsRefPtr<TSFRangeImpl> range = 1.2416 + new TSFRangeImpl(textChange.acpStart, 1.2417 + textChange.acpNewEnd - textChange.acpOldEnd); 1.2418 + if (!mMgr->GetFocusedAttrProp()) { 1.2419 + fail("TestComposition: GetFocusedAttrProp returns null #2"); 1.2420 + return false; 1.2421 + } 1.2422 + mMgr->GetFocusedAttrProp()->mRanges.AppendElement(range); 1.2423 + 1.2424 + BOOL okay = FALSE; 1.2425 + hr = sink->OnStartComposition(mMgr->GetFocusedContext(), &okay); 1.2426 + if (!(SUCCEEDED(hr) && 1.2427 + okay)) { 1.2428 + fail("TestComposition: OnStartComposition"); 1.2429 + return false; 1.2430 + } 1.2431 + 1.2432 + 1.2433 + if (!mMgr->GetFocusedStore()) { 1.2434 + fail("TestComposition: GetFocusedStore returns null #3"); 1.2435 + return false; 1.2436 + } 1.2437 + 1.2438 + NS_NAMED_LITERAL_STRING(insertString2, "Composition2"); 1.2439 + hr = mMgr->GetFocusedStore()->SetText(0, range->mStart + range->mLength, 1.2440 + range->mStart + range->mLength, 1.2441 + insertString2.get(), 1.2442 + insertString2.Length(), 1.2443 + &textChange); 1.2444 + if (!(SUCCEEDED(hr) && 1.2445 + sel.acpEnd == textChange.acpStart && 1.2446 + sel.acpEnd == textChange.acpOldEnd && 1.2447 + sel.acpEnd + insertString2.Length() == textChange.acpNewEnd)) { 1.2448 + fail("TestComposition: SetText 1"); 1.2449 + return false; 1.2450 + } 1.2451 + sel.acpEnd = textChange.acpNewEnd; 1.2452 + range->mLength += textChange.acpNewEnd - textChange.acpOldEnd; 1.2453 + 1.2454 + 1.2455 + if (!mMgr->GetFocusedStore()) { 1.2456 + fail("TestComposition: GetFocusedStore returns null #4"); 1.2457 + return false; 1.2458 + } 1.2459 + 1.2460 + const LONG COMPOSITION3_TEXT_START_OFFSET = -8; // offset 8 from the end 1.2461 + const LONG COMPOSITION3_TEXT_END_OFFSET = 4; 1.2462 + 1.2463 + const LONG COMPOSITION3_TEXT_START = range->mStart + range->mLength + 1.2464 + COMPOSITION3_TEXT_START_OFFSET; 1.2465 + const LONG COMPOSITION3_TEXT_END = COMPOSITION3_TEXT_START + 1.2466 + COMPOSITION3_TEXT_END_OFFSET; 1.2467 + 1.2468 + NS_NAMED_LITERAL_STRING(insertString3, "Compo3"); 1.2469 + hr = mMgr->GetFocusedStore()->SetText(0, COMPOSITION3_TEXT_START, 1.2470 + COMPOSITION3_TEXT_END, 1.2471 + insertString3.get(), 1.2472 + insertString3.Length(), 1.2473 + &textChange); 1.2474 + if (!(SUCCEEDED(hr) && 1.2475 + sel.acpEnd + COMPOSITION3_TEXT_START_OFFSET == textChange.acpStart && 1.2476 + sel.acpEnd + COMPOSITION3_TEXT_START_OFFSET + 1.2477 + COMPOSITION3_TEXT_END_OFFSET == textChange.acpOldEnd && 1.2478 + sel.acpEnd + insertString3.Length() + COMPOSITION3_TEXT_START_OFFSET == 1.2479 + textChange.acpNewEnd)) { 1.2480 + fail("TestComposition: SetText 2"); 1.2481 + return false; 1.2482 + } 1.2483 + sel.acpEnd = textChange.acpNewEnd; 1.2484 + range->mLength += textChange.acpNewEnd - textChange.acpOldEnd; 1.2485 + 1.2486 + 1.2487 + nsString referenceString; 1.2488 + referenceString.Append(mTestString.get(), sel.acpStart); 1.2489 + referenceString.Append(insertString1); 1.2490 + referenceString.Append(insertString2.get(), 1.2491 + insertString2.Length() + COMPOSITION3_TEXT_START_OFFSET); 1.2492 + referenceString.Append(insertString3); 1.2493 + referenceString.Append(insertString2.get() + insertString2.Length() - 1.2494 + COMPOSITION3_TEXT_END_OFFSET, COMPOSITION3_TEXT_END_OFFSET); 1.2495 + referenceString.Append(mTestString.get() + sel.acpStart, 1.2496 + COMPOSITION3_TEXT_END_OFFSET); 1.2497 + 1.2498 + if (!TestCompositionSelectionAndText("composition", 1.2499 + sel.acpEnd, sel.acpEnd, 1.2500 + referenceString)) 1.2501 + return false; 1.2502 + 1.2503 + 1.2504 + if (!mMgr->GetFocusedStore()) { 1.2505 + fail("TestComposition: GetFocusedStore returns null #5"); 1.2506 + return false; 1.2507 + } 1.2508 + 1.2509 + const LONG POSTCOMPOSITION_SEL_START = sel.acpEnd - 8; 1.2510 + const LONG POSTCOMPOSITION_SEL_END = POSTCOMPOSITION_SEL_START + 2; 1.2511 + 1.2512 + sel.acpStart = POSTCOMPOSITION_SEL_START; 1.2513 + sel.acpEnd = POSTCOMPOSITION_SEL_END; 1.2514 + hr = mMgr->GetFocusedStore()->SetSelection(1, &sel); 1.2515 + if (!(SUCCEEDED(hr))) { 1.2516 + fail("TestComposition: SetSelection (composition)"); 1.2517 + return false; 1.2518 + } 1.2519 + 1.2520 + if (!mMgr->GetFocusedAttrProp()) { 1.2521 + fail("TestComposition: GetFocusedAttrProp returns null #3"); 1.2522 + return false; 1.2523 + } 1.2524 + mMgr->GetFocusedAttrProp()->mRanges.Clear(); 1.2525 + 1.2526 + hr = sink->OnEndComposition(mMgr->GetFocusedContext()); 1.2527 + if (!(SUCCEEDED(hr))) { 1.2528 + fail("TestComposition: OnEndComposition"); 1.2529 + return false; 1.2530 + } 1.2531 + 1.2532 + if (!TestCompositionSelectionAndText("post-composition", 1.2533 + sel.acpStart, sel.acpEnd, 1.2534 + referenceString)) 1.2535 + return false; 1.2536 + 1.2537 + const LONG EMPTYCOMPOSITION_START = range->mStart + 2; 1.2538 + const LONG EMPTYCOMPOSITION_LENGTH = range->mLength - 4; 1.2539 + 1.2540 + range->mStart = EMPTYCOMPOSITION_START; 1.2541 + range->mLength = EMPTYCOMPOSITION_LENGTH; 1.2542 + if (!mMgr->GetFocusedAttrProp()) { 1.2543 + fail("TestComposition: GetFocusedAttrProp returns null #4"); 1.2544 + return false; 1.2545 + } 1.2546 + mMgr->GetFocusedAttrProp()->mRanges.AppendElement(range); 1.2547 + 1.2548 + okay = FALSE; 1.2549 + hr = sink->OnStartComposition(mMgr->GetFocusedContext(), &okay); 1.2550 + if (!(SUCCEEDED(hr) && 1.2551 + okay)) { 1.2552 + fail("TestComposition: OnStartComposition (empty composition)"); 1.2553 + return false; 1.2554 + } 1.2555 + 1.2556 + if (!mMgr->GetFocusedAttrProp()) { 1.2557 + fail("TestComposition: GetFocusedAttrProp returns null #5"); 1.2558 + return false; 1.2559 + } 1.2560 + mMgr->GetFocusedAttrProp()->mRanges.Clear(); 1.2561 + 1.2562 + hr = sink->OnEndComposition(mMgr->GetFocusedContext()); 1.2563 + if (!(SUCCEEDED(hr))) { 1.2564 + fail("TestComposition: OnEndComposition (empty composition)"); 1.2565 + return false; 1.2566 + } 1.2567 + 1.2568 + if (!TestCompositionSelectionAndText("empty composition", 1.2569 + range->mStart, range->mStart + range->mLength, 1.2570 + referenceString)) 1.2571 + return false; 1.2572 + 1.2573 + return true; 1.2574 +} 1.2575 + 1.2576 +bool 1.2577 +TestApp::TestNotificationTextChange(nsIWidget* aWidget, 1.2578 + uint32_t aCode, 1.2579 + const nsAString& aCharacter, 1.2580 + LONG aStart, 1.2581 + LONG aOldEnd, 1.2582 + LONG aNewEnd) 1.2583 +{ 1.2584 + MSG msg; 1.2585 + if (::PeekMessageW(&msg, nullptr, WM_USER_TSF_TEXTCHANGE, 1.2586 + WM_USER_TSF_TEXTCHANGE, PM_REMOVE)) 1.2587 + ::DispatchMessageW(&msg); 1.2588 + if (!mMgr->GetFocusedContext()) { 1.2589 + fail("TestNotificationTextChange: GetFocusedContext returns null"); 1.2590 + return false; 1.2591 + } 1.2592 + mMgr->GetFocusedContext()->mTextChanged = false; 1.2593 + nsresult nsr = aWidget->SynthesizeNativeKeyEvent(0, aCode, 0, 1.2594 + aCharacter, aCharacter); 1.2595 + if (::PeekMessageW(&msg, nullptr, WM_USER_TSF_TEXTCHANGE, 1.2596 + WM_USER_TSF_TEXTCHANGE, PM_REMOVE)) 1.2597 + ::DispatchMessageW(&msg); 1.2598 + return NS_SUCCEEDED(nsr) && 1.2599 + mMgr->GetFocusedContext()->mTextChanged && 1.2600 + aStart == mMgr->GetFocusedContext()->mTextChangeData.acpStart && 1.2601 + aOldEnd == mMgr->GetFocusedContext()->mTextChangeData.acpOldEnd && 1.2602 + aNewEnd == mMgr->GetFocusedContext()->mTextChangeData.acpNewEnd; 1.2603 +} 1.2604 + 1.2605 +bool 1.2606 +TestApp::TestNotification(void) 1.2607 +{ 1.2608 + nsresult nsr; 1.2609 + // get selection to test notification support 1.2610 + nsCOMPtr<nsISelectionController> selCon; 1.2611 + if (!(NS_SUCCEEDED(GetSelCon(getter_AddRefs(selCon))) && selCon)) { 1.2612 + fail("TestNotification: get nsISelectionController"); 1.2613 + return false; 1.2614 + } 1.2615 + 1.2616 + nsr = selCon->CompleteMove(false, false); 1.2617 + if (!(NS_SUCCEEDED(nsr))) { 1.2618 + fail("TestNotification: CompleteMove"); 1.2619 + return false; 1.2620 + } 1.2621 + 1.2622 + if (!mMgr->GetFocusedContext()) { 1.2623 + fail("TestNotification: GetFocusedContext returns null #1"); 1.2624 + return false; 1.2625 + } 1.2626 + 1.2627 + mMgr->GetFocusedContext()->mSelChanged = false; 1.2628 + nsr = selCon->CharacterMove(true, false); 1.2629 + if (!(NS_SUCCEEDED(nsr) && 1.2630 + mMgr->GetFocusedContext()->mSelChanged)) { 1.2631 + fail("TestNotification: CharacterMove"); 1.2632 + return false; 1.2633 + } 1.2634 + 1.2635 + if (!mMgr->GetFocusedContext()) { 1.2636 + fail("TestNotification: GetFocusedContext returns null #2"); 1.2637 + return false; 1.2638 + } 1.2639 + 1.2640 + mMgr->GetFocusedContext()->mSelChanged = false; 1.2641 + nsr = selCon->CharacterMove(true, true); 1.2642 + if (!(NS_SUCCEEDED(nsr) && 1.2643 + mMgr->GetFocusedContext()->mSelChanged)) { 1.2644 + fail("TestNotification: CharacterMove (extend)"); 1.2645 + return false; 1.2646 + } 1.2647 + 1.2648 + nsCOMPtr<nsIWidget> widget; 1.2649 + if (!GetWidget(getter_AddRefs(widget))) { 1.2650 + fail("TestNotification: get nsIWidget"); 1.2651 + return false; 1.2652 + } 1.2653 + 1.2654 + NS_NAMED_LITERAL_STRING(character, ""); 1.2655 + NS_NAMED_LITERAL_STRING(characterA, "A"); 1.2656 + 1.2657 + // The selection test code above placed the selection at offset 1 to 2 1.2658 + const LONG TEXTCHANGE1_START = 1; 1.2659 + const LONG TEXTCHANGE1_OLDEND = 2; 1.2660 + const LONG TEXTCHANGE1_NEWEND = 2; 1.2661 + 1.2662 + // replace single selected character with 'A' 1.2663 + if (!TestNotificationTextChange(widget, 'A', characterA, 1.2664 + TEXTCHANGE1_START, TEXTCHANGE1_OLDEND, TEXTCHANGE1_NEWEND)) { 1.2665 + fail("TestNotification: text change 1"); 1.2666 + return false; 1.2667 + } 1.2668 + 1.2669 + const LONG TEXTCHANGE2_START = TEXTCHANGE1_NEWEND; 1.2670 + const LONG TEXTCHANGE2_OLDEND = TEXTCHANGE1_NEWEND; 1.2671 + const LONG TEXTCHANGE2_NEWEND = TEXTCHANGE1_NEWEND + 1; 1.2672 + 1.2673 + // insert 'A' 1.2674 + if (!TestNotificationTextChange(widget, 'A', characterA, 1.2675 + TEXTCHANGE2_START, TEXTCHANGE2_OLDEND, TEXTCHANGE2_NEWEND)) { 1.2676 + fail("TestNotification: text change 2"); 1.2677 + return false; 1.2678 + } 1.2679 + 1.2680 + const LONG TEXTCHANGE3_START = TEXTCHANGE2_NEWEND - 1; 1.2681 + const LONG TEXTCHANGE3_OLDEND = TEXTCHANGE2_NEWEND; 1.2682 + const LONG TEXTCHANGE3_NEWEND = TEXTCHANGE2_NEWEND - 1; 1.2683 + 1.2684 + // backspace 1.2685 + if (!TestNotificationTextChange(widget, '\b', character, 1.2686 + TEXTCHANGE3_START, TEXTCHANGE3_OLDEND, TEXTCHANGE3_NEWEND)) { 1.2687 + fail("TestNotification: text change 3"); 1.2688 + return false; 1.2689 + } 1.2690 + return true; 1.2691 +} 1.2692 + 1.2693 +bool 1.2694 +TestApp::TestEditMessages(void) 1.2695 +{ 1.2696 + mTestString = NS_LITERAL_STRING( 1.2697 + "This is a test of\nthe native editing command messages"); 1.2698 + // 0123456789012345678901 2345678901234567890123456789012 1.2699 + // 0 1 2 3 4 5 1.2700 + 1.2701 + // The native text string is increased by converting \n to \r\n. 1.2702 + uint32_t testStringLength = mTestString.Length() + 1; 1.2703 + 1.2704 + mTextArea->SetValue(mTestString); 1.2705 + mTextArea->Focus(); 1.2706 + 1.2707 + nsCOMPtr<nsIWidget> widget; 1.2708 + if (!GetWidget(getter_AddRefs(widget))) { 1.2709 + fail("TestEditMessages: get nsIWidget"); 1.2710 + return false; 1.2711 + } 1.2712 + 1.2713 + HWND wnd = (HWND)widget->GetNativeData(NS_NATIVE_WINDOW); 1.2714 + bool result = true; 1.2715 + 1.2716 + if (!::SendMessage(wnd, EM_CANUNDO, 0, 0)) { 1.2717 + fail("TestEditMessages: EM_CANUNDO"); 1.2718 + return false; 1.2719 + } 1.2720 + 1.2721 + if (::SendMessage(wnd, EM_CANREDO, 0, 0)) { 1.2722 + fail("TestEditMessages: EM_CANREDO #1"); 1.2723 + return false; 1.2724 + } 1.2725 + 1.2726 + 1.2727 + if (!::SendMessage(wnd, EM_UNDO, 0, 0)) { 1.2728 + fail("TestEditMessages: EM_UNDO #1"); 1.2729 + return false; 1.2730 + } 1.2731 + 1.2732 + nsAutoString str; 1.2733 + mTextArea->GetValue(str); 1.2734 + if (str == mTestString) { 1.2735 + fail("TestEditMessage: EM_UNDO #1, failed to execute"); 1.2736 + printf("Current Str: \"%s\"\n", NS_ConvertUTF16toUTF8(str).get()); 1.2737 + return false; 1.2738 + } 1.2739 + 1.2740 + if (!::SendMessage(wnd, EM_CANREDO, 0, 0)) { 1.2741 + fail("TestEditMessages: EM_CANREDO #2"); 1.2742 + return false; 1.2743 + } 1.2744 + 1.2745 + if (!::SendMessage(wnd, EM_REDO, 0, 0)) { 1.2746 + fail("TestEditMessages: EM_REDO #1"); 1.2747 + return false; 1.2748 + } 1.2749 + 1.2750 + mTextArea->GetValue(str); 1.2751 + if (str != mTestString) { 1.2752 + fail("TestEditMessage: EM_REDO #1, failed to execute"); 1.2753 + printf("Current Str: \"%s\"\n", NS_ConvertUTF16toUTF8(str).get()); 1.2754 + return false; 1.2755 + } 1.2756 + 1.2757 + TS_SELECTION_ACP sel; 1.2758 + HRESULT hr; 1.2759 + 1.2760 + sel.acpStart = 0; 1.2761 + sel.acpEnd = testStringLength; 1.2762 + sel.style.ase = TS_AE_END; 1.2763 + sel.style.fInterimChar = FALSE; 1.2764 + hr = mMgr->GetFocusedStore()->SetSelection(1, &sel); 1.2765 + if (!(SUCCEEDED(hr))) { 1.2766 + fail("TestEditMessages: SetSelection #1"); 1.2767 + return false; 1.2768 + } 1.2769 + 1.2770 + ::SendMessage(wnd, WM_CUT, 0, 0); 1.2771 + mTextArea->GetValue(str); 1.2772 + if (!str.IsEmpty()) { 1.2773 + fail("TestEditMessages: WM_CUT"); 1.2774 + printf("Current Str: \"%s\"\n", NS_ConvertUTF16toUTF8(str).get()); 1.2775 + return false; 1.2776 + } 1.2777 + 1.2778 + ::SendMessage(wnd, WM_PASTE, 0, 0); 1.2779 + mTextArea->GetValue(str); 1.2780 + if (str != mTestString) { 1.2781 + fail("TestEditMessages: WM_PASTE #1"); 1.2782 + printf("Current Str: \"%s\"\n", NS_ConvertUTF16toUTF8(str).get()); 1.2783 + return false; 1.2784 + } 1.2785 + 1.2786 + ::SendMessage(wnd, WM_PASTE, 0, 0); 1.2787 + mTextArea->GetValue(str); 1.2788 + nsAutoString expectedStr(mTestString); 1.2789 + expectedStr += mTestString; 1.2790 + if (str != expectedStr) { 1.2791 + fail("TestEditMessages: WM_PASTE #2"); 1.2792 + printf("Current Str: \"%s\"\n", NS_ConvertUTF16toUTF8(str).get()); 1.2793 + return false; 1.2794 + } 1.2795 + 1.2796 + sel.acpStart = 0; 1.2797 + sel.acpEnd = testStringLength; 1.2798 + hr = mMgr->GetFocusedStore()->SetSelection(1, &sel); 1.2799 + if (!(SUCCEEDED(hr))) { 1.2800 + fail("TestEditMessages: SetSelection #2"); 1.2801 + return false; 1.2802 + } 1.2803 + 1.2804 + ::SendMessage(wnd, WM_CLEAR, 0, 0); 1.2805 + mTextArea->GetValue(str); 1.2806 + if (str != mTestString) { 1.2807 + fail("TestEditMessages: WM_CLEAR #1"); 1.2808 + printf("Current Str: \"%s\"\n", NS_ConvertUTF16toUTF8(str).get()); 1.2809 + return false; 1.2810 + } 1.2811 + 1.2812 + sel.acpStart = 4; 1.2813 + sel.acpEnd = testStringLength; 1.2814 + hr = mMgr->GetFocusedStore()->SetSelection(1, &sel); 1.2815 + if (!(SUCCEEDED(hr))) { 1.2816 + fail("TestEditMessages: SetSelection #3"); 1.2817 + return false; 1.2818 + } 1.2819 + 1.2820 + ::SendMessage(wnd, WM_COPY, 0, 0); 1.2821 + mTextArea->GetValue(str); 1.2822 + if (str != mTestString) { 1.2823 + fail("TestEditMessages: WM_COPY"); 1.2824 + printf("Current Str: \"%s\"\n", NS_ConvertUTF16toUTF8(str).get()); 1.2825 + return false; 1.2826 + } 1.2827 + 1.2828 + if (!::SendMessage(wnd, EM_CANPASTE, 0, 0)) { 1.2829 + fail("TestEditMessages: EM_CANPASTE #1"); 1.2830 + return false; 1.2831 + } 1.2832 + 1.2833 + if (!::SendMessage(wnd, EM_CANPASTE, CF_TEXT, 0)) { 1.2834 + fail("TestEditMessages: EM_CANPASTE #2"); 1.2835 + return false; 1.2836 + } 1.2837 + 1.2838 + if (!::SendMessage(wnd, EM_CANPASTE, CF_UNICODETEXT, 0)) { 1.2839 + fail("TestEditMessages: EM_CANPASTE #3"); 1.2840 + return false; 1.2841 + } 1.2842 + 1.2843 + ::SendMessage(wnd, WM_PASTE, 0, 0); 1.2844 + mTextArea->GetValue(str); 1.2845 + if (str != mTestString) { 1.2846 + fail("TestEditMessages: WM_PASTE #3"); 1.2847 + printf("Current Str: \"%s\"\n", NS_ConvertUTF16toUTF8(str).get()); 1.2848 + return false; 1.2849 + } 1.2850 + 1.2851 + sel.acpStart = 4; 1.2852 + sel.acpEnd = testStringLength; 1.2853 + hr = mMgr->GetFocusedStore()->SetSelection(1, &sel); 1.2854 + if (!(SUCCEEDED(hr))) { 1.2855 + fail("TestEditMessages: SetSelection #3"); 1.2856 + return false; 1.2857 + } 1.2858 + 1.2859 + ::SendMessage(wnd, WM_CLEAR, 0, 0); 1.2860 + mTextArea->GetValue(str); 1.2861 + if (str != NS_LITERAL_STRING("This")) { 1.2862 + fail("TestEditMessages: WM_CLEAR #2"); 1.2863 + printf("Current Str: \"%s\"\n", NS_ConvertUTF16toUTF8(str).get()); 1.2864 + return false; 1.2865 + } 1.2866 + 1.2867 + ::SendMessage(wnd, WM_PASTE, 0, 0); 1.2868 + mTextArea->GetValue(str); 1.2869 + if (str != mTestString) { 1.2870 + fail("TestEditMessages: WM_PASTE #4"); 1.2871 + printf("Current Str: \"%s\"\n", NS_ConvertUTF16toUTF8(str).get()); 1.2872 + return false; 1.2873 + } 1.2874 + 1.2875 + return true; 1.2876 +} 1.2877 + 1.2878 +bool 1.2879 +TestApp::TestScrollMessages(void) 1.2880 +{ 1.2881 + NS_NAMED_LITERAL_STRING(kLine, "ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss\n"); 1.2882 + mTestString.Truncate(); 1.2883 + for (uint32_t i = 0; i < 30; i++) { 1.2884 + mTestString.Append(kLine); 1.2885 + } 1.2886 + 1.2887 + mTextArea->SetAttribute(NS_LITERAL_STRING("style"), 1.2888 + NS_LITERAL_STRING("width:3em;height:3em;word-wrap:normal;")); 1.2889 + mTextArea->SetValue(mTestString); 1.2890 + mTextArea->Focus(); 1.2891 + 1.2892 + nsCOMPtr<nsIWidget> widget; 1.2893 + if (!GetWidget(getter_AddRefs(widget))) { 1.2894 + fail("TestScrollMessages: get nsIWidget"); 1.2895 + mTextArea->SetAttribute(NS_LITERAL_STRING("style"), EmptyString()); 1.2896 + return false; 1.2897 + } 1.2898 + 1.2899 + nsCOMPtr<nsIDOMElement> textArea = do_QueryInterface(mTextArea); 1.2900 + if (!textArea) { 1.2901 + fail("TestScrollMessages: get nsIDOMElement"); 1.2902 + mTextArea->SetAttribute(NS_LITERAL_STRING("style"), EmptyString()); 1.2903 + return false; 1.2904 + } 1.2905 + 1.2906 +#define DO_CHECK(aFailureCondition, aDescription) \ 1.2907 + if (aFailureCondition) { \ 1.2908 + nsAutoCString str(aDescription); \ 1.2909 + str.Append(": "); \ 1.2910 + str.Append(#aFailureCondition); \ 1.2911 + fail(str.get()); \ 1.2912 + mTextArea->SetAttribute(NS_LITERAL_STRING("style"), EmptyString()); \ 1.2913 + return false; \ 1.2914 + } 1.2915 + 1.2916 + HWND wnd = (HWND)widget->GetNativeData(NS_NATIVE_WINDOW); 1.2917 + 1.2918 + textArea->SetScrollTop(0); 1.2919 + textArea->SetScrollLeft(0); 1.2920 + 1.2921 + if (::SendMessage(wnd, WM_VSCROLL, SB_LINEDOWN, 0) != 0) { 1.2922 + fail("TestScrollMessages: SendMessage WM_VSCROLL #1"); 1.2923 + mTextArea->SetAttribute(NS_LITERAL_STRING("style"), EmptyString()); 1.2924 + return false; 1.2925 + } 1.2926 + 1.2927 + int32_t x, y, prevX, prevY; 1.2928 + textArea->GetScrollTop(&y); 1.2929 + textArea->GetScrollLeft(&x); 1.2930 + 1.2931 + DO_CHECK(x != 0, "TestScrollMessages: SendMessage WM_VSCROLL #1"); 1.2932 + DO_CHECK(y == 0, "TestScrollMessages: SendMessage WM_VSCROLL #1"); 1.2933 + 1.2934 + if (::SendMessage(wnd, WM_HSCROLL, SB_LINERIGHT, 0) != 0) { 1.2935 + fail("TestScrollMessages: SendMessage WM_HSCROLL #1"); 1.2936 + mTextArea->SetAttribute(NS_LITERAL_STRING("style"), EmptyString()); 1.2937 + return false; 1.2938 + } 1.2939 + 1.2940 + prevX = x; 1.2941 + prevY = y; 1.2942 + textArea->GetScrollTop(&y); 1.2943 + textArea->GetScrollLeft(&x); 1.2944 + 1.2945 + const int32_t kLineWidth = x; 1.2946 + const int32_t kLineHeight = y; 1.2947 + 1.2948 + DO_CHECK(x == 0, "TestScrollMessages: SendMessage WM_HSCROLL #1"); 1.2949 + DO_CHECK(y != prevY, "TestScrollMessages: SendMessage WM_HSCROLL #1"); 1.2950 + 1.2951 + if (::SendMessage(wnd, WM_VSCROLL, SB_LINEUP, 0) != 0) { 1.2952 + fail("TestScrollMessages: SendMessage WM_VSCROLL #2"); 1.2953 + mTextArea->SetAttribute(NS_LITERAL_STRING("style"), EmptyString()); 1.2954 + return false; 1.2955 + } 1.2956 + 1.2957 + prevX = x; 1.2958 + prevY = y; 1.2959 + textArea->GetScrollTop(&y); 1.2960 + textArea->GetScrollLeft(&x); 1.2961 + 1.2962 + DO_CHECK(x != prevX, "TestScrollMessages: SendMessage WM_VSCROLL #2"); 1.2963 + DO_CHECK(y != 0, "TestScrollMessages: SendMessage WM_VSCROLL #2"); 1.2964 + 1.2965 + if (::SendMessage(wnd, WM_HSCROLL, SB_LINELEFT, 0) != 0) { 1.2966 + fail("TestScrollMessages: SendMessage WM_HSCROLL #2"); 1.2967 + mTextArea->SetAttribute(NS_LITERAL_STRING("style"), EmptyString()); 1.2968 + return false; 1.2969 + } 1.2970 + 1.2971 + prevX = x; 1.2972 + prevY = y; 1.2973 + textArea->GetScrollTop(&y); 1.2974 + textArea->GetScrollLeft(&x); 1.2975 + 1.2976 + DO_CHECK(x != 0, "TestScrollMessages: SendMessage WM_HSCROLL #2"); 1.2977 + DO_CHECK(y != 0, "TestScrollMessages: SendMessage WM_HSCROLL #2"); 1.2978 + 1.2979 + if (::SendMessage(wnd, WM_VSCROLL, SB_PAGEDOWN, 0) != 0) { 1.2980 + fail("TestScrollMessages: SendMessage WM_VSCROLL #3"); 1.2981 + mTextArea->SetAttribute(NS_LITERAL_STRING("style"), EmptyString()); 1.2982 + return false; 1.2983 + } 1.2984 + 1.2985 + prevX = x; 1.2986 + prevY = y; 1.2987 + textArea->GetScrollTop(&y); 1.2988 + textArea->GetScrollLeft(&x); 1.2989 + 1.2990 + DO_CHECK(x != 0, "TestScrollMessages: SendMessage WM_VSCROLL #3"); 1.2991 + DO_CHECK(y <= kLineHeight, "TestScrollMessages: SendMessage WM_VSCROLL #3"); 1.2992 + 1.2993 + if (::SendMessage(wnd, WM_HSCROLL, SB_PAGERIGHT, 0) != 0) { 1.2994 + fail("TestScrollMessages: SendMessage WM_HSCROLL #3"); 1.2995 + mTextArea->SetAttribute(NS_LITERAL_STRING("style"), EmptyString()); 1.2996 + return false; 1.2997 + } 1.2998 + 1.2999 + prevX = x; 1.3000 + prevY = y; 1.3001 + textArea->GetScrollTop(&y); 1.3002 + textArea->GetScrollLeft(&x); 1.3003 + 1.3004 + DO_CHECK(x <= kLineWidth, "TestScrollMessages: SendMessage WM_HSCROLL #3"); 1.3005 + DO_CHECK(y != prevY, "TestScrollMessages: SendMessage WM_HSCROLL #3"); 1.3006 + 1.3007 + const int32_t kPageWidth = x; 1.3008 + const int32_t kPageHeight = y; 1.3009 + 1.3010 + ::SendMessage(wnd, WM_VSCROLL, SB_LINEDOWN, 0); 1.3011 + ::SendMessage(wnd, WM_VSCROLL, SB_LINEUP, 0); 1.3012 + ::SendMessage(wnd, WM_HSCROLL, SB_LINERIGHT, 0); 1.3013 + ::SendMessage(wnd, WM_HSCROLL, SB_LINELEFT, 0); 1.3014 + 1.3015 + prevX = x; 1.3016 + prevY = y; 1.3017 + textArea->GetScrollTop(&y); 1.3018 + textArea->GetScrollLeft(&x); 1.3019 + 1.3020 + DO_CHECK(x != prevX, "TestScrollMessages: SB_LINELEFT scrolled wrong amount"); 1.3021 + DO_CHECK(y != prevY, "TestScrollMessages: SB_LINEUP scrolled wrong amount"); 1.3022 + 1.3023 + if (::SendMessage(wnd, WM_VSCROLL, SB_PAGEUP, 0) != 0) { 1.3024 + fail("TestScrollMessages: SendMessage WM_VSCROLL #4"); 1.3025 + mTextArea->SetAttribute(NS_LITERAL_STRING("style"), EmptyString()); 1.3026 + return false; 1.3027 + } 1.3028 + 1.3029 + prevX = x; 1.3030 + prevY = y; 1.3031 + textArea->GetScrollTop(&y); 1.3032 + textArea->GetScrollLeft(&x); 1.3033 + 1.3034 + DO_CHECK(x != prevX, "TestScrollMessages: SendMessage WM_VSCROLL #4"); 1.3035 + DO_CHECK(y != 0, "TestScrollMessages: SendMessage WM_VSCROLL #4"); 1.3036 + 1.3037 + if (::SendMessage(wnd, WM_HSCROLL, SB_PAGELEFT, 0) != 0) { 1.3038 + fail("TestScrollMessages: SendMessage WM_HSCROLL #4"); 1.3039 + mTextArea->SetAttribute(NS_LITERAL_STRING("style"), EmptyString()); 1.3040 + return false; 1.3041 + } 1.3042 + 1.3043 + prevX = x; 1.3044 + prevY = y; 1.3045 + textArea->GetScrollTop(&y); 1.3046 + textArea->GetScrollLeft(&x); 1.3047 + 1.3048 + DO_CHECK(x != 0, "TestScrollMessages: SendMessage WM_HSCROLL #4"); 1.3049 + DO_CHECK(y != 0, "TestScrollMessages: SendMessage WM_HSCROLL #4"); 1.3050 + 1.3051 + if (::SendMessage(wnd, WM_VSCROLL, SB_BOTTOM, 0) != 0) { 1.3052 + fail("TestScrollMessages: SendMessage WM_VSCROLL #5"); 1.3053 + mTextArea->SetAttribute(NS_LITERAL_STRING("style"), EmptyString()); 1.3054 + return false; 1.3055 + } 1.3056 + 1.3057 + prevX = x; 1.3058 + prevY = y; 1.3059 + textArea->GetScrollTop(&y); 1.3060 + textArea->GetScrollLeft(&x); 1.3061 + 1.3062 + DO_CHECK(x != 0, "TestScrollMessages: SendMessage WM_VSCROLL #5"); 1.3063 + DO_CHECK(y <= kPageHeight, "TestScrollMessages: SendMessage WM_VSCROLL #5"); 1.3064 + 1.3065 + if (::SendMessage(wnd, WM_HSCROLL, SB_RIGHT, 0) != 0) { 1.3066 + fail("TestScrollMessages: SendMessage WM_HSCROLL #6"); 1.3067 + mTextArea->SetAttribute(NS_LITERAL_STRING("style"), EmptyString()); 1.3068 + return false; 1.3069 + } 1.3070 + 1.3071 + prevX = x; 1.3072 + prevY = y; 1.3073 + textArea->GetScrollTop(&y); 1.3074 + textArea->GetScrollLeft(&x); 1.3075 + 1.3076 + DO_CHECK(x <= kPageWidth, "TestScrollMessages: SendMessage WM_HSCROLL #5"); 1.3077 + DO_CHECK(y != prevY, "TestScrollMessages: SendMessage WM_HSCROLL #5"); 1.3078 + 1.3079 + ::SendMessage(wnd, WM_VSCROLL, SB_LINEDOWN, 0); 1.3080 + ::SendMessage(wnd, WM_HSCROLL, SB_LINERIGHT, 0); 1.3081 + 1.3082 + prevX = x; 1.3083 + prevY = y; 1.3084 + textArea->GetScrollTop(&y); 1.3085 + textArea->GetScrollLeft(&x); 1.3086 + 1.3087 + DO_CHECK(x != prevX, "SB_RIGHT didn't scroll to right most"); 1.3088 + DO_CHECK(y != prevY, "SB_BOTTOM didn't scroll to bottom most"); 1.3089 + 1.3090 + ::SendMessage(wnd, WM_VSCROLL, SB_PAGEUP, 0); 1.3091 + ::SendMessage(wnd, WM_VSCROLL, SB_PAGEDOWN, 0); 1.3092 + ::SendMessage(wnd, WM_HSCROLL, SB_PAGELEFT, 0); 1.3093 + ::SendMessage(wnd, WM_HSCROLL, SB_PAGERIGHT, 0); 1.3094 + 1.3095 + prevX = x; 1.3096 + prevY = y; 1.3097 + textArea->GetScrollTop(&y); 1.3098 + textArea->GetScrollLeft(&x); 1.3099 + 1.3100 + DO_CHECK(x != prevX, "TestScrollMessages: SB_PAGELEFT scrolled wrong amount"); 1.3101 + DO_CHECK(y != prevY, "TestScrollMessages: SB_PAGEUP scrolled wrong amount"); 1.3102 + 1.3103 + if (::SendMessage(wnd, WM_VSCROLL, SB_TOP, 0) != 0) { 1.3104 + fail("TestScrollMessages: SendMessage WM_VSCROLL #6"); 1.3105 + mTextArea->SetAttribute(NS_LITERAL_STRING("style"), EmptyString()); 1.3106 + return false; 1.3107 + } 1.3108 + 1.3109 + prevX = x; 1.3110 + prevY = y; 1.3111 + textArea->GetScrollTop(&y); 1.3112 + textArea->GetScrollLeft(&x); 1.3113 + 1.3114 + DO_CHECK(x != prevX, "TestScrollMessages: SendMessage WM_VSCROLL #6"); 1.3115 + DO_CHECK(y != 0, "TestScrollMessages: SendMessage WM_VSCROLL #6"); 1.3116 + 1.3117 + if (::SendMessage(wnd, WM_HSCROLL, SB_LEFT, 0) != 0) { 1.3118 + fail("TestScrollMessages: SendMessage WM_HSCROLL #4"); 1.3119 + mTextArea->SetAttribute(NS_LITERAL_STRING("style"), EmptyString()); 1.3120 + return false; 1.3121 + } 1.3122 + 1.3123 + prevX = x; 1.3124 + prevY = y; 1.3125 + textArea->GetScrollTop(&y); 1.3126 + textArea->GetScrollLeft(&x); 1.3127 + 1.3128 + DO_CHECK(x != 0, "TestScrollMessages: SendMessage WM_HSCROLL #6"); 1.3129 + DO_CHECK(y != 0, "TestScrollMessages: SendMessage WM_HSCROLL #6"); 1.3130 +#undef DO_CHECK 1.3131 + 1.3132 + mTextArea->SetAttribute(NS_LITERAL_STRING("style"), EmptyString()); 1.3133 + return true; 1.3134 +} 1.3135 + 1.3136 +bool 1.3137 +TestApp::GetWidget(nsIWidget** aWidget) 1.3138 +{ 1.3139 + nsCOMPtr<nsIDocShell> docShell; 1.3140 + nsresult rv = mWindow->GetDocShell(getter_AddRefs(docShell)); 1.3141 + if (NS_FAILED(rv) || !docShell) { 1.3142 + return false; 1.3143 + } 1.3144 + 1.3145 + nsCOMPtr<nsIPresShell> presShell; 1.3146 + rv = docShell->GetPresShell(getter_AddRefs(presShell)); 1.3147 + if (NS_FAILED(rv) || !presShell) { 1.3148 + return false; 1.3149 + } 1.3150 + 1.3151 + nsRefPtr<nsViewManager> viewManager = presShell->GetViewManager(); 1.3152 + if (!viewManager) { 1.3153 + return false; 1.3154 + } 1.3155 + 1.3156 + rv = viewManager->GetRootWidget(aWidget); 1.3157 + return (NS_SUCCEEDED(rv) && aWidget); 1.3158 +} 1.3159 + 1.3160 +nsresult 1.3161 +TestApp::GetSelCon(nsISelectionController** aSelCon) 1.3162 +{ 1.3163 + nsCOMPtr<nsIDocShell> docShell; 1.3164 + nsresult nsr = mWindow->GetDocShell(getter_AddRefs(docShell)); 1.3165 + if (NS_SUCCEEDED(nsr) && docShell) { 1.3166 + nsCOMPtr<nsIPresShell> presShell; 1.3167 + nsr = docShell->GetPresShell(getter_AddRefs(presShell)); 1.3168 + if (NS_SUCCEEDED(nsr) && presShell) { 1.3169 + nsIFrame* frame = 1.3170 + nsCOMPtr<nsIContent>(do_QueryInterface(mCurrentNode))->GetPrimaryFrame(); 1.3171 + if (frame) { 1.3172 + nsPresContext* presContext = presShell->GetPresContext(); 1.3173 + if (presContext) { 1.3174 + nsr = frame->GetSelectionController(presContext, aSelCon); 1.3175 + } 1.3176 + } 1.3177 + } 1.3178 + } 1.3179 + return nsr; 1.3180 +} 1.3181 + 1.3182 +int main(int argc, char** argv) 1.3183 +{ 1.3184 + ScopedXPCOM xpcom("TestWinTSF (bug #88831)"); 1.3185 + if (xpcom.failed()) 1.3186 + return 1; 1.3187 + 1.3188 + nsRefPtr<TestApp> tests = new TestApp(); 1.3189 + if (!tests) 1.3190 + return 1; 1.3191 + 1.3192 + if (NS_FAILED(tests->Run())) { 1.3193 + fail("run failed"); 1.3194 + return 1; 1.3195 + } 1.3196 + return int(tests->CheckFailed()); 1.3197 +}