aboutsummaryrefslogtreecommitdiff
path: root/src/reader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/reader.cpp')
-rw-r--r--src/reader.cpp205
1 files changed, 140 insertions, 65 deletions
diff --git a/src/reader.cpp b/src/reader.cpp
index 1d49d4e..4bc88a6 100644
--- a/src/reader.cpp
+++ b/src/reader.cpp
@@ -1,78 +1,107 @@
-#include "../include/reader.h"
+/* reader.cpp - terminal raw mode and editor utilities */
+
+#define _POSIX_C_SOURCE 200809L
+
#include <csignal>
-#include <iostream>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+#include <cctype>
+#include <string>
+#include <vector>
+
+#include "../include/reader.h"
-void die(const char *s) {
+static EditorCfg *g_cfg = NULL;
+
+void
+die(const char *s)
+{
write(STDOUT_FILENO, "\x1b[2J", 4);
write(STDOUT_FILENO, "\x1b[H", 3);
-
perror(s);
- fprintf(stderr, "[exit]: die(s) invoked, exiting..\n");
+ fprintf(stderr, "[exit]: die() invoked, exiting..\n");
exit(1);
}
-static editor_cfg *g_cfg = nullptr;
-
-void disable_raw_atexit() {
- if (g_cfg) {
+static void
+disable_raw_atexit(void)
+{
+ if (g_cfg)
tcsetattr(STDIN_FILENO, TCSAFLUSH, &(g_cfg->termios_inst));
- }
}
-void handle_signal(int sig) {
+static void
+handle_signal(int sig)
+{
disable_raw_atexit();
_exit(128 + sig);
}
-void disable_raw(editor_cfg *cfg) {
- if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &(cfg->termios_inst)))
+void
+disable_raw(EditorCfg *cfg)
+{
+ if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &(cfg->termios_inst)) < 0)
die("tcsetattr");
}
-void enable_raw(editor_cfg *cfg) {
- if (tcgetattr(STDIN_FILENO, &(cfg->termios_inst)) == -1)
+void
+enable_raw(EditorCfg *cfg)
+{
+ struct termios raw;
+
+ if (tcgetattr(STDIN_FILENO, &(cfg->termios_inst)) < 0)
die("tcgetattr");
g_cfg = cfg;
- std::atexit(disable_raw_atexit);
+ atexit(disable_raw_atexit);
- std::signal(SIGINT, handle_signal);
- std::signal(SIGTERM, handle_signal);
- std::signal(SIGQUIT, handle_signal);
+ signal(SIGINT, handle_signal);
+ signal(SIGTERM, handle_signal);
+ signal(SIGQUIT, handle_signal);
- struct termios raw = cfg->termios_inst;
+ raw = cfg->termios_inst;
+ /* disable XON/XOFF, CR-to-NL, break, parity, strip */
raw.c_iflag &= ~(IXON | ICRNL | BRKINT | INPCK | ISTRIP);
+ /* disable output processing */
raw.c_oflag &= ~(OPOST);
- raw.c_lflag &=
- ~(ECHO | ICANON | IEXTEN); // disables several keybinds in terminal
+ /* disable echo, canonical, extended; disables terminal keybinds */
+ raw.c_lflag &= ~(ECHO | ICANON | IEXTEN);
- raw.c_cc[VMIN] = 0;
+ raw.c_cc[VMIN] = 0;
raw.c_cc[VTIME] = 1;
- if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw) == -1)
+ if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw) < 0)
die("tcsetattr");
}
-char editor_readkey() {
- int nread;
+char
+editor_readkey(void)
+{
+ int nread;
char c;
while ((nread = read(STDIN_FILENO, &c, 1)) != 1) {
- if (nread == -1 && errno != EAGAIN)
+ if (nread < 0 && errno != EAGAIN)
die("read");
}
return c;
}
-int get_cursor_pos(int *rows, int *cols) {
- char buff[32];
+int
+get_cursor_pos(int *rows, int *cols)
+{
+ char buff[32];
unsigned int i = 0;
- if (write(STDOUT_FILENO, "\x1b[6n", 4) != 4) {
+ if (write(STDOUT_FILENO, "\x1b[6n", 4) != 4)
return -1;
- }
+
while (i < sizeof(buff) - 1) {
if (read(STDIN_FILENO, &buff[i], 1) != 1)
break;
@@ -89,11 +118,13 @@ int get_cursor_pos(int *rows, int *cols) {
return 0;
}
-int get_window_size(int *rows, int *cols) {
+int
+get_window_size(int *rows, int *cols)
+{
struct winsize w_size;
- if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w_size) == -1 ||
- w_size.ws_col == 0) {
+ if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w_size) < 0 ||
+ w_size.ws_col == 0) {
if (write(STDOUT_FILENO, "\x1b[999C\x1b[999B", 12) != 12)
return -1;
return get_cursor_pos(rows, cols);
@@ -105,50 +136,94 @@ int get_window_size(int *rows, int *cols) {
return 0;
}
-void window_size_callback(editor_cfg *cfg) {
- int a{};
- int b{};
+void
+window_size_callback(EditorCfg *cfg)
+{
+ int rows;
+ int cols;
+
+ if (get_window_size(&rows, &cols) < 0) {
+ fprintf(stderr,
+ "[err]: window_size_callback: get_window_size\n");
+ return;
+ }
+ if (cfg->screenrows != rows || cfg->screencols != cols) {
+ cfg->screenrows = rows;
+ cfg->screencols = cols;
+ }
+}
+
+void
+ab_append(AppendBuf *ab, const char *s, int len)
+{
+ char *n;
- if (get_window_size(&a, &b) != 0)
- std::cout << "[err]: window_size_callback: get_window_size\n";
- if ((cfg->screencols != a) || (cfg->screencols != b)) {
- cfg->screenrows = a;
- cfg->screencols = b;
- }
+ if (!(n = (char *)realloc(ab->b, ab->len + len)))
+ return;
+ memcpy(&n[ab->len], s, len);
+ ab->b = n;
+ ab->len += len;
}
-void editor_refresh_scrn(editor_cfg *cfg) {
- append_buffer::instance().append("\x1b[2J", 4);
- char buff[32];
+void
+ab_write(AppendBuf *ab)
+{
+ write(STDOUT_FILENO, ab->b, ab->len);
+}
+
+void
+ab_free(AppendBuf *ab)
+{
+ free(ab->b);
+ ab->b = NULL;
+ ab->len = 0;
+}
+
+void
+editor_refresh_scrn(EditorCfg *cfg)
+{
+ AppendBuf ab = {NULL, 0};
+ char buff[32];
+
+ ab_append(&ab, "\x1b[2J", 4);
memset(buff, 0, sizeof(buff));
+ snprintf(buff, sizeof(buff), "\x1b[%d;%dH",
+ cfg->screenrows / 2, cfg->screencols / 2);
+ ab_append(&ab, buff, strlen(buff));
+ ab_write(&ab);
+ ab_free(&ab);
+}
+
+void
+init_editor(EditorCfg *cfg)
+{
+ if (get_window_size(&(cfg->screenrows), &(cfg->screencols)) < 0)
+ die("get_window_size");
+}
- snprintf(buff, sizeof(buff), "\x1b[%d;%dH", cfg->screenrows / 2, cfg->screencols / 2);
+int
+is_number(char *strnum)
+{
+ std::string str = strnum;
+ std::string::const_iterator it = str.begin();
- append_buffer::instance().append(buff, strlen(buff));
- append_buffer::instance().write_output();
- append_buffer::instance().remove();
+ while (it != str.end() && std::isdigit(*it))
+ ++it;
+ return !str.empty() && it == str.end();
}
-size_t split(const std::string &txt, std::vector<std::string> &strings, const std::string &delims) {
+size_t
+split(const std::string &txt,
+ std::vector<std::string> &strings,
+ const std::string &delims)
+{
size_t initial_pos = txt.find_first_not_of(delims, 0);
- size_t pos = txt.find_first_of(delims, initial_pos);
+ size_t pos = txt.find_first_of(delims, initial_pos);
while (initial_pos != std::string::npos) {
strings.push_back(txt.substr(initial_pos, pos - initial_pos));
initial_pos = txt.find_first_not_of(delims, pos);
- pos = txt.find_first_of(delims, initial_pos);
+ pos = txt.find_first_of(delims, initial_pos);
}
return strings.size();
}
-
-void init_editor(editor_cfg *cfg) {
- if (get_window_size(&(cfg->screenrows), &(cfg->screencols)) == -1)
- die("get_window_size");
-}
-
-int is_number(char *strnum) {
- std::string str = strnum;
- std::string::const_iterator it = str.begin();
- while (it != str.end() && std::isdigit(*it)) ++it;
- return !str.empty() && it == str.end();
-}