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