From 58c0ceec95bd44dfc0c2a54659d3595605eb15dd Mon Sep 17 00:00:00 2001 From: Buginator Date: Mon, 13 Sep 2010 23:53:06 +0000 Subject: [PATCH] Fix edit boxes so they correctly calculate the string's pixel borders. Motivation of this patch was because of some whiny guy on IRC. ;) git-svn-id: https://warzone2100.svn.sourceforge.net/svnroot/warzone2100/branches/2.3@11668 4a71c877-e1ca-e34f-864e-861f7616d084 (cherry picked from commit 81f07188a3693007621496ac9fa0c0e2e8b24b87) --- lib/widget/editbox.c | 118 ++++++++++++++++++++++++++----------------- 1 file changed, 73 insertions(+), 45 deletions(-) diff --git a/lib/widget/editbox.c b/lib/widget/editbox.c index d9c8b0afb..dbb1f2675 100644 --- a/lib/widget/editbox.c +++ b/lib/widget/editbox.c @@ -267,65 +267,93 @@ static void delCharLeft(utf_32_char *pBuffer, UDWORD *pPos) static void fitStringStart(utf_32_char *pBuffer, UDWORD boxWidth, UWORD *pCount, UWORD *pCharWidth) { UDWORD len; - UWORD printWidth, printChars, width; - utf_32_char *pCurr; + UWORD printChars = 0, pixelWidth = 0; + char *utf = NULL; + char *utf2 = NULL; - len = utf32len(pBuffer); - printWidth = 0; - printChars = 0; - pCurr = pBuffer; - - /* Find the number of characters that will fit in boxWidth */ - while (printChars < len) + utf = UTF32toUTF8(pBuffer, NULL); + if (!utf) { - width = (UWORD)(printWidth + iV_GetCharWidth(*pCurr)); - if (width > boxWidth - WEDB_XGAP*2) - { - /* We've got as many characters as will fit in the box */ - break; - } - printWidth = width; - printChars += 1; - pCurr += 1; + debug(LOG_ERROR, "Couldn't convert UTF32 to UTF8?"); + *pCount = *pCharWidth = 0; + return; } + len = strlen(utf); - /* Return the number of characters and their width */ - *pCount = printChars; - *pCharWidth = printWidth; + // We need to calculate the whole string's pixel size. + // From QuesoGLC's notes: additional processing like kerning creates strings of text whose dimensions are not directly + // related to the simple juxtaposition of individual glyph metrics. For example, the advance width of "VA" isn't the + // sum of the advances of "V" and "A" taken separately. + pixelWidth = iV_GetTextWidth(utf); + + // Find the number of characters that will fit in boxWidth + if (pixelWidth < boxWidth - (WEDB_XGAP*2 + WEDB_CURSORSIZE)) + { + *pCharWidth = pixelWidth; // the actual pixelWidth we use for the string + *pCount = len; // and the length of said string. + } + else + { + utf2 = utf; + do + { + pixelWidth = iV_GetTextWidth(utf2); + printChars++; + utf2[(len - printChars)] = 0; // keep chopping off end until it fits + } + while (pixelWidth > boxWidth - (WEDB_XGAP*2 + WEDB_CURSORSIZE) && printChars < len); + + *pCharWidth = pixelWidth; // the actual pixelWidth we use for the string + *pCount = len - printChars; // and the length of the new string. + } + free(utf); // release the utf buffer } /* Calculate how much of the end of a string can fit into the edit box */ static void fitStringEnd(utf_32_char *pBuffer, UDWORD boxWidth, UWORD *pStart, UWORD *pCount, UWORD *pCharWidth) { - UDWORD len; - UWORD printWidth, printChars, width; - utf_32_char *pCurr; + UDWORD len; + UWORD printChars = 0, pixelWidth = 0; + char *utf = NULL; + char *utf2 = NULL; - len = utf32len(pBuffer); - - pCurr = pBuffer + len - 1; - printChars = 0; - printWidth = 0; - - /* Find the number of characters that will fit in boxWidth */ - while (printChars < len) + utf = UTF32toUTF8(pBuffer, NULL); + if (!utf) { - width = (UWORD)(printWidth + iV_GetCharWidth(*pCurr)); - if (width > boxWidth - (WEDB_XGAP*2 + WEDB_CURSORSIZE)) - { - /* Got as many characters as will fit into the box */ - break; - } - printWidth = width; - printChars += 1; - pCurr -= 1; + debug(LOG_ERROR, "Couldn't convert UTF32 to UTF8?"); + *pCount = *pStart = *pCharWidth = 0; + return; } + len = strlen(utf); - /* Return the number of characters and their width */ - *pStart = (UWORD)(len - printChars); - *pCount = printChars; - *pCharWidth = printWidth; + // We need to calculate the whole string's pixel size. + // From QuesoGLC's notes: additional processing like kerning creates strings of text whose dimensions are not directly + // related to the simple juxtaposition of individual glyph metrics. For example, the advance width of "VA" isn't the + // sum of the advances of "V" and "A" taken separately. + pixelWidth = iV_GetTextWidth(utf); + + // Find the number of characters that will fit in boxWidth + if (pixelWidth < boxWidth - (WEDB_XGAP*2 + WEDB_CURSORSIZE)) + { + *pStart = 0 ; // nothing to trim + *pCharWidth = pixelWidth; // the actual pixelWidth we use for the string + *pCount = len; // and the length of said string. + } + else + { + utf2 = utf; + while (pixelWidth > boxWidth - (WEDB_XGAP*2 + WEDB_CURSORSIZE) && printChars < len) + { + utf2++; // new string is 1 char shorter [abc] is now [bc] + pixelWidth = iV_GetTextWidth(utf2); + printChars++; + } + *pStart = len - (len - printChars); // the starting position of the string to display + *pCharWidth = pixelWidth; // the actual pixelWidth we use for the string + *pCount = len - printChars; // and the length of the new string. + } + free(utf); // release the utf buffer }