tFirst commit, set up terminal and fix key handling - ve - a minimal text editor (work in progress) (HTM) git clone git://src.adamsgaard.dk/ve (DIR) Log (DIR) Files (DIR) Refs (DIR) README (DIR) LICENSE --- (DIR) commit c477e00e088231070ea6f83ca1ad48f1b8c1ee49 (HTM) Author: Anders Damsgaard <anders@adamsgaard.dk> Date: Mon, 5 Aug 2019 11:27:23 +0200 First commit, set up terminal and fix key handling Diffstat: A Makefile | 36 +++++++++++++++++++++++++++++++ A input.c | 15 +++++++++++++++ A input.h | 1 + A main.c | 13 +++++++++++++ A output.c | 7 +++++++ A output.h | 1 + A terminal.c | 58 ++++++++++++++++++++++++++++++ A terminal.h | 4 ++++ 8 files changed, 135 insertions(+), 0 deletions(-) --- (DIR) diff --git a/Makefile b/Makefile t@@ -0,0 +1,36 @@ +CFLAGS = -g -std=c99 -pedantic -Wall -Wextra +#LDFLAGS = -lm +SRC = $(wildcard *.c) +OBJ = $(patsubst %.c,%.o,$(SRC)) +HDR = $(wildcard *.h) +BIN = ./byote + +PREFIX ?= /usr/local +INSTALL ?= install +STRIP ?= strip + +default: $(BIN) + +$(BIN): $(OBJ) $(HDR) + $(CC) $(LDFLAGS) $(OBJ) -o $@ + +install: $(BIN) + $(STRIP) $(BIN) + $(INSTALL) -m 0755 -d $(DESTDIR)$(PREFIX)/bin + $(INSTALL) -m 0755 $(BIN) $(DESTDIR)$(PREFIX)/bin + +uninstall: + $(RM) $(DESTDIR)$(PREFIX)/bin/$(BIN) + +test: $(BIN) + make -C test/ + +memtest: $(BIN) + valgrind --error-exitcode=1 --leak-check=full $(BIN) -h + valgrind --error-exitcode=1 --leak-check=full $(BIN) -v + +clean: + $(RM) *.o + $(RM) $(BIN) + +.PHONY: default install uninstall test memtest clean (DIR) diff --git a/input.c b/input.c t@@ -0,0 +1,15 @@ +#include <stdlib.h> +#include "terminal.h" + +#define CTRL_KEY(k) ((k) & 0x1f) + +void +editor_process_keypress() +{ + char c = editor_read_key(); + switch (c) { + case CTRL_KEY('q'): + exit(0); + break; + } +} (DIR) diff --git a/input.h b/input.h t@@ -0,0 +1 @@ +void editor_process_keypress(); (DIR) diff --git a/main.c b/main.c t@@ -0,0 +1,13 @@ +#include "terminal.h" +#include "output.h" +#include "input.h" + +int +main(int argc, char* argv[]) +{ + enable_raw_mode(); + while (1) { + editor_process_keypress(); + } + return 0; +} (DIR) diff --git a/output.c b/output.c t@@ -0,0 +1,7 @@ +#include <unistd.h> + +void +editor_refresh_screen() +{ + write(STDOUT_FILENO, "\x1b[2J", 4); +} (DIR) diff --git a/output.h b/output.h t@@ -0,0 +1 @@ +void editor_refresh_screen(); (DIR) diff --git a/terminal.c b/terminal.c t@@ -0,0 +1,58 @@ +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <termios.h> +#include <unistd.h> + +struct termios orig_termios; + +void +die(const char *s) +{ + perror(s); + exit(1); +} + +void +disable_raw_mode() +{ + if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &orig_termios) == -1) + die("tcsetattr in disable_raw_mode()"); +} + +void +enable_raw_mode() +{ + struct termios raw; + + if (tcgetattr(STDIN_FILENO, &orig_termios) == -1) + die("tcgetattr in enable_raw_mode()"); + atexit(disable_raw_mode); + + /* fix modifier keys, set 8 bits per char, ignore interrupts */ + raw = orig_termios; + raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); + raw.c_oflag &= ~(OPOST); + raw.c_cflag |= (CS8); + raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG); + + /* set read() timeout in tenths of seconds */ + raw.c_cc[VMIN] = 0; + raw.c_cc[VTIME] = 1; + + /* apply terminal settings */ + if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw) == -1) + die("tcsetattr in enable_raw_mode()"); +} + +char +editor_read_key() +{ + int nread; + char c; + while ((nread = read(STDIN_FILENO, &c, 1)) != 1) { + if (nread == -1 && errno != EAGAIN) + die("read in editor_read_key()"); + } + return c; +} (DIR) diff --git a/terminal.h b/terminal.h t@@ -0,0 +1,4 @@ +void die(const char *s); +void disable_raw_mode(); +void enable_raw_mode(); +char editor_read_key();