//----- Completing the reallocateString function -------
//
// The wpFreeMem and wpAllocMem functions are documented
// in the WPS Programming Reference.
//------------------------------------------------------

SOM_Scope string  SOMLINK ChFileX_reallocateString(
                          ChartFile *somSelf,
                          Environment *ev,
                          string oldString,
                          string newValue)
{
    ChartFileData *somThis = ChartFileGetData(somSelf);
    ChartFileMethodDebug("ChartFile",
                         "ChFileX_reallocateString");

 // Only call wpFreeMem if string was previously allocated

    if (oldString)
        somSelf->wpFreeMem(oldString);

 // Figure out how much memory is needed for the new string

    unsigned long ulReturnCode = 0;
    unsigned long ulBytes = strlen(newValue) + 1;

 // Allocate and populate the new string

    string newString = somSelf->wpAllocMem(ulBytes,
                                          &ulReturnCode);
    strcpy(newString, newValue);
    newString[ulBytes - 1] = 0;

    return newString;
}


//------ Completing the setStockSymbol function ----------
//
// This is a typical set function for a string member
// element. There is no need to include all string set
// functions because they are so similar.
//--------------------------------------------------------
SOM_Scope void  SOMLINK
                ChFileX_setStockSymbol(ChartFile *somSelf,
                                       Environment *ev,
                                       string s)
{
    ChartFileData *somThis = ChartFileGetData(somSelf);
    ChartFileMethodDebug("ChartFile",
                         "ChFileX_setStockSymbol");

 // manually added code

    somThis->stockSymbol = somSelf->reallocateString(ev,
                                somThis->stockSymbol, s);

    return;
}

//------ Completing the setLastYYYY function -----------
//
// This is a typical set function for a non-string data
// element. Again, because they are so similar, no other
// set functions for non-string attributes will be
// documented in this article.
//------------------------------------------------------

SOM_Scope void  SOMLINK
                ChFileX_setLastYYYY(ChartFile *somSelf,
                                    Environment *ev,
                                    short yyyy)
{
    ChartFileData *somThis = ChartFileGetData(somSelf);
    ChartFileMethodDebug("ChartFile","ChFileX_setLastYYYY");
    somThis->lastYYYY = yyyy;   // manually added
    return;
}

//------ Completing the getStockSymbol function ----------
//
// This is a typical get function. There is no special
// coding required in "get" functions for data members
// that are of the type "string."
//--------------------------------------------------------

SOM_Scope string  SOMLINK
                  ChFileX_getStockSymbol(ChartFile *somSelf,
                                         Environment *ev)
{
    ChartFileData *somThis = ChartFileGetData(somSelf);
    ChartFileMethodDebug("ChartFile",
                         "ChFileX_getStockSymbol");

 // Warning: returning a pointer. Other programs could
 // possibly modify the data at this address!

    return somThis->stockSymbol;
}

//----------------------------------------------------------
// Before adding settings pages, the window procedure
// functions must be declared.
//----------------------------------------------------------

MRESULT EXPENTRY ChFileWindowProc(HWND hwndDlg,
                                  ULONG msg,
                                  MPARAM mp1,
                                  MPARAM mp2);

MRESULT EXPENTRY ChFileBarWindowProc(HWND hwndDlg,
                                     ULONG msg,
                                     MPARAM mp1,
                                     MPARAM mp2);

MRESULT EXPENTRY ChFilePfWindowProc(HWND hwndDlg,
                                    ULONG msg,
                                    MPARAM mp1,
                                    MPARAM mp2);

//---------------wpAddSettingsPages-------------------------
//
// This function adds the settings pages. Notes:
//
// 1. The resources for this class are bound to the object
//    class' dll. Therefore, the handle for this class' dll
//    can be used for the resource dll handle.
//
// 2. Refer to the PM reference for information on the
//    pageinfo structure.
//----------------------------------------------------------

SOM_Scope BOOL  SOMLINK
             ChFileX_wpAddSettingsPages(ChartFile *somSelf,
                                        HWND hwndNotebook)
{
    ChartFileData *somThis = ChartFileGetData(somSelf);
    ChartFileMethodDebug("ChartFile",
                         "ChFileX_wpAddSettingsPages");

    unsigned long hDll =
             IDynamicLinkLibrary("chfile").handle();

    PAGEINFO pageinfo;

//  DID_STOCK_SETTINGS_DLG
    memset((PCH)&pageinfo,0,sizeof(PAGEINFO));
    pageinfo.cb                 = sizeof(PAGEINFO);
    pageinfo.hwndPage           = NULLHANDLE;
    pageinfo.usPageStyleFlags   = BKA_MAJOR;
    pageinfo.usPageInsertFlags  = BKA_FIRST;
    pageinfo.pfnwp              = ChFileWindowProc;
    pageinfo.resid              = hDll;
    pageinfo.dlgid              = DID_STOCK_SETTINGS_DLG;
    pageinfo.pszName            = "Stock";
    pageinfo.pCreateParams      = somSelf;
    pageinfo.idDefaultHelpPanel = 0;
    pageinfo.pszHelpLibraryName = 0;
    somSelf->wpInsertSettingsPage(hwndNotebook, &pageinfo);

//  DID_BAR_DLG
    memset((PCH)&pageinfo,0,sizeof(PAGEINFO));
    pageinfo.cb                 = sizeof(PAGEINFO);
    pageinfo.hwndPage           = NULLHANDLE;
    pageinfo.usPageStyleFlags   = BKA_MINOR;
    pageinfo.usPageInsertFlags  = BKA_LAST;
    pageinfo.pfnwp              = ChFileBarWindowProc;
    pageinfo.resid              = hDll;
    pageinfo.dlgid              = DID_BAR_DLG;
    pageinfo.pszName            = "Bar Chart";
    pageinfo.pCreateParams      = somSelf;
    pageinfo.idDefaultHelpPanel = 0;
    pageinfo.pszHelpLibraryName = 0;
    somSelf->wpInsertSettingsPage(hwndNotebook, &pageinfo);


//  DID_PF_DLG
    memset((PCH)&pageinfo,0,sizeof(PAGEINFO));
    pageinfo.cb                 = sizeof(PAGEINFO);
    pageinfo.hwndPage           = NULLHANDLE;
    pageinfo.usPageStyleFlags   = BKA_MINOR;
    pageinfo.usPageInsertFlags  = BKA_LAST;
    pageinfo.pfnwp              = ChFilePfWindowProc;
    pageinfo.resid              = hDll;
    pageinfo.dlgid              = DID_PF_DLG;
    pageinfo.pszName            = "P&F Chart";
    pageinfo.pCreateParams      = somSelf;
    pageinfo.idDefaultHelpPanel = 0;
    pageinfo.pszHelpLibraryName = 0;
    somSelf->wpInsertSettingsPage(hwndNotebook, &pageinfo);

    return
    (ChartFile_parent_WPDataFile_wpAddSettingsPages(somSelf,
                                             hwndNotebook));
}


//--------Sample Window Procedure-----------------------
//
// Now, let's take a look at the window procedures for the
// new settings pages. Its unfortunate that these are even
// necessary but since they are needed, let's make them as
// painless as possible. Only one of these procedures will
// be documented here as they all look the same.
//
// Notes:
//
// 1. The only message that needs to be processed in this
//    procedure is WM_INITDLG. This message allows the
//    programmer to instantiate the dialog class.
//
// 2. The class definition for StockDlg (StockDlg.hpp) can
//    be directly included in ChFile.cpp. There is no reason
//    to use a passthru statement in the IDL file to include
//    a settings page header file.
//
// 3. The window handle is passed to the dialog class so
//    that the dialog class can construct an IFrameWindow
//    wrapper for the underlying PM Frame Window. The dialog
//    class is covered later in this article.
//------------------------------------------------------
MRESULT EXPENTRY ChFileWindowProc(HWND hwndDlg, ULONG msg,
                                  MPARAM mp1,   MPARAM mp2)
{
     ChartFile *somSelf = (ChartFile *)mp2;   // Who am I?

     if (msg == WM_INITDLG)
        {
         try  {
               StockDlg *pDlg = new StockDlg(somSelf,
                                             hwndDlg);
               pDlg->setAutoDeleteObject();
              }
         catch (IException& e)
              {
               IMessageBox msgBox(IWindow::desktopWindow());
               msgBox.setTitle("StockDlg Exception");
               msgBox.show(e);
              }
         return (MRESULT) TRUE;
        }
     else
         return WinDefDlgProc(hwndDlg, msg, mp1, mp2);
}

//------------ Completing wpInitData -----------------------
//
// Allocate and initialize memory for this object.
// Note that no memory is allocated for strings in this
// function. The pointers are set to zero so the object
// knows that no memory has been allocated. The reason for
// this is that at this point, the program does not know
// whether or not data exists for these elements. This is
// determined in the wpRestoreState function (see below).
//----------------------------------------------------------

SOM_Scope void  SOMLINK
                ChFileX_wpInitData(ChartFile *somSelf)
{
    ChartFileData *somThis = ChartFileGetData(somSelf);
    ChartFileMethodDebug("ChartFile","ChFileX_wpInitData");

    somThis->stockSymbol = 0;  // initialize pointers to 0
    somThis->exchange    = 0;

    somThis->lastDD   = 1;     // set a default values for
    somThis->lastMM   = 1;     // all non-pointer fields.
    somThis->lastYYYY = 1997;

    somThis->reversalBoxes  = 3;
    somThis->boxSize = 1.0;

    somThis->daysInLongAvg = 150;
    somThis->daysInShortAvg = 50;

    somThis->barDataSaved   = 0;  // 0 = not saved
    somThis->pfDataSaved    = 0;  // 1 = saved
    somThis->stockDataSaved = 0;

    ChartFile_parent_WPDataFile_wpInitData(somSelf);
}

//------------ Completing wpUnInitData ---------------------
//
// This function is called to free allocated memory.
// Note that this function checks to see if memory was
// allocated before freeing it. wpFreeMem doesn't
// care for null pointers.
//----------------------------------------------------------

SOM_Scope void  SOMLINK
                ChFileX_wpUnInitData(ChartFile *somSelf)
{
    ChartFileData *somThis = ChartFileGetData(somSelf);
    ChartFileMethodDebug("ChartFile",
                         "ChFileX_wpUnInitData");

    if (somThis->stockSymbol)
        somSelf->wpFreeMem(somThis->stockSymbol);

    if (somThis->exchange)
        somSelf->wpFreeMem(somThis->exchange);

    ChartFile_parent_WPDataFile_wpUnInitData(somSelf);
}

//------------ Completing wpRestoreState -------------------
//
// This function restores state when object is awaken.
// Note that for WPDataFile objects and their descendants,
// object data are stored as extended attributes.
// wpRestoreString must be called to retrieve string data
// from the file's extended attributes. wpRestoreLong must
// be called to retrieve integer data from the file's
// extended attributes. To avoid multiple sets of ids, the
// dialog ids are used as keys when storing this data.
// Notice how easily extended attributes are handled by WPS
// programs.
//----------------------------------------------------------

SOM_Scope BOOL  SOMLINK
                ChFileX_wpRestoreState(ChartFile *somSelf,
                                       ULONG ulReserved)
{
    ChartFileData *somThis = ChartFileGetData(somSelf);
    ChartFileMethodDebug("ChartFile",
                         "ChFileX_wpRestoreState");

    char restoredData[40];
    unsigned long maxLength, anyLong;
    int rcOk(0);

 // Get the environment pointer needed to call this class'
 // set functions.

    Environment *pSomEnv = somGetGlobalEnvironment();

 // Now retrieve the data for this class' data members
 // and populate the data members.

    memset(restoredData,0,sizeof(restoredData));
    maxLength = sizeof(restoredData) - 1;

 // Arguments are: Class Name, Id or Key, Buffer, Length
 // See the WPS Reference for more information.

    rcOk = somSelf->wpRestoreString("ChartFile",
                                     DID_TICKER_SYMBOL,
                                     restoredData,
                                     &maxLength);
    if (rcOk)
        somSelf->setStockSymbol(pSomEnv, restoredData);
    else
        somSelf->setStockSymbol(pSomEnv, "");

    memset(restoredData,0,sizeof(restoredData));
    maxLength = sizeof(restoredData) - 1;
    rcOk = somSelf->wpRestoreString("ChartFile",
                                     DID_EXCHANGE,
                                     restoredData,
                                     &maxLength);
    if (rcOk)
        somSelf->setExchange(pSomEnv, restoredData);
    else
        somSelf->setExchange(pSomEnv, "");

 // Arguments are: Class Name, Id or Key, Buffer
 // See the WPS Reference for more information.

    rcOk = somSelf->wpRestoreLong("ChartFile",
                                   DID_MM,
                                   &anyLong);
    if (rcOk)
        somThis->lastMM = anyLong;
    else
        somThis->lastMM = 1;

    rcOk = somSelf->wpRestoreLong("ChartFile",
                                   DID_DD,
                                   &anyLong);
    if (rcOk)
        somThis->lastDD = anyLong;
    else
        somThis->lastDD = 1;

    rcOk = somSelf->wpRestoreLong("ChartFile",
                                  DID_YYYY,
                                  &anyLong);
    if (rcOk)
        somThis->lastYYYY = anyLong;
    else
        somThis->lastYYYY = 1997;

    memset(restoredData,0,sizeof(restoredData));
    maxLength = sizeof(restoredData) - 1;
    rcOk = somSelf->wpRestoreString("ChartFile",
                                     DID_PF_BOX_SIZE,
                                     restoredData,
                                     &maxLength);

 // Doubles and floats seem best stored as strings.

    if (rcOk)
        somThis->boxSize = IString(restoredData).asDouble();
    else
        somThis->boxSize = 1.0;

    rcOk = somSelf->wpRestoreLong("ChartFile",
                                  DID_PF_REVERSAL_BOXES,
                                  &anyLong);
    if (rcOk)
        somThis->reversalBoxes = anyLong;
    else
        somThis->reversalBoxes = 3;

    rcOk = somSelf->wpRestoreLong("ChartFile",
                                  DID_BAR_LONG_DAYS,
                                  &anyLong);
    if (rcOk)
        somThis->daysInLongAvg = anyLong;
    else
        somThis->daysInLongAvg = 150;

    rcOk = somSelf->wpRestoreLong("ChartFile",
                                  DID_BAR_SHORT_DAYS,
                                  &anyLong);
    if (rcOk)
        somThis->daysInShortAvg = anyLong;
    else
        somThis->daysInShortAvg = 50;

    return
   (ChartFile_parent_WPDataFile_wpRestoreState(somSelf,
                                               ulReserved));
}

//------------ Completing wpSaveState ----------------------
//
// This function saves an object's state during shut down or
// idle times. Note that to save this object's data,
// wpSaveString and wpSaveLong are invoked. Again, the
// dialog id's are used as the key with which this data is
// saved.
//----------------------------------------------------------

SOM_Scope BOOL  SOMLINK
                ChFileX_wpSaveState(ChartFile *somSelf)
{
    ChartFileData *somThis = ChartFileGetData(somSelf);
    ChartFileMethodDebug("ChartFile","ChFileX_wpSaveState");
    Environment *pSomEnv = somGetGlobalEnvironment();
    int rcOk(0);

    if (somThis->stockDataSaved)
       {
        rcOk = somSelf->wpSaveString("ChartFile",
                                      DID_TICKER_SYMBOL,
                                      somThis->stockSymbol);

        rcOk = somSelf->wpSaveString("ChartFile",
                                      DID_EXCHANGE,
                                      somThis->exchange);

        rcOk = somSelf->wpSaveLong("ChartFile", DID_MM,
                                   somThis->lastMM);

        rcOk = somSelf->wpSaveLong("ChartFile", DID_DD,
                                   somThis->lastDD);

        rcOk = somSelf->wpSaveLong("ChartFile", DID_YYYY,
                                   somThis->lastYYYY);

        somThis->stockDataSaved = 0;
       }

    if (somThis->pfDataSaved)
       {

     // Here, a float is stored as a string

        IString strBoxSize(somThis->boxSize);

        rcOk = somSelf->wpSaveString("ChartFile",
                                     DID_PF_BOX_SIZE,
                                     strBoxSize);

        rcOk = somSelf->wpSaveLong("ChartFile",
                                   DID_PF_REVERSAL_BOXES,
                                   somThis->reversalBoxes);

        somThis->pfDataSaved = 0;
       }

    if (somThis->barDataSaved)
       {
        rcOk = somSelf->wpSaveLong("ChartFile",
                                   DID_BAR_LONG_DAYS,
                                   somThis->daysInLongAvg);

        rcOk = somSelf->wpSaveLong("ChartFile",
                                   DID_BAR_SHORT_DAYS,
                                   somThis->daysInShortAvg);

        somThis->barDataSaved = 0;
       }

    return
       (ChartFile_parent_WPDataFile_wpSaveState(somSelf));
}

//------------ Completing wpModifyPopupMenu ----------------
//
// This function allows items to be added to object's the
// pop-up menu. Recall that the resources are bound to this
// class' dll.
//----------------------------------------------------------

SOM_Scope BOOL  SOMLINK
               ChFileX_wpModifyPopupMenu(ChartFile *somSelf,
                                         HWND hwndMenu,
                                         HWND hwndCnr,
                                         ULONG iPosition)
{
    ChartFileData *somThis = ChartFileGetData(somSelf);
    ChartFileMethodDebug("ChartFile",
                         "ChFileX_wpModifyPopupMenu");

    HMODULE hmod = IDynamicLinkLibrary("chfile").handle();

    if (hmod)
       {
        somSelf->wpInsertPopupMenuItems(hwndMenu, 0, hmod,
                                        WPMENUID_CHFILE, 0);
       }

    return
 (ChartFile_parent_WPDataFile_wpModifyPopupMenu(somSelf,
                                                hwndMenu,
                                                hwndCnr,
                                                iPosition));
}

//------------ Completing wpMenuItemSelected ---------------
//
// This function is called when the user selects an item
// from the objects pop-up menu. The classes that use the
// pointer to this object (e.g., BarChart) will be covered
// in the next article in this series. If you want to build
// this dll, comment out the references to BarChart and
// PfChart.
//----------------------------------------------------------

SOM_Scope BOOL  SOMLINK
             ChFileX_wpMenuItemSelected(ChartFile *somSelf,
                                        HWND hwndFrame,
                                        ULONG ulMenuId)
{
    ChartFileData *somThis = ChartFileGetData(somSelf);
    ChartFileMethodDebug("ChartFile",
                         "ChFileX_wpMenuItemSelected");

    if (ulMenuId == WPMENUID_CHFILE_BARCHART)
       {
        try {
             BarChart *bc = new BarChart(somSelf);
             bc->setAutoDeleteObject();
            }
        catch (IException& e)
            {
             IMessageBox msgBox(IWindow::desktopWindow());
             msgBox.setTitle("BarChart Exception");
             msgBox.show(e);
            }
       }
    else
    if (ulMenuId == WPMENUID_CHFILE_PFCHART)
       {
        try {
             PfChart *pf = new PfChart(somSelf);
             pf->setAutoDeleteObject();
            }
        catch (IException& e)
            {
             IMessageBox msgBox(IWindow::desktopWindow());
             msgBox.setTitle("PfChart Exception");
             msgBox.show(e);
            }
       }
    else
        ;


    return
 (ChartFile_parent_WPDataFile_wpMenuItemSelected(somSelf,
                                                 hwndFrame,
                                                 ulMenuId));
}

//------------------ Completing wpOpen ---------------------
//
// This function must be overridden to process class
// specific views. In this case, the bar chart view is
// established as the default view. Therefore, this
// function is called with the BarChart menu id when the
// user double clicks on a ChartFile object. (See
// wpclsQueryDefaultView in a later section.)
//----------------------------------------------------------

SOM_Scope HWND  SOMLINK ChFileX_wpOpen(ChartFile *somSelf,
                                       HWND hwndCnr,
                                       ULONG ulView,
                                       ULONG param)
{
    ChartFileData *somThis = ChartFileGetData(somSelf);
    ChartFileMethodDebug("ChartFile","ChFileX_wpOpen");

    if (ulView == WPOPEN_BARCHART)
       {
        try {
             BarChart *bc = new BarChart(somSelf);
             bc->setAutoDeleteObject();
            }
        catch (IException& e)
            {
             IMessageBox msgBox(IWindow::desktopWindow());
             msgBox.setTitle("BarChart Exception");
             msgBox.show(e);
            }
       }

    return
    (ChartFile_parent_WPDataFile_wpOpen(somSelf, hwndCnr,
                                        ulView, param));
}

<H2>Meta Class overrides in ChFile.cpp</H2>

//-------------- Completing wpclsInitData ------------------
//
// This function is overridden to load the icon that is used
// for objects of this classl. (In this case, resources are
// bound to the class' dll file.)
//----------------------------------------------------------

SOM_Scope void  SOMLINK
                ChFileX_wpclsInitData(M_ChartFile *somSelf)
{
    M_ChartFileData *somThis = M_ChartFileGetData(somSelf);
    M_ChartFileMethodDebug("M_ChartFile",
                           "ChFileX_wpclsInitData");

    somThis->hChartFileIcon =
    IDynamicLinkLibrary("chfile").loadIcon(WPICONID_CHFILE,
                                           false);

    M_ChartFile_parent_M_WPDataFile_wpclsInitData(somSelf);
}

//-------------- Completing wpclsUnInitData ----------------
//
// This function is overridden to free any meta-class
// allocated memory. It turns out, that for this class, this
// overrided was not needed.
//----------------------------------------------------------

SOM_Scope void  SOMLINK
              ChFileX_wpclsUnInitData(M_ChartFile *somSelf)
{
   M_ChartFileData *somThis = M_ChartFileGetData(somSelf);
   M_ChartFileMethodDebug("M_ChartFile",
                           "ChFileX_wpclsUnInitData");

   M_ChartFile_parent_M_WPDataFile_wpclsUnInitData(somSelf);
}


//-------------- Completing wpclsQueryIcon -----------------
//
// This function is overridden so that the same icon is
// always used for objects of this class. If this function
// is not overridden, the icon is lost whenever the
// underlying file is modified.
//----------------------------------------------------------
SOM_Scope HPOINTER  SOMLINK
                ChFileX_wpclsQueryIcon(M_ChartFile *somSelf)
{
    M_ChartFileData *somThis = M_ChartFileGetData(somSelf);
    M_ChartFileMethodDebug("M_ChartFile",
                           "ChartFileX_wpclsQueryIcon");

    if (somThis->hChartFileIcon)
        return somThis->hChartFileIcon; // loaded above
    else
        return
  (M_ChartFile_parent_M_WPDataFile_wpclsQueryIcon(somSelf));
}


//----------- Completing wpclsQueryDefaultView -------------
//
// This function is overridden to set the default
// (double click) open view for objects of this class.
// This causes the BarChart to be opened when the user
// double clicks on a ChartFile object. (See wpOpen, above.)
//----------------------------------------------------------
SOM_Scope ULONG  SOMLINK
        ChFileX_wpclsQueryDefaultView(M_ChartFile *somSelf)
{
    M_ChartFileData *somThis = M_ChartFileGetData(somSelf);
    M_ChartFileMethodDebug("M_ChartFile",
                           "ChFileX_wpclsQueryDefaultView");

    return WPOPEN_BARCHART;  // Return your favorite view
}
