Skip to content

Commit

Permalink
Fixed: Typing and drawing brackets { } in the console
Browse files Browse the repository at this point in the history
The { and } characters are used for embedded visual formatting
instructions in the font renderer. Added a format escape character
(ASCII 0x10) that allows escaping { so that it can be drawn as normal
text.
  • Loading branch information
skyjake committed Apr 13, 2012
1 parent 92138d4 commit 00eb6f1
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 25 deletions.
4 changes: 3 additions & 1 deletion doomsday/engine/portable/include/rend_font.h
Expand Up @@ -29,11 +29,13 @@
#ifndef LIBDENG_FONT_RENDERER
#define LIBDENG_FONT_RENDERER

#define DEFAULT_INITIALCOUNT (0) /// Used for animating type-in effects.
#define DEFAULT_INITIALCOUNT (0) ///< Used for animating type-in effects.

#define DEFAULT_ALIGNFLAGS (ALIGN_TOPLEFT)
#define DEFAULT_DRAWFLAGS (DTF_NO_EFFECTS)

#define FR_FORMAT_ESCAPE_CHAR ((char)0x10) ///< ASCII data link escape

/**
* Rendering formatted text requires a temporary working buffer in order
* to split up the larger blocks into individual text fragments.
Expand Down
67 changes: 53 additions & 14 deletions doomsday/engine/portable/src/rend_console.c
Expand Up @@ -641,6 +641,35 @@ static void drawSideText(const char* text, int line, float alpha)
FR_PopAttrib();
}

static void escapeFormatting(ddstring_t* dest, const char* src)
{
if(!src) return;
Str_Clear(dest);
for(; *src; ++src)
{
if(*src == '{')
{
Str_AppendChar(dest, FR_FORMAT_ESCAPE_CHAR);
}
Str_AppendChar(dest, *src);
}
}

static void applyFilter(char* buff)
{
con_textfilter_t printFilter = Con_PrintFilter();
ddstring_t* escaped = Str_New();

escapeFormatting(escaped, buff);
strcpy(buff, Str_Text(escaped));
Str_Delete(escaped);

if(printFilter)
{
printFilter(buff);
}
}

/**
* \note Slightly messy...
*/
Expand All @@ -661,7 +690,6 @@ static void drawConsole(float consoleAlpha)
char buff[LOCALBUFFSIZE];
font_t* cfont;
int lineHeight, textOffsetY;
con_textfilter_t printFilter = Con_PrintFilter();
uint reqLines, maxLineLength;
Point2Raw origin;
Size2Raw size;
Expand Down Expand Up @@ -745,10 +773,11 @@ static void drawConsole(float consoleAlpha)
const cbline_t* line = lines[i];

if(line->flags & CBLF_RULER)
{ // Draw a ruler here, and nothing else.
{
// Draw a ruler here, and nothing else.
drawRuler(XORIGIN + PADDING, (YORIGIN + y) / scale[1],
Window_Width(theWindow) / scale[0] - PADDING*2, lineHeight,
consoleAlpha);
Window_Width(theWindow) / scale[0] - PADDING*2, lineHeight,
consoleAlpha);
}
else
{
Expand All @@ -770,8 +799,8 @@ static void drawConsole(float consoleAlpha)
xOffset = 0;
}

if(printFilter)
printFilter(buff);
// Escape any visual formatting characters in the text.
applyFilter(buff);

// Set the color.
if(Font_Flags(cfont) & FF_COLORIZE)
Expand Down Expand Up @@ -820,13 +849,20 @@ static void drawConsole(float consoleAlpha)
}
}

dd_snprintf(buff, LOCALBUFFSIZE -1/*terminator*/, ">%s%.*s%s",
abbrevLeft? "{alpha=.5}[...]{alpha=1}" : "",
maxLineLength, cmdLine + offset,
abbrevRight? "{alpha=.5}[...]" : "");
// Apply filtering.
/// @todo Clean this up; use a common applyFilter() function.
{
ddstring_t* escaped = Str_New();
escapeFormatting(escaped, cmdLine + offset);

if(printFilter)
printFilter(buff);
dd_snprintf(buff, LOCALBUFFSIZE -1/*terminator*/, ">%s%.*s%s",
abbrevLeft? "{alpha=.5}[...]{alpha=1}" : "",
maxLineLength, Str_Text(escaped),
abbrevRight? "{alpha=.5}[...]" : "");

Str_Delete(escaped);
if(Con_PrintFilter()) (Con_PrintFilter())(buff);
}

glEnable(GL_TEXTURE_2D);
if(Font_Flags(cfont) & FF_COLORIZE)
Expand All @@ -850,7 +886,10 @@ static void drawConsole(float consoleAlpha)

// Where is the cursor?
memset(temp, 0, sizeof(temp));
strncpy(temp, buff, MIN_OF(LOCALBUFFSIZE -1/*prompt length*/ -1/*vis clamp*/, cmdCursor-offset + (abbrevLeft? 24/*abbrev length*/:0) + 1));
//strncpy(temp, cmdLine + offset, MIN_OF(LOCALBUFFSIZE -1/*prompt length*/ /*-1*//*vis clamp*/, cmdCursor-offset + (abbrevLeft? 24/*abbrev length*/:0) + 1));
strcpy(temp, ">");
strncpy(temp + 1, cmdLine + offset, MIN_OF(LOCALBUFFSIZE - 1, cmdCursor - offset));
applyFilter(temp);
xOffset = FR_TextWidth(temp);
if(Con_InputMode())
{
Expand All @@ -869,7 +908,7 @@ static void drawConsole(float consoleAlpha)
glColor4f(CcolYellow[0], CcolYellow[1], CcolYellow[2],
consoleAlpha * (((int) ConsoleBlink) & 0x10 ? .2f : .5f));
GL_DrawRectf2(XORIGIN + PADDING + xOffset, (int)((YORIGIN + y + yOffset) / scale[1]),
(int)width, MAX_OF(1, (int)(height / scale[1])));
(int)width, MAX_OF(1, (int)(height / scale[1])));
}

FR_PopAttrib();
Expand Down
41 changes: 31 additions & 10 deletions doomsday/engine/portable/src/rend_font.c
Expand Up @@ -1183,6 +1183,7 @@ void FR_DrawText3(const char* text, const Point2Raw* _origin, int alignFlags, sh
float origColor[4];
short textFlags;
char* str, *end;
boolean escaped = false;

errorIfNotInited("FR_DrawText");

Expand Down Expand Up @@ -1224,7 +1225,13 @@ void FR_DrawText3(const char* text, const Point2Raw* _origin, int alignFlags, sh
str = (char*)text;
while(*str)
{
if(*str == '{') // Paramaters included?
if(*str == FR_FORMAT_ESCAPE_CHAR)
{
escaped = true;
++str;
continue;
}
if(!escaped && *str == '{') // Paramaters included?
{
fontid_t lastFont = state.fontNum;
int lastTracking = state.tracking;
Expand Down Expand Up @@ -1267,7 +1274,7 @@ void FR_DrawText3(const char* text, const Point2Raw* _origin, int alignFlags, sh
FR_SetCaseScale(state.caseScale);
}

for(end = str; *end && *end != '{';)
for(end = str; *end && *end != FR_FORMAT_ESCAPE_CHAR && (escaped || *end != '{');)
{
int newlines = 0, fragmentAlignFlags;
float alignx = 0;
Expand All @@ -1277,7 +1284,8 @@ void FR_DrawText3(const char* text, const Point2Raw* _origin, int alignFlags, sh
{
curCase = -1;
// Select a substring with characters of the same case (or whitespace).
for(; *end && *end != '{' && *end != '\n'; end++)
for(; *end && *end != FR_FORMAT_ESCAPE_CHAR && (escaped || *end != '{') &&
*end != '\n'; end++)
{
// We can skip whitespace.
if(isspace(*end))
Expand All @@ -1292,9 +1300,13 @@ void FR_DrawText3(const char* text, const Point2Raw* _origin, int alignFlags, sh
else
{
curCase = 0;
for(; *end && *end != '{' && *end != '\n'; end++);
for(; *end && *end != FR_FORMAT_ESCAPE_CHAR && (escaped || *end != '{') &&
*end != '\n'; end++);
}

// No longer escaped.
escaped = false;

{ char* buffer = enlargeTextBuffer(end - str);
memcpy(buffer, str, end - str);
buffer[end - str] = '\0';
Expand Down Expand Up @@ -1424,7 +1436,7 @@ void FR_TextSize(Size2Raw* size, const char* text)
int FR_TextWidth(const char* string)
{
int w, maxWidth = -1;
boolean skip = false;
boolean skipping = false, escaped = false;
const char* ch;
size_t i, len;

Expand All @@ -1433,26 +1445,35 @@ int FR_TextWidth(const char* string)
if(!string || !string[0])
return 0;

/// @todo All visual format parsing should be done in one place.

w = 0;
len = strlen(string);
ch = string;
for(i = 0; i < len; ++i, ch++)
{
unsigned char c = *ch;

if(c == '{')
if(c == FR_FORMAT_ESCAPE_CHAR)
{
skip = true;
escaped = true;
continue;
}
else if(c == '}')
if(!escaped && c == '{')
{
skip = false;
skipping = true;
}
else if(skipping && c == '}')
{
skipping = false;
continue;
}

if(skip)
if(skipping)
continue;

escaped = false;

if(c == '\n')
{
if(w > maxWidth)
Expand Down

0 comments on commit 00eb6f1

Please sign in to comment.