Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifndef NSTEXTSTORE_H_
7 #define NSTEXTSTORE_H_
9 #include "nsAutoPtr.h"
10 #include "nsString.h"
11 #include "nsCOMPtr.h"
12 #include "nsIWidget.h"
13 #include "nsWindowBase.h"
14 #include "mozilla/Attributes.h"
15 #include "mozilla/TextRange.h"
16 #include "mozilla/WindowsVersion.h"
18 #include <msctf.h>
19 #include <textstor.h>
21 // GUID_PROP_INPUTSCOPE is declared in inputscope.h using INIT_GUID.
22 // With initguid.h, we get its instance instead of extern declaration.
23 #ifdef INPUTSCOPE_INIT_GUID
24 #include <initguid.h>
25 #endif
26 #include <inputscope.h>
28 // TSF InputScope, for earlier SDK 8
29 #define IS_SEARCH static_cast<InputScope>(50)
31 struct ITfThreadMgr;
32 struct ITfDocumentMgr;
33 struct ITfDisplayAttributeMgr;
34 struct ITfCategoryMgr;
35 class nsWindow;
36 #ifdef MOZ_METRO
37 class MetroWidget;
38 #endif
40 namespace mozilla {
41 namespace widget {
42 struct MSGResult;
43 } // namespace widget
44 } // namespace mozilla
46 /*
47 * Text Services Framework text store
48 */
50 class nsTextStore MOZ_FINAL : public ITextStoreACP,
51 public ITfContextOwnerCompositionSink,
52 public ITfActiveLanguageProfileNotifySink,
53 public ITfInputProcessorProfileActivationSink
54 {
55 public: /*IUnknown*/
56 STDMETHODIMP_(ULONG) AddRef(void);
57 STDMETHODIMP QueryInterface(REFIID, void**);
58 STDMETHODIMP_(ULONG) Release(void);
60 public: /*ITextStoreACP*/
61 STDMETHODIMP AdviseSink(REFIID, IUnknown*, DWORD);
62 STDMETHODIMP UnadviseSink(IUnknown*);
63 STDMETHODIMP RequestLock(DWORD, HRESULT*);
64 STDMETHODIMP GetStatus(TS_STATUS*);
65 STDMETHODIMP QueryInsert(LONG, LONG, ULONG, LONG*, LONG*);
66 STDMETHODIMP GetSelection(ULONG, ULONG, TS_SELECTION_ACP*, ULONG*);
67 STDMETHODIMP SetSelection(ULONG, const TS_SELECTION_ACP*);
68 STDMETHODIMP GetText(LONG, LONG, WCHAR*, ULONG, ULONG*, TS_RUNINFO*, ULONG,
69 ULONG*, LONG*);
70 STDMETHODIMP SetText(DWORD, LONG, LONG, const WCHAR*, ULONG, TS_TEXTCHANGE*);
71 STDMETHODIMP GetFormattedText(LONG, LONG, IDataObject**);
72 STDMETHODIMP GetEmbedded(LONG, REFGUID, REFIID, IUnknown**);
73 STDMETHODIMP QueryInsertEmbedded(const GUID*, const FORMATETC*, BOOL*);
74 STDMETHODIMP InsertEmbedded(DWORD, LONG, LONG, IDataObject*, TS_TEXTCHANGE*);
75 STDMETHODIMP RequestSupportedAttrs(DWORD, ULONG, const TS_ATTRID*);
76 STDMETHODIMP RequestAttrsAtPosition(LONG, ULONG, const TS_ATTRID*, DWORD);
77 STDMETHODIMP RequestAttrsTransitioningAtPosition(LONG, ULONG,
78 const TS_ATTRID*, DWORD);
79 STDMETHODIMP FindNextAttrTransition(LONG, LONG, ULONG, const TS_ATTRID*,
80 DWORD, LONG*, BOOL*, LONG*);
81 STDMETHODIMP RetrieveRequestedAttrs(ULONG, TS_ATTRVAL*, ULONG*);
82 STDMETHODIMP GetEndACP(LONG*);
83 STDMETHODIMP GetActiveView(TsViewCookie*);
84 STDMETHODIMP GetACPFromPoint(TsViewCookie, const POINT*, DWORD, LONG*);
85 STDMETHODIMP GetTextExt(TsViewCookie, LONG, LONG, RECT*, BOOL*);
86 STDMETHODIMP GetScreenExt(TsViewCookie, RECT*);
87 STDMETHODIMP GetWnd(TsViewCookie, HWND*);
88 STDMETHODIMP InsertTextAtSelection(DWORD, const WCHAR*, ULONG, LONG*, LONG*,
89 TS_TEXTCHANGE*);
90 STDMETHODIMP InsertEmbeddedAtSelection(DWORD, IDataObject*, LONG*, LONG*,
91 TS_TEXTCHANGE*);
93 public: /*ITfContextOwnerCompositionSink*/
94 STDMETHODIMP OnStartComposition(ITfCompositionView*, BOOL*);
95 STDMETHODIMP OnUpdateComposition(ITfCompositionView*, ITfRange*);
96 STDMETHODIMP OnEndComposition(ITfCompositionView*);
98 public: /*ITfActiveLanguageProfileNotifySink*/
99 STDMETHODIMP OnActivated(REFCLSID clsid, REFGUID guidProfile,
100 BOOL fActivated);
102 public: /*ITfInputProcessorProfileActivationSink*/
103 STDMETHODIMP OnActivated(DWORD, LANGID, REFCLSID, REFGUID, REFGUID,
104 HKL, DWORD);
106 protected:
107 typedef mozilla::widget::IMENotification IMENotification;
108 typedef mozilla::widget::IMEState IMEState;
109 typedef mozilla::widget::InputContext InputContext;
110 typedef mozilla::widget::InputContextAction InputContextAction;
112 public:
113 static void Initialize(void);
114 static void Terminate(void);
116 static bool ProcessRawKeyMessage(const MSG& aMsg);
117 static void ProcessMessage(nsWindowBase* aWindow, UINT aMessage,
118 WPARAM& aWParam, LPARAM& aLParam,
119 mozilla::widget::MSGResult& aResult);
122 static void SetIMEOpenState(bool);
123 static bool GetIMEOpenState(void);
125 static void CommitComposition(bool aDiscard)
126 {
127 NS_ENSURE_TRUE_VOID(sTsfTextStore);
128 sTsfTextStore->CommitCompositionInternal(aDiscard);
129 }
131 static void SetInputContext(nsWindowBase* aWidget,
132 const InputContext& aContext,
133 const InputContextAction& aAction);
135 static nsresult OnFocusChange(bool aGotFocus,
136 nsWindowBase* aFocusedWidget,
137 IMEState::Enabled aIMEEnabled);
138 static nsresult OnTextChange(const IMENotification& aIMENotification)
139 {
140 NS_ENSURE_TRUE(sTsfTextStore, NS_ERROR_NOT_AVAILABLE);
141 return sTsfTextStore->OnTextChangeInternal(aIMENotification);
142 }
144 static nsresult OnSelectionChange(void)
145 {
146 NS_ENSURE_TRUE(sTsfTextStore, NS_ERROR_NOT_AVAILABLE);
147 return sTsfTextStore->OnSelectionChangeInternal();
148 }
150 static nsresult OnLayoutChange()
151 {
152 NS_ENSURE_TRUE(sTsfTextStore, NS_ERROR_NOT_AVAILABLE);
153 return sTsfTextStore->OnLayoutChangeInternal();
154 }
156 static nsIMEUpdatePreference GetIMEUpdatePreference();
158 // Returns the address of the pointer so that the TSF automatic test can
159 // replace the system object with a custom implementation for testing.
160 static void* GetNativeData(uint32_t aDataType)
161 {
162 switch (aDataType) {
163 case NS_NATIVE_TSF_THREAD_MGR:
164 Initialize(); // Apply any previous changes
165 return static_cast<void*>(&sTsfThreadMgr);
166 case NS_NATIVE_TSF_CATEGORY_MGR:
167 return static_cast<void*>(&sCategoryMgr);
168 case NS_NATIVE_TSF_DISPLAY_ATTR_MGR:
169 return static_cast<void*>(&sDisplayAttrMgr);
170 default:
171 return nullptr;
172 }
173 }
175 static ITfMessagePump* GetMessagePump()
176 {
177 return sMessagePump;
178 }
180 static void* GetTextStore()
181 {
182 return static_cast<void*>(sTsfTextStore);
183 }
185 static bool ThinksHavingFocus()
186 {
187 return (sTsfTextStore && sTsfTextStore->mContext);
188 }
190 static bool IsInTSFMode()
191 {
192 return sTsfThreadMgr != nullptr;
193 }
195 static bool IsComposing()
196 {
197 return (sTsfTextStore && sTsfTextStore->mComposition.IsComposing());
198 }
200 static bool IsComposingOn(nsWindowBase* aWidget)
201 {
202 return (IsComposing() && sTsfTextStore->mWidget == aWidget);
203 }
205 static bool IsIMM_IME()
206 {
207 if (!sTsfTextStore || !sTsfTextStore->EnsureInitActiveTIPKeyboard()) {
208 return IsIMM_IME(::GetKeyboardLayout(0));
209 }
210 return sTsfTextStore->mIsIMM_IME;
211 }
213 static bool IsIMM_IME(HKL aHKL)
214 {
215 return (::ImmGetIMEFileNameW(aHKL, nullptr, 0) > 0);
216 }
218 #ifdef DEBUG
219 // Returns true when keyboard layout has IME (TIP).
220 static bool CurrentKeyboardLayoutHasIME();
221 #endif // #ifdef DEBUG
223 protected:
224 nsTextStore();
225 ~nsTextStore();
227 bool Init(ITfThreadMgr* aThreadMgr);
229 static void MarkContextAsKeyboardDisabled(ITfContext* aContext);
230 static void MarkContextAsEmpty(ITfContext* aContext);
232 static bool IsTIPCategoryKeyboard(REFCLSID aTextService, LANGID aLangID,
233 REFGUID aProfile);
234 static void GetTIPDescription(REFCLSID aTextService, LANGID aLangID,
235 REFGUID aProfile, nsAString& aDescription);
237 bool Create(nsWindowBase* aWidget);
238 bool Destroy(void);
240 bool IsReadLock(DWORD aLock) const
241 {
242 return (TS_LF_READ == (aLock & TS_LF_READ));
243 }
244 bool IsReadWriteLock(DWORD aLock) const
245 {
246 return (TS_LF_READWRITE == (aLock & TS_LF_READWRITE));
247 }
248 bool IsReadLocked() const { return IsReadLock(mLock); }
249 bool IsReadWriteLocked() const { return IsReadWriteLock(mLock); }
251 // This is called immediately after a call of OnLockGranted() of mSink.
252 // Note that mLock isn't cleared yet when this is called.
253 void DidLockGranted();
255 bool GetScreenExtInternal(RECT &aScreenExt);
256 // If aDispatchTextEvent is true, this method will dispatch text event if
257 // this is called during IME composing. aDispatchTextEvent should be true
258 // only when this is called from SetSelection. Because otherwise, the text
259 // event should not be sent from here.
260 HRESULT SetSelectionInternal(const TS_SELECTION_ACP*,
261 bool aDispatchTextEvent = false);
262 bool InsertTextAtSelectionInternal(const nsAString &aInsertStr,
263 TS_TEXTCHANGE* aTextChange);
264 void CommitCompositionInternal(bool);
265 nsresult OnTextChangeInternal(const IMENotification& aIMENotification);
266 nsresult OnSelectionChangeInternal(void);
267 HRESULT GetDisplayAttribute(ITfProperty* aProperty,
268 ITfRange* aRange,
269 TF_DISPLAYATTRIBUTE* aResult);
270 HRESULT RestartCompositionIfNecessary(ITfRange* pRangeNew = nullptr);
272 // Following methods record composing action(s) to mPendingActions.
273 // They will be flushed FlushPendingActions().
274 HRESULT RecordCompositionStartAction(ITfCompositionView* aCompositionView,
275 ITfRange* aRange,
276 bool aPreserveSelection);
277 HRESULT RecordCompositionUpdateAction();
278 HRESULT RecordCompositionEndAction();
280 // FlushPendingActions() performs pending actions recorded in mPendingActions
281 // and clear it.
282 void FlushPendingActions();
284 nsresult OnLayoutChangeInternal();
285 HRESULT ProcessScopeRequest(DWORD dwFlags,
286 ULONG cFilterAttrs,
287 const TS_ATTRID *paFilterAttrs);
288 void SetInputScope(const nsString& aHTMLInputType);
290 // Creates native caret over our caret. This method only works on desktop
291 // application. Otherwise, this does nothing.
292 void CreateNativeCaret();
294 bool EnsureInitActiveTIPKeyboard();
296 // Holds the pointer to our current win32 or metro widget
297 nsRefPtr<nsWindowBase> mWidget;
298 // Document manager for the currently focused editor
299 nsRefPtr<ITfDocumentMgr> mDocumentMgr;
300 // Edit cookie associated with the current editing context
301 DWORD mEditCookie;
302 // Cookie of installing ITfInputProcessorProfileActivationSink
303 DWORD mIPProfileCookie;
304 // Cookie of installing ITfActiveLanguageProfileNotifySink
305 DWORD mLangProfileCookie;
306 // Editing context at the bottom of mDocumentMgr's context stack
307 nsRefPtr<ITfContext> mContext;
308 // Currently installed notification sink
309 nsRefPtr<ITextStoreACPSink> mSink;
310 // TS_AS_* mask of what events to notify
311 DWORD mSinkMask;
312 // 0 if not locked, otherwise TS_LF_* indicating the current lock
313 DWORD mLock;
314 // 0 if no lock is queued, otherwise TS_LF_* indicating the queue lock
315 DWORD mLockQueued;
316 // Active TIP keyboard's description. If active language profile isn't TIP,
317 // i.e., IMM-IME or just a keyboard layout, this is empty.
318 nsString mActiveTIPKeyboardDescription;
320 class Composition MOZ_FINAL
321 {
322 public:
323 // nullptr if no composition is active, otherwise the current composition
324 nsRefPtr<ITfCompositionView> mView;
326 // Current copy of the active composition string. Only mString is
327 // changed during a InsertTextAtSelection call if we have a composition.
328 // mString acts as a buffer until OnUpdateComposition is called
329 // and mString is flushed to editor through NS_TEXT_TEXT. This
330 // way all changes are updated in batches to avoid
331 // inconsistencies/artifacts.
332 nsString mString;
334 // The latest composition string which was dispatched by composition update
335 // event.
336 nsString mLastData;
338 // The start of the current active composition, in ACP offsets
339 LONG mStart;
341 bool IsComposing() const
342 {
343 return (mView != nullptr);
344 }
346 LONG EndOffset() const
347 {
348 return mStart + static_cast<LONG>(mString.Length());
349 }
351 // Start() and End() updates the members for emulating the latest state.
352 // Unless flush the pending actions, this data never matches the actual
353 // content.
354 void Start(ITfCompositionView* aCompositionView,
355 LONG aCompositionStartOffset,
356 const nsAString& aCompositionString);
357 void End();
358 };
359 // While the document is locked, we cannot dispatch any events which cause
360 // DOM events since the DOM events' handlers may modify the locked document.
361 // However, even while the document is locked, TSF may queries us.
362 // For that, nsTextStore modifies mComposition even while the document is
363 // locked. With mComposition, query methods can returns the text content
364 // information.
365 Composition mComposition;
367 class Selection
368 {
369 public:
370 Selection() : mDirty(true) {}
372 bool IsDirty() const { return mDirty; };
373 void MarkDirty() { mDirty = true; }
375 TS_SELECTION_ACP& ACP()
376 {
377 MOZ_ASSERT(!mDirty);
378 return mACP;
379 }
381 void SetSelection(const TS_SELECTION_ACP& aSelection)
382 {
383 mDirty = false;
384 mACP = aSelection;
385 // Selection end must be active in our editor.
386 if (mACP.style.ase != TS_AE_START) {
387 mACP.style.ase = TS_AE_END;
388 }
389 // We're not support interim char selection for now.
390 // XXX Probably, this is necessary for supporting South Asian languages.
391 mACP.style.fInterimChar = FALSE;
392 }
394 void SetSelection(uint32_t aStart, uint32_t aLength, bool aReversed)
395 {
396 mDirty = false;
397 mACP.acpStart = static_cast<LONG>(aStart);
398 mACP.acpEnd = static_cast<LONG>(aStart + aLength);
399 mACP.style.ase = aReversed ? TS_AE_START : TS_AE_END;
400 mACP.style.fInterimChar = FALSE;
401 }
403 bool IsCollapsed() const
404 {
405 MOZ_ASSERT(!mDirty);
406 return (mACP.acpStart == mACP.acpEnd);
407 }
409 void CollapseAt(uint32_t aOffset)
410 {
411 mDirty = false;
412 mACP.acpStart = mACP.acpEnd = static_cast<LONG>(aOffset);
413 mACP.style.ase = TS_AE_END;
414 mACP.style.fInterimChar = FALSE;
415 }
417 LONG MinOffset() const
418 {
419 MOZ_ASSERT(!mDirty);
420 LONG min = std::min(mACP.acpStart, mACP.acpEnd);
421 MOZ_ASSERT(min >= 0);
422 return min;
423 }
425 LONG MaxOffset() const
426 {
427 MOZ_ASSERT(!mDirty);
428 LONG max = std::max(mACP.acpStart, mACP.acpEnd);
429 MOZ_ASSERT(max >= 0);
430 return max;
431 }
433 LONG StartOffset() const
434 {
435 MOZ_ASSERT(!mDirty);
436 MOZ_ASSERT(mACP.acpStart >= 0);
437 return mACP.acpStart;
438 }
440 LONG EndOffset() const
441 {
442 MOZ_ASSERT(!mDirty);
443 MOZ_ASSERT(mACP.acpEnd >= 0);
444 return mACP.acpEnd;
445 }
447 LONG Length() const
448 {
449 MOZ_ASSERT(!mDirty);
450 MOZ_ASSERT(mACP.acpEnd >= mACP.acpStart);
451 return std::abs(mACP.acpEnd - mACP.acpStart);
452 }
454 bool IsReversed() const
455 {
456 MOZ_ASSERT(!mDirty);
457 return (mACP.style.ase == TS_AE_START);
458 }
460 TsActiveSelEnd ActiveSelEnd() const
461 {
462 MOZ_ASSERT(!mDirty);
463 return mACP.style.ase;
464 }
466 bool IsInterimChar() const
467 {
468 MOZ_ASSERT(!mDirty);
469 return (mACP.style.fInterimChar != FALSE);
470 }
472 private:
473 TS_SELECTION_ACP mACP;
474 bool mDirty;
475 };
476 // Don't access mSelection directly except at calling MarkDirty().
477 // Use CurrentSelection() instead. This is marked as dirty when the
478 // selection or content is changed without document lock.
479 Selection mSelection;
481 // Get "current selection" while the document is locked. The selection is
482 // NOT modified immediately during document lock. The pending changes will
483 // be flushed at unlocking the document. The "current selection" is the
484 // modified selection during document lock. This is also called
485 // CurrentContent() too.
486 Selection& CurrentSelection();
488 struct PendingAction MOZ_FINAL
489 {
490 enum ActionType MOZ_ENUM_TYPE(uint8_t)
491 {
492 COMPOSITION_START,
493 COMPOSITION_UPDATE,
494 COMPOSITION_END,
495 SELECTION_SET
496 };
497 ActionType mType;
498 // For compositionstart and selectionset
499 LONG mSelectionStart;
500 LONG mSelectionLength;
501 // For compositionupdate and compositionend
502 nsString mData;
503 // For compositionupdate
504 nsRefPtr<mozilla::TextRangeArray> mRanges;
505 // For selectionset
506 bool mSelectionReversed;
507 };
508 // Items of mPendingActions are appended when TSF tells us to need to dispatch
509 // DOM composition events. However, we cannot dispatch while the document is
510 // locked because it can cause modifying the locked document. So, the pending
511 // actions should be performed when document lock is unlocked.
512 nsTArray<PendingAction> mPendingActions;
514 PendingAction* GetPendingCompositionUpdate()
515 {
516 if (!mPendingActions.IsEmpty()) {
517 PendingAction& lastAction = mPendingActions.LastElement();
518 if (lastAction.mType == PendingAction::COMPOSITION_UPDATE) {
519 return &lastAction;
520 }
521 }
522 PendingAction* newAction = mPendingActions.AppendElement();
523 newAction->mType = PendingAction::COMPOSITION_UPDATE;
524 newAction->mRanges = new mozilla::TextRangeArray();
525 return newAction;
526 }
528 // When On*Composition() is called without document lock, we need to flush
529 // the recorded actions at quitting the method.
530 // AutoPendingActionAndContentFlusher class is usedful for it.
531 class MOZ_STACK_CLASS AutoPendingActionAndContentFlusher MOZ_FINAL
532 {
533 public:
534 AutoPendingActionAndContentFlusher(nsTextStore* aTextStore)
535 : mTextStore(aTextStore)
536 {
537 MOZ_ASSERT(!mTextStore->mIsRecordingActionsWithoutLock);
538 if (!mTextStore->IsReadWriteLocked()) {
539 mTextStore->mIsRecordingActionsWithoutLock = true;
540 }
541 }
543 ~AutoPendingActionAndContentFlusher()
544 {
545 if (!mTextStore->mIsRecordingActionsWithoutLock) {
546 return;
547 }
548 mTextStore->FlushPendingActions();
549 mTextStore->mIsRecordingActionsWithoutLock = false;
550 }
552 private:
553 AutoPendingActionAndContentFlusher() {}
555 nsRefPtr<nsTextStore> mTextStore;
556 };
558 class Content MOZ_FINAL
559 {
560 public:
561 Content(nsTextStore::Composition& aComposition,
562 nsTextStore::Selection& aSelection) :
563 mComposition(aComposition), mSelection(aSelection)
564 {
565 Clear();
566 }
568 void Clear()
569 {
570 mText.Truncate();
571 mInitialized = false;
572 }
574 bool IsInitialized() const { return mInitialized; }
576 void Init(const nsAString& aText)
577 {
578 mText = aText;
579 mMinTextModifiedOffset = NOT_MODIFIED;
580 mInitialized = true;
581 }
583 const nsDependentSubstring GetSelectedText() const;
584 const nsDependentSubstring GetSubstring(uint32_t aStart,
585 uint32_t aLength) const;
586 void ReplaceSelectedTextWith(const nsAString& aString);
587 void ReplaceTextWith(LONG aStart, LONG aLength, const nsAString& aString);
589 void StartComposition(ITfCompositionView* aCompositionView,
590 const PendingAction& aCompStart,
591 bool aPreserveSelection);
592 void EndComposition(const PendingAction& aCompEnd);
594 const nsString& Text() const
595 {
596 MOZ_ASSERT(mInitialized);
597 return mText;
598 }
600 // Returns true if layout of the character at the aOffset has not been
601 // calculated.
602 bool IsLayoutChangedAfter(uint32_t aOffset) const
603 {
604 return mInitialized && (mMinTextModifiedOffset < aOffset);
605 }
606 // Returns true if layout of the content has been changed, i.e., the new
607 // layout has not been calculated.
608 bool IsLayoutChanged() const
609 {
610 return mInitialized && (mMinTextModifiedOffset != NOT_MODIFIED);
611 }
613 nsTextStore::Composition& Composition() { return mComposition; }
614 nsTextStore::Selection& Selection() { return mSelection; }
616 private:
617 nsString mText;
618 nsTextStore::Composition& mComposition;
619 nsTextStore::Selection& mSelection;
621 // The minimum offset of modified part of the text.
622 enum MOZ_ENUM_TYPE(uint32_t)
623 {
624 NOT_MODIFIED = UINT32_MAX
625 };
626 uint32_t mMinTextModifiedOffset;
628 bool mInitialized;
629 };
630 // mContent caches "current content" of the document ONLY while the document
631 // is locked. I.e., the content is cleared at unlocking the document since
632 // we need to reduce the memory usage. This is initialized by
633 // CurrentContent() automatically, so, don't access this member directly
634 // except at calling Clear(), IsInitialized(), IsLayoutChangedAfter() or
635 // IsLayoutChanged().
636 Content mContent;
638 Content& CurrentContent();
640 // The input scopes for this context, defaults to IS_DEFAULT.
641 nsTArray<InputScope> mInputScopes;
642 bool mInputScopeDetected;
643 bool mInputScopeRequested;
644 // If edit actions are being recorded without document lock, this is true.
645 // Otherwise, false.
646 bool mIsRecordingActionsWithoutLock;
647 // During recording actions, we shouldn't call mSink->OnSelectionChange()
648 // because it may cause TSF request new lock. This is a problem if the
649 // selection change is caused by a call of On*Composition() without document
650 // lock since RequestLock() tries to flush the pending actions again (which
651 // are flushing). Therefore, OnSelectionChangeInternal() sets this true
652 // during recoding actions and then, RequestLock() will call
653 // mSink->OnSelectionChange() after mLock becomes 0.
654 bool mPendingOnSelectionChange;
655 // If GetTextExt() or GetACPFromPoint() is called and the layout hasn't been
656 // calculated yet, these methods return TS_E_NOLAYOUT. Then, RequestLock()
657 // will call mSink->OnLayoutChange() and
658 // ITfContextOwnerServices::OnLayoutChange() after the layout is fixed and
659 // the document is unlocked.
660 bool mPendingOnLayoutChange;
661 // While there is native caret, this is true. Otherwise, false.
662 bool mNativeCaretIsCreated;
664 // True if current IME is implemented with IMM.
665 bool mIsIMM_IME;
666 // True if OnActivated() is already called
667 bool mOnActivatedCalled;
669 // TSF thread manager object for the current application
670 static ITfThreadMgr* sTsfThreadMgr;
671 // sMessagePump is QI'ed from sTsfThreadMgr
672 static ITfMessagePump* sMessagePump;
673 // sKeystrokeMgr is QI'ed from sTsfThreadMgr
674 static ITfKeystrokeMgr* sKeystrokeMgr;
675 // TSF display attribute manager
676 static ITfDisplayAttributeMgr* sDisplayAttrMgr;
677 // TSF category manager
678 static ITfCategoryMgr* sCategoryMgr;
680 // TSF client ID for the current application
681 static DWORD sTsfClientId;
682 // Current text store. Currently only ONE nsTextStore instance is ever used,
683 // although Create is called when an editor is focused and Destroy called
684 // when the focused editor is blurred.
685 static nsTextStore* sTsfTextStore;
687 // For IME (keyboard) disabled state:
688 static ITfDocumentMgr* sTsfDisabledDocumentMgr;
689 static ITfContext* sTsfDisabledContext;
691 static ITfInputProcessorProfiles* sInputProcessorProfiles;
693 // Enables/Disables hack for specific TIP.
694 static bool sCreateNativeCaretForATOK;
696 // Message the Tablet Input Panel uses to flush text during blurring.
697 // See comments in Destroy
698 static UINT sFlushTIPInputMessage;
700 private:
701 ULONG mRefCnt;
702 };
704 #endif /*NSTEXTSTORE_H_*/