WinWorkstation.st
branchjv
changeset 8426 e2051b1553f0
parent 8420 76e39223f5ab
--- a/WinWorkstation.st	Mon Jun 11 10:50:04 2018 +0100
+++ b/WinWorkstation.st	Wed Jul 11 16:58:29 2018 +0200
@@ -1,6 +1,6 @@
 "
 COPYRIGHT (c) 1996 by Claus Gittinger
-COPYRIGHT (c) 2017 Patrik Svestka
+COPYRIGHT (c) 2017-2018 Patrik Svestka
 COPYRIGHT (c) 2015-2018 Jan Vrany
 	      All Rights Reserved
 
@@ -172,6 +172,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <errno.h>
+#include <assert.h>
 /* #include <malloc.h> */
 /* #include <math.h> */
 /* #include <string.h> */
@@ -5284,7 +5285,7 @@
 copyright
 "
 COPYRIGHT (c) 1996 by Claus Gittinger
-COPYRIGHT (c) 2017 Patrik Svestka
+COPYRIGHT (c) 2017-2018 Patrik Svestka
 COPYRIGHT (c) 2015-2018 Jan Vrany
 	      All Rights Reserved
 
@@ -8087,11 +8088,15 @@
     ] valueUninterruptably.
 
     windowId notNil ifTrue:[
-	self addKnownView:aView withId:windowId
+        self addKnownView:aView withId:windowId.
+        (aView windowStyle == #toolWindow) ifTrue:[ 
+            self raiseWindowToTopMost: aView id.  
+        ].  
     ].
     ^ windowId
 
     "Modified: / 28-01-2012 / 10:20:30 / cg"
+    "Modified: / 25-01-2018 / 10:19:46 / jv"
 !
 
 dcGetClipBoxForGC: gcId
@@ -10773,10 +10778,13 @@
 
     unsigned char *cp;
     OBJ cls;
-    int i1, i2, n, l, toDisplay;
+    SIZE size;
+    TEXTMETRICW tmet;
+    short maxDisplayBuffer;
+    int i1, i2, n, l;
+    int maxWidth, toDisplay;
     int nInstBytes;
 
-
     if (__isExternalAddress(aGCId)
      && __isNonNilObject(aString)
      && __bothSmallInteger(index1, index2)
@@ -10787,9 +10795,6 @@
 	HDC hDC;
 	HFONT hOldFont;
 
-	/* Windows (as in 7 or newer) limits the string size for TextOut* to 3275 */
-	const int MAX_DISPLAY_BUFFER = 3275;
-
 	i1 = __intVal(index1) - 1;
 	i2 = __intVal(index2) - 1;
 	if ((i1 < 0) || (i2 < i1)) {
@@ -10813,6 +10818,34 @@
 		gcData->bkMode = BK_TRANSPARENT;
 	    }
 	}
+
+  /* The Windows (as in 7 or newer) limits the string size for TextOut*.  There is apparently 
+   * an undocumented limit to the overall raster size.  It changes according to the font size (width)!
+   * The maximum value for the raster size is apparently 16384 (experimentally tested on Windows 7).
+   */
+
+
+  /* GetTextMetricsW gives all needed font metrics (has a fallback when fails)
+   * - a maxWidth parameter takes in account the worst case scenario - user prints 
+   * with the widest possible characters from the selected font.
+   * - a overHang is a parameter which allows the font to grow outside the maxWidth size
+   */
+
+  if (GetTextMetricsW(hDC, &tmet)) {
+      maxWidth = tmet.tmMaxCharWidth;
+      // Dynamically calculate the maximum buffer size for the selected font and its size
+      maxDisplayBuffer = 16384 / (maxWidth + tmet.tmOverhang);
+  } else {
+      /* A fallback when GetTextMetricsW fails.  Should not normally happen!
+       * The works case scenario, experimentally tested from 1170 fonts, is Microsoft Uighur-build-italic-288
+       * with maxWidth = 2179.  That would mean only 7 characters at the maxDisplayBuffer (16384 / 2179).
+       * Such a buffer would be rediculously slow!. A compromise is needed (speed vs. functionality)
+       * Taking an avgWidth from all 1170 with fonts size 96pt -> avgWidth = 152,
+       * which should suffice 99.9% of time. The buffer would then be int(16384/152) = 107, which is reasonable.
+       */
+      maxDisplayBuffer = 107;
+  }
+
 #if 0
 	/* leftover code from tries to make TextOut honor the gc-mode,
 	 * until I googled, that TextOut does not (by purpose, or backward-bug compatibility)
@@ -10841,13 +10874,13 @@
 	        cp += i1;
 	        do {
 	            /* TA_UPDATECP used => pX, pY ignored */
-	            if (! TextOutA(hDC, 0, 0, (char *)cp, MIN(toDisplay, MAX_DISPLAY_BUFFER))) { 
+	            if (! TextOutA(hDC, 0, 0, (char *)cp, MIN(toDisplay, maxDisplayBuffer))) { 
 	                PRINTF(("WinWorkstation [warning]: TextOutA failed. [%d]\n", __LINE__));
 	                PRINTF(("WinWorkstation [warning]: lastError=%d x:%d y:%d len:%d leftToShow=%d\n", GetLastError(), pX, pY, l, toDisplay));
 	                goto error;
 	            }
-	            cp += MAX_DISPLAY_BUFFER;
-	            toDisplay -= MAX_DISPLAY_BUFFER;
+	            cp += maxDisplayBuffer;
+	            toDisplay -= maxDisplayBuffer;
 	        } while(toDisplay > 0);
 	    }
 	    goto ret;
@@ -10869,13 +10902,13 @@
 	        w_cp += i1;
 	        do {
 	            /* TA_UPDATECP used => pX, pY ignored */
-	            if (! TextOutW(hDC, 0, 0, w_cp, MIN(toDisplay, MAX_DISPLAY_BUFFER))) { 
+	            if (! TextOutW(hDC, 0, 0, w_cp, MIN(toDisplay, maxDisplayBuffer))) { 
 	                PRINTF(("WinWorkstation [warning]: TextOutW failed. [%d]\n", __LINE__));
 	                PRINTF(("WinWorkstation [warning]: lastError=%d x:%d y:%d len:%d leftToShow=%d\n", GetLastError(), pX, pY, l, toDisplay));
 	                goto error;
 	            }
-	            w_cp += MAX_DISPLAY_BUFFER;
-	            toDisplay -= MAX_DISPLAY_BUFFER;
+	            w_cp += maxDisplayBuffer;
+	            toDisplay -= maxDisplayBuffer;
 	        } while (toDisplay > 0);
 	    }
 	    goto ret;
@@ -13270,14 +13303,15 @@
       minCode:(rawData at:8)
       maxCode:16rFFFF "(rawData at:9)"
       direction:nil
-      encoding:(rawData at:11).
+      encoding:(rawData at:11)
+      overHang:(rawData at:12).
     ^ info
 !
 
 fontsInFamily:aFamilyName face:aFaceName filtering:filter
     "return a set of all available fonts in aFamily/aFace on this display.
-     On WinWorkStations there is curently Face
-     But only thise matching filter (if nonNil)."
+     On WinWorkStations there is currently Face
+     But only these matching filter (if nonNil)."
 
     |allFonts fonts|
 
@@ -13777,11 +13811,12 @@
       maxDescent -> (data at:4)
       minWidth   -> (data at:5)
       maxWidth   -> (data at:6)
-      avgWidth   -> (data at:7).
-      minChar    -> (data at:8).
-      maxChar    -> (data at:9).
-      defaultChar-> (data at:10).
-      charSet    -> (data at:11).
+      avgWidth   -> (data at:7)
+      minChar    -> (data at:8)
+      maxChar    -> (data at:9)
+      defaultChar-> (data at:10)
+      charSet    -> (data at:11)
+      overHang   -> (data at:12)
 "
 
 %{
@@ -13844,10 +13879,11 @@
 	__ArrayInstPtr(rawData)->a_element[9] = __MKSMALLINT(tmet.tmDefaultChar);   /* default    -> (data at:10) */
 	t = __charSetSymbolFor(tmet.tmCharSet);
 	__ArrayInstPtr(rawData)->a_element[10]= t; __STORE(rawData, t);             /* charSet    -> (data at:11) */
-
-	DPRINTF(("textMetrics h=%x  avgAsc=%d avgDesc=%d minW=%d maxW=%d avgW=%d\n",
+  __ArrayInstPtr(rawData)->a_element[11]= __MKSMALLINT(tmet.tmOverhang);      /* overHang   -> (data at:12) */
+
+	DPRINTF(("textMetrics h=%x  avgAsc=%d avgDesc=%d minW=%d maxW=%d avgW=%d overHang=%d\n",
 		    hFont, tmet.tmAscent, tmet.tmDescent, avgWidth, tmet.tmMaxCharWidth,
-		    tmet.tmAveCharWidth));
+		    tmet.tmAveCharWidth, tmet.tmOverhang));
 	RETURN (self);
     }
     RETURN (nil);