
/*
 *@@sourcefile xfontobj.c:
 *      This file contains SOM code for the following XWorkplace classes:
 *
 *      --  XWPFontObject: a subclass of WPTransient. One instance
 *                  is created in an XWPFontFolder for each font that
 *                  is installed on the system.
 *
 *@@added V0.9.7 (2001-01-12) [umoeller]
 *@@somclass XWPFontObject fono_
 *@@somclass M_XWPFontObject fonoM_
 */

/*
 *      Copyright (C) 2001-2002 Ulrich M”ller.
 *      This file is part of the XWorkplace source package.
 *      XWorkplace is free software; you can redistribute it and/or modify
 *      it under the terms of the GNU General Public License as published
 *      by the Free Software Foundation, in version 2 as it comes in the
 *      "COPYING" file of the XWorkplace main distribution.
 *      This program is distributed in the hope that it will be useful,
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *      GNU General Public License for more details.
 */

/*
 *  This file was generated by the SOM Compiler and Emitter Framework.
 *  Generated using:
 *      SOM Emitter emitctm: 2.41
 */

#ifndef SOM_Module_xfontobj_Source
#define SOM_Module_xfontobj_Source
#endif
#define XWPFontObject_Class_Source
#define M_XWPFontObject_Class_Source

#pragma strings(readonly)

/*
 *  Suggested #include order:
 *  1)  os2.h
 *  2)  C library headers
 *  3)  setup.h (code generation and debugging options)
 *  4)  headers in helpers\
 *  5)  at least one SOM implementation header (*.ih)
 *  6)  dlgids.h, headers in shared\ (as needed)
 *  7)  headers in implementation dirs (e.g. filesys\, as needed)
 *  8)  #pragma hdrstop and then more SOM headers which crash with precompiled headers
 */

#define INCL_DOSSEMAPHORES
#define INCL_DOSEXCEPTIONS
#define INCL_DOSPROCESS
#define INCL_DOSERRORS

#define INCL_WINSHELLDATA
#include <os2.h>

// C library headers
#include <stdio.h>              // needed for except.h
#include <setjmp.h>             // needed for except.h
#include <assert.h>             // needed for except.h

// generic headers
#include "setup.h"                      // code generation and debugging options

// headers in /helpers
#include "helpers\except.h"             // exception handling
#include "helpers\stringh.h"            // string helper routines

// SOM headers which don't crash with prec. header files
#include "xfont.ih"
#include "xfontobj.ih"

// XWorkplace implementation headers
#include "dlgids.h"                     // all the IDs that are shared with NLS
#include "shared\common.h"              // the majestic XWorkplace include file
#include "shared\helppanels.h"          // all XWorkplace help panel IDs
#include "shared\kernel.h"              // XWorkplace Kernel
#include "shared\notebook.h"            // generic XWorkplace notebook handling

#include "config\fonts.h"               // font folder implementation

// other SOM headers
#pragma hdrstop

/* ******************************************************************
 *
 *   Object details
 *
 ********************************************************************/

/*
 *@@ FNTO_DETAILS:
 *      extended object details for XWPFontObject
 *      (used in font folder Details view)
 */

typedef struct _FNTO_DETAILS
{
    PSZ     pszFontFile;            // points to _pszFontFile instance string

    PSZ     pszFontFamily;          // points to _pszFontFamily instance string

    PSZ     pszFontFileError;       // points to _pszFontFileError instance string
} FNTO_DETAILS, *PFNTO_DETAILS;

// extra data fields for XWPFontObject object details:
#define FNTO_EXTRAFIELDS 3
        // we add one field
static CLASSFIELDINFO G_acfiFontObject[FNTO_EXTRAFIELDS];
        // we add three fields
// See XWPFontObject::wpclsQueryDetailsInfo for details.

/* ******************************************************************
 *
 *   XWPFontObject instance methods
 *
 ********************************************************************/

/*
 *@@ xwpSetFontFile:
 *      sets the font file data for this font object.
 *
 *      Internal method, do not call this externally.
 */

SOM_Scope BOOL  SOMLINK fono_xwpSetFontFile(XWPFontObject *somSelf,
                                            PSZ pszFontFile)
{
    BOOL brc = FALSE;
    WPObject *pobjLock = NULL;

    XWPFontObjectData *somThis = XWPFontObjectGetData(somSelf);
    XWPFontObjectMethodDebug("XWPFontObject","fono_xwpSetFontFile");

    TRY_LOUD(excpt1)
    {
        if (pobjLock = cmnLockObject(somSelf))
        {
            strhStore(&_pszFontFile, pszFontFile, NULL);
            brc = TRUE;
        }
    }
    CATCH(excpt1) {} END_CATCH();

    if (pobjLock)
        _wpReleaseObjectMutexSem(pobjLock);

    return brc;
}

/*
 *@@ xwpQueryFontFile:
 *      returns the full path specification of the font file
 *      that this font object represents (e.g. "F:\PSFONTS\HELV.OFM")
 *      or NULL on errors.
 *
 *      pszFontFile receives the font file spec and is assumed to
 *      be at least CCHMAXPATH in size.
 */

SOM_Scope BOOL  SOMLINK fono_xwpQueryFontFile(XWPFontObject *somSelf,
                                              PSZ pszFontFile)
{
    BOOL brc = FALSE;
    WPObject *pobjLock = NULL;

    XWPFontObjectData *somThis = XWPFontObjectGetData(somSelf);
    XWPFontObjectMethodDebug("XWPFontObject","fono_xwpQueryFontFile");

    TRY_LOUD(excpt1)
    {
        if (pobjLock = cmnLockObject(somSelf))
        {
            if (_pszFontFile)
            {
                strcpy(pszFontFile, _pszFontFile);
                brc = TRUE;
            }
        }
    }
    CATCH(excpt1) {} END_CATCH();

    if (pobjLock)
        _wpReleaseObjectMutexSem(pobjLock);

    return brc;
}

/*
 *@@ xwpSetFontFamily:
 *      sets the font family data for this font object.
 *
 *      Internal method, do not call this externally.
 */

SOM_Scope BOOL  SOMLINK fono_xwpSetFontFamily(XWPFontObject *somSelf,
                                              PSZ pszFontFamily)
{
    BOOL brc = FALSE;
    WPObject *pobjLock = NULL;

    XWPFontObjectData *somThis = XWPFontObjectGetData(somSelf);
    XWPFontObjectMethodDebug("XWPFontObject","fono_xwpSetFontFamily");

    TRY_LOUD(excpt1)
    {
        if (pobjLock = cmnLockObject(somSelf))
        {
            strhStore(&_pszFontFamily, pszFontFamily, NULL);
            brc = TRUE;
        }
    }
    CATCH(excpt1) {} END_CATCH();

    if (pobjLock)
        _wpReleaseObjectMutexSem(pobjLock);

    return brc;
}

/*
 *@@ xwpQueryFontFamily:
 *      returns the family specification of the font that this font
 *      object represents (e.g. "Helvetica") or NULL on errors.
 *
 *      While the font object title is always set to the font
 *      face name (which is the family name plus possibly "Bold"
 *      etc.), the family name itself has to be retrieved using
 *      this method.
 *
 *      pszFontFamily receives the font file spec and is assumed to
 *      be at least 32 chars in size (which, unfortunately, is the
 *      limit for font specifications in OS/2).
 */

SOM_Scope BOOL  SOMLINK fono_xwpQueryFontFamily(XWPFontObject *somSelf,
                                                PSZ pszFontFamily)
{
    BOOL brc = FALSE;
    WPObject *pobjLock = NULL;

    XWPFontObjectData *somThis = XWPFontObjectGetData(somSelf);
    XWPFontObjectMethodDebug("XWPFontObject","fono_xwpQueryFontFamily");

    TRY_LOUD(excpt1)
    {
        if (pobjLock = cmnLockObject(somSelf))
        {
            if (_pszFontFamily)
            {
                strcpy(pszFontFamily, _pszFontFamily);
                brc = TRUE;
            }
        }
    }
    CATCH(excpt1) {} END_CATCH();

    if (pobjLock)
        _wpReleaseObjectMutexSem(pobjLock);

    return brc;
}

/*
 *@@ xwpSetFontFileError:
 *      sets an OS/2 error code on the font file object.
 *      This is displayed in Details view.
 *
 *      This also prepares the pszFontFileError member.
 */

SOM_Scope BOOL  SOMLINK fono_xwpSetFontFileError(XWPFontObject *somSelf,
                                                 ULONG arc)
{
    BOOL brc = FALSE;
    WPObject *pobjLock = NULL;

    XWPFontObjectData *somThis = XWPFontObjectGetData(somSelf);
    XWPFontObjectMethodDebug("XWPFontObject","fono_xwpSetFontFileError");

    TRY_LOUD(excpt1)
    {
        if (pobjLock = cmnLockObject(somSelf))
        {
            CHAR szError2[200];
            PSZ  pszError = NULL;

            _arcFontFileError = arc;

            switch (arc)
            {
                case NO_ERROR:
                    pszError = NULL;
                break;

                // give descriptions for a few common errors:
                case ERROR_FILE_NOT_FOUND:
                    pszError = "File not found.";
                break;

                case ERROR_PATH_NOT_FOUND:
                    pszError = "Path not found.";
                break;

                case ERROR_BAD_FORMAT:      // returned by our font description
                    pszError = "Unknown font format.";
                break;

                default:
                    sprintf(szError2, "Error %d occurred.", arc);
                    pszError = szError2;
            }

            strhStore(&_pszFontFileError, pszError, NULL);

            brc = TRUE;
        }
    }
    CATCH(excpt1) {} END_CATCH();

    if (pobjLock)
        _wpReleaseObjectMutexSem(pobjLock);

    return brc;
}

/*
 *@@ xwpQueryFontFileError:
 *      returns the error code previously set with
 *      XWPFontObject::xwpSetFontFileError.
 */

SOM_Scope ULONG  SOMLINK fono_xwpQueryFontFileError(XWPFontObject *somSelf)
{
    XWPFontObjectData *somThis = XWPFontObjectGetData(somSelf);
    XWPFontObjectMethodDebug("XWPFontObject","fono_xwpQueryFontFileError");

    return (_arcFontFileError);
}

/*
 *@@ xwpValidateFont:
 *
 */

SOM_Scope ULONG  SOMLINK fono_xwpValidateFont(XWPFontObject *somSelf)
{
    // XWPFontObjectData *somThis = XWPFontObjectGetData(somSelf);
    XWPFontObjectMethodDebug("XWPFontObject","fono_xwpValidateFont");

    return 1;           // @@todo
}

/*
 *@@ wpInitData:
 *      this WPObject instance method gets called when the
 *      object is being initialized (on wake-up or creation).
 *      We initialize our additional instance data here.
 *      Always call the parent method first.
 */

SOM_Scope void  SOMLINK fono_wpInitData(XWPFontObject *somSelf)
{
    XWPFontObjectData *somThis = XWPFontObjectGetData(somSelf);
    XWPFontObjectMethodDebug("XWPFontObject","fono_wpInitData");

    XWPFontObject_parent_WPTransient_wpInitData(somSelf);

    _pszFontFile = NULL;
    _pszFontFamily = NULL;

    _arcFontFileError = NO_ERROR;
    _pszFontFileError = NULL;

    _fShowingOpenViewMenu = FALSE;
}

/*
 *@@ wpUnInitData:
 *      this WPObject instance method is called when the object
 *      is destroyed as a SOM object, either because it's being
 *      made dormant or being deleted. All allocated resources
 *      should be freed here.
 *      The parent method must always be called last.
 */

SOM_Scope void  SOMLINK fono_wpUnInitData(XWPFontObject *somSelf)
{
    XWPFontObjectData *somThis = XWPFontObjectGetData(somSelf);
    XWPFontObjectMethodDebug("XWPFontObject","fono_wpUnInitData");

    XWPFontObject_parent_WPTransient_wpUnInitData(somSelf);

    strhStore(&_pszFontFile, NULL, NULL);
    strhStore(&_pszFontFamily, NULL, NULL);
    strhStore(&_pszFontFileError, NULL, NULL);
}

/*
 *@@ wpSetupOnce:
 *      this WPObject method allows special object handling
 *      based on a creation setup string after an object has
 *      been fully created.
 *      As opposed to WPObject::wpSetup, this method _only_
 *      gets called during object creation. The WPObject
 *      implementation calls wpSetup in turn.
 *      If FALSE is returned, object creation is aborted.
 */

SOM_Scope BOOL  SOMLINK fono_wpSetupOnce(XWPFontObject *somSelf,
                                         PSZ pszSetupString)
{
    BOOL    brc = FALSE;
    CHAR    szTemp[CCHMAXPATH];
    ULONG   cbTemp;

    // XWPFontObjectData *somThis = XWPFontObjectGetData(somSelf);
    XWPFontObjectMethodDebug("XWPFontObject","fono_wpSetupOnce");

    brc = XWPFontObject_parent_WPTransient_wpSetupOnce(somSelf,
                                                       pszSetupString);

    cbTemp = sizeof(szTemp);
    if (_wpScanSetupString(somSelf,
                           pszSetupString,
                           "FONTFILE",
                           szTemp,
                           &cbTemp))
    {
        _xwpSetFontFile(somSelf, szTemp);
    }

    cbTemp = sizeof(szTemp);
    if (_wpScanSetupString(somSelf,
                           pszSetupString,
                           "FONTFAMILY",
                           szTemp,
                           &cbTemp))
    {
        _xwpSetFontFamily(somSelf, szTemp);
    }

    cbTemp = sizeof(szTemp);
    if (_wpScanSetupString(somSelf,
                           pszSetupString,
                           "FONTFILEERROR",
                           szTemp,
                           &cbTemp))
    {
        APIRET arc = atoi(szTemp);
        // error code delivered:
        _xwpSetFontFileError(somSelf, arc);
    }
    // otherwise defaults to 0 (NO_ERROR)

    return brc;
}

/*
 *@@ wpQueryDetailsData:
 *      this instance method must fill in the details
 *      data which was abstractly defined by
 *      M_XWPFontObject::wpclsQueryDetailsInfo.
 *      We'll fill in the trash object details here.
 */

SOM_Scope ULONG  SOMLINK fono_wpQueryDetailsData(XWPFontObject *somSelf,
                                                 PVOID* ppDetailsData,
                                                 PULONG pcp)
{
    // return value: TRUE or FALSE, even though it's a ULONG
    ULONG ulrc;

    XWPFontObjectData *somThis = XWPFontObjectGetData(somSelf);
    XWPFontObjectMethodDebug("XWPFontObject","fono_wpQueryDetailsData");

    // call the parent first; this moves ppDetailsData to
    // point to the new data added by XWPFontObject
    // (in the wpclsQueryDetailsInfo structure)
    ulrc = XWPFontObject_parent_WPTransient_wpQueryDetailsData(somSelf,
                                                               ppDetailsData,
                                                               pcp);

    // pointer valid?
    if (ppDetailsData)
    {
        PFNTO_DETAILS pDetails = (PFNTO_DETAILS)*ppDetailsData;
        pDetails->pszFontFile = _pszFontFile;
        pDetails->pszFontFamily = _pszFontFamily;
        pDetails->pszFontFileError = _pszFontFileError;

        // move the pointer past our details structure
        *ppDetailsData = ((PBYTE) (*ppDetailsData)) + sizeof(FNTO_DETAILS);
    }
    else
    {
        // ppDetailsData == NULL:
        // caller is querying size of buffer
        *pcp += sizeof(FNTO_DETAILS);
    }

    return (ulrc);
}

/*
 *@@ wpFilterPopupMenu:
 *      this WPObject instance method allows the object to
 *      filter out unwanted menu items from the context menu.
 *      This gets called before wpModifyPopupMenu.
 */

SOM_Scope ULONG  SOMLINK fono_wpFilterPopupMenu(XWPFontObject *somSelf,
                                                ULONG ulFlags,
                                                HWND hwndCnr,
                                                BOOL fMultiSelect)
{
    // XWPFontObjectData *somThis = XWPFontObjectGetData(somSelf);
    XWPFontObjectMethodDebug("XWPFontObject","fono_wpFilterPopupMenu");

    return (XWPFontObject_parent_WPTransient_wpFilterPopupMenu(somSelf,
                                                               ulFlags,
                                                               hwndCnr,
                                                               fMultiSelect)
            & ~(    CTXT_SETTINGS
                  | CTXT_COPY
                  | CTXT_DELETE
                  | CTXT_MOVE
                  | CTXT_NEW
                  | CTXT_PRINT)
        );
}

/*
 *@@ wpModifyPopupMenu:
 *      this WPObject instance methods gets called by the WPS
 *      when a context menu needs to be built for the object
 *      and allows the object to manipulate its context menu.
 *      This gets called _after_ wpFilterPopupMenu.
 */

SOM_Scope BOOL  SOMLINK fono_wpModifyPopupMenu(XWPFontObject *somSelf,
                                               HWND hwndMenu,
                                               HWND hwndCnr,
                                               ULONG iPosition)
{
    BOOL brc = FALSE;
    // XWPFontObjectData *somThis = XWPFontObjectGetData(somSelf);
    XWPFontObjectMethodDebug("XWPFontObject","fono_wpModifyPopupMenu");

    if (XWPFontObject_parent_WPTransient_wpModifyPopupMenu(somSelf,
                                                           hwndMenu,
                                                           hwndCnr,
                                                           iPosition))
    {
        fonModifyFontPopupMenu(somSelf, hwndMenu);
        brc = TRUE;
    }

    return brc;
}

/*
 *@@ wpMenuItemSelected:
 *      this WPObject method processes menu selections.
 *      This must be overridden to support new menu
 *      items which have been added in wpModifyPopupMenu.
 *
 *      See XFldObject::wpMenuItemSelected for additional
 *      remarks.
 */

SOM_Scope BOOL  SOMLINK fono_wpMenuItemSelected(XWPFontObject *somSelf,
                                                HWND hwndFrame,
                                                ULONG ulMenuId)
{
    // XWPFontObjectData *somThis = XWPFontObjectGetData(somSelf);
    XWPFontObjectMethodDebug("XWPFontObject","fono_wpMenuItemSelected");

    if (fonMenuItemSelected(somSelf, ulMenuId))
        return TRUE;

    return (XWPFontObject_parent_WPTransient_wpMenuItemSelected(somSelf,
                                                                hwndFrame,
                                                                ulMenuId));
}

/*
 *@@ wpMenuItemHelpSelected:
 *      this instance method gets called when help is
 *      requested for a menu item in the object's context menu.
 *      We need to display help for our new menu items here.
 */

SOM_Scope BOOL  SOMLINK fono_wpMenuItemHelpSelected(XWPFontObject *somSelf,
                                                    ULONG MenuId)
{
    // XWPFontObjectData *somThis = XWPFontObjectGetData(somSelf);
    XWPFontObjectMethodDebug("XWPFontObject","fono_wpMenuItemHelpSelected");

    if (fonMenuItemHelpSelected(somSelf, MenuId))
        return TRUE;

    return (XWPFontObject_parent_WPTransient_wpMenuItemHelpSelected(somSelf,
                                                                    MenuId));
}

/*
 *@@ wpQueryDefaultView:
 *      this returns the default view of the object, which
 *      for XWPClassList is the "Class list" view. For
 *      user-defined views (which ours is one of), this
 *      must be the same as the menu item ID in the "Open"
 *      submenu.
 */

SOM_Scope ULONG  SOMLINK fono_wpQueryDefaultView(XWPFontObject *somSelf)
{
    // XWPFontObjectData *somThis = XWPFontObjectGetData(somSelf);
    XWPFontObjectMethodDebug("XWPFontObject","fono_wpQueryDefaultView");

    return *G_pulVarMenuOfs + ID_XFMI_OFS_XWPVIEW;
}

/*
 *@@ wpOpen:
 *      this WPObject instance method gets called when
 *      a new view needs to be opened. Normally, this
 *      gets called after wpViewObject has scanned the
 *      object's USEITEMs and has determined that a new
 *      view is needed.
 *
 *      This _normally_ runs on thread 1 of the WPS, but
 *      this is not always the case. If this gets called
 *      in response to a menu selection from the "Open"
 *      submenu or a double-click in the folder, this runs
 *      on the thread of the folder (which _normally_ is
 *      thread 1). However, if this results from WinOpenObject
 *      or an OPEN setup string, this will not be on thread 1.
 *
 *      We need to support the new "Sample" here.
 *
 *      The implementation is in fonCreateFontSampleView.
 */

SOM_Scope HWND  SOMLINK fono_wpOpen(XWPFontObject *somSelf, HWND hwndCnr,
                                    ULONG ulView, ULONG param)
{
    // XWPFontObjectData *somThis = XWPFontObjectGetData(somSelf);
    XWPFontObjectMethodDebug("XWPFontObject","fono_wpOpen");

    // we only support the "Sample" view; suppress all others
    if (ulView == *G_pulVarMenuOfs + ID_XFMI_OFS_XWPVIEW)
        return (fonCreateFontSampleView(somSelf,
                                        WinQueryAnchorBlock(hwndCnr),
                                        ulView));

    return NULLHANDLE;
}

/* ******************************************************************
 *
 *   XWPFontObject class methods
 *
 ********************************************************************/

/*
 *@@ xwpclsQueryFontSampleHints:
 *      returns the display hint flags for the font sample views.
 *
 *      This is any combination of:
 *
 *      --  HINTS_MAX_ASCENDER_DESCENDER_GRAYRECT   0x0001
 *
 *      --  HINTS_BASELINE_REDLINE                  0x0002
 *
 *      --  HINTS_LOWERCASEASCENT_REDRECT           0x0004
 *
 *      These flags are declared in include\config\fonts.h.
 */

SOM_Scope ULONG  SOMLINK fonoM_xwpclsQueryFontSampleHints(M_XWPFontObject *somSelf)
{
    /* M_XWPFontObjectData *somThis = M_XWPFontObjectGetData(somSelf); */
    M_XWPFontObjectMethodDebug("M_XWPFontObject","fonoM_xwpclsQueryFontSampleHints");

    return (G_ulFontSampleHints);
}

/*
 *@@ xwpclsSetFontSampleHints:
 *      reversely to M_XWPFontObject::xwpclsQueryFontSampleHints,
 *      this sets the display hint flags for the font sample views.
 *
 *      This affects all font sample views. All open font sample
 *      views are updated.
 */

SOM_Scope BOOL  SOMLINK fonoM_xwpclsSetFontSampleHints(M_XWPFontObject *somSelf,
                                                       ULONG ulHints)
{
    /* M_XWPFontObjectData *somThis = M_XWPFontObjectGetData(somSelf); */
    M_XWPFontObjectMethodDebug("M_XWPFontObject","fonoM_xwpclsSetFontSampleHints");

    if (G_ulFontSampleHints != ulHints)
    {
        G_ulFontSampleHints = ulHints;

        PrfWriteProfileData(HINI_USER,
                            (PSZ)INIAPP_XWORKPLACE,
                            (PSZ)INIKEY_FONTSAMPLEHINTS,
                            &G_ulFontSampleHints,
                            sizeof(G_ulFontSampleHints));

        // repaint all sample views
        fonInvalidateAllOpenSampleViews();
    }

    return TRUE;
}

/*
 *@@ wpclsInitData:
 *      this WPObject class method gets called when a class
 *      is loaded by the WPS (probably from within a
 *      somFindClass call) and allows the class to initialize
 *      itself.
 */

SOM_Scope void  SOMLINK fonoM_wpclsInitData(M_XWPFontObject *somSelf)
{
    PCLASSFIELDINFO pcfi;
    ULONG           i;
    // PNLSSTRINGS     pNLSStrings = cmnQueryNLSStrings();

    /* M_XWPFontObjectData *somThis = M_XWPFontObjectGetData(somSelf); */
    M_XWPFontObjectMethodDebug("M_XWPFontObject","fonoM_wpclsInitData");

    M_XWPFontObject_parent_M_WPTransient_wpclsInitData(somSelf);

    krnClassInitialized(G_pcszXWPFontObject);

    // load default hints
    i = sizeof(G_ulFontSampleHints);
    if (    (!PrfQueryProfileData(HINI_USER,
                                  (PSZ)INIAPP_XWORKPLACE,
                                  (PSZ)INIKEY_FONTSAMPLEHINTS,
                                  &G_ulFontSampleHints,
                                  &i))
         || (i == 0)
       )
        // not loaded: use default
        G_ulFontSampleHints = 0;

    // initialize the extra data file details
    // in the global variable at the top of this file
    for (i = 0, pcfi = G_acfiFontObject;
         i < FNTO_EXTRAFIELDS;
         i++, pcfi++)
    {
        memset((PCH)pcfi, 0, sizeof(CLASSFIELDINFO));

        pcfi->cb        = sizeof(CLASSFIELDINFO);

        // data column flags
        pcfi->flData    = CFA_SEPARATOR
                            | CFA_FIREADONLY
                            | CFA_VCENTER       // vertical align
                            // | CFA_LEFT          // horizontal align
                            // | CFA_INVISIBLE
                            ;

        // column title flags
        pcfi->flTitle   = CFA_FITITLEREADONLY
                            | CFA_VCENTER
                            | CFA_CENTER
                            ;

        pcfi->pNextFieldInfo = pcfi + 1;       /* point to next CLASSFIELDINFO */

        switch (i)
        {
            // first item: font filename
            case 0:
                pcfi->flCompare   = COMPARE_SUPPORTED | SORTBY_SUPPORTED;
                pcfi->pfnCompare   = 0; // (PFNCOMPARE)fnCompareExtensions;
                pcfi->flData            |= CFA_STRING | CFA_LEFT;
                pcfi->pTitleData        = cmnGetString(ID_XSSI_FONTFILE);  // pszFontFile
                pcfi->offFieldData      = (ULONG)(FIELDOFFSET(FNTO_DETAILS, pszFontFile));
                pcfi->ulLenFieldData    = sizeof(PSZ);
                pcfi->DefaultComparison = CMP_GREATER;
            break;

            // second item: font family
            case 1:
                pcfi->flCompare   = COMPARE_SUPPORTED | SORTBY_SUPPORTED;
                pcfi->pfnCompare   = 0; // (PFNCOMPARE)fnCompareExtensions;
                pcfi->flData            |= CFA_STRING | CFA_LEFT;
                pcfi->pTitleData        = cmnGetString(ID_XSSI_FONTFAMILY);  // pszFontFamily
                pcfi->offFieldData      = (ULONG)(FIELDOFFSET(FNTO_DETAILS, pszFontFamily));
                pcfi->ulLenFieldData    = sizeof(PSZ);
                pcfi->DefaultComparison = CMP_GREATER;
            break;

            // second item: font family
            case 2:
                pcfi->flCompare   = COMPARE_SUPPORTED | SORTBY_SUPPORTED;
                pcfi->pfnCompare   = 0; // (PFNCOMPARE)fnCompareExtensions;
                pcfi->flData            |= CFA_STRING | CFA_LEFT;
                pcfi->pTitleData        = cmnGetString(ID_XSSI_FONTERRORS);  // pszFontErrors
                pcfi->offFieldData      = (ULONG)(FIELDOFFSET(FNTO_DETAILS, pszFontFileError));
                pcfi->ulLenFieldData    = sizeof(PSZ);
                pcfi->DefaultComparison = CMP_GREATER;
            break;
        }   // end for
    } // end for

    // finally, terminate the linked list
    G_acfiFontObject[FNTO_EXTRAFIELDS-1].pNextFieldInfo = NULL;
}

/*
 *@@ wpclsCreateDefaultTemplates:
 *      this WPObject class method is called by the
 *      Templates folder to allow a class to
 *      create its default templates.
 *
 *      The default WPS behavior is to create new templates
 *      if the class default title is different from the
 *      existing templates.
 *
 *      Since we never want templates for font objects,
 *      we'll have to suppress this behavior.
 */

SOM_Scope BOOL  SOMLINK fonoM_wpclsCreateDefaultTemplates(M_XWPFontObject *somSelf,
                                                          WPObject* Folder)
{
    /* M_XWPFontObjectData *somThis = M_XWPFontObjectGetData(somSelf); */
    M_XWPFontObjectMethodDebug("M_XWPFontObject","fonoM_wpclsCreateDefaultTemplates");

    return TRUE;
    // means that the Templates folder should _not_ create templates
    // by itself; we pretend that we've done this
}

/*
 *@@ wpclsQueryDetailsInfo:
 *      this class method is called by the WPS to find out
 *      what details info objects of this class can provide.
 *      The "abstract" data returned by this function needs
 *      to be filled with instance information by
 *      XWPFontObject::wpQueryDetailsData.
 *      We'll define additional details for the trash objects
 *      here.
 */

SOM_Scope ULONG  SOMLINK fonoM_wpclsQueryDetailsInfo(M_XWPFontObject *somSelf,
                                                     PCLASSFIELDINFO* ppClassFieldInfo,
                                                     PULONG pSize)
{
    ULONG           ulParentColumns;
    PCLASSFIELDINFO pcfi;
    ULONG           i;

    /* M_XWPFontObjectData *somThis = M_XWPFontObjectGetData(somSelf); */
    M_XWPFontObjectMethodDebug("M_XWPFontObject","fonoM_wpclsQueryDetailsInfo");

    // always call the parent method first to retrieve the number of
    // details columns and any data already defined in the details buffer.
    // For WPTransient, these are probably only the default two fields
    // defined by WPObject (object title, object class).
    ulParentColumns = M_XWPFontObject_parent_M_WPTransient_wpclsQueryDetailsInfo(
                                                    somSelf,
                                                    ppClassFieldInfo,
                                                    pSize);

    // if pSize is non-NULL, we must add the size of our details
    // column data structure (that's "Query 2" in the WPS ref)
    if (pSize)
        *pSize += sizeof(FNTO_DETAILS);

    // if the request was for the chained fieldinfo structures
    // (ppClassFieldInfo is non-NULL), link the new ones in
    if (ppClassFieldInfo)
    {
        // if the beginning of the chain is 0, assign the address
        // of the first CLASSFIELDINFO structure to *ppClassFieldInfo.
        // Otherwise *pp points to the first column description in the
        // chain.  We need to walk the chain and link our CLASSFIELDINFO
        // structures at the end.
        if (*ppClassFieldInfo)
        {
            // find the last link in the chain; then add our CLASSFIELDINFO
            // structures to the chain.
            pcfi = *ppClassFieldInfo;
            for (i = 0;
                 i < ulParentColumns;
                 i++)
            {
                pcfi = (pcfi->pNextFieldInfo)
                            ? pcfi->pNextFieldInfo
                            : pcfi;     // appears to be a security check
            }

            // append our new field info to the list;
            // this data has been initialized in wpclsInitData
            pcfi->pNextFieldInfo = G_acfiFontObject;
        }
        else
            // no fields defined yet (very improbable):
            // make ours the first
            *ppClassFieldInfo = G_acfiFontObject;
    }

    return (ulParentColumns + FNTO_EXTRAFIELDS);
}

/*
 *@@ wpclsQueryTitle:
 *      this WPObject class method tells the WPS the clear
 *      name of a class, which is shown in the third column
 *      of a Details view and also used as the default title
 *      for new objects of a class.
 */

SOM_Scope PSZ  SOMLINK fonoM_wpclsQueryTitle(M_XWPFontObject *somSelf)
{
    // PNLSSTRINGS pNLSStrings = cmnQueryNLSStrings();
    /* M_XWPFontObjectData *somThis = M_XWPFontObjectGetData(somSelf); */
    M_XWPFontObjectMethodDebug("M_XWPFontObject","fonoM_wpclsQueryTitle");

    return (cmnGetString(ID_XSSI_FONTOBJECT)) ; // pszFontObject
}

/*
 *@@ wpclsQueryStyle:
 *
 *@@changed V0.9.16 (2001-11-25) [umoeller]: added nevertemplate
 */

SOM_Scope ULONG  SOMLINK fonoM_wpclsQueryStyle(M_XWPFontObject *somSelf)
{
    /* M_XWPFontObjectData *somThis = M_XWPFontObjectGetData(somSelf); */
    M_XWPFontObjectMethodDebug("M_XWPFontObject","fonoM_wpclsQueryStyle");

    return (CLSSTYLE_NEVERTEMPLATE          // V0.9.16 (2001-11-25) [umoeller]
                | CLSSTYLE_NEVERCOPY
                | CLSSTYLE_NEVERDELETE
                | CLSSTYLE_NEVERDRAG
                | CLSSTYLE_NEVERDROPON
                | CLSSTYLE_NEVERLINK
                | CLSSTYLE_NEVERMOVE
                | CLSSTYLE_NEVERPRINT
                | CLSSTYLE_NEVERRENAME);
}

/*
 *@@ wpclsQueryDefaultHelp:
 *      this WPObject class method returns the default help
 *      panel for objects of this class. This gets called
 *      from WPObject::wpQueryDefaultHelp if no instance
 *      help settings (HELPLIBRARY, HELPPANEL) have been
 *      set for an individual object. It is thus recommended
 *      to override this method instead of the instance
 *      method to change the default help panel for a class
 *      in order not to break instance help settings (fixed
 *      with 0.9.20).
 *
 *      Since this is a subclass of WPTransient which doesn't
 *      have any help at all, we return help for font objects
 *      here.
 *
 *@@added V0.9.20 (2002-07-12) [umoeller]
 */

SOM_Scope BOOL  SOMLINK fonoM_wpclsQueryDefaultHelp(M_XWPFontObject *somSelf,
                                                    PULONG pHelpPanelId,
                                                    PSZ pszHelpLibrary)
{
    /* M_XWPFontObjectData *somThis = M_XWPFontObjectGetData(somSelf); */
    M_XWPFontObjectMethodDebug("M_XWPFontObject","fonoM_wpclsQueryDefaultHelp");

    strcpy(pszHelpLibrary, cmnQueryHelpLibrary());
    *pHelpPanelId = ID_XSH_FONTOBJECT;
    return TRUE;
}

/*
 *@@ wpclsQueryIconData:
 *      this WPObject class method must return information
 *      about how to build the default icon for objects
 *      of a class. This gets called from various other
 *      methods whenever a class default icon is needed;
 *      most importantly, M_WPObject::wpclsQueryIcon
 *      calls this to build a class default icon, which
 *      is then cached in the class's instance data.
 *      If a subclass wants to change a class default icon,
 *      it should always override _this_ method instead of
 *      wpclsQueryIcon.
 *
 *      Note that the default WPS implementation does not
 *      allow for specifying the ICON_FILE format here,
 *      which is why we have overridden
 *      M_XFldObject::wpclsQueryIcon too. This allows us
 *      to return icon _files_ for theming too. For details
 *      about the WPS's crappy icon management, refer to
 *      src\filesys\icons.c.
 *
 *      We give this class a new standard icon here.
 */

SOM_Scope ULONG  SOMLINK fonoM_wpclsQueryIconData(M_XWPFontObject *somSelf,
                                                  PICONINFO pIconInfo)
{
    /* M_XWPFontObjectData *somThis = M_XWPFontObjectGetData(somSelf); */
    M_XWPFontObjectMethodDebug("M_XWPFontObject","fonoM_wpclsQueryIconData");

    if (pIconInfo)
    {
        pIconInfo->fFormat = ICON_RESOURCE;
        pIconInfo->resid   = ID_ICONXWPFONTOBJ;
        pIconInfo->hmod    = cmnQueryMainResModuleHandle();
    }

    return (sizeof(ICONINFO));
}

