Index: trunk/src/helpers/dialog.c
===================================================================
--- trunk/src/helpers/dialog.c	(revision 136)
+++ trunk/src/helpers/dialog.c	(revision 137)
@@ -73,4 +73,8 @@
 #include "helpers\xstring.h"
 
+#pragma hdrstop
+
+// #define DEBUG_DIALOG_WINDOWS 1
+
 /*
  *@@category: Helpers\PM helpers\Dialog templates
@@ -109,9 +113,12 @@
                                  // created
 
-    const char  *pcszControlsFont;  // from dlghCreateDlg
-
-    // V0.9.14 (2001-08-01) [umoeller]
+    PCSZ        pcszControlsFont;  // from dlghCreateDlg
+
+    // size of the client to be created
+    SIZEL       szlClient;
+
+    // various cached data V0.9.14 (2001-08-01) [umoeller]
     HPS         hps;
-    const char  *pcszFontLast;
+    PCSZ        pcszFontLast;
     LONG        lcidLast;
     FONTMETRICS fmLast;
@@ -190,4 +197,6 @@
 typedef struct _TABLEDEF
 {
+    PCOLUMNDEF  pOwningColumn;      // != NULL if this is a nested table
+
     LINKLIST    llRows;             // contains ROWDEF structs, no auto-free
 
@@ -205,7 +214,9 @@
 typedef enum _PROCESSMODE
 {
-    PROCESS_CALC_SIZES,             // step 1
-    PROCESS_CALC_POSITIONS,         // step 3
-    PROCESS_CREATE_CONTROLS         // step 4
+    PROCESS_1_CALC_SIZES,             // step 1
+    PROCESS_2_CALC_SIZES_FROM_TABLES, // step 2
+    PROCESS_3_CALC_FINAL_TABLE_SIZES, // step 3
+    PROCESS_4_CALC_POSITIONS,         // step 4
+    PROCESS_5_CREATE_CONTROLS         // step 5
 } PROCESSMODE;
 
@@ -217,5 +228,5 @@
 
 #define PM_GROUP_SPACING_X          16
-#define PM_GROUP_SPACING_TOP        20
+#define PM_GROUP_SPACING_TOP        16
 
 APIRET ProcessTable(PTABLEDEF pTableDef,
@@ -293,8 +304,10 @@
  *@@changed V0.9.14 (2001-08-01) [umoeller]: now caching fonts, which is significantly faster
  *@@changed V0.9.16 (2001-10-15) [umoeller]: added APIRET
+ *@@changed V0.9.16 (2002-02-02) [umoeller]: added ulWidth
  */
 
 APIRET CalcAutoSizeText(PCONTROLDEF pControlDef,
                         BOOL fMultiLine,          // in: if TRUE, multiple lines
+                        ULONG ulWidth,            // in: proposed width of control
                         PSIZEL pszlAuto,          // out: computed size
                         PDLGPRIVATE pDlgData)
@@ -317,8 +330,11 @@
         {
             RECTL rcl = {0, 0, 0, 0};
+            /*
             if (pControlDef->szlControlProposed.cx > 0)
                 rcl.xRight = pControlDef->szlControlProposed.cx;   // V0.9.12 (2001-05-31) [umoeller]
             else
                 rcl.xRight = winhQueryScreenCX() * 2 / 3;
+            */
+            rcl.xRight = ulWidth;
             if (pControlDef->szlControlProposed.cy > 0)
                 rcl.yTop = pControlDef->szlControlProposed.cy;   // V0.9.12 (2001-05-31) [umoeller]
@@ -358,4 +374,5 @@
 
 APIRET CalcAutoSize(PCONTROLDEF pControlDef,
+                    ULONG ulWidth,            // in: proposed width of control
                     PSIZEL pszlAuto,          // out: computed size
                     PDLGPRIVATE pDlgData)
@@ -372,4 +389,5 @@
             if (!(arc = CalcAutoSizeText(pControlDef,
                                          FALSE,         // no multiline
+                                         ulWidth,
                                          pszlAuto,
                                          pDlgData)))
@@ -404,4 +422,5 @@
                 arc = CalcAutoSizeText(pControlDef,
                                        ((pControlDef->flStyle & DT_WORDBREAK) != 0),
+                                       ulWidth,
                                        pszlAuto,
                                        pDlgData);
@@ -437,5 +456,5 @@
             pszlAuto->cy =   pDlgData->fmLast.lMaxBaselineExt
                            + pDlgData->fmLast.lExternalLeading
-                           + 5;         // some space
+                           + 7;         // some space
     }
 
@@ -445,6 +464,9 @@
 /*
  *@@ ColumnCalcSizes:
- *      implementation for PROCESS_CALC_SIZES in
+ *      implementation for PROCESS_1_CALC_SIZES in
  *      ProcessColumn.
+ *
+ *      This gets called a second time for
+ *      PROCESS_3_CALC_FINAL_TABLE_SIZES (V0.9.16).
  *
  *@@added V0.9.15 (2001-08-26) [umoeller]
@@ -455,10 +477,11 @@
 
 APIRET ColumnCalcSizes(PCOLUMNDEF pColumnDef,
+                       PROCESSMODE ProcessMode,     // in: PROCESS_1_CALC_SIZES or PROCESS_3_CALC_FINAL_TABLE_SIZES
                        PDLGPRIVATE pDlgData)
 {
     APIRET arc = NO_ERROR;
 
-    ULONG       ulXSpacing = 0,
-                ulYSpacing = 0;
+    ULONG       ulExtraCX = 0,
+                ulExtraCY = 0;
     if (pColumnDef->fIsNestedTable)
     {
@@ -467,5 +490,5 @@
         if (!(arc = ProcessTable(pTableDef,
                                  NULL,
-                                 PROCESS_CALC_SIZES,
+                                 ProcessMode,
                                  pDlgData)))
         {
@@ -491,7 +514,6 @@
 
                 // in any case, make this wider
-                ulXSpacing =    2 * PM_GROUP_SPACING_X;
-                ulYSpacing =    // 3 * PM_GROUP_SPACING_X;
-                            (PM_GROUP_SPACING_X + PM_GROUP_SPACING_TOP);
+                ulExtraCX =    2 * PM_GROUP_SPACING_X;
+                ulExtraCY =    (PM_GROUP_SPACING_X + PM_GROUP_SPACING_TOP);
             }
         }
@@ -501,50 +523,70 @@
         // no nested table, but control:
         PCONTROLDEF pControlDef = (PCONTROLDEF)pColumnDef->pvDefinition;
-        PSIZEL      pszl = &pControlDef->szlControlProposed;
         SIZEL       szlAuto;
 
-        if (    (pszl->cx < -1)
-             && (pszl->cx >= -100)
-           )
-        {
-            // other negative CX value:
-            // this is then a percentage of the row width... ignore for now
-            // V0.9.16 (2002-02-02) [umoeller]
-            szlAuto.cx = 0;
-            szlAuto.cy = 0;
-        }
-        else if (    (pszl->cx == -1)
-                  || (pszl->cy == -1)
-                )
-        {
-            arc = CalcAutoSize(pControlDef,
-                               &szlAuto,
-                               pDlgData);
-        }
-
-        if (!arc)
-        {
-            if (pszl->cx < 0)
-                pColumnDef->cpControl.cx = szlAuto.cx;
-            else
-                pColumnDef->cpControl.cx = pszl->cx;
-
-            if (pszl->cy < 0)
-                pColumnDef->cpControl.cy = szlAuto.cy;
-            else
-                pColumnDef->cpControl.cy = pszl->cy;
-
-            // @@todo hack sizes
-
-            ulXSpacing
-            = ulYSpacing
-            = (2 * pControlDef->ulSpacing);
-        }
+        // do auto-size calculations only on the first loop
+        // V0.9.16 (2002-02-02) [umoeller]
+        if (ProcessMode == PROCESS_1_CALC_SIZES)
+        {
+            if (    (pControlDef->szlControlProposed.cx == -1)
+                 || (pControlDef->szlControlProposed.cy == -1)
+               )
+            {
+                ULONG ulWidth;
+                if (pControlDef->szlControlProposed.cx == -1)
+                    ulWidth = 1000;
+                else
+                    ulWidth = pControlDef->szlControlProposed.cx;
+                arc = CalcAutoSize(pControlDef,
+                                   ulWidth,
+                                   &szlAuto,
+                                   pDlgData);
+            }
+
+            if (    (pControlDef->szlControlProposed.cx < -1)
+                 && (pControlDef->szlControlProposed.cx >= -100)
+               )
+            {
+                // other negative CX value:
+                // this is then a percentage of the table width... ignore for now
+                // V0.9.16 (2002-02-02) [umoeller]
+                szlAuto.cx = 0;
+            }
+
+            if (    (pControlDef->szlControlProposed.cy < -1)
+                 && (pControlDef->szlControlProposed.cy >= -100)
+               )
+            {
+                // other negative CY value:
+                // this is then a percentage of the row height... ignore for now
+                // V0.9.16 (2002-02-02) [umoeller]
+                szlAuto.cy = 0;
+            }
+
+            if (!arc)
+            {
+                if (pControlDef->szlControlProposed.cx < 0)
+                    pColumnDef->cpControl.cx = szlAuto.cx;
+                else
+                    pColumnDef->cpControl.cx = pControlDef->szlControlProposed.cx;
+
+                if (pControlDef->szlControlProposed.cy < 0)
+                    pColumnDef->cpControl.cy = szlAuto.cy;
+                else
+                    pColumnDef->cpControl.cy = pControlDef->szlControlProposed.cy;
+            }
+
+        } // end if (ProcessMode == PROCESS_1_CALC_SIZES)
+
+
+        ulExtraCX
+        = ulExtraCY
+        = (2 * pControlDef->ulSpacing);
     }
 
     pColumnDef->cpColumn.cx =   pColumnDef->cpControl.cx
-                               + ulXSpacing;
+                               + ulExtraCX;
     pColumnDef->cpColumn.cy =   pColumnDef->cpControl.cy
-                               + ulYSpacing;
+                               + ulExtraCY;
 
     return (arc);
@@ -553,5 +595,5 @@
 /*
  *@@ ColumnCalcPositions:
- *      implementation for PROCESS_CALC_POSITIONS in
+ *      implementation for PROCESS_4_CALC_POSITIONS in
  *      ProcessColumn.
  *
@@ -562,5 +604,5 @@
 APIRET ColumnCalcPositions(PCOLUMNDEF pColumnDef,
                            PROWDEF pOwningRow,          // in: current row from ProcessRow
-                           PLONG plX,                   // in/out: PROCESS_CALC_POSITIONS only
+                           PLONG plX,                   // in/out: PROCESS_4_CALC_POSITIONS only
                            PDLGPRIVATE pDlgData)
 {
@@ -568,5 +610,6 @@
 
     // calculate column position: this includes spacing
-    ULONG ulSpacing = 0;
+    LONG   lSpacingX = 0,
+           lSpacingY = 0;
 
     // column position = *plX on ProcessRow stack
@@ -599,6 +642,9 @@
         // should we create a PM control around the table?
         if (pTableDef->pCtlDef)
+        {
             // yes:
-            ulSpacing = PM_GROUP_SPACING_X / 2;     // V0.9.16 (2001-10-15) [umoeller]
+            lSpacingX = PM_GROUP_SPACING_X;     // V0.9.16 (2001-10-15) [umoeller]
+            lSpacingY = PM_GROUP_SPACING_X;     // V0.9.16 (2001-10-15) [umoeller]
+        }
     }
     else
@@ -606,5 +652,5 @@
         // no nested table, but control:
         PCONTROLDEF pControlDef = (PCONTROLDEF)pColumnDef->pvDefinition;
-        ulSpacing = pControlDef->ulSpacing;
+        lSpacingX = lSpacingY = pControlDef->ulSpacing;
     }
 
@@ -613,8 +659,8 @@
 
     // calculate CONTROL pos from COLUMN pos by applying spacing
-    pColumnDef->cpControl.x =   pColumnDef->cpColumn.x
-                              + ulSpacing;
-    pColumnDef->cpControl.y =   pColumnDef->cpColumn.y
-                              + ulSpacing;
+    pColumnDef->cpControl.x =   (LONG)pColumnDef->cpColumn.x
+                              + lSpacingX;
+    pColumnDef->cpControl.y =   (LONG)pColumnDef->cpColumn.y
+                              + lSpacingY;
 
     if (pColumnDef->fIsNestedTable)
@@ -626,5 +672,5 @@
         arc = ProcessTable(pTableDef,
                            &pColumnDef->cpControl,   // start pos for new table
-                           PROCESS_CALC_POSITIONS,
+                           PROCESS_4_CALC_POSITIONS,
                            pDlgData);
     }
@@ -635,5 +681,5 @@
 /*
  *@@ ColumnCreateControls:
- *      implementation for PROCESS_CREATE_CONTROLS in
+ *      implementation for PROCESS_5_CREATE_CONTROLS in
  *      ProcessColumn.
  *
@@ -648,7 +694,8 @@
     APIRET      arc = NO_ERROR;
 
-    PCONTROLPOS pcp = NULL;
     PCONTROLDEF pControlDef = NULL;
-    const char  *pcszTitle = NULL;
+
+    PCSZ        pcszClass = NULL;
+    PCSZ        pcszTitle = NULL;
     ULONG       flStyle = 0;
     LHANDLE     lHandleSet = NULLHANDLE;
@@ -665,5 +712,5 @@
         if (!(arc = ProcessTable(pTableDef,
                                  NULL,
-                                 PROCESS_CREATE_CONTROLS,
+                                 PROCESS_5_CREATE_CONTROLS,
                                  pDlgData)))
         {
@@ -674,17 +721,49 @@
             {
                 // yes:
-                pcp  = &pColumnDef->cpColumn;  // !! not control
+                // pcp  = &pColumnDef->cpColumn;  // !! not control
                 pControlDef = pTableDef->pCtlDef;
+                pcszClass = pControlDef->pcszClass;
                 pcszTitle = pControlDef->pcszText;
                 flStyle = pControlDef->flStyle;
 
-                x = pcp->x + pDlgData->ptlTotalOfs.x;
-                cx = pcp->cx - PM_GROUP_SPACING_X;
+                x  =   pColumnDef->cpColumn.x
+                     + pDlgData->ptlTotalOfs.x
+                     + PM_GROUP_SPACING_X / 2;
+                cx =   pColumnDef->cpColumn.cx
+                     - PM_GROUP_SPACING_X;
                     // note, just one spacing: for the _column_ size,
                     // we have specified 2 X spacings
-                y = pcp->y + pDlgData->ptlTotalOfs.y;
+                y  =   pColumnDef->cpColumn.y
+                     + pDlgData->ptlTotalOfs.y
+                     + PM_GROUP_SPACING_X / 2;
                 // cy = pcp->cy - PM_GROUP_SPACING_X;
-                cy = pcp->cy - /* PM_GROUP_SPACING_X - */ PM_GROUP_SPACING_TOP / 2;
+                // cy = pcp->cy - /* PM_GROUP_SPACING_X - */ PM_GROUP_SPACING_TOP;
+                cy =   pColumnDef->cpColumn.cy
+                     - PM_GROUP_SPACING_X / 2; //  - PM_GROUP_SPACING_TOP / 2;
             }
+
+#ifdef DEBUG_DIALOG_WINDOWS
+            {
+                HWND hwndDebug;
+                // debug: create a frame with the exact size
+                // of the _column_ (not the control), so this
+                // includes spacing
+                hwndDebug =
+                   WinCreateWindow(pDlgData->hwndDlg,   // parent
+                                WC_STATIC,
+                                "",
+                                WS_VISIBLE | SS_FGNDFRAME,
+                                pTableDef->cpTable.x + pDlgData->ptlTotalOfs.x,
+                                pTableDef->cpTable.y + pDlgData->ptlTotalOfs.y,
+                                pTableDef->cpTable.cx,
+                                pTableDef->cpTable.cy,
+                                pDlgData->hwndDlg,   // owner
+                                HWND_BOTTOM,
+                                -1,
+                                NULL,
+                                NULL);
+                winhSetPresColor(hwndDebug, PP_FOREGROUNDCOLOR, RGBCOL_BLUE);
+            }
+#endif
         }
     }
@@ -693,12 +772,15 @@
         // no nested table, but control:
         pControlDef = (PCONTROLDEF)pColumnDef->pvDefinition;
-        pcp = &pColumnDef->cpControl;
+        // pcp = &pColumnDef->cpControl;
+        pcszClass = pControlDef->pcszClass;
         pcszTitle = pControlDef->pcszText;
         flStyle = pControlDef->flStyle;
 
-        x = pcp->x + pDlgData->ptlTotalOfs.x;
-        cx = pcp->cx;
-        y = pcp->y + pDlgData->ptlTotalOfs.y;
-        cy = pcp->cy;
+        x  =   pColumnDef->cpControl.x
+             + pDlgData->ptlTotalOfs.x;
+        cx =   pColumnDef->cpControl.cx;
+        y  =   pColumnDef->cpControl.y
+             + pDlgData->ptlTotalOfs.y;
+        cy =   pColumnDef->cpControl.cy;
 
         // now implement hacks for certain controls
@@ -734,4 +816,5 @@
 
             case 0xffff0006L:   // entry field
+            case 0xffff000AL:   // MLE:
                 // the stupid entry field resizes itself if it has
                 // the ES_MARGIN style, so correlate that too... dammit
@@ -743,5 +826,8 @@
 
                     x += cxMargin;
-                    y += cxMargin;
+                    y += cyMargin;
+                    cx -= 2 * cxMargin;
+                    cy -= 2 * cyMargin;
+                    // cy -= cxMargin;
                 }
             break;
@@ -749,23 +835,15 @@
     }
 
-    if (pcp && pControlDef)
+    if (pControlDef)
     {
         // create something:
-        // PPRESPARAMS ppp = NULL;
-
-        const char  *pcszFont = pControlDef->pcszFont;
+        PCSZ pcszFont = pControlDef->pcszFont;
                         // can be NULL, or CTL_COMMON_FONT
         if (pcszFont == CTL_COMMON_FONT)
             pcszFont = pDlgData->pcszControlsFont;
 
-        /* if (pcszFont)
-            winhStorePresParam(&ppp,
-                               PP_FONTNAMESIZE,
-                               strlen(pcszFont),
-                               (PVOID)pcszFont); */
-
         if (pColumnDef->hwndControl
             = WinCreateWindow(pDlgData->hwndDlg,   // parent
-                              (PSZ)pControlDef->pcszClass,
+                              (PSZ)pcszClass,   // hacked
                               (pcszTitle)   // hacked
                                     ? (PSZ)pcszTitle
@@ -782,4 +860,28 @@
                               NULL))
         {
+#ifdef DEBUG_DIALOG_WINDOWS
+            {
+                HWND hwndDebug;
+                // debug: create a frame with the exact size
+                // of the _column_ (not the control), so this
+                // includes spacing
+                hwndDebug =
+                   WinCreateWindow(pDlgData->hwndDlg,   // parent
+                                WC_STATIC,
+                                "",
+                                WS_VISIBLE | SS_FGNDFRAME,
+                                pColumnDef->cpColumn.x + pDlgData->ptlTotalOfs.x,
+                                pColumnDef->cpColumn.y + pDlgData->ptlTotalOfs.y,
+                                pColumnDef->cpColumn.cx,
+                                pColumnDef->cpColumn.cy,
+                                pDlgData->hwndDlg,   // owner
+                                HWND_BOTTOM,
+                                -1,
+                                NULL,
+                                NULL);
+                winhSetPresColor(hwndDebug, PP_FOREGROUNDCOLOR, RGBCOL_RED);
+            }
+#endif
+
             if (lHandleSet)
             {
@@ -850,10 +952,10 @@
  *      This does the following:
  *
- *      -- PROCESS_CALC_SIZES: size is taken from control def,
+ *      -- PROCESS_1_CALC_SIZES: size is taken from control def,
  *         or for tables, this produces a recursive ProcessTable
  *         call.
  *         Preconditions: none.
  *
- *      -- PROCESS_CALC_POSITIONS: position of each column
+ *      -- PROCESS_4_CALC_POSITIONS: position of each column
  *         is taken from *plX, which is increased by the
  *         column width by this call.
@@ -865,5 +967,5 @@
  *         size here.
  *
- *      -- PROCESS_CREATE_CONTROLS: well, creates the controls.
+ *      -- PROCESS_5_CREATE_CONTROLS: well, creates the controls.
  *
  *         For tables, this recurses again. If the table has
@@ -878,5 +980,5 @@
                      PROWDEF pOwningRow,          // in: current row from ProcessRow
                      PROCESSMODE ProcessMode,     // in: processing mode (see ProcessAll)
-                     PLONG plX,                   // in/out: PROCESS_CALC_POSITIONS only
+                     PLONG plX,                   // in/out: PROCESS_4_CALC_POSITIONS only
                      PDLGPRIVATE pDlgData)
 {
@@ -888,19 +990,112 @@
     {
         /*
-         * PROCESS_CALC_SIZES:
+         * PROCESS_1_CALC_SIZES:
          *      step 1.
          */
 
-        case PROCESS_CALC_SIZES:
+        case PROCESS_1_CALC_SIZES:
             arc = ColumnCalcSizes(pColumnDef,
+                                  ProcessMode,
                                   pDlgData);
         break;
 
         /*
-         * PROCESS_CALC_POSITIONS:
-         *      step 2.
+         * PROCESS_2_CALC_SIZES_FROM_TABLES:
+         *
          */
 
-        case PROCESS_CALC_POSITIONS:
+        case PROCESS_2_CALC_SIZES_FROM_TABLES:
+            if (pColumnDef->fIsNestedTable)
+            {
+                PTABLEDEF pTableDef = (PTABLEDEF)pColumnDef->pvDefinition;
+                if (!(arc = ProcessTable(pTableDef,
+                                         NULL,
+                                         PROCESS_2_CALC_SIZES_FROM_TABLES,
+                                         pDlgData)))
+                    ;
+            }
+            else
+            {
+                // no nested table, but control:
+                PCONTROLDEF pControlDef = (PCONTROLDEF)pColumnDef->pvDefinition;
+
+                if (    (pControlDef->szlControlProposed.cx < -1)
+                     && (pControlDef->szlControlProposed.cx >= -100)
+                   )
+                {
+                    // other negative CX value:
+                    // this we ignored during PROCESS_1_CALC_SIZES
+                    // (see ColumnCalcSizes); now set it to the
+                    // table width!
+                    ULONG cxThis = pOwningRow->pOwningTable->cpTable.cx
+                                    * -pControlDef->szlControlProposed.cx / 100;
+
+                    // but the table already has spacing applied,
+                    // so reduce that
+                    pColumnDef->cpControl.cx = cxThis
+                                            - (2 * pControlDef->ulSpacing);
+
+                    pColumnDef->cpColumn.cx = cxThis;
+
+                    // now we might have to re-compute auto-size
+                    if (pControlDef->szlControlProposed.cy == -1)
+                    {
+                        SIZEL   szlAuto;
+                        if (!(arc = CalcAutoSize(pControlDef,
+                                                 // now that we now the width,
+                                                 // use that!
+                                                 pColumnDef->cpControl.cx,
+                                                 &szlAuto,
+                                                 pDlgData)))
+                        {
+                            LONG cyColumnOld = pColumnDef->cpColumn.cy;
+                            LONG lDelta;
+                            PROWDEF pRowThis;
+
+                            pColumnDef->cpControl.cy = szlAuto.cy;
+                            pColumnDef->cpColumn.cy = szlAuto.cy
+                                        + (2 * pControlDef->ulSpacing);
+                        }
+                    }
+                }
+
+                if (    (pControlDef->szlControlProposed.cy < -1)
+                     && (pControlDef->szlControlProposed.cy >= -100)
+                   )
+                {
+                    // same thing for CY, but this time we
+                    // take the row height
+                    ULONG cyThis = pOwningRow->cpRow.cy
+                                    * -pControlDef->szlControlProposed.cy / 100;
+
+                    // but the table already has spacing applied,
+                    // so reduce that
+                    pColumnDef->cpControl.cy = cyThis
+                                            - (2 * pControlDef->ulSpacing);
+
+                    pColumnDef->cpColumn.cy = cyThis;
+                }
+            }
+        break;
+
+        /*
+         * PROCESS_3_CALC_FINAL_TABLE_SIZES:
+         *
+         */
+
+        case PROCESS_3_CALC_FINAL_TABLE_SIZES:
+            // re-run calc sizes since we now know all
+            // the auto-size items
+            arc = ColumnCalcSizes(pColumnDef,
+                                  ProcessMode,
+                                  pDlgData);
+        break;
+
+        /*
+         * PROCESS_4_CALC_POSITIONS:
+         *      step 4.
+         */
+
+        case PROCESS_4_CALC_POSITIONS:
             arc = ColumnCalcPositions(pColumnDef,
                                       pOwningRow,
@@ -910,9 +1105,9 @@
 
         /*
-         * PROCESS_CREATE_CONTROLS:
-         *      step 3.
+         * PROCESS_5_CREATE_CONTROLS:
+         *      step 5.
          */
 
-        case PROCESS_CREATE_CONTROLS:
+        case PROCESS_5_CREATE_CONTROLS:
             arc = ColumnCreateControls(pColumnDef,
                                        pDlgData);
@@ -944,10 +1139,12 @@
     pRowDef->pOwningTable = pOwningTable;
 
-    if (ProcessMode == PROCESS_CALC_SIZES)
+    if (    (ProcessMode == PROCESS_1_CALC_SIZES)
+         || (ProcessMode == PROCESS_3_CALC_FINAL_TABLE_SIZES)
+       )
     {
         pRowDef->cpRow.cx = 0;
         pRowDef->cpRow.cy = 0;
     }
-    else if (ProcessMode == PROCESS_CALC_POSITIONS)
+    else if (ProcessMode == PROCESS_4_CALC_POSITIONS)
     {
         // set up x and y so that the columns can
@@ -969,5 +1166,7 @@
         if (!(arc = ProcessColumn(pColumnDefThis, pRowDef, ProcessMode, &lX, pDlgData)))
         {
-            if (ProcessMode == PROCESS_CALC_SIZES)
+            if (    (ProcessMode == PROCESS_1_CALC_SIZES)
+                 || (ProcessMode == PROCESS_3_CALC_FINAL_TABLE_SIZES)
+               )
             {
                 // row width = sum of all columns
@@ -997,5 +1196,5 @@
  *      nested table is found in a COLUMNDEF.
  *
- *      With PROCESS_CALC_POSITIONS, pptl must specify
+ *      With PROCESS_4_CALC_POSITIONS, pptl must specify
  *      the lower left corner of the table. For the
  *      root call, this will be {0, 0}; for nested calls,
@@ -1006,5 +1205,5 @@
 
 APIRET ProcessTable(PTABLEDEF pTableDef,
-                    const CONTROLPOS *pcpTable,       // in: table position with PROCESS_CALC_POSITIONS
+                    const CONTROLPOS *pcpTable,       // in: table position with PROCESS_4_CALC_POSITIONS
                     PROCESSMODE ProcessMode,          // in: processing mode (see ProcessAll)
                     PDLGPRIVATE pDlgData)
@@ -1014,16 +1213,19 @@
     PLISTNODE pNode;
 
-    if (ProcessMode == PROCESS_CALC_SIZES)
-    {
-        pTableDef->cpTable.cx = 0;
-        pTableDef->cpTable.cy = 0;
-    }
-    else if (ProcessMode == PROCESS_CALC_POSITIONS)
-    {
-        pTableDef->cpTable.x = pcpTable->x;
-        pTableDef->cpTable.y = pcpTable->y;
-
-        // start the rows on top
-        lY = pcpTable->y + pTableDef->cpTable.cy;
+    switch (ProcessMode)
+    {
+        case PROCESS_1_CALC_SIZES:
+        case PROCESS_3_CALC_FINAL_TABLE_SIZES:
+            pTableDef->cpTable.cx = 0;
+            pTableDef->cpTable.cy = 0;
+        break;
+
+        case PROCESS_4_CALC_POSITIONS:
+            pTableDef->cpTable.x = pcpTable->x;
+            pTableDef->cpTable.y = pcpTable->y;
+
+            // start the rows on top
+            lY = pcpTable->y + pTableDef->cpTable.cy;
+        break;
     }
 
@@ -1034,5 +1236,7 @@
         if (!(arc = ProcessRow(pRowDefThis, pTableDef, ProcessMode, &lY, pDlgData)))
         {
-            if (ProcessMode == PROCESS_CALC_SIZES)
+            if (    (ProcessMode == PROCESS_1_CALC_SIZES)
+                 || (ProcessMode == PROCESS_3_CALC_FINAL_TABLE_SIZES)
+               )
             {
                 // table width = maximum width of a row
@@ -1064,15 +1268,25 @@
  *      following for each call (in this order):
  *
- *      -- PROCESS_CALC_SIZES: calculates the sizes
- *         of all tables, rows, columns, and controls.
- *
- *         After this first call, we know all the sizes
- *         only and can then calculate the positions.
- *
- *      -- PROCESS_CALC_POSITIONS: calculates the positions
- *         based on the sizes calculated before.
- *
- *      -- PROCESS_CREATE_CONTROLS: creates the controls with the
- *         positions and sizes calculated before.
+ *      --  PROCESS_1_CALC_SIZES: calculates the preliminary
+ *          sizes of all tables, rows, columns, and controls
+ *          except those controls that have specified that
+ *          their size should depend on others.
+ *
+ *      --  PROCESS_2_CALC_SIZES_FROM_TABLES: calculates the
+ *          sizes of those controls that want to depend on
+ *          others.
+ *
+ *      --  PROCESS_3_CALC_FINAL_TABLE_SIZES: since the table
+ *          and row sizes might have changed during
+ *          PROCESS_2_CALC_SIZES_FROM_TABLES, we need to re-run
+ *          to re-calculate the size of all rows and tables.
+ *          After this first call, we know _all_ the sizes
+ *          and can then calculate the positions.
+ *
+ *      --  PROCESS_4_CALC_POSITIONS: calculates the positions
+ *          based on the sizes calculated before.
+ *
+ *      --  PROCESS_5_CREATE_CONTROLS: creates the controls with the
+ *          positions and sizes calculated before.
  *
  *      The second trick is the precondition that tables may
@@ -1084,5 +1298,4 @@
 
 APIRET ProcessAll(PDLGPRIVATE pDlgData,
-                  PSIZEL pszlClient,
                   PROCESSMODE ProcessMode)
 {
@@ -1094,12 +1307,13 @@
     switch (ProcessMode)
     {
-        case PROCESS_CALC_SIZES:
-            pszlClient->cx = 0;
-            pszlClient->cy = 0;
+        case PROCESS_1_CALC_SIZES:
+        case PROCESS_3_CALC_FINAL_TABLE_SIZES:
+            pDlgData->szlClient.cx = 0;
+            pDlgData->szlClient.cy = 0;
         break;
 
-        case PROCESS_CALC_POSITIONS:
+        case PROCESS_4_CALC_POSITIONS:
             // start with the table on top
-            cpTable.y = pszlClient->cy;
+            cpTable.y = pDlgData->szlClient.cy;
         break;
     }
@@ -1109,5 +1323,5 @@
         PTABLEDEF pTableDefThis = (PTABLEDEF)pNode->pItemData;
 
-        if (ProcessMode == PROCESS_CALC_POSITIONS)
+        if (ProcessMode == PROCESS_4_CALC_POSITIONS)
         {
             cpTable.x = 0;
@@ -1120,9 +1334,11 @@
                                  pDlgData)))
         {
-            if (ProcessMode == PROCESS_CALC_SIZES)
+            if (    (ProcessMode == PROCESS_2_CALC_SIZES_FROM_TABLES)
+                 || (ProcessMode == PROCESS_3_CALC_FINAL_TABLE_SIZES)
+               )
             {
                 // all sizes have now been computed:
-                pszlClient->cx += pTableDefThis->cpTable.cx;
-                pszlClient->cy += pTableDefThis->cpTable.cy;
+                pDlgData->szlClient.cx += pTableDefThis->cpTable.cx;
+                pDlgData->szlClient.cy += pTableDefThis->cpTable.cy;
             }
         }
@@ -1335,6 +1551,9 @@
                                                  pCurrentTable,
                                                  &pColumnDef)))
+                        {
+                            pCurrentTable->pOwningColumn = pColumnDef;
                             lstAppendItem(&pCurrentRow->llColumns,
                                           pColumnDef);
+                        }
                     }
                 }
@@ -1427,14 +1646,21 @@
  *@@ Dlg2_CalcSizes:
  *
+ *      After this, DLGPRIVATE.szlClient is valid.
+ *
  *@@added V0.9.15 (2001-08-26) [umoeller]
  */
 
-APIRET Dlg2_CalcSizes(PDLGPRIVATE pDlgData,
-                      PSIZEL pszlClient)          // out: dialog's client size
-{
-    APIRET arc = ProcessAll(pDlgData,
-                            pszlClient,
-                            PROCESS_CALC_SIZES);
+APIRET Dlg2_CalcSizes(PDLGPRIVATE pDlgData)
+{
+    APIRET arc;
+
+    if (!(arc = ProcessAll(pDlgData,
+                           PROCESS_1_CALC_SIZES)))
                      // this goes into major recursions...
+        // run again to compute sizes that depend on tables
+        if (!(arc = ProcessAll(pDlgData,
+                               PROCESS_2_CALC_SIZES_FROM_TABLES)))
+            arc = ProcessAll(pDlgData,
+                             PROCESS_3_CALC_FINAL_TABLE_SIZES);
 
     // free the cached font resources that
@@ -1461,5 +1687,4 @@
 
 APIRET Dlg3_PositionAndCreate(PDLGPRIVATE pDlgData,
-                              PSIZEL pszlClient,          // in: dialog's client size
                               HWND *phwndFocusItem)       // out: item to give focus to
 {
@@ -1472,6 +1697,5 @@
 
     ProcessAll(pDlgData,
-               pszlClient,
-               PROCESS_CALC_POSITIONS);
+               PROCESS_4_CALC_POSITIONS);
 
     /*
@@ -1485,6 +1709,5 @@
 
     ProcessAll(pDlgData,
-               pszlClient,
-               PROCESS_CREATE_CONTROLS);
+               PROCESS_5_CREATE_CONTROLS);
 
     if (pDlgData->hwndDefPushbutton)
@@ -1564,5 +1787,6 @@
  *      automatically here. Even better, for many controls,
  *      auto-sizing is supported according to the control's
- *      text (e.g. for statics and checkboxes).
+ *      text (e.g. for statics and checkboxes). In a way,
+ *      this is a bit similar to HTML tables.
  *
  *      A regular standard dialog would use something like
@@ -1600,5 +1824,5 @@
  *      in some table. Tables may also nest (see below).
  *
- *      The macros are:
+ *      The DLGHITEM macros are:
  *
  *      --  START_TABLE starts a new table. The tables may nest,
@@ -1653,33 +1877,33 @@
  *          always be a START_ROW first.
  *
+ *      While it is possible to set up the CONTROLDEFs manually
+ *      as static structures, I recommend using the bunch of
+ *      other macros that were defined in dialog.h for this.
+ *      For example, you can use CONTROLDEF_PUSHBUTTON to create
+ *      a push button, and many more.
+ *
  *      To create a dialog, set up arrays like the following:
  *
  +          // control definitions referenced by DlgTemplate:
  +          CONTROLDEF
- +      (1)             GroupDef = {
- +                                  WC_STATIC, "", ....,
- +                                  { 0, 0 },       // size, ignored for groups
- +                                  5               // spacing
- +                               },
- +      (2)             CnrDef = {
- +                                  WC_CONTAINER, "", ....,
- +                                  { 50, 50 },     // size
- +                                  5               // spacing
- +                               },
- +      (3)             Static = {
- +                                  WC_STATIC, "Static below cnr", ...,
- +                                  { SZL_AUTOSIZE, SZL_AUTOSIZE },     // size
- +                                  5               // spacing
- +                               },
- +      (4)             OKButton = {
- +                                  WC_STATIC, "~OK", ...,
- +                                  { 100, 30 },    // size
- +                                  5               // spacing
- +                               },
- +      (5)             CancelButton = {
- +                                  WC_STATIC, "~Cancel", ...,
- +                                  { 100, 30 },    // size
- +                                  5               // spacing
- +                               };
+ +      (1)             GroupDef = CONTROLDEF_GROUP("Group",
+ +                                                  -1,     // ID
+ +                                                  SZL_AUTOSIZE,
+ +                                                  SZL_AUTOSIZE),
+ +      (2)             CnrDef = CONTROLDEF_CONTAINER(-1,   // ID,
+ +                                                  50,
+ +                                                  50),
+ +      (3)             Static = CONTROLDEF_TEXT("Static below cnr",
+ +                                                  -1,     // ID
+ +                                                  SZL_AUTOSIZE,
+ +                                                  SZL_AUTOSIZE),
+ +      (4)             OKButton = CONTROLDEF_DEFPUSHBUTTON("~OK",
+ +                                                  DID_OK,
+ +                                                  SZL_AUTOSIZE,
+ +                                                  SZL_AUTOSIZE),
+ +      (5)             CancelButton = CONTROLDEF_PUSHBUTTON("~Cancel",
+ +                                                  DID_CANCEL,
+ +                                                  SZL_AUTOSIZE,
+ +                                                  SZL_AUTOSIZE);
  +
  +          DLGHITEM DlgTemplate[] =
@@ -1723,36 +1947,4 @@
  +          ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍŒ
  *
- *      <B>Errors:</B>
- *
- *      This does not return a HWND, but an APIRET. This will be
- *      one of the following:
- *
- *      --  NO_ERROR: only in that case, the phwndDlg ptr
- *          receives the HWND of the new dialog, which can
- *          then be given to WinProcessDlg. Don't forget
- *          WinDestroyWindow.
- *
- *      --  ERROR_NOT_ENOUGH_MEMORY
- *
- *      --  DLGERR_ROW_BEFORE_TABLE: a row definition appeared
- *          outside a table definition.
- *
- *      --  DLGERR_CONTROL_BEFORE_ROW: a control definition
- *          appeared right after a table definition. You must
- *          specify a row first.
- *
- *      --  DLGERR_NULL_CTL_DEF: TYPE_END_TABLE was specified,
- *          but the CONTROLDEF ptr was NULL.
- *
- *      --  DLGERR_CANNOT_CREATE_FRAME: unable to create the
- *          WC_FRAME window. Maybe an invalid owner was specified.
- *
- *      --  DLGERR_INVALID_CODE: invalid "Type" field in
- *          DLGHITEM.
- *
- *      --  DLGERR_TABLE_NOT_CLOSED, DLGERR_TOO_MANY_TABLES_CLOSED:
- *          improper nesting of TYPE_START_NEW_TABLE and
- *          TYPE_END_TABLE fields.
- *
  *      <B>Example:</B>
  *
@@ -1762,5 +1954,6 @@
  +          if (NO_ERROR == dlghCreateDlg(&hwndDlg,
  +                                        hwndOwner,
- +                                        FCF_DLGBORDER | FCF_NOBYTEALIGN,
+ +                                        FCF_TITLEBAR | FCF_SYSMENU
+ +                                           | FCF_DLGBORDER | FCF_NOBYTEALIGN,
  +                                        fnwpMyDlgProc,
  +                                        "My Dlg Title",
@@ -1773,4 +1966,46 @@
  +              WinDestroyWindow(hwndDlg);
  +          }
+ *
+ *      <B>Errors:</B>
+ *
+ *      This does not return a HWND, but an APIRET. This will be
+ *      one of the following:
+ *
+ *      --  NO_ERROR: only in that case, the phwndDlg ptr
+ *          receives the HWND of the new dialog, which can
+ *          then be given to WinProcessDlg. Don't forget
+ *          WinDestroyWindow.
+ *
+ *      --  ERROR_NOT_ENOUGH_MEMORY
+ *
+ *      --  DLGERR_ROW_BEFORE_TABLE: a row definition appeared
+ *          outside a table definition.
+ *
+ *      --  DLGERR_CONTROL_BEFORE_ROW: a control definition
+ *          appeared right after a table definition. You must
+ *          specify a row first.
+ *
+ *      --  DLGERR_NULL_CTL_DEF: TYPE_END_TABLE was specified,
+ *          but the CONTROLDEF ptr was NULL.
+ *
+ *      --  DLGERR_CANNOT_CREATE_FRAME: unable to create the
+ *          WC_FRAME window. Maybe an invalid owner was specified.
+ *
+ *      --  DLGERR_INVALID_CODE: invalid "Type" field in
+ *          DLGHITEM.
+ *
+ *      --  DLGERR_TABLE_NOT_CLOSED, DLGERR_TOO_MANY_TABLES_CLOSED:
+ *          improper nesting of TYPE_START_NEW_TABLE and
+ *          TYPE_END_TABLE fields.
+ *
+ *      --  DLGERR_CANNOT_CREATE_CONTROL: creation of some
+ *          sub-control failed. Maybe an invalid window class
+ *          was specified.
+ *
+ *      --  DLGERR_INVALID_CONTROL_TITLE: bad window title in
+ *          control.
+ *
+ *      --  DLGERR_INVALID_STATIC_BITMAP: static bitmap contains
+ *          an invalid bitmap handle.
  *
  *@@changed V0.9.14 (2001-07-07) [umoeller]: fixed disabled mouse with hwndOwner == HWND_DESKTOP
@@ -1860,5 +2095,4 @@
                 HWND    hwndDlg = pDlgData->hwndDlg;
                 HWND    hwndFocusItem = NULLHANDLE;
-                SIZEL   szlClient = {0};
                 RECTL   rclClient;
 
@@ -1868,6 +2102,5 @@
                  */
 
-                if (!(arc = Dlg2_CalcSizes(pDlgData,
-                                           &szlClient)))
+                if (!(arc = Dlg2_CalcSizes(pDlgData)))
                 {
                     WinSubclassWindow(hwndDlg, pfnwpDialogProc);
@@ -1881,6 +2114,6 @@
                     rclClient.xLeft = 10;
                     rclClient.yBottom = 10;
-                    rclClient.xRight = szlClient.cx + 2 * SPACING;
-                    rclClient.yTop = szlClient.cy + 2 * SPACING;
+                    rclClient.xRight = pDlgData->szlClient.cx + 2 * SPACING;
+                    rclClient.yTop = pDlgData->szlClient.cy + 2 * SPACING;
                     WinCalcFrameRect(hwndDlg,
                                      &rclClient,
@@ -1896,5 +2129,4 @@
 
                     arc = Dlg3_PositionAndCreate(pDlgData,
-                                                 &szlClient,
                                                  &hwndFocusItem);
 
@@ -2021,6 +2253,5 @@
              */
 
-            Dlg2_CalcSizes(pDlgData,
-                           &szlClient);
+            Dlg2_CalcSizes(pDlgData);
 
             // WinSubclassWindow(hwndDlg, pfnwpDialogProc);
@@ -2054,5 +2285,4 @@
             {
                 if (!(arc = Dlg3_PositionAndCreate(pDlgData,
-                                                   &szlClient,
                                                    &hwndFocusItem)))
                     WinSetFocus(HWND_DESKTOP, hwndFocusItem);
@@ -2359,7 +2589,7 @@
     ULONG flButtons = flFlags & 0xF;        // low nibble contains MB_YESNO etc.
 
-    const char  *p0 = "Error",
-                *p1 = NULL,
-                *p2 = NULL;
+    PCSZ        p0 = "Error",
+                p1 = NULL,
+                p2 = NULL;
 
     Icon.pcszText = (PCSZ)hptrIcon;
@@ -2672,5 +2902,5 @@
                             CTL_COMMON_FONT,
                             0,
-                            { 300, 20 },     // size
+                            { 300, SZL_AUTOSIZE },     // size
                             5               // spacing
                          },
Index: trunk/src/helpers/dosh.c
===================================================================
--- trunk/src/helpers/dosh.c	(revision 136)
+++ trunk/src/helpers/dosh.c	(revision 137)
@@ -4242,103 +4242,3 @@
 }
 
-/* ******************************************************************
- *
- *   Testcase
- *
- ********************************************************************/
-
-#ifdef BUILD_MAIN
-
-int main (int argc, char *argv[])
-{
-    ULONG ul;
-
-            printf("Drive checker ("__DATE__")\n");
-            printf("    type   fs      remot fixed parrm bootd       media audio eas   longn\n");
-
-    for (ul = 1;
-         ul <= 26;
-         ul++)
-    {
-        XDISKINFO xdi;
-        APIRET arc = doshGetDriveInfo(ul,
-                                      0, // DRVFL_TOUCHFLOPPIES,
-                                      &xdi);
-
-        printf(" %c: ", xdi.cDriveLetter, ul);
-
-        if (!xdi.fPresent)
-            printf("not present\n");
-        else
-        {
-            if (arc)
-                printf("error %d (IsFixedDisk: %d, QueryDiskParams %d, QueryMedia %d)\n",
-                        arc,
-                        xdi.arcIsFixedDisk,
-                        xdi.arcQueryDiskParams,
-                        xdi.arcQueryMedia);
-            else
-            {
-                ULONG   aulFlags[] =
-                    {
-                        DFL_REMOTE,
-                        DFL_FIXED,
-                        DFL_PARTITIONABLEREMOVEABLE,
-                        DFL_BOOTDRIVE,
-                        0,
-                        DFL_MEDIA_PRESENT,
-                        DFL_AUDIO_CD,
-                        DFL_SUPPORTS_EAS,
-                        DFL_SUPPORTS_LONGNAMES
-                    };
-                ULONG ul2;
-
-                PCSZ pcsz = NULL;
-
-                switch (xdi.bType)
-                {
-                    case DRVTYPE_HARDDISK:  pcsz = "HDISK ";    break;
-                    case DRVTYPE_FLOPPY:    pcsz = "FLOPPY"; break;
-                    case DRVTYPE_TAPE:      pcsz = "TAPE  "; break;
-                    case DRVTYPE_VDISK:     pcsz = "VDISK "; break;
-                    case DRVTYPE_CDROM:     pcsz = "CDROM "; break;
-                    case DRVTYPE_LAN:       pcsz = "LAN   "; break;
-                    case DRVTYPE_PARTITIONABLEREMOVEABLE:
-                                            pcsz = "PRTREM"; break;
-                    default:
-                                            printf("bType=%d, BPB.bDevType=%d",
-                                                    xdi.bType,
-                                                    xdi.bpb.bDeviceType);
-                                            printf("\n           ");
-                }
-
-                if (pcsz)
-                    printf("%s ", pcsz);
-
-                if (xdi.lFileSystem < 0)
-                    // negative means error
-                    printf("E%3d    ", xdi.lFileSystem); // , xdi.bFileSystem);
-                else
-                    printf("%7s ", xdi.szFileSystem); // , xdi.bFileSystem);
-
-                for (ul2 = 0;
-                     ul2 < ARRAYITEMCOUNT(aulFlags);
-                     ul2++)
-                {
-                    if (xdi.flDevice & aulFlags[ul2])
-                        printf("  X   ");
-                    else
-                        if (    (xdi.arcOpenLongnames)
-                             && (aulFlags[ul2] == DFL_SUPPORTS_LONGNAMES)
-                           )
-                            printf(" E%03d ", xdi.arcOpenLongnames);
-                        else
-                            printf("  -   ");
-                }
-                printf("\n");
-            }
-        }
-    }
-}
-
-#endif
+
Index: trunk/src/helpers/helpers_pre.in
===================================================================
--- trunk/src/helpers/helpers_pre.in	(revision 136)
+++ trunk/src/helpers/helpers_pre.in	(revision 137)
@@ -71,4 +71,5 @@
 $(OUTPUTDIR)\syssound.obj \
 $(OUTPUTDIR)\tmsgfile.obj \
+$(OUTPUTDIR)\vcard.obj \
 $(OUTPUTDIR)\wphandle.obj \
 $(OUTPUTDIR)\xprf.obj \
Index: trunk/src/helpers/makefile
===================================================================
--- trunk/src/helpers/makefile	(revision 136)
+++ trunk/src/helpers/makefile	(revision 137)
@@ -142,4 +142,58 @@
     @echo ----- Leaving $(MAKEDIR)
 
+# "test" target: for test cases
+TESTCASE_DIR = testcase
+
+TESTCASE_CC = icc /c /ti+ /w2 /ss /se /i$(HELPERS_BASE)\include /DDEBUG_DIALOG_WINDOWS /Fo$(TESTCASE_DIR)\$(@B).obj $(@B).c
+
+.c.{$(TESTCASE_DIR)}.obj:
+    @echo $(MAKEDIR)\makefile: Compiling $(@B).c
+    $(TESTCASE_CC)
+
+# testcase executables
+TESTCASE_TARGETS = \
+    dosh.exe \
+    dialog.exe \
+    vcard.exe \
+
+# dosh.exe
+DOSH_TEST_OBJS = \
+    $(TESTCASE_DIR)\dosh.obj \
+    $(TESTCASE_DIR)\_test_dosh.obj
+
+dosh.exe: $(DOSH_TEST_OBJS)
+    ilink /debug /optfunc /pmtype:vio $(DOSH_TEST_OBJS) /o:$@
+
+# dialog.exe
+DIALOG_TEST_OBJS = \
+    $(TESTCASE_DIR)\dialog.obj \
+    $(TESTCASE_DIR)\_test_dialog.obj \
+    $(TESTCASE_DIR)\winh.obj \
+    $(TESTCASE_DIR)\xstring.obj \
+    $(TESTCASE_DIR)\linklist.obj \
+    $(TESTCASE_DIR)\comctl.obj \
+    $(TESTCASE_DIR)\stringh.obj \
+    $(TESTCASE_DIR)\dosh.obj \
+    $(TESTCASE_DIR)\gpih.obj
+
+dialog.exe: $(DIALOG_TEST_OBJS)
+    ilink /debug /optfunc /pmtype:pm $(DIALOG_TEST_OBJS) /o:$@
+
+# vcard.exe
+VCARD_TEST_OBJS = \
+    $(TESTCASE_DIR)\vcard.obj \
+    $(TESTCASE_DIR)\_test_vcard.obj \
+    $(TESTCASE_DIR)\xstring.obj \
+    $(TESTCASE_DIR)\stringh.obj \
+    $(TESTCASE_DIR)\linklist.obj \
+    $(TESTCASE_DIR)\dosh.obj \
+    $(TESTCASE_DIR)\prfh.obj \
+    $(TESTCASE_DIR)\nls.obj
+
+vcard.exe: $(VCARD_TEST_OBJS)
+    ilink /debug /pmtype:vio $(VCARD_TEST_OBJS) /o:$@
+
+test: $(TESTCASE_TARGETS)
+
 # Define the main dependency between the output HELPERS.LIB and
 # all the object files.
Index: trunk/src/helpers/textview.c
===================================================================
--- trunk/src/helpers/textview.c	(revision 136)
+++ trunk/src/helpers/textview.c	(revision 137)
@@ -808,5 +808,4 @@
 
         case 6:     // A or /A HREF= (link)
-        {
             // four characters with hex anchor index (>=1)
             // or "####"
@@ -825,5 +824,5 @@
 
             ulSkip = 6;
-        break; }
+        break;
 
         case 7:     // A NAME= (anchor name)
@@ -834,6 +833,6 @@
             // only used with TXM_JUMPTOANCHORNAME, which then
             // searches the buffer
-            PSZ pEnd = strchr((*ppCurrent)+2, 0xFF);
-            if (pEnd)
+            PSZ pEnd;
+            if (pEnd = strchr((*ppCurrent)+2, 0xFF))
             {
                 ulSkip = pEnd - *ppCurrent + 1;
@@ -844,5 +843,6 @@
                 fPaintEscapeWord = TRUE;
             }
-        break; }
+        }
+        break;
 
         case 0x10:  // relative point size in percent
@@ -1155,8 +1155,7 @@
                     }
 
-                    pWord = txvCreateWord(hps,
-                                          &pCurrent, // advanced to next word
-                                          &flbuf);
-                    if (pWord)
+                    if (pWord = txvCreateWord(hps,
+                                              &pCurrent, // advanced to next word
+                                              &flbuf))
                     {
                         lstAppendItem(&pxfd->llWords, pWord);
@@ -2279,6 +2278,5 @@
 
             // allocate TEXTVIEWWINDATA for QWL_USER
-            ptxvd = (PTEXTVIEWWINDATA)malloc(sizeof(TEXTVIEWWINDATA));
-            if (ptxvd)
+            if (ptxvd = (PTEXTVIEWWINDATA)malloc(sizeof(TEXTVIEWWINDATA)))
             {
                 SIZEL   szlPage = {0, 0};
@@ -2380,5 +2378,6 @@
                 mrc = (MPARAM)FALSE;        // OK
             }
-        break; }
+        }
+        break;
 
         /*
@@ -2392,6 +2391,6 @@
         case WM_SETWINDOWPARAMS:
         {
-            WNDPARAMS *pwndParams = (WNDPARAMS *)mp1;
-            if (pwndParams)
+            WNDPARAMS *pwndParams;
+            if (pwndParams = (WNDPARAMS *)mp1)
             {
                 if (pwndParams->fsStatus & WPM_TEXT)
@@ -2412,5 +2411,6 @@
                 }
             }
-        break; }
+        }
+        break;
 
         /*
@@ -2442,5 +2442,6 @@
                 }
             }
-        break; }
+        }
+        break;
 
         /*
@@ -2538,5 +2539,6 @@
 
             // WinEndPaint(hps);
-        break; }
+        }
+        break;
 
         /*
@@ -2577,5 +2579,4 @@
 
         case WM_VSCROLL:
-        {
             if (ptxvd->fVScrollVisible)
             {
@@ -2589,5 +2590,5 @@
                                     mp2);
             }
-        break; }
+        break;
 
         /*
@@ -2597,5 +2598,4 @@
 
         case WM_HSCROLL:
-        {
             if (ptxvd->fHScrollVisible)
             {
@@ -2609,5 +2609,5 @@
                                     mp2);
             }
-        break; }
+        break;
 
         /*
@@ -2624,5 +2624,6 @@
                            (mp2 != 0));
             WinReleasePS(hps);
-        break; }
+        }
+        break;
 
         /*
@@ -2633,6 +2634,6 @@
         case WM_MOUSEMOVE:
         {
-            HWND    hwndOwner = WinQueryWindow(hwndTextView, QW_OWNER);
-            if (hwndOwner)
+            HWND    hwndOwner;
+            if (hwndOwner = WinQueryWindow(hwndTextView, QW_OWNER))
             {
                 HPOINTER hptrSet
@@ -2646,5 +2647,6 @@
                 WinSetPointer(HWND_DESKTOP, hptrSet);
             }
-        break; }
+        }
+        break;
 
         /*
@@ -2656,5 +2658,5 @@
         {
             POINTL ptlPos;
-            PLISTNODE pWordNodeClicked = NULL;
+            PLISTNODE pWordNodeClicked;
 
             ptlPos.x = SHORT1FROMMP(mp1) + ptxvd->ulViewXOfs;
@@ -2666,8 +2668,6 @@
             ptxvd->usLastAnchorClicked = 0;
 
-            pWordNodeClicked = txvFindWordFromPoint(&ptxvd->xfd,
-                                                    &ptlPos);
-
-            if (pWordNodeClicked)
+            if (pWordNodeClicked = txvFindWordFromPoint(&ptxvd->xfd,
+                                                        &ptlPos))
             {
                 PTXVWORD pWordClicked = (PTXVWORD)pWordNodeClicked->pItemData;
@@ -2709,5 +2709,6 @@
             WinSetCapture(HWND_DESKTOP, hwndTextView);
             mrc = (MPARAM)TRUE;
-        break; }
+        }
+        break;
 
         /*
@@ -2732,6 +2733,5 @@
 
                 // nofify owner
-                hwndOwner = WinQueryWindow(hwndTextView, QW_OWNER);
-                if (hwndOwner)
+                if (hwndOwner = WinQueryWindow(hwndTextView, QW_OWNER))
                     WinPostMsg(hwndOwner,
                                WM_CONTROL,
@@ -2743,5 +2743,6 @@
 
             mrc = (MPARAM)TRUE;
-        break; }
+        }
+        break;
 
         /*
@@ -2856,5 +2857,6 @@
             else
                 mrc = (MPARAM)TRUE;
-        break; }
+        }
+        break;
 
         /*
@@ -2893,5 +2895,6 @@
                 mrc = (MPARAM)TRUE;
             }
-        break; }
+        }
+        break;
 
         /*
@@ -2942,5 +2945,6 @@
                 mrc = (MPARAM)TRUE;
             }
-        break; }
+        }
+        break;
 
         /*
@@ -2962,5 +2966,6 @@
                                   FALSE,
                                   FALSE);       // quick format
-        break; }
+        }
+        break;
 
         /*
@@ -3020,5 +3025,4 @@
 
         case TXM_JUMPTOANCHORNAME:
-        {
             if (mp1)
             {
@@ -3058,5 +3062,5 @@
                 }
             }
-        break; }
+        break;
 
         /*
Index: trunk/src/helpers/winh.c
===================================================================
--- trunk/src/helpers/winh.c	(revision 136)
+++ trunk/src/helpers/winh.c	(revision 137)
@@ -3949,4 +3949,6 @@
  *      in WM_INITDLG of the notebook dlg function if the app
  *      has determined that it is running on Warp 4.
+ *
+ *@@changed V0.9.16 (2002-02-02) [umoeller]: fixed entry fields
  */
 
@@ -3993,10 +3995,21 @@
                 if (ulDownUnits)
                 {
+                    CHAR szClass[10];
                     SWP swp;
-                    // _Pmpf(("Moving downwards %d pixels", ptl.y));
+                    LONG lDeltaX = 0,
+                         lDeltaY = 0;
+                    // special handling for entry fields
+                    // V0.9.16 (2002-02-02) [umoeller]
+                    WinQueryClassName(hwndItem, sizeof(szClass), szClass);
+                    if (!strcmp(szClass, "#6"))
+                    {
+                        lDeltaX = 3 * WinQuerySysValue(HWND_DESKTOP, SV_CXBORDER);
+                        lDeltaY = 3 * WinQuerySysValue(HWND_DESKTOP, SV_CYBORDER);
+                    }
+
                     WinQueryWindowPos(hwndItem, &swp);
                     WinSetWindowPos(hwndItem, 0,
-                                    swp.x,
-                                    swp.y - ptl.y,
+                                    swp.x + lDeltaX,
+                                    swp.y - ptl.y + lDeltaY,
                                     0, 0,
                                     SWP_MOVE);
Index: trunk/src/helpers/xstring.c
===================================================================
--- trunk/src/helpers/xstring.c	(revision 136)
+++ trunk/src/helpers/xstring.c	(revision 137)
@@ -478,6 +478,6 @@
 PXSTRING xstrCreate(ULONG ulPreAllocate)
 {
-    PXSTRING pxstr = (PXSTRING)malloc(sizeof(XSTRING));
-    if (pxstr)
+    PXSTRING pxstr;
+    if (pxstr = (PXSTRING)malloc(sizeof(XSTRING)))
         xstrInit(pxstr, ulPreAllocate);
 
@@ -1404,7 +1404,9 @@
  *@@added V0.9.9 (2001-02-28) [umoeller]
  *@@changed V0.9.9 (2001-03-06) [lafaix]: removed memory allocation
- */
-
-ULONG xstrDecode(PXSTRING pxstr)       // in/out: string to be decoded
+ *@@changed V0.9.16 (2002-02-02) [umoeller]: added cKey
+ */
+
+ULONG xstrDecode2(PXSTRING pxstr,       // in/out: string to be decoded
+                  CHAR cKey)            // in: encoding key (normally '%')
 {
     ULONG   ulrc = 0;
@@ -1423,5 +1425,5 @@
             // pSource points to next char now
 
-            if (c == '%')
+            if (c == cKey)
             {
                 static char ach[] = "0123456789ABCDEF";
@@ -1453,5 +1455,5 @@
 
             // not encoding, or null after '%', or invalid encoding:
-            // just copy this
+            // just leave thisalone
             *pDest++ = c;
         } // while ((ch = *pSource++))
@@ -1465,4 +1467,16 @@
 
     return (ulrc);
+}
+
+/*
+ *@@ xstrDecode:
+ *      added for compatibility with exports.
+ *
+ *@@added V0.9.16 (2002-02-02) [umoeller]
+ */
+
+ULONG xstrDecode(PXSTRING pxstr)
+{
+    return (xstrDecode2(pxstr, '%'));
 }
 
