mshtml: Added beginning OnDataAvailable implementation.
[wine] / dlls / usp10 / tests / usp10.c
1 /*
2  * Tests for usp10 dll
3  *
4  * Copyright 2006 Jeff Latimer
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  *
20  * Notes:
21  * Uniscribe allows for processing of complex scripts such as joining
22  * and filtering characters and bi-directional text with custom line breaks.
23  */
24
25 #include <assert.h>
26 #include <stdio.h>
27
28 #include <wine/test.h>
29 #include <winbase.h>
30 #include <wingdi.h>
31 #include <winuser.h>
32 #include <winerror.h>
33 #include <usp10.h>
34
35 static void test_ScriptItemIzeShapePlace(unsigned short pwOutGlyphs[256])
36 {
37     HRESULT         hr;
38     int             iMaxProps;
39     const SCRIPT_PROPERTIES **ppSp;
40     HWND            hwnd;
41     HDC             hdc;
42
43     int             cInChars;
44     int             cMaxItems;
45     SCRIPT_ITEM     pItem[255];
46     int             pcItems;
47     WCHAR           TestItem1[6] = {'T', 'e', 's', 't', 0x0166, 0}; 
48     WCHAR           TestItem2[6] = {'T', 'e', 's', 't', 0x0166, 0}; 
49
50     SCRIPT_CACHE    psc;
51     int             cChars;
52     int             cMaxGlyphs;
53     unsigned short  pwOutGlyphs1[256];
54     unsigned short  pwOutGlyphs2[256];
55     unsigned short  pwLogClust[256];
56     SCRIPT_VISATTR  psva[256];
57     int             pcGlyphs;
58     int             piAdvance[256];
59     GOFFSET         pGoffset[256];
60     ABC             pABC[256];
61     int             cnt;
62
63     /* We need a valid HDC to drive a lot of Script functions which requires the following    *
64      * to set up for the tests.                                                               */
65     hwnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0,100,100,
66                            0, 0, 0, NULL);
67     assert(hwnd != 0);
68     ShowWindow(hwnd, SW_SHOW);
69     UpdateWindow(hwnd);
70
71     hdc = GetDC(hwnd);                                      /* We now have a hdc             */
72     ok( hdc != NULL, "HDC failed to be created %p\n", hdc);
73
74     /* Start testing usp10 functions                                                         */
75     /* This test determines that the pointer returned by ScriptGetProperties is valid
76      * by checking a known value in the table                                                */
77     hr = ScriptGetProperties(&ppSp, &iMaxProps);
78     trace("number of script properties %d\n", iMaxProps);
79     ok (iMaxProps > 0, "Number of scripts returned should not be 0\n"); 
80     if  (iMaxProps > 0)
81          ok( ppSp[5]->langid == 9, "Langid[5] not = to 9\n"); /* Check a known value to ensure   */
82                                                               /* ptrs work                       */
83
84
85     /* This set of tests are to check that the various edits in ScriptIemize work           */
86     cInChars = 5;                                        /* Length of test without NULL     */
87     cMaxItems = 1;                                       /* Check threshold value           */
88     hr = ScriptItemize(TestItem1, cInChars, cMaxItems, NULL, NULL, pItem, &pcItems);
89     ok (hr == E_INVALIDARG, "ScriptItemize should return E_INVALIDARG if cMaxItems < 2.  Was %d\n",
90         cMaxItems);
91     cInChars = 5;
92     cMaxItems = 255;
93     hr = ScriptItemize(NULL, cInChars, cMaxItems, NULL, NULL, pItem, &pcItems);
94     ok (hr == E_INVALIDARG, "ScriptItemize should return E_INVALIDARG if pwcInChars is NULL\n");
95
96     cInChars = 5;
97     cMaxItems = 255;
98     hr = ScriptItemize(TestItem1, 0, cMaxItems, NULL, NULL, pItem, &pcItems);
99     ok (hr == E_INVALIDARG, "ScriptItemize should return E_INVALIDARG if cInChars is 0\n");
100
101     cInChars = 5;
102     cMaxItems = 255;
103     hr = ScriptItemize(TestItem1, cInChars, cMaxItems, NULL, NULL, NULL, &pcItems);
104     ok (hr == E_INVALIDARG, "ScriptItemize should return E_INVALIDARG if pItems is NULL\n");
105
106     /* This is a valid test that will cause parsing to take place                             */
107     cInChars = 5;
108     cMaxItems = 255;
109     hr = ScriptItemize(TestItem1, cInChars, cMaxItems, NULL, NULL, pItem, &pcItems);
110     ok (hr == 0, "ScriptItemize should return 0, returned %08x\n", (unsigned int) hr);
111     /*  This test is for the interim operation of ScriptItemize where only one SCRIPT_ITEM is *
112      *  returned.                                                                             */
113     ok (pcItems > 0, "The number of SCRIPT_ITEMS should be greater than 0\n");
114     if (pcItems > 0)
115         ok (pItem[0].iCharPos == 0 && pItem[1].iCharPos == cInChars,
116             "Start pos not = 0 (%d) or end pos not = %d (%d)\n",
117             pItem[0].iCharPos, cInChars, pItem[1].iCharPos);
118
119     /* It would appear that we have a valid SCRIPT_ANALYSIS and can continue
120      * ie. ScriptItemize has succeeded and that pItem has been set                            */
121     cInChars = 5;
122     cMaxItems = 255;
123     if (hr == 0) {
124         psc = NULL;                                   /* must be null on first call           */
125         cChars = cInChars;
126         cMaxGlyphs = cInChars;
127         hr = ScriptShape(NULL, &psc, TestItem1, cChars,
128                          cMaxGlyphs, &pItem[0].a,
129                          pwOutGlyphs1, pwLogClust, psva, &pcGlyphs);
130         ok (hr == E_PENDING, "If psc is NULL (%08x) the E_PENDING should be returned\n",
131                       (unsigned int) hr);
132         cMaxGlyphs = 4;
133         hr = ScriptShape(hdc, &psc, TestItem1, cChars,
134                          cMaxGlyphs, &pItem[0].a,
135                          pwOutGlyphs1, pwLogClust, psva, &pcGlyphs);
136         ok (hr == E_OUTOFMEMORY, "If not enough output area cChars (%d) is > than CMaxGlyphs "
137                                  "(%d) but not E_OUTOFMEMORY\n",
138                                  cChars, cMaxGlyphs);
139         cMaxGlyphs = 256;
140         hr = ScriptShape(hdc, &psc, TestItem1, cChars,
141                          cMaxGlyphs, &pItem[0].a,
142                          pwOutGlyphs1, pwLogClust, psva, &pcGlyphs);
143         ok (hr == 0, "ScriptShape should return 0 not (%08x)\n", (unsigned int) hr);
144         ok (psc != NULL, "psc should not be null and have SCRIPT_CACHE buffer address\n");
145         ok (pcGlyphs == cChars, "Chars in (%d) should equal Glyphs out (%d)\n", cChars, pcGlyphs);
146         if (hr ==0) {
147             hr = ScriptPlace(NULL, &psc, pwOutGlyphs1, pcGlyphs, psva, &pItem[0].a, piAdvance,
148                              pGoffset, pABC);
149             ok (hr == 0, "Should return 0 not (%08x)\n", (unsigned int) hr);
150             for (cnt=0; cnt < pcGlyphs; cnt++)
151                 pwOutGlyphs[cnt] = pwOutGlyphs1[cnt];                 /* Send to next function */
152         }
153
154         /* This test will check to make sure that SCRIPT_CACHE is reused and that not translation   *
155          * takes place if fNoGlyphIndex is set.                                                     */
156
157         cInChars = 5;
158         cMaxItems = 255;
159         hr = ScriptItemize(TestItem2, cInChars, cMaxItems, NULL, NULL, pItem, &pcItems);
160         ok (hr == 0, "ScriptItemize should return 0, returned %08x\n", (unsigned int) hr);
161         /*  This test is for the intertrim operation of ScriptItemize where only one SCRIPT_ITEM is *
162          *  returned.                                                                               */
163         ok (pItem[0].iCharPos == 0 && pItem[1].iCharPos == cInChars,
164                             "Start pos not = 0 (%d) or end pos not = %d (%d)\n",
165                              pItem[0].iCharPos, cInChars, pItem[1].iCharPos);
166         /* It would appear that we have a valid SCRIPT_ANALYSIS and can continue                    */
167         if (hr == 0) {
168              cChars = cInChars;
169              cMaxGlyphs = 256;
170              pItem[0].a.fNoGlyphIndex = 1;                /* say no translate                     */
171              hr = ScriptShape(NULL, &psc, TestItem2, cChars,
172                               cMaxGlyphs, &pItem[0].a,
173                               pwOutGlyphs2, pwLogClust, psva, &pcGlyphs);
174              ok (hr != E_PENDING, "If psc should not be NULL (%08x) and the E_PENDING should be returned\n",
175                 (unsigned int) hr);
176              ok (hr == 0, "ScriptShape should return 0 not (%08x)\n", (unsigned int) hr);
177              ok (psc != NULL, "psc should not be null and have SCRIPT_CACHE buffer address\n");
178              ok (pcGlyphs == cChars, "Chars in (%d) should equal Glyphs out (%d)\n", cChars, pcGlyphs);
179              for (cnt=0; cnt < cChars && TestItem2[cnt] == pwOutGlyphs2[cnt]; cnt++) {}
180              ok (cnt == cChars, "Translation to place when told not to. WCHAR %d - %04x != %04x\n",
181                            cnt, TestItem2[cnt], pwOutGlyphs2[cnt]);
182              if (hr ==0) {
183                  hr = ScriptPlace(NULL, &psc, pwOutGlyphs2, pcGlyphs, psva, &pItem[0].a, piAdvance,
184                                   pGoffset, pABC);
185                  ok (hr == 0, "ScriptPlace should return 0 not (%08x)\n", (unsigned int) hr);
186              }
187         }
188         hr = ScriptFreeCache( &psc);
189         ok (!psc, "psc is not null after ScriptFreeCache\n");
190
191
192     }
193     ReleaseDC(hwnd, hdc);
194     DestroyWindow(hwnd);
195 }
196
197 void test_ScriptGetCMap(unsigned short pwOutGlyphs[256])
198 {
199     HRESULT         hr;
200     HWND            hwnd;
201     HDC             hdc;
202     SCRIPT_CACHE    psc = NULL;
203     int             cInChars;
204     int             cChars;
205     unsigned short  pwOutGlyphs3[256];
206     WCHAR           TestItem1[6] = {'T', 'e', 's', 't', 0x0166, 0}; 
207     DWORD           dwFlags;
208     int             cnt;
209
210     /* We need a valid HDC to drive a lot of Script functions which requires the following    *
211      * to set up for the tests.                                                               */
212     hwnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0,100,100,
213                            0, 0, 0, NULL);
214     assert(hwnd != 0);
215
216     hdc = GetDC(hwnd);
217     ok( hdc != NULL, "HDC failed to be created %p\n", hdc);
218
219     /*  Check to make sure that SCRIPT_CACHE gets allocated ok                     */
220     dwFlags = 0;
221     cInChars = cChars = 5;
222     /* Some sanity checks for ScriptGetCMap */
223
224     hr = ScriptGetCMap(NULL, NULL, NULL, 0, 0, NULL);
225     ok( hr == E_INVALIDARG, "(NULL,NULL,NULL,0,0,NULL), "
226                             "expected E_INVALIDARG, got %08x\n", (unsigned int)hr);
227
228     hr = ScriptGetCMap(NULL, NULL, TestItem1, cInChars, dwFlags, pwOutGlyphs3);
229     ok( hr == E_INVALIDARG, "(NULL,NULL,TestItem1, cInChars, dwFlags, pwOutGlyphs3), "
230                             "expected E_INVALIDARG, got %08x\n", (unsigned int)hr);
231
232     /* Set psc to NULL, to be able to check if a pointer is returned in psc */
233     psc = NULL;
234     hr = ScriptGetCMap(NULL, &psc, NULL, 0, 0, NULL);
235     ok( hr == E_INVALIDARG, "(NULL,&psc,NULL,0,0NULL), expected E_INVALIDARG, "
236                             "got %08x\n", (unsigned int)hr);
237     ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc);
238
239     /* Set psc to NULL, to be able to check if a pointer is returned in psc */
240     psc = NULL;
241     hr = ScriptGetCMap(NULL, &psc, TestItem1, cInChars, dwFlags, pwOutGlyphs3);
242     ok( hr == E_PENDING, "(NULL,&psc,), expected E_PENDING, got %08x\n", (unsigned int)hr);
243     ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc);
244     /*  Check to see if the results are the same as those returned by ScriptShape  */
245     hr = ScriptGetCMap(hdc, &psc, TestItem1, cInChars, dwFlags, pwOutGlyphs3);
246     ok (hr == 0, "ScriptGetCMap should return 0 not (%08x)\n", (unsigned int) hr);
247     ok (psc != NULL, "psc should not be null and have SCRIPT_CACHE buffer address\n");
248     for (cnt=0; cnt < cChars && pwOutGlyphs[cnt] == pwOutGlyphs3[cnt]; cnt++) {}
249     ok (cnt == cInChars, "Translation not correct. WCHAR %d - %04x != %04x\n",
250                          cnt, pwOutGlyphs[cnt], pwOutGlyphs3[cnt]);
251         
252     hr = ScriptFreeCache( &psc);
253     ok (!psc, "psc is not null after ScriptFreeCache\n");
254 }
255
256 void test_ScriptGetFontProperties(void)
257 {
258     HRESULT         hr;
259     HDC             hdc;
260     HWND            hwnd;
261     SCRIPT_CACHE    psc,old_psc;
262     SCRIPT_FONTPROPERTIES sfp;
263
264     /* Only do the bare minumum to get a valid hdc */
265     hwnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0,100,100,0, 0, 0, NULL);
266     assert(hwnd != 0);
267
268     hdc = GetDC(hwnd);
269     ok( hdc != NULL, "HDC failed to be created %p\n", hdc);
270
271     /* Some sanity checks for ScriptGetFontProperties */
272
273     hr = ScriptGetFontProperties(NULL,NULL,NULL);
274     ok( hr == E_INVALIDARG, "(NULL,NULL,NULL), expected E_INVALIDARG, got %08x\n", (unsigned int)hr);
275
276     hr = ScriptGetFontProperties(NULL,NULL,&sfp);
277     ok( hr == E_INVALIDARG, "(NULL,NULL,&sfp), expected E_INVALIDARG, got %08x\n", (unsigned int)hr);
278
279     /* Set psc to NULL, to be able to check if a pointer is returned in psc */
280     psc = NULL;
281     hr = ScriptGetFontProperties(NULL,&psc,NULL);
282     ok( hr == E_INVALIDARG, "(NULL,&psc,NULL), expected E_INVALIDARG, got %08x\n", (unsigned int)hr);
283     ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc);
284
285     /* Set psc to NULL, to be able to check if a pointer is returned in psc */
286     psc = NULL;
287     hr = ScriptGetFontProperties(NULL,&psc,&sfp);
288     ok( hr == E_PENDING, "(NULL,&psc,&sfp), expected E_PENDING, got %08x\n", (unsigned int)hr);
289     ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc);
290
291     hr = ScriptGetFontProperties(hdc,NULL,NULL);
292     ok( hr == E_INVALIDARG, "(hdc,NULL,NULL), expected E_INVALIDARG, got %08x\n", (unsigned int)hr);
293
294     hr = ScriptGetFontProperties(hdc,NULL,&sfp);
295     ok( hr == E_INVALIDARG, "(hdc,NULL,&sfp), expected E_INVALIDARG, got %08x\n", (unsigned int)hr);
296
297     /* Set psc to NULL, to be able to check if a pointer is returned in psc */
298     psc = NULL;
299     hr = ScriptGetFontProperties(hdc,&psc,NULL);
300     ok( hr == E_INVALIDARG, "(hdc,&psc,NULL), expected E_INVALIDARG, got %08x\n", (unsigned int)hr);
301     ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc);
302
303     /* Pass an uninitialized sfp */
304     psc = NULL;
305     hr = ScriptGetFontProperties(hdc,&psc,&sfp);
306     ok( hr == E_INVALIDARG, "(hdc,&psc,&sfp) partly uninitialized, expected E_INVALIDARG, got %08x\n", (unsigned int)hr);
307     ok( psc != NULL, "Expected a pointer in psc, got NULL\n");
308     ScriptFreeCache(&psc);
309     ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc);
310
311     /* Give it the correct cBytes, we don't care about what's coming back */
312     sfp.cBytes = sizeof(SCRIPT_FONTPROPERTIES);
313     psc = NULL;
314     hr = ScriptGetFontProperties(hdc,&psc,&sfp);
315     ok( hr == S_OK, "(hdc,&psc,&sfp) partly initialized, expected S_OK, got %08x\n", (unsigned int)hr);
316     ok( psc != NULL, "Expected a pointer in psc, got NULL\n");
317
318     /* Save the psc pointer */
319     old_psc = psc;
320     /* Now a NULL hdc again */
321     hr = ScriptGetFontProperties(NULL,&psc,&sfp);
322     ok( hr == S_OK, "(NULL,&psc,&sfp), expected S_OK, got %08x\n", (unsigned int)hr);
323     ok( psc == old_psc, "Expected psc not to be changed, was %p is now %p\n", old_psc, psc);
324     ScriptFreeCache(&psc);
325     ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc);
326
327     /* Cleanup */
328     ReleaseDC(hwnd, hdc);
329     DestroyWindow(hwnd);
330 }
331
332 void test_ScriptTextOut(void)
333 {
334     HRESULT         hr;
335     HWND            hwnd;
336     HDC             hdc;
337
338     int             cInChars;
339     int             cMaxItems;
340     SCRIPT_ITEM     pItem[255];
341     int             pcItems;
342     WCHAR           TestItem1[6] = {'T', 'e', 's', 't', 0x0166, 0}; 
343
344     SCRIPT_CACHE    psc;
345     int             cChars;
346     int             cMaxGlyphs;
347     unsigned short  pwOutGlyphs1[256];
348     unsigned short  pwLogClust[256];
349     SCRIPT_VISATTR  psva[256];
350     int             pcGlyphs;
351     int             piAdvance[256];
352     GOFFSET         pGoffset[256];
353     ABC             pABC[256];
354     RECT            rect;
355
356     /* We need a valid HDC to drive a lot of Script functions which requires the following    *
357      * to set up for the tests.                                                               */
358     hwnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0,100,100,
359                            0, 0, 0, NULL);
360     assert(hwnd != 0);
361     ShowWindow(hwnd, SW_SHOW);
362     UpdateWindow(hwnd);
363
364     hdc = GetDC(hwnd);                                      /* We now have a hdc             */
365     ok( hdc != NULL, "HDC failed to be created %p\n", hdc);
366
367     /* This is a valid test that will cause parsing to take place                             */
368     cInChars = 5;
369     cMaxItems = 255;
370     hr = ScriptItemize(TestItem1, cInChars, cMaxItems, NULL, NULL, pItem, &pcItems);
371     ok (hr == 0, "ScriptItemize should return 0, returned %08x\n", (unsigned int) hr);
372     /*  This test is for the interim operation of ScriptItemize where only one SCRIPT_ITEM is *
373      *  returned.                                                                             */
374     ok (pcItems > 0, "The number of SCRIPT_ITEMS should be greater than 0\n");
375     if (pcItems > 0)
376         ok (pItem[0].iCharPos == 0 && pItem[1].iCharPos == cInChars,
377             "Start pos not = 0 (%d) or end pos not = %d (%d)\n",
378             pItem[0].iCharPos, cInChars, pItem[1].iCharPos);
379
380     /* It would appear that we have a valid SCRIPT_ANALYSIS and can continue
381      * ie. ScriptItemize has succeeded and that pItem has been set                            */
382     cInChars = 5;
383     cMaxItems = 255;
384     if (hr == 0) {
385         psc = NULL;                                   /* must be null on first call           */
386         cChars = cInChars;
387         cMaxGlyphs = cInChars;
388         cMaxGlyphs = 256;
389         hr = ScriptShape(hdc, &psc, TestItem1, cChars,
390                          cMaxGlyphs, &pItem[0].a,
391                          pwOutGlyphs1, pwLogClust, psva, &pcGlyphs);
392         ok (hr == 0, "ScriptShape should return 0 not (%08x)\n", (unsigned int) hr);
393         ok (psc != NULL, "psc should not be null and have SCRIPT_CACHE buffer address\n");
394         ok (pcGlyphs == cChars, "Chars in (%d) should equal Glyphs out (%d)\n", cChars, pcGlyphs);
395         if (hr ==0) {
396             hr = ScriptPlace(NULL, &psc, pwOutGlyphs1, pcGlyphs, psva, &pItem[0].a, piAdvance,
397                              pGoffset, pABC);
398             ok (hr == 0, "Should return 0 not (%08x)\n", (unsigned int) hr);
399             ScriptFreeCache(&psc);              /* Get rid of psc for next test set */
400             ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc);
401
402             hr = ScriptTextOut(NULL, NULL, 0, 0, 0, NULL, NULL, NULL, 0, NULL, 0, NULL, NULL, NULL);
403             ok (hr == E_INVALIDARG, "Should return 0 not (%08x)\n", (unsigned int) hr);
404
405             hr = ScriptTextOut(NULL, NULL, 0, 0, 0, NULL, &pItem[0].a, NULL, 0, pwOutGlyphs1, pcGlyphs,
406                                piAdvance, NULL, pGoffset);
407             ok( hr == E_INVALIDARG, "(NULL,NULL,TestItem1, cInChars, dwFlags, pwOutGlyphs3), "
408                                     "expected E_INVALIDARG, got %08x\n", (unsigned int)hr);
409
410             /* Set psc to NULL, to be able to check if a pointer is returned in psc */
411             psc = NULL;
412             hr = ScriptTextOut(NULL, &psc, 0, 0, 0, NULL, NULL, NULL, 0, NULL, 0,
413                                NULL, NULL, NULL);
414             ok( hr == E_INVALIDARG, "(NULL,&psc,NULL,0,0,0,NULL,), expected E_INVALIDARG, "
415                                     "got %08x\n", (unsigned int)hr);
416             ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc);
417
418             /* Set psc to NULL, to be able to check if a pointer is returned in psc */
419             psc = NULL;
420             hr = ScriptTextOut(NULL, &psc, 0, 0, 0, NULL, &pItem[0].a, NULL, 0, pwOutGlyphs1, pcGlyphs,
421                                piAdvance, NULL, pGoffset);
422             ok( hr == E_PENDING, "(NULL,&psc,), expected E_PENDING, got %08x\n", (unsigned int)hr);
423             ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc);
424
425             /* Se that is gets a psc and that returns 0 status */
426             hr = ScriptTextOut(hdc, &psc, 0, 0, 0, NULL, &pItem[0].a, NULL, 0, pwOutGlyphs1, pcGlyphs,
427                                piAdvance, NULL, pGoffset);
428             ok (hr == 0, "ScriptTextOut should return 0 not (%08x)\n", (unsigned int) hr);
429             ok (psc != NULL, "psc should not be null and have SCRIPT_CACHE buffer address\n");
430
431             /* Test Rect Rgn is acceptable and that it works without hdc */
432             rect.top = 10;
433             rect.bottom = 20;
434             rect.left = 10;
435             rect.right = 40;
436             hr = ScriptTextOut(NULL, &psc, 0, 0, 0, &rect, &pItem[0].a, NULL, 0, pwOutGlyphs1, pcGlyphs,
437                                piAdvance, NULL, pGoffset);
438             ok (hr == 0, "ScriptTextOut should return 0 not (%08x)\n", (unsigned int) hr);
439             ok (psc != NULL, "psc should not be null and have SCRIPT_CACHE buffer address\n");
440
441             /* Clean up and go   */
442             ScriptFreeCache(&psc);
443             ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc);
444         }
445     }
446     ReleaseDC(hwnd, hdc);
447     DestroyWindow(hwnd);
448 }
449
450 static void test_ScriptString(void)
451 {
452     HRESULT         hr;
453     HDC             hdc = 0;
454     WCHAR           teststr[6] = {'T', 'e', 's', 't', '1', '\0'};
455     void            *pString = (WCHAR *) &teststr;
456     int             cString = 5;
457     int             cGlyphs = cString * 2 + 16;
458     int             iCharset = -1;
459     DWORD           dwFlags = SSA_GLYPHS;
460     int             iReqWidth = 100;
461     SCRIPT_CONTROL  psControl;
462     SCRIPT_STATE    psState;
463     const int       piDx[5] = {10, 10, 10, 10, 10};
464     SCRIPT_TABDEF   pTabdef;
465     const BYTE      pbInClass = 0;
466     SCRIPT_STRING_ANALYSIS pssa;
467
468     int iX = 10; 
469     int iY = 100;
470     UINT uOptions = 0; 
471     const RECT prc = {0, 50, 100, 100}; 
472     int iMinSel = 0; 
473     int iMaxSel = 0;
474     BOOL fDisabled = FALSE;
475     hr = ScriptStringAnalyse( hdc, pString, cString, cGlyphs, iCharset, dwFlags,
476                               iReqWidth, &psControl, &psState, piDx, &pTabdef,
477                               &pbInClass, &pssa);
478     ok(hr == E_INVALIDARG, "ScriptStringAnalyse Stub should return E_INVALIDARG not %08x\n", (unsigned int) hr);
479     hr = ScriptStringOut(pssa, iX, iY, uOptions, &prc, iMinSel, iMaxSel,fDisabled);
480     ok(hr == E_NOTIMPL, "ScriptStringOut Stub should return E_NOTIMPL not %08x\n", (unsigned int) hr);
481     hr = ScriptStringFree(&pssa);
482     ok(hr == S_OK, "ScriptStringFree Stub should return S_OK not %08x\n", (unsigned int) hr);
483 }
484
485 START_TEST(usp10)
486 {
487     unsigned short  pwOutGlyphs[256];
488
489     test_ScriptItemIzeShapePlace(pwOutGlyphs);
490     test_ScriptGetCMap(pwOutGlyphs);
491     test_ScriptGetFontProperties();
492     test_ScriptTextOut();
493     test_ScriptString();
494 }