widget/windows/nsTextStore.h

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     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_*/

mercurial