1 /* 2 * Copyright 2006 Jacek Caban for CodeWeavers 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 17 */ 18 19 #include "mshtml_private.h" 20 21 typedef struct { 22 DispatchEx dispex; 23 IHTMLSelectionObject IHTMLSelectionObject_iface; 24 IHTMLSelectionObject2 IHTMLSelectionObject2_iface; 25 26 LONG ref; 27 28 nsISelection *nsselection; 29 HTMLDocumentNode *doc; 30 31 struct list entry; 32 } HTMLSelectionObject; 33 34 static inline HTMLSelectionObject *impl_from_IHTMLSelectionObject(IHTMLSelectionObject *iface) 35 { 36 return CONTAINING_RECORD(iface, HTMLSelectionObject, IHTMLSelectionObject_iface); 37 } 38 39 static HRESULT WINAPI HTMLSelectionObject_QueryInterface(IHTMLSelectionObject *iface, 40 REFIID riid, void **ppv) 41 { 42 HTMLSelectionObject *This = impl_from_IHTMLSelectionObject(iface); 43 44 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv); 45 46 if(IsEqualGUID(&IID_IUnknown, riid)) { 47 *ppv = &This->IHTMLSelectionObject_iface; 48 }else if(IsEqualGUID(&IID_IDispatch, riid)) { 49 *ppv = &This->IHTMLSelectionObject_iface; 50 }else if(IsEqualGUID(&IID_IHTMLSelectionObject, riid)) { 51 *ppv = &This->IHTMLSelectionObject_iface; 52 }else if(IsEqualGUID(&IID_IHTMLSelectionObject2, riid)) { 53 *ppv = &This->IHTMLSelectionObject2_iface; 54 }else if(dispex_query_interface(&This->dispex, riid, ppv)) { 55 return *ppv ? S_OK : E_NOINTERFACE; 56 }else { 57 *ppv = NULL; 58 WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv); 59 return E_NOINTERFACE; 60 } 61 62 IUnknown_AddRef((IUnknown*)*ppv); 63 return S_OK; 64 } 65 66 static ULONG WINAPI HTMLSelectionObject_AddRef(IHTMLSelectionObject *iface) 67 { 68 HTMLSelectionObject *This = impl_from_IHTMLSelectionObject(iface); 69 LONG ref = InterlockedIncrement(&This->ref); 70 71 TRACE("(%p) ref=%d\n", This, ref); 72 73 return ref; 74 } 75 76 static ULONG WINAPI HTMLSelectionObject_Release(IHTMLSelectionObject *iface) 77 { 78 HTMLSelectionObject *This = impl_from_IHTMLSelectionObject(iface); 79 LONG ref = InterlockedDecrement(&This->ref); 80 81 TRACE("(%p) ref=%d\n", This, ref); 82 83 if(!ref) { 84 if(This->nsselection) 85 nsISelection_Release(This->nsselection); 86 if(This->doc) 87 list_remove(&This->entry); 88 release_dispex(&This->dispex); 89 heap_free(This); 90 } 91 92 return ref; 93 } 94 95 static HRESULT WINAPI HTMLSelectionObject_GetTypeInfoCount(IHTMLSelectionObject *iface, UINT *pctinfo) 96 { 97 HTMLSelectionObject *This = impl_from_IHTMLSelectionObject(iface); 98 99 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo); 100 } 101 102 static HRESULT WINAPI HTMLSelectionObject_GetTypeInfo(IHTMLSelectionObject *iface, UINT iTInfo, 103 LCID lcid, ITypeInfo **ppTInfo) 104 { 105 HTMLSelectionObject *This = impl_from_IHTMLSelectionObject(iface); 106 107 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo); 108 } 109 110 static HRESULT WINAPI HTMLSelectionObject_GetIDsOfNames(IHTMLSelectionObject *iface, REFIID riid, 111 LPOLESTR *rgszNames, UINT cNames, 112 LCID lcid, DISPID *rgDispId) 113 { 114 HTMLSelectionObject *This = impl_from_IHTMLSelectionObject(iface); 115 116 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, 117 cNames, lcid, rgDispId); 118 } 119 120 static HRESULT WINAPI HTMLSelectionObject_Invoke(IHTMLSelectionObject *iface, DISPID dispIdMember, 121 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, 122 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) 123 { 124 HTMLSelectionObject *This = impl_from_IHTMLSelectionObject(iface); 125 126 127 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, 128 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); 129 } 130 131 static HRESULT WINAPI HTMLSelectionObject_createRange(IHTMLSelectionObject *iface, IDispatch **range) 132 { 133 HTMLSelectionObject *This = impl_from_IHTMLSelectionObject(iface); 134 IHTMLTxtRange *range_obj = NULL; 135 nsIDOMRange *nsrange = NULL; 136 HRESULT hres; 137 138 TRACE("(%p)->(%p)\n", This, range); 139 140 if(This->nsselection) { 141 LONG nsrange_cnt = 0; 142 nsresult nsres; 143 144 nsISelection_GetRangeCount(This->nsselection, &nsrange_cnt); 145 if(!nsrange_cnt) { 146 nsIDOMHTMLElement *nsbody = NULL; 147 148 TRACE("nsrange_cnt = 0\n"); 149 150 if(!This->doc->nsdoc) { 151 WARN("nsdoc is NULL\n"); 152 return E_UNEXPECTED; 153 } 154 155 nsres = nsIDOMHTMLDocument_GetBody(This->doc->nsdoc, &nsbody); 156 if(NS_FAILED(nsres) || !nsbody) { 157 ERR("Could not get body: %08x\n", nsres); 158 return E_FAIL; 159 } 160 161 nsres = nsISelection_Collapse(This->nsselection, (nsIDOMNode*)nsbody, 0); 162 nsIDOMHTMLElement_Release(nsbody); 163 if(NS_FAILED(nsres)) 164 ERR("Collapse failed: %08x\n", nsres); 165 }else if(nsrange_cnt > 1) { 166 FIXME("range_cnt = %d\n", nsrange_cnt); 167 } 168 169 nsres = nsISelection_GetRangeAt(This->nsselection, 0, &nsrange); 170 if(NS_FAILED(nsres)) 171 ERR("GetRangeAt failed: %08x\n", nsres); 172 } 173 174 hres = HTMLTxtRange_Create(This->doc, nsrange, &range_obj); 175 176 if (nsrange) nsIDOMRange_Release(nsrange); 177 *range = (IDispatch*)range_obj; 178 return hres; 179 } 180 181 static HRESULT WINAPI HTMLSelectionObject_empty(IHTMLSelectionObject *iface) 182 { 183 HTMLSelectionObject *This = impl_from_IHTMLSelectionObject(iface); 184 FIXME("(%p)\n", This); 185 return E_NOTIMPL; 186 } 187 188 static HRESULT WINAPI HTMLSelectionObject_clear(IHTMLSelectionObject *iface) 189 { 190 HTMLSelectionObject *This = impl_from_IHTMLSelectionObject(iface); 191 FIXME("(%p)\n", This); 192 return E_NOTIMPL; 193 } 194 195 static HRESULT WINAPI HTMLSelectionObject_get_type(IHTMLSelectionObject *iface, BSTR *p) 196 { 197 HTMLSelectionObject *This = impl_from_IHTMLSelectionObject(iface); 198 cpp_bool collapsed = TRUE; 199 200 static const WCHAR wszNone[] = {'N','o','n','e',0}; 201 static const WCHAR wszText[] = {'T','e','x','t',0}; 202 203 TRACE("(%p)->(%p)\n", This, p); 204 205 if(This->nsselection) 206 nsISelection_GetIsCollapsed(This->nsselection, &collapsed); 207 208 *p = SysAllocString(collapsed ? wszNone : wszText); /* FIXME: control */ 209 TRACE("ret %s\n", debugstr_w(*p)); 210 return S_OK; 211 } 212 213 static const IHTMLSelectionObjectVtbl HTMLSelectionObjectVtbl = { 214 HTMLSelectionObject_QueryInterface, 215 HTMLSelectionObject_AddRef, 216 HTMLSelectionObject_Release, 217 HTMLSelectionObject_GetTypeInfoCount, 218 HTMLSelectionObject_GetTypeInfo, 219 HTMLSelectionObject_GetIDsOfNames, 220 HTMLSelectionObject_Invoke, 221 HTMLSelectionObject_createRange, 222 HTMLSelectionObject_empty, 223 HTMLSelectionObject_clear, 224 HTMLSelectionObject_get_type 225 }; 226 227 static inline HTMLSelectionObject *impl_from_IHTMLSelectionObject2(IHTMLSelectionObject2 *iface) 228 { 229 return CONTAINING_RECORD(iface, HTMLSelectionObject, IHTMLSelectionObject2_iface); 230 } 231 232 static HRESULT WINAPI HTMLSelectionObject2_QueryInterface(IHTMLSelectionObject2 *iface, REFIID riid, void **ppv) 233 { 234 HTMLSelectionObject *This = impl_from_IHTMLSelectionObject2(iface); 235 236 return IHTMLSelectionObject_QueryInterface(&This->IHTMLSelectionObject_iface, riid, ppv); 237 } 238 239 static ULONG WINAPI HTMLSelectionObject2_AddRef(IHTMLSelectionObject2 *iface) 240 { 241 HTMLSelectionObject *This = impl_from_IHTMLSelectionObject2(iface); 242 243 return IHTMLSelectionObject_AddRef(&This->IHTMLSelectionObject_iface); 244 } 245 246 static ULONG WINAPI HTMLSelectionObject2_Release(IHTMLSelectionObject2 *iface) 247 { 248 HTMLSelectionObject *This = impl_from_IHTMLSelectionObject2(iface); 249 250 return IHTMLSelectionObject_Release(&This->IHTMLSelectionObject_iface); 251 } 252 253 static HRESULT WINAPI HTMLSelectionObject2_GetTypeInfoCount(IHTMLSelectionObject2 *iface, UINT *pctinfo) 254 { 255 HTMLSelectionObject *This = impl_from_IHTMLSelectionObject2(iface); 256 257 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo); 258 } 259 260 static HRESULT WINAPI HTMLSelectionObject2_GetTypeInfo(IHTMLSelectionObject2 *iface, UINT iTInfo, 261 LCID lcid, ITypeInfo **ppTInfo) 262 { 263 HTMLSelectionObject *This = impl_from_IHTMLSelectionObject2(iface); 264 265 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo); 266 } 267 268 static HRESULT WINAPI HTMLSelectionObject2_GetIDsOfNames(IHTMLSelectionObject2 *iface, REFIID riid, 269 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId) 270 { 271 HTMLSelectionObject *This = impl_from_IHTMLSelectionObject2(iface); 272 273 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, 274 cNames, lcid, rgDispId); 275 } 276 277 static HRESULT WINAPI HTMLSelectionObject2_Invoke(IHTMLSelectionObject2 *iface, DISPID dispIdMember, 278 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, 279 EXCEPINFO *pExcepInfo, UINT *puArgErr) 280 { 281 HTMLSelectionObject *This = impl_from_IHTMLSelectionObject2(iface); 282 283 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, 284 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); 285 } 286 287 static HRESULT WINAPI HTMLSelectionObject2_createRangeCollection(IHTMLSelectionObject2 *iface, IDispatch **rangeCollection) 288 { 289 HTMLSelectionObject *This = impl_from_IHTMLSelectionObject2(iface); 290 FIXME("(%p)->(%p)\n", This, rangeCollection); 291 return E_NOTIMPL; 292 } 293 294 static HRESULT WINAPI HTMLSelectionObject2_get_typeDetail(IHTMLSelectionObject2 *iface, BSTR *p) 295 { 296 HTMLSelectionObject *This = impl_from_IHTMLSelectionObject2(iface); 297 FIXME("(%p)->(%p)\n", This, p); 298 return E_NOTIMPL; 299 } 300 301 static const IHTMLSelectionObject2Vtbl HTMLSelectionObject2Vtbl = { 302 HTMLSelectionObject2_QueryInterface, 303 HTMLSelectionObject2_AddRef, 304 HTMLSelectionObject2_Release, 305 HTMLSelectionObject2_GetTypeInfoCount, 306 HTMLSelectionObject2_GetTypeInfo, 307 HTMLSelectionObject2_GetIDsOfNames, 308 HTMLSelectionObject2_Invoke, 309 HTMLSelectionObject2_createRangeCollection, 310 HTMLSelectionObject2_get_typeDetail 311 }; 312 313 static const tid_t HTMLSelectionObject_iface_tids[] = { 314 IHTMLSelectionObject_tid, 315 IHTMLSelectionObject2_tid, 316 0 317 }; 318 static dispex_static_data_t HTMLSelectionObject_dispex = { 319 NULL, 320 IHTMLSelectionObject_tid, /* FIXME: We have a test for that, but it doesn't expose IHTMLSelectionObject2 iface. */ 321 NULL, 322 HTMLSelectionObject_iface_tids 323 }; 324 325 HRESULT HTMLSelectionObject_Create(HTMLDocumentNode *doc, nsISelection *nsselection, IHTMLSelectionObject **ret) 326 { 327 HTMLSelectionObject *selection; 328 329 selection = heap_alloc(sizeof(HTMLSelectionObject)); 330 if(!selection) 331 return E_OUTOFMEMORY; 332 333 init_dispex(&selection->dispex, (IUnknown*)&selection->IHTMLSelectionObject_iface, &HTMLSelectionObject_dispex); 334 335 selection->IHTMLSelectionObject_iface.lpVtbl = &HTMLSelectionObjectVtbl; 336 selection->IHTMLSelectionObject2_iface.lpVtbl = &HTMLSelectionObject2Vtbl; 337 selection->ref = 1; 338 selection->nsselection = nsselection; /* We shouldn't call AddRef here */ 339 340 selection->doc = doc; 341 list_add_head(&doc->selection_list, &selection->entry); 342 343 *ret = &selection->IHTMLSelectionObject_iface; 344 return S_OK; 345 } 346 347 void detach_selection(HTMLDocumentNode *This) 348 { 349 HTMLSelectionObject *iter; 350 351 LIST_FOR_EACH_ENTRY(iter, &This->selection_list, HTMLSelectionObject, entry) { 352 iter->doc = NULL; 353 } 354 } 355