Index: trunk/src/helpers/gpih.c
===================================================================
--- trunk/src/helpers/gpih.c	(revision 69)
+++ trunk/src/helpers/gpih.c	(revision 70)
@@ -1479,7 +1479,7 @@
         bih2.usReserved = 0;
         bih2.usRecording = BRA_BOTTOMUP;        // scan lines are bottom to top (default)
-        bih2.usRendering = BRH_NOTHALFTONED;    // other algorithms aren't documented anyways
-        bih2.cSize1 = 0;            // parameter for halftoning (undocumented anyways)
-        bih2.cSize2 = 0;            // parameter for halftoning (undocumented anyways)
+        bih2.usRendering = BRH_NOTHALFTONED;    // other algorithms aren't documented anyway
+        bih2.cSize1 = 0;            // parameter for halftoning (undocumented anyway)
+        bih2.cSize2 = 0;            // parameter for halftoning (undocumented anyway)
         bih2.ulColorEncoding = BCE_RGB;     // only possible value
         bih2.ulIdentifier = 0;              // application-specific data
@@ -1545,4 +1545,6 @@
  *      which can then be used for WinDrawBitmap and such, or
  *      NULLHANDLE upon errors.
+ *
+ *@@changed V0.9.12 (2001-05-20) [umoeller]: fixed excessive mem PS size
  */
 
@@ -1564,10 +1566,14 @@
     POINTL aptl[3];
 
-    SIZEL szlPage = {0, 0};
-    if (gpihCreateMemPS(hab, &szlPage, &hdcMem, &hpsMem))
+    SIZEL szlPage = {prcl->xRight - prcl->xLeft,
+                     prcl->yTop - prcl->yBottom};       // fixed V0.9.12 (2001-05-20) [umoeller]
+    if (gpihCreateMemPS(hab,
+                        &szlPage,
+                        &hdcMem,
+                        &hpsMem))
     {
         if ((hbm = gpihCreateBitmap(hpsMem,
-                                    prcl->xRight - prcl->xLeft,
-                                    prcl->yTop - prcl->yBottom)))
+                                    szlPage.cx,
+                                    szlPage.cy)))
         {
             // Associate the bit map and the memory presentation space.
@@ -1595,5 +1601,7 @@
                     hbm = NULLHANDLE; // for return code
                 }
-            } else {
+            }
+            else
+            {
                 // error selecting bitmap for hpsMem:
                 GpiDeleteBitmap(hbm);
@@ -2019,2 +2027,132 @@
 }
 
+/*
+ *@@category: Helpers\PM helpers\GPI helpers\XBitmaps
+ *      Extended bitmaps. See gpihCreateXBitmap for an introduction.
+ */
+
+/* ******************************************************************
+ *
+ *   XBitmap functions
+ *
+ ********************************************************************/
+
+/*
+ *@@ gpihCreateXBitmap:
+ *      creates an XBitmap, which is returned in an
+ *      _XBITMAP structure.
+ *
+ *      The problem with all the GPI bitmap functions
+ *      is that they are quite complex and it is easy
+ *      to forget one of the "disassociate" and "deselect"
+ *      functions, which then simply leads to enormous
+ *      resource leaks in the application.
+ *
+ *      This function may relieve this a bit. This
+ *      creates a memory DC, an memory PS, and a bitmap,
+ *      and selects the bitmap into the memory PS.
+ *      You can then use any GPI function on the memory
+ *      PS to draw into the bitmap. Use the fields from
+ *      _XBITMAP for that.
+ *
+ *      The bitmap is created in RGB mode.
+ *
+ *      Use gpihDestroyXBitmap to destroy the XBitmap
+ *      again.
+ *
+ *      Example:
+ *
+ +          PXBITMAP pbmp = gpihCreateXBitmap(hab, 100, 100);
+ +          if (pbmp)
+ +          {
+ +              GpiMove(pbmp->hpsMem, ...);
+ +              GpiBox(pbmp->hpsMem, ...);
+ +
+ +              WinDrawBitmap(hpsScreen,
+ +                            pbmp->hbm,       // bitmap handle
+ +                            ...);
+ +              gpihDestroyXBitmap(&pbmp);
+ +          }
+ *
+ *      Without the gpih* functions, the above would expand
+ *      to more than 100 lines.
+ *
+ *@@added V0.9.12 (2001-05-20) [umoeller]
+ */
+
+PXBITMAP gpihCreateXBitmap(HAB hab,         // in: anchor block
+                           LONG cx,         // in: bitmap width
+                           LONG cy)         // in: bitmap height
+{
+    BOOL fOK = FALSE;
+    PXBITMAP pbmp = (PXBITMAP)malloc(sizeof(XBITMAP));
+    if (pbmp)
+    {
+        memset(pbmp, 0, sizeof(XBITMAP));
+
+        // create memory PS for bitmap
+        pbmp->szl.cx = cx;
+        pbmp->szl.cy = cy;
+        if (gpihCreateMemPS(hab,
+                            &pbmp->szl,
+                            &pbmp->hdcMem,
+                            &pbmp->hpsMem))
+        {
+            gpihSwitchToRGB(pbmp->hpsMem);
+            if (pbmp->hbm = gpihCreateBitmap(pbmp->hpsMem,
+                                             cx,
+                                             cy))
+            {
+                if (GpiSetBitmap(pbmp->hpsMem,
+                                 pbmp->hbm)
+                        != HBM_ERROR)
+                    fOK = TRUE;
+            }
+        }
+
+        if (!fOK)
+            gpihDestroyXBitmap(&pbmp);
+    }
+
+    return (pbmp);
+}
+
+/*
+ *@@ gpihDestroyXBitmap:
+ *      destroys an XBitmap created with gpihCreateXBitmap.
+ *
+ *      To be on the safe side, this sets the
+ *      bitmap pointer to NULL as well.
+ *
+ *@@added V0.9.12 (2001-05-20) [umoeller]
+ */
+
+VOID gpihDestroyXBitmap(PXBITMAP *ppbmp)
+{
+    if (ppbmp)
+    {
+        PXBITMAP pbmp;
+        if (pbmp = *ppbmp)
+        {
+            if (pbmp->hbm)
+            {
+                if (pbmp->hpsMem)
+                    GpiSetBitmap(pbmp->hpsMem, NULLHANDLE);
+                GpiDeleteBitmap(pbmp->hbm);
+            }
+            if (pbmp->hpsMem)
+            {
+                GpiAssociate(pbmp->hpsMem, NULLHANDLE);
+                GpiDestroyPS(pbmp->hpsMem);
+            }
+            if (pbmp->hdcMem)
+                DevCloseDC(pbmp->hdcMem);
+
+            free(pbmp);
+
+            *ppbmp = NULL;
+        }
+    }
+}
+
+
Index: trunk/src/helpers/threads.c
===================================================================
--- trunk/src/helpers/threads.c	(revision 69)
+++ trunk/src/helpers/threads.c	(revision 70)
@@ -130,8 +130,4 @@
     if (pti)
     {
-        if (pti->pfRunning)
-            // set "running" flag
-            *(pti->pfRunning) = TRUE;
-
         if (pti->flFlags & THRF_WAIT)
             // "Wait" flag set: thrCreate is then
@@ -174,12 +170,12 @@
         }
 
-        // for non-transient threads: set exit flags
+        // set exit flags
         // V0.9.7 (2000-12-20) [umoeller]
         pti->fExitComplete = TRUE;
         pti->tid = NULLHANDLE;
 
-        if (pti->pfRunning)
+        if (pti->ptidRunning)
             // clear "running" flag
-            *(pti->pfRunning) = FALSE;
+            *(pti->ptidRunning) = 0;
 
         // (2000-12-18) [lafaix] clean up pti if thread is transient.
@@ -213,20 +209,9 @@
  *      The thread's ptiMyself is then a pointer to the
  *      THREADINFO structure passed to this function.
- *      ulData may be obtained like this:
+ *      In your thread function, ulData may be obtained like this:
  *
  +          ULONG ulData = ptiMyself->ulData;
  *
- *      The THREADINFO structure passed to this function must
- *      be accessible all the time while the thread is running
- *      because the thr* functions will use it for maintenance.
- *
- *      This function does NOT check whether a thread is
- *      already running in *pti. Do not use the same THREADINFO
- *      for several threads.
- *
- *      If you do not want to manage the structure yourself,
- *      you can pass the THRF_TRANSIENT flag (see below).
- *
- *      thrCreate does not call your thread func directly,
+ *      thrCreate does not start your thread func directly,
  *      but only through the thr_fntGeneric wrapper to
  *      provide additional functionality. As a consequence,
@@ -235,4 +220,24 @@
  *      (cleanup) in thr_fntGeneric. Instead, just fall out of
  *      your thread function, or return().
+ *
+ *      The THREADINFO structure passed to this function must
+ *      be accessible all the time while the thread is running
+ *      because the thr* functions will use it for maintenance.
+ *      This function does NOT check whether a thread is
+ *      already running in *pti. Do not use the same THREADINFO
+ *      for several threads.
+ *
+ *      If you do not want to manage the structure yourself,
+ *      you can pass the THRF_TRANSIENT flag (see below).
+ *
+ *      ptidRunning is an optional parameter and can be NULL.
+ *      If non-null, it must point to a ULONG which will contain
+ *      the thread's TID while the thread is still running.
+ *      Once the thread exits, the ULONG will automatically
+ *      be set to zero; this is useful for a quick check whether
+ *      the thread is currently busy.
+ *
+ *      Note: ptidRunning is only reliable if you set the
+ *      THRF_WAIT or THRF_WAIT_EXPLICIT flags.
  *
  *      flFlags can be any combination of the following:
@@ -252,5 +257,5 @@
  *
  *      -- THRF_WAIT_EXPLICIT: like THRF_WAIT, but in this case,
- *         your thread function must post THREADINFO.hevRunning
+ *         your thread function _must_ post THREADINFO.hevRunning
  *         yourself (thr_fntGeneric will not automatically
  *         post it). Useful for waiting until your own thread
@@ -282,9 +287,10 @@
  *@@changed V0.9.9 (2001-03-07) [umoeller]: added pcszThreadName
  *@@changed V0.9.9 (2001-03-14) [umoeller]: added THRF_WAIT_EXPLICIT
+ *@@changed V0.9.12 (2001-05-20) [umoeller]: changed pfRunning to ptidRunning
  */
 
 ULONG thrCreate(PTHREADINFO pti,     // out: THREADINFO data
                 PTHREADFUNC pfn,     // in: _Optlink thread function
-                PBOOL pfRunning,     // out: variable set to TRUE while thread is running;
+                PULONG ptidRunning,  // out: variable set to TID while thread is running;
                                      // ptr can be NULL
                 const char *pcszThreadName, // in: thread name (for identification)
@@ -307,5 +313,5 @@
         pti->cbStruct = sizeof(THREADINFO);
         pti->pThreadFunc = (PVOID)pfn;
-        pti->pfRunning = pfRunning;
+        pti->ptidRunning = ptidRunning;
         pti->pcszThreadName = pcszThreadName; // V0.9.9 (2001-03-07) [umoeller]
         pti->flFlags = flFlags;
@@ -336,4 +342,8 @@
                                     pti);   // parameter passed to thread
             ulrc = pti->tid;
+
+            if (pti->ptidRunning)
+                // set "running" flag // V0.9.12 (2001-05-20) [umoeller]
+                *(pti->ptidRunning) = pti->tid;
 
             if (ulrc)
