Index: trunk/src/helpers/apmh.c
===================================================================
--- trunk/src/helpers/apmh.c	(revision 103)
+++ trunk/src/helpers/apmh.c	(revision 105)
@@ -158,9 +158,14 @@
  *      After this, the status fields in APM
  *      are valid (if NO_ERROR is returned).
- */
-
-APIRET apmhReadStatus(PAPM pApm)        // in: APM structure created by apmhOpen
-{
-    APIRET arc = NO_ERROR;
+ *      If the values changed since the previous
+ *      call, *pfChanged is set to TRUE; FALSE
+ *      otherwise.
+ */
+
+APIRET apmhReadStatus(PAPM pApm,        // in: APM structure created by apmhOpen
+                      PBOOL pfChanged)  // out: values changed (ptr can be NULL)
+{
+    APIRET  arc = NO_ERROR;
+    BOOL    fChanged = FALSE;
 
     if ((pApm) && (pApm->hfAPMSys))
@@ -174,7 +179,19 @@
                               PowerStatus.ParmLength)))
         {
-            pApm->ulBatteryStatus = PowerStatus.BatteryStatus;
-            pApm->ulBatteryLife = PowerStatus.BatteryLife;
+            if (    (pApm->fAlreadyRead)
+                 || (pApm->ulBatteryStatus != PowerStatus.BatteryStatus)
+                 || (pApm->ulBatteryLife != PowerStatus.BatteryLife)
+               )
+            {
+                pApm->ulBatteryStatus = PowerStatus.BatteryStatus;
+                pApm->ulBatteryLife = PowerStatus.BatteryLife;
+
+                pApm->fAlreadyRead = FALSE;
+                fChanged = TRUE;
+            }
         }
+
+        if (pfChanged)
+            *pfChanged = fChanged;
     }
     else
Index: trunk/src/helpers/apps.c
===================================================================
--- trunk/src/helpers/apps.c	(revision 103)
+++ trunk/src/helpers/apps.c	(revision 105)
@@ -744,4 +744,10 @@
  *          this uses the default Win-OS/2 environment.
  *          See appQueryDefaultWin31Environment.
+ *
+ *      --  WARNING: Since this uses WinStartApp internally,
+ *          and WinStartApp completely hangs PM if a Win-OS/2
+ *          full-screen session is started from a thread that
+ *          is NOT thread1, THIS SHOULD ONLY BE CALLED ON
+ *          THREAD 1 of your application.
  *
  *      Even though this isn't clearly said in PMREF,
Index: trunk/src/helpers/dialog.c
===================================================================
--- trunk/src/helpers/dialog.c	(revision 103)
+++ trunk/src/helpers/dialog.c	(revision 105)
@@ -48,6 +48,7 @@
 #define INCL_WINDIALOGS
 #define INCL_WININPUT
+#define INCL_WINSTATICS
 #define INCL_WINBUTTONS
-#define INCL_WINSTATICS
+#define INCL_WINENTRYFIELDS
 #define INCL_WINSYS
 
@@ -70,4 +71,5 @@
 #include "helpers\stringh.h"
 #include "helpers\winh.h"
+#include "helpers\xstring.h"
 
 /*
@@ -2131,4 +2133,164 @@
 
 /*
+ *@@ cmnTextEntryBox:
+ *      common dialog for entering a text string.
+ *      The dialog has a descriptive text on top
+ *      with an entry field below and "OK" and "Cancel"
+ *      buttons.
+ *
+ *      The string from the user is returned in a
+ *      new buffer, which must be free'd by the caller.
+ *      Returns NULL if the user pressed "Cancel".
+ *
+ *      fl can be any combination of the following
+ *      flags:
+ *
+ *      --  TEBF_REMOVETILDE: tilde ("~") characters
+ *          are removed from pcszTitle before setting
+ *          the title. Useful for reusing menu item
+ *          texts.
+ *
+ *      --  TEBF_REMOVEELLIPSE: ellipse ("...") strings
+ *          are removed from pcszTitle before setting
+ *          the title. Useful for reusing menu item
+ *          texts.
+ *
+ *      --  TEBF_SELECTALL: the default text in the
+ *          entry field is initially highlighted.
+ *
+ *@@added V0.9.15 (2001-09-14) [umoeller]
+ */
+
+PSZ dlghTextEntryBox(HWND hwndOwner,
+                     const char *pcszTitle,          // in: dlg title
+                     const char *pcszDescription,    // in: descriptive text above entry field
+                     const char *pcszDefault,        // in: default text for entry field or NULL
+                     const char *pcszOK,             // in: "OK" string
+                     const char *pcszCancel,         // in: "Cancel" string
+                     ULONG ulMaxLen,                 // in: maximum length for entry
+                     ULONG fl,                       // in: TEBF_* flags
+                     const char *pcszFont)           // in: font (e.g. "9.WarpSans")
+{
+    CONTROLDEF
+                Static = {
+                            WC_STATIC,
+                            NULL,
+                            WS_VISIBLE | SS_TEXT | DT_LEFT | DT_WORDBREAK,
+                            -1,
+                            CTL_COMMON_FONT,
+                            0,
+                            { 300, SZL_AUTOSIZE },     // size
+                            5               // spacing
+                         },
+                Entry = {
+                            WC_ENTRYFIELD,
+                            NULL,
+                            WS_VISIBLE | WS_TABSTOP | ES_LEFT | ES_MARGIN | ES_AUTOSCROLL,
+                            999,
+                            CTL_COMMON_FONT,
+                            0,
+                            { 300, 20 },     // size
+                            5               // spacing
+                         },
+                OKButton = {
+                            WC_BUTTON,
+                            NULL,
+                            WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON | BS_DEFAULT,
+                            DID_OK,
+                            CTL_COMMON_FONT,
+                            0,
+                            { 100, 30 },    // size
+                            5               // spacing
+                         },
+                CancelButton = {
+                            WC_BUTTON,
+                            NULL,
+                            WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON,
+                            DID_CANCEL,
+                            CTL_COMMON_FONT,
+                            0,
+                            { 100, 30 },    // size
+                            5               // spacing
+                         };
+    DLGHITEM DlgTemplate[] =
+        {
+            START_TABLE,
+                START_ROW(0),
+                    CONTROL_DEF(&Static),
+                START_ROW(0),
+                    CONTROL_DEF(&Entry),
+                START_ROW(0),
+                    CONTROL_DEF(&OKButton),
+                    CONTROL_DEF(&CancelButton),
+            END_TABLE
+        };
+
+    HWND hwndDlg = NULLHANDLE;
+    PSZ  pszReturn = NULL;
+    XSTRING strTitle;
+
+    xstrInitCopy(&strTitle, pcszTitle, 0);
+
+    if (fl & (TEBF_REMOVEELLIPSE | TEBF_REMOVETILDE))
+    {
+        ULONG ulOfs;
+        if (fl & TEBF_REMOVEELLIPSE)
+        {
+            ulOfs = 0;
+            while (xstrFindReplaceC(&strTitle,
+                                    &ulOfs,
+                                    "...",
+                                    ""))
+                ;
+        }
+
+        if (fl & TEBF_REMOVETILDE)
+        {
+            ulOfs = 0;
+            while (xstrFindReplaceC(&strTitle,
+                                    &ulOfs,
+                                    "~",
+                                    ""))
+                ;
+        }
+    }
+
+    Static.pcszText = pcszDescription;
+
+    OKButton.pcszText = pcszOK;
+    CancelButton.pcszText = pcszCancel;
+
+    if (NO_ERROR == dlghCreateDlg(&hwndDlg,
+                                  hwndOwner,
+                                  FCF_TITLEBAR | FCF_SYSMENU | FCF_DLGBORDER | FCF_NOBYTEALIGN,
+                                  WinDefDlgProc,
+                                  strTitle.psz,
+                                  DlgTemplate,      // DLGHITEM array
+                                  ARRAYITEMCOUNT(DlgTemplate),
+                                  NULL,
+                                  pcszFont))
+    {
+        HWND hwndEF = WinWindowFromID(hwndDlg, 999);
+        winhCenterWindow(hwndDlg);
+        winhSetEntryFieldLimit(hwndEF, ulMaxLen);
+        if (pcszDefault)
+        {
+            WinSetWindowText(hwndEF, (PSZ)pcszDefault);
+            if (fl & TEBF_SELECTALL)
+                winhEntryFieldSelectAll(hwndEF);
+        }
+        WinSetFocus(HWND_DESKTOP, hwndEF);
+        if (DID_OK == WinProcessDlg(hwndDlg))
+            pszReturn = winhQueryWindowText(hwndEF);
+
+        WinDestroyWindow(hwndDlg);
+    }
+
+    xstrClear(&strTitle);
+
+    return (pszReturn);
+}
+
+/*
  *@@ dlghSetPrevFocus:
  *      "backward" function for rotating the focus
@@ -2246,12 +2408,4 @@
     }
 }
-
-/*
- *@@ MatchMnemonic:
- *      returns TRUE if the specified control matches
- *
- *
- *@@added V0.9.9 (2001-03-17) [umoeller]
- */
 
 /*
Index: trunk/src/helpers/dosh.c
===================================================================
--- trunk/src/helpers/dosh.c	(revision 103)
+++ trunk/src/helpers/dosh.c	(revision 105)
@@ -814,6 +814,6 @@
                           &fFixed);    // V0.9.13 (2001-06-14) [umoeller]
 
-    _Pmpf((__FUNCTION__ ": doshIsFixedDisk returned %d for disk %d", arc, ulLogicalDrive));
-    _Pmpf(("   fFixed is %d", fFixed));
+    // _Pmpf((__FUNCTION__ ": doshIsFixedDisk returned %d for disk %d", arc, ulLogicalDrive));
+    // _Pmpf(("   fFixed is %d", fFixed));
 
     if (!arc)
@@ -825,5 +825,5 @@
             arc = doshQueryDiskParams(ulLogicalDrive,
                                       &bpb);
-            _Pmpf(("   doshQueryDiskParams returned %d", arc));
+            // _Pmpf(("   doshQueryDiskParams returned %d", arc));
 
             if (    (!arc)
@@ -831,5 +831,5 @@
                )
             {
-                _Pmpf(("   --> is CD-ROM"));
+                // _Pmpf(("   --> is CD-ROM"));
                 fCDROM = TRUE;
             }
Index: trunk/src/helpers/stringh.c
===================================================================
--- trunk/src/helpers/stringh.c	(revision 103)
+++ trunk/src/helpers/stringh.c	(revision 105)
@@ -1914,11 +1914,15 @@
 /*
  * match_comp_os2:
- *      Compare a single component (directory name or file name) of the
- *      paths, for OS/2 and DOS styles.  MASK and NAME point into a
- *      component of the wildcard and the name to be checked, respectively.
- *      Comparing stops at the next separator.  The FLAGS argument is the
- *      same as that of fnmatch().  HAS_DOT is true if a dot is in the
- *      current component of NAME.  The number of dots is not restricted,
- *      even in DOS style.  Return FNM_MATCH iff MASK and NAME match.
+ *      compares a single component (directory name or file name)
+ *      of the paths, for OS/2 and DOS styles. MASK and NAME point
+ *      into a component of the wildcard and the name to be checked,
+ *      respectively. Comparing stops at the next separator.
+ *      The FLAGS argument is the same as that of fnmatch().
+ *
+ *      HAS_DOT is true if a dot is in the current component of NAME.
+ *      The number of dots is not restricted, even in DOS style.
+ *
+ *      Returns FNM_MATCH iff MASK and NAME match.
+ *
  *      Note that this function is recursive.
  *
@@ -1944,5 +1948,5 @@
                 if (*name == 0)
                     return FNM_MATCH;
-                if ((flags & _FNM_PATHPREFIX) && IS_OS2_COMP_SEP(*name))
+                if ((flags & FNM_PATHPREFIX) && IS_OS2_COMP_SEP(*name))
                     return FNM_MATCH;
                 return FNM_NOMATCH;
@@ -1959,5 +1963,5 @@
                  * is ignored at the end of NAME. */
 
-                if ((flags & _FNM_PATHPREFIX) && mask[1] == 0 && *name == 0)
+                if ((flags & FNM_PATHPREFIX) && mask[1] == 0 && *name == 0)
                     return FNM_MATCH;
 
@@ -1994,5 +1998,5 @@
                     if (IS_OS2_COMP_END(*name))
                         return FNM_NOMATCH;
-                    if (*name == '.' && (flags & _FNM_STYLE_MASK) == _FNM_DOS)
+                    if (*name == '.' && (flags & FNM_STYLE_MASK) == FNM_DOS)
                         return FNM_NOMATCH;
                     ++name;
@@ -2015,5 +2019,5 @@
                 /* All other characters match themselves. */
 
-                if (flags & _FNM_IGNORECASE)
+                if (flags & FNM_IGNORECASE)
                 {
                     if (tolower(*mask) != tolower(*name))
@@ -2033,9 +2037,12 @@
 /*
  * match_comp:
- *      compare a single component (directory name or file name) of the
- *      paths, for all styles which need component-by-component matching.
- *      MASK and NAME point to the start of a component of the wildcard and
- *      the name to be checked, respectively.  Comparing stops at the next
- *      separator.  The FLAGS argument is the same as that of fnmatch().
+ *      compares a single component (directory name or file
+ *      name) of the paths, for all styles which need
+ *      component-by-component matching. MASK and NAME point
+ *      to the start of a component of the wildcard and the
+ *      name to be checked, respectively.  Comparing stops at
+ *      the next separator. The FLAGS argument is the same as
+ *      that of fnmatch().
+ *
  *      Return FNM_MATCH iff MASK and NAME match.
  *
@@ -2049,8 +2056,8 @@
     const unsigned char *s;
 
-    switch (flags & _FNM_STYLE_MASK)
-    {
-        case _FNM_OS2:
-        case _FNM_DOS:
+    switch (flags & FNM_STYLE_MASK)
+    {
+        case FNM_OS2:
+        case FNM_DOS:
 
             /* For OS/2 and DOS styles, we add an implicit dot at the end of
@@ -2080,7 +2087,9 @@
 /*
  * match_unix:
- *      match complete paths for Unix styles.  The FLAGS argument is the
- *      same as that of fnmatch().  COMP points to the start of the current
- *      component in NAME.  Return FNM_MATCH iff MASK and NAME match.  The
+ *      matches complete paths for Unix styles.
+ *
+ *      The FLAGS argument is the same as that of fnmatch().
+ *      COMP points to the start of the current component in
+ *      NAME.  Return FNM_MATCH iff MASK and NAME match.  The
  *      backslash character is used for escaping ? and * unless
  *      FNM_NOESCAPE is set.
@@ -2110,5 +2119,5 @@
                 if (*name == 0)
                     return FNM_MATCH;
-                if ((flags & _FNM_PATHPREFIX) && IS_UNIX_COMP_SEP(*name))
+                if ((flags & FNM_PATHPREFIX) && IS_UNIX_COMP_SEP(*name))
                     return FNM_MATCH;
                 return FNM_NOMATCH;
@@ -2164,5 +2173,5 @@
 
                 if (!(IS_UNIX_COMP_SEP(*name)
-                      || ((flags & _FNM_PATHPREFIX) && *name == 0
+                      || ((flags & FNM_PATHPREFIX) && *name == 0
                       && (mask[1] == 0
                           || (!(flags & FNM_NOESCAPE) && mask[1] == '\\'
@@ -2292,5 +2301,5 @@
                 /* All other characters match themselves. */
 
-                if (flags & _FNM_IGNORECASE)
+                if (flags & FNM_IGNORECASE)
                 {
                     if (tolower(*mask) != tolower(*name))
@@ -2327,6 +2336,7 @@
                              unsigned flags)
 {
-    int             m_drive, n_drive,
-                    rc;
+    int     m_drive,
+            n_drive,
+            rc;
 
     /* Match and skip the drive name if present. */
@@ -2339,5 +2349,5 @@
         if (m_drive == -1 || n_drive == -1)
             return FNM_NOMATCH;
-        if (!(flags & _FNM_IGNORECASE))
+        if (!(flags & FNM_IGNORECASE))
             return FNM_NOMATCH;
         if (tolower(m_drive) != tolower(n_drive))
@@ -2359,8 +2369,8 @@
      * "\*\server\path".  Ditto for /. */
 
-    switch (flags & _FNM_STYLE_MASK)
-    {
-        case _FNM_OS2:
-        case _FNM_DOS:
+    switch (flags & FNM_STYLE_MASK)
+    {
+        case FNM_OS2:
+        case FNM_DOS:
 
             if (IS_OS2_COMP_SEP(name[0]) && IS_OS2_COMP_SEP(name[1]))
@@ -2373,5 +2383,5 @@
             break;
 
-        case _FNM_POSIX:
+        case FNM_POSIX:
 
             if (name[0] == '/' && name[1] == '/')
@@ -2404,5 +2414,5 @@
          * is reached even if there are components left in NAME. */
 
-        if (*mask == 0 && (flags & _FNM_PATHPREFIX))
+        if (*mask == 0 && (flags & FNM_PATHPREFIX))
             return FNM_MATCH;
 
@@ -2436,10 +2446,29 @@
  */
 
-BOOL strhMatchOS2(const unsigned char* pcszMask,     // in: mask (e.g. "*.txt")
-                  const unsigned char* pcszName)     // in: string to check (e.g. "test.txt")
-{
-    return ((BOOL)(_fnmatch_unsigned(pcszMask,
-                                     pcszName,
-                                     _FNM_OS2 | _FNM_IGNORECASE)
+BOOL strhMatchOS2(const char *pcszMask,     // in: mask (e.g. "*.txt")
+                  const char *pcszName)     // in: string to check (e.g. "test.txt")
+{
+    return ((BOOL)(_fnmatch_unsigned((const unsigned char *)pcszMask,
+                                     (const unsigned char *)pcszName,
+                                     FNM_OS2 | FNM_IGNORECASE)
+                   == FNM_MATCH)
+           );
+}
+
+/*
+ *@@ strhMatchExt:
+ *      like strhMatchOS2, but this takes all the flags
+ *      for input.
+ *
+ *@@added V0.9.15 (2001-09-14) [umoeller]
+ */
+
+BOOL strhMatchExt(const char *pcszMask,     // in: mask (e.g. "*.txt")
+                  const char *pcszName,     // in: string to check (e.g. "test.txt")
+                  unsigned flags)           // in: FNM_* flags
+{
+    return ((BOOL)(_fnmatch_unsigned((const unsigned char *)pcszMask,
+                                     (const unsigned char *)pcszName,
+                                     flags)
                    == FNM_MATCH)
            );
