diff --git a/kte/Makefile b/kte/Makefile new file mode 100644 index 0000000..cd86be9 --- /dev/null +++ b/kte/Makefile @@ -0,0 +1,31 @@ +BIN := kte +OBJS := main.o terminal.o input.o + + +LDFLAGS := -lncurses +CFLAGS := -pedantic -Wall -Werror -Wextra -O0 -std=c99 -g + +.PHONY: all +all: build + +.PHONY: build +build: $(BIN) + +$(BIN): $(OBJS) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJS) + +.PHONY: clean +clean: + rm -f $(BIN) $(OBJS) *.core + +.PHONY: run +run: $(BIN) + reset + ./$(BIN) hello.txt + +.PHONY: install +install: $(BIN) + cp $(BIN) $(HOME)/bin/ + +%.o: %.c + $(CC) $(CFLAGS) -c $< \ No newline at end of file diff --git a/kte/defs.h b/kte/defs.h new file mode 100644 index 0000000..17d9565 --- /dev/null +++ b/kte/defs.h @@ -0,0 +1,51 @@ +/* + * defs.h + * common definitions for kte. + */ + + +#ifndef KTE_DEFS_H +#define KTE_DEFS_H + +#include + + +#define KTE_TAB_STOP 8 +#define KTE_MSG_TIME 5 + +#define MODE_NORMAL 0 +#define MODE_KCMD 1 + + +struct file_buffer { + char *filename; + int nrows; + + /* where are we in the file? */ + int curx, cury; +}; + + +static struct { + WINDOW *main; + WINDOW *status; + WINDOW *message; + + time_t msgtm; + + LIST_HEAD(listhead, file_buffer) listhead; +} editor; + + +/* terminal.c */ +void terminal_refresh(); +void terminal_init(); +void terminal_deinit(); +void terminal_message(char *s, int l); +int terminal_getch(); + +/* input.c */ +int handle_keypress(int c); + + +#endif /* KTE_DEFS_H */ diff --git a/kte/input.c b/kte/input.c new file mode 100644 index 0000000..9be10a4 --- /dev/null +++ b/kte/input.c @@ -0,0 +1,24 @@ +/* + * input.c: process key strokes and what not. + */ + +#include + +#include "defs.h" + + +/* + * given the key, maybe do something with it, and return whether this + * means the screen should be refreshed. + */ +int +handle_keypress(int c) +{ + static int mode = MODE_NORMAL; + + if (mode == MODE_NORMAL) { + printf("%02x\t", c); + } + + return 1; +} diff --git a/kte/main.c b/kte/main.c new file mode 100644 index 0000000..ff42766 --- /dev/null +++ b/kte/main.c @@ -0,0 +1,41 @@ +/* + * kyle's text editor + * + * this is the v2 from-scratch rewrite + */ + + +#include +#include + +#include "defs.h" + + +void +deinit() +{ + endwin(); +} + + +int +main() +{ + int c, up = 1; + + terminal_init(); + terminal_message("welcome to KTE", 14); + terminal_refresh(); + + atexit(terminal_deinit); + + do { + if (up) { + terminal_refresh(); + } + c = terminal_getch(); + up = handle_keypress(c); + } while (1); + + return 0; +} diff --git a/kte/notes.txt b/kte/notes.txt new file mode 100644 index 0000000..d46d4b6 --- /dev/null +++ b/kte/notes.txt @@ -0,0 +1 @@ ++ http://www.cs.ukzn.ac.za/~hughm/os/notes/ncurses.html - useful tutorial \ No newline at end of file diff --git a/kte/terminal.c b/kte/terminal.c new file mode 100644 index 0000000..b5ac37c --- /dev/null +++ b/kte/terminal.c @@ -0,0 +1,84 @@ +#include +#include +#include + +#include "defs.h" + + +void +terminal_refresh() +{ + wrefresh(editor.main); + wrefresh(editor.status); + + if ((time(NULL) - editor.msgtm) > KTE_MSG_TIME) { + wrefresh(editor.message); + } +} + + +/* + * init follows the standard ncurses setup process: initialise the + * screen, switch to non-buffered input, turn off local echo, and + * allow capturing of special keys, which otherwise requires a + * gnarly switch statement. + * + * Then, we need to set up the three windows: the editor main window, + * a status line, and a message bar. + */ +void +terminal_init() +{ + initscr(); + cbreak(); + noecho(); + + editor.main = newwin(LINES - 3, COLS-1, 0, 0); + assert(editor.main != NULL); + + editor.status = newwin(1, COLS-1, LINES-3, 0); + assert(editor.status != NULL); + wattron(editor.status, A_REVERSE); + + editor.message = newwin(1, COLS-1, LINES-2, 0); + assert(editor.status != NULL); + + keypad(editor.main, TRUE); + keypad(editor.message, TRUE); + + scrollok(editor.message, FALSE); + scrollok(editor.status, FALSE); + + editor.msgtm = 0; + wmove(editor.main, 0, 0); +} + + +void +terminal_deinit() +{ + endwin(); +} + + +void +terminal_message(char *m, int l) +{ + if (l > COLS) { + l = COLS; + } + + for (int i = 0; i < l; i++) { + waddch(editor.message, m[i]); + } + + editor.msgtm = time(NULL); + wrefresh(editor.message); +} + + +int +terminal_getch() +{ + return wgetch(editor.main); +}