Use DrawFrameControl instead of bitmaps in certain cases.
[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 "winbase.h"
13 #include "wingdi.h"
14 #include "winuser.h"
15 #include "wine/unicode.h"
16 #include "oleauto.h"    /* for SysAllocString(....) */
17 #include "wine/obj_base.h"
18 #include "wine/obj_olefont.h"
19 #include "wine/obj_storage.h"
20 #include "ole2.h"
21 #include "olectl.h"
22 #include "debugtools.h"
23 #include "connpt.h" /* for CreateConnectionPoint */
24
25 DEFAULT_DEBUG_CHANNEL(ole);
26
27 /***********************************************************************
28  * Declaration of constants used when serializing the font object.
29  */
30 #define FONTPERSIST_ITALIC        0x02
31 #define FONTPERSIST_UNDERLINE     0x04
32 #define FONTPERSIST_STRIKETHROUGH 0x08
33
34 /***********************************************************************
35  * Declaration of the implementation class for the IFont interface
36  */
37 typedef struct OLEFontImpl OLEFontImpl;
38
39 struct OLEFontImpl
40 {
41   /*
42    * This class supports many interfaces. IUnknown, IFont, 
43    * IDispatch, IDispFont IPersistStream and IConnectionPointContainer.
44    * The first two are supported by the first vtable, the next two are
45    * supported by the second table and the last two have their own.
46    */
47   ICOM_VTABLE(IFont)*     lpvtbl1;
48   ICOM_VTABLE(IDispatch)* lpvtbl2;
49   ICOM_VTABLE(IPersistStream)*            lpvtbl3;
50   ICOM_VTABLE(IConnectionPointContainer)* lpvtbl4;
51   /*
52    * Reference count for that instance of the class.
53    */
54   ULONG ref;
55
56   /*
57    * This structure contains the description of the class.
58    */
59   FONTDESC description;
60
61   /*
62    * Contain the font associated with this object.
63    */
64   HFONT gdiFont;
65
66   /*
67    * Font lock count.
68    */
69   DWORD fontLock;
70
71   /*
72    * Size ratio
73    */
74   long cyLogical;
75   long cyHimetric;
76
77   IConnectionPoint *pCP;
78 };
79
80 /*
81  * Here, I define utility macros to help with the casting of the 
82  * "this" parameter.
83  * There is a version to accomodate all of the VTables implemented
84  * by this object.
85  */
86 #define _ICOM_THIS(class,name) class* this = (class*)name;
87 #define _ICOM_THIS_From_IDispatch(class, name) class* this = (class*)(((char*)name)-sizeof(void*)); 
88 #define _ICOM_THIS_From_IPersistStream(class, name) class* this = (class*)(((char*)name)-2*sizeof(void*)); 
89 #define _ICOM_THIS_From_IConnectionPointContainer(class, name) class* this = (class*)(((char*)name)-3*sizeof(void*)); 
90
91
92 /***********************************************************************
93  * Prototypes for the implementation functions for the IFont
94  * interface
95  */
96 static OLEFontImpl* OLEFontImpl_Construct(LPFONTDESC fontDesc);
97 static void         OLEFontImpl_Destroy(OLEFontImpl* fontDesc);
98 static HRESULT      WINAPI OLEFontImpl_QueryInterface(IFont* iface, REFIID riid, VOID** ppvoid);
99 static ULONG        WINAPI OLEFontImpl_AddRef(IFont* iface);
100 static ULONG        WINAPI OLEFontImpl_Release(IFont* iface);
101 static HRESULT      WINAPI OLEFontImpl_get_Name(IFont* iface, BSTR* pname);
102 static HRESULT      WINAPI OLEFontImpl_put_Name(IFont* iface, BSTR name);
103 static HRESULT      WINAPI OLEFontImpl_get_Size(IFont* iface, CY* psize);
104 static HRESULT      WINAPI OLEFontImpl_put_Size(IFont* iface, CY size);
105 static HRESULT      WINAPI OLEFontImpl_get_Bold(IFont* iface, BOOL* pbold);
106 static HRESULT      WINAPI OLEFontImpl_put_Bold(IFont* iface, BOOL bold);
107 static HRESULT      WINAPI OLEFontImpl_get_Italic(IFont* iface, BOOL* pitalic);
108 static HRESULT      WINAPI OLEFontImpl_put_Italic(IFont* iface, BOOL italic);
109 static HRESULT      WINAPI OLEFontImpl_get_Underline(IFont* iface, BOOL* punderline);
110 static HRESULT      WINAPI OLEFontImpl_put_Underline(IFont* iface, BOOL underline);
111 static HRESULT      WINAPI OLEFontImpl_get_Strikethrough(IFont* iface, BOOL* pstrikethrough);
112 static HRESULT      WINAPI OLEFontImpl_put_Strikethrough(IFont* iface, BOOL strikethrough);
113 static HRESULT      WINAPI OLEFontImpl_get_Weight(IFont* iface, short* pweight);
114 static HRESULT      WINAPI OLEFontImpl_put_Weight(IFont* iface, short weight);
115 static HRESULT      WINAPI OLEFontImpl_get_Charset(IFont* iface, short* pcharset);
116 static HRESULT      WINAPI OLEFontImpl_put_Charset(IFont* iface, short charset);
117 static HRESULT      WINAPI OLEFontImpl_get_hFont(IFont* iface, HFONT* phfont);
118 static HRESULT      WINAPI OLEFontImpl_Clone(IFont* iface, IFont** ppfont);
119 static HRESULT      WINAPI OLEFontImpl_IsEqual(IFont* iface, IFont* pFontOther);
120 static HRESULT      WINAPI OLEFontImpl_SetRatio(IFont* iface, long cyLogical, long cyHimetric);
121 static HRESULT      WINAPI OLEFontImpl_QueryTextMetrics(IFont* iface, TEXTMETRICOLE* ptm);
122 static HRESULT      WINAPI OLEFontImpl_AddRefHfont(IFont* iface, HFONT hfont);
123 static HRESULT      WINAPI OLEFontImpl_ReleaseHfont(IFont* iface, HFONT hfont);
124 static HRESULT      WINAPI OLEFontImpl_SetHdc(IFont* iface, HDC hdc);
125
126 /***********************************************************************
127  * Prototypes for the implementation functions for the IDispatch
128  * interface
129  */
130 static HRESULT WINAPI OLEFontImpl_IDispatch_QueryInterface(IDispatch* iface, 
131                                                     REFIID     riid, 
132                                                     VOID**     ppvoid);
133 static ULONG   WINAPI OLEFontImpl_IDispatch_AddRef(IDispatch* iface);
134 static ULONG   WINAPI OLEFontImpl_IDispatch_Release(IDispatch* iface);
135 static HRESULT WINAPI OLEFontImpl_GetTypeInfoCount(IDispatch*    iface, 
136                                                    unsigned int* pctinfo);
137 static HRESULT WINAPI OLEFontImpl_GetTypeInfo(IDispatch*  iface, 
138                                               UINT      iTInfo,
139                                               LCID        lcid, 
140                                               ITypeInfo** ppTInfo);
141 static HRESULT WINAPI OLEFontImpl_GetIDsOfNames(IDispatch*  iface,
142                                                 REFIID      riid, 
143                                                 LPOLESTR* rgszNames, 
144                                                 UINT      cNames, 
145                                                 LCID        lcid,
146                                                 DISPID*     rgDispId);
147 static HRESULT WINAPI OLEFontImpl_Invoke(IDispatch*  iface,
148                                          DISPID      dispIdMember, 
149                                          REFIID      riid, 
150                                          LCID        lcid, 
151                                          WORD        wFlags,
152                                          DISPPARAMS* pDispParams,
153                                          VARIANT*    pVarResult, 
154                                          EXCEPINFO*  pExepInfo,
155                                          UINT*     puArgErr); 
156
157 /***********************************************************************
158  * Prototypes for the implementation functions for the IPersistStream
159  * interface
160  */
161 static HRESULT WINAPI OLEFontImpl_IPersistStream_QueryInterface(IPersistStream* iface, 
162                                                     REFIID     riid, 
163                                                     VOID**     ppvoid);
164 static ULONG   WINAPI OLEFontImpl_IPersistStream_AddRef(IPersistStream* iface);
165 static ULONG   WINAPI OLEFontImpl_IPersistStream_Release(IPersistStream* iface);
166 static HRESULT WINAPI OLEFontImpl_GetClassID(IPersistStream* iface, 
167                                              CLSID*                pClassID);
168 static HRESULT WINAPI OLEFontImpl_IsDirty(IPersistStream*  iface);
169 static HRESULT WINAPI OLEFontImpl_Load(IPersistStream*  iface,
170                                        IStream*         pLoadStream);
171 static HRESULT WINAPI OLEFontImpl_Save(IPersistStream*  iface,
172                                        IStream*         pOutStream,
173                                        BOOL             fClearDirty); 
174 static HRESULT WINAPI OLEFontImpl_GetSizeMax(IPersistStream*  iface,
175                                              ULARGE_INTEGER*  pcbSize); 
176
177 /***********************************************************************
178  * Prototypes for the implementation functions for the
179  * IConnectionPointContainer interface
180  */
181 static HRESULT WINAPI OLEFontImpl_IConnectionPointContainer_QueryInterface(
182                                             IConnectionPointContainer* iface, 
183                                             REFIID     riid, 
184                                             VOID**     ppvoid);
185 static ULONG   WINAPI OLEFontImpl_IConnectionPointContainer_AddRef(
186                                             IConnectionPointContainer* iface);
187 static ULONG   WINAPI OLEFontImpl_IConnectionPointContainer_Release(
188                                             IConnectionPointContainer* iface);
189 static HRESULT WINAPI OLEFontImpl_EnumConnectionPoints(
190                                             IConnectionPointContainer* iface,
191                                             IEnumConnectionPoints **ppEnum);
192 static HRESULT WINAPI OLEFontImpl_FindConnectionPoint(
193                                             IConnectionPointContainer* iface,
194                                             REFIID riid,
195                                             IConnectionPoint **ppCp);
196
197 /*
198  * Virtual function tables for the OLEFontImpl class.
199  */
200 static ICOM_VTABLE(IFont) OLEFontImpl_VTable =
201 {
202   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
203   OLEFontImpl_QueryInterface,
204   OLEFontImpl_AddRef,
205   OLEFontImpl_Release,
206   OLEFontImpl_get_Name,
207   OLEFontImpl_put_Name,
208   OLEFontImpl_get_Size,
209   OLEFontImpl_put_Size,
210   OLEFontImpl_get_Bold,
211   OLEFontImpl_put_Bold,
212   OLEFontImpl_get_Italic,
213   OLEFontImpl_put_Italic,
214   OLEFontImpl_get_Underline,
215   OLEFontImpl_put_Underline,
216   OLEFontImpl_get_Strikethrough,
217   OLEFontImpl_put_Strikethrough,
218   OLEFontImpl_get_Weight,
219   OLEFontImpl_put_Weight,
220   OLEFontImpl_get_Charset,
221   OLEFontImpl_put_Charset,
222   OLEFontImpl_get_hFont,
223   OLEFontImpl_Clone, 
224   OLEFontImpl_IsEqual,
225   OLEFontImpl_SetRatio,
226   OLEFontImpl_QueryTextMetrics,
227   OLEFontImpl_AddRefHfont,
228   OLEFontImpl_ReleaseHfont,
229   OLEFontImpl_SetHdc
230 };
231
232 static ICOM_VTABLE(IDispatch) OLEFontImpl_IDispatch_VTable =
233 {
234   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
235   OLEFontImpl_IDispatch_QueryInterface,
236   OLEFontImpl_IDispatch_AddRef,
237   OLEFontImpl_IDispatch_Release,
238   OLEFontImpl_GetTypeInfoCount,
239   OLEFontImpl_GetTypeInfo,
240   OLEFontImpl_GetIDsOfNames,
241   OLEFontImpl_Invoke
242 };
243
244 static ICOM_VTABLE(IPersistStream) OLEFontImpl_IPersistStream_VTable =
245 {
246   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
247   OLEFontImpl_IPersistStream_QueryInterface,
248   OLEFontImpl_IPersistStream_AddRef,
249   OLEFontImpl_IPersistStream_Release,
250   OLEFontImpl_GetClassID,
251   OLEFontImpl_IsDirty,
252   OLEFontImpl_Load,
253   OLEFontImpl_Save,
254   OLEFontImpl_GetSizeMax
255 };
256
257 static ICOM_VTABLE(IConnectionPointContainer)
258      OLEFontImpl_IConnectionPointContainer_VTable =
259 {
260   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
261   OLEFontImpl_IConnectionPointContainer_QueryInterface,
262   OLEFontImpl_IConnectionPointContainer_AddRef,
263   OLEFontImpl_IConnectionPointContainer_Release,
264   OLEFontImpl_EnumConnectionPoints,
265   OLEFontImpl_FindConnectionPoint
266 };
267
268 /******************************************************************************
269  *              OleCreateFontIndirect   [OLEAUT32.420]
270  */
271 HRESULT WINAPI OleCreateFontIndirect(
272   LPFONTDESC lpFontDesc,
273   REFIID     riid,
274   LPVOID*     ppvObj)
275 {
276   OLEFontImpl* newFont = 0;
277   HRESULT      hr      = S_OK;
278
279   TRACE("(%p, %s, %p)\n", lpFontDesc, debugstr_guid(riid), ppvObj);
280   /*
281    * Sanity check
282    */
283   if (ppvObj==0)
284     return E_POINTER;
285
286   *ppvObj = 0;
287
288   /*
289    * Try to construct a new instance of the class.
290    */
291   newFont = OLEFontImpl_Construct(lpFontDesc);
292
293   if (newFont == 0)
294     return E_OUTOFMEMORY;
295
296   /*
297    * Make sure it supports the interface required by the caller.
298    */
299   hr = IFont_QueryInterface((IFont*)newFont, riid, ppvObj);
300
301   /*
302    * Release the reference obtained in the constructor. If
303    * the QueryInterface was unsuccessful, it will free the class.
304    */
305   IFont_Release((IFont*)newFont);
306
307   return hr;
308 }
309
310
311 /***********************************************************************
312  * Implementation of the OLEFontImpl class.
313  */
314
315 /***********************************************************************
316  *    OLEFont_SendNotify (internal)
317  *
318  * Sends notification messages of changed properties to any interested
319  * connections.
320  */
321 static void OLEFont_SendNotify(OLEFontImpl* this, DISPID dispID)
322 {
323   IEnumConnections *pEnum;
324   CONNECTDATA CD;
325
326   IConnectionPoint_EnumConnections(this->pCP, &pEnum);
327   
328   while(IEnumConnections_Next(pEnum, 1, &CD, NULL) == S_OK) {
329     IPropertyNotifySink *sink;
330
331     IUnknown_QueryInterface(CD.pUnk, &IID_IPropertyNotifySink, (LPVOID)&sink);
332     IPropertyNotifySink_OnChanged(sink, dispID);
333     IPropertyNotifySink_Release(sink);
334     IUnknown_Release(CD.pUnk);
335   }
336   IEnumConnections_Release(pEnum);
337   return;
338 }
339   
340 /************************************************************************
341  * OLEFontImpl_Construct
342  *
343  * This method will construct a new instance of the OLEFontImpl
344  * class.
345  *
346  * The caller of this method must release the object when it's
347  * done with it.
348  */
349 static OLEFontImpl* OLEFontImpl_Construct(LPFONTDESC fontDesc)
350 {
351   OLEFontImpl* newObject = 0;
352
353   /*
354    * Allocate space for the object.
355    */
356   newObject = HeapAlloc(GetProcessHeap(), 0, sizeof(OLEFontImpl));
357
358   if (newObject==0)
359     return newObject;
360   
361   /*
362    * Initialize the virtual function table.
363    */
364   newObject->lpvtbl1 = &OLEFontImpl_VTable;
365   newObject->lpvtbl2 = &OLEFontImpl_IDispatch_VTable;
366   newObject->lpvtbl3 = &OLEFontImpl_IPersistStream_VTable;
367   newObject->lpvtbl4 = &OLEFontImpl_IConnectionPointContainer_VTable;
368   
369   /*
370    * Start with one reference count. The caller of this function 
371    * must release the interface pointer when it is done.
372    */
373   newObject->ref = 1;
374
375   /*
376    * Copy the description of the font in the object.
377    */
378   assert(fontDesc->cbSizeofstruct >= sizeof(FONTDESC));
379
380   newObject->description.cbSizeofstruct = sizeof(FONTDESC);
381   newObject->description.lpstrName = HeapAlloc(GetProcessHeap(),
382                                                0, 
383                                                (lstrlenW(fontDesc->lpstrName)+1) * sizeof(WCHAR));
384   strcpyW(newObject->description.lpstrName, fontDesc->lpstrName);
385   newObject->description.cySize         = fontDesc->cySize;
386   newObject->description.sWeight        = fontDesc->sWeight;
387   newObject->description.sCharset       = fontDesc->sCharset;
388   newObject->description.fItalic        = fontDesc->fItalic;
389   newObject->description.fUnderline     = fontDesc->fUnderline;
390   newObject->description.fStrikethrough = fontDesc->fStrikethrough;
391
392   /*
393    * Initializing all the other members.
394    */
395   newObject->gdiFont  = 0;
396   newObject->fontLock = 0;
397   newObject->cyHimetric = 1;
398   newObject->cyLogical  = 1;
399
400   CreateConnectionPoint((IUnknown*)newObject, &IID_IPropertyNotifySink, &newObject->pCP);
401
402   TRACE("returning %p\n", newObject);
403   return newObject;
404 }
405
406 /************************************************************************
407  * OLEFontImpl_Destroy
408  *
409  * This method is called by the Release method when the reference
410  * count goes down to 0. It will free all resources used by
411  * this object.
412  */
413 static void OLEFontImpl_Destroy(OLEFontImpl* fontDesc)
414 {
415   TRACE("(%p)\n", fontDesc);
416
417   if (fontDesc->description.lpstrName!=0)
418     HeapFree(GetProcessHeap(), 0, fontDesc->description.lpstrName);
419
420   if (fontDesc->gdiFont!=0)
421     DeleteObject(fontDesc->gdiFont);
422
423   HeapFree(GetProcessHeap(), 0, fontDesc);
424 }
425
426 /************************************************************************
427  * OLEFontImpl_QueryInterface (IUnknown)
428  *
429  * See Windows documentation for more details on IUnknown methods.
430  */
431 HRESULT WINAPI OLEFontImpl_QueryInterface(
432   IFont*  iface,
433   REFIID  riid,
434   void**  ppvObject)
435 {
436   _ICOM_THIS(OLEFontImpl, iface);
437   TRACE("(%p)->(%s, %p)\n", this, debugstr_guid(riid), ppvObject);
438
439   /*
440    * Perform a sanity check on the parameters.
441    */
442   if ( (this==0) || (ppvObject==0) )
443     return E_INVALIDARG;
444   
445   /*
446    * Initialize the return parameter.
447    */
448   *ppvObject = 0;
449   
450   /*
451    * Compare the riid with the interface IDs implemented by this object.
452    */
453   if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0) 
454   {
455     *ppvObject = (IFont*)this;
456   }
457   else if (memcmp(&IID_IFont, riid, sizeof(IID_IFont)) == 0) 
458   {
459     *ppvObject = (IFont*)this;
460   }
461   else if (memcmp(&IID_IDispatch, riid, sizeof(IID_IDispatch)) == 0) 
462   {
463     *ppvObject = (IDispatch*)&(this->lpvtbl2);
464   }
465   else if (memcmp(&IID_IFontDisp, riid, sizeof(IID_IFontDisp)) == 0) 
466   {
467     *ppvObject = (IDispatch*)&(this->lpvtbl2);
468   }
469   else if (memcmp(&IID_IPersistStream, riid, sizeof(IID_IPersistStream)) == 0) 
470   {
471     *ppvObject = (IPersistStream*)&(this->lpvtbl3);
472   }
473   else if (memcmp(&IID_IConnectionPointContainer, riid,
474                   sizeof(IID_IConnectionPointContainer)) == 0) 
475   {
476     *ppvObject = (IPersistStream*)&(this->lpvtbl4);
477   }
478   
479   /*
480    * Check that we obtained an interface.
481    */
482   if ((*ppvObject)==0)
483   {
484     FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid));
485     return E_NOINTERFACE;
486   }
487   
488   /*
489    * Query Interface always increases the reference count by one when it is
490    * successful
491    */
492   OLEFontImpl_AddRef((IFont*)this);
493
494   return S_OK;;
495 }
496         
497 /************************************************************************
498  * OLEFontImpl_AddRef (IUnknown)
499  *
500  * See Windows documentation for more details on IUnknown methods.
501  */
502 ULONG WINAPI OLEFontImpl_AddRef( 
503   IFont* iface)
504 {
505   _ICOM_THIS(OLEFontImpl, iface);
506   TRACE("(%p)->(ref=%ld)\n", this, this->ref);
507   this->ref++;
508
509   return this->ref;
510 }
511         
512 /************************************************************************
513  * OLEFontImpl_Release (IUnknown)
514  *
515  * See Windows documentation for more details on IUnknown methods.
516  */
517 ULONG WINAPI OLEFontImpl_Release( 
518       IFont* iface)
519 {
520   _ICOM_THIS(OLEFontImpl, iface);
521   TRACE("(%p)->(ref=%ld)\n", this, this->ref);
522
523   /*
524    * Decrease the reference count on this object.
525    */
526   this->ref--;
527
528   /*
529    * If the reference count goes down to 0, perform suicide.
530    */
531   if (this->ref==0)
532   {
533     OLEFontImpl_Destroy(this);
534
535     return 0;
536   }
537   
538   return this->ref;
539 }
540         
541 /************************************************************************
542  * OLEFontImpl_get_Name (IFont)
543  *
544  * See Windows documentation for more details on IFont methods.
545  */
546 static HRESULT WINAPI OLEFontImpl_get_Name(
547   IFont*  iface, 
548   BSTR* pname)
549 {
550   _ICOM_THIS(OLEFontImpl, iface);
551   TRACE("(%p)->(%p)\n", this, pname);
552   /*
553    * Sanity check.
554    */
555   if (pname==0)
556     return E_POINTER;
557
558   if (this->description.lpstrName!=0)
559     *pname = SysAllocString(this->description.lpstrName);
560   else
561     *pname = 0;
562
563   return S_OK;
564 }
565
566 /************************************************************************
567  * OLEFontImpl_put_Name (IFont)
568  *
569  * See Windows documentation for more details on IFont methods.
570  */
571 static HRESULT WINAPI OLEFontImpl_put_Name(
572   IFont* iface, 
573   BSTR name)
574 {
575   _ICOM_THIS(OLEFontImpl, iface);
576   TRACE("(%p)->(%p)\n", this, name);
577
578   if (this->description.lpstrName==0)
579   {
580     this->description.lpstrName = HeapAlloc(GetProcessHeap(),
581                                             0, 
582                                             (lstrlenW(name)+1) * sizeof(WCHAR));
583   }
584   else
585   {
586     this->description.lpstrName = HeapReAlloc(GetProcessHeap(),
587                                               0, 
588                                               this->description.lpstrName,
589                                               (lstrlenW(name)+1) * sizeof(WCHAR));
590   }
591
592   if (this->description.lpstrName==0)
593     return E_OUTOFMEMORY;
594
595   strcpyW(this->description.lpstrName, name);
596   TRACE("new name %s\n", debugstr_w(this->description.lpstrName));
597   OLEFont_SendNotify(this, DISPID_FONT_NAME);
598   return S_OK;
599 }
600
601 /************************************************************************
602  * OLEFontImpl_get_Size (IFont)
603  *
604  * See Windows documentation for more details on IFont methods.
605  */
606 static HRESULT WINAPI OLEFontImpl_get_Size(
607   IFont* iface, 
608   CY*    psize)
609 {
610   _ICOM_THIS(OLEFontImpl, iface);
611   TRACE("(%p)->(%p)\n", this, psize);
612
613   /*
614    * Sanity check
615    */
616   if (psize==0)
617     return E_POINTER;
618
619   psize->s.Hi = 0;
620   psize->s.Lo = this->description.cySize.s.Lo;
621
622   return S_OK;
623 }
624
625 /************************************************************************
626  * OLEFontImpl_put_Size (IFont)
627  *
628  * See Windows documentation for more details on IFont methods.
629  */
630 static HRESULT WINAPI OLEFontImpl_put_Size(
631   IFont* iface, 
632   CY     size)
633 {
634   _ICOM_THIS(OLEFontImpl, iface);
635   TRACE("(%p)->(%ld)\n", this, size.s.Lo);
636   this->description.cySize.s.Hi = 0;
637   this->description.cySize.s.Lo = size.s.Lo;
638   OLEFont_SendNotify(this, DISPID_FONT_SIZE);
639
640   return S_OK;
641 }
642
643 /************************************************************************
644  * OLEFontImpl_get_Bold (IFont)
645  *
646  * See Windows documentation for more details on IFont methods.
647  */
648 static HRESULT WINAPI OLEFontImpl_get_Bold(
649   IFont*  iface, 
650   BOOL* pbold)
651 {
652   _ICOM_THIS(OLEFontImpl, iface);
653   TRACE("(%p)->(%p)\n", this, pbold);
654   /*
655    * Sanity check
656    */
657   if (pbold==0)
658     return E_POINTER;
659
660   *pbold = this->description.sWeight > 550;
661
662   return S_OK;
663 }
664
665 /************************************************************************
666  * OLEFontImpl_put_Bold (IFont)
667  *
668  * See Windows documentation for more details on IFont methods.
669  */
670 static HRESULT WINAPI OLEFontImpl_put_Bold(
671   IFont* iface,
672   BOOL bold)
673 {
674   _ICOM_THIS(OLEFontImpl, iface);
675   TRACE("(%p)->(%d)\n", this, bold);
676   this->description.sWeight = bold ? FW_BOLD : FW_NORMAL;
677   OLEFont_SendNotify(this, DISPID_FONT_BOLD);
678
679   return S_OK;
680 }
681
682 /************************************************************************
683  * OLEFontImpl_get_Italic (IFont)
684  *
685  * See Windows documentation for more details on IFont methods.
686  */
687 static HRESULT WINAPI OLEFontImpl_get_Italic(
688   IFont*  iface, 
689   BOOL* pitalic)
690 {
691   _ICOM_THIS(OLEFontImpl, iface);
692   TRACE("(%p)->(%p)\n", this, pitalic);
693   /*
694    * Sanity check
695    */
696   if (pitalic==0)
697     return E_POINTER;
698
699   *pitalic = this->description.fItalic;
700
701   return S_OK;
702 }
703
704 /************************************************************************
705  * OLEFontImpl_put_Italic (IFont)
706  *
707  * See Windows documentation for more details on IFont methods.
708  */
709 static HRESULT WINAPI OLEFontImpl_put_Italic(
710   IFont* iface, 
711   BOOL italic)
712 {
713   _ICOM_THIS(OLEFontImpl, iface);
714   TRACE("(%p)->(%d)\n", this, italic);
715
716   this->description.fItalic = italic;
717
718   OLEFont_SendNotify(this, DISPID_FONT_ITALIC);
719   return S_OK;
720 }
721
722 /************************************************************************
723  * OLEFontImpl_get_Underline (IFont)
724  *
725  * See Windows documentation for more details on IFont methods.
726  */
727 static HRESULT WINAPI OLEFontImpl_get_Underline(
728   IFont*  iface, 
729   BOOL* punderline)
730 {
731   _ICOM_THIS(OLEFontImpl, iface);
732   TRACE("(%p)->(%p)\n", this, punderline);
733
734   /*
735    * Sanity check
736    */
737   if (punderline==0)
738     return E_POINTER;
739
740   *punderline = this->description.fUnderline;
741
742   return S_OK;
743 }
744
745 /************************************************************************
746  * OLEFontImpl_put_Underline (IFont)
747  *
748  * See Windows documentation for more details on IFont methods.
749  */
750 static HRESULT WINAPI OLEFontImpl_put_Underline(
751   IFont* iface,
752   BOOL underline)
753 {
754   _ICOM_THIS(OLEFontImpl, iface);
755   TRACE("(%p)->(%d)\n", this, underline);
756
757   this->description.fUnderline = underline;
758
759   OLEFont_SendNotify(this, DISPID_FONT_UNDER);
760   return S_OK;
761 }
762
763 /************************************************************************
764  * OLEFontImpl_get_Strikethrough (IFont)
765  *
766  * See Windows documentation for more details on IFont methods.
767  */
768 static HRESULT WINAPI OLEFontImpl_get_Strikethrough(
769   IFont*  iface, 
770   BOOL* pstrikethrough)
771 {
772   _ICOM_THIS(OLEFontImpl, iface);
773   TRACE("(%p)->(%p)\n", this, pstrikethrough);
774
775   /*
776    * Sanity check
777    */
778   if (pstrikethrough==0)
779     return E_POINTER;
780
781   *pstrikethrough = this->description.fStrikethrough;
782
783   return S_OK;
784 }
785
786 /************************************************************************
787  * OLEFontImpl_put_Strikethrough (IFont)
788  *
789  * See Windows documentation for more details on IFont methods.
790  */
791 static HRESULT WINAPI OLEFontImpl_put_Strikethrough(
792  IFont* iface, 
793  BOOL strikethrough)
794 {
795   _ICOM_THIS(OLEFontImpl, iface);
796   TRACE("(%p)->(%d)\n", this, strikethrough);
797
798   this->description.fStrikethrough = strikethrough;
799   OLEFont_SendNotify(this, DISPID_FONT_STRIKE);
800
801   return S_OK;
802 }
803
804 /************************************************************************
805  * OLEFontImpl_get_Weight (IFont)
806  *
807  * See Windows documentation for more details on IFont methods.
808  */
809 static HRESULT WINAPI OLEFontImpl_get_Weight(
810   IFont* iface, 
811   short* pweight)
812 {
813   _ICOM_THIS(OLEFontImpl, iface);
814   TRACE("(%p)->(%p)\n", this, pweight);
815
816   /*
817    * Sanity check
818    */
819   if (pweight==0)
820     return E_POINTER;
821
822   *pweight = this->description.sWeight;
823
824   return S_OK;
825 }
826
827 /************************************************************************
828  * OLEFontImpl_put_Weight (IFont)
829  *
830  * See Windows documentation for more details on IFont methods.
831  */
832 static HRESULT WINAPI OLEFontImpl_put_Weight(
833   IFont* iface, 
834   short  weight)
835 {
836   _ICOM_THIS(OLEFontImpl, iface);
837   TRACE("(%p)->(%d)\n", this, weight);
838
839   this->description.sWeight = weight;
840
841   OLEFont_SendNotify(this, DISPID_FONT_WEIGHT);
842   return S_OK;
843 }
844
845 /************************************************************************
846  * OLEFontImpl_get_Charset (IFont)
847  *
848  * See Windows documentation for more details on IFont methods.
849  */
850 static HRESULT WINAPI OLEFontImpl_get_Charset(
851   IFont* iface, 
852   short* pcharset)
853 {
854   _ICOM_THIS(OLEFontImpl, iface);
855   TRACE("(%p)->(%p)\n", this, pcharset);
856
857   /*
858    * Sanity check
859    */
860   if (pcharset==0)
861     return E_POINTER;
862
863   *pcharset = this->description.sCharset;
864
865   return S_OK;
866 }
867
868 /************************************************************************
869  * OLEFontImpl_put_Charset (IFont)
870  *
871  * See Windows documentation for more details on IFont methods.
872  */
873 static HRESULT WINAPI OLEFontImpl_put_Charset(
874   IFont* iface, 
875   short charset)
876 {
877   _ICOM_THIS(OLEFontImpl, iface);
878   TRACE("(%p)->(%d)\n", this, charset);
879
880   this->description.sCharset = charset;
881   OLEFont_SendNotify(this, DISPID_FONT_CHARSET);
882
883   return S_OK;
884 }
885
886 /************************************************************************
887  * OLEFontImpl_get_hFont (IFont)
888  *
889  * See Windows documentation for more details on IFont methods.
890  */
891 static HRESULT WINAPI OLEFontImpl_get_hFont(
892   IFont*   iface,
893   HFONT* phfont)
894 {
895   _ICOM_THIS(OLEFontImpl, iface);
896   TRACE("(%p)->(%p)\n", this, phfont);
897   if (phfont==NULL)
898     return E_POINTER;
899
900   /*
901    * Realize the font if necessary
902  */
903   if (this->gdiFont==0)
904 {
905     LOGFONTW logFont;
906     INT      fontHeight;
907     CY       cySize;
908     
909     /*
910      * The height of the font returned by the get_Size property is the
911      * height of the font in points multiplied by 10000... Using some
912      * simple conversions and the ratio given by the application, it can
913      * be converted to a height in pixels.
914      */
915     IFont_get_Size(iface, &cySize);
916
917     fontHeight = MulDiv(cySize.s.Lo, 2540L, 72L);
918     fontHeight = MulDiv(fontHeight, this->cyLogical,this->cyHimetric);
919
920     memset(&logFont, 0, sizeof(LOGFONTW));
921
922     logFont.lfHeight          = ((fontHeight%10000L)>5000L) ? (-fontHeight/10000L)-1 :
923                                                               (-fontHeight/10000L);
924     logFont.lfItalic          = this->description.fItalic;
925     logFont.lfUnderline       = this->description.fUnderline;
926     logFont.lfStrikeOut       = this->description.fStrikethrough;
927     logFont.lfWeight          = this->description.sWeight;
928     logFont.lfCharSet         = this->description.sCharset;
929     logFont.lfOutPrecision    = OUT_CHARACTER_PRECIS;
930     logFont.lfClipPrecision   = CLIP_DEFAULT_PRECIS;
931     logFont.lfQuality         = DEFAULT_QUALITY;
932     logFont.lfPitchAndFamily  = DEFAULT_PITCH;
933     strcpyW(logFont.lfFaceName,this->description.lpstrName);
934
935     this->gdiFont = CreateFontIndirectW(&logFont);
936   }
937
938   *phfont = this->gdiFont;
939   TRACE("Returning %08x\n", *phfont);
940   return S_OK;
941 }
942
943 /************************************************************************
944  * OLEFontImpl_Clone (IFont)
945  *
946  * See Windows documentation for more details on IFont methods.
947  */
948 static HRESULT WINAPI OLEFontImpl_Clone(
949   IFont*  iface,
950   IFont** ppfont)
951 {
952   OLEFontImpl* newObject = 0;
953   LOGFONTW logFont;
954   INT      fontHeight;
955   CY       cySize;
956   _ICOM_THIS(OLEFontImpl, iface);
957   TRACE("(%p)->(%p)\n", this, ppfont);
958
959   if (ppfont == NULL)
960     return E_POINTER;
961
962   *ppfont = NULL;
963
964   /*
965    * Allocate space for the object.
966    */
967   newObject = HeapAlloc(GetProcessHeap(), 0, sizeof(OLEFontImpl));
968
969   if (newObject==NULL)
970     return E_OUTOFMEMORY;
971
972   *newObject = *this;
973
974   /* We need to alloc new memory for the string, otherwise
975    * we free memory twice.
976    */
977   newObject->description.lpstrName = HeapAlloc(
978         GetProcessHeap(),0,
979         (1+strlenW(this->description.lpstrName))*2
980   );
981   /* We need to clone the HFONT too. This is just cut & paste from above */
982   IFont_get_Size(iface, &cySize);
983
984   fontHeight = MulDiv(cySize.s.Lo, 2540L, 72L);
985   fontHeight = MulDiv(fontHeight, this->cyLogical,this->cyHimetric);
986
987   memset(&logFont, 0, sizeof(LOGFONTW));
988
989   logFont.lfHeight          = ((fontHeight%10000L)>5000L) ? (-fontHeight/10000L)-1 :
990                                                             (-fontHeight/10000L);
991   logFont.lfItalic          = this->description.fItalic;
992   logFont.lfUnderline       = this->description.fUnderline;
993   logFont.lfStrikeOut       = this->description.fStrikethrough;
994   logFont.lfWeight          = this->description.sWeight;
995   logFont.lfCharSet         = this->description.sCharset;
996   logFont.lfOutPrecision    = OUT_CHARACTER_PRECIS;
997   logFont.lfClipPrecision   = CLIP_DEFAULT_PRECIS;
998   logFont.lfQuality         = DEFAULT_QUALITY;
999   logFont.lfPitchAndFamily  = DEFAULT_PITCH;
1000   strcpyW(logFont.lfFaceName,this->description.lpstrName);
1001
1002   newObject->gdiFont = CreateFontIndirectW(&logFont);
1003
1004
1005   /* The cloned object starts with a reference count of 1 */
1006   newObject->ref          = 1;
1007
1008   *ppfont = (IFont*)newObject;
1009
1010   return S_OK;
1011 }
1012
1013 /************************************************************************
1014  * OLEFontImpl_IsEqual (IFont)
1015  *
1016  * See Windows documentation for more details on IFont methods.
1017  */
1018 static HRESULT WINAPI OLEFontImpl_IsEqual(
1019   IFont* iface, 
1020   IFont* pFontOther)
1021 {
1022   FIXME("():Stub\n");
1023   return E_NOTIMPL;
1024 }
1025
1026 /************************************************************************
1027  * OLEFontImpl_SetRatio (IFont)
1028  *
1029  * See Windows documentation for more details on IFont methods.
1030  */
1031 static HRESULT WINAPI OLEFontImpl_SetRatio(
1032   IFont* iface,
1033   long   cyLogical,
1034   long   cyHimetric)
1035 {
1036   _ICOM_THIS(OLEFontImpl, iface);
1037   TRACE("(%p)->(%ld, %ld)\n", this, cyLogical, cyHimetric);
1038
1039   this->cyLogical  = cyLogical;
1040   this->cyHimetric = cyHimetric;
1041
1042   return S_OK;
1043 }
1044
1045 /************************************************************************
1046  * OLEFontImpl_QueryTextMetrics (IFont)
1047  *
1048  * See Windows documentation for more details on IFont methods.
1049  */
1050 static HRESULT      WINAPI OLEFontImpl_QueryTextMetrics(
1051   IFont*         iface, 
1052   TEXTMETRICOLE* ptm)
1053 {
1054   FIXME("():Stub\n");
1055   return E_NOTIMPL;
1056 }
1057
1058 /************************************************************************
1059  * OLEFontImpl_AddRefHfont (IFont)
1060  *
1061  * See Windows documentation for more details on IFont methods.
1062  */
1063 static HRESULT WINAPI OLEFontImpl_AddRefHfont(
1064   IFont*  iface, 
1065   HFONT hfont)
1066 {
1067   _ICOM_THIS(OLEFontImpl, iface);
1068   TRACE("(%p)->(%08x) (lock=%ld)\n", this, hfont, this->fontLock);
1069
1070   if ( (hfont == 0) ||
1071        (hfont != this->gdiFont) )
1072     return E_INVALIDARG;
1073
1074   this->fontLock++;
1075
1076   return S_OK;
1077 }
1078
1079 /************************************************************************
1080  * OLEFontImpl_ReleaseHfont (IFont)
1081  *
1082  * See Windows documentation for more details on IFont methods.
1083  */
1084 static HRESULT WINAPI OLEFontImpl_ReleaseHfont(
1085   IFont*  iface,
1086   HFONT hfont)
1087 {
1088   _ICOM_THIS(OLEFontImpl, iface);
1089   TRACE("(%p)->(%08x) (lock=%ld)\n", this, hfont, this->fontLock);
1090
1091   if ( (hfont == 0) ||
1092        (hfont != this->gdiFont) )
1093     return E_INVALIDARG;
1094
1095   this->fontLock--;
1096
1097   /*
1098    * If we just released our last font reference, destroy it.
1099    */
1100   if (this->fontLock==0)
1101   {
1102     DeleteObject(this->gdiFont);
1103     this->gdiFont = 0; 
1104   }
1105
1106   return S_OK;
1107 }
1108
1109 /************************************************************************
1110  * OLEFontImpl_SetHdc (IFont)
1111  *
1112  * See Windows documentation for more details on IFont methods.
1113  */
1114 static HRESULT WINAPI OLEFontImpl_SetHdc(
1115   IFont* iface,
1116   HDC  hdc)
1117 {
1118   _ICOM_THIS(OLEFontImpl, iface);
1119   FIXME("(%p)->(%08x): Stub\n", this, hdc);
1120   return E_NOTIMPL;
1121 }
1122
1123 /************************************************************************
1124  * OLEFontImpl_IDispatch_QueryInterface (IUnknown)
1125  *
1126  * See Windows documentation for more details on IUnknown methods.
1127  */
1128 static HRESULT WINAPI OLEFontImpl_IDispatch_QueryInterface(
1129   IDispatch* iface,
1130   REFIID     riid,
1131   VOID**     ppvoid)
1132 {
1133   _ICOM_THIS_From_IDispatch(IFont, iface);
1134
1135   return IFont_QueryInterface(this, riid, ppvoid);
1136 }
1137
1138 /************************************************************************
1139  * OLEFontImpl_IDispatch_Release (IUnknown)
1140  *
1141  * See Windows documentation for more details on IUnknown methods.
1142  */
1143 static ULONG WINAPI OLEFontImpl_IDispatch_Release(
1144   IDispatch* iface)
1145 {
1146   _ICOM_THIS_From_IDispatch(IFont, iface);
1147
1148   return IFont_Release(this);
1149 }
1150
1151 /************************************************************************
1152  * OLEFontImpl_IDispatch_AddRef (IUnknown)
1153  *
1154  * See Windows documentation for more details on IUnknown methods.
1155  */
1156 static ULONG WINAPI OLEFontImpl_IDispatch_AddRef(
1157   IDispatch* iface)
1158 {
1159   _ICOM_THIS_From_IDispatch(IFont, iface);
1160
1161   return IFont_AddRef(this);
1162 }
1163
1164 /************************************************************************
1165  * OLEFontImpl_GetTypeInfoCount (IDispatch)
1166  *
1167  * See Windows documentation for more details on IDispatch methods.
1168  */
1169 static HRESULT WINAPI OLEFontImpl_GetTypeInfoCount(
1170   IDispatch*    iface, 
1171   unsigned int* pctinfo)
1172 {
1173   _ICOM_THIS_From_IDispatch(IFont, iface);
1174   FIXME("(%p)->(%p): Stub\n", this, pctinfo);
1175
1176   return E_NOTIMPL;
1177 }
1178
1179 /************************************************************************
1180  * OLEFontImpl_GetTypeInfo (IDispatch)
1181  *
1182  * See Windows documentation for more details on IDispatch methods.
1183  */
1184 static HRESULT WINAPI OLEFontImpl_GetTypeInfo(
1185   IDispatch*  iface, 
1186   UINT      iTInfo,
1187   LCID        lcid, 
1188   ITypeInfo** ppTInfo)
1189 {
1190   _ICOM_THIS_From_IDispatch(IFont, iface);
1191   FIXME("(%p):Stub\n", this);
1192
1193   return E_NOTIMPL;
1194 }
1195
1196 /************************************************************************
1197  * OLEFontImpl_GetIDsOfNames (IDispatch)
1198  *
1199  * See Windows documentation for more details on IDispatch methods.
1200  */
1201 static HRESULT WINAPI OLEFontImpl_GetIDsOfNames(
1202   IDispatch*  iface,
1203   REFIID      riid, 
1204   LPOLESTR* rgszNames, 
1205   UINT      cNames, 
1206   LCID        lcid,
1207   DISPID*     rgDispId)
1208 {
1209   _ICOM_THIS_From_IDispatch(IFont, iface);
1210   FIXME("(%p):Stub\n", this);
1211
1212   return E_NOTIMPL;
1213 }
1214
1215 /************************************************************************
1216  * OLEFontImpl_Invoke (IDispatch)
1217  *
1218  * See Windows documentation for more details on IDispatch methods.
1219  */
1220 static HRESULT WINAPI OLEFontImpl_Invoke(
1221   IDispatch*  iface,
1222   DISPID      dispIdMember, 
1223   REFIID      riid, 
1224   LCID        lcid, 
1225   WORD        wFlags,
1226   DISPPARAMS* pDispParams,
1227   VARIANT*    pVarResult, 
1228   EXCEPINFO*  pExepInfo,
1229   UINT*     puArgErr)
1230 {
1231   _ICOM_THIS_From_IDispatch(IFont, iface);
1232   FIXME("%p->(%ld,%s,%lx,%x), stub!\n", this,dispIdMember,debugstr_guid(riid),lcid,
1233     wFlags
1234   );
1235   return S_OK;
1236 }
1237
1238 /************************************************************************
1239  * OLEFontImpl_IPersistStream_QueryInterface (IUnknown)
1240  *
1241  * See Windows documentation for more details on IUnknown methods.
1242  */
1243 static HRESULT WINAPI OLEFontImpl_IPersistStream_QueryInterface(
1244   IPersistStream* iface,
1245   REFIID     riid,
1246   VOID**     ppvoid)
1247 {
1248   _ICOM_THIS_From_IPersistStream(IFont, iface);
1249
1250   return IFont_QueryInterface(this, riid, ppvoid);
1251 }
1252
1253 /************************************************************************
1254  * OLEFontImpl_IPersistStream_Release (IUnknown)
1255  *
1256  * See Windows documentation for more details on IUnknown methods.
1257  */
1258 static ULONG WINAPI OLEFontImpl_IPersistStream_Release(
1259   IPersistStream* iface)
1260 {
1261   _ICOM_THIS_From_IPersistStream(IFont, iface);
1262
1263   return IFont_Release(this);
1264 }
1265
1266 /************************************************************************
1267  * OLEFontImpl_IPersistStream_AddRef (IUnknown)
1268  *
1269  * See Windows documentation for more details on IUnknown methods.
1270  */
1271 static ULONG WINAPI OLEFontImpl_IPersistStream_AddRef(
1272   IPersistStream* iface)
1273 {
1274   _ICOM_THIS_From_IPersistStream(IFont, iface);
1275
1276   return IFont_AddRef(this);
1277 }
1278
1279 /************************************************************************
1280  * OLEFontImpl_GetClassID (IPersistStream)
1281  *
1282  * See Windows documentation for more details on IPersistStream methods.
1283  */
1284 static HRESULT WINAPI OLEFontImpl_GetClassID(
1285   IPersistStream* iface, 
1286   CLSID*                pClassID)
1287 {
1288   if (pClassID==0)
1289     return E_POINTER;
1290
1291   memcpy(pClassID, &CLSID_StdFont, sizeof(CLSID_StdFont));
1292
1293   return S_OK;
1294 }
1295
1296 /************************************************************************
1297  * OLEFontImpl_IsDirty (IPersistStream)
1298  *
1299  * See Windows documentation for more details on IPersistStream methods.
1300  */
1301 static HRESULT WINAPI OLEFontImpl_IsDirty(
1302   IPersistStream*  iface)
1303 {
1304   return S_OK;
1305 }
1306
1307 /************************************************************************
1308  * OLEFontImpl_Load (IPersistStream)
1309  *
1310  * See Windows documentation for more details on IPersistStream methods.
1311  *
1312  * This is the format of the standard font serialization as far as I
1313  * know
1314  *
1315  * Offset   Type   Value           Comment
1316  * 0x0000   Byte   Unknown         Probably a version number, contains 0x01
1317  * 0x0001   Short  Charset         Charset value from the FONTDESC structure
1318  * 0x0003   Byte   Attributes      Flags defined as follows:
1319  *                                     00000010 - Italic
1320  *                                     00000100 - Underline
1321  *                                     00001000 - Strikethrough
1322  * 0x0004   Short  Weight          Weight value from FONTDESC structure
1323  * 0x0006   DWORD  size            "Low" portion of the cySize member of the FONTDESC
1324  *                                 structure/
1325  * 0x000A   Byte   name length     Length of the font name string (no null character)
1326  * 0x000B   String name            Name of the font (ASCII, no nul character)
1327  */
1328 static HRESULT WINAPI OLEFontImpl_Load(
1329   IPersistStream*  iface,
1330   IStream*         pLoadStream)
1331 {
1332   char  readBuffer[0x100];
1333   ULONG cbRead;
1334   BYTE  bVersion;
1335   BYTE  bAttributes;
1336   BYTE  bStringSize;
1337   INT len;
1338
1339   _ICOM_THIS_From_IPersistStream(OLEFontImpl, iface);
1340   
1341   /*
1342    * Read the version byte
1343    */
1344   IStream_Read(pLoadStream, &bVersion, 1, &cbRead);
1345
1346   if ( (cbRead!=1) ||
1347        (bVersion!=0x01) )
1348     return E_FAIL;
1349
1350   /*
1351    * Charset
1352    */
1353   IStream_Read(pLoadStream, &this->description.sCharset, 2, &cbRead);
1354
1355   if (cbRead!=2)
1356     return E_FAIL;
1357
1358   /*
1359    * Attributes
1360    */
1361   IStream_Read(pLoadStream, &bAttributes, 1, &cbRead);
1362
1363   if (cbRead!=1)
1364     return E_FAIL;
1365
1366   this->description.fItalic        = (bAttributes & FONTPERSIST_ITALIC) != 0;
1367   this->description.fStrikethrough = (bAttributes & FONTPERSIST_STRIKETHROUGH) != 0;
1368   this->description.fUnderline     = (bAttributes & FONTPERSIST_UNDERLINE) != 0;
1369     
1370   /*
1371    * Weight
1372    */
1373   IStream_Read(pLoadStream, &this->description.sWeight, 2, &cbRead);
1374
1375   if (cbRead!=2)
1376     return E_FAIL;
1377
1378   /*
1379    * Size
1380    */
1381   IStream_Read(pLoadStream, &this->description.cySize.s.Lo, 4, &cbRead);
1382
1383   if (cbRead!=4)
1384     return E_FAIL;
1385
1386   this->description.cySize.s.Hi = 0;
1387
1388   /*
1389    * FontName
1390    */
1391   IStream_Read(pLoadStream, &bStringSize, 1, &cbRead);
1392
1393   if (cbRead!=1)
1394     return E_FAIL;
1395
1396   IStream_Read(pLoadStream, readBuffer, bStringSize, &cbRead);
1397
1398   if (cbRead!=bStringSize)
1399     return E_FAIL;
1400
1401   if (this->description.lpstrName!=0)
1402     HeapFree(GetProcessHeap(), 0, this->description.lpstrName);
1403
1404   len = MultiByteToWideChar( CP_ACP, 0, readBuffer, bStringSize, NULL, 0 );
1405   this->description.lpstrName = HeapAlloc( GetProcessHeap(), 0, (len+1) * sizeof(WCHAR) );
1406   MultiByteToWideChar( CP_ACP, 0, readBuffer, bStringSize, this->description.lpstrName, len );
1407   this->description.lpstrName[len] = 0;
1408
1409   return S_OK;
1410 }
1411
1412 /************************************************************************
1413  * OLEFontImpl_Save (IPersistStream)
1414  *
1415  * See Windows documentation for more details on IPersistStream methods.
1416  */
1417 static HRESULT WINAPI OLEFontImpl_Save(
1418   IPersistStream*  iface,
1419   IStream*         pOutStream,
1420   BOOL             fClearDirty)
1421 {
1422   char* writeBuffer = NULL;
1423   ULONG cbWritten;
1424   BYTE  bVersion = 0x01;
1425   BYTE  bAttributes;
1426   BYTE  bStringSize;
1427   
1428   _ICOM_THIS_From_IPersistStream(OLEFontImpl, iface);
1429
1430   /*
1431    * Read the version byte
1432    */
1433   IStream_Write(pOutStream, &bVersion, 1, &cbWritten);
1434
1435   if (cbWritten!=1)
1436     return E_FAIL;
1437
1438   /*
1439    * Charset
1440    */
1441   IStream_Write(pOutStream, &this->description.sCharset, 2, &cbWritten);
1442
1443   if (cbWritten!=2)
1444     return E_FAIL;
1445
1446   /*
1447    * Attributes
1448    */
1449   bAttributes = 0;
1450
1451   if (this->description.fItalic)
1452     bAttributes |= FONTPERSIST_ITALIC;
1453
1454   if (this->description.fStrikethrough)
1455     bAttributes |= FONTPERSIST_STRIKETHROUGH;
1456   
1457   if (this->description.fUnderline)
1458     bAttributes |= FONTPERSIST_UNDERLINE;
1459
1460   IStream_Write(pOutStream, &bAttributes, 1, &cbWritten);
1461
1462   if (cbWritten!=1)
1463     return E_FAIL;
1464   
1465   /*
1466    * Weight
1467    */
1468   IStream_Write(pOutStream, &this->description.sWeight, 2, &cbWritten);
1469
1470   if (cbWritten!=2)
1471     return E_FAIL;
1472
1473   /*
1474    * Size
1475    */
1476   IStream_Write(pOutStream, &this->description.cySize.s.Lo, 4, &cbWritten);
1477
1478   if (cbWritten!=4)
1479     return E_FAIL;
1480
1481   /*
1482    * FontName
1483    */
1484   if (this->description.lpstrName!=0)
1485     bStringSize = WideCharToMultiByte( CP_ACP, 0, this->description.lpstrName,
1486                                        strlenW(this->description.lpstrName), NULL, 0, NULL, NULL );
1487   else
1488     bStringSize = 0;
1489
1490   IStream_Write(pOutStream, &bStringSize, 1, &cbWritten);
1491
1492   if (cbWritten!=1)
1493     return E_FAIL;
1494
1495   if (bStringSize!=0)
1496   {
1497       if (!(writeBuffer = HeapAlloc( GetProcessHeap(), 0, bStringSize ))) return E_OUTOFMEMORY;
1498       WideCharToMultiByte( CP_ACP, 0, this->description.lpstrName,
1499                            strlenW(this->description.lpstrName),
1500                            writeBuffer, bStringSize, NULL, NULL );
1501
1502     IStream_Write(pOutStream, writeBuffer, bStringSize, &cbWritten);
1503     HeapFree(GetProcessHeap(), 0, writeBuffer);
1504
1505     if (cbWritten!=bStringSize)
1506       return E_FAIL;
1507   }
1508
1509   return S_OK;
1510 }
1511
1512 /************************************************************************
1513  * OLEFontImpl_GetSizeMax (IPersistStream)
1514  *
1515  * See Windows documentation for more details on IPersistStream methods.
1516  */
1517 static HRESULT WINAPI OLEFontImpl_GetSizeMax(
1518   IPersistStream*  iface,
1519   ULARGE_INTEGER*  pcbSize)
1520 {
1521   _ICOM_THIS_From_IPersistStream(OLEFontImpl, iface);
1522
1523   if (pcbSize==NULL)
1524     return E_POINTER;
1525
1526   pcbSize->s.HighPart = 0;
1527   pcbSize->s.LowPart = 0;
1528
1529   pcbSize->s.LowPart += sizeof(BYTE);  /* Version */
1530   pcbSize->s.LowPart += sizeof(WORD);  /* Lang code */
1531   pcbSize->s.LowPart += sizeof(BYTE);  /* Flags */
1532   pcbSize->s.LowPart += sizeof(WORD);  /* Weight */
1533   pcbSize->s.LowPart += sizeof(DWORD); /* Size */
1534   pcbSize->s.LowPart += sizeof(BYTE);  /* StrLength */
1535
1536   if (this->description.lpstrName!=0)
1537     pcbSize->s.LowPart += lstrlenW(this->description.lpstrName);
1538
1539   return S_OK;
1540 }
1541
1542 /************************************************************************
1543  * OLEFontImpl_IConnectionPointContainer_QueryInterface (IUnknown)
1544  *
1545  * See Windows documentation for more details on IUnknown methods.
1546  */
1547 static HRESULT WINAPI OLEFontImpl_IConnectionPointContainer_QueryInterface(
1548   IConnectionPointContainer* iface,
1549   REFIID     riid,
1550   VOID**     ppvoid)
1551 {
1552   _ICOM_THIS_From_IConnectionPointContainer(OLEFontImpl, iface);
1553
1554   return IFont_QueryInterface((IFont*)this, riid, ppvoid);
1555 }
1556
1557 /************************************************************************
1558  * OLEFontImpl_IConnectionPointContainer_Release (IUnknown)
1559  *
1560  * See Windows documentation for more details on IUnknown methods.
1561  */
1562 static ULONG WINAPI OLEFontImpl_IConnectionPointContainer_Release(
1563   IConnectionPointContainer* iface)
1564 {
1565   _ICOM_THIS_From_IConnectionPointContainer(OLEFontImpl, iface);
1566
1567   return IFont_Release((IFont*)this);
1568 }
1569
1570 /************************************************************************
1571  * OLEFontImpl_IConnectionPointContainer_AddRef (IUnknown)
1572  *
1573  * See Windows documentation for more details on IUnknown methods.
1574  */
1575 static ULONG WINAPI OLEFontImpl_IConnectionPointContainer_AddRef(
1576   IConnectionPointContainer* iface)
1577 {
1578   _ICOM_THIS_From_IConnectionPointContainer(OLEFontImpl, iface);
1579
1580   return IFont_AddRef((IFont*)this);
1581 }
1582
1583 /************************************************************************
1584  * OLEFontImpl_EnumConnectionPoints (IConnectionPointContainer)
1585  *
1586  * See Windows documentation for more details on IConnectionPointContainer
1587  * methods.
1588  */
1589 static HRESULT WINAPI OLEFontImpl_EnumConnectionPoints(
1590   IConnectionPointContainer* iface,
1591   IEnumConnectionPoints **ppEnum)
1592 {
1593   _ICOM_THIS_From_IConnectionPointContainer(OLEFontImpl, iface);
1594
1595   FIXME("(%p)->(%p): stub\n", this, ppEnum);
1596   return E_NOTIMPL;
1597 }
1598
1599 /************************************************************************
1600  * OLEFontImpl_FindConnectionPoint (IConnectionPointContainer)
1601  *
1602  * See Windows documentation for more details on IConnectionPointContainer
1603  * methods.
1604  */
1605 static HRESULT WINAPI OLEFontImpl_FindConnectionPoint(
1606    IConnectionPointContainer* iface,
1607    REFIID riid,
1608    IConnectionPoint **ppCp)
1609 {
1610   _ICOM_THIS_From_IConnectionPointContainer(OLEFontImpl, iface);
1611   TRACE("(%p)->(%s, %p): stub\n", this, debugstr_guid(riid), ppCp);
1612
1613   if(memcmp(riid, &IID_IPropertyNotifySink, sizeof(IID_IPropertyNotifySink)) == 0) {
1614     return IConnectionPoint_QueryInterface(this->pCP, &IID_IConnectionPoint,
1615                                            (LPVOID)ppCp);
1616   } else {
1617     FIXME("Tried to find connection point on %s\n", debugstr_guid(riid));
1618     return E_NOINTERFACE;
1619   }
1620 }
1621
1622 /*******************************************************************************
1623  * StdFont ClassFactory
1624  */
1625 typedef struct
1626 {
1627     /* IUnknown fields */
1628     ICOM_VFIELD(IClassFactory);
1629     DWORD                       ref;
1630 } IClassFactoryImpl;
1631
1632 static HRESULT WINAPI 
1633 SFCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
1634         ICOM_THIS(IClassFactoryImpl,iface);
1635
1636         FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
1637         return E_NOINTERFACE;
1638 }
1639
1640 static ULONG WINAPI
1641 SFCF_AddRef(LPCLASSFACTORY iface) {
1642         ICOM_THIS(IClassFactoryImpl,iface);
1643         return ++(This->ref);
1644 }
1645
1646 static ULONG WINAPI SFCF_Release(LPCLASSFACTORY iface) {
1647         ICOM_THIS(IClassFactoryImpl,iface);
1648         /* static class, won't be  freed */
1649         return --(This->ref);
1650 }
1651
1652 static HRESULT WINAPI SFCF_CreateInstance(
1653         LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
1654 ) {
1655         ICOM_THIS(IClassFactoryImpl,iface);
1656
1657         if (IsEqualGUID(riid,&IID_IFont)) {
1658             FONTDESC fd;
1659
1660             WCHAR fname[] = { 'S','y','s','t','e','m',0 };
1661
1662             fd.cbSizeofstruct = sizeof(fd);
1663             fd.lpstrName      = fname;
1664             fd.cySize.s.Lo    = 80000;
1665             fd.cySize.s.Hi    = 0;
1666             fd.sWeight        = 0;
1667             fd.sCharset       = 0;
1668             fd.fItalic        = 0;
1669             fd.fUnderline     = 0;
1670             fd.fStrikethrough = 0;
1671             return OleCreateFontIndirect(&fd,riid,ppobj);
1672         }
1673
1674         FIXME("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
1675         return E_NOINTERFACE;
1676 }
1677
1678 static HRESULT WINAPI SFCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
1679         ICOM_THIS(IClassFactoryImpl,iface);
1680         FIXME("(%p)->(%d),stub!\n",This,dolock);
1681         return S_OK;
1682 }
1683
1684 static ICOM_VTABLE(IClassFactory) SFCF_Vtbl = {
1685         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1686         SFCF_QueryInterface,
1687         SFCF_AddRef,
1688         SFCF_Release,
1689         SFCF_CreateInstance,
1690         SFCF_LockServer
1691 };
1692 static IClassFactoryImpl STDFONT_CF = {&SFCF_Vtbl, 1 };
1693
1694 void _get_STDFONT_CF(LPVOID *ppv) { *ppv = (LPVOID)&STDFONT_CF; }