diff --git a/src/f_finale.c b/src/f_finale.c index cd14941ef..64945543e 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -2281,7 +2281,24 @@ static void F_PreparePageText(char *pagetext) if (promptpagetext) Z_Free(promptpagetext); - promptpagetext = (pagetext && pagetext[0]) ? V_WordWrap(textx, textr, 0, pagetext) : Z_StrDup(""); + if (pagetext && pagetext[0]) + { + promptpagetext = Z_StrDup(pagetext); + V_ScaledWordWrap( + (textx - textr)<page[scenenum].textspeed ? textprompts[cutnum]->page[scenenum].textspeed : TICRATE/5; diff --git a/src/hu_stuff.c b/src/hu_stuff.c index d41bd60c9..70e59da1b 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -1270,56 +1270,21 @@ boolean HU_Responder(event_t *ev) //====================================================================== // Precompile a wordwrapped string to any given width. -// This is a muuuch better method than V_WORDWRAP. -// again stolen and modified a bit from video.c, don't mind me, will need to rearrange this one day. -// this one is simplified for the chat drawer. +// Now a wrapper for the chat drawer. static char *CHAT_WordWrap(INT32 x, INT32 w, INT32 option, const char *string) { - INT32 c; - size_t chw, i, lastusablespace = 0; - size_t slen; char *newstring = Z_StrDup(string); - INT32 spacewidth = (vid.width < 640) ? 8 : 4, charwidth = (vid.width < 640) ? 8 : 4; - slen = strlen(string); - x = 0; + fixed_t scale = (vid.width < 640) ? FRACUNIT : FRACUNIT/2; - for (i = 0; i < slen; ++i) - { - c = newstring[i]; - if ((UINT8)c >= 0x80 && (UINT8)c <= 0x8F) //color parsing! -Inuyasha 2.16.09 - continue; + V_ScaledWordWrap( + (w - x) << FRACBITS, + scale, scale, scale, + option, + HU_FONT, + newstring + ); - if (c == '\n') - { - x = 0; - lastusablespace = 0; - continue; - } - - if (!!(option & V_FORCEUPPERCASE)) - c = toupper(c); - c -= HU_FONTSTART; - - if (c < 0 || c >= HU_FONTSIZE || !fontv[HU_FONT].font[c]) - { - chw = spacewidth; - lastusablespace = i; - } - else - chw = charwidth; - - x += chw; - - if (lastusablespace != 0 && x > w) - { - //CONS_Printf("Wrap at index %d\n", i); - newstring[lastusablespace] = '\n'; - i = lastusablespace+1; - lastusablespace = 0; - x = 0; - } - } return newstring; } diff --git a/src/m_cond.c b/src/m_cond.c index 417b554a9..f2c84d153 100644 --- a/src/m_cond.c +++ b/src/m_cond.c @@ -1515,7 +1515,7 @@ char *M_BuildConditionSetString(UINT16 unlockid) size_t len = 1024, worklen; static char message[1024] = ""; const char *work = NULL; - size_t max = 0, maxatstart = 0, start = 0, i; + size_t i; boolean stopasap = false; message[0] = '\0'; @@ -1577,37 +1577,6 @@ char *M_BuildConditionSetString(UINT16 unlockid) } } - // Rudementary word wrapping. - // Simple and effective. Does not handle nonuniform letter sizes, etc. but who cares. - for (i = 0; message[i]; i++) - { - if (message[i] == ' ') - { - start = i; - max += 4; - maxatstart = max; - } - else if (message[i] == '\n') - { - start = 0; - max = 0; - maxatstart = 0; - continue; - } - else if (message[i] & 0x80) - continue; - else - max += 8; - - // Start trying to wrap if presumed length exceeds the space we have on-screen. - if (max >= DESCRIPTIONWIDTH && start > 0) - { - message[start] = '\n'; - max -= maxatstart; - start = 0; - } - } - // Valid sentence capitalisation handling. { // Finds the first : character, indicating the end of the prefix. @@ -1634,6 +1603,15 @@ char *M_BuildConditionSetString(UINT16 unlockid) } } + // Finally, do a clean wordwrap! + V_ScaledWordWrap( + DESCRIPTIONWIDTH << FRACBITS, + FRACUNIT, FRACUNIT, FRACUNIT, + 0, + HU_FONT, + message + ); + return message; } diff --git a/src/menus/transient/message-box.c b/src/menus/transient/message-box.c index 50ef95fb7..2d71bdca4 100644 --- a/src/menus/transient/message-box.c +++ b/src/menus/transient/message-box.c @@ -2,6 +2,7 @@ // \brief MESSAGE BOX (aka: a hacked, cobbled together menu) #include "../../k_menu.h" +#include "../../v_video.h" // V_ScaledWordWrap, HU_FONT #include "../../z_zone.h" // message prompt struct @@ -30,42 +31,18 @@ static inline size_t M_StringHeight(const char *string) void M_StartMessage(const char *header, const char *string, void (*routine)(INT32), menumessagetype_t itemtype, const char *confirmstr, const char *defaultstr) { const UINT8 pid = 0; - size_t max = 0, maxatstart = 0, start = 0, strlines, i; static char *message = NULL; Z_Free(message); message = Z_StrDup(string); DEBFILE(message); - // Rudementary word wrapping. - // Simple and effective. Does not handle nonuniform letter sizes, etc. but who cares. - for (i = 0; message[i]; i++) - { - if (message[i] == ' ') - { - start = i; - max += 4; - maxatstart = max; - } - else if (message[i] == '\n') - { - start = 0; - max = 0; - maxatstart = 0; - continue; - } - else if (message[i] & 0x80) - continue; - else - max += 8; - - // Start trying to wrap if presumed length exceeds the screen width. - if (max >= BASEVIDWIDTH && start > 0) - { - message[start] = '\n'; - max -= maxatstart; - start = 0; - } - } + V_ScaledWordWrap( + BASEVIDWIDTH << FRACBITS, + FRACUNIT, FRACUNIT, FRACUNIT, + 0, + HU_FONT, + message + ); strncpy(menumessage.message, string, MAXMENUMESSAGE); menumessage.header = header; @@ -77,9 +54,6 @@ void M_StartMessage(const char *header, const char *string, void (*routine)(INT3 menumessage.closing = 0; menumessage.active = true; - start = 0; - max = 0; - if (!routine) { menumessage.flags = MM_NOTHING; @@ -108,29 +82,7 @@ void M_StartMessage(const char *header, const char *string, void (*routine)(INT3 }*/ //added : 06-02-98: now draw a textbox around the message - // compute lenght max and the numbers of lines - for (strlines = 0; *(message+start); strlines++) - { - for (i = 0; i < strlen(message+start);i++) - { - if (*(message+start+i) == '\n') - { - if (i > max) - max = i; - start += i; - i = (size_t)-1; //added : 07-02-98 : damned! - start++; - break; - } - } - - if (i == strlen(message+start)) - { - start += i; - if (i > max) - max = i; - } - } + // oogh my god this was replaced in 2023 menumessage.x = (8 * MAXSTRINGLENGTH) - 1; menumessage.y = M_StringHeight(message); diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 0ab23236b..9c03b4010 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -305,6 +305,8 @@ static void I_ShowErrorMessageBox(const char *messagefordevelopers, boolean dump // Rudementary word wrapping. // Simple and effective. Does not handle nonuniform letter sizes, etc. but who cares. + // We can't use V_ScaledWordWrap, which this shares DNA with, because no guarantee + // string character graphics exist as reference in the error handler... { size_t max = 0, maxatstart = 0, start = 0, width = 0, i; diff --git a/src/v_video.cpp b/src/v_video.cpp index 3e85a9938..cc21a2303 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -2043,76 +2043,6 @@ void V_DrawTitleCardString(INT32 x, INT32 y, const char *str, INT32 flags, boole } } - -// Precompile a wordwrapped string to any given width. -// This is a muuuch better method than V_WORDWRAP. -char *V_WordWrap(INT32 x, INT32 w, INT32 option, const char *string) -{ - int c; - size_t chw, i, lastusablespace = 0; - size_t slen; - char *newstring = Z_StrDup(string); - INT32 spacewidth = 4, charwidth = 0; - - slen = strlen(string); - - if (w == 0) - w = BASEVIDWIDTH; - w -= x; - x = 0; - - switch (option & V_SPACINGMASK) - { - case V_MONOSPACE: - spacewidth = 8; - /* FALLTHRU */ - case V_OLDSPACING: - charwidth = 8; - break; - case V_6WIDTHSPACE: - spacewidth = 6; - default: - break; - } - - for (i = 0; i < slen; ++i) - { - c = newstring[i]; - if ((UINT8)c & 0x80) //color parsing! -Inuyasha 2.16.09 - continue; - - if (c == '\n') - { - x = 0; - lastusablespace = 0; - continue; - } - - if (!!(option & V_FORCEUPPERCASE)) - c = toupper(c); - c -= HU_FONTSTART; - - if (c < 0 || c >= HU_FONTSIZE || !fontv[HU_FONT].font[c]) - { - chw = spacewidth; - lastusablespace = i; - } - else - chw = (charwidth ? charwidth : fontv[HU_FONT].font[c]->width); - - x += chw; - - if (lastusablespace != 0 && x > w) - { - newstring[lastusablespace] = '\n'; - i = lastusablespace; - lastusablespace = 0; - x = 0; - } - } - return newstring; -} - static inline fixed_t FixedCharacterDim( fixed_t scale, fixed_t chw, @@ -2684,6 +2614,136 @@ fixed_t V_StringScaledWidth( return fullwidth; } +// Modify a string to wordwrap at any given width. +void V_ScaledWordWrap( + fixed_t w, + fixed_t scale, + fixed_t spacescale, + fixed_t lfscale, + INT32 flags, + int fontno, + char *newstring) +{ + INT32 hchw;/* half-width for centering */ + + INT32 dupx; + + font_t *font; + + boolean uppercase; + + fixed_t cx; + fixed_t right; + + fixed_t cw; + + int c; + + uppercase = ((flags & V_FORCEUPPERCASE) == V_FORCEUPPERCASE); + flags &= ~(V_FLIP);/* These two (V_FORCEUPPERCASE) share a bit. */ + + font = &fontv[fontno]; + + fontspec_t fontspec; + + V_GetFontSpecification(fontno, flags, &fontspec); + + hchw = fontspec.chw >> 1; + + fontspec.chw <<= FRACBITS; + fontspec.spacew <<= FRACBITS; + +#define Mul( id, scale ) ( id = FixedMul (scale, id) ) + Mul (fontspec.chw, scale); + Mul (fontspec.spacew, scale); + Mul (fontspec.lfh, scale); + + Mul (fontspec.spacew, spacescale); + Mul (fontspec.lfh, lfscale); +#undef Mul + + if (( flags & V_NOSCALESTART )) + { + dupx = vid.dupx; + + hchw *= dupx; + + fontspec.chw *= dupx; + fontspec.spacew *= dupx; + fontspec.lfh *= vid.dupy; + } + else + { + dupx = 1; + } + + cx = 0; + right = 0; + + size_t i = 0, start = 0; + fixed_t cxatstart = 0; + + for (; ( c = newstring[i] ); ++i) + { + switch (c) + { + case '\n': + cx = 0; + cxatstart = 0; + start = 0; + break; + default: + if (( c & 0x80 )) + continue; + + if (uppercase) + { + c = toupper(c); + } + else if (V_CharacterValid(font, c - font->start) == false) + { + // Try the other case if it doesn't exist + if (c >= 'A' && c <= 'Z') + { + c = tolower(c); + } + else if (c >= 'a' && c <= 'z') + { + c = toupper(c); + } + } + + c -= font->start; + if (V_CharacterValid(font, c) == true) + { + cw = SHORT (font->font[c]->width) * dupx; + + // How bunched dims work is by incrementing cx slightly less than a full character width. + // This causes the next character to be drawn overlapping the previous. + // We need to count the full width to get the rightmost edge of the string though. + right = cx + (cw * scale); + + (*fontspec.dim_fn)(scale, fontspec.chw, hchw, dupx, &cw); + cx += cw; + } + else + { + right = (cx += fontspec.spacew); + cxatstart = cx; + start = i; + } + } + + // Start trying to wrap if presumed length exceeds the space we have on-screen. + if (start != 0 && right > w) + { + newstring[start] = '\n'; + cx -= cxatstart; + start = 0; + } + } +} + void V_DrawCenteredString(INT32 x, INT32 y, INT32 option, const char *string) { x -= V_StringWidth(string, option)/2; diff --git a/src/v_video.h b/src/v_video.h index eeaf5d288..fc7afac33 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -273,9 +273,6 @@ UINT8 *V_GetStringColormap(INT32 colorflags); INT32 V_LevelNameHeight(const char *string); -// wordwrap a string using the hu_font -char *V_WordWrap(INT32 x, INT32 w, INT32 option, const char *string); - // draw a string using a font void V_DrawStringScaled( fixed_t x, @@ -296,6 +293,15 @@ fixed_t V_StringScaledWidth( int fontno, const char *s); +void V_ScaledWordWrap( + fixed_t w, + fixed_t scale, + fixed_t spacescale, + fixed_t lfscale, + INT32 flags, + int fontno, + char *newstring); + // draw a string using the hu_font #define V_DrawString( x,y,option,string ) \ V__DrawDupxString (x,y,FRACUNIT,option,NULL,HU_FONT,string)