aboutsummaryrefslogtreecommitdiff
path: root/box.c
diff options
context:
space:
mode:
authorRaymaekers Luca <raymaekers.luca@gmail.com>2024-12-07 19:17:33 +0100
committerRaymaekers Luca <luca@spacehb.net>2025-01-07 18:51:21 +0100
commit0574f5a7c5159a2ae1d7d2182cec982509947db9 (patch)
tree2a9678fd39bcf8ead03c7ee979caf668f2f17892 /box.c
parent4aec2e1331650cabb966bbf24ed83f76cbbe9912 (diff)
checkpoint
Diffstat (limited to 'box.c')
-rw-r--r--box.c456
1 files changed, 0 insertions, 456 deletions
diff --git a/box.c b/box.c
deleted file mode 100644
index 3c22aad..0000000
--- a/box.c
+++ /dev/null
@@ -1,456 +0,0 @@
-#define MAX_INPUT_LEN 128
-#define DEBUG
-
-#define TB_IMPL
-#include "external/termbox2.h"
-#undef TB_IMPL
-
-#define CHATTY_IMPL
-#include "chatty.h"
-#undef CHATTY_IMPL
-
-#include "ui.h"
-
-#include <locale.h>
-
-#ifdef DEBUG
-#define Assert(expr) if (!(expr)) \
- { \
- tb_shutdown(); \
- *(u8*)0 = 0; \
- }
-#else
-#define Assert(expr) ;
-#endif
-
-typedef struct {
- s32 X, Y, W, H;
-} rect;
-
-// Characters to use for drawing a box
-// See DrawBox() for an example
-typedef struct {
- wchar_t ur, ru, rd, dr, lr, ud;
-} box_characters;
-
-// Draw box Rect with optional Chars characters
-void
-DrawBox(rect Rect, box_characters *Chars)
-{
- wchar_t ur, ru, rd, dr, lr, ud;
- if (!Chars)
- {
- ur = L'╭';
- ru = L'╯';
- rd = L'╮';
- dr = L'╰';
- lr = L'─';
- ud = L'│';
- }
- else
- {
- ur = Chars->ur;
- ru = Chars->ru;
- rd = Chars->rd;
- dr = Chars->dr;
- lr = Chars->lr;
- ud = Chars->ud;
- }
-
- Rect.H--;
- Rect.W--;
-
- tb_printf(Rect.X, Rect.Y, 0, 0, "%lc", ur);
- for (u32 X = 1; X < Rect.W; X++)
- {
- tb_printf(Rect.X + X, Rect.Y, 0, 0, "%lc", lr);
- }
- tb_printf(Rect.X + Rect.W, Rect.Y, 0, 0, "%lc", rd);
-
- // Draw vertical bars
- for (u32 Y = 1; Y < Rect.H; Y++)
- {
- tb_printf(Rect.X, Rect.Y + Y, 0, 0, "%lc", ud);
- tb_printf(Rect.X + Rect.W, Rect.Y + Y, 0, 0, "%lc", ud);
- }
-
- tb_printf(Rect.X, Rect.Y + Rect.H, 0, 0, "%lc", dr);
- for (u32 X = 1; X < Rect.W; X++)
- {
- tb_printf(Rect.X + X, Rect.Y + Rect.H, 0, 0, "%lc", lr);
- }
- tb_printf(Rect.X + Rect.W, Rect.Y + Rect.H, 0, 0, "%lc", ru);
-}
-
-
-// Delete a character in Text at Pos
-void
-Delete(wchar_t* Text, u64 Pos)
-{
- memmove((u8*)(Text + Pos),
- (u8*)(Text + Pos + 1),
- (MAX_INPUT_LEN - Pos - 1) * sizeof(*Text));
-}
-
-// Check if coordinate (X,Y) is in rect boundaries
-Bool
-IsInRect(rect Rect, u32 X, u32 Y)
-{
- if ((X >= Rect.X && X <= Rect.X + Rect.W) &&
- (Y >= Rect.Y && Y <= Rect.Y + Rect.H)) return True;
- return False;
-}
-
-void
-ScrollLeft(rect Text, u32 *TextOffset, u32 Left)
-{
- u32 TextSurface = Text.H * Text.W;
-
- if (global.cursor_x - Left >= Text.X)
- {
- global.cursor_x -= Left;
- }
- else
- {
- global.cursor_x += Text.W - 1;
-
- if (global.cursor_y > Text.Y)
- {
- global.cursor_y--;
- }
- else
- {
- global.cursor_y = Text.Y + Text.H - 1;
- if (*TextOffset < TextSurface)
- {
- *TextOffset = 0;
- }
- else
- {
- *TextOffset -= TextSurface;
- }
- }
- }
-}
-
-int
-main(void)
-{
- assert(setlocale(LC_ALL, ""));
- struct tb_event ev = {0};
-
- tb_init();
-
- u32 InputLen = 0;
- wchar_t Input[MAX_INPUT_LEN] = {0};
-
-#if 1
- wchar_t *t = L"This is some text that no one would want to know, but you could.";
- u32 Len = wcslen(t);
- for (u32 At = 0; At < Len; At++) Input[At] = t[At];
- InputLen = Len;
-#endif
-
- bytebuf_puts(&global.out, global.caps[TB_CAP_SHOW_CURSOR]);
-
- rect TextBox = {0, 0, 32, 4};
-
-#define BOX_PADDING_X 1
-#define BOX_BORDER_WIDTH 1
- rect Text = {
- 2, 1,
- TextBox.W - 2*BOX_PADDING_X - 2*BOX_BORDER_WIDTH,
- TextBox.H - 2*BOX_BORDER_WIDTH
- };
-#undef BOX_PADDING_X
-#undef BOX_BORDER_WIDTH
- u32 TextSurface = Text.W * Text.H;
-
- global.cursor_x = Text.X;
- global.cursor_y = Text.Y;
-
- u32 TextOffset = 0;
- u32 InputPos = 0;
-
- while (ev.key != TB_KEY_CTRL_C)
- {
-
- tb_clear();
-
- DrawBox(TextBox, 0);
-
- // Draw the text right of the cursor
- // NOTE: the cursor is assumed to be in the box
- Assert(IsInRect(Text, global.cursor_x, global.cursor_y));
- u32 AtX = Text.X, AtY = Text.Y;
- u32 At = TextOffset;
- while (AtY < Text.Y + Text.H)
- {
- if (At < InputLen)
- {
- tb_printf(AtX++, AtY, 0, 0, "%lc", Input[At++]);
- }
- else
- {
- // Erase previous text
- tb_printf(AtX++, AtY, 0, 0, " ");
- }
-
- if (AtX == Text.X + Text.W) { AtY++; AtX = Text.X; }
- }
-
- // Position in input based on cursor position
- InputPos = TextOffset + (global.cursor_x - Text.X) + (global.cursor_y - Text.Y) * Text.W;
-
-#ifdef DEBUG
- tb_printf(TextBox.X, TextBox.Y, 0, 0,
- "%2d,%-2d +%d #%-2d %d/%d",
- global.cursor_x, global.cursor_y,
- TextOffset, InputPos,
- InputLen, MAX_INPUT_LEN);
-#endif
-
- tb_present();
-
- tb_poll_event(&ev);
-
- if (ev.mod & TB_MOD_CTRL)
- {
- switch (ev.key)
- {
- // Delete character backwards
- case TB_KEY_CTRL_8:
- // case TB_KEY_BACKSPACE2:
- {
- if (InputPos == 0) break;
- Delete(Input, InputPos - 1);
- InputLen--;
- // TODO: scrolling
-
- ScrollLeft(Text, &TextOffset, 1);
-
- } break;
- // Delete character forwards
- case TB_KEY_CTRL_D:
- {
- if (InputPos == InputLen) break;
- Delete(Input, InputPos);
- InputLen--;
- // Delete(Input, Position)
- } break;
- // Delete Word backwards
- case TB_KEY_CTRL_W:
- {
- u32 At = InputPos;
- // Find character to stop on
- while (At && is_whitespace(Input[At - 1])) At--;
- while (At && !is_whitespace(Input[At - 1])) At--;
-
- s32 NDelete = InputPos - At;
- memmove(Input + At, Input + InputPos, (InputLen - InputPos) * sizeof(Input[At]));
- InputLen -= NDelete;
-#ifdef DEBUG
- Input[InputLen] = 0;
-#endif
-
- // Update cursor position
- if (global.cursor_x - NDelete >= Text.X)
- {
- global.cursor_x -= NDelete;
- }
- else
- {
- global.cursor_x += Text.W - NDelete;
-
- if (global.cursor_y > Text.Y)
- {
- global.cursor_y--;
- }
- else
- {
- // Scroll
- global.cursor_y = Text.Y + Text.H - 1;
- TextOffset -= TextSurface;
- }
- }
-
- Assert(IsInRect(Text, global.cursor_x, global.cursor_y));
-
- } break;
- // Delete until start of line
- case TB_KEY_CTRL_U:
- {
- memmove(Input, Input + InputPos, (InputLen - InputPos) * sizeof(*Input));
- InputLen -= InputPos;
-#ifdef DEBUG
- Input[InputLen] = 0;
-#endif
- global.cursor_x = Text.X;
- global.cursor_y = Text.Y;
- TextOffset = 0;
- // memmove until first character
- } break;
- // Delete until end of input
- case TB_KEY_CTRL_K: break;
- // Move to start
- case TB_KEY_CTRL_A: global.cursor_x = Text.X; break;
- // Move to end
- case TB_KEY_CTRL_E:
- {
- if (global.cursor_x == Text.X + Text.W - 1) break;
-
- if (InputPos + Text.W > InputLen)
- {
- // Put the cursor on the last character
- global.cursor_x = Text.X + (InputLen - TextOffset) % (Text.W);
- }
- else
- {
- global.cursor_x = Text.X + Text.W - 1;
- }
- } break;
- // Move backwards by one character
- case TB_KEY_CTRL_B: break;
- // Move forwards by one character
- case TB_KEY_CTRL_F: break;
- // Move backwards by word
- case TB_KEY_ARROW_LEFT: break;
- // Move forwards by word
- case TB_KEY_ARROW_RIGHT: break;
- }
-
- }
- // Insert new character in Input at InputPos
- else if (ev.ch && InputLen < MAX_INPUT_LEN)
- {
- if (InputPos < InputLen)
- {
- memmove(Input + InputPos,
- Input + InputPos - 1,
- (InputLen - InputPos + 1) * sizeof(*Input));
- }
- Input[InputPos] = ev.ch;
- InputLen++;
-
- if (global.cursor_x == Text.X + Text.W - 1)
- {
- if (global.cursor_y == Text.Y + Text.H - 1)
- {
- TextOffset += Text.W;
- }
- else
- {
- global.cursor_y++;
- }
- global.cursor_x = Text.X;
- }
- else
- {
- global.cursor_x++;
- }
- }
- else
- {
- switch (ev.key)
- {
- case TB_KEY_ARROW_UP:
- {
- if (global.cursor_y == Text.Y)
- {
- if (TextOffset == 0)
- {
- global.cursor_x = Text.X;
-
- break;
- }
-
- TextOffset -= TextSurface;
- global.cursor_y = Text.Y + Text.H - 1;
- }
- else
- {
- global.cursor_y--;
- }
- } break;
- case TB_KEY_ARROW_DOWN:
- {
- if (InputPos + Text.W > InputLen)
- {
- // Put the cursor on the last character
- global.cursor_x = Text.X + (InputLen - TextOffset) % (Text.W);
- global.cursor_y = Text.Y + (InputLen - TextOffset) / Text.W;
-
- break;
- }
-
- if (global.cursor_y == Text.Y + Text.H - 1)
- {
- TextOffset += TextSurface;
- global.cursor_y = Text.Y;
- }
- else
- {
- global.cursor_y++;
- }
- } break;
-
- // Move character left or scroll
- case TB_KEY_ARROW_LEFT:
- {
- if (InputPos == 0) break;
-
- // If text is on the first character of the box scroll backwards
- if (global.cursor_x == Text.X &&
- global.cursor_y == Text.Y)
- {
-
- global.cursor_x = Text.X + Text.W - 1;
- global.cursor_y = Text.Y + Text.H - 1;
-
- // Scroll
- TextOffset -= TextSurface;
-
- break;
- }
-
- global.cursor_x--;
- if (global.cursor_x < Text.X)
- {
- global.cursor_x = Text.X + Text.W - 1;
- global.cursor_y--;
- }
-
- } break;
- // Move character right or scroll
- case TB_KEY_ARROW_RIGHT:
- {
- if (InputPos == InputLen) break;
-
- // If cursor is on the last character scroll forwards
- if (global.cursor_x == Text.X + Text.W - 1 &&
- global.cursor_y == Text.Y + Text.H - 1)
- {
- global.cursor_x = Text.X;
- global.cursor_y = Text.Y;
-
- // Scroll
- TextOffset += TextSurface;
-
- break;
- }
-
- global.cursor_x++;
- if (global.cursor_x == Text.X + Text.W)
- {
- global.cursor_x = Text.X;
- global.cursor_y++;
- }
- } break;
- }
- }
-
- }
-
- tb_shutdown();
- return 0;
-}