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} };