usp10: Fix glyph comparsion between tests.
[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(HDC hdc, unsigned short pwOutGlyphs[256])
36 {
37     HRESULT         hr;
38     int             iMaxProps;
39     const SCRIPT_PROPERTIES **ppSp;
40
41     int             cInChars;
42     int             cMaxItems;
43     SCRIPT_ITEM     pItem[255];
44     int             pcItems;
45     WCHAR           TestItem1[] = {'T', 'e', 's', 't', 'a', 0}; 
46     WCHAR           TestItem2[] = {'T', 'e', 's', 't', 'b', 0}; 
47
48     SCRIPT_CACHE    psc;
49     int             cChars;
50     int             cMaxGlyphs;
51     unsigned short  pwOutGlyphs1[256];
52     unsigned short  pwOutGlyphs2[256];
53     unsigned short  pwLogClust[256];
54     SCRIPT_VISATTR  psva[256];
55     int             pcGlyphs;
56     int             piAdvance[256];
57     GOFFSET         pGoffset[256];
58     ABC             pABC[256];
59     LOGFONTA        lf;
60     HFONT           zfont;
61     int             cnt;
62
63
64     lstrcpyA(lf.lfFaceName, "Symbol");
65     lf.lfHeight = 10;
66     lf.lfItalic = 0;
67     lf.lfEscapement = 0;
68     lf.lfOrientation = 0;
69     lf.lfUnderline = 0;
70     lf.lfStrikeOut = 0;
71     lf.lfWeight = 3;
72     lf.lfWidth = 10;
73
74     zfont = (HFONT) SelectObject(hdc, CreateFontIndirectA(&lf));
75
76     /* Start testing usp10 functions                                                         */
77     /* This test determines that the pointer returned by ScriptGetProperties is valid
78      * by checking a known value in the table                                                */
79     hr = ScriptGetProperties(&ppSp, &iMaxProps);
80     trace("number of script properties %d\n", iMaxProps);
81     ok (iMaxProps > 0, "Number of scripts returned should not be 0\n"); 
82     if  (iMaxProps > 0)
83          ok( ppSp[5]->langid == 9, "Langid[5] not = to 9\n"); /* Check a known value to ensure   */
84                                                               /* ptrs work                       */
85
86
87     /* This set of tests are to check that the various edits in ScriptIemize work           */
88     cInChars = 5;                                        /* Length of test without NULL     */
89     cMaxItems = 1;                                       /* Check threshold value           */
90     hr = ScriptItemize(TestItem1, cInChars, cMaxItems, NULL, NULL, pItem, &pcItems);
91     ok (hr == E_INVALIDARG, "ScriptItemize should return E_INVALIDARG if cMaxItems < 2.  Was %d\n",
92         cMaxItems);
93     cInChars = 5;
94     cMaxItems = 255;
95     hr = ScriptItemize(NULL, cInChars, cMaxItems, NULL, NULL, pItem, &pcItems);
96     ok (hr == E_INVALIDARG, "ScriptItemize should return E_INVALIDARG if pwcInChars is NULL\n");
97
98     cInChars = 5;
99     cMaxItems = 255;
100     hr = ScriptItemize(TestItem1, 0, cMaxItems, NULL, NULL, pItem, &pcItems);
101     ok (hr == E_INVALIDARG, "ScriptItemize should return E_INVALIDARG if cInChars is 0\n");
102
103     cInChars = 5;
104     cMaxItems = 255;
105     hr = ScriptItemize(TestItem1, cInChars, cMaxItems, NULL, NULL, NULL, &pcItems);
106     ok (hr == E_INVALIDARG, "ScriptItemize should return E_INVALIDARG if pItems is NULL\n");
107
108     /* This is a valid test that will cause parsing to take place                             */
109     cInChars = 5;
110     cMaxItems = 255;
111     hr = ScriptItemize(TestItem1, cInChars, cMaxItems, NULL, NULL, pItem, &pcItems);
112     ok (hr == 0, "ScriptItemize should return 0, returned %08x\n", (unsigned int) hr);
113     /*  This test is for the interim operation of ScriptItemize where only one SCRIPT_ITEM is *
114      *  returned.                                                                             */
115     ok (pcItems > 0, "The number of SCRIPT_ITEMS should be greater than 0\n");
116     if (pcItems > 0)
117         ok (pItem[0].iCharPos == 0 && pItem[1].iCharPos == cInChars,
118             "Start pos not = 0 (%d) or end pos not = %d (%d)\n",
119             pItem[0].iCharPos, cInChars, pItem[1].iCharPos);
120
121     /* It would appear that we have a valid SCRIPT_ANALYSIS and can continue
122      * ie. ScriptItemize has succeeded and that pItem has been set                            */
123     cInChars = 5;
124     cMaxItems = 255;
125     if (hr == 0) {
126         psc = NULL;                                   /* must be null on first call           */
127         cChars = cInChars;
128         cMaxGlyphs = cInChars;
129         hr = ScriptShape(NULL, &psc, TestItem1, cChars,
130                          cMaxGlyphs, &pItem[0].a,
131                          pwOutGlyphs1, pwLogClust, psva, &pcGlyphs);
132         ok (hr == E_PENDING, "If psc is NULL (%08x) the E_PENDING should be returned\n",
133                         (unsigned int) hr);
134         cMaxGlyphs = 4;
135         hr = ScriptShape(hdc, &psc, TestItem1, cChars,
136                          cMaxGlyphs, &pItem[0].a,
137                          pwOutGlyphs1, pwLogClust, psva, &pcGlyphs);
138         ok (hr == E_OUTOFMEMORY, "If not enough output area cChars (%d) is > than CMaxGlyphs "
139                                  "(%d) but not E_OUTOFMEMORY\n",
140                                  cChars, cMaxGlyphs);
141         cMaxGlyphs = 256;
142         hr = ScriptShape(hdc, &psc, TestItem1, cChars,
143                          cMaxGlyphs, &pItem[0].a,
144                          pwOutGlyphs1, pwLogClust, psva, &pcGlyphs);
145         ok (hr == 0, "ScriptShape should return 0 not (%08x)\n", (unsigned int) hr);
146         ok (psc != NULL, "psc should not be null and have SCRIPT_CACHE buffer address\n");
147         ok (pcGlyphs == cChars, "Chars in (%d) should equal Glyphs out (%d)\n", cChars, pcGlyphs);
148         if (hr ==0) {
149             hr = ScriptPlace(hdc, &psc, pwOutGlyphs1, pcGlyphs, psva, &pItem[0].a, piAdvance,
150                              pGoffset, pABC);
151             ok (hr == 0, "ScriptPlace should return 0 not (%08x)\n", (unsigned int) hr);
152             hr = ScriptPlace(NULL, &psc, pwOutGlyphs1, pcGlyphs, psva, &pItem[0].a, piAdvance,
153                              pGoffset, pABC);
154             ok (hr == 0, "ScriptPlace should return 0 not (%08x)\n", (unsigned int) hr);
155             for (cnt=0; cnt < pcGlyphs; cnt++)
156                 pwOutGlyphs[cnt] = pwOutGlyphs1[cnt];                 /* Send to next function */
157         }
158
159         /* This test will check to make sure that SCRIPT_CACHE is reused and that not translation   *
160          * takes place if fNoGlyphIndex is set.                                                     */
161
162         cInChars = 5;
163         cMaxItems = 255;
164         hr = ScriptItemize(TestItem2, cInChars, cMaxItems, NULL, NULL, pItem, &pcItems);
165         ok (hr == 0, "ScriptItemize should return 0, returned %08x\n", (unsigned int) hr);
166         /*  This test is for the intertrim operation of ScriptItemize where only one SCRIPT_ITEM is *
167          *  returned.                                                                               */
168         ok (pItem[0].iCharPos == 0 && pItem[1].iCharPos == cInChars,
169                             "Start pos not = 0 (%d) or end pos not = %d (%d)\n",
170                              pItem[0].iCharPos, cInChars, pItem[1].iCharPos);
171         /* It would appear that we have a valid SCRIPT_ANALYSIS and can continue                    */
172         if (hr == 0) {
173              cChars = cInChars;
174              cMaxGlyphs = 256;
175              pItem[0].a.fNoGlyphIndex = 1;                /* say no translate                     */
176              hr = ScriptShape(NULL, &psc, TestItem2, cChars,
177                               cMaxGlyphs, &pItem[0].a,
178                               pwOutGlyphs2, pwLogClust, psva, &pcGlyphs);
179              ok (hr != E_PENDING, "If psc should not be NULL (%08x) and the E_PENDING should be returned\n",
180                 (unsigned int) hr);
181              ok (hr == 0, "ScriptShape should return 0 not (%08x)\n", (unsigned int) hr);
182              ok (psc != NULL, "psc should not be null and have SCRIPT_CACHE buffer address\n");
183              ok (pcGlyphs == cChars, "Chars in (%d) should equal Glyphs out (%d)\n", cChars, pcGlyphs);
184              for (cnt=0; cnt < cChars && TestItem2[cnt] == pwOutGlyphs2[cnt]; cnt++) {}
185              ok (cnt == cChars, "Translation to place when told not to. WCHAR %d - %04x != %04x\n",
186                            cnt, TestItem2[cnt], pwOutGlyphs2[cnt]);
187              if (hr ==0) {
188                  hr = ScriptPlace(hdc, &psc, pwOutGlyphs2, pcGlyphs, psva, &pItem[0].a, piAdvance,
189                                   pGoffset, pABC);
190                  ok (hr == 0, "ScriptPlace should return 0 not (%08x)\n", (unsigned int) hr);
191              }
192         }
193         hr = ScriptFreeCache( &psc);
194         ok (!psc, "psc is not null after ScriptFreeCache\n");
195
196     }
197 }
198
199 void test_ScriptGetCMap(HDC hdc, unsigned short pwOutGlyphs[256])
200 {
201     HRESULT         hr;
202     SCRIPT_CACHE    psc = NULL;
203     int             cInChars;
204     int             cChars;
205     unsigned short  pwOutGlyphs3[256];
206     WCHAR           TestItem1[] = {'T', 'e', 's', 't', 'a', 0}; 
207     DWORD           dwFlags;
208     int             cnt;
209
210     /*  Check to make sure that SCRIPT_CACHE gets allocated ok                     */
211     dwFlags = 0;
212     cInChars = cChars = 5;
213     /* Some sanity checks for ScriptGetCMap */
214
215     hr = ScriptGetCMap(NULL, NULL, NULL, 0, 0, NULL);
216     ok( hr == E_INVALIDARG, "(NULL,NULL,NULL,0,0,NULL), "
217                             "expected E_INVALIDARG, got %08x\n", (unsigned int)hr);
218
219     hr = ScriptGetCMap(NULL, NULL, TestItem1, cInChars, dwFlags, pwOutGlyphs3);
220     ok( hr == E_INVALIDARG, "(NULL,NULL,TestItem1, cInChars, dwFlags, pwOutGlyphs3), "
221                             "expected E_INVALIDARG, got %08x\n", (unsigned int)hr);
222
223     /* Set psc to NULL, to be able to check if a pointer is returned in psc */
224     psc = NULL;
225     hr = ScriptGetCMap(NULL, &psc, NULL, 0, 0, NULL);
226     ok( hr == E_PENDING, "(NULL,&psc,NULL,0,0NULL), expected E_PENDING, "
227                          "got %08x\n", (unsigned int)hr);
228     ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc);
229
230     /* Set psc to NULL but add hdc, to be able to check if a pointer is returned in psc */
231     psc = NULL;
232     hr = ScriptGetCMap(hdc, &psc, NULL, 0, 0, NULL);
233     ok( hr == S_OK, "ScriptGetCMap(NULL,&psc,NULL,0,0,NULL), expected S_OK, "
234                     "got %08x\n", (unsigned int)hr);
235     ok( psc != NULL, "ScritpGetCMap expected psc to be not NULL\n");
236
237     /* Set psc to NULL, to be able to check if a pointer is returned in psc */
238     psc = NULL;
239     hr = ScriptGetCMap(NULL, &psc, TestItem1, cInChars, dwFlags, pwOutGlyphs3);
240     ok( hr == E_PENDING, "(NULL,&psc,), expected E_PENDING, got %08x\n", (unsigned int)hr);
241     ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc);
242     /*  Check to see if the results are the same as those returned by ScriptShape  */
243     hr = ScriptGetCMap(hdc, &psc, TestItem1, cInChars, dwFlags, pwOutGlyphs3);
244     ok (hr == 0, "ScriptGetCMap should return 0 not (%08x)\n", (unsigned int) hr);
245     ok (psc != NULL, "psc should not be null and have SCRIPT_CACHE buffer address\n");
246     for (cnt=0; cnt < cChars && pwOutGlyphs[cnt] == pwOutGlyphs3[cnt]; cnt++) {}
247     ok (cnt == cInChars, "Translation not correct. WCHAR %d - %04x != %04x\n",
248                          cnt, pwOutGlyphs[cnt], pwOutGlyphs3[cnt]);
249         
250     hr = ScriptFreeCache( &psc);
251     ok (!psc, "psc is not null after ScriptFreeCache\n");
252
253 }
254
255 void test_ScriptGetFontProperties(void)
256 {
257     HRESULT         hr;
258     HDC             hdc;
259     HWND            hwnd;
260     SCRIPT_CACHE    psc,old_psc;
261     SCRIPT_FONTPROPERTIES sfp;
262
263     /* Only do the bare minumum to get a valid hdc */
264     hwnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0,100,100,0, 0, 0, NULL);
265     assert(hwnd != 0);
266
267     hdc = GetDC(hwnd);
268     ok( hdc != NULL, "HDC failed to be created %p\n", hdc);
269
270     /* Some sanity checks for ScriptGetFontProperties */
271
272     hr = ScriptGetFontProperties(NULL,NULL,NULL);
273     ok( hr == E_INVALIDARG, "(NULL,NULL,NULL), expected E_INVALIDARG, got %08x\n", (unsigned int)hr);
274
275     hr = ScriptGetFontProperties(NULL,NULL,&sfp);
276     ok( hr == E_INVALIDARG, "(NULL,NULL,&sfp), expected E_INVALIDARG, got %08x\n", (unsigned int)hr);
277
278     /* Set psc to NULL, to be able to check if a pointer is returned in psc */
279     psc = NULL;
280     hr = ScriptGetFontProperties(NULL,&psc,NULL);
281     ok( hr == E_INVALIDARG, "(NULL,&psc,NULL), expected E_INVALIDARG, got %08x\n", (unsigned int)hr);
282     ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc);
283
284     /* Set psc to NULL, to be able to check if a pointer is returned in psc */
285     psc = NULL;
286     hr = ScriptGetFontProperties(NULL,&psc,&sfp);
287     ok( hr == E_PENDING, "(NULL,&psc,&sfp), expected E_PENDING, got %08x\n", (unsigned int)hr);
288     ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc);
289
290     hr = ScriptGetFontProperties(hdc,NULL,NULL);
291     ok( hr == E_INVALIDARG, "(hdc,NULL,NULL), expected E_INVALIDARG, got %08x\n", (unsigned int)hr);
292
293     hr = ScriptGetFontProperties(hdc,NULL,&sfp);
294     ok( hr == E_INVALIDARG, "(hdc,NULL,&sfp), expected E_INVALIDARG, got %08x\n", (unsigned int)hr);
295
296     /* Set psc to NULL, to be able to check if a pointer is returned in psc */
297     psc = NULL;
298     hr = ScriptGetFontProperties(hdc,&psc,NULL);
299     ok( hr == E_INVALIDARG, "(hdc,&psc,NULL), expected E_INVALIDARG, got %08x\n", (unsigned int)hr);
300     ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc);
301
302     /* Pass an uninitialized sfp */
303     psc = NULL;
304     hr = ScriptGetFontProperties(hdc,&psc,&sfp);
305     ok( hr == E_INVALIDARG, "(hdc,&psc,&sfp) partly uninitialized, expected E_INVALIDARG, got %08x\n", (unsigned int)hr);
306     ok( psc != NULL, "Expected a pointer in psc, got NULL\n");
307     ScriptFreeCache(&psc);
308     ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc);
309
310     /* Give it the correct cBytes, we don't care about what's coming back */
311     sfp.cBytes = sizeof(SCRIPT_FONTPROPERTIES);
312     psc = NULL;
313     hr = ScriptGetFontProperties(hdc,&psc,&sfp);
314     ok( hr == S_OK, "(hdc,&psc,&sfp) partly initialized, expected S_OK, got %08x\n", (unsigned int)hr);
315     ok( psc != NULL, "Expected a pointer in psc, got NULL\n");
316
317     /* Save the psc pointer */
318     old_psc = psc;
319     /* Now a NULL hdc again */
320     hr = ScriptGetFontProperties(NULL,&psc,&sfp);
321     ok( hr == S_OK, "(NULL,&psc,&sfp), expected S_OK, got %08x\n", (unsigned int)hr);
322     ok( psc == old_psc, "Expected psc not to be changed, was %p is now %p\n", old_psc, psc);
323     ScriptFreeCache(&psc);
324     ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc);
325
326     /* Cleanup */
327     ReleaseDC(hwnd, hdc);
328     DestroyWindow(hwnd);
329 }
330
331 void test_ScriptTextOut(void)
332 {
333     HRESULT         hr;
334     HWND            hwnd;
335     HDC             hdc;
336
337     int             cInChars;
338     int             cMaxItems;
339     SCRIPT_ITEM     pItem[255];
340     int             pcItems;
341     WCHAR           TestItem1[] = {'T', 'e', 's', 't', 'a', 0}; 
342
343     SCRIPT_CACHE    psc;
344     int             cChars;
345     int             cMaxGlyphs;
346     unsigned short  pwOutGlyphs1[256];
347     WORD            pwLogClust[256];
348     SCRIPT_VISATTR  psva[256];
349     int             pcGlyphs;
350     int             piAdvance[256];
351     GOFFSET         pGoffset[256];
352     ABC             pABC[256];
353     RECT            rect;
354     int             piX;
355     int             iCP = 1;
356     BOOL            fTrailing = FALSE;
357     SCRIPT_LOGATTR  *psla;
358     SCRIPT_LOGATTR  sla[256];
359
360     /* We need a valid HDC to drive a lot of Script functions which requires the following    *
361      * to set up for the tests.                                                               */
362     hwnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0,100,100,
363                            0, 0, 0, NULL);
364     assert(hwnd != 0);
365     ShowWindow(hwnd, SW_SHOW);
366     UpdateWindow(hwnd);
367
368     hdc = GetDC(hwnd);                                      /* We now have a hdc             */
369     ok( hdc != NULL, "HDC failed to be created %p\n", hdc);
370
371     /* This is a valid test that will cause parsing to take place                             */
372     cInChars = 5;
373     cMaxItems = 255;
374     hr = ScriptItemize(TestItem1, cInChars, cMaxItems, NULL, NULL, pItem, &pcItems);
375     ok (hr == 0, "ScriptItemize should return 0, returned %08x\n", (unsigned int) hr);
376     /*  This test is for the interim operation of ScriptItemize where only one SCRIPT_ITEM is *
377      *  returned.                                                                             */
378     ok (pcItems > 0, "The number of SCRIPT_ITEMS should be greater than 0\n");
379     if (pcItems > 0)
380         ok (pItem[0].iCharPos == 0 && pItem[1].iCharPos == cInChars,
381             "Start pos not = 0 (%d) or end pos not = %d (%d)\n",
382             pItem[0].iCharPos, cInChars, pItem[1].iCharPos);
383
384     /* It would appear that we have a valid SCRIPT_ANALYSIS and can continue
385      * ie. ScriptItemize has succeeded and that pItem has been set                            */
386     cInChars = 5;
387     cMaxItems = 255;
388     if (hr == 0) {
389         psc = NULL;                                   /* must be null on first call           */
390         cChars = cInChars;
391         cMaxGlyphs = cInChars;
392         cMaxGlyphs = 256;
393         hr = ScriptShape(hdc, &psc, TestItem1, cChars,
394                          cMaxGlyphs, &pItem[0].a,
395                          pwOutGlyphs1, pwLogClust, psva, &pcGlyphs);
396         ok (hr == 0, "ScriptShape should return 0 not (%08x)\n", (unsigned int) hr);
397         ok (psc != NULL, "psc should not be null and have SCRIPT_CACHE buffer address\n");
398         ok (pcGlyphs == cChars, "Chars in (%d) should equal Glyphs out (%d)\n", cChars, pcGlyphs);
399         if (hr ==0) {
400             /* Note hdc is needed as glyph info is not yet in psc                  */
401             hr = ScriptPlace(hdc, &psc, pwOutGlyphs1, pcGlyphs, psva, &pItem[0].a, piAdvance,
402                              pGoffset, pABC);
403             ok (hr == 0, "Should return 0 not (%08x)\n", (unsigned int) hr);
404             ScriptFreeCache(&psc);              /* Get rid of psc for next test set */
405             ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc);
406
407             hr = ScriptTextOut(NULL, NULL, 0, 0, 0, NULL, NULL, NULL, 0, NULL, 0, NULL, NULL, NULL);
408             ok (hr == E_INVALIDARG, "Should return 0 not (%08x)\n", (unsigned int) hr);
409
410             hr = ScriptTextOut(NULL, NULL, 0, 0, 0, NULL, &pItem[0].a, NULL, 0, pwOutGlyphs1, pcGlyphs,
411                                piAdvance, NULL, pGoffset);
412             ok( hr == E_INVALIDARG, "(NULL,NULL,TestItem1, cInChars, dwFlags, pwOutGlyphs3), "
413                                     "expected E_INVALIDARG, got %08x\n", (unsigned int)hr);
414
415             /* Set psc to NULL, to be able to check if a pointer is returned in psc */
416             psc = NULL;
417             hr = ScriptTextOut(NULL, &psc, 0, 0, 0, NULL, NULL, NULL, 0, NULL, 0,
418                                NULL, NULL, NULL);
419             ok( hr == E_INVALIDARG, "(NULL,&psc,NULL,0,0,0,NULL,), expected E_INVALIDARG, "
420                                     "got %08x\n", (unsigned int)hr);
421             ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc);
422
423             /* Set psc to NULL, to be able to check if a pointer is returned in psc
424              * hdc is required for this one rather than the usual optional          */
425             psc = NULL;
426             hr = ScriptTextOut(NULL, &psc, 0, 0, 0, NULL, &pItem[0].a, NULL, 0, pwOutGlyphs1, pcGlyphs,
427                                piAdvance, NULL, pGoffset);
428             ok( hr == E_INVALIDARG, "(NULL,&psc,), expected E_INVALIDARG, got %08x\n", (unsigned int)hr);
429             ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc);
430
431             /* Set that is gets a psc and that returns 0 status */
432             hr = ScriptTextOut(hdc, &psc, 0, 0, 0, NULL, &pItem[0].a, NULL, 0, pwOutGlyphs1, pcGlyphs,
433                                piAdvance, NULL, pGoffset);
434             ok (hr == 0, "ScriptTextOut should return 0 not (%08x)\n", (unsigned int) hr);
435             ok (psc != NULL, "psc should not be null and have SCRIPT_CACHE buffer address\n");
436
437             /* Test Rect Rgn is acceptable */
438             rect.top = 10;
439             rect.bottom = 20;
440             rect.left = 10;
441             rect.right = 40;
442             hr = ScriptTextOut(hdc, &psc, 0, 0, 0, &rect, &pItem[0].a, NULL, 0, pwOutGlyphs1, pcGlyphs,
443                                piAdvance, NULL, pGoffset);
444             ok (hr == 0, "ScriptTextOut should return 0 not (%08x)\n", (unsigned int) hr);
445             ok (psc != NULL, "psc should not be null and have SCRIPT_CACHE buffer address\n");
446
447             iCP = 1;
448             hr = ScriptCPtoX(iCP, fTrailing, cChars, pcGlyphs, (const WORD *) &pwLogClust,
449                             (const SCRIPT_VISATTR *) &psva, (const int *)&piAdvance, &pItem[0].a, &piX);
450             ok(hr == S_OK, "ScriptCPtoX Stub should return S_OK not %08x\n", (unsigned int) hr);
451
452             psla = (SCRIPT_LOGATTR *)&sla;
453             hr = ScriptBreak(TestItem1, cChars, &pItem[0].a, psla);
454             ok(hr == S_OK, "ScriptBreak Stub should return S_OK not %08x\n", (unsigned int) hr);
455
456             /* Clean up and go   */
457             ScriptFreeCache(&psc);
458             ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc);
459         }
460     }
461     ReleaseDC(hwnd, hdc);
462     DestroyWindow(hwnd);
463 }
464
465 static void test_ScriptXtoX(void)
466 /****************************************************************************************
467  *  This routine tests the ScriptXtoCP and ScriptCPtoX functions using static variables *
468  ****************************************************************************************/
469 {
470     int iX, iCP;
471     int cChars;
472     int cGlyphs;
473     WORD pwLogClust[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
474     SCRIPT_VISATTR psva[10];
475     int piAdvance[10] = {200, 190, 210, 180, 170, 204, 189, 195, 212, 203};
476     SCRIPT_ANALYSIS psa;
477     int piCP, piX;
478     int piTrailing;
479     BOOL fTrailing;
480     HRESULT hr;
481
482     iX = -1;
483     cChars = 10;
484     cGlyphs = 10;
485     hr = ScriptXtoCP(iX, cChars, cGlyphs, pwLogClust, psva, piAdvance, &psa, &piCP, &piTrailing);
486     ok(hr == S_OK, "ScriptXtoCP should return S_OK not %d\n", (unsigned int) hr);
487     ok(piCP == -1, "Negative iX should return piCP=-1 not %d\n", piCP);
488     ok(piTrailing == TRUE, "Negative iX should return piTrailing=TRUE not %d", piTrailing);
489     iX = 1954;
490     cChars = 10;
491     cGlyphs = 10;
492     hr = ScriptXtoCP(iX, cChars, cGlyphs, pwLogClust, psva, piAdvance, &psa, &piCP, &piTrailing);
493     ok(hr == S_OK, "ScriptXtoCP should return S_OK not %d\n", (unsigned int) hr);
494     ok(piCP == 10, "Excessive iX should return piCP=10 not %d\n", piCP);
495     ok(piTrailing == FALSE, "Excessive iX should return piTrailing=FALSE not %d\n", piTrailing);
496     iX = 779;
497     cChars = 10;
498     cGlyphs = 10;
499     hr = ScriptXtoCP(iX, cChars, cGlyphs, pwLogClust, psva, piAdvance, &psa, &piCP, &piTrailing);
500     ok(hr == S_OK, "ScriptXtoCP should return S_OK not %d\n", (unsigned int) hr);
501     ok(piCP == 3, "iX=%d should return piCP=3 not %d\n", iX, piCP);
502     ok(piTrailing == 1, "iX=%d should return piTrailing=1 not %d\n", iX, piTrailing);
503     iX = 780;
504     cChars = 10;
505     cGlyphs = 10;
506     hr = ScriptXtoCP(iX, cChars, cGlyphs, pwLogClust, psva, piAdvance, &psa, &piCP, &piTrailing);
507     ok(hr == S_OK, "ScriptXtoCP should return S_OK not %d\n", (unsigned int) hr);
508     ok(piCP == 3, "iX=%d should return piCP=3 not %d\n", iX, piCP);
509     ok(piTrailing == 1, "iX=%d should return piTrailing=1 not %d\n", iX, piTrailing);
510     iX = 868;
511     cChars = 10;
512     cGlyphs = 10;
513     hr = ScriptXtoCP(iX, cChars, cGlyphs, pwLogClust, psva, piAdvance, &psa, &piCP, &piTrailing);
514     ok(hr == S_OK, "ScriptXtoCP should return S_OK not %d\n", (unsigned int) hr);
515     ok(piCP == 4, "iX=%d should return piCP=4 not %d\n", iX, piCP);
516
517     iCP=5;
518     fTrailing = FALSE;
519     cChars = 10;
520     cGlyphs = 10;
521     hr = ScriptCPtoX(iCP, fTrailing, cChars, cGlyphs, pwLogClust, psva, piAdvance, &psa, &piX);
522     ok(hr == S_OK, "ScriptCPtoX should return S_OK not %d\n", (unsigned int) hr);
523     ok(piX == 976, "iCP=%d should return piX=976 not %d\n", iCP, piX);
524     iCP=5;
525     fTrailing = TRUE;
526     cChars = 10;
527     cGlyphs = 10;
528     hr = ScriptCPtoX(iCP, fTrailing, cChars, cGlyphs, pwLogClust, psva, piAdvance, &psa, &piX);
529     ok(hr == S_OK, "ScriptCPtoX should return S_OK not %d\n", (unsigned int) hr);
530     ok(piX == 1171, "iCP=%d should return piX=1171 not %d\n", iCP, piX);   
531     iCP=6;
532     fTrailing = FALSE;
533     cChars = 10;
534     cGlyphs = 10;
535     hr = ScriptCPtoX(iCP, fTrailing, cChars, cGlyphs, pwLogClust, psva, piAdvance, &psa, &piX);
536     ok(hr == S_OK, "ScriptCPtoX should return S_OK not %d\n", (unsigned int) hr);
537     ok(piX == 1171, "iCP=%d should return piX=1171 not %d\n", iCP, piX);
538     iCP=11;
539     fTrailing = FALSE;
540     cChars = 10;
541     cGlyphs = 10;
542     hr = ScriptCPtoX(iCP, fTrailing, cChars, cGlyphs, pwLogClust, psva, piAdvance, &psa, &piX);
543     ok(hr == S_OK, "ScriptCPtoX should return S_OK not %d\n", (unsigned int) hr);
544     ok(piX == 1953, "iCP=%d should return piX=1953 not %d\n", iCP, piX);
545     iCP=11;
546     fTrailing = TRUE;
547     cChars = 10;
548     cGlyphs = 10;
549     hr = ScriptCPtoX(iCP, fTrailing, cChars, cGlyphs, pwLogClust, psva, piAdvance, &psa, &piX);
550     ok(hr == S_OK, "ScriptCPtoX should return S_OK not %d\n", (unsigned int) hr);
551     ok(piX == 1953, "iCP=%d should return piX=1953 not %d\n", iCP, piX); 
552
553 }
554
555 static void test_ScriptString(void)
556 {
557     HRESULT         hr;
558     HWND            hwnd;
559     HDC             hdc = 0;
560     WCHAR           teststr[] = {'T', 'e', 's', 't', 'a', '\0'};
561     void            *pString = (WCHAR *) &teststr;
562     int             cString = 5;
563     int             cGlyphs = cString * 2 + 16;
564     int             iCharset = -1;
565     DWORD           dwFlags = SSA_GLYPHS;
566     int             iReqWidth = 100;
567     SCRIPT_CONTROL  psControl;
568     SCRIPT_STATE    psState;
569     const int       piDx[5] = {10, 10, 10, 10, 10};
570     SCRIPT_TABDEF   pTabdef;
571     const BYTE      pbInClass = 0;
572     SCRIPT_STRING_ANALYSIS pssa = NULL;
573
574     int             iX = 10; 
575     int             iY = 100;
576     UINT            uOptions = 0; 
577     const RECT      prc = {0, 50, 100, 100}; 
578     int             iMinSel = 0; 
579     int             iMaxSel = 0;
580     BOOL            fDisabled = FALSE;
581
582     LOGFONTA        lf;
583     HFONT           zfont;
584
585     /* We need a valid HDC to drive a lot of Script functions which requires the following    *
586      * to set up for the tests.                                                               */
587     hwnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0,100,100,
588                            0, 0, 0, NULL);
589     assert(hwnd != 0);
590
591     hdc = GetDC(hwnd);                                      /* We now have a hdc             */
592     ok( hdc != NULL, "HDC failed to be created %p\n", hdc);
593
594     lstrcpyA(lf.lfFaceName, "Symbol");
595     lf.lfHeight = 10;
596     lf.lfItalic = 0;
597     lf.lfEscapement = 0;
598     lf.lfOrientation = 0;
599     lf.lfUnderline = 0;
600     lf.lfStrikeOut = 0;
601     lf.lfWeight = 3;
602     lf.lfWidth = 10;
603
604     zfont = (HFONT) SelectObject(hdc, CreateFontIndirectA(&lf));
605  
606     /* Test without hdc to get E_INVALIDARG */
607     hr = ScriptStringAnalyse( NULL, pString, cString, cGlyphs, iCharset, dwFlags,
608                              iReqWidth, &psControl, &psState, piDx, &pTabdef,
609                              &pbInClass, &pssa);
610     ok(hr == E_PENDING, "ScriptStringAnalyse Stub should return E_PENDING not %08x\n", (unsigned int) hr);
611
612     /* test with hdc, this should be a valid test  */
613     hr = ScriptStringAnalyse( hdc, pString, cString, cGlyphs, iCharset, dwFlags,
614                               iReqWidth, &psControl, &psState, piDx, &pTabdef,
615                               &pbInClass, &pssa);
616     ok(hr == E_NOTIMPL, "ScriptStringAnalyse Stub should return E_NOTIMPL not %08x\n", (unsigned int) hr);
617 /*    Commented code it pending new code in ScriptStringAnalysis */
618 /*    ok(hr == S_OK, "ScriptStringAnalyse Stub should return S_OK not %08x\n", (unsigned int) hr);*/
619 /*    ok(pssa != NULL, "ScriptStringAnalyse pssa should not be NULL\n");*/
620     if  (hr == 0)
621     {
622         hr = ScriptStringOut(pssa, iX, iY, uOptions, &prc, iMinSel, iMaxSel,fDisabled);
623         ok(hr == E_NOTIMPL, "ScriptStringOut Stub should return E_NOTIMPL not %08x\n", (unsigned int) hr);
624         hr = ScriptStringFree(&pssa);
625         ok(hr == S_OK, "ScriptStringFree Stub should return S_OK not %08x\n", (unsigned int) hr);
626     }
627 }
628
629 START_TEST(usp10)
630 {
631     HWND            hwnd;
632     HDC             hdc;
633
634     unsigned short  pwOutGlyphs[256];
635
636     /* We need a valid HDC to drive a lot of Script functions which requires the following    *
637      * to set up for the tests.                                                               */
638     hwnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0,100,100,
639                            0, 0, 0, NULL);
640     assert(hwnd != 0);
641     ShowWindow(hwnd, SW_SHOW);
642     UpdateWindow(hwnd);
643
644     hdc = GetDC(hwnd);                                      /* We now have a hdc             */
645     ok( hdc != NULL, "HDC failed to be created %p\n", hdc);
646
647     test_ScriptItemIzeShapePlace(hdc,pwOutGlyphs);
648     test_ScriptGetCMap(hdc, pwOutGlyphs);
649
650     ReleaseDC(hwnd, hdc);
651     DestroyWindow(hwnd);
652
653     test_ScriptGetFontProperties();
654     test_ScriptTextOut();
655     test_ScriptXtoX();
656     test_ScriptString();
657 }