Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <sys.h>
- #include <stdlib.h>
- #include <errno.h>
- #include <string.h>
- #define assert(expr) ((expr) ? assert_void() : assert_fail (#expr, __FILE__, __LINE__, __FUNCTION__))
- #define MAX_CMD_SIZE 15
- #define STATE_VIEW 0
- #define STATE_CMD 1
- #define STATE_EDIT 2
- #define CODE_SPECIAL 224
- #define CODE_LEFT_ARROW 1001
- #define CODE_UP_ARROW 1002
- #define CODE_RIGHT_ARROW 1003
- #define CODE_DOWN_ARROW 1004
- #define CODE_BACKSPACE 8
- #define CODE_DELETE 127
- #define CODE_ENTER 10
- #define CODE_ESC 27
- #define COLOR_FG_BLACK 30
- #define COLOR_FG_RED 31
- #define COLOR_FG_GREEN 32
- #define COLOR_FG_YELLOW 33
- #define COLOR_FG_BLUE 34
- #define COLOR_FG_MAGENTA 35
- #define COLOR_FG_CYAN 36
- #define COLOR_FG_WHITE 37
- #define COLOR_FG_DEFAULT 39
- #define COLOR_BG_BLACK 40
- #define COLOR_BG_RED 41
- #define COLOR_BG_GREEN 42
- #define COLOR_BG_YELLOW 43
- #define COLOR_BG_BLUE 44
- #define COLOR_BG_MAGENTA 45
- #define COLOR_BG_CYAN 46
- #define COLOR_BG_WHITE 47
- #define COLOR_BG_DEFAULT 49
- #define CMD_FLAG_QUIT 0x1
- #define CMD_FLAG_WRITE 0x02
- #define CMD_FLAG_FORCE 0x04
- #define ROW_FLAG_WRAPPED 0x1
- #define MAX_ROW_SIZE 1000
- /**
- * INFO:
- * 1.) when we insert a new row, we just keep editing the current row
- * 2.) when we delete the row, we set ROW_FLAG_WRAPPED and empty the row
- */
- struct row_t {
- int index;
- int seek_start;
- int seek_end;
- size_t size;
- int flags;
- char buffer[MAX_ROW_SIZE];
- bool free;
- };
- struct showed_row_t {
- int length;
- int index;
- int num;
- };
- /**
- * graphic terminal
- */
- static char *colors;
- static char *terminal;
- static char *colors2;
- static char *terminal2;
- static int g_rows;
- static int g_cols;
- static int g_size;
- static char filepath[200];
- static char app_version[] = "0.0.1";
- static fd_t fd;
- static int state;
- static bool app_quit;
- static size_t filepos;
- /**
- * buffer
- */
- static size_t buffer_size;
- static char *buffer;
- static size_t buffer_cursor;
- static int cursorx;
- static int cursory;
- static int pagex;
- static int pagey;
- static int prev_pagex;
- static int prev_pagey;
- static int prev_pagey_pos;
- static int next_pagey_pos;
- size_t rows_max_size;
- size_t rows_size;
- size_t available_rows_count_max;
- size_t available_rows_count;
- static struct row_t **rows;
- static struct row_t *available_rows;
- static struct showed_row_t *showed_rows;
- fd_t w_fd = 0;
- int toprow = 0;
- int prev_toprow = 0;
- int next_toprow = 0;
- void current_file_save();
- void assert_void () {
- /** void */
- }
- void assert_fail (const char *expr, const char *file, int line, const char *func) {
- printf("assertion failed: %s. %s:%d in %s\n", expr, file, line, func);
- exit(-1);
- }
- void reverse(char *s) {
- char *j;
- int i = strlen(s);
- strcpy(j,s);
- while (i-- >= 0)
- *(s++) = j[i];
- *s = '\0';
- }
- /* itoa()
- * converts an integer into a string */
- void itoa(int n, char *buffer, int base) {
- char *ptr = buffer;
- int lowbit;
- base >>= 1;
- do
- {
- lowbit = n & 1;
- n = (n >> 1) & 32767;
- *ptr = ((n % base) << 1) + lowbit;
- if (*ptr < 10)
- *ptr +='0';
- else
- *ptr +=55;
- ++ptr;
- }
- while (n /= base);
- *ptr = '\0';
- reverse (buffer); /* reverse string */
- }
- int g_min (int a, int b) {
- return a < b ? a : b;
- }
- int g_max (int a, int b) {
- return a > b ? a : b;
- }
- void g_cursor_at (int y, int x) {
- printf("\033[%d;%dH", y, x);
- }
- void g_cursor_at_pos (int pos) {
- int rows = pos / (g_cols);
- g_cursor_at (rows, pos - rows * g_cols);
- }
- void m_init () {
- buffer = NULL;
- buffer_size = 0;
- buffer_cursor = 0;
- cursorx = 0;
- cursory = 0;
- app_quit = false;
- state = STATE_VIEW;
- fd = -1;
- filepos = 0;
- g_rows = 0;
- g_cols = 0;
- g_size = 0;
- pagex = 0;
- pagey = 0;
- prev_pagex = pagex;
- prev_pagey = pagey;
- prev_pagey_pos = 0;
- next_pagey_pos = -1;
- rows = NULL;
- available_rows = NULL;
- rows_max_size = 0;
- rows_size = 0;
- available_rows_count = 0;
- w_fd = 0;
- toprow = 0;
- prev_toprow = 0;
- next_toprow = -1;
- }
- /**
- * graphic check
- */
- void g_check () {
- g_rows = 37;
- g_cols = 100;
- g_size = g_rows * g_cols;
- buffer_size = g_max(g_size, 500);
- }
- /**
- * graphic init
- */
- void g_init () {
- memset (terminal, ' ', g_size);
- memset (terminal2, ' ', g_size);
- for (int i =0, j = 0; i < g_size; i++, j+=2) {
- colors[j] = (char)COLOR_BG_BLACK;
- colors[j+1] = (char)COLOR_FG_WHITE;
- colors2[j] = (char)COLOR_BG_BLACK;
- colors2[j+1] = (char)COLOR_FG_WHITE;
- }
- g_cursor_at (0,0);
- }
- /**
- * clear screen
- */
- void g_clear () {
- printf("\033[2J");
- }
- /**
- * force flush screen
- */
- void g_flush_force () {
- g_clear();
- for (int i = 0, j = 0; i < g_size; i++, j+=2) {
- printf("\033[%d;%dm", (int)colors[j], (int)colors[j+1]);
- putchar(terminal[i]);
- }
- }
- /**
- * smart flust
- */
- void g_flush (bool rst) {
- int prev_cursorx = cursorx;
- int prev_cursory = cursory;
- int cursor_pos = cursorx+cursory*g_cols;
- char prev_cursor_color[2] = {colors[cursor_pos*2], colors[cursor_pos*2+1]};
- if (!rst) {
- colors[cursor_pos*2] = COLOR_BG_WHITE;
- colors[cursor_pos*2+1] = COLOR_FG_BLACK;
- }
- for (int i = 0, j = 0; i < g_size; i++, j+=2) {
- int y = i / (g_cols);
- int x = i - y * g_cols;
- if ((colors[j] != colors2[j])||(colors[j+1]!=colors2[j+1])||terminal[i] != terminal2[i]) {
- g_cursor_at (y, x);
- printf("\033[%d;%dm", (int)colors[j], (int)colors[j+1]);
- colors2[j]=colors[j];
- colors2[j+1]=colors[j+1];
- g_cursor_at (y, x);
- putchar(terminal[i]);
- terminal2[i] = terminal[i];
- }
- }
- colors[cursor_pos*2] = prev_cursor_color[0];
- colors[cursor_pos*2+1] = prev_cursor_color[1];
- cursorx = prev_cursorx;
- cursory = prev_cursory;
- g_cursor_at (cursory, cursorx);
- }
- void g_set_bg (size_t index, char color) {
- colors[index*2] = color;
- }
- void g_set_fg (size_t index, char color) {
- colors[index*2+1] = color;
- }
- void g_set_line (int row, char c, char color[2]) {
- for (int i = 0; i < g_cols; i++) {
- int tindex = row * g_cols + i;
- terminal[tindex] = ' ';
- g_set_bg(tindex, color[0]);
- g_set_fg(tindex, color[1]);
- }
- }
- void g_empty_line (int row) {
- char color[2] = { COLOR_BG_BLACK, COLOR_FG_WHITE };
- g_set_line (row, ' ', color);
- }
- void show_message (char *msg, size_t len) {
- g_empty_line (g_rows - 1);
- memcpy(terminal + (g_rows - 1) * g_cols, msg, g_min(len, g_cols));
- }
- int rows_bin_search (int index) {
- int l = 0;
- int r = rows_size;
- while (l + 1 < r) {
- int mid = (r + l) / 2;
- if (rows[mid]->index > index) {
- r = mid;
- }
- else {
- l = mid;
- }
- }
- while (l > 0 && rows[l - 1]->index == index) {
- l--;
- }
- return l;
- }
- int rows_find (int prow) {
- int findex = rows_bin_search (prow);
- if (findex >= 0 && findex < rows_size && rows[findex]->index == prow) {
- return findex;
- }
- return -1;
- }
- int rows_insert_n (struct row_t *row, int npos) {
- /** array insert (can be replaced with r/b tree) */
- int prow = row->index;
- /** approximate position determination */
- int findex = rows_bin_search (prow);
- if (findex < rows_size && rows[findex]->index != row->index) {
- findex++;
- }
- while (findex < rows_size && rows[findex]->index == row->index && npos--) {
- findex++;
- }
- if (rows_size == rows_max_size) {
- return -1;
- }
- memmove((rows) + (1 + findex), (rows) + findex, (rows_size - findex) * sizeof (*rows));
- rows[findex] = row;
- rows_size++;
- return findex;
- }
- int rows_insert (struct row_t *row) {
- return rows_insert_n(row, -1);
- }
- void clear_content_editor () {
- char color[2] = {COLOR_BG_BLACK, COLOR_FG_WHITE};
- for (int i = 0; i < g_rows - 1; i++) {
- g_set_line (i, ' ', color);
- }
- }
- void detect_previous_frame () {
- int c_row = 0;
- int c_col = 0;
- int m_rows = g_rows - 1 + 1;
- int left = filepos;
- int ltoprow = 1;
- int skiprows = 0;
- buffer_cursor = 0;
- if (pagey == 0) {
- prev_pagey_pos = 0;
- return;
- }
- /** setup */
- lseek (fd, left, SEEK_SET);
- bool rowupdated = true;
- while ((c_row < m_rows) && left) {
- if (rowupdated) {
- int array_row_index = rows_find(toprow-ltoprow /** c_row + pagey * g_rows **/);
- if (array_row_index != -1) {
- if (!(rows[array_row_index]->flags & ROW_FLAG_WRAPPED)) {
- int lltoprow = toprow-ltoprow;
- for (int ind = array_row_index; ind < rows_size && rows[ind]->index == lltoprow; ind++) {
- c_row++;
- /** check */
- if (c_row >= m_rows) {
- break;
- }
- }
- ltoprow++;
- }
- skiprows++;
- continue;
- }
- }
- int st = g_min(left, buffer_size - buffer_cursor);
- int rhs = g_min(read (fd, buffer, st), st);
- assert ((rhs>=0&&"read failed"));
- for (int i = rhs - 1; i >= 0; i--) {
- if (buffer[i] == '\n') {
- if (skiprows) {
- skiprows--;
- }
- else {
- prev_pagey_pos = g_max(left + i + 1, 0);
- c_row++;
- ltoprow++;
- rowupdated=true;
- }
- /** check */
- if (c_row >= m_rows) {
- break;
- }
- }
- }
- left -= rhs;
- lseek (fd, left, SEEK_SET);
- }
- if (!left) {
- prev_pagey_pos = 0;
- prev_toprow = 0;
- }
- else {
- prev_toprow = toprow - ltoprow;
- }
- buffer_cursor = 0;
- }
- void fetch_current_frame_with_row (struct row_t *frow) {
- int c_row = 0;
- int c_col = 0;
- int m_rows = g_rows - 1;
- int eof = false;
- int buffer_current = 0;
- int ltoprow = 0;
- bool last_row = true;
- buffer_cursor = 0;
- if (!frow) {
- /** clear screen */
- clear_content_editor ();
- if (prev_pagey != pagey) {
- if (prev_pagey_pos == -1) {
- detect_previous_frame ();
- }
- if (prev_pagey > pagey) {
- next_pagey_pos = filepos;
- next_toprow = toprow;
- filepos = prev_pagey_pos;
- toprow = prev_toprow;
- prev_pagey_pos = -1;
- prev_toprow = -1;
- }
- else if (next_pagey_pos != -1) {
- prev_pagey_pos = filepos;
- prev_toprow = toprow;
- filepos = next_pagey_pos;
- toprow = next_toprow;
- }
- }
- }
- int c_filepos = filepos;
- lseek (fd, c_filepos, SEEK_SET);
- int max_size = lseek (fd, 0, SEEK_END);
- int left = max_size - c_filepos;
- int nline = -1;
- int skipcols = pagex * g_cols;
- int skiprows = 0;
- lseek (fd, c_filepos, SEEK_SET);
- if (!frow) {
- next_pagey_pos = -1;
- }
- bool updated_row = frow == NULL;
- while ((skiprows || c_row < m_rows) && !eof) {
- nline = -1;
- if (!frow && updated_row && c_row < m_rows) {
- int array_row_index = rows_find(ltoprow + toprow /** c_row + pagey * g_rows **/);
- if (array_row_index != -1) {
- if (!(rows[array_row_index]->flags & ROW_FLAG_WRAPPED)) {
- int lltoprow = rows[array_row_index]->index;
- for (int ind = array_row_index; ind < rows_size && rows[ind]->index == lltoprow && c_row < m_rows; ind++) {
- /** exists */
- struct row_t *row = rows[ind];
- int s = row->size;
- int off = g_min(s, pagex * g_cols);
- s -= off;
- memcpy (terminal + g_cols * c_row, row->buffer + off, g_min(s, g_cols));
- showed_rows[c_row].length = s;
- showed_rows[c_row].index = lltoprow;
- showed_rows[c_row].num = ind - array_row_index;
- c_row++;
- c_col = 0;
- }
- }
- ltoprow++;
- skiprows++;
- updated_row = false;
- last_row = false;
- continue;
- }
- }
- int st = g_min(buffer_size - buffer_cursor, left);
- assert((st>=0&&"BUG"));
- if (st) {
- int rhs = read (fd, buffer + buffer_cursor, st);
- rhs = g_min(rhs, st);
- assert ((rhs >= 0 && "read failed"));
- if (rhs==0) {
- /** eof */
- eof = true;
- }
- left -= rhs;
- c_filepos += rhs;
- assert((c_filepos<=max_size&&"position > max_size"));
- lseek(fd, c_filepos, SEEK_SET);
- buffer_cursor += rhs;
- }
- else {
- eof = true;
- }
- for (int i = buffer_current; i < buffer_cursor; i++) {
- if (buffer[i] == '\n') {
- /** new row */
- nline = i+1;
- break;
- }
- }
- if (nline!=-1) {
- if (frow) {
- if (frow->index == ltoprow + toprow/**pagey * g_rows + c_row **/) {
- int s = nline-buffer_current-1;
- if (!frow->size) {
- frow->seek_start = c_filepos - s + 1;
- }
- frow->seek_end = c_filepos - (buffer_cursor - nline + 1) - 1;
- memcpy (frow->buffer + frow->size, buffer+buffer_current, s);
- frow->size += s;
- }
- c_row ++;
- ltoprow++;
- }
- else if (skiprows) {
- skiprows--;
- }
- else {
- int avaialable = g_cols - c_col;
- int s = g_min(avaialable, nline-buffer_current-1);
- int off = g_min(s, skipcols);
- skipcols -= off;
- s -= off;
- memcpy (terminal + g_cols * c_row + c_col, buffer+buffer_current+off, s);
- /* set row length */
- showed_rows[c_row].length = c_col + s;
- showed_rows[c_row].num = 0;
- showed_rows[c_row].index = ltoprow + toprow;
- c_row ++;
- ltoprow++;
- last_row = false;
- }
- c_col = 0;
- /** new row */
- updated_row = frow == NULL;
- if (!frow) {
- next_toprow = toprow + ltoprow;
- next_pagey_pos = c_filepos - buffer_cursor + nline;
- }
- buffer_current = nline;
- skipcols = pagex * g_cols;
- if (buffer_current>=buffer_cursor) {
- buffer_current = 0;
- buffer_cursor = 0;
- }
- if (frow && frow->index == /**pagey * g_rows + c_row**/ ltoprow + toprow - 1) {
- goto end;
- }
- continue;
- }
- if (frow) {
- if (frow->index == ltoprow+toprow/* pagey * g_rows + c_row */) {
- int s = buffer_cursor-buffer_current;
- if (!frow->size) {
- frow->seek_start = c_filepos - s;
- }
- memcpy (frow->buffer + frow->size, buffer+buffer_current, s);
- frow->size += s;
- }
- }
- else if (skiprows) {
- }
- else {
- int avaialable = g_cols - c_col;
- int s = g_min(avaialable, buffer_cursor-buffer_current);
- int off = g_min(s, skipcols);
- skipcols -= off;
- s -= off;
- memcpy (terminal + g_cols * c_row + c_col, buffer+buffer_current+off, s);
- c_col += s;
- last_row = true;
- }
- buffer_cursor = 0;
- buffer_current = 0;
- updated_row = false;
- }
- if (!frow && last_row) {
- /** last row */
- showed_rows[c_row].length = c_col;
- showed_rows[c_row].num = 0;
- showed_rows[c_row].index = ltoprow + toprow;
- c_row++;
- ltoprow++;
- }
- if (!frow) {
- /** empty rows */
- for (; c_row < g_rows - 1; c_row++) {
- showed_rows[c_row].length = 0;
- showed_rows[c_row].index = -1;
- showed_rows[c_row].num = 0;
- next_pagey_pos = -1;
- next_toprow = 0;
- }
- prev_pagey = pagey;
- prev_pagex = pagex;
- }
- end: buffer_cursor = 0;
- }
- void fetch_current_frame () {
- fetch_current_frame_with_row(NULL);
- }
- bool input_move (int c) {
- bool refetch = false;
- bool rr = false;
- switch (c)
- {
- case CODE_LEFT_ARROW:
- case 'a':
- if (cursorx) {
- cursorx--;
- }
- else {
- if (pagex) {
- pagex--;
- cursorx = g_cols - 1;
- refetch = true;
- }
- }
- break;
- case CODE_RIGHT_ARROW:
- case 'd':
- if (cursorx+1 < g_cols) {
- cursorx++;
- }
- else {
- pagex++;
- cursorx = 0;
- refetch = true;
- }
- break;
- case 'w':
- case CODE_UP_ARROW:
- rr = true;
- if (cursory) {
- cursory--;
- }
- else {
- if (pagey) {
- cursory = g_rows - 1 - 1;
- pagey--;
- refetch = true;
- }
- }
- break;
- case 's':
- case CODE_DOWN_ARROW:
- rr = true;
- if (cursory+1 < g_rows - 1) {
- cursory++;
- }
- else if (next_pagey_pos >= 0) {
- cursory = 0;
- pagey++;
- refetch = true;
- }
- break;
- default:
- return false;
- }
- if (refetch) {
- fetch_current_frame ();
- cursorx = g_min(cursorx, showed_rows[cursory].length);
- g_cursor_at(cursory, cursorx);
- }
- else {
- cursorx = g_min(cursorx, showed_rows[cursory].length);
- g_cursor_at(cursory, cursorx);
- }
- if (rr) {
- snprintf (buffer, buffer_size, "index: %d num: %d size: %d", showed_rows[cursory].index, showed_rows[cursory].num, showed_rows[cursory].length);
- show_message (buffer, strlen(buffer));
- }
- return true;
- }
- void apply_command (int flg) {
- if ((flg & CMD_FLAG_WRITE)) {
- /** write */
- current_file_save ();
- }
- if ((flg & CMD_FLAG_QUIT)) {
- if ((flg & CMD_FLAG_FORCE)) {
- app_quit = true;
- }
- /** check */
- }
- }
- void input_state_cmd (int c) {
- if (c == CODE_BACKSPACE || c == CODE_DELETE) {
- /** pop */
- if (buffer_cursor) {
- terminal[g_cols*(g_rows-1)+(--buffer_cursor)] = ' ';
- }
- if (buffer_cursor==0) {
- state = STATE_VIEW;
- g_empty_line(g_rows-1);
- }
- return;
- }
- if (!(c >= 32 && c <= 126)) {
- if (c == CODE_ENTER) {
- /** apply command */
- int cmd_flg = 0;
- for (int i = 1; i < buffer_cursor; i++) {
- switch (buffer[i])
- {
- case '!':
- cmd_flg |= CMD_FLAG_FORCE;
- break;
- case 'w':
- cmd_flg |= CMD_FLAG_WRITE;
- break;
- case 'q':
- cmd_flg |= CMD_FLAG_QUIT;
- break;
- default:
- break;
- }
- }
- apply_command (cmd_flg);
- /** disable command mode */
- buffer_cursor = 0;
- state = STATE_VIEW;
- g_empty_line(g_rows-1);
- }
- else if (c == CODE_ESC) {
- /** disable command mode */
- buffer_cursor = 0;
- state = STATE_VIEW;
- g_empty_line(g_rows-1);
- }
- else {
- /** invalid symbol */
- }
- return;
- }
- /** state edit */
- if (buffer_cursor >= MAX_CMD_SIZE) {
- /** no space left */
- return;
- }
- terminal[g_cols*(g_rows-1)+buffer_cursor] = (char)c;
- buffer[buffer_cursor++] = (char)c;
- }
- void input_state_view (int c) {
- /** state view */
- switch (c)
- {
- case ':': {
- /* enter command */
- state = STATE_CMD;
- input_state_cmd (c);
- break;
- }
- case 'i': {
- /* edit mode */
- state = STATE_EDIT;
- break;
- }
- default:
- if (input_move (c)) {}
- break;
- }
- }
- struct row_t *get_available_row_storage () {
- if (available_rows_count) {
- struct row_t *p = &available_rows[0];
- available_rows = p + 1;
- available_rows_count--;
- p->size = 0;
- p->seek_start = 0;
- p->seek_end = 0;
- p->flags = 0;
- p->index = 0;
- p->free = false;
- return p;
- }
- return NULL;
- }
- void fetch_row (struct row_t *row) {
- fetch_current_frame_with_row (row);
- row->buffer[row->size] = '\0';
- }
- int get_row_storage (int row) {
- int index = rows_find (row);
- if (index != -1) {
- return index;
- }
- struct row_t *p = get_available_row_storage();
- if (p) {
- p->index = row;
- index = rows_insert (p);
- if (index == -1) {
- /** no left space */
- return -1;
- }
- fetch_row (p);
- }
- return index;
- }
- void ret_row_storage (struct row_t *row) {
- row->free = true;
- while (available_rows_count < available_rows_count_max) {
- struct row_t *next = available_rows + 1;
- if (next->free) {
- available_rows = next;
- available_rows_count++;
- }
- else {
- break;
- }
- }
- }
- void current_file_save () {
- char buff[256];
- int index = 0;
- do {
- assert((index < 10));
- snprintf(buff, sizeof (buff), "%s.%d.tmp", filepath, index++);
- }
- while ((w_fd = open (filepath, O_RDWR|O_CREAT|O_TRUNC)) <= 0);
- size_t c_filepos = 0;
- buffer_cursor = 0;
- lseek (fd, c_filepos, SEEK_SET);
- while (true)
- {
- size_t s = buffer_size;
- if (index < rows_size) {
- s = g_min(s, c_filepos - rows[index]->seek_start);
- if (s==0) {
- int cursor = 0;
- while (cursor < rows[index]->size) {
- int wrhs = write (w_fd, rows[index]->buffer + cursor, rows[index]->size - cursor);
- wrhs = g_min(wrhs, rows[index]->size - cursor);
- assert((wrhs >= 0 && "Write failed"));
- cursor += wrhs;
- }
- c_filepos = rows[index]->seek_end;
- lseek (fd, c_filepos, SEEK_SET);
- index++;
- continue;
- }
- }
- int rhs = read (fd, buffer, s);
- // bug
- rhs = g_min(rhs, s);
- assert((rhs >= 0));
- if (rhs == 0) {
- break;
- }
- c_filepos += rhs;
- lseek (fd, c_filepos, SEEK_SET);
- int cursor = 0;
- while (cursor < rhs) {
- int wrhs = write (w_fd, buffer + cursor, rhs - cursor);
- wrhs = g_min(wrhs, rhs - cursor);
- assert((wrhs >= 0 && "Write failed"));
- cursor += wrhs;
- }
- }
- for (int i = rows_size - 1; i >= 0; i--) {
- ret_row_storage(rows[i]);
- }
- rows_size = 0;
- close (fd);
- close (w_fd);
- pagex = 0;
- pagey = 0;
- cursorx = 0;
- cursory = 0;
- filepos = 0;
- w_fd = 0;
- fd = 0;
- buffer_size = 0;
- buffer_cursor = 0;
- filepos = 0;
- fd = open (buff, O_RDONLY);
- fetch_current_frame ();
- }
- void input_state_edit (int c) {
- int prow = showed_rows[cursory].index;
- int pcol = pagex*g_cols + cursorx;
- bool refresh = false;
- struct row_t *row;
- /** state edit */
- if (c == CODE_ESC) {
- /** disable edit mode */
- state = STATE_VIEW;
- buffer_cursor = 0;
- }
- else if (prow >= 0) {
- if (c == CODE_DELETE || c == CODE_BACKSPACE) {
- int row_index = get_row_storage(prow);
- if (row_index!=-1) {
- assert(rows[row_index]->index == prow);
- int num = showed_rows[cursory].num;
- row_index += num;
- row=rows[row_index];
- int index = cursorx + pagex * g_cols;
- if (index) {
- memmove(row->buffer + index - 1, row->buffer + index, row->size - index);
- row->size --;
- refresh = true;
- showed_rows[cursory].length = g_min(g_cols, row->size);
- input_move (CODE_LEFT_ARROW);
- }
- else {
- bool res2 = row->index > 0;
- bool res1 = num > 0 || (res2 && (rows_size > row_index + 1 && rows[row_index + 1]->index == row->index));
- int xpos = g_cols - 1;
- if (res1||res2) {
- struct row_t *ltoprow = rows[row_index - 1];
- if ((ltoprow->flags & ROW_FLAG_WRAPPED)) {
- ltoprow->flags ^= ROW_FLAG_WRAPPED;
- }
- int s = g_min(ltoprow->size + row->size, MAX_ROW_SIZE) - ltoprow->size; /** buffer overflow */
- memcpy (ltoprow->buffer + ltoprow->size, row->buffer, s);
- xpos = g_min(ltoprow->size, xpos);
- ltoprow->size += s;
- row->size = 0;
- ret_row_storage(row);
- }
- /** delete row */
- if (res1) {
- /** row is a child or has a child */
- if (rows_size > row_index + 1) {
- memmove ((rows) + row_index, rows + (row_index + 1), sizeof (*rows) *(rows_size - (row_index + 1)));
- }
- rows_size--;
- fetch_current_frame();
- cursorx = xpos;
- input_move(CODE_UP_ARROW);
- }
- else if (res2) {
- /** no childs */
- row->flags |= ROW_FLAG_WRAPPED;
- row->size = 0;
- fetch_current_frame();
- cursorx = xpos;
- input_move(CODE_UP_ARROW);
- }
- }
- }
- }
- else if (c >= 32 && c <= 126) {
- int row_index = get_row_storage(prow);
- if (row_index!=-1) {
- assert(rows[row_index]->index == prow);
- // snprintf (buffer, buffer_size, "row_index: %d num: %d rows_size: %d", row_index, showed_rows[cursory].num, rows_size);
- // show_message (buffer, strlen(buffer));
- row_index += showed_rows[cursory].num;
- assert((row_index < rows_size));
- row=rows[row_index];
- int index = cursorx + pagex * g_cols;
- memmove(row->buffer + index + 1, row->buffer + index, row->size - index);
- row->buffer[index] = c;
- row->size ++;
- refresh = true;
- showed_rows[cursory].length = g_min(g_cols, g_max(0, row->size - g_cols * pagex));
- input_move (CODE_RIGHT_ARROW);
- }
- }
- else if (c == CODE_ENTER) {
- /** new line */
- int row_index = get_row_storage(prow);
- if (row_index!=-1) {
- assert(rows[row_index]->index == prow);
- int num = showed_rows[cursory].num + 1;
- assert(((row_index + num - 1) < rows_size));
- struct row_t *parent = rows[row_index + num - 1];
- row = get_available_row_storage();
- row->index = parent->index;
- row->flags = 0;
- row->size = 0;
- int new_row_index;
- if (rows_size > row_index + 1 && (rows[row_index+1]->flags & ROW_FLAG_WRAPPED)) {
- new_row_index = row_index + 1;
- rows[new_row_index]->flags = rows[new_row_index]->flags ^ ROW_FLAG_WRAPPED;
- }
- else {
- new_row_index = rows_insert_n(row, num);
- }
- row=rows[new_row_index];
- // for (int trow = cursory + 1; trow < g_rows && showed_rows[trow].index == row->index; trow++) {
- // showed_rows[trow].num++;
- // }
- // for (int trow = g_rows - 3; trow > cursory; trow--) {
- // //memmove(terminal + (trow+1) * g_cols, terminal + (trow) * g_cols, g_cols);
- // //memcpy (showed_rows + trow + 1, showed_rows + trow, sizeof (struct showed_row_t));
- // }
- int x = cursorx+pagex*g_cols;
- int s = g_max(0, parent->size - x);
- memcpy (row->buffer, parent->buffer + x, s);
- // memset (terminal + g_cols * cursory + cursorx, ' ', g_cols - cursorx);
- row->size = s;
- parent->size -= s;
- // showed_rows[cursory].length = g_max(0, showed_rows[cursory].length - s);
- // if (cursory + 1 != g_rows - 1) {
- // showed_rows[cursory + 1].index = row->index;
- // showed_rows[cursory + 1].length = g_min(g_cols, g_max(0, row->size - g_cols * pagex));
- // showed_rows[cursory + 1].num = num;
- // }
- pagex = 0;
- cursorx = 0;
- input_move (CODE_DOWN_ARROW);
- refresh = true;
- fetch_current_frame();
- }
- }
- }
- if (refresh) {
- int s = row->size;
- int off = g_min(s, pagex * g_cols);
- s -= off;
- s = g_min(s, g_cols);
- memcpy (terminal + g_cols * cursory, row->buffer + off, s);
- memset (terminal + g_cols * cursory + s, ' ', g_cols - s);
- }
- }
- void input_event_switch (int c) {
- switch (state)
- {
- case STATE_VIEW:
- input_state_view (c);
- break;
- case STATE_EDIT:
- input_state_edit (c);
- break;
- case STATE_CMD:
- input_state_cmd (c);
- break;
- default:
- break;
- }
- }
- void input_event (int c) {
- if (c == '\t') {
- for (int i = 0; i < 4; i++) {
- input_event_switch (' ');
- }
- return;
- }
- input_event_switch (c);
- }
- void clean_up () {
- for (int i = 0; i < g_rows; i++) {
- g_empty_line(i);
- }
- g_flush(true);
- g_cursor_at(0,0);
- if (fd>=0) {
- close(fd);
- fd=-1;
- }
- }
- void die () {
- clean_up();
- exit(-1);
- }
- void quit() {
- clean_up();
- exit(0);
- }
- void init_params (int argc, const char *argv[]) {
- #define OPTION_HELP 1
- #define OPTION_VERSION 2
- int option = 0;
- for (int i = 1; i < argc; i++) {
- int flg = option == 0 ? 0 : 3;
- size_t size = strlen(argv[i]);
- for (int j = 0; j < size; j++) {
- if (flg==2||flg==3) {
- /** get full option name (2) or full option value (3) (-vhello -> name: v, value: hello) */
- memcpy (buffer, (&(argv[i][0]))+j, size - j);
- buffer_cursor = size - j;
- break;
- }
- if (flg==4) {
- /** without value */
- printf("there are exists option without value\n");
- exit(-1);
- }
- if (argv[i][j] == '-') {
- flg++;
- }
- else if (flg==0) {
- /** default value */
- assert((size <= sizeof (filepath) && "default option buffer overflow"));
- memcpy ((char *)&filepath, argv[i], size);
- filepath[size]='\0';
- break;
- }
- else {
- switch (argv[i][j])
- {
- case 'h':
- option = OPTION_HELP;
- /** without value */
- flg = 4;
- break;
- case 'v':
- option = OPTION_VERSION;
- flg = 4;
- break;
- default:
- printf ("undefined option: -%c\n", argv[i][j]);
- exit(-1);
- }
- }
- }
- if (flg == 2) {
- /** need to grab full option value if needed */
- buffer[buffer_cursor]='\0';
- if (strcmp ((const char *)buffer, "help")==0) {
- option = OPTION_HELP;
- flg = 4;
- }
- else if (strcmp ((const char *)buffer, "version")==0) {
- option = OPTION_VERSION;
- flg = 4;
- }
- else {
- printf("invalid option: %s (%d)\n", (const char *)buffer, buffer_cursor);
- exit(-1);
- }
- }
- if (flg == 3) {
- /** name -> value */
- continue;
- }
- if (flg == 4) {
- /** name -> null */
- switch (option)
- {
- case OPTION_HELP:
- printf("Usage: minivim [options...] <filepath/>\n");
- printf("-h, --help Get help for commands\n");
- printf("-v, --version Show version number and quit\n");
- exit(0);
- break;
- case OPTION_VERSION:
- printf("Version: %s\n", app_version);
- exit(0);
- break;
- }
- option = 0;
- continue;
- }
- }
- #undef OPTION_VERSION
- #undef OPTION_HELP
- if (!strlen((const char *)(&filepath))) {
- printf("no input file\n");
- exit(-1);
- }
- fd = open ((const char *)(&filepath), O_RDWR|O_CREAT);
- if (fd < 0) {
- printf ("failed to open file %s. fd: %d\n", (const char *)(&filepath), (int)fd);
- exit(-1);
- }
- }
- int read_code () {
- int c = getchar ();
- assert (c <= 127);
- return c;
- }
- int main(int argc, char const *argv[]) {
- m_init();
- /* get graphic size*/
- g_check();
- buffer_size = g_max(37*100, 500);
- static char buffer_[37*100];
- static char terminal_[37*100];
- static char terminal2_[37*100];
- static char colors_[37*100*2];
- static char colors2_[37*100*2];
- /** we can edit only [n] rows */
- available_rows_count = 100;
- available_rows_count_max = available_rows_count;
- static struct row_t available_rows2[100];
- /** we can handle only 'rows_count' rows */
- rows_max_size = 1000;
- rows_size = 0;
- static struct row_t *rows2[1000];
- static struct showed_row_t showed_rows2[37];
- rows = (struct row_t **)&rows2;
- available_rows = (struct row_t *)&available_rows2;
- buffer = (char*)&buffer_;
- terminal = (char*)&terminal_;
- terminal2 = (char*)&terminal2_;
- colors = (char*)&colors_;
- colors2 = (char*)&colors2_;
- showed_rows = (struct showed_row_t *)&showed_rows2;
- /** fill */
- memset(available_rows, '\0', available_rows_count * sizeof (struct row_t));
- memset(showed_rows, '\0', g_rows * sizeof (struct showed_row_t));
- memset(rows, '\0', rows_max_size * sizeof (struct row_t*));
- init_params (argc, argv);
- /** init graphic */
- g_init();
- g_flush_force();
- fetch_current_frame();
- while (!app_quit) {
- /** main loop */
- g_flush(false);
- /** main loop */
- int c = read_code();
- input_event (c);
- }
- /** clean up */
- clean_up();
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement