summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenji Dial <benji6283@gmail.com>2021-03-07 12:16:12 -0500
committerBenji Dial <benji6283@gmail.com>2021-03-07 12:16:12 -0500
commit348e1876d25320e6480f2795c9388b2bc080c743 (patch)
tree29fef9fa2a85ecd9565ea4a3cf78dba15c960750
parent76e39eac8cee2175ec62a191f7c91ca53857e80c (diff)
downloadportland-os-348e1876d25320e6480f2795c9388b2bc080c743.tar.gz
text entry, with cursor, but no keyboard
-rw-r--r--makefile6
-rw-r--r--src/user/include/cxx/raleigh/w/entry.h52
-rw-r--r--src/user/include/knob/format.h8
-rw-r--r--src/user/raleigh/w/entry.cpp138
-rw-r--r--src/user/raleigh/w/padding.cpp1
-rw-r--r--src/user/raleigh/w/vbox.cpp2
-rw-r--r--src/user/raleigh/window.cpp4
-rw-r--r--src/user/rhello/main.cpp5
-rw-r--r--src/user/runtimes/cxx/extra.ld3
9 files changed, 215 insertions, 4 deletions
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 <raleigh/widget.h>
+#include <libfont/fonts.h>
+
+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 <knob/heap.h>
#include <stdint.h>
@@ -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 <raleigh/w/entry.h>
+#include <knob/format.h>
+#include <knob/block.h>
+#include <knob/heap.h>
+
+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<widget &>::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 <popups/info.h>
#include <knob/heap.h>
+#include <knob/format.h>
+
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 <raleigh/w/padding.h>
#include <raleigh/w/button.h>
#include <raleigh/w/label.h>
+#include <raleigh/w/entry.h>
#include <raleigh/w/vbox.h>
#include <raleigh/runtime.h>
@@ -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<widget &> 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