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