mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2025-01-27 03:31:08 +00:00
Improved handling of multi-line strings:
- Centered/right-aligned string drawing now properly handles newlines - Measuring string width/height takes newlines into account - String height also takes V_RETURN8 into account - Cleaned up menu message code, removed now-redundant M_StringHeight
This commit is contained in:
parent
759ac6cf35
commit
66042ef8a1
3 changed files with 87 additions and 182 deletions
149
src/m_menu.c
149
src/m_menu.c
|
@ -4957,22 +4957,6 @@ static void M_DrawCenteredMenu(void)
|
|||
}
|
||||
}
|
||||
|
||||
//
|
||||
// M_StringHeight
|
||||
//
|
||||
// Find string height from hu_font chars
|
||||
//
|
||||
static inline size_t M_StringHeight(const char *string)
|
||||
{
|
||||
size_t h = 8, i;
|
||||
|
||||
for (i = 0; i < strlen(string); i++)
|
||||
if (string[i] == '\n')
|
||||
h += 8;
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
// ==========================================================================
|
||||
// Extraneous menu patching functions
|
||||
// ==========================================================================
|
||||
|
@ -6099,56 +6083,16 @@ menu_t MessageDef =
|
|||
NULL
|
||||
};
|
||||
|
||||
|
||||
void M_StartMessage(const char *string, void *routine,
|
||||
menumessagetype_t itemtype)
|
||||
void M_StartMessage(const char *string, void *routine, menumessagetype_t itemtype)
|
||||
{
|
||||
size_t max = 0, start = 0, i, strlines;
|
||||
static char *message = NULL;
|
||||
static char *message;
|
||||
Z_Free(message);
|
||||
message = Z_StrDup(string);
|
||||
message = V_WordWrap(0,0,V_ALLOWLOWERCASE,string);
|
||||
DEBFILE(message);
|
||||
|
||||
// Rudementary word wrapping.
|
||||
// Simple and effective. Does not handle nonuniform letter sizes, colors, etc. but who cares.
|
||||
strlines = 0;
|
||||
for (i = 0; message[i]; i++)
|
||||
{
|
||||
if (message[i] == ' ')
|
||||
{
|
||||
start = i;
|
||||
max += 4;
|
||||
}
|
||||
else if (message[i] == '\n')
|
||||
{
|
||||
strlines = i;
|
||||
start = 0;
|
||||
max = 0;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
max += 8;
|
||||
|
||||
// Start trying to wrap if presumed length exceeds the screen width.
|
||||
if (max >= BASEVIDWIDTH && start > 0)
|
||||
{
|
||||
message[start] = '\n';
|
||||
max -= (start-strlines)*8;
|
||||
strlines = start;
|
||||
start = 0;
|
||||
}
|
||||
}
|
||||
|
||||
start = 0;
|
||||
max = 0;
|
||||
|
||||
M_StartControlPanel(); // can't put menuactive to true
|
||||
|
||||
if (currentMenu == &MessageDef) // Prevent recursion
|
||||
MessageDef.prevMenu = &MainDef;
|
||||
else
|
||||
MessageDef.prevMenu = currentMenu;
|
||||
|
||||
MessageDef.prevMenu = (currentMenu == &MessageDef) ? &MainDef : currentMenu; // Prevent recursion
|
||||
MessageDef.menuitems[0].text = message;
|
||||
MessageDef.menuitems[0].alphaKey = (UINT8)itemtype;
|
||||
if (!routine && itemtype != MM_NOTHING) itemtype = MM_NOTHING;
|
||||
|
@ -6167,51 +6111,17 @@ void M_StartMessage(const char *string, void *routine,
|
|||
MessageDef.menuitems[0].itemaction = routine;
|
||||
break;
|
||||
}
|
||||
//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;
|
||||
}
|
||||
}
|
||||
MessageDef.x = (INT16)((BASEVIDWIDTH - V_StringWidth(message, 0)-32)/2);
|
||||
MessageDef.y = (INT16)((BASEVIDHEIGHT - V_StringHeight(message, V_RETURN8))/2);
|
||||
|
||||
if (i == strlen(message+start))
|
||||
start += i;
|
||||
}
|
||||
|
||||
MessageDef.x = (INT16)((BASEVIDWIDTH - 8*max-16)/2);
|
||||
MessageDef.y = (INT16)((BASEVIDHEIGHT - M_StringHeight(message))/2);
|
||||
|
||||
MessageDef.lastOn = (INT16)((strlines<<8)+max);
|
||||
|
||||
//M_SetupNextMenu();
|
||||
currentMenu = &MessageDef;
|
||||
itemOn = 0;
|
||||
}
|
||||
|
||||
#define MAXMSGLINELEN 256
|
||||
|
||||
static void M_DrawMessageMenu(void)
|
||||
{
|
||||
INT32 y = currentMenu->y;
|
||||
size_t i, start = 0;
|
||||
INT16 max;
|
||||
char string[MAXMSGLINELEN];
|
||||
INT32 mlines;
|
||||
const char *msg = currentMenu->menuitems[0].text;
|
||||
|
||||
mlines = currentMenu->lastOn>>8;
|
||||
max = (INT16)((UINT8)(currentMenu->lastOn & 0xFF)*8);
|
||||
|
||||
// hack: draw RA background in RA menus
|
||||
if (gamestate == GS_TIMEATTACK)
|
||||
{
|
||||
|
@ -6235,51 +6145,8 @@ static void M_DrawMessageMenu(void)
|
|||
V_DrawFadeScreen(0xFF00, curfadevalue);
|
||||
}
|
||||
|
||||
M_DrawTextBox(currentMenu->x, y - 8, (max+7)>>3, mlines);
|
||||
|
||||
while (*(msg+start))
|
||||
{
|
||||
size_t len = strlen(msg+start);
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
if (*(msg+start+i) == '\n')
|
||||
{
|
||||
memset(string, 0, MAXMSGLINELEN);
|
||||
if (i >= MAXMSGLINELEN)
|
||||
{
|
||||
CONS_Printf("M_DrawMessageMenu: too long segment in %s\n", msg);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
strncpy(string,msg+start, i);
|
||||
string[i] = '\0';
|
||||
start += i;
|
||||
i = (size_t)-1; //added : 07-02-98 : damned!
|
||||
start++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == strlen(msg+start))
|
||||
{
|
||||
if (i >= MAXMSGLINELEN)
|
||||
{
|
||||
CONS_Printf("M_DrawMessageMenu: too long segment in %s\n", msg);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(string, msg + start);
|
||||
start += i;
|
||||
}
|
||||
}
|
||||
|
||||
V_DrawString((BASEVIDWIDTH - V_StringWidth(string, 0))/2,y,V_ALLOWLOWERCASE,string);
|
||||
y += 8; //hu_font.chars[0]->height;
|
||||
}
|
||||
M_DrawTextBox(currentMenu->x, currentMenu->y - 8, 2+V_StringWidth(msg, 0)/8, V_StringHeight(msg, V_RETURN8)/8);
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, currentMenu->y, V_ALLOWLOWERCASE|V_RETURN8, msg);
|
||||
}
|
||||
|
||||
// default message handler
|
||||
|
|
114
src/v_video.c
114
src/v_video.c
|
@ -1990,10 +1990,7 @@ void V_DrawFontCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed, fi
|
|||
|
||||
flags = c & ~(V_CHARCOLORMASK | V_PARAMMASK);
|
||||
c &= 0x7f;
|
||||
if (lowercaseallowed)
|
||||
c -= FONTSTART;
|
||||
else
|
||||
c = toupper(c) - FONTSTART;
|
||||
c = (lowercaseallowed ? c : toupper(c)) - FONTSTART;
|
||||
if (c < 0 || c >= FONTSIZE || !font.chars[c])
|
||||
return;
|
||||
|
||||
|
@ -2009,8 +2006,7 @@ void V_DrawFontCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed, fi
|
|||
char *V_FontWordWrap(INT32 x, INT32 w, INT32 option, fixed_t scale, const char *string, fontdef_t font)
|
||||
{
|
||||
int c;
|
||||
size_t chw, i, lastusablespace = 0;
|
||||
size_t slen;
|
||||
size_t slen, chw, i, lastusablespace = 0;
|
||||
char *newstring = Z_StrDup(string);
|
||||
INT32 spacewidth = font.spacewidth, charwidth = 0;
|
||||
|
||||
|
@ -2048,10 +2044,7 @@ char *V_FontWordWrap(INT32 x, INT32 w, INT32 option, fixed_t scale, const char *
|
|||
continue;
|
||||
}
|
||||
|
||||
if (!(option & V_ALLOWLOWERCASE))
|
||||
c = toupper(c);
|
||||
c -= FONTSTART;
|
||||
|
||||
c = (option & V_ALLOWLOWERCASE ? c : toupper(c)) - FONTSTART;
|
||||
if (c < 0 || c >= FONTSIZE || !font.chars[c])
|
||||
{
|
||||
chw = spacewidth;
|
||||
|
@ -2148,20 +2141,11 @@ void V_DrawFontStringAtFixed(fixed_t x, fixed_t y, INT32 option, fixed_t pscale,
|
|||
if (*ch == '\n')
|
||||
{
|
||||
cx = x;
|
||||
|
||||
if (option & V_RETURN8)
|
||||
cy += FixedMul((8<<FRACBITS), dupy);
|
||||
else
|
||||
cy += FixedMul((font.linespacing<<FRACBITS), dupy);
|
||||
|
||||
cy += FixedMul(((option & V_RETURN8) ? 8 : font.linespacing)<<FRACBITS, dupy);
|
||||
continue;
|
||||
}
|
||||
|
||||
c = *ch;
|
||||
if (!lowercase)
|
||||
c = toupper(c);
|
||||
c -= FONTSTART;
|
||||
|
||||
c = (lowercase ? *ch : toupper(*ch)) - FONTSTART;
|
||||
if (c < 0 || c >= FONTSIZE || !font.chars[c])
|
||||
{
|
||||
cx += FixedMul((spacewidth<<FRACBITS), dupx);
|
||||
|
@ -2190,16 +2174,58 @@ void V_DrawFontStringAtFixed(fixed_t x, fixed_t y, INT32 option, fixed_t pscale,
|
|||
}
|
||||
}
|
||||
|
||||
#define MAXLINELEN 256
|
||||
void V_DrawAlignedFontStringAtFixed(fixed_t x, fixed_t y, INT32 option, fixed_t pscale, fixed_t vscale, const char *string, fontdef_t font, boolean center)
|
||||
{
|
||||
char line[MAXLINELEN];
|
||||
size_t i, start = 0;
|
||||
fixed_t lx = x, ly = y;
|
||||
|
||||
while (*(string+start))
|
||||
{
|
||||
for (i = 0; i < strlen(string+start); i++)
|
||||
{
|
||||
if (*(string+start+i) == '\n')
|
||||
{
|
||||
memset(line, 0, MAXLINELEN);
|
||||
if (i >= MAXLINELEN)
|
||||
{
|
||||
CONS_Printf("V_DrawAlignedFontStringAtFixed: a line exceeds max. length %d (string: %s)\n", MAXLINELEN, string);
|
||||
return;
|
||||
}
|
||||
strncpy(line,string + start, i);
|
||||
line[i] = '\0';
|
||||
start += i + 1;
|
||||
i = (size_t)-1; //added : 07-02-98 : damned!
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == strlen(string + start))
|
||||
{
|
||||
if (i >= MAXLINELEN)
|
||||
{
|
||||
CONS_Printf("V_DrawAlignedFontStringAtFixed: a line exceeds max. length %d (string: %s)\n", MAXLINELEN, string);
|
||||
return;
|
||||
}
|
||||
strcpy(line, string + start);
|
||||
start += i;
|
||||
}
|
||||
|
||||
lx = x - (V_FontStringWidth(line, option, font)*pscale) / (center ? 2 : 1);
|
||||
V_DrawFontStringAtFixed(lx, ly, option, pscale, vscale, line, font);
|
||||
ly += FixedMul(((option & V_RETURN8) ? 8 : font.linespacing)<<FRACBITS, vscale);
|
||||
}
|
||||
}
|
||||
|
||||
void V_DrawCenteredFontStringAtFixed(fixed_t x, fixed_t y, INT32 option, fixed_t pscale, fixed_t vscale, const char *string, fontdef_t font)
|
||||
{
|
||||
x -= (V_FontStringWidth(string, option, font)*pscale)/2;
|
||||
V_DrawFontStringAtFixed(x, y, option, pscale, vscale, string, font);
|
||||
V_DrawAlignedFontStringAtFixed(x, y, option, pscale, vscale, string, font, true);
|
||||
}
|
||||
|
||||
void V_DrawRightAlignedFontStringAtFixed(fixed_t x, fixed_t y, INT32 option, fixed_t pscale, fixed_t vscale, const char *string, fontdef_t font)
|
||||
{
|
||||
x -= V_FontStringWidth(string, option, font)*pscale;
|
||||
V_DrawFontStringAtFixed(x, y, option, pscale, vscale, string, font);
|
||||
V_DrawAlignedFontStringAtFixed(x, y, option, pscale, vscale, string, font, false);
|
||||
}
|
||||
|
||||
// Draws a tallnum. Replaces two functions in y_inter and st_stuff
|
||||
|
@ -2324,10 +2350,7 @@ static void V_DrawNameTagLine(INT32 x, INT32 y, INT32 option, fixed_t scale, UIN
|
|||
continue;
|
||||
}
|
||||
|
||||
c = toupper(*ch);
|
||||
c -= FONTSTART;
|
||||
|
||||
// character does not exist or is a space
|
||||
c = toupper(*ch) - FONTSTART;
|
||||
if (c < 0 || c >= FONTSIZE || !ntb_font.chars[c] || !nto_font.chars[c])
|
||||
{
|
||||
cx += FixedMul((ntb_font.spacewidth * dupx)*FRACUNIT, scale);
|
||||
|
@ -2464,9 +2487,8 @@ INT32 V_CountNameTagLines(const char *string)
|
|||
//
|
||||
INT32 V_FontStringWidth(const char *string, INT32 option, fontdef_t font)
|
||||
{
|
||||
INT32 c, w = 0;
|
||||
INT32 c, w = 0, wline = 0;
|
||||
INT32 spacewidth = font.spacewidth, charwidth = 0;
|
||||
size_t i;
|
||||
|
||||
switch (option & V_SPACINGMASK)
|
||||
{
|
||||
|
@ -2482,16 +2504,24 @@ INT32 V_FontStringWidth(const char *string, INT32 option, fontdef_t font)
|
|||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < strlen(string); i++)
|
||||
for (size_t i = 0; i < strlen(string); i++)
|
||||
{
|
||||
if (string[i] == '\n')
|
||||
{
|
||||
if (wline < w) wline = w;
|
||||
w = 0;
|
||||
continue;
|
||||
}
|
||||
if (string[i] & 0x80)
|
||||
continue;
|
||||
c = ((option & V_ALLOWLOWERCASE ? string[i] : toupper(string[i])) - FONTSTART);
|
||||
|
||||
c = (option & V_ALLOWLOWERCASE ? string[i] : toupper(string[i])) - FONTSTART;
|
||||
if (c < 0 || c >= FONTSIZE || !font.chars[c])
|
||||
w += spacewidth;
|
||||
else
|
||||
w += (charwidth ? charwidth : (font.chars[c]->width)) + font.kerning;
|
||||
}
|
||||
w = max(wline, w);
|
||||
|
||||
if (option & (V_NOSCALESTART|V_NOSCALEPATCH))
|
||||
w *= vid.dupx;
|
||||
|
@ -2501,22 +2531,28 @@ INT32 V_FontStringWidth(const char *string, INT32 option, fontdef_t font)
|
|||
|
||||
// Find max string height from supplied font characters
|
||||
//
|
||||
INT32 V_FontStringHeight(const char *string, fontdef_t font)
|
||||
INT32 V_FontStringHeight(const char *string, INT32 option, fontdef_t font)
|
||||
{
|
||||
INT32 c, h = 0;
|
||||
size_t i;
|
||||
INT32 c, h = 0, result = 0;
|
||||
|
||||
for (i = 0; i < strlen(string); i++)
|
||||
for (size_t i = 0; i < strlen(string); i++)
|
||||
{
|
||||
c = string[i] - FONTSTART;
|
||||
c = (option & V_ALLOWLOWERCASE ? string[i] : toupper(string[i])) - FONTSTART;
|
||||
if (c < 0 || c >= FONTSIZE || !font.chars[c])
|
||||
{
|
||||
if (string[i] == '\n')
|
||||
{
|
||||
result += (option & V_RETURN8) ? 8 : font.linespacing;
|
||||
h = 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (font.chars[c]->height > h)
|
||||
h = font.chars[c]->height;
|
||||
}
|
||||
|
||||
return h;
|
||||
return result + h;
|
||||
}
|
||||
|
||||
boolean *heatshifter = NULL;
|
||||
|
|
|
@ -213,6 +213,7 @@ void V_DrawCenteredFontString(INT32 x, INT32 y, INT32 option, fixed_t pscale, fi
|
|||
void V_DrawRightAlignedFontString(INT32 x, INT32 y, INT32 option, fixed_t pscale, fixed_t vscale, const char *string, fontdef_t font);
|
||||
// Draw a string, using a supplied font and scale, at fixed_t coordinates.
|
||||
void V_DrawFontStringAtFixed(fixed_t x, fixed_t y, INT32 option, fixed_t pscale, fixed_t vscale, const char *string, fontdef_t font);
|
||||
void V_DrawAlignedFontStringAtFixed(fixed_t x, fixed_t y, INT32 option, fixed_t pscale, fixed_t vscale, const char *string, fontdef_t font, boolean center);
|
||||
void V_DrawCenteredFontStringAtFixed(fixed_t x, fixed_t y, INT32 option, fixed_t pscale, fixed_t vscale, const char *string, fontdef_t font);
|
||||
void V_DrawRightAlignedFontStringAtFixed(fixed_t x, fixed_t y, INT32 option, fixed_t pscale, fixed_t vscale, const char *string, fontdef_t font);
|
||||
|
||||
|
@ -266,7 +267,7 @@ INT32 V_CountNameTagLines(const char *string);
|
|||
|
||||
// Find string width or height from supplied font chars
|
||||
INT32 V_FontStringWidth(const char *string, INT32 option, fontdef_t font);
|
||||
INT32 V_FontStringHeight(const char *string, fontdef_t font);
|
||||
INT32 V_FontStringHeight(const char *string, INT32 option, fontdef_t font);
|
||||
|
||||
// Defines for old string width functions.
|
||||
#define V_StringWidth(str,o) V_FontStringWidth(str,o,hu_font)
|
||||
|
@ -276,7 +277,8 @@ INT32 V_FontStringHeight(const char *string, fontdef_t font);
|
|||
#define V_CreditStringWidth(str) V_FontStringWidth(str,0,cred_font)
|
||||
#define V_NameTagWidth(str) V_FontStringWidth(str,0,ntb_font)
|
||||
#define V_LevelNameWidth(str) V_FontStringWidth(str,V_ALLOWLOWERCASE,lt_font)
|
||||
#define V_LevelNameHeight(str) V_FontStringHeight(str,lt_font)
|
||||
#define V_LevelNameHeight(str) V_FontStringHeight(str,0,lt_font)
|
||||
#define V_StringHeight(str,o) V_FontStringHeight(str,o,hu_font)
|
||||
|
||||
void V_DoPostProcessor(INT32 view, postimg_t type, INT32 param);
|
||||
|
||||
|
|
Loading…
Reference in a new issue