Use the Unicode string functions from wine/unicode.h instead of the
[wine] / dlls / oleaut32 / olefont.c
1 /*
2  * OLE Font encapsulation implementation
3  *
4  * This file contains an implementation of the IFont
5  * interface and the OleCreateFontIndirect API call.
6  *
7  * Copyright 1999 Francis Beaudet
8  */
9 #include <assert.h>
10 #include <string.h>
11 #include "winerror.h"
12 #include "oleauto.h"    /* for SysAllocString(....) */
13 #include "wine/obj_olefont.h"
14 #include "wine/obj_storage.h"
15 #include "olectl.h"
16 #include "debugtools.h"
17 #include "heap.h"
18
19 DEFAULT_DEBUG_CHANNEL(ole)
20
21 /***********************************************************************
22  * Declaration of constants used when serializing the font object.
23  */
24 #define FONTPERSIST_ITALIC        0x02
25 #define FONTPERSIST_UNDERLINE     0x04
26 #define FONTPERSIST_STRIKETHROUGH 0x08
27
28 /***********************************************************************
29  * Declaration of the implementation class for the IFont interface
30  */
31 typedef struct OLEFontImpl OLEFontImpl;
32
33 struct OLEFontImpl
34 {
35   /*
36    * This class supports many interfaces. IUnknown, IFont, 
37    * IDispatch, IDispFont and IPersistStream. The first two are
38    * supported by the first vtablem the next two are supported by 
39    * the second table and the last one has it's own.
40    */
41   ICOM_VTABLE(IFont)*     lpvtbl1;
42   ICOM_VTABLE(IDispatch)* lpvtbl2;
43   ICOM_VTABLE(IPersistStream)*            lpvtbl3;
44
45   /*
46    * Reference count for that instance of the class.
47    */
48   ULONG ref;
49
50   /*
51    * This structure contains the description of the class.
52    */
53   FONTDESC description;
54
55   /*
56    * Contain the font associated with this object.
57    */
58   HFONT gdiFont;
59
60   /*
61    * Font lock count.
62    */
63   DWORD fontLock;
64
65   /*
66    * Size ratio
67    */
68   long cyLogical;
69   long cyHimetric;
70 };
71
72 /*
73  * Here, I define utility macros to help with the casting of the 
74  * "this" parameter.
75  * There is a version to accomodate all of the VTables implemented
76  * by this object.
77  */
78 #define _ICOM_THIS(class,name) class* this = (class*)name;
79 #define _ICOM_THIS_From_IDispatch(class, name) class* this = (class*)(((char*)name)-sizeof(void*)); 
80 #define _ICOM_THIS_From_IPersistStream(class, name) class* this = (class*)(((char*)name)-2*sizeof(void*)); 
81
82 /***********************************************************************
83  * Prototypes for the implementation functions for the IFont
84  * interface
85  */
86 static OLEFontImpl* OLEFontImpl_Construct(LPFONTDESC fontDesc);
87 static void         OLEFontImpl_Destroy(OLEFontImpl* fontDesc);
88 static HRESULT      WINAPI OLEFontImpl_QueryInterface(IFont* iface, REFIID riid, VOID** ppvoid);
89 static ULONG        WINAPI OLEFontImpl_AddRef(IFont* iface);
90 static ULONG        WINAPI OLEFontImpl_Release(IFont* iface);
91 static HRESULT      WINAPI OLEFontImpl_get_Name(IFont* iface, BSTR* pname);
92 static HRESULT      WINAPI OLEFontImpl_put_Name(IFont* iface, BSTR name);
93 static HRESULT      WINAPI OLEFontImpl_get_Size(IFont* iface, CY* psize);
94 static HRESULT      WINAPI OLEFontImpl_put_Size(IFont* iface, CY size);
95 static HRESULT      WINAPI OLEFontImpl_get_Bold(IFont* iface, BOOL* pbold);
96 static HRESULT      WINAPI OLEFontImpl_put_Bold(IFont* iface, BOOL bold);
97 static HRESULT      WINAPI OLEFontImpl_get_Italic(IFont* iface, BOOL* pitalic);
98 static HRESULT      WINAPI OLEFontImpl_put_Italic(IFont* iface, BOOL italic);
99 static HRESULT      WINAPI OLEFontImpl_get_Underline(IFont* iface, BOOL* punderline);
100 static HRESULT      WINAPI OLEFontImpl_put_Underline(IFont* iface, BOOL underline);
101 static HRESULT      WINAPI OLEFontImpl_get_Strikethrough(IFont* iface, BOOL* pstrikethrough);
102 static HRESULT      WINAPI OLEFontImpl_put_Strikethrough(IFont* iface, BOOL strikethrough);
103 static HRESULT      WINAPI OLEFontImpl_get_Weight(IFont* iface, short* pweight);
104 static HRESULT      WINAPI OLEFontImpl_put_Weight(IFont* iface, short weight);
105 static HRESULT      WINAPI OLEFontImpl_get_Charset(IFont* iface, short* pcharset);
106 static HRESULT      WINAPI OLEFontImpl_put_Charset(IFont* iface, short charset);
107 static HRESULT      WINAPI OLEFontImpl_get_hFont(IFont* iface, HFONT* phfont);
108 static HRESULT      WINAPI OLEFontImpl_Clone(IFont* iface, IFont** ppfont);
109 static HRESULT      WINAPI OLEFontImpl_IsEqual(IFont* iface, IFont* pFontOther);
110 static HRESULT      WINAPI OLEFontImpl_SetRatio(IFont* iface, long cyLogical, long cyHimetric);
111 static HRESULT      WINAPI OLEFontImpl_QueryTextMetrics(IFont* iface, TEXTMETRICOLE* ptm);
112 static HRESULT      WINAPI OLEFontImpl_AddRefHfont(IFont* iface, HFONT hfont);
113 static HRESULT      WINAPI OLEFontImpl_ReleaseHfont(IFont* iface, HFONT hfont);
114 static HRESULT      WINAPI OLEFontImpl_SetHdc(IFont* iface, HDC hdc);
115
116 /***********************************************************************
117  * Prototypes for the implementation functions for the IDispatch
118  * interface
119  */
120 static HRESULT WINAPI OLEFontImpl_IDispatch_QueryInterface(IDispatch* iface, 
121                                                     REFIID     riid, 
122                                                     VOID**     ppvoid);
123 static ULONG   WINAPI OLEFontImpl_IDispatch_AddRef(IDispatch* iface);
124 static ULONG   WINAPI OLEFontImpl_IDispatch_Release(IDispatch* iface);
125 static HRESULT WINAPI OLEFontImpl_GetTypeInfoCount(IDispatch*    iface, 
126                                                    unsigned int* pctinfo);
127 static HRESULT WINAPI OLEFontImpl_GetTypeInfo(IDispatch*  iface, 
128                                               UINT      iTInfo,
129                                               LCID        lcid, 
130                                               ITypeInfo** ppTInfo);
131 static HRESULT WINAPI OLEFontImpl_GetIDsOfNames(IDispatch*  iface,
132                                                 REFIID      riid, 
133                                                 LPOLESTR* rgszNames, 
134                                                 UINT      cNames, 
135                                                 LCID        lcid,
136                                                 DISPID*     rgDispId);
137 static HRESULT WINAPI OLEFontImpl_Invoke(IDispatch*  iface,
138                                          DISPID      dispIdMember, 
139                                          REFIID      riid, 
140                                          LCID        lcid, 
141                                          WORD        wFlags,
142                                          DISPPARAMS* pDispParams,
143                                          VARIANT*    pVarResult, 
144                                          EXCEPINFO*  pExepInfo,
145                                          UINT*     puArgErr); 
146
147 /***********************************************************************
148  * Prototypes for the implementation functions for the IPersistStream
149  * interface
150  */
151 static HRESULT WINAPI OLEFontImpl_IPersistStream_QueryInterface(IPersistStream* iface, 
152                                                     REFIID     riid, 
153                                                     VOID**     ppvoid);
154 static ULONG   WINAPI OLEFontImpl_IPersistStream_AddRef(IPersistStream* iface);
155 static ULONG   WINAPI OLEFontImpl_IPersistStream_Release(IPersistStream* iface);
156 static HRESULT WINAPI OLEFontImpl_GetClassID(IPersistStream* iface, 
157                                              CLSID*                pClassID);
158 static HRESULT WINAPI OLEFontImpl_IsDirty(IPersistStream*  iface);
159 static HRESULT WINAPI OLEFontImpl_Load(IPersistStream*  iface,
160                                        IStream*         pLoadStream);
161 static HRESULT WINAPI OLEFontImpl_Save(IPersistStream*  iface,
162                                        IStream*         pOutStream,
163                                        BOOL             fClearDirty); 
164 static HRESULT WINAPI OLEFontImpl_GetSizeMax(IPersistStream*  iface,
165                                              ULARGE_INTEGER*  pcbSize); 
166
167 /*
168  * Virtual function tables for the OLEFontImpl class.
169  */
170 static ICOM_VTABLE(IFont) OLEFontImpl_VTable =
171 {
172   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
173   OLEFontImpl_QueryInterface,
174   OLEFontImpl_AddRef,
175   OLEFontImpl_Release,
176   OLEFontImpl_get_Name,
177   OLEFontImpl_put_Name,
178   OLEFontImpl_get_Size,
179   OLEFontImpl_put_Size,
180   OLEFontImpl_get_Bold,
181   OLEFontImpl_put_Bold,
182   OLEFontImpl_get_Italic,
183   OLEFontImpl_put_Italic,
184   OLEFontImpl_get_Underline,
185   OLEFontImpl_put_Underline,
186   OLEFontImpl_get_Strikethrough,
187   OLEFontImpl_put_Strikethrough,
188   OLEFontImpl_get_Weight,
189   OLEFontImpl_put_Weight,
190   OLEFontImpl_get_Charset,
191   OLEFontImpl_put_Charset,
192   OLEFontImpl_get_hFont,
193   OLEFontImpl_Clone, 
194   OLEFontImpl_IsEqual,
195   OLEFontImpl_SetRatio,
196   OLEFontImpl_QueryTextMetrics,
197   OLEFontImpl_AddRefHfont,
198   OLEFontImpl_ReleaseHfont,
199   OLEFontImpl_SetHdc
200 };
201
202 static ICOM_VTABLE(IDispatch) OLEFontImpl_IDispatch_VTable =
203 {
204   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
205   OLEFontImpl_IDispatch_QueryInterface,
206   OLEFontImpl_IDispatch_AddRef,
207   OLEFontImpl_IDispatch_Release,
208   OLEFontImpl_GetTypeInfoCount,
209   OLEFontImpl_GetTypeInfo,
210   OLEFontImpl_GetIDsOfNames,
211   OLEFontImpl_Invoke
212 };
213
214 static ICOM_VTABLE(IPersistStream) OLEFontImpl_IPersistStream_VTable =
215 {
216   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
217   OLEFontImpl_IPersistStream_QueryInterface,
218   OLEFontImpl_IPersistStream_AddRef,
219   OLEFontImpl_IPersistStream_Release,
220   OLEFontImpl_GetClassID,
221   OLEFontImpl_IsDirty,
222   OLEFontImpl_Load,
223   OLEFontImpl_Save,
224   OLEFontImpl_GetSizeMax
225 };
226
227 /******************************************************************************
228  *              OleCreateFontIndirect   [OLEAUT32.420]
229  */
230 HRESULT WINAPI OleCreateFontIndirect(
231   LPFONTDESC lpFontDesc,
232   REFIID     riid,
233   LPVOID*     ppvObj)
234 {
235   OLEFontImpl* newFont = 0;
236   HRESULT      hr      = S_OK;
237
238   /*
239    * Sanity check
240    */
241   if (ppvObj==0)
242     return E_POINTER;
243
244   *ppvObj = 0;
245
246   /*
247    * Try to construct a new instance of the class.
248    */
249   newFont = OLEFontImpl_Construct(lpFontDesc);
250
251   if (newFont == 0)
252     return E_OUTOFMEMORY;
253
254   /*
255    * Make sure it supports the interface required by the caller.
256    */
257   hr = IFont_QueryInterface((IFont*)newFont, riid, ppvObj);
258
259   /*
260    * Release the reference obtained in the constructor. If
261    * the QueryInterface was unsuccessful, it will free the class.
262    */
263   IFont_Release((IFont*)newFont);
264
265   return hr;
266 }
267
268
269 /***********************************************************************
270  * Implementation of the OLEFontImpl class.
271  */
272
273 /************************************************************************
274  * OLEFontImpl_Construct
275  *
276  * This method will construct a new instance of the OLEFontImpl
277  * class.
278  *
279  * The caller of this method must release the object when it's
280  * done with it.
281  */
282 static OLEFontImpl* OLEFontImpl_Construct(LPFONTDESC fontDesc)
283 {
284   OLEFontImpl* newObject = 0;
285
286   /*
287    * Allocate space for the object.
288    */
289   newObject = HeapAlloc(GetProcessHeap(), 0, sizeof(OLEFontImpl));
290
291   if (newObject==0)
292     return newObject;
293   
294   /*
295    * Initialize the virtual function table.
296    */
297   newObject->lpvtbl1 = &OLEFontImpl_VTable;
298   newObject->lpvtbl2 = &OLEFontImpl_IDispatch_VTable;
299   newObject->lpvtbl3 = &OLEFontImpl_IPersistStream_VTable;
300   
301   /*
302    * Start with one reference count. The caller of this function 
303    * must release the interface pointer when it is done.
304    */
305   newObject->ref = 1;
306
307   /*
308    * Copy the description of the font in the object.
309    */
310   assert(fontDesc->cbSizeofstruct >= sizeof(FONTDESC));
311
312   newObject->description.cbSizeofstruct = sizeof(FONTDESC);
313   newObject->description.lpstrName = HeapAlloc(GetProcessHeap(),
314                                                0, 
315                                                (lstrlenW(fontDesc->lpstrName)+1) * sizeof(WCHAR));
316   lstrcpyW(newObject->description.lpstrName, fontDesc->lpstrName);
317   newObject->description.cySize         = fontDesc->cySize;
318   newObject->description.sWeight        = fontDesc->sWeight;
319   newObject->description.sCharset       = fontDesc->sCharset;
320   newObject->description.fItalic        = fontDesc->fItalic;
321   newObject->description.fUnderline     = fontDesc->fUnderline;
322   newObject->description.fStrikethrough = fontDesc->fStrikethrough;
323
324   /*
325    * Initializing all the other members.
326    */
327   newObject->gdiFont  = 0;
328   newObject->fontLock = 0;
329   newObject->cyHimetric = 1;
330   newObject->cyLogical  = 1;
331
332   return newObject;
333 }
334
335 /************************************************************************
336  * OLEFontImpl_Construct
337  *
338  * This method is called by the Release method when the reference
339  * count goes doen to 0. it will free all resources used by
340  * this object.
341  */
342 static void OLEFontImpl_Destroy(OLEFontImpl* fontDesc)
343 {
344   if (fontDesc->description.lpstrName!=0)
345     HeapFree(GetProcessHeap(), 0, fontDesc->description.lpstrName);
346
347   if (fontDesc->gdiFont!=0)
348     DeleteObject(fontDesc->gdiFont);
349
350   HeapFree(GetProcessHeap(), 0, fontDesc);
351 }
352
353 /************************************************************************
354  * OLEFontImpl_QueryInterface (IUnknown)
355  *
356  * See Windows documentation for more details on IUnknown methods.
357  */
358 HRESULT WINAPI OLEFontImpl_QueryInterface(
359   IFont*  iface,
360   REFIID  riid,
361   void**  ppvObject)
362 {
363   _ICOM_THIS(OLEFontImpl, iface);
364
365   /*
366    * Perform a sanity check on the parameters.
367    */
368   if ( (this==0) || (ppvObject==0) )
369     return E_INVALIDARG;
370   
371   /*
372    * Initialize the return parameter.
373    */
374   *ppvObject = 0;
375   
376   /*
377    * Compare the riid with the interface IDs implemented by this object.
378    */
379   if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0) 
380   {
381     *ppvObject = (IFont*)this;
382   }
383   else if (memcmp(&IID_IFont, riid, sizeof(IID_IFont)) == 0) 
384   {
385     *ppvObject = (IFont*)this;
386   }
387   else if (memcmp(&IID_IDispatch, riid, sizeof(IID_IDispatch)) == 0) 
388   {
389     *ppvObject = (IDispatch*)&(this->lpvtbl2);
390   }
391   else if (memcmp(&IID_IFontDisp, riid, sizeof(IID_IFontDisp)) == 0) 
392   {
393     *ppvObject = (IDispatch*)&(this->lpvtbl2);
394   }
395   else if (memcmp(&IID_IPersistStream, riid, sizeof(IID_IPersistStream)) == 0) 
396   {
397     *ppvObject = (IPersistStream*)&(this->lpvtbl3);
398   }
399   
400   /*
401    * Check that we obtained an interface.
402    */
403   if ((*ppvObject)==0)
404   {
405     WARN("() : asking for un supported interface %s\n",debugstr_guid(riid));
406     return E_NOINTERFACE;
407   }
408   
409   /*
410    * Query Interface always increases the reference count by one when it is
411    * successful
412    */
413   OLEFontImpl_AddRef((IFont*)this);
414
415   return S_OK;;
416 }
417         
418 /************************************************************************
419  * OLEFontImpl_AddRef (IUnknown)
420  *
421  * See Windows documentation for more details on IUnknown methods.
422  */
423 ULONG WINAPI OLEFontImpl_AddRef( 
424   IFont* iface)
425 {
426   _ICOM_THIS(OLEFontImpl, iface);
427
428   this->ref++;
429
430   return this->ref;
431 }
432         
433 /************************************************************************
434  * OLEFontImpl_Release (IUnknown)
435  *
436  * See Windows documentation for more details on IUnknown methods.
437  */
438 ULONG WINAPI OLEFontImpl_Release( 
439       IFont* iface)
440 {
441   _ICOM_THIS(OLEFontImpl, iface);
442
443   /*
444    * Decrease the reference count on this object.
445    */
446   this->ref--;
447
448   /*
449    * If the reference count goes down to 0, perform suicide.
450    */
451   if (this->ref==0)
452   {
453     OLEFontImpl_Destroy(this);
454
455     return 0;
456   }
457   
458   return this->ref;
459 }
460         
461 /************************************************************************
462  * OLEFontImpl_get_Name (IFont)
463  *
464  * See Windows documentation for more details on IFont methods.
465  */
466 static HRESULT WINAPI OLEFontImpl_get_Name(
467   IFont*  iface, 
468   BSTR* pname)
469 {
470   _ICOM_THIS(OLEFontImpl, iface);
471
472   /*
473    * Sanity check.
474    */
475   if (pname==0)
476     return E_POINTER;
477
478   if (this->description.lpstrName!=0)
479     *pname = SysAllocString(this->description.lpstrName);
480   else
481     *pname = 0;
482
483   return S_OK;
484 }
485
486 /************************************************************************
487  * OLEFontImpl_put_Name (IFont)
488  *
489  * See Windows documentation for more details on IFont methods.
490  */
491 static HRESULT WINAPI OLEFontImpl_put_Name(
492   IFont* iface, 
493   BSTR name)
494 {
495   _ICOM_THIS(OLEFontImpl, iface);
496
497   if (this->description.lpstrName==0)
498   {
499     this->description.lpstrName = HeapAlloc(GetProcessHeap(),
500                                             0, 
501                                             (lstrlenW(name)+1) * sizeof(WCHAR));
502   }
503   else
504   {
505     this->description.lpstrName = HeapReAlloc(GetProcessHeap(),
506                                               0, 
507                                               this->description.lpstrName,
508                                               (lstrlenW(name)+1) * sizeof(WCHAR));
509   }
510
511   if (this->description.lpstrName==0)
512     return E_OUTOFMEMORY;
513
514   lstrcpyW(this->description.lpstrName, name);
515
516   return S_OK;
517 }
518
519 /************************************************************************
520  * OLEFontImpl_get_Size (IFont)
521  *
522  * See Windows documentation for more details on IFont methods.
523  */
524 static HRESULT WINAPI OLEFontImpl_get_Size(
525   IFont* iface, 
526   CY*    psize)
527 {
528   _ICOM_THIS(OLEFontImpl, iface);
529
530   /*
531    * Sanity check
532    */
533   if (psize==0)
534     return E_POINTER;
535
536   psize->s.Hi = 0;
537   psize->s.Lo = this->description.cySize.s.Lo;
538
539   return S_OK;
540 }
541
542 /************************************************************************
543  * OLEFontImpl_put_Size (IFont)
544  *
545  * See Windows documentation for more details on IFont methods.
546  */
547 static HRESULT WINAPI OLEFontImpl_put_Size(
548   IFont* iface, 
549   CY     size)
550 {
551   _ICOM_THIS(OLEFontImpl, iface);
552
553   this->description.cySize.s.Hi = 0;
554   this->description.cySize.s.Lo = this->description.cySize.s.Lo;
555
556   return S_OK;
557 }
558
559 /************************************************************************
560  * OLEFontImpl_get_Bold (IFont)
561  *
562  * See Windows documentation for more details on IFont methods.
563  */
564 static HRESULT WINAPI OLEFontImpl_get_Bold(
565   IFont*  iface, 
566   BOOL* pbold)
567 {
568   FIXME("():Stub\n");
569   return E_NOTIMPL;
570 }
571
572 /************************************************************************
573  * OLEFontImpl_put_Bold (IFont)
574  *
575  * See Windows documentation for more details on IFont methods.
576  */
577 static HRESULT WINAPI OLEFontImpl_put_Bold(
578   IFont* iface,
579   BOOL bold)
580 {
581   FIXME("():Stub\n");
582   return E_NOTIMPL;
583 }
584
585 /************************************************************************
586  * OLEFontImpl_get_Italic (IFont)
587  *
588  * See Windows documentation for more details on IFont methods.
589  */
590 static HRESULT WINAPI OLEFontImpl_get_Italic(
591   IFont*  iface, 
592   BOOL* pitalic)
593 {
594   _ICOM_THIS(OLEFontImpl, iface);
595
596   /*
597    * Sanity check
598    */
599   if (pitalic==0)
600     return E_POINTER;
601
602   *pitalic = this->description.fItalic;
603
604   return S_OK;
605 }
606
607 /************************************************************************
608  * OLEFontImpl_put_Italic (IFont)
609  *
610  * See Windows documentation for more details on IFont methods.
611  */
612 static HRESULT WINAPI OLEFontImpl_put_Italic(
613   IFont* iface, 
614   BOOL italic)
615 {
616   _ICOM_THIS(OLEFontImpl, iface);
617
618   this->description.fItalic = italic;
619
620   return S_OK;
621 }
622
623 /************************************************************************
624  * OLEFontImpl_get_Underline (IFont)
625  *
626  * See Windows documentation for more details on IFont methods.
627  */
628 static HRESULT WINAPI OLEFontImpl_get_Underline(
629   IFont*  iface, 
630   BOOL* punderline)
631 {
632   _ICOM_THIS(OLEFontImpl, iface);
633
634   /*
635    * Sanity check
636    */
637   if (punderline==0)
638     return E_POINTER;
639
640   *punderline = this->description.fUnderline;
641
642   return S_OK;
643 }
644
645 /************************************************************************
646  * OLEFontImpl_put_Underline (IFont)
647  *
648  * See Windows documentation for more details on IFont methods.
649  */
650 static HRESULT WINAPI OLEFontImpl_put_Underline(
651   IFont* iface,
652   BOOL underline)
653 {
654   _ICOM_THIS(OLEFontImpl, iface);
655
656   this->description.fUnderline = underline;
657
658   return S_OK;
659 }
660
661 /************************************************************************
662  * OLEFontImpl_get_Strikethrough (IFont)
663  *
664  * See Windows documentation for more details on IFont methods.
665  */
666 static HRESULT WINAPI OLEFontImpl_get_Strikethrough(
667   IFont*  iface, 
668   BOOL* pstrikethrough)
669 {
670   _ICOM_THIS(OLEFontImpl, iface);
671
672   /*
673    * Sanity check
674    */
675   if (pstrikethrough==0)
676     return E_POINTER;
677
678   *pstrikethrough = this->description.fStrikethrough;
679
680   return S_OK;
681 }
682
683 /************************************************************************
684  * OLEFontImpl_put_Strikethrough (IFont)
685  *
686  * See Windows documentation for more details on IFont methods.
687  */
688 static HRESULT WINAPI OLEFontImpl_put_Strikethrough(
689  IFont* iface, 
690  BOOL strikethrough)
691 {
692   _ICOM_THIS(OLEFontImpl, iface);
693
694   this->description.fStrikethrough = strikethrough;
695
696   return S_OK;
697 }
698
699 /************************************************************************
700  * OLEFontImpl_get_Weight (IFont)
701  *
702  * See Windows documentation for more details on IFont methods.
703  */
704 static HRESULT WINAPI OLEFontImpl_get_Weight(
705   IFont* iface, 
706   short* pweight)
707 {
708   _ICOM_THIS(OLEFontImpl, iface);
709
710   /*
711    * Sanity check
712    */
713   if (pweight==0)
714     return E_POINTER;
715
716   *pweight = this->description.sWeight;
717
718   return S_OK;
719 }
720
721 /************************************************************************
722  * OLEFontImpl_put_Weight (IFont)
723  *
724  * See Windows documentation for more details on IFont methods.
725  */
726 static HRESULT WINAPI OLEFontImpl_put_Weight(
727   IFont* iface, 
728   short  weight)
729 {
730   _ICOM_THIS(OLEFontImpl, iface);
731
732   this->description.sWeight = weight;
733
734   return S_OK;
735 }
736
737 /************************************************************************
738  * OLEFontImpl_get_Charset (IFont)
739  *
740  * See Windows documentation for more details on IFont methods.
741  */
742 static HRESULT WINAPI OLEFontImpl_get_Charset(
743   IFont* iface, 
744   short* pcharset)
745 {
746   _ICOM_THIS(OLEFontImpl, iface);
747
748   /*
749    * Sanity check
750    */
751   if (pcharset==0)
752     return E_POINTER;
753
754   *pcharset = this->description.sCharset;
755
756   return S_OK;
757 }
758
759 /************************************************************************
760  * OLEFontImpl_put_Charset (IFont)
761  *
762  * See Windows documentation for more details on IFont methods.
763  */
764 static HRESULT WINAPI OLEFontImpl_put_Charset(
765   IFont* iface, 
766   short charset)
767 {
768   _ICOM_THIS(OLEFontImpl, iface);
769
770   this->description.sCharset = charset;
771
772   return S_OK;
773 }
774
775 /************************************************************************
776  * OLEFontImpl_get_hFont (IFont)
777  *
778  * See Windows documentation for more details on IFont methods.
779  */
780 static HRESULT WINAPI OLEFontImpl_get_hFont(
781   IFont*   iface,
782   HFONT* phfont)
783 {
784   _ICOM_THIS(OLEFontImpl, iface);
785
786   if (phfont==NULL)
787     return E_POINTER;
788
789   /*
790    * Realize the font if necessary
791  */
792   if (this->gdiFont==0)
793 {
794     LOGFONTW logFont;
795     INT      fontHeight;
796     CY       cySize;
797     
798     /*
799      * The height of the font returned by the get_Size property is the
800      * height of the font in points multiplied by 10000... Using some
801      * simple conversions and the ratio given by the application, it can
802      * be converted to a height in pixels.
803      */
804     IFont_get_Size(iface, &cySize);
805
806     fontHeight = MulDiv(cySize.s.Lo, 2540L, 72L);
807     fontHeight = MulDiv(fontHeight, this->cyLogical,this->cyHimetric);
808
809     memset(&logFont, 0, sizeof(LOGFONTW));
810
811     logFont.lfHeight          = ((fontHeight%10000L)>5000L) ? (-fontHeight/10000L)-1 :
812                                                               (-fontHeight/10000L);
813     logFont.lfItalic          = this->description.fItalic;
814     logFont.lfUnderline       = this->description.fUnderline;
815     logFont.lfStrikeOut       = this->description.fStrikethrough;
816     logFont.lfWeight          = this->description.sWeight;
817     logFont.lfCharSet         = this->description.sCharset;
818     logFont.lfOutPrecision    = OUT_CHARACTER_PRECIS;
819     logFont.lfClipPrecision   = CLIP_DEFAULT_PRECIS;
820     logFont.lfQuality         = DEFAULT_QUALITY;
821     logFont.lfPitchAndFamily  = DEFAULT_PITCH;
822     lstrcpyW(logFont.lfFaceName,this->description.lpstrName);
823
824     this->gdiFont = CreateFontIndirectW(&logFont);
825   }
826
827   *phfont = this->gdiFont;
828
829   return S_OK;
830 }
831
832 /************************************************************************
833  * OLEFontImpl_Clone (IFont)
834  *
835  * See Windows documentation for more details on IFont methods.
836  */
837 static HRESULT WINAPI OLEFontImpl_Clone(
838   IFont*  iface,
839   IFont** ppfont)
840 {
841   OLEFontImpl* newObject = 0;
842
843   _ICOM_THIS(OLEFontImpl, iface);
844
845   if (ppfont == NULL)
846     return E_POINTER;
847
848   *ppfont = NULL;
849
850   /*
851    * Allocate space for the object.
852    */
853   newObject = HeapAlloc(GetProcessHeap(), 0, sizeof(OLEFontImpl));
854
855   if (newObject==NULL)
856     return E_OUTOFMEMORY;
857
858   *newObject = *this;
859
860   /*
861    * That new object starts with a reference count of 1
862    */
863   newObject->ref          = 1;
864
865   *ppfont = (IFont*)newObject;
866
867   return S_OK;
868 }
869
870 /************************************************************************
871  * OLEFontImpl_IsEqual (IFont)
872  *
873  * See Windows documentation for more details on IFont methods.
874  */
875 static HRESULT WINAPI OLEFontImpl_IsEqual(
876   IFont* iface, 
877   IFont* pFontOther)
878 {
879   FIXME("():Stub\n");
880   return E_NOTIMPL;
881 }
882
883 /************************************************************************
884  * OLEFontImpl_SetRatio (IFont)
885  *
886  * See Windows documentation for more details on IFont methods.
887  */
888 static HRESULT WINAPI OLEFontImpl_SetRatio(
889   IFont* iface,
890   long   cyLogical,
891   long   cyHimetric)
892 {
893   _ICOM_THIS(OLEFontImpl, iface);
894
895   this->cyLogical  = cyLogical;
896   this->cyHimetric = cyHimetric;
897
898   return S_OK;
899 }
900
901 /************************************************************************
902  * OLEFontImpl_QueryTextMetrics (IFont)
903  *
904  * See Windows documentation for more details on IFont methods.
905  */
906 static HRESULT      WINAPI OLEFontImpl_QueryTextMetrics(
907   IFont*         iface, 
908   TEXTMETRICOLE* ptm)
909 {
910   FIXME("():Stub\n");
911   return E_NOTIMPL;
912 }
913
914 /************************************************************************
915  * OLEFontImpl_AddRefHfont (IFont)
916  *
917  * See Windows documentation for more details on IFont methods.
918  */
919 static HRESULT WINAPI OLEFontImpl_AddRefHfont(
920   IFont*  iface, 
921   HFONT hfont)
922 {
923   _ICOM_THIS(OLEFontImpl, iface);
924
925   if ( (hfont == 0) ||
926        (hfont != this->gdiFont) )
927     return E_INVALIDARG;
928
929   this->fontLock++;
930
931   return S_OK;
932 }
933
934 /************************************************************************
935  * OLEFontImpl_ReleaseHfont (IFont)
936  *
937  * See Windows documentation for more details on IFont methods.
938  */
939 static HRESULT WINAPI OLEFontImpl_ReleaseHfont(
940   IFont*  iface,
941   HFONT hfont)
942 {
943   _ICOM_THIS(OLEFontImpl, iface);
944
945   if ( (hfont == 0) ||
946        (hfont != this->gdiFont) )
947     return E_INVALIDARG;
948
949   this->fontLock--;
950
951   /*
952    * If we just released our last font reference, destroy it.
953    */
954   if (this->fontLock==0)
955   {
956     DeleteObject(this->gdiFont);
957     this->gdiFont = 0; 
958 }
959
960   return S_OK;
961 }
962
963 /************************************************************************
964  * OLEFontImpl_SetHdc (IFont)
965  *
966  * See Windows documentation for more details on IFont methods.
967  */
968 static HRESULT WINAPI OLEFontImpl_SetHdc(
969   IFont* iface,
970   HDC  hdc)
971 {
972   FIXME("():Stub\n");
973   return E_NOTIMPL;
974 }
975
976 /************************************************************************
977  * OLEFontImpl_IDispatch_QueryInterface (IUnknown)
978  *
979  * See Windows documentation for more details on IUnknown methods.
980  */
981 static HRESULT WINAPI OLEFontImpl_IDispatch_QueryInterface(
982   IDispatch* iface,
983   REFIID     riid,
984   VOID**     ppvoid)
985 {
986   _ICOM_THIS_From_IDispatch(IFont, iface);
987
988   return IFont_QueryInterface(this, riid, ppvoid);
989 }
990
991 /************************************************************************
992  * OLEFontImpl_IDispatch_Release (IUnknown)
993  *
994  * See Windows documentation for more details on IUnknown methods.
995  */
996 static ULONG WINAPI OLEFontImpl_IDispatch_Release(
997   IDispatch* iface)
998 {
999   _ICOM_THIS_From_IDispatch(IFont, iface);
1000
1001   return IFont_Release(this);
1002 }
1003
1004 /************************************************************************
1005  * OLEFontImpl_IDispatch_AddRef (IUnknown)
1006  *
1007  * See Windows documentation for more details on IUnknown methods.
1008  */
1009 static ULONG WINAPI OLEFontImpl_IDispatch_AddRef(
1010   IDispatch* iface)
1011 {
1012   _ICOM_THIS_From_IDispatch(IFont, iface);
1013
1014   return IFont_AddRef(this);
1015 }
1016
1017 /************************************************************************
1018  * OLEFontImpl_GetTypeInfoCount (IDispatch)
1019  *
1020  * See Windows documentation for more details on IDispatch methods.
1021  */
1022 static HRESULT WINAPI OLEFontImpl_GetTypeInfoCount(
1023   IDispatch*    iface, 
1024   unsigned int* pctinfo)
1025 {
1026   FIXME("():Stub\n");
1027
1028   return E_NOTIMPL;
1029 }
1030
1031 /************************************************************************
1032  * OLEFontImpl_GetTypeInfo (IDispatch)
1033  *
1034  * See Windows documentation for more details on IDispatch methods.
1035  */
1036 static HRESULT WINAPI OLEFontImpl_GetTypeInfo(
1037   IDispatch*  iface, 
1038   UINT      iTInfo,
1039   LCID        lcid, 
1040   ITypeInfo** ppTInfo)
1041 {
1042   FIXME("():Stub\n");
1043
1044   return E_NOTIMPL;
1045 }
1046
1047 /************************************************************************
1048  * OLEFontImpl_GetIDsOfNames (IDispatch)
1049  *
1050  * See Windows documentation for more details on IDispatch methods.
1051  */
1052 static HRESULT WINAPI OLEFontImpl_GetIDsOfNames(
1053   IDispatch*  iface,
1054   REFIID      riid, 
1055   LPOLESTR* rgszNames, 
1056   UINT      cNames, 
1057   LCID        lcid,
1058   DISPID*     rgDispId)
1059 {
1060   FIXME("():Stub\n");
1061
1062   return E_NOTIMPL;
1063 }
1064
1065 /************************************************************************
1066  * OLEFontImpl_Invoke (IDispatch)
1067  *
1068  * See Windows documentation for more details on IDispatch methods.
1069  */
1070 static HRESULT WINAPI OLEFontImpl_Invoke(
1071   IDispatch*  iface,
1072   DISPID      dispIdMember, 
1073   REFIID      riid, 
1074   LCID        lcid, 
1075   WORD        wFlags,
1076   DISPPARAMS* pDispParams,
1077   VARIANT*    pVarResult, 
1078   EXCEPINFO*  pExepInfo,
1079   UINT*     puArgErr)
1080 {
1081   FIXME("():Stub\n");
1082
1083   return E_NOTIMPL;
1084 }
1085
1086 /************************************************************************
1087  * OLEFontImpl_IPersistStream_QueryInterface (IUnknown)
1088  *
1089  * See Windows documentation for more details on IUnknown methods.
1090  */
1091 static HRESULT WINAPI OLEFontImpl_IPersistStream_QueryInterface(
1092   IPersistStream* iface,
1093   REFIID     riid,
1094   VOID**     ppvoid)
1095 {
1096   _ICOM_THIS_From_IPersistStream(IFont, iface);
1097
1098   return IFont_QueryInterface(this, riid, ppvoid);
1099 }
1100
1101 /************************************************************************
1102  * OLEFontImpl_IPersistStream_Release (IUnknown)
1103  *
1104  * See Windows documentation for more details on IUnknown methods.
1105  */
1106 static ULONG WINAPI OLEFontImpl_IPersistStream_Release(
1107   IPersistStream* iface)
1108 {
1109   _ICOM_THIS_From_IPersistStream(IFont, iface);
1110
1111   return IFont_Release(this);
1112 }
1113
1114 /************************************************************************
1115  * OLEFontImpl_IPersistStream_AddRef (IUnknown)
1116  *
1117  * See Windows documentation for more details on IUnknown methods.
1118  */
1119 static ULONG WINAPI OLEFontImpl_IPersistStream_AddRef(
1120   IPersistStream* iface)
1121 {
1122   _ICOM_THIS_From_IPersistStream(IFont, iface);
1123
1124   return IFont_AddRef(this);
1125 }
1126
1127 /************************************************************************
1128  * OLEFontImpl_GetClassID (IPersistStream)
1129  *
1130  * See Windows documentation for more details on IPersistStream methods.
1131  */
1132 static HRESULT WINAPI OLEFontImpl_GetClassID(
1133   IPersistStream* iface, 
1134   CLSID*                pClassID)
1135 {
1136   if (pClassID==0)
1137     return E_POINTER;
1138
1139   memcpy(pClassID, &CLSID_StdFont, sizeof(CLSID_StdFont));
1140
1141   return S_OK;
1142 }
1143
1144 /************************************************************************
1145  * OLEFontImpl_IsDirty (IPersistStream)
1146  *
1147  * See Windows documentation for more details on IPersistStream methods.
1148  */
1149 static HRESULT WINAPI OLEFontImpl_IsDirty(
1150   IPersistStream*  iface)
1151 {
1152   return S_OK;
1153 }
1154
1155 /************************************************************************
1156  * OLEFontImpl_Load (IPersistStream)
1157  *
1158  * See Windows documentation for more details on IPersistStream methods.
1159  *
1160  * This is the format of the standard font serialization as far as I
1161  * know
1162  *
1163  * Offset   Type   Value           Comment
1164  * 0x0000   Byte   Unknown         Probably a version number, contains 0x01
1165  * 0x0001   Short  Charset         Charset value from the FONTDESC structure
1166  * 0x0003   Byte   Attributes      Flags defined as follows:
1167  *                                     00000010 - Italic
1168  *                                     00000100 - Underline
1169  *                                     00001000 - Strikethrough
1170  * 0x0004   Short  Weight          Weight value from FONTDESC structure
1171  * 0x0006   DWORD  size            "Low" portion of the cySize member of the FONTDESC
1172  *                                 structure/
1173  * 0x000A   Byte   name length     Length of the font name string (no null character)
1174  * 0x000B   String name            Name of the font (ASCII, no nul character)
1175  */
1176 static HRESULT WINAPI OLEFontImpl_Load(
1177   IPersistStream*  iface,
1178   IStream*         pLoadStream)
1179 {
1180   char  readBuffer[0x100];
1181   ULONG cbRead;
1182   BYTE  bVersion;
1183   BYTE  bAttributes;
1184   BYTE  bStringSize;
1185
1186   _ICOM_THIS_From_IPersistStream(OLEFontImpl, iface);
1187   
1188   /*
1189    * Read the version byte
1190    */
1191   IStream_Read(pLoadStream, &bVersion, 1, &cbRead);
1192
1193   if ( (cbRead!=1) ||
1194        (bVersion!=0x01) )
1195     return E_FAIL;
1196
1197   /*
1198    * Charset
1199    */
1200   IStream_Read(pLoadStream, &this->description.sCharset, 2, &cbRead);
1201
1202   if (cbRead!=2)
1203     return E_FAIL;
1204
1205   /*
1206    * Attributes
1207    */
1208   IStream_Read(pLoadStream, &bAttributes, 1, &cbRead);
1209
1210   if (cbRead!=1)
1211     return E_FAIL;
1212
1213   this->description.fItalic        = (bAttributes & FONTPERSIST_ITALIC) != 0;
1214   this->description.fStrikethrough = (bAttributes & FONTPERSIST_STRIKETHROUGH) != 0;
1215   this->description.fUnderline     = (bAttributes & FONTPERSIST_UNDERLINE) != 0;
1216     
1217   /*
1218    * Weight
1219    */
1220   IStream_Read(pLoadStream, &this->description.sWeight, 2, &cbRead);
1221
1222   if (cbRead!=2)
1223     return E_FAIL;
1224
1225   /*
1226    * Size
1227    */
1228   IStream_Read(pLoadStream, &this->description.cySize.s.Lo, 4, &cbRead);
1229
1230   if (cbRead!=4)
1231     return E_FAIL;
1232
1233   this->description.cySize.s.Hi = 0;
1234
1235   /*
1236    * FontName
1237    */
1238   IStream_Read(pLoadStream, &bStringSize, 1, &cbRead);
1239
1240   if (cbRead!=1)
1241     return E_FAIL;
1242
1243   memset(readBuffer, 0, 0x100);
1244   IStream_Read(pLoadStream, readBuffer, bStringSize, &cbRead);
1245
1246   if (cbRead!=bStringSize)
1247     return E_FAIL;
1248
1249   if (this->description.lpstrName!=0)
1250     HeapFree(GetProcessHeap(), 0, this->description.lpstrName);
1251
1252   this->description.lpstrName = HEAP_strdupAtoW(GetProcessHeap(), 
1253                                                     HEAP_ZERO_MEMORY,
1254                                                     readBuffer);
1255
1256   return S_OK;
1257 }
1258
1259 /************************************************************************
1260  * OLEFontImpl_Save (IPersistStream)
1261  *
1262  * See Windows documentation for more details on IPersistStream methods.
1263  */
1264 static HRESULT WINAPI OLEFontImpl_Save(
1265   IPersistStream*  iface,
1266   IStream*         pOutStream,
1267   BOOL             fClearDirty)
1268 {
1269   char* writeBuffer = NULL;
1270   ULONG cbWritten;
1271   BYTE  bVersion = 0x01;
1272   BYTE  bAttributes;
1273   BYTE  bStringSize;
1274   
1275   _ICOM_THIS_From_IPersistStream(OLEFontImpl, iface);
1276
1277   /*
1278    * Read the version byte
1279    */
1280   IStream_Write(pOutStream, &bVersion, 1, &cbWritten);
1281
1282   if (cbWritten!=1)
1283     return E_FAIL;
1284
1285   /*
1286    * Charset
1287    */
1288   IStream_Write(pOutStream, &this->description.sCharset, 2, &cbWritten);
1289
1290   if (cbWritten!=2)
1291     return E_FAIL;
1292
1293   /*
1294    * Attributes
1295    */
1296   bAttributes = 0;
1297
1298   if (this->description.fItalic)
1299     bAttributes |= FONTPERSIST_ITALIC;
1300
1301   if (this->description.fStrikethrough)
1302     bAttributes |= FONTPERSIST_STRIKETHROUGH;
1303   
1304   if (this->description.fUnderline)
1305     bAttributes |= FONTPERSIST_UNDERLINE;
1306
1307   IStream_Write(pOutStream, &bAttributes, 1, &cbWritten);
1308
1309   if (cbWritten!=1)
1310     return E_FAIL;
1311   
1312   /*
1313    * Weight
1314    */
1315   IStream_Write(pOutStream, &this->description.sWeight, 2, &cbWritten);
1316
1317   if (cbWritten!=2)
1318     return E_FAIL;
1319
1320   /*
1321    * Size
1322    */
1323   IStream_Write(pOutStream, &this->description.cySize.s.Lo, 4, &cbWritten);
1324
1325   if (cbWritten!=4)
1326     return E_FAIL;
1327
1328   /*
1329    * FontName
1330    */
1331   if (this->description.lpstrName!=0)
1332     bStringSize = lstrlenW(this->description.lpstrName);
1333   else
1334     bStringSize = 0;
1335
1336   IStream_Write(pOutStream, &bStringSize, 1, &cbWritten);
1337
1338   if (cbWritten!=1)
1339     return E_FAIL;
1340
1341   if (bStringSize!=0)
1342   {
1343     writeBuffer = HEAP_strdupWtoA(GetProcessHeap(), 
1344                                   HEAP_ZERO_MEMORY,
1345                                   this->description.lpstrName);
1346
1347     if (writeBuffer==0)
1348       return E_OUTOFMEMORY;
1349
1350     IStream_Write(pOutStream, writeBuffer, bStringSize, &cbWritten);
1351     
1352     HeapFree(GetProcessHeap(), 0, writeBuffer);
1353
1354     if (cbWritten!=bStringSize)
1355       return E_FAIL;
1356   }
1357
1358   return S_OK;
1359 }
1360
1361 /************************************************************************
1362  * OLEFontImpl_GetSizeMax (IPersistStream)
1363  *
1364  * See Windows documentation for more details on IPersistStream methods.
1365  */
1366 static HRESULT WINAPI OLEFontImpl_GetSizeMax(
1367   IPersistStream*  iface,
1368   ULARGE_INTEGER*  pcbSize)
1369 {
1370   _ICOM_THIS_From_IPersistStream(OLEFontImpl, iface);
1371
1372   if (pcbSize==NULL)
1373     return E_POINTER;
1374
1375   pcbSize->s.HighPart = 0;
1376   pcbSize->s.LowPart = 0;
1377
1378   pcbSize->s.LowPart += sizeof(BYTE);  /* Version */
1379   pcbSize->s.LowPart += sizeof(WORD);  /* Lang code */
1380   pcbSize->s.LowPart += sizeof(BYTE);  /* Flags */
1381   pcbSize->s.LowPart += sizeof(WORD);  /* Weight */
1382   pcbSize->s.LowPart += sizeof(DWORD); /* Size */
1383   pcbSize->s.LowPart += sizeof(BYTE);  /* StrLength */
1384
1385   if (this->description.lpstrName!=0)
1386     pcbSize->s.LowPart += lstrlenW(this->description.lpstrName);
1387
1388   return S_OK;
1389 }