From 437e447b6bbe4ad139c8098d60a547fd9921546b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 16 Sep 2022 00:58:25 +0900 Subject: [PATCH] [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. --- include/QF/draw.h | 3 +++ libs/video/renderer/r_draw.c | 50 +++++++++++++++++++++++++++++++++++ libs/video/renderer/r_progs.c | 12 +++++++++ 3 files changed, 65 insertions(+) diff --git a/include/QF/draw.h b/include/QF/draw.h index 6646ad90a..bbbbf8e9d 100644 --- a/include/QF/draw.h +++ b/include/QF/draw.h @@ -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; diff --git a/libs/video/renderer/r_draw.c b/libs/video/renderer/r_draw.c index 207980f88..3b2285ad5 100644 --- a/libs/video/renderer/r_draw.c +++ b/libs/video/renderer/r_draw.c @@ -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; + } + } +} diff --git a/libs/video/renderer/r_progs.c b/libs/video/renderer/r_progs.c index 7f20c0663..2b33da012 100644 --- a/libs/video/renderer/r_progs.c +++ b/libs/video/renderer/r_progs.c @@ -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} };