From 348e1876d25320e6480f2795c9388b2bc080c743 Mon Sep 17 00:00:00 2001 From: Benji Dial Date: Sun, 7 Mar 2021 12:16:12 -0500 Subject: text entry, with cursor, but no keyboard --- makefile | 6 +- src/user/include/cxx/raleigh/w/entry.h | 52 +++++++++++++ src/user/include/knob/format.h | 8 ++ src/user/raleigh/w/entry.cpp | 138 +++++++++++++++++++++++++++++++++ src/user/raleigh/w/padding.cpp | 1 + src/user/raleigh/w/vbox.cpp | 2 + src/user/raleigh/window.cpp | 4 +- src/user/rhello/main.cpp | 5 ++ src/user/runtimes/cxx/extra.ld | 3 + 9 files changed, 215 insertions(+), 4 deletions(-) create mode 100644 src/user/include/cxx/raleigh/w/entry.h create mode 100644 src/user/raleigh/w/entry.cpp diff --git a/makefile b/makefile index d03c43d..cea7ddd 100644 --- a/makefile +++ b/makefile @@ -102,10 +102,10 @@ obj/libfont.so: obj/libfont/bdf.o obj/libfont/pbf.o obj/libfont/fonts.o \ obj/popups.so: obj/popups/info.o obj/popups/popup.o ld ${partlink} $^ -o $@ -obj/raleigh.so: obj/raleigh/runtime.po obj/raleigh/window.po \ - obj/raleigh/w/label.po obj/raleigh/util.po \ +obj/raleigh.so: obj/raleigh/runtime.po obj/raleigh/window.po \ + obj/raleigh/w/label.po obj/raleigh/util.po \ obj/raleigh/w/padding.po obj/raleigh/w/button.po \ - obj/raleigh/w/vbox.po + obj/raleigh/w/vbox.po obj/raleigh/w/entry.po ld ${partlink} $^ -o $@ obj/init.elf: obj/init/init.o obj/knob.so obj/c.rto diff --git a/src/user/include/cxx/raleigh/w/entry.h b/src/user/include/cxx/raleigh/w/entry.h new file mode 100644 index 0000000..7ea2973 --- /dev/null +++ b/src/user/include/cxx/raleigh/w/entry.h @@ -0,0 +1,52 @@ +#ifndef RALEIGH_W_ENTRY_H +#define RALEIGH_W_ENTRY_H + +#include +#include + +namespace raleigh { + class entry : public widget { + public: + //default_text's data is copied, so it's okay if it changes or if the memory is freed + entry(uint32_t rows, uint32_t cols, const char *default_text="", + const char *font="fixed-10", _pixel_t bg=RGB(ff, ff, ff), + _pixel_t fg=RGB(00, 00, 00), _pixel_t border_color=RGB(00, 00, 00)); + + void notify_window_change(); + void paint(_pixel_t *pixbuf, uint32_t pitch); + bool try_handle_click(coord window_coords, enum mouse_packet::mouse_button click_type, bool up); + void notify_has_opaque_parent(widget *parent); + private: + uint32_t rows; + uint32_t cols; + _pixel_t bg; + _pixel_t fg; + _pixel_t border_color; + + struct font_info *fi; + char *data; + //line_indices[end_y + 1] == end_d + uint32_t *line_indices; + + uint32_t cur_y; + uint32_t cur_x; + uint32_t cur_d; + + //the row of the last character + uint32_t end_y; + //the column after the last character + uint32_t end_x; + //the index of the null terminator + uint32_t end_d; + + bool first_paint; + bool text_changed_since_last_paint; + uint32_t cur_y_last_paint; + uint32_t cur_x_last_paint; + uint32_t cur_d_last_paint; + + void paint_text(_pixel_t *pixbuf, uint32_t pitch); + }; +} + +#endif \ No newline at end of file diff --git a/src/user/include/knob/format.h b/src/user/include/knob/format.h index fed31c7..6ce7aad 100644 --- a/src/user/include/knob/format.h +++ b/src/user/include/knob/format.h @@ -1,6 +1,10 @@ #ifndef KNOB_FORMAT_H #define KNOB_FORMAT_H +#ifdef __cplusplus +extern "C" { +#endif + #include #include @@ -26,4 +30,8 @@ uint32_t try_swtou(const char *from, uint32_t *i_out); //returns 0 on failure uint32_t try_swtoh(const char *from, uint32_t *i_out); +#ifdef __cplusplus +} +#endif + #endif \ No newline at end of file diff --git a/src/user/raleigh/w/entry.cpp b/src/user/raleigh/w/entry.cpp new file mode 100644 index 0000000..de8bd82 --- /dev/null +++ b/src/user/raleigh/w/entry.cpp @@ -0,0 +1,138 @@ +#include +#include +#include +#include + +namespace raleigh { + entry::entry(uint32_t rows, uint32_t cols, const char *default_text, + const char *font, _pixel_t bg, _pixel_t fg, _pixel_t border_color) + : rows(rows), cols(cols), bg(bg), fg(fg), border_color(border_color), + fi(get_font(font)), data(new char[rows * cols]), + line_indices(new uint32_t[rows + 1]), first_paint(true) { + size = coord(fi->space_width * (cols - 1) + fi->char_width + 6, fi->space_height * (rows - 1) + fi->char_height + 6); + closest_opaque = this; + + end_x = 0; + end_y = 0; + line_indices[0] = 0; + for (end_d = 0; default_text[end_d]; ++end_d) { + if (end_d == rows * cols - 1) + break; + data[end_d] = default_text[end_d]; + if ((default_text[end_d] == '\n') || (++end_x == cols)) { + if (end_y == rows - 1) + break; + line_indices[++end_y] = end_d + 1; + end_x = 0; + } + } + line_indices[end_y + 1] = end_d; + cur_x = end_x; + cur_y = end_y; + cur_d = end_d; + data[end_d] = '\0'; + } + + void entry::notify_window_change() {} + + void entry::paint_text(_pixel_t *pixbuf, uint32_t pitch) { + uint32_t y = 0; + uint32_t x = -1; + for (const char *i = data; *i; ++i) { + if (*i == '\n') { + ++y; + x = -1; + } + else { + if (++x == cols) { + ++y; + x = 0; + } + put_char_no_bg(fi, *i, pixbuf + (window_offset.y + 3 + y * fi->space_height) * pitch + (window_offset.x + 3 + x * fi->space_width), pitch, fg); + } + } + } + + void entry::paint(_pixel_t *pixbuf, uint32_t pitch) { + _pixel_t *const cur_ptr = pixbuf + (window_offset.y + 3 + cur_y * fi->space_height) * pitch + (window_offset.x + 3 + cur_x * fi->space_width); + _pixel_t *const old_cur_ptr = pixbuf + (window_offset.y + 3 + cur_y_last_paint * fi->space_height) * pitch + (window_offset.x + 3 + cur_x_last_paint * fi->space_width); + + if (first_paint) { + for (uint32_t x = 0; x < size.x; ++x) { + pixbuf[(window_offset.y) * pitch + window_offset.x + x] = border_color; + pixbuf[(window_offset.y + size.y - 1) * pitch + window_offset.x + x] = border_color; + } + for (uint32_t y = 1; y < size.y - 1; ++y) { + pixbuf[(window_offset.y + y) * pitch + window_offset.x] = border_color; + pixbuf[(window_offset.y + y) * pitch + window_offset.x + size.x - 1] = border_color; + } + + for (uint32_t y = 1; y < size.y - 1; ++y) + for (uint32_t x = 1; x < size.x - 1; ++x) + pixbuf[(window_offset.y + y) * pitch + (window_offset.x + x)] = bg; + + paint_text(pixbuf, pitch); + first_paint = false; + } + + else if (text_changed_since_last_paint) { + for (uint32_t y = 3; y < size.y - 3; ++y) + for (uint32_t x = 3; x < size.x - 3; ++x) + pixbuf[(window_offset.y + y) * pitch + (window_offset.x + x)] = bg; + paint_text(pixbuf, pitch); + text_changed_since_last_paint = false; + } + + else { + for (uint32_t y = 0; y < fi->char_height; ++y) { + old_cur_ptr[y * pitch] = bg; + old_cur_ptr[y * pitch + 1] = bg; + } + if (data[cur_d_last_paint] && (data[cur_d_last_paint] != '\n')) + put_char_no_bg(fi, data[cur_d_last_paint], old_cur_ptr, pitch, fg); + } + + for (uint32_t y = 0; y < fi->char_height; ++y) { + cur_ptr[y * pitch] = fg; + cur_ptr[y * pitch + 1] = fg; + } + + cur_y_last_paint = cur_y; + cur_x_last_paint = cur_x; + cur_d_last_paint = cur_d; + } + + bool entry::try_handle_click(coord window_coords, enum mouse_packet::mouse_button click_type, bool up) { + if (up || (click_type != mouse_packet::LEFT)) + return false; + + if (window_coords.x - window_offset.x < 3) + window_coords.x = 3 + window_offset.x; + else if (window_coords.x - window_offset.x > size.x - 4) + window_coords.x = size.x - 4 + window_offset.x; + if (window_coords.y - window_offset.y < 3) + window_coords.y = 3 + window_offset.y; + else if (window_coords.y - window_offset.y > size.y - 4) + window_coords.y = size.y - 4 + window_offset.y; + + cur_y = (window_coords.y - window_offset.y - 3) / fi->space_height; + cur_x = (window_coords.x - window_offset.x - 3) / fi->space_width; + if (cur_y > end_y) { + cur_y = end_y; + cur_x = end_x; + } + cur_d = line_indices[cur_y] + cur_x; + + if (cur_d >= line_indices[cur_y + 1]) { + cur_d = line_indices[cur_y + 1] - 1; + if (data[cur_d] != '\n') + ++cur_d; + cur_x = cur_d - line_indices[cur_y]; + } + + w->notify_needs_paint(*this); + return true; + } + + void entry::notify_has_opaque_parent(widget *parent) {} +} \ No newline at end of file diff --git a/src/user/raleigh/w/padding.cpp b/src/user/raleigh/w/padding.cpp index 3dd027b..0f93216 100644 --- a/src/user/raleigh/w/padding.cpp +++ b/src/user/raleigh/w/padding.cpp @@ -27,5 +27,6 @@ namespace raleigh { void padding::notify_has_opaque_parent(widget *parent) { closest_opaque = parent; + inner.notify_has_opaque_parent(parent); } } \ No newline at end of file diff --git a/src/user/raleigh/w/vbox.cpp b/src/user/raleigh/w/vbox.cpp index 30b0902..51b87ed 100644 --- a/src/user/raleigh/w/vbox.cpp +++ b/src/user/raleigh/w/vbox.cpp @@ -41,5 +41,7 @@ namespace raleigh { void vbox::notify_has_opaque_parent(widget *parent) { closest_opaque = parent; + for (dllist::node *n = widgets.first; n; n = n->next) + n->d.notify_has_opaque_parent(parent); } } \ No newline at end of file diff --git a/src/user/raleigh/window.cpp b/src/user/raleigh/window.cpp index 41eb9ce..c23545b 100644 --- a/src/user/raleigh/window.cpp +++ b/src/user/raleigh/window.cpp @@ -3,6 +3,8 @@ #include #include +#include + namespace raleigh { window::window(widget &root, _pixel_t bg_color, bool (*on_close)(window &)) : handle(0), size(root.size), root(root), bg_color(bg_color), @@ -11,7 +13,7 @@ namespace raleigh { root.window_offset = coord(0, 0); root.notify_window_change(); - pixbuf = (_pixel_t *)get_block(size.x * size.y * sizeof(_pixel_t)); + pixbuf = new _pixel_t[size.x * size.y]; if (!pixbuf) show_error_and_quitf("Failed to create %d byte pixel buffer\nfor requested %dx%d pixel window.", size.x * size.y * sizeof(_pixel_t), size.x, size.y); diff --git a/src/user/rhello/main.cpp b/src/user/rhello/main.cpp index c92b430..f179317 100644 --- a/src/user/rhello/main.cpp +++ b/src/user/rhello/main.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include @@ -26,7 +27,11 @@ void main() { button b(pbl, &onclick); padding pb(b, 2); + entry e(6, 20, "I'm a text entry!\nEventually you will be able to edit me."); + padding pe(e, 2); + dllist wl; + wl.add_front(pe); wl.add_front(pb); wl.add_front(pl); vbox vb(wl); diff --git a/src/user/runtimes/cxx/extra.ld b/src/user/runtimes/cxx/extra.ld index 8eddedb..8ce5419 100644 --- a/src/user/runtimes/cxx/extra.ld +++ b/src/user/runtimes/cxx/extra.ld @@ -1,5 +1,8 @@ /* void *operator new(size_t) */ _Znwj = get_block; +/* void *operator new[](size_t) */ +_Znaj = get_block; + /* void operator delete(void *, size_t) */ _ZdlPvj = free_block; \ No newline at end of file -- cgit v1.2.3