ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

olefont.c
Go to the documentation of this file.
00001 /*
00002  * OLE Font encapsulation implementation
00003  *
00004  * This file contains an implementation of the IFont
00005  * interface and the OleCreateFontIndirect API call.
00006  *
00007  * Copyright 1999 Francis Beaudet
00008  * Copyright 2006 (Google) Benjamin Arai
00009  *
00010  * This library is free software; you can redistribute it and/or
00011  * modify it under the terms of the GNU Lesser General Public
00012  * License as published by the Free Software Foundation; either
00013  * version 2.1 of the License, or (at your option) any later version.
00014  *
00015  * This library is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018  * Lesser General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU Lesser General Public
00021  * License along with this library; if not, write to the Free Software
00022  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00023  */
00024 #include <assert.h>
00025 #include <stdarg.h>
00026 #include <string.h>
00027 
00028 #define COBJMACROS
00029 #define NONAMELESSUNION
00030 #define NONAMELESSSTRUCT
00031 
00032 #include "winerror.h"
00033 #include "windef.h"
00034 #include "winbase.h"
00035 #include "wingdi.h"
00036 #include "winuser.h"
00037 #include "wine/list.h"
00038 #include "wine/unicode.h"
00039 #include "objbase.h"
00040 #include "oleauto.h"    /* for SysAllocString(....) */
00041 #include "ole2.h"
00042 #include "olectl.h"
00043 #include "wine/debug.h"
00044 #include "connpt.h" /* for CreateConnectionPoint */
00045 #include "oaidl.h"
00046 
00047 WINE_DEFAULT_DEBUG_CHANNEL(ole);
00048 
00049 /***********************************************************************
00050  * Declaration of constants used when serializing the font object.
00051  */
00052 #define FONTPERSIST_ITALIC        0x02
00053 #define FONTPERSIST_UNDERLINE     0x04
00054 #define FONTPERSIST_STRIKETHROUGH 0x08
00055 
00056 static HDC olefont_hdc;
00057 
00058 /***********************************************************************
00059  * List of the HFONTs it has given out, with each one having a separate
00060  * ref count.
00061  */
00062 typedef struct _HFONTItem
00063 {
00064   struct list entry;
00065 
00066   /* Reference count of any IFont objects that own this hfont */
00067   LONG int_refs;
00068 
00069   /* Total reference count of any refs held by the application obtained by AddRefHfont plus any internal refs */
00070   LONG total_refs;
00071 
00072   /* The font associated with this object. */
00073   HFONT gdiFont;
00074 
00075 } HFONTItem, *PHFONTItem;
00076 
00077 static struct list OLEFontImpl_hFontList = LIST_INIT(OLEFontImpl_hFontList);
00078 
00079 /* Counts how many fonts contain at least one lock */
00080 static LONG ifont_cnt = 0;
00081 
00082 /***********************************************************************
00083  * Critical section for OLEFontImpl_hFontList
00084  */
00085 static CRITICAL_SECTION OLEFontImpl_csHFONTLIST;
00086 static CRITICAL_SECTION_DEBUG OLEFontImpl_csHFONTLIST_debug =
00087 {
00088   0, 0, &OLEFontImpl_csHFONTLIST,
00089   { &OLEFontImpl_csHFONTLIST_debug.ProcessLocksList,
00090     &OLEFontImpl_csHFONTLIST_debug.ProcessLocksList },
00091     0, 0, { (DWORD_PTR)(__FILE__ ": OLEFontImpl_csHFONTLIST") }
00092 };
00093 static CRITICAL_SECTION OLEFontImpl_csHFONTLIST = { &OLEFontImpl_csHFONTLIST_debug, -1, 0, 0, 0, 0 };
00094 
00095 static HDC get_dc(void)
00096 {
00097     HDC hdc;
00098     EnterCriticalSection(&OLEFontImpl_csHFONTLIST);
00099     if(!olefont_hdc)
00100         olefont_hdc = CreateCompatibleDC(NULL);
00101     hdc = olefont_hdc;
00102     LeaveCriticalSection(&OLEFontImpl_csHFONTLIST);
00103     return hdc;
00104 }
00105 
00106 static void delete_dc(void)
00107 {
00108     EnterCriticalSection(&OLEFontImpl_csHFONTLIST);
00109     if(olefont_hdc)
00110     {
00111         DeleteDC(olefont_hdc);
00112         olefont_hdc = NULL;
00113     }
00114     LeaveCriticalSection(&OLEFontImpl_csHFONTLIST);
00115 }
00116 
00117 static void HFONTItem_Delete(PHFONTItem item)
00118 {
00119   DeleteObject(item->gdiFont);
00120   list_remove(&item->entry);
00121   HeapFree(GetProcessHeap(), 0, item);
00122 }
00123 
00124 /* Find hfont item entry in the list.  Should be called while holding the crit sect */
00125 static HFONTItem *find_hfontitem(HFONT hfont)
00126 {
00127     HFONTItem *item;
00128 
00129     LIST_FOR_EACH_ENTRY(item, &OLEFontImpl_hFontList, HFONTItem, entry)
00130     {
00131         if (item->gdiFont == hfont)
00132             return item;
00133     }
00134     return NULL;
00135 }
00136 
00137 /* Add an item to the list with one internal reference */
00138 static HRESULT add_hfontitem(HFONT hfont)
00139 {
00140     HFONTItem *new_item = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_item));
00141 
00142     if(!new_item) return E_OUTOFMEMORY;
00143 
00144     new_item->int_refs = 1;
00145     new_item->total_refs = 1;
00146     new_item->gdiFont = hfont;
00147     EnterCriticalSection(&OLEFontImpl_csHFONTLIST);
00148     list_add_tail(&OLEFontImpl_hFontList,&new_item->entry);
00149     LeaveCriticalSection(&OLEFontImpl_csHFONTLIST);
00150     return S_OK;
00151 }
00152 
00153 static HRESULT inc_int_ref(HFONT hfont)
00154 {
00155     HFONTItem *item;
00156     HRESULT hr = S_FALSE;
00157 
00158     EnterCriticalSection(&OLEFontImpl_csHFONTLIST);
00159     item = find_hfontitem(hfont);
00160 
00161     if(item)
00162     {
00163         item->int_refs++;
00164         item->total_refs++;
00165         hr = S_OK;
00166     }
00167     LeaveCriticalSection(&OLEFontImpl_csHFONTLIST);
00168 
00169     return hr;
00170 }
00171 
00172 /* decrements the internal ref of a hfont item.  If both refs are zero it'll
00173    remove the item from the list and delete the hfont */
00174 static HRESULT dec_int_ref(HFONT hfont)
00175 {
00176     HFONTItem *item;
00177     HRESULT hr = S_FALSE;
00178 
00179     EnterCriticalSection(&OLEFontImpl_csHFONTLIST);
00180     item = find_hfontitem(hfont);
00181 
00182     if(item)
00183     {
00184         item->int_refs--;
00185         item->total_refs--;
00186         if(item->int_refs == 0 && item->total_refs == 0)
00187             HFONTItem_Delete(item);
00188         hr = S_OK;
00189     }
00190     LeaveCriticalSection(&OLEFontImpl_csHFONTLIST);
00191 
00192     return hr;
00193 }
00194 
00195 static HRESULT inc_ext_ref(HFONT hfont)
00196 {
00197     HFONTItem *item;
00198     HRESULT hr = S_FALSE;
00199 
00200     EnterCriticalSection(&OLEFontImpl_csHFONTLIST);
00201 
00202     item = find_hfontitem(hfont);
00203     if(item)
00204     {
00205         item->total_refs++;
00206         hr = S_OK;
00207     }
00208     LeaveCriticalSection(&OLEFontImpl_csHFONTLIST);
00209 
00210     return hr;
00211 }
00212 
00213 static HRESULT dec_ext_ref(HFONT hfont)
00214 {
00215     HFONTItem *item;
00216     HRESULT hr = S_FALSE;
00217 
00218     EnterCriticalSection(&OLEFontImpl_csHFONTLIST);
00219 
00220     item = find_hfontitem(hfont);
00221     if(item)
00222     {
00223         if(--item->total_refs >= 0) hr = S_OK;
00224     }
00225     LeaveCriticalSection(&OLEFontImpl_csHFONTLIST);
00226 
00227     return hr;
00228 }
00229 
00230 static WCHAR *strdupW(const WCHAR* str)
00231 {
00232     WCHAR *ret;
00233     DWORD size = (strlenW(str) + 1) * sizeof(WCHAR);
00234 
00235     ret = HeapAlloc(GetProcessHeap(), 0, size);
00236     if(ret)
00237         memcpy(ret, str, size);
00238     return ret;
00239 }
00240 
00241 /***********************************************************************
00242  * Declaration of the implementation class for the IFont interface
00243  */
00244 typedef struct OLEFontImpl OLEFontImpl;
00245 
00246 struct OLEFontImpl
00247 {
00248   /*
00249    * This class supports many interfaces. IUnknown, IFont,
00250    * IDispatch, IDispFont IPersistStream and IConnectionPointContainer.
00251    * The first two are supported by the first vtable, the next two are
00252    * supported by the second table and the last two have their own.
00253    */
00254   const IFontVtbl*                     lpVtbl;
00255   const IDispatchVtbl*                 lpvtblIDispatch;
00256   const IPersistStreamVtbl*            lpvtblIPersistStream;
00257   const IConnectionPointContainerVtbl* lpvtblIConnectionPointContainer;
00258   const IPersistPropertyBagVtbl*       lpvtblIPersistPropertyBag;
00259   const IPersistStreamInitVtbl*        lpvtblIPersistStreamInit;
00260   /*
00261    * Reference count for that instance of the class.
00262    */
00263   LONG ref;
00264 
00265   /*
00266    * This structure contains the description of the class.
00267    */
00268   FONTDESC description;
00269 
00270   /*
00271    * Contain the font associated with this object.
00272    */
00273   HFONT gdiFont;
00274   BOOL dirty;
00275   /*
00276    * Size ratio
00277    */
00278   LONG cyLogical;
00279   LONG cyHimetric;
00280 
00281   IConnectionPoint *pPropertyNotifyCP;
00282   IConnectionPoint *pFontEventsCP;
00283 };
00284 
00285 /*
00286  * Here, I define utility macros to help with the casting of the
00287  * "this" parameter.
00288  * There is a version to accommodate all of the VTables implemented
00289  * by this object.
00290  */
00291 
00292 static inline OLEFontImpl *impl_from_IDispatch( IDispatch *iface )
00293 {
00294     return (OLEFontImpl *)((char*)iface - FIELD_OFFSET(OLEFontImpl, lpvtblIDispatch));
00295 }
00296 
00297 static inline OLEFontImpl *impl_from_IPersistStream( IPersistStream *iface )
00298 {
00299     return (OLEFontImpl *)((char*)iface - FIELD_OFFSET(OLEFontImpl, lpvtblIPersistStream));
00300 }
00301 
00302 static inline OLEFontImpl *impl_from_IConnectionPointContainer( IConnectionPointContainer *iface )
00303 {
00304     return (OLEFontImpl *)((char*)iface - FIELD_OFFSET(OLEFontImpl, lpvtblIConnectionPointContainer));
00305 }
00306 
00307 static inline OLEFontImpl *impl_from_IPersistPropertyBag( IPersistPropertyBag *iface )
00308 {
00309     return (OLEFontImpl *)((char*)iface - FIELD_OFFSET(OLEFontImpl, lpvtblIPersistPropertyBag));
00310 }
00311 
00312 static inline OLEFontImpl *impl_from_IPersistStreamInit( IPersistStreamInit *iface )
00313 {
00314     return (OLEFontImpl *)((char*)iface - FIELD_OFFSET(OLEFontImpl, lpvtblIPersistStreamInit));
00315 }
00316 
00317 
00318 /***********************************************************************
00319  * Prototypes for the implementation functions for the IFont
00320  * interface
00321  */
00322 static OLEFontImpl* OLEFontImpl_Construct(const FONTDESC *fontDesc);
00323 static void         OLEFontImpl_Destroy(OLEFontImpl* fontDesc);
00324 static ULONG        WINAPI OLEFontImpl_AddRef(IFont* iface);
00325 
00326 /******************************************************************************
00327  *      OleCreateFontIndirect   [OLEAUT32.420]
00328  */
00329 HRESULT WINAPI OleCreateFontIndirect(
00330   LPFONTDESC lpFontDesc,
00331   REFIID     riid,
00332   LPVOID*     ppvObj)
00333 {
00334   OLEFontImpl* newFont = 0;
00335   HRESULT      hr      = S_OK;
00336 
00337   TRACE("(%p, %s, %p)\n", lpFontDesc, debugstr_guid(riid), ppvObj);
00338   /*
00339    * Sanity check
00340    */
00341   if (ppvObj==0)
00342     return E_POINTER;
00343 
00344   *ppvObj = 0;
00345 
00346   if (!lpFontDesc) {
00347     FONTDESC fd;
00348 
00349     static WCHAR fname[] = { 'S','y','s','t','e','m',0 };
00350 
00351     fd.cbSizeofstruct = sizeof(fd);
00352     fd.lpstrName      = fname;
00353     fd.cySize.s.Lo    = 80000;
00354     fd.cySize.s.Hi    = 0;
00355     fd.sWeight        = 0;
00356     fd.sCharset       = 0;
00357     fd.fItalic        = 0;
00358     fd.fUnderline     = 0;
00359     fd.fStrikethrough = 0;
00360     lpFontDesc = &fd;
00361   }
00362 
00363   /*
00364    * Try to construct a new instance of the class.
00365    */
00366   newFont = OLEFontImpl_Construct(lpFontDesc);
00367 
00368   if (newFont == 0)
00369     return E_OUTOFMEMORY;
00370 
00371   /*
00372    * Make sure it supports the interface required by the caller.
00373    */
00374   hr = IFont_QueryInterface((IFont*)newFont, riid, ppvObj);
00375 
00376   /*
00377    * Release the reference obtained in the constructor. If
00378    * the QueryInterface was unsuccessful, it will free the class.
00379    */
00380   IFont_Release((IFont*)newFont);
00381 
00382   return hr;
00383 }
00384 
00385 
00386 /***********************************************************************
00387  * Implementation of the OLEFontImpl class.
00388  */
00389 
00390 /***********************************************************************
00391  *    OLEFont_SendNotify (internal)
00392  *
00393  * Sends notification messages of changed properties to any interested
00394  * connections.
00395  */
00396 static void OLEFont_SendNotify(OLEFontImpl* this, DISPID dispID)
00397 {
00398   static const WCHAR wszName[] = {'N','a','m','e',0};
00399   static const WCHAR wszSize[] = {'S','i','z','e',0};
00400   static const WCHAR wszBold[] = {'B','o','l','d',0};
00401   static const WCHAR wszItalic[] = {'I','t','a','l','i','c',0};
00402   static const WCHAR wszUnder[] = {'U','n','d','e','r','l','i','n','e',0};
00403   static const WCHAR wszStrike[] = {'S','t','r','i','k','e','t','h','r','o','u','g','h',0};
00404   static const WCHAR wszWeight[] = {'W','e','i','g','h','t',0};
00405   static const WCHAR wszCharset[] = {'C','h','a','r','s','s','e','t',0};
00406   static const LPCWSTR dispid_mapping[] =
00407   {
00408     wszName,
00409     NULL,
00410     wszSize,
00411     wszBold,
00412     wszItalic,
00413     wszUnder,
00414     wszStrike,
00415     wszWeight,
00416     wszCharset
00417   };
00418 
00419   IEnumConnections *pEnum;
00420   CONNECTDATA CD;
00421   HRESULT hres;
00422 
00423   this->dirty = TRUE;
00424 
00425   hres = IConnectionPoint_EnumConnections(this->pPropertyNotifyCP, &pEnum);
00426   if (SUCCEEDED(hres))
00427   {
00428     while(IEnumConnections_Next(pEnum, 1, &CD, NULL) == S_OK) {
00429       IPropertyNotifySink *sink;
00430 
00431       IUnknown_QueryInterface(CD.pUnk, &IID_IPropertyNotifySink, (LPVOID)&sink);
00432       IPropertyNotifySink_OnChanged(sink, dispID);
00433       IPropertyNotifySink_Release(sink);
00434       IUnknown_Release(CD.pUnk);
00435     }
00436     IEnumConnections_Release(pEnum);
00437   }
00438 
00439   hres = IConnectionPoint_EnumConnections(this->pFontEventsCP, &pEnum);
00440   if (SUCCEEDED(hres))
00441   {
00442     DISPPARAMS dispparams;
00443     VARIANTARG vararg;
00444 
00445     VariantInit(&vararg);
00446     V_VT(&vararg) = VT_BSTR;
00447     V_BSTR(&vararg) = SysAllocString(dispid_mapping[dispID]);
00448 
00449     dispparams.cArgs = 1;
00450     dispparams.cNamedArgs = 0;
00451     dispparams.rgdispidNamedArgs = NULL;
00452     dispparams.rgvarg = &vararg;
00453 
00454     while(IEnumConnections_Next(pEnum, 1, &CD, NULL) == S_OK) {
00455         IFontEventsDisp *disp;
00456 
00457         IUnknown_QueryInterface(CD.pUnk, &IID_IFontEventsDisp, (LPVOID)&disp);
00458         IDispatch_Invoke(disp, DISPID_FONT_CHANGED, &IID_NULL,
00459                          LOCALE_NEUTRAL, INVOKE_FUNC, &dispparams, NULL,
00460                          NULL, NULL);
00461 
00462         IDispatch_Release(disp);
00463         IUnknown_Release(CD.pUnk);
00464     }
00465     VariantClear(&vararg);
00466     IEnumConnections_Release(pEnum);
00467   }
00468 }
00469 
00470 /************************************************************************
00471  * OLEFontImpl_QueryInterface (IUnknown)
00472  *
00473  * See Windows documentation for more details on IUnknown methods.
00474  */
00475 static HRESULT WINAPI OLEFontImpl_QueryInterface(
00476   IFont*  iface,
00477   REFIID  riid,
00478   void**  ppvObject)
00479 {
00480   OLEFontImpl *this = (OLEFontImpl *)iface;
00481   TRACE("(%p)->(%s, %p)\n", this, debugstr_guid(riid), ppvObject);
00482 
00483   /*
00484    * Perform a sanity check on the parameters.
00485    */
00486   if ( (this==0) || (ppvObject==0) )
00487     return E_INVALIDARG;
00488 
00489   /*
00490    * Initialize the return parameter.
00491    */
00492   *ppvObject = 0;
00493 
00494   /*
00495    * Compare the riid with the interface IDs implemented by this object.
00496    */
00497   if (IsEqualGUID(&IID_IUnknown, riid))
00498     *ppvObject = this;
00499   if (IsEqualGUID(&IID_IFont, riid))
00500     *ppvObject = this;
00501   if (IsEqualGUID(&IID_IDispatch, riid))
00502     *ppvObject = &this->lpvtblIDispatch;
00503   if (IsEqualGUID(&IID_IFontDisp, riid))
00504     *ppvObject = &this->lpvtblIDispatch;
00505   if (IsEqualIID(&IID_IPersist, riid) || IsEqualGUID(&IID_IPersistStream, riid))
00506     *ppvObject = &this->lpvtblIPersistStream;
00507   if (IsEqualGUID(&IID_IConnectionPointContainer, riid))
00508     *ppvObject = &this->lpvtblIConnectionPointContainer;
00509   if (IsEqualGUID(&IID_IPersistPropertyBag, riid))
00510     *ppvObject = &this->lpvtblIPersistPropertyBag;
00511   if (IsEqualGUID(&IID_IPersistStreamInit, riid))
00512     *ppvObject = &this->lpvtblIPersistStreamInit;
00513 
00514   /*
00515    * Check that we obtained an interface.
00516    */
00517   if ((*ppvObject)==0)
00518   {
00519     FIXME("() : asking for unsupported interface %s\n",debugstr_guid(riid));
00520     return E_NOINTERFACE;
00521   }
00522   OLEFontImpl_AddRef((IFont*)this);
00523   return S_OK;
00524 }
00525 
00526 /************************************************************************
00527  * OLEFontImpl_AddRef (IUnknown)
00528  *
00529  * See Windows documentation for more details on IUnknown methods.
00530  */
00531 static ULONG WINAPI OLEFontImpl_AddRef(
00532   IFont* iface)
00533 {
00534   OLEFontImpl *this = (OLEFontImpl *)iface;
00535   TRACE("(%p)->(ref=%d)\n", this, this->ref);
00536   return InterlockedIncrement(&this->ref);
00537 }
00538 
00539 /************************************************************************
00540  * OLEFontImpl_Release (IUnknown)
00541  *
00542  * See Windows documentation for more details on IUnknown methods.
00543  */
00544 static ULONG WINAPI OLEFontImpl_Release(
00545       IFont* iface)
00546 {
00547   OLEFontImpl *this = (OLEFontImpl *)iface;
00548   ULONG ret;
00549   TRACE("(%p)->(ref=%d)\n", this, this->ref);
00550 
00551   /* Decrease the reference count for current interface */
00552   ret = InterlockedDecrement(&this->ref);
00553 
00554   /* If the reference count goes down to 0, destroy. */
00555   if (ret == 0)
00556   {
00557     ULONG fontlist_refs = InterlockedDecrement(&ifont_cnt);
00558 
00559     /* Final IFont object so destroy font cache */
00560     if (fontlist_refs == 0)
00561     {
00562       HFONTItem *item, *cursor2;
00563 
00564       EnterCriticalSection(&OLEFontImpl_csHFONTLIST);
00565       LIST_FOR_EACH_ENTRY_SAFE(item, cursor2, &OLEFontImpl_hFontList, HFONTItem, entry)
00566         HFONTItem_Delete(item);
00567       LeaveCriticalSection(&OLEFontImpl_csHFONTLIST);
00568       delete_dc();
00569     }
00570     else
00571     {
00572       dec_int_ref(this->gdiFont);
00573     }
00574     OLEFontImpl_Destroy(this);
00575   }
00576 
00577   return ret;
00578 }
00579 
00580 typedef struct
00581 {
00582     short orig_cs;
00583     short avail_cs;
00584 } enum_data;
00585 
00586 static int CALLBACK font_enum_proc(const LOGFONTW *elf, const TEXTMETRICW *ntm, DWORD type, LPARAM lp)
00587 {
00588     enum_data *data = (enum_data*)lp;
00589 
00590     if(elf->lfCharSet == data->orig_cs)
00591     {
00592         data->avail_cs = data->orig_cs;
00593         return 0;
00594     }
00595     if(data->avail_cs == -1) data->avail_cs = elf->lfCharSet;
00596     return 1;
00597 }
00598 
00599 static void realize_font(OLEFontImpl *This)
00600 {
00601     if (This->dirty)
00602     {
00603         LOGFONTW logFont;
00604         INT fontHeight;
00605         WCHAR text_face[LF_FACESIZE];
00606         HDC hdc = get_dc();
00607         HFONT old_font;
00608         TEXTMETRICW tm;
00609 
00610         text_face[0] = 0;
00611 
00612         if(This->gdiFont)
00613         {
00614             old_font = SelectObject(hdc, This->gdiFont);
00615             GetTextFaceW(hdc, sizeof(text_face) / sizeof(text_face[0]), text_face);
00616             SelectObject(hdc, old_font);
00617             dec_int_ref(This->gdiFont);
00618             This->gdiFont = 0;
00619         }
00620 
00621         memset(&logFont, 0, sizeof(LOGFONTW));
00622 
00623         lstrcpynW(logFont.lfFaceName, This->description.lpstrName, LF_FACESIZE);
00624         logFont.lfCharSet         = This->description.sCharset;
00625 
00626         /* If the font name has been changed then enumerate all charsets
00627            and pick one that'll result in the font specified being selected */
00628         if(text_face[0] && lstrcmpiW(text_face, This->description.lpstrName))
00629         {
00630             enum_data data;
00631             data.orig_cs = This->description.sCharset;
00632             data.avail_cs = -1;
00633             logFont.lfCharSet = DEFAULT_CHARSET;
00634             EnumFontFamiliesExW(get_dc(), &logFont, font_enum_proc, (LPARAM)&data, 0);
00635             if(data.avail_cs != -1) logFont.lfCharSet = data.avail_cs;
00636         }
00637 
00638 
00639         /*
00640          * The height of the font returned by the get_Size property is the
00641          * height of the font in points multiplied by 10000... Using some
00642          * simple conversions and the ratio given by the application, it can
00643          * be converted to a height in pixels.
00644          *
00645          * Standard ratio is 72 / 2540, or 18 / 635 in lowest terms.
00646          * Ratio is applied here relative to the standard.
00647          */
00648 
00649         fontHeight = MulDiv( This->description.cySize.s.Lo, This->cyLogical*635, This->cyHimetric*18 );
00650 
00651 
00652         logFont.lfHeight          = ((fontHeight%10000L)>5000L) ? (-fontHeight/10000L) - 1 :
00653                                                                   (-fontHeight/10000L);
00654         logFont.lfItalic          = This->description.fItalic;
00655         logFont.lfUnderline       = This->description.fUnderline;
00656         logFont.lfStrikeOut       = This->description.fStrikethrough;
00657         logFont.lfWeight          = This->description.sWeight;
00658         logFont.lfOutPrecision    = OUT_CHARACTER_PRECIS;
00659         logFont.lfClipPrecision   = CLIP_DEFAULT_PRECIS;
00660         logFont.lfQuality         = DEFAULT_QUALITY;
00661         logFont.lfPitchAndFamily  = DEFAULT_PITCH;
00662 
00663         This->gdiFont = CreateFontIndirectW(&logFont);
00664         This->dirty = FALSE;
00665 
00666         add_hfontitem(This->gdiFont);
00667 
00668         /* Fixup the name and charset properties so that they match the
00669            selected font */
00670         old_font = SelectObject(get_dc(), This->gdiFont);
00671         GetTextFaceW(hdc, sizeof(text_face) / sizeof(text_face[0]), text_face);
00672         if(lstrcmpiW(text_face, This->description.lpstrName))
00673         {
00674             HeapFree(GetProcessHeap(), 0, This->description.lpstrName);
00675             This->description.lpstrName = strdupW(text_face);
00676         }
00677         GetTextMetricsW(hdc, &tm);
00678         This->description.sCharset = tm.tmCharSet;
00679         SelectObject(hdc, old_font);
00680     }
00681 }
00682 
00683 /************************************************************************
00684  * OLEFontImpl_get_Name (IFont)
00685  *
00686  * See Windows documentation for more details on IFont methods.
00687  */
00688 static HRESULT WINAPI OLEFontImpl_get_Name(
00689   IFont*  iface,
00690   BSTR* pname)
00691 {
00692   OLEFontImpl *this = (OLEFontImpl *)iface;
00693   TRACE("(%p)->(%p)\n", this, pname);
00694   /*
00695    * Sanity check.
00696    */
00697   if (pname==0)
00698     return E_POINTER;
00699 
00700   if(this->dirty) realize_font(this);
00701 
00702   if (this->description.lpstrName!=0)
00703     *pname = SysAllocString(this->description.lpstrName);
00704   else
00705     *pname = 0;
00706 
00707   return S_OK;
00708 }
00709 
00710 /************************************************************************
00711  * OLEFontImpl_put_Name (IFont)
00712  *
00713  * See Windows documentation for more details on IFont methods.
00714  */
00715 static HRESULT WINAPI OLEFontImpl_put_Name(
00716   IFont* iface,
00717   BSTR name)
00718 {
00719   OLEFontImpl *this = (OLEFontImpl *)iface;
00720   TRACE("(%p)->(%p)\n", this, name);
00721 
00722   if (!name)
00723     return CTL_E_INVALIDPROPERTYVALUE;
00724 
00725   if (this->description.lpstrName==0)
00726   {
00727     this->description.lpstrName = HeapAlloc(GetProcessHeap(),
00728                         0,
00729                         (lstrlenW(name)+1) * sizeof(WCHAR));
00730   }
00731   else
00732   {
00733     this->description.lpstrName = HeapReAlloc(GetProcessHeap(),
00734                           0,
00735                           this->description.lpstrName,
00736                           (lstrlenW(name)+1) * sizeof(WCHAR));
00737   }
00738 
00739   if (this->description.lpstrName==0)
00740     return E_OUTOFMEMORY;
00741 
00742   strcpyW(this->description.lpstrName, name);
00743   TRACE("new name %s\n", debugstr_w(this->description.lpstrName));
00744   OLEFont_SendNotify(this, DISPID_FONT_NAME);
00745   return S_OK;
00746 }
00747 
00748 /************************************************************************
00749  * OLEFontImpl_get_Size (IFont)
00750  *
00751  * See Windows documentation for more details on IFont methods.
00752  */
00753 static HRESULT WINAPI OLEFontImpl_get_Size(
00754   IFont* iface,
00755   CY*    psize)
00756 {
00757   OLEFontImpl *this = (OLEFontImpl *)iface;
00758   TRACE("(%p)->(%p)\n", this, psize);
00759 
00760   /*
00761    * Sanity check
00762    */
00763   if (psize==0)
00764     return E_POINTER;
00765 
00766   if(this->dirty) realize_font(this);
00767 
00768   psize->s.Hi = 0;
00769   psize->s.Lo = this->description.cySize.s.Lo;
00770 
00771   return S_OK;
00772 }
00773 
00774 /************************************************************************
00775  * OLEFontImpl_put_Size (IFont)
00776  *
00777  * See Windows documentation for more details on IFont methods.
00778  */
00779 static HRESULT WINAPI OLEFontImpl_put_Size(
00780   IFont* iface,
00781   CY     size)
00782 {
00783   OLEFontImpl *this = (OLEFontImpl *)iface;
00784   TRACE("(%p)->(%d)\n", this, size.s.Lo);
00785   this->description.cySize.s.Hi = 0;
00786   this->description.cySize.s.Lo = size.s.Lo;
00787   OLEFont_SendNotify(this, DISPID_FONT_SIZE);
00788 
00789   return S_OK;
00790 }
00791 
00792 /************************************************************************
00793  * OLEFontImpl_get_Bold (IFont)
00794  *
00795  * See Windows documentation for more details on IFont methods.
00796  */
00797 static HRESULT WINAPI OLEFontImpl_get_Bold(
00798   IFont*  iface,
00799   BOOL* pbold)
00800 {
00801   OLEFontImpl *this = (OLEFontImpl *)iface;
00802   TRACE("(%p)->(%p)\n", this, pbold);
00803   /*
00804    * Sanity check
00805    */
00806   if (pbold==0)
00807     return E_POINTER;
00808 
00809   if(this->dirty) realize_font(this);
00810 
00811   *pbold = this->description.sWeight > 550;
00812 
00813   return S_OK;
00814 }
00815 
00816 /************************************************************************
00817  * OLEFontImpl_put_Bold (IFont)
00818  *
00819  * See Windows documentation for more details on IFont methods.
00820  */
00821 static HRESULT WINAPI OLEFontImpl_put_Bold(
00822   IFont* iface,
00823   BOOL bold)
00824 {
00825   OLEFontImpl *this = (OLEFontImpl *)iface;
00826   TRACE("(%p)->(%d)\n", this, bold);
00827   this->description.sWeight = bold ? FW_BOLD : FW_NORMAL;
00828   OLEFont_SendNotify(this, DISPID_FONT_BOLD);
00829 
00830   return S_OK;
00831 }
00832 
00833 /************************************************************************
00834  * OLEFontImpl_get_Italic (IFont)
00835  *
00836  * See Windows documentation for more details on IFont methods.
00837  */
00838 static HRESULT WINAPI OLEFontImpl_get_Italic(
00839   IFont*  iface,
00840   BOOL* pitalic)
00841 {
00842   OLEFontImpl *this = (OLEFontImpl *)iface;
00843   TRACE("(%p)->(%p)\n", this, pitalic);
00844   /*
00845    * Sanity check
00846    */
00847   if (pitalic==0)
00848     return E_POINTER;
00849 
00850   if(this->dirty) realize_font(this);
00851 
00852   *pitalic = this->description.fItalic;
00853 
00854   return S_OK;
00855 }
00856 
00857 /************************************************************************
00858  * OLEFontImpl_put_Italic (IFont)
00859  *
00860  * See Windows documentation for more details on IFont methods.
00861  */
00862 static HRESULT WINAPI OLEFontImpl_put_Italic(
00863   IFont* iface,
00864   BOOL italic)
00865 {
00866   OLEFontImpl *this = (OLEFontImpl *)iface;
00867   TRACE("(%p)->(%d)\n", this, italic);
00868 
00869   this->description.fItalic = italic;
00870 
00871   OLEFont_SendNotify(this, DISPID_FONT_ITALIC);
00872   return S_OK;
00873 }
00874 
00875 /************************************************************************
00876  * OLEFontImpl_get_Underline (IFont)
00877  *
00878  * See Windows documentation for more details on IFont methods.
00879  */
00880 static HRESULT WINAPI OLEFontImpl_get_Underline(
00881   IFont*  iface,
00882   BOOL* punderline)
00883 {
00884   OLEFontImpl *this = (OLEFontImpl *)iface;
00885   TRACE("(%p)->(%p)\n", this, punderline);
00886 
00887   /*
00888    * Sanity check
00889    */
00890   if (punderline==0)
00891     return E_POINTER;
00892 
00893   if(this->dirty) realize_font(this);
00894 
00895   *punderline = this->description.fUnderline;
00896 
00897   return S_OK;
00898 }
00899 
00900 /************************************************************************
00901  * OLEFontImpl_put_Underline (IFont)
00902  *
00903  * See Windows documentation for more details on IFont methods.
00904  */
00905 static HRESULT WINAPI OLEFontImpl_put_Underline(
00906   IFont* iface,
00907   BOOL underline)
00908 {
00909   OLEFontImpl *this = (OLEFontImpl *)iface;
00910   TRACE("(%p)->(%d)\n", this, underline);
00911 
00912   this->description.fUnderline = underline;
00913 
00914   OLEFont_SendNotify(this, DISPID_FONT_UNDER);
00915   return S_OK;
00916 }
00917 
00918 /************************************************************************
00919  * OLEFontImpl_get_Strikethrough (IFont)
00920  *
00921  * See Windows documentation for more details on IFont methods.
00922  */
00923 static HRESULT WINAPI OLEFontImpl_get_Strikethrough(
00924   IFont*  iface,
00925   BOOL* pstrikethrough)
00926 {
00927   OLEFontImpl *this = (OLEFontImpl *)iface;
00928   TRACE("(%p)->(%p)\n", this, pstrikethrough);
00929 
00930   /*
00931    * Sanity check
00932    */
00933   if (pstrikethrough==0)
00934     return E_POINTER;
00935 
00936   if(this->dirty) realize_font(this);
00937 
00938   *pstrikethrough = this->description.fStrikethrough;
00939 
00940   return S_OK;
00941 }
00942 
00943 /************************************************************************
00944  * OLEFontImpl_put_Strikethrough (IFont)
00945  *
00946  * See Windows documentation for more details on IFont methods.
00947  */
00948 static HRESULT WINAPI OLEFontImpl_put_Strikethrough(
00949  IFont* iface,
00950  BOOL strikethrough)
00951 {
00952   OLEFontImpl *this = (OLEFontImpl *)iface;
00953   TRACE("(%p)->(%d)\n", this, strikethrough);
00954 
00955   this->description.fStrikethrough = strikethrough;
00956   OLEFont_SendNotify(this, DISPID_FONT_STRIKE);
00957 
00958   return S_OK;
00959 }
00960 
00961 /************************************************************************
00962  * OLEFontImpl_get_Weight (IFont)
00963  *
00964  * See Windows documentation for more details on IFont methods.
00965  */
00966 static HRESULT WINAPI OLEFontImpl_get_Weight(
00967   IFont* iface,
00968   short* pweight)
00969 {
00970   OLEFontImpl *this = (OLEFontImpl *)iface;
00971   TRACE("(%p)->(%p)\n", this, pweight);
00972 
00973   /*
00974    * Sanity check
00975    */
00976   if (pweight==0)
00977     return E_POINTER;
00978 
00979   if(this->dirty) realize_font(this);
00980 
00981   *pweight = this->description.sWeight;
00982 
00983   return S_OK;
00984 }
00985 
00986 /************************************************************************
00987  * OLEFontImpl_put_Weight (IFont)
00988  *
00989  * See Windows documentation for more details on IFont methods.
00990  */
00991 static HRESULT WINAPI OLEFontImpl_put_Weight(
00992   IFont* iface,
00993   short  weight)
00994 {
00995   OLEFontImpl *this = (OLEFontImpl *)iface;
00996   TRACE("(%p)->(%d)\n", this, weight);
00997 
00998   this->description.sWeight = weight;
00999 
01000   OLEFont_SendNotify(this, DISPID_FONT_WEIGHT);
01001   return S_OK;
01002 }
01003 
01004 /************************************************************************
01005  * OLEFontImpl_get_Charset (IFont)
01006  *
01007  * See Windows documentation for more details on IFont methods.
01008  */
01009 static HRESULT WINAPI OLEFontImpl_get_Charset(
01010   IFont* iface,
01011   short* pcharset)
01012 {
01013   OLEFontImpl *this = (OLEFontImpl *)iface;
01014   TRACE("(%p)->(%p)\n", this, pcharset);
01015 
01016   /*
01017    * Sanity check
01018    */
01019   if (pcharset==0)
01020     return E_POINTER;
01021 
01022   if(this->dirty) realize_font(this);
01023 
01024   *pcharset = this->description.sCharset;
01025 
01026   return S_OK;
01027 }
01028 
01029 /************************************************************************
01030  * OLEFontImpl_put_Charset (IFont)
01031  *
01032  * See Windows documentation for more details on IFont methods.
01033  */
01034 static HRESULT WINAPI OLEFontImpl_put_Charset(
01035   IFont* iface,
01036   short charset)
01037 {
01038   OLEFontImpl *this = (OLEFontImpl *)iface;
01039   TRACE("(%p)->(%d)\n", this, charset);
01040 
01041   this->description.sCharset = charset;
01042   OLEFont_SendNotify(this, DISPID_FONT_CHARSET);
01043 
01044   return S_OK;
01045 }
01046 
01047 /************************************************************************
01048  * OLEFontImpl_get_hFont (IFont)
01049  *
01050  * See Windows documentation for more details on IFont methods.
01051  */
01052 static HRESULT WINAPI OLEFontImpl_get_hFont(
01053   IFont*   iface,
01054   HFONT* phfont)
01055 {
01056   OLEFontImpl *this = (OLEFontImpl *)iface;
01057   TRACE("(%p)->(%p)\n", this, phfont);
01058   if (phfont==NULL)
01059     return E_POINTER;
01060 
01061   if(this->dirty) realize_font(this);
01062 
01063   *phfont = this->gdiFont;
01064   TRACE("Returning %p\n", *phfont);
01065   return S_OK;
01066 }
01067 
01068 /************************************************************************
01069  * OLEFontImpl_Clone (IFont)
01070  *
01071  * See Windows documentation for more details on IFont methods.
01072  */
01073 static HRESULT WINAPI OLEFontImpl_Clone(
01074   IFont*  iface,
01075   IFont** ppfont)
01076 {
01077   OLEFontImpl* newObject = 0;
01078   OLEFontImpl *this = (OLEFontImpl *)iface;
01079 
01080   TRACE("(%p)->(%p)\n", this, ppfont);
01081 
01082   if (ppfont == NULL)
01083     return E_POINTER;
01084 
01085   *ppfont = NULL;
01086 
01087   /*
01088    * Allocate space for the object.
01089    */
01090   newObject = HeapAlloc(GetProcessHeap(), 0, sizeof(OLEFontImpl));
01091 
01092   if (newObject==NULL)
01093     return E_OUTOFMEMORY;
01094 
01095   *newObject = *this;
01096 
01097   /* We need to alloc new memory for the string, otherwise
01098    * we free memory twice.
01099    */
01100   newObject->description.lpstrName = HeapAlloc(
01101     GetProcessHeap(),0,
01102     (1+strlenW(this->description.lpstrName))*2
01103   );
01104   strcpyW(newObject->description.lpstrName, this->description.lpstrName);
01105 
01106 
01107   /* Increment internal ref in hfont item list */
01108   if(newObject->gdiFont) inc_int_ref(newObject->gdiFont);
01109 
01110   InterlockedIncrement(&ifont_cnt);
01111 
01112   /* create new connection points */
01113   newObject->pPropertyNotifyCP = NULL;
01114   newObject->pFontEventsCP = NULL;
01115   CreateConnectionPoint((IUnknown*)newObject, &IID_IPropertyNotifySink, &newObject->pPropertyNotifyCP);
01116   CreateConnectionPoint((IUnknown*)newObject, &IID_IFontEventsDisp, &newObject->pFontEventsCP);
01117 
01118   if (!newObject->pPropertyNotifyCP || !newObject->pFontEventsCP)
01119   {
01120     OLEFontImpl_Destroy(newObject);
01121     return E_OUTOFMEMORY;
01122   }
01123 
01124   /* The cloned object starts with a reference count of 1 */
01125   newObject->ref          = 1;
01126 
01127   *ppfont = (IFont*)newObject;
01128 
01129   return S_OK;
01130 }
01131 
01132 /************************************************************************
01133  * OLEFontImpl_IsEqual (IFont)
01134  *
01135  * See Windows documentation for more details on IFont methods.
01136  */
01137 static HRESULT WINAPI OLEFontImpl_IsEqual(
01138   IFont* iface,
01139   IFont* pFontOther)
01140 {
01141   OLEFontImpl *left = (OLEFontImpl *)iface;
01142   OLEFontImpl *right = (OLEFontImpl *)pFontOther;
01143   INT ret;
01144   INT left_len,right_len;
01145 
01146   if((iface == NULL) || (pFontOther == NULL))
01147     return E_POINTER;
01148   else if (left->description.cySize.s.Lo != right->description.cySize.s.Lo)
01149     return S_FALSE;
01150   else if (left->description.cySize.s.Hi != right->description.cySize.s.Hi)
01151     return S_FALSE;
01152   else if (left->description.sWeight != right->description.sWeight)
01153     return S_FALSE;
01154   else if (left->description.sCharset != right->description.sCharset)
01155     return S_FALSE;
01156   else if (left->description.fItalic != right->description.fItalic)
01157     return S_FALSE;
01158   else if (left->description.fUnderline != right->description.fUnderline)
01159     return S_FALSE;
01160   else if (left->description.fStrikethrough != right->description.fStrikethrough)
01161     return S_FALSE;
01162 
01163   /* Check from string */
01164   left_len = strlenW(left->description.lpstrName);
01165   right_len = strlenW(right->description.lpstrName);
01166   ret = CompareStringW(0,0,left->description.lpstrName, left_len,
01167     right->description.lpstrName, right_len);
01168   if (ret != CSTR_EQUAL)
01169     return S_FALSE;
01170 
01171   return S_OK;
01172 }
01173 
01174 /************************************************************************
01175  * OLEFontImpl_SetRatio (IFont)
01176  *
01177  * See Windows documentation for more details on IFont methods.
01178  */
01179 static HRESULT WINAPI OLEFontImpl_SetRatio(
01180   IFont* iface,
01181   LONG   cyLogical,
01182   LONG   cyHimetric)
01183 {
01184   OLEFontImpl *this = (OLEFontImpl *)iface;
01185   TRACE("(%p)->(%d, %d)\n", this, cyLogical, cyHimetric);
01186 
01187   this->cyLogical  = cyLogical;
01188   this->cyHimetric = cyHimetric;
01189 
01190   return S_OK;
01191 }
01192 
01193 /************************************************************************
01194  * OLEFontImpl_QueryTextMetrics (IFont)
01195  *
01196  * See Windows documentation for more details on IFont methods.
01197  */
01198 static HRESULT      WINAPI OLEFontImpl_QueryTextMetrics(
01199   IFont*         iface,
01200   TEXTMETRICOLE* ptm)
01201 {
01202   HDC hdcRef;
01203   HFONT hOldFont, hNewFont;
01204 
01205   hdcRef = GetDC(0);
01206   OLEFontImpl_get_hFont(iface, &hNewFont);
01207   hOldFont = SelectObject(hdcRef, hNewFont);
01208   GetTextMetricsW(hdcRef, ptm);
01209   SelectObject(hdcRef, hOldFont);
01210   ReleaseDC(0, hdcRef);
01211   return S_OK;
01212 }
01213 
01214 /************************************************************************
01215  * OLEFontImpl_AddRefHfont (IFont)
01216  *
01217  * See Windows documentation for more details on IFont methods.
01218  */
01219 static HRESULT WINAPI OLEFontImpl_AddRefHfont(
01220   IFont*  iface,
01221   HFONT hfont)
01222 {
01223     OLEFontImpl *this = (OLEFontImpl *)iface;
01224 
01225     TRACE("(%p)->(%p)\n", this, hfont);
01226 
01227     if (!hfont) return E_INVALIDARG;
01228 
01229     return inc_ext_ref(hfont);
01230 }
01231 
01232 /************************************************************************
01233  * OLEFontImpl_ReleaseHfont (IFont)
01234  *
01235  * See Windows documentation for more details on IFont methods.
01236  */
01237 static HRESULT WINAPI OLEFontImpl_ReleaseHfont(
01238   IFont*  iface,
01239   HFONT hfont)
01240 {
01241     OLEFontImpl *this = (OLEFontImpl *)iface;
01242 
01243     TRACE("(%p)->(%p)\n", this, hfont);
01244 
01245     if (!hfont) return E_INVALIDARG;
01246 
01247     return dec_ext_ref(hfont);
01248 }
01249 
01250 /************************************************************************
01251  * OLEFontImpl_SetHdc (IFont)
01252  *
01253  * See Windows documentation for more details on IFont methods.
01254  */
01255 static HRESULT WINAPI OLEFontImpl_SetHdc(
01256   IFont* iface,
01257   HDC  hdc)
01258 {
01259   OLEFontImpl *this = (OLEFontImpl *)iface;
01260   FIXME("(%p)->(%p): Stub\n", this, hdc);
01261   return E_NOTIMPL;
01262 }
01263 
01264 /*
01265  * Virtual function tables for the OLEFontImpl class.
01266  */
01267 static const IFontVtbl OLEFontImpl_VTable =
01268 {
01269   OLEFontImpl_QueryInterface,
01270   OLEFontImpl_AddRef,
01271   OLEFontImpl_Release,
01272   OLEFontImpl_get_Name,
01273   OLEFontImpl_put_Name,
01274   OLEFontImpl_get_Size,
01275   OLEFontImpl_put_Size,
01276   OLEFontImpl_get_Bold,
01277   OLEFontImpl_put_Bold,
01278   OLEFontImpl_get_Italic,
01279   OLEFontImpl_put_Italic,
01280   OLEFontImpl_get_Underline,
01281   OLEFontImpl_put_Underline,
01282   OLEFontImpl_get_Strikethrough,
01283   OLEFontImpl_put_Strikethrough,
01284   OLEFontImpl_get_Weight,
01285   OLEFontImpl_put_Weight,
01286   OLEFontImpl_get_Charset,
01287   OLEFontImpl_put_Charset,
01288   OLEFontImpl_get_hFont,
01289   OLEFontImpl_Clone,
01290   OLEFontImpl_IsEqual,
01291   OLEFontImpl_SetRatio,
01292   OLEFontImpl_QueryTextMetrics,
01293   OLEFontImpl_AddRefHfont,
01294   OLEFontImpl_ReleaseHfont,
01295   OLEFontImpl_SetHdc
01296 };
01297 
01298 /************************************************************************
01299  * OLEFontImpl_IDispatch_QueryInterface (IUnknown)
01300  *
01301  * See Windows documentation for more details on IUnknown methods.
01302  */
01303 static HRESULT WINAPI OLEFontImpl_IDispatch_QueryInterface(
01304   IDispatch* iface,
01305   REFIID     riid,
01306   VOID**     ppvoid)
01307 {
01308   OLEFontImpl *this = impl_from_IDispatch(iface);
01309 
01310   return IFont_QueryInterface((IFont *)this, riid, ppvoid);
01311 }
01312 
01313 /************************************************************************
01314  * OLEFontImpl_IDispatch_Release (IUnknown)
01315  *
01316  * See Windows documentation for more details on IUnknown methods.
01317  */
01318 static ULONG WINAPI OLEFontImpl_IDispatch_Release(
01319   IDispatch* iface)
01320 {
01321   OLEFontImpl *this = impl_from_IDispatch(iface);
01322 
01323   return IFont_Release((IFont *)this);
01324 }
01325 
01326 /************************************************************************
01327  * OLEFontImpl_IDispatch_AddRef (IUnknown)
01328  *
01329  * See Windows documentation for more details on IUnknown methods.
01330  */
01331 static ULONG WINAPI OLEFontImpl_IDispatch_AddRef(
01332   IDispatch* iface)
01333 {
01334   OLEFontImpl *this = impl_from_IDispatch(iface);
01335 
01336   return IFont_AddRef((IFont *)this);
01337 }
01338 
01339 /************************************************************************
01340  * OLEFontImpl_GetTypeInfoCount (IDispatch)
01341  *
01342  * See Windows documentation for more details on IDispatch methods.
01343  */
01344 static HRESULT WINAPI OLEFontImpl_GetTypeInfoCount(
01345   IDispatch*    iface,
01346   unsigned int* pctinfo)
01347 {
01348   OLEFontImpl *this = impl_from_IDispatch(iface);
01349   TRACE("(%p)->(%p)\n", this, pctinfo);
01350   *pctinfo = 1;
01351 
01352   return S_OK;
01353 }
01354 
01355 /************************************************************************
01356  * OLEFontImpl_GetTypeInfo (IDispatch)
01357  *
01358  * See Windows documentation for more details on IDispatch methods.
01359  */
01360 static HRESULT WINAPI OLEFontImpl_GetTypeInfo(
01361   IDispatch*  iface,
01362   UINT      iTInfo,
01363   LCID        lcid,
01364   ITypeInfo** ppTInfo)
01365 {
01366   static const WCHAR stdole2tlb[] = {'s','t','d','o','l','e','2','.','t','l','b',0};
01367   ITypeLib *tl;
01368   HRESULT hres;
01369 
01370   OLEFontImpl *this = impl_from_IDispatch(iface);
01371   TRACE("(%p, iTInfo=%d, lcid=%04x, %p)\n", this, iTInfo, (int)lcid, ppTInfo);
01372   if (iTInfo != 0)
01373     return E_FAIL;
01374   hres = LoadTypeLib(stdole2tlb, &tl);
01375   if (FAILED(hres)) {
01376     ERR("Could not load the stdole2.tlb?\n");
01377     return hres;
01378   }
01379   hres = ITypeLib_GetTypeInfoOfGuid(tl, &IID_IFontDisp, ppTInfo);
01380   ITypeLib_Release(tl);
01381   if (FAILED(hres)) {
01382     FIXME("Did not IDispatch typeinfo from typelib, hres %x\n",hres);
01383   }
01384   return hres;
01385 }
01386 
01387 /************************************************************************
01388  * OLEFontImpl_GetIDsOfNames (IDispatch)
01389  *
01390  * See Windows documentation for more details on IDispatch methods.
01391  */
01392 static HRESULT WINAPI OLEFontImpl_GetIDsOfNames(
01393   IDispatch*  iface,
01394   REFIID      riid,
01395   LPOLESTR* rgszNames,
01396   UINT      cNames,
01397   LCID        lcid,
01398   DISPID*     rgDispId)
01399 {
01400   ITypeInfo * pTInfo;
01401   HRESULT hres;
01402 
01403   OLEFontImpl *this = impl_from_IDispatch(iface);
01404 
01405   TRACE("(%p,%s,%p,cNames=%d,lcid=%04x,%p)\n", this, debugstr_guid(riid),
01406         rgszNames, cNames, (int)lcid, rgDispId);
01407 
01408   if (cNames == 0)
01409   {
01410     return E_INVALIDARG;
01411   }
01412   else
01413   {
01414     /* retrieve type information */
01415     hres = OLEFontImpl_GetTypeInfo(iface, 0, lcid, &pTInfo);
01416 
01417     if (FAILED(hres))
01418     {
01419       ERR("GetTypeInfo failed.\n");
01420       return hres;
01421     }
01422 
01423     /* convert names to DISPIDs */
01424     hres = DispGetIDsOfNames (pTInfo, rgszNames, cNames, rgDispId);
01425     ITypeInfo_Release(pTInfo);
01426 
01427     return hres;
01428   }
01429 }
01430 
01431 /************************************************************************
01432  * OLEFontImpl_Invoke (IDispatch)
01433  *
01434  * See Windows documentation for more details on IDispatch methods.
01435  * 
01436  * Note: Do not call _put_Xxx methods, since setting things here
01437  * should not call notify functions as I found out debugging the generic
01438  * MS VB5 installer.
01439  */
01440 static HRESULT WINAPI OLEFontImpl_Invoke(
01441   IDispatch*  iface,
01442   DISPID      dispIdMember,
01443   REFIID      riid,
01444   LCID        lcid,
01445   WORD        wFlags,
01446   DISPPARAMS* pDispParams,
01447   VARIANT*    pVarResult,
01448   EXCEPINFO*  pExepInfo,
01449   UINT*     puArgErr)
01450 {
01451   OLEFontImpl *this = impl_from_IDispatch(iface);
01452   HRESULT hr;
01453 
01454   TRACE("%p->(%d,%s,0x%x,0x%x,%p,%p,%p,%p)\n", this, dispIdMember,
01455     debugstr_guid(riid), lcid, wFlags, pDispParams, pVarResult, pExepInfo,
01456     puArgErr);
01457 
01458   /* validate parameters */
01459 
01460   if (!IsEqualIID(riid, &IID_NULL))
01461   {
01462     ERR("riid was %s instead of IID_NULL\n", debugstr_guid(riid));
01463     return DISP_E_UNKNOWNINTERFACE;
01464   }
01465 
01466   if (wFlags & DISPATCH_PROPERTYGET)
01467   {
01468     if (!pVarResult)
01469     {
01470       ERR("null pVarResult not allowed when DISPATCH_PROPERTYGET specified\n");
01471       return DISP_E_PARAMNOTOPTIONAL;
01472     }
01473   }
01474   else if (wFlags & DISPATCH_PROPERTYPUT)
01475   {
01476     if (!pDispParams)
01477     {
01478       ERR("null pDispParams not allowed when DISPATCH_PROPERTYPUT specified\n");
01479       return DISP_E_PARAMNOTOPTIONAL;
01480     }
01481     if (pDispParams->cArgs != 1)
01482     {
01483       ERR("param count for DISPATCH_PROPERTYPUT was %d instead of 1\n", pDispParams->cArgs);
01484       return DISP_E_BADPARAMCOUNT;
01485     }
01486   }
01487   else
01488   {
01489     ERR("one of DISPATCH_PROPERTYGET or DISPATCH_PROPERTYPUT must be specified\n");
01490     return DISP_E_MEMBERNOTFOUND;
01491   }
01492 
01493   switch (dispIdMember) {
01494   case DISPID_FONT_NAME:
01495     if (wFlags & DISPATCH_PROPERTYGET) {
01496       V_VT(pVarResult) = VT_BSTR;
01497       return IFont_get_Name((IFont *)this, &V_BSTR(pVarResult));
01498     } else {
01499       VARIANTARG vararg;
01500 
01501       VariantInit(&vararg);
01502       hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_BSTR);
01503       if (FAILED(hr))
01504         return hr;
01505 
01506       hr = IFont_put_Name((IFont *)this, V_BSTR(&vararg));
01507 
01508       VariantClear(&vararg);
01509       return hr;
01510     }
01511     break;
01512   case DISPID_FONT_BOLD:
01513     if (wFlags & DISPATCH_PROPERTYGET) {
01514       BOOL value;
01515       hr = IFont_get_Bold((IFont *)this, &value);
01516       V_VT(pVarResult) = VT_BOOL;
01517       V_BOOL(pVarResult) = value ? VARIANT_TRUE : VARIANT_FALSE;
01518       return hr;
01519     } else {
01520       VARIANTARG vararg;
01521 
01522       VariantInit(&vararg);
01523       hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_BOOL);
01524       if (FAILED(hr))
01525         return hr;
01526 
01527       hr = IFont_put_Bold((IFont *)this, V_BOOL(&vararg));
01528 
01529       VariantClear(&vararg);
01530       return hr;
01531     }
01532     break;
01533   case DISPID_FONT_ITALIC:
01534     if (wFlags & DISPATCH_PROPERTYGET) {
01535       BOOL value;
01536       hr = IFont_get_Italic((IFont *)this, &value);
01537       V_VT(pVarResult) = VT_BOOL;
01538       V_BOOL(pVarResult) = value ? VARIANT_TRUE : VARIANT_FALSE;
01539       return hr;
01540     } else {
01541       VARIANTARG vararg;
01542 
01543       VariantInit(&vararg);
01544       hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_BOOL);
01545       if (FAILED(hr))
01546         return hr;
01547 
01548       hr = IFont_put_Italic((IFont *)this, V_BOOL(&vararg));
01549 
01550       VariantClear(&vararg);
01551       return hr;
01552     }
01553     break;
01554   case DISPID_FONT_UNDER:
01555     if (wFlags & DISPATCH_PROPERTYGET) {
01556       BOOL value;
01557       hr = IFont_get_Underline((IFont *)this, &value);
01558       V_VT(pVarResult) = VT_BOOL;
01559       V_BOOL(pVarResult) = value ? VARIANT_TRUE : VARIANT_FALSE;
01560       return hr;
01561     } else {
01562       VARIANTARG vararg;
01563 
01564       VariantInit(&vararg);
01565       hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_BOOL);
01566       if (FAILED(hr))
01567         return hr;
01568 
01569       hr = IFont_put_Underline((IFont *)this, V_BOOL(&vararg));
01570 
01571       VariantClear(&vararg);
01572       return hr;
01573     }
01574     break;
01575   case DISPID_FONT_STRIKE:
01576     if (wFlags & DISPATCH_PROPERTYGET) {
01577       BOOL value;
01578       hr = IFont_get_Strikethrough((IFont *)this, &value);
01579       V_VT(pVarResult) = VT_BOOL;
01580       V_BOOL(pVarResult) = value ? VARIANT_TRUE : VARIANT_FALSE;
01581       return hr;
01582     } else {
01583       VARIANTARG vararg;
01584 
01585       VariantInit(&vararg);
01586       hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_BOOL);
01587       if (FAILED(hr))
01588         return hr;
01589 
01590       hr = IFont_put_Strikethrough((IFont *)this, V_BOOL(&vararg));
01591 
01592       VariantClear(&vararg);
01593       return hr;
01594     }
01595     break;
01596   case DISPID_FONT_SIZE:
01597     if (wFlags & DISPATCH_PROPERTYGET) {
01598       V_VT(pVarResult) = VT_CY;
01599       return OLEFontImpl_get_Size((IFont *)this, &V_CY(pVarResult));
01600     } else {
01601       VARIANTARG vararg;
01602 
01603       VariantInit(&vararg);
01604       hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_CY);
01605       if (FAILED(hr))
01606         return hr;
01607 
01608       hr = IFont_put_Size((IFont *)this, V_CY(&vararg));
01609 
01610       VariantClear(&vararg);
01611       return hr;
01612     }
01613     break;
01614   case DISPID_FONT_WEIGHT:
01615     if (wFlags & DISPATCH_PROPERTYGET) {
01616       V_VT(pVarResult) = VT_I2;
01617       return OLEFontImpl_get_Weight((IFont *)this, &V_I2(pVarResult));
01618     } else {
01619       VARIANTARG vararg;
01620 
01621       VariantInit(&vararg);
01622       hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_I2);
01623       if (FAILED(hr))
01624         return hr;
01625 
01626       hr = IFont_put_Weight((IFont *)this, V_I2(&vararg));
01627 
01628       VariantClear(&vararg);
01629       return hr;
01630     }
01631     break;
01632   case DISPID_FONT_CHARSET:
01633     if (wFlags & DISPATCH_PROPERTYGET) {
01634       V_VT(pVarResult) = VT_I2;
01635       return OLEFontImpl_get_Charset((IFont *)this, &V_I2(pVarResult));
01636     } else {
01637       VARIANTARG vararg;
01638 
01639       VariantInit(&vararg);
01640       hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_I2);
01641       if (FAILED(hr))
01642         return hr;
01643 
01644       hr = IFont_put_Charset((IFont *)this, V_I2(&vararg));
01645 
01646       VariantClear(&vararg);
01647       return hr;
01648     }
01649     break;
01650   default:
01651     ERR("member not found for dispid 0x%x\n", dispIdMember);
01652     return DISP_E_MEMBERNOTFOUND;
01653   }
01654 }
01655 
01656 static const IDispatchVtbl OLEFontImpl_IDispatch_VTable =
01657 {
01658   OLEFontImpl_IDispatch_QueryInterface,
01659   OLEFontImpl_IDispatch_AddRef,
01660   OLEFontImpl_IDispatch_Release,
01661   OLEFontImpl_GetTypeInfoCount,
01662   OLEFontImpl_GetTypeInfo,
01663   OLEFontImpl_GetIDsOfNames,
01664   OLEFontImpl_Invoke
01665 };
01666 
01667 /************************************************************************
01668  * OLEFontImpl_IPersistStream_QueryInterface (IUnknown)
01669  *
01670  * See Windows documentation for more details on IUnknown methods.
01671  */
01672 static HRESULT WINAPI OLEFontImpl_IPersistStream_QueryInterface(
01673   IPersistStream* iface,
01674   REFIID     riid,
01675   VOID**     ppvoid)
01676 {
01677   OLEFontImpl *this = impl_from_IPersistStream(iface);
01678 
01679   return IFont_QueryInterface((IFont *)this, riid, ppvoid);
01680 }
01681 
01682 /************************************************************************
01683  * OLEFontImpl_IPersistStream_Release (IUnknown)
01684  *
01685  * See Windows documentation for more details on IUnknown methods.
01686  */
01687 static ULONG WINAPI OLEFontImpl_IPersistStream_Release(
01688   IPersistStream* iface)
01689 {
01690   OLEFontImpl *this = impl_from_IPersistStream(iface);
01691 
01692   return IFont_Release((IFont *)this);
01693 }
01694 
01695 /************************************************************************
01696  * OLEFontImpl_IPersistStream_AddRef (IUnknown)
01697  *
01698  * See Windows documentation for more details on IUnknown methods.
01699  */
01700 static ULONG WINAPI OLEFontImpl_IPersistStream_AddRef(
01701   IPersistStream* iface)
01702 {
01703   OLEFontImpl *this = impl_from_IPersistStream(iface);
01704 
01705   return IFont_AddRef((IFont *)this);
01706 }
01707 
01708 /************************************************************************
01709  * OLEFontImpl_GetClassID (IPersistStream)
01710  *
01711  * See Windows documentation for more details on IPersistStream methods.
01712  */
01713 static HRESULT WINAPI OLEFontImpl_GetClassID(
01714   IPersistStream* iface,
01715   CLSID*                pClassID)
01716 {
01717   TRACE("(%p,%p)\n",iface,pClassID);
01718   if (pClassID==0)
01719     return E_POINTER;
01720 
01721   *pClassID = CLSID_StdFont;
01722 
01723   return S_OK;
01724 }
01725 
01726 /************************************************************************
01727  * OLEFontImpl_IsDirty (IPersistStream)
01728  *
01729  * See Windows documentation for more details on IPersistStream methods.
01730  */
01731 static HRESULT WINAPI OLEFontImpl_IsDirty(
01732   IPersistStream*  iface)
01733 {
01734   TRACE("(%p)\n",iface);
01735   return S_OK;
01736 }
01737 
01738 /************************************************************************
01739  * OLEFontImpl_Load (IPersistStream)
01740  *
01741  * See Windows documentation for more details on IPersistStream methods.
01742  *
01743  * This is the format of the standard font serialization as far as I
01744  * know
01745  *
01746  * Offset   Type   Value           Comment
01747  * 0x0000   Byte   Unknown         Probably a version number, contains 0x01
01748  * 0x0001   Short  Charset         Charset value from the FONTDESC structure
01749  * 0x0003   Byte   Attributes      Flags defined as follows:
01750  *                                     00000010 - Italic
01751  *                                     00000100 - Underline
01752  *                                     00001000 - Strikethrough
01753  * 0x0004   Short  Weight          Weight value from FONTDESC structure
01754  * 0x0006   DWORD  size            "Low" portion of the cySize member of the FONTDESC
01755  *                                 structure/
01756  * 0x000A   Byte   name length     Length of the font name string (no null character)
01757  * 0x000B   String name            Name of the font (ASCII, no nul character)
01758  */
01759 static HRESULT WINAPI OLEFontImpl_Load(
01760   IPersistStream*  iface,
01761   IStream*         pLoadStream)
01762 {
01763   char  readBuffer[0x100];
01764   ULONG cbRead;
01765   BYTE  bVersion;
01766   BYTE  bAttributes;
01767   BYTE  bStringSize;
01768   INT len;
01769 
01770   OLEFontImpl *this = impl_from_IPersistStream(iface);
01771 
01772   /*
01773    * Read the version byte
01774    */
01775   IStream_Read(pLoadStream, &bVersion, 1, &cbRead);
01776 
01777   if ( (cbRead!=1) ||
01778        (bVersion!=0x01) )
01779     return E_FAIL;
01780 
01781   /*
01782    * Charset
01783    */
01784   IStream_Read(pLoadStream, &this->description.sCharset, 2, &cbRead);
01785 
01786   if (cbRead!=2)
01787     return E_FAIL;
01788 
01789   /*
01790    * Attributes
01791    */
01792   IStream_Read(pLoadStream, &bAttributes, 1, &cbRead);
01793 
01794   if (cbRead!=1)
01795     return E_FAIL;
01796 
01797   this->description.fItalic        = (bAttributes & FONTPERSIST_ITALIC) != 0;
01798   this->description.fStrikethrough = (bAttributes & FONTPERSIST_STRIKETHROUGH) != 0;
01799   this->description.fUnderline     = (bAttributes & FONTPERSIST_UNDERLINE) != 0;
01800 
01801   /*
01802    * Weight
01803    */
01804   IStream_Read(pLoadStream, &this->description.sWeight, 2, &cbRead);
01805 
01806   if (cbRead!=2)
01807     return E_FAIL;
01808 
01809   /*
01810    * Size
01811    */
01812   IStream_Read(pLoadStream, &this->description.cySize.s.Lo, 4, &cbRead);
01813 
01814   if (cbRead!=4)
01815     return E_FAIL;
01816 
01817   this->description.cySize.s.Hi = 0;
01818 
01819   /*
01820    * FontName
01821    */
01822   IStream_Read(pLoadStream, &bStringSize, 1, &cbRead);
01823 
01824   if (cbRead!=1)
01825     return E_FAIL;
01826 
01827   IStream_Read(pLoadStream, readBuffer, bStringSize, &cbRead);
01828 
01829   if (cbRead!=bStringSize)
01830     return E_FAIL;
01831 
01832   HeapFree(GetProcessHeap(), 0, this->description.lpstrName);
01833 
01834   len = MultiByteToWideChar( CP_ACP, 0, readBuffer, bStringSize, NULL, 0 );
01835   this->description.lpstrName = HeapAlloc( GetProcessHeap(), 0, (len+1) * sizeof(WCHAR) );
01836   MultiByteToWideChar( CP_ACP, 0, readBuffer, bStringSize, this->description.lpstrName, len );
01837   this->description.lpstrName[len] = 0;
01838 
01839   /* Ensure use of this font causes a new one to be created */
01840   dec_int_ref(this->gdiFont);
01841   this->gdiFont = 0;
01842   this->dirty = TRUE;
01843 
01844   return S_OK;
01845 }
01846 
01847 /************************************************************************
01848  * OLEFontImpl_Save (IPersistStream)
01849  *
01850  * See Windows documentation for more details on IPersistStream methods.
01851  */
01852 static HRESULT WINAPI OLEFontImpl_Save(
01853   IPersistStream*  iface,
01854   IStream*         pOutStream,
01855   BOOL             fClearDirty)
01856 {
01857   char* writeBuffer = NULL;
01858   ULONG cbWritten;
01859   BYTE  bVersion = 0x01;
01860   BYTE  bAttributes;
01861   BYTE  bStringSize;
01862 
01863   OLEFontImpl *this = impl_from_IPersistStream(iface);
01864 
01865   /*
01866    * Read the version byte
01867    */
01868   IStream_Write(pOutStream, &bVersion, 1, &cbWritten);
01869 
01870   if (cbWritten!=1)
01871     return E_FAIL;
01872 
01873   /*
01874    * Charset
01875    */
01876   IStream_Write(pOutStream, &this->description.sCharset, 2, &cbWritten);
01877 
01878   if (cbWritten!=2)
01879     return E_FAIL;
01880 
01881   /*
01882    * Attributes
01883    */
01884   bAttributes = 0;
01885 
01886   if (this->description.fItalic)
01887     bAttributes |= FONTPERSIST_ITALIC;
01888 
01889   if (this->description.fStrikethrough)
01890     bAttributes |= FONTPERSIST_STRIKETHROUGH;
01891 
01892   if (this->description.fUnderline)
01893     bAttributes |= FONTPERSIST_UNDERLINE;
01894 
01895   IStream_Write(pOutStream, &bAttributes, 1, &cbWritten);
01896 
01897   if (cbWritten!=1)
01898     return E_FAIL;
01899 
01900   /*
01901    * Weight
01902    */
01903   IStream_Write(pOutStream, &this->description.sWeight, 2, &cbWritten);
01904 
01905   if (cbWritten!=2)
01906     return E_FAIL;
01907 
01908   /*
01909    * Size
01910    */
01911   IStream_Write(pOutStream, &this->description.cySize.s.Lo, 4, &cbWritten);
01912 
01913   if (cbWritten!=4)
01914     return E_FAIL;
01915 
01916   /*
01917    * FontName
01918    */
01919   if (this->description.lpstrName!=0)
01920     bStringSize = WideCharToMultiByte( CP_ACP, 0, this->description.lpstrName,
01921                                        strlenW(this->description.lpstrName), NULL, 0, NULL, NULL );
01922   else
01923     bStringSize = 0;
01924 
01925   IStream_Write(pOutStream, &bStringSize, 1, &cbWritten);
01926 
01927   if (cbWritten!=1)
01928     return E_FAIL;
01929 
01930   if (bStringSize!=0)
01931   {
01932       if (!(writeBuffer = HeapAlloc( GetProcessHeap(), 0, bStringSize ))) return E_OUTOFMEMORY;
01933       WideCharToMultiByte( CP_ACP, 0, this->description.lpstrName,
01934                            strlenW(this->description.lpstrName),
01935                            writeBuffer, bStringSize, NULL, NULL );
01936 
01937     IStream_Write(pOutStream, writeBuffer, bStringSize, &cbWritten);
01938     HeapFree(GetProcessHeap(), 0, writeBuffer);
01939 
01940     if (cbWritten!=bStringSize)
01941       return E_FAIL;
01942   }
01943 
01944   return S_OK;
01945 }
01946 
01947 /************************************************************************
01948  * OLEFontImpl_GetSizeMax (IPersistStream)
01949  *
01950  * See Windows documentation for more details on IPersistStream methods.
01951  */
01952 static HRESULT WINAPI OLEFontImpl_GetSizeMax(
01953   IPersistStream*  iface,
01954   ULARGE_INTEGER*  pcbSize)
01955 {
01956   OLEFontImpl *this = impl_from_IPersistStream(iface);
01957 
01958   if (pcbSize==NULL)
01959     return E_POINTER;
01960 
01961   pcbSize->u.HighPart = 0;
01962   pcbSize->u.LowPart = 0;
01963 
01964   pcbSize->u.LowPart += sizeof(BYTE);  /* Version */
01965   pcbSize->u.LowPart += sizeof(WORD);  /* Lang code */
01966   pcbSize->u.LowPart += sizeof(BYTE);  /* Flags */
01967   pcbSize->u.LowPart += sizeof(WORD);  /* Weight */
01968   pcbSize->u.LowPart += sizeof(DWORD); /* Size */
01969   pcbSize->u.LowPart += sizeof(BYTE);  /* StrLength */
01970 
01971   if (this->description.lpstrName!=0)
01972       pcbSize->u.LowPart += WideCharToMultiByte( CP_ACP, 0, this->description.lpstrName,
01973                                                  strlenW(this->description.lpstrName),
01974                                                  NULL, 0, NULL, NULL );
01975 
01976   return S_OK;
01977 }
01978 
01979 static const IPersistStreamVtbl OLEFontImpl_IPersistStream_VTable =
01980 {
01981   OLEFontImpl_IPersistStream_QueryInterface,
01982   OLEFontImpl_IPersistStream_AddRef,
01983   OLEFontImpl_IPersistStream_Release,
01984   OLEFontImpl_GetClassID,
01985   OLEFontImpl_IsDirty,
01986   OLEFontImpl_Load,
01987   OLEFontImpl_Save,
01988   OLEFontImpl_GetSizeMax
01989 };
01990 
01991 /************************************************************************
01992  * OLEFontImpl_IConnectionPointContainer_QueryInterface (IUnknown)
01993  *
01994  * See Windows documentation for more details on IUnknown methods.
01995  */
01996 static HRESULT WINAPI OLEFontImpl_IConnectionPointContainer_QueryInterface(
01997   IConnectionPointContainer* iface,
01998   REFIID     riid,
01999   VOID**     ppvoid)
02000 {
02001   OLEFontImpl *this = impl_from_IConnectionPointContainer(iface);
02002 
02003   return IFont_QueryInterface((IFont*)this, riid, ppvoid);
02004 }
02005 
02006 /************************************************************************
02007  * OLEFontImpl_IConnectionPointContainer_Release (IUnknown)
02008  *
02009  * See Windows documentation for more details on IUnknown methods.
02010  */
02011 static ULONG WINAPI OLEFontImpl_IConnectionPointContainer_Release(
02012   IConnectionPointContainer* iface)
02013 {
02014   OLEFontImpl *this = impl_from_IConnectionPointContainer(iface);
02015 
02016   return IFont_Release((IFont*)this);
02017 }
02018 
02019 /************************************************************************
02020  * OLEFontImpl_IConnectionPointContainer_AddRef (IUnknown)
02021  *
02022  * See Windows documentation for more details on IUnknown methods.
02023  */
02024 static ULONG WINAPI OLEFontImpl_IConnectionPointContainer_AddRef(
02025   IConnectionPointContainer* iface)
02026 {
02027   OLEFontImpl *this = impl_from_IConnectionPointContainer(iface);
02028 
02029   return IFont_AddRef((IFont*)this);
02030 }
02031 
02032 /************************************************************************
02033  * OLEFontImpl_EnumConnectionPoints (IConnectionPointContainer)
02034  *
02035  * See Windows documentation for more details on IConnectionPointContainer
02036  * methods.
02037  */
02038 static HRESULT WINAPI OLEFontImpl_EnumConnectionPoints(
02039   IConnectionPointContainer* iface,
02040   IEnumConnectionPoints **ppEnum)
02041 {
02042   OLEFontImpl *this = impl_from_IConnectionPointContainer(iface);
02043 
02044   FIXME("(%p)->(%p): stub\n", this, ppEnum);
02045   return E_NOTIMPL;
02046 }
02047 
02048 /************************************************************************
02049  * OLEFontImpl_FindConnectionPoint (IConnectionPointContainer)
02050  *
02051  * See Windows documentation for more details on IConnectionPointContainer
02052  * methods.
02053  */
02054 static HRESULT WINAPI OLEFontImpl_FindConnectionPoint(
02055    IConnectionPointContainer* iface,
02056    REFIID riid,
02057    IConnectionPoint **ppCp)
02058 {
02059   OLEFontImpl *this = impl_from_IConnectionPointContainer(iface);
02060   TRACE("(%p)->(%s, %p)\n", this, debugstr_guid(riid), ppCp);
02061 
02062   if(IsEqualIID(riid, &IID_IPropertyNotifySink)) {
02063     return IConnectionPoint_QueryInterface(this->pPropertyNotifyCP,
02064                                            &IID_IConnectionPoint,
02065                                            (LPVOID)ppCp);
02066   } else if(IsEqualIID(riid, &IID_IFontEventsDisp)) {
02067     return IConnectionPoint_QueryInterface(this->pFontEventsCP,
02068                                            &IID_IConnectionPoint,
02069                                            (LPVOID)ppCp);
02070   } else {
02071     FIXME("no connection point for %s\n", debugstr_guid(riid));
02072     return CONNECT_E_NOCONNECTION;
02073   }
02074 }
02075 
02076 static const IConnectionPointContainerVtbl
02077      OLEFontImpl_IConnectionPointContainer_VTable =
02078 {
02079   OLEFontImpl_IConnectionPointContainer_QueryInterface,
02080   OLEFontImpl_IConnectionPointContainer_AddRef,
02081   OLEFontImpl_IConnectionPointContainer_Release,
02082   OLEFontImpl_EnumConnectionPoints,
02083   OLEFontImpl_FindConnectionPoint
02084 };
02085 
02086 /************************************************************************
02087  * OLEFontImpl implementation of IPersistPropertyBag.
02088  */
02089 static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_QueryInterface(
02090    IPersistPropertyBag *iface, REFIID riid, LPVOID *ppvObj
02091 ) {
02092   OLEFontImpl *this = impl_from_IPersistPropertyBag(iface);
02093   return IFont_QueryInterface((IFont *)this,riid,ppvObj);
02094 }
02095 
02096 static ULONG WINAPI OLEFontImpl_IPersistPropertyBag_AddRef(
02097    IPersistPropertyBag *iface
02098 ) {
02099   OLEFontImpl *this = impl_from_IPersistPropertyBag(iface);
02100   return IFont_AddRef((IFont *)this);
02101 }
02102 
02103 static ULONG WINAPI OLEFontImpl_IPersistPropertyBag_Release(
02104    IPersistPropertyBag *iface
02105 ) {
02106   OLEFontImpl *this = impl_from_IPersistPropertyBag(iface);
02107   return IFont_Release((IFont *)this);
02108 }
02109 
02110 static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_GetClassID(
02111    IPersistPropertyBag *iface, CLSID *classid
02112 ) {
02113   FIXME("(%p,%p), stub!\n", iface, classid);
02114   return E_FAIL;
02115 }
02116 
02117 static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_InitNew(
02118    IPersistPropertyBag *iface
02119 ) {
02120   FIXME("(%p), stub!\n", iface);
02121   return S_OK;
02122 }
02123 
02124 static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_Load(
02125    IPersistPropertyBag *iface, IPropertyBag* pPropBag, IErrorLog* pErrorLog
02126 ) {
02127 /* (from Visual Basic 6 property bag)
02128          Name            =   "MS Sans Serif"
02129          Size            =   13.8
02130          Charset         =   0
02131          Weight          =   400
02132          Underline       =   0   'False
02133          Italic          =   0   'False
02134          Strikethrough   =   0   'False
02135 */
02136     static const WCHAR sAttrName[] = {'N','a','m','e',0};
02137     static const WCHAR sAttrSize[] = {'S','i','z','e',0};
02138     static const WCHAR sAttrCharset[] = {'C','h','a','r','s','e','t',0};
02139     static const WCHAR sAttrWeight[] = {'W','e','i','g','h','t',0};
02140     static const WCHAR sAttrUnderline[] = {'U','n','d','e','r','l','i','n','e',0};
02141     static const WCHAR sAttrItalic[] = {'I','t','a','l','i','c',0};
02142     static const WCHAR sAttrStrikethrough[] = {'S','t','r','i','k','e','t','h','r','o','u','g','h',0};
02143     VARIANT rawAttr;
02144     VARIANT valueAttr;
02145     HRESULT iRes = S_OK;
02146     OLEFontImpl *this = impl_from_IPersistPropertyBag(iface);
02147 
02148     VariantInit(&rawAttr);
02149     VariantInit(&valueAttr);
02150 
02151     if (iRes == S_OK) {
02152         iRes = IPropertyBag_Read(pPropBag, sAttrName, &rawAttr, pErrorLog);
02153         if (iRes == S_OK)
02154         {
02155             iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_BSTR);
02156             if (iRes == S_OK)
02157                 iRes = IFont_put_Name((IFont *)this, V_BSTR(&valueAttr));
02158         }
02159         else if (iRes == E_INVALIDARG)
02160             iRes = S_OK;
02161         VariantClear(&rawAttr);
02162         VariantClear(&valueAttr);
02163     }
02164 
02165     if (iRes == S_OK) {
02166         iRes = IPropertyBag_Read(pPropBag, sAttrSize, &rawAttr, pErrorLog);
02167         if (iRes == S_OK)
02168         {
02169             iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_CY);
02170             if (iRes == S_OK)
02171                 iRes = IFont_put_Size((IFont *)this, V_CY(&valueAttr));
02172         }
02173         else if (iRes == E_INVALIDARG)
02174             iRes = S_OK;
02175         VariantClear(&rawAttr);
02176         VariantClear(&valueAttr);
02177     }
02178 
02179     if (iRes == S_OK) {
02180         iRes = IPropertyBag_Read(pPropBag, sAttrCharset, &rawAttr, pErrorLog);
02181         if (iRes == S_OK)
02182         {
02183             iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_I2);
02184             if (iRes == S_OK)
02185                 iRes = IFont_put_Charset((IFont *)this, V_I2(&valueAttr));
02186         }
02187         else if (iRes == E_INVALIDARG)
02188             iRes = S_OK;
02189         VariantClear(&rawAttr);
02190         VariantClear(&valueAttr);
02191     }
02192 
02193     if (iRes == S_OK) {
02194         iRes = IPropertyBag_Read(pPropBag, sAttrWeight, &rawAttr, pErrorLog);
02195         if (iRes == S_OK)
02196         {
02197             iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_I2);
02198             if (iRes == S_OK)
02199                 iRes = IFont_put_Weight((IFont *)this, V_I2(&valueAttr));
02200         }
02201         else if (iRes == E_INVALIDARG)
02202             iRes = S_OK;
02203         VariantClear(&rawAttr);
02204         VariantClear(&valueAttr);
02205 
02206     }
02207 
02208     if (iRes == S_OK) {
02209         iRes = IPropertyBag_Read(pPropBag, sAttrUnderline, &rawAttr, pErrorLog);
02210         if (iRes == S_OK)
02211         {
02212             iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_BOOL);
02213             if (iRes == S_OK)
02214                 iRes = IFont_put_Underline((IFont *)this, V_BOOL(&valueAttr));
02215         }
02216         else if (iRes == E_INVALIDARG)
02217             iRes = S_OK;
02218         VariantClear(&rawAttr);
02219         VariantClear(&valueAttr);
02220     }
02221 
02222     if (iRes == S_OK) {
02223         iRes = IPropertyBag_Read(pPropBag, sAttrItalic, &rawAttr, pErrorLog);
02224         if (iRes == S_OK)
02225         {
02226             iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_BOOL);
02227             if (iRes == S_OK)
02228                 iRes = IFont_put_Italic((IFont *)this, V_BOOL(&valueAttr));
02229         }
02230         else if (iRes == E_INVALIDARG)
02231             iRes = S_OK;
02232         VariantClear(&rawAttr);
02233         VariantClear(&valueAttr);
02234     }
02235 
02236     if (iRes == S_OK) {
02237         iRes = IPropertyBag_Read(pPropBag, sAttrStrikethrough, &rawAttr, pErrorLog);
02238         if (iRes == S_OK)
02239         {
02240             iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_BOOL);
02241             if (iRes == S_OK)
02242                 IFont_put_Strikethrough((IFont *)this, V_BOOL(&valueAttr));
02243         }
02244         else if (iRes == E_INVALIDARG)
02245             iRes = S_OK;
02246         VariantClear(&rawAttr);
02247         VariantClear(&valueAttr);
02248     }
02249 
02250     if (FAILED(iRes))
02251         WARN("-- 0x%08x\n", iRes);
02252     return iRes;
02253 }
02254 
02255 static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_Save(
02256    IPersistPropertyBag *iface, IPropertyBag* pPropBag, BOOL fClearDirty,
02257    BOOL fSaveAllProperties
02258 ) {
02259   FIXME("(%p,%p,%d,%d), stub!\n", iface, pPropBag, fClearDirty, fSaveAllProperties);
02260   return E_FAIL;
02261 }
02262 
02263 static const IPersistPropertyBagVtbl OLEFontImpl_IPersistPropertyBag_VTable = 
02264 {
02265   OLEFontImpl_IPersistPropertyBag_QueryInterface,
02266   OLEFontImpl_IPersistPropertyBag_AddRef,
02267   OLEFontImpl_IPersistPropertyBag_Release,
02268 
02269   OLEFontImpl_IPersistPropertyBag_GetClassID,
02270   OLEFontImpl_IPersistPropertyBag_InitNew,
02271   OLEFontImpl_IPersistPropertyBag_Load,
02272   OLEFontImpl_IPersistPropertyBag_Save
02273 };
02274 
02275 /************************************************************************
02276  * OLEFontImpl implementation of IPersistStreamInit.
02277  */
02278 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_QueryInterface(
02279    IPersistStreamInit *iface, REFIID riid, LPVOID *ppvObj
02280 ) {
02281   OLEFontImpl *this = impl_from_IPersistStreamInit(iface);
02282   return IFont_QueryInterface((IFont *)this,riid,ppvObj);
02283 }
02284 
02285 static ULONG WINAPI OLEFontImpl_IPersistStreamInit_AddRef(
02286    IPersistStreamInit *iface
02287 ) {
02288   OLEFontImpl *this = impl_from_IPersistStreamInit(iface);
02289   return IFont_AddRef((IFont *)this);
02290 }
02291 
02292 static ULONG WINAPI OLEFontImpl_IPersistStreamInit_Release(
02293    IPersistStreamInit *iface
02294 ) {
02295   OLEFontImpl *this = impl_from_IPersistStreamInit(iface);
02296   return IFont_Release((IFont *)this);
02297 }
02298 
02299 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_GetClassID(
02300    IPersistStreamInit *iface, CLSID *classid
02301 ) {
02302   FIXME("(%p,%p), stub!\n", iface, classid);
02303   return E_FAIL;
02304 }
02305 
02306 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_IsDirty(
02307    IPersistStreamInit *iface
02308 ) {
02309   FIXME("(%p), stub!\n", iface);
02310   return E_FAIL;
02311 }
02312 
02313 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_Load(
02314    IPersistStreamInit *iface, LPSTREAM pStm
02315 ) {
02316   FIXME("(%p,%p), stub!\n", iface, pStm);
02317   return E_FAIL;
02318 }
02319 
02320 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_Save(
02321    IPersistStreamInit *iface, LPSTREAM pStm, BOOL fClearDirty
02322 ) {
02323   FIXME("(%p,%p,%d), stub!\n", iface, pStm, fClearDirty);
02324   return E_FAIL;
02325 }
02326 
02327 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_GetSizeMax(
02328    IPersistStreamInit *iface, ULARGE_INTEGER *pcbSize
02329 ) {
02330   FIXME("(%p,%p), stub!\n", iface, pcbSize);
02331   return E_FAIL;
02332 }
02333 
02334 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_InitNew(
02335    IPersistStreamInit *iface
02336 ) {
02337   FIXME("(%p), stub!\n", iface);
02338   return S_OK;
02339 }
02340 
02341 static const IPersistStreamInitVtbl OLEFontImpl_IPersistStreamInit_VTable = 
02342 {
02343   OLEFontImpl_IPersistStreamInit_QueryInterface,
02344   OLEFontImpl_IPersistStreamInit_AddRef,
02345   OLEFontImpl_IPersistStreamInit_Release,
02346 
02347   OLEFontImpl_IPersistStreamInit_GetClassID,
02348   OLEFontImpl_IPersistStreamInit_IsDirty,
02349   OLEFontImpl_IPersistStreamInit_Load,
02350   OLEFontImpl_IPersistStreamInit_Save,
02351   OLEFontImpl_IPersistStreamInit_GetSizeMax,
02352   OLEFontImpl_IPersistStreamInit_InitNew
02353 };
02354 
02355 /************************************************************************
02356  * OLEFontImpl_Construct
02357  *
02358  * This method will construct a new instance of the OLEFontImpl
02359  * class.
02360  *
02361  * The caller of this method must release the object when it's
02362  * done with it.
02363  */
02364 static OLEFontImpl* OLEFontImpl_Construct(const FONTDESC *fontDesc)
02365 {
02366   OLEFontImpl* newObject = 0;
02367 
02368   /*
02369    * Allocate space for the object.
02370    */
02371   newObject = HeapAlloc(GetProcessHeap(), 0, sizeof(OLEFontImpl));
02372 
02373   if (newObject==0)
02374     return newObject;
02375 
02376   /*
02377    * Initialize the virtual function table.
02378    */
02379   newObject->lpVtbl = &OLEFontImpl_VTable;
02380   newObject->lpvtblIDispatch = &OLEFontImpl_IDispatch_VTable;
02381   newObject->lpvtblIPersistStream = &OLEFontImpl_IPersistStream_VTable;
02382   newObject->lpvtblIConnectionPointContainer = &OLEFontImpl_IConnectionPointContainer_VTable;
02383   newObject->lpvtblIPersistPropertyBag = &OLEFontImpl_IPersistPropertyBag_VTable;
02384   newObject->lpvtblIPersistStreamInit = &OLEFontImpl_IPersistStreamInit_VTable;
02385 
02386   /*
02387    * Start with one reference count. The caller of this function
02388    * must release the interface pointer when it is done.
02389    */
02390   newObject->ref = 1;
02391 
02392   /*
02393    * Copy the description of the font in the object.
02394    */
02395   assert(fontDesc->cbSizeofstruct >= sizeof(FONTDESC));
02396 
02397   newObject->description.cbSizeofstruct = sizeof(FONTDESC);
02398   newObject->description.lpstrName = HeapAlloc(GetProcessHeap(),
02399                            0,
02400                            (lstrlenW(fontDesc->lpstrName)+1) * sizeof(WCHAR));
02401   strcpyW(newObject->description.lpstrName, fontDesc->lpstrName);
02402   newObject->description.cySize         = fontDesc->cySize;
02403   newObject->description.sWeight        = fontDesc->sWeight;
02404   newObject->description.sCharset       = fontDesc->sCharset;
02405   newObject->description.fItalic        = fontDesc->fItalic;
02406   newObject->description.fUnderline     = fontDesc->fUnderline;
02407   newObject->description.fStrikethrough = fontDesc->fStrikethrough;
02408 
02409   /*
02410    * Initializing all the other members.
02411    */
02412   newObject->gdiFont  = 0;
02413   newObject->dirty = TRUE;
02414   newObject->cyLogical  = 72L;
02415   newObject->cyHimetric = 2540L;
02416   newObject->pPropertyNotifyCP = NULL;
02417   newObject->pFontEventsCP = NULL;
02418 
02419   CreateConnectionPoint((IUnknown*)newObject, &IID_IPropertyNotifySink, &newObject->pPropertyNotifyCP);
02420   CreateConnectionPoint((IUnknown*)newObject, &IID_IFontEventsDisp, &newObject->pFontEventsCP);
02421 
02422   if (!newObject->pPropertyNotifyCP || !newObject->pFontEventsCP)
02423   {
02424     OLEFontImpl_Destroy(newObject);
02425     return NULL;
02426   }
02427 
02428   InterlockedIncrement(&ifont_cnt);
02429 
02430   TRACE("returning %p\n", newObject);
02431   return newObject;
02432 }
02433 
02434 /************************************************************************
02435  * OLEFontImpl_Destroy
02436  *
02437  * This method is called by the Release method when the reference
02438  * count goes down to 0. It will free all resources used by
02439  * this object.
02440  */
02441 static void OLEFontImpl_Destroy(OLEFontImpl* fontDesc)
02442 {
02443   TRACE("(%p)\n", fontDesc);
02444 
02445   HeapFree(GetProcessHeap(), 0, fontDesc->description.lpstrName);
02446 
02447   if (fontDesc->pPropertyNotifyCP)
02448       IConnectionPoint_Release(fontDesc->pPropertyNotifyCP);
02449   if (fontDesc->pFontEventsCP)
02450       IConnectionPoint_Release(fontDesc->pFontEventsCP);
02451 
02452   HeapFree(GetProcessHeap(), 0, fontDesc);
02453 }
02454 
02455 /*******************************************************************************
02456  * StdFont ClassFactory
02457  */
02458 typedef struct
02459 {
02460     /* IUnknown fields */
02461     const IClassFactoryVtbl    *lpVtbl;
02462     LONG                        ref;
02463 } IClassFactoryImpl;
02464 
02465 static HRESULT WINAPI
02466 SFCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
02467     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
02468 
02469     FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
02470     return E_NOINTERFACE;
02471 }
02472 
02473 static ULONG WINAPI
02474 SFCF_AddRef(LPCLASSFACTORY iface) {
02475     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
02476     return InterlockedIncrement(&This->ref);
02477 }
02478 
02479 static ULONG WINAPI SFCF_Release(LPCLASSFACTORY iface) {
02480     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
02481     /* static class, won't be  freed */
02482     return InterlockedDecrement(&This->ref);
02483 }
02484 
02485 static HRESULT WINAPI SFCF_CreateInstance(
02486     LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
02487 ) {
02488     return OleCreateFontIndirect(NULL,riid,ppobj);
02489 
02490 }
02491 
02492 static HRESULT WINAPI SFCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
02493     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
02494     FIXME("(%p)->(%d),stub!\n",This,dolock);
02495     return S_OK;
02496 }
02497 
02498 static const IClassFactoryVtbl SFCF_Vtbl = {
02499     SFCF_QueryInterface,
02500     SFCF_AddRef,
02501     SFCF_Release,
02502     SFCF_CreateInstance,
02503     SFCF_LockServer
02504 };
02505 static IClassFactoryImpl STDFONT_CF = {&SFCF_Vtbl, 1 };
02506 
02507 void _get_STDFONT_CF(LPVOID *ppv) { *ppv = &STDFONT_CF; }

Generated on Mon May 28 2012 04:25:25 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.