dinput8: DirectInput8Create rewrite.
[wine] / dlls / usp10 / usp10.c
1 /*
2  * Implementation of Uniscribe Script Processor (usp10.dll)
3  *
4  * Copyright 2005 Steven Edwards for CodeWeavers
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 <stdarg.h>
26
27 #include "windef.h"
28 #include "winbase.h"
29 #include "wingdi.h"
30 #include "winuser.h"
31 #include "usp10.h"
32
33 #include "wine/debug.h"
34
35 /**
36  * some documentation here:
37  *   http://www.microsoft.com/typography/developers/uniscribe/uniscribe.htm
38  */
39
40 WINE_DEFAULT_DEBUG_CHANNEL(uniscribe);
41
42 #define MAX_SCRIPTS  8
43
44 /*  Set up a default for ScriptGetProperties    */
45 static const SCRIPT_PROPERTIES Default_Script_0 = {0, 0, 0, 0, 0, 0, 0, 0, 
46                                             0, 0, 0, 0, 0, 0, 0};
47 static const SCRIPT_PROPERTIES Default_Script_1 = {0, 0, 0, 0, 0, 0, 0, 0, 
48                                             0, 0, 0, 0, 0, 0, 0};
49 static const SCRIPT_PROPERTIES Default_Script_2 = {0, 0, 0, 0, 0, 0, 0, 0, 
50                                             0, 0, 0, 0, 0, 0, 0};
51 static const SCRIPT_PROPERTIES Default_Script_3 = {9, 0, 0, 0, 0, 0, 0, 0, 
52                                             0, 0, 0, 0, 0, 0, 0};
53 static const SCRIPT_PROPERTIES Default_Script_4 = {9, 1, 0, 0, 0, 0, 0, 0, 
54                                             0, 0, 0, 0, 0, 0, 0};
55 static const SCRIPT_PROPERTIES Default_Script_5 = {9, 0, 0, 0, 0, 0, 0, 0, 
56                                             0, 0, 0, 0, 1, 0, 0};
57 static const SCRIPT_PROPERTIES Default_Script_6 = {9, 1, 0, 0, 0, 0, 0, 0, 
58                                             0, 0, 0, 0, 1, 0, 0};
59 static const SCRIPT_PROPERTIES Default_Script_7 = {8, 0, 0, 0, 0, 161, 0, 0, 
60                                             0, 0, 0, 0, 0, 0, 0};
61 static const SCRIPT_PROPERTIES *Global_Script[MAX_SCRIPTS] =
62                                       {&Default_Script_0,
63                                        &Default_Script_1,
64                                        &Default_Script_2,
65                                        &Default_Script_3,
66                                        &Default_Script_4,
67                                        &Default_Script_5,
68                                        &Default_Script_6,
69                                        &Default_Script_7};
70
71 typedef struct scriptcache {
72        HDC hdc;
73 } Scriptcache;
74
75 /***********************************************************************
76  *      DllMain
77  *
78  */
79 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
80 {
81     switch(fdwReason) {
82         case DLL_PROCESS_ATTACH:
83             DisableThreadLibraryCalls(hInstDLL);
84             break;
85         case DLL_PROCESS_DETACH:
86             break;
87     }
88     return TRUE;
89 }
90
91 /***********************************************************************
92  *      ScriptFreeCache (USP10.@)
93  *
94  */
95 HRESULT WINAPI ScriptFreeCache(SCRIPT_CACHE *psc)
96 {
97     TRACE("%p\n", psc);
98
99     if (psc) {
100        HeapFree ( GetProcessHeap(), 0, *psc);
101        *psc = NULL;
102     }
103     return 0;
104 }
105
106 /***********************************************************************
107  *      ScriptGetProperties (USP10.@)
108  *
109  */
110 HRESULT WINAPI ScriptGetProperties(const SCRIPT_PROPERTIES ***ppSp, int *piNumScripts)
111 {
112     TRACE("%p,%p\n", ppSp, piNumScripts);
113
114     if (!ppSp && !piNumScripts) return E_INVALIDARG;
115
116     /* Set up a sensible default and intialise pointers  */
117     if (piNumScripts) *piNumScripts = MAX_SCRIPTS;
118     if (ppSp) *ppSp = Global_Script;
119     TRACE("ppSp:%p, *ppSp:%p, **ppSp:%p, %d\n",
120           ppSp, ppSp ? *ppSp : NULL, (ppSp && *ppSp) ? **ppSp : NULL,
121           piNumScripts ? *piNumScripts : -1);
122     return 0;
123 }
124
125 /***********************************************************************
126  *      ScriptGetFontProperties (USP10.@)
127  *
128  */
129 HRESULT WINAPI ScriptGetFontProperties(HDC hdc, SCRIPT_CACHE *psc, SCRIPT_FONTPROPERTIES *sfp)
130 {
131     HDC phdc;
132     Scriptcache *pScriptcache;
133     TEXTMETRICW ptm;
134
135     TRACE("%p,%p,%p\n", hdc, psc, sfp);
136
137     if (!psc || !sfp)
138         return E_INVALIDARG;
139     if  (!hdc && !*psc) {
140         TRACE("No Script_Cache (psc) and no hdc. Ask for one. Hdc=%p, psc=%p\n", hdc, *psc);
141         return E_PENDING;
142     }   else 
143         if  (hdc && !*psc) {
144             pScriptcache = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(Scriptcache) );
145             pScriptcache->hdc = (HDC) hdc;
146             phdc = hdc;
147             *psc = (Scriptcache *) pScriptcache;
148         }   else
149             if  (*psc) {
150                 pScriptcache = (Scriptcache *) *psc;
151                 phdc = pScriptcache->hdc;
152             }
153                 
154     if (sfp->cBytes != sizeof(SCRIPT_FONTPROPERTIES))
155         return E_INVALIDARG;
156
157     /* return something sensible? */
158     sfp->wgBlank       = 0;
159     if  (GetTextMetricsW(phdc, &ptm)) 
160         sfp->wgDefault = ptm.tmDefaultChar;
161     else
162         sfp->wgDefault = 0;
163     sfp->wgInvalid     = 0;
164     sfp->wgKashida     = 0xffff;
165     sfp->iKashidaWidth = 0;
166     return 0;
167 }
168
169 /***********************************************************************
170  *      ScriptRecordDigitSubstitution (USP10.@)
171  *
172  */
173 HRESULT WINAPI ScriptRecordDigitSubstitution(LCID Locale,SCRIPT_DIGITSUBSTITUTE *psds)
174 {
175     FIXME("%ld,%p\n",Locale,psds);
176     return E_NOTIMPL;
177 }
178
179 /***********************************************************************
180  *      ScriptApplyDigitSubstitution (USP10.@)
181  *
182  */
183 HRESULT WINAPI ScriptApplyDigitSubstitution(const SCRIPT_DIGITSUBSTITUTE* psds, 
184                                             SCRIPT_CONTROL* psc, SCRIPT_STATE* pss)
185 {
186     FIXME("%p,%p,%p\n",psds,psc,pss);
187     return E_NOTIMPL;
188 }
189
190 /***********************************************************************
191  *      ScriptItemize (USP10.@)
192  *
193  */
194 HRESULT WINAPI ScriptItemize(const WCHAR *pwcInChars, int cInChars, int cMaxItems, 
195                              const SCRIPT_CONTROL *psControl, const SCRIPT_STATE *psState, 
196                              SCRIPT_ITEM *pItems, int *pcItems)
197 {
198     /* This implementation currently treats the entire string represented in 
199      * pwcInChars as a single entity.  Hence pcItems will be set to 1.          */
200
201     FIXME("%s,%d,%d,%p,%p,%p,%p: semi-stub\n", debugstr_wn(pwcInChars, cInChars), cInChars, cMaxItems, 
202           psControl, psState, pItems, pcItems);
203
204     if (!pwcInChars || !cInChars || !pItems || cMaxItems < 2)
205         return E_INVALIDARG;
206
207     /*  Set a sensible default                              */
208     /*  Set SCRIPT_ITEM                                     */
209     pItems[0].iCharPos = 0;
210     /*  Set the SCRIPT_ANALYSIS                             */
211     pItems[0].a.eScript = SCRIPT_UNDEFINED;
212     pItems[0].a.fRTL = 0;
213     pItems[0].a.fLayoutRTL = 0;
214     pItems[0].a.fLinkBefore = 0;
215     pItems[0].a.fLinkAfter = 0;
216     pItems[0].a.fLogicalOrder = 0;
217     pItems[0].a.fNoGlyphIndex = 0;
218     /*  set the SCRIPT_STATE                                */
219     pItems[0].a.s.uBidiLevel = 0;
220     pItems[0].a.s.fOverrideDirection = 0;
221     pItems[0].a.s.fInhibitSymSwap = FALSE;
222     pItems[0].a.s.fCharShape = 0;
223     pItems[0].a.s.fDigitSubstitute = 0;
224     pItems[0].a.s.fInhibitLigate = 0;
225     pItems[0].a.s.fDisplayZWG = 0;
226     pItems[0].a.s.fArabicNumContext = 0;
227     pItems[0].a.s.fGcpClusters = 0;
228     pItems[0].a.s.fReserved = 0;
229     pItems[0].a.s.fEngineReserved = 0;
230
231     /* While not strickly necessary according to the spec, make sure the n+1
232      * item is set up to prevent random behaviour if the caller eroneously
233      * checks the n+1 structure                                              */
234     pItems[1].a.eScript = 0;
235     pItems[1].a.fRTL = 0;
236     pItems[1].a.fLayoutRTL = 0;
237     pItems[1].a.fLinkBefore = 0;
238     pItems[1].a.fLinkAfter = 0;
239     pItems[1].a.fLogicalOrder = 0;
240     pItems[1].a.fNoGlyphIndex = 0;
241     /*  set the SCRIPT_STATE                                */
242     pItems[1].a.s.uBidiLevel = 0;
243     pItems[1].a.s.fOverrideDirection = 0;
244     pItems[1].a.s.fInhibitSymSwap = FALSE;
245     pItems[1].a.s.fCharShape = 0;
246     pItems[1].a.s.fDigitSubstitute = 0;
247     pItems[1].a.s.fInhibitLigate = 0;
248     pItems[1].a.s.fDisplayZWG = 0;
249     pItems[1].a.s.fArabicNumContext = 0;
250     pItems[1].a.s.fGcpClusters = 0;
251     pItems[1].a.s.fReserved = 0;
252     pItems[1].a.s.fEngineReserved = 0;
253
254     /*  Set one SCRIPT_STATE item being returned  */
255     *pcItems = 1;
256
257     /*  Set SCRIPT_ITEM                                     */
258     pItems[1].iCharPos = cInChars - pItems[0].iCharPos ; /* the last + 1 item
259                                              contains the ptr to the lastchar */
260     TRACE("%s,%d,%d,%p,%p,%p,%p,%d\n", debugstr_wn(pwcInChars, cInChars), cInChars, cMaxItems, 
261           psControl, psState, pItems, pcItems, *pcItems);
262     TRACE("Start Pos in string: %d, Stop Pos %d\n", pItems[0].iCharPos, pItems[1].iCharPos);
263     return 0;
264 }
265
266 /***********************************************************************
267  *      ScriptStringAnalyse (USP10.@)
268  *
269  */
270 HRESULT WINAPI ScriptStringAnalyse(HDC hdc, 
271                                    const void *pString, 
272                                    int cString, 
273                                    int cGlyphs,
274                                    int iCharset,
275                                    DWORD dwFlags,
276                                    int iReqWidth,
277                                    SCRIPT_CONTROL *psControl,
278                                    SCRIPT_STATE *psState,
279                                    const int *piDx,
280                                    SCRIPT_TABDEF *pTabdef,
281                                    const BYTE *pbInClass,
282                                    SCRIPT_STRING_ANALYSIS *pssa)
283 {
284   FIXME("(%p,%p,%d,%d,%d,0x%lx,%d,%p,%p,%p,%p,%p,%p): stub\n",
285         hdc, pString, cString, cGlyphs, iCharset, dwFlags,
286         iReqWidth, psControl, psState, piDx, pTabdef, pbInClass, pssa);
287   if (1 > cString || NULL == pString) {
288     return E_INVALIDARG;
289   }
290   if ((dwFlags & SSA_GLYPHS) && NULL == hdc) {
291     return E_PENDING;
292   }
293
294   return E_NOTIMPL;
295 }
296
297 /***********************************************************************
298  *      ScriptStringOut (USP10.@)
299  *
300  */
301 HRESULT WINAPI ScriptStringOut(SCRIPT_STRING_ANALYSIS ssa, 
302                                int iX, 
303                                int iY, 
304                                UINT uOptions, 
305                                const RECT *prc, 
306                                int iMinSel, 
307                                int iMaxSel, 
308                                BOOL fDisabled)
309 {
310     FIXME("(%p,%d,%d,0x%1x,%p,%d,%d,%d): stub\n",
311          ssa, iX, iY, uOptions, prc, iMinSel, iMaxSel, fDisabled);
312     if  (!ssa) {
313         return E_INVALIDARG;
314     }
315
316     return E_NOTIMPL;
317 }
318
319 /***********************************************************************
320  *      ScriptStringCPtoX (USP10.@)
321  *
322  */
323 HRESULT WINAPI ScriptStringCPtoX(SCRIPT_STRING_ANALYSIS ssa, int icp, BOOL fTrailing, int* pX)
324 {
325     FIXME("(%p), %d, %d, (%p): stub\n", ssa, icp, fTrailing, pX);
326     *pX = 0;                             /* Set a reasonable value */
327     return S_OK;
328 }
329
330 /***********************************************************************
331  *      ScriptStringXtoCP (USP10.@)
332  *
333  */
334 HRESULT WINAPI ScriptStringXtoCP(SCRIPT_STRING_ANALYSIS ssa, int iX, int* piCh, int* piTrailing) 
335 {
336     FIXME("(%p), %d, (%p), (%p): stub\n", ssa, iX, piCh, piTrailing);
337     *piCh = 0;                          /* Set a reasonable value */
338     *piTrailing = 0;
339     return S_OK;
340 }
341
342 /***********************************************************************
343  *      ScriptStringFree (USP10.@)
344  *
345  */
346 HRESULT WINAPI ScriptStringFree(SCRIPT_STRING_ANALYSIS *pssa) {
347     FIXME("(%p): stub\n",pssa);
348     return S_OK;
349 }
350
351 /***********************************************************************
352  *      ScriptCPtoX (USP10.@)
353  *
354  */
355 HRESULT WINAPI ScriptCPtoX(int iCP,
356                            BOOL fTrailing,
357                            int cChars,
358                            int cGlyphs,
359                            const WORD *pwLogClust,
360                            const SCRIPT_VISATTR *psva,
361                            const int *piAdvance,
362                            const SCRIPT_ANALYSIS *psa,
363                            int *piX)
364 {
365     FIXME("(%d,%d,%d,%d,%p,%p,%p,%p,%p): stub\n",
366           iCP, fTrailing, cChars, cGlyphs, pwLogClust, psva, piAdvance,
367           psa, piX);
368
369     *piX = 1;                    /* Return something in range */
370     return S_OK;
371 }
372
373 /***********************************************************************
374  *      ScriptXtoCP (USP10.@)
375  *
376  */
377 HRESULT WINAPI ScriptXtoCP(int iX,
378                            int cChars,
379                            int cGlyphs,
380                            const WORD *pwLogClust,
381                            const SCRIPT_VISATTR *psva,
382                            const int *piAdvance,
383                            const SCRIPT_ANALYSIS *psa,
384                            int *piCP,
385                            int *piTrailing)
386 {
387     FIXME("(%d,%d,%d,%p,%p,%p,%p,%p,%p): stub\n",
388           iX, cChars, cGlyphs, pwLogClust, psva, piAdvance,
389           psa, piCP, piTrailing);
390
391     *piCP = 1;                   /* Return something in range */
392     *piTrailing = 0;
393     return S_OK;
394 }
395
396 /***********************************************************************
397  *      ScriptBreak (USP10.@)
398  *
399  */
400 HRESULT WINAPI ScriptBreak(const WCHAR *pwcChars, int cChars,  const SCRIPT_ANALYSIS *psa,
401                     SCRIPT_LOGATTR *psla)
402 {
403     FIXME("(%p,%d,%p,%p): stub\n",
404           pwcChars, cChars, psa, psla);
405
406     return S_OK;
407 }
408
409 /***********************************************************************
410  *      ScriptIsComplex (USP10.@)
411  *
412  */
413 HRESULT WINAPI ScriptIsComplex(const WCHAR* pwcInChars, int cInChars, DWORD dwFlags) {
414   FIXME("(%s,%d,0x%lx): stub\n",  debugstr_wn(pwcInChars, cInChars), cInChars, dwFlags);
415    return E_NOTIMPL;
416 }
417
418 /***********************************************************************
419  *      ScriptShape (USP10.@)
420  *
421  */
422 HRESULT WINAPI ScriptShape(HDC hdc, SCRIPT_CACHE *psc, const WCHAR *pwcChars, 
423                            int cChars, int cMaxGlyphs,
424                            SCRIPT_ANALYSIS *psa, WORD *pwOutGlyphs, WORD *pwLogClust, 
425                            SCRIPT_VISATTR *psva, int *pcGlyphs)
426 {
427     /*  Note SCRIPT_CACHE (*psc) appears to be a good place to save info that needs to be 
428      *  passed between functions.                                                         */
429
430     HDC phdc;
431     int cnt;
432     DWORD hr;
433     Scriptcache *pScriptcache;
434     *pcGlyphs = cChars;
435     FIXME("(%p, %p, %p, %d, %d, %p): semi-stub\n",  hdc, psc, pwcChars,
436                                        cChars, cMaxGlyphs, psa);
437     if (psa) TRACE("psa values: %d, %d, %d, %d, %d, %d, %d\n", psa->eScript, psa->fRTL, psa->fLayoutRTL,
438                                          psa->fLinkBefore, psa->fLinkAfter,
439                                          psa->fLogicalOrder, psa->fNoGlyphIndex);
440
441     if  (cChars > cMaxGlyphs) return E_OUTOFMEMORY;
442
443     if  (!hdc && !*psc) {
444         TRACE("No Script_Cache (psc) and no hdc. Ask for one. Hdc=%p, psc=%p\n", hdc, *psc);
445         return E_PENDING;
446     }   else 
447         if  (hdc && !*psc) {
448             pScriptcache = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(Scriptcache) );
449             pScriptcache->hdc = (HDC) hdc;
450             phdc = hdc;
451             *psc = (Scriptcache *) pScriptcache;
452        }   else
453             if  (*psc) {
454                 pScriptcache = (Scriptcache *) *psc;
455                 phdc = pScriptcache->hdc;
456             }
457                 
458     TRACE("Before: ");
459     for (cnt = 0; cnt < cChars; cnt++)
460          TRACE("%4x",pwcChars[cnt]);
461     TRACE("\n");
462
463     if  (!psa->fNoGlyphIndex) {                                         /* Glyph translate */
464         hr = GetGlyphIndicesW(phdc, pwcChars, cChars, pwOutGlyphs, 0);
465         TRACE("After:  ");
466         for (cnt = 0; cnt < cChars; cnt++) {
467              TRACE("%04x",pwOutGlyphs[cnt]);
468         }
469         TRACE("\n");
470     }
471     else {
472         TRACE("After:  ");
473         for (cnt = 0; cnt < cChars; cnt++) {                           /* no translate so set up */
474              pwOutGlyphs[cnt] = pwcChars[cnt];                         /* copy in to out and     */
475              TRACE("%04x",pwOutGlyphs[cnt]);
476         }
477        TRACE("\n");
478     }
479
480     /*  Set up a valid SCRIPT_VISATTR and LogClust for each char in this run */     
481     for (cnt = 0;  cnt < cChars; cnt++) {
482          psva[cnt].uJustification = 2;
483          psva[cnt].fClusterStart = 1;
484          psva[cnt].fDiacritic = 0;
485          psva[cnt].fZeroWidth = 0;
486          pwLogClust[cnt] = cnt;
487     }
488     return 0; 
489 }
490
491 /***********************************************************************
492  *      ScriptPlace (USP10.@)
493  *
494  */
495 HRESULT WINAPI ScriptPlace(HDC hdc, SCRIPT_CACHE *psc, const WORD *pwGlyphs, 
496                            int cGlyphs, const SCRIPT_VISATTR *psva,
497                            SCRIPT_ANALYSIS *psa, int *piAdvance, GOFFSET *pGoffset, ABC *pABC )
498 {
499     HDC phdc;
500     int wcnt;
501     LPABC lpABC;
502     Scriptcache *pScriptcache;
503     FIXME("(%p, %p, %p, %s, %d, %p, %p, %p): semi-stub\n",  hdc, psc, pwGlyphs,
504                                                 debugstr_wn(pwGlyphs, cGlyphs), 
505                                                 cGlyphs, psva, psa, 
506                                                 piAdvance);
507
508     /*  We need a valid hdc to do any of the font calls.  The spec says that hdc is optional and 
509      *  psc will be used first.  If psc and hdc are not specified E_PENDING is returned to get 
510      *  the caller to return the hdc.  For convience, the hdc is cached in SCRIPT_CACHE.    */
511
512     if  (!hdc && !*psc) {
513         TRACE("No Script_Cache (psc) and no hdc. Ask for one. Hdc=%p, psc=%p\n", hdc, *psc);
514         return E_PENDING;
515     }   else 
516         if  (hdc && !*psc) {
517             pScriptcache = HeapAlloc( GetProcessHeap(), 0, sizeof(Scriptcache) );
518             pScriptcache->hdc = hdc;
519             phdc = hdc;
520             *psc = pScriptcache;
521         }   else
522             if  (*psc) {
523                 pScriptcache = *psc;
524                 phdc = pScriptcache->hdc;
525             }
526
527     /*   Here we need to calculate the width of the run unit.  At this point the input string
528      *   has been converted to glyphs and we till need to translate back to the original chars
529      *   to get the correct ABC widths.   */
530
531      lpABC = HeapAlloc(GetProcessHeap(), 0 , sizeof(ABC)*cGlyphs);
532      pABC->abcA = 0; 
533      pABC->abcB = 0; 
534      pABC->abcC = 0; 
535      if  (!GetCharABCWidthsI(phdc, 0, cGlyphs, (WORD *) pwGlyphs, lpABC )) 
536      {
537          WARN("Could not get ABC values\n");
538          for (wcnt = 0; wcnt < cGlyphs; wcnt++) {
539              piAdvance[wcnt] = 0;
540              pGoffset[wcnt].du = 0;
541              pGoffset[wcnt].dv = 0;
542          }
543      }
544      else
545      {
546          for (wcnt = 0; wcnt < cGlyphs ; wcnt++) {          /* add up the char lengths  */
547              TRACE("     Glyph=%04x,  abcA=%d,  abcB=%d,  abcC=%d  wcnt=%d\n",
548                                   pwGlyphs[wcnt],  
549                                   lpABC[wcnt].abcA,
550                                   lpABC[wcnt].abcB,
551                                   lpABC[wcnt].abcC, wcnt);
552              pABC->abcA += lpABC[wcnt].abcA;
553              pABC->abcB += lpABC[wcnt].abcB;
554              pABC->abcC += lpABC[wcnt].abcC;
555              piAdvance[wcnt] = lpABC[wcnt].abcA + lpABC[wcnt].abcB + lpABC[wcnt].abcC;
556              pGoffset[wcnt].du = 0;
557              pGoffset[wcnt].dv = 0;
558          }
559      }
560      TRACE("Total for run:   abcA=%d,  abcB=%d,  abcC=%d\n", pABC->abcA, pABC->abcB, pABC->abcC);
561
562      HeapFree(GetProcessHeap(), 0, lpABC );
563
564      return 0;
565 }
566
567 /***********************************************************************
568  *      ScriptGetCMap (USP10.@)
569  *
570  */
571 HRESULT WINAPI ScriptGetCMap(HDC hdc, SCRIPT_CACHE *psc, const WCHAR *pwcInChars,
572                               int cChars, DWORD dwFlags, WORD *pwOutGlyphs)
573 {
574     HDC phdc;
575     int cnt;
576     DWORD hr;
577     Scriptcache *pScriptcache;
578     FIXME("(%p,%p,%s,%d,0x%lx,%p): semi-stub\n", hdc, psc, debugstr_wn(pwcInChars,cChars), 
579                                                  cChars, dwFlags, pwOutGlyphs);
580
581     if  (!psc)
582         return E_INVALIDARG;
583
584     if  (!hdc && !*psc) {
585         TRACE("No Script_Cache (psc) and no hdc. Ask for one. Hdc=%p, psc=%p\n", hdc, *psc);
586         return E_PENDING;
587     }   else 
588         if  (hdc && !*psc) {
589             pScriptcache = HeapAlloc( GetProcessHeap(), 0, sizeof(Scriptcache) );
590             pScriptcache->hdc = hdc;
591             phdc = hdc;
592             *psc = pScriptcache;
593         }   else
594             if  (*psc) {
595                 pScriptcache = *psc;
596                 phdc = pScriptcache->hdc;
597             }
598
599     TRACE("Before: ");
600     for (cnt = 0; cnt < cChars; cnt++)
601          TRACE("%4x",pwcInChars[cnt]);
602     TRACE("\n");
603
604     hr = GetGlyphIndicesW(phdc, pwcInChars, cChars, pwOutGlyphs, 0);
605     TRACE("After:  ");
606     for (cnt = 0; cnt < cChars; cnt++) {
607          TRACE("%04x",pwOutGlyphs[cnt]);
608     }
609     TRACE("\n");
610
611     return 0; 
612 }
613
614 /***********************************************************************
615  *      ScriptTextOut (USP10.@)
616  *
617  */
618 HRESULT WINAPI ScriptTextOut(const HDC hdc, SCRIPT_CACHE *psc, int x, int y, UINT fuOptions, 
619                              const RECT *lprc, const SCRIPT_ANALYSIS *psa, const WCHAR *pwcReserved, 
620                              int iReserved, const WORD *pwGlyphs, int cGlyphs, const int *piAdvance, 
621                              const int *piJustify, const GOFFSET *pGoffset)
622 {
623     HDC phdc;
624     DWORD hr;
625     Scriptcache *pScriptcache;
626     TRACE     ("(%p, %p, %d, %d, %04x, %p, %p, %p, %d, %p, %d, %p, %p, %p): stub\n",
627          hdc, psc, x, y, fuOptions, lprc, psa, pwcReserved, iReserved, pwGlyphs, cGlyphs,
628          piAdvance, piJustify, pGoffset);
629
630     if  (!hdc || !psc || !piAdvance || !psa || !pwGlyphs)         /* hdc is mandatory                 */
631         return E_INVALIDARG;
632         
633     if  (!*psc) {
634         pScriptcache = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(Scriptcache) );
635         pScriptcache->hdc = hdc;
636         phdc = hdc;
637         *psc = pScriptcache;
638     } else {
639         pScriptcache = *psc;
640         phdc = pScriptcache->hdc;
641     }
642
643     fuOptions &= ETO_CLIPPED + ETO_OPAQUE;
644     if  (!psa->fNoGlyphIndex)                                     /* Have Glyphs?                      */
645         fuOptions |= ETO_GLYPH_INDEX;                             /* Say don't do tranlastion to glyph */
646
647     hr = ExtTextOutW(phdc, x, y, fuOptions, lprc, pwGlyphs, cGlyphs, NULL);
648
649     if  (hr) return S_OK;
650     else {
651         FIXME("ExtTextOut returned:=%ld\n", hr);
652         return hr;
653     }
654 }
655
656 /***********************************************************************
657  *      ScriptCacheGetHeight (USP10.@)
658  *
659  * Retrieve the height of the font in the cache.
660  *
661  * PARAMS
662  *  hdc    [I]    Device context.
663  *  psc    [I/O]  Opaque pointer to a script cache.
664  *  height [O]    Receives font height.
665  *
666  * RETURNS
667  *  Success: S_OK
668  *  Failure: Non-zero HRESULT value.
669  */
670 HRESULT WINAPI ScriptCacheGetHeight(HDC hdc, SCRIPT_CACHE *psc, long *height)
671 {
672     HDC phdc;
673     Scriptcache *pScriptcache;
674     TEXTMETRICW metric;
675
676     TRACE("(%p, %p, %p)\n", hdc, psc, height);
677
678     if  (!psc || !height)
679         return E_INVALIDARG;
680
681     if (!hdc) return E_PENDING;
682
683     if  (!*psc) {
684         pScriptcache = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(Scriptcache));
685         pScriptcache->hdc = hdc;
686         phdc = hdc;
687         *psc = pScriptcache;
688     } else {
689         pScriptcache = *psc;
690         phdc = pScriptcache->hdc;
691     }
692
693     /* FIXME: get this from the cache */
694     if (!GetTextMetricsW(phdc, &metric))
695         return E_INVALIDARG;
696
697     *height = metric.tmHeight;
698     return S_OK;
699 }