summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorrubidium <rubidium@openttd.org>2009-10-13 20:19:34 +0000
committerrubidium <rubidium@openttd.org>2009-10-13 20:19:34 +0000
commit3bb1f4217dcb229c2e064e9f0e1d58a757474cc0 (patch)
treee06f35be311d13016ca78baa6bf5972cf9dff6de /src
parent313fb659433b0af187e04185d0b7875889548372 (diff)
downloadopenttd-3bb1f4217dcb229c2e064e9f0e1d58a757474cc0.tar.xz
(svn r17772) -Fix [FS#3264]: CJK languages don't have spaces, so for adding newlines (multi line strings) we need to (properly) handle the case when there are no spaces instead of truncating the string.
Diffstat (limited to 'src')
-rw-r--r--src/gfx.cpp57
-rw-r--r--src/gfx_func.h2
-rw-r--r--src/network/network_chat_gui.cpp2
3 files changed, 47 insertions, 14 deletions
diff --git a/src/gfx.cpp b/src/gfx.cpp
index 328e6da1c..8b9c09360 100644
--- a/src/gfx.cpp
+++ b/src/gfx.cpp
@@ -619,12 +619,13 @@ int DrawString(int left, int right, int top, StringID str, TextColour colour, St
* starting with index 0 is the real string end.
*
* @param str string to check and correct for length restrictions
+ * @param last the last valid location (for '\0') in the buffer of str
* @param maxw the maximum width the string can have on one line
* @return return a 32bit wide number consisting of 2 packed values:
* 0 - 15 the number of lines ADDED to the string
* 16 - 31 the fontsize in which the length calculation was done at
*/
-uint32 FormatStringLinebreaks(char *str, int maxw)
+uint32 FormatStringLinebreaks(char *str, const char *last, int maxw)
{
FontSize size = _cur_fontsize;
int num = 0;
@@ -632,6 +633,7 @@ uint32 FormatStringLinebreaks(char *str, int maxw)
assert(maxw > 0);
for (;;) {
+ /* The character *after* the last space. */
char *last_space = NULL;
int w = 0;
@@ -641,18 +643,49 @@ uint32 FormatStringLinebreaks(char *str, int maxw)
if (IsWhitespace(c)) last_space = str;
if (IsPrintable(c)) {
- w += GetCharacterWidth(size, c);
- /* string is longer than maximum width so we need to decide what to
- * do. We can do two things:
- * 1. If no whitespace was found at all up until now (on this line) then
- * we will truncate the string and bail out.
- * 2. In all other cases force a linebreak at the last seen whitespace */
+ int char_w = GetCharacterWidth(size, c);
+ w += char_w;
if (w > maxw) {
- if (last_space == NULL) {
- *Utf8PrevChar(str) = '\0';
+ /* The string is longer than maximum width so we need to decide
+ * what to do with it. */
+ if (w == char_w) {
+ /* The character is wider than allowed width; don't know
+ * what to do with this case... bail out! */
return num + (size << 16);
}
- str = last_space;
+ if (last_space == NULL) {
+ /* No space has been found. Just terminate at our current
+ * location. This usually happens for languages that do not
+ * require spaces in strings, like Chinese, Japanese and
+ * Korean. For other languages terminating mid-word might
+ * not be the best, but terminating the whole string instead
+ * of continuing the word at the next line is worse. */
+ str = Utf8PrevChar(str);
+ size_t len = strlen(str);
+ char *terminator = str + len;
+
+ /* The string location + length of the string + 1 for '\0'
+ * always fits; otherwise there's no trailing '\0' and it
+ * it not a valid string. */
+ assert(terminator <= last);
+ assert(*terminator == '\0');
+
+ /* If the string is too long we have to terminate it earlier. */
+ if (terminator == last) {
+ /* Get the 'begin' of the previous character and make that
+ * the terminator of the string; we truncate it 'early'. */
+ *Utf8PrevChar(terminator) = '\0';
+ len = strlen(str);
+ }
+ /* Also move the terminator! */
+ memmove(str + 1, str, len + 1);
+ *str = '\0';
+ /* str needs to point to the character *after* the last space */
+ str++;
+ } else {
+ /* A space is found; perfect place to terminate */
+ str = last_space;
+ }
break;
}
} else {
@@ -721,7 +754,7 @@ int GetStringHeight(StringID str, int maxw)
GetString(buffer, str, lastof(buffer));
- uint32 tmp = FormatStringLinebreaks(buffer, maxw);
+ uint32 tmp = FormatStringLinebreaks(buffer, lastof(buffer), maxw);
return GetMultilineStringHeight(buffer, GB(tmp, 0, 16));
}
@@ -761,7 +794,7 @@ int DrawStringMultiLine(int left, int right, int top, int bottom, StringID str,
char buffer[DRAW_STRING_BUFFER];
GetString(buffer, str, lastof(buffer));
- uint32 tmp = FormatStringLinebreaks(buffer, maxw);
+ uint32 tmp = FormatStringLinebreaks(buffer, lastof(buffer), maxw);
int num = GB(tmp, 0, 16);
int mt = GetCharacterHeight((FontSize)GB(tmp, 16, 16));
diff --git a/src/gfx_func.h b/src/gfx_func.h
index 5dbef7917..c8ba4c0d6 100644
--- a/src/gfx_func.h
+++ b/src/gfx_func.h
@@ -115,7 +115,7 @@ void DrawBox(int x, int y, int dx1, int dy1, int dx2, int dy2, int dx3, int dy3)
Dimension GetStringBoundingBox(const char *str);
Dimension GetStringBoundingBox(StringID strid);
-uint32 FormatStringLinebreaks(char *str, int maxw);
+uint32 FormatStringLinebreaks(char *str, const char *last, int maxw);
int GetStringHeight(StringID str, int maxw);
Dimension GetStringMultiLineBoundingBox(StringID str, const Dimension &suggestion);
void LoadStringWidthTable();
diff --git a/src/network/network_chat_gui.cpp b/src/network/network_chat_gui.cpp
index 8e9b4cc66..ef05ad931 100644
--- a/src/network/network_chat_gui.cpp
+++ b/src/network/network_chat_gui.cpp
@@ -86,7 +86,7 @@ void CDECL NetworkAddChatMessage(TextColour colour, uint8 duration, const char *
Utf8TrimString(buf, DRAW_STRING_BUFFER);
/* Force linebreaks for strings that are too long */
- lines = GB(FormatStringLinebreaks(buf, _chatmsg_box.width - 8), 0, 16) + 1;
+ lines = GB(FormatStringLinebreaks(buf, lastof(buf), _chatmsg_box.width - 8), 0, 16) + 1;
if (lines >= MAX_CHAT_MESSAGES) return;
msg_count = GetChatMessageCount();