hhctrl.ocx: Open a specific topic when requested.
[wine/multimedia.git] / dlls / jscript / vbarray.c
blobda17a07090f19028fc7eda7e68dacd29c443e7aa
1 /*
2 * Copyright 2010 Piotr Caban for CodeWeavers
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.
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.
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
19 #include "jscript.h"
21 #include "wine/debug.h"
23 WINE_DEFAULT_DEBUG_CHANNEL(jscript);
25 typedef struct {
26 jsdisp_t dispex;
28 SAFEARRAY *safearray;
29 } VBArrayInstance;
31 static const WCHAR dimensionsW[] = {'d','i','m','e','n','s','i','o','n','s',0};
32 static const WCHAR getItemW[] = {'g','e','t','I','t','e','m',0};
33 static const WCHAR lboundW[] = {'l','b','o','u','n','d',0};
34 static const WCHAR toArrayW[] = {'t','o','A','r','r','a','y',0};
35 static const WCHAR uboundW[] = {'u','b','o','u','n','d',0};
37 static inline VBArrayInstance *vbarray_from_vdisp(vdisp_t *vdisp)
39 return (VBArrayInstance*)vdisp->u.jsdisp;
42 static inline VBArrayInstance *vbarray_this(vdisp_t *jsthis)
44 return is_vclass(jsthis, JSCLASS_VBARRAY) ? vbarray_from_vdisp(jsthis) : NULL;
47 static HRESULT VBArray_dimensions(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPPARAMS *dp,
48 VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
50 VBArrayInstance *vbarray;
52 TRACE("\n");
54 vbarray = vbarray_this(vthis);
55 if(!vbarray)
56 return throw_type_error(ctx, ei, JS_E_VBARRAY_EXPECTED, NULL);
58 if(retv)
59 num_set_int(retv, SafeArrayGetDim(vbarray->safearray));
60 return S_OK;
63 static HRESULT VBArray_getItem(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPPARAMS *dp,
64 VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
66 VBArrayInstance *vbarray;
67 int i, *indexes, size;
68 VARIANT out;
69 HRESULT hres;
71 TRACE("\n");
73 vbarray = vbarray_this(vthis);
74 if(!vbarray)
75 return throw_type_error(ctx, ei, JS_E_VBARRAY_EXPECTED, NULL);
77 size = arg_cnt(dp);
78 if(size < SafeArrayGetDim(vbarray->safearray))
79 return throw_range_error(ctx, ei, JS_E_SUBSCRIPT_OUT_OF_RANGE, NULL);
81 indexes = heap_alloc(sizeof(int)*size);
82 if(!indexes)
83 return E_OUTOFMEMORY;
85 for(i=0; i<size; i++) {
86 hres = to_int32(ctx, get_arg(dp, i), ei, indexes+i);
87 if(FAILED(hres)) {
88 heap_free(indexes);
89 return hres;
93 hres = SafeArrayGetElement(vbarray->safearray, indexes, (void*)&out);
94 heap_free(indexes);
95 if(hres == DISP_E_BADINDEX)
96 return throw_range_error(ctx, ei, JS_E_SUBSCRIPT_OUT_OF_RANGE, NULL);
97 else if(FAILED(hres))
98 return hres;
100 if(retv)
101 hres = VariantCopy(retv, &out);
103 return hres;
106 static HRESULT VBArray_lbound(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPPARAMS *dp,
107 VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
109 VBArrayInstance *vbarray;
110 int dim;
111 HRESULT hres;
113 TRACE("\n");
115 vbarray = vbarray_this(vthis);
116 if(!vbarray)
117 return throw_type_error(ctx, ei, JS_E_VBARRAY_EXPECTED, NULL);
119 if(arg_cnt(dp)) {
120 hres = to_int32(ctx, get_arg(dp, 0), ei, &dim);
121 if(FAILED(hres))
122 return hres;
123 } else
124 dim = 1;
126 hres = SafeArrayGetLBound(vbarray->safearray, dim, &dim);
127 if(hres == DISP_E_BADINDEX)
128 return throw_range_error(ctx, ei, JS_E_SUBSCRIPT_OUT_OF_RANGE, NULL);
129 else if(FAILED(hres))
130 return hres;
132 if(retv)
133 num_set_int(retv, dim);
134 return S_OK;
137 static HRESULT VBArray_toArray(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPPARAMS *dp,
138 VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
140 VBArrayInstance *vbarray;
141 jsdisp_t *array;
142 VARIANT *v;
143 int i, size = 1, ubound, lbound;
144 HRESULT hres;
146 TRACE("\n");
148 vbarray = vbarray_this(vthis);
149 if(!vbarray)
150 return throw_type_error(ctx, ei, JS_E_VBARRAY_EXPECTED, NULL);
152 for(i=1; i<=SafeArrayGetDim(vbarray->safearray); i++) {
153 SafeArrayGetLBound(vbarray->safearray, i, &lbound);
154 SafeArrayGetUBound(vbarray->safearray, i, &ubound);
155 size *= ubound-lbound+1;
158 hres = SafeArrayAccessData(vbarray->safearray, (void**)&v);
159 if(FAILED(hres))
160 return hres;
162 hres = create_array(ctx, 0, &array);
163 if(FAILED(hres)) {
164 SafeArrayUnaccessData(vbarray->safearray);
165 return hres;
168 for(i=0; i<size; i++) {
169 hres = jsdisp_propput_idx(array, i, v, ei, caller);
170 if(FAILED(hres)) {
171 SafeArrayUnaccessData(vbarray->safearray);
172 jsdisp_release(array);
173 return hres;
175 v++;
178 SafeArrayUnaccessData(vbarray->safearray);
180 if(retv)
181 var_set_jsdisp(retv, array);
182 return S_OK;
185 static HRESULT VBArray_ubound(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPPARAMS *dp,
186 VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
188 VBArrayInstance *vbarray;
189 int dim;
190 HRESULT hres;
192 TRACE("\n");
194 vbarray = vbarray_this(vthis);
195 if(!vbarray)
196 return throw_type_error(ctx, ei, JS_E_VBARRAY_EXPECTED, NULL);
198 if(arg_cnt(dp)) {
199 hres = to_int32(ctx, get_arg(dp, 0), ei, &dim);
200 if(FAILED(hres))
201 return hres;
202 } else
203 dim = 1;
205 hres = SafeArrayGetUBound(vbarray->safearray, dim, &dim);
206 if(hres == DISP_E_BADINDEX)
207 return throw_range_error(ctx, ei, JS_E_SUBSCRIPT_OUT_OF_RANGE, NULL);
208 else if(FAILED(hres))
209 return hres;
211 if(retv)
212 num_set_int(retv, dim);
213 return S_OK;
216 static HRESULT VBArray_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
217 VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
219 FIXME("\n");
221 switch(flags) {
222 default:
223 FIXME("unimplemented flags %x\n", flags);
224 return E_NOTIMPL;
227 return S_OK;
230 static void VBArray_destructor(jsdisp_t *dispex)
232 VBArrayInstance *vbarray = (VBArrayInstance*)dispex;
234 SafeArrayDestroy(vbarray->safearray);
235 heap_free(vbarray);
238 static const builtin_prop_t VBArray_props[] = {
239 {dimensionsW, VBArray_dimensions, PROPF_METHOD},
240 {getItemW, VBArray_getItem, PROPF_METHOD|1},
241 {lboundW, VBArray_lbound, PROPF_METHOD},
242 {toArrayW, VBArray_toArray, PROPF_METHOD},
243 {uboundW, VBArray_ubound, PROPF_METHOD}
246 static const builtin_info_t VBArray_info = {
247 JSCLASS_VBARRAY,
248 {NULL, VBArray_value, 0},
249 sizeof(VBArray_props)/sizeof(*VBArray_props),
250 VBArray_props,
251 VBArray_destructor,
252 NULL
255 static HRESULT alloc_vbarray(script_ctx_t *ctx, jsdisp_t *object_prototype, VBArrayInstance **ret)
257 VBArrayInstance *vbarray;
258 HRESULT hres;
260 vbarray = heap_alloc_zero(sizeof(VBArrayInstance));
261 if(!vbarray)
262 return E_OUTOFMEMORY;
264 if(object_prototype)
265 hres = init_dispex(&vbarray->dispex, ctx, &VBArray_info, object_prototype);
266 else
267 hres = init_dispex_from_constr(&vbarray->dispex, ctx, &VBArray_info, ctx->vbarray_constr);
269 if(FAILED(hres)) {
270 heap_free(vbarray);
271 return hres;
274 *ret = vbarray;
275 return S_OK;
278 static HRESULT VBArrayConstr_value(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPPARAMS *dp,
279 VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
281 VARIANT *arg;
282 VBArrayInstance *vbarray;
283 HRESULT hres;
285 TRACE("\n");
287 switch(flags) {
288 case DISPATCH_METHOD:
289 if(arg_cnt(dp)<1 || V_VT((arg = get_arg(dp, 0)))!=(VT_ARRAY|VT_VARIANT))
290 return throw_type_error(ctx, ei, JS_E_VBARRAY_EXPECTED, NULL);
292 hres = VariantCopy(retv, arg);
293 return hres;
295 case DISPATCH_CONSTRUCT:
296 if(arg_cnt(dp)<1 || V_VT((arg = get_arg(dp, 0)))!=(VT_ARRAY|VT_VARIANT))
297 return throw_type_error(ctx, ei, JS_E_VBARRAY_EXPECTED, NULL);
299 hres = alloc_vbarray(ctx, NULL, &vbarray);
300 if(FAILED(hres))
301 return hres;
303 hres = SafeArrayCopy(V_ARRAY(arg), &vbarray->safearray);
304 if(FAILED(hres)) {
305 jsdisp_release(&vbarray->dispex);
306 return hres;
309 var_set_jsdisp(retv, &vbarray->dispex);
310 break;
312 default:
313 FIXME("unimplemented flags: %x\n", flags);
314 return E_NOTIMPL;
317 return S_OK;
320 HRESULT create_vbarray_constr(script_ctx_t *ctx, jsdisp_t *object_prototype, jsdisp_t **ret)
322 VBArrayInstance *vbarray;
323 HRESULT hres;
325 static const WCHAR VBArrayW[] = {'V','B','A','r','r','a','y',0};
327 hres = alloc_vbarray(ctx, object_prototype, &vbarray);
328 if(FAILED(hres))
329 return hres;
331 hres = create_builtin_function(ctx, VBArrayConstr_value, VBArrayW, NULL, PROPF_CONSTR|1, &vbarray->dispex, ret);
333 jsdisp_release(&vbarray->dispex);
334 return hres;
337 HRESULT create_vbarray(script_ctx_t *ctx, SAFEARRAY *sa, jsdisp_t **ret)
339 VBArrayInstance *vbarray;
340 HRESULT hres;
342 hres = alloc_vbarray(ctx, NULL, &vbarray);
343 if(FAILED(hres))
344 return hres;
346 hres = SafeArrayCopy(sa, &vbarray->safearray);
347 if(FAILED(hres)) {
348 jsdisp_release(&vbarray->dispex);
349 return hres;
352 *ret = &vbarray->dispex;
353 return S_OK;