
/*
 *@@sourcefile xfsys.c:
 *      This file contains the following major XFolder parts
 *      (in this order):
 *
 *      --  XFldWPS notebook callbacks (for notebook.c)
 *      --  XFldWPS SOM stuff
 *      --  XFldSystem notebook callbacks (for notebook.c)
 *      --  XFldSystem SOM stuff
 *
 *      Check the other files starting with xf* for the
 *      other XFolder classes.
 *
 *      These classes implement the "Workplace Shell" and
 *      "OS/2 Kernel" settings objects, respectively.
 *
 *      Installation of these classes is optional, but you
 *      won't be able to change XFolder's settings without
 *      them.
 *
 *      This file has undergone major changes with V0.82, but this
 *      was mainly reorganized and clarified without introducing
 *      new features.
 *
 *@@somclass XFldWPS xfwps_
 *@@somclass M_XFldWPS xfwpsM_
 *@@somclass XFldSystem xfsys_
 *@@somclass M_XFldSystem xfsysM_
 */

/*
 *      Copyright (C) 1997-99 Ulrich M”ller.
 *      This file is part of the XFolder source package.
 *      XFolder 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 XFolder 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_xfsys_Source
#define SOM_Module_xfsys_Source
#endif
#define xfsys_Class_Source
#define M_xfsys_Class_Source

/*
 *  Suggested #include order:
 *  1)  os2.h
 *  2)  C library headers
 *  3)  SOM headers which work with precompiled header files
 *  4)  headers in /helpers
 *  5)  headers in /main with dlgids.h and common.h first
 *  6)  #pragma hdrstop to prevent VAC++ crashes
 *  7)  other needed SOM headers
 *  8)  for non-SOM-class files: corresponding header (e.g. classlst.h)
 */

#define INCL_DOSFILEMGR
#define INCL_DOSMODULEMGR
#define INCL_DOSPROCESS         // DosSleep, priorities, PIDs etc.
#define INCL_DOSSEMAPHORES      // needed for xthreads.h
#define INCL_DOSEXCEPTIONS
#define INCL_DOSERRORS
#define INCL_DOSDEVICES
#define INCL_DOSDEVIOCTL
#define INCL_DOSMISC            // DosGetMessage etc.

#define INCL_WINWINDOWMGR
#define INCL_WINFRAMEMGR        // WM_FORMATFRAME, SC_CLOSE etc.
#define INCL_WINSYS             // presparams, WinQuerySysValue()
#define INCL_WINPOINTERS
#define INCL_WININPUT           // WM_BUTTON1DOWN etc.

#define INCL_WINSHELLDATA       // profile funcs
#define INCL_WINPROGRAMLIST     // needed for WPProgram
#define INCL_WINCOUNTRY         // WinCompareStrings, WinUpper
#define INCL_WINTIMER
#define INCL_WINERRORS
#define INCL_WINRECTANGLES      // rcl functions
#define INCL_WINCLIPBOARD
#define INCL_WINMESSAGEMGR      // sophisticated msg funcs

#define INCL_WINDIALOGS
#define INCL_WINSTATICS
#define INCL_WINMENUS           // needed for menus.h
#define INCL_WINENTRYFIELDS
#define INCL_WINBUTTONS
#define INCL_WINLISTBOXES

#define INCL_WINSTDSPIN         // spin buttons
#define INCL_WINSTDCNR          // needed for winh.h
#define INCL_WINSTDBOOK         // notebooks
#define INCL_WINSTDFILE         // file dialog
#define INCL_WINMLE             // multi-line entry field

#define INCL_WINWORKPLACE

#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
#include <ctype.h>

// headers in /helpers
#include "dosh.h"               // Control Program helper routines
#include "winh.h"               // PM helper routines

#include "animate.h"            // icon and other animations
#include "linklist.h"           // linked list helper routines
#include "procstat.h"           // DosQProcStat handling
#include "stringh.h"            // string helper routines
#include "undoc.h"              // some undocumented stuff

// SOM headers which don't crash with prec. header files
#include "xfsys.ih"
#include "xfdesk.h"
#include "xfldr.h"
#include "xfobj.h"

// headers in /main
#include "dlgids.h"             // all the IDs that are shared with NLS
#include "common.h"             // the majestic XFolder include file

#include "classlst.h"           // SOM logic for "WPS Classes" page
#include "cnrsort.h"            // container sort comparison functions
#include "module.h"             // XFolder main DLL information
#include "notebook.h"           // generic XFolder notebook handling
#include "statbars.h"           // status bar translation logic
#include "xthreads.h"           // XFolder threads; this includes threads.h

// other SOM headers
#pragma hdrstop                 // VAC++ keeps crashing otherwise

// we include statbars.h last because we need the
// WPFolder include before

// notebook callbacks for "Sort" page in xfldr.c

VOID fncbSortInitPage(PVOID pnbi, ULONG ulExtra);

MRESULT fncbSortItemChanged(PVOID pnbi,
                USHORT usItemID, USHORT usNotifyCode,
                ULONG ulExtra);

/* ******************************************************************
 *                                                                  *
 *   here come some notebook helper routines                        *
 *                                                                  *
 ********************************************************************/

/*
 *@@ AddResourceDLLToLB:
 *      this loads a given DLL temporarily in order to
 *      find out if it's an XFolder NLS DLL; if so,
 *      its language string is loaded and a descriptive
 *      string is inserted into a given list box
 *      (used for "XFolder Internals" settings page)
 *
 *@@changes 0.85 Language string now initialized to ""
 */

VOID AddResourceDLLToLB(HWND hwndDlg, ULONG idLB, PSZ pszFileName)
{
    CHAR    szLBEntry[200] = "",   // changed V0.85
            szResourceModuleName[CCHMAXPATH];
    HMODULE hmodDLL = NULLHANDLE;
    // PVOID   pProc;
    ULONG   ulCopied;
    APIRET  rc;

    #ifdef DEBUG_LANGCODES
        _Pmpf(("  Entering AddResourceDLLtoLB: %s", pszFileName));
    #endif
    if (cmnQueryXFolderBasePath(szResourceModuleName))
    {
        strcat(szResourceModuleName, "\\bin\\");
        strcat(szResourceModuleName, pszFileName);

        #ifdef DEBUG_LANGCODES
            _Pmpf(("  Loading module '%s'", szResourceModuleName));
        #endif
        rc = DosLoadModule(NULL, 0,
                      szResourceModuleName,
                      &hmodDLL);
        if (rc == NO_ERROR)
        {
            #ifdef DEBUG_LANGCODES
                _Pmpf(("  Testing for language string"));
            #endif
            if (WinLoadString(WinQueryAnchorBlock(HWND_DESKTOP), hmodDLL,
                ID_XSSI_DLLLANGUAGE, sizeof(szLBEntry), szLBEntry))
            {
                #ifdef DEBUG_LANGCODES
                    _Pmpf(("    found %s", szLBEntry));
                #endif
                strcat(szLBEntry, " -- ");
                strcat(szLBEntry, pszFileName);

                WinSendDlgItemMsg(hwndDlg, idLB,
                                LM_INSERTITEM,
                                (MPARAM)LIT_SORTASCENDING,
                                (MPARAM)szLBEntry);
            }

            DosFreeModule(hmodDLL);
        }
        #ifdef DEBUG_LANGCODES
            else
                _Pmpf(("    Error %d", rc));
        #endif
    }
}

/*
 *  Folder hotkeys descriptions arrays:
 *      every item these arrays must match exactly one
 *      item in the ulLBCommands array in common.c.
 */

CHAR  szLBEntries[FLDRHOTKEYCOUNT][MAXLBENTRYLENGTH];

ULONG szLBStringIDs[FLDRHOTKEYCOUNT] = {
         ID_XSSI_LB_REFRESHNOW          ,
         ID_XSSI_LB_SNAPTOGRID          ,
         ID_XSSI_LB_SELECTALL           ,
         ID_XSSI_LB_OPENPARENTFOLDER    ,

         ID_XSSI_LB_OPENSETTINGSNOTEBOOK,
         ID_XSSI_LB_OPENNEWDETAILSVIEW  ,
         ID_XSSI_LB_OPENNEWICONVIEW     ,
         ID_XSSI_LB_DESELECTALL         ,
         ID_XSSI_LB_OPENNEWTREEVIEW     ,

         ID_XSSI_LB_FIND                ,

         ID_XSSI_LB_PICKUP              ,
         ID_XSSI_LB_PICKUPCANCELDRAG    ,

         ID_XSSI_LB_SORTBYNAME          ,
         ID_XSSI_LB_SORTBYSIZE          ,
         ID_XSSI_LB_SORTBYTYPE          ,
         ID_XSSI_LB_SORTBYREALNAME      ,
         ID_XSSI_LB_SORTBYWRITEDATE     ,
         ID_XSSI_LB_SORTBYACCESSDATE    ,
         ID_XSSI_LB_SORTBYCREATIONDATE  ,

         ID_XSSI_LB_SWITCHTOICONVIEW    ,
         ID_XSSI_LB_SWITCHTODETAILSVIEW ,
         ID_XSSI_LB_SWITCHTOTREEVIEW    ,

         ID_XSSI_LB_ARRANGEDEFAULT      ,
         ID_XSSI_LB_ARRANGEFROMTOP      ,
         ID_XSSI_LB_ARRANGEFROMLEFT     ,
         ID_XSSI_LB_ARRANGEFROMRIGHT    ,
         ID_XSSI_LB_ARRANGEFROMBOTTOM   ,
         ID_XSSI_LB_ARRANGEPERIMETER    ,
         ID_XSSI_LB_ARRANGEHORIZONTALLY ,
         ID_XSSI_LB_ARRANGEVERTICALLY   ,

         ID_XSSI_LB_INSERT              ,

         ID_XSSI_LB_SORTBYEXTENSION     ,
         ID_XSSI_LB_OPENPARENTFOLDERANDCLOSE,

         ID_XSSI_LB_CLOSEWINDOW,
         ID_XSSI_LB_SELECTSOME,
         ID_XSSI_LB_SORTFOLDERSFIRST,
         ID_XSSI_LB_SORTBYCLASS,

         ID_XSSI_LB_CONTEXTMENU,
         ID_XSSI_LB_TASKLIST,

         ID_XSSI_LB_COPYFILENAME_SHORT,
         ID_XSSI_LB_COPYFILENAME_FULL

    };

ULONG ulLBCommands[FLDRHOTKEYCOUNT] = {
        WPMENUID_REFRESH,
        ID_XFMI_OFS_SNAPTOGRID,
        WPMENUID_SELALL,
        ID_XFMI_OFS_OPENPARENT,

        WPMENUID_PROPERTIES,
        WPMENUID_DETAILS,
        WPMENUID_ICON,
        WPMENUID_DESELALL,
        WPMENUID_TREE,

        WPMENUID_FIND,

        WPMENUID_PICKUP,
        WPMENUID_PUTDOWN_CANCEL,

        ID_WPMI_SORTBYNAME,
        ID_WPMI_SORTBYSIZE,
        ID_WPMI_SORTBYTYPE,
        ID_WPMI_SORTBYREALNAME,
        ID_WPMI_SORTBYWRITEDATE,
        ID_WPMI_SORTBYACCESSDATE,
        ID_WPMI_SORTBYCREATIONDATE,

        ID_WPMI_SHOWICONVIEW,
        ID_WPMI_SHOWDETAILSVIEW,
        ID_WPMI_SHOWTREEVIEW,

        WPMENUID_ARRANGE,
        ID_WPMI_ARRANGEFROMTOP,
        ID_WPMI_ARRANGEFROMLEFT,
        ID_WPMI_ARRANGEFROMRIGHT,
        ID_WPMI_ARRANGEFROMBOTTOM,
        ID_WPMI_ARRANGEPERIMETER,
        ID_WPMI_ARRANGEHORIZONTALLY,
        ID_WPMI_ARRANGEVERTICALLY,

        ID_WPMI_PASTE,

        ID_XFMI_OFS_SORTBYEXT,
        ID_XFMI_OFS_OPENPARENTANDCLOSE,

        ID_XFMI_OFS_CLOSE,
        ID_XFMI_OFS_SELECTSOME,
        ID_XFMI_OFS_SORTFOLDERSFIRST,
        ID_XFMI_OFS_SORTBYCLASS,

        ID_XFMI_OFS_CONTEXTMENU,
        0x8011,                     // show task list (sysmenu)

        ID_XFMI_OFS_COPYFILENAME_SHORT,
        ID_XFMI_OFS_COPYFILENAME_FULL
    };

/*
 *@@ FindHotkeyFromLBSel:
 *      this subroutine finds an index to the global
 *      FolderHotkeys[] array according to the currently
 *      selected list box item. This is used on the
 *      "Folder hotkeys" notebook page.
 *      This returns:
 *        NULL  if no accelerator has been defined yet
 *          -1  if LB entries do not match array strings
 *              (should not happen)
 *       other: means that an accelerator has been defined.
 *              We then return the pointer to the hotkey.
 *      If pusCommand is != NULL, it will then contain the
 *      menu "command" of the selected LB item, such that
 *      a new accelerator can be created.
 */

PXFLDHOTKEY FindHotkeyFromLBSel(HWND hwndDlg, USHORT *pusCommand)
{
    SHORT               i, i2 = 0;
    CHAR                szTemp[MAXLBENTRYLENGTH];
    SHORT               sItem;
    SHORT               LBIndex = -1;
    PXFLDHOTKEY         pHotkey = cmnQueryFldrHotkeys(),
                        pHotkeyFound = NULL;

    sItem = (SHORT)WinSendDlgItemMsg(hwndDlg, ID_XSDI_LISTBOX,
                            LM_QUERYSELECTION,
                            (MPARAM)LIT_CURSOR,
                            MPNULL);

    WinSendDlgItemMsg(hwndDlg, ID_XSDI_LISTBOX,
                            LM_QUERYITEMTEXT,
                            MPFROM2SHORT(sItem, sizeof(szTemp)),
                            (MPARAM)szTemp);
    // szTemp now contains the selected list box entry's text

    for (i = 0; i < FLDRHOTKEYCOUNT; i++)
    {
        if (strcmp(szTemp, szLBEntries[i]) == 0)
        {
            LBIndex = i;
            break;
        }
    }
    // i now contains the index in the listbox arrays:
    // -- szLBEntries[] for the strings,
    // -- ulLBCommands[] for the corresponding commands
    // or -1 if not found.

    // item found?
    if (LBIndex != -1)
    {
        // yes:
        // loop thru the hotkeys array
        while (pHotkey->usCommand)
        {
            if (pHotkey->usCommand == ulLBCommands[i])
            {
                // hotkey defined for this listbox item already:
                pHotkeyFound = pHotkey;
                break;
            }
            // else: go for next item
            pHotkey++;
            i2++;
        }

        if ( (pHotkeyFound == NULL) && (pusCommand) )
            // hotkey not yet defined: store the command
            // which corresponds to the selected item, so
            // a new hotkey can be added
            *pusCommand = ulLBCommands[i];

        return (pHotkeyFound);
    }
    else
        return (PXFLDHOTKEY)-1;     // LB entry not found
}

/*
 *@@ fnwpHotkeyEntryField:
 *      this is the window proc for the subclassed entry
 *      field on the "Folder Hotkeys" notebook page. We will
 *      intercept all WM_CHAR messages and set the entry field
 *      display to the key description instead of the character.
 *      Moreover, we will update the global folder hotkey array
 *      according to the currently selected listbox item on that
 *      page.
 */

MRESULT EXPENTRY fnwpHotkeyEntryField(HWND hwndEdit, ULONG msg, MPARAM mp1, MPARAM mp2)
{
    // get original wnd proc; this was stored in the
    // window words in xfsys.c
    PFNWP       OldEditProc = (PFNWP)WinQueryWindowULong(hwndEdit, QWL_USER);

    MRESULT mrc = (MPARAM)FALSE; // WM_CHAR not-processed flag

    switch (msg) {
        case WM_CHAR: {
            int i, i3;
            USHORT usCommand;
            USHORT usKeyCode;
            USHORT usFlags    = SHORT1FROMMP(mp1);
            USHORT usch       = SHORT1FROMMP(mp2);
            USHORT usvk       = SHORT2FROMMP(mp2);

            if (    ((usFlags & KC_KEYUP) == 0)
                &&  (     ((usFlags & KC_VIRTUALKEY) != 0)
                       || ((usFlags & KC_CTRL) != 0)
                       || ((usFlags & KC_ALT) != 0)
                       || (   ((usFlags & KC_VIRTUALKEY) == 0)
                           && (     (usch == 0xEC00)
                                ||  (usch == 0xED00)
                                ||  (usch == 0xEE00)
                              )
                          )
                    )
               )
            {
                PXFLDHOTKEY pHotkeyFound = NULL;

                usFlags &= (KC_VIRTUALKEY | KC_CTRL | KC_ALT | KC_SHIFT);
                if (usFlags & KC_VIRTUALKEY)
                    usKeyCode = usvk;
                else
                    usKeyCode = usch;

                pHotkeyFound = FindHotkeyFromLBSel(WinQueryWindow(hwndEdit, QW_PARENT),
                                             &usCommand);

                #ifdef DEBUG_KEYS
                    _Pmpf(("List box index: %d", i));
                #endif

                if (pHotkeyFound == NULL)
                {
                    // no hotkey defined yet: append a new one
                    pHotkeyFound = cmnQueryFldrHotkeys();

                    // go to the end of the list
                    while (pHotkeyFound->usCommand)
                        pHotkeyFound++;

                    pHotkeyFound->usCommand = usCommand;
                    // set a new list terminator
                    (*(pHotkeyFound+1)).usCommand = 0;

                }

                if ((ULONG)pHotkeyFound != -1)
                {
                    // no error: set hotkey data
                    CHAR szKeyName[200];
                    pHotkeyFound->usFlags      = usFlags;
                    pHotkeyFound->usKeyCode    = usKeyCode;
                    #ifdef DEBUG_KEYS
                        _Pmpf(("Stored usFlags = 0x%lX, usKeyCode = 0x%lX", usFlags, usKeyCode));
                    #endif

                    // show description
                    cmnDescribeKey(szKeyName, usFlags, usKeyCode);
                    WinSetWindowText(hwndEdit, szKeyName);
                    winhEnableDlgItem(WinQueryWindow(hwndEdit, QW_PARENT),
                            ID_XSDI_CLEARACCEL, TRUE);

                    // save hotkeys to INIs
                    cmnStoreFldrHotkeys();

                    mrc = (MPARAM)TRUE; // WM_CHAR processed flag;
                }
            }
        break; }

        default:
            mrc = OldEditProc(hwndEdit, msg, mp1, mp2);
    }
    return (mrc);
}

/* ******************************************************************
 *                                                                  *
 *   "Workplace Shell" notebook callbacks                           *
 *                                                                  *
 ********************************************************************/

/*
 *  All the following functions starting with fncbWPS* are callbacks
 *  for the common notebook dlg function in notebook.c. There are
 *  two callbacks for each notebook page in "Workplace Shell", one
 *  for (re)initializing the page's controls and one for reacting
 *  to controls being changed by the user.
 *  These callbacks are specified in xfwps::xfAddXFldWPSPages.
 *  These callbacks are all new with V0.82 and replace the awful
 *  dialog procedures which were previously used, because these
 *  became hard to maintain over time.
 */

/*
 *@@ fncbWPSXFolder1InitPage:
 *      notebook callback function (notebook.c) for the
 *      first "XFolder" page in "Workplace Shell" object.
 *      Sets the controls on the page according to the
 *      Global Settings.
 */

VOID fncbWPSXFolder1InitPage(PVOID pnbi,   // notebook info struct
                         ULONG ulExtra)        // INIT_* flags (notebook.h)
{
    PCREATENOTEBOOKPAGE pcnbp = (PCREATENOTEBOOKPAGE)pnbi;
    PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();

    if (ulExtra & CBI_INIT)
    {
        if (pcnbp->pBackup == NULL)
        {
            // first call: backup Global Settings for "Undo" button;
            // this memory will be freed automatically by the
            // common notebook window function (notebook.c) when
            // the notebook page is destroyed
            pcnbp->pBackup = malloc(sizeof(GLOBALSETTINGS));
            memcpy(pcnbp->pBackup, pGlobalSettings, sizeof(GLOBALSETTINGS));
        }
    }

    if (ulExtra & CBI_SET)
    {
        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_ADDINTERNALS,
                pGlobalSettings->ShowInternals);
        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_REPLICONS,
                pGlobalSettings->ReplIcons);
        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_FULLPATH,
                pGlobalSettings->FullPath);
        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_KEEPTITLE,
                pGlobalSettings->KeepTitle);
        // maximum path chars spin button
        winhSetDlgItemSpinData(pcnbp->hwndPage, ID_XSDI_MAXPATHCHARS,
                11, 200,        // limits
                pGlobalSettings->MaxPathChars);  // data
        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_TREEVIEWAUTOSCROLL,
                pGlobalSettings->TreeViewAutoScroll);
    }

    if (ulExtra & CBI_ENABLE)
    {
        winhEnableDlgItem(pcnbp->hwndPage, ID_XSDI_TREEVIEWAUTOSCROLL,
                (    (pGlobalSettings->NoWorkerThread == FALSE)
                  && (pGlobalSettings->NoSubclassing == FALSE)
                ));
    }
}

/*
 *@@ fncbWPSXFolder1ItemChanged:
 *      notebook callback function (notebook.c) for the
 *      first "XFolder" page in "Workplace Shell" object.
 *      Reacts to changes of any of the dialog controls.
 */

MRESULT fncbWPSXFolder1ItemChanged(PVOID pnbi,
                USHORT usItemID, USHORT usNotifyCode,
                ULONG ulExtra)      // for checkboxes: contains new state
{
    PCREATENOTEBOOKPAGE pcnbp = (PCREATENOTEBOOKPAGE)pnbi;
    PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
    BOOL fSave = TRUE,
         fUpdate = FALSE;

    LONG lTemp;

    switch (usItemID) {
        case ID_XSDI_ADDINTERNALS:
            pGlobalSettings->ShowInternals = ulExtra;
        break;

        case ID_XSDI_REPLICONS:
            pGlobalSettings->ReplIcons = ulExtra;
        break;

        case ID_XSDI_FULLPATH:
            pGlobalSettings->FullPath  = ulExtra;
            fUpdate = TRUE;
        break;

        case ID_XSDI_KEEPTITLE:
            pGlobalSettings->KeepTitle = ulExtra;
            fUpdate = TRUE;
        break;

        case ID_XSDI_TREEVIEWAUTOSCROLL:
            pGlobalSettings->TreeViewAutoScroll = ulExtra;
        break;

        case ID_XSDI_MAXPATHCHARS:  // spinbutton
            pGlobalSettings->MaxPathChars = ulExtra;
            fUpdate = TRUE;
        break;

        case DID_UNDO: {
            // "Undo" button: get pointer to backed-up Global Settings
            PGLOBALSETTINGS pGSBackup = (PGLOBALSETTINGS)(pcnbp->pBackup);

            // and restore the settings for this page
            pGlobalSettings->ShowInternals = pGSBackup->ShowInternals;
            pGlobalSettings->ReplIcons = pGSBackup->ReplIcons;
            pGlobalSettings->FullPath  = pGSBackup->FullPath ;
            pGlobalSettings->KeepTitle = pGSBackup->KeepTitle;
            pGlobalSettings->TreeViewAutoScroll = pGSBackup->TreeViewAutoScroll;
            pGlobalSettings->MaxPathChars = pGSBackup->MaxPathChars;

            // update the display by calling the INIT callback
            (*(pcnbp->pfncbInitPage))(pnbi, CBI_SET | CBI_ENABLE);
            fUpdate = TRUE;
        break; }

        case DID_DEFAULT: {
            // set the default settings for this settings page
            // (this is in common.c because it's also used at
            // WPS startup)
            cmnSetDefaultSettings(pcnbp->ulPageID);
            // update the display by calling the INIT callback
            (*(pcnbp->pfncbInitPage))(pnbi, CBI_SET | CBI_ENABLE);
            fUpdate = TRUE;
        break; }

        default:
            fSave = FALSE;
    }

    if (fSave)
        cmnStoreGlobalSettings();

    if (fUpdate)
        // have Worker thread update all open folder windows
        // with the full-path-in-title settings
        xthrPostWorkerMsg(WOM_REFRESHFOLDERVIEWS,
                (MPARAM)NULL, // update all, not just children
                MPNULL);

    return ((MPARAM)-1);
}

/*
 *@@ fncbWPSXFolder2InitPage:
 *      notebook callback function (notebook.c) for the
 *      second "XFolder" page in "Workplace Shell" object.
 *      Sets the controls on the page according to the
 *      Global Settings.
 */

VOID fncbWPSXFolder2InitPage(PVOID pnbi,   // notebook info struct
                         ULONG ulExtra)        // INIT_* flags (notebook.h)
{
    PCREATENOTEBOOKPAGE pcnbp = (PCREATENOTEBOOKPAGE)pnbi;
    PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();

    if (ulExtra & CBI_INIT)
    {
        if (pcnbp->pBackup == NULL)
        {
            // first call: backup Global Settings for "Undo" button;
            // this memory will be freed automatically by the
            // common notebook window function (notebook.c) when
            // the notebook page is destroyed
            pcnbp->pBackup = malloc(sizeof(GLOBALSETTINGS));
            memcpy(pcnbp->pBackup, pGlobalSettings, sizeof(GLOBALSETTINGS));
            pcnbp->pBackup2 = malloc(DEFAULTTITLELENGTH);
            strcpy(pcnbp->pBackup2, _wpclsQueryTitle(_WPFolder));
        }
    }

    if (ulExtra & CBI_SET)
    {
        CHAR          szSearchMask[CCHMAXPATH];
        HDIR          hdirFindHandle = HDIR_SYSTEM;
        FILEFINDBUF3  FindBuffer     = {0};      // Returned from FindFirst/Next
        ULONG         ulResultBufLen = sizeof(FILEFINDBUF3);
        ULONG         ulFindCount    = 1;        // Look for 1 file at a time
        APIRET        rc             = NO_ERROR; // Return code
        ULONG         ulCopied;

        // variable menu ID offset spin button
        winhSetDlgItemSpinData(pcnbp->hwndPage, ID_XSDI_VARMENUOFFSET, 100, 2000, pGlobalSettings->VarMenuOffset);

        // default class title entry field
        WinSetDlgItemText(pcnbp->hwndPage, ID_XSDI_DEFAULTTITLE,
                         _wpclsQueryTitle(_WPFolder));

        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_NOWORKERTHREAD, pGlobalSettings->NoWorkerThread);
        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_NOSUBCLASSING,  pGlobalSettings->NoSubclassing);
        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_XFOLDERANIMATION,  pGlobalSettings->ShowXFolderAnim);

        // language drop-down box
        WinSendDlgItemMsg(pcnbp->hwndPage, ID_XSDI_LANGUAGE, LM_DELETEALL, 0, 0);

        if (cmnQueryXFolderBasePath(szSearchMask))
        {
            strcat(szSearchMask, "\\bin\\xfldr*.dll");

            #ifdef DEBUG_LANGCODES
                _Pmpf(("  szSearchMask: %s", szSearchMask));
                _Pmpf(("  DosFindFirst"));
            #endif
            rc = DosFindFirst( szSearchMask,          // File pattern
                                &hdirFindHandle,      // Directory search handle
                                FILE_NORMAL,          // Search attribute
                                &FindBuffer,          // Result buffer
                                ulResultBufLen,       // Result buffer length
                                &ulFindCount,         // Number of entries to find
                                FIL_STANDARD);        // Return level 1 file info

            if (rc != NO_ERROR) {
                DebugBox("XFolder", "XFolder was unable to find any National Language Support DLLs. You need to re-install XFolder.");
            } else {
                // no error:
                #ifdef DEBUG_LANGCODES
                    _Pmpf(("  Found file: %s", FindBuffer.achName));
                #endif
                AddResourceDLLToLB(pcnbp->hwndPage, ID_XSDI_LANGUAGE, FindBuffer.achName);

                // Keep finding the next file until there are no more files
                while (rc != ERROR_NO_MORE_FILES) {
                    ulFindCount = 1;                      // Reset find count.

                    rc = DosFindNext(hdirFindHandle,      // Directory handle
                                     &FindBuffer,         // Result buffer
                                     ulResultBufLen,      // Result buffer length
                                     &ulFindCount);       // Number of entries to find

                    if (rc == NO_ERROR) {
                        AddResourceDLLToLB(pcnbp->hwndPage, ID_XSDI_LANGUAGE, FindBuffer.achName);
                        #ifdef DEBUG_LANGCODES
                            _Pmpf(("  Found next: %s", FindBuffer.achName));
                        #endif
                    }
                } // endwhile

                rc = DosFindClose(hdirFindHandle);    // close our find handle
                if (rc != NO_ERROR) {
                    DebugBox("XFolder", "DosFindClose error");
                }

                #ifdef DEBUG_LANGCODES
                    _Pmpf(("  Selecting: %s", cmnQueryLanguageCode()));
                #endif
                WinSendDlgItemMsg(pcnbp->hwndPage, ID_XSDI_LANGUAGE,
                    LM_SELECTITEM,
                    WinSendDlgItemMsg(pcnbp->hwndPage, ID_XSDI_LANGUAGE, // find matching item
                        LM_SEARCHSTRING,
                        MPFROM2SHORT(LSS_SUBSTRING, LIT_FIRST),
                        (MPARAM)cmnQueryLanguageCode()),
                    (MPARAM)TRUE); // select
            }
        }
    }
}

/*
 *@@ fncbWPSXFolder2ItemChanged:
 *      notebook callback function (notebook.c) for the
 *      second "XFolder" page in "Workplace Shell" object.
 *      Reacts to changes of any of the dialog controls.
 */

MRESULT fncbWPSXFolder2ItemChanged(PVOID pnbi,
                USHORT usItemID, USHORT usNotifyCode,
                ULONG ulExtra)      // for checkboxes: contains new state
{
    PCREATENOTEBOOKPAGE pcnbp = (PCREATENOTEBOOKPAGE)pnbi;
    PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
    BOOL fSave = TRUE,
         fUpdateOtherPages = FALSE;
    CHAR szTemp[200];

    switch (usItemID) {
        case ID_XSDI_XFOLDERANIMATION:
            pGlobalSettings->ShowXFolderAnim = ulExtra;
        break;

        case ID_XSDI_NOWORKERTHREAD:
            pGlobalSettings->NoWorkerThread  = ulExtra;
            // set flag to iterate over other notebook pages
            fUpdateOtherPages = TRUE;
        break;

        case ID_XSDI_NOSUBCLASSING:
            pGlobalSettings->NoSubclassing   = ulExtra;
            // set flag to iterate over other notebook pages
            fUpdateOtherPages = TRUE;
        break;

        // language drop-down box: load/unload resource modules
        case ID_XSDI_LANGUAGE: {
            if (usNotifyCode == LN_SELECT)
            {
                CHAR   szOldLanguageCode[LANGUAGECODELENGTH];
                LONG   lTemp2 = 0;
                CHAR   szTemp2[10];
                PSZ    p;

                strcpy(szOldLanguageCode, cmnQueryLanguageCode());

                WinQueryDlgItemText(pcnbp->hwndPage, ID_XSDI_LANGUAGE,
                        sizeof(szTemp),
                        szTemp);
                p = strhistr(szTemp, " -- XFLDR")+9; // my own case-insensitive routine
                if (p) {
                    strncpy(szTemp2, p, 3);
                    szTemp2[4] = '\0';
                    cmnSetLanguageCode(szTemp2);
                }

                // did language really change?
                if (strcmp(szOldLanguageCode, cmnQueryLanguageCode()) != 0)
                {
                    // enforce reload of resource DLL
                    if (cmnQueryNLSModuleHandle(
                                TRUE        // reload flag
                       ) == NULLHANDLE)
                    {
                        // error occured loading the module: restore
                        //   old language
                        cmnSetLanguageCode(szOldLanguageCode);
                        // update display
                        (*(pcnbp->pfncbInitPage))(pnbi, CBI_SET | CBI_ENABLE);
                    }
                    else {
                        HWND      hwndSystemFrame,
                                  hwndCurrent = pcnbp->hwndPage;
                        HWND      hwndDesktop = WinQueryDesktopWindow(
                                    WinQueryAnchorBlock(HWND_DESKTOP), NULLHANDLE);

                        // "closing system window"
                        cmnMessageBoxMsg(pcnbp->hwndPage,
                                        // set the page as the owner, so the
                                        // user cannot switch pages any more
                                102, 103,
                                MB_OK);

                        // find frame window handle of "Workplace Shell" window
                        while ((hwndCurrent) && (hwndCurrent != hwndDesktop)) {
                            hwndSystemFrame = hwndCurrent;
                            hwndCurrent = WinQueryWindow(hwndCurrent, QW_PARENT);
                        }
                        if (hwndCurrent)
                            WinPostMsg(hwndSystemFrame,
                                WM_SYSCOMMAND,
                                (MPARAM)SC_CLOSE,
                                MPFROM2SHORT(0, 0));
                    }
                } // end if (strcmp(szOldLanguageCode, szLanguageCode) != 0)
            } // end if (usNotifyCode == LN_SELECT)
        break; }

        case ID_XSDI_VARMENUOFFSET:
            pGlobalSettings->VarMenuOffset = ulExtra;
        break;

        case ID_XSDI_DEFAULTTITLE: {
            WinQueryDlgItemText(pcnbp->hwndPage, ID_XSDI_DEFAULTTITLE,
                             sizeof(szTemp),
                             szTemp);
            _xfclsSetDefaultTitle(_XFolder, szTemp);
        break; }

        case DID_UNDO: {
            // "Undo" button: get pointer to backed-up Global Settings
            PGLOBALSETTINGS pGSBackup = (PGLOBALSETTINGS)(pcnbp->pBackup);

            // and restore the settings for this page
            pGlobalSettings->ShowXFolderAnim = pGSBackup->ShowXFolderAnim;
            pGlobalSettings->NoWorkerThread  = pGSBackup->NoWorkerThread;
            pGlobalSettings->NoSubclassing   = pGSBackup->NoSubclassing;
            pGlobalSettings->VarMenuOffset   = pGSBackup->VarMenuOffset;
            _xfclsSetDefaultTitle(_XFolder, pcnbp->pBackup2);

            // update the display by calling the INIT callback
            (*(pcnbp->pfncbInitPage))(pnbi, CBI_SET | CBI_ENABLE);
        break; }

        case DID_DEFAULT: {
            // set the default settings for this settings page
            // (this is in common.c because it's also used at
            // WPS startup)
            cmnSetDefaultSettings(pcnbp->ulPageID);
            _xfclsSetDefaultTitle(_XFolder, "XFolder");
            // update the display by calling the INIT callback
            (*(pcnbp->pfncbInitPage))(pnbi, CBI_SET | CBI_ENABLE);
        break; }

        default:
            fSave = FALSE;
    }

    if (fSave)
        cmnStoreGlobalSettings();

    if (fUpdateOtherPages) {
        PCREATENOTEBOOKPAGE pcnbp = NULL;
        // iterate over all currently open notebook pages
        while (pcnbp = ntbQueryOpenPages(pcnbp)) {
            if (pcnbp->fPageVisible)
                if (pcnbp->pfncbInitPage)
                    // enable/disable items on visible page
                    (*(pcnbp->pfncbInitPage))(pcnbp, CBI_ENABLE);
        }
    }

    return ((MPARAM)-1);
}

/*
 *@@ fncbWPSFileOpsInitPage:
 *      notebook callback function (notebook.c) for the
 *      "File operations" page in "Workplace Shell"
 *      object.
 *      Sets the controls on the page according to the
 *      Global Settings.
 */

VOID fncbWPSFileOpsInitPage(PVOID pnbi,   // notebook info struct
                         ULONG ulExtra)        // INIT_* flags (notebook.h)
{
    PCREATENOTEBOOKPAGE pcnbp = (PCREATENOTEBOOKPAGE)pnbi;
    PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();

    if (ulExtra & CBI_INIT)
    {
        if (pcnbp->pBackup == NULL)
        {
            // first call: backup Global Settings for "Undo" button;
            // this memory will be freed automatically by the
            // common notebook window function (notebook.c) when
            // the notebook page is destroyed
            pcnbp->pBackup = malloc(sizeof(GLOBALSETTINGS));
            memcpy(pcnbp->pBackup, pGlobalSettings, sizeof(GLOBALSETTINGS));
        }
    }

    if (ulExtra & CBI_SET)
    {
        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_CLEANUPINIS,
                pGlobalSettings->CleanupINIs);
        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_REPLCONFIRMS,
                pGlobalSettings->ReplConfirms);
    }

    if (ulExtra & CBI_ENABLE)
    {
        winhEnableDlgItem(pcnbp->hwndPage, ID_XSDI_CLEANUPINIS,
                !(pGlobalSettings->NoWorkerThread));
    }
}

/*
 *@@ fncbWPSFileOpsChanged:
 *      notebook callback function (notebook.c) for the
 *      "File operations" page in "Workplace Shell"
 *      object.
 *      Reacts to changes of any of the dialog controls.
 */

MRESULT fncbWPSFileOpsItemChanged(PVOID pnbi,
                USHORT usItemID, USHORT usNotifyCode,
                ULONG ulExtra)      // for checkboxes: contains new state
{
    PCREATENOTEBOOKPAGE pcnbp = (PCREATENOTEBOOKPAGE)pnbi;
    PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
    BOOL fSave = TRUE;

    switch (usItemID) {
        case ID_XSDI_REPLCONFIRMS:
            pGlobalSettings->ReplConfirms = ulExtra;
        break;

        case ID_XSDI_CLEANUPINIS:
            pGlobalSettings->CleanupINIs = ulExtra;
        break;

        case DID_UNDO: {
            // "Undo" button: get pointer to backed-up Global Settings
            PGLOBALSETTINGS pGSBackup = (PGLOBALSETTINGS)(pcnbp->pBackup);

            // and restore the settings for this page
            pGlobalSettings->ReplConfirms = pGSBackup->ReplConfirms;
            pGlobalSettings->CleanupINIs = pGSBackup->CleanupINIs;

            // update the display by calling the INIT callback
            (*(pcnbp->pfncbInitPage))(pnbi, CBI_SET | CBI_ENABLE);
        break; }

        case DID_DEFAULT: {
            // set the default settings for this settings page
            // (this is in common.c because it's also used at
            // WPS startup)
            cmnSetDefaultSettings(pcnbp->ulPageID);
            // update the display by calling the INIT callback
            (*(pcnbp->pfncbInitPage))(pnbi, CBI_SET | CBI_ENABLE);
        break; }

        default:
            fSave = FALSE;
    }

    if (fSave)
        cmnStoreGlobalSettings();

    return ((MPARAM)-1);
}

/*
 *@@ fncbWPSAddMenusInitPage:
 *      notebook callback function (notebook.c) for the
 *      first "Context Menus" page in "Workplace Shell"
 *      object ("Add menu items").
 *      Sets the controls on the page according to the
 *      Global Settings.
 */

VOID fncbWPSAddMenusInitPage(PVOID pnbi,   // notebook info struct
                         ULONG ulExtra)        // INIT_* flags (notebook.h)
{
    PCREATENOTEBOOKPAGE pcnbp = (PCREATENOTEBOOKPAGE)pnbi;
    PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();

    if (ulExtra & CBI_INIT)
    {
        if (pcnbp->pBackup == NULL)
        {
            // first call: backup Global Settings for "Undo" button;
            // this memory will be freed automatically by the
            // common notebook window function (notebook.c) when
            // the notebook page is destroyed
            pcnbp->pBackup = malloc(sizeof(GLOBALSETTINGS));
            memcpy(pcnbp->pBackup, pGlobalSettings, sizeof(GLOBALSETTINGS));
        }
    }

    if (ulExtra & CBI_SET)
    {
        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_FILEATTRIBS,
                pGlobalSettings->FileAttribs);
        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_COPYFILENAME,
                pGlobalSettings->AddCopyFilenameItem);
        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_FLDRVIEWS,
                pGlobalSettings->ExtendFldrViewMenu);
        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_MOVE4REFRESH,
                pGlobalSettings->MoveRefreshNow);
        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_SELECTSOME,
                pGlobalSettings->AddSelectSomeItem);
        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_FOLDERCONTENT,
                pGlobalSettings->AddFolderContentItem);
        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_FC_SHOWICONS,
                pGlobalSettings->FCShowIcons);
    }

    if (ulExtra & CBI_ENABLE)
    {
        BOOL fIsWarp4 = doshIsWarp4();
        BOOL fViewVisible =
               (    ( (fIsWarp4)  && (pGlobalSettings->RemoveViewMenu == 0) )
                 || ( (!fIsWarp4) && ((pGlobalSettings->DefaultMenuItems & CTXT_SELECT) == 0)
               ));
        winhEnableDlgItem(pcnbp->hwndPage, ID_XSDI_FOLDERCONTENT,
                !(pGlobalSettings->NoSubclassing));
        winhEnableDlgItem(pcnbp->hwndPage, ID_XSDI_FC_SHOWICONS,
                !(pGlobalSettings->NoSubclassing));
        winhEnableDlgItem(pcnbp->hwndPage, ID_XSDI_SELECTSOME, fViewVisible);
        winhEnableDlgItem(pcnbp->hwndPage, ID_XSDI_FLDRVIEWS, fViewVisible);
    }
}

/*
 *@@ fncbWPSAddMenusItemChanged:
 *      notebook callback function (notebook.c) for the
 *      first "Context Menus" page in "Workplace Shell"
 *      object ("Add menu items").
 *      Reacts to changes of any of the dialog controls.
 */

MRESULT fncbWPSAddMenusItemChanged(PVOID pnbi,
                USHORT usItemID, USHORT usNotifyCode,
                ULONG ulExtra)      // for checkboxes: contains new state
{
    PCREATENOTEBOOKPAGE pcnbp = (PCREATENOTEBOOKPAGE)pnbi;
    PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
    BOOL fSave = TRUE;

    switch (usItemID) {
        case ID_XSDI_FILEATTRIBS:
            pGlobalSettings->FileAttribs = ulExtra;
        break;

        case ID_XSDI_COPYFILENAME:
            pGlobalSettings->AddCopyFilenameItem = ulExtra;
        break;

        case ID_XSDI_FLDRVIEWS:
            pGlobalSettings->ExtendFldrViewMenu = ulExtra;
        break;

        case ID_XSDI_MOVE4REFRESH:
            pGlobalSettings->MoveRefreshNow = ulExtra;
        break;

        case ID_XSDI_SELECTSOME:
            pGlobalSettings->AddSelectSomeItem = ulExtra;
        break;

        case ID_XSDI_FOLDERCONTENT:
            pGlobalSettings->AddFolderContentItem = ulExtra;
        break;

        case ID_XSDI_FC_SHOWICONS:
            pGlobalSettings->FCShowIcons = ulExtra;
            if (ulExtra)
                // enabled: show warning msg box (video driver bugs)
                cmnMessageBoxMsg(pcnbp->hwndPage, 116, 117, MB_OK);
        break;

        case DID_UNDO: {
            // "Undo" button: get pointer to backed-up Global Settings
            PGLOBALSETTINGS pGSBackup = (PGLOBALSETTINGS)(pcnbp->pBackup);

            // and restore the settings for this page
            pGlobalSettings->FileAttribs = pGSBackup->FileAttribs;
            pGlobalSettings->AddCopyFilenameItem = pGSBackup->AddCopyFilenameItem;
            pGlobalSettings->ExtendFldrViewMenu = pGSBackup->ExtendFldrViewMenu;
            pGlobalSettings->MoveRefreshNow = pGSBackup->MoveRefreshNow;
            pGlobalSettings->AddSelectSomeItem = pGSBackup->AddSelectSomeItem;
            pGlobalSettings->AddFolderContentItem = pGSBackup->AddFolderContentItem;
            pGlobalSettings->FCShowIcons = pGSBackup->FCShowIcons;

            // update the display by calling the INIT callback
            (*(pcnbp->pfncbInitPage))(pnbi, CBI_SET | CBI_ENABLE);
        break; }

        case DID_DEFAULT: {
            // set the default settings for this settings page
            // (this is in common.c because it's also used at
            // WPS startup)
            cmnSetDefaultSettings(pcnbp->ulPageID);
            // update the display by calling the INIT callback
            (*(pcnbp->pfncbInitPage))(pnbi, CBI_SET | CBI_ENABLE);
        break; }

        default:
            fSave = FALSE;
    }

    if (fSave)
        cmnStoreGlobalSettings();

    return ((MPARAM)-1);
}

/*
 *@@ fncbWPSConfigFolderMenusInitPage:
 *      notebook callback function (notebook.c) for the
 *      second "Context Menus" page in "Workplace Shell"
 *      object ("Config folder items").
 *      Sets the controls on the page according to the
 *      Global Settings.
 */

VOID fncbWPSConfigFolderMenusInitPage(PVOID pnbi,   // notebook info struct
                         ULONG ulExtra)        // INIT_* flags (notebook.h)
{
    PCREATENOTEBOOKPAGE pcnbp = (PCREATENOTEBOOKPAGE)pnbi;
    PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();

    if (ulExtra & CBI_INIT)
    {
        if (pcnbp->pBackup == NULL)
        {
            // first call: backup Global Settings for "Undo" button;
            // this memory will be freed automatically by the
            // common notebook window function (notebook.c) when
            // the notebook page is destroyed
            pcnbp->pBackup = malloc(sizeof(GLOBALSETTINGS));
            memcpy(pcnbp->pBackup, pGlobalSettings, sizeof(GLOBALSETTINGS));
        }
    }

    if (ulExtra & CBI_SET)
    {
        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_CASCADE,
                    pGlobalSettings->MenuCascadeMode);
        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_REMOVEX,
                    pGlobalSettings->RemoveX);
        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_APPDPARAM,
                    pGlobalSettings->AppdParam);

        switch (pGlobalSettings->TemplatesOpenSettings)
        {
            case 0:  winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_TPL_DONOTHING, 1); break;
            case 1:  winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_TPL_OPENSETTINGS, 1); break;
            default:  winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_TPL_EDITTITLE, 1); break;
        }

        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_TPL_POSITION,
                    pGlobalSettings->TemplatesReposition);
    }
}

/*
 *@@ fncbWPSConfigFolderMenusItemChanged:
 *      notebook callback function (notebook.c) for the
 *      second "Context Menus" page in "Workplace Shell"
 *      object ("Config folder items").
 *      Reacts to changes of any of the dialog controls.
 */

MRESULT fncbWPSConfigFolderMenusItemChanged(PVOID pnbi,
                USHORT usItemID, USHORT usNotifyCode,
                ULONG ulExtra)      // for checkboxes: contains new state
{
    PCREATENOTEBOOKPAGE pcnbp = (PCREATENOTEBOOKPAGE)pnbi;
    PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
    BOOL fSave = TRUE;

    switch (usItemID) {
        case ID_XSDI_CASCADE:
            pGlobalSettings->MenuCascadeMode   = ulExtra;
        break;

        case ID_XSDI_REMOVEX:
            pGlobalSettings->RemoveX   = ulExtra;
        break;

        case ID_XSDI_APPDPARAM:
            pGlobalSettings->AppdParam = ulExtra;
        break;

        // "create from templates" settings
        case ID_XSDI_TPL_DONOTHING:
            pGlobalSettings->TemplatesOpenSettings = 0;
        break;

        case ID_XSDI_TPL_EDITTITLE:
            pGlobalSettings->TemplatesOpenSettings = BM_INDETERMINATE;
        break;

        case ID_XSDI_TPL_OPENSETTINGS:
            pGlobalSettings->TemplatesOpenSettings = BM_CHECKED;
        break;

        case ID_XSDI_TPL_POSITION:
            pGlobalSettings->TemplatesReposition = ulExtra;
        break;

        case DID_UNDO: {
            // "Undo" button: get pointer to backed-up Global Settings
            PGLOBALSETTINGS pGSBackup = (PGLOBALSETTINGS)(pcnbp->pBackup);

            // and restore the settings for this page
            pGlobalSettings->MenuCascadeMode   = pGSBackup->MenuCascadeMode;
            pGlobalSettings->RemoveX   = pGSBackup->RemoveX;
            pGlobalSettings->AppdParam = pGSBackup->AppdParam;
            pGlobalSettings->TemplatesOpenSettings = pGSBackup->TemplatesOpenSettings;
            pGlobalSettings->TemplatesReposition = pGSBackup->TemplatesReposition;

            // update the display by calling the INIT callback
            (*(pcnbp->pfncbInitPage))(pnbi, CBI_SET | CBI_ENABLE);
        break; }

        case DID_DEFAULT: {
            // set the default settings for this settings page
            // (this is in common.c because it's also used at
            // WPS startup)
            cmnSetDefaultSettings(pcnbp->ulPageID);
            // update the display by calling the INIT callback
            (*(pcnbp->pfncbInitPage))(pnbi, CBI_SET | CBI_ENABLE);
        break; }

        default:
            fSave = FALSE;
    }

    if (fSave)
        cmnStoreGlobalSettings();

    return ((MPARAM)-1);
}

/*
 *@@ fncbWPSRemoveItemsInitPage:
 *      notebook callback function (notebook.c) for the
 *      third "Context Menus" page in "Workplace Shell"
 *      object ("Remove menu items").
 *      Sets the controls on the page according to the
 *      Global Settings.
 */

VOID fncbWPSRemoveItemsInitPage(PVOID pnbi,   // notebook info struct
                         ULONG ulExtra)        // INIT_* flags (notebook.h)
{
    PCREATENOTEBOOKPAGE pcnbp = (PCREATENOTEBOOKPAGE)pnbi;
    PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();

    if (ulExtra & CBI_INIT)
    {
        if (pcnbp->pBackup == NULL)
        {
            // first call: backup Global Settings for "Undo" button;
            // this memory will be freed automatically by the
            // common notebook window function (notebook.c) when
            // the notebook page is destroyed
            pcnbp->pBackup = malloc(sizeof(GLOBALSETTINGS));
            memcpy(pcnbp->pBackup, pGlobalSettings, sizeof(GLOBALSETTINGS));
        }
    }

    if (ulExtra & CBI_SET)
    {
        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_HELP  ,
                (pGlobalSettings->DefaultMenuItems & CTXT_HELP) == 0);
        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_CRANOTHER,
                (pGlobalSettings->DefaultMenuItems & CTXT_CRANOTHER) == 0);
        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_COPY  ,
                (pGlobalSettings->DefaultMenuItems & CTXT_COPY     ) == 0);
        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_MOVE  ,
                (pGlobalSettings->DefaultMenuItems & CTXT_MOVE     ) == 0);
        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_SHADOW,
                (pGlobalSettings->DefaultMenuItems & CTXT_SHADOW   ) == 0);
        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_DELETE,
                (pGlobalSettings->DefaultMenuItems & CTXT_DELETE   ) == 0);
        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_PICKUP,
                (pGlobalSettings->DefaultMenuItems & CTXT_PICKUP   ) == 0);
        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_FIND  ,
                (pGlobalSettings->DefaultMenuItems & CTXT_FIND     ) == 0);
        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_SELECT,
                (pGlobalSettings->DefaultMenuItems & CTXT_SELECT   ) == 0);
        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_SORT  ,
                (pGlobalSettings->DefaultMenuItems & CTXT_SORT     ) == 0);
        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_ARRANGE,
                (pGlobalSettings->DefaultMenuItems & CTXT_ARRANGE ) == 0);
        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_PRINT  ,
                (pGlobalSettings->DefaultMenuItems & CTXT_PRINT   ) == 0);

        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_WARP4DISPLAY,
                !pGlobalSettings->RemoveViewMenu);
        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_INSERT,
                !pGlobalSettings->RemovePasteItem);
        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_LOCKINPLACE,
                !pGlobalSettings->RemoveLockInPlaceItem);
        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_CHECKDISK,
                !pGlobalSettings->RemoveCheckDiskItem);
        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_FORMATDISK,
                !pGlobalSettings->RemoveFormatDiskItem);
    }

    if (ulExtra & CBI_INIT)
    {
        // disable items for Warp 3/4
        if (doshIsWarp4()) {
            winhEnableDlgItem(pcnbp->hwndPage, ID_XSDI_SELECT, FALSE);
        } else {
            winhEnableDlgItem(pcnbp->hwndPage, ID_XSDI_LOCKINPLACE, FALSE);
            winhEnableDlgItem(pcnbp->hwndPage, ID_XSDI_WARP4DISPLAY, FALSE);
            winhEnableDlgItem(pcnbp->hwndPage, ID_XSDI_INSERT, FALSE);
        }
    }
}

/*
 *@@ fncbWPSRemoveItemsItemChanged:
 *      notebook callback function (notebook.c) for the
 *      third "Context Menus" page in "Workplace Shell"
 *      object ("Remove menu items").
 *      Reacts to changes of any of the dialog controls.
 */

MRESULT fncbWPSRemoveItemsItemChanged(PVOID pnbi,
                USHORT usItemID, USHORT usNotifyCode,
                ULONG ulExtra)      // for checkboxes: contains new state
{
    PCREATENOTEBOOKPAGE pcnbp = (PCREATENOTEBOOKPAGE)pnbi;
    PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
    BOOL fSave = TRUE;

    LONG lTemp;

    switch (usItemID) {
        case ID_XSDI_HELP:
            if (ulExtra)
                pGlobalSettings->DefaultMenuItems &= ~CTXT_HELP;
            else
                pGlobalSettings->DefaultMenuItems |= CTXT_HELP;
        break;

        case ID_XSDI_CRANOTHER:
            if (ulExtra)
                pGlobalSettings->DefaultMenuItems &= ~CTXT_CRANOTHER;
            else
                pGlobalSettings->DefaultMenuItems |= CTXT_CRANOTHER;
        break;

        case ID_XSDI_COPY:
            if (ulExtra)
                pGlobalSettings->DefaultMenuItems &= ~CTXT_COPY;
            else
                pGlobalSettings->DefaultMenuItems |= CTXT_COPY;
        break;

        case ID_XSDI_MOVE:
            if (ulExtra)
                pGlobalSettings->DefaultMenuItems &= ~CTXT_MOVE;
            else
                pGlobalSettings->DefaultMenuItems |= CTXT_MOVE;
        break;

        case ID_XSDI_SHADOW:
            if (ulExtra)
                pGlobalSettings->DefaultMenuItems &= ~CTXT_SHADOW;
            else
                pGlobalSettings->DefaultMenuItems |= CTXT_SHADOW;
        break;

        case ID_XSDI_DELETE:
            if (ulExtra)
                pGlobalSettings->DefaultMenuItems &= ~CTXT_DELETE;
            else
                pGlobalSettings->DefaultMenuItems |= CTXT_DELETE;
        break;

        case ID_XSDI_PICKUP:
            if (ulExtra)
                pGlobalSettings->DefaultMenuItems &= ~CTXT_PICKUP;
            else
                pGlobalSettings->DefaultMenuItems |= CTXT_PICKUP;
        break;

        case ID_XSDI_FIND:
            if (ulExtra)
                pGlobalSettings->DefaultMenuItems &= ~CTXT_FIND;
            else
                pGlobalSettings->DefaultMenuItems |= CTXT_FIND;
        break;

        case ID_XSDI_SELECT:
            if (ulExtra)
                pGlobalSettings->DefaultMenuItems &= ~CTXT_SELECT;
            else
                pGlobalSettings->DefaultMenuItems |= CTXT_SELECT;
        break;

        case ID_XSDI_SORT:
            if (ulExtra)
                pGlobalSettings->DefaultMenuItems &= ~CTXT_SORT;
            else
                pGlobalSettings->DefaultMenuItems |= CTXT_SORT;
        break;

        case ID_XSDI_ARRANGE:
            if (ulExtra)
                pGlobalSettings->DefaultMenuItems &= ~CTXT_ARRANGE;
            else
                pGlobalSettings->DefaultMenuItems |= CTXT_ARRANGE;
        break;

        case ID_XSDI_PRINT:
            if (ulExtra)
                pGlobalSettings->DefaultMenuItems &= ~CTXT_PRINT;
            else
                pGlobalSettings->DefaultMenuItems |= CTXT_PRINT;
        break;

        case ID_XSDI_WARP4DISPLAY:
            pGlobalSettings->RemoveViewMenu = 1-ulExtra;
        break;

        case ID_XSDI_INSERT:
            pGlobalSettings->RemovePasteItem = 1-ulExtra;
        break;

        case ID_XSDI_LOCKINPLACE:
            pGlobalSettings->RemoveLockInPlaceItem = 1-ulExtra;
        break;

        case ID_XSDI_CHECKDISK:
            pGlobalSettings->RemoveCheckDiskItem = 1-ulExtra;
        break;

        case ID_XSDI_FORMATDISK:
            pGlobalSettings->RemoveFormatDiskItem = 1-ulExtra;
        break;

        case DID_UNDO: {
            // "Undo" button: get pointer to backed-up Global Settings
            PGLOBALSETTINGS pGSBackup = (PGLOBALSETTINGS)(pcnbp->pBackup);

            // and restore the settings for this page
            pGlobalSettings->DefaultMenuItems = pGSBackup->DefaultMenuItems;
            pGlobalSettings->RemoveViewMenu = pGSBackup->RemoveViewMenu;
            pGlobalSettings->RemovePasteItem = pGSBackup->RemovePasteItem;
            pGlobalSettings->RemoveLockInPlaceItem = pGSBackup->RemoveLockInPlaceItem;
            pGlobalSettings->RemoveCheckDiskItem = pGSBackup->RemoveCheckDiskItem;
            pGlobalSettings->RemoveFormatDiskItem = pGSBackup->RemoveFormatDiskItem;

            // update the display by calling the INIT callback
            (*(pcnbp->pfncbInitPage))(pnbi, CBI_SET | CBI_ENABLE);
        break; }

        case DID_DEFAULT: {
            // set the default settings for this settings page
            // (this is in common.c because it's also used at
            // WPS startup)
            cmnSetDefaultSettings(pcnbp->ulPageID);
            // update the display by calling the INIT callback
            (*(pcnbp->pfncbInitPage))(pnbi, CBI_SET | CBI_ENABLE);
        break; }

        default:
            fSave = FALSE;
    }

    if (fSave)
        cmnStoreGlobalSettings();

    return ((MPARAM)-1);
}

/*
 *@@ fncbWPSStatusBar1InitPage:
 *      notebook callback function (notebook.c) for the
 *      first "Status bars" page in "Workplace Shell" object.
 *      Sets the controls on the page according to the
 *      Global Settings.
 */

VOID fncbWPSStatusBar1InitPage(PVOID pnbi,   // notebook info struct
                         ULONG ulExtra)        // INIT_* flags (notebook.h)
{
    PCREATENOTEBOOKPAGE pcnbp = (PCREATENOTEBOOKPAGE)pnbi;
    PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();

    if (ulExtra & CBI_INIT)
    {
        if (pcnbp->pBackup == NULL)
        {
            // first call: backup Global Settings for "Undo" button;
            // this memory will be freed automatically by the
            // common notebook window function (notebook.c) when
            // the notebook page is destroyed
            pcnbp->pBackup = malloc(sizeof(GLOBALSETTINGS));
            memcpy(pcnbp->pBackup, pGlobalSettings, sizeof(GLOBALSETTINGS));
        }
    }

    if (ulExtra & CBI_SET)
    {
        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_ENABLESTATUSBAR,
                        pGlobalSettings->StatusBar);

        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_SBFORICONVIEWS,
                        (pGlobalSettings->SBForViews & SBV_ICON) != 0);
        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_SBFORTREEVIEWS,
                        (pGlobalSettings->SBForViews & SBV_TREE) != 0);
        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_SBFORDETAILSVIEWS,
                        (pGlobalSettings->SBForViews & SBV_DETAILS) != 0);

        if (pGlobalSettings->SBStyle == SBSTYLE_WARP3RAISED)
            winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_SBSTYLE_3RAISED, TRUE);
        else if (pGlobalSettings->SBStyle == SBSTYLE_WARP3SUNKEN)
            winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_SBSTYLE_3SUNKEN, TRUE);
        else if (pGlobalSettings->SBStyle == SBSTYLE_WARP4RECT)
            winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_SBSTYLE_4RECT, TRUE);
        else
            winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_SBSTYLE_4MENU, TRUE);
    }

    if (ulExtra & CBI_ENABLE)
    {
        BOOL fEnable = !(pGlobalSettings->NoSubclassing);
        winhEnableDlgItem(pcnbp->hwndPage, ID_XSDI_ENABLESTATUSBAR, fEnable);
        winhEnableDlgItem(pcnbp->hwndPage, ID_XSDI_SBSTYLE_3RAISED, fEnable);
        winhEnableDlgItem(pcnbp->hwndPage, ID_XSDI_SBSTYLE_3SUNKEN, fEnable);
        winhEnableDlgItem(pcnbp->hwndPage, ID_XSDI_SBSTYLE_4MENU,   fEnable);
        winhEnableDlgItem(pcnbp->hwndPage, ID_XSDI_SBSTYLE_4RECT,   fEnable);

        winhEnableDlgItem(pcnbp->hwndPage, ID_XSDI_SBFORICONVIEWS,   fEnable);
        winhEnableDlgItem(pcnbp->hwndPage, ID_XSDI_SBFORTREEVIEWS,   fEnable);
        winhEnableDlgItem(pcnbp->hwndPage, ID_XSDI_SBFORDETAILSVIEWS,   fEnable);
    }
}

/*
 *@@ fncbWPSStatusBar1ItemChanged:
 *      notebook callback function (notebook.c) for the
 *      second "Status bars" page in "Workplace Shell" object.
 *      Reacts to changes of any of the dialog controls.
 */

MRESULT fncbWPSStatusBar1ItemChanged(PVOID pnbi,
                USHORT usItemID, USHORT usNotifyCode,
                ULONG ulExtra)      // for checkboxes: contains new state
{
    PCREATENOTEBOOKPAGE pcnbp = (PCREATENOTEBOOKPAGE)pnbi;
    PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
    BOOL fSave = TRUE,
         fShowStatusBars = FALSE,
         fRefreshStatusBars = FALSE;

    switch (usItemID) {
        case ID_XSDI_ENABLESTATUSBAR:
            pGlobalSettings->StatusBar = ulExtra;
            fShowStatusBars = TRUE;
        break;

        case ID_XSDI_SBFORICONVIEWS:
            if (ulExtra)
                pGlobalSettings->SBForViews |= SBV_ICON;
            else
                pGlobalSettings->SBForViews &= ~SBV_ICON;
            fShowStatusBars = TRUE;
        break;

        case ID_XSDI_SBFORTREEVIEWS:
            if (ulExtra)
                pGlobalSettings->SBForViews |= SBV_TREE;
            else
                pGlobalSettings->SBForViews &= ~SBV_TREE;
            fShowStatusBars = TRUE;
        break;

        case ID_XSDI_SBFORDETAILSVIEWS:
            if (ulExtra)
                pGlobalSettings->SBForViews |= SBV_DETAILS;
            else
                pGlobalSettings->SBForViews &= ~SBV_DETAILS;
            fShowStatusBars = TRUE;
        break;

        case ID_XSDI_SBSTYLE_3RAISED:
            pGlobalSettings->SBStyle = SBSTYLE_WARP3RAISED;
            fRefreshStatusBars = TRUE;
        break;

        case ID_XSDI_SBSTYLE_3SUNKEN:
            pGlobalSettings->SBStyle = SBSTYLE_WARP3SUNKEN;
            fRefreshStatusBars = TRUE;
        break;

        case ID_XSDI_SBSTYLE_4RECT:
            pGlobalSettings->SBStyle = SBSTYLE_WARP4RECT;
            fRefreshStatusBars = TRUE;
        break;

        case ID_XSDI_SBSTYLE_4MENU:
            pGlobalSettings->SBStyle = SBSTYLE_WARP4MENU;
            fRefreshStatusBars = TRUE;
        break;

        case DID_UNDO: {
            // "Undo" button: get pointer to backed-up Global Settings
            PGLOBALSETTINGS pGSBackup = (PGLOBALSETTINGS)(pcnbp->pBackup);

            // and restore the settings for this page
            pGlobalSettings->StatusBar  = pGSBackup->StatusBar;
            pGlobalSettings->SBForViews = pGSBackup->SBForViews;
            pGlobalSettings->SBStyle = pGSBackup->SBStyle;

            // update the display by calling the INIT callback
            (*(pcnbp->pfncbInitPage))(pnbi, CBI_SET | CBI_ENABLE);
            fRefreshStatusBars = TRUE;
            fShowStatusBars = TRUE;
        break; }

        case DID_DEFAULT: {
            // set the default settings for this settings page
            // (this is in common.c because it's also used at
            // WPS startup)
            cmnSetDefaultSettings(pcnbp->ulPageID);
            // update the display by calling the INIT callback
            (*(pcnbp->pfncbInitPage))(pnbi, CBI_SET | CBI_ENABLE);
            fRefreshStatusBars = TRUE;
            fShowStatusBars = TRUE;
        break; }

        default:
            fSave = FALSE;
    }

    if (fSave) {
        cmnStoreGlobalSettings();
    }

    // have the Worker thread update the
    // status bars for all currently open
    // folders
    if (fRefreshStatusBars)
        xthrPostWorkerMsg(WOM_UPDATEALLSTATUSBARS,
                (MPARAM)2,
                MPNULL);

    if (fShowStatusBars) {
        xthrPostWorkerMsg(WOM_UPDATEALLSTATUSBARS,
                (MPARAM)1,
                MPNULL);
        ntbUpdateVisiblePage(NULL,   // all somSelf's
                SP_XFOLDER_FLDR);
    }

    return ((MPARAM)-1);
}

/*
 *@@ fncbWPSStatusBar2InitPage:
 *      notebook callback function (notebook.c) for the
 *      second "Status bars" page in "Workplace Shell" object.
 *      Sets the controls on the page according to the
 *      Global Settings.
 */

CHAR                    szSBTextNoneSelBackup[CCHMAXMNEMONICS],
                        szSBText1SelBackup[CCHMAXMNEMONICS],
                        szSBTextMultiSelBackup[CCHMAXMNEMONICS],
                        szSBClassSelected[256];
SOMClass                *pSBClassObjectSelected = NULL;
somId                   somidClassSelected;

// definitions for "Select Class" dialog for status bars
MRESULT EXPENTRY fncbStatusBarReturnClassAttr(HWND hwndCnr, ULONG ulscd,
                    MPARAM mpwps, MPARAM mpreccParent);

MRESULT EXPENTRY fncbStatusBarClassSelected(HWND hwndCnr,  ULONG ulNLSStrings,
                    MPARAM mpwps, MPARAM mphwndInfo);

// struct passed to callbacks
typedef struct _STATUSBARSELECTCLASS {
    HWND            hwndOKButton;
    PNLSSTRINGS     pNLSStrings;
} STATUSBARSELECTCLASS, *PSTATUSBARSELECTCLASS;

VOID fncbWPSStatusBar2InitPage(PVOID pnbi,   // notebook info struct
                         ULONG ulExtra)        // INIT_* flags (notebook.h)
{
    PCREATENOTEBOOKPAGE pcnbp = (PCREATENOTEBOOKPAGE)pnbi;
    PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();

    if (ulExtra & CBI_INIT)
    {
        if (pcnbp->pBackup == NULL)
        {
            // first call: backup Global Settings for "Undo" button;
            // this memory will be freed automatically by the
            // common notebook window function (notebook.c) when
            // the notebook page is destroyed
            pcnbp->pBackup = malloc(sizeof(GLOBALSETTINGS));
            memcpy(pcnbp->pBackup, pGlobalSettings, sizeof(GLOBALSETTINGS));
        }

        strcpy(szSBTextNoneSelBackup,
                    cmnQueryStatusBarSetting(SBS_TEXTNONESEL));
        strcpy(szSBTextMultiSelBackup,
                    cmnQueryStatusBarSetting(SBS_TEXTMULTISEL));
        // status bar settings page: get last selected
        // class from INIs (for single-object mode)
        // and query the SOM class object from this string
        PrfQueryProfileString(HINI_USER, INIAPP_XFOLDER,
                INIKEY_SB_LASTCLASS, "XFldObject",
                szSBClassSelected, sizeof(szSBClassSelected));
        if (pSBClassObjectSelected == NULL) {
            somidClassSelected = somIdFromString(szSBClassSelected);
            if (somidClassSelected) {
                // get pointer to class object (e.g. M_WPObject)
                pSBClassObjectSelected = _somFindClass(SOMClassMgrObject, somidClassSelected, 0, 0);
            }
        }
        if (pSBClassObjectSelected) {
            stbQueryClassMnemonics(pSBClassObjectSelected,
                    szSBText1SelBackup,
                    sizeof(szSBText1SelBackup));
        }
    }

    if (ulExtra & CBI_SET)
    {
        CHAR    szTemp[CCHMAXMNEMONICS];

        WinSetDlgItemText(pcnbp->hwndPage, ID_XSDI_SBCURCLASS, szSBClassSelected);

        // descriptive status bar strings
        WinSendDlgItemMsg(pcnbp->hwndPage, ID_XSDI_SBTEXTNONESEL, EM_SETTEXTLIMIT,
            (MPARAM)(CCHMAXMNEMONICS-1), MPNULL);
        WinSetDlgItemText(pcnbp->hwndPage, ID_XSDI_SBTEXTNONESEL ,
            cmnQueryStatusBarSetting(SBS_TEXTNONESEL));

        WinSendDlgItemMsg(pcnbp->hwndPage, ID_XSDI_SBTEXT1SEL, EM_SETTEXTLIMIT,
            (MPARAM)(CCHMAXMNEMONICS-1), MPNULL);
        if (pSBClassObjectSelected == NULL) {
            somidClassSelected = somIdFromString(szSBClassSelected);
            if (somidClassSelected) {
                // get pointer to class object (e.g. M_WPObject)
                pSBClassObjectSelected = _somFindClass(SOMClassMgrObject, somidClassSelected, 0, 0);
            }
        }

        if (pSBClassObjectSelected) {
            stbQueryClassMnemonics(pSBClassObjectSelected,
                    szTemp,
                    sizeof(szTemp));
            WinSetDlgItemText(pcnbp->hwndPage, ID_XSDI_SBTEXT1SEL, szTemp);
        }

        WinSendDlgItemMsg(pcnbp->hwndPage, ID_XSDI_SBTEXTMULTISEL, EM_SETTEXTLIMIT,
            (MPARAM)(CCHMAXMNEMONICS-1), MPNULL);
        WinSetDlgItemText(pcnbp->hwndPage, ID_XSDI_SBTEXTMULTISEL,
            cmnQueryStatusBarSetting(SBS_TEXTMULTISEL));
    }

    if (ulExtra & CBI_ENABLE)
    {
        BOOL fEnable = !(pGlobalSettings->NoSubclassing);
        winhEnableDlgItem(pcnbp->hwndPage, ID_XSDI_SBTEXTNONESEL,   fEnable);
        winhEnableDlgItem(pcnbp->hwndPage, ID_XSDI_SBTEXT1SEL,      fEnable);
        winhEnableDlgItem(pcnbp->hwndPage, ID_XSDI_SBTEXTMULTISEL,  fEnable);
    }

    if (ulExtra & CBI_DESTROY)
        if (pSBClassObjectSelected) {
            SOMFree(somidClassSelected);
            pSBClassObjectSelected = NULL;
        }
}

/*
 *@@ fncbWPSStatusBar2ItemChanged:
 *      notebook callback function (notebook.c) for the
 *      second "Status bars" page in "Workplace Shell" object.
 *      Reacts to changes of any of the dialog controls.
 */

MRESULT fncbWPSStatusBar2ItemChanged(PVOID pnbi,
                USHORT usItemID, USHORT usNotifyCode,
                ULONG ulExtra)      // for checkboxes: contains new state
{
    PCREATENOTEBOOKPAGE pcnbp = (PCREATENOTEBOOKPAGE)pnbi;
    PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
    BOOL fSave = TRUE;
    CHAR szDummy[CCHMAXMNEMONICS];

    switch (usItemID) {
        case ID_XSDI_SBTEXTNONESEL:
            WinQueryDlgItemText(pcnbp->hwndPage, ID_XSDI_SBTEXTNONESEL,
                            sizeof(szDummy)-1, szDummy);
            cmnSetStatusBarSetting(SBS_TEXTNONESEL, szDummy);

            if (pSBClassObjectSelected == NULL) {
                somidClassSelected = somIdFromString(szSBClassSelected);
                if (somidClassSelected) {
                    // get pointer to class object (e.g. M_WPObject)
                    pSBClassObjectSelected = _somFindClass(SOMClassMgrObject, somidClassSelected, 0, 0);
                }
            }
        break;

        case ID_XSDI_SBTEXT1SEL:
            if (pSBClassObjectSelected) {
                WinQueryDlgItemText(pcnbp->hwndPage, ID_XSDI_SBTEXT1SEL,
                                sizeof(szDummy)-1, szDummy);
                stbSetClassMnemonics(pSBClassObjectSelected,
                                szDummy);
            }
        break;

        case ID_XSDI_SBTEXTMULTISEL:
            WinQueryDlgItemText(pcnbp->hwndPage, ID_XSDI_SBTEXTMULTISEL,
                            sizeof(szDummy)-1, szDummy);
            cmnSetStatusBarSetting(SBS_TEXTMULTISEL, szDummy);
        break;

        // "Select class" on "Status Bars" page:
        // set up WPS classes dialog
        case ID_XSDI_SBSELECTCLASS: {
            SELECTCLASSDATA         scd;
            STATUSBARSELECTCLASS    sbsc;

            CHAR szTitle[100] = "title";
            CHAR szIntroText[2000] = "intro";

            cmnGetMessage(NULL, 0, szTitle, sizeof(szTitle), 112);
            cmnGetMessage(NULL, 0, szIntroText, sizeof(szIntroText), 113);
            scd.pszDlgTitle = szTitle;
            scd.pszIntroText = szIntroText;
            scd.pszRootClass = "WPObject";
            scd.pszOrphans = NULL;
            strcpy(scd.szClassSelected, szSBClassSelected);

            // these callback funcs are defined way more below
            scd.pfnwpReturnAttrForClass = fncbStatusBarReturnClassAttr;
            scd.pfnwpClassSelected = fncbStatusBarClassSelected;
            // the folllowing data will be passed to the callbacks
            // so the callback can display NLS messages
            sbsc.pNLSStrings = cmnQueryNLSStrings();
            scd.ulUserClassSelected = (ULONG)&sbsc;

            scd.pszHelpLibrary = cmnQueryHelpLibrary();
            scd.ulHelpPanel = ID_XFH_SELECTCLASS;

            if (clsSelectWpsClassDlg(pcnbp->hwndPage,
                    NLS_MODULE, ID_XSD_SELECTCLASS,
                    &scd) == DID_OK)
            {
                strcpy(szSBClassSelected, scd.szClassSelected);
                WinSetDlgItemText(pcnbp->hwndPage, ID_XSDI_SBCURCLASS, szSBClassSelected);
                PrfWriteProfileString(HINI_USER, INIAPP_XFOLDER, INIKEY_SB_LASTCLASS,
                            szSBClassSelected);
                if (pSBClassObjectSelected) {
                    SOMFree(somidClassSelected);
                    pSBClassObjectSelected = NULL;
                    // this will provoke the following func to re-read
                    // the class's status bar mnemonics
                }

                // update the display by calling the INIT callback
                (*(pcnbp->pfncbInitPage))(pnbi, CBI_SET | CBI_ENABLE);

                // refresh the "Undo" data for this
                stbQueryClassMnemonics(pSBClassObjectSelected,
                        szSBText1SelBackup,
                        sizeof(szSBText1SelBackup));

            }
        break; }

        case DID_UNDO: {
            // "Undo" button: get pointer to backed-up Global Settings
            PGLOBALSETTINGS pGSBackup = (PGLOBALSETTINGS)(pcnbp->pBackup);

            // and restore the settings for this page
            cmnSetStatusBarSetting(SBS_TEXTNONESEL,
                    szSBTextNoneSelBackup);
            cmnSetStatusBarSetting(SBS_TEXTMULTISEL,
                    szSBTextMultiSelBackup);

            if (pSBClassObjectSelected == NULL) {
                somidClassSelected = somIdFromString(szSBClassSelected);
                if (somidClassSelected) {
                    // get pointer to class object (e.g. M_WPObject)
                    pSBClassObjectSelected = _somFindClass(SOMClassMgrObject, somidClassSelected, 0, 0);
                }
            }
            if (pSBClassObjectSelected) {
                stbSetClassMnemonics(pSBClassObjectSelected,
                                szSBText1SelBackup);
            }

            // update the display by calling the INIT callback
            (*(pcnbp->pfncbInitPage))(pnbi, CBI_SET | CBI_ENABLE);
        break; }

        case DID_DEFAULT: {
            // set the default settings for this settings page
            // (this is in common.c because it's also used at
            // WPS startup)
            cmnSetStatusBarSetting(SBS_TEXTNONESEL, NULL);  // load default
            cmnSetStatusBarSetting(SBS_TEXTMULTISEL, NULL); // load default

            if (pSBClassObjectSelected == NULL) {
                somidClassSelected = somIdFromString(szSBClassSelected);
                if (somidClassSelected) {
                    // get pointer to class object (e.g. M_WPObject)
                    pSBClassObjectSelected = _somFindClass(SOMClassMgrObject, somidClassSelected, 0, 0);
                }
            }
            if (pSBClassObjectSelected) {
                stbSetClassMnemonics(pSBClassObjectSelected,
                                NULL);  // load default
            }
            // update the display by calling the INIT callback
            (*(pcnbp->pfncbInitPage))(pnbi, CBI_SET | CBI_ENABLE);
        break; }

        default:
            fSave = FALSE;
    }

    if (fSave) {
        cmnStoreGlobalSettings();
        // have the Worker thread update the
        // status bars for all currently open
        // folders
        xthrPostWorkerMsg(WOM_UPDATEALLSTATUSBARS,
                (MPARAM)2, // update display
                MPNULL);
    }

    return ((MPARAM)-1);
}

/*
 *@@ fncbWPSSnap2GridInitPage:
 *      notebook callback function (notebook.c) for the
 *      "Snap to grid" page in "Workplace Shell" object.
 *      Sets the controls on the page according to the
 *      Global Settings.
 */

VOID fncbWPSSnap2GridInitPage(PVOID pnbi,   // notebook info struct
                         ULONG ulExtra)        // INIT_* flags (notebook.h)
{
    PCREATENOTEBOOKPAGE pcnbp = (PCREATENOTEBOOKPAGE)pnbi;
    PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();

    if (ulExtra & CBI_INIT)
    {
        if (pcnbp->pBackup == NULL)
        {
            // first call: backup Global Settings for "Undo" button;
            // this memory will be freed automatically by the
            // common notebook window function (notebook.c) when
            // the notebook page is destroyed
            pcnbp->pBackup = malloc(sizeof(GLOBALSETTINGS));
            memcpy(pcnbp->pBackup, pGlobalSettings, sizeof(GLOBALSETTINGS));
        }
    }

    if (ulExtra & CBI_SET)
    {
        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_SNAPTOGRID, pGlobalSettings->AddSnapToGridItem);
        winhSetDlgItemSpinData(pcnbp->hwndPage, ID_XSDI_GRID_X, 0, 500, pGlobalSettings->GridX);
        winhSetDlgItemSpinData(pcnbp->hwndPage, ID_XSDI_GRID_Y, 0, 500, pGlobalSettings->GridY);
        winhSetDlgItemSpinData(pcnbp->hwndPage, ID_XSDI_GRID_CX, 1, 500, pGlobalSettings->GridCX);
        winhSetDlgItemSpinData(pcnbp->hwndPage, ID_XSDI_GRID_CY, 1, 500, pGlobalSettings->GridCY);
    }
}

/*
 *@@ fncbWPSSnap2GridItemChanged:
 *      notebook callback function (notebook.c) for the
 *      "Snap to grid" page in "Workplace Shell" object.
 *      Reacts to changes of any of the dialog controls.
 */

MRESULT fncbWPSSnap2GridItemChanged(PVOID pnbi,
                USHORT usItemID, USHORT usNotifyCode,
                ULONG ulExtra)      // for checkboxes: contains new state
{
    PCREATENOTEBOOKPAGE pcnbp = (PCREATENOTEBOOKPAGE)pnbi;
    PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
    BOOL fSave = TRUE;

    switch (usItemID) {
        case ID_XSDI_SNAPTOGRID:
            pGlobalSettings->AddSnapToGridItem = ulExtra;
        break;

        case ID_XSDI_GRID_X:
            pGlobalSettings->GridX = ulExtra;
        break;

        case ID_XSDI_GRID_Y:
            pGlobalSettings->GridY = ulExtra;
        break;

        case ID_XSDI_GRID_CX:
            pGlobalSettings->GridCX = ulExtra;
        break;

        case ID_XSDI_GRID_CY:
            pGlobalSettings->GridCY = ulExtra;
        break;

        case DID_UNDO: {
            // "Undo" button: get pointer to backed-up Global Settings
            PGLOBALSETTINGS pGSBackup = (PGLOBALSETTINGS)(pcnbp->pBackup);

            // and restore the settings for this page
            pGlobalSettings->AddSnapToGridItem = pGSBackup->AddSnapToGridItem;
            pGlobalSettings->GridX = pGSBackup->GridX;
            pGlobalSettings->GridY = pGSBackup->GridY;
            pGlobalSettings->GridCX = pGSBackup->GridCX;
            pGlobalSettings->GridCY = pGSBackup->GridCY;

            // update the display by calling the INIT callback
            (*(pcnbp->pfncbInitPage))(pnbi, CBI_SET | CBI_ENABLE);
        break; }

        case DID_DEFAULT: {
            // set the default settings for this settings page
            // (this is in common.c because it's also used at
            // WPS startup)
            cmnSetDefaultSettings(pcnbp->ulPageID);
            // update the display by calling the INIT callback
            (*(pcnbp->pfncbInitPage))(pnbi, CBI_SET | CBI_ENABLE);
        break; }

        default:
            fSave = FALSE;
    }

    if (fSave)
        cmnStoreGlobalSettings();

    return ((MPARAM)-1);
}

/*
 *@@ fncbWPSFldrHotkeysInitPage:
 *      notebook callback function (notebook.c) for the
 *      "Folder hotkeys" page in "Workplace Shell" object.
 *      Sets the controls on the page according to the
 *      Global Settings.
 */

VOID fncbWPSFldrHotkeysInitPage(PVOID pnbi,   // notebook info struct
                         ULONG ulExtra)        // INIT_* flags (notebook.h)
{
    PCREATENOTEBOOKPAGE pcnbp = (PCREATENOTEBOOKPAGE)pnbi;
    PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();

    HWND    hwndEditField = WinWindowFromID(pcnbp->hwndPage, ID_XSDI_DESCRIPTION);
    HWND    hwndListbox = WinWindowFromID(pcnbp->hwndPage, ID_XSDI_LISTBOX);

    SHORT i;

    if (ulExtra & CBI_INIT)
    {
        HAB     hab = WinQueryAnchorBlock(pcnbp->hwndPage);
        HMODULE hmod = NLS_MODULE;
        PFNWP   OldEditProc;

        if (pcnbp->pBackup == NULL)
        {
            // first call: backup Global Settings for "Undo" button;
            // this memory will be freed automatically by the
            // common notebook window function (notebook.c) when
            // the notebook page is destroyed
            pcnbp->pBackup = malloc(sizeof(GLOBALSETTINGS));
            memcpy(pcnbp->pBackup, pGlobalSettings, sizeof(GLOBALSETTINGS));
            // and also backup the Folder Hotkeys array in the
            // second pointer
            pcnbp->pBackup2 = malloc(FLDRHOTKEYSSIZE);
            memcpy(pcnbp->pBackup2,
                        cmnQueryFldrHotkeys(),
                        FLDRHOTKEYSSIZE);
        }

        for (i = 0; i < FLDRHOTKEYCOUNT; i++)
        {
            if (WinLoadString(hab, hmod,
                    szLBStringIDs[i],
                    sizeof(szLBEntries[i]),
                    szLBEntries[i])
               == 0)
            {
                DebugBox("XFolder", "Unable to load strings.");
                break;
            }
        }

        OldEditProc = WinSubclassWindow(hwndEditField, fnwpHotkeyEntryField);
        WinSetWindowULong(hwndEditField, QWL_USER, (ULONG)OldEditProc);
    }

    if (ulExtra & CBI_SET)
    {
        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_ACCELERATORS, pGlobalSettings->Accelerators);

        WinSendMsg(hwndListbox, LM_DELETEALL, 0, 0);
        WinSetWindowText(hwndEditField, "");

        for (i = 0; i < FLDRHOTKEYCOUNT; i++)
        {
            if (szLBEntries[i])
            {
                WinSendMsg(hwndListbox,
                        LM_INSERTITEM,
                        (MPARAM)LIT_SORTASCENDING,
                        (MPARAM)szLBEntries[i]);
            }
            else break;
        }
    }

    if (ulExtra & CBI_ENABLE)
    {
        BOOL fEnable = !(pGlobalSettings->NoSubclassing);
        winhEnableDlgItem(pcnbp->hwndPage, ID_XSDI_ACCELERATORS, fEnable);
        winhEnableDlgItem(pcnbp->hwndPage, ID_XSDI_LISTBOX, fEnable);
        winhEnableDlgItem(pcnbp->hwndPage, ID_XSDI_CLEARACCEL, fEnable);
    }
}

/*
 *@@ fncbWPSFldrHotkeysItemChanged:
 *      notebook callback function (notebook.c) for the
 *      "Snap to grid" page in "Workplace Shell" object.
 *      Reacts to changes of any of the dialog controls.
 */

MRESULT fncbWPSFldrHotkeysItemChanged(PVOID pnbi,
                USHORT usItemID, USHORT usNotifyCode,
                ULONG ulExtra)      // for checkboxes: contains new state
{
    PCREATENOTEBOOKPAGE pcnbp = (PCREATENOTEBOOKPAGE)pnbi;
    PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();

    switch (usItemID) {
        case ID_XSDI_ACCELERATORS:
            pGlobalSettings->Accelerators = ulExtra;
            cmnStoreGlobalSettings();
        break;

        case ID_XSDI_LISTBOX: {
            if (usNotifyCode == LN_SELECT)
            {
                // new hotkey description from listbox selected:
                CHAR            szKeyName[200];
                PXFLDHOTKEY     pHotkeyFound;

                // update the Edit field with new
                // key description, but do NOT save settings yet
                pHotkeyFound = FindHotkeyFromLBSel(pcnbp->hwndPage, NULL);
                if ( (pHotkeyFound) && ((ULONG)pHotkeyFound != -1) )
                {
                    cmnDescribeKey(szKeyName, pHotkeyFound->usFlags,
                                              pHotkeyFound->usKeyCode);
                    winhEnableDlgItem(pcnbp->hwndPage, ID_XSDI_CLEARACCEL, TRUE);
                }
                else { // not found: set to "not defined"
                    strcpy(szKeyName,
                        (cmnQueryNLSStrings())->pszNotDefined);

                    winhEnableDlgItem(pcnbp->hwndPage, ID_XSDI_CLEARACCEL, FALSE);
                }

                // set edit field to description text
                WinSetDlgItemText(pcnbp->hwndPage, ID_XSDI_DESCRIPTION,
                            szKeyName);
                // enable previously disabled items
                winhEnableDlgItem(pcnbp->hwndPage, ID_XSDI_DESCRIPTION, TRUE);
                winhEnableDlgItem(pcnbp->hwndPage, ID_XSDI_DESCRIPTION_TX1, TRUE);
            }
        break; }

        // we need not handle the entry field, because the
        // subclassed window procedure for that is smart
        // enough to update the hotkeys data itself

        case ID_XSDI_CLEARACCEL: {
            // "Clear" button:
            USHORT      usCommand;
            PXFLDHOTKEY pHotkeyFound;

            pHotkeyFound = FindHotkeyFromLBSel(pcnbp->hwndPage, &usCommand);

            if ( (pHotkeyFound) && ((ULONG)pHotkeyFound != -1) )
            {
                // accelerator defined:
                PXFLDHOTKEY pHotkey = pHotkeyFound;

                // in order to delete the marked accelerator,
                // move all following hotkeys in the global
                // hotkeys table one position ahead
                while (pHotkey->usCommand)
                {
                    memcpy(pHotkey, pHotkey+1, sizeof(XFLDHOTKEY));
                    pHotkey++;
                }

                WinSetDlgItemText(pcnbp->hwndPage, ID_XSDI_DESCRIPTION,
                            (cmnQueryNLSStrings())->pszNotDefined);
                winhEnableDlgItem(pcnbp->hwndPage, ID_XSDI_CLEARACCEL, FALSE);
                cmnStoreFldrHotkeys();
            }
        break; }

        case DID_UNDO: {
            // "Undo" button: get pointer to backed-up Global Settings
            PGLOBALSETTINGS pGSBackup = (PGLOBALSETTINGS)(pcnbp->pBackup);

            // and restore the settings for this page
            pGlobalSettings->Accelerators = pGSBackup->Accelerators;

            // here, also restore the backed-up FolderHotkeys array
            // second pointer
            memcpy(cmnQueryFldrHotkeys(), pcnbp->pBackup2, FLDRHOTKEYSSIZE);

            // update the display by calling the INIT callback
            (*(pcnbp->pfncbInitPage))(pnbi, CBI_SET | CBI_ENABLE);
            cmnStoreFldrHotkeys();
        break; }

        case DID_DEFAULT: {
            // set the default settings for this settings page
            // (this is in common.c because it's also used at
            // WPS startup)
            cmnSetDefaultSettings(pcnbp->ulPageID);
            cmnLoadDefaultFldrHotkeys();
            // update the display by calling the INIT callback
            (*(pcnbp->pfncbInitPage))(pnbi, CBI_SET | CBI_ENABLE);
            cmnStoreGlobalSettings();
            cmnStoreFldrHotkeys();
        break; }
    }

    return ((MPARAM)-1);
}

/* ******************************************************************
 *                                                                  *
 *   callback funcs for "Select Statusbar Class" dlg                *
 *                                                                  *
 ********************************************************************/

/*
 * All these funcs are called from the dialog funcs in
 * classlst.c, which are in turn called when the "Select class"
 * button is pressed on the "Status bars" settings page.
 *
 */

/*
 *@@ fncbStatusBarReturnClassAttr:
 *      this callback function is called for every single
 *      record core which represents a WPS class; we need
 *      to return the record core attributes
 */

MRESULT EXPENTRY fncbStatusBarReturnClassAttr(HWND hwndCnr,
                    ULONG ulscd,   // SELECTCLASSDATA struct
                    MPARAM mpwps,  // current WPSLISTITEM struct
                    MPARAM mpreccParent) // parent record core
{
    USHORT          usAttr = CRA_RECORDREADONLY | CRA_COLLAPSED | CRA_DISABLED;
    PWPSLISTITEM     pwps = (PWPSLISTITEM)mpwps;
    PSELECTCLASSDATA pscd = (PSELECTCLASSDATA)ulscd;
    PRECORDCORE     preccParent = NULL;

    if (pwps) {
        #ifdef DEBUG_SETTINGS
            _Pmpf(("Checking %s", pwps->pszClassName));
        #endif
        if (pwps->pClassObject) {

            // now check if the class supports new sort mnemonics
            // if (somResolveByName(pwps->pClassObject, "xfclsAddsNewStatusBarMnemonics"))
            if (    (stbClassAddsNewMnemonics(pwps->pClassObject))
                 // && (strlen(pwps->szReplacedByClass) == 0)
               )
            {
                // class _does_ support mnemonics: give the
                // new recc attr the "in use" flag
                usAttr = CRA_RECORDREADONLY | CRA_COLLAPSED | CRA_INUSE;

                // and select it if the settings notebook wants it
                if (strcmp(pwps->pszClassName, pscd->szClassSelected) == 0)
                    usAttr |= CRA_SELECTED;

                // expand all the parent records of the new record
                // so that classes with status bar mnemonics are
                // all initially visible in the container
                preccParent = (PRECORDCORE)mpreccParent;
                while (preccParent)
                {
                    WinSendMsg(hwndCnr, CM_EXPANDTREE, (MPARAM)preccParent, MPNULL);

                    preccParent = WinSendMsg(hwndCnr, CM_QUERYRECORD,
                            preccParent,
                            MPFROM2SHORT(CMA_PARENT, CMA_ITEMORDER));

                    if (preccParent == (PRECORDCORE)-1) {
                        preccParent = NULL;
                    }
                }
            }

        } // end if if (pwps->pClassObject)
        else {
            // invalid class: hide in cnr
            usAttr = CRA_FILTERED;
        }
    }
    return (MPARAM)(usAttr);
}

/*
 *@@ fncbStatusBarClassSelected:
 *      callback func for class selected;
 *      mphwndInfo has been set to the static control hwnd.
 *      Returns TRUE if the selection is valid; the dlg func
 *      will then enable the OK button.
 */

MRESULT EXPENTRY fncbStatusBarClassSelected(HWND hwndCnr, ULONG ulpsbsc,
                    MPARAM mpwps, MPARAM mphwndInfo)
{
    PWPSLISTITEM pwps = (PWPSLISTITEM)mpwps;
    PSTATUSBARSELECTCLASS psbsc = (PSTATUSBARSELECTCLASS)ulpsbsc;
    CHAR szInfo[2000];
    MRESULT mrc = (MPARAM)FALSE;
    PSZ pszClassTitle;

    strcpy(szInfo, pwps->pszClassName);

    if (pwps->pClassObject) {
        pszClassTitle = _wpclsQueryTitle(pwps->pClassObject);
        if (pszClassTitle)
            sprintf(szInfo, "%s (\"%s\")\n",
                    pwps->pszClassName,
                    pszClassTitle);
    }

    if (pwps->pRecord->flRecordAttr & CRA_INUSE) {
        strcat(szInfo, (psbsc->pNLSStrings)->pszSBClassMnemonics );
        strcat(szInfo, "\n");
        stbQueryClassMnemonics(pwps->pClassObject,
                &(szInfo[strlen(szInfo)]), 256);
        mrc = (MPARAM)TRUE;
    } else {
        strcat(szInfo,
                psbsc->pNLSStrings->pszSBClassNotSupported);
    }

    WinSetWindowText((HWND)mphwndInfo, szInfo);

    return (mrc);
}

/* ******************************************************************
 *                                                                  *
 *   "WPS Classes" notebook page functions                          *
 *                                                                  *
 ********************************************************************/

/*
 *  The "WPS Classes" notebook page in "Workplace Shell" does not
 *  use the callbacks, but a regular notebook dlg function because
 *  it needs to handle lots of container messages, which the function
 *  in notebook.c does not handle.
 */

/*
 *@@ strParseDescription:
 *      searches pszBuf for pszSrch0 ; if found, the line containing
 *      pszSrch is parsed as follows:
 *          <pszSrch0 > <ulFlags> <RestOfLine>
 *             PSZ       hex str     PSZ
 *      Returns length of what was copied to pszDescription or
 *      zero on errors.
 *      This is used for explaing a certain WPS class when it is
 *      being selected in the "WPS classes" notebook page.
 *      This returns TRUE if pszSrch0 was found.
 */

BOOL strParseDescription(PSZ pszBuf, PSZ pszSrch0, PULONG pulFlags, PSZ pszDescription)
{
    BOOL brc = FALSE;
    PSZ p1, p2;

    // create search string for beginning of line
    PSZ pszSrch2 = malloc(strlen(pszSrch0) + 4);
    strcpy(pszSrch2, "\r\n");
    strcat(pszSrch2, pszSrch0);

    p1 = strstr(pszBuf, pszSrch2);
    if (p1) {
        p1 += 2; // skip \r\n
        p1 = strchr(p1, ' ');
        if (p1) {
            // p1 now has ulFlags
            sscanf(p1, "%lX ", pulFlags);
            p1 = strchr(p1+1, ' ');
            if (p1) {
                brc = TRUE;
                // p1 now has beginning of description
                p2 = strstr(p1, "\r\n");
                if (p2) {
                    // p2 now has end of description
                    strncpy(pszDescription, p1+1, (p2-p1-1));
                } else
                    strncat(pszDescription, p1+1, 200);
            }
        }
    }
    return (brc);
}

PSZ pszClassInfo = NULL;
HWND hwndClassInfo = NULLHANDLE;

/*
 *@@ UpdateClassInfo:
 *      this is called every time a new class gets selected
 *      in the "WPS classes" page: update the infos
 */

VOID UpdateClassInfo(HWND hwndDlg, PCLASSRECORDCORE pRecordSelected)
{
    PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
    HWND hwndIcon = NULLHANDLE;
    HPOINTER hClassIcon = NULLHANDLE;

    if (pGlobalSettings->WpsShowClassInfo) {
        PWPSLISTITEM pwps = pRecordSelected->pwps;
        CHAR szInfo[1000] = "", szInfo2[256] = "";
        BOOL fCreate = FALSE;
        PNLSSTRINGS pNLSStrings = cmnQueryNLSStrings();

        if (hwndClassInfo)
            fCreate = !(WinIsWindow(
                    WinQueryAnchorBlock(HWND_DESKTOP),
                    hwndClassInfo));
        if (    (hwndClassInfo == NULLHANDLE)
             || (fCreate)
           )
        {
            hwndClassInfo = WinLoadDlg(HWND_DESKTOP, hwndDlg,
                              fnwpDlgGeneric,
                              NLS_MODULE, ID_XSD_SETTINGS_WPSCL_INFO,
                              NULL);
            hwndIcon = WinWindowFromID(hwndClassInfo, ID_XSDI_SC_ICON);
            anmPrepareStaticIcon(hwndIcon, 1);
        }

        if (pwps) {
                /* WinSendDlgItemMsg(hwndDlg, ID_XSDI_SC_CLASSICON,
                        SM_SETHANDLE,
                        (MPARAM)_ wpclsQueryIcon(pwps->pClassObject),
                        MPNULL); */
            // dll name
            WinSetDlgItemText(hwndClassInfo, ID_XSDI_SC_CLASSMODULE, pwps->pszModName);

            // class name
            strcpy(szInfo, pwps->pszClassName);
            WinSetDlgItemText(hwndClassInfo, ID_XSDI_SC_CLASSNAME, szInfo);

            // "replaced by"
            WinSetDlgItemText(hwndClassInfo, ID_XSDI_SC_REPLACEDBY,
                    (pwps->pszReplacedWithClasses)
                        ? pwps->pszReplacedWithClasses
                        : "");

            // class icon
            hwndIcon = WinWindowFromID(hwndClassInfo, ID_XSDI_SC_ICON);
            if (pwps->pClassObject)
                hClassIcon = _wpclsQueryIcon(pwps->pClassObject);
            WinSendMsg(hwndIcon,
                       SM_SETHANDLE,
                       (MPARAM)hClassIcon,  // NULLHANDLE if error -> hide
                       MPNULL);

            // class title
            if (pwps->pClassObject) {
                PSZ pszClassTitle = _wpclsQueryTitle(
                                pwps->pClassObject);
                if (pszClassTitle)
                    sprintf(szInfo2,
                        "\"%s\"",
                        pszClassTitle);
                else
                    strcpy(szInfo2, "?");
            } else
                strcpy(szInfo2, pNLSStrings->pszWpsClassLoadingFailed);
            WinSetDlgItemText(hwndClassInfo, ID_XSDI_SC_CLASSTITLE, szInfo2);

            // class information
            if (pszClassInfo) {
                ULONG ulFlags;
                if (!strParseDescription(pszClassInfo,
                            pwps->pszClassName,
                            &ulFlags,
                            szInfo))
                {
                    // not found: search for "UnknownClass"
                    strParseDescription(pszClassInfo,
                            "UnknownClass",
                            &ulFlags,
                            szInfo);
                }
            }
        } // end if (pwps)
        else {
            // if (pwps == NULL), the "Orphans" item has been
            // selected: give info for this
            strcpy(szInfo, pNLSStrings->pszWpsClassOrphansInfo);
            WinSetDlgItemText(hwndClassInfo, ID_XSDI_SC_CLASSMODULE, "");
            WinSetDlgItemText(hwndClassInfo, ID_XSDI_SC_CLASSNAME, "");
            WinSetDlgItemText(hwndClassInfo, ID_XSDI_SC_REPLACEDBY, "");
            WinSetDlgItemText(hwndClassInfo, ID_XSDI_SC_CLASSTITLE, "");

            hwndIcon = WinWindowFromID(hwndClassInfo, ID_XSDI_SC_ICON);
            WinSendMsg(hwndIcon,
                       SM_SETHANDLE,
                       (MPARAM)NULLHANDLE,  // hide icon
                       MPNULL);
        }

        // give MLE new text
        WinSetDlgItemText(hwndClassInfo, ID_XSDI_SC_TEXT2, szInfo);
        // scroll MLE to top
        WinSendDlgItemMsg(hwndClassInfo, ID_XSDI_SC_TEXT2,
                MLM_SETFIRSTCHAR,
                (MPARAM)0,
                MPNULL);

        WinShowWindow(hwndClassInfo, TRUE);
    } // end if (pGlobalSettings->WpsShowClassInfo)
    else {
        if (hwndClassInfo)
            if (WinIsWindow(
                    WinQueryAnchorBlock(HWND_DESKTOP),
                    hwndClassInfo))
                WinShowWindow(hwndClassInfo, FALSE);
    }
}

/*
 *@@ fncbReturnWPSClassAttr:
 *      this callback function is called for every single
 *      record core which represents a WPS class; we need
 *      to return the record core attributes
 */

MRESULT EXPENTRY fncbReturnWPSClassAttr(HWND hwndCnr,
                    ULONG ulscd,   // SELECTCLASSDATA struct
                    MPARAM mpwps,  // current WPSLISTITEM struct
                    MPARAM mpreccParent) // parent record core
{
    USHORT          usAttr = CRA_RECORDREADONLY | CRA_COLLAPSED;
    PWPSLISTITEM     pwps = (PWPSLISTITEM)mpwps;
    PSELECTCLASSDATA pscd = (PSELECTCLASSDATA)ulscd;
    PRECORDCORE     preccParent = NULL;

    if (pwps) {
        #ifdef DEBUG_SETTINGS
            _Pmpf(("Checking %s\n", pwps->pszClassName));
        #endif
        // if the class is one of the following,
        // expand all the parent records of the new record
        // so that these classes are initially visible
        if (    (strcmp(pwps->pszClassName, "WPAbstract") == 0)
             || (strcmp(pwps->pszClassName, "XFldDataFile") == 0)
             || (strcmp(pwps->pszClassName, "XFolder") == 0)
           )
        {
            preccParent = (PRECORDCORE)mpreccParent;
            while (preccParent)
            {
                WinSendMsg(hwndCnr, CM_EXPANDTREE, (MPARAM)preccParent, MPNULL);

                preccParent = WinSendMsg(hwndCnr, CM_QUERYRECORD,
                        preccParent,
                        MPFROM2SHORT(CMA_PARENT, CMA_ITEMORDER));

                if (preccParent == (PRECORDCORE)-1) {
                    preccParent = NULL;
                }
            }
        }
    }
    return (MPARAM)(usAttr);
}

/*
 *@@ fncbReplaceClassSelected:
 *      callback func for class selected in the "Replace
 *      with subclass" dlg;
 *      mphwndInfo has been set to the static control hwnd.
 *      Returns TRUE if the selection is valid; the dlg func
 *      will then enable the OK button.
 */

MRESULT EXPENTRY fncbReplaceClassSelected(HWND hwndCnr, ULONG ulpsbsc,
                    MPARAM mpwps, MPARAM mphwndInfo)
{
    PWPSLISTITEM pwps = (PWPSLISTITEM)mpwps;
    PSTATUSBARSELECTCLASS psbsc = (PSTATUSBARSELECTCLASS)ulpsbsc;
    PSZ pszClassTitle;
    CHAR szInfo[2000] = "";

    if (pwps->pClassObject) {
        if (pszClassInfo) {
            ULONG ulFlags;
            if (!strParseDescription(pszClassInfo,
                        pwps->pszClassName,
                        &ulFlags,
                        szInfo))
            {
                // not found: search for "UnknownClass"
                strParseDescription(pszClassInfo,
                        "UnknownClass",
                        &ulFlags,
                        szInfo);
            }
        }
    }

    WinSetWindowText((HWND)mphwndInfo, szInfo);

    return (MRESULT)TRUE;
}

/*
 *@@ fnwpSettingsWpsClasses:
 *      dlg func for "WPS Classes" notebook page; this does
 *      _not_ use the common notebook funcs, because it needs
 *      to handle too many different (cnr) messages
 */

BOOL fFillingCnr = FALSE;

MRESULT EXPENTRY fnwpSettingsWpsClasses(HWND hwndDlg, ULONG msg, MPARAM mp1, MPARAM mp2)
{
    MRESULT mrc = MPNULL;
    PSELECTCLASSDATA pscd = (PSELECTCLASSDATA)WinQueryWindowULong(hwndDlg, QWL_USER);

    switch(msg) {

        /*
         * WM_INITDLG:
         *      set up the container data and colors
         */

        case WM_INITDLG: {
            CNRINFO CnrInfo;

            mrc = WinDefDlgProc(hwndDlg, msg, mp1, mp2);

            pscd = (PSELECTCLASSDATA)malloc(sizeof(SELECTCLASSDATA));
            memset(pscd, 0, sizeof(SELECTCLASSDATA));
            WinSetWindowULong(hwndDlg, QWL_USER, (ULONG)pscd);

            // make Warp 4 notebook buttons and move controls
            winhAssertWarp4Notebook(hwndDlg,
                    100,         // ID threshold
                    WARP4_NOTEBOOK_OFFSET);   // move other controls offset (common.h)

            // setup container
            pscd->hwndCnr = WinWindowFromID(hwndDlg, ID_XSDI_SC_CNR);
            WinSendMsg(pscd->hwndCnr, CM_QUERYCNRINFO, &CnrInfo, (MPARAM)sizeof(CnrInfo));
            CnrInfo.pSortRecord = (PVOID)fnCompareName;
            CnrInfo.flWindowAttr =
                    CV_TREE | CA_TREELINE | CV_TEXT;
            CnrInfo.cxTreeIndent = 30;
            WinSendMsg(pscd->hwndCnr, CM_SETCNRINFO,
                    &CnrInfo,
                    (MPARAM)(CMA_PSORTRECORD | CMA_FLWINDOWATTR | CMA_CXTREEINDENT));

            WinPostMsg(hwndDlg, WM_SETTINGS2DLG, MPNULL, MPNULL);

            // fill container later
            fFillingCnr = FALSE;
            WinSendMsg(hwndDlg, WM_FILLCNR, MPNULL, MPNULL);
        break; }

        /*
         * WM_FILLCNR:
         *      this fills the cnr with all the WPS classes
         */

        case WM_FILLCNR: {
            HPOINTER hptrOld = WinQueryPointer(HWND_DESKTOP);
            CHAR szClassInfoFile[CCHMAXPATH];
            ULONG ulCopied;
            PNLSSTRINGS pNLSStrings = cmnQueryNLSStrings();

            WinSetPointer(HWND_DESKTOP,
                    WinQuerySysPointer(HWND_DESKTOP, SPTR_WAIT, FALSE));
            fFillingCnr = TRUE;

            pscd->pszRootClass = "WPObject";
            strcpy(pscd->szClassSelected, "WPObject");

            pscd->pfnwpReturnAttrForClass = fncbReturnWPSClassAttr;
            pscd->pfnwpClassSelected = NULL; // fncbStatusBarClassSelected;
            // scd.ulUserClassSelected = (ULONG)&sbsc;

            if (cmnQueryXFolderBasePath(szClassInfoFile))
            {
                sprintf(szClassInfoFile+strlen(szClassInfoFile),
                        "\\help\\xfcls%s.txt",
                        cmnQueryLanguageCode());
                // _Pmpf(("Class info file: %s", szClassInfoFile));
                pszClassInfo = doshReadTextFile(szClassInfoFile, 100);
            } else
                return (NULL);

            // add orphans; this is done by setting the title
            // for the "Orphans" recc tree
            pscd->pszOrphans = pNLSStrings->pszWpsClassOrphans;

            // fill container with WPS data (classlst.c)
            pscd->pwpsc = clsWpsClasses2Cnr(pscd->hwndCnr, pscd->pszRootClass,
                    pscd);  // also contains callback

            fFillingCnr = FALSE;
            WinSetPointer(HWND_DESKTOP, hptrOld);
        break; }

        case WM_SETTINGS2DLG: {
            PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
            winhSetDlgItemChecked(hwndDlg, ID_XSDI_SC_BOOTUPSTATUS, pGlobalSettings->ShowBootupStatus);
        break; }

        case WM_DLG2SETTINGS: {
            PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
            pGlobalSettings->ShowBootupStatus = winhIsDlgItemChecked(hwndDlg, ID_XSDI_SC_BOOTUPSTATUS);
            cmnStoreGlobalSettings(); // update INI
        break; }

        /*
         * WM_TIMER:
         *      timer for tree view auto-scroll (we don't
         *      use the Worker thread here)
         */

        case WM_TIMER: {
            if ( ( pscd->preccExpanded->flRecordAttr & CRA_EXPANDED) != 0 ) {
                PRECORDCORE     preccLastChild;
                WinStopTimer(WinQueryAnchorBlock(hwndDlg),
                        hwndDlg,
                        1);
                // scroll the tree view properly
                preccLastChild = WinSendMsg(pscd->hwndCnr,
                        CM_QUERYRECORD,
                        pscd->preccExpanded,   // expanded PRECORDCORE from CN_EXPANDTREE
                    MPFROM2SHORT(CMA_LASTCHILD, CMA_ITEMORDER));
                if (preccLastChild) {
                    // ULONG ulrc;
                    winhCnrScrollToRecord(pscd->hwndCnr,
                            (PRECORDCORE)preccLastChild,
                            CMA_TEXT,   // record text rectangle only
                            TRUE);      // keep parent visible
                }
            }
        }

        /*
         * WM_CONTROL:
         *      capture cnr notifications
         */

        case WM_CONTROL: {
            if (SHORT1FROMMP(mp1) == ID_XSDI_SC_BOOTUPSTATUS) {
                WinPostMsg(hwndDlg, WM_DLG2SETTINGS, MPNULL, MPNULL);
            } else if (SHORT1FROMMP(mp1) == ID_XSDI_SC_CNR) {

                switch (SHORT2FROMMP(mp1)) { // notify code

                    /*
                     * CN_EXPANDTREE:
                     *      tree view has been expanded:
                     *      do cnr auto-scroll if we're
                     *      not initially filling the cnr
                     */

                    case CN_EXPANDTREE: {
                        if (!fFillingCnr) {
                            PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
                            if (pGlobalSettings->TreeViewAutoScroll) {
                                pscd->preccExpanded = (PRECORDCORE)mp2;
                                WinStartTimer(WinQueryAnchorBlock(hwndDlg),
                                        hwndDlg,
                                        1,
                                        100);
                            }
                        }
                        mrc = MPNULL;
                    break; }

                    /*
                     * CN_CONTEXTMENU:
                     *      context menu requested
                     */

                    case CN_CONTEXTMENU: {
                        POINTL ptl;
                        HWND   hPopupMenu;
                        PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
                        ULONG ulFlagsSelected = 0;
                        CHAR szDummy[2000];

                        pscd->preccSource = (PCLASSRECORDCORE)mp2;
                        if (pscd->preccSource) {
                            QUERYRECORDRECT qRect;
                            RECTL rclRecc;

                            // we have a selection
                            LONG lrc2;
                            hPopupMenu = WinLoadMenu(hwndDlg, NLS_MODULE,
                                    ID_XSM_WPSCLASSES_SEL);

                            // give the marked item source emphasis
                            WinSendMsg(pscd->hwndCnr,
                                        CM_SETRECORDEMPHASIS,
                                        (MPARAM)pscd->preccSource,
                                        MPFROM2SHORT(TRUE,  // set emphasis
                                                CRA_SOURCE));

                            // allow deregistering?
                            if (pscd->preccSource->pwps) {
                                BOOL fAllowDeregister = TRUE;
                                if (pscd->preccSource->pwps->pszModName == NULL)
                                    // DLL == NULL: not in WPS class list,
                                    // so we better not allow touching this
                                    fAllowDeregister = FALSE;
                                else  if (pszClassInfo)
                                    // parse class info text whether this
                                    // class may be deregistered
                                    if (strParseDescription(pszClassInfo,
                                            pscd->preccSource->pwps->pszClassName,
                                            &ulFlagsSelected,
                                            szDummy))
                                        if (ulFlagsSelected == 0)
                                            fAllowDeregister = FALSE;
                                if (!fAllowDeregister)
                                    // disable "Deregister" menu item
                                    WinEnableMenuItem(hPopupMenu,
                                            ID_XSMI_WPS_DEREGISTER, FALSE);

                                // allow replacements only if the
                                // class has subclasses
                                lrc2 = (LONG)WinSendMsg(
                                        pscd->hwndCnr, CM_QUERYRECORD,
                                        (MPARAM)pscd->preccSource,
                                        MPFROM2SHORT(CMA_FIRSTCHILD, CMA_ITEMORDER));
                                if ((lrc2 == 0) || (lrc2 == -1))
                                    WinEnableMenuItem(hPopupMenu,
                                        ID_XSMI_WPS_REPLACE, FALSE);
                                // allow de-replacement only if the
                                // replaces another class
                                if (pscd->preccSource->pwps->pszReplacesThisClass == NULL)
                                    WinEnableMenuItem(hPopupMenu,
                                        ID_XSMI_WPS_UNREPLACE, FALSE);

                            } else {
                                WinEnableMenuItem(hPopupMenu,
                                    ID_XSMI_WPS_DEREGISTER, FALSE);
                                WinEnableMenuItem(hPopupMenu,
                                    ID_XSMI_WPS_REPLACE, FALSE);
                                WinEnableMenuItem(hPopupMenu,
                                    ID_XSMI_WPS_UNREPLACE, FALSE);
                            }

                            // calculate the point where to show the context
                            // menu; we use the lower-right corner of the
                            // source record core
                            qRect.cb = sizeof(qRect);
                            qRect.pRecord = (PRECORDCORE)pscd->preccSource;
                            qRect.fsExtent = CMA_TEXT;
                            WinSendMsg(pscd->hwndCnr,
                                       CM_QUERYRECORDRECT,
                                       &rclRecc,
                                       &qRect);
                            ptl.x = rclRecc.xRight;
                            ptl.y = rclRecc.yBottom;
                            // convert this to screen coordinates
                            WinMapWindowPoints(pscd->hwndCnr,
                                       HWND_DESKTOP,
                                       &ptl,
                                       1);
                        } else {
                            // no selection: different menu
                            hPopupMenu = WinLoadMenu(hwndDlg, NLS_MODULE,
                                    ID_XSM_WPSCLASSES_NOSEL);
                            WinSendMsg(pscd->hwndCnr,
                                        CM_SETRECORDEMPHASIS,
                                        (MPARAM)NULL,   // undocumented: if precc == NULL,
                                                        // the whole cnr is given emphasis
                                        MPFROM2SHORT(TRUE,  // set emphasis
                                                CRA_SOURCE));
                            // use mouse coordinates for context menu
                            WinQueryPointerPos(HWND_DESKTOP, &ptl);
                        }

                        if (hwndClassInfo) {
                            if (!WinIsWindow(
                                    WinQueryAnchorBlock(hwndDlg),
                                    hwndClassInfo))
                                pGlobalSettings->WpsShowClassInfo = FALSE;
                        } else
                            pGlobalSettings->WpsShowClassInfo = FALSE;

                        // check "info" menu item?
                        winhSetMenuItemChecked(hPopupMenu,
                                ID_XSMI_WPS_INFO,
                                (pGlobalSettings->WpsShowClassInfo));

                        _Pmpf(("ptl.x: %d, ptl.y: %d", ptl.x, ptl.y));

                        // finally, show context menu
                        WinPopupMenu(HWND_DESKTOP, hwndDlg,
                                hPopupMenu,
                                (SHORT)ptl.x,
                                (SHORT)ptl.y,
                                0,
                                PU_NONE | PU_MOUSEBUTTON1 | PU_KEYBOARD
                                | PU_HCONSTRAIN | PU_VCONSTRAIN);
                    break; }

                    /*
                     * CN_EMPHASIS:
                     *      selection changed: call UpdateClassInfo
                     */

                    case CN_EMPHASIS: {
                        // get cnr notification struct
                        PNOTIFYRECORDEMPHASIS pnre = (PNOTIFYRECORDEMPHASIS)mp2;

                        if (pnre)
                            if (    (pnre->fEmphasisMask & CRA_SELECTED)
                                 && (pnre->pRecord)
                               )
                            {
                                pscd->preccSelection = (PCLASSRECORDCORE)(pnre->pRecord);
                                UpdateClassInfo(hwndDlg, pscd->preccSelection);
                            }
                    break; }
                }
            } // end if (SHORT1FROMMP(mp1) == ID_XSDI_SC_CNR) {
        break; }

        /*
         * WM_COMMAND:
         *
         */

        case WM_COMMAND: {
            PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();

            switch (SHORT1FROMMP(mp1)) {

                // "Information" menu command
                case ID_XSMI_WPS_INFO: {
                    if (pGlobalSettings->WpsShowClassInfo) {
                        pGlobalSettings->WpsShowClassInfo = FALSE;
                    } else {
                        pGlobalSettings->WpsShowClassInfo = TRUE;
                    }
                    cmnStoreGlobalSettings();
                    UpdateClassInfo(hwndDlg, pscd->preccSelection);
                break; }

                // "Register" menu command
                case ID_XSMI_WPS_REGISTER: {
                    REGISTERCLASSDATA rcd;
                    rcd.pszHelpLibrary = cmnQueryHelpLibrary();
                    rcd.ulHelpPanel = ID_XFH_REGISTERCLASS;
                    if (WinDlgBox(HWND_DESKTOP, hwndDlg,
                                             fnwpRegisterClass,
                                             NLS_MODULE, ID_XSD_SETTINGS_WPSCL_REGISTER,
                                             &rcd) == DID_OK)
                    {
                        PSZ pTable[1];
                        HPOINTER hptrOld = WinQueryPointer(HWND_DESKTOP);
                        pTable[0] = rcd.szClassName;
                        WinSetPointer(HWND_DESKTOP,
                                WinQuerySysPointer(HWND_DESKTOP, SPTR_WAIT, FALSE));
                        WinSendMsg(pscd->hwndCnr,
                                    CM_REMOVERECORD,
                                    (MPARAM)NULL,
                                    MPFROM2SHORT(0, // remove all records
                                            CMA_FREE | CMA_INVALIDATE));
                        clsCleanupWpsClasses(pscd->pwpsc);
                        WinSetPointer(HWND_DESKTOP, hptrOld);
                        free(pszClassInfo);
                        pszClassInfo = NULL;

                        if (WinRegisterObjectClass(rcd.szClassName, rcd.szModName))
                            // success
                            cmnMessageBoxMsgExt(hwndDlg,
                                    121,
                                    pTable, 1, 131,
                                    MB_OK);
                        else
                            // error
                            cmnMessageBoxMsgExt(hwndDlg,
                                    104,
                                    pTable, 1, 132,
                                    MB_OK);

                        // fill cnr again
                        WinPostMsg(hwndDlg, WM_FILLCNR, MPNULL, MPNULL);
                    }
                break; }

                // "Deregister" menu command
                case ID_XSMI_WPS_DEREGISTER: {
                    if (pscd->preccSource)
                        if (pscd->preccSource->pwps) {
                            BOOL fAllow = FALSE;
                            CHAR szTemp[CCHMAXPATH];
                            PSZ pTable[2];
                            pTable[0] = szTemp;
                            pTable[1] = pscd->preccSource->pwps->pszReplacedWithClasses;

                            strcpy(szTemp, pscd->preccSource->pwps->pszClassName);
                                // save for later

                            // do not allow deregistering if the class is currently
                            // replaced by another class
                            if ( pscd->preccSource->pwps->pszReplacedWithClasses)
                            {
                                // show warning
                                cmnMessageBoxMsgExt(hwndDlg,
                                            116,
                                            pTable, 2, 139,
                                            MB_OK);
                                // and stop
                                break;
                            }

                            if (strncmp(pscd->preccSource->pwps->pszClassName,
                                            "XFld", 4) == 0) {
                                // XFolder class
                                if (cmnMessageBoxMsgExt(hwndDlg,
                                            116,
                                            pTable, 1, 120,
                                            MB_YESNO | MB_DEFBUTTON2)
                                        == MBID_YES)
                                    fAllow = TRUE;
                            } else
                                if (cmnMessageBoxMsgExt(hwndDlg,
                                            116,
                                            pTable, 1, 118,
                                            MB_YESNO | MB_DEFBUTTON2)
                                        == MBID_YES)
                                    fAllow = TRUE;

                            if (fAllow) {
                                if (WinDeregisterObjectClass(pscd->preccSource->pwps->pszClassName))
                                {
                                    // success
                                    lstRemoveItem((PLISTITEM*)(&(pscd->pwpsc->pwpsClassList)),
                                            NULL,
                                            (PLISTITEM)pscd->preccSource->pwps);
                                                    // remove item from list

                                    // free(pscd->pRecordSelected->pwps);

                                    WinSendMsg(pscd->hwndCnr,
                                                CM_REMOVERECORD,
                                                (MPARAM)&(pscd->preccSource),
                                                MPFROM2SHORT(1, // remove one record
                                                        CMA_FREE | CMA_INVALIDATE));

                                    cmnMessageBoxMsgExt(hwndDlg,
                                            121,
                                            pTable, 1, 122,
                                            MB_OK);
                                } else
                                    // error
                                    cmnMessageBoxMsgExt(hwndDlg,
                                            104,
                                            pTable, 1, 119,
                                            MB_OK);
                            }
                        }
                break; }

                // "Replace class" menu command:
                // show yet another WPS classes dlg
                case ID_XSMI_WPS_REPLACE: {
                    if (pscd->preccSource)
                        if (pscd->preccSource)
                        {
                            SELECTCLASSDATA         scd;
                            STATUSBARSELECTCLASS    sbsc;
                            PSZ                     pszClassName =
                                        pscd->preccSource->pwps->pszClassName;

                            CHAR szTitle[CCHMAXPATH] = "title";
                            CHAR szIntroText[2000] = "intro";

                            cmnGetMessage(NULL, 0,
                                    szTitle, sizeof(szTitle), 112);
                            // replace "%1" by class name which is to be
                            // replaced
                            cmnGetMessage(&pszClassName, 1,
                                    szIntroText, sizeof(szIntroText), 123);
                            scd.pszDlgTitle = szTitle;
                            scd.pszIntroText = szIntroText;
                            scd.pszRootClass = pszClassName;
                            scd.pszOrphans = NULL;
                            strcpy(scd.szClassSelected, scd.pszRootClass);

                            scd.pfnwpReturnAttrForClass = NULL; // fncbStatusBarReturnClassAttr;
                            scd.pfnwpClassSelected = fncbReplaceClassSelected;
                            // the folllowing data will be passed to the callbacks
                            // so the callback can display NLS messages
                            sbsc.pNLSStrings = cmnQueryNLSStrings();
                            scd.ulUserClassSelected = (ULONG)&sbsc;

                            scd.pszHelpLibrary = cmnQueryHelpLibrary();
                            scd.ulHelpPanel = 0;

                            if (clsSelectWpsClassDlg(hwndDlg,
                                    NLS_MODULE, ID_XSD_SELECTCLASS,
                                    &scd) == DID_OK)
                            {
                                PSZ pTable[2];
                                pTable[0] = pscd->preccSource->pwps->pszClassName;
                                pTable[1] = scd.szClassSelected;
                                if (cmnMessageBoxMsgExt(hwndDlg,
                                            116,
                                            pTable, 2, 124,
                                            MB_YESNO | MB_DEFBUTTON2)
                                        == MBID_YES)
                                    if (WinReplaceObjectClass(
                                            pscd->preccSource->pwps->pszClassName,
                                            scd.szClassSelected,
                                            TRUE))
                                        // success
                                        cmnMessageBoxMsgExt(hwndDlg,
                                                121,
                                                pTable, 2, 129,
                                                MB_OK);
                                    else
                                        // error
                                        cmnMessageBoxMsgExt(hwndDlg,
                                                104,
                                                pTable, 2, 130,
                                                MB_OK);
                            }
                        }
                break; }

                // "Unreplace class" menu command
                case ID_XSMI_WPS_UNREPLACE: {
                    if (pscd->preccSource)
                        if (pscd->preccSource->pwps) {
                            BOOL fAllow = FALSE;
                            PSZ pTable[2];
                            pTable[0] = pscd->preccSource->pwps->pszReplacesThisClass;
                            pTable[1] = pscd->preccSource->pwps->pszClassName;

                            if (strncmp(pscd->preccSource->pwps->pszClassName,
                                            "XFld", 4) == 0) {
                                // XFolder class
                                if (cmnMessageBoxMsgExt(hwndDlg,
                                            116,
                                            pTable, 2, 125,
                                            MB_YESNO | MB_DEFBUTTON2)
                                        == MBID_YES)
                                    fAllow = TRUE;
                            } else
                                if (cmnMessageBoxMsgExt(hwndDlg,
                                            116,
                                            pTable, 2, 126,
                                            MB_YESNO | MB_DEFBUTTON2)
                                        == MBID_YES)
                                    fAllow = TRUE;

                            if (fAllow) {
                                if (WinReplaceObjectClass(
                                        pscd->preccSource->pwps->pszReplacesThisClass,
                                        pscd->preccSource->pwps->pszClassName,
                                        FALSE))
                                    // success
                                    cmnMessageBoxMsgExt(hwndDlg,
                                            121,
                                            pTable, 2, 127,
                                            MB_OK);
                                else
                                    // error
                                    cmnMessageBoxMsgExt(hwndDlg,
                                            104,
                                            pTable, 2, 128,
                                            MB_OK);
                            }
                        }
                break; }
            } // end switch (SHORT1FROMMP(mp1))
            pscd->preccSource = NULL;
        break; }

        /*
         * WM_MENUEND:
         *      if the context menu is dismissed, we'll need
         *      to remove the cnr source emphasis which we
         *      set above
         */

        case WM_MENUEND: {
            WinSendMsg(pscd->hwndCnr,
                        CM_SETRECORDEMPHASIS,
                        (MPARAM)pscd->preccSource,
                        MPFROM2SHORT(FALSE,  // remove emphasis
                                CRA_SOURCE));
        break; }

        /*
         * WM_WINDOWPOSCHANGED:
         *      cheap trick: this msg is posted when
         *      the user switches to a different notebook
         *      page. Since every notebook page is really
         *      a separate dialog window, PM simulates
         *      switching notebook pages by showing or
         *      hiding the various dialog windows.
         *      We also show or hide the "Information"
         *      window then.
         */

        case WM_WINDOWPOSCHANGED: {
            PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
            PSWP pswp = (PSWP)mp1;

            // call default
            mrc = WinDefDlgProc(hwndDlg, msg, mp1, mp2);

            if (pswp->fl & SWP_SHOW) {
                // notebook page is shown:
                // also show "Info" window
                if ( pGlobalSettings->WpsShowClassInfo)
                    WinShowWindow(hwndClassInfo, TRUE);
            } else if (pswp->fl & SWP_HIDE)
                // notebook page is hidden:
                // hide "Info" window
                WinShowWindow(hwndClassInfo, FALSE);
        break; }

        /*
         * WM_DESTROY:
         *      clean up big time
         */

        case WM_DESTROY: {
            HPOINTER hptrOld = WinQueryPointer(HWND_DESKTOP);
            WinSetPointer(HWND_DESKTOP,
                    WinQuerySysPointer(HWND_DESKTOP, SPTR_WAIT, FALSE));
            if (hwndClassInfo) {
                WinDestroyWindow(hwndClassInfo);
                hwndClassInfo = NULLHANDLE;
            }
            // free cnr records
            WinSendMsg(pscd->hwndCnr,
                        CM_REMOVERECORD,
                        (MPARAM)NULL,
                        MPFROM2SHORT(0, // remove all records
                                CMA_FREE | CMA_INVALIDATE));

            // cleanup allocated WPS data (classlst.c)
            clsCleanupWpsClasses(pscd->pwpsc);
            free(pscd);
            free(pszClassInfo);
            pszClassInfo = NULL;
            mrc = WinDefDlgProc(hwndDlg, msg, mp1, mp2);
            WinSetPointer(HWND_DESKTOP, hptrOld);
        break; }

        default:
            mrc = WinDefDlgProc(hwndDlg, msg, mp1, mp2);
    }
    return (mrc);
}

/* ******************************************************************
 *                                                                  *
 *   here come the XFldWPS instance methods                         *
 *                                                                  *
 ********************************************************************/

/*
 *@@ xfAddXFldWPSPages:
 *           this actually adds the XFolder pages into the "Workplace Shell" notebook
 */

SOM_Scope ULONG  SOMLINK xfwps_xfAddXFldWPSPages(XFldWPS *somSelf,
                                                   HWND hwndDlg)
{
    PAGEINFO        pi;
    PCREATENOTEBOOKPAGE pcnbp;
    HMODULE         savehmod = NLS_MODULE;
    CHAR            szXFolderVersion[100];
    PNLSSTRINGS pNLSStrings = cmnQueryNLSStrings();
    PSZ pszHelpLibrary = cmnQueryHelpLibrary();
    /* XFldWPSData *somThis = XFldWPSGetData(somSelf); */
    XFldWPSMethodDebug("XFldWPS","xfwps_xfAddXFldWPSPages");

    strcpy(szXFolderVersion, "~XFolder ");
    strcat(szXFolderVersion, XFOLDER_VERSION);
    memset((PCH)&pi, 0, sizeof(PAGEINFO));

    // insert "WPS Classes" page
    pi.cb                  = sizeof(PAGEINFO);
    pi.hwndPage            = NULLHANDLE;
    pi.pfnwp               = fnwpSettingsWpsClasses;
    pi.resid               = savehmod;
    pi.pCreateParams       = somSelf;
    pi.dlgid               = ID_XSD_SETTINGS_WPSCLASSES;
    pi.usPageStyleFlags    = BKA_STATUSTEXTON | BKA_MAJOR;   // major tab;
    pi.usPageInsertFlags   = BKA_FIRST;
    pi.usSettingsFlags     = 0; // don't enumerate in status line
    pi.pszName             = pNLSStrings->pszWpsClasses;

    pi.pszHelpLibraryName  = pszHelpLibrary;
    pi.idDefaultHelpPanel  = ID_XSH_SETTINGS_WPSCLASSES;

    _wpInsertSettingsPage(somSelf, hwndDlg, &pi);

    // insert "Sort" page
    pcnbp = malloc(sizeof(CREATENOTEBOOKPAGE));
    memset(pcnbp, 0, sizeof(CREATENOTEBOOKPAGE));
    pcnbp->somSelf = somSelf;
    pcnbp->hwndNotebook = hwndDlg;
    pcnbp->hmod = savehmod;
    pcnbp->ulDlgID = ID_XSD_SETTINGS_FLDRSORT;
    pcnbp->fMajorTab = TRUE;
    pcnbp->pszName = pNLSStrings->pszSort;
    pcnbp->ulDefaultHelpPanel  = ID_XSH_SETTINGS_FLDRSORT;
    // mark this page as "global", because both
    // the instance settings notebook and the
    // "Workplace Shell" object use the same
    // callbacks
    pcnbp->ulPageID = SP_FLDRSORT_GLOBAL;
    pcnbp->pfncbInitPage    = fncbSortInitPage;
    pcnbp->pfncbItemChanged = fncbSortItemChanged;
    ntbInsertPage(pcnbp);

    // insert "Hotkeys" page
    pcnbp = malloc(sizeof(CREATENOTEBOOKPAGE));
    memset(pcnbp, 0, sizeof(CREATENOTEBOOKPAGE));
    pcnbp->somSelf = somSelf;
    pcnbp->hwndNotebook = hwndDlg;
    pcnbp->hmod = savehmod;
    pcnbp->ulDlgID = ID_XSD_SET4ACCELS;
    pcnbp->fMajorTab = TRUE;
    pcnbp->pszName = pNLSStrings->psz4Accelerators;
    pcnbp->ulDefaultHelpPanel  = ID_XSH_SETTINGS1+5;
    pcnbp->ulPageID = SP_4ACCELERATORS;
    pcnbp->pfncbInitPage    = fncbWPSFldrHotkeysInitPage;
    pcnbp->pfncbItemChanged = fncbWPSFldrHotkeysItemChanged;
    ntbInsertPage(pcnbp);

    // insert "Snap to grid" page
    pcnbp = malloc(sizeof(CREATENOTEBOOKPAGE));
    memset(pcnbp, 0, sizeof(CREATENOTEBOOKPAGE));
    pcnbp->somSelf = somSelf;
    pcnbp->hwndNotebook = hwndDlg;
    pcnbp->hmod = savehmod;
    pcnbp->fMajorTab = TRUE;
    pcnbp->pszName = pNLSStrings->psz3SnapToGrid;
    pcnbp->ulDlgID = ID_XSD_SET3SNAPTOGRID;
    pcnbp->ulDefaultHelpPanel  = ID_XSH_SETTINGS1+4;
    pcnbp->ulPageID = SP_3SNAPTOGRID;
    pcnbp->pfncbInitPage    = fncbWPSSnap2GridInitPage;
    pcnbp->pfncbItemChanged = fncbWPSSnap2GridItemChanged;
    ntbInsertPage(pcnbp);

    /*
     * "Status bar" pages
     */

    // insert "Status bar" page 2
    pcnbp = malloc(sizeof(CREATENOTEBOOKPAGE));
    memset(pcnbp, 0, sizeof(CREATENOTEBOOKPAGE));
    pcnbp->somSelf = somSelf;
    pcnbp->hwndNotebook = hwndDlg;
    pcnbp->hmod = savehmod;
    pcnbp->fEnumerate = TRUE;
    pcnbp->pszName = pNLSStrings->psz27StatusBar;
    pcnbp->ulDlgID = ID_XSD_SET28STATUSBARS2;
    pcnbp->ulDefaultHelpPanel  = ID_XSH_SETTINGS_SB2;
    pcnbp->ulPageID = SP_28STATUSBAR2;
    pcnbp->pfncbInitPage    = fncbWPSStatusBar2InitPage;
    pcnbp->pfncbItemChanged = fncbWPSStatusBar2ItemChanged;
    ntbInsertPage(pcnbp);

    // insert "Status bar" page 1
    pcnbp = malloc(sizeof(CREATENOTEBOOKPAGE));
    memset(pcnbp, 0, sizeof(CREATENOTEBOOKPAGE));
    pcnbp->somSelf = somSelf;
    pcnbp->hwndNotebook = hwndDlg;
    pcnbp->hmod = savehmod;
    pcnbp->fMajorTab = TRUE;
    pcnbp->fEnumerate = TRUE;
    pcnbp->pszName = pNLSStrings->psz27StatusBar;
    pcnbp->ulDlgID = ID_XSD_SET27STATUSBARS;
    pcnbp->ulDefaultHelpPanel  = ID_XSH_SETTINGS1+3;
    pcnbp->ulPageID = SP_27STATUSBAR;
    pcnbp->pfncbInitPage    = fncbWPSStatusBar1InitPage;
    pcnbp->pfncbItemChanged = fncbWPSStatusBar1ItemChanged;
    ntbInsertPage(pcnbp);

    /*
     * "Menu items" pages
     */

    pcnbp = malloc(sizeof(CREATENOTEBOOKPAGE));
    memset(pcnbp, 0, sizeof(CREATENOTEBOOKPAGE));
    pcnbp->somSelf = somSelf;
    pcnbp->hwndNotebook = hwndDlg;
    pcnbp->hmod = savehmod;
    pcnbp->fEnumerate = TRUE;
    pcnbp->pszName = pNLSStrings->psz2RemoveItems;
    pcnbp->ulDlgID = ID_XSD_SET2REMOVEMENUS;
    pcnbp->ulDefaultHelpPanel  = ID_XSH_SETTINGS1+1;
    pcnbp->ulPageID = SP_2REMOVEITEMS;
    pcnbp->pfncbInitPage    = fncbWPSRemoveItemsInitPage;
    pcnbp->pfncbItemChanged = fncbWPSRemoveItemsItemChanged;
    ntbInsertPage(pcnbp);

    // insert "Config folder menu items" page
    pcnbp = malloc(sizeof(CREATENOTEBOOKPAGE));
    memset(pcnbp, 0, sizeof(CREATENOTEBOOKPAGE));
    pcnbp->somSelf = somSelf;
    pcnbp->hwndNotebook = hwndDlg;
    pcnbp->hmod = savehmod;
    pcnbp->fEnumerate = TRUE;
    pcnbp->pszName = pNLSStrings->psz26ConfigFolderMenus;
    pcnbp->ulDlgID = ID_XSD_SET26CONFIGMENUS;
    pcnbp->ulDefaultHelpPanel  = ID_XSH_SETTINGS_CFGM;
    pcnbp->ulPageID = SP_26CONFIGITEMS;
    pcnbp->pfncbInitPage    = fncbWPSConfigFolderMenusInitPage;
    pcnbp->pfncbItemChanged = fncbWPSConfigFolderMenusItemChanged;
    ntbInsertPage(pcnbp);

    // insert "Add Menu Items" page
    pcnbp = malloc(sizeof(CREATENOTEBOOKPAGE));
    memset(pcnbp, 0, sizeof(CREATENOTEBOOKPAGE));
    pcnbp->somSelf = somSelf;
    pcnbp->hwndNotebook = hwndDlg;
    pcnbp->hmod = savehmod;
    pcnbp->fMajorTab = TRUE;
    pcnbp->fEnumerate = TRUE;
    pcnbp->pszName = pNLSStrings->psz25AddItems;
    pcnbp->ulDlgID = ID_XSD_SET25ADDMENUS;
    pcnbp->ulDefaultHelpPanel  = ID_XSH_SETTINGS1+2;
    pcnbp->ulPageID = SP_25ADDITEMS;
    pcnbp->pfncbInitPage    = fncbWPSAddMenusInitPage;
    pcnbp->pfncbItemChanged = fncbWPSAddMenusItemChanged;
    ntbInsertPage(pcnbp);

    /*
     * "File Operations" page
     */

    pcnbp = malloc(sizeof(CREATENOTEBOOKPAGE));
    memset(pcnbp, 0, sizeof(CREATENOTEBOOKPAGE));
    pcnbp->somSelf = somSelf;
    pcnbp->hwndNotebook = hwndDlg;
    pcnbp->hmod = savehmod;
    pcnbp->fMajorTab = TRUE;
    pcnbp->pszName = pNLSStrings->pszFileOps;
    pcnbp->ulDlgID = ID_XSD_SETTINGS_FILEOPS;
    pcnbp->ulDefaultHelpPanel  = ID_XSH_SETTINGS_FILEOPS;
    pcnbp->ulPageID = SP_FILEOPS;
    pcnbp->pfncbInitPage    = fncbWPSFileOpsInitPage;
    pcnbp->pfncbItemChanged = fncbWPSFileOpsItemChanged;
    ntbInsertPage(pcnbp);

    /*
     * "XFolder" pages
     */

    // insert "XFolder" settings page 2 ("Internals")
    pcnbp = malloc(sizeof(CREATENOTEBOOKPAGE));
    memset(pcnbp, 0, sizeof(CREATENOTEBOOKPAGE));
    pcnbp->somSelf = somSelf;
    pcnbp->hwndNotebook = hwndDlg;
    pcnbp->hmod = savehmod;
    pcnbp->fEnumerate = TRUE;
    pcnbp->pszName = pNLSStrings->psz5Internals;
    pcnbp->ulDlgID = ID_XSD_SET5INTERNALS;
    pcnbp->ulDefaultHelpPanel  = ID_XSH_SETTINGS1+6;
    pcnbp->ulPageID = SP_5INTERNALS;
    pcnbp->pfncbInitPage    = fncbWPSXFolder2InitPage;
    pcnbp->pfncbItemChanged = fncbWPSXFolder2ItemChanged;
    ntbInsertPage(pcnbp);

    /* memset((PCH)&pi, 0, sizeof(PAGEINFO));
    pi.cb                  = sizeof(PAGEINFO);
    pi.hwndPage            = NULLHANDLE;
    pi.pfnwp               = fnwpSettingsXFolderInternals;
    pi.resid               = savehmod;
    pi.pCreateParams       = somSelf;
    pi.dlgid               = ;
    pi.usPageStyleFlags    = BKA_STATUSTEXTON | BKA_MINOR;                // no major tabs
    pi.usPageInsertFlags   = BKA_FIRST;
    pi.usSettingsFlags     = SETTINGS_PAGE_NUMBERS;          // auto enumerate in status line
    pi.pszName             = ;

    pi.pszHelpLibraryName  = pszHelpLibrary;
    pi.idDefaultHelpPanel  = ;

    _wpInsertSettingsPage(somSelf, hwndDlg, &pi); */

    // insert "XFolder" settings page 1
    pcnbp = malloc(sizeof(CREATENOTEBOOKPAGE));
    memset(pcnbp, 0, sizeof(CREATENOTEBOOKPAGE));
    pcnbp->somSelf = somSelf;
    pcnbp->hwndNotebook = hwndDlg;
    pcnbp->hmod = savehmod;
    pcnbp->fMajorTab = TRUE;
    pcnbp->fEnumerate = TRUE;
    pcnbp->pszName = szXFolderVersion;
    pcnbp->ulDlgID = ID_XSD_SET1XFOLDER;
    pcnbp->ulDefaultHelpPanel  = ID_XSH_SETTINGS1;
    pcnbp->ulPageID = SP_1GENERIC;
    pcnbp->pfncbInitPage    = fncbWPSXFolder1InitPage;
    pcnbp->pfncbItemChanged = fncbWPSXFolder1ItemChanged;
    return (ntbInsertPage(pcnbp));
}

/*
 *@@ wpAddSystemScreenPage:
 *           this WPSystem instance method is overridden in order
 *           to suppress the "Screen" page in the "Workplace Shell"
 *           object, because we want that page in "OS/2 Kernel"
 *           only.
 */

SOM_Scope ULONG  SOMLINK xfwps_wpAddSystemScreenPage(XFldWPS *somSelf,
                                                     HWND hwndNotebook)
{
    /* XFldWPSData *somThis = XFldWPSGetData(somSelf); */
    XFldWPSMethodDebug("XFldWPS","xfwps_wpAddSystemScreenPage");

    return (SETTINGS_PAGE_REMOVED);
}

/*
 *@@ wpAddDMQSDisplayTypePage:
 *           this WPSystem instance method is overridden in order
 *           to suppress the second "Screen" page in the "Workplace
 *           Shell" object. Depending on the installed video driver,
 *           this page may or may not be displayed in the "System"
 *           notebook, but we never want this in "Workplace Shell",
 *           but in "OS/2 Kernel" instead.
 */

SOM_Scope ULONG  SOMLINK xfwps_wpAddDMQSDisplayTypePage(XFldWPS *somSelf,
                                                        HWND hwndNotebook)
{
    /* XFldWPSData *somThis = XFldWPSGetData(somSelf); */
    XFldWPSMethodDebug("XFldWPS","xfwps_wpAddDMQSDisplayTypePage");

    return (SETTINGS_PAGE_REMOVED);
}

/*
 *@@ wpAddSettingsPages:
 *           this instance method is overridden in order
 *           to add the new XFolder pages on top of
 *           the other WPS settings pages from the old "System"
 *           notebook.
 */

SOM_Scope BOOL  SOMLINK xfwps_wpAddSettingsPages(XFldWPS *somSelf,
                                                   HWND hwndNotebook)
{
    /* XFldWPSData *somThis = XFldWPSGetData(somSelf); */
    XFldWPSMethodDebug("XFldWPS","xfwps_wpAddSettingsPages");

    XFldWPS_parent_WPSystem_wpAddSettingsPages(somSelf,
                                                       hwndNotebook);

    // add XFolder pages on top
    _xfAddXFldWPSPages(somSelf, hwndNotebook);

    return (TRUE);
}

/* ******************************************************************
 *                                                                  *
 *   here come the XFldWPS class methods                            *
 *                                                                  *
 ********************************************************************/

/*
 *@@ wpclsSetSetting:
 *           this WPAbstract method sets the class object
 *           settings in the settings notebook via setup
 *           strings. WPSystem defines the WPS-wide system
 *           setting strings here, and XFolder needs to
 *           introduce its own settings here also.
 */

SOM_Scope BOOL  SOMLINK xfwpsM_wpclsSetSetting(M_XFldWPS *somSelf,
                                                 PSZ pszSetting,
                                                 PVOID pValue)
{
    // M_XFldWPSData *somThis = M_XFldWPSGetData(somSelf);
    M_XFldWPSMethodDebug("M_XFldWPS","xfwpsM_wpclsSetSetting");

    return (M_XFldWPS_parent_M_WPSystem_wpclsSetSetting(somSelf,
                                                        pszSetting,
                                                        pValue));
}

/*
 *@@ wpclsQuerySettingsPageSize:
 *           this WPObject class method should return the
 *           size of the largest settings page in dialog
 *           units; if a settings notebook is initially
 *           opened, i.e. no window pos has been stored
 *           yet, the WPS will use this size, to avoid
 *           truncated settings pages.
 */

SOM_Scope BOOL  SOMLINK xfwpsM_wpclsQuerySettingsPageSize(M_XFldWPS *somSelf,
                                                          PSIZEL pSizl)
{
    BOOL brc;
    /* M_XFldWPSData *somThis = M_XFldWPSGetData(somSelf); */
    M_XFldWPSMethodDebug("M_XFldWPS","xfwpsM_wpclsQuerySettingsPageSize");

    brc = M_XFldWPS_parent_M_WPSystem_wpclsQuerySettingsPageSize(somSelf,
                                                                   pSizl);
    if (brc) {
        pSizl->cy = 170;        // this is the height of the "WPS Classes" page,
                                // which seems to be the largest in the "Workplace
                                // Shell" object
        if (doshIsWarp4())
            // on Warp 4, reduce again, because we're moving
            // the notebook buttons to the bottom
            pSizl->cy -= WARP4_NOTEBOOK_OFFSET;
    }
    return (brc);
}

/*
 *@@ wpclsQueryIconData:
 *           give the WPS object a new icon
 */

SOM_Scope ULONG  SOMLINK xfwpsM_wpclsQueryIconData(M_XFldWPS *somSelf,
                                                   PICONINFO pIconInfo)
{
    // M_XFldWPSData *somThis = M_XFldWPSGetData(somSelf);
    M_XFldWPSMethodDebug("M_XFldWPS","xfwpsM_wpclsQueryIconData");

    if (pIconInfo) {
       pIconInfo->fFormat = ICON_RESOURCE;
       pIconInfo->resid   = ID_ICONWPS;
       pIconInfo->hmod    = modQueryHandle();
    }

    return (sizeof(ICONINFO));

    /* return (M_XFldWPS_parent_M_WPSystem_wpclsQueryIconData(somSelf,
                                                           pIconInfo)); */
}

/*
 *@@ wpclsQueryTitle:
 *           tell the WPS the new class name: "Workplace Shell"
 */

SOM_Scope PSZ  SOMLINK xfwpsM_wpclsQueryTitle(M_XFldWPS *somSelf)
{
    // M_XFldWPSData *somThis = M_XFldWPSGetData(somSelf);
    M_XFldWPSMethodDebug("M_XFldWPS","xfwpsM_wpclsQueryTitle");

    return ("Workplace Shell");
}

/*
 *@@ wpclsInitData:
 *           initialize XFldWPS class data
 */

SOM_Scope void  SOMLINK xfwpsM_wpclsInitData(M_XFldWPS *somSelf)
{
    // M_XFldWPSData *somThis = M_XFldWPSGetData(somSelf);
    M_XFldWPSMethodDebug("M_XFldWPS","xfwpsM_wpclsInitData");

    M_XFldWPS_parent_M_WPSystem_wpclsInitData(somSelf);

    // _hmodXFldWPS = NULLHANDLE;
}

/* ******************************************************************
 *                                                                  *
 *   "OS/2 Kernel" notebook callbacks                               *
 *                                                                  *
 ********************************************************************/

/*
 *  All the following functions starting with fncbConfig* are callbacks
 *  for the common notebook dlg function in notebook.c. There are
 *  two callbacks for each notebook page in "OS/2 Kernel", one
 *  for (re)initializing the page's controls and one for reacting
 *  to controls being changed by the user.
 *  These callbacks are specified in xfsys::xfAddXFldSystemPages.
 *  These callbacks are all new with V0.82 and replace the awful
 *  dialog procedures which were previously used, because these
 *  became hard to maintain over time.
 */

CHAR    szOrigSwapPath[CCHMAXPATH] = "";
CHAR    szConfigSys[CCHMAXPATH];
CHAR    aszAllDrives[30][5];  // 30 strings with 5 chars each for spin button
PSZ     apszAllDrives[30];    // 30 pointers to the buffers
LONG    lDriveCount = 0;

/*
 *@@ fncbConfigInitPage:
 *      common notebook callback function (notebook.c) for
 *      all the notebook pages dealing with CONFIG.SYS settings.
 *      Sets the controls on the page according to the CONFIG.SYS
 *      statements.
 *      Since this callback is shared among all the CONFIG.SYS
 *      pages, pcnbp->ulPageID is used for telling them apart by
 *      using the SP_* identifiers.
 */

VOID fncbConfigInitPage(PVOID pnbi, ULONG ulExtra)  // notebook info struct
{
    PCREATENOTEBOOKPAGE pcnbp = (PCREATENOTEBOOKPAGE)pnbi;
    // CHAR    szConfigSys[CCHMAXPATH];
    PSZ     pszConfigSys;

    if (ulExtra & CBI_INIT)
    {
        HPOINTER hptrOld = WinQueryPointer(HWND_DESKTOP);
        HPOINTER hptrWait = WinQuerySysPointer(HWND_DESKTOP,
                    SPTR_WAIT, FALSE);
        WinSetPointer(HWND_DESKTOP, hptrWait);

        sprintf(szConfigSys, "%c:\\config.sys", doshQueryBootDrive());

        WinSetPointer(HWND_DESKTOP, hptrOld);

        winhEnableDlgItem(pcnbp->hwndPage, DID_APPLY, TRUE);

        // on the "HPFS" page:
        // if the system has any HPFS drives,
        // we disable the "HPFS installed" item
        if (pcnbp->ulPageID == SP_HPFS) {
            CHAR szHPFSDrives[30];
            doshEnumDrives(szHPFSDrives, "HPFS");
            if (strlen(szHPFSDrives) > 0)
                winhEnableDlgItem(pcnbp->hwndPage, ID_XSDI_OS_FSINSTALLED, FALSE);
        }
        else if (pcnbp->ulPageID == SP_ERRORS) {
            CHAR szAllDrives[30];
            PSZ p = szAllDrives;
            ULONG ul = 0;
            doshEnumDrives(szAllDrives, NULL); // all drives

            while (*p) {
                aszAllDrives[ul][0] = szAllDrives[ul];
                aszAllDrives[ul][1] = '\0';
                apszAllDrives[ul] = &(aszAllDrives[ul][0]);
                p++;
                ul++;
            }
            aszAllDrives[ul][0] = '0';
            aszAllDrives[ul][1] = 0;
            apszAllDrives[ul] = &(aszAllDrives[ul][0]);
            lDriveCount = ul;
            ul++;
            WinSendDlgItemMsg(pcnbp->hwndPage, ID_XSDI_OS_SUPRESSP_DRIVE,
                    SPBM_SETARRAY,
                    (MPARAM)apszAllDrives,
                    (MPARAM)ul);
        }

        pszConfigSys = doshReadTextFile(szConfigSys, 1000);
        if (pszConfigSys == NULL)
            DebugBox(szConfigSys, "XFolder was unable to open the CONFIG.SYS file.");
        else
        {
            PSZ     p;
            ULONG   ul;

            switch (pcnbp->ulPageID) {
                case SP_SCHEDULER: {
                    if (p = strhGetParameter(pszConfigSys, "THREADS=", NULL, 0)) {
                        sscanf(p, "%d", &ul);
                    } else // default
                        ul = 64;
                    winhSetDlgItemSpinData(pcnbp->hwndPage, ID_XSDI_OS_MAXTHREADS, 128, 4096, ul);

                    if (p = strhGetParameter(pszConfigSys, "MAXWAIT=", NULL, 0)) {
                        sscanf(p, "%d", &ul);
                    } else // default
                        ul = 3;
                    winhSetDlgItemSpinData(pcnbp->hwndPage, ID_XSDI_OS_MAXWAIT, 1, 10, ul);

                    if (p = strhGetParameter(pszConfigSys, "PRIORITY_DISK_IO=", NULL, 0)) {
                        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_PRIORITYDISKIO,
                            (strncmp(p, "YES", 3) == 0));
                    } else // default
                        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_PRIORITYDISKIO,
                            TRUE);
                break; }

                case SP_MEMORY: {
                    // installed physical memory
                    CHAR szMemory[30];
                    ULONG   aulSysInfo[QSV_MAX] = {0};
                    DosQuerySysInfo(1L, QSV_MAX,
                                        (PVOID)aulSysInfo, sizeof(ULONG)*QSV_MAX);
                    sprintf(szMemory, "%d",
                               (aulSysInfo[QSV_TOTPHYSMEM-1] + (512*1000)) / 1024 / 1024);
                    WinSetDlgItemText(pcnbp->hwndPage, ID_XSDI_OS_PHYSICALMEMORY, szMemory);

                    // parse SWAPPATH command
                    if (p = strhGetParameter(pszConfigSys, "SWAPPATH=", NULL, 0)) {
                        CHAR    szSwapPath[CCHMAXPATH] = "Error";
                        ULONG   ulMinFree = 2048, ulMinSize = 2048;
                        // int     iScanned;
                        sscanf(p, "%s %d %d",
                                    &szSwapPath, &ulMinFree, &ulMinSize);

                        WinSetDlgItemText(pcnbp->hwndPage, ID_XSDI_OS_SWAPPATH, szSwapPath);
                        winhSetDlgItemSpinData(pcnbp->hwndPage, ID_XSDI_OS_MINSWAPSIZE,
                                2, 100, (ulMinSize / 1024));
                        winhSetDlgItemSpinData(pcnbp->hwndPage, ID_XSDI_OS_MINSWAPFREE,
                                2, 1000, (ulMinFree / 1024));

                        if (strlen(szOrigSwapPath) == 0) {
                            if (szSwapPath[strlen(szSwapPath)-1] != '\\')
                                sprintf(szOrigSwapPath, "%s\\swapper.dat", szSwapPath);
                            else
                                sprintf(szOrigSwapPath, "%sswapper.dat", szSwapPath);
                        }
                    }
                break; }

                case SP_HPFS: {
                    CHAR    szParameter[300] = "",
                            // szTemp[300] = "",
                            szSearchKey[100],
                            szAutoCheck[200] = "";
                    ULONG   ulCacheSize = 0,
                            ulThreshold = 4,
                            ulMaxAge = 5000,
                            ulDiskIdle = 1000,
                            ulBufferIdle = 500;
                    BOOL    fLazyWrite = TRUE;

                    szAutoCheck[0] = doshQueryBootDrive();  // default value

                    // evaluate IFS=...\HPFS.IFS
                    sprintf(szSearchKey, "IFS=%c:\\OS2\\HPFS.IFS ", doshQueryBootDrive());
                    p = strhGetParameter(pszConfigSys, szSearchKey,
                            szParameter, sizeof(szParameter));

                    if (p) {
                        PSZ p2;
                        if (p2 = strhistr(szParameter, "/CACHE:"))
                            sscanf(p2+7, "%d", &ulCacheSize);
                        if (p2 = strhistr(szParameter, "/CRECL:"))
                            sscanf(p2+7, "%d", &ulThreshold);
                        if (p2 = strhistr(szParameter, "/AUTOCHECK:"))
                            sscanf(p2+11, "%s", &szAutoCheck);
                    }

                    winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_FSINSTALLED,
                                (p != 0));
                    winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_CACHESIZE_AUTO,
                                (ulCacheSize == 0));
                    winhSetDlgItemSpinData(pcnbp->hwndPage, ID_XSDI_OS_CACHESIZE,
                                0, 2048, ulCacheSize);
                    winhSetDlgItemSpinData(pcnbp->hwndPage, ID_XSDI_OS_CACHE_THRESHOLD,
                                4, 64, ulThreshold);
                    WinSetDlgItemText(pcnbp->hwndPage, ID_XSDI_OS_AUTOCHECK, szAutoCheck);

                    // evaluate
                    // RUN=...\CACHE.EXE /MAXAGE:60000 /DISKIDLE:1000 /BUFFERIDLE:40000
                    sprintf(szSearchKey, "RUN=%c:\\OS2\\CACHE.EXE ", doshQueryBootDrive());
                    p = strhGetParameter(pszConfigSys, szSearchKey,
                                szParameter, sizeof(szParameter));

                    if (p) {
                        PSZ p2;
                        if (p2 = strhistr(szParameter, "/MAXAGE:"))
                            sscanf(p2+8,  "%d", &ulMaxAge);
                        if (p2 = strhistr(szParameter, "/DISKIDLE:"))
                            sscanf(p2+10, "%d", &ulDiskIdle);
                        if (p2 = strhistr(szParameter, "/BUFFERIDLE:"))
                            sscanf(p2+12, "%d", &ulBufferIdle);
                        if (strhistr(szParameter, "/LAZY:OFF"))
                            fLazyWrite = FALSE;
                    }

                    winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_CACHE_LAZYWRITE,
                                fLazyWrite);
                    winhSetDlgItemSpinData(pcnbp->hwndPage, ID_XSDI_OS_CACHE_MAXAGE,
                                500, 100*1000, ulMaxAge);
                    winhSetDlgItemSpinData(pcnbp->hwndPage, ID_XSDI_OS_CACHE_BUFFERIDLE,
                                500, 100*1000, ulBufferIdle);
                    winhSetDlgItemSpinData(pcnbp->hwndPage, ID_XSDI_OS_CACHE_DISKIDLE,
                                500, 100*1000, ulDiskIdle);

                break; }

                case SP_FAT: {
                    CHAR    szParameter[300] = "",
                            // szTemp[300] = "",
                            szAutoCheck[200] = "";
                    ULONG   ulCacheSize = 512,
                            ulThreshold = 4;
                    PSZ     p2;

                    // evaluate DISKCACHE
                    p = strhGetParameter(pszConfigSys, "DISKCACHE=",
                            szParameter, sizeof(szParameter));

                    // enable "Cache installed" item if DISKCACHE= found
                    winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_FSINSTALLED,
                                (p != NULL));

                    // now set the other items according to the DISKCACHE
                    // parameters; if that was not found, the default values
                    // above will be used
                    if (szParameter[0] == 'D')
                        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_CACHESIZE_AUTO,
                                    TRUE);
                    else
                        sscanf(szParameter, "%d", &ulCacheSize);

                    p2 = strchr(szParameter, ','); // get next parameter
                    // optional "LW" parameter (lazy write)
                    if (p2) {
                        if (strncmp(p2+1, "LW", 2) == 0) {
                            winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_CACHE_LAZYWRITE,
                                        TRUE);
                            p2 = strchr(p2+1, ','); // get next parameter
                        }
                    }
                    // optional threshold parameter
                    if (p2) {
                        sscanf(p2+1, "%d", &ulThreshold);
                        p2 = strchr(p2+1, ','); // get next parameter
                    }
                    // optional "autocheck" parameter
                    if (p2) {
                        if (strncmp(p2+1, "AC:", 3) == 0)
                            strcpy(szAutoCheck, p2+4);
                    }

                    winhSetDlgItemSpinData(pcnbp->hwndPage, ID_XSDI_OS_CACHESIZE,
                                0, 14400, ulCacheSize);
                    // the threshold param is in sectors of 512 bytes
                    // each, so for getting KB, we need to divide by 2
                    winhSetDlgItemSpinData(pcnbp->hwndPage, ID_XSDI_OS_CACHE_THRESHOLD,
                                4, 64, ulThreshold / 2);
                    WinSetDlgItemText(pcnbp->hwndPage, ID_XSDI_OS_AUTOCHECK, szAutoCheck);

                break; }

                case SP_WPS: {
                    CHAR    szParameter[300] = "";
                    PSZ p = strhGetParameter(pszConfigSys, "SET AUTOSTART=",
                            szParameter, sizeof(szParameter));
                    BOOL fAutoRefreshFolders = TRUE;
                    if (p) {
                        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_AUTO_PROGRAMS,
                            (strhistr(szParameter, "PROGRAMS") != NULL));
                        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_AUTO_TASKLIST,
                            (strhistr(szParameter, "TASKLIST") != NULL));
                        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_AUTO_CONNECTIONS,
                            (strhistr(szParameter, "CONNECTIONS") != NULL));
                        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_AUTO_LAUNCHPAD,
                            (strhistr(szParameter, "LAUNCHPAD") != NULL));
                        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_AUTO_WARPCENTER,
                            (strhistr(szParameter, "WARPCENTER") != NULL));
                    }

                    p = strhGetParameter(pszConfigSys, "SET RESTARTOBJECTS=",
                            szParameter, sizeof(szParameter));
                    if ( (p == NULL) || (strhistr(szParameter, "YES")) )
                        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_RESTART_YES, TRUE);
                    else if (strhistr(szParameter, "NO"))
                        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_RESTART_NO, TRUE);
                    else if (strhistr(szParameter, "STARTUPFOLDERSONLY"))
                        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_RESTART_FOLDERS, TRUE);

                    if (strhistr(szParameter, "REBOOTONLY"))
                        winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_RESTART_REBOOT, TRUE);

                    // auto-refresh folders: cannot be disabled on Warp 3
                    p = strhGetParameter(pszConfigSys, "SET AUTOREFRESHFOLDERS=",
                            szParameter, sizeof(szParameter));
                    if (p)
                        if (strhistr(szParameter, "NO"))
                            fAutoRefreshFolders = FALSE;
                    winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_AUTOREFRESHFOLDERS,
                                fAutoRefreshFolders);
                break; }

                case SP_ERRORS: {
                    CHAR    szParameter[300] = "";
                    BOOL fAutoFail = FALSE,
                         fReIPL = FALSE;
                    PSZ p = strhGetParameter(pszConfigSys, "AUTOFAIL=",
                            szParameter, sizeof(szParameter));
                    if (p)
                        if (strhistr(szParameter, "YES"))
                            fAutoFail = TRUE;
                    winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_AUTOFAIL, fAutoFail);

                    p = strhGetParameter(pszConfigSys, "REIPL=",
                            szParameter, sizeof(szParameter));
                    if (p)
                        if (strhistr(szParameter, "ON"))
                            fReIPL = TRUE;
                    winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_REIPL, fReIPL);

                    p = strhGetParameter(pszConfigSys, "SUPPRESSPOPUPS=",
                            szParameter, sizeof(szParameter));
                    winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_SUPRESSPOPUPS,
                            (p != NULL));
                    if (p) {
                        LONG lIndex = 0;           // default for "0" param
                        if (*p != '0') {
                            CHAR c = toupper(*p);
                            lIndex = c-'C'; // 0 for C, 1 for D etc.
                        } else {
                            // "0" character:
                            lIndex = lDriveCount;
                        }

                        WinSendDlgItemMsg(pcnbp->hwndPage, ID_XSDI_OS_SUPRESSP_DRIVE,
                                SPBM_SETCURRENTVALUE,
                                (MPARAM)lIndex,
                                (MPARAM)NULL);
                    }

                break; }
            } // end switch

            free(pszConfigSys);
            pszConfigSys = NULL;
        }
    }

    if (ulExtra & CBI_ENABLE)
    {
        // enable items
        if (pcnbp->ulPageID == SP_HPFS)
        {
            BOOL fLazyWrite = winhIsDlgItemChecked(pcnbp->hwndPage,
                            ID_XSDI_OS_CACHE_LAZYWRITE);
            winhEnableDlgItem(pcnbp->hwndPage,
                        ID_XSDI_OS_CACHE_MAXAGE, fLazyWrite);
            winhEnableDlgItem(pcnbp->hwndPage,
                        ID_XSDI_OS_CACHE_BUFFERIDLE, fLazyWrite);
            winhEnableDlgItem(pcnbp->hwndPage,
                        ID_XSDI_OS_CACHE_DISKIDLE, fLazyWrite);
        }

        if (    (pcnbp->ulPageID == SP_HPFS)
            ||  (pcnbp->ulPageID == SP_FAT)
           )
        {
            winhEnableDlgItem(pcnbp->hwndPage, ID_XSDI_OS_CACHESIZE,
                        !winhIsDlgItemChecked(pcnbp->hwndPage,
                            ID_XSDI_OS_CACHESIZE_AUTO));
        }
        else if (pcnbp->ulPageID == SP_WPS)
        {
            winhEnableDlgItem(pcnbp->hwndPage, ID_XSDI_OS_AUTO_WARPCENTER, (doshIsWarp4()));
            winhEnableDlgItem(pcnbp->hwndPage, ID_XSDI_OS_AUTOREFRESHFOLDERS, (doshIsWarp4()));
        }
        else if (pcnbp->ulPageID == SP_ERRORS)
            winhEnableDlgItem(pcnbp->hwndPage, ID_XSDI_OS_SUPRESSP_DRIVE,
                winhIsDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_SUPRESSPOPUPS));
    }
}

/*
 *@@ fncbConfigItemChanged:
 *      common notebook callback function (notebook.c) for
 *      all the notebook pages dealing with CONFIG.SYS settings.
 *      This monster function reacts to changes of any of the
 *      dialog controls and reads/writes CONFIG.SYS settings.
 *      Since this callback is shared among all the CONFIG.SYS
 *      pages, pcnbp->ulPageID is used for telling them apart by
 *      using the SP_* identifiers.
 */

MRESULT fncbConfigItemChanged(PVOID pnbi,
                USHORT usItemID, USHORT usNotifyCode,
                ULONG ulExtra)      // for checkboxes: contains new state
{
    PCREATENOTEBOOKPAGE pcnbp = (PCREATENOTEBOOKPAGE)pnbi;
    LONG    lGrid = 0;

    switch (usItemID)
    {

        case ID_XSDI_OS_MAXTHREADS:
            // "Scheduler" page; 64 steps
            lGrid = 64;
            goto adjustspin;

        case ID_XSDI_OS_MINSWAPSIZE:
        case ID_XSDI_OS_MINSWAPFREE:
            lGrid = 2;
            goto adjustspin;

        case ID_XSDI_OS_CACHESIZE:
            // HPFS and FAT pages; 64 KB steps
            lGrid = 64;
            goto adjustspin;

        case ID_XSDI_OS_CACHE_THRESHOLD:
            // HPFS and FAT pages; 4 KB steps
            lGrid = 4;
            goto adjustspin;

        case ID_XSDI_OS_CACHE_MAXAGE:
        case ID_XSDI_OS_CACHE_BUFFERIDLE:
        case ID_XSDI_OS_CACHE_DISKIDLE:
            // HPFS page; 1000 ms steps
            lGrid = 1000;

            adjustspin:
            if (   (usNotifyCode == SPBN_UPARROW)
                || (usNotifyCode == SPBN_DOWNARROW)
               )
            {
                winhAdjustDlgItemSpinData(pcnbp->hwndPage, usItemID,
                            lGrid, usNotifyCode);
            }
        break;

        /*
         * DID_APPLY:
         *      "Apply" button
         */

        case DID_APPLY: {

            if (cmnMessageBoxMsg(pcnbp->hwndPage,
                    100, 101,
                    MB_YESNO | MB_DEFBUTTON2)
                 == MBID_YES)
            {
                PSZ     pszConfigSys = NULL;
                if (pszConfigSys == NULL) {
                    pszConfigSys = doshReadTextFile(szConfigSys, 1000);
                    if (pszConfigSys == NULL)
                        DebugBox(szConfigSys, "XFolder was unable to open the CONFIG.SYS file.");
                }

                if (pszConfigSys) {
                    // PSZ     p;
                    ULONG   ul = 0, ulMinFree = 0, ulMinSize = 0;
                    CHAR    szTemp[CCHMAXPATH];
                    CHAR    szSwapPath[CCHMAXPATH];

                    switch (pcnbp->ulPageID) {
                        case SP_SCHEDULER: {
                            WinSendDlgItemMsg(pcnbp->hwndPage, ID_XSDI_OS_MAXTHREADS,
                                  SPBM_QUERYVALUE,
                                  (MPARAM)&ul,
                                  MPFROM2SHORT(0, SPBQ_UPDATEIFVALID));
                            sprintf(szTemp, "%d", ul);
                            strhSetParameter(pszConfigSys, "THREADS=", szTemp, TRUE);

                            WinSendDlgItemMsg(pcnbp->hwndPage, ID_XSDI_OS_MAXWAIT,
                                  SPBM_QUERYVALUE,
                                  (MPARAM)&ul,
                                  MPFROM2SHORT(0, SPBQ_UPDATEIFVALID));
                            sprintf(szTemp, "%d", ul);
                            strhSetParameter(pszConfigSys, "MAXWAIT=", szTemp, TRUE);

                            strhSetParameter(pszConfigSys, "PRIORITY_DISK_IO=",
                                    (winhIsDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_PRIORITYDISKIO)
                                            ? "yes" : "no"),
                                    TRUE);
                        break; }

                        case SP_MEMORY: {
                            WinQueryDlgItemText(pcnbp->hwndPage, ID_XSDI_OS_SWAPPATH,
                                            sizeof(szSwapPath)-1, szSwapPath);
                            WinSendDlgItemMsg(pcnbp->hwndPage, ID_XSDI_OS_MINSWAPSIZE,
                                  SPBM_QUERYVALUE,
                                  (MPARAM)&ulMinSize,
                                  MPFROM2SHORT(0, SPBQ_UPDATEIFVALID));
                            WinSendDlgItemMsg(pcnbp->hwndPage, ID_XSDI_OS_MINSWAPFREE,
                                  SPBM_QUERYVALUE,
                                  (MPARAM)&ulMinFree,
                                  MPFROM2SHORT(0, SPBQ_UPDATEIFVALID));
                            sprintf(szTemp, "%s %d %d", szSwapPath, ulMinFree*1024, ulMinSize*1024);
                            strhSetParameter(pszConfigSys, "SWAPPATH=", szTemp, TRUE);
                        break; }

                        case SP_HPFS: {
                            CHAR    szTemp[300] = "",
                                    szAutoCheck[200] = "",
                                    szSearchKey[100] = "";
                            ULONG   ulCacheSize = 0,
                                    ulThreshold = 4,
                                    ulMaxAge = 5000,
                                    ulDiskIdle = 1000,
                                    ulBufferIdle = 500;
                            // BOOL    fLazyWrite = TRUE;

                            WinSendDlgItemMsg(pcnbp->hwndPage, ID_XSDI_OS_CACHE_THRESHOLD,
                                  SPBM_QUERYVALUE,
                                  (MPARAM)&ulThreshold,
                                  MPFROM2SHORT(0, SPBQ_UPDATEIFVALID));
                            WinQueryDlgItemText(pcnbp->hwndPage, ID_XSDI_OS_AUTOCHECK,
                                            sizeof(szAutoCheck)-1, szAutoCheck);

                            if (winhIsDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_CACHESIZE_AUTO)) {
                                // auto-size cache: leave out /CACHE
                                sprintf(szTemp,
                                        "/crecl:%d /autocheck:%s",
                                        doshQueryBootDrive(),
                                        ulThreshold,
                                        szAutoCheck);
                            } else {
                                // no auto-size cache
                                WinSendDlgItemMsg(pcnbp->hwndPage, ID_XSDI_OS_CACHESIZE,
                                      SPBM_QUERYVALUE,
                                      (MPARAM)&ulCacheSize,
                                      MPFROM2SHORT(0, SPBQ_UPDATEIFVALID));
                                sprintf(szTemp,
                                        "/cache:%d /crecl:%d /autocheck:%s",
                                        ulCacheSize,
                                        ulThreshold,
                                        szAutoCheck);
                            }
                            sprintf(szSearchKey, "IFS=%c:\\OS2\\HPFS.IFS ",
                                        doshQueryBootDrive());
                            strhSetParameter(pszConfigSys, szSearchKey, szTemp, TRUE);

                            if (winhIsDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_CACHE_LAZYWRITE)) {
                                WinSendDlgItemMsg(pcnbp->hwndPage, ID_XSDI_OS_CACHE_MAXAGE,
                                      SPBM_QUERYVALUE,
                                      (MPARAM)&ulMaxAge,
                                      MPFROM2SHORT(0, SPBQ_UPDATEIFVALID));
                                WinSendDlgItemMsg(pcnbp->hwndPage, ID_XSDI_OS_CACHE_DISKIDLE,
                                      SPBM_QUERYVALUE,
                                      (MPARAM)&ulDiskIdle,
                                      MPFROM2SHORT(0, SPBQ_UPDATEIFVALID));
                                WinSendDlgItemMsg(pcnbp->hwndPage, ID_XSDI_OS_CACHE_BUFFERIDLE,
                                      SPBM_QUERYVALUE,
                                      (MPARAM)&ulBufferIdle,
                                      MPFROM2SHORT(0, SPBQ_UPDATEIFVALID));
                                sprintf(szTemp,
                                        "/maxage:%d /diskidle:%d /bufferidle:%d "
                                        "/readahead:on /lazy:1",
                                        ulMaxAge,
                                        ulDiskIdle,
                                        ulBufferIdle);
                            } else {
                                strcpy(szTemp, "/lazy:off");
                            }
                            // compose the key with CACHE;
                            sprintf(szSearchKey, "RUN=%c:\\OS2\\CACHE.EXE ",
                                        doshQueryBootDrive());
                            strhSetParameter(pszConfigSys, szSearchKey, szTemp, TRUE);

                        break; }

                        case SP_FAT: {
                            // "Cache installed" checked?
                            if (winhIsDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_FSINSTALLED)) {
                                CHAR    // szParameter[300] = "",
                                        szTemp[300] = "",
                                        szAutoCheck[200] = "";
                                ULONG   ulCacheSize = 512,
                                        ulThreshold = 4;
                                // PSZ     p2;

                                if (winhIsDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_CACHESIZE_AUTO))
                                    strcpy(szTemp, "d");
                                else {
                                    // no auto-size cache
                                    WinSendDlgItemMsg(pcnbp->hwndPage, ID_XSDI_OS_CACHESIZE,
                                          SPBM_QUERYVALUE,
                                          (MPARAM)&ulCacheSize,
                                          MPFROM2SHORT(0, SPBQ_UPDATEIFVALID));
                                    sprintf(szTemp, "%d", ulCacheSize);
                                }

                                if (winhIsDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_CACHE_LAZYWRITE))
                                    strcat(szTemp, ",lw");

                                WinSendDlgItemMsg(pcnbp->hwndPage, ID_XSDI_OS_CACHE_THRESHOLD,
                                      SPBM_QUERYVALUE,
                                      (MPARAM)&ulThreshold,
                                      MPFROM2SHORT(0, SPBQ_UPDATEIFVALID));
                                // again, convert KB to sectors for the threshold
                                sprintf(szTemp+strlen(szTemp), ",%d", ulThreshold*2);

                                WinQueryDlgItemText(pcnbp->hwndPage, ID_XSDI_OS_AUTOCHECK,
                                                sizeof(szAutoCheck)-1, szAutoCheck);
                                if (strlen(szAutoCheck))
                                    sprintf(szTemp+strlen(szTemp), ",ac:%s", szAutoCheck, TRUE);

                                strhSetParameter(pszConfigSys, "DISKCACHE=", szTemp, TRUE);

                            } else {
                                // no "Cache installed":
                                strhDeleteLine(pszConfigSys, "DISKCACHE=");
                            }
                        break; }

                        case SP_WPS: {
                            CHAR   szTemp[300] = "";
                            BOOL   fCopied = FALSE;
                            if (winhIsDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_AUTO_PROGRAMS)) {
                                strcpy(szTemp, "programs");
                                fCopied = TRUE;
                            }
                            if (winhIsDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_AUTO_TASKLIST)) {
                                if (fCopied)
                                    strcat(szTemp, ",");
                                strcat(szTemp, "tasklist");
                                fCopied = TRUE;
                            }
                            if (fCopied)
                                strcat(szTemp, ",");
                            strcat(szTemp, "folders");
                            if (winhIsDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_AUTO_CONNECTIONS)) {
                                strcat(szTemp, ",connections");
                            }
                            if (winhIsDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_AUTO_LAUNCHPAD)) {
                                strcat(szTemp, ",launchpad");
                            }
                            if (winhIsDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_AUTO_WARPCENTER)) {
                                strcat(szTemp, ",warpcenter");
                            }
                            strhSetParameter(pszConfigSys, "SET AUTOSTART=", szTemp, TRUE);

                            if (winhIsDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_RESTART_FOLDERS))
                                strcpy(szTemp, "STARTUPFOLDERSONLY");
                            else if (winhIsDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_RESTART_NO))
                                strcpy(szTemp, "no");
                            else
                                strcpy(szTemp, "yes");
                            if (winhIsDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_RESTART_REBOOT))
                                strcat(szTemp, ",rebootonly");
                            strhSetParameter(pszConfigSys, "SET RESTARTOBJECTS=", szTemp, TRUE);

                            if (doshIsWarp4())
                                if (winhIsDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_AUTOREFRESHFOLDERS))
                                    strhDeleteLine(pszConfigSys, "SET AUTOREFRESHFOLDERS=");
                                else
                                    strhSetParameter(pszConfigSys, "SET AUTOREFRESHFOLDERS=",
                                            "no", TRUE);
                        break; }

                        case SP_ERRORS: {
                            if (winhIsDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_AUTOFAIL))
                                strhSetParameter(pszConfigSys, "AUTOFAIL=", "yes", TRUE);
                            else
                                strhDeleteLine(pszConfigSys, "AUTOFAIL=");

                            if (winhIsDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_REIPL))
                                strhSetParameter(pszConfigSys, "REIPL=", "on", TRUE);
                            else
                                strhDeleteLine(pszConfigSys, "REIPL=");

                            if (winhIsDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_SUPRESSPOPUPS)) {
                                CHAR szSpinButtonValue[5];
                                WinSendDlgItemMsg(pcnbp->hwndPage, ID_XSDI_OS_SUPRESSP_DRIVE,
                                        SPBM_QUERYVALUE,
                                        (MPARAM)szSpinButtonValue,
                                        MPFROM2SHORT(sizeof(szSpinButtonValue)-1,
                                            SPBQ_UPDATEIFVALID));
                                strhSetParameter(pszConfigSys, "SUPPRESSPOPUPS=",
                                        szSpinButtonValue, TRUE);
                            } else
                                strhDeleteLine(pszConfigSys, "SUPPRESSPOPUPS=");


                        break; }
                    } // end switch

                    sprintf(szConfigSys, "%c:\\config.sys", doshQueryBootDrive());
                    doshWriteTextFile(szConfigSys, pszConfigSys, TRUE);

                    cmnMessageBoxMsg(pcnbp->hwndPage, 100, 136, MB_OK);

                    if (pszConfigSys) {
                        free(pszConfigSys);
                        pszConfigSys = NULL;
                    }
                }
            }
        break; }

        /*
         * DID_OPTIMIZE:
         *      "Optimize" button
         */

        case DID_OPTIMIZE: {

            switch (pcnbp->ulPageID) {
                case SP_SCHEDULER: {
                    // THREADS=
                    winhSetDlgItemSpinData(pcnbp->hwndPage, ID_XSDI_OS_MAXTHREADS,
                            128, 4096,
                            // get current thread count, add 50% for safety,
                            // and round up to the next multiple of 128
                            (( (    (prcQueryThreadCount(0)  // whole system
                                  * 3) / 2) + 127 ) / 128) * 128
                    );

                    // MAXWAIT=2
                    winhSetDlgItemSpinData(pcnbp->hwndPage, ID_XSDI_OS_MAXWAIT, 1, 10,
                        2);

                    winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_PRIORITYDISKIO,
                        TRUE);
                break; }

                case SP_MEMORY: {
                    // minsize: get current size, add 50% and
                    // round up to the next multiple of 2 MB
                    if (strlen(szOrigSwapPath) != 0) {
                        ULONG ulSize = doshQueryPathSize(szOrigSwapPath)/1024/1024;
                        winhSetDlgItemSpinData(pcnbp->hwndPage, ID_XSDI_OS_MINSWAPSIZE,
                                2, 100,
                                ( (((ulSize*3)/2)+1) / 2 ) * 2
                        );
                    }

                    // minfree = 2
                    winhSetDlgItemSpinData(pcnbp->hwndPage, ID_XSDI_OS_MINSWAPFREE,
                            2, 1000,
                            2);
                break; }

                case SP_HPFS: {
                    ULONG   aulSysInfo[QSV_MAX] = {0},
                            ulInstalledMB;
                    CHAR szHPFSDrives[30];
                    DosQuerySysInfo(1L, QSV_MAX,
                                        (PVOID)aulSysInfo, sizeof(ULONG)*QSV_MAX);
                    ulInstalledMB =
                               (aulSysInfo[QSV_TOTPHYSMEM-1] + (512*1000)) / 1024 / 1024;
                    doshEnumDrives(szHPFSDrives, "HPFS");

                    winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_FSINSTALLED,
                                (strlen(szHPFSDrives) > 0));
                    winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_CACHESIZE_AUTO,
                                FALSE);
                    winhSetDlgItemSpinData(pcnbp->hwndPage, ID_XSDI_OS_CACHESIZE,
                                0, 2048,
                                (ulInstalledMB > 16) ? 2048 : 1024);
                    winhSetDlgItemSpinData(pcnbp->hwndPage, ID_XSDI_OS_CACHE_THRESHOLD,
                                4, 64, 64);
                    WinSetDlgItemText(pcnbp->hwndPage, ID_XSDI_OS_AUTOCHECK, szHPFSDrives);

                    winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_CACHE_LAZYWRITE,
                                TRUE);
                    winhSetDlgItemSpinData(pcnbp->hwndPage, ID_XSDI_OS_CACHE_MAXAGE,
                                500, 100*1000, 60*1000);
                    winhSetDlgItemSpinData(pcnbp->hwndPage, ID_XSDI_OS_CACHE_BUFFERIDLE,
                                500, 100*1000, 30*1000);
                    winhSetDlgItemSpinData(pcnbp->hwndPage, ID_XSDI_OS_CACHE_DISKIDLE,
                                500, 100*1000, 60*1000);

                break; }

                case SP_FAT: {
                    ULONG   aulSysInfo[QSV_MAX] = {0},
                            ulInstalledMB;
                    CHAR szFATDrives[30];
                    DosQuerySysInfo(1L, QSV_MAX,
                                        (PVOID)aulSysInfo, sizeof(ULONG)*QSV_MAX);
                    ulInstalledMB =
                               (aulSysInfo[QSV_TOTPHYSMEM-1] + (512*1000)) / 1024 / 1024;
                    doshEnumDrives(szFATDrives, "FAT");

                    winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_FSINSTALLED,
                                (strlen(szFATDrives) > 0));

                    winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_CACHESIZE_AUTO, FALSE);
                    winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_CACHE_LAZYWRITE, TRUE);
                    winhSetDlgItemSpinData(pcnbp->hwndPage, ID_XSDI_OS_CACHESIZE,
                                0, 14400,
                                (ulInstalledMB > 16) ? 2048 : 1024);
                    winhSetDlgItemSpinData(pcnbp->hwndPage, ID_XSDI_OS_CACHE_THRESHOLD,
                                4, 64, 64);
                    // do not auto-check FAT drives
                    WinSetDlgItemText(pcnbp->hwndPage, ID_XSDI_OS_AUTOCHECK, "");

                break; }

                case SP_WPS: {
                    winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_AUTO_PROGRAMS, TRUE);
                    winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_AUTO_TASKLIST, TRUE);
                    winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_AUTO_CONNECTIONS, TRUE);
                    winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_AUTO_LAUNCHPAD, FALSE);
                    winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_AUTO_WARPCENTER, FALSE);
                    winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_RESTART_FOLDERS, TRUE);
                    winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_RESTART_REBOOT, FALSE);
                    winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_AUTOREFRESHFOLDERS,
                                FALSE);
                break; }

                case SP_ERRORS: {
                    winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_AUTOFAIL, TRUE);
                    winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_REIPL, FALSE);
                    winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_SUPRESSPOPUPS, FALSE);
                break; }
            } // end switch

            fncbConfigInitPage(pnbi, 100); // re-enable items
        break; }

        /*
         * DID_DEFAULT:
         *      "Default" button
         */

        case DID_DEFAULT: {
            switch (pcnbp->ulPageID) {
                case SP_SCHEDULER: {
                    winhSetDlgItemSpinData(pcnbp->hwndPage, ID_XSDI_OS_MAXTHREADS,
                            128, 4096, (doshIsWarp4()) ? 512 : 256);
                    winhSetDlgItemSpinData(pcnbp->hwndPage, ID_XSDI_OS_MAXWAIT, 1, 10,
                        3);
                    winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_PRIORITYDISKIO,
                        TRUE);
                break; }

                case SP_MEMORY: {
                    winhSetDlgItemSpinData(pcnbp->hwndPage, ID_XSDI_OS_MINSWAPSIZE,
                            2, 100, 2);
                    winhSetDlgItemSpinData(pcnbp->hwndPage, ID_XSDI_OS_MINSWAPFREE,
                            2, 1000, 2);
                break; }

                case SP_HPFS: {
                    CHAR szHPFSDrives[30];
                    doshEnumDrives(szHPFSDrives, "HPFS");

                    winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_FSINSTALLED, TRUE);
                    winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_CACHESIZE_AUTO, FALSE);
                    winhSetDlgItemSpinData(pcnbp->hwndPage, ID_XSDI_OS_CACHESIZE,
                                0, 2048, 1024);
                    winhSetDlgItemSpinData(pcnbp->hwndPage, ID_XSDI_OS_CACHE_THRESHOLD,
                                4, 64, 4);
                    WinSetDlgItemText(pcnbp->hwndPage, ID_XSDI_OS_AUTOCHECK, szHPFSDrives);

                    winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_CACHE_LAZYWRITE,
                                TRUE);
                    winhSetDlgItemSpinData(pcnbp->hwndPage, ID_XSDI_OS_CACHE_MAXAGE,
                                500, 100*1000, 5*1000);
                    winhSetDlgItemSpinData(pcnbp->hwndPage, ID_XSDI_OS_CACHE_BUFFERIDLE,
                                500, 100*1000, 500);
                    winhSetDlgItemSpinData(pcnbp->hwndPage, ID_XSDI_OS_CACHE_DISKIDLE,
                                500, 100*1000, 1000);

                break; }

                case SP_FAT: {
                    winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_FSINSTALLED, TRUE);
                    winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_CACHESIZE_AUTO, TRUE);
                    winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_CACHE_LAZYWRITE, TRUE);
                    winhSetDlgItemSpinData(pcnbp->hwndPage, ID_XSDI_OS_CACHESIZE,
                                0, 14400, 1024);
                    winhSetDlgItemSpinData(pcnbp->hwndPage, ID_XSDI_OS_CACHE_THRESHOLD,
                                4, 64, 4);
                    WinSetDlgItemText(pcnbp->hwndPage, ID_XSDI_OS_AUTOCHECK, "");
                break; }

                case SP_WPS: {
                    winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_AUTO_PROGRAMS, TRUE);
                    winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_AUTO_TASKLIST, TRUE);
                    winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_AUTO_CONNECTIONS, TRUE);
                    winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_AUTO_LAUNCHPAD, TRUE);
                    winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_AUTO_WARPCENTER,
                                    (doshIsWarp4()));
                    winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_RESTART_YES, TRUE);
                    winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_RESTART_REBOOT, FALSE);
                    winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_AUTOREFRESHFOLDERS,
                                    (doshIsWarp4()));
                break; }

                case SP_ERRORS: {
                    winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_AUTOFAIL, FALSE);
                    winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_REIPL, FALSE);
                    winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_OS_SUPRESSPOPUPS, FALSE);
                break; }
            } // end switch

            fncbConfigInitPage(pnbi, 100); // re-enable items
        break; }

        case ID_XSDI_OS_AUTOCHECK_PROPOSE: {
            // "Propose" button for auto-chkdsk (HPFS/FAT pages):
            // enumerate all HPFS or FAT drives on the system
            CHAR szHPFSDrives[30];
            doshEnumDrives(szHPFSDrives,
                    (pcnbp->ulPageID == SP_HPFS) ? "HPFS" : "FAT");
            WinSetDlgItemText(pcnbp->hwndPage, ID_XSDI_OS_AUTOCHECK, szHPFSDrives);
        break; }
    }

    if (    (usNotifyCode == SPBN_CHANGE)
         || (usNotifyCode == BN_CLICKED)
       )
       // if we had any changes, we might need to
       // re-enable controls
       fncbConfigInitPage(pnbi, 100);

    return ((MPARAM)-1);
}

/*
 *@@ fncbConfigTimer:
 *      common callback func for the "Memory" and "Scheduler"
 *      pages, which have a 2-sec timer set for updating the
 *      display
 */

VOID fncbConfigTimer(PVOID pnbi, ULONG ulTimer)
{
    PCREATENOTEBOOKPAGE pcnbp = (PCREATENOTEBOOKPAGE)pnbi;
    CHAR szTemp[50];

    switch (pcnbp->ulPageID)
    {
        case SP_SCHEDULER: {
            sprintf(szTemp, "%d", prcQueryThreadCount(0));
            WinSetDlgItemText(pcnbp->hwndPage, ID_XSDI_OS_CURRENTTHREADS, szTemp);
        break; }

        case SP_MEMORY: {
            if (strlen(szOrigSwapPath) != 0) {
                ULONG ulSize = doshQueryPathSize(szOrigSwapPath)/1024/1024;
                if (ulSize) {
                    sprintf(szTemp, "%d", ulSize);
                    WinSetDlgItemText(pcnbp->hwndPage, ID_XSDI_OS_CURRENTSWAPSIZE,
                        (szTemp));
                } else
                    WinSetDlgItemText(pcnbp->hwndPage, ID_XSDI_OS_CURRENTSWAPSIZE, "???");
            }
        break; }
    }
}

/* ******************************************************************
 *                                                                  *
 *   here come the XFldSystem instance methods                      *
 *                                                                  *
 ********************************************************************/

/*
 *@@ xfAddXFldSystemPages:
 *           this actually adds the "XFolder" pages into the System notebook
 */

SOM_Scope ULONG  SOMLINK xfsys_xfAddXFldSystemPages(XFldSystem *somSelf,
                                                 HWND hwndDlg)
{
    PCREATENOTEBOOKPAGE pcnbp;
    PAGEINFO        pi;
    HMODULE         savehmod;
    // CHAR            szXFolderVersion[100];
    PNLSSTRINGS pNLSStrings = cmnQueryNLSStrings();
    PSZ pszHelpLibrary = cmnQueryHelpLibrary();

    // XFldSystemData *somThis = XFldSystemGetData(somSelf);
    XFldSystemMethodDebug("XFldSystem","xfsys_xfAddXFldSystemPages");

    savehmod = NLS_MODULE;
    memset((PCH)&pi, 0, sizeof(PAGEINFO));

    // "Errors"
    pcnbp = malloc(sizeof(CREATENOTEBOOKPAGE));
    memset(pcnbp, 0, sizeof(CREATENOTEBOOKPAGE));
    pcnbp->somSelf = somSelf;
    pcnbp->hwndNotebook = hwndDlg;
    pcnbp->hmod = savehmod;
    pcnbp->pfncbInitPage    = fncbConfigInitPage;
    pcnbp->pfncbItemChanged = fncbConfigItemChanged;
    pcnbp->fMajorTab = TRUE;
    pcnbp->pszName = pNLSStrings->pszErrors;
    pcnbp->ulDlgID = ID_XSD_SETTINGS_ERRORS;
    pcnbp->ulDefaultHelpPanel  = ID_XSH_SETTINGS_ERRORS;
    // give this page a unique ID, which is
    // passed to the common config.sys callbacks
    pcnbp->ulPageID = SP_ERRORS;
    ntbInsertPage(pcnbp);

    // "WPS" settings
    pcnbp = malloc(sizeof(CREATENOTEBOOKPAGE));
    memset(pcnbp, 0, sizeof(CREATENOTEBOOKPAGE));
    pcnbp->somSelf = somSelf;
    pcnbp->hwndNotebook = hwndDlg;
    pcnbp->hmod = savehmod;
    pcnbp->pfncbInitPage    = fncbConfigInitPage;
    pcnbp->pfncbItemChanged = fncbConfigItemChanged;
    pcnbp->fMajorTab = TRUE;
    pcnbp->pszName = pNLSStrings->pszWPS;
    pcnbp->ulDlgID = ID_XSD_SETTINGS_WPS;
    pcnbp->ulDefaultHelpPanel  = ID_XSH_SETTINGS_WPS;
    // give this page a unique ID, which is
    // passed to the common config.sys callbacks
    pcnbp->ulPageID = SP_WPS;
    ntbInsertPage(pcnbp);

    // insert file-system settings pages
    pcnbp = malloc(sizeof(CREATENOTEBOOKPAGE));
    memset(pcnbp, 0, sizeof(CREATENOTEBOOKPAGE));
    pcnbp->somSelf = somSelf;
    pcnbp->hwndNotebook = hwndDlg;
    pcnbp->hmod = savehmod;
    pcnbp->pfncbInitPage    = fncbConfigInitPage;
    pcnbp->pfncbItemChanged = fncbConfigItemChanged;
    pcnbp->fMajorTab = TRUE;
    pcnbp->pszName = "~FAT";
    pcnbp->ulDlgID = ID_XSD_SETTINGS_FAT;
    pcnbp->ulDefaultHelpPanel  = ID_XSH_SETTINGS_HPFS;
    // give this page a unique ID, which is
    // passed to the common config.sys callbacks
    pcnbp->ulPageID = SP_FAT;
    ntbInsertPage(pcnbp);

    pcnbp = malloc(sizeof(CREATENOTEBOOKPAGE));
    memset(pcnbp, 0, sizeof(CREATENOTEBOOKPAGE));
    pcnbp->somSelf = somSelf;
    pcnbp->hwndNotebook = hwndDlg;
    pcnbp->hmod = savehmod;
    pcnbp->pfncbInitPage    = fncbConfigInitPage;
    pcnbp->pfncbItemChanged = fncbConfigItemChanged;
    pcnbp->fMajorTab = TRUE;
    pcnbp->pszName = "~HPFS";
    pcnbp->ulDlgID = ID_XSD_SETTINGS_HPFS;
    pcnbp->ulDefaultHelpPanel  = ID_XSH_SETTINGS_HPFS;
    // give this page a unique ID, which is
    // passed to the common config.sys callbacks
    pcnbp->ulPageID = SP_HPFS;
    ntbInsertPage(pcnbp);

    // "Memory"
    pcnbp = malloc(sizeof(CREATENOTEBOOKPAGE));
    memset(pcnbp, 0, sizeof(CREATENOTEBOOKPAGE));
    pcnbp->somSelf = somSelf;
    pcnbp->hwndNotebook = hwndDlg;
    pcnbp->hmod = savehmod;
    pcnbp->pfncbInitPage    = fncbConfigInitPage;
    pcnbp->pfncbItemChanged = fncbConfigItemChanged;
    pcnbp->fMajorTab = TRUE;
    pcnbp->pszName = pNLSStrings->pszMemory;
    pcnbp->ulDlgID = ID_XSD_SETTINGS_KERNEL2;
    pcnbp->ulDefaultHelpPanel  = ID_XSH_SETTINGS_KERNEL2;
    // give this page a unique ID, which is
    // passed to the common config.sys callbacks
    pcnbp->ulPageID = SP_MEMORY;
    // for this page, start a timer
    pcnbp->ulTimer = 2000;
    pcnbp->pfncbTimer = fncbConfigTimer;
    ntbInsertPage(pcnbp);

    // "Scheduler"
    pcnbp = malloc(sizeof(CREATENOTEBOOKPAGE));
    memset(pcnbp, 0, sizeof(CREATENOTEBOOKPAGE));
    pcnbp->somSelf = somSelf;
    pcnbp->hwndNotebook = hwndDlg;
    pcnbp->hmod = savehmod;
    pcnbp->pfncbInitPage    = fncbConfigInitPage;
    pcnbp->pfncbItemChanged = fncbConfigItemChanged;
    pcnbp->fMajorTab = TRUE;
    pcnbp->pszName = pNLSStrings->pszScheduler;
    pcnbp->ulDlgID = ID_XSD_SETTINGS_KERNEL1;
    pcnbp->ulDefaultHelpPanel  = ID_XSH_SETTINGS_KERNEL1;
    // give this page a unique ID, which is
    // passed to the common config.sys callbacks
    pcnbp->ulPageID = SP_SCHEDULER;
    // for this page, start a timer
    pcnbp->ulTimer = 2000;
    pcnbp->pfncbTimer = fncbConfigTimer;
    return (ntbInsertPage(pcnbp));

}

/*
 *@@ wpAddSettingsPages:
 *           this instance method is overridden in order
 *           to add the new XFolder page after the default
 *           "Screen" page in the settings notebook. In
 *           order to to this, unlike the procedure used in
 *           the "Workplace Shell" object, we will explicitly
 *           call the WPSystem methods which insert the
 *           pages we want to see here into the notebook.
 *           As a result, the "Workplace Shell" object
 *           inherits all pages from the "System" object
 *           which might be added by other WPS utils, while
 *           this thing does not.
 */

SOM_Scope BOOL  SOMLINK xfsys_wpAddSettingsPages(XFldSystem *somSelf,
                                                 HWND hwndNotebook)
{
    // XFldSystemData *somThis = XFldSystemGetData(somSelf);
    XFldSystemMethodDebug("XFldSystem","xfsys_wpwpAddSettingsPages");

    // do _not_ call the parent, but call the page methods
    // explicitly
    /* if (ulRC)
        ulRC = XFldSystem_parent_WPSystem_wpAddSystemScreenPage(somSelf, hwndNotebook); */

    // XFolder "Internals" page bottommost
    _xfAddObjectInternalsPage(somSelf, hwndNotebook);
    // "Symbol" page next
    _wpAddObjectGeneralPage(somSelf, hwndNotebook);
    // "Screen" page 2 next; this page may exist on some systems
    // depending on the video driver, and we want this in "OS/2 Kernel"
    // also
    _wpAddDMQSDisplayTypePage(somSelf, hwndNotebook);
    // "Screen" page 1 next
    _wpAddSystemScreenPage(somSelf, hwndNotebook);

    // XFolder CONFIG.SYS pages on top
    _xfAddXFldSystemPages(somSelf, hwndNotebook);

    return (TRUE);
}

/* ******************************************************************
 *                                                                  *
 *   here come the XFldSystem class methods                         *
 *                                                                  *
 ********************************************************************/

/*
 *@@ wpclsSetSetting:
 *           this WPAbstract method sets the class object
 *           settings in the settings notebook via setup
 *           strings. WPSystem defines the WPS-wide system
 *           setting strings here, and XFolder needs to
 *           introduce its own settings here also.
 */

SOM_Scope BOOL  SOMLINK xfsysM_wpclsSetSetting(M_XFldSystem *somSelf,
                                               PSZ pszSetting,
                                               PVOID pValue)
{
    // M_XFldSystemData *somThis = M_XFldSystemGetData(somSelf);
    M_XFldSystemMethodDebug("M_XFldSystem","xfsysM_wpclsSetSetting");

    return (M_XFldSystem_parent_M_WPSystem_wpclsSetSetting(somSelf,
                                                           pszSetting,
                                                           pValue));
}

/*
 *@@ wpclsQuerySettingsPageSize:
 *           this WPObject class method should return the
 *           size of the largest settings page in dialog
 *           units; if a settings notebook is initially
 *           opened, i.e. no window pos has been stored
 *           yet, the WPS will use this size, to avoid
 *           truncated settings pages.
 */

SOM_Scope BOOL  SOMLINK xfsysM_wpclsQuerySettingsPageSize(M_XFldSystem *somSelf,
                                                          PSIZEL pSizl)
{
    BOOL brc;
    /* M_XFldSystemData *somThis = M_XFldSystemGetData(somSelf); */
    M_XFldSystemMethodDebug("M_XFldSystem","xfsysM_wpclsQuerySettingsPageSize");

    brc = M_XFldSystem_parent_M_WPSystem_wpclsQuerySettingsPageSize(somSelf,
                                                                      pSizl);
    if (brc) {
        pSizl->cy = 162;        // this is the height of the "WPS Classes" page,
                                // which seems to be the largest in the "Workplace
                                // Shell" object
        if (doshIsWarp4())
            // on Warp 4, reduce again, because we're moving
            // the notebook buttons to the bottom
            pSizl->cy -= WARP4_NOTEBOOK_OFFSET;
    }

    return (brc);
}

/*
 *@@ wpclsQueryIconData:
 *           give the WPS object a new icon
 */

SOM_Scope ULONG  SOMLINK xfsysM_wpclsQueryIconData(M_XFldSystem *somSelf,
                                                   PICONINFO pIconInfo)
{
    // M_XFldSystemData *somThis = M_XFldSystemGetData(somSelf);
    M_XFldSystemMethodDebug("M_XFldSystem","xfsysM_wpclsQueryIconData");

    if (pIconInfo) {
       pIconInfo->fFormat = ICON_RESOURCE;
       pIconInfo->resid   = ID_ICONSYS;
       pIconInfo->hmod    = modQueryHandle();
    }

    return (sizeof(ICONINFO));

    /* return (M_XFldSystem_parent_M_WPSystem_wpclsQueryIconData(somSelf,
                                                              pIconInfo)); */
}

/*
 *@@ wpclsQueryTitle:
 *           tell the WPS the new class name: System (XFolder)
 */

SOM_Scope PSZ  SOMLINK xfsysM_wpclsQueryTitle(M_XFldSystem *somSelf)
{
    // M_XFldSystemData *somThis = M_XFldSystemGetData(somSelf);
    M_XFldSystemMethodDebug("M_XFldSystem","xfsysM_wpclsQueryTitle");

    return ("OS/2 Kernel");
}

/*
 *@@ wpclsInitData:
 *           initialize XFldSystem class data
 */

SOM_Scope void  SOMLINK xfsysM_wpclsInitData(M_XFldSystem *somSelf)
{
    // M_XFldSystemData *somThis = M_XFldSystemGetData(somSelf);
    M_XFldSystemMethodDebug("M_XFldSystem","xfsysM_wpclsInitData");

    M_XFldSystem_parent_M_WPSystem_wpclsInitData(somSelf);

    // _hmodXFldSystem = NULLHANDLE;
}


