range.c 9.4 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
/*
 *  ITfRange implementation
 *
 *  Copyright 2009 Aric Stewart, CodeWeavers
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#include "config.h"

#include <stdarg.h>

#define COBJMACROS

#include "wine/debug.h"
#include "windef.h"
#include "winbase.h"
#include "winreg.h"
#include "winuser.h"
#include "shlwapi.h"
#include "winerror.h"
#include "objbase.h"

#include "wine/unicode.h"

#include "msctf.h"
#include "msctf_internal.h"

WINE_DEFAULT_DEBUG_CHANNEL(msctf);

typedef struct tagRange {
44
    ITfRange ITfRange_iface;
45 46 47 48 49 50 51 52 53 54 55 56
    /* const ITfRangeACPVtb *RangeACPVtbl; */
    LONG refCount;

    ITextStoreACP   *pITextStoreACP;
    ITfContext      *pITfContext;

    DWORD lockType;
    TfGravity gravityStart, gravityEnd;
    DWORD anchorStart, anchorEnd;

} Range;

57 58 59 60 61
static inline Range *impl_from_ITfRange(ITfRange *iface)
{
    return CONTAINING_RECORD(iface, Range, ITfRange_iface);
}

62 63 64 65 66 67 68 69
static void Range_Destructor(Range *This)
{
    TRACE("destroying %p\n", This);
    HeapFree(GetProcessHeap(),0,This);
}

static HRESULT WINAPI Range_QueryInterface(ITfRange *iface, REFIID iid, LPVOID *ppvOut)
{
70
    Range *This = impl_from_ITfRange(iface);
71 72 73 74
    *ppvOut = NULL;

    if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITfRange))
    {
75
        *ppvOut = &This->ITfRange_iface;
76 77 78 79
    }

    if (*ppvOut)
    {
80
        ITfRange_AddRef(iface);
81 82 83 84 85 86 87 88 89
        return S_OK;
    }

    WARN("unsupported interface: %s\n", debugstr_guid(iid));
    return E_NOINTERFACE;
}

static ULONG WINAPI Range_AddRef(ITfRange *iface)
{
90
    Range *This = impl_from_ITfRange(iface);
91 92 93 94 95
    return InterlockedIncrement(&This->refCount);
}

static ULONG WINAPI Range_Release(ITfRange *iface)
{
96
    Range *This = impl_from_ITfRange(iface);
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
    ULONG ret;

    ret = InterlockedDecrement(&This->refCount);
    if (ret == 0)
        Range_Destructor(This);
    return ret;
}

/*****************************************************
 * ITfRange functions
 *****************************************************/

static HRESULT WINAPI Range_GetText(ITfRange *iface, TfEditCookie ec,
        DWORD dwFlags, WCHAR *pchText, ULONG cchMax, ULONG *pcch)
{
112
    Range *This = impl_from_ITfRange(iface);
113 114 115 116 117 118 119
    FIXME("STUB:(%p)\n",This);
    return E_NOTIMPL;
}

static HRESULT WINAPI Range_SetText(ITfRange *iface, TfEditCookie ec,
         DWORD dwFlags, const WCHAR *pchText, LONG cch)
{
120
    Range *This = impl_from_ITfRange(iface);
121 122 123 124 125 126 127
    FIXME("STUB:(%p)\n",This);
    return E_NOTIMPL;
}

static HRESULT WINAPI Range_GetFormattedText(ITfRange *iface, TfEditCookie ec,
        IDataObject **ppDataObject)
{
128
    Range *This = impl_from_ITfRange(iface);
129 130 131 132 133 134 135
    FIXME("STUB:(%p)\n",This);
    return E_NOTIMPL;
}

static HRESULT WINAPI Range_GetEmbedded(ITfRange *iface, TfEditCookie ec,
        REFGUID rguidService, REFIID riid, IUnknown **ppunk)
{
136
    Range *This = impl_from_ITfRange(iface);
137 138 139 140 141 142 143
    FIXME("STUB:(%p)\n",This);
    return E_NOTIMPL;
}

static HRESULT WINAPI Range_InsertEmbedded(ITfRange *iface, TfEditCookie ec,
        DWORD dwFlags, IDataObject *pDataObject)
{
144
    Range *This = impl_from_ITfRange(iface);
145 146 147 148 149 150 151
    FIXME("STUB:(%p)\n",This);
    return E_NOTIMPL;
}

static HRESULT WINAPI Range_ShiftStart(ITfRange *iface, TfEditCookie ec,
        LONG cchReq, LONG *pcch, const TF_HALTCOND *pHalt)
{
152
    Range *This = impl_from_ITfRange(iface);
153 154 155 156 157 158 159
    FIXME("STUB:(%p)\n",This);
    return E_NOTIMPL;
}

static HRESULT WINAPI Range_ShiftEnd(ITfRange *iface, TfEditCookie ec,
        LONG cchReq, LONG *pcch, const TF_HALTCOND *pHalt)
{
160
    Range *This = impl_from_ITfRange(iface);
161 162 163 164 165 166 167
    FIXME("STUB:(%p)\n",This);
    return E_NOTIMPL;
}

static HRESULT WINAPI Range_ShiftStartToRange(ITfRange *iface, TfEditCookie ec,
        ITfRange *pRange, TfAnchor aPos)
{
168
    Range *This = impl_from_ITfRange(iface);
169 170 171 172 173 174 175
    FIXME("STUB:(%p)\n",This);
    return E_NOTIMPL;
}

static HRESULT WINAPI Range_ShiftEndToRange(ITfRange *iface, TfEditCookie ec,
        ITfRange *pRange, TfAnchor aPos)
{
176
    Range *This = impl_from_ITfRange(iface);
177 178 179 180 181 182 183
    FIXME("STUB:(%p)\n",This);
    return E_NOTIMPL;
}

static HRESULT WINAPI Range_ShiftStartRegion(ITfRange *iface, TfEditCookie ec,
        TfShiftDir dir, BOOL *pfNoRegion)
{
184
    Range *This = impl_from_ITfRange(iface);
185 186 187 188 189 190 191
    FIXME("STUB:(%p)\n",This);
    return E_NOTIMPL;
}

static HRESULT WINAPI Range_ShiftEndRegion(ITfRange *iface, TfEditCookie ec,
        TfShiftDir dir, BOOL *pfNoRegion)
{
192
    Range *This = impl_from_ITfRange(iface);
193 194 195 196 197 198 199
    FIXME("STUB:(%p)\n",This);
    return E_NOTIMPL;
}

static HRESULT WINAPI Range_IsEmpty(ITfRange *iface, TfEditCookie ec,
        BOOL *pfEmpty)
{
200
    Range *This = impl_from_ITfRange(iface);
201 202 203 204 205 206 207
    FIXME("STUB:(%p)\n",This);
    return E_NOTIMPL;
}

static HRESULT WINAPI Range_Collapse(ITfRange *iface, TfEditCookie ec,
        TfAnchor aPos)
{
208
    Range *This = impl_from_ITfRange(iface);
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
    TRACE("(%p) %i %i\n",This,ec,aPos);

    switch (aPos)
    {
        case TF_ANCHOR_START:
            This->anchorEnd = This->anchorStart;
            break;
        case TF_ANCHOR_END:
            This->anchorStart = This->anchorEnd;
            break;
        default:
            return E_INVALIDARG;
    }

    return S_OK;
224 225 226 227 228
}

static HRESULT WINAPI Range_IsEqualStart(ITfRange *iface, TfEditCookie ec,
        ITfRange *pWith, TfAnchor aPos, BOOL *pfEqual)
{
229
    Range *This = impl_from_ITfRange(iface);
230 231 232 233 234 235 236
    FIXME("STUB:(%p)\n",This);
    return E_NOTIMPL;
}

static HRESULT WINAPI Range_IsEqualEnd(ITfRange *iface, TfEditCookie ec,
        ITfRange *pWith, TfAnchor aPos, BOOL *pfEqual)
{
237
    Range *This = impl_from_ITfRange(iface);
238 239 240 241 242 243 244
    FIXME("STUB:(%p)\n",This);
    return E_NOTIMPL;
}

static HRESULT WINAPI Range_CompareStart(ITfRange *iface, TfEditCookie ec,
        ITfRange *pWith, TfAnchor aPos, LONG *plResult)
{
245
    Range *This = impl_from_ITfRange(iface);
246 247 248 249 250 251 252
    FIXME("STUB:(%p)\n",This);
    return E_NOTIMPL;
}

static HRESULT WINAPI Range_CompareEnd(ITfRange *iface, TfEditCookie ec,
        ITfRange *pWith, TfAnchor aPos, LONG *plResult)
{
253
    Range *This = impl_from_ITfRange(iface);
254 255 256 257 258 259 260
    FIXME("STUB:(%p)\n",This);
    return E_NOTIMPL;
}

static HRESULT WINAPI Range_AdjustForInsert(ITfRange *iface, TfEditCookie ec,
        ULONG cchInsert, BOOL *pfInsertOk)
{
261
    Range *This = impl_from_ITfRange(iface);
262 263 264 265 266 267 268
    FIXME("STUB:(%p)\n",This);
    return E_NOTIMPL;
}

static HRESULT WINAPI Range_GetGravity(ITfRange *iface,
        TfGravity *pgStart, TfGravity *pgEnd)
{
269
    Range *This = impl_from_ITfRange(iface);
270 271 272 273 274 275 276
    FIXME("STUB:(%p)\n",This);
    return E_NOTIMPL;
}

static HRESULT WINAPI Range_SetGravity(ITfRange *iface, TfEditCookie ec,
         TfGravity gStart, TfGravity gEnd)
{
277
    Range *This = impl_from_ITfRange(iface);
278 279 280 281 282 283
    FIXME("STUB:(%p)\n",This);
    return E_NOTIMPL;
}

static HRESULT WINAPI Range_Clone(ITfRange *iface, ITfRange **ppClone)
{
284
    Range *This = impl_from_ITfRange(iface);
285 286 287 288 289 290
    FIXME("STUB:(%p)\n",This);
    return E_NOTIMPL;
}

static HRESULT WINAPI Range_GetContext(ITfRange *iface, ITfContext **ppContext)
{
291
    Range *This = impl_from_ITfRange(iface);
292 293 294 295 296
    TRACE("(%p)\n",This);
    if (!ppContext)
        return E_INVALIDARG;
    *ppContext = This->pITfContext;
    return S_OK;
297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338
}

static const ITfRangeVtbl Range_RangeVtbl =
{
    Range_QueryInterface,
    Range_AddRef,
    Range_Release,

    Range_GetText,
    Range_SetText,
    Range_GetFormattedText,
    Range_GetEmbedded,
    Range_InsertEmbedded,
    Range_ShiftStart,
    Range_ShiftEnd,
    Range_ShiftStartToRange,
    Range_ShiftEndToRange,
    Range_ShiftStartRegion,
    Range_ShiftEndRegion,
    Range_IsEmpty,
    Range_Collapse,
    Range_IsEqualStart,
    Range_IsEqualEnd,
    Range_CompareStart,
    Range_CompareEnd,
    Range_AdjustForInsert,
    Range_GetGravity,
    Range_SetGravity,
    Range_Clone,
    Range_GetContext
};

HRESULT Range_Constructor(ITfContext *context, ITextStoreACP *textstore, DWORD lockType, DWORD anchorStart, DWORD anchorEnd, ITfRange **ppOut)
{
    Range *This;

    This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(Range));
    if (This == NULL)
        return E_OUTOFMEMORY;

    TRACE("(%p) %p %p\n",This, context, textstore);

339
    This->ITfRange_iface.lpVtbl = &Range_RangeVtbl;
340 341 342 343 344 345 346
    This->refCount = 1;
    This->pITfContext = context;
    This->pITextStoreACP = textstore;
    This->lockType = lockType;
    This->anchorStart = anchorStart;
    This->anchorEnd = anchorEnd;

347
    *ppOut = &This->ITfRange_iface;
348
    TRACE("returning %p\n", *ppOut);
349 350 351

    return S_OK;
}
352 353 354 355 356

/* Internal conversion functions */

HRESULT TF_SELECTION_to_TS_SELECTION_ACP(const TF_SELECTION *tf, TS_SELECTION_ACP *tsAcp)
{
357
    Range *This;
358 359 360 361

    if (!tf || !tsAcp || !tf->range)
        return E_INVALIDARG;

362
    This = impl_from_ITfRange(tf->range);
363

364 365 366 367 368 369
    tsAcp->acpStart = This->anchorStart;
    tsAcp->acpEnd = This->anchorEnd;
    tsAcp->style.ase = tf->style.ase;
    tsAcp->style.fInterimChar = tf->style.fInterimChar;
    return S_OK;
}