Index: trunk/src/helpers/apps.c
===================================================================
--- trunk/src/helpers/apps.c	(revision 195)
+++ trunk/src/helpers/apps.c	(revision 196)
@@ -15,5 +15,5 @@
 
 /*
- *      Copyright (C) 1997-2001 Ulrich Mller.
+ *      Copyright (C) 1997-2002 Ulrich Mller.
  *      This file is part of the "XWorkplace helpers" source package.
  *      This is free software; you can redistribute it and/or modify
Index: trunk/src/helpers/cctl_chart.c
===================================================================
--- trunk/src/helpers/cctl_chart.c	(revision 195)
+++ trunk/src/helpers/cctl_chart.c	(revision 196)
@@ -166,5 +166,5 @@
 
 /*
- *      Copyright (C) 1997-2000 Ulrich Mller.
+ *      Copyright (C) 1997-2002 Ulrich Mller.
  *      This file is part of the "XWorkplace helpers" source package.
  *      This is free software; you can redistribute it and/or modify
Index: trunk/src/helpers/cctl_checkcnr.c
===================================================================
--- trunk/src/helpers/cctl_checkcnr.c	(revision 195)
+++ trunk/src/helpers/cctl_checkcnr.c	(revision 196)
@@ -15,5 +15,5 @@
 
 /*
- *      Copyright (C) 1997-2000 Ulrich Mller.
+ *      Copyright (C) 1997-2002 Ulrich Mller.
  *      This file is part of the "XWorkplace helpers" source package.
  *      This is free software; you can redistribute it and/or modify
Index: trunk/src/helpers/cctl_tooltip.c
===================================================================
--- trunk/src/helpers/cctl_tooltip.c	(revision 195)
+++ trunk/src/helpers/cctl_tooltip.c	(revision 196)
@@ -15,5 +15,5 @@
 
 /*
- *      Copyright (C) 1997-2000 Ulrich Mller.
+ *      Copyright (C) 1997-2002 Ulrich Mller.
  *      This file is part of the "XWorkplace helpers" source package.
  *      This is free software; you can redistribute it and/or modify
Index: trunk/src/helpers/comctl.c
===================================================================
--- trunk/src/helpers/comctl.c	(revision 195)
+++ trunk/src/helpers/comctl.c	(revision 196)
@@ -52,5 +52,5 @@
 
 /*
- *      Copyright (C) 1997-2000 Ulrich Mller.
+ *      Copyright (C) 1997-2002 Ulrich Mller.
  *      This file is part of the "XWorkplace helpers" source package.
  *      This is free software; you can redistribute it and/or modify
Index: trunk/src/helpers/configsys.c
===================================================================
--- trunk/src/helpers/configsys.c	(revision 195)
+++ trunk/src/helpers/configsys.c	(revision 196)
@@ -22,5 +22,5 @@
 
 /*
- *      Copyright (C) 1997-2001 Ulrich Mller.
+ *      Copyright (C) 1997-2002 Ulrich Mller.
  *      This file is part of the "XWorkplace helpers" source package.
  *      This is free software; you can redistribute it and/or modify
Index: trunk/src/helpers/dialog.c
===================================================================
--- trunk/src/helpers/dialog.c	(revision 195)
+++ trunk/src/helpers/dialog.c	(revision 196)
@@ -29,5 +29,5 @@
 
 /*
- *      Copyright (C) 2001 Ulrich Mller.
+ *      Copyright (C) 2001-2002 Ulrich Mller.
  *      This file is part of the "XWorkplace helpers" source package.
  *      This is free software; you can redistribute it and/or modify
Index: trunk/src/helpers/eah.c
===================================================================
--- trunk/src/helpers/eah.c	(revision 195)
+++ trunk/src/helpers/eah.c	(revision 196)
@@ -66,5 +66,5 @@
  *
  *      Copyright (C) 1995 Massachusetts Institute of Technology.
- *      Copyright (C) 1997-2000 Ulrich Mller.
+ *      Copyright (C) 1997-2002 Ulrich Mller.
  *      This file is part of the "XWorkplace helpers" source package.
  *      This is free software; you can redistribute it and/or modify
Index: trunk/src/helpers/gpih.c
===================================================================
--- trunk/src/helpers/gpih.c	(revision 195)
+++ trunk/src/helpers/gpih.c	(revision 196)
@@ -2648,4 +2648,9 @@
            )
         {
+            LONG    lPatternOld = -1;               // mark as "not changed" for now
+            LONG    lAndROP = ROP_SRCAND,           // 0x0088 = 10001000
+                    lPaintROP = ROP_SRCPAINT,       // 0x00EE = 11101110
+                    lInvertROP = ROP_SRCINVERT;     // 0x0066 = 01100110
+
             // colors are constant too
             GpiSetColor(hps, RGBCOL_WHITE);
@@ -2653,5 +2658,11 @@
 
             if (fl & DP_HALFTONED) // V0.9.20 (2002-08-04) [umoeller]
+            {
+                lPatternOld = GpiQueryPattern(hps);
                 GpiSetPattern(hps, PATSYM_HALFTONE);
+
+                lAndROP     = 0x00A8;               //          10101000
+                lInvertROP  = 0x00A6;               //          10100110
+            }
 
             /*
@@ -2688,5 +2699,5 @@
                             4L,         // must always be 4
                             aptl,       // point array
-                            ROP_SRCAND,   // source AND target
+                            lAndROP, // ROP_SRCAND,   // source AND target
                             BBO_IGNORE);
             }
@@ -2722,5 +2733,5 @@
                             4L,         // must always be 4
                             aptl,       // point array
-                            ROP_SRCPAINT,
+                            lPaintROP, // ROP_SRCPAINT,
                             BBO_IGNORE);
             }
@@ -2761,7 +2772,11 @@
                             4L,         // must always be 4
                             aptl,       // point array
-                            ROP_SRCINVERT,   // source XOR target
+                            lInvertROP, // ROP_SRCINVERT,   // source XOR target
                             BBO_IGNORE);
             }
+
+            // reset old pattern, if changed
+            if (lPatternOld != -1)
+                GpiSetPattern(hps, lPatternOld);
 
             return TRUE;
Index: trunk/src/helpers/helpers_post.in
===================================================================
--- trunk/src/helpers/helpers_post.in	(revision 195)
+++ trunk/src/helpers/helpers_post.in	(revision 196)
@@ -20,14 +20,18 @@
 
 .c.{$(OUTPUTDIR)}.obj:
-        @echo $(MAKEDIR)\makefile: Compiling $(@B).c
+    @echo $(MAKEDIR)\makefile: Compiling $(@B).c
 !ifdef EMX
-        $(CC_HELPERS) -o $(OUTPUTDIR)\$(@B).obj $(@B).c
+    $(CC_HELPERS) -o $(OUTPUTDIR)\$(@B).obj $(@B).c
 !else
 !ifndef PRECH
-        $(CC_HELPERS) /Fo$(OUTPUTDIR)\$(@B).obj $(@B).c
+    $(CC_HELPERS) /Fo$(OUTPUTDIR)\$(@B).obj $(@B).c
 !else
-        $(CC_HELPERS) /fi"$(PRECH)\$(@B).pch" /si"$(PRECH)\$(@B).pch" /Fo$(OUTPUTDIR)\$(@B).obj $(@B).c
+    $(CC_HELPERS) /fi"$(PRECH)\$(@B).pch" /si"$(PRECH)\$(@B).pch" /Fo$(OUTPUTDIR)\$(@B).obj $(@B).c
 !endif
 !endif
+
+$(OUTPUTDIR)\interlock.obj: $(@B).asm
+    @echo $(MAKEDIR)\makefile: Assembling $(@B).asm
+    alp -Sv:ALP -Fdo:$(OUTPUTDIR) $(@B).asm
 
 # The .OBJ-from-sources dependencies are now automatically
Index: trunk/src/helpers/helpers_pre.in
===================================================================
--- trunk/src/helpers/helpers_pre.in	(revision 195)
+++ trunk/src/helpers/helpers_pre.in	(revision 196)
@@ -69,5 +69,6 @@
 $(OUTPUTDIR)\prfh2.obj \
 $(OUTPUTDIR)\resh.obj \
-$(OUTPUTDIR)\semaphores.obj \
+$(OUTPUTDIR)\sem.obj \
+$(OUTPUTDIR)\interlock.obj \
 $(OUTPUTDIR)\stringh.obj \
 $(OUTPUTDIR)\syssound.obj \
Index: trunk/src/helpers/interlock.asm
===================================================================
--- trunk/src/helpers/interlock.asm	(revision 196)
+++ trunk/src/helpers/interlock.asm	(revision 196)
@@ -0,0 +1,125 @@
+
+;/*
+; * Interlocked apis
+; *
+; * Copyright 1999 Sander van Leeuwen
+; * Copyright 1999 Patrick Haller
+; *
+; * Based on WINE code: win32\thread.c (990815)
+; *
+; * Copyright 1995 Martin von Loewis
+; * Copyright 1997 Onno Hovers
+; *
+; * Project Odin Software License can be found in LICENSE.TXT
+; *
+; */
+.586P
+               NAME    interlocked
+
+CODE32         SEGMENT DWORD PUBLIC USE32 'CODE'
+
+;* LONG DosInterlockedIncrement(PLONG);
+;*
+;* InterlockedIncrement adds 1 to a long variable and returns
+;*  -  a negative number if the result < 0
+;*  -  zero if the result == 0
+;*  -  a positive number if the result > 0
+;*
+;* The returned number need not be equal to the result!!!!
+
+public  DosInterlockedIncrement
+DosInterlockedIncrement proc near
+        ;we are allowed to trash edx
+        mov     edx, dword ptr [esp+4] ; LPLONG lpAddend
+        mov     eax, 1
+        lock    xadd dword ptr [edx], eax
+        inc     eax
+        ret     4
+DosInterlockedIncrement endp
+
+;* LONG DosInterlockedDecrement(PLONG);
+;*
+;* InterlockedIncrement adds 1 to a long variable and returns
+;*  -  a negative number if the result < 0
+;*  -  zero if the result == 0
+;*  -  a positive number if the result > 0
+;*
+;* The returned number need not be equal to the result!!!!
+
+public  DosInterlockedDecrement
+DosInterlockedDecrement proc near
+        ;we are allowed to trash edx
+        mov     edx, dword ptr [esp+4] ; LPLONG lpAddend
+        mov     eax, -1
+        lock    xadd dword ptr [edx], eax
+        dec     eax
+        ret     4
+DosInterlockedDecrement endp
+
+
+; * LONG DosInterlockedExchange(PLONG, LONG);
+; *
+; * Atomically exchanges a pair of values.
+; *
+; * RETURNS
+; * Prior value of value pointed to by Target
+
+public  DosInterlockedExchange
+DosInterlockedExchange proc near
+        push    edx
+        mov     eax, [esp+12]           ; LONG value
+        mov     edx,[esp+8]             ; LPLONG target
+        lock    xchg eax, dword ptr [edx]
+        pop     edx
+        ret     8
+DosInterlockedExchange endp
+
+
+;/************************************************************************
+; * LONG DosInterlockedCompareExchange(PLONG dest, LONG xchg, LONG compare)
+; *
+; * Atomically compares Destination and Comperand, and if found equal exchanges
+; * the value of Destination with Exchange
+; *
+; */
+
+public DosInterlockedCompareExchange
+DosInterlockedCompareExchange proc near
+        push    ebp
+        mov     ebp, esp
+        push    edx
+        push    ebx
+
+        mov     ebx, dword ptr [ebp+8]  ;PVOID *Destination, /* Address of 32-bit value to exchange */
+        mov     eax, [ebp+16]       ;PVOID Comperand      /* value to compare, 32 bits */
+        mov     edx, [ebp+12]       ;PVOID Exchange,      /* change value, 32 bits */
+        lock    cmpxchg dword ptr [ebx],edx
+
+        pop     ebx
+        pop     edx
+        pop     ebp
+        ret     12
+DosInterlockedCompareExchange endp
+
+; * LONG DosInterlockedExchangeAdd(PLONG dest, LONG incr);
+; *
+; * Atomically adds Increment to Addend and returns the previous value of
+; * Addend
+; *
+; * RETURNS
+; * Prior value of value pointed to by cwAddendTarget
+; */
+
+public DosInterlockedExchangeAdd
+DosInterlockedExchangeAdd proc near
+        push    edx
+        mov     eax, dword ptr [esp+12] ;LONG Increment /* Value to add */
+        mov     edx, dword ptr [esp+8]  ;PLONG Addend, /* Address of 32-bit value to exchange */
+        lock    xadd dword ptr [edx], eax
+        pop     edx
+        ret     8
+DosInterlockedExchangeAdd endp
+
+CODE32          ENDS
+
+                END
Index: trunk/src/helpers/sem.c
===================================================================
--- trunk/src/helpers/sem.c	(revision 196)
+++ trunk/src/helpers/sem.c	(revision 196)
@@ -0,0 +1,305 @@
+
+/*
+ *@@sourcefile sem.c:
+ *      implements fast mutex semaphores a la Win32
+ *      critical sections.
+ *
+ *      This is an OS/2 implementation of what Win32 calls as
+ *      "critical sections"
+ *      It is an implementation that is highly optimized for
+ *      the case where there is only one thread trying to
+ *      access the critical section, i.e. it is available most
+ *      of the time. Therefore we can use these critical
+ *      sections for all our serialization and not lose any
+ *      performance when concurrent access is unlikely.
+ *
+ *      In case there is multiple access, we use the OS/2 kernel
+ *      event semaphores.
+ *
+ *      Function prefix:
+ *
+ *      --  sem*: semaphore helpers.
+ *
+ *@@added V0.9.20 (2002-08-04) [umoeller]
+ *@@header "helpers\semaphores.h"
+ */
+
+/*
+ *      Copyright (C) 2002 Sander van Leeuwen.
+ *      Copyright (C) 2002 Ulrich Mller.
+ *      This file is part of the "XWorkplace helpers" source package.
+ *      This is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published
+ *      by the Free Software Foundation, in version 2 as it comes in the
+ *      "COPYING" file of the XWorkplace main distribution.
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ */
+
+#define OS2EMX_PLAIN_CHAR
+    // this is needed for "os2emx.h"; if this is defined,
+    // emx will define PSZ as _signed_ char, otherwise
+    // as unsigned char
+
+#define INCL_DOSPROCESS
+#define INCL_DOSSEMAPHORES
+#define INCL_DOSERRORS
+
+#define INCL_WINMESSAGEMGR
+#include <os2.h>
+
+#include <stdlib.h>
+
+#include "setup.h"                      // code generation and debugging options
+
+#include "helpers\sem.h"
+
+#pragma hdrstop
+
+/*
+ *@@category: Helpers\Control program helpers\Semaphores
+ *      see sem.c.
+ */
+
+// encode PID and TID into one 32bit value
+#define MAKE_THREADID(processid, threadid)  ((processid << 16) | threadid)
+
+/*
+ *@@ GetTID:
+ *
+ */
+
+ULONG GetTID(VOID)
+{
+    PTIB   ptib;
+    PPIB   ppib;
+    APIRET rc;
+
+    if (!(rc = DosGetInfoBlocks(&ptib, &ppib)))
+        return MAKE_THREADID(ppib->pib_ulpid,
+                             ptib->tib_ptib2->tib2_ultid);
+
+    return 0;
+}
+
+/*
+ *@@ GetPID:
+ *
+ */
+
+ULONG GetPID(VOID)
+{
+    PTIB   ptib;
+    PPIB   ppib;
+    APIRET rc;
+
+    if (!(rc = DosGetInfoBlocks(&ptib, &ppib)))
+        return ppib->pib_ulpid;
+
+    return 0;
+}
+
+/*
+ *@@ semCreate:
+ *      the equivalent to DosCreateMutexSem.
+ */
+
+APIRET semCreate(PFASTMTX pmtx,
+                 PCSZ pszSemName)
+{
+    APIRET rc;
+
+    if (!pmtx)
+        return ERROR_INVALID_PARAMETER;
+
+    // initialize lock count with special value -1, meaning noone posesses it
+    pmtx->LockCount      = -1;
+    pmtx->RecursionCount = 0;
+    pmtx->OwningThread   = 0;
+
+    if (rc = DosCreateEventSem((PSZ)pszSemName,
+                               &pmtx->hmtxLock,
+                               (pszSemName) ? DC_SEM_SHARED : 0,
+                               0))
+        pmtx->hmtxLock = 0;
+
+    pmtx->Reserved = GetPID();
+
+    return rc;
+}
+
+/*
+ *@@ semOpen:
+ *      the equivalent to DosOpenMutexSem.
+ */
+
+APIRET semOpen(PFASTMTX pmtx,
+               PCSZ pszSemName)
+{
+    HMTX   hmtxLock = 0;
+    APIRET rc;
+
+    if (!pszSemName)
+        return ERROR_INVALID_PARAMETER;
+
+    return DosOpenEventSem((PSZ)pszSemName, &hmtxLock);
+}
+
+/*
+ *@@ semClose:
+ *      the equivalent to DosCloseMutexSem.
+ */
+
+APIRET semClose(PFASTMTX pmtx)
+{
+    APIRET rc;
+
+    if (!pmtx)
+        return ERROR_INVALID_PARAMETER;
+
+    if (!pmtx->hmtxLock)
+        return ERROR_INVALID_HANDLE;
+
+    if (pmtx->RecursionCount)  /* Should not happen */
+        return ERROR_SEM_BUSY;
+
+    pmtx->LockCount      = -1;
+    pmtx->RecursionCount = 0;
+    pmtx->OwningThread   = 0;
+    rc = DosCloseEventSem(pmtx->hmtxLock);
+    pmtx->hmtxLock       = 0;
+    pmtx->Reserved       = (ULONG)-1;
+
+    return rc;
+}
+
+/*
+ *@@ semRequest:
+ *      the equivalent to DosRequestMutexSem.
+ */
+
+APIRET semRequest(PFASTMTX pmtx)
+{
+    ULONG   threadid = GetTID();
+
+    if (!pmtx)
+        return ERROR_INVALID_PARAMETER;
+
+    // create pmtx sect just in time...
+    if (!pmtx->hmtxLock)
+        semCreate(pmtx, NULL);
+
+    // do an atomic increase of the lockcounter and see if it is > 0
+    // (i.e. it is already posessed)
+    if (DosInterlockedIncrement(&pmtx->LockCount))
+    {
+        // semaphore was already requested:
+
+testenter:
+        // if the same thread is requesting it again, memorize it
+        if (pmtx->OwningThread == threadid)
+        {
+            pmtx->RecursionCount++;
+            return NO_ERROR;
+        }
+
+        // current owner is different thread thread:
+
+        // do an atomic operation where we compare the owning thread id with 0
+        // and if this is true, exchange it with the id of the current thread
+        if (DosInterlockedCompareExchange((PLONG)&pmtx->OwningThread, threadid, 0))
+        {
+            // the compare did not return equal, i.e. the pmtx sect is in use
+
+            ULONG   cPosts;
+            APIRET  rc;
+
+            /* Now wait for it */
+            if (rc = DosWaitEventSem(pmtx->hmtxLock, SEM_INDEFINITE_WAIT))
+                return rc;
+
+            DosResetEventSem(pmtx->hmtxLock, &cPosts);
+
+            // multiple waiters could be running now. Repeat the logic so that
+            // only one actually can get the critical section
+            goto testenter;
+        }
+    }
+
+    pmtx->OwningThread   = GetTID();
+    pmtx->RecursionCount = 1;
+
+    return NO_ERROR;
+}
+
+/*
+ *@@ semAssert:
+ *      returns TRUE if the current thread currently owns
+ *      the mutex.
+ *
+ */
+
+BOOL semAssert(PFASTMTX pmtx)
+{
+    return (    (pmtx)
+             && (pmtx->OwningThread)
+             && (pmtx->OwningThread == GetTID())
+           );
+}
+
+/*
+ *@@ semTry:
+ *
+ */
+
+BOOL semTry(PFASTMTX pmtx)
+{
+    if (DosInterlockedIncrement(&pmtx->LockCount))
+    {
+        if (pmtx->OwningThread == GetTID())
+        {
+            pmtx->RecursionCount++;
+            return TRUE;
+        }
+
+        DosInterlockedDecrement(&pmtx->LockCount);
+
+        return FALSE;
+    }
+
+    pmtx->OwningThread   = GetTID();
+    pmtx->RecursionCount = 1;
+
+    return TRUE;
+}
+
+/*
+ *@@ semRelease:
+ *      the equivalent of DosReleaseMutexSem.
+ */
+
+APIRET semRelease(PFASTMTX pmtx)
+{
+    if (!pmtx)
+        return ERROR_INVALID_PARAMETER;
+
+    if (pmtx->OwningThread != GetTID())
+        return ERROR_NOT_OWNER;
+
+    if (--pmtx->RecursionCount)
+    {
+        DosInterlockedDecrement(&pmtx->LockCount );
+        return NO_ERROR;
+    }
+
+    pmtx->OwningThread = 0;
+
+    if (DosInterlockedDecrement(&pmtx->LockCount) >= 0)
+        // someone is waiting
+        DosPostEventSem(pmtx->hmtxLock);
+
+    return NO_ERROR;
+}
+
Index: trunk/src/helpers/semaphores.c
===================================================================
--- trunk/src/helpers/semaphores.c	(revision 195)
+++ 	(revision )
@@ -1,797 +1,0 @@
-
-/*
- *@@sourcefile semaphores.c:
- *      implements read-write semaphores.
- *
- *      Read-write semaphores are similar to the regular
- *      OS/2 mutex semaphores in that they are used to
- *      serialize access to a resource. See CPREF for an
- *      introduction to mutex semaphores -- do not use
- *      the things in this file if you have never used
- *      regular mutexes.
- *
- *      Regular mutexes are inefficient though if most
- *      of the access to the protected resource is
- *      read-only. It is not dangerous if several threads
- *      read from the same resource at the same time,
- *      as long as none of the threads actually modifies
- *      the resource. Still, with regular mutexes, a
- *      reading thread will be blocked out while another
- *      thread is reading, which isn't really necessary.
- *
- *      So read-write mutexes differentiate between read
- *      and write access. After creating a read-write
- *      semaphore using semCreateRWMutex,
- *
- *      --  to request read access, call semRequestRead
- *          (and semReleaseRead when done); this will
- *          let the thread in as long as no other thread
- *          has write access;
- *
- *      --  to request write access, call semRequestWrite
- *          (and semReleaseWrite when done); this will
- *          let the thread in _only_ if no other thread
- *          currently has requested either read or write
- *          access.
- *
- *      In other words, only write access is exclusive as with
- *      regular mutexes.
- *
- *      This file is new with V0.9.12 (2001-05-24) [umoeller].
- *
- *      Usage: All PM programs.
- *
- *      Function prefix:
- *
- *      --  sem*: semaphore helpers.
- *
- *@@added V0.9.12 (2001-05-24) [umoeller]
- *@@header "helpers\semaphores.h"
- */
-
-#define OS2EMX_PLAIN_CHAR
-    // this is needed for "os2emx.h"; if this is defined,
-    // emx will define PSZ as _signed_ char, otherwise
-    // as unsigned char
-
-#define INCL_DOSERRORS
-#define INCL_DOSSEMAPHORES
-
-#define INCL_WINMESSAGEMGR
-#include <os2.h>
-
-#include <stdlib.h>
-
-#include "setup.h"                      // code generation and debugging options
-
-#include "helpers\dosh.h"
-#include "helpers\semaphores.h"
-#include "helpers\standards.h"
-#include "helpers\tree.h"
-
-#pragma hdrstop
-
-/*
- *@@category: Helpers\Control program helpers\Semaphores
- *      see semaphores.c.
- */
-
-/* ******************************************************************
- *
- *   Private declarations
- *
- ********************************************************************/
-
-/*
- *@@ RWMUTEX:
- *      read-write mutex, as created by
- *      mtxCreateRWMutex.
- *
- *      The HRW handle is really a PRWMUTEX.
- */
-
-typedef struct _RWMUTEX
-{
-    ULONG   cReaders;
-                // current no. of readers on all threads,
-                // including nested read requests (0 if none)
-    TREE    *ReaderThreadsTree;
-                // red-black tree (tree.c) containing a
-                // READERTREENODE for each thread which
-                // ever requested read access; items are
-                // only added, but never removed (for speed)
-    ULONG   cReaderThreads;
-                // tree item count
-                // (this is NOT the same as cReaders)
-
-    ULONG   cWriters;
-                // current no. of writers (0 if none);
-                // this will only be > 1 if the same
-                // thread did a nested write request,
-                // since only one thread can ever have
-                // write access at a time
-    ULONG   tidWriter;
-                // TID of current writer or 0 if none
-
-    HEV     hevWriterDone;
-                // posted after writers count goes to 0;
-                // semRequestRead blocks on this
-
-    HEV     hevReadersDone;
-                // posted after readers or writers count
-                // goes to 0; semRequestWrite blocks on this
-
-} RWMUTEX, *PRWMUTEX;
-
-/*
- *@@ READERTREENODE:
- *      tree item structure which describes
- *      a thread which requested read access.
- *
- *      These nodes are stored in RWMUTEX.ReadersTree
- *      and only ever allocated, but never removed
- *      from the tree for speed.
- *
- *      Since TREE.id holds the thread ID, this
- *      tree is sorted by thread IDs.
- */
-
-typedef struct _READERTREENODE
-{
-    TREE    Tree;               // tree base struct; "id" member
-                                // has the TID
-
-    ULONG   cRequests;          // read requests from this thread;
-                                // 0 after the last read request
-                                // was released (since tree node
-                                // won't be freed then)
-
-} READERTREENODE, *PREADERTREENODE;
-
-/* ******************************************************************
- *
- *   Global variables
- *
- ********************************************************************/
-
-static HMTX         G_hmtxGlobal = NULLHANDLE;
-
-/* ******************************************************************
- *
- *   Private helpers
- *
- ********************************************************************/
-
-/*
- *@@ LockGlobal:
- *
- *      WARNING: As opposed to most other Lock* functions
- *      I have created, this returns an APIRET.
- *
- */
-
-static APIRET LockGlobal(VOID)
-{
-    if (!G_hmtxGlobal)
-        // first call:
-        return (DosCreateMutexSem(NULL,
-                                  &G_hmtxGlobal,
-                                  0,
-                                  TRUE));      // request!
-
-    return DosRequestMutexSem(G_hmtxGlobal, SEM_INDEFINITE_WAIT);
-}
-
-/*
- *@@ UnlockGlobal:
- *
- */
-
-static VOID UnlockGlobal(VOID)
-{
-    DosReleaseMutexSem(G_hmtxGlobal);
-}
-
-/* ******************************************************************
- *
- *   Public interfaces
- *
- ********************************************************************/
-
-/*
- *@@ semCreateRWMutex:
- *      creates a read-write mutex.
- *
- *      If this returns NO_ERROR, a new RWMUTEX
- *      has been created in *ppMutex. You must
- *      use semDeleteRWMutex to free it again.
- */
-
-APIRET semCreateRWMutex(PHRW phrw)
-{
-    APIRET      arc = NO_ERROR;
-
-    if (!(arc = LockGlobal()))
-    {
-        PRWMUTEX    pMutex = NEW(RWMUTEX);
-        if (!pMutex)
-            arc = ERROR_NOT_ENOUGH_MEMORY;
-        else
-        {
-            ZERO(pMutex);
-
-            if (    (!(arc = DosCreateEventSem(NULL,
-                                               &pMutex->hevWriterDone,
-                                               0,
-                                               FALSE)))
-                 && (!(arc = DosCreateEventSem(NULL,
-                                               &pMutex->hevReadersDone,
-                                               0,
-                                               FALSE)))
-               )
-            {
-                treeInit(&pMutex->ReaderThreadsTree, NULL);
-            }
-        }
-
-        if (arc)
-            semDeleteRWMutex((PHRW)&pMutex);
-        else
-            *phrw = (HRW)pMutex;
-
-        UnlockGlobal();
-    }
-
-    return arc;
-}
-
-/*
- *@@ semDeleteRWMutex:
- *      deletes a RW mutex previously created by
- *      semCreateRWMutex.
- *
- *      Returns:
- *
- *      --  NO_ERROR: sem was deleted, and *phrw
- *          was set to NULLHANDLE.
- *
- *      --  ERROR_SEM_BUSY: semaphore is currently
- *          requested.
- */
-
-APIRET semDeleteRWMutex(PHRW phrw)      // in/out: rwsem handle
-{
-    APIRET  arc = NO_ERROR;
-
-    if (!(arc = LockGlobal()))
-    {
-        PRWMUTEX pMutex;
-        if (    (phrw)
-             && (pMutex = (PRWMUTEX)(*phrw))
-           )
-        {
-            if (    (pMutex->cReaders)
-                 || (pMutex->cWriters)
-               )
-                arc = ERROR_SEM_BUSY;
-            else
-            {
-                if (    (!(arc = DosCloseEventSem(pMutex->hevWriterDone)))
-                     && (!(arc = DosCloseEventSem(pMutex->hevReadersDone)))
-                   )
-                {
-                    LONG cItems = pMutex->cReaderThreads;
-                    TREE **papNodes = treeBuildArray(pMutex->ReaderThreadsTree,
-                                                     &cItems);
-                    if (papNodes)
-                    {
-                        ULONG ul;
-                        for (ul = 0; ul < cItems; ul++)
-                            free(papNodes[ul]);
-
-                        free(papNodes);
-                    }
-
-                    free(pMutex);
-                    *phrw = NULLHANDLE;
-                }
-            }
-        }
-        else
-            arc = ERROR_INVALID_PARAMETER;
-
-        UnlockGlobal();
-    }
-
-    return arc;
-}
-
-/*
- *@@ semRequestRead:
- *      requests read access from the read-write mutex.
- *
- *      Returns:
- *
- *      --  NO_ERROR: caller has read access and must
- *          call semReleaseRead when done.
- *
- *      --  ERROR_INVALID_PARAMETER
- *
- *      --  ERROR_TIMEOUT
- *
- *      This function will block only if another thread
- *      currently holds write access.
- *
- *      It will not block if other threads also have
- *      write access, or it is the current thread which
- *      holds write access, or if this is a nested read
- *      request on the same thread.
- *
- *      If this function returns NO_ERROR, the calling
- *      thread is stored as a reader in the read-write
- *      mutex and will block out other threads which
- *      call semRequestWrite.
- */
-
-APIRET semRequestRead(HRW hrw,              // in: rw-sem created by semCreateRWMutex
-                      ULONG ulTimeout)      // in: timeout in ms, or SEM_INDEFINITE_WAIT
-{
-    APIRET  arc = NO_ERROR;
-    BOOL    fLocked = FALSE;
-
-    // protect the RW by requesting the global mutex;
-    // note, we ignore ulTimeout here, since this request
-    // will only ever take a very short time
-    if (!(arc = LockGlobal()))
-    {
-        PRWMUTEX pMutex = (PRWMUTEX)hrw;
-        fLocked = TRUE;
-
-        if (!pMutex)
-            arc = ERROR_INVALID_PARAMETER;
-        else
-        {
-            // get our own thread ID
-            ULONG   tidMyself = doshMyTID();
-
-            // if there are any writers in the RW
-            // besides our own thread, wait for the
-            // writer to release write
-            if (    (pMutex->cWriters)
-                 && (pMutex->tidWriter != tidMyself)
-               )
-            {
-                while (    (pMutex->cWriters)
-                        && (!arc)
-                      )
-                {
-                    ULONG ul;
-                    DosResetEventSem(pMutex->hevWriterDone, &ul);
-
-                    // while we're waiting on the writer to post
-                    // "writers done", release the global mutex
-                    UnlockGlobal();
-                    fLocked = FALSE;
-
-                    // block on "writer done"; this gets posted from
-                    // semReleaseWrite after the writer has released
-                    // its last write request...
-                    // so after this unblocks, we must check cWriters
-                    // again, in case another writer has come in between
-                    if (!(arc = WinWaitEventSem(pMutex->hevWriterDone, ulTimeout)))
-                        // writer done:
-                        // request global mutex again
-                        if (!(arc = LockGlobal()))
-                            fLocked = TRUE;
-                    // else: probably timeout, do not loop again
-                }
-            }
-
-            if (!arc)
-            {
-                PREADERTREENODE pReader;
-
-                // add readers count
-                (pMutex->cReaders)++;
-
-                // check if this thread has a reader entry already
-                if (pReader = (PREADERTREENODE)treeFind(pMutex->ReaderThreadsTree,
-                                                        tidMyself,  // ID to look for
-                                                        treeCompareKeys))
-                {
-                    // yes:
-                    // this is either
-                    // -- a nested read request for the same thread
-                    // -- or a tree item from a previous read request
-                    //    which went to 0, but wasn't deleted for speed
-                    //    (cRequests is then 0)
-                    (pReader->cRequests)++;
-                }
-                else
-                {
-                    // no entry for this thread yet:
-                    // add a new one
-                    pReader = NEW(READERTREENODE);
-                    if (!pReader)
-                        arc = ERROR_NOT_ENOUGH_MEMORY;
-                    else
-                    {
-                        // store the thread ID as the tree ID to
-                        // sort by (so we can find by TID)
-                        pReader->Tree.ulKey = tidMyself;
-                        // set requests count to 1
-                        pReader->cRequests = 1;
-
-                        treeInsert(&pMutex->ReaderThreadsTree,
-                                   NULL,
-                                   (TREE*)pReader,
-                                   treeCompareKeys);
-                        (pMutex->cReaderThreads)++;
-                    }
-                }
-            }
-        }
-    } // end if (!(arc = LockGlobal()))
-
-    if (fLocked)
-        UnlockGlobal();
-
-    return arc;
-}
-
-/*
- *@@ semReleaseRead:
- *      releases read access previously requested
- *      by semRequestRead.
- *
- *      This may unblock other threads which have
- *      blocked in semRequestWrite.
- */
-
-APIRET semReleaseRead(HRW hrw)      // in: rw-sem created by semCreateRWMutex
-{
-    APIRET  arc = NO_ERROR;
-
-    // protect the RW by requesting global mutex
-    if (!(arc = LockGlobal()))
-    {
-        PRWMUTEX pMutex = (PRWMUTEX)hrw;
-
-        if (!pMutex)
-            arc = ERROR_INVALID_PARAMETER;
-        else
-        {
-            // get our own thread ID
-            ULONG   tidMyself = doshMyTID();
-
-            PREADERTREENODE pReader;
-
-            // find the READERTREENODE for our TID
-            if (    (pReader = (PREADERTREENODE)treeFind(pMutex->ReaderThreadsTree,
-                                                         tidMyself,  // ID to look for
-                                                         treeCompareKeys))
-                 && (pReader->cRequests)
-               )
-            {
-                // lower user count then (will be zero now,
-                // unless read requests were nested)
-                (pReader->cRequests)--;
-
-                // note: we don't delete the tree item,
-                // since it will probably be reused soon
-                // (speed)
-
-                // lower total requests count
-                (pMutex->cReaders)--;
-
-                if (pMutex->cReaders == 0)
-                    // no more readers now:
-                    // post "readers done" semaphore
-                    DosPostEventSem(pMutex->hevReadersDone);
-                            // this sets all threads blocking
-                            // in semRequestWrite to "ready"
-            }
-            else
-                // excessive releases for this thread,
-                // or this wasn't requested at all:
-                arc = ERROR_NOT_OWNER;
-        }
-
-        UnlockGlobal();
-
-    } // end if (!(arc = LockGlobal()))
-
-    return arc;
-}
-
-/*
- *@@ semQueryRead:
- *      checks if the thread currently has read
- *      access to the read-write semaphore.
- *
- *      Returns:
- *
- *      --  NO_ERROR if the same thread request
- *          read access before and thus is a reader.
- *
- *      --  ERROR_NOT_OWNER if the thread does not
- *          currently have read access.
- */
-
-APIRET semQueryRead(HRW hrw)        // in: rw-sem created by semCreateRWMutex
-{
-    APIRET  arc = NO_ERROR;
-
-    // protect the RW by requesting global mutex
-    if (!(arc = LockGlobal()))
-    {
-        PRWMUTEX pMutex = (PRWMUTEX)hrw;
-
-        if (!pMutex)
-            arc = ERROR_INVALID_PARAMETER;
-        else
-        {
-            // get our own thread ID
-            ULONG   tidMyself = doshMyTID();
-
-            PREADERTREENODE pReader;
-
-            // find the READERTREENODE for our TID
-            if (    (!(pReader = (PREADERTREENODE)treeFind(pMutex->ReaderThreadsTree,
-                                                           tidMyself,          // ID to look for
-                                                           treeCompareKeys)))
-                 || (pReader->cRequests == 0)
-               )
-                arc = ERROR_NOT_OWNER;
-            // else: pReader exists, and pReader->cRequests > 0 --> NO_ERROR
-        }
-
-        UnlockGlobal();
-
-    } // end if (!(arc = LockGlobal()))
-
-    return arc;
-}
-
-/*
- *@@ semRequestWrite:
- *      requests write access from the read-write mutex.
- *
- *      Returns:
- *
- *      --  NO_ERROR: caller has write access and must
- *          call semReleaseWrite when done.
- *
- *      --  ERROR_INVALID_PARAMETER
- *
- *      --  ERROR_TIMEOUT
- *
- *      This function will block if any other thread
- *      currently has read or write access.
- *
- *      It will not block if the current thread is the
- *      only thread that has requested read access
- *      before, or if this is a nested write request
- *      on the same thread.
- *
- *      If this function returns NO_ERROR, the calling
- *      thread owns the read-write mutex all alone,
- *      as if it were a regular mutex. While write
- *      access is held, other threads are blocked in
- *      semRequestRead or semRequestWrite.
- */
-
-APIRET semRequestWrite(HRW hrw,             // in: rw-sem created by semCreateRWMutex
-                       ULONG ulTimeout)     // in: timeout in ms, or SEM_INDEFINITE_WAIT
-{
-    APIRET  arc = NO_ERROR;
-    BOOL    fLocked = FALSE;
-
-    // protect the RW by requesting global mutex;
-    // note, we ignore ulTimeout here, since this request
-    // will only ever take a very short time
-    if (!(arc = LockGlobal()))
-    {
-        PRWMUTEX pMutex = (PRWMUTEX)hrw;
-        fLocked = TRUE;
-
-        if (!pMutex)
-            arc = ERROR_INVALID_PARAMETER;
-        else
-        {
-            // get our own thread ID
-            ULONG   tidMyself = doshMyTID();
-
-            while (!arc)
-            {
-                // check if current TID holds read request also
-                PREADERTREENODE pReader
-                    = (PREADERTREENODE)treeFind(pMutex->ReaderThreadsTree,
-                                                tidMyself,
-                                                treeCompareKeys);
-                            // != NULL if this TID has a reader already
-
-                // let the writer in if one of the three is true:
-                if (
-                     // 1) no readers and no writers at all currently
-                        (    (pMutex->cWriters == 0)
-                          && (pMutex->cReaders == 0)
-                        )
-                     // or 2) there is a writer (which implies that there
-                     //    are no readers), but the writer has the
-                     //    same TID as the caller --> nested writer call
-                     //    on the same thread
-                     || (    (pMutex->cWriters)
-                          && (pMutex->tidWriter == tidMyself)
-                        )
-                     // or 3) a reader tree item was found above, and
-                     //    current thread is the only reader
-                     || (    (pReader)
-                          && (pReader->cRequests)
-                          && (pReader->cRequests == pMutex->cReaders)
-                        )
-                   )
-                {
-                    // we're safe!
-                    break;
-                }
-                else
-                {
-                    // we're NOT safe:
-                    // this means that
-                    // 1)   a writer other than current thread is active, or
-                    // 2)   readers exist and we're not the only reader...
-                    // block then until "readers done" is posted
-                    ULONG ul;
-                    DosResetEventSem(pMutex->hevReadersDone, &ul);
-
-                    // while we're waiting on the last reader to post
-                    // "readers done", release the global mutex
-                    UnlockGlobal();
-                    fLocked = FALSE;
-
-                    // wait for all readers and writers to finish;
-                    // this gets posted by
-                    // -- semReleaseRead if pMutex->cReaders goes to 0
-                    // -- semReleaseWrite after another writer has
-                    //    released its last write request
-                    if (!(arc = WinWaitEventSem(pMutex->hevReadersDone, ulTimeout)))
-                        // readers done:
-                        // request global mutex again
-                        if (!(arc = LockGlobal()))
-                            fLocked = TRUE;
-                    // else: probably timeout, do not loop again
-                }
-            } // end while (!arc)
-
-            if (!arc)
-            {
-                // OK, raise writers count
-                (pMutex->cWriters)++;
-                // and store our TID as the current writer
-                pMutex->tidWriter = tidMyself;
-            }
-        }
-
-        if (fLocked)
-            UnlockGlobal();
-
-    } // end if (!(arc = LockGlobal()))
-
-    return arc;
-}
-
-/*
- *@@ semReleaseWrite:
- *      releases write access previously requested
- *      by semRequestWrite.
- *
- *      This may unblock other threads which have
- *      blocked in either semRequestRead or
- *      semRequestWrite.
- */
-
-APIRET semReleaseWrite(HRW hrw)             // in: rw-sem created by semCreateRWMutex
-{
-    APIRET  arc = NO_ERROR;
-
-    // protect the RW by requesting the global mutex
-    if (!(arc = LockGlobal()))
-    {
-        PRWMUTEX pMutex = (PRWMUTEX)hrw;
-
-        if (!pMutex)
-            arc = ERROR_INVALID_PARAMETER;
-        else
-        {
-            // get our own thread ID
-            ULONG   tidMyself = doshMyTID();
-
-            if (    (pMutex->cWriters)
-                 && (pMutex->tidWriter == tidMyself)
-               )
-            {
-                (pMutex->cWriters)--;
-
-                if (pMutex->cWriters == 0)
-                {
-                    ULONG ul;
-                    // last write request released:
-                    // post the "writer done" semaphore
-                    DosResetEventSem(pMutex->hevWriterDone, &ul);
-                    DosPostEventSem(pMutex->hevWriterDone);
-                            // this sets all threads blocking
-                            // in semRequestRead to "ready"
-
-                    // and post the "reader done" semaphore
-                    // as well, in case another thread is
-                    // waiting for write request
-                    DosResetEventSem(pMutex->hevReadersDone, &ul);
-                    DosPostEventSem(pMutex->hevReadersDone);
-                            // this sets all threads blocking
-                            // in semRequestWrite to "ready"
-
-                    // and set tidWriter to 0
-                    pMutex->tidWriter = 0;
-                }
-                // else: nested write request on this
-                // thread (there can only ever be one
-                // writer thread)
-            }
-            else
-                // excessive releases for this thread,
-                // or this wasn't requested at all:
-                arc = ERROR_NOT_OWNER;
-        }
-
-        UnlockGlobal();
-
-    } // end if (!(arc = LockGlobal()))
-
-    return arc;
-}
-
-/*
- *@@ semQueryWrite:
- *      checks if the thread currently has write
- *      access to the read-write semaphore.
- *
- *      Returns:
- *
- *      --  NO_ERROR if the same thread request
- *          write access before and thus is a writer.
- *
- *      --  ERROR_NOT_OWNER if the thread does not
- *          currently have write access.
- */
-
-APIRET semQueryWrite(HRW hrw)           // in: rw-sem created by semCreateRWMutex
-{
-    APIRET  arc = NO_ERROR;
-
-    // protect the RW by requesting the global mutex
-    if (!(arc = LockGlobal()))
-    {
-        PRWMUTEX pMutex = (PRWMUTEX)hrw;
-
-        if (!pMutex)
-            arc = ERROR_INVALID_PARAMETER;
-        else
-        {
-            // get our own thread ID
-            ULONG   tidMyself = doshMyTID();
-
-            if (    (pMutex->cWriters == 0)
-                 || (pMutex->tidWriter != tidMyself)
-               )
-                arc = ERROR_NOT_OWNER;
-        }
-
-        UnlockGlobal();
-
-    } // end if (!(arc = LockGlobal()))
-
-    return arc;
-}
-
-
Index: trunk/src/helpers/stringh.c
===================================================================
--- trunk/src/helpers/stringh.c	(revision 195)
+++ trunk/src/helpers/stringh.c	(revision 196)
@@ -23,5 +23,5 @@
 
 /*
- *      Copyright (C) 1997-2000 Ulrich Mller.
+ *      Copyright (C) 1997-2002 Ulrich Mller.
  *      Parts Copyright (C) 1991-1999 iMatix Corporation.
  *      This file is part of the "XWorkplace helpers" source package.
Index: trunk/src/helpers/threads.c
===================================================================
--- trunk/src/helpers/threads.c	(revision 195)
+++ trunk/src/helpers/threads.c	(revision 196)
@@ -23,5 +23,5 @@
 
 /*
- *      Copyright (C) 1997-2000 Ulrich Mller.
+ *      Copyright (C) 1997-2002 Ulrich Mller.
  *      This file is part of the "XWorkplace helpers" source package.
  *      This is free software; you can redistribute it and/or modify
Index: trunk/src/helpers/tmsgfile.c
===================================================================
--- trunk/src/helpers/tmsgfile.c	(revision 195)
+++ trunk/src/helpers/tmsgfile.c	(revision 196)
@@ -53,5 +53,5 @@
 
 /*
- *      Copyright (C) 2001 Ulrich Mller.
+ *      Copyright (C) 2001-2002 Ulrich Mller.
  *      This file is part of the "XWorkplace helpers" source package.
  *      This is free software; you can redistribute it and/or modify
Index: trunk/src/helpers/tree.c
===================================================================
--- trunk/src/helpers/tree.c	(revision 195)
+++ trunk/src/helpers/tree.c	(revision 196)
@@ -312,7 +312,9 @@
     if (ul1 < ul2)
         return -1;
+
     if (ul1 > ul2)
         return +1;
-    return (0);
+
+    return 0;
 }
 
@@ -336,16 +338,18 @@
     {
         int i = strcmp(p1, p2);
-        if (i < 0) return (-1);
-        if (i > 0) return (+1);
+        if (i < 0)
+            return -1;
+        if (i > 0)
+            return +1;
     }
     else if (p1)
         // but p2 is NULL: p1 greater than p2 then
-        return (+1);
+        return +1;
     else if (p2)
         // but p1 is NULL: p1 less than p2 then
-        return (-1);
+        return -1;
 
     // return 0 if strcmp returned 0 above or both strings are NULL
-    return (0);
+    return 0;
 }
 
@@ -358,7 +362,5 @@
                        TREE *x)
 {
-   /**************************
-    *  rotate node x to left *
-    **************************/
+    // rotate node x to left
 
     TREE *y = x->right;
@@ -372,4 +374,5 @@
     if (y != LEAF)
         y->parent = x->parent;
+
     if (x->parent)
     {
@@ -396,8 +399,5 @@
                         TREE *x)
 {
-
-   /****************************
-    *  rotate node x to right  *
-    ****************************/
+    // rotate node x to right
 
     TREE *y = x->left;
@@ -411,4 +411,5 @@
     if (y != LEAF)
         y->parent = x->parent;
+
     if (x->parent)
     {
@@ -435,9 +436,4 @@
                         TREE *x)
 {
-   /*************************************
-    *  maintain Red-Black tree balance  *
-    *  after inserting node x           *
-    *************************************/
-
     // check Red-Black properties
     while (    x != *root
@@ -503,4 +499,5 @@
         }
     }
+
     (*root)->color = BLACK;
 }
@@ -546,9 +543,9 @@
     {
         int iResult;
-        if (0 == (iResult = pfnCompare(key, current->ulKey))) // if (compEQ(key, current->key))
+        if (!(iResult = pfnCompare(key, current->ulKey)))
             return STATUS_DUPLICATE_KEY;
 
         parent = current;
-        current = (iResult < 0)    // compLT(key, current->key)
+        current = (iResult < 0)
                     ? current->left
                     : current->right;
@@ -556,12 +553,8 @@
 
     // set up new node
-    /* if ((x = malloc (sizeof(*x))) == 0)
-        return STATUS_MEM_EXHAUSTED; */
     x->parent = parent;
     x->left = LEAF;
     x->right = LEAF;
     x->color = RED;
-    // x->key = key;
-    // x->rec = *rec;
 
     // insert node in tree
@@ -578,5 +571,4 @@
     insertFixup(root,
                 x);
-    // lastFind = NULL;
 
     if (plCount)
@@ -667,89 +659,6 @@
         }
     }
+
     tree->color = BLACK;
-
-   /*************************************
-    *  maintain Red-Black tree balance  *
-    *  after deleting node x            *
-    *************************************/
-
-    /* while (    x != *root
-            && x->color == BLACK
-          )
-    {
-        if (x == x->parent->left)
-        {
-            TREE *w = x->parent->right;
-            if (w->color == RED)
-            {
-                w->color = BLACK;
-                x->parent->color = RED;
-                rotateLeft(root,
-                           x->parent);
-                w = x->parent->right;
-            }
-            if (    w->left->color == BLACK
-                 && w->right->color == BLACK
-               )
-            {
-                w->color = RED;
-                x = x->parent;
-            }
-            else
-            {
-                if (w->right->color == BLACK)
-                {
-                    w->left->color = BLACK;
-                    w->color = RED;
-                    rotateRight(root,
-                                w);
-                    w = x->parent->right;
-                }
-                w->color = x->parent->color;
-                x->parent->color = BLACK;
-                w->right->color = BLACK;
-                rotateLeft(root,
-                           x->parent);
-                x = *root;
-            }
-        }
-        else
-        {
-            TREE *w = x->parent->left;
-            if (w->color == RED)
-            {
-                w->color = BLACK;
-                x->parent->color = RED;
-                rotateRight(root,
-                            x->parent);
-                w = x->parent->left;
-            }
-            if (    w->right->color == BLACK
-                 && w->left->color == BLACK
-               )
-            {
-                w->color = RED;
-                x = x->parent;
-            }
-            else
-            {
-                if (w->left->color == BLACK)
-                {
-                    w->right->color = BLACK;
-                    w->color = RED;
-                    rotateLeft(root,
-                               w);
-                    w = x->parent->left;
-                }
-                w->color = x->parent->color;
-                x->parent->color = BLACK;
-                w->left->color = BLACK;
-                rotateRight(root,
-                            x->parent);
-                x = *root;
-            }
-        }
-    }
-    x->color = BLACK; */
 }
 
@@ -803,4 +712,5 @@
     if (y != LEAF)
         y->parent = d->parent;
+
     if (d->parent)
     {
@@ -863,20 +773,14 @@
                FNTREE_COMPARE *pfnCompare)    // in: comparison func
 {
-   /*******************************
-    *  find node containing data  *
-    *******************************/
-
     TREE *current = root;
     while (current != LEAF)
     {
         int iResult;
-        if (0 == (iResult = pfnCompare(key, current->ulKey)))
-            return (current);
-        else
-        {
-            current = (iResult < 0) // compLT (key, current->key)
-                ? current->left
-                : current->right;
-        }
+        if (!(iResult = pfnCompare(key, current->ulKey)))
+            return current;
+
+        current = (iResult < 0)
+            ? current->left
+            : current->right;
     }
 
@@ -957,21 +861,20 @@
     p = r;
     if (p->right != LEAF)
-        return treeFirst (p->right);
-    else
-    {
-        p = r;
-        child   = LEAF;
-        while (    (p->parent)
-                && (p->right == child)
-              )
-        {
-            child = p;
-            p = p->parent;
-        }
-        if (p->right != child)
-            return p;
-        else
-            return NULL;
-    }
+        return treeFirst(p->right);
+
+    p = r;
+    child   = LEAF;
+    while (    (p->parent)
+            && (p->right == child)
+          )
+    {
+        child = p;
+        p = p->parent;
+    }
+
+    if (p->right != child)
+        return p;
+
+    return NULL;
 }
 
@@ -987,5 +890,6 @@
 
     if (    (!r)
-         || (r == LEAF))
+         || (r == LEAF)
+       )
         return NULL;
 
@@ -993,19 +897,19 @@
     if (p->left != LEAF)
         return treeLast (p->left);
-    else
-    {
-        p = r;
-        child   = LEAF;
-        while ((p->parent)
-           &&  (p->left == child))
-        {
-            child = p;
-            p = p->parent;
-        }
-        if (p->left != child)
-            return p;
-        else
-            return NULL;
-    }
+
+    p = r;
+    child   = LEAF;
+    while (    (p->parent)
+            && (p->left == child)
+          )
+    {
+        child = p;
+        p = p->parent;
+    }
+
+    if (p->left != child)
+        return p;
+
+    return NULL;
 }
 
Index: trunk/src/helpers/winh.c
===================================================================
--- trunk/src/helpers/winh.c	(revision 195)
+++ trunk/src/helpers/winh.c	(revision 196)
@@ -19,5 +19,5 @@
 
 /*
- *      Copyright (C) 1997-2000 Ulrich Mller.
+ *      Copyright (C) 1997-2002 Ulrich Mller.
  *      This file is part of the "XWorkplace helpers" source package.
  *      This is free software; you can redistribute it and/or modify
Index: trunk/src/helpers/xml.c
===================================================================
--- trunk/src/helpers/xml.c	(revision 195)
+++ trunk/src/helpers/xml.c	(revision 196)
@@ -107,5 +107,5 @@
 
 /*
- *      Copyright (C) 2000-2001 Ulrich Mller.
+ *      Copyright (C) 2000-2002 Ulrich Mller.
  *      This file is part of the "XWorkplace helpers" source package.
  *      This is free software; you can redistribute it and/or modify
