[renderer] Add a buffer print function

It handles basic cursor motion respecting \r \n \f and \t (might be a
problem for id chars), wraps at the right edge, and automatically
scrolls when the cursor tries to pass the bottom of the screen.

Clearing the buffer resets its cursor to the upper left.
This commit is contained in:
Bill Currie 2022-09-16 00:58:25 +09:00
parent c5099d30b1
commit 437e447b6b
3 changed files with 65 additions and 0 deletions

View file

@ -50,6 +50,8 @@ typedef struct draw_charbuffer_s {
int width; ///< width in character cells
int height; ///< height in character cells
char *chars; ///< width * height characters
int cursx; ///< horizontal cursor position
int cursy; ///< vertical cursor position
} draw_charbuffer_t;
draw_charbuffer_t *Draw_CreateBuffer (int width, int height);
@ -57,6 +59,7 @@ void Draw_DestroyBuffer (draw_charbuffer_t *buffer);
void Draw_ClearBuffer (draw_charbuffer_t *buffer);
void Draw_ScrollBuffer (draw_charbuffer_t *buffer, int lines);
void Draw_CharBuffer (int x, int y, draw_charbuffer_t *buffer);
void Draw_PrintBuffer (draw_charbuffer_t *buffer, const char *str);
extern byte *draw_chars;

View file

@ -43,6 +43,7 @@ Draw_CreateBuffer (int width, int height)
buffer->width = width;
buffer->height = height;
buffer->chars = (char *) (buffer + 1);
buffer->cursx = buffer->cursy = 0;
return buffer;
}
@ -56,6 +57,7 @@ VISIBLE void
Draw_ClearBuffer (draw_charbuffer_t *buffer)
{
memset (buffer->chars, ' ', buffer->height * buffer->width);
buffer->cursx = buffer->cursy = 0;
}
VISIBLE void
@ -86,3 +88,51 @@ Draw_CharBuffer (int x, int y, draw_charbuffer_t *buffer)
{
r_funcs->Draw_CharBuffer (x, y, buffer);
}
#define TAB 8
VISIBLE void
Draw_PrintBuffer (draw_charbuffer_t *buffer, const char *str)
{
char *dst = buffer->chars;
char c;
int tab;
dst += buffer->cursy * buffer->width + buffer->cursx;
while ((c = *str++)) {
switch (c) {
case '\r':
dst -= buffer->cursx;
buffer->cursx = 0;
break;
case '\n':
dst -= buffer->cursx;
buffer->cursx = 0;
dst += buffer->width;
buffer->cursy++;
break;
case '\f':
dst += buffer->width;
buffer->cursy++;
break;
case '\t':
tab = TAB - buffer->cursx % TAB;
buffer->cursx += tab;
dst += tab;
break;
default:
*dst++ = c;
buffer->cursx++;
break;
}
if (buffer->cursx >= buffer->width) {
buffer->cursx -= buffer->width;
buffer->cursy++;
}
if (buffer->cursy >= buffer->height) {
int lines = buffer->cursy - buffer->height + 1;
Draw_ScrollBuffer (buffer, lines);
dst -= lines * buffer->width;
buffer->cursy -= lines;
}
}
}

View file

@ -462,6 +462,17 @@ bi_Draw_CharBuffer (progs_t *pr, void *_res)
Draw_CharBuffer (x, y, cbuff->buffer);
}
static void
bi_Draw_PrintBuffer (progs_t *pr, void *_res)
{
draw_resources_t *res = _res;
pr_ptr_t cbuff_handle = P_POINTER (pr, 0);
bi_charbuff_t *cbuff = get_charbuff (pr, res, __FUNCTION__, cbuff_handle);
const char *str = P_GSTRING (pr, 1);
Draw_PrintBuffer (cbuff->buffer, str);
}
static const char *
bi_draw_get_key (const void *p, void *unused)
{
@ -527,6 +538,7 @@ static builtin_t builtins[] = {
bi(Draw_ClearBuffer, 1, p(ptr)),
bi(Draw_ScrollBuffer, 2, p(ptr), p(int)),
bi(Draw_CharBuffer, 3, p(int), p(int), p(ptr)),
bi(Draw_PrintBuffer, 2, p(ptr), p(string)),
{0}
};