OpenClonk
C4LogBuffer Class Reference

#include <C4LogBuf.h>

Public Member Functions

 C4LogBuffer (int iSize, int iMaxLines, int iLBWidth, const char *szIndentChars=" ", bool fDynamicGrow=false, bool fMarkup=true)
 
 ~C4LogBuffer ()
 
void AppendLines (const char *szLine, CStdFont *pFont, DWORD dwClr, CStdFont *pFirstLineFont=nullptr)
 
const char * GetLine (int iLineIndex, CStdFont **ppFont, DWORD *pdwClr, bool *pNewParagraph) const
 
void Clear ()
 
int GetCount () const
 
void SetLBWidth (int iToWidth)
 

Detailed Description

Definition at line 22 of file C4LogBuf.h.

Constructor & Destructor Documentation

◆ C4LogBuffer()

C4LogBuffer::C4LogBuffer ( int  iSize,
int  iMaxLines,
int  iLBWidth,
const char *  szIndentChars = "    ",
bool  fDynamicGrow = false,
bool  fMarkup = true 
)

Definition at line 23 of file C4LogBuf.cpp.

24  : iBufSize(iSize), iFirstLinePos(0), iAfterLastLinePos(0), iLineDataPos(0),
25  iNextLineDataPos(0), iMaxLineCount(iMaxLines), iLineCount(0), iLineBreakWidth(iLBWidth), fDynamicGrow(fDynamicGrow), fMarkup(fMarkup)
26 {
27  // copy indent
28  if (szIndentChars && *szIndentChars)
29  {
30  szIndent = new char[strlen(szIndentChars)+1];
31  strcpy(szIndent, szIndentChars);
32  }
33  else szIndent = nullptr;
34  // create buffers, if buffer size is given. Otherwise, create/grow them dynamically
35  if (iBufSize) szBuf = new char[iBufSize]; else szBuf=nullptr;
36  if (iMaxLineCount) pLineDataBuf = new LineData[iMaxLineCount]; else pLineDataBuf=nullptr;
37  assert(fDynamicGrow || (iBufSize && iMaxLineCount));
38 }
int iSize
Definition: TstC4NetIO.cpp:32

◆ ~C4LogBuffer()

C4LogBuffer::~C4LogBuffer ( )

Definition at line 40 of file C4LogBuf.cpp.

41 {
42  // free buffers
43  delete [] pLineDataBuf;
44  delete [] szBuf;
45  // free indent
46  if (szIndent) delete [] szIndent;
47 }

Member Function Documentation

◆ AppendLines()

void C4LogBuffer::AppendLines ( const char *  szLine,
CStdFont pFont,
DWORD  dwClr,
CStdFont pFirstLineFont = nullptr 
)

Definition at line 170 of file C4LogBuf.cpp.

171 {
172  char LineBreakChars [] = { 0x0D, 0x0A, '|' };
173  int32_t iLineBreakCharCount = 2 + fMarkup;
174  // safety
175  if (!szLine) return;
176  // split '|'/CR/LF-separations first, if there are any
177  bool fAnyLineBreakChar = false;
178  for (int i = 0; i < iLineBreakCharCount; ++i)
179  if (strchr(szLine, LineBreakChars[i]))
180  {
181  fAnyLineBreakChar = true;
182  break;
183  }
184  if (fAnyLineBreakChar)
185  {
186  char *szBuf = new char[strlen(szLine)+1];
187  char *szBufPos, *szPos2 = szBuf, *szBufFind;
188  strcpy(szBuf, szLine);
189  while ((szBufPos = szPos2))
190  {
191  // find first occurance of any line break char
192  szPos2 = nullptr;
193  for (int i = 0; i < iLineBreakCharCount; ++i)
194  if ((szBufFind = strchr(szBufPos, LineBreakChars[i])))
195  if (!szPos2 || szBufFind < szPos2)
196  szPos2 = szBufFind;
197  // split string at linebreak char
198  if (szPos2) *szPos2++ = '\0';
199  // output current line if not empty
200  if (!*szBufPos) continue;
201  // first line in caption font
202  if (pFirstLineFont)
203  {
204  AppendLines(szBufPos, pFirstLineFont, dwClr);
205  pFirstLineFont = nullptr;
206  }
207  else
208  AppendLines(szBufPos, pFont, dwClr);
209  }
210  delete [] szBuf;
211  return;
212  }
213  // no line breaks desired: Output all in one line
214  if (!iLineBreakWidth || !pFont)
215  {
216  AppendSingleLine(szLine, strlen(szLine), nullptr, pFont, dwClr, true);
217  }
218  else
219  {
220  C4Markup markup(false);
221  const char *markupPos = szLine;
222  std::string rline;
223  // output broken lines until there are any
224  int iLineIndex = 0;
225  while (*szLine)
226  {
227  // get line width of this line
228  int iBreakWdt = iLineBreakWidth;
229  if (iLineIndex && szIndent)
230  {
231  int32_t iIndentWdt, Q;
232  pFont->GetTextExtent(szIndent, iIndentWdt, Q, true);
233  iBreakWdt -= iIndentWdt;
234  }
235  // get number of characters printable into this line
236  const char *szNextLine;
237  int iNumChars = pFont->GetMessageBreak(szLine, &szNextLine, iBreakWdt);
238  // make sure not to break markup
239  if (fMarkup)
240  {
241  std::string opening = markup.OpeningTags();
242  while (markupPos < szNextLine)
243  {
244  if (*markupPos == '<')
245  {
246  if (markup.Read(&markupPos))
247  {
248  if (markupPos > szNextLine)
249  {
250  // The message break is within a tag.
251  iNumChars += markupPos - szNextLine + 1;
252  szNextLine = markupPos;
253  }
254  // Read already moved us over a valid tag.
255  continue;
256  }
257  }
258  markupPos++;
259  }
260  std::string closing = markup.ClosingTags();
261  if (!opening.empty() || !closing.empty())
262  {
263  rline = std::move(opening);
264  rline.append(szLine, iNumChars);
265  rline.append(closing);
266  szLine = rline.c_str();
267  iNumChars = rline.size();
268  }
269  }
270  // add them
271  AppendSingleLine(szLine, iNumChars, iLineIndex ? szIndent : nullptr, pFont, dwClr, !iLineIndex);
272  // next line
273  szLine = szNextLine;
274  ++iLineIndex;
275  rline.clear();
276  }
277  }
278 }
void AppendLines(const char *szLine, CStdFont *pFont, DWORD dwClr, CStdFont *pFirstLineFont=nullptr)
Definition: C4LogBuf.cpp:170
bool GetTextExtent(const char *szText, int32_t &rsx, int32_t &rsy, bool fCheckMarkup=true)
int GetMessageBreak(const char *szMsg, const char **ppNewPos, int iBreakWidth, float fZoom=1.0f)

References C4Markup::ClosingTags(), CStdFont::GetMessageBreak(), CStdFont::GetTextExtent(), C4Markup::OpeningTags(), and C4Markup::Read().

Referenced by C4GUI::MultilineLabel::AddLine(), and C4MessageBoard::AddLog().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Clear()

void C4LogBuffer::Clear ( )

Definition at line 308 of file C4LogBuf.cpp.

309 {
310  // clear buffer usage
311  iFirstLinePos = iAfterLastLinePos = iLineCount = iNextLineDataPos = iLineDataPos = 0;
312 }

Referenced by C4GUI::MultilineLabel::Clear(), C4MessageBoard::ClearLog(), and C4MessageBoard::~C4MessageBoard().

Here is the caller graph for this function:

◆ GetCount()

int C4LogBuffer::GetCount ( ) const
inline

Definition at line 57 of file C4LogBuf.h.

57 { return iLineCount; }// retrieve number of valid lines in buffer

◆ GetLine()

const char * C4LogBuffer::GetLine ( int  iLineIndex,
CStdFont **  ppFont,
DWORD pdwClr,
bool *  pNewParagraph 
) const

Definition at line 280 of file C4LogBuf.cpp.

281 {
282  // evaluate negative indices
283  if (iLineIndex < 0)
284  {
285  iLineIndex += iLineCount;
286  if (iLineIndex < 0) return nullptr;
287  }
288  // range check
289  if (iLineIndex >= iLineCount) return nullptr;
290  // assign data
291  LineData &rData = pLineDataBuf[(iLineDataPos + iLineIndex) % iMaxLineCount];
292  if (ppFont) *ppFont = rData.pFont;
293  if (pdwClr) *pdwClr = rData.dwClr;
294  if (pfNewPar) *pfNewPar = rData.fNewParagraph;
295  // advance in lines until desired line is found
296  char *szResult = szBuf + iFirstLinePos;
297  while (iLineIndex--)
298  {
299  // skip this line
300  while (*szResult++) ;
301  // double delimeter or end of buffer: reset searching to front of buffer
302  if (szResult == (szBuf+iBufSize) || !*szResult) szResult = szBuf;
303  }
304  // return found buffer pos
305  return szResult;
306 }

Referenced by C4MessageBoard::Draw(), C4LoaderScreen::Draw(), C4GUI::MultilineLabel::DrawElement(), C4MessageBoard::Execute(), and C4GUI::MultilineLabel::UpdateHeight().

Here is the caller graph for this function:

◆ SetLBWidth()

void C4LogBuffer::SetLBWidth ( int  iToWidth)

Definition at line 314 of file C4LogBuf.cpp.

315 {
316  iLineBreakWidth = iToWidth;
317 }

Referenced by C4MessageBoard::Init(), C4GUI::MultilineLabel::UpdateSize(), and C4MessageBoard::~C4MessageBoard().

Here is the caller graph for this function:

The documentation for this class was generated from the following files: