- use a saner data structure to store the BrokenLines.

Calling the old method with a pointer to an array of unspecified length 'dirty' would be an understatement.
Now it uses a TArray to store the single elements
This commit is contained in:
Christoph Oelckers 2018-10-31 19:13:54 +01:00
parent b911bbc424
commit 0d54d335c4
15 changed files with 62 additions and 135 deletions

View File

@ -1194,13 +1194,12 @@ static void PrintSecretString(const char *string, bool thislevel)
else colstr = TEXTCOLOR_GREEN; else colstr = TEXTCOLOR_GREEN;
} }
} }
FBrokenLines *brok = V_BreakLines(ConFont, screen->GetWidth()*95/100, string); auto brok = V_BreakLines(ConFont, screen->GetWidth()*95/100, string);
for (int k = 0; brok[k].Width >= 0; k++) for (int k = 0; brok[k].Width >= 0; k++)
{ {
Printf("%s%s\n", colstr, brok[k].Text.GetChars()); Printf("%s%s\n", colstr, brok[k].Text.GetChars());
} }
V_FreeBrokenLines(brok);
} }
} }

View File

@ -732,8 +732,8 @@ void FNotifyBuffer::Shift(int maxlines)
void FNotifyBuffer::AddString(int printlevel, FString source) void FNotifyBuffer::AddString(int printlevel, FString source)
{ {
FBrokenLines *lines; TArray<FBrokenLines> lines;
int i, width; int width;
if ((printlevel != 128 && !show_messages) || if ((printlevel != 128 && !show_messages) ||
source.IsEmpty() || source.IsEmpty() ||
@ -764,14 +764,14 @@ void FNotifyBuffer::AddString(int printlevel, FString source)
} }
} }
if (lines == NULL) if (lines.Size() == 0)
return; return;
for (i = 0; lines[i].Width >= 0; i++) for (auto &line : lines)
{ {
FNotifyText newline; FNotifyText newline;
newline.Text = lines[i].Text; newline.Text = line.Text;
newline.TimeOut = gametic + int(con_notifytime * TICRATE); newline.TimeOut = gametic + int(con_notifytime * TICRATE);
newline.PrintLevel = printlevel; newline.PrintLevel = printlevel;
if (AddType == NEWLINE || Text.Size() == 0) if (AddType == NEWLINE || Text.Size() == 0)
@ -789,9 +789,6 @@ void FNotifyBuffer::AddString(int printlevel, FString source)
AddType = NEWLINE; AddType = NEWLINE;
} }
V_FreeBrokenLines (lines);
lines = NULL;
switch (source[source.Len()-1]) switch (source[source.Len()-1])
{ {
case '\r': AddType = REPLACELINE; break; case '\r': AddType = REPLACELINE; break;
@ -1185,22 +1182,22 @@ void C_DrawConsole ()
// No more enqueuing because adding new text to the console won't touch the actual print data. // No more enqueuing because adding new text to the console won't touch the actual print data.
conbuffer->FormatText(ConFont, ConWidth / textScale); conbuffer->FormatText(ConFont, ConWidth / textScale);
unsigned int consolelines = conbuffer->GetFormattedLineCount(); unsigned int consolelines = conbuffer->GetFormattedLineCount();
FBrokenLines **blines = conbuffer->GetLines(); FBrokenLines *blines = conbuffer->GetLines();
FBrokenLines **printline = blines + consolelines - 1 - RowAdjust; FBrokenLines *printline = blines + consolelines - 1 - RowAdjust;
int bottomline = ConBottom / textScale - ConFont->GetHeight()*2 - 4; int bottomline = ConBottom / textScale - ConFont->GetHeight()*2 - 4;
ConsoleDrawing = true; ConsoleDrawing = true;
for(FBrokenLines **p = printline; p >= blines && lines > 0; p--, lines--) for(FBrokenLines *p = printline; p >= blines && lines > 0; p--, lines--)
{ {
if (textScale == 1) if (textScale == 1)
{ {
screen->DrawText(ConFont, CR_TAN, LEFTMARGIN, offset + lines * ConFont->GetHeight(), (*p)->Text, TAG_DONE); screen->DrawText(ConFont, CR_TAN, LEFTMARGIN, offset + lines * ConFont->GetHeight(), p->Text, TAG_DONE);
} }
else else
{ {
screen->DrawText(ConFont, CR_TAN, LEFTMARGIN, offset + lines * ConFont->GetHeight(), (*p)->Text, screen->DrawText(ConFont, CR_TAN, LEFTMARGIN, offset + lines * ConFont->GetHeight(), p->Text,
DTA_VirtualWidth, screen->GetWidth() / textScale, DTA_VirtualWidth, screen->GetWidth() / textScale,
DTA_VirtualHeight, screen->GetHeight() / textScale, DTA_VirtualHeight, screen->GetHeight() / textScale,
DTA_KeepRatio, true, TAG_DONE); DTA_KeepRatio, true, TAG_DONE);

View File

@ -74,11 +74,11 @@ FConsoleBuffer::~FConsoleBuffer()
void FConsoleBuffer::FreeBrokenText(unsigned start, unsigned end) void FConsoleBuffer::FreeBrokenText(unsigned start, unsigned end)
{ {
if (end > mBrokenConsoleText.Size()) end = mBrokenConsoleText.Size(); if (end > m_BrokenConsoleText.Size()) end = m_BrokenConsoleText.Size();
for (unsigned i = start; i < end; i++) for (unsigned i = start; i < end; i++)
{ {
if (mBrokenConsoleText[i] != NULL) V_FreeBrokenLines(mBrokenConsoleText[i]); m_BrokenConsoleText[i].Clear();
mBrokenConsoleText[i] = NULL; m_BrokenConsoleText[i].ShrinkToFit();
} }
} }
@ -260,7 +260,7 @@ void FConsoleBuffer::FormatText(FFont *formatfont, int displaywidth)
if (formatfont != mLastFont || displaywidth != mLastDisplayWidth || mBufferWasCleared) if (formatfont != mLastFont || displaywidth != mLastDisplayWidth || mBufferWasCleared)
{ {
FreeBrokenText(); FreeBrokenText();
mBrokenConsoleText.Clear(); m_BrokenConsoleText.Clear();
mBrokenStart.Clear(); mBrokenStart.Clear();
mBrokenStart.Push(0); mBrokenStart.Push(0);
mBrokenLines.Clear(); mBrokenLines.Clear();
@ -268,7 +268,7 @@ void FConsoleBuffer::FormatText(FFont *formatfont, int displaywidth)
mLastDisplayWidth = displaywidth; mLastDisplayWidth = displaywidth;
mBufferWasCleared = false; mBufferWasCleared = false;
} }
unsigned brokensize = mBrokenConsoleText.Size(); unsigned brokensize = m_BrokenConsoleText.Size();
if (brokensize == mConsoleText.Size()) if (brokensize == mConsoleText.Size())
{ {
// The last line got text appended. We have to wait until here to format it because // The last line got text appended. We have to wait until here to format it because
@ -276,21 +276,19 @@ void FConsoleBuffer::FormatText(FFont *formatfont, int displaywidth)
if (mLastLineNeedsUpdate) if (mLastLineNeedsUpdate)
{ {
brokensize--; brokensize--;
V_FreeBrokenLines(mBrokenConsoleText[brokensize]); m_BrokenConsoleText.Resize(brokensize);
mBrokenConsoleText.Resize(brokensize);
} }
} }
mBrokenLines.Resize(mBrokenStart[brokensize]); mBrokenLines.Resize(mBrokenStart[brokensize]);
mBrokenStart.Resize(brokensize); mBrokenStart.Resize(brokensize);
for (unsigned i = brokensize; i < mConsoleText.Size(); i++) for (unsigned i = brokensize; i < mConsoleText.Size(); i++)
{ {
FBrokenLines *bl = V_BreakLines(formatfont, displaywidth, mConsoleText[i], true); auto bl = V_BreakLines(formatfont, displaywidth, mConsoleText[i], true);
mBrokenConsoleText.Push(bl); m_BrokenConsoleText.Push(bl);
mBrokenStart.Push(mBrokenLines.Size()); mBrokenStart.Push(mBrokenLines.Size());
while (bl->Width != -1) for(auto &bline : bl)
{ {
mBrokenLines.Push(bl); mBrokenLines.Push(bline);
bl++;
} }
} }
mTextLines = mBrokenLines.Size(); mTextLines = mBrokenLines.Size();

View File

@ -49,9 +49,9 @@ enum EAddType
class FConsoleBuffer class FConsoleBuffer
{ {
TArray<FString> mConsoleText; TArray<FString> mConsoleText;
TArray<FBrokenLines *> mBrokenConsoleText; // This holds the structures returned by V_BreakLines and is used for memory management. TArray<TArray<FBrokenLines>> m_BrokenConsoleText; // This holds the structures returned by V_BreakLines and is used for memory management.
TArray<unsigned int> mBrokenStart; TArray<unsigned int> mBrokenStart;
TArray<FBrokenLines *> mBrokenLines; // This holds the single lines, indexed by mBrokenStart and is used for printing. TArray<FBrokenLines> mBrokenLines; // This holds the single lines, indexed by mBrokenStart and is used for printing.
FILE * mLogFile; FILE * mLogFile;
EAddType mAddType; EAddType mAddType;
int mTextLines; int mTextLines;
@ -80,6 +80,6 @@ public:
mConsoleText.Clear(); mConsoleText.Clear();
} }
int GetFormattedLineCount() { return mTextLines; } int GetFormattedLineCount() { return mTextLines; }
FBrokenLines **GetLines() { return &mBrokenLines[0]; } FBrokenLines *GetLines() { return &mBrokenLines[0]; }
}; };

View File

@ -194,7 +194,6 @@ DHUDMessage::DHUDMessage (FFont *font, const char *text, float x, float y, int h
WrapWidth = 0; WrapWidth = 0;
HandleAspect = true; HandleAspect = true;
Top = y; Top = y;
Lines = NULL;
HoldTics = (int)(holdTime * TICRATE); HoldTics = (int)(holdTime * TICRATE);
Tics = 0; Tics = 0;
TextColor = textColor; TextColor = textColor;
@ -215,11 +214,6 @@ DHUDMessage::DHUDMessage (FFont *font, const char *text, float x, float y, int h
void DHUDMessage::OnDestroy() void DHUDMessage::OnDestroy()
{ {
if (Lines)
{
V_FreeBrokenLines (Lines);
Lines = NULL;
}
if (SourceText != NULL) if (SourceText != NULL)
{ {
delete[] SourceText; delete[] SourceText;
@ -260,7 +254,6 @@ void DHUDMessage::Serialize(FSerializer &arc)
if (arc.isReading()) if (arc.isReading())
{ {
Lines = NULL;
ResetText(SourceText); ResetText(SourceText);
} }
} }
@ -329,24 +322,16 @@ void DHUDMessage::ResetText (const char *text)
width = SCREENWIDTH / active_con_scaletext(); width = SCREENWIDTH / active_con_scaletext();
} }
if (Lines != NULL)
{
V_FreeBrokenLines (Lines);
}
Lines = V_BreakLines (Font, NoWrap ? INT_MAX : width, (uint8_t *)text); Lines = V_BreakLines (Font, NoWrap ? INT_MAX : width, (uint8_t *)text);
NumLines = 0; NumLines = Lines.Size();
Width = 0; Width = 0;
Height = 0; Height = 0;
if (Lines) for (auto &line : Lines)
{ {
for (; Lines[NumLines].Width >= 0; NumLines++) Height += Font->GetHeight ();
{ Width = MAX<int> (Width, line.Width);
Height += Font->GetHeight ();
Width = MAX<int> (Width, Lines[NumLines].Width);
}
} }
} }

View File

@ -133,7 +133,7 @@ public:
} }
protected: protected:
FBrokenLines *Lines; TArray<FBrokenLines> Lines;
int Width, Height, NumLines; int Width, Height, NumLines;
float Left, Top; float Left, Top;
bool CenterX, NoWrap; bool CenterX, NoWrap;

View File

@ -686,12 +686,11 @@ class CommandDrawString : public SBarInfoCommand
{ {
if(lineBreaks) if(lineBreaks)
{ {
FBrokenLines *lines = V_BreakLines(font, breakWidth, str.GetChars()); auto lines = V_BreakLines(font, breakWidth, str.GetChars());
for(int i = 0;lines[i].Width >= 0;i++) for(unsigned i = 0; i < lines.Size();i++)
{ {
statusBar->DrawString(font, lines[i].Text, x, y+i*(font->GetHeight()+4), block->XOffset(), block->YOffset(), block->Alpha(), block->FullScreenOffsets(), translation, spacing, shadow, shadowX, shadowY); statusBar->DrawString(font, lines[i].Text, x, y+i*(font->GetHeight()+4), block->XOffset(), block->YOffset(), block->Alpha(), block->FullScreenOffsets(), translation, spacing, shadow, shadowX, shadowY);
} }
V_FreeBrokenLines(lines);
} }
else else
statusBar->DrawString(font, str.GetChars(), x, y, block->XOffset(), block->YOffset(), block->Alpha(), block->FullScreenOffsets(), translation, spacing, shadow, shadowX, shadowY); statusBar->DrawString(font, str.GetChars(), x, y, block->XOffset(), block->YOffset(), block->Alpha(), block->FullScreenOffsets(), translation, spacing, shadow, shadowX, shadowY);

View File

@ -1106,10 +1106,10 @@ void DBaseStatusBar::DrawLog ()
hudheight = SCREENHEIGHT / scale; hudheight = SCREENHEIGHT / scale;
int linelen = hudwidth<640? Scale(hudwidth,9,10)-40 : 560; int linelen = hudwidth<640? Scale(hudwidth,9,10)-40 : 560;
FBrokenLines *lines = V_BreakLines (SmallFont, linelen, CPlayer->LogText); auto lines = V_BreakLines (SmallFont, linelen, CPlayer->LogText);
int height = 20; int height = 20;
for (int i = 0; lines[i].Width != -1; i++) height += SmallFont->GetHeight () + 1; for (unsigned i = 0; i < lines.Size(); i++) height += SmallFont->GetHeight () + 1;
int x,y,w; int x,y,w;
@ -1138,8 +1138,6 @@ void DBaseStatusBar::DrawLog ()
DTA_VirtualWidth, hudwidth, DTA_VirtualHeight, hudheight, TAG_DONE); DTA_VirtualWidth, hudwidth, DTA_VirtualHeight, hudheight, TAG_DONE);
y += SmallFont->GetHeight ()+1; y += SmallFont->GetHeight ()+1;
} }
V_FreeBrokenLines (lines);
} }
} }
@ -1882,13 +1880,12 @@ DEFINE_ACTION_FUNCTION(DBaseStatusBar, DrawString)
if (wrapwidth > 0) if (wrapwidth > 0)
{ {
FBrokenLines *brk = V_BreakLines(font->mFont, wrapwidth, string, true); auto brk = V_BreakLines(font->mFont, wrapwidth, string, true);
for (int i = 0; brk[i].Width >= 0; i++) for (auto &line : brk)
{ {
self->DrawString(font->mFont, brk[i].Text, x, y, flags, alpha, trans, font->mSpacing, font->mMonospaced, font->mShadowX, font->mShadowY); self->DrawString(font->mFont, line.Text, x, y, flags, alpha, trans, font->mSpacing, font->mMonospaced, font->mShadowX, font->mShadowY);
y += font->mFont->GetHeight() + linespacing; y += font->mFont->GetHeight() + linespacing;
} }
V_FreeBrokenLines(brk);
} }
else else
{ {

View File

@ -535,13 +535,10 @@ void FSavegameManager::UnloadSaveData()
{ {
delete SavePic; delete SavePic;
} }
if (SaveComment != nullptr) SaveComment.Clear();
{ SaveComment.ShrinkToFit();
V_FreeBrokenLines(SaveComment);
}
SavePic = nullptr; SavePic = nullptr;
SaveComment = nullptr;
SavePicData.Clear(); SavePicData.Clear();
} }
@ -615,7 +612,7 @@ void FSavegameManager::DrawSaveComment(FFont *font, int cr, int x, int y, int sc
// I'm not sure why SaveComment would go nullptr in this loop, but I got // I'm not sure why SaveComment would go nullptr in this loop, but I got
// a crash report where it was nullptr when i reached 1, so now I check // a crash report where it was nullptr when i reached 1, so now I check
// for that. // for that.
for (int i = 0; SaveComment != nullptr && SaveComment[i].Width >= 0 && i < maxlines; ++i) for (int i = 0; i < maxlines && (unsigned)i < SaveComment.Size(); ++i)
{ {
screen->DrawText(font, cr, x, y + font->GetHeight() * i * scalefactor, SaveComment[i].Text, DTA_CleanNoMove, true, TAG_DONE); screen->DrawText(font, cr, x, y + font->GetHeight() * i * scalefactor, SaveComment[i].Text, DTA_CleanNoMove, true, TAG_DONE);
} }
@ -647,14 +644,9 @@ void FSavegameManager::SetFileInfo(int Selected)
{ {
if (!SaveGames[Selected]->Filename.IsEmpty()) if (!SaveGames[Selected]->Filename.IsEmpty())
{ {
char workbuf[512]; FString work;
work.Format("File on disk:\n%s", SaveGames[Selected]->Filename.GetChars());
mysnprintf(workbuf, countof(workbuf), "File on disk:\n%s", SaveGames[Selected]->Filename.GetChars()); SaveComment = V_BreakLines(SmallFont, WindowSize, work);
if (SaveComment != nullptr)
{
V_FreeBrokenLines(SaveComment);
}
SaveComment = V_BreakLines(SmallFont, WindowSize, workbuf);
} }
} }

View File

@ -73,7 +73,7 @@ private:
int LastAccessed = -1; int LastAccessed = -1;
TArray<char> SavePicData; TArray<char> SavePicData;
FTexture *SavePic = nullptr; FTexture *SavePic = nullptr;
FBrokenLines *SaveComment = nullptr; TArray<FBrokenLines> SaveComment;
public: public:
int WindowSize = 0; int WindowSize = 0;

View File

@ -715,27 +715,6 @@ DEFINE_ACTION_FUNCTION(DConversationMenu, SendConversationReply)
} }
// Needed for the conversion process.
class DBrokenLines : public DObject
{
DECLARE_ABSTRACT_CLASS(DBrokenLines, DObject)
public:
FBrokenLines *mBroken;
unsigned int mCount;
DBrokenLines(FBrokenLines *broken, unsigned int count)
{
mBroken = broken;
mCount = count;
}
void OnDestroy() override
{
V_FreeBrokenLines(mBroken);
}
};
//============================================================================ //============================================================================
// //
// P_FreeStrifeConversations // P_FreeStrifeConversations

View File

@ -358,7 +358,7 @@ void P_GeometryRadiusAttack(AActor* bombspot, AActor* bombsource, int bombdamage
TArray<line_t*> lines; TArray<line_t*> lines;
while ((ln = it.Next())) // iterator and Trace both use validcount and interfere with each other while ((ln = it.Next())) // iterator and Trace both use validcount and interfere with each other
lines.Push(ln); lines.Push(ln);
for (int i = 0; i < lines.Size(); i++) for (unsigned i = 0; i < lines.Size(); i++)
{ {
ln = lines[i]; ln = lines[i];
DVector2 pos2d = bombspot->Pos().XY(); DVector2 pos2d = bombspot->Pos().XY();

View File

@ -87,6 +87,7 @@ The FON2 header is followed by variable length data:
#include "cmdlib.h" #include "cmdlib.h"
#include "sc_man.h" #include "sc_man.h"
#include "hu_stuff.h" #include "hu_stuff.h"
#include "gstrings.h"
#include "v_text.h" #include "v_text.h"
#include "vm.h" #include "vm.h"
@ -919,7 +920,9 @@ DEFINE_ACTION_FUNCTION(FFont, StringWidth)
{ {
PARAM_SELF_STRUCT_PROLOGUE(FFont); PARAM_SELF_STRUCT_PROLOGUE(FFont);
PARAM_STRING(str); PARAM_STRING(str);
ACTION_RETURN_INT(self->StringWidth(str)); const char *txt = str[0] == '$' ? GStrings(&str[1]) : str.GetChars();
ACTION_RETURN_INT(self->StringWidth(txt));
} }
//========================================================================== //==========================================================================

View File

@ -345,7 +345,7 @@ static void breakit (FBrokenLines *line, FFont *font, const uint8_t *start, cons
line->Width = font->StringWidth (line->Text); line->Width = font->StringWidth (line->Text);
} }
FBrokenLines *V_BreakLines (FFont *font, int maxwidth, const uint8_t *string, bool preservecolor, unsigned int *count) TArray<FBrokenLines> V_BreakLines (FFont *font, int maxwidth, const uint8_t *string, bool preservecolor, unsigned int *count)
{ {
TArray<FBrokenLines> Lines(128); TArray<FBrokenLines> Lines(128);
@ -448,21 +448,7 @@ FBrokenLines *V_BreakLines (FFont *font, int maxwidth, const uint8_t *string, bo
} }
} }
} }
return Lines;
// Make a copy of the broken lines and return them
FBrokenLines *broken = new FBrokenLines[Lines.Size() + 1];
for (unsigned ii = 0; ii < Lines.Size(); ++ii)
{
broken[ii] = Lines[ii];
}
broken[Lines.Size()].Width = -1;
if (count != nullptr)
{
*count = Lines.Size();
}
return broken;
} }
void V_FreeBrokenLines (FBrokenLines *lines) void V_FreeBrokenLines (FBrokenLines *lines)
@ -478,18 +464,11 @@ class DBrokenLines : public DObject
DECLARE_ABSTRACT_CLASS(DBrokenLines, DObject) DECLARE_ABSTRACT_CLASS(DBrokenLines, DObject)
public: public:
FBrokenLines *mBroken; TArray<FBrokenLines> mBroken;
unsigned int mCount;
DBrokenLines(FBrokenLines *broken, unsigned int count) DBrokenLines(TArray<FBrokenLines> &broken)
{ {
mBroken = broken; mBroken = std::move(broken);
mCount = count;
}
void OnDestroy() override
{
V_FreeBrokenLines(mBroken);
} }
}; };
@ -498,21 +477,21 @@ IMPLEMENT_CLASS(DBrokenLines, true, false);
DEFINE_ACTION_FUNCTION(DBrokenLines, Count) DEFINE_ACTION_FUNCTION(DBrokenLines, Count)
{ {
PARAM_SELF_PROLOGUE(DBrokenLines); PARAM_SELF_PROLOGUE(DBrokenLines);
ACTION_RETURN_INT(self->mCount); ACTION_RETURN_INT(self->mBroken.Size());
} }
DEFINE_ACTION_FUNCTION(DBrokenLines, StringWidth) DEFINE_ACTION_FUNCTION(DBrokenLines, StringWidth)
{ {
PARAM_SELF_PROLOGUE(DBrokenLines); PARAM_SELF_PROLOGUE(DBrokenLines);
PARAM_INT(index); PARAM_INT(index);
ACTION_RETURN_INT((unsigned)index >= self->mCount? -1 : self->mBroken[index].Width); ACTION_RETURN_INT((unsigned)index >= self->mBroken.Size()? -1 : self->mBroken[index].Width);
} }
DEFINE_ACTION_FUNCTION(DBrokenLines, StringAt) DEFINE_ACTION_FUNCTION(DBrokenLines, StringAt)
{ {
PARAM_SELF_PROLOGUE(DBrokenLines); PARAM_SELF_PROLOGUE(DBrokenLines);
PARAM_INT(index); PARAM_INT(index);
ACTION_RETURN_STRING((unsigned)index >= self->mCount? -1 : self->mBroken[index].Text); ACTION_RETURN_STRING((unsigned)index >= self->mBroken.Size() ? -1 : self->mBroken[index].Text);
} }
DEFINE_ACTION_FUNCTION(FFont, BreakLines) DEFINE_ACTION_FUNCTION(FFont, BreakLines)
@ -522,6 +501,6 @@ DEFINE_ACTION_FUNCTION(FFont, BreakLines)
PARAM_INT(maxwidth); PARAM_INT(maxwidth);
unsigned int count; unsigned int count;
FBrokenLines *broken = V_BreakLines(self, maxwidth, text, true, &count); TArray<FBrokenLines> broken = V_BreakLines(self, maxwidth, text, true, &count);
ACTION_RETURN_OBJECT(Create<DBrokenLines>(broken, count)); ACTION_RETURN_OBJECT(Create<DBrokenLines>(broken));
} }

View File

@ -39,7 +39,7 @@
struct FBrokenLines struct FBrokenLines
{ {
int Width; unsigned Width;
FString Text; FString Text;
}; };
@ -79,11 +79,10 @@ struct FBrokenLines
#define TEXTCOLOR_CHAT "\034*" #define TEXTCOLOR_CHAT "\034*"
#define TEXTCOLOR_TEAMCHAT "\034!" #define TEXTCOLOR_TEAMCHAT "\034!"
FBrokenLines *V_BreakLines (FFont *font, int maxwidth, const uint8_t *str, bool preservecolor = false, unsigned int *count = nullptr); TArray<FBrokenLines> V_BreakLines (FFont *font, int maxwidth, const uint8_t *str, bool preservecolor = false, unsigned int *count = nullptr);
void V_FreeBrokenLines (FBrokenLines *lines); inline TArray<FBrokenLines> V_BreakLines (FFont *font, int maxwidth, const char *str, bool preservecolor = false, unsigned int *count = nullptr)
inline FBrokenLines *V_BreakLines (FFont *font, int maxwidth, const char *str, bool preservecolor = false, unsigned int *count = nullptr)
{ return V_BreakLines (font, maxwidth, (const uint8_t *)str, preservecolor, count); } { return V_BreakLines (font, maxwidth, (const uint8_t *)str, preservecolor, count); }
inline FBrokenLines *V_BreakLines (FFont *font, int maxwidth, const FString &str, bool preservecolor = false, unsigned int *count = nullptr) inline TArray<FBrokenLines> V_BreakLines (FFont *font, int maxwidth, const FString &str, bool preservecolor = false, unsigned int *count = nullptr)
{ return V_BreakLines (font, maxwidth, (const uint8_t *)str.GetChars(), preservecolor, count); } { return V_BreakLines (font, maxwidth, (const uint8_t *)str.GetChars(), preservecolor, count); }
int GetCharFromString(const uint8_t *&string); int GetCharFromString(const uint8_t *&string);