summaryrefslogtreecommitdiff
path: root/shed_io.c
diff options
context:
space:
mode:
Diffstat (limited to 'shed_io.c')
-rw-r--r--shed_io.c91
1 files changed, 91 insertions, 0 deletions
diff --git a/shed_io.c b/shed_io.c
new file mode 100644
index 0000000..17aee8e
--- /dev/null
+++ b/shed_io.c
@@ -0,0 +1,91 @@
+#define _POSIX_C_SOURCE 200809L
+#include <string.h>
+#include <unistd.h>
+#include "shed.h"
+
+void shed_replace_char(struct buffer *b, char c)
+{
+ if (b->pos >= (size_t)b->nread) {
+ shed_insert_char(b, c);
+ return;
+ }
+ b->buf[b->pos] = c;
+ write(STDOUT_FILENO, &c, 1);
+ b->pos++;
+}
+
+void shed_insert_char(struct buffer *b, char c)
+{
+ if (b->pos >= (size_t)b->nread) {
+ b->buf[b->pos] = c;
+ write(STDOUT_FILENO, &c, 1);
+ } else {
+ size_t shift = b->nread - b->pos;
+ char *start = b->buf + b->pos;
+ memmove(start + 1, start, shift);
+ *start = c;
+
+ char back[shift];
+ memset(back, '\b', shift);
+ write(STDOUT_FILENO, start, shift + 1);
+ write(STDOUT_FILENO, back, shift);
+ }
+
+ b->pos++;
+ b->nread++;
+}
+
+void shed_remove_char(struct buffer *b, int forward)
+{
+ /* TODO: don't forward delete past the end */
+ if (forward) {
+ write(STDOUT_FILENO, b->buf + b->pos, 1);
+ b->pos++;
+ }
+
+ if (b->pos == 0) {
+ return;
+ }
+
+ b->pos--;
+
+ char *start = b->buf + b->pos;
+ size_t shift = (size_t)b->nread - b->pos;
+
+ b->nread--;
+
+ for (size_t i = 0; i < shift; i++) {
+ start[i] = start[i + 1];
+ }
+ start[shift] = '\0';
+
+ char back[shift];
+ memset(back, '\b', shift);
+ write(STDOUT_FILENO, back, 1);
+ write(STDOUT_FILENO, start, shift);
+ write(STDOUT_FILENO, " \b", 2);
+ write(STDOUT_FILENO, back, shift - 1);
+}
+
+void shed_move_cursor(struct buffer *b, int move)
+{
+ if (move > 0) {
+ int maxfwd = (int)(b->nread - b->pos);
+ if (move > maxfwd) {
+ move = maxfwd;
+ }
+ write(STDOUT_FILENO, b->buf + b->pos, move);
+ b->pos += move;
+ }
+
+ if (move < 0) {
+ size_t len = (size_t)(-move);
+ if (len > b->pos) {
+ len = b->pos;
+ }
+ char back[len];
+ memset(back, '\b', len);
+ write(STDOUT_FILENO, back, len);
+ b->pos -= len;
+ }
+}