home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: WPS_PM / WPS_PM.zip / xfld085s.zip / main / xfldr.c < prev    next >
C/C++ Source or Header  |  1999-02-23  |  254KB  |  6,294 lines

  1.  
  2. /*
  3.  *@@sourcefile xfldr.c:
  4.  *      This file contains the following major XFolder parts:
  5.  *
  6.  *      --  XFolder class
  7.  *      --  XFldStartup (startup folder) class
  8.  *      --  XFldShutdown (shutdown folder) class
  9.  *
  10.  *      Check the other files starting with xf* for the
  11.  *      other XFolder classes.
  12.  *
  13.  *      XFolder is probably the most complex class of this
  14.  *      package. Not only are context menus manipulated, but
  15.  *      open folder view windows are also subclassed to
  16.  *      introduce additional functionality (fnwpSubclassedFolderFrame).
  17.  *
  18.  *      Most of the code in this file is "responsive" in that
  19.  *      it is only called upon invocation of folder SOM methods.
  20.  *      However, this also hooks a lot of functionality into
  21.  *      the WPS using the subclassed folder frame proc.
  22.  *
  23.  *      The XFolder class must always be installed.
  24.  *      Installation of XFldStartup and XFldShutdown is
  25.  *      optional.
  26.  *
  27.  *@@somclass XFolder xf_
  28.  *@@somclass M_XFolder xfM_
  29.  *@@somclass XFldStartup xfstup_
  30.  *@@somclass M_XFldStartup xfstupM_
  31.  *@@somclass XFldShutdown xfshut_
  32.  *@@somclass M_XFldShutdown xfshutM_
  33.  */
  34.  
  35. /*
  36.  *      Copyright (C) 1997-99 Ulrich Möller.
  37.  *      This file is part of the XFolder source package.
  38.  *      XFolder is free software; you can redistribute it and/or modify
  39.  *      it under the terms of the GNU General Public License as published
  40.  *      by the Free Software Foundation, in version 2 as it comes in the
  41.  *      "COPYING" file of the XFolder main distribution.
  42.  *      This program is distributed in the hope that it will be useful,
  43.  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
  44.  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  45.  *      GNU General Public License for more details.
  46.  */
  47.  
  48. /*
  49.  *  This file was generated by the SOM Compiler and Emitter Framework.
  50.  *  Generated using:
  51.  *      SOM Emitter emitctm: 2.41
  52.  */
  53.  
  54. #ifndef SOM_Module_xfldr_Source
  55. #define SOM_Module_xfldr_Source
  56. #endif
  57. #define XFolder_Class_Source
  58. #define M_XFolder_Class_Source
  59.  
  60. /*
  61.  *  Suggested #include order:
  62.  *  1)  os2.h
  63.  *  2)  C library headers
  64.  *  3)  SOM headers which work with precompiled header files
  65.  *  4)  headers in /helpers
  66.  *  5)  headers in /main with dlgids.h and common.h first
  67.  *  6)  #pragma hdrstop to prevent VAC++ crashes
  68.  *  7)  other needed SOM headers
  69.  *  8)  for non-SOM-class files: corresponding header (e.g. classlst.h)
  70.  */
  71.  
  72. #define INCL_DOSFILEMGR
  73. #define INCL_DOSMODULEMGR
  74. #define INCL_DOSMEMMGR
  75. #define INCL_DOSPROCESS         // DosSleep, priorities, PIDs etc.
  76. #define INCL_DOSSEMAPHORES      // needed for xthreads.h
  77. #define INCL_DOSEXCEPTIONS
  78. #define INCL_DOSERRORS
  79. #define INCL_DOSMISC            // DosGetMessage etc.
  80.  
  81. #define INCL_WINWINDOWMGR
  82. #define INCL_WINFRAMEMGR        // WM_FORMATFRAME, SC_CLOSE etc.
  83. #define INCL_WINSYS             // presparams, WinQuerySysValue()
  84. #define INCL_WININPUT           // Focus, WM_BUTTON1DOWN, WM_CONTEXTMENU etc.
  85.  
  86. #define INCL_WINSHELLDATA       // profile funcs
  87. #define INCL_WINPROGRAMLIST     // needed for WPProgram
  88. #define INCL_WINTIMER
  89. #define INCL_WINPOINTERS
  90. #define INCL_WINERRORS
  91. #define INCL_WINRECTANGLES      // rcl functions
  92. #define INCL_WINMESSAGEMGR      // WinQueryMsgPos
  93.  
  94. #define INCL_WINDIALOGS
  95. #define INCL_WINSTATICS
  96. #define INCL_WINMENUS           // needed for menus.h
  97. #define INCL_WINENTRYFIELDS
  98. #define INCL_WINBUTTONS
  99. #define INCL_WINLISTBOXES
  100. #define INCL_WINSTDCNR          // needed for winh.h
  101. #define INCL_WINSTDBOOK         // notebooks
  102. #define INCL_WINSTDFILE         // file dialog
  103. #define INCL_WINMLE             // multi-line entry field
  104.  
  105. #define INCL_WINWORKPLACE
  106.  
  107. #define INCL_GPILOGCOLORTABLE
  108. #define INCL_GPIPRIMITIVES
  109.  
  110. #include <os2.h>
  111.  
  112. // C library headers
  113. #include <stdio.h>              // needed for except.h
  114. #include <setjmp.h>             // needed for except.h
  115. #include <assert.h>             // needed for except.h
  116.  
  117. #pragma hdrstop                 // VAC++ keeps crashing otherwise
  118.  
  119. // headers in /helpers
  120. #include "dosh.h"               // Control Program helper routines
  121. #include "winh.h"               // PM helper routines
  122. #include "gpih.h"               // GPI helper routines
  123.  
  124. #include "eas.h"                // extended attributes helper routines
  125. #include "linklist.h"           // linked list helper routines
  126. #include "wphandle.h"           // Henk Kelder's HOBJECT handling
  127.  
  128. // SOM headers which don't crash with prec. header files
  129. #include "xfldr.ih"
  130.  
  131. // headers in /main
  132. #include "dlgids.h"             // all the IDs that are shared with NLS
  133.  
  134. #include "common.h"             // the majestic XFolder include file
  135. #include "cnrsort.h"            // container sort comparison functions
  136. #include "except.h"             // XFolder exception handling
  137. #include "menus.h"              // common XFolder context menu logic
  138. #include "module.h"             // XFolder main DLL information
  139. #include "notebook.h"           // generic XFolder notebook handling
  140. #include "sound.h"              // declarations for SOUND.DLL
  141. #include "statbars.h"           // status bar translation logic
  142. #include "xthreads.h"           // XFolder threads; this includes threads.h
  143.  
  144. // other SOM headers
  145. #include <wppgm.h>              // WPProgram
  146. #include <wprootf.h>            // WPRootFolder
  147. #include <wpshadow.h>           // WPShadow
  148. #include "xfobj.h"
  149. #include "xfdesk.h"
  150. #include "xfdisk.h"
  151.  
  152. #include "xwps.h"               // XFolder pseudo SOM functions
  153.  
  154. /* ******************************************************************
  155.  *                                                                  *
  156.  *   Global variables                                               *
  157.  *                                                                  *
  158.  ********************************************************************/
  159.  
  160. // roots of linked lists for favorite/quick-open folders
  161. PCONTENTMENULISTITEM pcmliFavoriteFolders = NULL,
  162.                     pcmliQuickOpenFolders = NULL;
  163. // mutex semaphores for these lists
  164. HMTX                hmtxFavoriteFolders = NULLHANDLE,
  165.                     hmtxQuickOpenFolders = NULLHANDLE;
  166. CHAR                szXFolderVersion[100];
  167.  
  168. // forward declarations
  169. MRESULT EXPENTRY fnwpSupplObject(HWND hwndObject, ULONG msg, MPARAM mp1, MPARAM mp2);
  170.  
  171. // SORTBYICONPOS:
  172. // structure for GetICONPOS
  173. typedef struct _SORTBYICONPOS {
  174.     CHAR    szRealName[CCHMAXPATH];
  175.     PBYTE   pICONPOS;
  176.     USHORT  usICONPOSSize;
  177. } SORTBYICONPOS, *PSORTBYICONPOS;
  178.  
  179. /* ******************************************************************
  180.  *                                                                  *
  181.  *   Common routines used by several XFolder methods                *
  182.  *                                                                  *
  183.  ********************************************************************/
  184.  
  185. /*
  186.  *@@ QuerySortFunc:
  187.  *      this returns the sort comparison function for
  188.  *      the specified sort criterion. See XFolder::xfSortViewOnce
  189.  *      for details.
  190.  */
  191.  
  192. PFN QuerySortFunc(USHORT usSort)
  193. {
  194.     USHORT usSort2 = usSort;
  195.  
  196.     if (usSort == SET_DEFAULT)
  197.     {
  198.         PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
  199.         usSort2 =  pGlobalSettings->DefaultSort;
  200.     }
  201.  
  202.     switch (usSort2) {
  203.         case SV_TYPE:           return ((PFN)fnCompareType);
  204.         case SV_CLASS:          return ((PFN)fnCompareClass);
  205.         case SV_REALNAME:       return ((PFN)fnCompareRealName);
  206.         case SV_SIZE:           return ((PFN)fnCompareSize);
  207.         case SV_LASTWRITEDATE:  return ((PFN)fnCompareLastWriteDate);
  208.         case SV_LASTACCESSDATE: return ((PFN)fnCompareLastAccessDate);
  209.         case SV_CREATIONDATE:   return ((PFN)fnCompareCreationDate);
  210.         case SV_EXT:            return ((PFN)fnCompareExt);
  211.         case SV_FOLDERSFIRST:   return ((PFN)fnCompareFoldersFirst);
  212.     };
  213.  
  214.     // default:
  215.     return ((PFN)fnCompareName);
  216. }
  217.  
  218. /*
  219.  *@@ SetOneFrameWndTitle:
  220.  *           this changes the window title of a given folder frame window
  221.  *           to the full path of the folder; this method does NOT check
  222.  *           the respective XFolder settings any more, so this has to be
  223.  *           done by the caller.
  224.  */
  225.  
  226. BOOL SetOneFrameWndTitle(XFolder *somSelf, HWND hwndFrame)
  227. {
  228.     PSZ                 pFirstSlash, pSrchSlash, pNextSlash;
  229.     CHAR                szTemp[CCHMAXPATH];
  230.     XFolderData         *somThis = XFolderGetData(somSelf);
  231.     PGLOBALSETTINGS     pGlobalSettings = cmnQueryGlobalSettings();
  232.     BOOL                brc;
  233.  
  234.     if (    (_bFullPath == 1)
  235.          || ((_bFullPath == 2) && (pGlobalSettings->FullPath))
  236.        )
  237.     {
  238.         // settings allow full path in title for this folder:
  239.  
  240.         // get real name (= full path), if allowed)
  241.         _wpQueryFilename(somSelf, szTemp, TRUE);
  242.  
  243.         // now truncate path if it's longer than allowed by user
  244.         pFirstSlash = strchr(szTemp, '\\');
  245.         if ((pFirstSlash) && (pGlobalSettings->MaxPathChars > 10)) {
  246.             pSrchSlash = pFirstSlash+3;
  247.             while (strlen(szTemp) > pGlobalSettings->MaxPathChars) {
  248.                 pNextSlash = strchr(pSrchSlash, '\\');
  249.                 if (pNextSlash) {
  250.                     strcpy(pFirstSlash+4, pNextSlash);
  251.                     pFirstSlash[1] = '.';
  252.                     pFirstSlash[2] = '.';
  253.                     pFirstSlash[3] = '.';
  254.                     pSrchSlash = pFirstSlash+5;
  255.                 }
  256.                 else break;
  257.             }
  258.         }
  259.  
  260.         // now either append the full path in brackets to or replace window title
  261.         if (pGlobalSettings->KeepTitle) {
  262.             CHAR szFullPathTitle[CCHMAXPATH*2];
  263.             sprintf(szFullPathTitle, "%s (%s)",
  264.                     _wpQueryTitle(somSelf),
  265.                     szTemp);
  266.             WinSetWindowText(hwndFrame, szFullPathTitle);
  267.         }
  268.         else
  269.             WinSetWindowText(hwndFrame, szTemp);
  270.  
  271.         brc = TRUE;
  272.     } else {
  273.         // settings DON'T allow full path in title for this folder:
  274.         // set to title only
  275.         WinSetWindowText(hwndFrame, _wpQueryTitle(somSelf));
  276.         brc = FALSE;
  277.     }
  278.     return (brc);
  279. }
  280.  
  281. /* ******************************************************************
  282.  *                                                                  *
  283.  *   here come the XFolder instance methods                         *
  284.  *                                                                  *
  285.  ********************************************************************/
  286.  
  287. /*
  288.  *@@ xfUpdateAllFrameWndTitles:
  289.  *           this method sets the frame wnd titles for all currently
  290.  *           open views of a given folder to the full path;
  291.  *           it is called on the Worker thread after XFolder's replacements
  292.  *           of wpMoveObject, wpSetTitle, or wpRefresh have been called.
  293.  *           It does check the respective Global / folder settings.
  294.  */
  295.  
  296. SOM_Scope BOOL     SOMLINK xf_xfUpdateAllFrameWndTitles(XFolder *somSelf)
  297. {
  298.     HWND        hwndFrame;
  299.     BOOL        brc = FALSE;
  300.  
  301.     if (hwndFrame = xwpsQueryFrameFromView(somSelf, OPEN_CONTENTS)) {
  302.         SetOneFrameWndTitle(somSelf, hwndFrame);
  303.         brc = TRUE;
  304.     }
  305.     if (hwndFrame = xwpsQueryFrameFromView(somSelf, OPEN_DETAILS)) {
  306.         SetOneFrameWndTitle(somSelf, hwndFrame);
  307.         brc = TRUE;
  308.     }
  309.     if (hwndFrame = xwpsQueryFrameFromView(somSelf, OPEN_TREE)) {
  310.         SetOneFrameWndTitle(somSelf, hwndFrame);
  311.         brc = TRUE;
  312.     }
  313.  
  314.     ntbUpdateVisiblePage(somSelf, SP_XFOLDER_FLDR);
  315.  
  316.     return (brc);
  317. }
  318.  
  319. /*
  320.  *@@ xfSnapToGrid:
  321.  *           makes all objects in the folder "snap" on a grid whose
  322.  *           coordinates are to be defined in the "system" object.
  323.  *           This method checks if an Icon view of the folder is
  324.  *           currently open; if not and fNotify == TRUE, it displays
  325.  *           a message box.
  326.  */
  327.  
  328. SOM_Scope BOOL  SOMLINK xf_xfSnapToGrid(XFolder *somSelf,
  329.                                            BOOL fNotify)
  330. {
  331.     // WPObject            *obj;
  332.     HWND                hwndFrame = 0,
  333.                         hwndCnr = 0;
  334.     PMINIRECORDCORE     pmrc;
  335.     LONG                lNewX, lNewY;
  336.     BOOL                brc = FALSE;
  337.     // if Shift is pressed, move all the objects, otherwise
  338.     // only the selected ones
  339.     BOOL                fShiftPressed = doshQueryShiftState();
  340.     BOOL                fMoveThisObject = FALSE;
  341.  
  342.     PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
  343.     // XFolderData *somThis = XFolderGetData(somSelf);
  344.     XFolderMethodDebug("XFolder","xf_xfSnapToGrid");
  345.  
  346.     // first we need the frame handle of a currently open icon view;
  347.     // all others don't make sense */
  348.     hwndFrame = xwpsQueryFrameFromView(somSelf, OPEN_CONTENTS);
  349.  
  350.     if (hwndFrame) {
  351.  
  352.         // now get the container handle
  353.         hwndCnr = xwpsQueryCnrFromFrame(hwndFrame);
  354.  
  355.         if (hwndCnr)
  356.         {
  357.             // now begin iteration over the folder's objects; we don't
  358.             // use the WPS method (wpQueryContent) because this is too
  359.             // slow. Instead, we query the container directly.
  360.  
  361.             pmrc = NULL;
  362.             do {
  363.                 if (fShiftPressed)
  364.                     // shift pressed: move all objects, so loop
  365.                     // thru the whole container content
  366.                     pmrc =
  367.                         (PMINIRECORDCORE)WinSendMsg(hwndCnr,
  368.                                 CM_QUERYRECORD,
  369.                                 (MPARAM)pmrc,           // NULL at first loop
  370.                                 MPFROM2SHORT(
  371.                                     (pmrc)
  372.                                         ? CMA_NEXT      // not first loop: get next object
  373.                                         : CMA_FIRST,    // first loop: get first objecct
  374.                                     CMA_ITEMORDER)
  375.                                 );
  376.                 else
  377.                     // shift _not_ pressed: move selected objects
  378.                     // only, so loop thru these objects
  379.                     pmrc =
  380.                         (PMINIRECORDCORE)WinSendMsg(hwndCnr,
  381.                                 CM_QUERYRECORDEMPHASIS,
  382.                                 (pmrc)                  // NULL at first loop
  383.                                     ? (MPARAM)pmrc
  384.                                     : (MPARAM)CMA_FIRST, // flag for getting first selected
  385.                                 (MPARAM)(CRA_SELECTED)
  386.                                 );
  387.                 if (pmrc) {
  388.                     // record found:
  389.                     // the WPS shares records among views, so we need
  390.                     // to update the record core info first
  391.                     WinSendMsg(hwndCnr,
  392.                                 CM_QUERYRECORDINFO,
  393.                                 (MPARAM)&pmrc,
  394.                                 (MPARAM)1);         // one record only
  395.                     // un-display the new object at the old (default) location
  396.                     WinSendMsg(hwndCnr,
  397.                                 CM_ERASERECORD,
  398.                                     // this only changes the visibility of the
  399.                                     // record without changing the recordcore;
  400.                                     // this msg is intended for drag'n'drop and such
  401.                                 (MPARAM)pmrc,
  402.                                 NULL);
  403.  
  404.                     // now play with the objects coordinates
  405.                     lNewX =
  406.                         ( (
  407.                             ( (pmrc->ptlIcon.x - pGlobalSettings->GridX)
  408.                               + (pGlobalSettings->GridCX / 2)
  409.                             )
  410.                         / pGlobalSettings->GridCX ) * pGlobalSettings->GridCX )
  411.                         + pGlobalSettings->GridX;
  412.                     lNewY =
  413.                         ( (
  414.                             ( (pmrc->ptlIcon.y - pGlobalSettings->GridY)
  415.                               + (pGlobalSettings->GridCY / 2)
  416.                             )
  417.                         / pGlobalSettings->GridCY ) * pGlobalSettings->GridCY )
  418.                         + pGlobalSettings->GridY;
  419.  
  420.                     // update the record core
  421.                     if ( (lNewX) && (lNewX != pmrc->ptlIcon.x) ) {
  422.                         pmrc->ptlIcon.x = lNewX;         // X
  423.                     }
  424.                     if ( (lNewY) && (lNewY != pmrc->ptlIcon.y) ) {
  425.                         pmrc->ptlIcon.y = lNewY;         // Y
  426.                     }
  427.  
  428.                     // repaint at new position
  429.                     WinSendMsg(hwndCnr,
  430.                                 CM_INVALIDATERECORD,
  431.                                 (MPARAM)&pmrc,
  432.                                 MPFROM2SHORT(1,     // one record only
  433.                                     CMA_REPOSITION | CMA_ERASE));
  434.                 }
  435.             } while (pmrc);
  436.  
  437.             brc = TRUE; // "OK" flag
  438.         } // end if (hwndCnr)
  439.     } // end if (hwndFrame)
  440.     else { // no open icon view: complain
  441.         if (fNotify) {
  442.             cmnSetHelpPanel(-1);                   // disable F1
  443.             WinDlgBox(HWND_DESKTOP,
  444.                          HWND_DESKTOP,             // owner is desktop
  445.                          (PFNWP)fnwpDlgGeneric,    // common.c
  446.                          NLS_MODULE,               // load from resource file
  447.                          ID_XFD_NOICONVIEW,        // dialog resource id
  448.                          (PVOID)NULL);
  449.         }
  450.     }
  451.     return (brc);
  452. }
  453.  
  454. /*
  455.  *@@ xfQueryFldrSort:
  456.  *           this returns the folder's sort settings into the specified
  457.  *           USHORT variables. These are set to SET_DEFAULT if no instance
  458.  *           data has been defined; you will then need to query the Global
  459.  *           Settings' values.
  460.  */
  461.  
  462. SOM_Scope BOOL  SOMLINK xf_xfQueryFldrSort(XFolder *somSelf,
  463.                                               PUSHORT pusDefaultSort,
  464.                                               PUSHORT pusAlwaysSort)
  465. {
  466.     XFolderData *somThis = XFolderGetData(somSelf);
  467.     XFolderMethodDebug("XFolder","xf_xfQueryFldrSort");
  468.  
  469.     if ((pusDefaultSort) && (pusAlwaysSort)) {
  470.         *pusDefaultSort = (USHORT)_DefaultSort;
  471.         *pusAlwaysSort  = (USHORT)_AlwaysSort;
  472.         return (TRUE);
  473.     } else
  474.         return (FALSE);
  475. }
  476.  
  477. /*
  478.  * fncbSortAllViews:
  479.  *      callback function for sorting all folder views.
  480.  *      This is called by xf(cls)ForEachOpenView, which also passes
  481.  *      the parameters to this func.
  482.  */
  483.  
  484. MRESULT EXPENTRY fncbSortAllViews(HWND hwndView,    // open folder view frame hwnd
  485.                                   ULONG ulSort,     // sort flag
  486.                                   MPARAM mpView,    // OPEN_xxx flag
  487.                                   MPARAM mpFolder)  // XFolder*
  488. {
  489.     XFolder     *somSelf = (XFolder*)mpFolder;
  490.     MRESULT     mrc = (MPARAM)FALSE;
  491.  
  492.     if (   ((ULONG)mpView == OPEN_CONTENTS)
  493.         || ((ULONG)mpView == OPEN_TREE)
  494.         || ((ULONG)mpView == OPEN_DETAILS)
  495.        )
  496.     {
  497.         _xfSortViewOnce(somSelf, hwndView, ulSort);
  498.         mrc = (MPARAM)TRUE;
  499.     }
  500.     return (mrc);
  501. }
  502.  
  503. /*
  504.  * fncbUpdateFolderSorts:
  505.  *      callback function for updating all folder sorts.
  506.  *      This is called by xf(cls)ForEachOpenView, which also passes
  507.  *      the parameters to this func.
  508.  */
  509.  
  510. MRESULT EXPENTRY fncbUpdateFolderSorts(HWND hwndView,   // frame wnd handle
  511.                         ULONG ulDummy,
  512.                         MPARAM mpView,                  // OPEN_xxx flag for this view
  513.                         MPARAM mpFolder)                // somSelf
  514. {
  515.     XFolder     *somSelf = (XFolder*)mpFolder;
  516.     MRESULT     mrc = (MPARAM)FALSE;
  517.  
  518.     #ifdef DEBUG_SORT
  519.         _Pmpf(( "fncbUpdateFolderSorts: %s", _wpQueryTitle(somSelf) ));
  520.     #endif
  521.  
  522.     if (   ((ULONG)mpView == OPEN_CONTENTS)
  523.         || ((ULONG)mpView == OPEN_TREE)
  524.         || ((ULONG)mpView == OPEN_DETAILS)
  525.        )
  526.     {
  527.         _xfSetCnrSort(somSelf, xwpsQueryCnrFromFrame(hwndView), FALSE);
  528.         mrc = (MPARAM)TRUE;
  529.     }
  530.     return (mrc);
  531. }
  532.  
  533. /*
  534.  *@@ xfSetFldrSort:
  535.  *           this is the new XFolder method for setting the sort data
  536.  *           for a certain folder.
  537.  *
  538.  *           usDefaultSort should be one of the SV_ constants as in
  539.  *           XFolder::xfSortViewOnce or SET_DEFAULT for resetting the folder's
  540.  *           default sort criterion to the Global Settings's value.
  541.  *
  542.  *           usAlwaysSort can be 0 or 1 or SET_DEFAULT also.
  543.  *
  544.  *           This method updates all open folder views with the new
  545.  *           sort settings.
  546.  *           This method returns TRUE if any visible change occured as
  547.  *           a result to the new settings.
  548.  */
  549.  
  550. SOM_Scope BOOL  SOMLINK xf_xfSetFldrSort(XFolder *somSelf,
  551.                                 USHORT usDefaultSort,
  552.                                 USHORT usAlwaysSort)
  553. {
  554.     BOOL Update = FALSE;
  555.     PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
  556.     XFolderData *somThis = XFolderGetData(somSelf);
  557.     XFolderMethodDebug("XFolder","xf_xfSetFldrSort");
  558.  
  559.     #ifdef DEBUG_SORT
  560.         _Pmpf(("xfSetFldrSort %s", _wpQueryTitle(somSelf)));
  561.         _Pmpf(("  Old: Default %d, Always %d", _DefaultSort, _AlwaysSort));
  562.         _Pmpf(("  New: Default %d, Always %d", usDefaultSort, usAlwaysSort));
  563.     #endif
  564.  
  565.     if (usDefaultSort != _DefaultSort) {
  566.         _DefaultSort = usDefaultSort;
  567.         Update = TRUE;
  568.     }
  569.     if (usAlwaysSort != _AlwaysSort) {
  570.         _AlwaysSort = usAlwaysSort;
  571.         // if _wpRestoreState has found the pointer to the
  572.         // WPFOlder-internal sort structure, we will update
  573.         // this one also, because otherwise the WPS keeps
  574.         // messing with the container attributes
  575.         if (_pFldrSortInfo)
  576.             (_pFldrSortInfo)->fAlwaysSort = ALWAYS_SORT;
  577.         Update = TRUE;
  578.     }
  579.  
  580.     if (Update) {
  581.         // update open views of this folder
  582.         _xfForEachOpenView(somSelf, 0, &fncbUpdateFolderSorts);
  583.         _wpSaveDeferred(somSelf);
  584.         // update folder "Sort" notebook page, if open
  585.         ntbUpdateVisiblePage(somSelf, SP_FLDRSORT_FLDR);
  586.     }
  587.  
  588.     return (Update);
  589. }
  590.  
  591. /*
  592.  *@@ xfSetCnrSort:
  593.  *           this is the most central function of XFolder's
  594.  *           extended sorting capabilities. This is called
  595.  *           every time the container in an open folder view
  596.  *           needs to have its sort settings updated. In other
  597.  *           words, this function evaluates the current folder
  598.  *           sort settings and finds out the corresponding
  599.  *           container sort comparison functions and other
  600.  *           settings.
  601.  *
  602.  *           Parameters:
  603.  *           --  HWND hwndCnr     cnr of open view of somSelf
  604.  *           --  BOOL fForce      TRUE: always update the cnr
  605.  *                                settings, even if they have
  606.  *                                not changed
  607.  *
  608.  *           This function gets called:
  609.  *           1)  from our wpOpen override to set folder sort
  610.  *               when a new folder view opens;
  611.  *           2)  from our wpSetFldrSort override (see notes
  612.  *               there);
  613.  *           3)  after folder sort settings have been changed
  614.  *               using xfSetFldrSort.
  615.  *
  616.  *           It is usually not necessary to call this method
  617.  *           directly. To sort folders, you should call
  618.  *           XFolder::xfSetFldrSort or XFolder::xfSortViewOnce
  619.  *           instead.
  620.  *
  621.  *           Note that XFolder does not use the WPS's sort
  622.  *           mechanisms at all. Instead, we set our own
  623.  *           container sort comparison functions directly
  624.  *           _always_. Those functions are all in cnrsort.c.
  625.  *
  626.  *           See the XFolder Programming Guide for an
  627.  *           overview of how XFolder sorting works.
  628.  */
  629.  
  630. SOM_Scope void  SOMLINK xf_xfSetCnrSort(XFolder *somSelf, HWND hwndCnr,
  631.                                         BOOL fForce)
  632. {
  633.     XFolderData *somThis = XFolderGetData(somSelf);
  634.     XFolderMethodDebug("XFolder","xf_xfSetCnrSort");
  635.  
  636.     if (hwndCnr) {
  637.         PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
  638.         XFolderData     *somThis = XFolderGetData(somSelf);
  639.  
  640.         // use our macro for determining this folder's always-sort flag;
  641.         // this is TRUE if "Always sort" is on either locally or globally
  642.         BOOL            AlwaysSort = ALWAYS_SORT;
  643.  
  644.         // get our sort comparison func
  645.         PFN             pfnSort =  (AlwaysSort)
  646.                                        ? QuerySortFunc(DEFAULT_SORT)
  647.                                        : NULL
  648.                                    ;
  649.  
  650.         CNRINFO         CnrInfo;
  651.         BOOL            Update = FALSE;
  652.  
  653.         winhQueryCnrInfo(hwndCnr, CnrInfo);
  654.  
  655.         #ifdef DEBUG_SORT
  656.             _Pmpf(( "_xfSetCnrSort: %s", _wpQueryTitle(somSelf) ));
  657.             _Pmpf(( "  _Always: %d, Global->Always: %d", _AlwaysSort, pGlobalSettings->AlwaysSort ));
  658.             _Pmpf(( "  _Default: %d, Global->Default: %d", _DefaultSort, pGlobalSettings->DefaultSort ));
  659.         #endif
  660.  
  661.         // for icon views, we need extra precautions
  662.         if ((CnrInfo.flWindowAttr & (CV_ICON | CV_TREE)) == CV_ICON)
  663.         {
  664.             // for some reason, cnr icon views need to have "auto arrange" on
  665.             // when sorting, or the cnr will allow to drag'n'drop icons freely
  666.             // within the same cnr, which is not useful when auto-sort is on
  667.  
  668.             ULONG       ulStyle = WinQueryWindowULong(hwndCnr, QWL_STYLE);
  669.  
  670.             if (AlwaysSort) {
  671.                 // always sort: we need to set CCS_AUTOPOSITION, if not set
  672.                 if ((ulStyle & CCS_AUTOPOSITION) == 0) {
  673.                     #ifdef DEBUG_SORT
  674.                         _Pmpf(( "  New ulStyle = %lX", ulStyle | CCS_AUTOPOSITION ));
  675.                     #endif
  676.                     WinSetWindowULong(hwndCnr, QWL_STYLE, (ulStyle | CCS_AUTOPOSITION));
  677.                     Update = TRUE;
  678.                 }
  679.             } else {
  680.                 // NO always sort: we need to unset CCS_AUTOPOSITION, if set
  681.                 if ((ulStyle & CCS_AUTOPOSITION) != 0) {
  682.                     #ifdef DEBUG_SORT
  683.                         _Pmpf(( "  New ulStyle = %lX", ulStyle & (~CCS_AUTOPOSITION) ));
  684.                     #endif
  685.                     WinSetWindowULong(hwndCnr, QWL_STYLE, (ulStyle & (~CCS_AUTOPOSITION)));
  686.                     Update = TRUE;
  687.                 }
  688.             }
  689.         }
  690.  
  691.         // now also update the internal WPFolder sort info, because otherwise
  692.         // the WPS will keep reverting the cnr attrs; we have obtained the pointer
  693.         // to this structure in wpRestoreData
  694.         if (_pFldrSortInfo)
  695.             _pFldrSortInfo->fAlwaysSort = AlwaysSort;
  696.  
  697.         // finally, set the cnr sort function: we perform these checks
  698.         // to avoid cnr flickering
  699.         if (    // sort function changed?
  700.                 (CnrInfo.pSortRecord != (PVOID)pfnSort)
  701.                 // CCS_AUTOPOSITION flag changed above?
  702.              || (Update)
  703.              || (fForce)
  704.            )
  705.         {
  706.             #ifdef DEBUG_SORT
  707.                 _Pmpf(( "  Resetting pSortRecord to %lX", CnrInfo.pSortRecord ));
  708.             #endif
  709.  
  710.             // set the cnr sort function; if this is != NULL, the
  711.             // container will always sort the records. If auto-sort
  712.             // is off, pfnSort has been set to NULL above.
  713.             CnrInfo.pSortRecord = (PVOID)pfnSort;
  714.  
  715.             // now update the CnrInfo, which will repaint the cnr also
  716.             WinSendMsg(hwndCnr,
  717.                         CM_SETCNRINFO,
  718.                         (MPARAM)&CnrInfo,
  719.                         (MPARAM)CMA_PSORTRECORD);
  720.         }
  721.     }
  722. }
  723.  
  724. /*
  725.  *@@ xfSortViewOnce:
  726.  *           sorts the content of given folder.
  727.  *           As opposed to xfSetFldrSort, this does not change the
  728.  *           folder sort settings, but only sorts the view once.
  729.  *           This is used by the context menu entries in the "Sort"
  730.  *           menu.
  731.  *
  732.  *           ulSort must be one of the following:
  733.  *           --  SV_NAME
  734.  *           --  SV_TYPE
  735.  *           --  SV_CLASS                (new: sort by object class)
  736.  *           --  SV_REALNAME
  737.  *           --  SV_SIZE
  738.  *           --  SV_LASTWRITEDATE
  739.  *           --  SV_LASTACCESSDATE
  740.  *           --  SV_CREATIONDATE
  741.  *           --  SV_EXT                  (new: sort by extension)
  742.  *           --  SV_FOLDERSFIRST         (new: sort folders first)
  743.  */
  744.  
  745. /*
  746.  *@@ xfSortViewOnce:
  747.  *           sorts the content of given folder.
  748.  *           As opposed to XFolder::xfSetFldrSort, this does not
  749.  *           change the folder sort settings, but only sorts the view
  750.  *           once.
  751.  *           This is used by the context menu entries in the "Sort"
  752.  *           menu.
  753.  *
  754.  *           ulSort must be one of the following:
  755.  *           --  SV_NAME
  756.  *           --  SV_TYPE
  757.  *           --  SV_CLASS                (new: sort by object class)
  758.  *           --  SV_REALNAME
  759.  *           --  SV_SIZE
  760.  *           --  SV_LASTWRITEDATE
  761.  *           --  SV_LASTACCESSDATE
  762.  *           --  SV_CREATIONDATE
  763.  *           --  SV_EXT                  (new: sort by extension)
  764.  *           --  SV_FOLDERSFIRST         (new: sort folders first)
  765.  */
  766.  
  767. SOM_Scope BOOL  SOMLINK xf_xfSortViewOnce(XFolder *somSelf, HWND hwndFrame,
  768.                                          USHORT usSort)
  769. {
  770.     BOOL rc = FALSE;
  771.     HWND hwndCnr = xwpsQueryCnrFromFrame(hwndFrame);
  772.     // XFolderData *somThis = XFolderGetData(somSelf);
  773.     XFolderMethodDebug("XFolder","xf_xfSortByExt");
  774.  
  775.     if (hwndCnr) {
  776.         CNRINFO CnrInfo;
  777.         ULONG   ulStyle = 0;
  778.  
  779.         winhQueryCnrInfo(hwndCnr, CnrInfo);
  780.  
  781.         if ((CnrInfo.flWindowAttr & (CV_ICON | CV_TREE)) == CV_ICON) {
  782.             // for some reason, icon views need to have "auto arrange" on,
  783.             // or nothing will happen
  784.             ulStyle = WinQueryWindowULong(hwndCnr, QWL_STYLE);
  785.             WinSetWindowULong(hwndCnr, QWL_STYLE, ulStyle | CCS_AUTOPOSITION);
  786.         }
  787.  
  788.         // send sort msg with proper sort (comparison) func
  789.         WinSendMsg(hwndCnr, CM_SORTRECORD,
  790.                 (MPARAM)QuerySortFunc(usSort),
  791.                 MPNULL);
  792.  
  793.         if ((CnrInfo.flWindowAttr & (CV_ICON | CV_TREE)) == CV_ICON)
  794.             // restore old cnr style
  795.             WinSetWindowULong(hwndCnr, QWL_STYLE, ulStyle);
  796.  
  797.         rc = TRUE;
  798.     }
  799.     return (rc);
  800. }
  801.  
  802. /*
  803.  *@@ xfQueryIconPos:
  804.  *           this new instance method retrieves the icon position of an
  805.  *           object in a currently populated folder; you need to initialize
  806.  *           the pICONPOS structure first, whose size you need to pass in
  807.  *           ulICONPOSSize; the ICONPOS data will be copied to pipReturn.
  808.  *           The method returns FALSE if something went wrong.
  809.  */
  810.  
  811. SOM_Scope BOOL  SOMLINK xf_xfGetIconPos(XFolder *somSelf,
  812.                                            WPObject *pObject,
  813.                                            PBYTE pICONPOS, USHORT usICONPOSSize,
  814.                                            PICONPOS pipReturn)
  815. {
  816.     USHORT   usStartPos;
  817.     PICONPOS pip;
  818.  
  819.     CHAR     szKey[100],
  820.              szPath[CCHMAXPATH];
  821.  
  822.     HOBJECT  hObject = _wpQueryHandle(pObject);
  823.     PSZ      pszClass = _somGetClassName(pObject);
  824.  
  825.     // XFolderData *somThis = XFolderGetData(somSelf);
  826.     XFolderMethodDebug("XFolder","xf_xfGetIconPos");
  827.  
  828.     usStartPos = 21; // with OS/2 2.1 and above, Henk Kelder says
  829.  
  830.     /* first step: the icon position of each object within a given
  831.        .ICONPOS EA starts with a string identifying the object; so
  832.        first, we need to compose this string depending on the type
  833.        of the passed object */
  834.     if (IsObjectAbstract(hObject))
  835.         sprintf(szKey, "%s:A%lX", pszClass, LOUSHORT(hObject));
  836.     else
  837.     {   // file system object
  838.         WPFileSystem    *pobjFile;
  839.         if (pobjFile = _wpclsQueryObject(_WPObject, hObject)) {
  840.             if (_wpQueryFilename(pobjFile, szPath, FALSE)) {
  841.                 sprintf(szKey, "%s:%c%s", pszClass,
  842.                    (_somIsA(pobjFile, _WPFolder) ? 'D' : 'F'),
  843.                    szPath);
  844.             } else
  845.                 return FALSE;
  846.         } else
  847.             return FALSE;
  848.  
  849.     }
  850.  
  851.     // now we have the key to search for within the .ICONPOS EA
  852.  
  853.     if ((pICONPOS) && (pipReturn))
  854.     {
  855.         /* now we go through the .ICONPOS data that was given to us
  856.            and check each item in there if it matches the key we
  857.            composed above */
  858.         for (pip = (PICONPOS)( pICONPOS + usStartPos );
  859.             (PBYTE)pip < pICONPOS + usICONPOSSize; )
  860.         {
  861.             if (!stricmp(pip->szIdentity, szKey))
  862.             {
  863.                 *pipReturn = *pip;
  864.                 return TRUE;
  865.             }
  866.             pip = (PICONPOS)( (PBYTE)pip + sizeof(POINTL) + strlen(pip->szIdentity) + 1 );
  867.         }
  868.     }
  869.  
  870.     return FALSE;
  871. }
  872.  
  873. /*
  874.  * GetICONPOS:
  875.  *
  876.  */
  877.  
  878. PICONPOS GetICONPOS(PORDEREDLISTITEM poli, PSORTBYICONPOS psip)
  879. {
  880.     PICONPOS                    pip;
  881.     CHAR                        *p;
  882.     USHORT usStartPos = 21;  // OS/2 2.1 and above, says Henk
  883.  
  884.     // ICONPOS is defined in PMWP.H as folllows:
  885.     //     typedef struct _ICONPOS
  886.     //     {
  887.     //        POINTL  ptlIcon;
  888.     //        CHAR    szIdentity[1];
  889.     //     } ICONPOS;
  890.     //     typedef ICONPOS *PICONPOS;
  891.  
  892.     // now compare all the objects in the .ICONPOS structure
  893.     // to the identity string of the search object
  894.  
  895.     for (   pip = (PICONPOS)( psip->pICONPOS + usStartPos );
  896.             (PBYTE)pip < (psip->pICONPOS + psip->usICONPOSSize);
  897.         )
  898.     {   // pip now points to an ICONPOS structure
  899.  
  900.         // go beyond the class name
  901.         p = strchr(pip->szIdentity, ':');
  902.         if (p) {
  903.  
  904.             /* #ifdef DEBUG_ORDEREDLIST
  905.                 _Pmpf(("      Identities: %s and %s...", p, poli->szIdentity));
  906.             #endif */
  907.  
  908.             if (stricmp(p, poli->szIdentity) == 0)
  909.                 // object found: return the ICONPOS address
  910.                 return (pip);
  911.             else
  912.                 // not identical: go to next ICONPOS structure
  913.                 pip = (PICONPOS)( (PBYTE)pip + sizeof(POINTL) + strlen(pip->szIdentity) + 1 );
  914.         } else
  915.             break;
  916.     }
  917.     return (NULL);
  918. }
  919.  
  920. /*
  921.  * fnSortByICONPOS:
  922.  *      callback sort function for lstSort to sort the
  923.  *      menu items according to a folder's ICONPOS EAs.
  924.  *      pICONPOS points to the ICONPOS data.
  925.  */
  926.  
  927. SHORT fnSortByICONPOS(PVOID pItem1, PVOID pItem2, PVOID psip)
  928. {
  929.     /* #ifdef DEBUG_ORDEREDLIST
  930.         _Pmpf(("    Comparing %s and %s...",
  931.             _wpQueryTitle(((PORDEREDLISTITEM)pItem1)->pObj),
  932.             _wpQueryTitle(((PORDEREDLISTITEM)pItem2)->pObj)
  933.         ));
  934.     #endif */
  935.     if ((pItem1) && (pItem2)) {
  936.         PICONPOS pip1 = GetICONPOS(((PORDEREDLISTITEM)pItem1), psip),
  937.                  pip2 = GetICONPOS(((PORDEREDLISTITEM)pItem2), psip);
  938.  
  939.         if ((pip1) && (pip2))
  940.             if (pip1 < pip2)
  941.                 return (-1);
  942.             else return (1);
  943.         else if (pip1)
  944.             return (-1);
  945.         else if (pip2)
  946.             return (1);
  947.     }
  948.  
  949.     return (0);
  950. }
  951.  
  952. /*
  953.  * InvalidateOrderedContent:
  954.  *
  955.  */
  956.  
  957. BOOL InvalidateOrderedContent(XFolderData *somThis)
  958. {
  959.     BOOL brc = FALSE;
  960.  
  961.     if (_hmtxOrderedContent == NULLHANDLE) {
  962.         DosCreateMutexSem(NULL, // unnamed
  963.             &(_hmtxOrderedContent),
  964.             0,                  // unshared
  965.             FALSE);             // unowned
  966.     }
  967.  
  968.     if (_pliOrderedContentFirst)
  969.     {
  970.         BOOL fSemOwned = FALSE;
  971.         TRY_LOUD(excpt1)
  972.         {
  973.             fSemOwned = (DosRequestMutexSem(_hmtxOrderedContent, 4000) == NO_ERROR);
  974.  
  975.             if (fSemOwned)
  976.                 lstClear((PLISTITEM*)&(_pliOrderedContentFirst),
  977.                          (PLISTITEM*)&(_pliOrderedContentLast));
  978.             else
  979.                 _Pmpf(("Could not request sem, InvalidateOrderedContent"));
  980.  
  981.             brc = TRUE;
  982.         }
  983.         CATCH(excpt1) { } END_CATCH;
  984.  
  985.         if (fSemOwned) {
  986.             DosReleaseMutexSem(_hmtxOrderedContent);
  987.             fSemOwned = FALSE;
  988.         }
  989.     }
  990.     return (brc);
  991. }
  992.  
  993. /*
  994.  *@@ xfInvalidateOrderedContent:
  995.  *           this deletes the ordered content list so that it will
  996.  *           be rebuilt when it's needed. This is necessary if
  997.  *           objects in the folder have changed.
  998.  */
  999.  
  1000. SOM_Scope BOOL  SOMLINK xf_xfInvalidateOrderedContent(XFolder *somSelf)
  1001. {
  1002.     XFolderData *somThis = XFolderGetData(somSelf);
  1003.     XFolderMethodDebug("XFolder","xf_xfInvalidateOrderedContent");
  1004.  
  1005.     return (InvalidateOrderedContent(somThis));
  1006. }
  1007.  
  1008. /*
  1009.  * UpdateOrderedContent:
  1010.  *      this is called by the xfUpdateOrderedContent method
  1011.  *      just below. We needed to extract this code because
  1012.  *      it is accessed from xfQueryOrderedContent without
  1013.  *      the semaphore handling.
  1014.  */
  1015.  
  1016. BOOL UpdateOrderedContent(XFolder *somSelf, XFolderData *somThis, BOOL fReqSem)
  1017. {
  1018.     BOOL                 brc = FALSE;
  1019.     PORDEREDLISTITEM     poliNew;
  1020.     PEABINDING           peab;
  1021.     WPObject             *pObj;
  1022.     SORTBYICONPOS        sip;
  1023.     ULONG                ulrc;
  1024.  
  1025.     BOOL fSemOwned = FALSE;
  1026.  
  1027.     if (_hmtxOrderedContent == NULLHANDLE) {
  1028.         DosCreateMutexSem(NULL, // unnamed
  1029.             &(_hmtxOrderedContent),
  1030.             0,                  // unshared
  1031.             FALSE);             // unowned
  1032.     }
  1033.  
  1034.     TRY_LOUD(excpt1)
  1035.     {
  1036.         if (fReqSem)
  1037.             fSemOwned = (DosRequestMutexSem(_hmtxOrderedContent, 4000) == NO_ERROR);
  1038.  
  1039.         if ((fSemOwned) || (!fReqSem))
  1040.         {
  1041.             // first clean up
  1042.             if (_pliOrderedContentFirst)
  1043.                 lstClear((PLISTITEM*)&(_pliOrderedContentFirst),
  1044.                          (PLISTITEM*)&(_pliOrderedContentLast));
  1045.  
  1046.             if (_pICONPOS)
  1047.             {
  1048.                 _wpFreeMem(somSelf, _pICONPOS);
  1049.                 _pICONPOS = NULL;
  1050.             }
  1051.  
  1052.             // build new list:
  1053.  
  1054.             // get the folder's content as the WPS delivers it.
  1055.             // This is unsorted. Apparently, the WPS returns items
  1056.             // in the following order:
  1057.             // a)   first: file-system objects in the order returned
  1058.             //      by the file system (i.e. alphabetically on HPFS)
  1059.             // b)   then all abstract objects in the order they were
  1060.             //      placed in this folder.
  1061.  
  1062.             for (   pObj = _wpQueryContent(somSelf, NULL, (ULONG)QC_FIRST);
  1063.                     (pObj);
  1064.                     pObj = _wpQueryContent(somSelf, pObj, (ULONG)QC_NEXT)
  1065.                 )
  1066.             {
  1067.                 poliNew = malloc(sizeof(ORDEREDLISTITEM));
  1068.                 poliNew->pObj = pObj;
  1069.  
  1070.                 // Each ICONPOS struct's identity string has the following format:
  1071.                 // <class>:<t><identity>
  1072.                 // with: <class> being the class of the object
  1073.                 //       <t> == A for abstracts, D for folders, F for files
  1074.                 //       <identity> for abstract objects: the handle
  1075.                 //                  for file-system objects: the filename
  1076.  
  1077.                 // now create the identity string for the search object
  1078.                 if (_somIsA(pObj, _WPAbstract)) {
  1079.                     // for abstract objects, this is the low word
  1080.                     // of the object handle
  1081.                     HOBJECT hobjSearch = _wpQueryHandle(pObj);
  1082.                     sprintf(poliNew->szIdentity, ":A%lX", (hobjSearch & 0xFFFF));
  1083.                 } else {
  1084.                     // for file-system objects, this is the object's real name
  1085.                     ULONG   ulSize = sizeof(poliNew->szIdentity)-2;
  1086.                     if (_somIsA(pObj, _WPFolder))
  1087.                         strcpy(poliNew->szIdentity, ":D");
  1088.                     else
  1089.                         strcpy(poliNew->szIdentity, ":F");
  1090.                     // append real name
  1091.                     _wpQueryRealName(pObj, (poliNew->szIdentity)+2, &ulSize, FALSE);
  1092.                 }
  1093.  
  1094.                 lstAppendItem((PLISTITEM*)&(_pliOrderedContentFirst),
  1095.                          (PLISTITEM*)&(_pliOrderedContentLast),
  1096.                          (PLISTITEM)poliNew);
  1097.             }
  1098.  
  1099.             // read .ICONPOS extended attributes of this folder
  1100.             _wpQueryFilename(somSelf, sip.szRealName, TRUE);
  1101.             if (peab = eaPathReadOneByName(sip.szRealName, ".ICONPOS"))
  1102.             {
  1103.                 //  typedef struct
  1104.                 //  {
  1105.                 //    BYTE bFlags;
  1106.                 //    BYTE bNameLength;
  1107.                 //    USHORT usValueLength;
  1108.                 //    PSZ pszName;
  1109.                 //    PSZ pszValue;
  1110.                 //  } EABINDING, *PEABINDING;
  1111.  
  1112.                 _pICONPOS = _wpAllocMem(somSelf, peab->usValueLength+100, &ulrc);
  1113.  
  1114.                 if (_pICONPOS) {
  1115.                     memcpy(_pICONPOS, peab->pszValue+4, peab->usValueLength-3);
  1116.                     _ulICONPOSSize = (peab->usValueLength)-5;
  1117.                     eaFreeBinding(peab);
  1118.  
  1119.                     // finally, we have the ICONPOS data in _pICONPOS;
  1120.                     // now we pass the ICONPOS data to the sort function
  1121.                     // defined above
  1122.  
  1123.                     #ifdef DEBUG_ORDEREDLIST
  1124.                         _Pmpf(("  Sorting..."));
  1125.                     #endif
  1126.  
  1127.                     sip.pICONPOS = _pICONPOS;
  1128.                     sip.usICONPOSSize = _ulICONPOSSize;
  1129.  
  1130.                     lstQuickSort((PLISTITEM*)&(_pliOrderedContentFirst),
  1131.                              (PLISTITEM*)&(_pliOrderedContentLast),
  1132.                              fnSortByICONPOS,
  1133.                              &sip);
  1134.  
  1135.                 }
  1136.             }
  1137.  
  1138.             brc = TRUE;
  1139.         } else
  1140.             _Pmpf(("Could not request sem, UpdateOrderedContent, Req: %d, hmtx: 0x%lX",
  1141.                             fReqSem,
  1142.                             _hmtxOrderedContent));
  1143.     }
  1144.     CATCH(excpt1) { } END_CATCH;
  1145.  
  1146.     if (fSemOwned) {
  1147.         DosReleaseMutexSem(_hmtxOrderedContent);
  1148.         fSemOwned = FALSE;
  1149.     }
  1150.  
  1151.     return (brc);
  1152. }
  1153.  
  1154. /*
  1155.  *@@ xfUpdateOrderedContent:
  1156.  *           this new instance methods builds or updates a list of the
  1157.  *           folder contents in memory. The root of the list is saved
  1158.  *           in the folder instance data.
  1159.  *
  1160.  *           This method is called by XFolder::xfQueryOrderedContent if the
  1161.  *           list in memory has not been built yet. You do not need to call this
  1162.  *           method manually.
  1163.  */
  1164.  
  1165. SOM_Scope BOOL  SOMLINK xf_xfUpdateOrderedContent(XFolder *somSelf)
  1166. {
  1167.     BOOL            fSemOwned = FALSE;
  1168.  
  1169.     XFolderData *somThis = XFolderGetData(somSelf);
  1170.     XFolderMethodDebug("XFolder","xf_xfUpdateOrderedContent");
  1171.  
  1172.     #ifdef DEBUG_ORDEREDLIST
  1173.         _Pmpf(("Entering xf_xfUpdateOrderedContent for %s", _wpQueryTitle(somSelf) ));
  1174.     #endif
  1175.  
  1176.     return (UpdateOrderedContent(somSelf, somThis,
  1177.             TRUE)); // request semaphore
  1178. }
  1179.  
  1180. /*
  1181.  *@@ xfQueryOrderedContent:
  1182.  *           this new instance method has the same parameters als wpQueryContent,
  1183.  *           but it returns items from the list built by
  1184.  *           XFolder::xfUpdateOrderedContent.
  1185.  *
  1186.  *           As opposed to the list returned by wpQueryContent, the objects
  1187.  *           in this list are in the same order as in the name or details views,
  1188.  *           because the list is built according to the .ICONPOS EAs.
  1189.  */
  1190.  
  1191. SOM_Scope WPObject*  SOMLINK xf_xfQueryOrderedContent(XFolder *somSelf,
  1192.                                                          WPObject* Object,
  1193.                                                          ULONG ulOption)
  1194. {
  1195.     WPObject                    *pobjReturn = NULL;
  1196.     PORDEREDLISTITEM            poli;
  1197.     BOOL                        fSemOwned = FALSE;
  1198.  
  1199.     XFolderData *somThis = XFolderGetData(somSelf);
  1200.     XFolderMethodDebug("XFolder","xf_xfQueryOrderedContent");
  1201.  
  1202.     #ifdef DEBUG_ORDEREDLIST
  1203.         _Pmpf(("xfQueryOrderedContent for %s, ulOption: %d",
  1204.                 _wpQueryTitle(somSelf),
  1205.                 ulOption));
  1206.     #endif
  1207.  
  1208.     xwpsCheckIfPopulated(somSelf);
  1209.  
  1210.     if (    (ulOption == QC_FIRST)
  1211.          && (_pliOrderedContentFirst == NULL)
  1212.        )
  1213.     {
  1214.         UpdateOrderedContent(somSelf, somThis,
  1215.                 TRUE); // request semaphore
  1216.     }
  1217.  
  1218.     TRY_LOUD(excpt1)
  1219.     {
  1220.         if (_pliOrderedContentFirst)
  1221.         {
  1222.             fSemOwned = (DosRequestMutexSem(_hmtxOrderedContent, 4000) == NO_ERROR);
  1223.             if (fSemOwned)
  1224.             {
  1225.                 poli = _pliOrderedContentFirst;
  1226.                 if (poli) {
  1227.                     switch (ulOption) {
  1228.                         case QC_FIRST: {
  1229.                             #ifdef DEBUG_ORDEREDLIST
  1230.                                 _Pmpf(("  returning first"));
  1231.                             #endif
  1232.                             pobjReturn = poli->pObj;
  1233.                         break; }
  1234.  
  1235.                         case QC_NEXT: {
  1236.                             while (poli)
  1237.                                 if (poli->pObj == Object)
  1238.                                 {
  1239.                                     BOOL fValid = TRUE;
  1240.                                     #ifdef DEBUG_ORDEREDLIST
  1241.                                         _Pmpf(("  found just-before"));
  1242.                                         _Pmpf(("    Title: %s",
  1243.                                                 _wpQueryTitle(poli->pObj) ));
  1244.                                     #endif
  1245.                                     if (poli->pNext) {
  1246.                                         pobjReturn = (poli->pNext->pObj);
  1247.  
  1248.                                         // check validity of object
  1249.                                         fValid = xwpsCheckObject(pobjReturn);
  1250.                                         if (fValid)
  1251.                                             fValid = (_wpQueryTitle(pobjReturn) != NULL);
  1252.  
  1253.                                     }
  1254.  
  1255.                                     if (fValid) {
  1256.                                         #ifdef DEBUG_ORDEREDLIST
  1257.                                             _Pmpf(("  found valid next"));
  1258.                                             if (pobjReturn)
  1259.                                                 _Pmpf(("    Title: %s",
  1260.                                                     _wpQueryTitle(pobjReturn) ));
  1261.                                             else
  1262.                                                 _Pmpf(("    NULL"));
  1263.                                             _Pmpf(("  Returning."));
  1264.                                         #endif
  1265.                                         break; // while
  1266.                                     } else {
  1267.                                         // invalid object: restart search, since
  1268.                                         // we've changed the list
  1269.                                         #ifdef DEBUG_ORDEREDLIST
  1270.                                             _Pmpf(("  rebuilding list"));
  1271.                                         #endif
  1272.                                         // if the object we found is not a valid SOM object
  1273.                                         // any more, we will delete it from the list
  1274.                                         /* lstRemoveItem((PLISTITEM*)&(_pliOrderedContentFirst),
  1275.                                                  (PLISTITEM*)&(_pliOrderedContentLast),
  1276.                                                  (PLISTITEM)poli,
  1277.                                                  0, 0); // we already have the semaphore
  1278.                                                  */
  1279.  
  1280.                                         UpdateOrderedContent(somSelf, somThis,
  1281.                                                 FALSE);     // we already have the semaphore
  1282.  
  1283.                                         poli = _pliOrderedContentFirst;
  1284.                                     }
  1285.                                 } // end if (poli->pObj == Object)
  1286.                                 else {
  1287.                                     #ifdef DEBUG_ORDEREDLIST
  1288.                                         _Pmpf(("  searching next"));
  1289.                                     #endif
  1290.                                     poli = poli->pNext;
  1291.                                 }
  1292.                         break; }
  1293.                     }
  1294.                 }
  1295.             }
  1296.             else
  1297.                 _Pmpf(("Could not request sem, xfQueryOrderedContent"));
  1298.         }
  1299.         else
  1300.             pobjReturn = _wpQueryContent(somSelf, Object, ulOption);
  1301.     }
  1302.     CATCH(excpt1) { } END_CATCH;
  1303.  
  1304.     if (fSemOwned) {
  1305.         DosReleaseMutexSem(_hmtxOrderedContent);
  1306.         fSemOwned = FALSE;
  1307.     }
  1308.  
  1309.     return (pobjReturn);
  1310. }
  1311.  
  1312. /*
  1313.  *@@ xfBeginProcessOrderedContent:
  1314.  *           this new instance method uses XFolder::xfQueryOrderedContent to open
  1315.  *           all the objects in the given folder. This method returns immediately;
  1316.  *           further processing is done in the background Worker thread.
  1317.  *
  1318.  *           Parameters:
  1319.  *           -- ULONG ulTiming:     the time to wait between starting objects
  1320.  *                                  in milliseconds; if set to 0, this function
  1321.  *                                  will work in "Wait" mode, i.e. the next
  1322.  *                                  object will open the next object only if
  1323.  *                                  the previous one has been closed again
  1324.  *                                  (e.g. for XShutdown folder)
  1325.  *           -- PFNWP pfnwpCallback: a callback routine which will be called on
  1326.  *                                  every object which is started;
  1327.  *           -- ULONG ulCallbackParam: the first parameter to pass to this proc.
  1328.  *
  1329.  *           pfnwpCallback will be passed the following parameters:
  1330.  *           -- HWND  hwnd:     will not be a hwnd, but ulCallbackParam;
  1331.  *           -- ULONG msg:      will contain the current object of the
  1332.  *                              folder on which this mthd is invoked;
  1333.  *                              this must be cast manually to (WPObject*)
  1334.  *           -- MPARAM mp1:     contains the current object count
  1335.  *                              (starting with 1 and increasing for each
  1336.  *                              subsequent object);
  1337.  *           -- MPARAM mp2:     the (constant) number of objects in the folder.
  1338.  *
  1339.  *           This callback func may be used for implementing a progress bar.
  1340.  *           You can use ulCallbackParam for the msg window handle and display
  1341.  *           the progress according to mp1 and mp2; the object title may be
  1342.  *           obtained by calling _wpQueryTitle((WPObject*)msg).
  1343.  *
  1344.  *           After all objects have been processed, the callback will called
  1345.  *           once more with msg == 0 to allow cleaning up. If the folder does
  1346.  *           not contain any objects, callback will only be called this one time.
  1347.  *
  1348.  *           If you're running in "Wait" mode, the callback must return the
  1349.  *           hwnd of the object which you must have opened with wpViewObject,
  1350.  *           so that XFolder can wait for this window to be closed.
  1351.  *
  1352.  *           Note that even though the processing of the folder is done in the
  1353.  *           Worker thread, the callback func is actually called on the main
  1354.  *           (Workplace) thread, so you can create your window there and have
  1355.  *           work done on it without having to worry about thread safety. This
  1356.  *           is implemented because wpViewObject is having problems when not
  1357.  *           being called in the Workplace thread.
  1358.  *
  1359.  *           This method returns a handle which may be used in
  1360.  *           XFolder::xfCancelProcessOrderedContent to abort processing,
  1361.  *           or 0 upon errors.
  1362.  */
  1363.  
  1364. SOM_Scope ULONG  SOMLINK xf_xfBeginProcessOrderedContent(XFolder *somSelf,
  1365.                                                            ULONG ulTiming,
  1366.                                                            PFNWP pfnwpCallback,
  1367.                                                            ULONG ulCallbackParam)
  1368. {
  1369.     PPROCESSCONTENTINFO pPCI;
  1370.     // XFolderData *somThis = XFolderGetData(somSelf);
  1371.     XFolderMethodDebug("XFolder","xf_xfBeginProcessOrderedContent");
  1372.  
  1373.     pPCI = (PPROCESSCONTENTINFO)malloc(sizeof(PROCESSCONTENTINFO));
  1374.  
  1375.     if (pPCI) {
  1376.         pPCI->ulObjectNow = 0;
  1377.         pPCI->ulTiming = ulTiming;
  1378.         pPCI->pfnwpCallback = pfnwpCallback;
  1379.         pPCI->ulCallbackParam = ulCallbackParam;
  1380.         pPCI->fCancelled = FALSE;
  1381.  
  1382.         xthrPostWorkerMsg(WOM_PROCESSORDEREDCONTENT, (MPARAM)somSelf, pPCI);
  1383.  
  1384.         return ((ULONG)pPCI);
  1385.     }
  1386.     return (0);
  1387. }
  1388.  
  1389. /*
  1390.  *@@ xfCancelProcessOrderedContent:
  1391.  *           this method cancels a folder content process started with
  1392.  *           XFolder::xfBeginProcessOrderedContent; hPOC must the handle
  1393.  *           returned by that function.
  1394.  *
  1395.  *           Warning: After folder content processing has finished, hPOC is
  1396.  *           no longer valid, and calling this function then will simply
  1397.  *           crash the WPS. As a result, your callback function MUST keep
  1398.  *           track if hPOC is still valid; after the callback func has been
  1399.  *           called with msg == 0, calling this function is no longer allowed.
  1400.  */
  1401.  
  1402. SOM_Scope BOOL  SOMLINK xf_xfCancelProcessOrderedContent(XFolder *somSelf,
  1403.                                                             ULONG hPOC)
  1404. {
  1405.     // XFolderData *somThis = XFolderGetData(somSelf);
  1406.     XFolderMethodDebug("XFolder","xf_xfCancelProcessOrderedContent");
  1407.  
  1408.     ((PPROCESSCONTENTINFO)hPOC)->fCancelled = TRUE;
  1409.  
  1410.     return (TRUE);
  1411. }
  1412.  
  1413. /*
  1414.  *@@ xfMakeFavoriteFolder:
  1415.  *           if fInsert is TRUE, this folder will be made a "favorite folder",
  1416.  *           i.e. added to all context menus; if FALSE, it will be removed.
  1417.  */
  1418.  
  1419. SOM_Scope ULONG  SOMLINK xf_xfMakeFavoriteFolder(XFolder *somSelf,
  1420.                                                     BOOL fInsert)
  1421. {
  1422.     BOOL    fSemOwned = FALSE;
  1423.     CHAR    szFavoriteFolders[1000] = "";
  1424.     PCONTENTMENULISTITEM pcmli, pFound = NULL;
  1425.  
  1426.     // XFolderData     *somThis = XFolderGetData(somSelf);
  1427.     M_XFolderData   *somThat = M_XFolderGetData(_XFolder);
  1428.  
  1429.     XFolderMethodDebug("XFolder","xf_xfMakeFavoriteFolder");
  1430.  
  1431.     TRY_LOUD(excpt1)
  1432.     {
  1433.         fSemOwned = (DosRequestMutexSem(hmtxFavoriteFolders, 4000) == NO_ERROR);
  1434.         if (fSemOwned)
  1435.         {
  1436.             pcmli = pcmliFavoriteFolders;
  1437.             while (pcmli)
  1438.                 if (pcmli->pFolder == somSelf) {
  1439.                     pFound = pcmli;
  1440.                     break;
  1441.                 } else
  1442.                     pcmli = pcmli->pNext;
  1443.  
  1444.             if (fInsert)
  1445.             {
  1446.                 if (!pFound) {
  1447.                     pcmli = malloc(sizeof(CONTENTMENULISTITEM));
  1448.                     pcmli->pFolder = somSelf;
  1449.                     lstAppendItem((PLISTITEM*)&(pcmliFavoriteFolders), NULL,
  1450.                         (PLISTITEM)pcmli);
  1451.                 }
  1452.             }
  1453.             else
  1454.                 lstRemoveItem((PLISTITEM*)&(pcmliFavoriteFolders), NULL,
  1455.                         (PLISTITEM)pFound);
  1456.  
  1457.             // write list to INI as a string of handles
  1458.             pcmli = pcmliFavoriteFolders;
  1459.             if (pcmli)
  1460.             {
  1461.                 while (pcmli) {
  1462.                     sprintf(szFavoriteFolders+strlen(szFavoriteFolders),
  1463.                         "%lX ", _wpQueryHandle(pcmli->pFolder));
  1464.                     pcmli = pcmli->pNext;
  1465.                 }
  1466.  
  1467.                 PrfWriteProfileString(HINI_USERPROFILE, INIAPP_XFOLDER, INIKEY_FAVORITEFOLDERS,
  1468.                             szFavoriteFolders);
  1469.             } else
  1470.             {
  1471.                 PrfWriteProfileData(HINI_USERPROFILE, INIAPP_XFOLDER, INIKEY_FAVORITEFOLDERS,
  1472.                             NULL, 0);
  1473.             }
  1474.         }
  1475.     }
  1476.     CATCH(excpt1) {} END_CATCH;
  1477.  
  1478.     if (fSemOwned) {
  1479.         DosReleaseMutexSem(hmtxFavoriteFolders);
  1480.         fSemOwned = FALSE;
  1481.     }
  1482.  
  1483.     return 0;
  1484. }
  1485.  
  1486. /*
  1487.  *@@ xfIsFavoriteFolder:
  1488.  *           returns TRUE if somSelf is on the list of "favorite" folders.
  1489.  */
  1490.  
  1491. SOM_Scope BOOL  SOMLINK xf_xfIsFavoriteFolder(XFolder *somSelf)
  1492. {
  1493.     PCONTENTMENULISTITEM pcmli;
  1494.     BOOL                 rc = FALSE,
  1495.                          fSemOwned = FALSE;
  1496.  
  1497.     // XFolderData     *somThis = XFolderGetData(somSelf);
  1498.     M_XFolderData   *somThat = M_XFolderGetData(_XFolder);
  1499.     XFolderMethodDebug("XFolder","xf_xfIsFavoriteFolder");
  1500.  
  1501.     TRY_LOUD(excpt1)
  1502.     {
  1503.         fSemOwned = (DosRequestMutexSem(hmtxFavoriteFolders, 4000) == NO_ERROR);
  1504.         if (fSemOwned)
  1505.         {
  1506.             pcmli = pcmliFavoriteFolders;
  1507.             while (pcmli) {
  1508.                 if (pcmli->pFolder == somSelf) {
  1509.                     rc = TRUE;
  1510.                     break;
  1511.                 } else
  1512.                     pcmli = pcmli->pNext;
  1513.             }
  1514.         }
  1515.     }
  1516.     CATCH(excpt1) { } END_CATCH;
  1517.  
  1518.     if (fSemOwned) {
  1519.         DosReleaseMutexSem(hmtxFavoriteFolders);
  1520.         fSemOwned = FALSE;
  1521.     }
  1522.     return (rc);
  1523. }
  1524.  
  1525. /*
  1526.  *@@ xfSetQuickOpen:
  1527.  *           if fQuickOpen == TRUE, somSelf will automatically be
  1528.  *           populated at WPS bootup.
  1529.  */
  1530.  
  1531. SOM_Scope ULONG  SOMLINK xf_xfSetQuickOpen(XFolder *somSelf,
  1532.                                            BOOL fQuickOpen)
  1533. {
  1534.     BOOL    fSemOwned = FALSE;
  1535.     CHAR    szQuickOpenFolders[1000] = "";
  1536.     PCONTENTMENULISTITEM pcmli, pFound = NULL;
  1537.  
  1538.     // XFolderData     *somThis = XFolderGetData(somSelf);
  1539.     M_XFolderData   *somThat = M_XFolderGetData(_XFolder);
  1540.     XFolderMethodDebug("XFolder","xf_xfSetQuickOpen");
  1541.  
  1542.     TRY_LOUD(excpt1)
  1543.     {
  1544.         fSemOwned = (DosRequestMutexSem(hmtxQuickOpenFolders, 4000) == NO_ERROR);
  1545.         if (fSemOwned)
  1546.         {
  1547.             pcmli = pcmliQuickOpenFolders;
  1548.             while (pcmli)
  1549.                 if (pcmli->pFolder == somSelf) {
  1550.                     pFound = pcmli;
  1551.                     break;
  1552.                 } else
  1553.                     pcmli = pcmli->pNext;
  1554.  
  1555.             if (fQuickOpen)
  1556.             {
  1557.                 if (!pFound) {
  1558.                     pcmli = malloc(sizeof(CONTENTMENULISTITEM));
  1559.                     pcmli->pFolder = somSelf;
  1560.                     lstAppendItem((PLISTITEM*)&(pcmliQuickOpenFolders), NULL,
  1561.                         (PLISTITEM)pcmli);
  1562.                 }
  1563.             }
  1564.             else
  1565.                 lstRemoveItem((PLISTITEM*)&(pcmliQuickOpenFolders), NULL,
  1566.                         (PLISTITEM)pFound);
  1567.  
  1568.             // write list to INI as a string of handles
  1569.             pcmli = pcmliQuickOpenFolders;
  1570.             if (pcmli) {
  1571.                 while (pcmli) {
  1572.                     sprintf(szQuickOpenFolders+strlen(szQuickOpenFolders),
  1573.                         "%lX ", _wpQueryHandle(pcmli->pFolder));
  1574.                     pcmli = pcmli->pNext;
  1575.                 }
  1576.                 PrfWriteProfileString(HINI_USERPROFILE, INIAPP_XFOLDER, INIKEY_QUICKOPENFOLDERS,
  1577.                             szQuickOpenFolders);
  1578.             } else {
  1579.                 PrfWriteProfileData(HINI_USERPROFILE, INIAPP_XFOLDER, INIKEY_QUICKOPENFOLDERS,
  1580.                             NULL, 0);
  1581.             }
  1582.         }
  1583.     }
  1584.     CATCH(excpt1) { } END_CATCH;
  1585.  
  1586.     if (fSemOwned) {
  1587.         DosReleaseMutexSem(hmtxQuickOpenFolders);
  1588.         fSemOwned = FALSE;
  1589.     }
  1590.  
  1591.     return 0;
  1592. }
  1593.  
  1594. /*
  1595.  *@@ xfQueryQuickOpen:
  1596.  *           returns TRUE if somSelf has the QuickOpen feature ON.
  1597.  */
  1598.  
  1599. SOM_Scope BOOL  SOMLINK xf_xfQueryQuickOpen(XFolder *somSelf)
  1600. {
  1601.     PCONTENTMENULISTITEM pcmli;
  1602.     BOOL                 rc = FALSE,
  1603.                          fSemOwned = FALSE;
  1604.  
  1605.     // XFolderData     *somThis = XFolderGetData(somSelf);
  1606.     M_XFolderData   *somThat = M_XFolderGetData(_XFolder);
  1607.     XFolderMethodDebug("XFolder","xf_xfQueryQuickOpen");
  1608.  
  1609.     TRY_LOUD(excpt1)
  1610.     {
  1611.         fSemOwned = (DosRequestMutexSem(hmtxQuickOpenFolders, 4000) == NO_ERROR);
  1612.         if (fSemOwned)
  1613.         {
  1614.             pcmli = pcmliQuickOpenFolders;
  1615.             while (pcmli) {
  1616.                 if (pcmli->pFolder == somSelf) {
  1617.                     rc = TRUE;
  1618.                     break;
  1619.                 } else
  1620.                     pcmli = pcmli->pNext;
  1621.             }
  1622.         }
  1623.     }
  1624.     CATCH(excpt1) { } END_CATCH;
  1625.  
  1626.     if (fSemOwned) {
  1627.         DosReleaseMutexSem(hmtxQuickOpenFolders);
  1628.         fSemOwned = FALSE;
  1629.     }
  1630.  
  1631.     return (rc);
  1632. }
  1633.  
  1634. /*
  1635.  *@@ xfShowStatusBar:
  1636.  *           depending on fShow, this shows or hides the folder status
  1637.  *           bar for a certain folder.
  1638.  *
  1639.  *           Parameters:
  1640.  *           --  psli:      list item of this folder frame from the global
  1641.  *                          linked list (of PSUBCLASSEDLISTITEM's); this
  1642.  *                          item contains the folder frame window handle
  1643.  *           --  fShow:     show / hide flag
  1644.  *
  1645.  *           This func returns the hwnd of the status bar or NULL if calling
  1646.  *           the func was useless, because the status bar was already
  1647.  *           (de)activated.
  1648.  *           Note that this does _not_ change the folder's visibility
  1649.  *           settings, but only shows or hides the status bar "factually"
  1650.  *           by reformatting the folder frame's PM windows.
  1651.  *           This function _must_ be called only from the same thread
  1652.  *           where the folder frame window is running (normally TID 1),
  1653.  *           otherwise the WPS will crash or PM will hang.
  1654.  *
  1655.  *           Because of all this, call XFolder::xfSetStatusBarVisibility
  1656.  *           instead if you wish to change folder status bars. That function
  1657.  *           will do the display also.
  1658.  */
  1659.  
  1660. SOM_Scope HWND  SOMLINK xf_xfShowStatusBar(XFolder *somSelf,
  1661.                                            PVOID psli,
  1662.                                            BOOL fShow)
  1663. {
  1664.     HWND hrc = NULLHANDLE;
  1665.     BOOL fUpdateNotebook = FALSE;
  1666.  
  1667.     CHAR    szFolderPosKey[50];
  1668.     ULONG   ulIni;
  1669.     ULONG   cbIni;
  1670.  
  1671.     XFolderData *somThis = XFolderGetData(somSelf);
  1672.     XFolderMethodDebug("XFolder","xf_xfShowStatusBar");
  1673.  
  1674.     #ifdef DEBUG_STATUSBARS
  1675.         _Pmpf(("xfShowStatusBar %d", fShow));
  1676.     #endif
  1677.  
  1678.     if (psli) {
  1679.         // we had to declare psli as a PVOID because
  1680.         // SOM does not know the PSUBCLASSEDLISTITEM struct;
  1681.         // so we do the conversion per macro
  1682.         #define psli2 ((PSUBCLASSEDLISTITEM)psli)
  1683.         // CHAR szINIKey[50];
  1684.         // HOBJECT hObj = _wpQueryHandle(somSelf);
  1685.         // ULONG ulDummy;
  1686.  
  1687.         if (fShow)
  1688.         {
  1689.             // show status bar
  1690.  
  1691.             if (psli2->hwndStatusBar) { // already activated: update only
  1692.                 WinPostMsg(psli2->hwndStatusBar, STBM_UPDATESTATUSBAR, MPNULL, MPNULL);
  1693.                 // and quit
  1694.             }
  1695.             // else create status bar as a static control
  1696.             // (which will be subclassed below)
  1697.             else if (psli2->hwndStatusBar = WinCreateWindow(
  1698.                             psli2->hwndFrame,        // parent
  1699.                             WC_STATIC,              // wnd class
  1700.                             (cmnQueryNLSStrings())->pszPopulating, // title
  1701.                             (SS_TEXT | DT_LEFT | DT_VCENTER // wnd style flags
  1702.                                 | DT_ERASERECT
  1703.                                 | WS_VISIBLE | WS_CLIPSIBLINGS),
  1704.                             0L, 0L, -1L, -1L,
  1705.                             psli2->hwndFrame,        // owner
  1706.                             HWND_BOTTOM,
  1707.                             0x9001,                 // ID
  1708.                             (PVOID)NULL,
  1709.                             (PVOID)NULL))
  1710.             {
  1711.                 BOOL    fInflate = FALSE;
  1712.                 SWP     swp;
  1713.                 PSZ     pszStatusBarFont = cmnQueryStatusBarSetting(SBS_STATUSBARFONT);
  1714.  
  1715.                 // set up window data (QWL_USER) for status bar
  1716.                 PSTATUSBARDATA psbd = malloc(sizeof(STATUSBARDATA));
  1717.                 psbd->somSelf    = somSelf;
  1718.                 psbd->psli       = psli2;
  1719.                 psbd->idTimer    = 0;
  1720.                 psbd->fDontBroadcast = TRUE;
  1721.                             // prevents broadcasting of WM_PRESPARAMSCHANGED
  1722.                 psbd->fFolderPopulated = FALSE;
  1723.                             // suspends updating until folder is populated;
  1724.                 WinSetWindowULong(psli2->hwndStatusBar, QWL_USER, (ULONG)psbd);
  1725.  
  1726.                 // subclass static control to make it a status bar
  1727.                 psbd->pfnwpStatusBarOriginal = WinSubclassWindow(psli2->hwndStatusBar,
  1728.                         fnwpStatusBar);
  1729.                 WinSetPresParam(psli2->hwndStatusBar, PP_FONTNAMESIZE,
  1730.                      (ULONG)strlen(pszStatusBarFont) + 1, (PVOID)pszStatusBarFont);
  1731.  
  1732.                 // now "inflate" the folder frame window if this is the first
  1733.                 // time that this folder view has been opened with a status bar;
  1734.                 // if we didn't do this, the folder frame would be too small
  1735.                 // for the status bar and scroll bars would appear. We store
  1736.                 // a flag in the folder's instance data for each different view
  1737.                 // that we've inflated the folder frame, so that this happens
  1738.                 // only once per view.
  1739.  
  1740.                 // From wpobject.h:
  1741.                 // #define VIEW_CONTENTS      0x00000001
  1742.                 // #define VIEW_SETTINGS      0x00000002
  1743.                 // #define VIEW_HELP          0x00000004
  1744.                 // #define VIEW_RUNNING       0x00000008
  1745.                 // #define VIEW_DETAILS       0x00000010
  1746.                 // #define VIEW_TREE          0x00000020
  1747.  
  1748.                 sprintf(szFolderPosKey, "%d@XFSB",
  1749.                             _wpQueryHandle(psli2->pRealObject));
  1750.                 cbIni = sizeof(ulIni);
  1751.                 if (PrfQueryProfileData(HINI_USER,
  1752.                             WPINIAPP_FOLDERPOS,     // "PM_Workplace:FolderPos"
  1753.                             szFolderPosKey,
  1754.                             &ulIni,
  1755.                             &cbIni) == FALSE)
  1756.                     ulIni = 0;
  1757.  
  1758.                 if (ulIni & (   (psli2->ulView == OPEN_CONTENTS) ? VIEW_CONTENTS
  1759.                               : (psli2->ulView == OPEN_TREE) ? VIEW_TREE
  1760.                               : VIEW_DETAILS
  1761.                             ))
  1762.                     fInflate = FALSE;
  1763.                 else
  1764.                     fInflate = TRUE;
  1765.  
  1766.                 // _Pmpf(( "Old _ulSBInflatedFrame: %lX", _ulSBInflatedFrame ));
  1767.                 /* if (   (  _ulSBInflatedFrame
  1768.                           & (   (psli2->ulView == OPEN_CONTENTS) ? VIEW_CONTENTS
  1769.                               : (psli2->ulView == OPEN_TREE) ? VIEW_TREE
  1770.                               : VIEW_DETAILS
  1771.                             )
  1772.                    ) == 0) */
  1773.  
  1774.                 // the folder pos entries in OS2.INI have the following
  1775.                 // format:
  1776.                 // <handle>@<view>
  1777.                 // with:
  1778.                 //      handle being the decimal string of the five-digit
  1779.                 //             object handle (2xxxx for abstract objects);
  1780.                 //      key    being some code for the view. I'm not
  1781.                 //             perfectly sure about this, but from my testing
  1782.                 //             I got the following:
  1783.                 //               @10    Icon view folder pos
  1784.                 //               @1010  Tree view folder pos
  1785.                 //               @1020  Details view folder pos
  1786.                 //               @      if any fonts were changed;
  1787.                 //                      might be a WPS bug (?!?)
  1788.  
  1789.                 // so now we check OS2.INI if the key for our view exists
  1790.                 // already, ie. the WPS has already saved a folder pos for
  1791.                 // this folder view
  1792.                 /* sprintf(szFolderPosKey, "%d@%s",
  1793.                             _wpQueryHandle(psli2->pRealObject),
  1794.                             (psli2->ulView == OPEN_CONTENTS) ? "10"
  1795.                             : (psli2->ulView == OPEN_TREE) ? "1010"
  1796.                             : "1020"
  1797.                         );
  1798.                 if (PrfQueryProfileSize(HINI_USER,
  1799.                             WPINIAPP_FOLDERPOS,     // "PM_Workplace:FolderPos"
  1800.                             szFolderPosKey,
  1801.                             &ulDummy)
  1802.                         == FALSE)
  1803.                     // key does not exist: inflate!
  1804.                     fInflate = TRUE;
  1805.                 else
  1806.                     fInflate = FALSE; */
  1807.  
  1808.                 if (fInflate)
  1809.                 {
  1810.                     // this view has not been inflated yet:
  1811.                     // inflate now and set flag for this view
  1812.  
  1813.                     ULONG ulStatusBarHeight = cmnQueryStatusBarHeight();
  1814.                     WinQueryWindowPos(psli2->hwndFrame, &swp);
  1815.                     // inflate folder frame
  1816.                     WinSetWindowPos(psli2->hwndFrame, 0,
  1817.                                 swp.x, (swp.y - ulStatusBarHeight),
  1818.                                 swp.cx, (swp.cy + ulStatusBarHeight),
  1819.                                 SWP_MOVE | SWP_SIZE);
  1820.  
  1821.                     // mark this folder view as "inflated" in OS2.INI
  1822.                     ulIni |= (   (psli2->ulView == OPEN_CONTENTS) ? VIEW_CONTENTS
  1823.                                : (psli2->ulView == OPEN_TREE) ? VIEW_TREE
  1824.                                : VIEW_DETAILS
  1825.                              );
  1826.                     PrfWriteProfileData(HINI_USER,
  1827.                             WPINIAPP_FOLDERPOS,     // "PM_Workplace:FolderPos"
  1828.                             szFolderPosKey,
  1829.                             &ulIni,
  1830.                             sizeof(ulIni));
  1831.  
  1832.                     // finally, set a flag for the subclassed folder frame
  1833.                     // window proc that this folder view needs no additional scrolling
  1834.                     // (this is evaluated in WM_FORMATFRAME msgs)
  1835.                     psli2->fNeedCnrScroll = FALSE;
  1836.                 }
  1837.                 else
  1838.                     // if the folder frame has been inflated already,
  1839.                     // WM_FORMATFRAME _will_ have to scroll the container.
  1840.                     // We do this for icon views only.
  1841.                     if (psli2->ulView == OPEN_CONTENTS)
  1842.                         psli2->fNeedCnrScroll = TRUE;
  1843.  
  1844.                 // enforce reformatting / repaint of frame window
  1845.                 WinSendMsg(psli2->hwndFrame, WM_UPDATEFRAME, (MPARAM)0, MPNULL);
  1846.  
  1847.                 // update status bar contents
  1848.                 WinPostMsg(psli2->hwndStatusBar, STBM_UPDATESTATUSBAR, MPNULL, MPNULL);
  1849.  
  1850.                 hrc = psli2->hwndStatusBar;
  1851.                 fUpdateNotebook = TRUE;
  1852.             }
  1853.         } else {
  1854.             // hide status bar:
  1855.             if (psli2->hwndStatusBar) {
  1856.                 SWP     swp;
  1857.                 HWND    hwndStatus = psli2->hwndStatusBar;
  1858.                 BOOL    fDeflate = FALSE;
  1859.  
  1860.                 psli2->hwndStatusBar = 0;
  1861.                 WinSendMsg(psli2->hwndFrame, WM_UPDATEFRAME, (MPARAM)0, MPNULL);
  1862.                 WinDestroyWindow(hwndStatus);
  1863.  
  1864.                 // decrease the size of the frame window by the status bar height,
  1865.                 // if we did this before
  1866.                 // _Pmpf(( "Old _ulSBInflatedFrame: %lX", _ulSBInflatedFrame ));
  1867.                 /* if ( (  _ulSBInflatedFrame
  1868.                       & (   (psli2->ulView == OPEN_CONTENTS) ? VIEW_CONTENTS
  1869.                           : (psli2->ulView == OPEN_TREE) ? VIEW_TREE
  1870.                           : VIEW_DETAILS
  1871.                         )
  1872.                      ) != 0) */
  1873.                 sprintf(szFolderPosKey, "%d@XFSB",
  1874.                             _wpQueryHandle(psli2->pRealObject));
  1875.                 cbIni = sizeof(ulIni);
  1876.                 if (PrfQueryProfileData(HINI_USER,
  1877.                             WPINIAPP_FOLDERPOS,     // "PM_Workplace:FolderPos"
  1878.                             szFolderPosKey,
  1879.                             &ulIni,
  1880.                             &cbIni) == FALSE)
  1881.                     ulIni = 0;
  1882.  
  1883.                 if (ulIni & (   (psli2->ulView == OPEN_CONTENTS) ? VIEW_CONTENTS
  1884.                               : (psli2->ulView == OPEN_TREE) ? VIEW_TREE
  1885.                               : VIEW_DETAILS
  1886.                             ))
  1887.                     fDeflate = TRUE;
  1888.                 else
  1889.                     fDeflate = TRUE;
  1890.  
  1891.                 if (fDeflate)
  1892.                 {
  1893.                     ULONG ulStatusBarHeight = cmnQueryStatusBarHeight();
  1894.                     WinQueryWindowPos(psli2->hwndFrame, &swp);
  1895.                     WinSetWindowPos(psli2->hwndFrame, 0,
  1896.                                 swp.x, (swp.y + ulStatusBarHeight),
  1897.                                 swp.cx, (swp.cy - ulStatusBarHeight),
  1898.                                 SWP_MOVE | SWP_SIZE);
  1899.  
  1900.                     ulIni &= ~(   (psli2->ulView == OPEN_CONTENTS) ? VIEW_CONTENTS
  1901.                                 : (psli2->ulView == OPEN_TREE) ? VIEW_TREE
  1902.                                 : VIEW_DETAILS
  1903.                               );
  1904.                     PrfWriteProfileData(HINI_USER,
  1905.                             WPINIAPP_FOLDERPOS,     // "PM_Workplace:FolderPos"
  1906.                             szFolderPosKey,
  1907.                             &ulIni,
  1908.                             sizeof(ulIni));
  1909.  
  1910.  
  1911.  
  1912.                     // now unset the "inflated" flag for this view
  1913.                     /* _ulSBInflatedFrame &= ~(    (psli2->ulView == OPEN_CONTENTS) ? VIEW_CONTENTS
  1914.                                               : (psli2->ulView == OPEN_TREE) ? VIEW_TREE
  1915.                                               : VIEW_DETAILS
  1916.                                            );
  1917.                     _wpSaveDeferred(somSelf); */
  1918.                     // _Pmpf(( "New _ulSBInflatedFrame: %lX", _ulSBInflatedFrame ));
  1919.                 }
  1920.  
  1921.                 hrc = psli2->hwndStatusBar;
  1922.                 fUpdateNotebook = TRUE;
  1923.             }
  1924.         }
  1925.     }
  1926.  
  1927.     return (hrc);
  1928. }
  1929.  
  1930. /*
  1931.  * fncbUpdateStatusBars:
  1932.  *      callback func for WOM_UPDATEALLSTATUSBARS in
  1933.  *      XFolder Worker thread (xfdesk.c); should not
  1934.  *      be called directly (it must reside in this file
  1935.  *      to be able to access folder instance data).
  1936.  *      This is called by xf(cls)ForEachOpenView, which also passes
  1937.  *      the parameters to this func.
  1938.  */
  1939.  
  1940. MRESULT EXPENTRY fncbUpdateStatusBars(HWND hwndView,        // folder frame
  1941.                         ULONG ulActivate,
  1942.                                 // 1: show/hide status bars according to
  1943.                                 //    folder/Global settings
  1944.                                 // 2: reformat status bars (e.g. because
  1945.                                 //    fonts have changed)
  1946.                         MPARAM mpView,                      // OPEN_xxx flag
  1947.                         MPARAM mpFolder)                    // folder object
  1948. {
  1949.     MRESULT             mrc = (MPARAM)FALSE;
  1950.  
  1951.     #ifdef DEBUG_STATUSBARS
  1952.         _Pmpf(("fncbUpdateStatusBars ulActivate = %d", ulActivate));
  1953.     #endif
  1954.  
  1955.     if (mpFolder != _wpclsQueryActiveDesktop(_WPDesktop))
  1956.     {
  1957.         PSUBCLASSEDLISTITEM psli = cmnQueryPSLI(hwndView);
  1958.         if (psli)
  1959.         {
  1960.             if (ulActivate == 2) // "update" flag
  1961.                 WinPostMsg(psli->hwndSupplObject,
  1962.                         SOM_ACTIVATESTATUSBAR,
  1963.                         (MPARAM)2,
  1964.                         (MPARAM)hwndView);
  1965.             else {
  1966.                 // show/hide flag:
  1967.                 PGLOBALSETTINGS     pGlobalSettings = cmnQueryGlobalSettings();
  1968.                 XFolderData *somThis = XFolderGetData(mpFolder);
  1969.                 BOOL fVisible = (
  1970.                                 (    (_bStatusBar == STATUSBAR_ON)
  1971.                                   || (    (_bStatusBar == STATUSBAR_DEFAULT)
  1972.                                        && (pGlobalSettings->StatusBar)
  1973.                                      )
  1974.                                 )
  1975.                             &&
  1976.                                 (   (   ((ULONG)mpView == OPEN_CONTENTS)
  1977.                                      && (pGlobalSettings->SBForViews & SBV_ICON)
  1978.                                     )
  1979.                                  || (   ((ULONG)mpView == OPEN_TREE)
  1980.                                      && (pGlobalSettings->SBForViews & SBV_TREE)
  1981.                                     )
  1982.                                  || (   ((ULONG)mpView == OPEN_DETAILS)
  1983.                                      && (pGlobalSettings->SBForViews & SBV_DETAILS)
  1984.                                     )
  1985.                                 )
  1986.                             );
  1987.  
  1988.                 if ( fVisible != (psli->hwndStatusBar != NULLHANDLE) )
  1989.                 {
  1990.                     // visibility changed:
  1991.                     // we now post a message to the folder frame's
  1992.                     // supplementary object window;
  1993.                     // because we cannot mess with the windows on
  1994.                     // the Worker thread, we need to have the
  1995.                     // status bar created/destroyed/changed on the
  1996.                     // folder's thread
  1997.                     WinPostMsg(psli->hwndSupplObject,
  1998.                             SOM_ACTIVATESTATUSBAR,
  1999.                             (MPARAM)( (fVisible) ? 1 : 0 ),      // show or hide
  2000.                             (MPARAM)hwndView);
  2001.                     mrc = (MPARAM)TRUE;
  2002.                 }
  2003.             }
  2004.         }
  2005.     }
  2006.  
  2007.     return (mrc);
  2008. }
  2009.  
  2010. /*
  2011.  *@@ xfSetStatusBarVisibility:
  2012.  *           this new instance method sets the status bar visibility of
  2013.  *           a folder.
  2014.  *           ulVisibility may be:
  2015.  *           -- STATUSBAR_ON:        show status bars
  2016.  *           -- STATUSBAR_OFF:       hide status bars
  2017.  *           -- STATUSBAR_DEFAULT:   use Global Setting for this folder
  2018.  *
  2019.  *           If fUpdate is TRUE, XFolder will have the Worker thread search
  2020.  *           for open folder views and update their frame controls accordingly.
  2021.  *           Otherwise the status bar setting will only be changed internally
  2022.  *           for the next time the folder is opened. Might lead to errors.
  2023.  *           Returns TRUE if successful.
  2024.  */
  2025.  
  2026. SOM_Scope BOOL  SOMLINK xf_xfSetStatusBarVisibility(XFolder *somSelf,
  2027.                                                     ULONG ulVisibility,
  2028.                                                     BOOL fUpdate)
  2029. {
  2030.     XFolderData *somThis = XFolderGetData(somSelf);
  2031.     XFolderMethodDebug("XFolder","xf_xfSetStatusBarVisibility");
  2032.  
  2033.     if (_bStatusBar != ulVisibility) {
  2034.         #ifdef DEBUG_STATUSBARS
  2035.             _Pmpf(( "xfSetStatusBarVisibility: %d", ulVisibility));
  2036.         #endif
  2037.         _bStatusBar = ulVisibility;
  2038.  
  2039.         if (fUpdate) {
  2040.             // update open folder views in Worker thread;
  2041.             // this will call fncbUpdateStatusBars for each
  2042.             // open folder window
  2043.             xthrPostWorkerMsg(WOM_UPDATEALLSTATUSBARS,
  2044.                     (MPARAM)1,      // show/hide flag
  2045.                     MPNULL);
  2046.             // update "XFolder" notebook page, if open
  2047.             ntbUpdateVisiblePage(somSelf, SP_XFOLDER_FLDR);
  2048.         }
  2049.     }
  2050.     return (TRUE);
  2051. }
  2052.  
  2053. /*
  2054.  *@@ xfQueryStatusBarVisibility:
  2055.  *           this new instance method returns the status bar visibility of
  2056.  *           a folder:
  2057.  *           -- STATUSBAR_ON:        status bars visible
  2058.  *           -- STATUSBAR_OFF:       status bars invisible
  2059.  *           -- STATUSBAR_DEFAULT:   Global Setting used for this folder
  2060.  */
  2061.  
  2062. SOM_Scope BOOL  SOMLINK xf_xfQueryStatusBarVisibility(XFolder *somSelf)
  2063. {
  2064.     XFolderData *somThis = XFolderGetData(somSelf);
  2065.     XFolderMethodDebug("XFolder","xf_xfQueryStatusBarVisibility");
  2066.  
  2067.     return (_bStatusBar);
  2068. }
  2069.  
  2070. /*
  2071.  *@@ xfForEachOpenView:
  2072.  *           this instance method goes through all open views of a folder and calls
  2073.  *           pfnwpCallback for each them (as opposed to xfclsForEachOpenView, which
  2074.  *           goes through all open folders on the system).
  2075.  *
  2076.  *           The following params are then passed to pfnwpCallback:
  2077.  *           --   hwnd    HWND       hwndView   the hwnd of the view frame window;
  2078.  *           --   mp1     ULONG      ulView     the view type (as def'd in wpOpen)
  2079.  *           --   mp2     XFolder*   pFolder    somSelf.
  2080.  *
  2081.  *           This method does not return until all views have been processed.
  2082.  *           You might want to call this method in a different thread if the task
  2083.  *           will take long.
  2084.  *           This method returns TRUE if the callback returned TRUE at least once.
  2085.  *           Note on disk objects/root folders: the WPS does not maintain an open
  2086.  *           view list for root folders, but only for the corresponding disk object.
  2087.  *           xfForEachOpenView will call open disk views also, but the callback
  2088.  *           will still be passed the root folder in pFolder!
  2089.  */
  2090.  
  2091. SOM_Scope BOOL  SOMLINK xf_xfForEachOpenView(XFolder *somSelf,
  2092.                                                 ULONG ulMsg,
  2093.                                                 PFNWP pfnwpCallback)
  2094. {
  2095.     BOOL brc = FALSE;
  2096.     WPObject *somSelf2;
  2097.     // XFolderData *somThis = XFolderGetData(somSelf);
  2098.     XFolderMethodDebug("XFolder","xf_xfForEachOpenView");
  2099.  
  2100.     if (_somIsA(somSelf, _WPRootFolder)) {
  2101.         // for disk/root folder views: root folders have no
  2102.         // open view, instead the disk object is registered
  2103.         // to have the open view. Duh. So we need to find
  2104.         // the disk object first
  2105.         somSelf2 = _xfclsQueryDiskObject(_XFldDisk, somSelf);
  2106.     } else
  2107.         somSelf2 = somSelf;
  2108.  
  2109.     if (somSelf2) {
  2110.         if (_wpFindUseItem(somSelf2, USAGE_OPENVIEW, NULL))
  2111.         {   // folder has an open view;
  2112.             // now we go search the open views of the folder and get the
  2113.             // frame handle of the desired view (ulView) */
  2114.             PVIEWITEM   pViewItem;
  2115.             for (pViewItem = _wpFindViewItem(somSelf2, VIEW_ANY, NULL);
  2116.                 pViewItem;
  2117.                 pViewItem = _wpFindViewItem(somSelf2, VIEW_ANY, pViewItem))
  2118.             {
  2119.                 if ((*pfnwpCallback)(
  2120.                         pViewItem->handle,
  2121.                         ulMsg,
  2122.                         (MPARAM)pViewItem->view,
  2123.                         // but even if we have found a disk object
  2124.                         // above, we need to pass it the root folder
  2125.                         // pointer, because otherwise the callback
  2126.                         // might get into trouble
  2127.                         (MPARAM)somSelf)
  2128.                     == (MPARAM)TRUE)
  2129.                 brc = TRUE;
  2130.             } // end for
  2131.         } // end if
  2132.     }
  2133.     return (brc);
  2134. }
  2135.  
  2136. /*
  2137.  * fncbXFolderInitPage:
  2138.  *      "XFolder" page notebook callback function (notebook.c).
  2139.  *      Sets the controls on the page according to a folder's
  2140.  *      instance settings.
  2141.  */
  2142.  
  2143. VOID fncbXFolderInitPage(PVOID pnbi,           // notebook info struct
  2144.                          ULONG ulExtra)        // INIT_* flags (notebook.h)
  2145. {
  2146.     PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
  2147.     PCREATENOTEBOOKPAGE pcnbp = (PCREATENOTEBOOKPAGE)pnbi;
  2148.     XFolderData *somThis = XFolderGetData(pcnbp->somSelf);
  2149.  
  2150.     if (ulExtra & CBI_INIT)
  2151.     {
  2152.         if (pcnbp->pBackup == NULL)
  2153.         {
  2154.             // first call: backup instance data for "Undo" button;
  2155.             // this memory will be freed automatically by the
  2156.             // common notebook window function (notebook.c) when
  2157.             // the notebook page is destroyed
  2158.             pcnbp->pBackup = malloc(sizeof(XFolderData));
  2159.             memcpy(pcnbp->pBackup, somThis, sizeof(XFolderData));
  2160.         }
  2161.     }
  2162.  
  2163.     if (ulExtra & CBI_SET)
  2164.     {
  2165.         winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_FAVORITEFOLDER,
  2166.                 _xfIsFavoriteFolder(pcnbp->somSelf));
  2167.  
  2168.         winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_QUICKOPEN,
  2169.                 _xfQueryQuickOpen(pcnbp->somSelf));
  2170.  
  2171.         winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_SNAPTOGRID,
  2172.                (MPARAM)( (_bSnapToGridAllowed == 2)
  2173.                         ? pGlobalSettings->AddSnapToGridItem
  2174.                         : _bSnapToGridAllowed ));
  2175.         winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_FULLPATH,
  2176.                (MPARAM)( (_bFullPath == 2)
  2177.                         ? pGlobalSettings->FullPath
  2178.                         : _bFullPath ));
  2179.         winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_ACCELERATORS,
  2180.                (MPARAM)( (_bAcceleratorsAllowed == 2)
  2181.                         ? pGlobalSettings->Accelerators
  2182.                         : _bAcceleratorsAllowed ));
  2183.         winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_ENABLESTATUSBAR,
  2184.                (MPARAM)( ( (_bStatusBar == STATUSBAR_DEFAULT)
  2185.                                     ? pGlobalSettings->StatusBar
  2186.                                     : _bStatusBar )
  2187.                          // always uncheck for Desktop
  2188.                          && (pcnbp->somSelf != _wpclsQueryActiveDesktop(_WPDesktop))
  2189.                        ));
  2190.     }
  2191.  
  2192.     if (ulExtra & CBI_ENABLE)
  2193.     {
  2194.         // disable items
  2195.         winhEnableDlgItem(pcnbp->hwndPage, ID_XSDI_ACCELERATORS,
  2196.                     (!(pGlobalSettings->NoSubclassing)));
  2197.         // disable for Desktop
  2198.         winhEnableDlgItem(pcnbp->hwndPage, ID_XSDI_ENABLESTATUSBAR,
  2199.                 (   (pcnbp->somSelf != _wpclsQueryActiveDesktop(_WPDesktop))
  2200.                  && (!(pGlobalSettings->NoSubclassing))
  2201.                 ));
  2202.     }
  2203. }
  2204.  
  2205. /*
  2206.  * fncbXFolderItemChanged:
  2207.  *      "XFolder" page notebook callback function (notebook.c).
  2208.  *      Reacts to changes of any of the dialog controls.
  2209.  */
  2210.  
  2211. MRESULT fncbXFolderItemChanged(PVOID pnbi,  // notebook info
  2212.                 USHORT usItemID, USHORT usNotifyCode,
  2213.                 ULONG ulExtra)      // for checkboxes: contains new state
  2214. {
  2215.     PCREATENOTEBOOKPAGE pcnbp = (PCREATENOTEBOOKPAGE)pnbi;
  2216.     XFolderData *somThis = XFolderGetData(pcnbp->somSelf);
  2217.     BOOL fUpdate = TRUE;
  2218.  
  2219.     switch (usItemID)
  2220.     {
  2221.         case ID_XSDI_SNAPTOGRID:
  2222.             _bSnapToGridAllowed = ulExtra;
  2223.         break;
  2224.  
  2225.         case ID_XSDI_FULLPATH:
  2226.             _bFullPath = ulExtra;
  2227.             _xfUpdateAllFrameWndTitles(pcnbp->somSelf);
  2228.         break;
  2229.  
  2230.         case ID_XSDI_ACCELERATORS:
  2231.             _bAcceleratorsAllowed = ulExtra;
  2232.         break;
  2233.  
  2234.         case ID_XSDI_ENABLESTATUSBAR:
  2235.             _xfSetStatusBarVisibility(pcnbp->somSelf,
  2236.                         ulExtra,
  2237.                         TRUE);  // update open folder views
  2238.         break;
  2239.  
  2240.         case ID_XSDI_FAVORITEFOLDER:
  2241.             _xfMakeFavoriteFolder(pcnbp->somSelf, ulExtra);
  2242.         break;
  2243.  
  2244.         case ID_XSDI_QUICKOPEN:
  2245.             _xfSetQuickOpen(pcnbp->somSelf, ulExtra);
  2246.         break;
  2247.  
  2248.         case DID_UNDO:
  2249.             if (pcnbp->pBackup) {
  2250.                 XFolderData *Backup = (pcnbp->pBackup);
  2251.                 // "Undo" button: restore backed up instance data
  2252.                 _bFullPath = Backup->bFullPath;
  2253.                 _bSnapToGridAllowed = Backup->bSnapToGridAllowed;
  2254.                 _bAcceleratorsAllowed = Backup->bAcceleratorsAllowed;
  2255.                 _xfSetStatusBarVisibility(pcnbp->somSelf,
  2256.                             Backup->bStatusBar,
  2257.                             TRUE);  // update open folder views
  2258.                 // have the page updated by calling the callback above
  2259.                 fncbXFolderInitPage(pcnbp, CBI_SHOW | CBI_ENABLE);
  2260.                 _xfUpdateAllFrameWndTitles(pcnbp->somSelf);
  2261.             }
  2262.         break;
  2263.  
  2264.         case DID_DEFAULT:
  2265.             // "Default" button:
  2266.             _bFullPath = 2;
  2267.             _bSnapToGridAllowed = 2;
  2268.             _bAcceleratorsAllowed = 2;
  2269.             _xfSetStatusBarVisibility(pcnbp->somSelf,
  2270.                         STATUSBAR_DEFAULT,
  2271.                         TRUE);  // update open folder views
  2272.             // have the page updated by calling the callback above
  2273.             fncbXFolderInitPage(pcnbp, CBI_SET | CBI_ENABLE);
  2274.             _xfUpdateAllFrameWndTitles(pcnbp->somSelf);
  2275.         break;
  2276.  
  2277.         default:
  2278.             fUpdate = FALSE;
  2279.         break;
  2280.     }
  2281.  
  2282.     if (fUpdate)
  2283.         _wpSaveDeferred(pcnbp->somSelf);
  2284.  
  2285.     return ((MPARAM)-1);
  2286. }
  2287.  
  2288. /*
  2289.  *@@ xfAddXFolderPages:
  2290.  *           this actually adds the "XFolder" pages into all folder notebooks.
  2291.  */
  2292.  
  2293. SOM_Scope ULONG  SOMLINK xf_xfAddXFolderPages(XFolder *somSelf,
  2294.                                               HWND hwndDlg)
  2295. {
  2296.     PCREATENOTEBOOKPAGE pcnbp = malloc(sizeof(CREATENOTEBOOKPAGE));
  2297.     memset(pcnbp, 0, sizeof(CREATENOTEBOOKPAGE));
  2298.  
  2299.     XFolderMethodDebug("XFolder","xf_xfAddXFolderPages");
  2300.  
  2301.     strcpy(szXFolderVersion, "~XFolder ");
  2302.     strcat(szXFolderVersion, XFOLDER_VERSION);
  2303.  
  2304.     pcnbp->somSelf = somSelf;
  2305.     pcnbp->hwndNotebook = hwndDlg;
  2306.     pcnbp->hmod = NLS_MODULE;
  2307.     pcnbp->ulDlgID = ID_XSD_SETTINGS_FLDR1;
  2308.     pcnbp->ulPageID = SP_XFOLDER_FLDR;
  2309.     pcnbp->fMajorTab = TRUE;
  2310.     pcnbp->pszName = szXFolderVersion;
  2311.     pcnbp->ulDefaultHelpPanel  = ID_XSH_SETTINGS_FLDR1;
  2312.  
  2313.     pcnbp->pfncbInitPage    = fncbXFolderInitPage;
  2314.     pcnbp->pfncbItemChanged = fncbXFolderItemChanged;
  2315.  
  2316.     return (ntbInsertPage(pcnbp));
  2317. }
  2318.  
  2319. /*
  2320.  *@@ wpInitData:
  2321.  *           here XFolder will initialize its instance data
  2322.  */
  2323.  
  2324. SOM_Scope void  SOMLINK xf_wpInitData(XFolder *somSelf)
  2325. {
  2326.     // PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
  2327.     XFolderData *somThis = XFolderGetData(somSelf);
  2328.     XFolderMethodDebug("XFolder","xf_wpInitData");
  2329.  
  2330.     XFolder_parent_WPFolder_wpInitData(somSelf);
  2331.  
  2332.     // set all the instance variables to safe defaults
  2333.     _pliOrderedContentFirst = NULL;
  2334.     _pliOrderedContentLast = NULL;
  2335.     _hmtxOrderedContent = NULLHANDLE;
  2336.     _pICONPOS = NULL;
  2337.     _ulICONPOSSize = 0;
  2338.     _bSnapToGridAllowed = 2;
  2339.     _bFullPath = 2;
  2340.     _bAcceleratorsAllowed = 2;
  2341.     _bStatusBar = STATUSBAR_DEFAULT;
  2342.     _AlwaysSort = SET_DEFAULT;
  2343.     _DefaultSort = SET_DEFAULT;
  2344.     // _ulSBInflatedFrame = 0;
  2345.  
  2346.     _pFldrSortInfo = NULL;
  2347.     _pFldrLongArray = NULL;
  2348.     _pszFldrStrArray = NULL;
  2349.     _pusFldrBackground = NULL;
  2350.     _cbFldrStrArray = 0;
  2351.     _cbFldrLongArray = 0;
  2352.  
  2353.     _pulShowAllInTreeView = NULL;
  2354.  
  2355.     _fUnInitCalled = FALSE;
  2356.     _hwndCnrSaved = NULLHANDLE;
  2357. }
  2358.  
  2359. /*
  2360.  *@@ wpUnInitData:
  2361.  *           clean up when object is deleted or made dormant
  2362.  */
  2363.  
  2364. SOM_Scope void  SOMLINK xf_wpUnInitData(XFolder *somSelf)
  2365. {
  2366.     XFolderData *somThis = XFolderGetData(somSelf);
  2367.     XFolderMethodDebug("XFolder","xf_wpUnInitData");
  2368.  
  2369.     // make sure we only do this once, because we
  2370.     // seem to get called several times sometimes
  2371.     if (!_fUnInitCalled)
  2372.     {
  2373.         _fUnInitCalled = TRUE;
  2374.  
  2375.         if (_pliOrderedContentFirst)
  2376.             InvalidateOrderedContent(somThis);
  2377.  
  2378.         if (_hmtxOrderedContent)
  2379.             DosCloseMutexSem(_hmtxOrderedContent);
  2380.  
  2381.         if (_pICONPOS) {
  2382.             _wpFreeMem(somSelf, _pICONPOS);
  2383.             _pICONPOS = NULL;
  2384.         }
  2385.  
  2386.         XFolder_parent_WPFolder_wpUnInitData(somSelf);
  2387.     }
  2388. }
  2389.  
  2390. /*
  2391.  *@@ wpFree:
  2392.  *           this WPObject method destroys the persistent form of the object
  2393.  *           and then frees the memory that represented that object. For
  2394.  *           WPFolders, this is called when a folder is actually to be
  2395.  *           deleted. We will call the parent method and then also remove
  2396.  *           those darn PMWorkplace:FolderPos entries which the WPS never
  2397.  *           deletes
  2398.  */
  2399.  
  2400. SOM_Scope BOOL  SOMLINK xf_wpFree(XFolder *somSelf)
  2401. {
  2402.     BOOL brc;
  2403.     PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
  2404.     HOBJECT hObj;
  2405.  
  2406.     // XFolderData *somThis = XFolderGetData(somSelf);
  2407.     XFolderMethodDebug("XFolder","xf_wpFree");
  2408.  
  2409.     if (pGlobalSettings->CleanupINIs)
  2410.     {
  2411.         // "clean up INI files": get object handle for
  2412.         // folderpos deletion later. This doesn't hurt
  2413.         // because every folder has a handle once it has
  2414.         // been opened
  2415.         hObj = _wpQueryHandle(somSelf);
  2416.     }
  2417.  
  2418.     // according to WPS docs, the parent method should be called
  2419.     // AFTER additional processing; probably somSelf becomes invalid
  2420.     // after this
  2421.     brc = XFolder_parent_WPFolder_wpFree(somSelf);
  2422.  
  2423.     if (brc)
  2424.         if (pGlobalSettings->CleanupINIs)
  2425.             // have FOLDERPOS entries
  2426.             // deleted by Worker thread; we only pass the
  2427.             // object HANDLE and not somSelf because somSelf
  2428.             // is no longer valid after having called the parent
  2429.             xthrPostWorkerMsg(WOM_DELETEFOLDERPOS,
  2430.                         (MPARAM)hObj, NULL);
  2431.  
  2432.     return (brc);
  2433. }
  2434.  
  2435. /*
  2436.  *@@ wpSetup:
  2437.  *           this instance method is called to allow a
  2438.  *           newly created object to initialize itself.
  2439.  *           XFolder will examine its setup strings here
  2440.  */
  2441.  
  2442. SOM_Scope BOOL  SOMLINK xf_wpSetup(XFolder *somSelf, PSZ pszSetupString)
  2443. {
  2444.     BOOL        rc,
  2445.                 fChanged = FALSE;
  2446.     CHAR        szValue[CCHMAXPATH+1];
  2447.     ULONG       cbValue;
  2448.     USHORT      usDefaultSort, usAlwaysSort;
  2449.  
  2450.     XFolderData *somThis = XFolderGetData(somSelf);
  2451.     XFolderMethodDebug("XFolder","xf_wpSetup");
  2452.  
  2453.     rc = (XFolder_parent_WPFolder_wpSetup(somSelf, pszSetupString));
  2454.  
  2455.     if (rc) {
  2456.         cbValue = sizeof(szValue);
  2457.         if (_wpScanSetupString(somSelf, pszSetupString,
  2458.                     "SNAPTOGRID", szValue, &cbValue))
  2459.         {
  2460.             if (strnicmp(szValue, "NO", 2) == 0)
  2461.                 _bSnapToGridAllowed = 0;
  2462.             else if (strnicmp(szValue, "YES", 3) == 0)
  2463.                 _bSnapToGridAllowed = 1;
  2464.             else if (strnicmp(szValue, "DEFAULT", 7) == 0)
  2465.                 _bSnapToGridAllowed = 2;
  2466.             else if (strnicmp(szValue, "EXEC", 4) == 0)
  2467.                 _xfSnapToGrid(somSelf, FALSE);
  2468.             fChanged = TRUE;
  2469.         }
  2470.  
  2471.         cbValue = sizeof(szValue);
  2472.         if (_wpScanSetupString(somSelf, pszSetupString,
  2473.                     "FULLPATH", szValue, &cbValue))
  2474.         {
  2475.             if (strnicmp(szValue, "NO", 2) == 0)
  2476.                 _bFullPath = 0;
  2477.             else if (strnicmp(szValue, "YES", 3) == 0)
  2478.                 _bFullPath = 1;
  2479.             else if (strnicmp(szValue, "DEFAULT", 7) == 0)
  2480.                 _bFullPath = 2;
  2481.  
  2482.             _xfUpdateAllFrameWndTitles(somSelf);
  2483.             fChanged = TRUE;
  2484.         }
  2485.  
  2486.         cbValue = sizeof(szValue);
  2487.         if (_wpScanSetupString(somSelf, pszSetupString,
  2488.                     "ACCELERATORS", szValue, &cbValue))
  2489.         {
  2490.             if (strnicmp(szValue, "NO", 2) == 0)
  2491.                 _bAcceleratorsAllowed = 0;
  2492.             else if (strnicmp(szValue, "YES", 3) == 0)
  2493.                 _bAcceleratorsAllowed = 1;
  2494.             else if (strnicmp(szValue, "DEFAULT", 7) == 0)
  2495.                 _bAcceleratorsAllowed = 2;
  2496.             fChanged = TRUE;
  2497.         }
  2498.  
  2499.         cbValue = sizeof(szValue);
  2500.         if (_wpScanSetupString(somSelf, pszSetupString,
  2501.                     "FAVORITEFOLDER", szValue, &cbValue))
  2502.         {
  2503.             if (strnicmp(szValue, "NO", 2) == 0)
  2504.                 _xfMakeFavoriteFolder(somSelf, FALSE);
  2505.             else if (strnicmp(szValue, "YES", 3) == 0)
  2506.                 _xfMakeFavoriteFolder(somSelf, TRUE);
  2507.             fChanged = TRUE;
  2508.         }
  2509.  
  2510.         cbValue = sizeof(szValue);
  2511.         if (_wpScanSetupString(somSelf, pszSetupString,
  2512.                     "QUICKOPEN", szValue, &cbValue))
  2513.         {
  2514.             if (strnicmp(szValue, "NO", 2) == 0)
  2515.                 _xfSetQuickOpen(somSelf, FALSE);
  2516.             else if (strnicmp(szValue, "YES", 3) == 0)
  2517.                 _xfSetQuickOpen(somSelf, TRUE);
  2518.             fChanged = TRUE;
  2519.         }
  2520.  
  2521.         if (somSelf != _wpclsQueryActiveDesktop(_WPDesktop))
  2522.         {
  2523.             cbValue = sizeof(szValue);
  2524.             if (_wpScanSetupString(somSelf, pszSetupString,
  2525.                         "STATUSBAR", szValue, &cbValue))
  2526.             {
  2527.                 if (strnicmp(szValue, "NO", 2) == 0)
  2528.                     _bStatusBar = STATUSBAR_OFF;
  2529.                 else if (strnicmp(szValue, "YES", 3) == 0)
  2530.                     _bStatusBar = STATUSBAR_ON;
  2531.                 else if (strnicmp(szValue, "DEFAULT", 7) == 0)
  2532.                     _bStatusBar = STATUSBAR_DEFAULT;
  2533.             }
  2534.             xthrPostWorkerMsg(WOM_UPDATEALLSTATUSBARS,
  2535.                     (MPARAM)1,  // show/hide flag
  2536.                     MPNULL);
  2537.             fChanged = TRUE;
  2538.         }
  2539.  
  2540.         _xfQueryFldrSort(somSelf, &usDefaultSort, &usAlwaysSort);
  2541.  
  2542.         cbValue = sizeof(szValue);
  2543.         if (_wpScanSetupString(somSelf, pszSetupString,
  2544.                     "ALWAYSSORT", szValue, &cbValue))
  2545.         {
  2546.             if (strnicmp(szValue, "NO", 2) == 0)
  2547.                 usAlwaysSort = 0;
  2548.             else if (strnicmp(szValue, "YES", 3) == 0)
  2549.                 usAlwaysSort = 1;
  2550.             else if (strnicmp(szValue, "DEFAULT", 7) == 0)
  2551.                 usAlwaysSort = SET_DEFAULT;
  2552.             _xfSetFldrSort(somSelf, usDefaultSort, usAlwaysSort);
  2553.             fChanged = TRUE;
  2554.         }
  2555.  
  2556.         cbValue = sizeof(szValue);
  2557.         if (_wpScanSetupString(somSelf, pszSetupString,
  2558.                     "DEFAULTSORT", szValue, &cbValue))
  2559.         {
  2560.             LONG lValue;
  2561.             sscanf(szValue, "%d", &lValue);
  2562.             if ( (lValue >=0) && (lValue <= SV_LAST) )
  2563.                 usDefaultSort = lValue;
  2564.             else
  2565.                 usDefaultSort = SET_DEFAULT;
  2566.             _xfSetFldrSort(somSelf, usDefaultSort, usAlwaysSort);
  2567.             fChanged = TRUE;
  2568.         }
  2569.  
  2570.         cbValue = sizeof(szValue);
  2571.         if (_wpScanSetupString(somSelf, pszSetupString,
  2572.                     "SORTNOW", szValue, &cbValue))
  2573.         {
  2574.             LONG lValue;
  2575.             sscanf(szValue, "%d", &lValue);
  2576.             if ( (lValue >=0) && (lValue <= SV_LAST) )
  2577.                 usDefaultSort = lValue;
  2578.             else
  2579.                 usDefaultSort = SET_DEFAULT;
  2580.             _xfclsForEachOpenView(_XFolder, 0, &fncbSortAllViews);
  2581.         }
  2582.  
  2583.         if (fChanged)
  2584.             _wpSaveDeferred(somSelf);
  2585.     }
  2586.     return (rc);
  2587. }
  2588.  
  2589. /*
  2590.  *@@ wpSaveState:
  2591.  *           this instance method is called to allow an
  2592.  *           an object to save its state; XFolder will
  2593.  *           save its instance settings (NB page) here
  2594.  */
  2595.  
  2596. SOM_Scope BOOL  SOMLINK xf_wpSaveState(XFolder *somSelf)
  2597. {
  2598.     XFolderData *somThis = XFolderGetData(somSelf);
  2599.     XFolderMethodDebug("XFolder","xf_wpSaveState");
  2600.  
  2601.     // we will now save all our instance data; in order
  2602.     // not to blow up the EA size too much, we will only
  2603.     // save data which is different from the "transparent"
  2604.     // (i.e. Global) setting
  2605.  
  2606.     if (_bSnapToGridAllowed != 2)
  2607.         _wpSaveLong(somSelf, "XFolder", 1, (ULONG)_bSnapToGridAllowed);
  2608.     if (_bFullPath != 2)
  2609.         _wpSaveLong(somSelf, "XFolder", 2, (ULONG)_bFullPath);
  2610.     if (_bAcceleratorsAllowed != 2)
  2611.         _wpSaveLong(somSelf, "XFolder", 3, (ULONG)_bAcceleratorsAllowed);
  2612.     if (_bStatusBar != STATUSBAR_DEFAULT)
  2613.         _wpSaveLong(somSelf, "XFolder", 4, (ULONG)_bStatusBar);
  2614.     /* if (_ulSBInflatedFrame)
  2615.         _wpSaveLong(somSelf, "XFolder", 5, (ULONG)_ulSBInflatedFrame); */
  2616.     if (_AlwaysSort != SET_DEFAULT)
  2617.         _wpSaveLong(somSelf, "XFolder", 6, (ULONG)_AlwaysSort);
  2618.     if (_DefaultSort != SET_DEFAULT)
  2619.         _wpSaveLong(somSelf, "XFolder", 7, (ULONG)_DefaultSort);
  2620.  
  2621.     return (XFolder_parent_WPFolder_wpSaveState(somSelf));
  2622. }
  2623.  
  2624. /*
  2625.  *@@ wpRestoreState:
  2626.  *           this instance method is called to allow an
  2627.  *           an object to restore its state; XFolder will
  2628.  *           restore its instance settings (NB page) here
  2629.  */
  2630.  
  2631. SOM_Scope BOOL  SOMLINK xf_wpRestoreState(XFolder *somSelf,
  2632.                                              ULONG ulReserved)
  2633. {
  2634.     ULONG   ul;
  2635.     BOOL    brc;
  2636.     XFolderData *somThis = XFolderGetData(somSelf);
  2637.     // XFolderMethodDebug("XFolder","xf_wpRestoreState");
  2638.  
  2639.     #ifdef DEBUG_SOMMETHODS
  2640.         _Pmpf(("XFolder::wpRestoreState for %s", _wpQueryTitle(somSelf) ));
  2641.     #endif
  2642.  
  2643.     // we will now restore all the different XFolder settings
  2644.     // into the instance data; note that if _wpRestoreLong
  2645.     // returns FALSE (i.e. setting not found), we always use
  2646.     // the "transparent" value which makes this folder use
  2647.     // the corresponding Global Setting
  2648.  
  2649.     if (_wpRestoreLong(somSelf, "XFolder", 1, &ul))
  2650.         _bSnapToGridAllowed = (BYTE)ul;
  2651.     else _bSnapToGridAllowed = 2;
  2652.  
  2653.     if (_wpRestoreLong(somSelf, "XFolder", 2, &ul))
  2654.         _bFullPath = (BYTE)ul;
  2655.     else _bFullPath = 2;
  2656.  
  2657.     if (_wpRestoreLong(somSelf, "XFolder", 3, &ul))
  2658.         _bAcceleratorsAllowed = (BYTE)ul;
  2659.     else _bAcceleratorsAllowed = 2;
  2660.  
  2661.     if (_wpRestoreLong(somSelf, "XFolder", 4, &ul))
  2662.         _bStatusBar = (BYTE)ul;
  2663.     else _bStatusBar = STATUSBAR_DEFAULT;
  2664.  
  2665.     /* if (_wpRestoreLong(somSelf, "XFolder", 5, &ul))
  2666.         _ulSBInflatedFrame = (BYTE)ul;
  2667.     else _ulSBInflatedFrame = 0; */
  2668.  
  2669.     if (_wpRestoreLong(somSelf, "XFolder", 6, &ul))
  2670.         _AlwaysSort = (USHORT)ul;
  2671.  
  2672.     if (_wpRestoreLong(somSelf, "XFolder", 7, &ul))
  2673.         _DefaultSort = (USHORT)ul;
  2674.  
  2675.     brc = (XFolder_parent_WPFolder_wpRestoreState(somSelf, ulReserved));
  2676.  
  2677.     #ifdef DEBUG_SOMMETHODS
  2678.         _Pmpf(("  End of XFolder::wpRestoreState"));
  2679.     #endif
  2680.     return (brc);
  2681. }
  2682.  
  2683. /*
  2684.  *@@ wpRestoreLong:
  2685.  *           this instance method restores a 32-bit data
  2686.  *           value from the folder EAs upon object awakening.
  2687.  *           We check the "ulKey" value after having called
  2688.  *           the parent to be able to intercept the pointer
  2689.  *           to certain WPS-internal folder data, which
  2690.  *           we cannot access otherwise. That's a real ugly
  2691.  *           kludge, but there's no other way to get certain
  2692.  *           folder settings. ;-)
  2693.  *           On Warp 4, the WPS queries the
  2694.  *           IDKEY_FDRTREEVIEWCONTENTS key here, which is
  2695.  *           == 1 if the "SHOWALLINTREEVIEW" flag is on.
  2696.  */
  2697.  
  2698. SOM_Scope BOOL  SOMLINK xf_wpRestoreLong(XFolder *somSelf, PSZ pszClass,
  2699.                                          ULONG ulKey, PULONG pulValue)
  2700. {
  2701.     BOOL        brc;
  2702.     XFolderData *somThis = XFolderGetData(somSelf);
  2703.     XFolderMethodDebug("XFolder","xf_wpRestoreLong");
  2704.  
  2705.     brc = XFolder_parent_WPFolder_wpRestoreLong(somSelf, pszClass,
  2706.                                                   ulKey, pulValue);
  2707.  
  2708.     if (strcmp(pszClass, "WPFolder") == 0)
  2709.     {
  2710.         switch (ulKey)
  2711.         {
  2712.             // Warp 4
  2713.             #ifndef IDKEY_FDRTREEVIEWCONTENTS
  2714.                 #define IDKEY_FDRTREEVIEWCONTENTS 2939
  2715.             #endif
  2716.  
  2717.             case IDKEY_FDRTREEVIEWCONTENTS: {
  2718.                 // then the pointer given to this method (pValue) must
  2719.                 // be the pointer to the WPFolder-internal SHOWALLINTREEVIEW
  2720.                 // flag
  2721.                     if (pulValue) {
  2722.                         XFolderData *somThis = XFolderGetData(somSelf);
  2723.                         _pulShowAllInTreeView = pulValue;
  2724.                     }
  2725.             break; }
  2726.  
  2727.             #ifdef DEBUG_RESTOREDATA
  2728.                 default: {
  2729.                     _Pmpf(("Long IDKEY_xxx (%s %d) --> 0x%lX",
  2730.                             pszClass, ulKey,
  2731.                             *pulValue));        // data returned
  2732.                 break; }
  2733.             #endif
  2734.         }
  2735.     }
  2736.     return (brc);
  2737. }
  2738.  
  2739. /*
  2740.  *@@ wpRestoreData:
  2741.  *           this instance method restores binary instance
  2742.  *           data from the folder EAs upon object awakening.
  2743.  *           We check the "ulKey" value after having called
  2744.  *           the parent to be able to intercept the pointer
  2745.  *           to certain WPS-internal folder data, which
  2746.  *           we cannot access otherwise. That's a real ugly
  2747.  *           kludge, but there's no other way to get certain
  2748.  *           folder settings. ;-)
  2749.  *           On Warp 4, the WPS queries lots of sort and
  2750.  *           folder view settings here, whose pointers we
  2751.  *           can store in XFolder's instance data.
  2752.  */
  2753.  
  2754. SOM_Scope BOOL  SOMLINK xf_wpRestoreData(XFolder *somSelf,
  2755.                                             PSZ pszClass, ULONG ulKey,
  2756.                                             PBYTE pValue, PULONG pcbValue)
  2757. {
  2758.     BOOL        brc;
  2759.     ULONG       cbOrigValue = 0;
  2760.     // PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
  2761.     XFolderMethodDebug("XFolder","xf_wpRestoreData");
  2762.  
  2763.     // get the size of the buffer which was given to us
  2764.     if (pValue)
  2765.         // pValue given:
  2766.         cbOrigValue = *pcbValue;
  2767.     // else: caller is requesting the size of the data
  2768.  
  2769.     // always call parent, even for the sort data, or
  2770.     // the WPFolder original gets confused
  2771.     brc = XFolder_parent_WPFolder_wpRestoreData(somSelf, pszClass,
  2772.                                               ulKey, pValue,
  2773.                                               pcbValue);
  2774.  
  2775.     // after we have restored the setting by calling the
  2776.     // default WPFolder method, we check for a few flags
  2777.     // which we might be interested in; we can then store
  2778.     // the pointer to WPS-internal data in XFolder instance
  2779.     // data
  2780.     if (strcmp(pszClass, "WPFolder") == 0)
  2781.     {
  2782.         switch (ulKey)
  2783.         {
  2784.             case IDKEY_FDRSORTINFO:
  2785.             {
  2786.                 // then the pointer given to this method (pValue) must
  2787.                 // be the pointer to the WPFolder-internal FDRSORTINFO
  2788.                 // structure (undocumented, I've declared it in
  2789.                 // xfldr.idl); we store this pointer in the instance
  2790.                 // data so that we can manipulate it later
  2791.                 if (cbOrigValue == sizeof(FDRSORTINFO))
  2792.                 {
  2793.                     if (pValue) {
  2794.                         XFolderData *somThis = XFolderGetData(somSelf);
  2795.                         _pFldrSortInfo = (PFDRSORTINFO)pValue;
  2796.  
  2797.                         if (brc)
  2798.                             // if the parent method has found sort data,
  2799.                             // and the user had set "Always sort" on for
  2800.                             // the folder using the regular WPS "Sort" page,
  2801.                             // we need to update the XFolder sort data, but
  2802.                             // only update this if this hasn't been set
  2803.                             // by wpRestoreState yet; as a result, the
  2804.                             // XFolder sort settings will follow the WPFolder
  2805.                             // sort settings, but can be overridden
  2806.                             if (_AlwaysSort == SET_DEFAULT) // not set yet?
  2807.                                 _AlwaysSort = ((PFDRSORTINFO)pValue)->fAlwaysSort;
  2808.                     }
  2809.                 }
  2810.                 // _Pmpf(("IDKEY_FDRSORTINFO size %d -> %d", cbOrigValue, *pcbValue));
  2811.             break; }
  2812.  
  2813.             case IDKEY_FDRBACKGROUND:       // size: 2 bytes
  2814.                 if (cbOrigValue == 2)
  2815.                 {
  2816.                     if (pValue) {
  2817.                         XFolderData *somThis = XFolderGetData(somSelf);
  2818.                         _pusFldrBackground = (PUSHORT)pValue;
  2819.                     }
  2820.                 }
  2821.             break;
  2822.  
  2823.             case IDKEY_FDRLONGARRAY:        // size: 84 bytes
  2824.             {
  2825.                 XFolderData *somThis = XFolderGetData(somSelf);
  2826.                 // store the size of the data returned in
  2827.                 // folder instance data, in case it is not
  2828.                 // 84 bytes (as it is with Warp 4 fixpak 8)
  2829.                 _cbFldrLongArray = *pcbValue;
  2830.                 if (pValue)
  2831.                     _pFldrLongArray = (PFDRLONGARRAY)pValue;
  2832.             break; }
  2833.  
  2834.             case IDKEY_FDRSTRARRAY:         // size: 400 bytes
  2835.             {
  2836.                 XFolderData *somThis = XFolderGetData(somSelf);
  2837.                 // store the size of the data returned in
  2838.                 // folder instance data, in case it is not
  2839.                 // 400 bytes (as it is with Warp 4 fixpak 8)
  2840.                 _cbFldrStrArray = *pcbValue;
  2841.                 if (pValue)
  2842.                     _pszFldrStrArray = (PSZ)pValue;
  2843.             break; }
  2844.  
  2845.             #ifdef DEBUG_RESTOREDATA
  2846.                 default: {
  2847.                     _Pmpf(("Data IDKEY_xxx (%s %d) size %d -> %d",
  2848.                             pszClass, ulKey,
  2849.                             cbOrigValue,    // size in or 0 if size queried
  2850.                             *pcbValue));    // size out
  2851.                 break; }
  2852.             #endif
  2853.  
  2854.             /*
  2855.              * the following others were queried for G:\root\test
  2856.              * under Warp 4 fixpak 8:
  2857.              */
  2858.  
  2859.             /*
  2860.                 IDKEY_xxx (WPObject 11) size 32 -> 32           WPOBJECT_DATA
  2861.                 IDKEY_xxx (WPObject 12) size 400 -> 400         WPOBJECT_STRINGS
  2862.                 IDKEY_xxx (WPObject 4) size 8 -> 8              ?!?
  2863.                 IDKEY_xxx (WPFolder 2924) size 542 -> 542       IDKEY_CNRBACKGROUND
  2864.                 IDKEY_xxx (WPFolder 2920) size 542 -> 542       IDKEY_FDRINCCLASS
  2865.                 IDKEY_xxx (WPFolder 2925) size 542 -> 542       IDKEY_FDRINCCRITERIA
  2866.                 IDKEY_xxx (WPFolder 2938) size 8 -> 8           IDKEY_FDRGRIDINFO
  2867.  
  2868.             and these under Warp 3, no fixpaks:
  2869.                 IDKEY_xxx (WPObject 11) size 28 -> 28           (+) four bytes less
  2870.                 IDKEY_xxx (WPObject 12) size 400 -> 400         (+)
  2871.                 IDKEY_xxx (WPObject 4) size 8 -> 8              (+)
  2872.                 IDKEY_xxx (WPFolder 2924) size 542 -> 542       (+)
  2873.                 IDKEY_xxx (WPFolder 2920) size 542 -> 542       (+)
  2874.                 IDKEY_xxx (WPFolder 2925) size 542 -> 542       (+)
  2875.                 i.e. the same, except the grid info
  2876.  
  2877.             but if we had a folder background set (Warp 4):
  2878.                 IDKEY_xxx (WPObject 11) size 32 -> 32
  2879.                 IDKEY_xxx (WPObject 12) size 400 -> 400
  2880.                 IDKEY_xxx (WPObject 4) size 8 -> 8
  2881.                 IDKEY_xxx (WPFolder 2924) size 542 -> 542       IDKEY_CNRBACKGROUND
  2882.                 IDKEY_xxx (WPFolder 2920) size 542 -> 542       IDKEY_FDRINCCLASS
  2883.                 IDKEY_xxx (WPFolder 2925) size 542 -> 107       IDKEY_FDRINCCRITERIA
  2884.                 IDKEY_xxx (WPFolder 2920) size 260 -> 260       IDKEY_FDRINCCLASS
  2885.                 IDKEY_xxx (WPFolder 2925) size 260 -> 107       IDKEY_FDRINCCRITERIA
  2886.                 IDKEY_xxx (WPFolder 2925) size 107 -> 107       IDKEY_FDRINCCRITERIA
  2887.                 IDKEY_xxx (WPFolder 2938) size 8 -> 8
  2888.             and on Warp 3:
  2889.                 IDKEY_xxx (WPObject 11) size 28 -> 28
  2890.                 IDKEY_xxx (WPObject 12) size 400 -> 400
  2891.                 IDKEY_xxx (WPObject 4) size 8 -> 8
  2892.                                                             no  IDKEY_CNRBACKGROUND
  2893.                 IDKEY_xxx (WPFolder 2920) size 259 -> 259       IDKEY_FDRINCCLASS
  2894.                 IDKEY_xxx (WPFolder 2925) size 259 -> 178       IDKEY_FDRINCCRITERIA
  2895.                 IDKEY_xxx (WPFolder 2920) size 260 -> 260       IDKEY_FDRINCCLASS
  2896.                 IDKEY_xxx (WPFolder 2925) size 260 -> 178       IDKEY_FDRINCCRITERIA
  2897.                 IDKEY_xxx (WPFolder 2925) size 178 -> 178       IDKEY_FDRINCCRITERIA
  2898.  
  2899.             */
  2900.  
  2901.             /* this is what we got from the "Programme" folder (Warp 4):
  2902.  
  2903.                  Long IDKEY_xxx (WPFileSystem 4) --> 0x0
  2904.                  Data IDKEY_xxx (WPObject 11) size 32 -> 32         WPOBJECT_DATA
  2905.                  Data IDKEY_xxx (WPObject 12) size 400 -> 400       WPOBJECT_STRINGS
  2906.                  Data IDKEY_xxx (WPObject 4) size 8 -> 8            ?!?
  2907.                  Data IDKEY_xxx (WPFolder 2924) size 542 -> 542     IDKEY_CNRBACKGROUND
  2908.                  Strg IDKEY_xxx (WPFolder 2921) --> NULL            IDKEY_FDRINCNAME
  2909.                  Data IDKEY_xxx (WPFolder 2920) size 0 -> 542       IDKEY_FDRINCCLASS
  2910.                  Data IDKEY_xxx (WPFolder 2925) size 0 -> 107       IDKEY_FDRINCCRITERIA
  2911.                  Data IDKEY_xxx (WPFolder 2920) size 0 -> 260       * IDKEY_FDRINCCLASS
  2912.                  Data IDKEY_xxx (WPFolder 2925) size 0 -> 107       * IDKEY_FDRINCCRITERIA
  2913.                  Data IDKEY_xxx (WPFolder 2925) size 107 -> 107     * IDKEY_FDRINCCRITERIA
  2914.                  Strg IDKEY_xxx (WPFolder 2921) -->                 * IDKEY_FDRINCNAME
  2915.                  Data IDKEY_xxx (WPFolder 2938) size 8 -> 8         IDKEY_FDRGRIDINFO
  2916.                  Long IDKEY_xxx (WPFolder 2939) --> 0x0             IDKEY_FDRTREEVIEWCONTENTS
  2917.  
  2918.                  Long IDKEY_xxx (WPFileSystem 4) --> 0x0
  2919.                  Data IDKEY_xxx (WPObject 11) size 32 -> 32
  2920.                  Data IDKEY_xxx (WPObject 12) size 400 -> 400
  2921.                  Data IDKEY_xxx (WPObject 4) size 8 -> 8
  2922.                  Strg IDKEY_xxx (WPFolder 2934) --> F:\OS2\BITMAP\PLASTER.BMP
  2923.                                                                     IDKEY_FDRCNRBACKGROUND
  2924.                  Strg IDKEY_xxx (WPFolder 2921) --> NULL
  2925.                  Data IDKEY_xxx (WPFolder 2920) size 0 -> 259
  2926.                  Data IDKEY_xxx (WPFolder 2925) size 0 -> 107
  2927.                  Data IDKEY_xxx (WPFolder 2920) size 0 -> 260
  2928.                  Data IDKEY_xxx (WPFolder 2925) size 0 -> 107
  2929.                  Data IDKEY_xxx (WPFolder 2925) size 107 -> 107
  2930.                  Strg IDKEY_xxx (WPFolder 2921) --> F:\OS2\BITMAP\PLASTER.BMP
  2931.                                                                     IDKEY_FDRCNRBACKGROUND
  2932.                  Data IDKEY_xxx (WPFolder 2938) size 8 -> 8
  2933.                  Long IDKEY_xxx (WPFolder 2939) --> 0x0             IDKEY_FDRTREEVIEWCONTENTS
  2934.  
  2935.             */
  2936.  
  2937.             /*
  2938.              *  the following are apperently never queried
  2939.              *  (Warp 4 FP 8 German):
  2940.              */
  2941.  
  2942.             /*
  2943.                 case IDKEY_FDRSORTATTRIBS:
  2944.                 case IDKEY_FDRSORTCLASS:
  2945.                 case IDKEY_FDRINVISCOLUMNS:
  2946.                 case IDKEY_FDRCONTENTATTR:
  2947.                 case IDKEY_FDRSNEAKYCOUNT:
  2948.                 case IDKEY_FDRCNRBACKGROUND:
  2949.                 case IDKEY_FDRBKGNDIMAGEFILE:
  2950.             */
  2951.  
  2952.  
  2953.         }   // end switch
  2954.     }
  2955.  
  2956.     return (brc);
  2957. }
  2958.  
  2959. /*
  2960.  *@@ wpAddSettingsPages:
  2961.  *           call xfAddXFolderPages
  2962.  */
  2963.  
  2964. SOM_Scope BOOL  SOMLINK xf_wpAddSettingsPages(XFolder *somSelf,
  2965.                                                  HWND hwndNotebook)
  2966. {
  2967.     BOOL            rc;
  2968.     // PAGEINFO        pi;
  2969.  
  2970.     // XFolderData *somThis = XFolderGetData(somSelf);
  2971.     XFolderMethodDebug("XFolder","xf_wpAddSettingsPages");
  2972.  
  2973.     rc = (XFolder_parent_WPFolder_wpAddSettingsPages(somSelf,
  2974.                                                        hwndNotebook));
  2975.  
  2976.     if (rc)
  2977.         rc = _xfAddXFolderPages(somSelf, hwndNotebook);
  2978.  
  2979.     return (rc);
  2980. }
  2981.  
  2982. /*
  2983.  * fncbSortInitPage:
  2984.  *      "Sort" page notebook callback function (notebook.c).
  2985.  *      Sets the controls on the page.
  2986.  *      The "Sort" callbacks are used both for the folder settings notebook page
  2987.  *      AND the respective "Sort" page in the "Workplace Shell" object, so we
  2988.  *      need to keep instance data and the XFolder Global Settings apart.
  2989.  *      We do this by examining the page ID in the notebook info struct.
  2990.  */
  2991.  
  2992. VOID fncbSortInitPage(PVOID pnbi, ULONG ulExtra)  // notebook info struct
  2993. {
  2994.     PCREATENOTEBOOKPAGE pcnbp = (PCREATENOTEBOOKPAGE)pnbi;
  2995.     PNLSSTRINGS pNLSStrings = cmnQueryNLSStrings();
  2996.     PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
  2997.     HWND        hwndListbox = WinWindowFromID(pcnbp->hwndPage,
  2998.                     ID_XSDI_SORTLISTBOX);
  2999.     XFolderData *somThis = NULL;
  3000.  
  3001.     if (pcnbp->ulPageID == SP_FLDRSORT_FLDR) {
  3002.         // if we're being called from a folder's notebook,
  3003.         // get instance data
  3004.         somThis = XFolderGetData(pcnbp->somSelf);
  3005.  
  3006.         if (ulExtra & CBI_INIT)
  3007.         {
  3008.             if (pcnbp->pBackup == NULL)
  3009.             {
  3010.                 // first call: backup instance data for "Undo" button;
  3011.                 // this memory will be freed automatically by the
  3012.                 // common notebook window function (notebook.c) when
  3013.                 // the notebook page is destroyed
  3014.                 pcnbp->pBackup = malloc(sizeof(XFolderData));
  3015.                 memcpy(pcnbp->pBackup, somThis, sizeof(XFolderData));
  3016.             }
  3017.  
  3018.             // hide the "Enable extended sort" checkbox, which is
  3019.             // only visible in the "Workplace Shell" object
  3020.             WinShowWindow(WinWindowFromID(pcnbp->hwndPage, ID_XSDI_REPLACESORT), FALSE);
  3021.         }
  3022.     }
  3023.  
  3024.     if (ulExtra & CBI_INIT)
  3025.     {
  3026.         WinInsertLboxItem(hwndListbox, LIT_END, pNLSStrings->pszSortByName);
  3027.         WinInsertLboxItem(hwndListbox, LIT_END, pNLSStrings->pszSortByType);
  3028.         WinInsertLboxItem(hwndListbox, LIT_END, pNLSStrings->pszSortByClass);
  3029.         WinInsertLboxItem(hwndListbox, LIT_END, pNLSStrings->pszSortByRealName);
  3030.         WinInsertLboxItem(hwndListbox, LIT_END, pNLSStrings->pszSortBySize);
  3031.         WinInsertLboxItem(hwndListbox, LIT_END, pNLSStrings->pszSortByWriteDate);
  3032.         WinInsertLboxItem(hwndListbox, LIT_END, pNLSStrings->pszSortByAccessDate);
  3033.         WinInsertLboxItem(hwndListbox, LIT_END, pNLSStrings->pszSortByCreationDate);
  3034.         WinInsertLboxItem(hwndListbox, LIT_END, pNLSStrings->pszSortByExt);
  3035.         WinInsertLboxItem(hwndListbox, LIT_END, pNLSStrings->pszSortFoldersFirst);
  3036.     }
  3037.  
  3038.     if (somThis) {
  3039.         // "folder" mode:
  3040.         if (ulExtra & CBI_SET)
  3041.         {
  3042.             winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_ALWAYSSORT,
  3043.                     ALWAYS_SORT);
  3044.             WinSendMsg(hwndListbox,
  3045.                     LM_SELECTITEM,
  3046.                     (MPARAM)DEFAULT_SORT,
  3047.                     (MPARAM)TRUE);
  3048.         }
  3049.     } else {
  3050.         // "global" mode:
  3051.         if (ulExtra & CBI_SET)
  3052.         {
  3053.             winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_REPLACESORT,
  3054.                    pGlobalSettings->ReplaceSort);
  3055.             winhSetDlgItemChecked(pcnbp->hwndPage, ID_XSDI_ALWAYSSORT,
  3056.                    pGlobalSettings->AlwaysSort);
  3057.  
  3058.             WinSendMsg(hwndListbox,
  3059.                     LM_SELECTITEM,
  3060.                     (MPARAM)(pGlobalSettings->DefaultSort),
  3061.                     (MPARAM)TRUE);
  3062.         }
  3063.  
  3064.         if (ulExtra & CBI_ENABLE)
  3065.         {
  3066.             // disable items if extended sorting is off
  3067.             winhEnableDlgItem(pcnbp->hwndPage, ID_XSDI_SORTTEXT,
  3068.                     pGlobalSettings->ReplaceSort);
  3069.             winhEnableDlgItem(pcnbp->hwndPage, ID_XSDI_SORTLISTBOX,
  3070.                     pGlobalSettings->ReplaceSort);
  3071.             winhEnableDlgItem(pcnbp->hwndPage, ID_XSDI_ALWAYSSORT,
  3072.                     pGlobalSettings->ReplaceSort);
  3073.         }
  3074.     }
  3075. }
  3076.  
  3077. /*
  3078.  * fncbSortItemChanged:
  3079.  *      "Sort" page notebook callback function (notebook.c).
  3080.  *      Reacts to changes of any of the dialog controls.
  3081.  *      The "Sort" callbacks are used both for the folder settings notebook page
  3082.  *      AND the respective "Sort" page in the "Workplace Shell" object, so we
  3083.  *      need to keep instance data and the XFolder GLobal Settings apart.
  3084.  */
  3085.  
  3086. MRESULT fncbSortItemChanged(PVOID pnbi,
  3087.                 USHORT usItemID, USHORT usNotifyCode,
  3088.                 ULONG ulExtra)      // for checkboxes: contains new state
  3089. {
  3090.     PCREATENOTEBOOKPAGE pcnbp = (PCREATENOTEBOOKPAGE)pnbi;
  3091.     BOOL fUpdate = TRUE;
  3092.  
  3093.     switch (usItemID) {
  3094.  
  3095.         case ID_XSDI_ALWAYSSORT:
  3096.         case ID_XSDI_SORTLISTBOX: {
  3097.  
  3098.             PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
  3099.             HWND        hwndListbox = WinWindowFromID(pcnbp->hwndPage,
  3100.                             ID_XSDI_SORTLISTBOX);
  3101.             // XFolderData *somThis = NULL;
  3102.  
  3103.             if (pcnbp->ulPageID == SP_FLDRSORT_FLDR) {
  3104.                 // if we're being called from a folder's notebook,
  3105.                 // change instance data
  3106.                 _xfSetFldrSort(pcnbp->somSelf,
  3107.                             // DefaultSort:
  3108.                                 (USHORT)(WinSendMsg(hwndListbox,
  3109.                                         LM_QUERYSELECTION,
  3110.                                         (MPARAM)LIT_CURSOR,
  3111.                                         MPNULL)),
  3112.                             // AlwaysSort:
  3113.                                 (USHORT)(winhIsDlgItemChecked(pcnbp->hwndPage, ID_XSDI_ALWAYSSORT))
  3114.                             );
  3115.             } else {
  3116.                 BOOL bTemp;
  3117.                 pGlobalSettings->ReplaceSort =
  3118.                     winhIsDlgItemChecked(pcnbp->hwndPage, ID_XSDI_REPLACESORT);
  3119.                 pGlobalSettings->DefaultSort =
  3120.                         (BYTE)WinSendMsg(hwndListbox,
  3121.                             LM_QUERYSELECTION,
  3122.                             (MPARAM)LIT_CURSOR,
  3123.                             MPNULL);
  3124.                 bTemp = winhIsDlgItemChecked(pcnbp->hwndPage, ID_XSDI_ALWAYSSORT);
  3125.                 if (bTemp) {
  3126.                     USHORT usDefaultSort, usAlwaysSort;
  3127.                     _xfQueryFldrSort(_wpclsQueryActiveDesktop(_WPDesktop),
  3128.                             &usDefaultSort, &usAlwaysSort);
  3129.                     if (usAlwaysSort != 0)
  3130.                     {
  3131.                         // issue warning that this might also sort the Desktop
  3132.                         if (cmnMessageBoxMsg(pcnbp->hwndPage, 116, 133, MB_YESNO) == MBID_YES)
  3133.                             _xfSetFldrSort(_wpclsQueryActiveDesktop(_WPDesktop),
  3134.                                 usDefaultSort, 0);
  3135.                     }
  3136.                 }
  3137.                 pGlobalSettings->AlwaysSort = bTemp;
  3138.             }
  3139.         break; }
  3140.  
  3141.         case ID_XSDI_REPLACESORT: {
  3142.             PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
  3143.             // "extended sorting on": exists on global page only
  3144.             pGlobalSettings->ReplaceSort = ulExtra;
  3145.             fncbSortInitPage(pnbi, CBI_ENABLE);
  3146.         break; }
  3147.  
  3148.         // control other than listbox:
  3149.         case DID_UNDO:
  3150.             // "Undo" button: restore backed up instance/global data
  3151.             if (pcnbp->ulPageID == SP_FLDRSORT_FLDR) {
  3152.                 // if we're being called from a folder's notebook,
  3153.                 // restore instance data
  3154.                 if (pcnbp->pBackup) {
  3155.                     XFolderData *Backup = (pcnbp->pBackup);
  3156.                     _xfSetFldrSort(pcnbp->somSelf,
  3157.                             Backup->DefaultSort,
  3158.                             Backup->AlwaysSort);
  3159.                 }
  3160.             } else {
  3161.                 // global sort page:
  3162.                  cmnSetDefaultSettings(SP_FLDRSORT_GLOBAL);
  3163.             }
  3164.             fncbSortInitPage(pnbi, CBI_SET | CBI_ENABLE);
  3165.         break;
  3166.  
  3167.         case DID_DEFAULT:
  3168.             // "Default" button:
  3169.             if (pcnbp->ulPageID == SP_FLDRSORT_FLDR) {
  3170.                 _xfSetFldrSort(pcnbp->somSelf, SET_DEFAULT, SET_DEFAULT);
  3171.             } else {
  3172.                 cmnSetDefaultSettings(SP_FLDRSORT_GLOBAL);
  3173.             }
  3174.             fncbSortInitPage(pnbi, CBI_SET | CBI_ENABLE);
  3175.         break;
  3176.  
  3177.         default:
  3178.             fUpdate = FALSE;
  3179.         break;
  3180.     }
  3181.  
  3182.     if (fUpdate) {
  3183.         if (pcnbp->ulPageID == SP_FLDRSORT_FLDR) {
  3184.             _wpSaveDeferred(pcnbp->somSelf);
  3185.             // update our folder only
  3186.             _xfForEachOpenView(pcnbp->somSelf, 0,
  3187.                     &fncbUpdateFolderSorts);
  3188.         } else {
  3189.             cmnStoreGlobalSettings();
  3190.             // update all open folders
  3191.             _xfclsForEachOpenView(_XFolder, 0,
  3192.                     &fncbUpdateFolderSorts);
  3193.         }
  3194.     }
  3195.     return ((MPARAM)-1);
  3196. }
  3197.  
  3198. /*
  3199.  *@@ wpAddFolderSortPage:
  3200.  *           this normally adds the "Sort" page to the folder
  3201.  *           settings notebook; if allowed, we will replace this
  3202.  *           by the new XFolder version of it
  3203.  */
  3204.  
  3205. SOM_Scope ULONG  SOMLINK xf_wpAddFolderSortPage(XFolder *somSelf,
  3206.                                                    HWND hwndNotebook)
  3207. {
  3208.     PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
  3209.     PNLSSTRINGS pNLSStrings = cmnQueryNLSStrings();
  3210.     // XFolderData *somThis = XFolderGetData(somSelf);
  3211.     XFolderMethodDebug("XFolder","xf_wpAddFolderSortPage");
  3212.  
  3213.     if (pGlobalSettings->ReplaceSort)
  3214.     {
  3215.         // extended sorting enabled:
  3216.         // check whether the "sort class" of the folder
  3217.         // is WPFileSystem (which is the default); only
  3218.         // then replace the "Sort" page with ours. Some
  3219.         // WPS extensions define their own Details views,
  3220.         // and we don't want to mess with that
  3221.         if (_wpQueryFldrSortClass(somSelf) == _WPFileSystem)
  3222.         {
  3223.             PCREATENOTEBOOKPAGE pcnbp = malloc(sizeof(CREATENOTEBOOKPAGE));
  3224.             memset(pcnbp, 0, sizeof(CREATENOTEBOOKPAGE));
  3225.  
  3226.             pcnbp->somSelf = somSelf;
  3227.             pcnbp->hwndNotebook = hwndNotebook;
  3228.             pcnbp->hmod = NLS_MODULE;
  3229.             pcnbp->ulDlgID = ID_XSD_SETTINGS_FLDRSORT;
  3230.             pcnbp->fMajorTab = TRUE;
  3231.             pcnbp->pszName = pNLSStrings->pszSort;
  3232.             pcnbp->ulDefaultHelpPanel  = ID_XSH_SETTINGS_FLDRSORT;
  3233.  
  3234.             // mark this page as "instance", because both
  3235.             // the instance settings notebook and the
  3236.             // "Workplace Shell" object use the same
  3237.             // callbacks
  3238.             pcnbp->ulPageID = SP_FLDRSORT_FLDR;
  3239.  
  3240.             pcnbp->pfncbInitPage    = fncbSortInitPage;
  3241.             pcnbp->pfncbItemChanged = fncbSortItemChanged;
  3242.  
  3243.             ntbInsertPage(pcnbp);
  3244.  
  3245.             return (SETTINGS_PAGE_REMOVED);
  3246.         }
  3247.     }
  3248.  
  3249.     return (XFolder_parent_WPFolder_wpAddFolderSortPage(somSelf,
  3250.                                                         hwndNotebook));
  3251. }
  3252.  
  3253. /*
  3254.  *@@ wpFilterPopupMenu:
  3255.  *           this removes default menu entries according to the
  3256.  *           Global Settings.
  3257.  */
  3258.  
  3259. SOM_Scope ULONG  SOMLINK xf_wpFilterPopupMenu(XFolder *somSelf,
  3260.                                                  ULONG ulFlags,
  3261.                                                  HWND hwndCnr,
  3262.                                                  BOOL fMultiSelect)
  3263. {
  3264.     ULONG ulMenuFilter = 0;
  3265.     // XFolderData *somThis = XFolderGetData(somSelf);
  3266.     PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
  3267.     XFolderMethodDebug("XFolder","xf_wpFilterPopupMenu");
  3268.  
  3269.     ulMenuFilter = XFolder_parent_WPFolder_wpFilterPopupMenu(somSelf,
  3270.                                                          ulFlags,
  3271.                                                          hwndCnr,
  3272.                                                          fMultiSelect);
  3273.     #ifdef DEBUG_MENUS
  3274.         _Pmpf(("XFolder::wpFilterPopupMenu parent flags:"));
  3275.         _Pmpf(("  CTXT_CRANOTHER %d", ulMenuFilter & CTXT_CRANOTHER));
  3276.     #endif
  3277.  
  3278.     // now suppress default menu items according to
  3279.     // Global Settings;
  3280.     // the DefaultMenuItems field in pGlobalSettings is
  3281.     // ready-made for this function; the "Workplace Shell"
  3282.     // notebook page for removing menu items sets this field with
  3283.     // the proper CTXT_xxx flags
  3284.     return ((ulMenuFilter)
  3285.             & ~(pGlobalSettings->DefaultMenuItems)
  3286.         );
  3287. }
  3288.  
  3289. /*
  3290.  *@@ wpModifyPopupMenu:
  3291.  *           this routine allows an object to modify a context
  3292.  *           menu. We add the various XFolder menu entries here
  3293.  *           by calling the common XFolder function in menus.c,
  3294.  *           which is also used by the XFldDisk class.
  3295.  */
  3296.  
  3297. SOM_Scope BOOL  SOMLINK xf_wpModifyPopupMenu(XFolder   *somSelf,
  3298.                                                     HWND  hwndMenu,
  3299.                                                     HWND  hwndCnr,
  3300.                                                     ULONG iPosition)
  3301. {
  3302.     BOOL                rc = TRUE;
  3303.     HWND                hwndCnr2 = hwndCnr;
  3304.  
  3305.     // XFolderData *somThis = XFolderGetData(somSelf);
  3306.     XFolderMethodDebug("XFolder","xf_wpModifyPopupMenu");
  3307.  
  3308.     // call parent
  3309.     XFolder_parent_WPFolder_wpModifyPopupMenu(somSelf,hwndMenu,hwndCnr,iPosition);
  3310.  
  3311.     if (hwndCnr == NULLHANDLE)
  3312.     {
  3313.         // bug in Warp 3: if the popup menu is requested
  3314.         // on container whitespace, hwndCnr is passed as
  3315.         // NULLHANDLE; we therefore use this ugly
  3316.         // workaround
  3317.         XFolderData     *somThis = XFolderGetData(somSelf);
  3318.         hwndCnr2 = _hwndCnrSaved;   // set by WM_INITMENU in fnwpSubclassedFolderFrame
  3319.     }
  3320.  
  3321.     // call menu manipulator common to XFolder and XFldDisk (menus.c)
  3322.     rc = mnuModifyPopupMenu(somSelf, hwndMenu, hwndCnr2, iPosition);
  3323.  
  3324.     return (rc);
  3325. }
  3326.  
  3327. /*
  3328.  *@@ wpMenuItemSelected:
  3329.  *           process input when any menu item was selected;
  3330.  *           we do this by calling the common XFolder function
  3331.  *           in menus.c, which is also used by XFldDisk.
  3332.  */
  3333.  
  3334. SOM_Scope BOOL  SOMLINK xf_wpMenuItemSelected(XFolder *somSelf,
  3335.                                                  HWND hwndFrame,
  3336.                                                  ULONG ulMenuId)
  3337. {
  3338.     // XFolderData *somThis = XFolderGetData(somSelf);
  3339.     XFolderMethodDebug("XFolder","xf_wpMenuItemSelected");
  3340.  
  3341.     // call the menu item checker common to XFolder and XFldDisk
  3342.     // (menus.c); this returns TRUE if one of the manipulated
  3343.     // menu items was selected
  3344.     if (mnuMenuItemSelected(somSelf, hwndFrame, ulMenuId))
  3345.         return (TRUE);
  3346.     else
  3347.         // none of our menu items: pass on to parent
  3348.         return (XFolder_parent_WPFolder_wpMenuItemSelected(somSelf, hwndFrame, ulMenuId));
  3349. }
  3350.  
  3351. /*
  3352.  *@@ wpMenuItemHelpSelected:
  3353.  *           display help for a context menu item.
  3354.  */
  3355.  
  3356. SOM_Scope BOOL  SOMLINK xf_wpMenuItemHelpSelected(XFolder *somSelf,
  3357.                                                      ULONG MenuId)
  3358. {
  3359.     // XFolderData *somThis = XFolderGetData(somSelf);
  3360.     XFolderMethodDebug("XFolder","xf_wpMenuItemHelpSelected");
  3361.  
  3362.     // call the common help processor in menus.c;
  3363.     // if this returns TRUE, help was requested for one
  3364.     // of the new menu items
  3365.     if (mnuMenuItemHelpSelected(somSelf, MenuId))
  3366.         return TRUE;
  3367.     else
  3368.         // else: none of our menu items, call default
  3369.         return (XFolder_parent_WPFolder_wpMenuItemHelpSelected(somSelf,
  3370.                                                                MenuId));
  3371. }
  3372.  
  3373. /*
  3374.  *@@ wpOpen:
  3375.  *           this instance method opens a new folder view.
  3376.  *           This is one of the main hooks where the XFolder
  3377.  *           features are inserted into the WPS.
  3378.  *           We call the parent method first (which will create
  3379.  *           the folder window) and then subclass the
  3380.  *           resulting frame window with the new
  3381.  *           fnwpSubclassedFolderFrame window procedure.
  3382.  */
  3383.  
  3384. SOM_Scope HWND  SOMLINK xf_wpOpen(XFolder *somSelf, HWND hwndCnr,
  3385.                                      ULONG ulView, ULONG param)
  3386. {
  3387.     HWND                hwndNewFrame;
  3388.     XFolderMethodDebug("XFolder","xf_wpOpen");
  3389.  
  3390.     // have parent do the window creation
  3391.     hwndNewFrame = XFolder_parent_WPFolder_wpOpen(somSelf, hwndCnr, ulView, param);
  3392.  
  3393.     if (   (ulView == OPEN_CONTENTS)
  3394.         || (ulView == OPEN_TREE)
  3395.         || (ulView == OPEN_DETAILS)
  3396.        )
  3397.     {
  3398.         PSUBCLASSEDLISTITEM    psli;
  3399.         PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
  3400.         XFolderData *somThis = XFolderGetData(somSelf);
  3401.  
  3402.         // subclass the new folder frame window
  3403.         psli = cmnSubclassFolderFrame(hwndNewFrame, somSelf, somSelf, ulView);
  3404.  
  3405.         // change the window title to full path, if allowed
  3406.         if (    (_bFullPath == 1)
  3407.              || ((_bFullPath == 2) && (pGlobalSettings->FullPath))
  3408.            )
  3409.             SetOneFrameWndTitle(somSelf, hwndNewFrame);
  3410.  
  3411.         // add status bar, if allowed:
  3412.         // 1) status bar only if allowed for the current folder
  3413.         if (    (_bStatusBar == STATUSBAR_ON)
  3414.              || (   (_bStatusBar == STATUSBAR_DEFAULT)
  3415.                  && (pGlobalSettings->StatusBar)
  3416.                 )
  3417.            )
  3418.             // 2) no status bar for active Desktop
  3419.             if (somSelf != _wpclsQueryActiveDesktop(_WPDesktop))
  3420.                 // 3) check that subclassed list item is valid
  3421.                 if (psli)
  3422.                     // 4) status bar only if allowed for the current view type
  3423.                     if (    (   (ulView == OPEN_CONTENTS)
  3424.                              && (pGlobalSettings->SBForViews & SBV_ICON)
  3425.                             )
  3426.                          || (   (ulView == OPEN_TREE)
  3427.                              && (pGlobalSettings->SBForViews & SBV_TREE)
  3428.                             )
  3429.                          || (   (ulView == OPEN_DETAILS)
  3430.                              && (pGlobalSettings->SBForViews & SBV_DETAILS)
  3431.                             )
  3432.                         )
  3433.                         _xfShowStatusBar(somSelf, psli, TRUE);
  3434.  
  3435.         // replace sort stuff
  3436.         if (pGlobalSettings->ReplaceSort)
  3437.         {
  3438.             hwndCnr = xwpsQueryCnrFromFrame(hwndNewFrame);
  3439.             if (hwndCnr)
  3440.                 _xfSetCnrSort(somSelf, hwndCnr, FALSE);
  3441.         }
  3442.     }
  3443.  
  3444.     return (hwndNewFrame);
  3445. }
  3446.  
  3447. /*
  3448.  *@@ wpRefresh:
  3449.  *           this method updates a folder; after doing
  3450.  *           this, we will also update the title of the
  3451.  *           window and maybe status bars.
  3452.  */
  3453.  
  3454. SOM_Scope BOOL  SOMLINK xf_wpRefresh(XFolder *somSelf, ULONG ulView,
  3455.                                         PVOID pReserved)
  3456. {
  3457.     BOOL        rc;
  3458.  
  3459.     // XFolderData *somThis = XFolderGetData(somSelf);
  3460.     XFolderMethodDebug("XFolder","xf_wpRefresh");
  3461.  
  3462.     rc = XFolder_parent_WPFolder_wpRefresh(somSelf, ulView, pReserved);
  3463.  
  3464.     _xfForEachOpenView(somSelf,
  3465.                 (ULONG)2,           // update
  3466.                 (PFNWP)fncbUpdateStatusBars);
  3467.  
  3468.     xthrPostWorkerMsg(WOM_REFRESHFOLDERVIEWS, (MPARAM)somSelf, MPNULL);
  3469.  
  3470.     return rc;
  3471. }
  3472.  
  3473. /*
  3474.  *@@ wpSetFldrAttr:
  3475.  *           this sets new container attributes
  3476.  *           (those CV_* flags) for the specified folder view
  3477.  *           (OPEN_CONTENTS, OPEN_TREE, OPEN_DETAILS)
  3478.  */
  3479.  
  3480. SOM_Scope BOOL  SOMLINK xf_wpSetFldrAttr(XFolder *somSelf, ULONG Attr,
  3481.                                          ULONG ulView)
  3482. {
  3483.     XFolderData *somThis = XFolderGetData(somSelf);
  3484.     XFolderMethodDebug("XFolder","xf_wpSetFldrAttr");
  3485.  
  3486.     #ifdef DEBUG_SORT
  3487.     {
  3488.         CHAR szInfo[300] = "";
  3489.         _Pmpf(("wpSetFldrAttr for %s", _wpQueryTitle(somSelf)));
  3490.         if (Attr & CV_ICON)
  3491.             strcpy(szInfo, "CV_ICON ");
  3492.         if (Attr & CV_NAME)
  3493.             strcat(szInfo, "CV_NAME ");
  3494.         if (Attr & CV_TEXT)
  3495.             strcat(szInfo, "CV_TEXT ");
  3496.         if (Attr & CV_TREE)
  3497.             strcat(szInfo, "CV_TREE ");
  3498.         if (Attr & CV_DETAIL)
  3499.             strcat(szInfo, "CV_DETAIL ");
  3500.         if (Attr & CV_MINI)
  3501.             strcat(szInfo, "CV_MINI ");
  3502.         if (Attr & CV_FLOW)
  3503.             strcat(szInfo, "CV_FLOW ");
  3504.         if (Attr & CA_OWNERDRAW)
  3505.             strcat(szInfo, "CA_OWNERDRAW ");
  3506.         if (Attr & CA_OWNERPAINTBACKGROUND)
  3507.             strcat(szInfo, "CA_OWNERPAINTBACKGROUND ");
  3508.  
  3509.         _Pmpf(("  Flags: %s", szInfo));
  3510.     }
  3511.     #endif
  3512.  
  3513.     return (XFolder_parent_WPFolder_wpSetFldrAttr(somSelf, Attr,
  3514.                                                   ulView));
  3515. }
  3516.  
  3517. /*
  3518.  *@@ wpQueryFldrAttr:
  3519.  *           this returns the current container attributes
  3520.  *           (those CV_* flags) for the specified folder view
  3521.  *           (OPEN_CONTENTS, OPEN_TREE, OPEN_DETAILS)
  3522.  */
  3523.  
  3524. SOM_Scope ULONG  SOMLINK xf_wpQueryFldrAttr(XFolder *somSelf,
  3525.                                             ULONG ulView)
  3526. {
  3527.     ULONG ulAttr = 0;
  3528.     // XFolderData *somThis = XFolderGetData(somSelf);
  3529.     XFolderMethodDebug("XFolder","xf_wpQueryFldrAttr");
  3530.  
  3531.     ulAttr = XFolder_parent_WPFolder_wpQueryFldrAttr(somSelf,
  3532.                                                     ulView);
  3533.     #ifdef DEBUG_SORT
  3534.     {
  3535.         CHAR szInfo[300] = "";
  3536.         _Pmpf(("wpQueryFldrAttr for %s", _wpQueryTitle(somSelf)));
  3537.         if (ulAttr & CV_ICON)
  3538.             strcpy(szInfo, "CV_ICON ");
  3539.         if (ulAttr & CV_NAME)
  3540.             strcat(szInfo, "CV_NAME ");
  3541.         if (ulAttr & CV_TEXT)
  3542.             strcat(szInfo, "CV_TEXT ");
  3543.         if (ulAttr & CV_TREE)
  3544.             strcat(szInfo, "CV_TREE ");
  3545.         if (ulAttr & CV_DETAIL)
  3546.             strcat(szInfo, "CV_DETAIL ");
  3547.         if (ulAttr & CV_MINI)
  3548.             strcat(szInfo, "CV_MINI ");
  3549.         if (ulAttr & CV_FLOW)
  3550.             strcat(szInfo, "CV_FLOW ");
  3551.         if (ulAttr & CA_OWNERDRAW)
  3552.             strcat(szInfo, "CA_OWNERDRAW ");
  3553.         if (ulAttr & CA_OWNERPAINTBACKGROUND)
  3554.             strcat(szInfo, "CA_OWNERPAINTBACKGROUND ");
  3555.  
  3556.         _Pmpf(("  Flags: %s", szInfo));
  3557.     }
  3558.     #endif
  3559.  
  3560.     return (ulAttr);
  3561. }
  3562.  
  3563. /*
  3564.  *@@ wpAddToContent:
  3565.  *           this method is overridden to intercept the
  3566.  *           notification of the "Added an object to a folder"
  3567.  *           event for subclasses that define their own folder view.
  3568.  *           The parent must always be called.
  3569.  */
  3570.  
  3571. SOM_Scope BOOL  SOMLINK xf_wpAddToContent(XFolder *somSelf,
  3572.                                              WPObject* Object)
  3573. {
  3574.     // XFolderData *somThis = XFolderGetData(somSelf);
  3575.     XFolderMethodDebug("XFolder","xf_wpAddToContent");
  3576.  
  3577.     #ifdef DEBUG_CNRCONTENT
  3578.          _Pmpf(("wpAddToContent, folder: %s, object: %s",
  3579.              _wpQueryTitle(somSelf),
  3580.              _wpQueryTitle(Object)));
  3581.     #endif
  3582.  
  3583.     return (XFolder_parent_WPFolder_wpAddToContent(somSelf, Object));
  3584. }
  3585.  
  3586. /*
  3587.  *@@ wpDeleteFromContent:
  3588.  *           this method should be overridden to intercept the
  3589.  *           notification of the "Removed an object from a folder"
  3590.  *           event for subclasses that define their own folder view.
  3591.  *           The parent must always be called.
  3592.  */
  3593.  
  3594. SOM_Scope BOOL  SOMLINK xf_wpDeleteFromContent(XFolder *somSelf,
  3595.                                                   WPObject* Object)
  3596. {
  3597.     // XFolderData *somThis = XFolderGetData(somSelf);
  3598.     XFolderMethodDebug("XFolder","xf_wpDeleteFromContent");
  3599.  
  3600.     #ifdef DEBUG_CNRCONTENT
  3601.          _Pmpf(("wpDeleteFromContent, folder: %s, object: %s",
  3602.              _wpQueryTitle(somSelf),
  3603.              _wpQueryTitle(Object)));
  3604.     #endif
  3605.  
  3606.     return (XFolder_parent_WPFolder_wpDeleteFromContent(somSelf,
  3607.                                                         Object));
  3608. }
  3609.  
  3610. /*
  3611.  *@@ wpStoreIconPosData:
  3612.  *           this method is documented only for Warp 4
  3613.  *           (but exists in Warp 3 also, see WPFOLDER.H);
  3614.  *           it is called when an open folder in icon or
  3615.  *           details view is closed.
  3616.  *           The WPS then apparently saves the .ICONPOS
  3617.  *           data to disk; we only override this method to be
  3618.  *           notified that we need to to update our
  3619.  *           icon order data (xfUpdateOrderedContent).
  3620.  */
  3621.  
  3622. SOM_Scope BOOL  SOMLINK xf_wpStoreIconPosData(XFolder *somSelf,
  3623.                                                  PICONPOS pIconPos,
  3624.                                                  ULONG cbSize)
  3625. {
  3626.     BOOL rc;
  3627.  
  3628.     // XFolderData *somThis = XFolderGetData(somSelf);
  3629.     XFolderMethodDebug("XFolder","xf_wpStoreIconPosData");
  3630.  
  3631.     rc =  (XFolder_parent_WPFolder_wpStoreIconPosData(somSelf,
  3632.                                                        pIconPos,
  3633.                                                        cbSize));
  3634.  
  3635.     #ifdef DEBUG_SORT
  3636.         _Pmpf(("wpStoreIconPosData -- pIconPos: 0x%lX, ulSize: 0x%lX",
  3637.             pIconPos, cbSize));
  3638.     #endif
  3639.     xthrPostWorkerMsg(WOM_INVALIDATEORDEREDCONTENT,
  3640.         (MPARAM)somSelf, MPNULL);
  3641.  
  3642.     return (rc);
  3643. }
  3644.  
  3645. /*
  3646.  *@@ wpMoveObject:
  3647.  *           this is called when the folder is moved to a
  3648.  *           different location; we then need to update
  3649.  *           the titles of this folder AND of possibly open
  3650.  *           subfolders with the full path; we pass this
  3651.  *           to the Worker thread
  3652.  */
  3653.  
  3654. SOM_Scope BOOL  SOMLINK xf_wpMoveObject(XFolder *somSelf,
  3655.                                            WPFolder* Folder)
  3656. {
  3657.     BOOL rc;
  3658.  
  3659.     // XFolderData *somThis = XFolderGetData(somSelf);
  3660.     XFolderMethodDebug("XFolder","xf_wpMoveObject");
  3661.  
  3662.     /* call the parent method first, which will actually move the
  3663.        folder */
  3664.     rc = XFolder_parent_WPFolder_wpMoveObject(somSelf, Folder);
  3665.  
  3666.     xthrPostWorkerMsg(WOM_REFRESHFOLDERVIEWS, (MPARAM)somSelf, MPNULL);
  3667.  
  3668.     return rc;
  3669. }
  3670.  
  3671. /*
  3672.  *@@ wpSetTitle:
  3673.  *           this is called when the folder is renamed.
  3674.  *           We then need to update the titles of this
  3675.  *           folder AND of possibly open subfolders with
  3676.  *           the full path; we pass this task to the Worker
  3677.  *           thread, since it may take a while
  3678.  */
  3679.  
  3680. SOM_Scope BOOL  SOMLINK xf_wpSetTitle(XFolder *somSelf, PSZ pszNewTitle)
  3681. {
  3682.     BOOL rc;
  3683.  
  3684.     // XFolderData *somThis = XFolderGetData(somSelf);
  3685.     XFolderMethodDebug("XFolder","xf_wpSetTitle");
  3686.  
  3687.     rc = XFolder_parent_WPFolder_wpSetTitle(somSelf, pszNewTitle);
  3688.  
  3689.     if (_wpFindUseItem(somSelf, USAGE_OPENVIEW, NULL))
  3690.         xthrPostWorkerMsg(WOM_REFRESHFOLDERVIEWS, (MPARAM)somSelf, MPNULL);
  3691.  
  3692.     return (rc);
  3693. }
  3694.  
  3695. /*
  3696.  *@@ wpSetFldrSort:
  3697.  *           apparently, this method normally gets called by the
  3698.  *           WPS every time it tries to sort a folder. That is,
  3699.  *           when one of the "Sort" menu items is selected or when
  3700.  *           the folder is sorted for another reason, e.g. because
  3701.  *           "Always sort" is on and a file in the folder was
  3702.  *           renamed.
  3703.  *
  3704.  *           The WPS ref. says about this method:
  3705.  *           "This instance method sets the sort attributes on
  3706.  *           the folder window and  saves those values in the
  3707.  *           instance data. Note:  This method only rearranges a
  3708.  *           folder open in icon view. If (pSortRecord == NULL),
  3709.  *           the values are reset to the default sort values."
  3710.  *
  3711.  *           However, the description of this method in the WPS
  3712.  *           ref. is complete garbage. The SORTFASTINFO structure
  3713.  *           described there is obviously not used, but some
  3714.  *           undocumented data instead. (I guess that's why IBM
  3715.  *           uses a PVOID here, so they need not apologize.)
  3716.  *           Also, this method rearranges _all_ open folders, not
  3717.  *           just icons views.
  3718.  *
  3719.  *           Anyway, if XFolder extended sorting is enabled,
  3720.  *           we can intercept this method call to prevent the
  3721.  *           WPS from sorting the container. We will then not
  3722.  *           call the default method, but our own one instead.
  3723.  *           Since XFolder completely takes over the other sort
  3724.  *           functions, this method probably only gets called
  3725.  *           when files are renamed any more.
  3726.  */
  3727.  
  3728. SOM_Scope BOOL  SOMLINK xf_wpSetFldrSort(XFolder *somSelf, PVOID pSortRecord,
  3729.                                          ULONG ulView, ULONG ulType)
  3730. {
  3731.     PGLOBALSETTINGS     pGlobalSettings = cmnQueryGlobalSettings();
  3732.  
  3733.     if (pGlobalSettings->ReplaceSort) {
  3734.         HWND hwndFrame = xwpsQueryFrameFromView(somSelf, ulView);
  3735.         if (hwndFrame) {
  3736.             HWND hwndCnr = xwpsQueryCnrFromFrame(hwndFrame);
  3737.             if (hwndCnr) {
  3738.                 _xfSetCnrSort(somSelf, hwndCnr,
  3739.                             TRUE);  // enfore cnr sort
  3740.                 return (TRUE);
  3741.             }
  3742.         }
  3743.     }
  3744.  
  3745.     return (XFolder_parent_WPFolder_wpSetFldrSort(somSelf,
  3746.                                     pSortRecord,
  3747.                                     ulView,
  3748.                                     ulType));
  3749. }
  3750.  
  3751. /*
  3752.  *@@ wpQueryDefaultHelp:
  3753.  *           this instance method specifies the default
  3754.  *           help panel for this instance; XFolder will
  3755.  *           return something different for the
  3756.  *           Config folder and its subfolders.
  3757.  */
  3758.  
  3759. SOM_Scope BOOL  SOMLINK xf_wpQueryDefaultHelp(XFolder *somSelf,
  3760.                                                  PULONG pHelpPanelId,
  3761.                                                  PSZ HelpLibrary)
  3762. {
  3763.     BOOL        rc;
  3764.  
  3765.     // XFolderData *somThis = XFolderGetData(somSelf);
  3766.     XFolderMethodDebug("XFolder","xf_wpQueryDefaultHelp");
  3767.  
  3768.     if (xwpsResidesBelow(somSelf,
  3769.                 _wpclsQueryFolder(_WPFolder, XFOLDER_CONFIGID, TRUE)))
  3770.     {
  3771.         // somSelf is in the config folder hierarchy:
  3772.         // display help for config folders
  3773.         strncpy(HelpLibrary, cmnQueryHelpLibrary(), CCHMAXPATH);
  3774.         *pHelpPanelId = ID_XMH_CONFIGFOLDER;
  3775.         rc = TRUE;
  3776.     } else
  3777.         rc = (XFolder_parent_WPFolder_wpQueryDefaultHelp(somSelf,
  3778.                                                            pHelpPanelId,
  3779.                                                            HelpLibrary));
  3780.  
  3781.     return (rc);
  3782. }
  3783.  
  3784.  
  3785. /* ******************************************************************
  3786.  *                                                                  *
  3787.  *   here come the XFolder class methods                            *
  3788.  *                                                                  *
  3789.  ********************************************************************/
  3790.  
  3791. /*
  3792.  *@@ xfclsForEachOpenView:
  3793.  *           this class method goes through all open folder windows and calls
  3794.  *           pfnwpCallback for each open view of each open folder.
  3795.  *
  3796.  *           The following params will be passed to pfnwpCallback:
  3797.  *           -- hwnd    HWND       hwndView   the hwnd of the view frame window;
  3798.  *           -- mp1     ULONG      ulView     the view type (as def'd in wpOpen)
  3799.  *           -- mp2     XFolder*   pFolder    the currently open folder.
  3800.  *
  3801.  *           This method does not return until all views have been processed.
  3802.  *           You might want to call this method in a different thread if the task
  3803.  *           will take long.
  3804.  */
  3805.  
  3806. SOM_Scope BOOL  SOMLINK xfM_xfclsForEachOpenView(M_XFolder *somSelf,
  3807.                                                     ULONG ulMsg,
  3808.                                                     PFNWP pfnwpCallback)
  3809. {
  3810.     XFolder     *pFolder;
  3811.     // M_XFolderData *somThis = M_XFolderGetData(somSelf);
  3812.     M_XFolderMethodDebug("M_XFolder","xfM_xfclsForEachOpenView");
  3813.  
  3814.     for ( pFolder = _wpclsQueryOpenFolders(somSelf, NULL, QC_FIRST, FALSE);
  3815.           pFolder;
  3816.           pFolder = _wpclsQueryOpenFolders(somSelf, pFolder, QC_NEXT, FALSE))
  3817.     {
  3818.         if (_somIsA(pFolder, _WPFolder))
  3819.         {
  3820.             _xfForEachOpenView(pFolder, ulMsg, pfnwpCallback);
  3821.         }
  3822.     }
  3823.     return TRUE;
  3824. }
  3825.  
  3826. /*
  3827.  *@@ xfclsQueryFavoriteFolder:
  3828.  *           This returns "favorite" folders.
  3829.  *           If pFolder == NULL, the first favorite folder is returned,
  3830.  *           otherwise the favorite folder which comes after pFolder
  3831.  *           in the favorite folder list.
  3832.  *           This returns NULL if no more folders are found.
  3833.  */
  3834.  
  3835. SOM_Scope XFolder*  SOMLINK xfM_xfclsQueryFavoriteFolder(M_XFolder *somSelf,
  3836.                                                             XFolder* pFolder)
  3837. {
  3838.     BOOL        fSemOwned = FALSE;
  3839.     M_XFolderData *somThis = M_XFolderGetData(somSelf);
  3840.     PCONTENTMENULISTITEM    pliFavoriteFolders = pcmliFavoriteFolders,
  3841.                             pItem;
  3842.  
  3843.     M_XFolderMethodDebug("M_XFolder","xfM_xfclsQueryFavoriteFolder");
  3844.  
  3845.     TRY_LOUD(excpt1)
  3846.     {
  3847.         fSemOwned = (DosRequestMutexSem(hmtxFavoriteFolders, 4000) == NO_ERROR);
  3848.         if (fSemOwned)
  3849.         {
  3850.             if (pliFavoriteFolders == NULL)
  3851.             {
  3852.                 // if the list of favorite folders has not yet been built
  3853.                 // in the class data, we will do this now
  3854.                 CHAR        szFavorites[1000], szDummy[1000];
  3855.                 PSZ         pszFavorites;
  3856.                 // ULONG       rc;
  3857.  
  3858.                 PrfQueryProfileString(HINI_USERPROFILE, INIAPP_XFOLDER, INIKEY_FAVORITEFOLDERS,
  3859.                             "", &szFavorites, sizeof(szFavorites));
  3860.                 pszFavorites = szFavorites;
  3861.                 do {
  3862.                     HOBJECT          hObject;
  3863.                     WPFolder         *pFolder2;
  3864.                     sscanf(pszFavorites, "%lX %s", &hObject, &szDummy);
  3865.                     pFolder2 = _wpclsQueryObject(_WPFolder, hObject);
  3866.                     if (pFolder2) {
  3867.                         if (xwpsCheckObject(pFolder2))
  3868.                             if (_somIsA(pFolder2, _WPFolder))
  3869.                             {
  3870.                                  PCONTENTMENULISTITEM pNew = malloc(sizeof(CONTENTMENULISTITEM));
  3871.                                  pNew->pFolder = pFolder2;
  3872.                                  lstAppendItem((PLISTITEM*)&pliFavoriteFolders, NULL,
  3873.                                      (PLISTITEM)pNew);
  3874.                             }
  3875.                     }
  3876.                     pszFavorites += 6;
  3877.                 } while (strlen(pszFavorites) > 0);
  3878.  
  3879.                 pcmliFavoriteFolders = pliFavoriteFolders;
  3880.             }
  3881.  
  3882.             pItem = pliFavoriteFolders;
  3883.             if (pFolder) {
  3884.                 // folder given as param: look for this folder
  3885.                 // and return the following in the list
  3886.                 while (pItem)
  3887.                     if (pItem->pFolder == pFolder) {
  3888.                         pItem = pItem->pNext;
  3889.                         break;
  3890.                     }
  3891.                     else
  3892.                         pItem = pItem->pNext;
  3893.             } // else: pItem == pliFavoriteFolders
  3894.         }
  3895.     }
  3896.     CATCH(excpt1) { } END_CATCH;
  3897.  
  3898.     if (fSemOwned) {
  3899.         DosReleaseMutexSem(hmtxFavoriteFolders);
  3900.         fSemOwned = FALSE;
  3901.     }
  3902.  
  3903.     if (pItem)
  3904.         return (pItem->pFolder);
  3905.     else
  3906.         return (NULL);
  3907. }
  3908.  
  3909. /*
  3910.  *@@ xfclsQueryQuickOpenFolder:
  3911.  *           This returns folders which have the "QuickOpen" flag on.
  3912.  *           If pFolder == NULL, the first such folder is returned,
  3913.  *           otherwise the folder which comes after pFolder
  3914.  *           in the quick-open folder list.
  3915.  *           This returns NULL if no more folders are found.
  3916.  */
  3917.  
  3918. SOM_Scope XFolder*  SOMLINK xfM_xfclsQueryQuickOpenFolder(M_XFolder *somSelf,
  3919.                                                           XFolder* pFolder)
  3920. {
  3921.     BOOL fSemOwned = FALSE;
  3922.     M_XFolderData *somThis = M_XFolderGetData(somSelf);
  3923.     PCONTENTMENULISTITEM    pliQuickOpenFolders = pcmliQuickOpenFolders,
  3924.                             pItem;
  3925.     M_XFolderMethodDebug("M_XFolder","xfM_xfclsQueryQuickOpenFolder");
  3926.  
  3927.     TRY_LOUD(excpt1)
  3928.     {
  3929.         fSemOwned = (DosRequestMutexSem(hmtxQuickOpenFolders, 4000) == NO_ERROR);
  3930.         if (fSemOwned)
  3931.         {
  3932.             if (pliQuickOpenFolders == NULL)
  3933.             {
  3934.                 // if the list of QuickOpen folders has not yet been built
  3935.                 // in the class data, we will do this now
  3936.                 CHAR        szQuickOpen[1000], szDummy[1000];
  3937.                 PSZ         pszQuickOpen;
  3938.                 // ULONG       rc;
  3939.  
  3940.                 PrfQueryProfileString(HINI_USERPROFILE, INIAPP_XFOLDER, INIKEY_QUICKOPENFOLDERS,
  3941.                             "", &szQuickOpen, sizeof(szQuickOpen));
  3942.                 pszQuickOpen = szQuickOpen;
  3943.                 do {
  3944.                     HOBJECT          hObject;
  3945.                     WPFolder         *pFolder2;
  3946.                     sscanf(pszQuickOpen, "%lX %s", &hObject, &szDummy);
  3947.                     pFolder2 = _wpclsQueryObject(_WPFolder, hObject);
  3948.                     if (pFolder2) {
  3949.                         if (xwpsCheckObject(pFolder2))
  3950.                             if (_somIsA(pFolder2, _WPFolder))
  3951.                             {
  3952.                                  PCONTENTMENULISTITEM pNew = malloc(sizeof(CONTENTMENULISTITEM));
  3953.                                  pNew->pFolder = pFolder2;
  3954.                                  lstAppendItem((PLISTITEM*)&pliQuickOpenFolders, NULL,
  3955.                                      (PLISTITEM)pNew);
  3956.                             }
  3957.                     }
  3958.                     pszQuickOpen += 6;
  3959.                 } while (strlen(pszQuickOpen) > 0);
  3960.  
  3961.                 pcmliQuickOpenFolders = pliQuickOpenFolders;
  3962.             }
  3963.  
  3964.             pItem = pliQuickOpenFolders;
  3965.             if (pFolder) {
  3966.                 // folder given as param: look for this folder
  3967.                 // and return the following in the list
  3968.                 while (pItem)
  3969.                     if (pItem->pFolder == pFolder) {
  3970.                         pItem = pItem->pNext;
  3971.                         break;
  3972.                     }
  3973.                     else
  3974.                         pItem = pItem->pNext;
  3975.             } // else: pItem == pliQuickOpenFolders
  3976.         }
  3977.     }
  3978.     CATCH(excpt1) { } END_CATCH;
  3979.  
  3980.     if (fSemOwned)
  3981.     {
  3982.         DosReleaseMutexSem(hmtxQuickOpenFolders);
  3983.         fSemOwned = FALSE;
  3984.     }
  3985.  
  3986.     if (pItem)
  3987.         return (pItem->pFolder);
  3988.     else
  3989.         return (NULL);
  3990. }
  3991.  
  3992. /*
  3993.  *@@ xfclsSetDefaultTitle:
  3994.  *           changes the default title to pszNewTitle. The default
  3995.  *           title appears in the third column in folder Details
  3996.  *           views.
  3997.  */
  3998.  
  3999. SOM_Scope BOOL SOMLINK xfM_xfclsSetDefaultTitle(M_XFolder *somSelf,
  4000.                                                    PSZ pszNewTitle)
  4001. {
  4002.     M_XFolderData *somThis = M_XFolderGetData(somSelf);
  4003.     M_XFolderMethodDebug("M_XFolder","xfM_xfclsSetDefaultTItle");
  4004.  
  4005.     strncpy(_szDefaultTitle, pszNewTitle, sizeof(_szDefaultTitle)-1);
  4006.     return (PrfWriteProfileString(HINI_USERPROFILE, INIAPP_XFOLDER, INIKEY_DEFAULTTITLE,
  4007.                 _szDefaultTitle));
  4008. }
  4009.  
  4010. /*
  4011.  *@@ wpclsInitData:
  4012.  *           this initializes the WPFolder / XFolder class as a whole;
  4013.  *           we need to call the parent and then set some XFolder
  4014.  *           data
  4015.  */
  4016.  
  4017. SOM_Scope void  SOMLINK xfM_wpclsInitData(M_XFolder *somSelf)
  4018. {
  4019.     PTHREADGLOBALS pThreadGlobals = xthrQueryGlobals();
  4020.  
  4021.     M_XFolderData *somThis = M_XFolderGetData(somSelf);
  4022.     M_XFolderMethodDebug("M_XFolder","xfM_wpclsInitData");
  4023.  
  4024.     M_XFolder_parent_M_WPFolder_wpclsInitData(somSelf);
  4025.  
  4026.     if (hmtxFavoriteFolders == NULLHANDLE) {
  4027.         // first call:
  4028.  
  4029.         // create mutex semaphores for serialized access
  4030.  
  4031.         cmnInitPSLI();
  4032.  
  4033.         if (DosCreateMutexSem(NULL,
  4034.                             &hmtxFavoriteFolders, 0, FALSE) != NO_ERROR)
  4035.         {
  4036.             DosBeep(100, 300);
  4037.             hmtxFavoriteFolders = -1;
  4038.         }
  4039.         if (DosCreateMutexSem(NULL,
  4040.                             &hmtxQuickOpenFolders, 0, FALSE) != NO_ERROR)
  4041.         {
  4042.             DosBeep(100, 300);
  4043.             hmtxQuickOpenFolders = -1;
  4044.         }
  4045.  
  4046.         // initialize other data
  4047.         pcmliFavoriteFolders = NULL;
  4048.         pcmliQuickOpenFolders = NULL;
  4049.  
  4050.         PrfQueryProfileString(HINI_USERPROFILE, INIAPP_XFOLDER, INIKEY_DEFAULTTITLE,
  4051.                  "XFolder", &(_szDefaultTitle), sizeof(_szDefaultTitle));
  4052.  
  4053.         cmnLoadFolderHotkeys();
  4054.  
  4055.         // register class for supplementary object
  4056.         // windows, which are created for each folder view
  4057.         // which is opened
  4058.         WinRegisterClass(WinQueryAnchorBlock(HWND_DESKTOP),
  4059.                          WNDCLASS_SUPPLOBJECT,    // class name
  4060.                          (PFNWP)fnwpSupplObject,    // Window procedure
  4061.                          0,       // class style
  4062.                          4);      // extra window words for SUBCLASSEDLISTITEM
  4063.                                   // pointer (see cmnSubclassFolderFrame)
  4064.     }
  4065. }
  4066.  
  4067. /*
  4068.  *@@ wpclsCreateDefaultTemplates:
  4069.  *           this is called by the system to allow a class to
  4070.  *           create its default templates. The default WPS
  4071.  *           behavior is to create new templates if the class
  4072.  *           default title is different from the existing
  4073.  *           templates, but since we are replacing the class,
  4074.  *           we will have to suppress this in order not to
  4075.  *           crowd the Templates folder.
  4076.  */
  4077.  
  4078. SOM_Scope BOOL  SOMLINK xfM_wpclsCreateDefaultTemplates(M_XFolder *somSelf,
  4079.                                                         WPObject* Folder)
  4080. {
  4081.     // M_XFolderData *somThis = M_XFolderGetData(somSelf);
  4082.     M_XFolderMethodDebug("M_XFolder","xfM_wpclsCreateDefaultTemplates");
  4083.  
  4084.     // we only override this class method if it is
  4085.     // being called for the XFolder class object itself.
  4086.     // If this is being called for a subclass, we use
  4087.     // the parent method, because we do not want to
  4088.     // break the default behavior for subclasses.
  4089.     if (somSelf == _XFolder)
  4090.         return (TRUE);
  4091.         // means that the Templates folder should _not_ create templates
  4092.         // by itself; we pretend that we've done this
  4093.     else
  4094.         return (M_XFolder_parent_M_WPFolder_wpclsCreateDefaultTemplates(somSelf,
  4095.                                                                     Folder));
  4096. }
  4097.  
  4098. /*
  4099.  *@@ wpclsQueryTitle:
  4100.  *           tell the WPS the new class name: XFolder or whatever
  4101.  *           was specified in the "Workplace Shell" object
  4102.  */
  4103.  
  4104. SOM_Scope PSZ  SOMLINK xfM_wpclsQueryTitle(M_XFolder *somSelf)
  4105. {
  4106.     M_XFolderData *somThis = M_XFolderGetData(somSelf);
  4107.     M_XFolderMethodDebug("M_XFolder","xf_wpclsQueryTitle");
  4108.  
  4109.     if (somSelf == _XFolder)
  4110.         return (_szDefaultTitle);
  4111.     else
  4112.         return (M_XFolder_parent_M_WPFolder_wpclsQueryTitle(somSelf));
  4113. }
  4114.  
  4115. /*
  4116.  *@@ wpclsQueryIconData:
  4117.  *           give folders a new default closed icon, if the
  4118.  *           global settings allow this.
  4119.  *           This is loaded from /ICONS/ICONS.DLL.
  4120.  *           Unfortunately, it appears to be impossible to
  4121.  *           dynamically load default icons as specified for
  4122.  *           the ICONINFO structure in the WPS reference.
  4123.  *           ICON_FILE at least doesn't work, and the format
  4124.  *           for ICON_DATA is not explained. So we have to
  4125.  *           use a DLL here.
  4126.  */
  4127.  
  4128. SOM_Scope ULONG  SOMLINK xfM_wpclsQueryIconData(M_XFolder *somSelf,
  4129.                                                 PICONINFO pIconInfo)
  4130. {
  4131.     ULONG ulrc;
  4132.     PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
  4133.     // M_XFolderData *somThis = M_XFolderGetData(somSelf);
  4134.     M_XFolderMethodDebug("M_XFolder","xfM_wpclsQueryIconData");
  4135.  
  4136.     if (pGlobalSettings->ReplIcons)
  4137.     {
  4138.         // icon replacements allowed:
  4139.         if (pIconInfo) {
  4140.             pIconInfo->fFormat = ICON_RESOURCE;
  4141.             pIconInfo->hmod = cmnQueryIconsDLL();
  4142.             pIconInfo->resid = 100;
  4143.         }
  4144.         ulrc = sizeof(ICONINFO);
  4145.     }
  4146.     else
  4147.         // icon replacements not allowed: call default
  4148.         ulrc = M_XFolder_parent_M_WPFolder_wpclsQueryIconData(somSelf,
  4149.                                                                 pIconInfo);
  4150.     return (ulrc);
  4151. }
  4152.  
  4153. /*
  4154.  *@@ wpclsQueryIconDataN:
  4155.  *           give folders a new default open icon, if the
  4156.  *           global settings allow this.
  4157.  *           See the notes for wpclsQueryIconData.
  4158.  */
  4159.  
  4160. SOM_Scope ULONG  SOMLINK xfM_wpclsQueryIconDataN(M_XFolder *somSelf,
  4161.                                                  ICONINFO* pIconInfo,
  4162.                                                  ULONG ulIconIndex)
  4163. {
  4164.     ULONG ulrc;
  4165.     PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
  4166.     // M_XFolderData *somThis = M_XFolderGetData(somSelf);
  4167.     M_XFolderMethodDebug("M_XFolder","xfM_wpclsQueryIconDataN");
  4168.  
  4169.     if (pGlobalSettings->ReplIcons)
  4170.     {
  4171.         // icon replacements allowed:
  4172.         if (pIconInfo) {
  4173.             pIconInfo->fFormat = ICON_RESOURCE;
  4174.             pIconInfo->hmod = cmnQueryIconsDLL();
  4175.             pIconInfo->resid = 101;
  4176.         }
  4177.         ulrc = sizeof(ICONINFO);
  4178.     }
  4179.     else
  4180.         // icon replacements not allowed: call default
  4181.         ulrc = M_XFolder_parent_M_WPFolder_wpclsQueryIconDataN(somSelf,
  4182.                                                                 pIconInfo,
  4183.                                                                 ulIconIndex);
  4184.     return (ulrc);
  4185. }
  4186.  
  4187. /* ******************************************************************
  4188.  *                                                                  *
  4189.  *   here come the XFldStartup methods                              *
  4190.  *                                                                  *
  4191.  ********************************************************************/
  4192.  
  4193. /*
  4194.  *@@ wpModifyPopupMenu:
  4195.  *           add a "Process content" menu item to this
  4196.  *           popup menu; the other menu items are inherited
  4197.  *           from XFolder
  4198.  */
  4199.  
  4200. SOM_Scope BOOL  SOMLINK xfstup_wpModifyPopupMenu(XFldStartup *somSelf,
  4201.                                                  HWND hwndMenu,
  4202.                                                  HWND hwndCnr,
  4203.                                                  ULONG iPosition)
  4204. {
  4205.     BOOL rc;
  4206.     PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
  4207.     PNLSSTRINGS pNLSStrings = cmnQueryNLSStrings();
  4208.     /* XFldStartupData *somThis = XFldStartupGetData(somSelf); */
  4209.     XFldStartupMethodDebug("XFldStartup","xfstup_wpModifyPopupMenu");
  4210.  
  4211.     rc = XFldStartup_parent_XFolder_wpModifyPopupMenu(somSelf,
  4212.                                                          hwndMenu,
  4213.                                                          hwndCnr,
  4214.                                                          iPosition);
  4215.  
  4216.     winhInsertMenuSeparator(hwndMenu, MIT_END,
  4217.             (pGlobalSettings->VarMenuOffset + ID_XFMI_OFS_SEPARATOR));
  4218.  
  4219.     winhInsertMenuItem(hwndMenu,
  4220.             MIT_END,
  4221.             (pGlobalSettings->VarMenuOffset + ID_XFMI_OFS_PROCESSCONTENT),
  4222.             pNLSStrings->pszProcessContent,
  4223.             MIS_TEXT, 0);
  4224.  
  4225.     return (rc);
  4226. }
  4227.  
  4228. /*
  4229.  *@@ wpMenuItemSelected:
  4230.  *           react to selection of "Process content"
  4231.  *           menu item
  4232.  */
  4233.  
  4234. SOM_Scope BOOL  SOMLINK xfstup_wpMenuItemSelected(XFldStartup *somSelf,
  4235.                                                   HWND hwndFrame,
  4236.                                                   ULONG ulMenuId)
  4237. {
  4238.     PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
  4239.     /* XFldStartupData *somThis = XFldStartupGetData(somSelf); */
  4240.     XFldStartupMethodDebug("XFldStartup","xfstup_wpMenuItemSelected");
  4241.  
  4242.     if ( (ulMenuId - pGlobalSettings->VarMenuOffset) == ID_XFMI_OFS_PROCESSCONTENT ) {
  4243.         if (cmnMessageBoxMsg((hwndFrame) ? hwndFrame : HWND_DESKTOP,
  4244.                             116, 138, MB_YESNO | MB_DEFBUTTON2)
  4245.                         == MBID_YES) {
  4246.                 xthrPostWorkplaceObjectMsg(XOM_BEGINSTARTUP, MPNULL, MPNULL);
  4247.         }
  4248.         return (TRUE);
  4249.     } else
  4250.         return (XFldStartup_parent_XFolder_wpMenuItemSelected(somSelf,
  4251.                                                           hwndFrame,
  4252.                                                           ulMenuId));
  4253. }
  4254.  
  4255. /*
  4256.  *@@ wpMenuItemHelpSelected:
  4257.  *           display help for "Process content"
  4258.  *           menu item
  4259.  */
  4260.  
  4261. SOM_Scope BOOL  SOMLINK xfstup_wpMenuItemHelpSelected(XFldStartup *somSelf,
  4262.                                                       ULONG MenuId)
  4263. {
  4264.     /* XFldStartupData *somThis = XFldStartupGetData(somSelf); */
  4265.     XFldStartupMethodDebug("XFldStartup","xfstup_wpMenuItemHelpSelected");
  4266.  
  4267.     return (XFldStartup_parent_XFolder_wpMenuItemHelpSelected(somSelf,
  4268.                                                               MenuId));
  4269. }
  4270.  
  4271. /*
  4272.  *@@ wpQueryDefaultHelp:
  4273.  *           this instance method specifies the default
  4274.  *           help panel for this instance; display some
  4275.  *           help for the Startup folder
  4276.  */
  4277.  
  4278. SOM_Scope BOOL  SOMLINK xfstup_wpQueryDefaultHelp(XFldStartup *somSelf,
  4279.                                                   PULONG pHelpPanelId,
  4280.                                                   PSZ HelpLibrary)
  4281. {
  4282.     /* XFldStartupData *somThis = XFldStartupGetData(somSelf); */
  4283.     XFldStartupMethodDebug("XFldStartup","xfstup_wpQueryDefaultHelp");
  4284.  
  4285.     strcpy(HelpLibrary, cmnQueryHelpLibrary());
  4286.     *pHelpPanelId = ID_XMH_STARTUPSHUTDOWN;
  4287.     return (TRUE);
  4288.  
  4289.     /* return (XFldStartup_parent_XFolder_wpQueryDefaultHelp(somSelf,
  4290.                                                           pHelpPanelId,
  4291.                                                           HelpLibrary)); */
  4292. }
  4293.  
  4294. /*
  4295.  *@@ wpclsQueryTitle:
  4296.  *           tell the WPS the new class name: "XFolder Startup"
  4297.  */
  4298.  
  4299. SOM_Scope PSZ  SOMLINK xfstupM_wpclsQueryTitle(M_XFldStartup *somSelf)
  4300. {
  4301.     /* M_XFldStartupData *somThis = M_XFldStartupGetData(somSelf); */
  4302.     M_XFldStartupMethodDebug("M_XFldStartup","xfstupM_wpclsQueryTitle");
  4303.  
  4304.     return ("XFolder Startup");
  4305.     // return (M_XFldStartup_parent_M_XFolder_wpclsQueryTitle(somSelf));
  4306. }
  4307.  
  4308. /*
  4309.  *@@ wpclsQueryStyle:
  4310.  *           we return a flag so that no templates are created
  4311.  *           for the Startup folder
  4312.  */
  4313.  
  4314. SOM_Scope ULONG  SOMLINK xfstupM_wpclsQueryStyle(M_XFldStartup *somSelf)
  4315. {
  4316.     /* M_XFldStartupData *somThis = M_XFldStartupGetData(somSelf); */
  4317.     M_XFldStartupMethodDebug("M_XFldStartup","xfstupM_wpclsQueryStyle");
  4318.  
  4319.     return (M_XFldStartup_parent_M_XFolder_wpclsQueryStyle(somSelf)
  4320.                 | CLSSTYLE_NEVERTEMPLATE
  4321.                 | CLSSTYLE_NEVERCOPY
  4322.                 // | CLSSTYLE_NEVERDELETE
  4323.            );
  4324.  
  4325. }
  4326.  
  4327. /*
  4328.  *@@ wpclsQueryIconData:
  4329.  *           give the Startup folder a new closed icon
  4330.  */
  4331.  
  4332. SOM_Scope ULONG  SOMLINK xfstupM_wpclsQueryIconData(M_XFldStartup *somSelf,
  4333.                                                     PICONINFO pIconInfo)
  4334. {
  4335.     /* M_XFldStartupData *somThis = M_XFldStartupGetData(somSelf); */
  4336.     M_XFldStartupMethodDebug("M_XFldStartup","xfstupM_wpclsQueryIconData");
  4337.  
  4338.     if (pIconInfo) {
  4339.        pIconInfo->fFormat = ICON_RESOURCE;
  4340.        pIconInfo->resid   = ID_STARTICON1;
  4341.        pIconInfo->hmod    = modQueryHandle();
  4342.     }
  4343.  
  4344.     return (sizeof(ICONINFO));
  4345.  
  4346.     /* return (M_XFldStartup_parent_M_XFolder_wpclsQueryIconData(somSelf,
  4347.                                                               pIconInfo)); */
  4348. }
  4349.  
  4350. /*
  4351.  *@@ wpclsQueryIconDataN:
  4352.  *           give the Startup folder a new animated icon
  4353.  */
  4354.  
  4355. SOM_Scope ULONG  SOMLINK xfstupM_wpclsQueryIconDataN(M_XFldStartup *somSelf,
  4356.                                                      ICONINFO* pIconInfo,
  4357.                                                      ULONG ulIconIndex)
  4358. {
  4359.     /* M_XFldStartupData *somThis = M_XFldStartupGetData(somSelf); */
  4360.     M_XFldStartupMethodDebug("M_XFldStartup","xfstupM_wpclsQueryIconDataN");
  4361.  
  4362.     if (pIconInfo) {
  4363.        pIconInfo->fFormat = ICON_RESOURCE;
  4364.        pIconInfo->resid   = ID_STARTICON2;
  4365.        pIconInfo->hmod    = modQueryHandle();
  4366.     }
  4367.  
  4368.     return (sizeof(ICONINFO));
  4369.  
  4370.     /* return (M_XFldStartup_parent_M_XFolder_wpclsQueryIconDataN(somSelf,
  4371.                                                                pIconInfo,
  4372.                                                                ulIconIndex)); */
  4373. }
  4374.  
  4375.  
  4376. /* ******************************************************************
  4377.  *                                                                  *
  4378.  *   here come the XFldShutdown methods                             *
  4379.  *                                                                  *
  4380.  ********************************************************************/
  4381.  
  4382. /*
  4383.  *@@ wpQueryDefaultHelp:
  4384.  *           this instance method specifies the default
  4385.  *           help panel for this instance; display some
  4386.  *           help for the Shutdown folder
  4387.  */
  4388.  
  4389. SOM_Scope BOOL  SOMLINK xfshut_wpQueryDefaultHelp(XFldShutdown *somSelf,
  4390.                                                   PULONG pHelpPanelId,
  4391.                                                   PSZ HelpLibrary)
  4392. {
  4393.     /* XFldShutdownData *somThis = XFldShutdownGetData(somSelf); */
  4394.     XFldShutdownMethodDebug("XFldShutdown","xfshut_wpQueryDefaultHelp");
  4395.  
  4396.     strcpy(HelpLibrary, cmnQueryHelpLibrary());
  4397.     *pHelpPanelId = ID_XMH_STARTUPSHUTDOWN;
  4398.     return (TRUE);
  4399.  
  4400.     /* return (XFldShutdown_parent_XFolder_wpQueryDefaultHelp(somSelf,
  4401.                                                            pHelpPanelId,
  4402.                                                            HelpLibrary)); */
  4403. }
  4404.  
  4405. /*
  4406.  *@@ wpclsQueryTitle:
  4407.  *           tell the WPS the new class name: "XFolderShutdown"
  4408.  */
  4409.  
  4410. SOM_Scope PSZ  SOMLINK xfshutM_wpclsQueryTitle(M_XFldShutdown *somSelf)
  4411. {
  4412.     /* M_XFldShutdownData *somThis = M_XFldShutdownGetData(somSelf); */
  4413.     M_XFldShutdownMethodDebug("M_XFldShutdown","xfshutM_wpclsQueryTitle");
  4414.  
  4415.     return ("XFolder Shutdown");
  4416.     // return (M_XFldShutdown_parent_M_XFolder_wpclsQueryTitle(somSelf));
  4417. }
  4418.  
  4419. /*
  4420.  *@@ wpclsQueryStyle:
  4421.  *           we return a flag so that no templates are created
  4422.  *           for the Shutdown folder
  4423.  */
  4424.  
  4425. SOM_Scope ULONG  SOMLINK xfshutM_wpclsQueryStyle(M_XFldShutdown *somSelf)
  4426. {
  4427.     /* M_XFldShutdownData *somThis = M_XFldShutdownGetData(somSelf); */
  4428.     M_XFldShutdownMethodDebug("M_XFldShutdown","xfshutM_wpclsQueryStyle");
  4429.  
  4430.     return (M_XFldShutdown_parent_M_XFolder_wpclsQueryStyle(somSelf)
  4431.                 | CLSSTYLE_NEVERTEMPLATE
  4432.                 | CLSSTYLE_NEVERCOPY
  4433.                 // | CLSSTYLE_NEVERDELETE
  4434.            );
  4435. }
  4436.  
  4437. /*
  4438.  *@@ wpclsQueryIconData:
  4439.  *           give the Shutdown folder a new closed icon
  4440.  */
  4441.  
  4442. SOM_Scope ULONG  SOMLINK xfshutM_wpclsQueryIconData(M_XFldShutdown *somSelf,
  4443.                                                     PICONINFO pIconInfo)
  4444. {
  4445.     /* M_XFldShutdownData *somThis = M_XFldShutdownGetData(somSelf); */
  4446.     M_XFldShutdownMethodDebug("M_XFldShutdown","xfshutM_wpclsQueryIconData");
  4447.  
  4448.     if (pIconInfo) {
  4449.        pIconInfo->fFormat = ICON_RESOURCE;
  4450.        pIconInfo->resid   = ID_SHUTICON1;
  4451.        pIconInfo->hmod    = modQueryHandle();
  4452.     }
  4453.  
  4454.     return (sizeof(ICONINFO));
  4455.  
  4456.     /* return (M_XFldShutdown_parent_M_XFolder_wpclsQueryIconData(somSelf,
  4457.                                                                pIconInfo)); */
  4458. }
  4459.  
  4460. /*
  4461.  *@@ wpclsQueryIconDataN:
  4462.  *           give the Shutdown folder a new animated icon
  4463.  */
  4464.  
  4465. SOM_Scope ULONG  SOMLINK xfshutM_wpclsQueryIconDataN(M_XFldShutdown *somSelf,
  4466.                                                      ICONINFO* pIconInfo,
  4467.                                                      ULONG ulIconIndex)
  4468. {
  4469.     /* M_XFldShutdownData *somThis = M_XFldShutdownGetData(somSelf); */
  4470.     M_XFldShutdownMethodDebug("M_XFldShutdown","xfshutM_wpclsQueryIconDataN");
  4471.  
  4472.     if (pIconInfo) {
  4473.        pIconInfo->fFormat = ICON_RESOURCE;
  4474.        pIconInfo->resid   = ID_SHUTICON2;
  4475.        pIconInfo->hmod    = modQueryHandle();
  4476.     }
  4477.  
  4478.     return (sizeof(ICONINFO));
  4479.  
  4480.     /* return (M_XFldShutdown_parent_M_XFolder_wpclsQueryIconDataN(somSelf,
  4481.                                                                 pIconInfo,
  4482.                                                                 ulIconIndex)); */
  4483. }
  4484.  
  4485.  
  4486. /* ******************************************************************
  4487.  *                                                                  *
  4488.  *   here come all the XFolder window procedures                    *
  4489.  *                                                                  *
  4490.  ********************************************************************/
  4491.  
  4492. /*
  4493.  *@@ fnwpStatusBar:
  4494.  *      since the status bar is just created as a static frame
  4495.  *      control, it is subclassed (by XFolder::xfShowStatusBar),
  4496.  *      and this is the wnd proc for this.
  4497.  *      This handles the new STBM_UPDATESTATUSBAR message (which
  4498.  *      is posted any time the status bar needs to be updated)
  4499.  *      and intercepts WM_TIMER and WM_PAINT.
  4500.  */
  4501.  
  4502. MRESULT EXPENTRY fnwpStatusBar(HWND hwndBar, ULONG msg, MPARAM mp1, MPARAM mp2)
  4503. {
  4504.     PSTATUSBARDATA psbd = (PSTATUSBARDATA)WinQueryWindowULong(hwndBar, QWL_USER);
  4505.     MRESULT        mrc = 0;
  4506.  
  4507.     PGLOBALSETTINGS pGlobalSettings =
  4508.             cmnQueryGlobalSettings();
  4509.  
  4510.     if (psbd)
  4511.     {
  4512.         PFNWP      pfnwpStatusBarOriginal = psbd->pfnwpStatusBarOriginal;
  4513.  
  4514.         switch(msg)
  4515.         {
  4516.             /*
  4517.              * STBM_UPDATESTATUSBAR:
  4518.              *      mp1: MPNULL,
  4519.              *      mp2: MPNULL
  4520.              *      Update status bar text. We will set a timer
  4521.              *      for a short delay to filter out repetitive
  4522.              *      messages here.
  4523.              *      This timer is "one-shot" in that it will be
  4524.              *      started here and stopped as soon as WM_TIMER
  4525.              *      is received.
  4526.              */
  4527.  
  4528.             case STBM_UPDATESTATUSBAR: {
  4529.                 if (psbd->idTimer == 0) {
  4530.                     // only if timer is not yet running: start it now
  4531.                     psbd->idTimer = WinStartTimer(WinQueryAnchorBlock(hwndBar),
  4532.                                                   hwndBar,
  4533.                                                   1,
  4534.                                                   100); // delay: 100 ms
  4535.                 }
  4536.             break; }
  4537.  
  4538.             /*
  4539.              * WM_TIMER:
  4540.              *      a timer is started by STBM_UPDATESTATUSBAR
  4541.              *      to avoid flickering;
  4542.              *      we now compose the actual text to be displayed
  4543.              */
  4544.  
  4545.             case WM_TIMER: {
  4546.                 CHAR szText[1000];
  4547.  
  4548.                 TRY_LOUD(excpt1)
  4549.                 {
  4550.                     // stop timer (it's just for one shot)
  4551.                     WinStopTimer(WinQueryAnchorBlock(hwndBar), hwndBar, 1);
  4552.                     psbd->idTimer = 0;
  4553.  
  4554.                     // if we're not fully populated yet, start timer again and quit;
  4555.                     // otherwise we would display false information.
  4556.                     // We need an extra flag in the status bar data because the
  4557.                     // FOI_POPULATEDWITHALL is reset to 0 by the WPS for some reason
  4558.                     // when an object is deleted from an open folder, and no further
  4559.                     // status bar updates would occur then
  4560.                     if (psbd->fFolderPopulated == FALSE) {
  4561.                         ULONG ulFlags = _wpQueryFldrFlags(psbd->somSelf);
  4562.                         #ifdef DEBUG_STATUSBARS
  4563.                             _Pmpf(( "  Folder flags: %lX", ulFlags ));
  4564.                             _Pmpf(( "  View: %s",
  4565.                                     (psbd->psli->ulView == OPEN_TREE) ? "Tree"
  4566.                                     : (psbd->psli->ulView == OPEN_CONTENTS) ? "Content"
  4567.                                     : (psbd->psli->ulView == OPEN_DETAILS) ? "Details"
  4568.                                     : "unknown"
  4569.                                  ));
  4570.                         #endif
  4571.  
  4572.                         // for tree views, check if folder is populated with folders;
  4573.                         // otherwise check for populated with all
  4574.                         if (    (   (psbd->psli->ulView == OPEN_TREE)
  4575.                                  && ((ulFlags & FOI_POPULATEDWITHFOLDERS) !=0)
  4576.                                 )
  4577.                             || ((ulFlags & FOI_POPULATEDWITHALL) != 0)
  4578.                            )
  4579.                         {
  4580.                             psbd->fFolderPopulated = TRUE;
  4581.                         } else {
  4582.                             // folder not yet populated:
  4583.                             // restart timer with a lower frequency
  4584.                             // to have this checked again
  4585.                             psbd->idTimer = WinStartTimer(WinQueryAnchorBlock(hwndBar),
  4586.                                     hwndBar,
  4587.                                     1,
  4588.                                     300);   // this time, use 300 ms
  4589.                             // and stop
  4590.                             break;
  4591.                         }
  4592.                     }
  4593.  
  4594.                     // OK:
  4595.                     // translate the template text (szText) into something
  4596.                     // meaningful (statbars.c)
  4597.                     stbComposeText(psbd->somSelf,
  4598.                             psbd->psli->hwndCnr,    // cnr hwnd in frame wnd struct
  4599.                             szText, sizeof(szText));
  4600.                 }
  4601.                 CATCH(excpt1)
  4602.                 {
  4603.                     strcpy(szText, "*** error composing text");
  4604.                 } END_CATCH;
  4605.  
  4606.                 // set window text (provokes WM_PAINT) and quit
  4607.                 WinSetWindowText(hwndBar, szText);
  4608.             break; }
  4609.  
  4610.             /*
  4611.              * WM_PAINT:
  4612.              *      this, well, paints the status bar.
  4613.              *      Since the status bar is just a static control,
  4614.              *      we want to do some extra stuff to make it prettier.
  4615.              *      At this point, the window text (of the status bar)
  4616.              *      contains the fully translated status bar mnemonics,
  4617.              *      except for the tabulators ("$x" flags), which we'll
  4618.              *      deal with here.
  4619.              */
  4620.  
  4621.             case WM_PAINT: {
  4622.                 // preparations:
  4623.                 RECTL   rclBar, rcl;
  4624.                 HPS hps = WinBeginPaint(hwndBar, NULLHANDLE, &rcl);
  4625.  
  4626.                 TRY_LOUD(excpt1)
  4627.                 {
  4628.                     POINTL  ptl1;
  4629.                     CHAR    szText[1000], szTemp[100] = "0";
  4630.                     USHORT  usLength;
  4631.                     LONG    lNextX;
  4632.                     PSZ     p1, p2, p3;
  4633.  
  4634.                     WinQueryWindowRect(hwndBar, &rclBar);
  4635.                     // switch to RGB mode
  4636.                     GpiCreateLogColorTable(hps, 0,
  4637.                         LCOLF_RGB,
  4638.                         0, 0, NULL);
  4639.  
  4640.                     // 1) draw background
  4641.                     WinFillRect(hps, &rclBar, pGlobalSettings->lSBBgndColor);
  4642.  
  4643.                     // 2) draw 3D frame in selected style
  4644.                     if (pGlobalSettings->SBStyle == SBSTYLE_WARP3RAISED)
  4645.                         // Warp 3 style, raised
  4646.                         gpihDraw3DFrame(hps, &rclBar, 1, TRUE);
  4647.                     else if (pGlobalSettings->SBStyle == SBSTYLE_WARP3SUNKEN)
  4648.                         // Warp 3 style, sunken
  4649.                         gpihDraw3DFrame(hps, &rclBar, 1, FALSE);
  4650.                     else if (pGlobalSettings->SBStyle == SBSTYLE_WARP4MENU) {
  4651.                         // Warp 4 menu style: draw 3D line at top only
  4652.                         rcl = rclBar;
  4653.                         rcl.yBottom = rcl.yTop-2;
  4654.                         gpihDraw3DFrame(hps, &rcl, 1, FALSE);
  4655.                     } else {
  4656.                         // Warp 4 button style
  4657.                         rcl = rclBar;
  4658.                         // draw "sunken" outer rect
  4659.                         gpihDraw3DFrame(hps, &rclBar, 2, FALSE);
  4660.                         // draw "raised" inner rect
  4661.                         WinInflateRect(WinQueryAnchorBlock(hwndBar),
  4662.                                 &rcl, -1, -1);
  4663.                         gpihDraw3DFrame(hps, &rcl, 2, TRUE);
  4664.                     }
  4665.  
  4666.                     // 3) start working on text; we do "simple" GpiCharString
  4667.                     //    if no tabulators are defined, but calculate some
  4668.                     //    subrectangles otherwise
  4669.                     WinQueryWindowText(hwndBar, sizeof(szText)-1, &szText[0]);
  4670.                             // szText now has the translated status bar text
  4671.                             // except for the tabulators ("$x" keys)
  4672.                     p1 = szText;
  4673.                     p2 = NULL;
  4674.                     ptl1.x = 7;
  4675.  
  4676.                     do {    // while tabulators are present
  4677.  
  4678.                         // search for tab mnemonic
  4679.                         if (p2 = strstr(p1, "$x(")) {
  4680.                             // tab found: calculate next x position into lNextX
  4681.                             usLength = (p2-p1);
  4682.                             strcpy(szTemp, "100");
  4683.                             if (p3 = strchr(p2, ')')) {
  4684.                                 PSZ p4 = strchr(p2, '%');
  4685.                                 strncpy(szTemp, p2+3, p3-p2-3);
  4686.                                 // get the parameter
  4687.                                 sscanf(szTemp, "%d", &lNextX);
  4688.  
  4689.                                 if (lNextX < 0) {
  4690.                                     // if the result is negative, it's probably
  4691.                                     // meant to be an offset from the right
  4692.                                     // status bar border
  4693.                                     lNextX = (rclBar.xRight + lNextX); // lNextX is negative
  4694.                                 }
  4695.                                 else if ((p4) && (p4 < p3)) {
  4696.                                     // if we have a '%' char before the closing
  4697.                                     // bracket, consider lNextX a percentage
  4698.                                     // parameter and now translate it into an
  4699.                                     // absolute x position using the status bar's
  4700.                                     // width
  4701.                                     lNextX = (rclBar.xRight * lNextX) / 100;
  4702.                                 }
  4703.                             } else
  4704.                                 p2 = NULL;
  4705.                         } else
  4706.                             usLength = strlen(p1);
  4707.  
  4708.                         ptl1.y = (pGlobalSettings->SBStyle == SBSTYLE_WARP4MENU) ? 5 : 7;
  4709.                         // set the text color to the global value;
  4710.                         // this might have changed via color drag'n'drop
  4711.                         GpiSetColor(hps, pGlobalSettings->lSBTextColor);
  4712.                             // the font is already preset by the static
  4713.                             // text control (phhhh...)
  4714.  
  4715.                         if (p2) {
  4716.                             // did we have tabs? if so, print text clipped to rect
  4717.                             rcl.xLeft   = 0;
  4718.                             rcl.yBottom = 0; // ptl1.y;
  4719.                             rcl.xRight  = lNextX-10; // 10 pels space
  4720.                             rcl.yTop    = rclBar.yTop;
  4721.                             GpiCharStringPosAt(hps, &ptl1, &rcl, CHS_CLIP,
  4722.                                     usLength, p1, NULL);
  4723.                         } else {
  4724.                             // no (more) tabs: just print
  4725.                             GpiMove(hps, &ptl1);
  4726.                             GpiCharString(hps, usLength, p1);
  4727.                         }
  4728.  
  4729.                         if (p2) { // "tabulator" was found: set next x pos
  4730.                             ptl1.x = lNextX;
  4731.                             p1 = p3+1;
  4732.                         }
  4733.  
  4734.                     } while (p2);       // go for next tabulator, if we had one
  4735.  
  4736.                 }
  4737.                 CATCH(excpt1)
  4738.                 {
  4739.                     PSZ pszErr = "*** error painting status bar";
  4740.                     POINTL ptl = {5, 5};
  4741.                     GpiMove(hps, &ptl);
  4742.                     GpiCharString(hps, strlen(pszErr), pszErr);
  4743.                 } END_CATCH;
  4744.  
  4745.                 WinEndPaint(hps);
  4746.  
  4747.             break; }
  4748.  
  4749.             /*
  4750.              * STBM_PROHIBITBROADCASTING:
  4751.              *      this msg is sent to us to tell us we will
  4752.              *      be given new presentation parameters soon;
  4753.              *      we will set a flag to TRUE in order to
  4754.              *      prevent broadcasting the pres params again.
  4755.              *      We need this flag because there are two
  4756.              *      situations in which we are given
  4757.              *      WM_PRESPARAMCHANGED messages:
  4758.              *      1)   the user has dropped something on this
  4759.              *           status bar window; in this case, we're
  4760.              *           getting WM_PRESPARAMCHANGED directly,
  4761.              *           without STBM_PROHIBITBROADCASTING, which
  4762.              *           means that we should notify the Worker
  4763.              *           thread to broadcast WM_PRESPARAMCHANGED
  4764.              *           to all status bars;
  4765.              *      2)   a status bar other than this one had been
  4766.              *           dropped something upon; in this case, we'll
  4767.              *           get WM_PRESPARAMCHANGED also (from the
  4768.              *           Worker thread), but STBM_PROHIBITBROADCASTING
  4769.              *           beforehand so that we know we should not
  4770.              *           notify the Worker thread again.
  4771.              *      See WM_PRESPARAMCHANGED below.
  4772.              */
  4773.  
  4774.             case STBM_PROHIBITBROADCASTING: {
  4775.                 psbd->fDontBroadcast = TRUE;
  4776.             break; }
  4777.  
  4778.             /*
  4779.              * WM_PRESPARAMCHANGED:
  4780.              *      if fonts or colors were dropped on the bar, update
  4781.              *      GlobalSettings and have this message broadcast to all
  4782.              *      other status bars on the system.
  4783.              *      This is also posted to us by the Worker thread
  4784.              *      after some OTHER status bar has been dropped
  4785.              *      fonts or colors upon; in this case, psbd->fDontBroadcast
  4786.              *      is TRUE (see above), and we will only update our
  4787.              *      own display and NOT broadcast, because this is
  4788.              *      already being done.
  4789.              */
  4790.  
  4791.             case WM_PRESPARAMCHANGED: {
  4792.                 mrc = (MRESULT)(*pfnwpStatusBarOriginal)(hwndBar, msg, mp1, mp2);
  4793.  
  4794.                 if (psbd->fDontBroadcast) {
  4795.                     // this flag has been set if it was not this status
  4796.                     // bar whose presparams have changed, but some other
  4797.                     // status bar; in this case, update only
  4798.                     psbd->fDontBroadcast = FALSE;
  4799.                     // update parent's frame controls (because font size
  4800.                     // might have changed)
  4801.                     WinSendMsg(WinQueryWindow(hwndBar, QW_PARENT), WM_UPDATEFRAME, MPNULL, MPNULL);
  4802.                     // update ourselves
  4803.                     WinPostMsg(hwndBar, STBM_UPDATESTATUSBAR, MPNULL, MPNULL);
  4804.                     // and quit
  4805.                     break;
  4806.                 }
  4807.  
  4808.                 // else: it was us that the presparam has been set for
  4809.                 #ifdef DEBUG_STATUSBARS
  4810.                     _Pmpf(( "WM_PRESPARAMCHANGED: %lX", mp1 ));
  4811.                 #endif
  4812.  
  4813.                 // now check what has changed
  4814.                 switch ((ULONG)mp1) {
  4815.                     case PP_FONTNAMESIZE: {
  4816.                         ULONG attrFound;
  4817.                         // CHAR  szDummy[200];
  4818.                         CHAR  szNewFont[100];
  4819.                         WinQueryPresParam(hwndBar,
  4820.                                     PP_FONTNAMESIZE,
  4821.                                     0,
  4822.                                     &attrFound,
  4823.                                     (ULONG)sizeof(szNewFont),
  4824.                                     (PVOID)&szNewFont,
  4825.                                     0);
  4826.                         cmnSetStatusBarSetting(SBS_STATUSBARFONT,
  4827.                                 szNewFont);
  4828.                         // update parent's frame controls (because font size
  4829.                         // might have changed)
  4830.                         WinSendMsg(WinQueryWindow(hwndBar, QW_PARENT),
  4831.                                 WM_UPDATEFRAME, MPNULL, MPNULL);
  4832.                     break; }
  4833.  
  4834.                     case PP_FOREGROUNDCOLOR:
  4835.                     case PP_BACKGROUNDCOLOR: {
  4836.                         ULONG ul = 0, attrFound = 0;
  4837.                         WinQueryPresParam(hwndBar,
  4838.                                     (ULONG)mp1,
  4839.                                     0,
  4840.                                     &attrFound,
  4841.                                     (ULONG)sizeof(ul),
  4842.                                     (PVOID)&ul,
  4843.                                     0);
  4844.                         if ((ULONG)mp1 == PP_FOREGROUNDCOLOR)
  4845.                             pGlobalSettings->lSBTextColor = ul;
  4846.                         else
  4847.                             pGlobalSettings->lSBBgndColor = ul;
  4848.                         PrfWriteProfileData(HINI_USERPROFILE, INIAPP_XFOLDER, INIKEY_GLOBALSETTINGS,
  4849.                                     pGlobalSettings, sizeof(GLOBALSETTINGS));
  4850.                         WinPostMsg(hwndBar, STBM_UPDATESTATUSBAR, MPNULL, MPNULL);
  4851.                     break; }
  4852.                 }
  4853.  
  4854.                 // finally, broadcast this message to all other status bars;
  4855.                 // this is handled by the Worker thread
  4856.                 xthrPostWorkerMsg(WOM_UPDATEALLSTATUSBARS,
  4857.                         (MPARAM)2,      // update display
  4858.                         MPNULL);
  4859.             break; }
  4860.  
  4861.             /*
  4862.              * WM_BUTTON1CLICK:
  4863.              *      if button1 is clicked on the status
  4864.              *      bar, we should reset the focus to the
  4865.              *      container.
  4866.              */
  4867.  
  4868.             case WM_BUTTON1CLICK:
  4869.                 // mrc = (MRESULT)(*pfnwpStatusBarOriginal)(hwndBar, msg, mp1, mp2);
  4870.                 WinSetFocus(HWND_DESKTOP, psbd->psli->hwndCnr);
  4871.             break;
  4872.  
  4873.             /*
  4874.              * WM_BUTTON1DBLCLK:
  4875.              *      on double-click on the status bar,
  4876.              *      open the folder's settings notebook.
  4877.              *      If DEBUG_RESTOREDATA is on (common.h),
  4878.              *      dump some internal folder data to
  4879.              *      PMPRINTF instead.
  4880.              */
  4881.  
  4882.             case WM_BUTTON1DBLCLK: {
  4883.  
  4884.                 /* TRY_LOUD(excpt1) {
  4885.                     CRASH;
  4886.                 }
  4887.                 CATCH(excpt1) {
  4888.                 } END_CATCH; */
  4889.  
  4890.                 #ifdef DEBUG_RESTOREDATA
  4891.                     XFolderData     *somThis = XFolderGetData(psbd->somSelf);
  4892.                     _Pmpf(("Dump for %s", _wpQueryTitle(psbd->somSelf) ));
  4893.                     _Pmpf(("FDRLONGARRAY: "));
  4894.                     dbgDump((PBYTE)_pFldrLongArray, _cbFldrLongArray, 3);
  4895.                 #else
  4896.                     WinPostMsg(psbd->psli->hwndFrame,
  4897.                             WM_COMMAND,
  4898.                             (MPARAM)WPMENUID_PROPERTIES,
  4899.                             MPFROM2SHORT(CMDSRC_MENU,
  4900.                                     FALSE) );     // results from keyboard operation
  4901.                 #endif
  4902.             break; }
  4903.  
  4904.             /*
  4905.              * WM_CONTEXTMENU:
  4906.              *      if the user right-clicks on status bar,
  4907.              *      display folder's context menu. Parameters:
  4908.              *      mp1:
  4909.              *          POINTS mp1      pointer position
  4910.              *      mp2:
  4911.              *          USHORT usReserved  should be 0
  4912.              *          USHORT fPointer    if TRUE: results from keyboard
  4913.              */
  4914.  
  4915.             case WM_CONTEXTMENU: {
  4916.                 if (psbd->psli) {
  4917.                     POINTL ptl;
  4918.                     WinSetFocus(HWND_DESKTOP, psbd->psli->hwndCnr);
  4919.                     // give the cnr source emphasis
  4920.                     // (needed for some wpSelectingMenu funcs)
  4921.                     WinSendMsg(psbd->psli->hwndCnr,
  4922.                                 CM_SETRECORDEMPHASIS,
  4923.                                 (MPARAM)NULL,   // undocumented: if precc == NULL,
  4924.                                                 // the whole cnr is given emphasis
  4925.                                 MPFROM2SHORT(TRUE,  // set emphasis
  4926.                                         CRA_SOURCE));
  4927.  
  4928.                     ptl.x = SHORT1FROMMP(mp1)-30;
  4929.                     ptl.y = SHORT2FROMMP(mp1);
  4930.                     _wpDisplayMenu(psbd->somSelf,
  4931.                                 WinQueryWindow(hwndBar, QW_PARENT), // owner: folder frame
  4932.                                 hwndBar,                            // parent: status bar
  4933.                                 &ptl,
  4934.                                 MENU_OBJECTPOPUP,
  4935.                                 0);
  4936.  
  4937.                     // set flag so that the fnwpSubclassedFolderFrame
  4938.                     // can remove the cnr source emphasis after the
  4939.                     // menu has been terminated
  4940.                     psbd->psli->fRemoveSrcEmphasis = TRUE;
  4941.                 }
  4942.             break; }
  4943.  
  4944.             /*
  4945.              * WM_DESTROY:
  4946.              *      call original wnd proc, then free psbd
  4947.              */
  4948.  
  4949.             case WM_DESTROY:
  4950.                 mrc = (MRESULT)(*pfnwpStatusBarOriginal)(hwndBar, msg, mp1, mp2);
  4951.                 WinSetWindowULong(hwndBar, QWL_USER, 0);
  4952.                 free(psbd);
  4953.             break;
  4954.  
  4955.             default:
  4956.                 mrc = (MRESULT)(*pfnwpStatusBarOriginal)(hwndBar, msg, mp1, mp2);
  4957.             break;
  4958.         } // end switch
  4959.     } // end if (psbd)
  4960.     /* else // error: call default
  4961.         mrc = (MRESULT)(*pfnwpStatusBarOriginal)(hwndBar, msg, mp1, mp2); */
  4962.  
  4963.     return (mrc);
  4964. }
  4965.  
  4966. /*
  4967.  * CalcFrameRect:
  4968.  *      this gets called from fnwpSubclassedFolderFrame
  4969.  *      when WM_CALCFRAMERECT is received. This implements
  4970.  *      folder status bars.
  4971.  */
  4972.  
  4973. VOID CalcFrameRect(MPARAM mp1, MPARAM mp2)
  4974. {
  4975.     PRECTL prclPassed = (PRECTL)mp1;
  4976.     ULONG ulStatusBarHeight = cmnQueryStatusBarHeight();
  4977.  
  4978.     if (SHORT1FROMMP(mp2))
  4979.         //     TRUE:  Frame rectangle provided, calculate client
  4980.         //     FALSE: Client area rectangle provided, calculate frame
  4981.     {
  4982.         //  TRUE: calculate the rectl of the client;
  4983.         //  call default window procedure to subtract child frame
  4984.         //  controls from the rectangle's height
  4985.         LONG lClientHeight;
  4986.  
  4987.         //  position the static text frame extension below the client
  4988.         lClientHeight = prclPassed->yTop - prclPassed->yBottom;
  4989.         if ( ulStatusBarHeight  > lClientHeight  )
  4990.         {
  4991.             // extension is taller than client, so set client height to 0
  4992.             prclPassed->yTop = prclPassed->yBottom;
  4993.         }
  4994.         else
  4995.         {
  4996.             //  set the origin of the client and shrink it based upon the
  4997.             //  static text control's height
  4998.             prclPassed->yBottom += ulStatusBarHeight;
  4999.             prclPassed->yTop -= ulStatusBarHeight;
  5000.         }
  5001.     }
  5002.     else
  5003.     {
  5004.         //  FALSE: calculate the rectl of the frame;
  5005.         //  call default window procedure to subtract child frame
  5006.         //  controls from the rectangle's height;
  5007.         //  set the origin of the frame and increase it based upon the
  5008.         //  static text control's height
  5009.         prclPassed->yBottom -= ulStatusBarHeight;
  5010.         prclPassed->yTop += ulStatusBarHeight;
  5011.     }
  5012. }
  5013.  
  5014. /*
  5015.  * FormatFrame:
  5016.  *      this gets called from fnwpSubclassedFolderFrame
  5017.  *      when WM_FORMATFRAME is received. This implements
  5018.  *      folder status bars.
  5019.  */
  5020.  
  5021. VOID FormatFrame(PSUBCLASSEDLISTITEM psli, // in: frame information
  5022.                  MPARAM mp1,            // in: mp1 from WM_FORMATFRAME
  5023.                                         //     (points to SWP array)
  5024.                  ULONG *pulCount)       // in/out: frame control count
  5025.                                         //         from default wnd proc
  5026. {
  5027.     // access the SWP array that is passed to us
  5028.     // and search all the controls for the container child window,
  5029.     // which for folders always has the ID 0x8008
  5030.     ULONG       ul;
  5031.     PSWP        swpArr = (PSWP)mp1;
  5032.     CNRINFO     CnrInfo;
  5033.  
  5034.     for (ul = 0; ul < *pulCount; ul++)
  5035.     {
  5036.         if (WinQueryWindowUShort( swpArr[ul].hwnd, QWS_ID ) == 0x8008 )
  5037.                                                          // FID_CLIENT
  5038.         {
  5039.             // container found: reduce size of container by
  5040.             // status bar height
  5041.             POINTL          ptlBorderSizes;
  5042.             // XFolderData     *somThis = XFolderGetData(psli->somSelf);
  5043.             ULONG ulStatusBarHeight = cmnQueryStatusBarHeight();
  5044.             WinSendMsg(psli->hwndFrame, WM_QUERYBORDERSIZE,
  5045.                     (MPARAM)&ptlBorderSizes, MPNULL);
  5046.  
  5047.             // first initialize the _new_ SWP for the status bar.
  5048.             // Since the SWP array for the std frame controls is
  5049.             // zero-based, and the standard frame controls occupy
  5050.             // indices 0 thru ulCount-1 (where ulCount is the total
  5051.             // count), we use ulCount for our static text control.
  5052.             swpArr[*pulCount].fl = SWP_MOVE | SWP_SIZE | SWP_NOADJUST | SWP_ZORDER;
  5053.             swpArr[*pulCount].x  = ptlBorderSizes.x;
  5054.             swpArr[*pulCount].y  = ptlBorderSizes.y;
  5055.             swpArr[*pulCount].cx = swpArr[ul].cx;
  5056.             swpArr[*pulCount].cy = ulStatusBarHeight;
  5057.             swpArr[*pulCount].hwndInsertBehind = HWND_BOTTOM; // HWND_TOP;
  5058.             swpArr[*pulCount].hwnd = psli->hwndStatusBar;
  5059.  
  5060.             // adjust the origin and height of the container to
  5061.             // accomodate our static text control
  5062.             swpArr[ul].y  += swpArr[*pulCount].cy;
  5063.             swpArr[ul].cy -= swpArr[*pulCount].cy;
  5064.  
  5065.             // now we need to adjust the workspace origin of the cnr
  5066.             // accordingly, or otherwise the folder icons will appear
  5067.             // outside the visible cnr workspace and scroll bars will
  5068.             // show up.
  5069.             // We only do this the first time we're arriving here
  5070.             // (which should be before the WPS is populating the folder);
  5071.             // psli->fNeedCnrScroll has been initially set to TRUE
  5072.             // by xfShowStatusBar
  5073.             if (psli->fNeedCnrScroll)
  5074.             {
  5075.                 winhQueryCnrInfo(swpArr[ul].hwnd, CnrInfo);
  5076.                 #ifdef DEBUG_STATUSBARS
  5077.                     _Pmpf(( "Old CnrInfo.ptlOrigin.y: %lX", CnrInfo.ptlOrigin.y ));
  5078.                 #endif
  5079.                 if (    ((LONG)CnrInfo.ptlOrigin.y >= (LONG)ulStatusBarHeight)
  5080.                    )
  5081.                 {
  5082.                     CnrInfo.ptlOrigin.y -= ulStatusBarHeight;
  5083.                     #ifdef DEBUG_STATUSBARS
  5084.                         _Pmpf(( "New CnrInfo.ptlOrigin.y: %lX", CnrInfo.ptlOrigin.y ));
  5085.                     #endif
  5086.                     WinSendMsg(swpArr[ul].hwnd, CM_SETCNRINFO,
  5087.                             (MPARAM)&CnrInfo, (MPARAM)CMA_PTLORIGIN);
  5088.                     // set flag to FALSE to prevent a second adjustment
  5089.                     psli->fNeedCnrScroll = FALSE;
  5090.                 }
  5091.             } // end if (psli->fNeedCnrScroll)
  5092.         } // end if WinQueryWindowUShort
  5093.     } // end for (ul = 0; ul < ulCount; ul++)
  5094. }
  5095.  
  5096. /*
  5097.  * InitMenu:
  5098.  *      this gets called from fnwpSubclassedFolderFrame
  5099.  *      when WM_INITMENU is received.
  5100.  *      This is needed for various menu features:
  5101.  *      1)  for folder content menus, because these
  5102.  *          are initially empty and only filled if the user
  5103.  *          clicks on them.
  5104.  *          We will query a bunch of data first, which we need
  5105.  *          later for drawing our items, and then call
  5106.  *          mnuFillContentSubmenu, which populates the folder
  5107.  *          and fills the menu with the items therein;
  5108.  *      2)  for the menu system sounds;
  5109.  *      3)  for manipulating Warp 4 folder menu _bars_.
  5110.  *      WM_INITMENU parameters:
  5111.  *          SHORT mp1   menu item id
  5112.  *          HWND  mp2   menu window handle
  5113.  *      Returns: NULL always.
  5114.  */
  5115.  
  5116. // original wnd proc for folder content menus,
  5117. // which we must subclass
  5118. PFNWP   pfnwpFolderContentMenuOriginal = NULL;
  5119.  
  5120. VOID InitMenu(PSUBCLASSEDLISTITEM psli, // in: frame information
  5121.               MPARAM mp1,
  5122.               MPARAM mp2)   // in: mp1, mp2 from WM_INITMENU
  5123. {
  5124.     PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
  5125.     XFolderData     *somThis = XFolderGetData(psli->somSelf);
  5126.     PTHREADGLOBALS pThreadGlobals = xthrQueryGlobals();
  5127.     ULONG           *pulWorkplaceFunc2 = &(pThreadGlobals->ulWorkplaceFunc2);
  5128.  
  5129.     #ifdef DEBUG_MENUS
  5130.         _Pmpf(( "WM_INITMENU: mp1 = %lX, mp2 = %lX", mp1, mp2 ));
  5131.     #endif
  5132.  
  5133.     // store the container window handle in instance
  5134.     // data for wpPopupMenu workaround (see wpPopupMenu)
  5135.     _hwndCnrSaved = psli->hwndCnr;
  5136.  
  5137.     // play system sound
  5138.     if (    ((USHORT)mp1 <  0x8000) // avoid system menu
  5139.          || ((USHORT)mp1 == 0x8020) // include context menu
  5140.        )
  5141.         xthrPlaySystemSound(MMSOUND_XFLD_CTXTOPEN);
  5142.  
  5143.     *pulWorkplaceFunc2 = 200;
  5144.     // find out whether the menu of which we are notified
  5145.     // is a folder content menu; if so (and it is not filled
  5146.     // yet), the first menu item is ID_XFMI_OFS_DUMMY
  5147.     if ((ULONG)WinSendMsg((HWND)mp2, MM_ITEMIDFROMPOSITION, (MPARAM)0, MPNULL)
  5148.         == (pGlobalSettings->VarMenuOffset + ID_XFMI_OFS_DUMMY))
  5149.     {
  5150.         // okay, let's go
  5151.         if (pGlobalSettings->FCShowIcons)
  5152.         {
  5153.             #ifdef DEBUG_MENUS
  5154.                 _Pmpf(( "  preparing owner draw"));
  5155.             #endif
  5156.             // show folder content icons ON:
  5157.             mnuPrepareOwnerDraw(mp1, mp2);
  5158.         }
  5159.  
  5160.         *pulWorkplaceFunc2 = 200;
  5161.         mnuFillContentSubmenu(
  5162.                         (SHORT)mp1, (HWND)mp2,
  5163.                         // this func subclasses the folder content
  5164.                         // menu wnd and stores the result here
  5165.                         &pfnwpFolderContentMenuOriginal);
  5166.     } else {
  5167.         // no folder content menu:
  5168.  
  5169.         // on Warp 4, check if the folder has a menu bar
  5170.         if (doshIsWarp4()) {
  5171.  
  5172.             #ifdef DEBUG_MENUS
  5173.                 _Pmpf(( "  checking for menu bar"));
  5174.             #endif
  5175.  
  5176.             if (SHORT1FROMMP(mp1) == 0x8005) {
  5177.                 // seems to be some WPS menu item;
  5178.                 // since the WPS seems to be using this
  5179.                 // same ID for all the menu bar submenus,
  5180.                 // we need to check the last selected
  5181.                 // menu item, which was stored in the psli
  5182.                 // structure by WM_MENUSELECT (below).
  5183.                 PNLSSTRINGS pNLSStrings = cmnQueryNLSStrings();
  5184.  
  5185.                 switch (psli->usLastSelMenuItem) {
  5186.                     case 0x2D3:
  5187.                         // "Help" submenu: add XFolder product info
  5188.                         #ifdef DEBUG_MENUS
  5189.                             _Pmpf(("  'Help' menu found"));
  5190.                         #endif
  5191.                         winhInsertMenuSeparator((HWND)mp2, MIT_END,
  5192.                                 (pGlobalSettings->VarMenuOffset
  5193.                                         + ID_XFMI_OFS_SEPARATOR));
  5194.                         winhInsertMenuItem((HWND)mp2, MIT_END,
  5195.                                 (pGlobalSettings->VarMenuOffset
  5196.                                         + ID_XFMI_OFS_PRODINFO),
  5197.                                 pNLSStrings->pszProductInfo,
  5198.                                 MIS_TEXT, 0);
  5199.                     break;
  5200.  
  5201.                     case 0x2D0: { // "Edit" submenu
  5202.                         // find position of "Deselect all" item
  5203.                         SHORT sPos = (SHORT)WinSendMsg((HWND)mp2,
  5204.                                     MM_ITEMPOSITIONFROMID,
  5205.                                     MPFROM2SHORT(0x73, FALSE),
  5206.                                     MPNULL);
  5207.                         #ifdef DEBUG_MENUS
  5208.                             _Pmpf(("  'Edit' menu found"));
  5209.                         #endif
  5210.                         // insert "Select by name" after that item
  5211.                         winhInsertMenuItem((HWND)mp2,
  5212.                                 sPos+1,
  5213.                                 (pGlobalSettings->VarMenuOffset
  5214.                                         + ID_XFMI_OFS_SELECTSOME),
  5215.                                 pNLSStrings->pszSelectSome,
  5216.                                 MIS_TEXT, 0);
  5217.                     break; }
  5218.  
  5219.                     case 0x2D1: { // "View" submenu
  5220.                         CNRINFO             CnrInfo;
  5221.                         #ifdef DEBUG_MENUS
  5222.                             _Pmpf(("  'View' menu found"));
  5223.                         #endif
  5224.                         // modify the "Sort" menu, as we would
  5225.                         // do it for context menus also
  5226.                         mnuModifySortMenu((HWND)mp2,
  5227.                                 XFolderGetData(psli->somSelf),
  5228.                                 pGlobalSettings,
  5229.                                 pNLSStrings);
  5230.                         winhQueryCnrInfo(psli->hwndCnr, CnrInfo);
  5231.                         // and now insert the "folder view" items
  5232.                         winhInsertMenuSeparator((HWND)mp2,
  5233.                                 MIT_END,
  5234.                                 (pGlobalSettings->VarMenuOffset + ID_XFMI_OFS_SEPARATOR));
  5235.                         mnuInsertFldrViewItems(psli->somSelf,
  5236.                                         (HWND)mp2,
  5237.                                         psli->hwndCnr,
  5238.                                         FALSE,
  5239.                                         &CnrInfo);
  5240.                     break; }
  5241.                 }
  5242.             }
  5243.         }
  5244.     }
  5245. }
  5246.  
  5247. /*
  5248.  * MenuSelect:
  5249.  *      this gets called from fnwpSubclassedFolderFrame
  5250.  *      when WM_MENUSELECT is received.
  5251.  *      We need this for three reasons:
  5252.  *      1) we will play a system sound, if desired;
  5253.  *      2) we need to swallow this for very large folder
  5254.  *         content menus, because for some reason, PM will
  5255.  *         select a random menu item after we have moved
  5256.  *         these menus on the screen;
  5257.  *      3) we can intercept certain menu items so that
  5258.  *         these don't get passed to wpMenuItemSelected.
  5259.  *         This is needed for menu items such as those in
  5260.  *         the "Sort" menu so that the menu is not dismissed
  5261.  *         after selection.
  5262.  *      WM_MENUSELECT parameters:
  5263.  *          mp1 USHORT usItem - selected menu item
  5264.  *              USHORT usPostCommand - TRUE: if we return TRUE,
  5265.  *                  a message will be posted to the owner.
  5266.  *          mp2 HWND - menu control wnd handle
  5267.  *      If we set pfDismiss to TRUE, wpMenuItemSelected will be
  5268.  *      called, and the menu will be dismissed.
  5269.  *      Otherwise the message will be swallowed.
  5270.  *      We return TRUE if the menu item has been handled here.
  5271.  *      Otherwise the default wnd proc will be used.
  5272.  */
  5273.  
  5274. // flags for fnwpSubclassedFolderFrame;
  5275. // these are set by fnwpFolderContentMenu.
  5276. // We can afford using global variables here
  5277. // because there will never be more than one
  5278. // open window at a time.
  5279. BOOL    fFldrContentMenuMoved = FALSE,
  5280.         fFldrContentMenuButtonDown = FALSE;
  5281.  
  5282. BOOL MenuSelect(PSUBCLASSEDLISTITEM psli, // in: frame information
  5283.                 MPARAM mp1, MPARAM mp2,   // in: mp1, mp2 from WM_MENUSELECT
  5284.                 BOOL *pfDismiss)          // out: dismissal flag
  5285. {
  5286.     BOOL fHandled = FALSE;
  5287.  
  5288.     // return value for WM_MENUSELECT;
  5289.     // TRUE means dismiss menu
  5290.     psli->usLastSelMenuItem = SHORT1FROMMP(mp1);
  5291.  
  5292.     // check if we have moved a folder content menu
  5293.     // (this flag is set by fnwpFolderContentMenu); for
  5294.     // some reason, PM gets confused with the menu items
  5295.     // then and automatically tries to select the menu
  5296.     // item under the mouse, so we swallow this one
  5297.     // message if (a) the folder content menu has been
  5298.     // moved by fnwpFolderContentMenu and (b) no mouse
  5299.     // button is pressed. These flags are all set by
  5300.     // fnwpFolderContentMenu.
  5301.     if (fFldrContentMenuMoved)
  5302.     {
  5303.         #ifdef DEBUG_MENUS
  5304.             _Pmpf(( "  FCMenuMoved set!"));
  5305.         #endif
  5306.         if (!fFldrContentMenuButtonDown) {
  5307.             // mouse was not pressed: swallow this
  5308.             // menu selection
  5309.             *pfDismiss = FALSE;
  5310.         } else {
  5311.             // mouse was pressed: allow selection
  5312.             // and unset flags
  5313.             *pfDismiss = TRUE;
  5314.             fFldrContentMenuButtonDown = FALSE;
  5315.             fFldrContentMenuMoved = FALSE;
  5316.         }
  5317.         fHandled = TRUE;
  5318.     } else {
  5319.         if (    (SHORT2FROMMP(mp1) == TRUE)
  5320.             && (    ((USHORT)mp1 <  0x8000) // avoid system menu
  5321.                  || ((USHORT)mp1 == 0x8020) // include context menu
  5322.                )
  5323.            )
  5324.         {
  5325.             HWND hwndCnr = xwpsQueryCnrFromFrame(psli->hwndFrame);
  5326.  
  5327.             // play system sound
  5328.             xthrPlaySystemSound(MMSOUND_XFLD_CTXTSELECT);
  5329.  
  5330.             // Now check if we have a menu item which we don't
  5331.             // want to see dismissed.
  5332.  
  5333.             if (hwndCnr) {
  5334.                 // first find out what kind of objects we have here
  5335.  
  5336.                 ULONG ulSelection = 0;
  5337.                 WPObject *pObject1 =
  5338.                      mnuQuerySelectedObject(psli->somSelf,
  5339.                             hwndCnr,
  5340.                             &ulSelection);
  5341.  
  5342.                 WPObject *pObject = pObject1;
  5343.  
  5344.                 #ifdef DEBUG_MENUS
  5345.                     _Pmpf(( "  Object selections: %d", ulSelection));
  5346.                 #endif
  5347.  
  5348.                 // dereference shadows
  5349.                 if (pObject)
  5350.                     if (_somIsA(pObject, _WPShadow))
  5351.                         pObject = _wpQueryShadowedObject(pObject, TRUE);
  5352.  
  5353.                 // now call the functions in menus.c for this,
  5354.                 // depending on the class of the object for which
  5355.                 // the menu was opened
  5356.                 if (pObject) {
  5357.                     if (_somIsA(pObject, _WPFileSystem))
  5358.                     {
  5359.                         fHandled = mnuFileSystemSelectingMenuItem(
  5360.                                 pObject1,   // note that we're passing
  5361.                                             // pObject1 instead of pObject;
  5362.                                             // pObject1 might be a shadow!
  5363.                                 SHORT1FROMMP(mp1),       // usItem
  5364.                                 (BOOL)SHORT2FROMMP(mp1), // fPostCommand
  5365.                                 (HWND)mp2,               // hwndMenu
  5366.                                 hwndCnr,
  5367.                                 ulSelection,             // SEL_* flags
  5368.                                 pfDismiss);              // dismiss-menu flag
  5369.                     }
  5370.  
  5371.                     if (    (!fHandled)
  5372.                          && (_somIsA(pObject, _WPFolder))
  5373.                        )
  5374.                     {
  5375.                         fHandled = mnuFolderSelectingMenuItem(pObject,
  5376.                                 SHORT1FROMMP(mp1),       // usItem
  5377.                                 (BOOL)SHORT2FROMMP(mp1), // fPostCommand
  5378.                                 (HWND)mp2,               // hwndMenu
  5379.                                 hwndCnr,
  5380.                                 ulSelection,             // SEL_* flags
  5381.                                 pfDismiss);              // dismiss-menu flag
  5382.                     }
  5383.  
  5384.                     if ( (fHandled) && (!(*pfDismiss)) )
  5385.                     {
  5386.                         // menu not to be dismissed: set the flag
  5387.                         // which will remove cnr source
  5388.                         // emphasis when the menu is dismissed
  5389.                         // later (WM_ENDMENU msg here)
  5390.                         psli->fRemoveSrcEmphasis = TRUE;
  5391.                     }
  5392.                 }
  5393.             }
  5394.         }
  5395.     }
  5396.     return (fHandled);
  5397. }
  5398.  
  5399. /*
  5400.  *@@ fnwpSubclassedFolderFrame:
  5401.  *          New window proc for subclassed folder frame windows.
  5402.  *          Folder frame windows are subclassed in XFolder::wpOpen
  5403.  *          (or XFldDisk::wpOpen for Disk views) with the address
  5404.  *          of this window procedure.
  5405.  *
  5406.  *          This is maybe the most central part of XFolder. Since
  5407.  *          most WPS methods are really just reacting to messages
  5408.  *          in the default WPS frame window proc, but for some
  5409.  *          features methods are just not sufficient, basically we
  5410.  *          simulate what the WPS does here by intercepting _lots_
  5411.  *          of messages before the WPS gets them.
  5412.  *
  5413.  *          Things we do in this proc:
  5414.  *          --  frame control manipulation for status bars
  5415.  *          --  Warp 4 folder menu bar manipulation (WM_INITMENU)
  5416.  *          --  handling of certain menu items w/out dismissing
  5417.  *              the menu; this calls functions in menus.c
  5418.  *          --  menu owner draw (folder content menus w/ icons);
  5419.  *              this calls functions in menus.c also
  5420.  *          --  container control messages: tree view auto-scroll,
  5421.  *              updating status bars etc.
  5422.  *          --  playing the new system sounds for menus and such
  5423.  *              by calling xthrPlaySystemSound.
  5424.  *
  5425.  *          Note that this function calls lots of "external" functions
  5426.  *          spread across all over the XFolder code. This reduces the
  5427.  *          code size of this function, which gets called very often,
  5428.  *          to avoid excessive use of the processor caches.
  5429.  */
  5430.  
  5431. MRESULT EXPENTRY fnwpSubclassedFolderFrame(HWND hwndFrame, ULONG msg, MPARAM mp1, MPARAM mp2)
  5432. {
  5433.     PTHREADGLOBALS pThreadGlobals = xthrQueryGlobals();
  5434.     ULONG           *pulWorkplaceFunc2 = &(pThreadGlobals->ulWorkplaceFunc2);
  5435.  
  5436.     PSUBCLASSEDLISTITEM psli = NULL;
  5437.     PFNWP           pfnwpOriginal = NULL;
  5438.  
  5439.     XFolder         *somSelf;
  5440.     MRESULT         mrc = MRFALSE;
  5441.     BOOL            fCallDefault = FALSE;
  5442.  
  5443.  
  5444.     *pulWorkplaceFunc2 = 100;
  5445.  
  5446.     TRY_LOUD(excpt1)   // install "loud" exception handler (except.h)
  5447.     {
  5448.         // find the original wnd proc in the
  5449.         // global linked list, so we can pass messages
  5450.         // on to it
  5451.         *pulWorkplaceFunc2 = 110;
  5452.         psli = cmnQueryPSLI(hwndFrame);
  5453.         if (psli) {
  5454.             pfnwpOriginal = psli->pfnwpOriginal;
  5455.             somSelf = psli->somSelf;
  5456.         }
  5457.  
  5458.         if (pfnwpOriginal)
  5459.         {
  5460.             *pulWorkplaceFunc2 = 120;
  5461.             switch(msg)
  5462.             {
  5463.                 /* *************************
  5464.                  *                         *
  5465.                  * Status bar:             *
  5466.                  *                         *
  5467.                  **************************/
  5468.  
  5469.                 case WM_QUERYFRAMECTLCOUNT: {
  5470.                     // query the standard frame controls count
  5471.                     ULONG ulrc = (ULONG)((*pfnwpOriginal)(hwndFrame, msg, mp1, mp2));
  5472.  
  5473.                     // if we have a status bar, increment the count
  5474.                     if (psli->hwndStatusBar)
  5475.                         ulrc++;
  5476.  
  5477.                     mrc = (MPARAM)ulrc;
  5478.                 break; }
  5479.  
  5480.                 /*
  5481.                  * WM_FORMATFRAME:
  5482.                  *    this message is sent to a frame window to calculate the sizes
  5483.                  *    and positions of all of the frame controls and the client window:
  5484.                  *          mp1     PSWP    pswp        structure array
  5485.                  *          mp2     PRECTL  pprectl     pointer to client window
  5486.                  *                                      rectangle
  5487.                  *          returns USHORT  ccount      count of the number of SWP
  5488.                  *                                      arrays returned
  5489.                  */
  5490.  
  5491.                 case WM_FORMATFRAME:
  5492.                 {
  5493.                     //  query the number of standard frame controls
  5494.                     ULONG ulCount = (ULONG)((*pfnwpOriginal)(hwndFrame, msg, mp1, mp2));
  5495.  
  5496.                     #ifdef DEBUG_STATUSBARS
  5497.                         _Pmpf(( "WM_FORMATFRAME ulCount = %d", ulCount ));
  5498.                     #endif
  5499.  
  5500.                     if (psli->hwndStatusBar)
  5501.                     {
  5502.                         // we have a status bar:
  5503.                         // format the frame
  5504.                         FormatFrame(psli, mp1, &ulCount);
  5505.  
  5506.                         // increment the number of frame controls
  5507.                         // to include our status bar
  5508.                         mrc = (MRESULT)(ulCount + 1);
  5509.                     } // end if (psli->hwndStatusBar)
  5510.                     else
  5511.                         mrc = (MRESULT)ulCount;
  5512.                 break; }
  5513.  
  5514.                 /*
  5515.                  * WM_CALCFRAMERECT:
  5516.                  *     this message occurs when an application uses the
  5517.                  *     WinCalcFrameRect function. Parameters:
  5518.                  *          mp1     PRECTL  pRect      rectangle structure
  5519.                  *          mp2     USHORT  usFrame    frame indicator
  5520.                  *          returns BOOL    rc         rectangle-calculated indicator
  5521.                  */
  5522.  
  5523.                 case WM_CALCFRAMERECT:
  5524.                 {
  5525.                     mrc = (*pfnwpOriginal)(hwndFrame, msg, mp1, mp2);
  5526.  
  5527.                     if (psli->hwndStatusBar)
  5528.                         // we have a status bar: calculate its rectangle
  5529.                         CalcFrameRect(mp1, mp2);
  5530.                 break; }
  5531.  
  5532.                 /* *************************
  5533.                  *                         *
  5534.                  * Menu items:             *
  5535.                  *                         *
  5536.                  **************************/
  5537.  
  5538.                 /*
  5539.                  * WM_INITMENU:
  5540.                  *      this message is sent to a frame whenever a menu
  5541.                  *      is about to be displayed. This is needed for
  5542.                  *      various menu features; see InitMenu() above.
  5543.                  */
  5544.  
  5545.                 case WM_INITMENU: {
  5546.                     // always call the default, in case someone else
  5547.                     // is subclassing folders (ObjectDesktop?!?)
  5548.                     mrc = (MRESULT)(*pfnwpOriginal)(hwndFrame, msg, mp1, mp2);
  5549.  
  5550.                     InitMenu(psli, mp1, mp2);
  5551.                 break; }
  5552.  
  5553.                 /*
  5554.                  * WM_MENUSELECT:
  5555.                  *      this is SENT to a menu owner by the menu control to
  5556.                  *      determine what to do right after a menu item has been
  5557.                  *      selected. If we return TRUE, the menu will be dismissed.
  5558.                  *      See MenuSelect() above.
  5559.                  */
  5560.  
  5561.                 case WM_MENUSELECT: {
  5562.                     BOOL fDismiss = TRUE;
  5563.  
  5564.                     #ifdef DEBUG_MENUS
  5565.                         _Pmpf(( "WM_MENUSELECT: mp1 = %lX/%lX, mp2 = %lX",
  5566.                                 SHORT1FROMMP(mp1),
  5567.                                 SHORT2FROMMP(mp1),
  5568.                                 mp2 ));
  5569.                     #endif
  5570.  
  5571.                     // always call the default, in case someone else
  5572.                     // is subclassing folders (ObjectDesktop?!?)
  5573.                     mrc = (MRESULT)(*pfnwpOriginal)(hwndFrame, msg, mp1, mp2);
  5574.  
  5575.                     // now handle our stuff; this might modify mrc to
  5576.                     // have the menu stay on the screen
  5577.                     if (MenuSelect(psli, mp1, mp2, &fDismiss))
  5578.                         mrc = (MRESULT)fDismiss;
  5579.                 break; }
  5580.  
  5581.                 /*
  5582.                  * WM_MENUEND:
  5583.                  *      this message occurs when a menu control is about to
  5584.                  *      terminate. We need to remove cnr source emphasis
  5585.                  *      if the user has requested a context menu from a
  5586.                  *      status bar.
  5587.                  */
  5588.  
  5589.                 case WM_MENUEND: {
  5590.                     #ifdef DEBUG_MENUS
  5591.                         _Pmpf(( "WM_MENUEND: mp1 = %lX, mp2 = %lX",
  5592.                                 mp1, mp2 ));
  5593.                         /* _Pmpf(( "  fFolderContentWindowPosChanged: %d",
  5594.                                 fFolderContentWindowPosChanged));
  5595.                         _Pmpf(( "  fFolderContentButtonDown: %d",
  5596.                                 fFolderContentButtonDown)); */
  5597.                     #endif
  5598.                     // menu opened from status bar?
  5599.                     if (psli->fRemoveSrcEmphasis) {
  5600.                         // if so, remove cnr source emphasis
  5601.                         WinSendMsg(psli->hwndCnr,
  5602.                                     CM_SETRECORDEMPHASIS,
  5603.                                     (MPARAM)NULL,   // undocumented: if precc == NULL,
  5604.                                                     // the whole cnr is given emphasis
  5605.                                     MPFROM2SHORT(FALSE,  // remove emphasis
  5606.                                             CRA_SOURCE));
  5607.                         // and make sure the container has the
  5608.                         // focus
  5609.                         WinSetFocus(HWND_DESKTOP, psli->hwndCnr);
  5610.                         // reset flag for next context menu
  5611.                         psli->fRemoveSrcEmphasis = FALSE;
  5612.                     }
  5613.  
  5614.                     // unset flag for WM_MENUSELECT above
  5615.                     fFldrContentMenuMoved = FALSE;
  5616.  
  5617.                     mrc = (MRESULT)(*pfnwpOriginal)(hwndFrame, msg, mp1, mp2);
  5618.                 break; }
  5619.  
  5620.                 /*
  5621.                  * WM_MEASUREITEM:
  5622.                  *      this msg is sent only once per owner-draw item when
  5623.                  *      PM needs to know its size. This gets sent to us for
  5624.                  *      items in folder content menus; the height of our items
  5625.                  *      will be the same as with non-owner-draw ones, but
  5626.                  *      we need to calculate the width according to the item
  5627.                  *      text. Return value: check mnuMeasureItem (menus.c)
  5628.                  */
  5629.  
  5630.                 case WM_MEASUREITEM: {
  5631.                     PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
  5632.                     *pulWorkplaceFunc2 = 300;
  5633.                     if ( (SHORT)mp1 > (pGlobalSettings->VarMenuOffset+ID_XFMI_OFS_VARIABLE) )
  5634.                     {
  5635.                         // call the measure-item func in menus.c
  5636.                         mrc = mnuMeasureItem((POWNERITEM)mp2, pGlobalSettings);
  5637.                     }
  5638.                     else
  5639.                         // none of our items: pass to original wnd proc
  5640.                         mrc = (MRESULT)(*pfnwpOriginal)(hwndFrame, msg, mp1, mp2);
  5641.                 break; }
  5642.  
  5643.                 /*
  5644.                  * WM_DRAWITEM:
  5645.                  *      this msg is sent for each item every time it
  5646.                  *      needs to be redrawn. This gets sent to us for
  5647.                  *      items in folder content menus.
  5648.                  */
  5649.  
  5650.                 case WM_DRAWITEM: {
  5651.                     PGLOBALSETTINGS pGlobalSettings =
  5652.                             cmnQueryGlobalSettings();
  5653.                     *pulWorkplaceFunc2 = 400;
  5654.                     if ( (SHORT)mp1 > (pGlobalSettings->VarMenuOffset+ID_XFMI_OFS_VARIABLE) )
  5655.                     {
  5656.                         // variable menu item: this must be a folder-content
  5657.                         // menu item, because for others no WM_DRAWITEM is sent
  5658.                         // (menus.c)
  5659.                         if (mnuDrawItem(pGlobalSettings,
  5660.                                     mp1, mp2))
  5661.                             mrc = (MRESULT)TRUE;
  5662.                         else // error occured:
  5663.                             mrc = (MRESULT)(*pfnwpOriginal)(hwndFrame, msg, mp1, mp2);
  5664.                     }
  5665.                     else
  5666.                         mrc = (MRESULT)(*pfnwpOriginal)(hwndFrame, msg, mp1, mp2);
  5667.                     *pulWorkplaceFunc2 = 499;
  5668.                 break; }
  5669.  
  5670.                 /* *************************
  5671.                  *                         *
  5672.                  * Miscellaneae:           *
  5673.                  *                         *
  5674.                  **************************/
  5675.  
  5676.                 /*
  5677.                  * WM_CHAR:
  5678.                  *      this is intercepted to provide folder hotkeys
  5679.                  */
  5680.  
  5681.                 case WM_CHAR: {
  5682.                     XFolderData         *somThis = XFolderGetData(somSelf);
  5683.                     PGLOBALSETTINGS pGlobalSettings =
  5684.                                         cmnQueryGlobalSettings();
  5685.  
  5686.                     if  (   (_bAcceleratorsAllowed == 1)
  5687.                         || ((_bAcceleratorsAllowed == 2) && (pGlobalSettings->Accelerators))
  5688.                         )
  5689.                     {
  5690.                         if (cmnProcessFldrHotkey(hwndFrame, mp1, mp2)) {
  5691.                             mrc = (MRESULT)TRUE;
  5692.                             break;
  5693.                         }
  5694.                     }
  5695.  
  5696.                     mrc = (MRESULT)(*pfnwpOriginal)(hwndFrame, msg, mp1, mp2);
  5697.                 break; }
  5698.  
  5699.                 /*
  5700.                  * WM_CONTROL:
  5701.                  *      this is intercepted to check for container
  5702.                  *      notifications we might be interested in
  5703.                  */
  5704.  
  5705.                 case WM_CONTROL: {
  5706.                     *pulWorkplaceFunc2 = 950;
  5707.                     if (SHORT1FROMMP(mp1) /* id */ == 0x8008) // container!!
  5708.                     {
  5709.                         #ifdef DEBUG_CNRCNTRL
  5710.                             CHAR szTemp2[30];
  5711.                             sprintf(szTemp2, "unknown: %d", SHORT2FROMMP(mp1));
  5712.                             _Pmpf(("Cnr cntrl msg: %s, mp2: %lX",
  5713.                                 (SHORT2FROMMP(mp1) == CN_BEGINEDIT) ? "CN_BEGINEDIT"
  5714.                                     : (SHORT2FROMMP(mp1) == CN_COLLAPSETREE) ? "CN_COLLAPSETREE"
  5715.                                     : (SHORT2FROMMP(mp1) == CN_CONTEXTMENU) ? "CN_CONTEXTMENU"
  5716.                                     : (SHORT2FROMMP(mp1) == CN_DRAGAFTER) ? "CN_DRAGAFTER"
  5717.                                     : (SHORT2FROMMP(mp1) == CN_DRAGLEAVE) ? "CN_DRAGLEAVE"
  5718.                                     : (SHORT2FROMMP(mp1) == CN_DRAGOVER) ? "CN_DRAGOVER"
  5719.                                     : (SHORT2FROMMP(mp1) == CN_DROP) ? "CN_DROP"
  5720.                                     : (SHORT2FROMMP(mp1) == CN_DROPNOTIFY) ? "CN_DROPNOTIFY"
  5721.                                     : (SHORT2FROMMP(mp1) == CN_DROPHELP) ? "CN_DROPHELP"
  5722.                                     : (SHORT2FROMMP(mp1) == CN_EMPHASIS) ? "CN_EMPHASIS"
  5723.                                     : (SHORT2FROMMP(mp1) == CN_ENDEDIT) ? "CN_ENDEDIT"
  5724.                                     : (SHORT2FROMMP(mp1) == CN_ENTER) ? "CN_ENTER"
  5725.                                     : (SHORT2FROMMP(mp1) == CN_EXPANDTREE) ? "CN_EXPANDTREE"
  5726.                                     : (SHORT2FROMMP(mp1) == CN_HELP) ? "CN_HELP"
  5727.                                     : (SHORT2FROMMP(mp1) == CN_INITDRAG) ? "CN_INITDRAG"
  5728.                                     : (SHORT2FROMMP(mp1) == CN_KILLFOCUS) ? "CN_KILLFOCUS"
  5729.                                     : (SHORT2FROMMP(mp1) == CN_PICKUP) ? "CN_PICKUP"
  5730.                                     : (SHORT2FROMMP(mp1) == CN_QUERYDELTA) ? "CN_QUERYDELTA"
  5731.                                     : (SHORT2FROMMP(mp1) == CN_REALLOCPSZ) ? "CN_REALLOCPSZ"
  5732.                                     : (SHORT2FROMMP(mp1) == CN_SCROLL) ? "CN_SCROLL"
  5733.                                     : (SHORT2FROMMP(mp1) == CN_SETFOCUS) ? "CN_SETFOCUS"
  5734.                                     : szTemp2,
  5735.                                 mp2));
  5736.                         #endif
  5737.  
  5738.                         switch (SHORT2FROMMP(mp1)) {
  5739.  
  5740.                             /*
  5741.                              * CN_BEGINEDIT:
  5742.                              *      this is sent by the container control
  5743.                              *      when direct text editing is about to
  5744.                              *      begin, that is, when the user alt-clicks
  5745.                              *      on an object title.
  5746.                              *      We'll select the file stem of the object.
  5747.                              */
  5748.  
  5749.                             /* case CN_BEGINEDIT: {
  5750.                                 PCNREDITDATA pced = (PCNREDITDATA)mp2;
  5751.                                 mrc = (MRESULT)(*pfnwpOriginal)(hwndFrame, msg, mp1, mp2);
  5752.                                 if (pced) {
  5753.                                     PMINIRECORDCORE pmrc = (PMINIRECORDCORE)pced->pRecord;
  5754.                                     if (pmrc) {
  5755.                                         // editing WPS record core, not title etc.:
  5756.                                         // get the window ID of the MLE control
  5757.                                         // in the cnr window
  5758.                                         HWND hwndMLE = WinWindowFromID(pced->hwndCnr,
  5759.                                                             CID_MLE);
  5760.                                         if (hwndMLE) {
  5761.                                             ULONG cbText = WinQueryWindowTextLength(
  5762.                                                                     hwndMLE)+1;
  5763.                                             PSZ pszText = malloc(cbText);
  5764.                                             _Pmpf(("textlen: %d", cbText));
  5765.                                             if (WinQueryWindowText(hwndMLE,
  5766.                                                                    cbText,
  5767.                                                                    pszText))
  5768.                                             {
  5769.                                                 PSZ pszLastDot = strrchr(pszText, '.');
  5770.                                                 _Pmpf(("text: %s", pszText));
  5771.                                                 WinSendMsg(hwndMLE,
  5772.                                                         EM_SETSEL,
  5773.                                                         MPFROM2SHORT(
  5774.                                                             // first char: 0
  5775.                                                             0,
  5776.                                                             // last char:
  5777.                                                             (pszLastDot)
  5778.                                                                 ? (pszLastDot-pszText)
  5779.                                                                 : 10000
  5780.                                                         ), MPNULL);
  5781.                                             }
  5782.                                             free(pszText);
  5783.                                         }
  5784.                                     }
  5785.                                 }
  5786.                             break; } */
  5787.  
  5788.                             /*
  5789.                              * CN_ENTER:
  5790.                              *      double-click or enter key:
  5791.                              *      play sound
  5792.                              */
  5793.  
  5794.                             case CN_ENTER:
  5795.                                 *pulWorkplaceFunc2 = 951;
  5796.                                 xthrPlaySystemSound(MMSOUND_XFLD_CNRDBLCLK);
  5797.                                 mrc = (MRESULT)(*pfnwpOriginal)(hwndFrame, msg, mp1, mp2);
  5798.                             break;
  5799.  
  5800.                             /*
  5801.                              * CN_EMPHASIS:
  5802.                              *      selection changed:
  5803.                              *      update status bar
  5804.                              */
  5805.  
  5806.                             case CN_EMPHASIS:
  5807.                                 *pulWorkplaceFunc2 = 952;
  5808.                                 mrc = (MRESULT)(*pfnwpOriginal)(hwndFrame, msg, mp1, mp2);
  5809.                                 if (psli->hwndStatusBar) {
  5810.                                     #ifdef DEBUG_STATUSBARS
  5811.                                         _Pmpf(( "CN_EMPHASIS: posting PM_UPDATESTATUSBAR to hwnd %lX", psli->hwndStatusBar ));
  5812.                                     #endif
  5813.                                     WinPostMsg(psli->hwndStatusBar,
  5814.                                              STBM_UPDATESTATUSBAR,
  5815.                                              MPNULL,
  5816.                                              MPNULL);
  5817.                                 }
  5818.                             break;
  5819.  
  5820.                             /*
  5821.                              * CN_EXPANDTREE:
  5822.                              *      tree view has been expanded:
  5823.                              *      do cnr auto-scroll
  5824.                              */
  5825.  
  5826.                             case CN_EXPANDTREE: {
  5827.                                 PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
  5828.                                 *pulWorkplaceFunc2 = 953;
  5829.                                 mrc = (MRESULT)(*pfnwpOriginal)(hwndFrame, msg, mp1, mp2);
  5830.                                 if (pGlobalSettings->TreeViewAutoScroll) {
  5831.                                     xthrPostWorkerMsg(WOM_TREEVIEWAUTOSCROLL,
  5832.                                             (MPARAM)hwndFrame,
  5833.                                             mp2); // PMINIRECORDCORE
  5834.                                 }
  5835.                             break; }
  5836.  
  5837.                             default:
  5838.                                 *pulWorkplaceFunc2 = 954;
  5839.                                 fCallDefault = TRUE;
  5840.                             break;
  5841.                         }
  5842.                     }
  5843.                 break; }
  5844.  
  5845.                 /*
  5846.                  * WM_CLOSE:
  5847.                  *      upon this, we need to clean up our linked list
  5848.                  *      of subclassed windows
  5849.                  */
  5850.  
  5851.                 case WM_CLOSE: {
  5852.                     // first remove the status bar to store the correct wnd size
  5853.                     // xfShowStatusBar(hwndFrame, psli->somSelf, psli, FALSE);
  5854.                     // then do the default stuff
  5855.                     *pulWorkplaceFunc2 = 990;
  5856.                     mrc = (MRESULT)(*pfnwpOriginal)(hwndFrame, msg, mp1, mp2);
  5857.                     // upon closing the window, undo the subclassing, in case
  5858.                     // some other message still comes in
  5859.                     WinSubclassWindow(hwndFrame, pfnwpOriginal);
  5860.                     // destroy the supplementary object window for this folder
  5861.                     // frame window
  5862.                     WinDestroyWindow(psli->hwndSupplObject);
  5863.                     // and remove this window from our subclassing linked list
  5864.                     cmnRemovePSLI(psli);
  5865.                 break; }
  5866.  
  5867.                 default:
  5868.                     fCallDefault = TRUE;
  5869.                 break;
  5870.  
  5871.             } // end switch
  5872.         } // end if (pfnwpOriginal)
  5873.         else {
  5874.             #ifdef DEBUG_MENUS
  5875.                 DosBeep(10000, 10);
  5876.             #endif
  5877.         }
  5878.     } CATCH(excpt1) {
  5879.         // exception occured:
  5880.         return (0);
  5881.     } END_CATCH;
  5882.  
  5883.     if (fCallDefault)
  5884.     {
  5885.         // this has only been set to TRUE for "default" in
  5886.         // the switch statement above; we then call the
  5887.         // default window procedure.
  5888.         // This is either the original folder frame window proc
  5889.         // of the WPS itself or maybe the one of other WPS enhancers
  5890.         // which have subclassed folder windows (ObjectDesktop
  5891.         // and the like).
  5892.         // We do this outside the TRY/CATCH stuff above so that
  5893.         // we don't get blamed for exceptions which we are not
  5894.         // responsible for. ;-)
  5895.         *pulWorkplaceFunc2 = 997;
  5896.         mrc = (MRESULT)(*pfnwpOriginal)(hwndFrame, msg, mp1, mp2);
  5897.         *pulWorkplaceFunc2 = 998;
  5898.     }
  5899.  
  5900.     *pulWorkplaceFunc2 = 999;
  5901.     return (mrc);
  5902. }
  5903.  
  5904. /*
  5905.  *@@ fnwpSupplObject:
  5906.  *      this is the wnd proc for the "Supplementary Object wnd"
  5907.  *      which is created for each folder frame window when it's
  5908.  *      subclassed. We need this window to handle additional
  5909.  *      messages which are not part of the normal message set,
  5910.  *      which is handled by fnwpSubclassedFolderFrame.
  5911.  *
  5912.  *      If we added additional messages to that proc, we'd probably
  5913.  *      ruin other WPS enhancers which might use the same message
  5914.  *      in a different context (ObjectDesktop?), so we use a
  5915.  *      different window.
  5916.  *
  5917.  *      We cannot use the global XFolder object window
  5918.  *      (fnwpXFolderObject, xthreads.c) because
  5919.  *      sometimes folder windows do not run in the main PM thread
  5920.  *      (TID 1), esp. when they're opened using WinOpenObject or
  5921.  *      REXX functions. This wnd proc always runs in the same
  5922.  *      thread as the folder frame wnd does.
  5923.  *
  5924.  *      This func is new with XFolder V0.82.
  5925.  */
  5926.  
  5927. MRESULT EXPENTRY fnwpSupplObject(HWND hwndObject, ULONG msg, MPARAM mp1, MPARAM mp2)
  5928. {
  5929.     MPARAM mrc = NULL;
  5930.     PSUBCLASSEDLISTITEM psli = (PSUBCLASSEDLISTITEM)
  5931.                 WinQueryWindowULong(hwndObject, QWL_USER);
  5932.  
  5933.     switch (msg) {
  5934.         case WM_CREATE:
  5935.             // set the USER window word to the SUBCLASSEDLISTITEM
  5936.             // structure which is passed to us upon window
  5937.             // creation (see cmnSubclassFrameWnd, which creates
  5938.             // us)
  5939.             mrc = WinDefWindowProc(hwndObject, msg, mp1, mp2);
  5940.             psli = (PSUBCLASSEDLISTITEM)mp1;
  5941.             WinSetWindowULong(hwndObject, QWL_USER, (ULONG)psli);
  5942.         break;
  5943.  
  5944.         /*
  5945.          * SOM_ACTIVATESTATUSBAR:
  5946.          *      add / remove / repaint the folder status bar;
  5947.          *      this is posted every time XFolder needs to change
  5948.          *      anything about status bars. We must not play with
  5949.          *      frame controls from threads other than the thread
  5950.          *      in which the status bar was created, i.e. the thread
  5951.          *      in which the folder frame is running (which, in most
  5952.          *      cases, is thread 1, the main PM thread of the WPS),
  5953.          *      because reformatting frame controls from other
  5954.          *      threads will cause PM hangs or WPS crashes.
  5955.          *      Parameters:
  5956.          *      ULONG mp1   0: disable (destroy) status bar
  5957.          *                  1: enable (create) status bar
  5958.          *                  2: update (reformat) status bar
  5959.          *      HWND  mp2:  hwndView (frame) to update
  5960.          */
  5961.  
  5962.         case SOM_ACTIVATESTATUSBAR: {
  5963.             HWND hwndFrame = (HWND)mp2;
  5964.             #ifdef DEBUG_STATUSBARS
  5965.                 _Pmpf(( "SOM_ACTIVATESTATUSBAR, mp1: %lX, psli: %lX", mp1, psli));
  5966.             #endif
  5967.  
  5968.             if (psli)
  5969.                 switch ((ULONG)mp1) {
  5970.                     case 0:
  5971.                         _xfShowStatusBar(psli->somSelf, psli, FALSE);
  5972.                     break;
  5973.  
  5974.                     case 1:
  5975.                         _xfShowStatusBar(psli->somSelf, psli, TRUE);
  5976.                     break;
  5977.  
  5978.                     default: {
  5979.                         // == 2 => update status bars; this is
  5980.                         // neccessary if the font etc. has changed
  5981.                         PSZ pszStatusBarFont =
  5982.                                 cmnQueryStatusBarSetting(SBS_STATUSBARFONT);
  5983.                         WinSendMsg(psli->hwndStatusBar, STBM_PROHIBITBROADCASTING,
  5984.                             (MPARAM)TRUE, MPNULL);
  5985.                         WinSetPresParam(psli->hwndStatusBar, PP_FONTNAMESIZE,
  5986.                              (ULONG)strlen(pszStatusBarFont) + 1, (PVOID)pszStatusBarFont);
  5987.                         WinSendMsg(hwndFrame, WM_UPDATEFRAME, MPNULL, MPNULL);
  5988.                         WinSendMsg(psli->hwndStatusBar, STBM_UPDATESTATUSBAR, MPNULL, MPNULL);
  5989.                     break; }
  5990.                 }
  5991.         break; }
  5992.  
  5993.         default:
  5994.             mrc = WinDefWindowProc(hwndObject, msg, mp1, mp2);
  5995.     }
  5996.     return (mrc);
  5997. }
  5998.  
  5999. /*
  6000.  *@@ fnwpFolderContentMenu:
  6001.  *      this is the subclassed wnd proc for folder content menus;
  6002.  *      we need to intercept mouse button 2 msgs to open a folder
  6003.  *      (WarpCenter behavior).
  6004.  */
  6005.  
  6006. MRESULT EXPENTRY fnwpFolderContentMenu(HWND hwndMenu, ULONG msg, MPARAM mp1, MPARAM mp2)
  6007. {
  6008.     PTHREADGLOBALS pThreadGlobals = xthrQueryGlobals();
  6009.     ULONG       *pulWorkplaceFunc2 = &(pThreadGlobals->ulWorkplaceFunc2);
  6010.     ULONG       ulOldWorkplaceFunc2 = *pulWorkplaceFunc2;
  6011.     MRESULT     mrc = 0;
  6012.  
  6013.     *pulWorkplaceFunc2 = 10000;
  6014.  
  6015.     TRY_LOUD(excpt1)   // install "loud" exception handler (except.h)
  6016.     {
  6017.         USHORT  sSelected;
  6018.         POINTL  ptlMouse;
  6019.         RECTL   rtlItem;
  6020.  
  6021.         switch(msg)
  6022.         {
  6023.             case WM_ADJUSTWINDOWPOS:
  6024.             {
  6025.                 PSWP pswp = (PSWP)mp1;
  6026.                 BOOL fAdjusted = FALSE;
  6027.                 #ifdef DEBUG_MENUS
  6028.                     _Pmpf(("WM_ADJUSTWINDOWPOS"));
  6029.                 #endif
  6030.  
  6031.                 if ((pswp->fl & (SWP_MOVE)) == (SWP_MOVE)) {
  6032.                     #ifdef DEBUG_MENUS
  6033.                         _Pmpf(("  SWP_MOVE set"));
  6034.                     #endif
  6035.  
  6036.                     if (!fFldrContentMenuMoved) {
  6037.                         #ifdef DEBUG_MENUS
  6038.                             _Pmpf(("    Checking bounds"));
  6039.                         #endif
  6040.                         if ((pswp->x + pswp->cx) >
  6041.                                 WinQuerySysValue(HWND_DESKTOP, SV_CXSCREEN))
  6042.                         {
  6043.                             pswp->x = 0;
  6044.                             #ifdef DEBUG_MENUS
  6045.                                 _Pmpf(("    Changed x pos"));
  6046.                             #endif
  6047.                             // avoid several changes for this menu;
  6048.                             // this flag is reset by WM_INITMENU in
  6049.                             // fnwpSubclassedFolderFrame
  6050.                             fFldrContentMenuMoved = TRUE;
  6051.                             fAdjusted = TRUE;
  6052.                         }
  6053.                         if ((pswp->y + pswp->cy) >
  6054.                                 WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN))
  6055.                         {
  6056.                             pswp->y = 0;
  6057.                             #ifdef DEBUG_MENUS
  6058.                                 _Pmpf(("    Changed y pos"));
  6059.                             #endif
  6060.                             // avoid several changes for this menu;
  6061.                             // this flag is reset by WM_INITMENU in
  6062.                             // fnwpSubclassedFolderFrame
  6063.                             fFldrContentMenuMoved = TRUE;
  6064.                             fAdjusted = TRUE;
  6065.                         }
  6066.                     }
  6067.                 }
  6068.                 if (fAdjusted)
  6069.                     pswp->fl |= (SWP_NOADJUST);
  6070.                 mrc = (MRESULT)(*pfnwpFolderContentMenuOriginal)(hwndMenu, msg, mp1, mp2);
  6071.                 fFldrContentMenuButtonDown = FALSE;
  6072.             break; }
  6073.  
  6074.             #ifdef DEBUG_MENUS
  6075.                 case MM_SELECTITEM: {
  6076.                     _Pmpf(( "MM_SELECTITEM: mp1 = %lX/%lX, mp2 = %lX",
  6077.                         SHORT1FROMMP(mp1),
  6078.                         SHORT2FROMMP(mp1),
  6079.                         mp2 ));
  6080.                     mrc = (MRESULT)(*pfnwpFolderContentMenuOriginal)(hwndMenu, msg, mp1, mp2);
  6081.                 break; }
  6082.             #endif
  6083.  
  6084.             case WM_BUTTON2DOWN:
  6085.                 #ifdef DEBUG_MENUS
  6086.                     _Pmpf(("WM_BUTTON2DOWN"));
  6087.                 #endif
  6088.  
  6089.                 ptlMouse.x = SHORT1FROMMP(mp1);
  6090.                 ptlMouse.y = SHORT2FROMMP(mp1);
  6091.                 WinSendMsg(hwndMenu, MM_SELECTITEM,
  6092.                     MPFROM2SHORT(MIT_NONE, FALSE),
  6093.                     MPFROM2SHORT(0, FALSE));
  6094.                 sSelected = winhQueryItemUnderMouse(hwndMenu, &ptlMouse, &rtlItem);
  6095.                 WinSendMsg(hwndMenu, MM_SETITEMATTR,
  6096.                         MPFROM2SHORT(sSelected,
  6097.                             FALSE),
  6098.                         MPFROM2SHORT(MIA_HILITED, MIA_HILITED)
  6099.                     );
  6100.             break;
  6101.  
  6102.             case WM_BUTTON1DOWN:
  6103.                 // let this be handled by the default proc
  6104.                 #ifdef DEBUG_MENUS
  6105.                     _Pmpf(("WM_BUTTON1DOWN"));
  6106.                 #endif
  6107.                 fFldrContentMenuButtonDown = TRUE;
  6108.                 mrc = (MRESULT)(*pfnwpFolderContentMenuOriginal)(hwndMenu, msg, mp1, mp2);
  6109.             break;
  6110.  
  6111.             case WM_BUTTON1DBLCLK:
  6112.             case WM_BUTTON2UP: {
  6113.                 // upon receiving these, we will open the object directly; we need to
  6114.                 // cheat a little bit because sending MM_SELECTITEM would open the submenu
  6115.                 #ifdef DEBUG_MENUS
  6116.                     _Pmpf(("WM_BUTTON2UP"));
  6117.                 #endif
  6118.                 fFldrContentMenuButtonDown = TRUE;
  6119.                 *pulWorkplaceFunc2 = 10100;
  6120.                 ptlMouse.x = SHORT1FROMMP(mp1);
  6121.                 ptlMouse.y = SHORT2FROMMP(mp1);
  6122.                 WinSendMsg(hwndMenu, MM_SELECTITEM,
  6123.                     MPFROM2SHORT(MIT_NONE, FALSE),
  6124.                     MPFROM2SHORT(0, FALSE));
  6125.                 sSelected = winhQueryItemUnderMouse(hwndMenu, &ptlMouse, &rtlItem);
  6126.  
  6127.                 xthrPlaySystemSound(MMSOUND_XFLD_CTXTSELECT);
  6128.  
  6129.                 WinPostMsg(WinQueryWindow(hwndMenu, QW_OWNER),
  6130.                     WM_COMMAND,
  6131.                     (MPARAM)sSelected,
  6132.                     MPFROM2SHORT(CMDSRC_MENU, FALSE));
  6133.             break; }
  6134.  
  6135.             default:
  6136.                 *pulWorkplaceFunc2 = 11000;
  6137.                 mrc = (MRESULT)(*pfnwpFolderContentMenuOriginal)(hwndMenu, msg, mp1, mp2);
  6138.                 *pulWorkplaceFunc2 = 11001;
  6139.             break;
  6140.         } // end switch
  6141.     }
  6142.     CATCH(excpt1) {
  6143.         // exception occured:
  6144.         return (MRESULT)0; // keep compiler happy
  6145.     } END_CATCH;
  6146.  
  6147.     *pulWorkplaceFunc2 = ulOldWorkplaceFunc2;
  6148.     return (mrc);
  6149. }
  6150.  
  6151. /*
  6152.  * fnwpSelectSome:
  6153.  *      dlg proc for "Select by name" window
  6154.  */
  6155.  
  6156. MRESULT EXPENTRY fnwpSelectSome(HWND hwndDlg, ULONG msg, MPARAM mp1, MPARAM mp2)
  6157. {
  6158.     MRESULT mrc = MPNULL;
  6159.  
  6160.     switch (msg) {
  6161.         case WM_INITDLG:  {
  6162.             CHAR szTitle[CCHMAXPATH];
  6163.             WinSetWindowULong(hwndDlg, QWL_USER, (ULONG)mp2); // Owner frame hwnd;
  6164.             WinQueryWindowText((HWND)mp2,
  6165.                     sizeof(szTitle),
  6166.                     szTitle);
  6167.             WinSetWindowText(hwndDlg, szTitle);
  6168.  
  6169.             WinSetDlgItemText(hwndDlg, ID_XFDI_SOME_ENTRYFIELD, "*");
  6170.             WinSendDlgItemMsg(hwndDlg, ID_XFDI_SOME_ENTRYFIELD,
  6171.                     EM_SETSEL,
  6172.                     MPFROM2SHORT(0, 1000), // select all
  6173.                     MPNULL);
  6174.  
  6175.             mrc = fnwpDlgGeneric(hwndDlg, msg, mp1, mp2);
  6176.         break; }
  6177.  
  6178.         case WM_COMMAND: {
  6179.             switch (SHORT1FROMMP(mp1)) {
  6180.  
  6181.                 /*
  6182.                  * ID_XFDI_SOME_SELECT / DESELECT:
  6183.                  *      these are the "select" / "deselect" buttons
  6184.                  */
  6185.  
  6186.                 case ID_XFDI_SOME_SELECT:
  6187.                 case ID_XFDI_SOME_DESELECT: {
  6188.                     CHAR szMask[CCHMAXPATH];
  6189.                     HWND hwndFrame = WinQueryWindowULong(hwndDlg, QWL_USER);
  6190.                     if (hwndFrame) {
  6191.  
  6192.                         HWND hwndCnr = xwpsQueryCnrFromFrame(hwndFrame);
  6193.  
  6194.                         if (hwndCnr) {
  6195.                             WinQueryDlgItemText(hwndDlg, ID_XFDI_SOME_ENTRYFIELD,
  6196.                                 sizeof(szMask),
  6197.                                 szMask);
  6198.  
  6199.                             if (strlen(szMask)) {
  6200.                                 // now go through all the container items in hwndCnr
  6201.                                 // and select / deselct them accordingly
  6202.                                 PMINIRECORDCORE pmrc = NULL;
  6203.                                 do {
  6204.                                     pmrc =
  6205.                                         (PMINIRECORDCORE)WinSendMsg(hwndCnr,
  6206.                                                 CM_QUERYRECORD,
  6207.                                                 (MPARAM)pmrc,
  6208.                                                 MPFROM2SHORT(
  6209.                                                     (pmrc) ? CMA_NEXT : CMA_FIRST,
  6210.                                                     CMA_ITEMORDER)
  6211.                                                 );
  6212.                                     if (pmrc) {
  6213.                                         CHAR szTarget[CCHMAXPATH];
  6214.                                         // CHAR szTemp[3000];
  6215.                                         DosEditName(1,
  6216.                                             pmrc->pszIcon,
  6217.                                             szMask,
  6218.                                             szTarget,
  6219.                                             sizeof(szTarget)-1);
  6220.                                         if (stricmp(pmrc->pszIcon, szTarget) == 0)
  6221.                                             // if the two are equal, the cnr item matches
  6222.                                             // the search mask
  6223.                                             WinSendMsg(hwndCnr,
  6224.                                                 CM_SETRECORDEMPHASIS,
  6225.                                                 pmrc,
  6226.                                                 MPFROM2SHORT(
  6227.                                                     // select or deselect flag
  6228.                                                     (SHORT1FROMMP(mp1) == ID_XFDI_SOME_SELECT),
  6229.                                                     CRA_SELECTED
  6230.                                                 ));
  6231.                                     }
  6232.                                 } while (pmrc);
  6233.                             }
  6234.  
  6235.                             winhSetDlgItemFocus(hwndDlg, ID_XFDI_SOME_ENTRYFIELD);
  6236.                             WinSendDlgItemMsg(hwndDlg, ID_XFDI_SOME_ENTRYFIELD,
  6237.                                     EM_SETSEL,
  6238.                                     MPFROM2SHORT(0, 1000), // select all
  6239.                                     MPNULL);
  6240.                         }
  6241.                     }
  6242.                 break; }
  6243.  
  6244.                 case ID_XFDI_SOME_SELECTALL:
  6245.                 case ID_XFDI_SOME_DESELECTALL: {
  6246.                     HWND hwndFrame = WinQueryWindowULong(hwndDlg, QWL_USER);
  6247.                     if (hwndFrame) {
  6248.                         HWND hwndCnr = xwpsQueryCnrFromFrame(hwndFrame);
  6249.                         if (hwndCnr) {
  6250.                             PMINIRECORDCORE pmrc = NULL;
  6251.                             do {
  6252.                                 pmrc =
  6253.                                     (PMINIRECORDCORE)WinSendMsg(hwndCnr,
  6254.                                             CM_QUERYRECORD,
  6255.                                             (MPARAM)pmrc,
  6256.                                             MPFROM2SHORT(
  6257.                                                 (pmrc) ? CMA_NEXT : CMA_FIRST,
  6258.                                                 CMA_ITEMORDER)
  6259.                                             );
  6260.                                 if (pmrc) {
  6261.                                     WinSendMsg(hwndCnr,
  6262.                                         CM_SETRECORDEMPHASIS,
  6263.                                         pmrc,
  6264.                                         MPFROM2SHORT(
  6265.                                             // select or deselect flag
  6266.                                             (SHORT1FROMMP(mp1) == ID_XFDI_SOME_SELECTALL),
  6267.                                             CRA_SELECTED
  6268.                                         ));
  6269.                                 }
  6270.                             } while (pmrc);
  6271.  
  6272.                             winhSetDlgItemFocus(hwndDlg, ID_XFDI_SOME_ENTRYFIELD);
  6273.                             WinSendDlgItemMsg(hwndDlg, ID_XFDI_SOME_ENTRYFIELD,
  6274.                                     EM_SETSEL,
  6275.                                     MPFROM2SHORT(0, 1000), // select all
  6276.                                     MPNULL);
  6277.                         }
  6278.                     }
  6279.                 break; }
  6280.  
  6281.                 default:
  6282.                     mrc = fnwpDlgGeneric(hwndDlg, msg, mp1, mp2);
  6283.             }
  6284.         break; }
  6285.  
  6286.         default:
  6287.             mrc = fnwpDlgGeneric(hwndDlg, msg, mp1, mp2);
  6288.     }
  6289.     return (mrc);
  6290. }
  6291.  
  6292.  
  6293.  
  6294.