Reactos
1/*
2 * PROJECT: ReactOS CTF
3 * LICENSE: LGPL-2.0-or-later (https://spdx.org/licenses/LGPL-2.0-or-later)
4 * PURPOSE: ITfRangeACP implementation
5 * COPYRIGHT: Copyright 2009 Aric Stewart, CodeWeavers
6 * Copyright 2025 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
7 */
8
9#include "precomp.h"
10#include "range.h"
11
12#include <wine/debug.h>
13WINE_DEFAULT_DEBUG_CHANNEL(msctf);
14
15////////////////////////////////////////////////////////////////////////////
16
17CRange::CRange(
18 _In_ ITfContext *context,
19 _In_ TfAnchor anchorStart,
20 _In_ TfAnchor anchorEnd
21)
22 : m_cRefs(1)
23 , m_context(context)
24 , m_anchorStart(anchorStart)
25 , m_anchorEnd(anchorEnd)
26{
27 if (context)
28 context->AddRef();
29}
30
31CRange::~CRange()
32{
33 TRACE("destroying %p\n", this);
34 if (m_context)
35 m_context->Release();
36}
37
38CRange *CRange::_Clone()
39{
40 CRange *pRange = new(cicNoThrow) CRange(m_context, m_anchorStart, m_anchorEnd);
41 if (!pRange)
42 return NULL;
43 return pRange;
44}
45
46HRESULT CRange::_IsEqualX(TfEditCookie ec, BOOL bEnd, ITfRange *pWith, TfAnchor aPos, BOOL *pfEqual)
47{
48 return E_NOTIMPL;
49}
50
51HRESULT CRange::_CompareX(
52 TfEditCookie ec,
53 BOOL bEnd,
54 ITfRange *pWidth,
55 TfAnchor aPos,
56 LONG *plResult)
57{
58 return E_NOTIMPL;
59}
60
61HRESULT CRange::TF_SELECTION_to_TS_SELECTION_ACP(const TF_SELECTION *tf, TS_SELECTION_ACP *tsAcp)
62{
63 if (!tf || !tsAcp || !tf->range)
64 {
65 ERR("E_INVALIDARG: %p, %p, %p\n", tf, tsAcp, tf->range);
66 return E_INVALIDARG;
67 }
68
69 CRange *This = static_cast<CRange *>(static_cast<ITfRangeACP *>(tf->range));
70 tsAcp->acpStart = This->m_anchorStart;
71 tsAcp->acpEnd = This->m_anchorEnd;
72 tsAcp->style.ase = static_cast<TsActiveSelEnd>(tf->style.ase);
73 tsAcp->style.fInterimChar = tf->style.fInterimChar;
74 return S_OK;
75}
76
77STDMETHODIMP CRange::QueryInterface(REFIID riid, void **ppvObj)
78{
79 if (riid == IID_PRIV_CRANGE)
80 {
81 *ppvObj = this;
82 return S_OK; // No AddRef
83 }
84
85 if (riid == IID_IUnknown || riid == IID_ITfRange || riid == IID_ITfRangeACP)
86 *ppvObj = static_cast<ITfRangeACP *>(this);
87 else if (riid == IID_ITfRangeAnchor)
88 *ppvObj = static_cast<ITfRangeAnchor *>(this);
89 else if (riid == IID_ITfSource)
90 *ppvObj = static_cast<ITfSource *>(this);
91 else
92 *ppvObj = NULL;
93
94 if (*ppvObj)
95 {
96 AddRef();
97 return S_OK;
98 }
99
100 WARN("unsupported interface: %s\n", debugstr_guid(&riid));
101 return E_NOINTERFACE;
102}
103
104STDMETHODIMP_(ULONG) CRange::AddRef()
105{
106 TRACE("%p -> ()\n", this);
107 return ::InterlockedIncrement(&m_cRefs);
108}
109
110STDMETHODIMP_(ULONG) CRange::Release()
111{
112 TRACE("%p -> ()\n", this);
113 ULONG ret = InterlockedDecrement(&m_cRefs);
114 if (!ret)
115 delete this;
116 return ret;
117}
118
119STDMETHODIMP CRange::GetText(
120 _In_ TfEditCookie ec,
121 _In_ DWORD dwFlags,
122 _Out_ WCHAR *pchText,
123 _In_ ULONG cchMax,
124 _Out_ ULONG *pcch)
125{
126 FIXME("\n");
127 return E_NOTIMPL;
128}
129
130STDMETHODIMP CRange::SetText(
131 _In_ TfEditCookie ec,
132 _In_ DWORD dwFlags,
133 _In_ const WCHAR *pchText,
134 _In_ LONG cch)
135{
136 FIXME("\n");
137 return E_NOTIMPL;
138}
139
140STDMETHODIMP CRange::GetFormattedText(
141 _In_ TfEditCookie ec,
142 _Out_ IDataObject **ppDataObject)
143{
144 FIXME("\n");
145 return E_NOTIMPL;
146}
147
148STDMETHODIMP CRange::GetEmbedded(
149 _In_ TfEditCookie ec,
150 _In_ REFGUID rguidService,
151 _In_ REFIID riid,
152 _Out_ IUnknown **ppunk)
153{
154 FIXME("\n");
155 return E_NOTIMPL;
156}
157
158STDMETHODIMP CRange::InsertEmbedded(
159 _In_ TfEditCookie ec,
160 _In_ DWORD dwFlags,
161 _In_ IDataObject *pDataObject)
162{
163 FIXME("\n");
164 return E_NOTIMPL;
165}
166
167STDMETHODIMP CRange::ShiftStart(
168 _In_ TfEditCookie ec,
169 _In_ LONG cchReq,
170 _Out_ LONG *pcch,
171 _In_ const TF_HALTCOND *pHalt)
172{
173 FIXME("\n");
174 return E_NOTIMPL;
175}
176
177STDMETHODIMP CRange::ShiftEnd(
178 _In_ TfEditCookie ec,
179 _In_ LONG cchReq,
180 _Out_ LONG *pcch,
181 _In_ const TF_HALTCOND *pHalt)
182{
183 FIXME("\n");
184 return E_NOTIMPL;
185}
186
187STDMETHODIMP CRange::ShiftStartToRange(
188 _In_ TfEditCookie ec,
189 _In_ ITfRange *pRange,
190 _In_ TfAnchor aPos)
191{
192 FIXME("\n");
193 return E_NOTIMPL;
194}
195
196STDMETHODIMP CRange::ShiftEndToRange(
197 _In_ TfEditCookie ec,
198 _In_ ITfRange *pRange,
199 _In_ TfAnchor aPos)
200{
201 FIXME("\n");
202 return E_NOTIMPL;
203}
204
205STDMETHODIMP CRange::ShiftStartRegion(
206 _In_ TfEditCookie ec,
207 _In_ TfShiftDir dir,
208 _Out_ BOOL *pfNoRegion)
209{
210 FIXME("\n");
211 return E_NOTIMPL;
212}
213
214STDMETHODIMP CRange::ShiftEndRegion(
215 _In_ TfEditCookie ec,
216 _In_ TfShiftDir dir,
217 _Out_ BOOL *pfNoRegion)
218{
219 FIXME("\n");
220 return E_NOTIMPL;
221}
222
223STDMETHODIMP CRange::IsEmpty(
224 _In_ TfEditCookie ec,
225 _Out_ BOOL *pfEmpty)
226{
227 TRACE("(%d, %p)\n", ec, pfEmpty);
228 return IsEqualStart(ec, static_cast<ITfRangeACP *>(this), TF_ANCHOR_END, pfEmpty);
229}
230
231STDMETHODIMP CRange::Collapse(
232 _In_ TfEditCookie ec,
233 _In_ TfAnchor aPos)
234{
235 FIXME("\n");
236 return E_NOTIMPL;
237}
238
239STDMETHODIMP CRange::IsEqualStart(
240 _In_ TfEditCookie ec,
241 _In_ ITfRange *pWith,
242 _In_ TfAnchor aPos,
243 _Out_ BOOL *pfEqual)
244{
245 FIXME("\n");
246 return _IsEqualX(ec, FALSE, pWith, aPos, pfEqual);
247}
248
249STDMETHODIMP CRange::IsEqualEnd(
250 _In_ TfEditCookie ec,
251 _In_ ITfRange *pWith,
252 _In_ TfAnchor aPos,
253 _Out_ BOOL *pfEqual)
254{
255 FIXME("\n");
256 return _IsEqualX(ec, TRUE, pWith, aPos, pfEqual);
257}
258
259STDMETHODIMP CRange::CompareStart(
260 _In_ TfEditCookie ec,
261 _In_ ITfRange *pWith,
262 _In_ TfAnchor aPos,
263 _Out_ LONG *plResult)
264{
265 FIXME("\n");
266 return E_NOTIMPL;
267}
268
269STDMETHODIMP CRange::CompareEnd(
270 _In_ TfEditCookie ec,
271 _In_ ITfRange *pWith,
272 _In_ TfAnchor aPos,
273 _Out_ LONG *plResult)
274{
275 FIXME("\n");
276 return E_NOTIMPL;
277}
278
279STDMETHODIMP CRange::AdjustForInsert(
280 _In_ TfEditCookie ec,
281 _In_ ULONG cchInsert,
282 _Out_ BOOL *pfInsertOk)
283{
284 FIXME("\n");
285 return E_NOTIMPL;
286}
287
288STDMETHODIMP CRange::GetGravity(
289 _Out_ TfGravity *pgStart,
290 _Out_ TfGravity *pgEnd)
291{
292 FIXME("\n");
293 return E_NOTIMPL;
294}
295
296STDMETHODIMP CRange::SetGravity(
297 _In_ TfEditCookie ec,
298 _In_ TfGravity gStart,
299 _In_ TfGravity gEnd)
300{
301 FIXME("\n");
302 return E_NOTIMPL;
303}
304
305STDMETHODIMP CRange::Clone(
306 _Out_ ITfRange **ppClone)
307{
308 TRACE("%p\n", ppClone);
309
310 if (!ppClone)
311 return E_INVALIDARG;
312
313 CRange *pCloned = _Clone();
314 if (!pCloned)
315 return E_OUTOFMEMORY;
316
317 *ppClone = static_cast<ITfRangeACP *>(pCloned);
318 return S_OK;
319}
320
321STDMETHODIMP CRange::GetContext(
322 _Out_ ITfContext **ppContext)
323{
324 FIXME("%p\n", ppContext);
325 return E_NOTIMPL;
326}
327
328STDMETHODIMP CRange::GetExtent(_Out_ LONG *pacpAnchor, _Out_ LONG *pcch)
329{
330 FIXME("\n");
331 return E_NOTIMPL;
332}
333
334STDMETHODIMP CRange::SetExtent(_In_ LONG acpAnchor, _In_ LONG cch)
335{
336 FIXME("\n");
337 return E_NOTIMPL;
338}
339
340STDMETHODIMP CRange::GetExtent(_Out_ IAnchor **ppStart, _Out_ IAnchor **ppEnd)
341{
342 FIXME("\n");
343 return E_NOTIMPL;
344}
345
346STDMETHODIMP CRange::SetExtent(_In_ IAnchor *pAnchorStart, _In_ IAnchor *pAnchorEnd)
347{
348 FIXME("\n");
349 return E_NOTIMPL;
350}
351
352STDMETHODIMP CRange::AdviseSink(
353 _In_ REFIID riid,
354 _In_ IUnknown *punk,
355 _Out_ DWORD *pdwCookie)
356{
357 FIXME("\n");
358 return E_NOTIMPL;
359}
360
361STDMETHODIMP CRange::UnadviseSink(
362 _In_ DWORD dwCookie)
363{
364 FIXME("\n");
365 return E_NOTIMPL;
366}
367
368////////////////////////////////////////////////////////////////////////////
369
370EXTERN_C
371HRESULT
372Range_Constructor(ITfContext *context, DWORD anchorStart, DWORD anchorEnd, ITfRange **ppOut)
373{
374 CRange *This = new(cicNoThrow) CRange(context, (TfAnchor)anchorStart, (TfAnchor)anchorEnd);
375 if (!This)
376 return E_OUTOFMEMORY;
377
378 *ppOut = static_cast<ITfRangeACP *>(This);
379 return S_OK;
380}
381
382/* Internal conversion functions */
383
384EXTERN_C
385HRESULT TF_SELECTION_to_TS_SELECTION_ACP(const TF_SELECTION *tf, TS_SELECTION_ACP *tsAcp)
386{
387 return CRange::TF_SELECTION_to_TS_SELECTION_ACP(tf, tsAcp);
388}