Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / win8 / metro_driver / ime / text_store.h
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef WIN8_METRO_DRIVER_IME_TEXT_STORE_H_
6 #define WIN8_METRO_DRIVER_IME_TEXT_STORE_H_
7
8 #include <atlbase.h>
9 #include <atlcom.h>
10 #include <initguid.h>
11 #include <inputscope.h>
12 #include <msctf.h>
13
14 #include <deque>
15 #include <vector>
16
17 #include "base/basictypes.h"
18 #include "base/compiler_specific.h"
19 #include "base/memory/ref_counted.h"
20 #include "base/strings/string16.h"
21 #include "base/win/scoped_comptr.h"
22 #include "ui/metro_viewer/ime_types.h"
23
24 namespace metro_driver {
25
26 class TextStoreDelegate;
27
28 // TextStore is used to interact with the input method via TSF manager.
29 // TextStore have a string buffer which is manipulated by TSF manager through
30 // ITextStoreACP interface methods such as SetText().
31 // When the input method updates the composition, TextStore calls
32 // TextInputClient::SetCompositionText(). And when the input method finishes the
33 // composition, TextStore calls TextInputClient::InsertText() and clears the
34 // buffer.
35 //
36 // How TextStore works:
37 //  - The user enters "a".
38 //    - The input method set composition as "a".
39 //    - TSF manager calls TextStore::RequestLock().
40 //    - TextStore callbacks ITextStoreACPSink::OnLockGranted().
41 //    - In OnLockGranted(), TSF manager calls
42 //      - TextStore::OnStartComposition()
43 //      - TextStore::SetText()
44 //        The string buffer is set as "a".
45 //      - TextStore::OnUpdateComposition()
46 //      - TextStore::OnEndEdit()
47 //        TextStore can get the composition information such as underlines.
48 //   - TextStore calls TextInputClient::SetCompositionText().
49 //     "a" is shown with an underline as composition string.
50 // - The user enters <space>.
51 //    - The input method set composition as "A".
52 //    - TSF manager calls TextStore::RequestLock().
53 //    - TextStore callbacks ITextStoreACPSink::OnLockGranted().
54 //    - In OnLockGranted(), TSF manager calls
55 //      - TextStore::SetText()
56 //        The string buffer is set as "A".
57 //      - TextStore::OnUpdateComposition()
58 //      - TextStore::OnEndEdit()
59 //   - TextStore calls TextInputClient::SetCompositionText().
60 //     "A" is shown with an underline as composition string.
61 // - The user enters <enter>.
62 //    - The input method commits "A".
63 //    - TSF manager calls TextStore::RequestLock().
64 //    - TextStore callbacks ITextStoreACPSink::OnLockGranted().
65 //    - In OnLockGranted(), TSF manager calls
66 //      - TextStore::OnEndComposition()
67 //      - TextStore::OnEndEdit()
68 //        TextStore knows "A" is committed.
69 //   - TextStore calls TextInputClient::InsertText().
70 //     "A" is shown as committed string.
71 //   - TextStore clears the string buffer.
72 //   - TextStore calls OnSelectionChange(), OnLayoutChange() and
73 //     OnTextChange() of ITextStoreACPSink to let TSF manager know that the
74 //     string buffer has been changed.
75 //
76 // About the locking scheme:
77 // When TSF manager manipulates the string buffer it calls RequestLock() to get
78 // the lock of the document. If TextStore can grant the lock request, it
79 // callbacks ITextStoreACPSink::OnLockGranted().
80 // RequestLock() is called from only one thread, but called recursively in
81 // OnLockGranted() or OnSelectionChange() or OnLayoutChange() or OnTextChange().
82 // If the document is locked and the lock request is asynchronous, TextStore
83 // queues the request. The queued requests will be handled after the current
84 // lock is removed.
85 // More information about document locks can be found here:
86 //   http://msdn.microsoft.com/en-us/library/ms538064
87 //
88 // More information about TSF can be found here:
89 //   http://msdn.microsoft.com/en-us/library/ms629032
90 class ATL_NO_VTABLE TextStore
91     : public CComObjectRootEx<CComMultiThreadModel>,
92       public ITextStoreACP,
93       public ITfContextOwnerCompositionSink,
94       public ITfTextEditSink {
95  public:
96   virtual ~TextStore();
97
98   BEGIN_COM_MAP(TextStore)
99     COM_INTERFACE_ENTRY(ITextStoreACP)
100     COM_INTERFACE_ENTRY(ITfContextOwnerCompositionSink)
101     COM_INTERFACE_ENTRY(ITfTextEditSink)
102   END_COM_MAP()
103
104   // ITextStoreACP:
105   STDMETHOD(AdviseSink)(REFIID iid, IUnknown* unknown, DWORD mask) override;
106   STDMETHOD(FindNextAttrTransition)(LONG acp_start,
107                                     LONG acp_halt,
108                                     ULONG num_filter_attributes,
109                                     const TS_ATTRID* filter_attributes,
110                                     DWORD flags,
111                                     LONG* acp_next,
112                                     BOOL* found,
113                                     LONG* found_offset) override;
114   STDMETHOD(GetACPFromPoint)(TsViewCookie view_cookie,
115                              const POINT* point,
116                              DWORD flags,
117                              LONG* acp) override;
118   STDMETHOD(GetActiveView)(TsViewCookie* view_cookie) override;
119   STDMETHOD(GetEmbedded)(LONG acp_pos,
120                          REFGUID service,
121                          REFIID iid,
122                          IUnknown** unknown) override;
123   STDMETHOD(GetEndACP)(LONG* acp) override;
124   STDMETHOD(GetFormattedText)(LONG acp_start,
125                               LONG acp_end,
126                               IDataObject** data_object) override;
127   STDMETHOD(GetScreenExt)(TsViewCookie view_cookie, RECT* rect) override;
128   STDMETHOD(GetSelection)(ULONG selection_index,
129                           ULONG selection_buffer_size,
130                           TS_SELECTION_ACP* selection_buffer,
131                           ULONG* fetched_count) override;
132   STDMETHOD(GetStatus)(TS_STATUS* pdcs) override;
133   STDMETHOD(GetText)(LONG acp_start,
134                      LONG acp_end,
135                      wchar_t* text_buffer,
136                      ULONG text_buffer_size,
137                      ULONG* text_buffer_copied,
138                      TS_RUNINFO* run_info_buffer,
139                      ULONG run_info_buffer_size,
140                      ULONG* run_info_buffer_copied,
141                      LONG* next_acp) override;
142   STDMETHOD(GetTextExt)(TsViewCookie view_cookie,
143                         LONG acp_start,
144                         LONG acp_end,
145                         RECT* rect,
146                         BOOL* clipped) override;
147   STDMETHOD(GetWnd)(TsViewCookie view_cookie, HWND* window_handle) override;
148   STDMETHOD(InsertEmbedded)(DWORD flags,
149                             LONG acp_start,
150                             LONG acp_end,
151                             IDataObject* data_object,
152                             TS_TEXTCHANGE* change) override;
153   STDMETHOD(InsertEmbeddedAtSelection)(DWORD flags,
154                                        IDataObject* data_object,
155                                        LONG* acp_start,
156                                        LONG* acp_end,
157                                        TS_TEXTCHANGE* change) override;
158   STDMETHOD(InsertTextAtSelection)(DWORD flags,
159                                    const wchar_t* text_buffer,
160                                    ULONG text_buffer_size,
161                                    LONG* acp_start,
162                                    LONG* acp_end,
163                                    TS_TEXTCHANGE* text_change) override;
164   STDMETHOD(QueryInsert)(LONG acp_test_start,
165                          LONG acp_test_end,
166                          ULONG text_size,
167                          LONG* acp_result_start,
168                          LONG* acp_result_end) override;
169   STDMETHOD(QueryInsertEmbedded)(const GUID* service,
170                                  const FORMATETC* format,
171                                  BOOL* insertable) override;
172   STDMETHOD(RequestAttrsAtPosition)(LONG acp_pos,
173                                     ULONG attribute_buffer_size,
174                                     const TS_ATTRID* attribute_buffer,
175                                     DWORD flags) override;
176   STDMETHOD(RequestAttrsTransitioningAtPosition)(
177       LONG acp_pos,
178       ULONG attribute_buffer_size,
179       const TS_ATTRID* attribute_buffer,
180       DWORD flags) override;
181   STDMETHOD(RequestLock)(DWORD lock_flags, HRESULT* result) override;
182   STDMETHOD(RequestSupportedAttrs)(DWORD flags,
183                                    ULONG attribute_buffer_size,
184                                    const TS_ATTRID* attribute_buffer) override;
185   STDMETHOD(RetrieveRequestedAttrs)(ULONG attribute_buffer_size,
186                                     TS_ATTRVAL* attribute_buffer,
187                                     ULONG* attribute_buffer_copied) override;
188   STDMETHOD(SetSelection)(ULONG selection_buffer_size,
189                           const TS_SELECTION_ACP* selection_buffer) override;
190   STDMETHOD(SetText)(DWORD flags,
191                      LONG acp_start,
192                      LONG acp_end,
193                      const wchar_t* text_buffer,
194                      ULONG text_buffer_size,
195                      TS_TEXTCHANGE* text_change) override;
196   STDMETHOD(UnadviseSink)(IUnknown* unknown) override;
197
198   // ITfContextOwnerCompositionSink:
199   STDMETHOD(OnStartComposition)(ITfCompositionView* composition_view,
200                                 BOOL* ok) override;
201   STDMETHOD(OnUpdateComposition)(ITfCompositionView* composition_view,
202                                  ITfRange* range) override;
203   STDMETHOD(OnEndComposition)(ITfCompositionView* composition_view) override;
204
205   // ITfTextEditSink:
206   STDMETHOD(OnEndEdit)(ITfContext* context, TfEditCookie read_only_edit_cookie,
207                        ITfEditRecord* edit_record) override;
208
209   // Cancels the ongoing composition if exists.
210   bool CancelComposition();
211
212   // Confirms the ongoing composition if exists.
213   bool ConfirmComposition();
214
215   // Sends OnLayoutChange() via |text_store_acp_sink_|.
216   void SendOnLayoutChange();
217
218   // Creates an instance of TextStore. Returns NULL if fails.
219   static scoped_refptr<TextStore> Create(
220       HWND window_handle,
221       const std::vector<InputScope>& input_scopes,
222       TextStoreDelegate* delegate);
223
224  private:
225   friend CComObject<TextStore>;
226   TextStore();
227
228   void Initialize(HWND window_handle,
229                   ITfCategoryMgr* category_manager,
230                   ITfDisplayAttributeMgr* display_attribute_manager,
231                   ITfInputScope* input_scope,
232                   TextStoreDelegate* delegate);
233
234   // Checks if the document has a read-only lock.
235   bool HasReadLock() const;
236
237   // Checks if the document has a read and write lock.
238   bool HasReadWriteLock() const;
239
240   // Gets the display attribute structure.
241   bool GetDisplayAttribute(TfGuidAtom guid_atom,
242                            TF_DISPLAYATTRIBUTE* attribute);
243
244   // Gets the committed string size and underline information of the context.
245   bool GetCompositionStatus(
246       ITfContext* context,
247       const TfEditCookie read_only_edit_cookie,
248       uint32* committed_size,
249       std::vector<metro_viewer::UnderlineInfo>* undelines);
250
251   // A pointer of ITextStoreACPSink, this instance is given in AdviseSink.
252   base::win::ScopedComPtr<ITextStoreACPSink> text_store_acp_sink_;
253
254   // The current mask of |text_store_acp_sink_|.
255   DWORD text_store_acp_sink_mask_;
256
257   // HWND of the attached window.
258   HWND window_handle_;
259
260   //  |string_buffer_| contains committed string and composition string.
261   //  Example: "aoi" is committed, and "umi" is under composition.
262   //    |string_buffer_|: "aoiumi"
263   //    |committed_size_|: 3
264   base::string16 string_buffer_;
265   uint32 committed_size_;
266
267   //  |selection_start_| and |selection_end_| indicates the selection range.
268   //  Example: "iue" is selected
269   //    |string_buffer_|: "aiueo"
270   //    |selection_start_|: 1
271   //    |selection_end_|: 4
272   uint32 selection_start_;
273   uint32 selection_end_;
274
275   //  |start_offset| and |end_offset| of |composition_undelines_| indicates
276   //  the offsets in |string_buffer_|.
277   //  Example: "aoi" is committed. There are two underlines in "umi" and "no".
278   //    |string_buffer_|: "aoiumino"
279   //    |committed_size_|: 3
280   //    underlines_[0].start_offset: 3
281   //    underlines_[0].end_offset: 6
282   //    underlines_[1].start_offset: 6
283   //    underlines_[1].end_offset: 8
284   std::vector<metro_viewer::UnderlineInfo> underlines_;
285
286   // |edit_flag_| indicates that the status is edited during
287   // ITextStoreACPSink::OnLockGranted().
288   bool edit_flag_;
289
290   // The type of current lock.
291   //   0: No lock.
292   //   TS_LF_READ: read-only lock.
293   //   TS_LF_READWRITE: read/write lock.
294   DWORD current_lock_type_;
295
296   // Queue of the lock request used in RequestLock().
297   std::deque<DWORD> lock_queue_;
298
299   // Category manager and Display attribute manager are used to obtain the
300   // attributes of the composition string.
301   base::win::ScopedComPtr<ITfCategoryMgr> category_manager_;
302   base::win::ScopedComPtr<ITfDisplayAttributeMgr> display_attribute_manager_;
303
304   // Represents the context information of this text.
305   base::win::ScopedComPtr<ITfInputScope> input_scope_;
306
307   // The delegate attached to this text store.
308   TextStoreDelegate* delegate_;
309
310   DISALLOW_COPY_AND_ASSIGN(TextStore);
311 };
312
313 }  // namespace metro_driver
314
315 #endif  // WIN8_METRO_DRIVER_IME_TEXT_STORE_H_