Index: trunk/src/helpers/apps.c
===================================================================
--- trunk/src/helpers/apps.c	(revision 90)
+++ trunk/src/helpers/apps.c	(revision 91)
@@ -210,5 +210,5 @@
         {
             PSZ     *ppszThis = pEnv->papszVars;
-            PSZ     pszThis;
+            // PSZ     pszThis;
             ULONG   ul = 0;
             ULONG   ulVarNameLen = 0;
@@ -233,6 +233,4 @@
                  ul++)
             {
-                pszThis = *ppszThis;
-
                 if (strnicmp(*ppszThis, pszSearch, ulVarNameLen) == 0)
                 {
Index: trunk/src/helpers/cctl_chart.c
===================================================================
--- trunk/src/helpers/cctl_chart.c	(revision 90)
+++ trunk/src/helpers/cctl_chart.c	(revision 91)
@@ -423,6 +423,6 @@
     {
         HRGN        hrgnThis;
-        SHORT       sSweepAngle,
-                    sStartAngle;
+        /* SHORT       sSweepAngle,
+                    sStartAngle; */
 
         GpiSetCurrentPosition(hpsMem, &ptlLowerLeft);
@@ -1457,5 +1457,5 @@
                        LONG ly)
 {
-    LONG lRegionFound = -1; // none
+    // LONG lRegionFound = -1; // none
 
     POINTL ptlMouse = {lx, ly};
Index: trunk/src/helpers/cctl_tooltip.c
===================================================================
--- trunk/src/helpers/cctl_tooltip.c	(revision 90)
+++ trunk/src/helpers/cctl_tooltip.c	(revision 91)
@@ -1224,5 +1224,5 @@
 
         POINTL      ptlPointer;
-        HPS         hps;
+        // HPS         hps;
 
         // free old text
Index: trunk/src/helpers/comctl.c
===================================================================
--- trunk/src/helpers/comctl.c	(revision 90)
+++ trunk/src/helpers/comctl.c	(revision 91)
@@ -310,4 +310,5 @@
  *@@added V0.9.0 [umoeller]
  *@@changed V0.9.2 (2000-02-28) [umoeller]: menu was displayed even if button was disabled; fixed
+ *@@changed V0.9.14 (2001-07-31) [umoeller]: fixed WM_MENUEND submenu quirk
  */
 
@@ -486,38 +487,41 @@
         case WM_MENUEND:
         {
-            BOOL fUnHilite = TRUE;
-            // _Pmpf(("WM_MENUEND"));
-            // At this point, the menu has been
-            // destroyed already.
-            // Since WM_BUTTON1UP handles the
-            // default case that the user presses
-            // the menu button a second time while
-            // the menu is open, we only need
-            // to handle the case that the user
-            // c)   presses some key on the menu (ESC, menu selection) or
-            // a)   selects a menu item (which
-            //      dismisses the menu) or
-            // b)   clicks anywhere else.
-
-            // Case a) if mouse button 1 is not currently down
-            if ((WinGetKeyState(HWND_DESKTOP, VK_BUTTON1) & 0x8000) == 0)
-                // button 1 _not_ down:
-                // must be keyboard
-                fUnHilite = TRUE;
-            else
-                // button 1 _is_ down:
-                // query window under mouse pointer
-                ;
-
-            if (fUnHilite)
+            if ((HWND)mp2 == pmbd->hwndMenu) // V0.9.14 (2001-07-31) [umoeller]
             {
-                // _Pmpf(("  Unsinking menu WM_MENUEND"));
-                pmbd->fButtonSunk = FALSE;
-                WinSendMsg(hwndButton,
-                           BM_SETHILITE,
-                           (MPARAM)FALSE,
-                           (MPARAM)0);
-            }
-            pmbd->hwndMenu = NULLHANDLE;
+                BOOL fUnHilite = TRUE;
+                // _Pmpf(("WM_MENUEND"));
+                // At this point, the menu has been
+                // destroyed already.
+                // Since WM_BUTTON1UP handles the
+                // default case that the user presses
+                // the menu button a second time while
+                // the menu is open, we only need
+                // to handle the case that the user
+                // c)   presses some key on the menu (ESC, menu selection) or
+                // a)   selects a menu item (which
+                //      dismisses the menu) or
+                // b)   clicks anywhere else.
+
+                // Case a) if mouse button 1 is not currently down
+                if ((WinGetKeyState(HWND_DESKTOP, VK_BUTTON1) & 0x8000) == 0)
+                    // button 1 _not_ down:
+                    // must be keyboard
+                    fUnHilite = TRUE;
+                else
+                    // button 1 _is_ down:
+                    // query window under mouse pointer
+                    ;
+
+                if (fUnHilite)
+                {
+                    // _Pmpf(("  Unsinking menu WM_MENUEND"));
+                    pmbd->fButtonSunk = FALSE;
+                    WinSendMsg(hwndButton,
+                               BM_SETHILITE,
+                               (MPARAM)FALSE,
+                               (MPARAM)0);
+                }
+                pmbd->hwndMenu = NULLHANDLE;
+            } // end if ((HWND)mp1 == pmbd->pmbd->hwndMenu) // V0.9.14 (2001-07-31) [umoeller]
         break; }
 
Index: trunk/src/helpers/configsys.c
===================================================================
--- trunk/src/helpers/configsys.c	(revision 90)
+++ trunk/src/helpers/configsys.c	(revision 91)
@@ -378,5 +378,5 @@
     {
         // key found in file:
-        ULONG   ulOfs;
+        // ULONG   ulOfs;
 
         // replace existing parameter
Index: trunk/src/helpers/dialog.c
===================================================================
--- trunk/src/helpers/dialog.c	(revision 90)
+++ trunk/src/helpers/dialog.c	(revision 91)
@@ -110,7 +110,10 @@
     const char  *pcszControlsFont;  // from dlghCreateDlg
 
+    // V0.9.14 (2001-08-01) [umoeller]
     HPS         hps;
-    /* const char  *pcszFontLast;
-    LONG        lcidLast; */
+    const char  *pcszFontLast;
+    LONG        lcidLast;
+    FONTMETRICS fmLast;
+
 } DLGPRIVATE, *PDLGPRIVATE;
 
@@ -148,5 +151,5 @@
     BOOL        fIsNestedTable;     // if TRUE, pvDefinition points to a nested TABLEDEF;
                                     // if FALSE, pvDefinition points to a CONTROLDEF as
-                                    // specified by the user
+                                    // specified by the caller
 
     PVOID       pvDefinition;       // either a PTABLEDEF or a PCONTROLDEF
@@ -225,4 +228,5 @@
  *@@changed V0.9.12 (2001-05-31) [umoeller]: fixed various things with statics
  *@@changed V0.9.12 (2001-05-31) [umoeller]: fixed broken fonts
+ *@@changed V0.9.14 (2001-08-01) [umoeller]: now caching fonts, which is significantly faster
  */
 
@@ -232,8 +236,4 @@
                       PDLGPRIVATE pDlgData)
 {
-    BOOL        fFind = FALSE;
-    RECTL       rclText;
-    LONG        lcid = 0;
-
     const char *pcszFontThis = pControlDef->pcszFont;
                     // can be NULL,
@@ -248,19 +248,37 @@
     if (pcszFontThis)
     {
-        FONTMETRICS fm;
         LONG lPointSize = 0;
 
-        // create new font
-        lcid = gpihFindPresFont(NULLHANDLE,        // no window yet
-                                FALSE,
-                                pDlgData->hps,
-                                pcszFontThis,
-                                &fm,
-                                &lPointSize);
-        GpiSetCharSet(pDlgData->hps, lcid);
-        if (fm.fsDefn & FM_DEFN_OUTLINE)
-            gpihSetPointSize(pDlgData->hps, lPointSize);
-
-        pszlAuto->cy = fm.lMaxBaselineExt + fm.lExternalLeading;
+        // check if we can reuse font data from last time
+        // V0.9.14 (2001-08-01) [umoeller]
+        if (strhcmp(pcszFontThis,
+                    pDlgData->pcszFontLast))
+        {
+            // different font than last time:
+
+            // delete old font?
+            if (pDlgData->lcidLast)
+            {
+                GpiSetCharSet(pDlgData->hps, LCID_DEFAULT);
+                GpiDeleteSetId(pDlgData->hps, pDlgData->lcidLast);
+            }
+
+            // create new font
+            pDlgData->lcidLast = gpihFindPresFont(NULLHANDLE,        // no window yet
+                                                  FALSE,
+                                                  pDlgData->hps,
+                                                  pcszFontThis,
+                                                  &pDlgData->fmLast,
+                                                  &lPointSize);
+
+            GpiSetCharSet(pDlgData->hps, pDlgData->lcidLast);
+            if (pDlgData->fmLast.fsDefn & FM_DEFN_OUTLINE)
+                gpihSetPointSize(pDlgData->hps, lPointSize);
+
+            pDlgData->pcszFontLast = pcszFontThis;
+        }
+
+        pszlAuto->cy =   pDlgData->fmLast.lMaxBaselineExt
+                       + pDlgData->fmLast.lExternalLeading;
     }
 
@@ -300,11 +318,4 @@
         }
     }
-
-    /* if (lcid)
-    {
-        GpiSetCharSet(pDlgData->hps, LCID_DEFAULT);
-        GpiDeleteSetId(pDlgData->hps, lcid);
-    } */
-
 }
 
@@ -336,5 +347,10 @@
                                         | BS_CHECKBOX
                                         | BS_RADIOBUTTON))
+            {
+                // give a little extra width for the box bitmap
                 pszlAuto->cx += 20;     // @@todo
+                // and height
+                pszlAuto->cy += 2;
+            }
             else if (pControlDef->flStyle & BS_BITMAP)
                 ;
@@ -722,5 +738,5 @@
                 PDLGPRIVATE pDlgData)
 {
-    ULONG   ul;
+    // ULONG   ul;
     LONG    lX;
     PLISTNODE pNode;
@@ -791,5 +807,5 @@
                   PDLGPRIVATE pDlgData)
 {
-    ULONG   ul;
+    // ULONG   ul;
     LONG    lY;
     PLISTNODE pNode;
@@ -864,5 +880,5 @@
                 PROCESSMODE ProcessMode)
 {
-    ULONG ul;
+    // ULONG ul;
     PLISTNODE pNode;
     CONTROLPOS cpTable;
@@ -943,4 +959,47 @@
 
     return (arc);
+}
+
+/*
+ *@@ FreeTable:
+ *      frees the specified table and recurses
+ *      into nested tables, if necessary.
+ *
+ *      This was added with V0.9.14 to fix the
+ *      bad memory leaks with nested tables.
+ *
+ *@@added V0.9.14 (2001-08-01) [umoeller]
+ */
+
+VOID FreeTable(PTABLEDEF pTable)
+{
+    // for each table, clean up the rows
+    PLISTNODE pRowNode;
+    FOR_ALL_NODES(&pTable->llRows, pRowNode)
+    {
+        PROWDEF pRow = (PROWDEF)pRowNode->pItemData;
+
+        // for each row, clean up the columns
+        PLISTNODE pColumnNode;
+        FOR_ALL_NODES(&pRow->llColumns, pColumnNode)
+        {
+            PCOLUMNDEF pColumn = (PCOLUMNDEF)pColumnNode->pItemData;
+
+            if (pColumn->fIsNestedTable)
+            {
+                // nested table: recurse!
+                PTABLEDEF pNestedTable = (PTABLEDEF)pColumn->pvDefinition;
+                FreeTable(pNestedTable);
+            }
+
+            free(pColumn);
+        }
+        lstClear(&pRow->llColumns);
+
+        free(pRow);
+    }
+    lstClear(&pTable->llRows);
+
+    free(pTable);
 }
 
@@ -1181,4 +1240,5 @@
  *
  *@@changed V0.9.14 (2001-07-07) [umoeller]: fixed disabled mouse with hwndOwner == HWND_DESKTOP
+ *@@changed V0.9.14 (2001-08-01) [umoeller]: fixed major memory leaks with nested tables
  */
 
@@ -1270,10 +1330,10 @@
                         // create "table" column for this
                         PCOLUMNDEF pColumnDef;
-                        arc = CreateColumn(pCurrentRow,
-                                           TRUE,        // nested table
-                                           pCurrentTable,
-                                           &pColumnDef);
-                        if (!arc)
-                            lstAppendItem(&pCurrentRow->llColumns, pColumnDef);
+                        if (!(arc = CreateColumn(pCurrentRow,
+                                                 TRUE,        // nested table
+                                                 pCurrentTable,
+                                                 &pColumnDef)))
+                            lstAppendItem(&pCurrentRow->llColumns,
+                                          pColumnDef);
                     }
                 }
@@ -1319,10 +1379,10 @@
             {
                 PCOLUMNDEF pColumnDef;
-                arc = CreateColumn(pCurrentRow,
-                                   FALSE,        // no nested table
-                                   (PVOID)pItemThis->ulData,
-                                   &pColumnDef);
-                if (!arc)
-                    lstAppendItem(&pCurrentRow->llColumns, pColumnDef);
+                if (!(arc = CreateColumn(pCurrentRow,
+                                         FALSE,        // no nested table
+                                         (PVOID)pItemThis->ulData,
+                                         &pColumnDef)))
+                    lstAppendItem(&pCurrentRow->llColumns,
+                                  pColumnDef);
             break; }
 
@@ -1416,4 +1476,9 @@
                        PROCESS_CALC_SIZES);
 
+            if (pDlgData->lcidLast)
+            {
+                GpiSetCharSet(pDlgData->hps, LCID_DEFAULT);
+                GpiDeleteSetId(pDlgData->hps, pDlgData->lcidLast);
+            }
             if (pDlgData->hps)
                 WinReleasePS(pDlgData->hps);
@@ -1506,24 +1571,6 @@
             PTABLEDEF pTable = (PTABLEDEF)pTableNode->pItemData;
 
-            // for each table, clean up the rows
-            PLISTNODE pRowNode;
-            FOR_ALL_NODES(&pTable->llRows, pRowNode)
-            {
-                PROWDEF pRow = (PROWDEF)pRowNode->pItemData;
-
-                // for each row, clean up the columns
-                PLISTNODE pColumnNode;
-                FOR_ALL_NODES(&pRow->llColumns, pColumnNode)
-                {
-                    PCOLUMNDEF pColumn = (PCOLUMNDEF)pColumnNode->pItemData;
-                    free(pColumn);
-                }
-                lstClear(&pRow->llColumns);
-
-                free(pRow);
-            }
-            lstClear(&pTable->llRows);
-
-            free(pTable);
+            FreeTable(pTable);
+                    // this may recurse for nested tables
         }
 
@@ -1532,4 +1579,13 @@
 
         free(pDlgData);
+    }
+
+    if (arc)
+    {
+        CHAR szErr[300];
+        sprintf(szErr, "Error %d occured in dlghCreateDlg.", arc);
+        winhDebugBox(hwndOwner,
+                     "Error in Dialog Manager",
+                     szErr);
     }
 
Index: trunk/src/helpers/dosh.c
===================================================================
--- trunk/src/helpers/dosh.c	(revision 90)
+++ trunk/src/helpers/dosh.c	(revision 91)
@@ -375,6 +375,6 @@
  */
 
-APIRET doshIsFixedDisk(ULONG  ulLogicalDrive,   // in: 1 for A:, 2 for B:, 3 for C:, ...
-                       PBOOL  pfFixed)          // out: TRUE for fixed disks
+APIRET doshIsFixedDisk(ULONG ulLogicalDrive,   // in: 1 for A:, 2 for B:, 3 for C:, ...
+                       PBOOL pfFixed)          // out: TRUE for fixed disks
 {
     APIRET arc = ERROR_INVALID_DRIVE;
@@ -505,4 +505,150 @@
              && (pdp->usSectorsPerTrack == (USHORT)-1)
            );
+}
+
+/*
+ *@@ doshHasAudioCD:
+ *      sets *pfAudio to whether ulLogicalDrive
+ *      currently has an audio CD inserted.
+ *
+ *      Better call this only if you're sure that
+ *      ulLogicalDrive is a CD-ROM drive. Use
+ *      doshIsCDROM to check.
+ *
+ *@@added V0.9.14 (2001-08-01) [umoeller]
+ */
+
+APIRET doshHasAudioCD(ULONG ulLogicalDrive,
+                      BOOL fMixedModeCD,
+                      PBOOL pfAudio)
+{
+    APIRET  arc = NO_ERROR;
+
+    HFILE   hfDrive = 0;
+    ULONG   ulTemp = 0;
+
+    CHAR    szDrive[3] = "C:";
+    szDrive[0] = 'A' + ulLogicalDrive - 1;
+
+    *pfAudio = FALSE;
+
+    arc = DosOpen(szDrive,   // "C:", "D:", ...
+                  &hfDrive,
+                  &ulTemp,
+                  0,
+                  FILE_NORMAL,
+                  OPEN_ACTION_FAIL_IF_NEW
+                         | OPEN_ACTION_OPEN_IF_EXISTS,
+                  OPEN_FLAGS_DASD
+                         | OPEN_FLAGS_FAIL_ON_ERROR
+                         | OPEN_FLAGS_NOINHERIT     // V0.9.6 (2000-11-25) [pr]
+              //            | OPEN_ACCESS_READONLY  // V0.9.13 (2001-06-14) [umoeller]
+                         | OPEN_SHARE_DENYNONE,
+                  NULL);
+
+    // _Pmpf(("   DosOpen(OPEN_FLAGS_DASD) returned %d", arc));
+
+    // this still returns NO_ERROR for audio CDs in a
+    // CD-ROM drive...
+    // however, the WPS then attempts to read in the
+    // root directory for audio CDs, which produces
+    // a "sector not found" error box...
+
+    if (!arc && hfDrive)     // determined above
+    {
+        ULONG ulAudioTracks = 0,
+              ulDataTracks = 0;
+
+        CHAR cds1[4] = { 'C', 'D', '0', '1' };
+        CHAR cds2[4];
+        // check for proper driver signature
+        if (!(arc = doshDevIOCtl(hfDrive,
+                                 IOCTL_CDROMDISK,
+                                 CDROMDISK_GETDRIVER,
+                                 &cds1, sizeof(cds1),
+                                 &cds2, sizeof(cds2))))
+        {
+            if (memcmp(&cds1, &cds2, 4))
+                // this is not a CD-ROM then:
+                arc = NO_ERROR;
+            else
+            {
+                struct {
+                    UCHAR   ucFirstTrack,
+                            ucLastTrack;
+                    ULONG   ulLeadOut;
+                } cdat;
+
+                // get track count
+                if (!(arc = doshDevIOCtl(hfDrive,
+                                         IOCTL_CDROMAUDIO,
+                                         CDROMAUDIO_GETAUDIODISK,
+                                         &cds1, sizeof(cds1),
+                                         &cdat, sizeof(cdat))))
+                {
+                    // still no error: build the audio TOC
+                    ULONG i;
+                    for (i = cdat.ucFirstTrack;
+                         i <= cdat.ucLastTrack;
+                         i++)
+                    {
+                        BYTE cdtp[5] =
+                          { 'C', 'D', '0', '1', (UCHAR)i };
+
+                        struct {
+                            ULONG   ulTrackAddress;
+                            BYTE    bFlags;
+                        } trackdata;
+
+                        if (!(arc = doshDevIOCtl(hfDrive,
+                                                 IOCTL_CDROMAUDIO,
+                                                 CDROMAUDIO_GETAUDIOTRACK,
+                                                 &cdtp, sizeof(cdtp),
+                                                 &trackdata, sizeof(trackdata))))
+                        {
+                            if (trackdata.bFlags & 64)
+                                ulDataTracks++;
+                            else
+                            {
+                                ulAudioTracks++;
+
+                                if (!fMixedModeCD)
+                                {
+                                    // caller doesn't want mixed mode:
+                                    // stop here
+                                    ulDataTracks = 0;
+                                    break;
+                                }
+                            }
+                        }
+                    }
+
+                    // _Pmpf(("   got %d audio, %d data tracks",
+                    //             ulAudioTracks, ulDataTracks));
+
+                    if (!ulDataTracks)
+                        *pfAudio = TRUE;
+                }
+                else
+                {
+                    // not audio disk:
+                    // go on then
+                    // _Pmpf(("   CDROMAUDIO_GETAUDIODISK returned %d", arc));
+                    arc = NO_ERROR;
+                }
+            }
+        }
+        else
+        {
+            // not CD-ROM: go on then
+            // _Pmpf(("   CDROMDISK_GETDRIVER returned %d", arc));
+            arc = NO_ERROR;
+        }
+    }
+
+    if (hfDrive)
+        DosClose(hfDrive);
+
+    return (arc);
 }
 
@@ -679,6 +825,4 @@
                        ULONG fl)                // in: ASSERTFL_* flags
 {
-    HFILE   hfDrive = 0;
-    ULONG   ulTemp = 0;
     APIRET  arc = NO_ERROR;
     BOOL    fFixed = FALSE,
@@ -713,121 +857,13 @@
         }
 
-    if (!arc)
-    {
-        CHAR    szDrive[3] = "C:";
-        szDrive[0] = 'A' + ulLogicalDrive - 1;
-        arc = DosOpen(szDrive,   // "C:", "D:", ...
-                      &hfDrive,
-                      &ulTemp,
-                      0,
-                      FILE_NORMAL,
-                      OPEN_ACTION_FAIL_IF_NEW
-                             | OPEN_ACTION_OPEN_IF_EXISTS,
-                      OPEN_FLAGS_DASD
-                             | OPEN_FLAGS_FAIL_ON_ERROR
-                             | OPEN_FLAGS_NOINHERIT     // V0.9.6 (2000-11-25) [pr]
-                  //            | OPEN_ACCESS_READONLY  // V0.9.13 (2001-06-14) [umoeller]
-                             | OPEN_SHARE_DENYNONE,
-                      NULL);
-
-        // _Pmpf(("   DosOpen(OPEN_FLAGS_DASD) returned %d", arc));
-
-        // this still returns NO_ERROR for audio CDs in a
-        // CD-ROM drive...
-        // however, the WPS then attempts to read in the
-        // root directory for audio CDs, which produces
-        // a "sector not found" error box...
-
-        if (!arc && hfDrive && fCDROM)     // determined above
-        {
-            ULONG ulAudioTracks = 0,
-                  ulDataTracks = 0;
-
-            CHAR cds1[4] = { 'C', 'D', '0', '1' };
-            CHAR cds2[4];
-            // check for proper driver signature
-            if (!(arc = doshDevIOCtl(hfDrive,
-                                     IOCTL_CDROMDISK,
-                                     CDROMDISK_GETDRIVER,
-                                     &cds1, sizeof(cds1),
-                                     &cds2, sizeof(cds2))))
-            {
-                if (memcmp(&cds1, &cds2, 4))
-                    // this is not a CD-ROM then:
-                    arc = NO_ERROR;
-                else
-                {
-                    struct {
-                        UCHAR   ucFirstTrack,
-                                ucLastTrack;
-                        ULONG   ulLeadOut;
-                    } cdat;
-
-                    // get track count
-                    if (!(arc = doshDevIOCtl(hfDrive,
-                                             IOCTL_CDROMAUDIO,
-                                             CDROMAUDIO_GETAUDIODISK,
-                                             &cds1, sizeof(cds1),
-                                             &cdat, sizeof(cdat))))
-                    {
-                        // still no error: build the audio TOC
-                        ULONG i;
-                        for (i = cdat.ucFirstTrack;
-                             i <= cdat.ucLastTrack;
-                             i++)
-                        {
-                            BYTE cdtp[5] =
-                              { 'C', 'D', '0', '1', (UCHAR)i };
-
-                            struct {
-                                ULONG   ulTrackAddress;
-                                BYTE    bFlags;
-                            } trackdata;
-
-                            if (!(arc = doshDevIOCtl(hfDrive,
-                                                     IOCTL_CDROMAUDIO,
-                                                     CDROMAUDIO_GETAUDIOTRACK,
-                                                     &cdtp, sizeof(cdtp),
-                                                     &trackdata, sizeof(trackdata))))
-                            {
-                                if (trackdata.bFlags & 64)
-                                    ulDataTracks++;
-                                else
-                                {
-                                    ulAudioTracks++;
-
-                                    if (!(fl & ASSERTFL_MIXEDMODECD))
-                                    {
-                                        // caller doesn't want mixed mode:
-                                        // stop here
-                                        ulDataTracks = 0;
-                                        break;
-                                    }
-                                }
-                            }
-                        }
-
-                        // _Pmpf(("   got %d audio, %d data tracks",
-                        //             ulAudioTracks, ulDataTracks));
-
-                        if (!ulDataTracks)
-                            arc = ERROR_AUDIO_CD_ROM;       // special private error code (10000)
-                    }
-                    else
-                    {
-                        // not audio disk:
-                        // go on then
-                        // _Pmpf(("   CDROMAUDIO_GETAUDIODISK returned %d", arc));
-                        arc = NO_ERROR;
-                    }
-                }
-            }
-            else
-            {
-                // not CD-ROM: go on then
-                // _Pmpf(("   CDROMDISK_GETDRIVER returned %d", arc));
-                arc = NO_ERROR;
-            }
-        }
+    if ((!arc) && (fCDROM))
+    {
+        BOOL fAudio;
+        if (    (!(arc = doshHasAudioCD(ulLogicalDrive,
+                                        ((fl & ASSERTFL_MIXEDMODECD) != 0),
+                                        &fAudio)))
+             && (fAudio)
+           )
+            arc = ERROR_AUDIO_CD_ROM;       // special private error code (10000)
     }
 
@@ -867,7 +903,4 @@
     }
 
-    if (hfDrive)
-        DosClose(hfDrive);
-
     return (arc);
 }
@@ -887,7 +920,7 @@
     CHAR    name[3] = "?:";
     ULONG   fd = 0,
-            action = 0,
-            paramsize = 0,
-            datasize = 0;
+            action = 0;
+//             paramsize = 0;
+//             datasize = 0;
     APIRET  rc = NO_ERROR;
     USHORT  data,
@@ -913,6 +946,6 @@
         param = 0;
         data = (USHORT)ulLogicalDrive;
-        paramsize = sizeof(param);
-        datasize = sizeof(data);
+        // paramsize = sizeof(param);
+        // datasize = sizeof(data);
         rc = doshDevIOCtl(fd,
                           IOCTL_DISK, DSK_SETLOGICALMAP,
@@ -941,5 +974,5 @@
     APIRET      arc = NO_ERROR;
     FSALLOCATE  fsa;
-    double      dbl = -1;
+    // double      dbl = -1;
 
     if (!(arc = DosQueryFSInfo(ulLogicalDrive, FSIL_ALLOC, &fsa, sizeof(fsa))))
@@ -967,5 +1000,5 @@
     APIRET      arc = NO_ERROR;
     FSALLOCATE  fsa;
-    double      dbl = -1;
+    // double      dbl = -1;
 
     if (!(arc = DosQueryFSInfo(ulLogicalDrive, FSIL_ALLOC, &fsa, sizeof(fsa))))
@@ -983,4 +1016,5 @@
  *
  *@@changed V0.9.1 (99-12-12) [umoeller]: added cbBuf to prototype
+ *@@changed V0.9.14 (2001-08-01) [umoeller]: fixed, this never respected cbBuf
  */
 
@@ -1015,6 +1049,8 @@
             // Each data field following fsqBuffer.szName begins
             // immediately after the previous item.
-            strcpy(pszBuf,
-                   (CHAR*)(&pfsqBuffer->szName) + pfsqBuffer->cbName + 1);
+            strncpy(pszBuf,
+                    (CHAR*)(&pfsqBuffer->szName) + pfsqBuffer->cbName + 1,
+                    cbBuf);         // V0.9.14 (2001-08-01) [umoeller]
+            *(pszBuf + cbBuf) = '\0';
         }
     }
@@ -2462,5 +2498,5 @@
  ********************************************************************/
 
-static PVOID    G_pvGlobalInfoSeg = NULL,
+static PVOID    // G_pvGlobalInfoSeg = NULL,
                 G_pvLocalInfoSeg = NULL;
 
@@ -2482,6 +2518,6 @@
                     &LocalInfoSegSelector);
     // thunk
-    G_pvGlobalInfoSeg = (PVOID)(   (GlobalInfoSegSelector << 0x000D)
-                                 & 0x01fff0000);
+    /* G_pvGlobalInfoSeg = (PVOID)(   (GlobalInfoSegSelector << 0x000D)
+                                 & 0x01fff0000); */
     G_pvLocalInfoSeg  = (PVOID)(   (LocalInfoSegSelector << 0x000D)
                                  & 0x01fff0000);
Index: trunk/src/helpers/dosh2.c
===================================================================
--- trunk/src/helpers/dosh2.c	(revision 90)
+++ trunk/src/helpers/dosh2.c	(revision 91)
@@ -753,5 +753,5 @@
 VOID ParseBldLevel(PEXECUTABLE pExec)
 {
-    const char  *pStartOfAuthor = 0,
+    const char  // *pStartOfAuthor = 0,
                 *pStartOfVendor = 0;
 
@@ -1601,5 +1601,5 @@
         BYTE   bLen;
         CHAR   achName[256];
-        int    i;
+        // int    i;
 
         ENSURE(DosRead(pExec->hfExe, &bLen, 1, &ulDummy));
@@ -1747,6 +1747,6 @@
             if (cFunctions)
             {
-                USHORT usOrdinal = 1,
-                       usCurrent = 0;
+                // USHORT usOrdinal = 1;
+                       // usCurrent = 0;
 
                 paFunctions = (PFSYSFUNCTION)malloc(sizeof(FSYSFUNCTION) * cFunctions);
@@ -3707,5 +3707,5 @@
                 ADDRESS hDrive = pDriveControlRecord->Drive_Handle;
 
-                Drive_Information_Record pDriveInfoRecord
+                /* Drive_Information_Record pDriveInfoRecord
                     = pLVMInfo->Get_Drive_Status(hDrive,
                                                  &Error);
@@ -3713,5 +3713,5 @@
                 _Pmpf(("  drive %d Get_Drive_Status Error: %d", ulDisk, Error));
 
-                if (!Error)
+                if (!Error) */
                 {
                     Partition_Information_Array PIA
@@ -3770,7 +3770,7 @@
                     }
                 }
-                else
+                /* else
                     // error:
-                    break;
+                    break; */
             }
 
Index: trunk/src/helpers/gpih.c
===================================================================
--- trunk/src/helpers/gpih.c	(revision 90)
+++ trunk/src/helpers/gpih.c	(revision 91)
@@ -603,5 +603,6 @@
  *
  *      gpihFindFont uses this mutex. If you call GpiCreateLogFont
- *      yourself somewhere, do this after you called this function.
+ *      yourself somewhere, you should do this under the protection
+ *      of this function.
  *
  *      Call gpihUnlockLCIDs to unlock.
@@ -612,17 +613,13 @@
 BOOL gpihLockLCIDs(VOID)
 {
-    BOOL brc = FALSE;
-
-    if (G_hmtxLCIDs == NULLHANDLE)
+    if (!G_hmtxLCIDs)
         // first call: create
-        brc = !DosCreateMutexSem(NULL,
-                                 &G_hmtxLCIDs,
-                                 0,
-                                 TRUE);     // request!
-    else
-        // subsequent calls: request
-        brc = !WinRequestMutexSem(G_hmtxLCIDs, SEM_INDEFINITE_WAIT);
-
-    return (brc);
+        return (!DosCreateMutexSem(NULL,
+                                   &G_hmtxLCIDs,
+                                   0,
+                                   TRUE));     // request!
+
+    // subsequent calls: request
+    return (!WinRequestMutexSem(G_hmtxLCIDs, SEM_INDEFINITE_WAIT));
 }
 
@@ -741,93 +738,4 @@
         if (allcids)
             free(allcids);
-
-/*
-        PLONG   pBase;
-        APIRET  arc;
-
-        // _Pmpf(("gpihQueryNextFontID: calling DosAllocMem"));
-
-        arc = DosAllocMem((PPVOID)(&pBase),
-                          GQNCL_BLOCK_SIZE,
-                                   // space is needed for an array of lCount longs.
-                          PAG_READ |
-                          PAG_WRITE);
-        if (arc == NO_ERROR)
-        {
-            arc = DosSubSetMem(pBase,
-                               DOSSUB_INIT | DOSSUB_SPARSE_OBJ,
-                               GQNCL_BLOCK_SIZE);
-            if (arc == NO_ERROR)
-            {
-                PLONG  alTypes;  // object types
-                PSTR8  aNames;   // font names
-                PLONG  allcids;  // local identifiers
-
-                arc = DosSubAllocMem((PVOID)pBase,
-                                     (PPVOID)(&aNames),
-                                     (ULONG)(lCount*(ULONG)sizeof(STR8)));
-                                             // space is needed for an array of
-                                             // lCount longs
-                if (arc == NO_ERROR)
-                {
-                    arc = DosSubAllocMem((PVOID)pBase,
-                                             (PPVOID)(&allcids),
-                                             (ULONG)lCount*sizeof(LONG));
-                                                // space is needed for an array of
-                                                // lCount longs.
-                    if (arc == NO_ERROR)
-                    {
-                        arc = DosSubAllocMem((PVOID)pBase,
-                                                 (PPVOID)(&alTypes),
-                                                 (ULONG)lCount*sizeof(LONG));
-                                                    // space is needed for an array of
-                                                    // lCount longs.
-                        if (arc == NO_ERROR)
-                        {
-                            if (GpiQuerySetIds(hps,
-                                               lCount,
-                                               alTypes,
-                                               aNames,
-                                               allcids))
-                            {
-                                // FINALLY we have all the lcids in use.
-                                BOOL    fContinue = TRUE;
-                                lcidNext = 1;
-
-                                // now, check if this lcid is in use already:
-                                while (fContinue)
-                                {
-                                    BOOL fFound = FALSE;
-                                    ULONG ul;
-                                    fContinue = FALSE;
-                                    for (ul = 0;
-                                         ul < lCount;
-                                         ul++)
-                                    {
-                                        if (allcids[ul] == lcidNext)
-                                        {
-                                            fFound = TRUE;
-                                            break;
-                                        }
-                                    }
-
-                                    if (fFound)
-                                    {
-                                        // lcid found:
-                                        // try next higher one
-                                        lcidNext++;
-                                        fContinue = TRUE;
-                                    }
-                                    // else: return that one
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-
-            arc = DosFreeMem(pBase);
-        }
-        */
     }
 
@@ -1006,4 +914,5 @@
  *@@changed V0.9.4 (2000-08-08) [umoeller]: added fFamily
  *@@changed V0.9.9 (2001-04-01) [umoeller]: made this thread-safe, finally
+ *@@changed V0.9.14 (2001-08-01) [umoeller]: some optimizations
  */
 
@@ -1012,5 +921,5 @@
                   BOOL fFamily,          // in: if TRUE, pszName specifies font family;
                                          //     if FALSE, pszName specifies font face
-                  PSZ pszName,           // in: font family or face name (without point size)
+                  const char *pcszName,  // in: font family or face name (without point size)
                   USHORT usFormat,       // in: none, one or several of:
                                          // -- FATTR_SEL_ITALIC
@@ -1034,7 +943,10 @@
                                    sizeof(FONTMETRICS),
                                    NULL);
-    PFONTMETRICS pfm = (PFONTMETRICS)malloc(cFonts * sizeof(FONTMETRICS)),
-                 pfm2 = pfm,
-                 pfmFound = NULL;
+    PFONTMETRICS    pfm = (PFONTMETRICS)malloc(cFonts * sizeof(FONTMETRICS)),
+                    pfm2 = pfm,
+                    pfmFound = NULL;
+
+    BOOL            fQueriedDevice = FALSE;     // V0.9.14 (2001-08-01) [umoeller]
+    LONG            alDevRes[2];            // device resolution
 
     // _Pmpf(("gpihFindFont: enumerating for %s, %d points", pszFaceName, lSize));
@@ -1047,4 +959,5 @@
                                             // -- _not_ total buffer size!
                   pfm);
+
     // now we have an array of FONTMETRICS
     // for EVERY font that is installed on the system...
@@ -1066,5 +979,5 @@
     FontAttrs.fsSelection = usFormat; // changed later if better font is found
     FontAttrs.lMatch = 0L;             // closest match
-    strcpy(FontAttrs.szFacename, pszName);
+    strcpy(FontAttrs.szFacename, pcszName);
     FontAttrs.idRegistry = 0;          // default registry
     FontAttrs.usCodePage = 0;          // default codepage
@@ -1095,9 +1008,9 @@
                pfm2->lAveCharWidth)); */
 
-        PSZ pszCompare = (fFamily)
-                              ? pfm2->szFamilyname
-                              : pfm2->szFacename;
-
-        if (strcmp(pszCompare, pszName) == 0)
+        const char *pcszCompare = (fFamily)
+                                     ? pfm2->szFamilyname
+                                     : pfm2->szFacename;
+
+        if (!strcmp(pcszCompare, pcszName))
         {
             /* _Pmpf(("  Found font %s; slope %d, usWeightClass %d",
@@ -1117,9 +1030,13 @@
                     // for bitmap fonts, there are always two versions:
                     // one for low resolutions, one for high resolutions
-                    LONG    alDevRes[2];
-                    DevQueryCaps(GpiQueryDevice(hps),
-                                 CAPS_HORIZONTAL_FONT_RES,
-                                 2L,
-                                 alDevRes);
+                    if (!fQueriedDevice)
+                    {
+                        DevQueryCaps(GpiQueryDevice(hps),
+                                     CAPS_HORIZONTAL_FONT_RES,
+                                     2L,
+                                     alDevRes);
+                        fQueriedDevice = TRUE;
+                    }
+
                     if (    (pfm2->sXDeviceRes == alDevRes[0])
                          && (pfm2->sYDeviceRes == alDevRes[1])
@@ -1151,5 +1068,5 @@
                                  && (pfm2->usWeightClass == 7) // bold
                                 )
-                            ||  (   ((usFormat & FATTR_SEL_BOLD) == 0)
+                            ||  (   (!(usFormat & FATTR_SEL_BOLD))
                                  && (pfm2->usWeightClass == 5) // regular
                                 )
@@ -1158,5 +1075,5 @@
                                  && (pfm2->sCharSlope != 0) // italics
                                 )
-                            ||  (   ((usFormat & FATTR_SEL_ITALIC) == 0)
+                            ||  (   (!(usFormat & FATTR_SEL_ITALIC))
                                  && (pfm2->sCharSlope == 0) // regular
                                 )
@@ -2075,5 +1992,5 @@
  *      You can then use any GPI function on the memory
  *      PS to draw into the bitmap. Use the fields from
- *      _XBITMAP for that.
+ *      XBITMAP for that.
  *
  *      The bitmap is created in RGB mode.
@@ -2144,5 +2061,5 @@
  *
  *      To be on the safe side, this sets the
- *      bitmap pointer to NULL as well.
+ *      given XBITMAP pointer to NULL as well.
  *
  *@@added V0.9.12 (2001-05-20) [umoeller]
Index: trunk/src/helpers/helpers_pre.in
===================================================================
--- trunk/src/helpers/helpers_pre.in	(revision 90)
+++ trunk/src/helpers/helpers_pre.in	(revision 91)
@@ -52,4 +52,5 @@
 
 CPOBJS = $(PLAINCOBJS) $(XMLOBJS) \
+$(OUTPUTDIR)\apmh.obj \
 $(OUTPUTDIR)\datetime.obj \
 $(OUTPUTDIR)\debug.obj \
Index: trunk/src/helpers/linklist.c
===================================================================
--- trunk/src/helpers/linklist.c	(revision 90)
+++ trunk/src/helpers/linklist.c	(revision 91)
@@ -85,4 +85,5 @@
 #include "setup.h"                      // code generation and debugging options
 
+#define DONT_REPLACE_LIST_MALLOC
 #include "helpers\linklist.h"
 
@@ -263,5 +264,7 @@
 }
 
-#else       // __DEBUG_MALLOC_ENABLED__
+#endif
+
+// #else       // __DEBUG_MALLOC_ENABLED__
 
 /*
@@ -295,5 +298,5 @@
 }
 
-#endif      // __DEBUG_MALLOC_ENABLED__
+// #endif      // __DEBUG_MALLOC_ENABLED__
 
 /*
@@ -616,5 +619,7 @@
 }
 
-#else  // __DEBUG_MALLOC_ENABLED__
+#endif
+
+// #else  // __DEBUG_MALLOC_ENABLED__
 
 /*
@@ -670,5 +675,5 @@
 }
 
-#endif // __DEBUG_MALLOC_ENABLED__
+// #endif // __DEBUG_MALLOC_ENABLED__
 
 /*
@@ -790,5 +795,6 @@
  */
 
-BOOL lstRemoveNode(PLINKLIST pList, PLISTNODE pRemoveNode)
+BOOL lstRemoveNode(PLINKLIST pList,
+                   PLISTNODE pRemoveNode)
 {
     BOOL fFound = FALSE;
Index: trunk/src/helpers/memdebug.c
===================================================================
--- trunk/src/helpers/memdebug.c	(revision 90)
+++ trunk/src/helpers/memdebug.c	(revision 91)
@@ -382,4 +382,5 @@
         {
             if (pHeapItem->pAfterMagic == p)
+            {
                 // the same address may be allocated and freed
                 // several times, so if this address has been
@@ -429,4 +430,5 @@
                     break;
                 } // if (!pHeapItem->fFreed)
+            }
 
             pHeapItem = pHeapItem->pNext;
@@ -702,4 +704,5 @@
 {
     int i = 0;
+    i++;
 }
 #endif
Index: trunk/src/helpers/memdebug_win.c
===================================================================
--- trunk/src/helpers/memdebug_win.c	(revision 90)
+++ trunk/src/helpers/memdebug_win.c	(revision 91)
@@ -104,4 +104,7 @@
 
     ULONG       ulLine;
+
+    ULONG       ulAddress;      // has pAfterMagic, invisible, only
+                                // for sorting V0.9.14 (2001-08-01) [umoeller]
 
     PSZ         pszAddress;     // points to szAddress
@@ -235,6 +238,10 @@
                 }
 
-                sprintf(pMemRecordThis->szAddress, "0x%lX", pMemRecordThis->pObject);
-                strcpy(pMemRecordThis->szSource,
+                pMemRecordThis->ulAddress = (ULONG)pMemRecordThis->pObject;
+
+                sprintf(pMemRecordThis->szAddress,
+                        "0x%lX",
+                        pMemRecordThis->pObject);
+                strhcpy(pMemRecordThis->szSource,
                         (pMemRecordThis->filename)
                             ? pMemRecordThis->filename
@@ -332,13 +339,17 @@
                 pMemRecordThis->ulTID = pHeapItem->ulTID;
 
-                strcpy(pMemRecordThis->szSource, pHeapItem->pcszSourceFile);
+                strhcpy(pMemRecordThis->szSource, pHeapItem->pcszSourceFile);
                 pMemRecordThis->pszSource = pMemRecordThis->szSource;
 
                 pMemRecordThis->ulLine = pHeapItem->ulLine;
 
-                strcpy(pMemRecordThis->szFunction, pHeapItem->pcszFunction);
+                strhcpy(pMemRecordThis->szFunction, pHeapItem->pcszFunction);
                 pMemRecordThis->pszFunction = pMemRecordThis->szFunction;
 
-                sprintf(pMemRecordThis->szAddress, "0x%lX", pHeapItem->pAfterMagic);
+                pMemRecordThis->ulAddress = (ULONG)pHeapItem->pAfterMagic;
+
+                sprintf(pMemRecordThis->szAddress,
+                        "0x%lX",
+                        pHeapItem->pAfterMagic);
                 pMemRecordThis->pszAddress = pMemRecordThis->szAddress;
 
@@ -361,5 +372,5 @@
 
                 sprintf(pMemRecordThis->szAddress, "0x%lX", pMemRecordThis->pObject);
-                strcpy(pMemRecordThis->szSource,
+                strhcpy(pMemRecordThis->szSource,
                         (pMemRecordThis->filename)
                             ? pMemRecordThis->filename
@@ -391,5 +402,4 @@
 SHORT EXPENTRY mnu_fnCompareIndex(PMEMRECORD pmrc1, PMEMRECORD  pmrc2, PVOID pStorage)
 {
-    // HAB habDesktop = WinQueryAnchorBlock(HWND_DESKTOP);
     pStorage = pStorage; // to keep the compiler happy
     if ((pmrc1) && (pmrc2))
@@ -434,10 +444,9 @@
  *@@ mnu_fnCompareSourceFile:
  *
- *V0.9.6 (2000-11-12) [umoeller]
+ *@@added V0.9.6 (2000-11-12) [umoeller]
  */
 
 SHORT EXPENTRY mnu_fnCompareSize(PMEMRECORD pmrc1, PMEMRECORD  pmrc2, PVOID pStorage)
 {
-    HAB habDesktop = WinQueryAnchorBlock(HWND_DESKTOP);
     pStorage = pStorage; // to keep the compiler happy
     if ((pmrc1) && (pmrc2))
@@ -452,4 +461,24 @@
 }
 
+/*
+ *@@ mnu_fnCompareAddress:
+ *
+ *@@added V0.9.14 (2001-08-01) [umoeller]
+ */
+
+SHORT EXPENTRY mnu_fnCompareAddress(PMEMRECORD pmrc1, PMEMRECORD  pmrc2, PVOID pStorage)
+{
+    pStorage = pStorage; // to keep the compiler happy
+    if ((pmrc1) && (pmrc2))
+    {
+        if (pmrc1->ulAddress > pmrc2->ulAddress)
+            return (1);
+        else if (pmrc1->ulAddress < pmrc2->ulAddress)
+            return (-1);
+    }
+
+    return (0);
+}
+
 #define ID_MEMCNR   1000
 
@@ -469,4 +498,5 @@
  *
  *@@added V0.9.1 (99-12-04) [umoeller]
+ *@@changed V0.9.14 (2001-08-01) [umoeller]: added sort by address
  */
 
@@ -648,4 +678,9 @@
                                        "Sort by object size",
                                        MIS_TEXT, 0);
+                    winhInsertMenuItem(G_hwndMemDebugMenu,
+                                       MIT_END,
+                                       1004,
+                                       "Sort by address",
+                                       MIS_TEXT, 0);
 
                     WinSetFocus(HWND_DESKTOP, hwndCnr);
@@ -715,4 +750,11 @@
                                CM_SORTRECORD,
                                (MPARAM)mnu_fnCompareSize,
+                               0);
+                break;
+
+                case 1004: // sort by address V0.9.14 (2001-08-01) [umoeller]
+                    WinSendMsg(WinWindowFromID(hwndClient, ID_MEMCNR),
+                               CM_SORTRECORD,
+                               (MPARAM)mnu_fnCompareAddress,
                                0);
                 break;
@@ -788,4 +830,5 @@
 {
     int i = 0;
+    i++;
 }
 #endif
Index: trunk/src/helpers/stringh.c
===================================================================
--- trunk/src/helpers/stringh.c	(revision 90)
+++ trunk/src/helpers/stringh.c	(revision 91)
@@ -52,4 +52,5 @@
 #include "setup.h"                      // code generation and debugging options
 
+#define DONT_REPLACE_STRINGH_MALLOC
 #include "helpers\stringh.h"
 #include "helpers\xstring.h"            // extended string helpers
@@ -68,7 +69,52 @@
 
 /*
+ *@@ strcpy:
+ *      like strdup, but this one doesn't crash if string2 is NULL,
+ *      but sets the first byte in string1 to \0 instead.
+ *
+ *@@added V0.9.14 (2001-08-01) [umoeller]
+ */
+
+PSZ strhcpy(PSZ string1, const char *string2)
+{
+    if (string2)
+        return (strcpy(string1, string2));
+
+    *string1 = '\0';
+    return (string1);
+}
+
+#ifdef __DEBUG_MALLOC_ENABLED__
+
+/*
  *@@ strhdup:
- *      like strdup, but this one
- *      doesn't crash if pszSource is NULL,
+ *      memory debug version of strhdup.
+ *
+ *@@added V0.9.0 [umoeller]
+ */
+
+PSZ strhdupDebug(const char *pszSource,
+                 const char *pcszSourceFile,
+                 unsigned long ulLine,
+                 const char *pcszFunction)
+{
+    if (pszSource)
+    {
+        PSZ p = (PSZ)memdMalloc(strlen(pszSource) + 1,
+                                pcszSourceFile,
+                                ulLine,
+                                pcszFunction);
+        strcpy(p,  pszSource);
+        return (p);
+    }
+    else
+        return (0);
+}
+
+#endif // __DEBUG_MALLOC_ENABLED__
+
+/*
+ *@@ strhdup:
+ *      like strdup, but this one doesn't crash if pszSource is NULL,
  *      but returns NULL also.
  *
@@ -248,4 +294,40 @@
 }
 
+#ifdef __DEBUG_MALLOC_ENABLED__
+
+/*
+ *@@ strhSubstrDebug:
+ *      memory debug version of strhSubstr.
+ *
+ *@@added V0.9.14 (2001-08-01) [umoeller]
+ */
+
+PSZ strhSubstrDebug(const char *pBegin,      // in: first char
+                    const char *pEnd,        // in: last char (not included)
+                    const char *pcszSourceFile,
+                    unsigned long ulLine,
+                    const char *pcszFunction)
+{
+    PSZ pszSubstr = NULL;
+
+    if (pEnd > pBegin)      // V0.9.9 (2001-04-04) [umoeller]
+    {
+        ULONG cbSubstr = (pEnd - pBegin);
+        if (pszSubstr = (PSZ)memdMalloc(cbSubstr + 1,
+                                        pcszSourceFile,
+                                        ulLine,
+                                        pcszFunction))
+        {
+            // strhncpy0(pszSubstr, pBegin, cbSubstr);
+            memcpy(pszSubstr, pBegin, cbSubstr);        // V0.9.9 (2001-04-04) [umoeller]
+            *(pszSubstr + cbSubstr) = '\0';
+        }
+    }
+
+    return (pszSubstr);
+}
+
+#endif // __DEBUG_MALLOC_ENABLED__
+
 /*
  *@@ strhSubstr:
@@ -274,8 +356,6 @@
     {
         ULONG cbSubstr = (pEnd - pBegin);
-        pszSubstr = (PSZ)malloc(cbSubstr + 1);
-        if (pszSubstr)
+        if (pszSubstr = (PSZ)malloc(cbSubstr + 1))
         {
-            // strhncpy0(pszSubstr, pBegin, cbSubstr);
             memcpy(pszSubstr, pBegin, cbSubstr);        // V0.9.9 (2001-04-04) [umoeller]
             *(pszSubstr + cbSubstr) = '\0';
Index: trunk/src/helpers/textv_html.c
===================================================================
--- trunk/src/helpers/textv_html.c	(revision 90)
+++ trunk/src/helpers/textv_html.c	(revision 91)
@@ -1341,5 +1341,5 @@
             // end of tag found:
             ULONG cbTag;
-            PSZ pStartOfAttrs = 0;
+            // PSZ pStartOfAttrs = 0;
 
             if ((pNextSpace) && (pNextSpace < pNextClose))
@@ -1347,5 +1347,5 @@
                 // we have attributes:
                 cbTag = pNextSpace - (pStartOfTag + 1);
-                pStartOfAttrs = pNextSpace;
+                // pStartOfAttrs = pNextSpace;
             }
             else
Index: trunk/src/helpers/textview.c
===================================================================
--- trunk/src/helpers/textview.c	(revision 90)
+++ trunk/src/helpers/textview.c	(revision 91)
@@ -625,6 +625,6 @@
                     pWordEnd = NULL;
         PSZ         pCheck = *ppStartOfWord;
-        ULONG       cChars = 0,
-                    cCheck = 0;
+        ULONG       cChars = 0;
+                    // cCheck = 0;
 
         pWord = (PTXVWORD)malloc(sizeof(TXVWORD));
@@ -656,5 +656,5 @@
             // cChars is != 0 if strhGetWord succeeded AND the
             // line is not empty, so go on
-            cCheck = cChars;
+            // cCheck = cChars;
 
             // advance input pointer
@@ -3048,5 +3048,5 @@
                         if (ptxvd->cdata.flStyle & XTXF_VSCROLL)
                         {
-                            BOOL fEnabled = winhUpdateScrollBar(ptxvd->hwndVScroll,
+                            /* BOOL fEnabled = */ winhUpdateScrollBar(ptxvd->hwndVScroll,
                                                                 ulWinCY,
                                                                 ptxvd->xfd.ulViewportCY,
@@ -3219,5 +3219,5 @@
                       NULL);    // reserved
 
-    if (cbNeeded)
+    if (!rc && cbNeeded)
     {
         pprq3 = (PRQINFO3*)malloc(cbNeeded);
Index: trunk/src/helpers/timer.c
===================================================================
--- trunk/src/helpers/timer.c	(revision 90)
+++ trunk/src/helpers/timer.c	(revision 91)
@@ -110,4 +110,5 @@
 #include "helpers\linklist.h"
 #include "helpers\math.h"
+#include "helpers\standards.h"
 #include "helpers\threads.h"
 #include "helpers\timer.h"
@@ -248,6 +249,6 @@
 {
     PLINKLIST pllXTimers = (PLINKLIST)pSet->pvllXTimers;
-    PLISTNODE pNode = lstQueryFirstNode(pllXTimers);
-    if (!pNode)
+    ULONG   cTimers = lstCountItems(pllXTimers);
+    if (!cTimers)
     {
         // no XTimers running:
@@ -268,19 +269,20 @@
         // we have timers:
 
-        ULONG ulOldPMTimeout = pSet->ulPMTimeout;
-
-        if (!pNode->pNext)
+        ULONG       ulOldPMTimeout = pSet->ulPMTimeout;
+
+        PLISTNODE   pNode = lstQueryFirstNode(pllXTimers);
+        PXTIMER     pTimer1 = (PXTIMER)pNode->pItemData;
+
+        if (cTimers == 1)
         {
             // only one timer:
             // that's easy
-            PXTIMER pTimer = (PXTIMER)pNode->pItemData;
-            pSet->ulPMTimeout = pTimer->ulTimeout;
-        }
-        else if (!pNode->pNext->pNext)
+            pSet->ulPMTimeout = pTimer1->ulTimeout;
+        }
+        else if (cTimers == 2)
         {
             // exactly two timers:
             // find the greatest common denominator
-            PXTIMER pTimer1 = (PXTIMER)pNode->pItemData,
-                    pTimer2 = (PXTIMER)pNode->pNext->pItemData;
+            PXTIMER pTimer2 = (PXTIMER)pNode->pNext->pItemData;
 
             pSet->ulPMTimeout = mathGCD(pTimer1->ulTimeout,
@@ -289,13 +291,11 @@
         else
         {
-            // several timers:
+            // more than two timers:
             // run through all timers and find the greatest
             // common denominator of all frequencies...
-
-            ULONG   cTimers = lstCountItems(pllXTimers);
             int     *paInts = (int*)_alloca(sizeof(int) * cTimers),
                     i = 0;
 
-            _Pmpf(("Recalculating, got %d timers %d", cTimers));
+            // _Pmpf(("Recalculating, got %d timers", cTimers));
 
             // fill an array of integers with the
@@ -303,9 +303,9 @@
             while (pNode)
             {
-                PXTIMER pTimer = (PXTIMER)pNode->pItemData;
-
-                _Pmpf(("  timeout %d is %d", i, pTimer->ulTimeout));
-
-                paInts[i++] = pTimer->ulTimeout;
+                pTimer1 = (PXTIMER)pNode->pItemData;
+
+                // _Pmpf(("  timeout %d is %d", i, pTimer1->ulTimeout));
+
+                paInts[i++] = pTimer1->ulTimeout;
 
                 pNode = pNode->pNext;
@@ -314,8 +314,8 @@
             pSet->ulPMTimeout = mathGCDMulti(paInts,
                                              cTimers);
-            _Pmpf(("--> GCD is %d", pSet->ulPMTimeout));
-        }
-
-        if (    (pSet->idPMTimerRunning == 0)       // timer not running?
+            // _Pmpf(("--> GCD is %d", pSet->ulPMTimeout));
+        }
+
+        if (    (!pSet->idPMTimerRunning)       // timer not running?
              || (pSet->ulPMTimeout != ulOldPMTimeout) // timeout changed?
            )
@@ -355,7 +355,5 @@
                         USHORT usPMTimerID)
 {
-    PXTIMERSET pSet = NULL;
-
-    pSet = (PXTIMERSET)malloc(sizeof(*pSet));
+    PXTIMERSET pSet = NEW(XTIMERSET);
     if (pSet)
     {
@@ -434,5 +432,6 @@
  *@@added V0.9.9 (2001-02-28) [umoeller]
  *@@changed V0.9.12 (2001-05-12) [umoeller]: added mutex protection
- *@@changed V0.9.12 (2001-05-24) [umoeller]: fixed crash if timer was deleted during winproc's WM_TIMER processing
+ *@@changed V0.9.12 (2001-05-24) [umoeller]: fixed crash if this got called during tmrTimerTick
+ *@@changed V0.9.14 (2001-08-01) [umoeller]: fixed mem overwrite which might have caused crashes if this got called during tmrTimerTick
  */
 
@@ -498,4 +497,8 @@
                                 PFNWP pfnwp = (PFNWP)WinQueryWindowPtr(pTimer->hwndTarget,
                                                                        QWP_PFNWP);
+
+                                // moved this up V0.9.14 (2001-08-01) [umoeller]
+                                pTimer->ulNextFire = ulTimeNow + pTimer->ulTimeout;
+
                                 // call the window proc DIRECTLY
                                 pfnwp(pTimer->hwndTarget,
@@ -511,5 +514,10 @@
                                     //    the list, so we'll see it in this loop
 
-                                pTimer->ulNextFire = ulTimeNow + pTimer->ulTimeout;
+                                // V0.9.14 (2001-08-01) [umoeller]
+
+                                // DO NOT REFERENCE pTimer AFTER THIS CODE;
+                                // tmrTimerTick might have removed the timer,
+                                // and since the list is auto-free, pTimer
+                                // might have been freed!!
                             }
                             else
@@ -598,5 +606,5 @@
 
                 // fix the timeout... we allow only multiples of
-                // 20, and it must be at least 20 (otherwise our
+                // 25, and it must be at least 25 (otherwise our
                 // internal master timer calculations will fail)
                 // V0.9.14 (2001-07-07) [umoeller]
@@ -607,8 +615,7 @@
 
                 // check if this timer exists already
-                pTimer = FindTimer(pSet,
-                                   hwnd,
-                                   usTimerID);
-                if (pTimer)
+                if (pTimer = FindTimer(pSet,
+                                       hwnd,
+                                       usTimerID))
                 {
                     // exists already: reset only
@@ -617,11 +624,10 @@
                                     &ulTimeNow, sizeof(ulTimeNow));
                     pTimer->ulNextFire = ulTimeNow + ulTimeout;
-                    usrc = pTimer->usTimerID;
+                    usrc = usTimerID;
                 }
                 else
                 {
                     // new timer needed:
-                    pTimer = (PXTIMER)malloc(sizeof(XTIMER));
-                    if (pTimer)
+                    if (pTimer = NEW(XTIMER))
                     {
                         ULONG ulTimeNow;
@@ -635,5 +641,5 @@
                         lstAppendItem(pllXTimers,
                                       pTimer);
-                        usrc = pTimer->usTimerID;
+                        usrc = usTimerID;
                     }
                 }
@@ -673,6 +679,5 @@
         if (pSet && pSet->pvllXTimers)
         {
-            PLINKLIST pllXTimers = (PLINKLIST)pSet->pvllXTimers;
-            BOOL fLocked = FALSE;
+            // PLINKLIST pllXTimers = (PLINKLIST)pSet->pvllXTimers;
 
             PXTIMER pTimer = FindTimer(pSet,
Index: trunk/src/helpers/winh.c
===================================================================
--- trunk/src/helpers/winh.c	(revision 90)
+++ trunk/src/helpers/winh.c	(revision 91)
@@ -601,5 +601,5 @@
                              i++)
                         {
-                            CHAR szItemText[100];
+                            // CHAR szItemText[100];
                             SHORT id = SHORT1FROMMR(WinSendMsg(mi.hwndSubMenu,
                                                          MM_ITEMIDFROMPOSITION,
@@ -689,5 +689,5 @@
         MENUITEM mi = {0};
         SHORT src = 0;
-        SHORT s = 0;
+        // SHORT s = 0;
         mi.iPosition = MIT_END;
         mi.afStyle = MIS_TEXT | MIS_SUBMENU;
@@ -744,4 +744,9 @@
  *      to free the return value.
  *
+ *      This uses MM_QUERYITEMTEXT internally.
+ *      PMREF doesn't say anything about this,
+ *      but from my testing this always recurses
+ *      into submenus.
+ *
  *      Use the WinSetMenuItemText macro to
  *      set the menu item text.
@@ -753,7 +758,8 @@
     PSZ     prc = NULL;
 
-    SHORT sLength = SHORT1FROMMR(WinSendMsg(hwndMenu, MM_QUERYITEMTEXTLENGTH,
-                                           (MPARAM)(ULONG)usItemID,
-                                           (MPARAM)NULL));
+    SHORT sLength = SHORT1FROMMR(WinSendMsg(hwndMenu,
+                                            MM_QUERYITEMTEXTLENGTH,
+                                            (MPARAM)(ULONG)usItemID,
+                                            (MPARAM)NULL));
     if (sLength)
     {
@@ -4063,5 +4069,5 @@
 {
     SWBLOCK  swblock;
-    HWND     hwndTasklist = winhQueryTasklistWindow();
+    // HWND     hwndTasklist = winhQueryTasklistWindow();
     // the tasklist has entry #0 in the SWBLOCK
     WinQuerySwitchList(NULLHANDLE, &swblock, sizeof(SWBLOCK));
Index: trunk/src/helpers/xml.c
===================================================================
--- trunk/src/helpers/xml.c	(revision 90)
+++ trunk/src/helpers/xml.c	(revision 91)
@@ -455,5 +455,5 @@
             case ATTRIBUTE_DECLARATION:
             {
-                PCMATTRIBUTEDECL pDecl = (PCMATTRIBUTEDECL)pNode;
+                // PCMATTRIBUTEDECL pDecl = (PCMATTRIBUTEDECL)pNode;
             break; }
 
@@ -1524,5 +1524,5 @@
     if (!pDom->arcDOM)
     {
-        ULONG       i;
+        // ULONG       i;
 
         if (len)
@@ -1533,6 +1533,6 @@
             if (!pDom->arcDOM)
             {
-                PDOMNODE    pParent = pSI->pDomNode,
-                            pNew = NULL;
+                PDOMNODE    pParent = pSI->pDomNode;
+                            // pNew = NULL;
 
                 // shall we validate?
@@ -2588,5 +2588,5 @@
                                   const char *pcszName)
 {
-    APIRET arc = NO_ERROR;
+    // APIRET arc = NO_ERROR;
 
     PLINKLIST pll = lstCreate(FALSE);       // no free
Index: trunk/src/helpers/xprf.c
===================================================================
--- trunk/src/helpers/xprf.c	(revision 90)
+++ trunk/src/helpers/xprf.c	(revision 91)
@@ -434,5 +434,5 @@
                                                 pKey->lenKeyData);
 
-                                if (!pKey)
+                                if (!pIniKey)
                                 {
                                     brc = FALSE;
Index: trunk/src/helpers/xstring.c
===================================================================
--- trunk/src/helpers/xstring.c	(revision 90)
+++ trunk/src/helpers/xstring.c	(revision 91)
@@ -112,4 +112,5 @@
 
 #include "helpers\stringh.h"
+#define DONT_REPLACE_XSTR_MALLOC
 #include "helpers\xstring.h"            // extended string helpers
 
@@ -118,4 +119,40 @@
  *      See xstring.c.
  */
+
+#ifdef __DEBUG_MALLOC_ENABLED__
+
+/*
+ *@@ xstrInitDebug:
+ *
+ *@@added V0.9.14 (2001-08-01) [umoeller]
+ */
+
+void XWPENTRY xstrInitDebug(PXSTRING pxstr,
+                            ULONG ulPreAllocate,
+                            const char *file,
+                            unsigned long line,
+                            const char *function)
+{
+    memset(pxstr, 0, sizeof(XSTRING));
+    if (ulPreAllocate)
+    {
+        pxstr->psz = (PSZ)memdMalloc(ulPreAllocate,
+                                     file,
+                                     line,
+                                     function);
+        pxstr->cbAllocated = ulPreAllocate;
+                // ulLength is still zero
+        *(pxstr->psz) = 0;
+
+        pxstr->ulDelta = ulPreAllocate * 10 / 100;
+    }
+
+    // else: pxstr->ulDelta is still 0
+    pxstr->file = file;
+    pxstr->line = line;
+    pxstr->function = function;
+}
+
+#endif // __DEBUG_MALLOC_ENABLED__
 
 /*
@@ -319,5 +356,14 @@
         // this gives the C runtime a chance to expand the
         // existing block
-        if (pxstr->psz = (PSZ)realloc(pxstr->psz, cbAllocate))
+#ifdef __DEBUG_MALLOC_ENABLED__
+        if (pxstr->psz = (PSZ)memdRealloc(pxstr->psz,
+                                          cbAllocate,
+                                          pxstr->file,
+                                          pxstr->line,
+                                          pxstr->function))
+#else
+        if (pxstr->psz = (PSZ)realloc(pxstr->psz,
+                                      cbAllocate))
+#endif
                     // if pxstr->psz is NULL, realloc behaves like malloc
             pxstr->cbAllocated = cbAllocate;
