From 37b85a90f50b387f4d9ac7952f9936203c0076f7 Mon Sep 17 00:00:00 2001 From: ElectricAlchemist Date: Tue, 22 Oct 2019 12:40:23 +0200 Subject: [PATCH] not so initial commit --- Makefile | 7 + hello | 1 + ste | Bin 0 -> 17944 bytes ste-tcc | Bin 0 -> 11708 bytes ste.c | 464 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 472 insertions(+) create mode 100644 Makefile create mode 100644 hello create mode 100755 ste create mode 100755 ste-tcc create mode 100644 ste.c diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..279c44b --- /dev/null +++ b/Makefile @@ -0,0 +1,7 @@ +CC=gcc +CFLAGS=-Wall -Wextra -pedantic -Werror +OFLAGS=-O3 +LFLAGS=-lncurses + +ste: ste.c + $(CC) $(CFLAGS) $(OFLAGS) $(LFLAGS) -o ste $^ \ No newline at end of file diff --git a/hello b/hello new file mode 100644 index 0000000..3b18e51 --- /dev/null +++ b/hello @@ -0,0 +1 @@ +hello world diff --git a/ste b/ste new file mode 100755 index 0000000000000000000000000000000000000000..0ef058de42d5ec788f0c3731620ab70430b5fff5 GIT binary patch literal 17944 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 Kz?$+z<$nN=C9Z`4 literal 0 HcmV?d00001 diff --git a/ste-tcc b/ste-tcc new file mode 100755 index 0000000000000000000000000000000000000000..af3931c79e53aa844f14d98f86adf1f8f687b865 GIT binary patch literal 11708 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 literal 0 HcmV?d00001 diff --git a/ste.c b/ste.c new file mode 100644 index 0000000..946901c --- /dev/null +++ b/ste.c @@ -0,0 +1,464 @@ +#include +#include +#include + +/* defines */ +#define CTRL(k) ((k) & 0x1f) // Control mask modifier +#define TABSIZE 4 // Tab size as used in render + +/* main data structure containing: + * -cursor position + * -real (matching memory) + * -offset (memory and screen offset) + * -render (drawn on the screen) + * -window size + * -statusbar message */ +struct term { + struct { + int x; + int y; + int off_x; + int off_y; + int r_x; + int r_y; + } cur; + + struct { + int x; + int y; + } dim; + + char statusbar[30]; + int ln_s; +} t; + +/* Row structure, defines actual and + * render chars, actual and render size + * and difference between render and + * real size of the row */ +typedef struct row { + int size; + char *chars; + int r_size; + char *render; + int delta; +} row; + +/* Rows structure (or file buffer) + * defines rows and teh number of rows */ +struct { + row *rw; + int rownum; +} rows; + +/* Prototypes */ +/* draw operations */ +static void drawBar (char *s); +static void drawScreen (); +static void drawLines (void); +static void updateRender (row *rw); +static void updateScroll (void); +static void cursorMove(int a); +static int getLineNumberSize (void); +static void lnMove (int y, int x); +static int curRealToRender (row *rw, int c_x); + +/* Row operations */ +static inline void rowInit (void); + +/* Terminal operations */ +static void termInit (void); +static void termExit (void); +static void termDie (char *s); + +/* file operations */ +static void fileOpen (char *filename); +void fileSave (char *filename); + +/* buffer operations */ +static void rowAdd (char *s, int len); + +/* garbage */ +//inline void bufferFree (void); +static int whatsThat (void); + +/* --------------------------------- main ------------------------------------ */ +int main (int argc, char *argv[]) +{ + /* Initialize the first row */ + rowInit(); + + /* Try to open the file */ + if (argc != 2) { + perror("File not found"); + exit(1); + } else fileOpen(argv[1]); + + /* Initialize the terminal in raw mode, + * start curses and initialize the term struct */ + termInit(); + + /* Set the statusbar left (static) message */ + sprintf(t.statusbar, "%s : %s %d lines %dx%d", argv[0], argv[1], rows.rownum, t.dim.y, t.dim.y); + + /* Main event loop */ + int c; + while (1) { + /* Redraw the screen */ + drawScreen(); + + /* Wait for an event (keypress) */ + switch (c = getch()) { + case (CTRL('q')): + termExit(); + break; + case (KEY_LEFT): + case (KEY_RIGHT): + case (KEY_UP): + case (KEY_DOWN): + cursorMove(c); + break; + } + } + + /* If by chance i find myself here be sure + * end curses mode and clenaup */ + termExit(); + return 0; +} + +/* ----------------------------- end of main ---------------------------------- */ + +void termInit (void) +{ + /* Init the screen and refresh */ + initscr(); + refresh(); + + /* Enable raw mode, this makes the termianl ignore + * interrupt signals like CTRL+C and CTRL+Z + * allowing us to make our own bindings */ + raw(); + + /* Allow use of function keys */ + keypad(stdscr, TRUE); + + /* Turn off echoing */ + noecho(); + + /* Set the tab size */ + set_tabsize(TABSIZE); + + /* Start color mode */ + start_color(); + init_pair(1, COLOR_BLUE, COLOR_BLACK); + + /* Populate the main data structure */ + getmaxyx(stdscr, t.dim.y, t.dim.x); + t.dim.y -= 1; + t.ln_s = getLineNumberSize(); + t.dim.x -= t.ln_s + 1; + + /* Initialize the data staructure */ + t.cur.x = t.cur.off_x = 0; + t.cur.y = t.cur.off_y = 0; +} + +/* Calculate the correct spacing for the line numbers + * based on the size of the file */ +int getLineNumberSize (void) +{ + int n = rows.rownum, l = 0; + for (l = 0; n > 0; l++) n /= 10; + return l + 1; +} + +void termExit (void) +{ +// bufferFree(); + erase(); + refresh(); + endwin(); + exit(0); +} + +void termDie (char *s) +{ + refresh(); + endwin(); + perror(s); + exit(1); +} + +/* ----------------------------- term operations -------------------------------- */ + +void drawScreen () +{ + /* Clear the screen */ + erase(); + /* Update Scroll */ + updateScroll(); + /* draw the lines */ + drawLines(); + /* draw the bar */ + drawBar(t.statusbar); + /* move back to the cursor position */ + lnMove(t.cur.y, t.cur.r_x); + /* refresh the screen */ + refresh(); +} + +/* Draw all the appropriate lines (following cursor) to the screen */ +void drawLines (void) +{ + int line = 0, ln; + /* move to the beginning of the screen */ + lnMove(0, 0); + + for (int i = 0; i < t.dim.y; i++) { + if (i >= rows.rownum) break; + ln = i + t.cur.off_y; + + /* Draw the line number */ + attron(COLOR_PAIR(1)); + mvprintw(i, 0, "%d", ln + 1); + attroff(COLOR_PAIR(1)); + lnMove(i, 0); + + /* Draw the line matcing render memory */ + if (rows.rw[ln].r_size >= t.cur.off_x) { + addnstr(&rows.rw[ln].render[t.cur.off_x], t.dim.x + 1 - rows.rw[ln].delta); + } + lnMove(++line, 0); + } + lnMove(t.cur.y, t.cur.x); +} + +/* Move avoiding the space allocated for line numbers */ +void lnMove (int y, int x) +{ + x += t.ln_s; + move(y, x); +} + +/* Draw the status bar at the bottom of the screen */ +void drawBar (char *s) +{ + /* Set maximum contrast for bar */ + attron(A_STANDOUT); + /* get the length of the statusbar text */ + int len = strlen(s); + /* Print the message */ + mvprintw(t.dim.y, 0, s); + /* Fill everything else with spaces */ + for (int i = len; i <= t.dim.x + t.ln_s; i++) + mvaddch(t.dim.y, i, ' '); + + char m[10]; + sprintf(m, "Zoom:\t%c", whatsThat()); + mvaddstr(t.dim.y, t.dim.x + t.ln_s - strlen(m), m); + + /* Return to normal contrast mode */ + attroff(A_STANDOUT); +} + +/* convert the cursor matchoing the memory to the drawn one */ +int curRealToRender (row *rw, int c_x) +{ + int r_x = 0; + for (int i = 0; i < c_x; i++) { + if (rw->chars[i] == '\t') r_x += (TABSIZE - 1) - (r_x % TABSIZE); + r_x++; + } + return r_x; +} + +/* -------------------------------- draw operations -------------------------------- */ + +/* Open a file and put it into a buffer line by line */ +void fileOpen (char *filename) +{ + FILE *fp = fopen(filename, "r"); + if (!fp) termDie("Cannot open file"); + + /* Init the linebuffer */ + char *line = NULL; + /* Set linecap to 0 so getline will atumatically allocate + * memory for the line buffer*/ + size_t linecap = 0; + ssize_t linelen; + + /* getline returns -1 if no new line is present */ + while ((linelen = getline(&line, &linecap, fp)) != -1) { + while (linelen > 0 && (line[linelen - 1] == '\n' || line[linelen - 1] == '\r')) + linelen--; + rowAdd(line, linelen); + } + /* free the line buffer */ + free(line); + /* close the file */ + fclose(fp); +} + +/* Add a row to the file buffer */ +void rowAdd (char *s, int len) +{ + /* Extend the block of memory containing the lines */ + rows.rw = realloc(rows.rw, sizeof(row) * (rows.rownum + 1)); + + /* Allocate memory for the line and copy it + * at the current row number */ + rows.rw[rows.rownum].chars = malloc(len + 1); + memcpy(rows.rw[rows.rownum].chars, s, len); + rows.rw[rows.rownum].chars[len] = '\0'; + rows.rw[rows.rownum].size = len; + updateRender(&rows.rw[rows.rownum]); + rows.rownum++; +} + +void updateRender (row *rw) +{ + /* count the special characters (only tabs for now) */ + int tabs = 0, i; + for (i = 0; i < rw->size; i++) { + if (rw->chars[i] == '\t') tabs++; + } + rw->render = NULL; + free(rw->render); + + /* Render is long as size with the added tab spaces - 1 + * (we already count for the \t as a char) */ + rw->render = malloc(rw->size + tabs * (TABSIZE - 1) + 1); + + if (rw->render == NULL) termDie ("malloc in updateRender"); + + /* put all the characters (substituing all special chars) + * into the render buffer */ + int off = 0; + for (i = 0; i < rw->size; i++) { + if (rw->chars[i] == '\t') { + for (int j = 0; j < TABSIZE; j++) + rw->render[off++] = ' '; + } else { + rw->render[off++] = rw->chars[i]; + } + } + rw->render[off] = '\0'; + rw->r_size = off; +} + +void rowInit (void) +{ + rows.rw = NULL; + rows.rownum = 0; +} + +/* ----------------------------- file operations --------------------------- */ + +/* take care of the cursor movement */ +void cursorMove (int a) +{ + switch (a) { + case (KEY_LEFT): + if (t.cur.x <= 0 && !t.cur.off_x) { + if (t.cur.y) { + t.cur.y--; + t.cur.x = rows.rw[t.cur.y + t.cur.off_y].size; + } + } else t.cur.x--; + break; + + case (KEY_RIGHT): + if (t.cur.x + t.cur.off_x >= rows.rw[t.cur.y + t.cur.off_y].size) { + if (t.cur.y + t.cur.off_y < rows.rownum - 1) { + t.cur.y++; + if (t.cur.off_x) t.cur.off_x = 0; + t.cur.x = rows.rw[t.cur.y + t.cur.off_y].size; + } + } else t.cur.x++; + break; + + case (KEY_UP): + if (t.cur.y + t.cur.off_y > 0) { + if (t.cur.y) t.cur.y--; + if (t.cur.x + t.cur.off_x > rows.rw[t.cur.y + t.cur.off_y].size) { + if (t.cur.off_x) t.cur.off_x = 0; + t.cur.x = rows.rw[t.cur.y + t.cur.off_y].size; + } + } + break; + + case (KEY_DOWN): + if (t.cur.y + t.cur.off_y < rows.rownum - 1) { + t.cur.y++; + if (t.cur.x + t.cur.off_x > rows.rw[t.cur.y + t.cur.off_y].size) { + if (t.cur.off_x) t.cur.off_x = 0; + t.cur.x = rows.rw[t.cur.y + t.cur.off_y].size; + } + } + break; + } +} + +void updateScroll (void) +{ + /* Set y offset */ + if (t.cur.y >= t.dim.y) { + if (t.cur.y == t.dim.y) t.cur.off_y++; + else t.cur.off_y += t.cur.y - t.dim.y; + + t.cur.y = t.dim.y - 1; + + } else if (t.cur.y <= 0 && t.cur.off_y > 0) { + t.cur.off_y--; + t.cur.y = 0; + } + + /* Set x offeset */ + if (t.cur.x >= t.dim.x) { + if (t.cur.x == t.dim.x) t.cur.off_x++; + else t.cur.off_x += t.cur.x - t.dim.x; + + t.cur.x = t.dim.x; + + } else if (t.cur.x <= 0 && t.cur.off_x > 0) { + t.cur.off_x--; + t.cur.x = 0; + } + /* convert the cursor from real to render */ + int ln = t.cur.y + t.cur.off_y; + t.cur.r_x = curRealToRender(&rows.rw[ln], t.cur.x); +} + +/*---------------------------------- scroll ------------------------------------*/ + +/* +void bufferFree (void) +{ + for (int i = 0; i < rows.rownum; i++) { + free(&rows.rw[i].chars); + free(&rows.rw[i].render); + } + free(rows.rw); +} +*/ + +/* See whats under the cursor (memory) */ +int whatsThat (void) { + int ln = t.cur.y + t.cur.off_y; + int c = rows.rw[ln].chars[t.cur.x + t.cur.off_x]; + switch (c) { + case ('\t'): + return '^'; + break; + case (' '): + return '~'; + break; + default: + return c; + break; + } + return 0; +} + +/*--------------------------------- garbage ------------------------------------*/ \ No newline at end of file