diff --git a/.vscode/launch.json b/.vscode/launch.json index 8c85847..097130b 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -2,7 +2,7 @@ "version": "0.2.0", "configurations": [ { - "name": "(gdb) Debug", + "name": "gdb_debug_unix", "type": "cppdbg", "request": "launch", "program": "${workspaceFolder}/bin/scolte", @@ -22,6 +22,29 @@ "ignoreFailures": true } ] + }, + // the only difference is .exe + { + "name": "gdb_debug_win", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/bin/scolte.exe", + "preLaunchTask": "build_exec_dbg", + "stopAtEntry": false, + "cwd": "${workspaceFolder}/bin", + "externalConsole": false, + "MIMode": "gdb", + "miDebuggerPath": "gdb", + "setupCommands": [ + { + "text": "-enable-pretty-printing", + "ignoreFailures": true + }, + { + "text": "-gdb-set disassembly-flavor intel", + "ignoreFailures": true + } + ] } ] } \ No newline at end of file diff --git a/kerep b/kerep index 5391862..430b626 160000 --- a/kerep +++ b/kerep @@ -1 +1 @@ -Subproject commit 5391862d029e64fa41c888a0db3ee83979a3954f +Subproject commit 430b6267d19a04b725b19d01ec04d587d000405d diff --git a/src/Canvas.c b/src/TUI/Canvas.c similarity index 71% rename from src/Canvas.c rename to src/TUI/Canvas.c index ffb0b4b..250e364 100644 --- a/src/Canvas.c +++ b/src/TUI/Canvas.c @@ -1,4 +1,4 @@ -#include "tui.h" +#include "tui_internal.h" void Canvas_freeMembers(void* _self){ Canvas* self=(Canvas*)_self; @@ -7,12 +7,14 @@ void Canvas_freeMembers(void* _self){ Autoarr_freeWithoutMembers(self->children, true); } -void Canvas_draw(UIElement* _self, DrawingArea place){ +UI_Maybe Canvas_draw(Renderer* renderer, UIElement* _self, DrawingArea area){ Canvas* self=(Canvas*)_self; Autoarr_foreach(self->children, ch, ({ - UIElement_draw((UIElement*)ch,place); - fputc('\n', stdout); + if(ch==NULL) + UI_safethrow(UIError_NullPtr,;); + UI_try(UIElement_draw(renderer, (UIElement*)ch, area),_,;); })); + return MaybeNull; } kt_define(Canvas, Canvas_freeMembers, NULL); @@ -25,7 +27,5 @@ Canvas* Canvas_create(){ } void Canvas_addChild(Canvas* self, UIElement* child){ - if (child == NULL) - throw(ERR_NULLPTR); Autoarr_add(self->children, child); } diff --git a/src/TUI/Renderer.c b/src/TUI/Renderer.c new file mode 100644 index 0000000..29268af --- /dev/null +++ b/src/TUI/Renderer.c @@ -0,0 +1,158 @@ +#include "tui_internal.h" + +////////////////////////////////////// +// FrameBuffer // +////////////////////////////////////// + +void FrameBuffer_freeMembers(void* _self){ + FrameBuffer* self=(FrameBuffer*)_self; + free(self->data); +} + +kt_define(FrameBuffer, FrameBuffer_freeMembers, NULL); + +/// creates new frame buffer and fills it with spaces +UI_THROWING_FUNC_DECL(FrameBuffer_create(FrameBuffer* fb)); +Maybe FrameBuffer_create(FrameBuffer* fb){ + if(!term_getSize(&fb->size)){ + fb->size=term_default_size; + //TODO log error + kprintf("can't get terminal size, fallback to default (%ux%u)\n", + term_default_size.cols, term_default_size.rows); + } + u32 length=fb->size.cols * fb->size.rows; + fb->data=malloc(sizeof(*fb->data) * length); + + for(u32 i=0; idata[i]=UTFCHAR('#'); + + return MaybeNull; +} + +void Renderer_freeMembers(void * _self){ + Renderer* self=(Renderer*)_self; + FrameBuffer_freeMembers(&self->frameBuffer); +} + +////////////////////////////////////// +// Renderer // +////////////////////////////////////// + +UI_Maybe __Renderer_set(Renderer* self, utfchar c, u16 x, u16 y) { + if(x >= self->frameBuffer.size.cols) + UI_safethrow(UIError_InvalidX,;); + if(y >= self->frameBuffer.size.rows) + UI_safethrow(UIError_InvalidY,;); + self->frameBuffer.data[self->frameBuffer.size.cols * y + x] = c; + return MaybeNull; +} + +#include + +UI_Maybe __Renderer_drawFrame(Renderer* self){ + // save current buffer + FrameBuffer buf=self->frameBuffer; + // recreate frame buffer + UI_try(FrameBuffer_create(&self->frameBuffer),_,;); + + for(u16 y=0; yframeBuffer),_); + renderer->set=__Renderer_set; + renderer->drawFrame=__Renderer_drawFrame; + return renderer; +} + +////////////////////////////////////// +// drawing functions // +////////////////////////////////////// + +UI_Maybe Renderer_fill(Renderer* renderer, utfchar c, DrawingArea area){ + UI_try(DrawingArea_validate(area),_,;); + for(u16 y=area.y; y0){ + UI_try(Renderer_set(renderer, c, x, y),_,;); + x++; length--; + } + return MaybeNull; +} + +UI_Maybe Renderer_drawLineY(Renderer* renderer, utfchar c, u16 x, u16 y, u16 length){ + while(length>0){ + UI_try(Renderer_set(renderer, c, x, y),_,;); + y++; length--; + } + return MaybeNull; +} + +UI_Maybe Renderer_drawBorder(Renderer* renderer, UIBorder border, DrawingArea area){ + UI_try(DrawingArea_validate(area),_0,;); + + //lines + utfchar topChar = UIBorder_char_h[border.top ]; + utfchar bottomChar = UIBorder_char_h[border.bottom]; + utfchar leftChar = UIBorder_char_v[border.left ]; + utfchar rightChar = UIBorder_char_v[border.right ]; + // top + + // TODO check neighbor borders and insert crossing chars like '╄' + + UI_try(Renderer_drawLineX(renderer, topChar, area.x+1, area.y, area.w-2),_1,;) + // bottom + UI_try(Renderer_drawLineX(renderer, bottomChar, area.x+1, area.y+area.h-1, area.w-2),_2,;) + // left + UI_try(Renderer_drawLineY(renderer, leftChar, area.x, area.y+1, area.h-2),_3,;) + // right + UI_try(Renderer_drawLineY(renderer, rightChar, area.x+area.w-1, area.y+1, area.h-2),_4,;) + + // corners + utfchar ltCornerChar = UIBorder_char_lt[border.left ][border.top ]; + utfchar rtCornerChar = UIBorder_char_rt[border.right][border.top ]; + utfchar rbCornerChar = UIBorder_char_rb[border.right][border.bottom]; + utfchar lbCornerChar = UIBorder_char_lb[border.left ][border.bottom]; + // left top corner + UI_try(Renderer_set(renderer, ltCornerChar, area.x, area.y),_5,;); + // right top corner + UI_try(Renderer_set(renderer, rtCornerChar, area.x+area.w-1, area.y),_6,;); + // right bottom corner + UI_try(Renderer_set(renderer, rbCornerChar, area.x+area.w-1, area.y+area.h-1),_7,;); + // left bottom corner + UI_try(Renderer_set(renderer, lbCornerChar, area.x, area.y+area.h-1),_8,;); + + return MaybeNull; +} diff --git a/src/TextBlock.c b/src/TUI/TextBlock.c similarity index 57% rename from src/TextBlock.c rename to src/TUI/TextBlock.c index 63a01df..8895e6f 100644 --- a/src/TextBlock.c +++ b/src/TUI/TextBlock.c @@ -1,14 +1,16 @@ -#include "tui.h" - +#include "tui_internal.h" void TextBlock_freeMembers(void* _self){ TextBlock* self=(TextBlock*)_self; free(self->text.ptr); } -void TextBlock_draw(UIElement* _self, DrawingArea place){ +UI_Maybe TextBlock_draw(Renderer* renderer, UIElement* _self, DrawingArea area){ TextBlock* self=(TextBlock*)_self; - fputs(self->text.ptr, stdout); + UI_try(UIElement_validate((UIElement*)self, area),_0,;); + UI_try(Renderer_fill(renderer, UTFCHAR(' '), area),_2,;); + UI_try(Renderer_drawBorder(renderer, self->base.borders, area),_1,;); + return MaybeNull; } kt_define(TextBlock, TextBlock_freeMembers, NULL); diff --git a/src/UIElement.c b/src/TUI/UIElement.c similarity index 50% rename from src/UIElement.c rename to src/TUI/UIElement.c index e2a6a6c..6f8db0e 100644 --- a/src/UIElement.c +++ b/src/TUI/UIElement.c @@ -1,4 +1,4 @@ -#include "tui.h" +#include "tui_internal.h" kt_define(UIElement, NULL, NULL); @@ -16,7 +16,7 @@ UIElement __UIElement_createDefault(ktid typeId, UIElement_draw_t drawFunc){ .anchor=UIAnchor_Center, .borders={ .left=UIBorder_Thin, .right=UIBorder_Thin, - .top=UIBorder_Thick, .bottom=UIBorder_Thin + .top=UIBorder_Thin, .bottom=UIBorder_Thin }, .draw=drawFunc }; @@ -27,3 +27,23 @@ void UIElement_destroy(UIElement* self){ self->type->freeMembers(self); free(self); } + + +UI_Maybe DrawingArea_validate(DrawingArea a){ + if(a.h<1) UI_safethrow(UIError_InvalidWidth,;); + if(a.w<1) UI_safethrow(UIError_InvalidHeight,;); + return MaybeNull; +} + +UI_Maybe UIElement_validate(UIElement* u, DrawingArea a){ + UI_try(DrawingArea_validate(a),_,;); + if(u->max_heightmin_height) + UI_safethrow(UIError_InvalidHeight,;); + if(u->max_widthmin_width) + UI_safethrow(UIError_InvalidWidth,;); + if(u->min_height>a.h) + UI_safethrow(UIError_InvalidHeight,;); + if(u->min_width>a.w) + UI_safethrow(UIError_InvalidWidth,;); + return MaybeNull; +} diff --git a/src/TUI/UIError.h b/src/TUI/UIError.h new file mode 100644 index 0000000..d1e1124 --- /dev/null +++ b/src/TUI/UIError.h @@ -0,0 +1,26 @@ +#pragma once + +#if __cplusplus +extern "C" { +#endif + +#include "../../kerep/src/base/base.h" + +PACKED_ENUM(UIError, + UIError_Success=0, + UIError_NullPtr, + UIError_InvalidHeight, UIError_InvalidWidth, + UIError_InvalidX, UIError_InvalidY, + UIError_PrintError +) + +// this macros can be changed later to improve debugging +#define UI_safethrow(ERRCODE, FREEMEM) safethrow(nameof(ERRCODE), FREEMEM) +#define UI_safethrow_msg(ERRMSG, FREEMEM) safethrow(ERRMSG, FREEMEM) +#define UI_try(CALL,RZLT,FREEMEM) try(CALL,RZLT,FREEMEM) +#define UI_Maybe Maybe +#define UI_THROWING_FUNC_DECL(NAME_AND_ARGS) UI_Maybe NAME_AND_ARGS WARN_UNUSED_REZULT + +#if __cplusplus +} +#endif diff --git a/src/tui.c b/src/TUI/tui.c similarity index 73% rename from src/tui.c rename to src/TUI/tui.c index 066fde0..5cdbd72 100644 --- a/src/tui.c +++ b/src/TUI/tui.c @@ -1,11 +1,11 @@ #include "tui.h" kt_define(DrawingArea, NULL, NULL); -kt_define(UIBorderParams, NULL, NULL); +kt_define(UIBorder, NULL, NULL); void kt_initScolteTypes(){ kt_register(DrawingArea); - kt_register(UIBorderParams); + kt_register(UIBorder); kt_register(UIElement); kt_register(Canvas); kt_register(TextBlock); diff --git a/src/tui.h b/src/TUI/tui.h similarity index 54% rename from src/tui.h rename to src/TUI/tui.h index 0def569..d4e5a86 100644 --- a/src/tui.h +++ b/src/TUI/tui.h @@ -4,18 +4,18 @@ extern "C" { #endif -#include "../kerep/src/base/base.h" -#include "../kerep/src/String/string.h" -#include "../kerep/src/kprint/kprint_colors.h" -#include "../kerep/src/Array/Array.h" -#include "terminal.h" +#include "../../kerep/src/String/string.h" +#include "../../kerep/src/kprint/kprint_colors.h" +#include "../../kerep/src/Array/Array.h" +#include "../term/term.h" +#include "unicode.h" +#include "UIError.h" /// initializes type descriptors for this project's types /// call this function between kt_beginInit() and kt_endInit() void kt_initScolteTypes(); - ////////////////////////////////////// // Enums // ////////////////////////////////////// @@ -32,11 +32,12 @@ PACKED_ENUM(UIAnchor, UIAnchor_LeftBottom=UIAnchor_Left|UIAnchor_Bottom ) -PACKED_ENUM(UIBorderType, - UIBorder_NoBorder, +PACKED_ENUM(UIBorderThickness, + UIBorder_Hidden, /* blank space */ UIBorder_Thin, UIBorder_Thick, - UIBorder_Double + UIBorder_Double, + UiBorder_NoBorder /* no space */ ) ////////////////////////////////////// @@ -49,20 +50,48 @@ STRUCT(DrawingArea, u16 w; u16 h; ) -STRUCT(UIBorderParams, - UIBorderType right; - UIBorderType left; - UIBorderType top; - UIBorderType bottom; +STRUCT(UIBorder, + UIBorderThickness right; + UIBorderThickness left; + UIBorderThickness top; + UIBorderThickness bottom; ) +////////////////////////////////////// +// Renderer // +////////////////////////////////////// + +STRUCT(FrameBuffer, + utfchar* data; + TerminalSize size; +) + +typedef struct Renderer Renderer; + +STRUCT(Renderer, + FrameBuffer frameBuffer; + UI_THROWING_FUNC_DECL((*drawFrame)(Renderer*)); + UI_THROWING_FUNC_DECL((*set)(Renderer*, utfchar c, u16 x, u16 y)); +) + +#define Renderer_drawFrame(RENDERER) RENDERER->drawFrame(RENDERER) +#define Renderer_set(RENDERER, CH, X, Y) RENDERER->set(RENDERER, CH, X, Y) + +Renderer* Renderer_create(); +void Renderer_destroy(Renderer* self); + +UI_THROWING_FUNC_DECL(Renderer_fill(Renderer* renderer, utfchar c, DrawingArea area)); +UI_THROWING_FUNC_DECL(Renderer_drawLineX(Renderer* renderer, utfchar c, u16 x, u16 y, u16 length)); +UI_THROWING_FUNC_DECL(Renderer_drawLineY(Renderer* renderer, utfchar c, u16 x, u16 y, u16 length)); +UI_THROWING_FUNC_DECL(Renderer_drawBorder(Renderer* renderer, UIBorder border, DrawingArea area)); + ////////////////////////////////////// // UIElement abstract struct // ////////////////////////////////////// typedef struct UIElement UIElement; typedef UIElement* UIElementPtr; -typedef void (*UIElement_draw_t)(UIElement* self,DrawingArea place); +typedef UI_THROWING_FUNC_DECL((*UIElement_draw_t)(Renderer* renderer, UIElement* self, DrawingArea area)); #define UIElement_stretch (u16)-1 @@ -75,14 +104,14 @@ STRUCT(UIElement, kp_fgColor fgColor; kp_bgColor bgColor; UIAnchor anchor; - UIBorderParams borders; + UIBorder borders; UIElement_draw_t draw; ) -UIElement __UIElement_createDefault(ktid typeId, UIElement_draw_t drawFunc); /// proper way to free UIElement and all its members void UIElement_destroy(UIElement* self); -#define UIElement_draw(UIE_PTR, PLACE_RECT) ((UIElement*)UIE_PTR)->draw((UIElement*)UIE_PTR, PLACE_RECT) +#define UIElement_draw(RENDERER, UIE_PTR, PLACE_RECT) \ + ((UIElement*)UIE_PTR)->draw(RENDERER, UIE_PTR, PLACE_RECT) ////////////////////////////////////// // UIElement derivatives // diff --git a/src/TUI/tui_internal.h b/src/TUI/tui_internal.h new file mode 100644 index 0000000..a5b1536 --- /dev/null +++ b/src/TUI/tui_internal.h @@ -0,0 +1,22 @@ +#pragma once + +#if __cplusplus +extern "C" { +#endif + +#include "tui.h" + +UIElement __UIElement_createDefault(ktid typeId, UIElement_draw_t drawFunc); +UI_THROWING_FUNC_DECL(DrawingArea_validate(DrawingArea a)); +UI_THROWING_FUNC_DECL(UIElement_validate(UIElement* u, DrawingArea a)); + +extern utfchar UIBorder_char_h[4]; +extern utfchar UIBorder_char_v[4]; +extern utfchar UIBorder_char_lt[4][4]; +extern utfchar UIBorder_char_rt[4][4]; +extern utfchar UIBorder_char_rb[4][4]; +extern utfchar UIBorder_char_lb[4][4]; + +#if __cplusplus +} +#endif diff --git a/src/TUI/uiBorder_charTables.c b/src/TUI/uiBorder_charTables.c new file mode 100644 index 0000000..4b9a396 --- /dev/null +++ b/src/TUI/uiBorder_charTables.c @@ -0,0 +1,108 @@ +#include "tui_internal.h" + +utfchar UIBorder_char_h[4]={ + [UIBorder_Hidden]=UTFCHAR(' '), + [UIBorder_Thin ]=UTFCHAR('─'), + [UIBorder_Thick ]=UTFCHAR('━'), + [UIBorder_Double]=UTFCHAR('═') +}; + +utfchar UIBorder_char_v[4]={ + [UIBorder_Hidden]=UTFCHAR(' '), + [UIBorder_Thin ]=UTFCHAR('│'), + [UIBorder_Thick ]=UTFCHAR('┃'), + [UIBorder_Double]=UTFCHAR('║') +}; + +/// [left_border][top_border] +utfchar UIBorder_char_lt[4][4]={ + [UIBorder_Hidden][UIBorder_Hidden]=UTFCHAR(' '), + [UIBorder_Hidden][UIBorder_Thin ]=UTFCHAR('─'), + [UIBorder_Hidden][UIBorder_Thick ]=UTFCHAR('━'), + [UIBorder_Hidden][UIBorder_Double]=UTFCHAR('═'), + + [UIBorder_Thin ][UIBorder_Hidden]=UTFCHAR('│'), + [UIBorder_Thin ][UIBorder_Thin ]=UTFCHAR('┌'), + [UIBorder_Thin ][UIBorder_Thick ]=UTFCHAR('┍'), + [UIBorder_Thin ][UIBorder_Double]=UTFCHAR('╒'), + + [UIBorder_Thick ][UIBorder_Hidden]=UTFCHAR('┃'), + [UIBorder_Thick ][UIBorder_Thin ]=UTFCHAR('┎'), + [UIBorder_Thick ][UIBorder_Thick ]=UTFCHAR('┏'), + [UIBorder_Thick ][UIBorder_Double]=UTFCHAR('╒'), + + [UIBorder_Double][UIBorder_Hidden]=UTFCHAR('║'), + [UIBorder_Double][UIBorder_Thin ]=UTFCHAR('╓'), + [UIBorder_Double][UIBorder_Thick ]=UTFCHAR('╓'), + [UIBorder_Double][UIBorder_Double]=UTFCHAR('╔') +}; + + +/// [right_border][top_border] +utfchar UIBorder_char_rt[4][4]={ + [UIBorder_Hidden][UIBorder_Hidden]=UTFCHAR(' '), + [UIBorder_Hidden][UIBorder_Thin ]=UTFCHAR('─'), + [UIBorder_Hidden][UIBorder_Thick ]=UTFCHAR('━'), + [UIBorder_Hidden][UIBorder_Double]=UTFCHAR('═'), + + [UIBorder_Thin ][UIBorder_Hidden]=UTFCHAR('│'), + [UIBorder_Thin ][UIBorder_Thin ]=UTFCHAR('┐'), + [UIBorder_Thin ][UIBorder_Thick ]=UTFCHAR('┑'), + [UIBorder_Thin ][UIBorder_Double]=UTFCHAR('╕'), + + [UIBorder_Thick ][UIBorder_Hidden]=UTFCHAR('┃'), + [UIBorder_Thick ][UIBorder_Thin ]=UTFCHAR('┒'), + [UIBorder_Thick ][UIBorder_Thick ]=UTFCHAR('┓'), + [UIBorder_Thick ][UIBorder_Double]=UTFCHAR('╕'), + + [UIBorder_Double][UIBorder_Hidden]=UTFCHAR('║'), + [UIBorder_Double][UIBorder_Thin ]=UTFCHAR('╖'), + [UIBorder_Double][UIBorder_Thick ]=UTFCHAR('╖'), + [UIBorder_Double][UIBorder_Double]=UTFCHAR('╗') +}; + +/// [right_border][bottom_border] +utfchar UIBorder_char_rb[4][4]={ + [UIBorder_Hidden][UIBorder_Hidden]=UTFCHAR(' '), + [UIBorder_Hidden][UIBorder_Thin ]=UTFCHAR('─'), + [UIBorder_Hidden][UIBorder_Thick ]=UTFCHAR('━'), + [UIBorder_Hidden][UIBorder_Double]=UTFCHAR('═'), + + [UIBorder_Thin ][UIBorder_Hidden]=UTFCHAR('│'), + [UIBorder_Thin ][UIBorder_Thin ]=UTFCHAR('┘'), + [UIBorder_Thin ][UIBorder_Thick ]=UTFCHAR('┙'), + [UIBorder_Thin ][UIBorder_Double]=UTFCHAR('╛'), + + [UIBorder_Thick ][UIBorder_Hidden]=UTFCHAR('┃'), + [UIBorder_Thick ][UIBorder_Thin ]=UTFCHAR('┚'), + [UIBorder_Thick ][UIBorder_Thick ]=UTFCHAR('┛'), + [UIBorder_Thick ][UIBorder_Double]=UTFCHAR('╛'), + + [UIBorder_Double][UIBorder_Hidden]=UTFCHAR('║'), + [UIBorder_Double][UIBorder_Thin ]=UTFCHAR('╜'), + [UIBorder_Double][UIBorder_Thick ]=UTFCHAR('╜'), + [UIBorder_Double][UIBorder_Double]=UTFCHAR('╝') +}; + +/// [left_border][bottom_border] +utfchar UIBorder_char_lb[4][4]={ + [UIBorder_Hidden][UIBorder_Hidden]=UTFCHAR(' '), + [UIBorder_Hidden][UIBorder_Thin ]=UTFCHAR('─'), + [UIBorder_Hidden][UIBorder_Thick ]=UTFCHAR('━'), + [UIBorder_Hidden][UIBorder_Double]=UTFCHAR('═'), + + [UIBorder_Thin ][UIBorder_Hidden]=UTFCHAR('│'), + [UIBorder_Thin ][UIBorder_Thin ]=UTFCHAR('└'), + [UIBorder_Thin ][UIBorder_Thick ]=UTFCHAR('┕'), + [UIBorder_Thin ][UIBorder_Double]=UTFCHAR('╘'), + + [UIBorder_Thick ][UIBorder_Hidden]=UTFCHAR('┃'), + [UIBorder_Thick ][UIBorder_Thin ]=UTFCHAR('┖'), + [UIBorder_Thick ][UIBorder_Thick ]=UTFCHAR('┗'), + [UIBorder_Thick ][UIBorder_Double]=UTFCHAR('╘'), + + [UIBorder_Double][UIBorder_Hidden]=UTFCHAR('║'), + [UIBorder_Double][UIBorder_Thin ]=UTFCHAR('╙'), + [UIBorder_Double][UIBorder_Thick ]=UTFCHAR('╙'), + [UIBorder_Double][UIBorder_Double]=UTFCHAR('╚') +}; diff --git a/src/TUI/unicode.h b/src/TUI/unicode.h new file mode 100644 index 0000000..69c5778 --- /dev/null +++ b/src/TUI/unicode.h @@ -0,0 +1,31 @@ +#pragma once + +#if __cplusplus +extern "C" { +#endif + +// #include +#include + +typedef char16_t utfchar; +#define UTFCHAR(CHAR) u##CHAR +#define UTFSTR(STR) u##STR + +// returns length of written bytes or error code +static inline size_t utfchar_write(utfchar ch, FILE* file){ + char multibyteUtf8[8]={0}; + mbstate_t mbs={0}; + size_t length=c16rtomb(multibyteUtf8, ch, &mbs); + if(length!=-1) + for(u8 i=0; i Maybe tryReadFile(char* filePath){ @@ -14,6 +14,9 @@ Maybe tryReadFile(char* filePath){ } i32 main(const i32 argc, const char* const* argv){ + if(setlocale(LC_CTYPE, "C.UTF-8")!=0) + kprintf("\e[93msetlocale failed!\n"); + kt_beginInit(); kt_initKerepTypes(); kt_initScolteTypes(); @@ -29,15 +32,15 @@ i32 main(const i32 argc, const char* const* argv){ char* text=(char*)_m_text.value.VoidPtr; fputs(text,stdout);*/ + Renderer* renderer=Renderer_create(); Canvas* mainCanvas=Canvas_create(); TextBlock* testTextBlock=TextBlock_create(string_fromCptr("some example text")); Canvas_addChild(mainCanvas, (UIElement*)testTextBlock); - UIElement_draw(mainCanvas, ((DrawingArea){.x=-1, .y=-1, .h=-1, .w=-1})); - UIElement_destroy((UIElement*)mainCanvas); + tryLast(UIElement_draw(renderer, (UIElement*)mainCanvas, ((DrawingArea){.x=4, .y=4, .h=4, .w=4})),_); + tryLast(Renderer_drawFrame(renderer),_2); - TerminalSize tsize=terminal_getSize(); - kprintf("rows: %u culumns: %u\n", tsize.rows, tsize.cols); - fflush(stdout); + UIElement_destroy((UIElement*)mainCanvas); + Renderer_destroy(renderer); kt_free(); return 0; diff --git a/src/term/term.c b/src/term/term.c new file mode 100644 index 0000000..e41dfbf --- /dev/null +++ b/src/term/term.c @@ -0,0 +1,38 @@ +#include "term.h" +#include +#include +#include IFWIN("windows.h", "sys/ioctl.h") + +void term_moveCursor(u16 row, u16 column){ + printf("\e[%u;%uf",row,column); + +} + +void term_clear() { + printf("\e[2j"); +} + +bool term_getSize(TerminalSize* out) { +#if defined(_WIN64) || defined(_WIN32) + // helps when STD_OUT is redirected to a file + HANDLE hConsoleErr = GetStdHandle(STD_ERROR_HANDLE); + CONSOLE_SCREEN_BUFFER_INFO consoleInfo; + if(!GetConsoleScreenBufferInfo(hConsoleErr, &consoleInfo)) + return false; + *out=(TerminalSize){ + .cols=consoleInfo.srWindow.Right-consoleInfo.srWindow.Left+1, + .rows=consoleInfo.srWindow.Bottom-consoleInfo.srWindow.Top+1 + }; +#else + struct winsize w={0,0,0,0}; + if(ioctl(STDOUT_FILENO, TIOCGWINSZ, &w)!=0) + return false; + *out=(TerminalSize){ + .cols=w.ws_col, + .rows=w.ws_row + }; +#endif + return true; +} + +TerminalSize term_default_size={.cols=80, .rows=16}; diff --git a/src/term/term.h b/src/term/term.h new file mode 100644 index 0000000..2bc9cdd --- /dev/null +++ b/src/term/term.h @@ -0,0 +1,25 @@ +#pragma once + +#if __cplusplus +extern "C" { +#endif + +#include "../../kerep/src/base/base.h" + +void term_moveCursor(u16 row, u16 column); +void term_clear(); + +STRUCT(TerminalSize, + u16 rows; + u16 cols; +) + +///@return TRUE if have got terminal size, otherwise FALSE +bool term_getSize(TerminalSize* out) WARN_UNUSED_REZULT; + +/// can be used if term_getSize() fails +extern TerminalSize term_default_size; + +#if __cplusplus +} +#endif diff --git a/src/terminal.c b/src/terminal.c deleted file mode 100644 index e22035d..0000000 --- a/src/terminal.c +++ /dev/null @@ -1,23 +0,0 @@ -#include "terminal.h" -#include -#include -#include - -void terminal_moveCursor(u16 row, u16 column){ - printf("\e[%u;%uf",row,column); -} - -void terminal_clear() { - printf("\e[2j"); -} - -TerminalSize terminal_getSize(){ - struct winsize w={0,0,0,0}; - if(ioctl(STDOUT_FILENO, TIOCGWINSZ, &w)!=0) - kprintf("\e[93mterminal_getSize() error\n"); - TerminalSize tsize={ - .cols=w.ws_col, - .rows=w.ws_row - }; - return tsize; -} diff --git a/src/terminal.h b/src/terminal.h deleted file mode 100644 index 5e462b8..0000000 --- a/src/terminal.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#if __cplusplus -extern "C" { -#endif - -#include "../kerep/src/base/base.h" - -void terminal_moveCursor(u16 row, u16 column); -void terminal_clear(); - -STRUCT(TerminalSize, - u16 rows; - u16 cols; -) - -TerminalSize terminal_getSize(); - -#if __cplusplus -} -#endif