summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gfx.c61
-rw-r--r--gfx.h1
2 files changed, 44 insertions, 18 deletions
diff --git a/gfx.c b/gfx.c
index 8ffb5de59..749131a67 100644
--- a/gfx.c
+++ b/gfx.c
@@ -415,41 +415,66 @@ void DrawStringCenterUnderlineTruncated(int xl, int xr, int y, StringID str, uin
GfxFillRect((xl + xr - w) / 2, y + 10, (xl + xr + w) / 2, y + 10, _string_colorremap[1]);
}
-static uint32 FormatStringLinebreaks(char *str, int maxw)
+/** 'Correct' a string to a maximum length. Longer strings will be cut into
+ * additional lines at whitespace characters if possible. The string parameter
+ * is modified with terminating characters mid-string which are the
+ * placeholders for the newlines.<br/>
+ * The string WILL be truncated if there was no whitespace for the current
+ * line's maximum width.
+ *
+ * @note To know if the the terminating '\0' is the string end or just a
+ * newline, the returned 'num' value should be consulted. The num'th '\0',
+ * starting with index 0 is the real string end.
+ *
+ * @param str string to check and correct for length restrictions
+ * @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)
{
- int num = 0;
FontSize size = _cur_fontsize;
- int w;
- char *last_space;
- byte c;
+ int num = 0;
+
+ assert(maxw > 0);
for (;;) {
- w = 0;
- last_space = NULL;
+ char *last_space = NULL;
+ int w = 0;
for (;;) {
- c = *str++;
+ byte c = *str++;
+ /* whitespace is where we will insert the line-break */
if (c == ASCII_LETTERSTART) last_space = str;
if (c >= ASCII_LETTERSTART) {
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 */
if (w > maxw) {
- str = last_space;
- if (str == NULL)
+ if (last_space == NULL) {
+ str[-1] = '\0';
return num + (size << 16);
+ }
+ str = last_space;
break;
}
} else {
- if (c == 0) return num + (size << 16);
- if (c == ASCII_NL) break;
-
- if (c == ASCII_SETX) str++;
- else if (c == ASCII_SETXY) str += 2;
- else if (c == ASCII_TINYFONT) size = FS_SMALL;
- else if (c == ASCII_BIGFONT) size = FS_LARGE;
+ switch (c) {
+ case '\0': return num + (size << 16); break;
+ case ASCII_SETX: str++; break;
+ case ASCII_SETXY: str +=2; break;
+ case ASCII_TINYFONT: size = FS_SMALL; break;
+ case ASCII_BIGFONT: size = FS_LARGE; break;
+ case ASCII_NL: goto end_of_inner_loop;
+ }
}
}
-
+end_of_inner_loop:
+ /* string didn't fit on line, so 'dummy' terminate and increase linecount */
num++;
str[-1] = '\0';
}
diff --git a/gfx.h b/gfx.h
index 0976f4a0e..0d63d2287 100644
--- a/gfx.h
+++ b/gfx.h
@@ -68,6 +68,7 @@ void GfxFillRect(int left, int top, int right, int bottom, int color);
void GfxDrawLine(int left, int top, int right, int bottom, int color);
BoundingRect GetStringBoundingBox(const char *str);
+uint32 FormatStringLinebreaks(char *str, int maxw);
void LoadStringWidthTable(void);
void DrawStringMultiCenter(int x, int y, StringID str, int maxw);
uint DrawStringMultiLine(int x, int y, StringID str, int maxw);