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