home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: WPS_PM / WPS_PM.zip / xfld085s.zip / main / xfobj.c < prev    next >
C/C++ Source or Header  |  1999-02-26  |  83KB  |  1,946 lines

  1.  
  2. /*
  3.  *@@sourcefile xfobj.c:
  4.  *      This file contains the following major XFolder parts:
  5.  *
  6.  *      --  XFldObject SOM stuff
  7.  *
  8.  *      Check the other files starting with xf* for the
  9.  *      other XFolder classes.
  10.  *
  11.  *      XFldObject gives the other classes access to WPS
  12.  *      internals that cannot be reached otherwise. It
  13.  *      also initializes the whole XFolder environment
  14.  *      at WPS bootup by overriding M_XFldObject::wpclsInitData.
  15.  *
  16.  *      This class must always be installed.
  17.  *
  18.  *@@somclass XFldObject xfobj_
  19.  *@@somclass M_XFldObject xfobjM_
  20.  */
  21.  
  22. /*
  23.  *      Copyright (C) 1997-99 Ulrich Möller.
  24.  *      This file is part of the XFolder source package.
  25.  *      XFolder is free software; you can redistribute it and/or modify
  26.  *      it under the terms of the GNU General Public License as published
  27.  *      by the Free Software Foundation, in version 2 as it comes in the
  28.  *      "COPYING" file of the XFolder main distribution.
  29.  *      This program is distributed in the hope that it will be useful,
  30.  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
  31.  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  32.  *      GNU General Public License for more details.
  33.  */
  34.  
  35. /*
  36.  *  This file was generated by the SOM Compiler and Emitter Framework.
  37.  *  Generated using:
  38.  *      SOM Emitter emitctm: 2.42
  39.  */
  40.  
  41. #ifndef SOM_Module_xfobj_Source
  42. #define SOM_Module_xfobj_Source
  43. #endif
  44. #define XFldObject_Class_Source
  45. #define M_XFldObject_Class_Source
  46.  
  47. /*
  48.  *  Suggested #include order:
  49.  *  1)  os2.h
  50.  *  2)  C library headers
  51.  *  3)  SOM headers which work with precompiled header files
  52.  *  4)  headers in /helpers
  53.  *  5)  headers in /main with dlgids.h and common.h first
  54.  *  6)  #pragma hdrstop to prevent VAC++ crashes
  55.  *  7)  other needed SOM headers
  56.  *  8)  for non-SOM-class files: corresponding header (e.g. classlst.h)
  57.  */
  58.  
  59. #define INCL_DOSFILEMGR
  60. #define INCL_DOSMODULEMGR
  61. #define INCL_DOSPROCESS         // DosSleep, priorities, PIDs etc.
  62. #define INCL_DOSSEMAPHORES      // needed for xthreads.h
  63. #define INCL_DOSEXCEPTIONS
  64. #define INCL_DOSERRORS
  65.  
  66. #define INCL_WINWINDOWMGR
  67. #define INCL_WINPROGRAMLIST     // needed for WPProgram
  68. #define INCL_WINFRAMEMGR        // WM_FORMATFRAME, SC_CLOSE etc.
  69. #define INCL_WINSYS             // presparams, WinQuerySysValue()
  70. #define INCL_WINCOUNTRY         // WinCompareStrings, WinUpper
  71. #define INCL_WINPOINTERS
  72.  
  73. #define INCL_WINSHELLDATA       // profile funcs
  74. #define INCL_WINTIMER
  75. #define INCL_WINCLIPBOARD
  76. #define INCL_WININPUT           // WinQueryFocus etc.
  77.  
  78. #define INCL_WINDIALOGS
  79. #define INCL_WINMENUS           // needed for menus.h
  80. #define INCL_WINENTRYFIELDS
  81. #define INCL_WINBUTTONS
  82. #define INCL_WINSTDBOOK         // notebooks
  83. #define INCL_WINSTDCNR          // needed for winh.h
  84.  
  85. #include <os2.h>
  86.  
  87. // C library headers
  88. #include <stdio.h>
  89. #include <malloc.h>
  90.  
  91. // headers in /helpers
  92. #include "dosh.h"               // Control Program helper routines
  93. #include "winh.h"               // PM helper routines
  94.  
  95. #include "linklist.h"           // linked list helper routines
  96. #include "procstat.h"           // DosQProcStat handling
  97. #include "stringh.h"            // string helper routines
  98. #include "undoc.h"              // some undocumented stuff
  99. #include "wphandle.h"           // Henk Kelder's HOBJECT handling
  100.  
  101. // SOM headers which don't crash with prec. header files
  102. #pragma hdrstop                 // VAC++ keeps crashing otherwise
  103. #include "xfobj.ih"
  104.  
  105. // headers in /main
  106. #include "dlgids.h"             // all the IDs that are shared with NLS
  107. #include "common.h"             // the majestic XFolder include file
  108.  
  109. #include "classlst.h"           // SOM logic for "WPS Classes" page
  110. #include "cnrsort.h"            // container sort comparison functions
  111. #include "xthreads.h"           // XFolder threads; this includes threads.h
  112.  
  113. // other SOM headers
  114. #include "xfldr.h"              // needed for XFolder SOM methods
  115. #include "xfpgmf.ih"
  116. #include <wpdesk.h>             // WPDesktop
  117. #include <wpshadow.h>
  118.  
  119. #include "xwps.h"               // XFolder pseudo SOM functions
  120.  
  121. /*
  122.  * Global variables::
  123.  *
  124.  */
  125.  
  126. VOID FillCnrWithObjectUsage(HWND hwndCnr, WPObject *pObject);
  127. MRESULT EXPENTRY fnwpObjectUsage(HWND hwndDlg, ULONG msg, MPARAM mp1, MPARAM mp2);
  128.  
  129. /*
  130.  * XFOBJWINDATA:
  131.  *      structure for data exchange with XFolder instance data.
  132.  *      Created in WM_INITDLG.
  133.  */
  134.  
  135. typedef struct _XFOBJWINDATA
  136. {
  137.     SOMAny          *somSelf;
  138.     CHAR            szOldID[CCHMAXPATH];
  139.     HWND            hwndCnr;
  140.     CHAR            szOldObjectID[256];
  141.     BOOL            fEscPressed;
  142.     PRECORDCORE     preccExpanded;
  143. } XFOBJWINDATA, *PXFOBJWINDATA;
  144.  
  145. /*
  146.  * fnwpSettingsObjDetails:
  147.  *      notebook dlg func for XFldObject "Details" page.
  148.  *      Here's a trick how to interface the corresponding
  149.  *      SOM (WPS) object from within this procedure:
  150.  *      1)  declare a structure with all the data which is
  151.  *          needed in this wnd proc (see XFOBJWINDATA below)
  152.  *      2)  when inserting the notebook page, specify
  153.  *          somSelf as the pCreateParams parameter in the
  154.  *          PAGEINFO structure;
  155.  *      3)  somSelf is then passed in mp2 of WM_INITDLG;
  156.  *          with that message, we create our structure on
  157.  *          the heap and store the address to it in the
  158.  *          notebook's window words. We can then access
  159.  *          our structure from later messages too.
  160.  *      4)  Don't forget to free the structure at WM_DESTROY.
  161.  *
  162.  *@@changed 0.85 fixed object ID error message
  163.  */
  164.  
  165. MRESULT EXPENTRY fnwpSettingsObjDetails(HWND hwndDlg, ULONG msg, MPARAM mp1, MPARAM mp2)
  166. {
  167.     PXFOBJWINDATA   pWinData = (PXFOBJWINDATA)WinQueryWindowULong(hwndDlg, QWL_USER);
  168.     MRESULT         mrc = FALSE;
  169.  
  170.     switch(msg)
  171.     {
  172.         case WM_INITDLG: {
  173.             // we need to initialize SOM stuff to be able to
  174.             // access instance variables later
  175.             PSZ     pszObjectID;
  176.             CNRINFO CnrInfo;
  177.             pWinData = (PXFOBJWINDATA)_wpAllocMem((SOMAny*)mp2, sizeof(XFOBJWINDATA), NULL);
  178.             WinSetWindowPtr(hwndDlg, QWL_USER, pWinData);
  179.  
  180.             // somSelf is given to us in mp2 (see pCreateParams
  181.             // in XFldObject::xfAddObjectInternalsPage below)
  182.             pWinData->somSelf     = (SOMAny*)mp2;
  183.             // initialize the fields in the structure
  184.             pszObjectID = _wpQueryObjectID(pWinData->somSelf);
  185.             if (pszObjectID)
  186.                 strcpy(pWinData->szOldID, pszObjectID);
  187.             else
  188.                 strcpy(pWinData->szOldID, "");
  189.  
  190.             // make Warp 4 notebook buttons and move controls
  191.             winhAssertWarp4Notebook(hwndDlg,
  192.                     100,         // ID threshold
  193.                     WARP4_NOTEBOOK_OFFSET);   // move other controls offset (common.h)
  194.  
  195.             // setup container
  196.             pWinData->hwndCnr = WinWindowFromID(hwndDlg, ID_XSDI_DTL_CNR);
  197.             WinSendMsg(pWinData->hwndCnr, CM_QUERYCNRINFO,
  198.                         &CnrInfo, (MPARAM)sizeof(CnrInfo));
  199.             CnrInfo.pSortRecord = (PVOID)fnCompareName;
  200.             CnrInfo.flWindowAttr = CV_TREE | CV_TEXT | CA_TREELINE;
  201.             CnrInfo.cxTreeIndent = 30;
  202.             WinSendMsg(pWinData->hwndCnr, CM_SETCNRINFO,
  203.                     &CnrInfo,
  204.                     (MPARAM)(CMA_PSORTRECORD | CMA_FLWINDOWATTR | CMA_CXTREEINDENT));
  205.  
  206.             WinPostMsg(hwndDlg, WM_SETTINGS2DLG, 0, 0);
  207.  
  208.             mrc = WinDefDlgProc(hwndDlg, msg, mp1, mp2);
  209.         break; }
  210.  
  211.         case WM_SETTINGS2DLG: {
  212.             HPOINTER hptrOld = WinQueryPointer(HWND_DESKTOP);
  213.             WinSetPointer(HWND_DESKTOP, WinQuerySysPointer(HWND_DESKTOP, SPTR_WAIT, FALSE));
  214.             FillCnrWithObjectUsage(pWinData->hwndCnr, pWinData->somSelf);
  215.             WinSetPointer(HWND_DESKTOP, hptrOld);
  216.         }   // continue, no break
  217.  
  218.         case WM_ENABLEITEMS:
  219.         break;
  220.  
  221.         case WM_DLG2SETTINGS: {
  222.         break; }
  223.  
  224.         /*
  225.          * WM_TIMER:
  226.          *      timer for tree view auto-scroll
  227.          */
  228.  
  229.         case WM_TIMER: {
  230.             if ( ( pWinData->preccExpanded->flRecordAttr & CRA_EXPANDED) != 0 ) {
  231.                 PRECORDCORE     preccLastChild;
  232.                 WinStopTimer(WinQueryAnchorBlock(hwndDlg),
  233.                         hwndDlg,
  234.                         1);
  235.                 // scroll the tree view properly
  236.                 preccLastChild = WinSendMsg(pWinData->hwndCnr,
  237.                         CM_QUERYRECORD,
  238.                         pWinData->preccExpanded,   // expanded PRECORDCORE from CN_EXPANDTREE
  239.                     MPFROM2SHORT(CMA_LASTCHILD, CMA_ITEMORDER));
  240.                 if (preccLastChild) {
  241.                     // ULONG ulrc;
  242.                     winhCnrScrollToRecord(pWinData->hwndCnr,
  243.                             (PRECORDCORE)preccLastChild,
  244.                             CMA_TEXT,   // record text rectangle only
  245.                             TRUE);      // keep parent visible
  246.                 }
  247.             }
  248.         }
  249.  
  250.         /*
  251.          * WM_CONTROL:
  252.          *
  253.          */
  254.  
  255.         case WM_CONTROL:
  256.         {
  257.             if (SHORT1FROMMP(mp1) == ID_XSDI_DTL_CNR)
  258.                 switch (SHORT2FROMMP(mp1)) {
  259.  
  260.                     /*
  261.                      * CN_EXPANDTREE:
  262.                      *      do tree-view auto scroll
  263.                      */
  264.  
  265.                     case CN_EXPANDTREE: {
  266.                         PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
  267.                         mrc = WinDefDlgProc(hwndDlg, msg, mp1, mp2);
  268.                         if (pGlobalSettings->TreeViewAutoScroll) {
  269.                             pWinData->preccExpanded = (PRECORDCORE)mp2;
  270.                             WinStartTimer(WinQueryAnchorBlock(hwndDlg),
  271.                                     hwndDlg,
  272.                                     1,
  273.                                     100);
  274.                         }
  275.                     break; }
  276.  
  277.                     /*
  278.                      * CN_BEGINEDIT:
  279.                      *      when user alt-clicked on a recc
  280.                      */
  281.  
  282.                     case CN_BEGINEDIT: {
  283.                         pWinData->fEscPressed = TRUE;
  284.                         mrc = (MPARAM)0;
  285.                     break;}
  286.  
  287.                     /*
  288.                      * CN_REALLOCPSZ:
  289.                      *      just before the edit MLE is closed
  290.                      */
  291.  
  292.                     case CN_REALLOCPSZ: {
  293.                         PCNREDITDATA pced = (PCNREDITDATA)mp2;
  294.                         PSZ pszChanging = *(pced->ppszText);
  295.                         strcpy(pWinData->szOldObjectID, pszChanging);
  296.                         pWinData->fEscPressed = FALSE;
  297.                         mrc = (MPARAM)TRUE;
  298.                     break; }
  299.  
  300.                     /*
  301.                      * CN_ENDEDIT:
  302.                      *      recc text changed: update our data
  303.                      */
  304.  
  305.                     case CN_ENDEDIT: {
  306.                         if (!pWinData->fEscPressed) {
  307.                             PCNREDITDATA pced = (PCNREDITDATA)mp2;
  308.                             PSZ pszNew = *(pced->ppszText);
  309.                             BOOL fChange = FALSE;
  310.                             // has the object ID changed?
  311.                             if (strcmp(pWinData->szOldObjectID, pszNew) != 0)
  312.                             {
  313.                                 // is this a valid object ID?
  314.                                 if (    (pszNew[0] != '<')
  315.                                      || (*(pszNew + strlen(pszNew)-1) != '>')
  316.                                    )
  317.                                     cmnMessageBoxMsg(hwndDlg, 104, 108, MB_OK);
  318.                                         // fixed (V0.85)
  319.                                 else
  320.                                     // valid: confirm change
  321.                                     if (cmnMessageBoxMsg(hwndDlg, 107, 109, MB_YESNO) == MBID_YES)
  322.                                         fChange = TRUE;
  323.  
  324.                                 if (fChange)
  325.                                     _wpSetObjectID(pWinData->somSelf, pszNew);
  326.                                 else
  327.                                 {
  328.                                     // change aborted: restore old recc text
  329.                                     strcpy(((POBJECTUSAGERECORDCORE)(pced->pRecord))->szText,
  330.                                             pWinData->szOldObjectID);
  331.                                     WinSendMsg(pWinData->hwndCnr, CM_INVALIDATERECORD,
  332.                                         (MPARAM)pced->pRecord,
  333.                                         MPFROM2SHORT(1, CMA_TEXTCHANGED));
  334.                                 }
  335.                             }
  336.                         }
  337.                         mrc = (MPARAM)0;
  338.                     break; }
  339.  
  340.                     default:
  341.                         mrc = WinDefDlgProc(hwndDlg, msg, mp1, mp2);
  342.                     } // end switch
  343.             else
  344.                 mrc = WinDefDlgProc(hwndDlg, msg, mp1, mp2);
  345.         break; } // end of WM_CONTROL
  346.  
  347.         case WM_COMMAND: {
  348.             switch (SHORT1FROMMP(mp1))
  349.             {
  350.                 case DID_REFRESH: { // "Refresh" button
  351.                     HPOINTER hptrOld = WinQueryPointer(HWND_DESKTOP);
  352.                     WinSetPointer(HWND_DESKTOP, WinQuerySysPointer(HWND_DESKTOP, SPTR_WAIT, FALSE));
  353.                     WinSendMsg(pWinData->hwndCnr,
  354.                             CM_REMOVERECORD,
  355.                             NULL,
  356.                             MPFROM2SHORT(0, // remove all reccs
  357.                                     CMA_FREE));
  358.                     FillCnrWithObjectUsage(pWinData->hwndCnr, pWinData->somSelf);
  359.                     WinSetPointer(HWND_DESKTOP, hptrOld);
  360.                 break; }
  361.             }
  362.         break; } // end of WM_COMMAND
  363.  
  364.         case WM_HELP: {
  365.             PSZ pszHelpLibrary = cmnQueryHelpLibrary();
  366.             // always display help for the whole page, not for single items
  367.             if (!_wpDisplayHelp(pWinData->somSelf,
  368.                     ID_XSH_SETTINGS_OBJINTERNALS,
  369.                     pszHelpLibrary))
  370.             {
  371.                 cmnMessageBoxMsg(HWND_DESKTOP, 104, 134, MB_OK);
  372.             }
  373.         break; }
  374.  
  375.         default:
  376.             mrc = WinDefDlgProc(hwndDlg, msg, mp1, mp2);
  377.     }
  378.  
  379.     return (mrc);
  380. }
  381.  
  382. /* ******************************************************************
  383.  *                                                                  *
  384.  *   here come the XFldObject instance methods                      *
  385.  *                                                                  *
  386.  ********************************************************************/
  387.  
  388. /*
  389.  *@@ xfAddObjectInternalsPage:
  390.  *           this actually adds the "Internals" pages into all object notebooks,
  391.  *           if the Global Settings allow it
  392.  */
  393.  
  394. SOM_Scope ULONG  SOMLINK xfobj_xfAddObjectInternalsPage(XFldObject *somSelf,
  395.                                                             HWND hwndNotebook)
  396. {
  397.     PAGEINFO pi;
  398.     PSZ pszHelpLibrary = cmnQueryHelpLibrary();
  399.  
  400.     /* XFldObjectData *somThis = XFldObjectGetData(somSelf); */
  401.     XFldObjectMethodDebug("XFldObject","xfobj_xfAddObjectInternalsPages");
  402.  
  403.     // insert Shutdown settings page
  404.     memset((PCH)&pi, 0, sizeof(PAGEINFO));
  405.     pi.cb                  = sizeof(PAGEINFO);
  406.     pi.hwndPage            = NULLHANDLE;
  407.     pi.pfnwp               = fnwpSettingsObjDetails;
  408.     pi.resid               = NLS_MODULE;
  409.     pi.pCreateParams       = somSelf;
  410.                 // passed to fnwpSettingsObjDetails in mp2
  411.     pi.dlgid               = ID_XSD_OBJECTDETAILS;
  412.     pi.usPageStyleFlags    = BKA_STATUSTEXTON | BKA_MAJOR;   // major tab;
  413.     pi.usPageInsertFlags   = BKA_FIRST;
  414.     pi.usSettingsFlags     = 0; // don't enumerate in status line
  415.     pi.pszName             = cmnQueryNLSStrings()->pszInternals;
  416.  
  417.     pi.pszHelpLibraryName  = pszHelpLibrary;
  418.     pi.idDefaultHelpPanel  = ID_XSH_SETTINGS_OBJINTERNALS;
  419.  
  420.     return (_wpInsertSettingsPage(somSelf, hwndNotebook, &pi));
  421. }
  422.  
  423. /*
  424.  *@@ wpObjectReady:
  425.  *           this instance method is called by the system when
  426.  *           object awakening is complete and object data seems
  427.  *           to be stable in memory;
  428.  *           we will have this object's pointer stored
  429.  *           in a global list (maintained by the Worker thread)
  430.  *           so that XShutdown knows which objects are currently awake
  431.  */
  432.  
  433. /*
  434.  *@@ wpObjectReady:
  435.  *           this instance method is called by the system when
  436.  *           object awakening is complete and object data seems
  437.  *           to be stable in memory.
  438.  *           We will have this object's pointer stored
  439.  *           in a global list (maintained by the Worker thread)
  440.  *           so that XShutdown knows which objects are currently awake.
  441.  */
  442.  
  443. SOM_Scope void  SOMLINK xfobj_wpObjectReady(XFldObject *somSelf,
  444.                                               ULONG ulCode, WPObject* refObject)
  445. {
  446.     // XFldObjectData *somThis = XFldObjectGetData(somSelf);
  447.     XFldObjectMethodDebug("XFldObject","xfobj_wpObjectReady");
  448.  
  449.     XFldObject_parent_WPObject_wpObjectReady(somSelf, ulCode,
  450.                                              refObject);
  451.  
  452.     /* if (    (_somIsA(somSelf, _WPFolder))
  453.          || (_somIsA(somSelf, _WPAbstract))
  454.        ) */
  455.     {
  456.         xthrPostWorkerMsg(WOM_ADDAWAKEOBJECT,
  457.                 (MPARAM)somSelf,
  458.                 MPNULL);
  459.         // _fAddedToAwakeList = TRUE;
  460.     } /* else
  461.         _fAddedToAwakeList = FALSE; */
  462. }
  463.  
  464. /*
  465.  *@@ wpUnInitData:
  466.  *           reverse to wpInitData, this instance method is
  467.  *           called by the system when an object is made
  468.  *           dormant; we will have this object removed from our
  469.  *           global list of awake objects
  470.  */
  471.  
  472. /*
  473.  *@@ wpUnInitData:
  474.  *           reverse to XFldObject::wpObjectReady, this instance
  475.  *           method is called by the system when an object is made
  476.  *           dormant. We will have this object removed from our
  477.  *           global list of awake objects.
  478.  */
  479.  
  480. SOM_Scope void  SOMLINK xfobj_wpUnInitData(XFldObject *somSelf)
  481. {
  482.     // XFldObjectData *somThis = XFldObjectGetData(somSelf);
  483.     XFldObjectMethodDebug("XFldObject","xfobj_wpUnInitData");
  484.  
  485.     // if (_fAddedToAwakeList)
  486.         xthrPostWorkerMsg(WOM_REMOVEAWAKEOBJECT,
  487.                 (MPARAM)somSelf,
  488.                 MPNULL);
  489.  
  490.     XFldObject_parent_WPObject_wpUnInitData(somSelf);
  491. }
  492.  
  493. /*
  494.  *@@ wpFilterPopupMenu:
  495.  *           remove default entries according to global settings
  496.  */
  497.  
  498. /*
  499.  *@@ wpFilterPopupMenu:
  500.  *           remove default entries according to global settings.
  501.  */
  502.  
  503. SOM_Scope ULONG  SOMLINK xfobj_wpFilterPopupMenu(XFldObject *somSelf,
  504.                                                    ULONG ulFlags,
  505.                                                    HWND hwndCnr,
  506.                                                    BOOL fMultiSelect)
  507. {
  508.     ULONG ulMenuFilter = 0;
  509.     PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
  510.     // XFldObjectData *somThis = XFldObjectGetData(somSelf);
  511.     XFldObjectMethodDebug("XFldObject","xfobj_wpFilterPopupMenu");
  512.  
  513.     ulMenuFilter = XFldObject_parent_WPObject_wpFilterPopupMenu(somSelf,
  514.                                                          ulFlags,
  515.                                                          hwndCnr,
  516.                                                          fMultiSelect);
  517.     #ifdef DEBUG_MENUS
  518.         _Pmpf(("XFldObject::wpFilterPopupMenu: ulMenuFilter & CTXT_CRANOTHER: 0x%lX %d",
  519.                 ulMenuFilter, ((ulMenuFilter) & CTXT_CRANOTHER)));
  520.     #endif
  521.  
  522.     // now suppress default menu items according to
  523.     // Global Settings;
  524.     // the DefaultMenuItems field in pGlobalSettings is
  525.     // ready-made for this function; the "Workplace Shell"
  526.     // notebook page for removing menu items sets this field with
  527.     // the proper CTXT_xxx flags
  528.     return ((ulMenuFilter
  529.             // first we add "Create another", because for
  530.             // some reason it's always disabled if XFolder
  531.             // is installed; I don't know why
  532.             | CTXT_CRANOTHER )
  533.             // then disable items, this may include CTXT_CRANOTHER
  534.             & ~(pGlobalSettings->DefaultMenuItems)
  535.         );
  536. }
  537.  
  538. /*
  539.  *@@ wpModifyPopupMenu:
  540.  *           add my own popup menu entries
  541.  */
  542.  
  543. /*
  544.  *@@ wpModifyPopupMenu:
  545.  *           add my own popup menu entries.
  546.  */
  547.  
  548. SOM_Scope BOOL  SOMLINK xfobj_wpModifyPopupMenu(XFldObject *somSelf,
  549.                                                   HWND hwndMenu,
  550.                                                   HWND hwndCnr,
  551.                                                   ULONG iPosition)
  552. {
  553.     HWND        hwndSettingsMenu;
  554.     BOOL        rc;
  555.     MENUITEM    mi;
  556.     PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
  557.     PNLSSTRINGS pNLSStrings = cmnQueryNLSStrings();
  558.     // XFldObjectData *somThis = XFldObjectGetData(somSelf);
  559.     XFldObjectMethodDebug("XFldObject","xfobj_wpModifyPopupMenu");
  560.  
  561.     rc = (XFldObject_parent_WPObject_wpModifyPopupMenu(somSelf,
  562.                                                          hwndMenu,
  563.                                                          hwndCnr,
  564.                                                          iPosition));
  565.     if (pGlobalSettings->RemoveLockInPlaceItem) {
  566.         // first we need a handle to the WPObject's "Lock in place"
  567.         // submenu in the the folder's popup menu
  568.  
  569.         WinSendMsg(hwndMenu, MM_REMOVEITEM,
  570.             MPFROM2SHORT(ID_WPM_LOCKINPLACE, FALSE),
  571.             0);
  572.     }
  573.  
  574.     return rc;
  575. }
  576.  
  577. /*
  578.  *@@ wpMenuItemSelected:
  579.  *           process input when any menu item was selected
  580.  */
  581.  
  582. /*
  583.  *@@ wpMenuItemSelected:
  584.  *           process input when any menu item was selected.
  585.  */
  586.  
  587. SOM_Scope BOOL  SOMLINK xfobj_wpMenuItemSelected(XFldObject *somSelf,
  588.                                                    HWND hwndFrame,
  589.                                                    ULONG ulMenuId)
  590. {
  591.     PGLOBALSETTINGS     pGlobalSettings = cmnQueryGlobalSettings();
  592.     BOOL                brc = FALSE;
  593.  
  594.     // XFldObjectData *somThis = XFldObjectGetData(somSelf);
  595.     XFldObjectMethodDebug("XFldObject","xfobj_wpMenuItemSelected");
  596.  
  597.     switch (ulMenuId) {
  598.         #ifdef DEBUG_CONTEXT
  599.         case ID_XFMI_RECORDCORE: {
  600.             int                 i;
  601.             CHAR                szMsg[1024] = "No record core.",
  602.                                 szTitle[1024],
  603.                                 szBuf[20] = "0x00000000";
  604.             PMINIRECORDCORE     pMRC = _wpQueryCoreRecord(somSelf);
  605.             PCLASSFIELDINFO     pCFI, pCFI2;
  606.             ULONG               ulCFISize = 0, ulErr;
  607.  
  608.             strcpy(szTitle, "Record core for ");
  609.             strcat(szTitle, _wpQueryTitle(somSelf));
  610.  
  611.             strcpy(szMsg, "Size of core record (cb): ");
  612.             UL2H(szBuf+2, pMRC->cb);
  613.             strcat(szMsg, szBuf);
  614.  
  615.             strcat(szMsg, "\nSize of MINIRECORDCORE:   ");
  616.             UL2H(szBuf+2, sizeof(MINIRECORDCORE));
  617.             strcat(szMsg, szBuf);
  618.  
  619.             strcat(szMsg, "\nSize of RECORDCORE:       ");
  620.             UL2H(szBuf+2, sizeof(RECORDCORE));
  621.             strcat(szMsg, szBuf);
  622.  
  623.             strcat(szMsg, "\nNext record:              ");
  624.             UL2H(szBuf+2, (ULONG)pMRC->preccNextRecord);
  625.             strcat(szMsg, szBuf);
  626.  
  627.             strcat(szMsg, "\nIcon X pos:               ");
  628.             UL2H(szBuf+2, pMRC->ptlIcon.x);
  629.             strcat(szMsg, szBuf);
  630.  
  631.             strcat(szMsg, "\nIcon Y pos:               ");
  632.             UL2H(szBuf+2, pMRC->ptlIcon.y);
  633.             strcat(szMsg, szBuf);
  634.  
  635.             strcat(szMsg, "\n\nDetails CLASSFIELDINFO:");
  636.  
  637.             strcat(szMsg, "\nSize of structure:        ");
  638.             _wpQueryDetailsData(somSelf, NULL, &ulCFISize);
  639.             UL2H(szBuf+2, ulCFISize);
  640.             strcat(szMsg, szBuf);
  641.  
  642.             pCFI = (PCLASSFIELDINFO)_wpAllocMem(somSelf, ulCFISize, &ulErr);
  643.             pCFI2 = pCFI;
  644.             _wpQueryDetailsData(somSelf, (PVOID)&pCFI2, &ulCFISize);
  645.  
  646.             _wpFreeMem(somSelf, (PVOID)pCFI);
  647.  
  648.             DebugBox(szTitle, szMsg);
  649.  
  650.             brc = TRUE;
  651.         break; }
  652.  
  653.         case ID_XFMI_SHOWFOLDERDATA: {
  654.             xthrPostWorkerMsg(WM_SHOWFOLDERDATA,
  655.                 (MPARAM)somSelf,
  656.                 MPNULL);
  657.             brc = TRUE;
  658.         break; }
  659.         #endif
  660.  
  661.         default:
  662.             brc = XFldObject_parent_WPObject_wpMenuItemSelected(somSelf,
  663.                                                           hwndFrame,
  664.                                                           ulMenuId);
  665.     }
  666.  
  667.     return (brc);
  668. }
  669.  
  670. /*
  671.  *@@ wpAddSettingsPages:
  672.  *           this instance method inserts all the settings
  673.  *           pages into an object's settings notebook.
  674.  *           We will add the object's "Internals" page here.
  675.  */
  676.  
  677. SOM_Scope BOOL  SOMLINK xfobj_wpAddSettingsPages(XFldObject *somSelf,
  678.                                                  HWND hwndNotebook)
  679. {
  680.     PGLOBALSETTINGS     pGlobalSettings = cmnQueryGlobalSettings();
  681.     // XFldObjectData *somThis = XFldObjectGetData(somSelf);
  682.     XFldObjectMethodDebug("XFldObject","xfobj_wpAddSettingsPages");
  683.  
  684.     if (pGlobalSettings->ShowInternals)
  685.         _xfAddObjectInternalsPage(somSelf, hwndNotebook);
  686.  
  687.     return (XFldObject_parent_WPObject_wpAddSettingsPages(somSelf,
  688.                                                           hwndNotebook));
  689. }
  690.  
  691. /*
  692.  *@@ fnwpTitleClashDlg:
  693.  *      dlg proc for the "File exists" dialog.
  694.  *      Most of the logic for that dialog is in the
  695.  *      XFldObject::wpConfirmObjectTitle method actually; this
  696.  *      function is only responsible for adjusting the dialog items'
  697.  *      keyboard focus and such.
  698.  */
  699.  
  700. MRESULT EXPENTRY fnwpTitleClashDlg(HWND hwndDlg, ULONG msg, MPARAM mp1, MPARAM mp2)
  701. {
  702.     #define WM_DELAYEDFOCUS WM_USER+1
  703.     MRESULT mrc = (MRESULT)0;
  704.  
  705.     switch (msg) {
  706.  
  707.         /*
  708.          * WM_CONTROL:
  709.          *      intercept focus messages and
  710.          *      set focus to what we really want
  711.          */
  712.  
  713.         case WM_CONTROL: {
  714.             switch (SHORT2FROMMP(mp1)) // usNotifyCode
  715.             {
  716.                 case EN_SETFOCUS: {
  717.                 // == BN_CLICKED
  718.                     if (SHORT1FROMMP(mp1) == ID_XFDI_CLASH_RENAMENEWTXT) {
  719.                         winhSetDlgItemChecked(hwndDlg, ID_XFDI_CLASH_RENAMENEW, TRUE);
  720.                     } else if (SHORT1FROMMP(mp1) == ID_XFDI_CLASH_RENAMEOLDTXT) {
  721.                         winhSetDlgItemChecked(hwndDlg, ID_XFDI_CLASH_RENAMEOLD, TRUE);
  722.                     } else if (SHORT1FROMMP(mp1) == ID_XFDI_CLASH_RENAMENEW) {
  723.                         WinPostMsg(hwndDlg, WM_DELAYEDFOCUS,
  724.                             (MPARAM)ID_XFDI_CLASH_RENAMENEWTXT, MPNULL);
  725.                     } else if (SHORT1FROMMP(mp1) == ID_XFDI_CLASH_RENAMEOLD) {
  726.                         WinPostMsg(hwndDlg, WM_DELAYEDFOCUS,
  727.                             (MPARAM)ID_XFDI_CLASH_RENAMEOLDTXT, MPNULL);
  728.                     }
  729.                 }
  730.             }
  731.         break; }
  732.  
  733.         case WM_DELAYEDFOCUS: {
  734.             winhSetDlgItemFocus(hwndDlg, (HWND)mp1);
  735.         break; }
  736.  
  737.         /*
  738.          * WM_COMMAND:
  739.          *      intercept "OK"/"Cancel" buttons
  740.          */
  741.  
  742.         case WM_COMMAND: {
  743.             mrc = (MRESULT)0;
  744.             switch ((ULONG)mp1)
  745.             {
  746.                 case DID_OK: {
  747.                     ULONG ulSelection = DID_CANCEL,
  748.                           ulLastFocusID = 0;
  749.                     CHAR szLastFocusID[20] = "";
  750.                     if (winhIsDlgItemChecked(hwndDlg, ID_XFDI_CLASH_RENAMENEW)) {
  751.                         ulSelection = ID_XFDI_CLASH_RENAMENEW;
  752.                         ulLastFocusID = ID_XFDI_CLASH_RENAMENEWTXT;
  753.                     } else if (winhIsDlgItemChecked(hwndDlg, ID_XFDI_CLASH_RENAMEOLD)) {
  754.                         ulSelection = ID_XFDI_CLASH_RENAMEOLD;
  755.                         ulLastFocusID = ID_XFDI_CLASH_RENAMEOLDTXT;
  756.                     } else {
  757.                         ulSelection = ID_XFDI_CLASH_REPLACE;
  758.                         ulLastFocusID = ID_XFDI_CLASH_REPLACE;
  759.                     }
  760.  
  761.                     // store focus
  762.                     sprintf(szLastFocusID, "%d",
  763.                             ulLastFocusID);
  764.                     PrfWriteProfileString(HINI_USER, INIAPP_XFOLDER,
  765.                                 INIKEY_NAMECLASHFOCUS,
  766.                                 szLastFocusID);
  767.                     // store window pos
  768.                     winhSaveWindowPos(hwndDlg,
  769.                                 HINI_USER,
  770.                                 INIAPP_XFOLDER, INIKEY_WNDPOSNAMECLASH);
  771.                     WinDismissDlg(hwndDlg, ulSelection);
  772.                 break; }
  773.  
  774.                 case DID_CANCEL:
  775.                     WinDismissDlg(hwndDlg, DID_CANCEL);
  776.                 break;
  777.             }
  778.         break; }
  779.  
  780.         case WM_HELP: {
  781.             WPObject    *pHelpSomSelf = _wpclsQueryActiveDesktop(_WPDesktop);
  782.             if (pHelpSomSelf) {
  783.                 PSZ pszHelpLibrary;
  784.                 BOOL fProcessed = FALSE;
  785.                 if (pszHelpLibrary = cmnQueryHelpLibrary())
  786.                     // path found: display help panel
  787.                     if (_wpDisplayHelp(pHelpSomSelf, ID_XFH_TITLECLASH, pszHelpLibrary))
  788.                         fProcessed = TRUE;
  789.  
  790.                 if (!fProcessed)
  791.                     cmnMessageBoxMsg(HWND_DESKTOP, 104, 134, MB_OK);
  792.             }
  793.         break; }
  794.  
  795.         default:
  796.             mrc = WinDefDlgProc(hwndDlg, msg, mp1, mp2);
  797.     }
  798.  
  799.     return (mrc);
  800. }
  801.  
  802. // the return codes are only #define'd in the Warp 4 Toolkit,
  803. // so we might need to define them here:
  804. #ifndef NAMECLASH_CANCEL
  805.     #define NAMECLASH_CANCEL    0
  806. #endif
  807. #ifndef NAMECLASH_NONE
  808.     #define NAMECLASH_NONE      1
  809. #endif
  810. #ifndef NAMECLASH_RENAME
  811.     #define NAMECLASH_RENAME    2
  812. #endif
  813. #ifndef NAMECLASH_REPLACE
  814.     #define NAMECLASH_REPLACE   8
  815. #endif
  816.  
  817. /*
  818.  *@@ wpConfirmObjectTitle:
  819.  *           this instance method is called by the WPS during file
  820.  *           operations (copy, move, rename etc.) for every single
  821.  *           file that is being processed. This method must verify
  822.  *           that the operation is valid WRT name clashes and display
  823.  *           a confirmation dialog in case it is not.
  824.  *           Apparently, this method is not overridden by subclasses,
  825.  *           not even WPFileSystem.
  826.  *           XFolder implements its own "Object exists" dialog here,
  827.  *           if the Global Settings allow it.
  828.  *           Like most interesting methods in the WPS, this thing is
  829.  *           barely documented, so this is what I found out.
  830.  *
  831.  *           Parameters:
  832.  *           -- *somSelf      in: the object being worked on
  833.  *           -- *Folder       in: the folder being worked on
  834.  *           -- **ppDuplicate out: if we return NAMECLASH_REPLACE,
  835.  *                            we need to set this to the object to
  836.  *                            be replaced
  837.  *           -- pszTitle      out: if we return NAMECLASH_RENAME,
  838.  *                            we need to set this to somSelf's new title
  839.  *           -- cbTitle       in: sizeof(*pszTitle)
  840.  *           -- menuID        in: the user's operation, which is:
  841.  *                              0x006B    move
  842.  *                              0x006C    copy
  843.  *                              0x006E    rename
  844.  *                              0x013C    create shadow
  845.  *
  846.  *           Returns:
  847.  *           -- NAMECLASH_CANCEL (0):
  848.  *                  abort processing, have the WPS do nothing ("Cancel"
  849.  *                  button pressed in confirmation dialog); this will
  850.  *                  just skip the current file;
  851.  *           -- NAMECLASH_NONE (1):
  852.  *                  continue processing, but perform no further
  853.  *                  renaming etc.; we return this if no duplicate file
  854.  *                  exists;
  855.  *           -- NAMECLASH_RENAME (2):
  856.  *                  have the WPS change the title to pszTitle, which we
  857.  *                  need to set here; note that this does NOT change
  858.  *                  the real name! So we do the renaming ourselves here;
  859.  *           -- NAMECLASH_REPLACE (8):
  860.  *                  have the WPS delete *ppDuplicate, which we need to
  861.  *                  set here if we return this code; we need to find the
  862.  *                  duplicate in this method then.
  863.  */
  864.  
  865. SOM_Scope ULONG  SOMLINK xfobj_wpConfirmObjectTitle(XFldObject *somSelf,
  866.                                                     WPFolder* Folder,
  867.                                                     WPObject** ppDuplicate,
  868.                                                     PSZ pszTitle,
  869.                                                     ULONG cbTitle,
  870.                                                     ULONG menuID)
  871. {
  872.     ULONG ulrc = NAMECLASH_NONE;
  873.  
  874.     PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
  875.  
  876.     // XFldObjectData *somThis = XFldObjectGetData(somSelf);
  877.     XFldObjectMethodDebug("XFldObject","xfobj_wpConfirmObjectTitle");
  878.  
  879.     #ifdef DEBUG_TITLECLASH
  880.     {
  881.         CHAR szFolder2[CCHMAXPATH];
  882.         _Pmpf(("Entering wpConfirmObjectTitle"));
  883.         _Pmpf(("  somSelf == 0x%lX", somSelf));
  884.         _Pmpf(("    pszTitle: %s", pszTitle));
  885.         _wpQueryFilename(_wpQueryFolder(somSelf), szFolder2, TRUE);
  886.         _Pmpf(("    in folder: %s", szFolder2));
  887.         _Pmpf(("  menuID: 0x%lX", menuID));
  888.     }
  889.     #endif
  890.  
  891.     // first of all, check whether the confirmation
  892.     // dialogs have been replaced in the global settings;
  893.     // if not, we call the default method
  894.     if (pGlobalSettings->ReplConfirms)
  895.     {
  896.         // nameclashs are only a problem for file-system objects,
  897.         // and only if we're not creating shadows
  898.         if (    (_somIsA(somSelf, _WPFileSystem))
  899.              && (menuID != 0x13C) // "create shadow" code
  900.            )
  901.         {
  902.             WPFileSystem *pobjExisting = NULL;
  903.             CHAR szNewRealName[CCHMAXPATH],
  904.                  szTemp[600],
  905.                  szFolder[CCHMAXPATH];
  906.             BOOL fFAT;
  907.  
  908.             // check whether the target folder is valid
  909.             if (Folder) {
  910.                 if (!_wpQueryFilename(Folder, szFolder, TRUE))
  911.                     return (NAMECLASH_CANCEL);
  912.             } else
  913.                 return (NAMECLASH_CANCEL);
  914.  
  915.             // before checking names, determine whether
  916.             // the folder is on a FAT drive; we need this
  917.             // flag for title-to-realname translations later
  918.             fFAT = doshIsFileOnFAT(szFolder);
  919.  
  920.             // this is not trivial, since we need to take
  921.             // in account all the FAT and HPFS file name
  922.             // conversion.
  923.             // 1)   get real name, unless we're renaming;
  924.             //      we then need to check for pszTitle
  925.             if (menuID != 0x6E)    // not "rename" code
  926.                 _wpQueryFilename(somSelf, szTemp, FALSE);
  927.                 // (V0.84) this now does work for FAT to FAT;
  928.                 // HPFS to FAT needs to be checked
  929.             else
  930.                 strcpy(szTemp, pszTitle);
  931.             // 2)   if the file is on FAT, make this 8+3
  932.             doshMakeRealName(szNewRealName,   // buffer
  933.                             szTemp,
  934.                             '!',              // replace-with char
  935.                             fFAT);
  936.             // this should mimic the default WPS behavior close enough
  937.  
  938.             #ifdef DEBUG_TITLECLASH
  939.                 _Pmpf(("  Checking for existence of %s", szNewRealName));
  940.             #endif
  941.  
  942.             // does this file exist in pFolder?
  943.             pobjExisting = xwpsContainsFile(Folder, szNewRealName);
  944.             if (pobjExisting)
  945.             {
  946.                 #ifdef DEBUG_TITLECLASH
  947.                     CHAR szFolder2[CCHMAXPATH];
  948.                     _Pmpf(("  pObjExisting == 0x%lX", pobjExisting));
  949.                     _Pmpf(("    Title: %s", _wpQueryTitle(pobjExisting) ));
  950.                     _wpQueryFilename(_wpQueryFolder(pobjExisting), szFolder2, TRUE);
  951.                     _Pmpf(("    in folder: %s", szFolder2));
  952.                 #endif
  953.  
  954.                 // file exists: now we need to differentiate.
  955.                 // 1)   If we're copying, we need to always
  956.                 //      display the confirmation.
  957.                 // 2)   If we're renaming somSelf, we only
  958.                 //      display the confirmation if the
  959.                 //      existing object is != somSelf, because
  960.                 //      otherwise we have no problem.
  961.                 /* if  (   (menuID != 0x6E)    // not "rename" code
  962.                      || (   (menuID == 0x6E)
  963.                          && (somSelf != pobjExisting)
  964.                         )
  965.                     ) */
  966.                 if (    (somSelf != pobjExisting)
  967.                      || (menuID != 0x6E)    // not "rename"
  968.                    )
  969.                 {
  970.                     CHAR    szProposeTitle[CCHMAXPATH],
  971.                             szProposeRealName[CCHMAXPATH],
  972.                             szFileCount[20],
  973.                             szSelfFilename[CCHMAXPATH],
  974.                             szExistingFilename[CCHMAXPATH];
  975.                     ULONG   ulDlgReturn = 0,
  976.                             ulLastFocusID = 0,
  977.                             ulLastDot = 0;
  978.                     PSZ     p, p2;
  979.                     BOOL    fReplaceValid = TRUE,
  980.                             fFileExists = FALSE;
  981.                     LONG    lFileCount = -1;
  982.                     HWND    hwndConfirm;
  983.  
  984.                     // prepare file date/time etc. for
  985.                     // display in window
  986.                     FILESTATUS3 fs3;
  987.                     ULONG ulDateFormat =
  988.                         PrfQueryProfileInt(HINI_USER, "PM_National", "iDate", 0);
  989.                     ULONG ulTimeFormat =
  990.                         PrfQueryProfileInt(HINI_USER, "PM_National", "iTime", 0);
  991.                     CHAR szDateSep[10],
  992.                          szTimeSep[10],
  993.                          szThousand[10];
  994.                     PrfQueryProfileString(HINI_USER, "PM_National", "sDate", "/",
  995.                         szDateSep, sizeof(szDateSep)-1);
  996.                     PrfQueryProfileString(HINI_USER, "PM_National", "sTime", ":",
  997.                         szTimeSep, sizeof(szTimeSep)-1);
  998.                     PrfQueryProfileString(HINI_USER, "PM_Default_National", "sThousand",
  999.                             ",", szThousand, sizeof(szThousand)-1);
  1000.  
  1001.                     // *** load confirmation dialog
  1002.                     hwndConfirm = WinLoadDlg(HWND_DESKTOP, HWND_DESKTOP,
  1003.                                       fnwpTitleClashDlg,
  1004.                                       NLS_MODULE, ID_XFD_TITLECLASH,
  1005.                                       NULL);
  1006.  
  1007.                     // disable window updates for the following changes
  1008.                     WinEnableWindowUpdate(hwndConfirm, FALSE);
  1009.  
  1010.                     WinQueryDlgItemText(hwndConfirm, ID_XFDI_CLASH_TXT1,
  1011.                                     sizeof(szTemp)-1, szTemp);
  1012.                     strhReplace(szTemp, "%1", szNewRealName);
  1013.                     strhReplace(szTemp, "%2", szFolder);
  1014.                     WinSetDlgItemText(hwndConfirm, ID_XFDI_CLASH_TXT1,
  1015.                                     szTemp);
  1016.  
  1017.                     // set object information fields
  1018.                     // _wpQueryDateInfo(pobjExisting, &ffb4);
  1019.                     _wpQueryFilename(pobjExisting, szExistingFilename, TRUE);
  1020.                     DosQueryPathInfo(szExistingFilename,
  1021.                                     FIL_STANDARD,
  1022.                                     &fs3, sizeof(fs3));
  1023.                     strhFileDate(szTemp, &(fs3.fdateLastWrite), ulDateFormat, szDateSep[0]);
  1024.                     WinSetDlgItemText(hwndConfirm, ID_XFDI_CLASH_DATEOLD,
  1025.                                     szTemp);
  1026.                     strhFileTime(szTemp, &(fs3.ftimeLastWrite), ulTimeFormat, szTimeSep[0]);
  1027.                     WinSetDlgItemText(hwndConfirm, ID_XFDI_CLASH_TIMEOLD,
  1028.                                     szTemp);
  1029.                     // strhThousandsULong(szTemp, (_wpQueryFileSize(pobjExisting)+512) / 1024,
  1030.                     strhThousandsULong(szTemp, ((fs3.cbFile)+512) / 1024,
  1031.                                 szThousand[0]);
  1032.                     WinSetDlgItemText(hwndConfirm, ID_XFDI_CLASH_SIZEOLD,
  1033.                                     szTemp);
  1034.  
  1035.                     if (pobjExisting != somSelf) {
  1036.                         // if we're not copying within the same folder,
  1037.                         // i.e. if the two objects are different,
  1038.                         // give info on ourselves too
  1039.                         // _wpQueryDateInfo(somSelf, &ffb4);
  1040.                         _wpQueryFilename(somSelf, szSelfFilename, TRUE);
  1041.                         DosQueryPathInfo(szSelfFilename,
  1042.                                         FIL_STANDARD,
  1043.                                         &fs3, sizeof(fs3));
  1044.                         strhFileDate(szTemp, &(fs3.fdateLastWrite), ulDateFormat, szDateSep[0]);
  1045.                         WinSetDlgItemText(hwndConfirm, ID_XFDI_CLASH_DATENEW,
  1046.                                         szTemp);
  1047.                         strhFileTime(szTemp, &(fs3.ftimeLastWrite), ulTimeFormat, szTimeSep[0]);
  1048.                         WinSetDlgItemText(hwndConfirm, ID_XFDI_CLASH_TIMENEW,
  1049.                                         szTemp);
  1050.                         // strhThousandsULong(szTemp, (_wpQueryFileSize(somSelf)+512) / 1024,
  1051.                         strhThousandsULong(szTemp, ((fs3.cbFile)+512) / 1024,
  1052.                                     szThousand[0]);
  1053.                         WinSetDlgItemText(hwndConfirm, ID_XFDI_CLASH_SIZENEW,
  1054.                                         szTemp);
  1055.                     } else {
  1056.                         // if we're copying within the same folder,
  1057.                         // set the "new object" fields empty
  1058.                         WinSetDlgItemText(hwndConfirm, ID_XFDI_CLASH_DATENEW, "");
  1059.                         WinSetDlgItemText(hwndConfirm, ID_XFDI_CLASH_TIMENEW, "");
  1060.                         WinSetDlgItemText(hwndConfirm, ID_XFDI_CLASH_SIZENEW, "");
  1061.                     }
  1062.  
  1063.                     // propose new name; we will use the title and
  1064.                     // add a ":num" before the extension and then
  1065.                     // transform that one into a real name and keep
  1066.                     // increasing "num" until no file with that
  1067.                     // real name exists (as the WPS does it too)
  1068.                     strcpy(szTemp, pszTitle);
  1069.                     // check if title contains a ':num' already
  1070.                     p2 = strchr(szTemp, ':');
  1071.                     if (p2) {
  1072.                         lFileCount = atoi(p2+1);
  1073.                         if (lFileCount) {
  1074.                             // if we have a valid number following ":", remove it
  1075.                             p = strchr(szTemp, '.');
  1076.                             if (p)
  1077.                                 strcpy(p2, p);
  1078.                             else
  1079.                                 *p2 = '\0';
  1080.                         }
  1081.                     }
  1082.  
  1083.                     // insert new number
  1084.                     p = strrchr(szTemp, '.');       // last dot == extension
  1085.                     lFileCount = 1;
  1086.                     do {
  1087.                         WPFileSystem *pExistingFile2;
  1088.  
  1089.                         sprintf(szFileCount, ":%d", lFileCount);
  1090.                         if (p) {
  1091.                             // has extension: insert
  1092.                             ULONG ulBeforeDot = (p - szTemp);
  1093.                             // we don't care about FAT, because
  1094.                             // we propose titles, not real names
  1095.                             // (V0.84)
  1096.                             /* if (   (fFAT)
  1097.                                 && ((ulBeforeDot+strlen(szFileCount)) > 8)
  1098.                                )
  1099.                                 ulBeforeDot = 8 - strlen(szFileCount); */
  1100.                             strncpy(szProposeTitle, szTemp, ulBeforeDot);
  1101.                             szProposeTitle[ulBeforeDot] = '\0';
  1102.                             strcat(szProposeTitle, szFileCount);
  1103.                             strcat(szProposeTitle, p);
  1104.                         }
  1105.                         else {
  1106.                             // has no extension: append
  1107.                             strncpy(szProposeTitle, szTemp, 255);
  1108.                             // we don't care about FAT, because
  1109.                             // we propose titles, not real names
  1110.                             // (V0.84)
  1111.                             /*     (fFAT) ? 8 : 255);
  1112.                             if (fFAT)
  1113.                                 szProposeTitle[8] = '\0'; */
  1114.                             strcat(szProposeTitle, szFileCount);
  1115.                         }
  1116.                         lFileCount++;
  1117.  
  1118.                         if (lFileCount > 99)
  1119.                             // avoid endless loops
  1120.                             break;
  1121.  
  1122.                         // now go through the folder content and
  1123.                         // check whether we already have a file
  1124.                         // with the proposed title (not real name!)
  1125.                         // (V0.84)
  1126.                         fFileExists = FALSE;
  1127.                         for (   pExistingFile2 = _wpQueryContent(Folder, NULL, (ULONG)QC_FIRST);
  1128.                                 (pExistingFile2);
  1129.                                 pExistingFile2 = _wpQueryContent(Folder, pExistingFile2, (ULONG)QC_NEXT)
  1130.                             )
  1131.                         {
  1132.                             fFileExists = (stricmp(_wpQueryTitle(pExistingFile2),
  1133.                                                   szProposeTitle) == 0);
  1134.                             if (fFileExists)
  1135.                                 break;
  1136.                         }
  1137.  
  1138.                         /*
  1139.                         // make real name from this title and check
  1140.                         // if that file exists; if so, try the next
  1141.                         // ":num"
  1142.                         doshMakeRealName(szProposeRealName, szProposeTitle, '!',
  1143.                             // FAT filenames?
  1144.                             fFAT);
  1145.  
  1146.                         // extended file exists check (V0.84); we
  1147.                         // need to compare titles, not real names
  1148.                         pExistingFile2 = xwpsContainsFile(Folder, szProposeRealName);
  1149.                         if (pExistingFile2)
  1150.                         {
  1151.                             if (lFileCount > 99)
  1152.                                 // avoid endless loops
  1153.                                 fFileExists = FALSE;
  1154.                             else
  1155.                                 fFileExists = (stricmp(_wpQueryTitle(pExistingFile2),
  1156.                                                       szProposeTitle) == 0);
  1157.                         } else
  1158.                             fFileExists = FALSE; */
  1159.  
  1160.                     } while (fFileExists);
  1161.  
  1162.                     // OK, we've found a new filename: set dlg items
  1163.                     WinSendDlgItemMsg(hwndConfirm, ID_XFDI_CLASH_RENAMENEWTXT,
  1164.                             EM_SETTEXTLIMIT,
  1165.                             (MPARAM)(250), MPNULL);
  1166.                     WinSetDlgItemText(hwndConfirm, ID_XFDI_CLASH_RENAMENEWTXT,
  1167.                             szProposeTitle);
  1168.                     WinSendDlgItemMsg(hwndConfirm, ID_XFDI_CLASH_RENAMEOLDTXT,
  1169.                             EM_SETTEXTLIMIT,
  1170.                             (MPARAM)(250), MPNULL);
  1171.                     WinSetDlgItemText(hwndConfirm, ID_XFDI_CLASH_RENAMEOLDTXT,
  1172.                             szProposeTitle);
  1173.  
  1174.                     // select the first characters up to the extension
  1175.                     // in the edit field
  1176.                     p = strrchr(szProposeTitle, '.');       // last dot == extension
  1177.                     if (p)
  1178.                         ulLastDot = (p-szProposeTitle);
  1179.                     else
  1180.                         ulLastDot = 300;                    // too large == select all
  1181.  
  1182.                     WinSendDlgItemMsg(hwndConfirm, ID_XFDI_CLASH_RENAMENEWTXT,
  1183.                             EM_SETSEL,
  1184.                             MPFROM2SHORT(0, ulLastDot), MPNULL);
  1185.                     WinSendDlgItemMsg(hwndConfirm, ID_XFDI_CLASH_RENAMEOLDTXT,
  1186.                             EM_SETSEL,
  1187.                             MPFROM2SHORT(0, ulLastDot), MPNULL);
  1188.  
  1189.                     // find the selection the user has made last time;
  1190.                     // this INI key item is maintained by fnwpTitleClashDlg above
  1191.                     ulLastFocusID = PrfQueryProfileInt(HINI_USER, INIAPP_XFOLDER,
  1192.                                         INIKEY_NAMECLASHFOCUS,
  1193.                                         ID_XFDI_CLASH_RENAMENEWTXT); // default value if not set
  1194.  
  1195.                     // disable "Replace" and "Rename old"
  1196.                     // if we're copying within the same folder
  1197.                     // or if we're copying a folder to its parent
  1198.                     if (    (pobjExisting == somSelf)
  1199.                          || (pobjExisting == _wpQueryFolder(somSelf))
  1200.                        )
  1201.                     {
  1202.                         winhEnableDlgItem(hwndConfirm, ID_XFDI_CLASH_REPLACE, FALSE);
  1203.                         winhEnableDlgItem(hwndConfirm, ID_XFDI_CLASH_RENAMEOLD, FALSE);
  1204.                         winhEnableDlgItem(hwndConfirm, ID_XFDI_CLASH_RENAMEOLDTXT, FALSE);
  1205.                         // if the last focus is one of the disabled items,
  1206.                         // change it
  1207.                         if (   (ulLastFocusID == ID_XFDI_CLASH_REPLACE)
  1208.                             || (ulLastFocusID == ID_XFDI_CLASH_RENAMEOLDTXT)
  1209.                            )
  1210.                             ulLastFocusID = ID_XFDI_CLASH_RENAMENEWTXT;
  1211.                     }
  1212.  
  1213.                     // disable "Replace" for "Rename" mode; this is
  1214.                     // not allowed
  1215.                     else if (menuID == 0x006E)
  1216.                     {
  1217.                         winhEnableDlgItem(hwndConfirm, ID_XFDI_CLASH_REPLACE, FALSE);
  1218.                         // if the last focus is one of the disabled items,
  1219.                         // change it
  1220.                         if (ulLastFocusID == ID_XFDI_CLASH_REPLACE)
  1221.                             ulLastFocusID = ID_XFDI_CLASH_RENAMENEWTXT;
  1222.                     }
  1223.  
  1224.                     // set focus to that item
  1225.                     winhSetDlgItemFocus(hwndConfirm, ulLastFocusID);
  1226.                         // this will automatically select the corresponding
  1227.                         // radio button, see fnwpTitleClashDlg above
  1228.  
  1229.                     // *** go!
  1230.                     winhRestoreWindowPos(hwndConfirm,
  1231.                             HINI_USER,
  1232.                             INIAPP_XFOLDER, INIKEY_WNDPOSNAMECLASH,
  1233.                             // move only, no resize
  1234.                             SWP_MOVE | SWP_SHOW | SWP_ACTIVATE);
  1235.                     ulDlgReturn = WinProcessDlg(hwndConfirm);
  1236.  
  1237.                     // check return value
  1238.                     switch (ulDlgReturn) {
  1239.                         case ID_XFDI_CLASH_RENAMENEW: {
  1240.                             // rename new: copy user's entry to buffer
  1241.                             // provided by the method
  1242.                             WinQueryDlgItemText(hwndConfirm, ID_XFDI_CLASH_RENAMENEWTXT,
  1243.                                             cbTitle-1, pszTitle);
  1244.                             ulrc = NAMECLASH_RENAME;
  1245.                         break; }
  1246.  
  1247.                         case ID_XFDI_CLASH_RENAMEOLD: {
  1248.                             // rename old: use wpSetTitle on existing object
  1249.                             WinQueryDlgItemText(hwndConfirm, ID_XFDI_CLASH_RENAMEOLDTXT,
  1250.                                             sizeof(szTemp)-1, szTemp);
  1251.                             _wpSetTitleAndRenameFile(pobjExisting, szTemp, 0);
  1252.  
  1253.                             if (menuID == 0x6E)     // "rename" code
  1254.                             {
  1255.                                 CHAR szNewRealName[CCHMAXPATH];
  1256.                                 doshMakeRealName(szNewRealName, pszTitle, '!', TRUE);
  1257.                                 _wpSetTitleAndRenameFile(somSelf, pszTitle, 0);
  1258.                             }
  1259.                             ulrc = NAMECLASH_NONE;
  1260.                         break; }
  1261.  
  1262.                         case ID_XFDI_CLASH_REPLACE:
  1263.                             *ppDuplicate = pobjExisting;
  1264.                             ulrc = NAMECLASH_REPLACE;
  1265.                         break;
  1266.  
  1267.                         case DID_CANCEL:
  1268.                             ulrc = NAMECLASH_CANCEL;
  1269.                         break;
  1270.                     }
  1271.                     WinDestroyWindow(hwndConfirm);
  1272.                 } // end if  (   (menuID != 0x6E) // "rename" code
  1273.                   // || (somSelf != pobjExisting)
  1274.                   // )
  1275.             }
  1276.             else if (menuID == 0x6E)     // "rename" code
  1277.             {
  1278.                 // if (!pobjExisting) and we're renaming
  1279.                 CHAR szNewRealName[CCHMAXPATH];
  1280.                 doshMakeRealName(szNewRealName, pszTitle, '!', TRUE);
  1281.                 if (_wpSetTitleAndRenameFile(somSelf, pszTitle, 0))
  1282.                     // no error:
  1283.                     ulrc = NAMECLASH_NONE;
  1284.                 else
  1285.                     ulrc = NAMECLASH_CANCEL;
  1286.             }
  1287.         } // end if (_somIsA(somSelf, _WPFileSystem))
  1288.     } // end if (pGlobalSettings->ReplConfirms)
  1289.     else {
  1290.         // global settings do not allow dialog
  1291.         // replacement: call default
  1292.         #ifdef DEBUG_TITLECLASH
  1293.             _Pmpf(("  Calling original"));
  1294.         #endif
  1295.         ulrc = XFldObject_parent_WPObject_wpConfirmObjectTitle(somSelf,
  1296.                                                             Folder,
  1297.                                                             ppDuplicate,
  1298.                                                             pszTitle,
  1299.                                                             cbTitle,
  1300.                                                             menuID);
  1301.     }
  1302.  
  1303.     #ifdef DEBUG_TITLECLASH
  1304.     {
  1305.         CHAR szFolder2[CCHMAXPATH];
  1306.         _Pmpf(("  Return value: %d", ulrc));
  1307.         _Pmpf(("  New somSelf == 0x%lX", somSelf));
  1308.         _Pmpf(("    New pszTitle: %s", pszTitle));
  1309.         _wpQueryFilename(_wpQueryFolder(somSelf), szFolder2, TRUE);
  1310.         _Pmpf(("    in folder: %s", szFolder2));
  1311.  
  1312.         if (ppDuplicate) {
  1313.             _Pmpf(("  ppDuplicate neu != NULL"));
  1314.             if (*ppDuplicate) {
  1315.                 _Pmpf(("    *ppDuplicate neu == 0x%lX", *ppDuplicate));
  1316.                 _Pmpf(("      Title neu: %s", _wpQueryTitle(*ppDuplicate) ));
  1317.                 _wpQueryFilename(_wpQueryFolder(*ppDuplicate), szFolder2, TRUE);
  1318.                 _Pmpf(("      in folder: %s", szFolder2));
  1319.             }
  1320.         }
  1321.         _Pmpf(("Done."));
  1322.     }
  1323.     #endif
  1324.  
  1325.     return (ulrc);
  1326. }
  1327.  
  1328. /* ******************************************************************
  1329.  *                                                                  *
  1330.  *   here come the XFldObject class methods                         *
  1331.  *                                                                  *
  1332.  ********************************************************************/
  1333.  
  1334. BOOL fThreadsInitialized = FALSE;
  1335.  
  1336. /*
  1337.  *@@ wpclsInitData:
  1338.  *           we override this to initialize XFolder altogether.
  1339.  *           This is probably the first SOM method called on the
  1340.  *           system (for M_WPObject, that is), so we use this
  1341.  *           to set up some stuff, most notably, start the
  1342.  *           additional XFolder threads.
  1343.  */
  1344.  
  1345. /*
  1346.  *@@ wpclsInitData:
  1347.  *           we override this to initialize XFolder altogether.
  1348.  *           This is probably the first SOM method called on the
  1349.  *           system (for M_WPObject, that is), so we use this
  1350.  *           to set up some stuff, most notably, start the
  1351.  *           additional XFolder threads by calling
  1352.  *           xthrInitializeThreads (xthreads.c).
  1353.  */
  1354.  
  1355. SOM_Scope void  SOMLINK xfobjM_wpclsInitData(M_XFldObject *somSelf)
  1356. {
  1357.     PGLOBALSETTINGS pGlobalSettings = cmnQueryGlobalSettings();
  1358.  
  1359.     // M_XFldObjectData *somThis = M_XFldObjectGetData(somSelf);
  1360.     // M_XFldObjectMethodDebug("M_XFldObject","xfobjM_wpclsInitData");
  1361.     #ifdef DEBUG_SOMMETHODS
  1362.         _Pmpf(("M_XFldObject::xfobjM_wpclsInitData for class %s",
  1363.                     _somGetName(somSelf) ));
  1364.     #endif
  1365.  
  1366.     M_XFldObject_parent_M_WPObject_wpclsInitData(somSelf);
  1367.  
  1368.     // since this code is reached for every single WPS class
  1369.     // that gets initialized, we need to check if we're being
  1370.     // called for the first time
  1371.     if (!fThreadsInitialized)
  1372.     {
  1373.         fThreadsInitialized = TRUE;
  1374.  
  1375.         // initialize all the thread stuff (xthreads.c)
  1376.         xthrInitializeThreads();
  1377.     }
  1378.  
  1379.     // even if not first invocation (i.e. some class other
  1380.     // than WPObject gets initialized): notify Quick thread
  1381.     // of class initialization
  1382.     if (pGlobalSettings->ShowBootupStatus)
  1383.         xthrPostQuickMsg(QM_BOOTUPSTATUS, (MPARAM)somSelf, MPNULL);
  1384. }
  1385.  
  1386. /* ******************************************************************
  1387.  *                                                                  *
  1388.  *   "Object usage" dialog                                          *
  1389.  *                                                                  *
  1390.  ********************************************************************/
  1391.  
  1392. /*
  1393.  *@@ AddObjectUsage2Cnr:
  1394.  *      shortcut for the "object usage" functions below
  1395.  *      to add one cnr record core
  1396.  */
  1397.  
  1398. POBJECTUSAGERECORDCORE AddObjectUsage2Cnr(HWND hwndCnr,
  1399.     POBJECTUSAGERECORDCORE preccParent, PSZ pszTitle, ULONG flAttrs)
  1400. {
  1401.     POBJECTUSAGERECORDCORE preccNew = (POBJECTUSAGERECORDCORE)
  1402.         winhCnrAllocRecord(hwndCnr, sizeof(OBJECTUSAGERECORDCORE));
  1403.  
  1404.     strcpy(preccNew->szText, pszTitle);
  1405.     winhCnrInsertRecord(hwndCnr, (PRECORDCORE)preccParent, (PRECORDCORE)preccNew,
  1406.             preccNew->szText, flAttrs);
  1407.     return (preccNew);
  1408. }
  1409.  
  1410. #ifdef DEBUG_MEMORY
  1411.  
  1412.     LONG    lObjectCount,
  1413.             lTotalObjectSize,
  1414.             lFreedObjectCount,
  1415.             lHeapStatus;
  1416.  
  1417.     /*
  1418.      * fncbHeapWalk:
  1419.      *      callback func for _heap_walk function used for
  1420.      *      object usage (FillCnrWithObjectUsage)
  1421.      */
  1422.  
  1423.     int fncbHeapWalk(const void *pObject, size_t Size, int useflag, int status,
  1424.                           const char *filename, size_t line)
  1425.     {
  1426.         if (status != _HEAPOK) {
  1427.             lHeapStatus = status;
  1428.         }
  1429.         if (useflag == _USEDENTRY) {
  1430.             // object not freed
  1431.             lObjectCount++;
  1432.             lTotalObjectSize += Size;
  1433.         } else
  1434.             lFreedObjectCount++;
  1435.  
  1436.         return 0;
  1437.     }
  1438. #endif
  1439.  
  1440. /*
  1441.  *@@ FillCnrWithObjectUsage:
  1442.  *      adds all the object details into a given
  1443.  *      container window
  1444.  */
  1445.  
  1446. VOID FillCnrWithObjectUsage(HWND hwndCnr, WPObject *pObject)
  1447. {
  1448.     POBJECTUSAGERECORDCORE
  1449.                     preccRoot, preccLevel2, preccLevel3;
  1450.     CHAR            szTemp1[100], szText[300];
  1451.     PUSEITEM        pUseItem;
  1452.  
  1453.     CHAR            szObjectHandle[20];
  1454.     HOBJECT         hObject;
  1455.     PSZ             pszObjectID;
  1456.     ULONG           ul;
  1457.  
  1458.     PTHREADGLOBALS   pThreadGlobals = xthrQueryGlobals();
  1459.  
  1460.     // printf("Cnr: %d\n", hwndCnr);
  1461.     if (pObject) {
  1462.         sprintf(szText, "%s (Class: %s)",
  1463.                 _wpQueryTitle(pObject), _somGetClassName(pObject));
  1464.         preccRoot = AddObjectUsage2Cnr(hwndCnr, NULL, szText,
  1465.                 CRA_RECORDREADONLY | CRA_EXPANDED);
  1466.  
  1467.         // object ID
  1468.         preccLevel2 = AddObjectUsage2Cnr(hwndCnr, preccRoot, "Object ID",
  1469.                 CRA_RECORDREADONLY | CRA_EXPANDED);
  1470.         pszObjectID = _wpQueryObjectID(pObject);
  1471.         if (pszObjectID)
  1472.             AddObjectUsage2Cnr(hwndCnr, preccLevel2, pszObjectID,
  1473.                     (strcmp(pszObjectID, "<WP_DESKTOP") != 0
  1474.                         ? 0 // editable!
  1475.                         : CRA_RECORDREADONLY)); // for the Desktop
  1476.         else
  1477.             AddObjectUsage2Cnr(hwndCnr, preccLevel2, "none set", 0); // editable!
  1478.  
  1479.         // object handle
  1480.         preccLevel2 = AddObjectUsage2Cnr(hwndCnr, preccRoot, "Object handle",
  1481.                 CRA_RECORDREADONLY | CRA_EXPANDED);
  1482.         if (_somIsA(pObject, _WPFileSystem)) {
  1483.             CHAR    szPath[CCHMAXPATH];
  1484.             _wpQueryFilename(pObject, szPath,
  1485.                     TRUE);      // fully qualified
  1486.             hObject = wphQueryHandleFromPath(HINI_USER, HINI_SYSTEM,
  1487.                                 szPath);
  1488.         } else if (_somIsA(pObject, _WPAbstract)) {
  1489.             hObject = _wpQueryHandle(pObject);
  1490.         }
  1491.         if ((LONG)hObject > 0)
  1492.             sprintf(szObjectHandle, "0x%lX", hObject);
  1493.         else
  1494.             sprintf(szObjectHandle, "(none queried)");
  1495.         AddObjectUsage2Cnr(hwndCnr, preccLevel2, szObjectHandle, CRA_RECORDREADONLY);
  1496.  
  1497.         // object style
  1498.         preccLevel2 = AddObjectUsage2Cnr(hwndCnr, preccRoot, "Object style",
  1499.                             CRA_RECORDREADONLY);
  1500.         ul = _wpQueryStyle(pObject);
  1501.         if (ul & OBJSTYLE_CUSTOMICON)
  1502.             AddObjectUsage2Cnr(hwndCnr, preccLevel2,
  1503.                         "Custom icon (destroy icon when object goes dormant)",
  1504.                         CRA_RECORDREADONLY);
  1505.         if (ul & OBJSTYLE_NOCOPY)
  1506.             AddObjectUsage2Cnr(hwndCnr, preccLevel2, "no copy",
  1507.                                 CRA_RECORDREADONLY);
  1508.         if (ul & OBJSTYLE_NODELETE)
  1509.             AddObjectUsage2Cnr(hwndCnr, preccLevel2, "no delete",
  1510.                                 CRA_RECORDREADONLY);
  1511.         if (ul & OBJSTYLE_NODRAG)
  1512.             AddObjectUsage2Cnr(hwndCnr, preccLevel2, "no drag",
  1513.                                 CRA_RECORDREADONLY);
  1514.         if (ul & OBJSTYLE_NODROPON)
  1515.             AddObjectUsage2Cnr(hwndCnr, preccLevel2, "no drop-on",
  1516.                                 CRA_RECORDREADONLY);
  1517.         if (ul & OBJSTYLE_NOLINK)
  1518.             AddObjectUsage2Cnr(hwndCnr, preccLevel2, "no link (cannot have shadows)",
  1519.                                 CRA_RECORDREADONLY);
  1520.         if (ul & OBJSTYLE_NOMOVE)
  1521.             AddObjectUsage2Cnr(hwndCnr, preccLevel2, "no move",
  1522.                                 CRA_RECORDREADONLY);
  1523.         if (ul & OBJSTYLE_NOPRINT)
  1524.             AddObjectUsage2Cnr(hwndCnr, preccLevel2, "no print",
  1525.                                 CRA_RECORDREADONLY);
  1526.         if (ul & OBJSTYLE_NORENAME)
  1527.             AddObjectUsage2Cnr(hwndCnr, preccLevel2, "no rename",
  1528.                                 CRA_RECORDREADONLY);
  1529.         if (ul & OBJSTYLE_NOSETTINGS)
  1530.             AddObjectUsage2Cnr(hwndCnr, preccLevel2, "no settings",
  1531.                                 CRA_RECORDREADONLY);
  1532.         if (ul & OBJSTYLE_NOSETTINGS)
  1533.             AddObjectUsage2Cnr(hwndCnr, preccLevel2, "not visible",
  1534.                                 CRA_RECORDREADONLY);
  1535.         if (ul & OBJSTYLE_TEMPLATE)
  1536.             AddObjectUsage2Cnr(hwndCnr, preccLevel2, "template",
  1537.                                 CRA_RECORDREADONLY);
  1538.         /* if (ul & OBJSTYLE_LOCKEDINPLACE)
  1539.             AddObjectUsage2Cnr(hwndCnr, preccLevel2, "locked in place",
  1540.                                 CRA_RECORDREADONLY); */
  1541.  
  1542.         // folder data
  1543.         if (_somIsA(pObject, _WPFolder)) {
  1544.             preccLevel2 = AddObjectUsage2Cnr(hwndCnr, preccRoot, "Folder flags",
  1545.                                 CRA_RECORDREADONLY);
  1546.             ul = _wpQueryFldrFlags(pObject);
  1547.             if (ul & FOI_POPULATEDWITHALL)
  1548.                 AddObjectUsage2Cnr(hwndCnr, preccLevel2, "Fully populated",
  1549.                                     CRA_RECORDREADONLY);
  1550.             if (ul & FOI_POPULATEDWITHFOLDERS)
  1551.                 AddObjectUsage2Cnr(hwndCnr, preccLevel2, "Populated with folders",
  1552.                                     CRA_RECORDREADONLY);
  1553.             if (ul & FOI_FIRSTPOPULATE)
  1554.                 AddObjectUsage2Cnr(hwndCnr, preccLevel2, "Populated with first objects",
  1555.                                     CRA_RECORDREADONLY);
  1556.             if (ul & FOI_WORKAREA)
  1557.                 AddObjectUsage2Cnr(hwndCnr, preccLevel2, "Work area",
  1558.                                     CRA_RECORDREADONLY);
  1559.             if (ul & FOI_CHANGEFONT)
  1560.                 AddObjectUsage2Cnr(hwndCnr, preccLevel2, "FOI_CHANGEFONT",
  1561.                                     CRA_RECORDREADONLY);
  1562.             if (ul & FOI_NOREFRESHVIEWS)
  1563.                 AddObjectUsage2Cnr(hwndCnr, preccLevel2, "FOI_NOREFRESHVIEWS",
  1564.                                     CRA_RECORDREADONLY);
  1565.             if (ul & FOI_ASYNCREFRESHONOPEN)
  1566.                 AddObjectUsage2Cnr(hwndCnr, preccLevel2, "FOI_ASYNCREFRESHONOPEN",
  1567.                                     CRA_RECORDREADONLY);
  1568.             if (ul & FOI_REFRESHINPROGRESS)
  1569.                 AddObjectUsage2Cnr(hwndCnr, preccLevel2, "FOI_REFRESHINPROGRESS",
  1570.                                     CRA_RECORDREADONLY);
  1571.             if (ul & FOI_WAMCRINPROGRESS)
  1572.                 AddObjectUsage2Cnr(hwndCnr, preccLevel2, "FOI_WAMCRINPROGRESS",
  1573.                                     CRA_RECORDREADONLY);
  1574.             if (ul & FOI_CNRBKGNDOLDFORMAT)
  1575.                 AddObjectUsage2Cnr(hwndCnr, preccLevel2, "FOI_CNRBKGNDOLDFORMAT",
  1576.                                     CRA_RECORDREADONLY);
  1577.             if (ul & FOI_DELETEINPROGRESS)
  1578.                 AddObjectUsage2Cnr(hwndCnr, preccLevel2, "FOI_DELETEINPROGRESS",
  1579.                                     CRA_RECORDREADONLY);
  1580.  
  1581.             // Desktop: add WPS data
  1582.             if (pObject == _wpclsQueryActiveDesktop(_WPDesktop)) {
  1583.                 PRCPROCESS       prcp;
  1584.                 PTIB             ptib;
  1585.                 PPIB             ppib;
  1586.                 TID              tidWorkerThread = 0,
  1587.                                  tidQuickThread = 0;
  1588.  
  1589.                 preccLevel2 = AddObjectUsage2Cnr(hwndCnr, preccRoot, "Workplace Shell status",
  1590.                                     CRA_RECORDREADONLY);
  1591.  
  1592.                 // we use a conditional compile flag here because
  1593.                 // _heap_walk adds additional overhead to malloc()
  1594.                 #ifdef DEBUG_MEMORY
  1595.                     lObjectCount = 0;
  1596.                     lTotalObjectSize = 0;
  1597.                     lFreedObjectCount = 0;
  1598.                     lHeapStatus = _HEAPOK;
  1599.  
  1600.                     // get heap info using the callback above
  1601.                     _heap_walk(fncbHeapWalk);
  1602.  
  1603.                     strths(szTemp1, lTotalObjectSize, ',');
  1604.                     sprintf(szText, "XFolder memory consumption: %s bytes\n"
  1605.                                 "(%d objects used, %d objects freed)",
  1606.                                 szTemp1,
  1607.                                 lObjectCount,
  1608.                                 lFreedObjectCount);
  1609.                     AddObjectUsage2Cnr(hwndCnr, preccLevel2, szText,
  1610.                                         CRA_RECORDREADONLY);
  1611.  
  1612.                     sprintf(szText, "XFolder memory heap status: %s",
  1613.                                 (lHeapStatus == _HEAPOK) ? "OK"
  1614.                                 : (lHeapStatus == _HEAPBADBEGIN) ? "Invalid heap (_HEAPBADBEGIN)"
  1615.                                 : (lHeapStatus == _HEAPBADNODE) ? "Damaged memory node"
  1616.                                 : (lHeapStatus == _HEAPEMPTY) ? "Heap not initialized"
  1617.                                 : "unknown error"
  1618.                                 );
  1619.                     AddObjectUsage2Cnr(hwndCnr, preccLevel2, szText,
  1620.                                         CRA_RECORDREADONLY);
  1621.                 #endif
  1622.  
  1623.                 sprintf(szText, "Currently awake WPS objects: %d",
  1624.                             pThreadGlobals->lAwakeObjectsCount);
  1625.                 AddObjectUsage2Cnr(hwndCnr, preccLevel2, szText,
  1626.                                     CRA_RECORDREADONLY);
  1627.  
  1628.                 DosGetInfoBlocks(&ptib, &ppib);
  1629.                 sprintf(szText, "Workplace Shell process ID: 0x%lX", ppib->pib_ulpid);
  1630.                 AddObjectUsage2Cnr(hwndCnr, preccLevel2, szText,
  1631.                                     CRA_RECORDREADONLY);
  1632.  
  1633.                 prcQueryProcessInfo(ppib->pib_ulpid, &prcp);
  1634.                 sprintf(szText, "Workplace Shell thread count: %d", prcp.usThreads);
  1635.                 AddObjectUsage2Cnr(hwndCnr, preccLevel2, szText,
  1636.                                     CRA_RECORDREADONLY);
  1637.  
  1638.                 tidWorkerThread = thrQueryID(pThreadGlobals->ptiWorkerThread);
  1639.                 sprintf(szText, "XFolder Worker thread: TID 0x%lX, prty 0x%04lX",
  1640.                             tidWorkerThread,
  1641.                             prcQueryThreadPriority(ppib->pib_ulpid, tidWorkerThread));
  1642.                 AddObjectUsage2Cnr(hwndCnr, preccLevel2, szText,
  1643.                                     CRA_RECORDREADONLY);
  1644.  
  1645.                 tidQuickThread = thrQueryID(pThreadGlobals->ptiQuickThread);
  1646.                 sprintf(szText, "XFolder Quick thread: TID 0x%lX, prty 0x%04lX",
  1647.                             tidQuickThread,
  1648.                             prcQueryThreadPriority(ppib->pib_ulpid, tidQuickThread));
  1649.                 AddObjectUsage2Cnr(hwndCnr, preccLevel2, szText,
  1650.                                     CRA_RECORDREADONLY);
  1651.  
  1652.                 sprintf(szText, "Last Workplace Shell startup: %02d:%02d:%02d",
  1653.                                     pThreadGlobals->StartupDateTime.hours,
  1654.                                     pThreadGlobals->StartupDateTime.minutes,
  1655.                                     pThreadGlobals->StartupDateTime.seconds);
  1656.                 AddObjectUsage2Cnr(hwndCnr, preccLevel2, szText,
  1657.                                     CRA_RECORDREADONLY);
  1658.  
  1659.                 sprintf(szText, "XFolder sound status: %s",
  1660.                                 (pThreadGlobals->ulMMPM2Working == MMSTAT_UNKNOWN)
  1661.                                         ? "not initialized"
  1662.                                 : (pThreadGlobals->ulMMPM2Working == MMSTAT_WORKING)
  1663.                                         ? "OK"
  1664.                                 : (pThreadGlobals->ulMMPM2Working == MMSTAT_MMDIRNOTFOUND)
  1665.                                         ? "MMPM/2 directory not found"
  1666.                                 : (pThreadGlobals->ulMMPM2Working == MMSTAT_SOUNDLLNOTFOUND)
  1667.                                         ? "SOUND.DLL not found"
  1668.                                 : (pThreadGlobals->ulMMPM2Working == MMSTAT_SOUNDLLNOTLOADED)
  1669.                                         ? "SOUND.DLL could not be loaded"
  1670.                                 : (pThreadGlobals->ulMMPM2Working == MMSTAT_SOUNDLLFUNCERROR)
  1671.                                         ? "SOUND.DLL functions could not be imported"
  1672.                                 : (pThreadGlobals->ulMMPM2Working == MMSTAT_CRASHED)
  1673.                                         ? "Quick thread crashed"
  1674.                                 : "unknown"
  1675.                        );
  1676.                 AddObjectUsage2Cnr(hwndCnr, preccLevel2, szText,
  1677.                                     CRA_RECORDREADONLY);
  1678.             }
  1679.         } // end WPFolder
  1680.         else if (_somIsA(pObject, _XFldProgramFile))
  1681.         {
  1682.             ULONG ulAppType = _xfQueryProgType(pObject);
  1683.  
  1684.             preccLevel2 = AddObjectUsage2Cnr(hwndCnr, preccRoot,
  1685.                                 "Program file data",
  1686.                                 CRA_RECORDREADONLY);
  1687.  
  1688.             sprintf(szText, "DosQueryAppType return value: 0x%lX",
  1689.                         XFldProgramFileGetData(pObject)->ulDosAppType);
  1690.             AddObjectUsage2Cnr(hwndCnr, preccLevel2, szText,
  1691.                                 CRA_RECORDREADONLY);
  1692.  
  1693.             sprintf(szText, "Using custom icon: %s",
  1694.                         (XFldProgramFileGetData(pObject)->fProgIconSet)
  1695.                             ? "yes" : "no");
  1696.             AddObjectUsage2Cnr(hwndCnr, preccLevel2, szText,
  1697.                                 CRA_RECORDREADONLY);
  1698.  
  1699.             strcpy(szText, "Determined AppType: ");
  1700.             switch (ulAppType)
  1701.             {
  1702.                 case PROG_PM:
  1703.                     strcat(szText, "PM"); break;
  1704.  
  1705.                 case PROG_WINDOW_REAL         :
  1706.                 case PROG_30_STD              :
  1707.                 case PROG_WINDOW_AUTO         :
  1708.                 case PROG_30_STDSEAMLESSVDM   :
  1709.                 case PROG_30_STDSEAMLESSCOMMON:
  1710.                 case PROG_31_STDSEAMLESSVDM   :
  1711.                 case PROG_31_STDSEAMLESSCOMMON:
  1712.                 case PROG_31_ENHSEAMLESSVDM   :
  1713.                 case PROG_31_ENHSEAMLESSCOMMON:
  1714.                 case PROG_31_ENH              :
  1715.                 case PROG_31_STD              :
  1716.                     sprintf(szText+strlen(szText),
  1717.                             "Win-OS/2 (0x%lX)",
  1718.                             XFldProgramFileGetData(pObject)->ulAppType);
  1719.                     break;
  1720.  
  1721.                 case PROG_WINDOWABLEVIO:
  1722.                     strcat(szText, "OS/2 VIO window"); break;
  1723.  
  1724.                 case PROG_FULLSCREEN:
  1725.                     strcat(szText, "OS/2 fullscreen"); break;
  1726.  
  1727.                 case PROG_WINDOWEDVDM:
  1728.                     strcat(szText, "DOS window"); break;
  1729.  
  1730.                 case PROG_VDM: // == PROG_REAL
  1731.                     strcat(szText, "DOS fullscreen"); break;
  1732.  
  1733.                 case PROG_XF_DLL:
  1734.                     strcat(szText, "Dynamic Link Library"); break;
  1735.  
  1736.                 case PROG_XF_DRIVER:
  1737.                     strcat(szText, "Device Driver"); break;
  1738.  
  1739.                 default:
  1740.                         sprintf(szText+strlen(szText),
  1741.                                 "unknown (0x%lX)",
  1742.                                 XFldProgramFileGetData(pObject)->ulAppType);
  1743.                 break;
  1744.             }
  1745.             AddObjectUsage2Cnr(hwndCnr, preccLevel2, szText,
  1746.                                 CRA_RECORDREADONLY);
  1747.         }
  1748.  
  1749.         // object usage
  1750.         preccLevel2 = AddObjectUsage2Cnr(hwndCnr, preccRoot, "Object usage",
  1751.                             CRA_RECORDREADONLY);
  1752.  
  1753.         preccLevel3 = NULL;
  1754.         for (pUseItem = _wpFindUseItem(pObject, USAGE_OPENVIEW, NULL);
  1755.             pUseItem;
  1756.             pUseItem = _wpFindUseItem(pObject, USAGE_OPENVIEW, pUseItem))
  1757.         {
  1758.             PVIEWITEM pViewItem = (PVIEWITEM)(pUseItem+1);
  1759.             switch (pViewItem->view) {
  1760.                 case OPEN_SETTINGS: strcpy(szTemp1, "Settings"); break;
  1761.                 case OPEN_CONTENTS: strcpy(szTemp1, "Icon"); break;
  1762.                 case OPEN_DETAILS:  strcpy(szTemp1, "Details"); break;
  1763.                 case OPEN_TREE:     strcpy(szTemp1, "Tree"); break;
  1764.                 case OPEN_RUNNING:  strcpy(szTemp1, "Program running"); break;
  1765.                 case OPEN_PROMPTDLG:strcpy(szTemp1, "Prompt dialog"); break;
  1766.                 case OPEN_PALETTE:  strcpy(szTemp1, "Palette"); break;
  1767.                 default:            sprintf(szTemp1, "unknown (0x%lX)", pViewItem->view); break;
  1768.             }
  1769.             if (pViewItem->view != OPEN_RUNNING) {
  1770.                 PID pid;
  1771.                 TID tid;
  1772.                 WinQueryWindowProcess(pViewItem->handle, &pid, &tid);
  1773.                 sprintf(szText, "%s (HWND: 0x%lX, thread ID: 0x%lX)",
  1774.                         szTemp1, pViewItem->handle, tid);
  1775.             } else {
  1776.                 sprintf(szText, "%s (HWND: 0x%lX)",
  1777.                         szTemp1, pViewItem->handle);
  1778.             }
  1779.             if (!preccLevel3)
  1780.                 preccLevel3 = AddObjectUsage2Cnr(hwndCnr, preccLevel2, "Currently open views",
  1781.                         CRA_RECORDREADONLY | CRA_EXPANDED);
  1782.             AddObjectUsage2Cnr(hwndCnr, preccLevel3, szText, CRA_RECORDREADONLY);
  1783.         }
  1784.  
  1785.         preccLevel3 = NULL;
  1786.         for (pUseItem = _wpFindUseItem(pObject, USAGE_MEMORY, NULL);
  1787.             pUseItem;
  1788.             pUseItem = _wpFindUseItem(pObject, USAGE_MEMORY, pUseItem))
  1789.         {
  1790.             PMEMORYITEM pMemoryItem = (PMEMORYITEM)(pUseItem+1);
  1791.             sprintf(szText, "Size: %d", pMemoryItem->cbBuffer);
  1792.             if (!preccLevel3)
  1793.                 preccLevel3 = AddObjectUsage2Cnr(hwndCnr, preccLevel2, "Allocated memory",
  1794.                         CRA_RECORDREADONLY);
  1795.             AddObjectUsage2Cnr(hwndCnr, preccLevel3, szText, CRA_RECORDREADONLY);
  1796.         }
  1797.  
  1798.         preccLevel3 = NULL;
  1799.         for (pUseItem = _wpFindUseItem(pObject, USAGE_LINK, NULL);
  1800.             pUseItem;
  1801.             pUseItem = _wpFindUseItem(pObject, USAGE_LINK, pUseItem))
  1802.         {
  1803.             PLINKITEM pLinkItem = (PLINKITEM)(pUseItem+1);
  1804.             CHAR      szShadowPath[CCHMAXPATH];
  1805.             if (pLinkItem->LinkObj) {
  1806.                 _wpQueryFilename(_wpQueryFolder(pLinkItem->LinkObj),
  1807.                         szShadowPath, CRA_RECORDREADONLY | CRA_EXPANDED);
  1808.                 sprintf(szText, "%s in \n%s", _wpQueryTitle(pLinkItem->LinkObj),
  1809.                         szShadowPath);
  1810.             } else
  1811.                 strcpy(szText, "broken");
  1812.  
  1813.             if (!preccLevel3)
  1814.                 preccLevel3 = AddObjectUsage2Cnr(hwndCnr, preccLevel2,
  1815.                         "Awake shadows of this object",
  1816.                         CRA_RECORDREADONLY | CRA_EXPANDED);
  1817.             AddObjectUsage2Cnr(hwndCnr, preccLevel3, szText, CRA_RECORDREADONLY);
  1818.         }
  1819.  
  1820.         preccLevel3 = NULL;
  1821.         for (pUseItem = _wpFindUseItem(pObject, USAGE_RECORD, NULL);
  1822.             pUseItem;
  1823.             pUseItem = _wpFindUseItem(pObject, USAGE_RECORD, pUseItem))
  1824.         {
  1825.             PRECORDITEM pRecordItem = (PRECORDITEM)(pUseItem+1);
  1826.             CHAR szFolderTitle[256];
  1827.             WinQueryWindowText(WinQueryWindow(pRecordItem->hwndCnr, QW_PARENT),
  1828.                                 sizeof(szFolderTitle)-1,
  1829.                                 szFolderTitle);
  1830.             sprintf(szText, "Container HWND: 0x%lX\n(\"%s\")",
  1831.                         pRecordItem->hwndCnr,
  1832.                         szFolderTitle);
  1833.             if (!preccLevel3)
  1834.                 preccLevel3 = AddObjectUsage2Cnr(hwndCnr, preccLevel2,
  1835.                         "Folder windows containing this object",
  1836.                         CRA_RECORDREADONLY | CRA_EXPANDED);
  1837.             AddObjectUsage2Cnr(hwndCnr, preccLevel3, szText, CRA_RECORDREADONLY);
  1838.         }
  1839.  
  1840.         preccLevel3 = NULL;
  1841.         for (pUseItem = _wpFindUseItem(pObject, USAGE_OPENFILE, NULL);
  1842.             pUseItem;
  1843.             pUseItem = _wpFindUseItem(pObject, USAGE_OPENFILE, pUseItem))
  1844.         {
  1845.             PVIEWFILE pViewFile = (PVIEWFILE)(pUseItem+1);
  1846.             sprintf(szText, "Open handle: 0x%lX", pViewFile->handle);
  1847.             if (!preccLevel3)
  1848.                 preccLevel3 = AddObjectUsage2Cnr(hwndCnr, preccLevel2,
  1849.                         "Applications which opened this object",
  1850.                         CRA_RECORDREADONLY | CRA_EXPANDED);
  1851.             AddObjectUsage2Cnr(hwndCnr, preccLevel3, szText, CRA_RECORDREADONLY);
  1852.         }
  1853.  
  1854.         preccLevel3 = NULL;
  1855.         for (ul = 0; ul < 100; ul++)
  1856.             if (    (ul != USAGE_OPENVIEW)
  1857.                  && (ul != USAGE_MEMORY)
  1858.                  && (ul != USAGE_LINK)
  1859.                  && (ul != USAGE_RECORD)
  1860.                  && (ul != USAGE_OPENFILE)
  1861.                )
  1862.             {
  1863.                 for (pUseItem = _wpFindUseItem(pObject, ul, NULL);
  1864.                     pUseItem;
  1865.                     pUseItem = _wpFindUseItem(pObject, ul, pUseItem))
  1866.                 {
  1867.                     sprintf(szText, "Type: 0x%lX", pUseItem->type);
  1868.                     if (!preccLevel3)
  1869.                         preccLevel3 = AddObjectUsage2Cnr(hwndCnr, preccLevel2,
  1870.                                 "Undocumented usage types",
  1871.                                 CRA_RECORDREADONLY | CRA_EXPANDED);
  1872.                     AddObjectUsage2Cnr(hwndCnr, preccLevel3, szText, CRA_RECORDREADONLY);
  1873.                 }
  1874.             }
  1875.     }
  1876. }
  1877.  
  1878. /*
  1879.  * fnwpObjectUsage:
  1880.  *      dlg proc for "Object usage" dlg
  1881.  */
  1882.  
  1883. MRESULT EXPENTRY fnwpObjectUsage(HWND hwndDlg, ULONG msg, MPARAM mp1, MPARAM mp2)
  1884. {
  1885.     MRESULT mrc;
  1886.     POBJECTUSAGEDATA poud = (POBJECTUSAGEDATA)WinQueryWindowULong(hwndDlg, QWL_USER);
  1887.  
  1888.     switch(msg) {
  1889.         case WM_INITDLG: {
  1890.             CNRINFO CnrInfo;
  1891.             WinSetWindowULong(hwndDlg, QWL_USER, (ULONG)mp2);
  1892.             poud = (POBJECTUSAGEDATA)mp2;
  1893.  
  1894.             WinSetWindowText(hwndDlg, poud->szDlgTitle);
  1895.             WinSetDlgItemText(hwndDlg, ID_XSDI_SC_INTROTEXT, poud->szIntroText);
  1896.  
  1897.             // setup container
  1898.             poud->hwndCnr = WinWindowFromID(hwndDlg, ID_XSDI_SC_CNR);
  1899.             WinSendMsg(poud->hwndCnr, CM_QUERYCNRINFO, &CnrInfo, (MPARAM)sizeof(CnrInfo));
  1900.             CnrInfo.pSortRecord = (PVOID)fnCompareName;
  1901.             CnrInfo.flWindowAttr = CV_TREE | CV_TEXT | CA_TREELINE;
  1902.             CnrInfo.cxTreeIndent = 30;
  1903.             WinSendMsg(poud->hwndCnr, CM_SETCNRINFO,
  1904.                     &CnrInfo,
  1905.                     (MPARAM)(CMA_PSORTRECORD | CMA_FLWINDOWATTR | CMA_CXTREEINDENT));
  1906.  
  1907.             if (poud->ulHelpPanel == 0)
  1908.                 winhShowDlgItem(hwndDlg, DID_HELP, FALSE);
  1909.  
  1910.             WinPostMsg(hwndDlg, WM_FILLCNR, MPNULL, MPNULL);
  1911.             mrc = WinDefDlgProc(hwndDlg, msg, mp1, mp2);
  1912.         break; }
  1913.  
  1914.         case WM_FILLCNR: {
  1915.             HPOINTER hptrOld = WinQueryPointer(HWND_DESKTOP);
  1916.             WinSetPointer(HWND_DESKTOP, WinQuerySysPointer(HWND_DESKTOP, SPTR_WAIT, FALSE));
  1917.             FillCnrWithObjectUsage(poud->hwndCnr, poud->pObject);
  1918.             WinSetPointer(HWND_DESKTOP, hptrOld);
  1919.         break; }
  1920.  
  1921.         case WM_CONTROL: {
  1922.             mrc = WinDefDlgProc(hwndDlg, msg, mp1, mp2);
  1923.             if (SHORT1FROMMP(mp1) == ID_XSDI_SC_CNR) {
  1924.                 switch (SHORT2FROMMP(mp1)) { // notify code
  1925.                     case CN_EMPHASIS: {
  1926.                         PNOTIFYRECORDEMPHASIS pnre = (PNOTIFYRECORDEMPHASIS)mp2;
  1927.                         if (pnre)
  1928.                             if (pnre->fEmphasisMask & CRA_SELECTED) {
  1929.                             }
  1930.                     break; }
  1931.                 }
  1932.             }
  1933.         break; }
  1934.  
  1935.         case WM_DESTROY: {
  1936.             mrc = WinDefDlgProc(hwndDlg, msg, mp1, mp2);
  1937.         break; }
  1938.  
  1939.         default:
  1940.             mrc = WinDefDlgProc(hwndDlg, msg, mp1, mp2);
  1941.     }
  1942.     return (mrc);
  1943. }
  1944.  
  1945.  
  1946.