Faculty of Information Technology
Software Engineering Group

Ticket #126: issue_126_patch_1_of_1_redc9b78c5b42.patch

File issue_126_patch_1_of_1_redc9b78c5b42.patch, 5.2 KB (added by Patrik Svestka, 3 years ago)

The new improved version of the fix - Drawing TextOutA and TextOutW chunk-by-chunk

  • WinWorkstation.st

    # HG changeset patch
    # User Patrik Svestka <patrik.svestka@gmail.com>
    # Date 1491301233 -7200
    #      Tue Apr 04 12:20:33 2017 +0200
    # Branch jv
    # Node ID edc9b78c5b42767cecfbf199b4f153c213237004
    # Parent  76834c6940c7f04c6aa22cdd3669b263e64b0fb6
    Issue #126: String text becomes invisible when string length exceeds buffer (an undocumented internal limit)
    
    Short description: The patch fixes an issue, where strings longer are than 3275 characters, for both TextOutA and TextOutW (an undocumented internal limit).
    Now such strings are correctly displayed.
    
    Detailed description: The position of pX and pY is set by SetTextAlign(hDC, TA_UPDATECP) and MoveToEx(hDC, pX, pY, NULL).  The side effect when
    using TA_UPDATECP (sets the current point to the reference point) is that any TextOut will ignore pX and pY.  Both TextOutA and TextOutW will
    have pX=0 and pX=0.  The MIN function is used for selecting the lowest value to display - never exceeding MAX_DISPLAY_BUFFER.  The loop iterates
    till it has nothing more toDisplay.
    
    note: I have also added parentheses around MIN definition to avoid operator precedence problem in the future.
    
    To see more about the issue visit:
    https://swing.fit.cvut.cz/projects/stx-jv/ticket/126
    
    diff -r 76834c6940c7 -r edc9b78c5b42 WinWorkstation.st
    a b  
    28002800                  lpmmi->ptMaxPosition.y = 0;
    28012801                  lpmmi->ptMaxSize.x = lI->currentMonitorWidth;
    28022802                  lpmmi->ptMaxSize.y = lI->currentMonitorHeight;
    2803 #define MIN(a, b) (a < b ? a : b)
     2803/* Added Extra parentheses to avoid operator precedence problem */
     2804#define MIN(a,b) (((a)<(b))?(a):(b))
    28042805                  lpmmi->ptMaxSize.x = MIN(GetSystemMetrics(SM_CXMAXIMIZED), lI->maxWidth);
    28052806                  lpmmi->ptMaxSize.y = MIN(GetSystemMetrics(SM_CYMAXIMIZED), lI->maxHeight);
    28062807
     
    1076010761    "draw a sub-string - if opaque is false, draw foreground only; otherwise, draw both
    1076110762     foreground and background characters.
    1076210763     If the coordinates are not integers, an error is triggered."
    10763 
    10764 %{  /* NOCONTEXT */
     10764%{  /* NOCONTEXT */
     10765  /* NOTICE:
     10766   * A change here was forced by (an undocumented) limited internal display buffer.
     10767   * A check is needed to draw against such internal limit; then draw it chunk-by-chunk.
     10768   */
     10769
    1076510770    unsigned char *cp;
    1076610771    OBJ cls;
    10767     int i1, i2, l, n;
     10772    int i1, i2, n, l, toDisplay;
    1076810773    int nInstBytes;
    1076910774
     10775
    1077010776    if (__isExternalAddress(aGCId)
    1077110777     && __isNonNilObject(aString)
    1077210778     && __bothSmallInteger(index1, index2)
     
    1077710783        HDC hDC;
    1077810784        HFONT hOldFont;
    1077910785
     10786        /* Windows (as in 7 or newer) limits the string size for TextOut* to 3275 */
     10787        const int MAX_DISPLAY_BUFFER = 3275;
     10788
    1078010789        i1 = __intVal(index1) - 1;
    1078110790        i2 = __intVal(index2) - 1;
    1078210791        if ((i1 < 0) || (i2 < i1)) {
     
    1081310822#endif
    1081410823
    1081510824        cls = __qClass(aString);
    10816 
    1081710825        cp = __stringVal(aString);
    1081810826        l = i2 - i1 + 1;
    10819         if (l > 32758) {
    10820             /* Windows (as in XP) limits the string size for TextOut* to 32758 */
    10821             l = 32758;
    10822         }
     10827        toDisplay = l;
     10828
     10829        /* Set the current point to the reference point. */
     10830        SetTextAlign(hDC, TA_UPDATECP);
     10831        MoveToEx(hDC, pX, pY, NULL);
    1082310832
    1082410833        if (__isStringLike(aString)) {
    1082510834            n = __stringSize(aString);
    1082610835commonOutChars:
    1082710836            if (i2 < n) {
    10828                 cp += i1;
    10829                 CPRINTF(("string1: %s pos=%d/%d l=%d hDC=%x\n", cp, pX, pY,l,hDC));
    10830                 if (! TextOutA(hDC, pX, pY, (char *)cp, l)) {
    10831                     PRINTF(("WinWorkstation [warning]: TextOutA failed. [%d]\n", __LINE__));
    10832                     PRINTF(("WinWorkstation [warning]: lastError=%d x:%d y:%d len:%d\n", GetLastError(), pX, pY, l));
    10833                     goto error;
    10834                 }
     10837                cp += i1;
     10838                do {
     10839                    /* TA_UPDATECP used => pX, pY ignored */
     10840                    if (! TextOutA(hDC, 0, 0, (char *)cp, MIN(toDisplay, MAX_DISPLAY_BUFFER))) {
     10841                        PRINTF(("WinWorkstation [warning]: TextOutA failed. [%d]\n", __LINE__));
     10842                        PRINTF(("WinWorkstation [warning]: lastError=%d x:%d y:%d len:%d leftToShow=%d\n", GetLastError(), pX, pY, l, toDisplay));
     10843                        goto error;
     10844                    }
     10845                    cp += MAX_DISPLAY_BUFFER;
     10846                    toDisplay -= MAX_DISPLAY_BUFFER;
     10847                } while(toDisplay > 0);
    1083510848            }
    1083610849            goto ret;
    1083710850        }
     
    1084710860        /* Unicode */
    1084810861        if (__isWords(aString)) {
    1084910862            n = n / 2;
    10850             if (i2 < n) {
    10851                 WIDECHAR *w_cp = (WIDECHAR *)cp;
    10852                 w_cp += i1;
    10853                 if (! TextOutW(hDC, pX, pY, w_cp, l)) {
    10854                     PRINTF(("WinWorkstation [warning]: TextOutW failed. [%d]\n", __LINE__));
    10855                     PRINTF(("WinWorkstation [warning]: lastError=%d x:%d y:%d len:%d\n", GetLastError(), pX, pY, l));
    10856                 }
    10857                 goto ret;
    10858             }
     10863            WIDECHAR *w_cp = (WIDECHAR *)cp;
     10864            if (i2 < n){
     10865                w_cp += i1;
     10866                do {
     10867                    /* TA_UPDATECP used => pX, pY ignored */
     10868                    if (! TextOutW(hDC, 0, 0, w_cp, MIN(toDisplay, MAX_DISPLAY_BUFFER))) {
     10869                        PRINTF(("WinWorkstation [warning]: TextOutW failed. [%d]\n", __LINE__));
     10870                        PRINTF(("WinWorkstation [warning]: lastError=%d x:%d y:%d len:%d leftToShow=%d\n", GetLastError(), pX, pY, l, toDisplay));
     10871                        goto error;
     10872                    }
     10873                    w_cp += MAX_DISPLAY_BUFFER;
     10874                    toDisplay -= MAX_DISPLAY_BUFFER;
     10875                } while (toDisplay > 0);
     10876            }
     10877            goto ret;
    1085910878        }
    1086010879ret:;
    1086110880#if 0