Changeset - r13253:68f8abb2808c
[Not reviewed]
master
0 3 0
rubidium - 15 years ago 2009-10-13 20:19:34
rubidium@openttd.org
(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.
3 files changed with 47 insertions and 14 deletions:
0 comments (0 inline, 0 general)
src/gfx.cpp
Show inline comments
 
@@ -619,12 +619,13 @@ int DrawString(int left, int right, int 
 
 * 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,
 
	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,
 
			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 ma
 

	
 
	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 ri
 
	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));
src/gfx_func.h
Show inline comments
 
@@ -115,7 +115,7 @@ void DrawBox(int x, int y, int dx1, int 
 

	
 
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();
src/network/network_chat_gui.cpp
Show inline comments
 
@@ -86,7 +86,7 @@ void CDECL NetworkAddChatMessage(TextCol
 
	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();
0 comments (0 inline, 0 general)