Compare commits

...

9 Commits

158
editor.c
View File

@@ -5,8 +5,13 @@
#include <string.h> #include <string.h>
#include <stdbool.h> #include <stdbool.h>
#include <unistd.h> #include <unistd.h>
#include <sys/stat.h>
#define ctrl(x) ((x) & 0x1f)
int index_to_start = 0; int index_to_start = 0;
WINDOW* mainwin;
WINDOW* statusbar;
typedef struct Buffer_struct Buffer; typedef struct Buffer_struct Buffer;
struct Buffer_struct { struct Buffer_struct {
@@ -58,13 +63,20 @@ void buffer_insert(char ch, Buffer* buffer) {
} }
} }
void buffer_delete(Buffer* buffer) { void buffer_delete_front(Buffer* buffer) {
if (buffer->start != buffer->text) { if (buffer->start != buffer->text) {
buffer->start--; buffer->start--;
buffer->gap_size++; buffer->gap_size++;
} }
} }
void buffer_delete_back(Buffer* buffer) {
if (buffer->end != buffer->text + buffer->size) {
buffer->end++;
buffer->gap_size++;
}
}
void buffer_right(Buffer* buffer) { void buffer_right(Buffer* buffer) {
if (buffer->end != buffer->text + buffer->size) { if (buffer->end != buffer->text + buffer->size) {
char c = *(buffer->end); char c = *(buffer->end);
@@ -74,6 +86,12 @@ void buffer_right(Buffer* buffer) {
} }
} }
void right_key_handler(Buffer* buffer) {
if ((*(buffer->end) != '\n') || (getcury(mainwin) + 1 < getmaxy(mainwin))) {
buffer_right(buffer);
}
}
void buffer_left(Buffer* buffer) { void buffer_left(Buffer* buffer) {
if (buffer->start != buffer->text) { if (buffer->start != buffer->text) {
char c = *(buffer->start - 1); char c = *(buffer->start - 1);
@@ -84,7 +102,11 @@ void buffer_left(Buffer* buffer) {
} }
} }
void left_key_handler(Buffer* buffer) {
if ((getcurx(mainwin) > 0) || (getcury(mainwin) > 0)) {
buffer_left(buffer);
}
}
void scroll_page_down_handler(Buffer* buffer) { void scroll_page_down_handler(Buffer* buffer) {
while (*(buffer->text + index_to_start) != '\n') { while (*(buffer->text + index_to_start) != '\n') {
@@ -94,18 +116,18 @@ void scroll_page_down_handler(Buffer* buffer) {
} }
void page_down_handler(Buffer* buffer) { void page_down_handler(Buffer* buffer) {
if ((getcury(mainwin) + 1) == getmaxy(mainwin)) {
scroll_page_down_handler(buffer);
}
buffer_right(buffer); /* I must advance the cursor at least buffer_right(buffer); /* I must advance the cursor at least
once, so this hardcoded statement is fine. */ once, so this hardcoded statement is fine. */
while (*(buffer->start - 1) != '\n') { while ((*(buffer->start - 1) != '\n') && (buffer->end != (buffer->text + buffer->size))) {
buffer_right(buffer); buffer_right(buffer);
} }
if ((getcury(stdscr) + 1) == getmaxy(stdscr)) {
scroll_page_down_handler(buffer);
}
/* You would think that I need to call 'buffer_right' once /* You would think that I need to call 'buffer_right' once
more, to advance the cursor onto the next line. In fact, if more, to advance the cursor onto the next line. In fact, if
you think about it, the place where the cursor (the rectangle) you think about it, the place where the cursor (the rectangle)
@@ -140,28 +162,67 @@ void page_up_handler(Buffer* buffer) {
} }
if ((getcury(stdscr) == 0) && (index_to_start > 0)) { if ((getcury(mainwin) == 0) && (index_to_start > 0)) {
scroll_page_up_handler(buffer); scroll_page_up_handler(buffer);
} }
} }
void init_curses() { void keypress_handler(char key, Buffer* buffer) {
initscr(); buffer_insert(key,buffer);
noecho(); if ((getcury(mainwin) + 1) == getmaxy(mainwin)) {
keypad(stdscr,TRUE); scroll_page_down_handler(buffer);
cbreak(); }
// scrollok(stdscr,TRUE);
} }
void sigint_handler(int dummy) { int is_file(char* path) {
struct stat st;
if (stat(path, &st) < 0) {
return -1;
}
return S_ISREG(st.st_mode);
}
void save_text_helper(Buffer* buffer,char* filename) {
FILE* file = fopen(filename,"w");
int i = 0;
while (i < buffer->size) {
if ((buffer->start - buffer->text) == i) { /* If we have encountered
the start of the gap */
i += buffer->gap_size;
}
if (i >= buffer->size) {
break;
}
fputc(*(buffer->text + i),file);
i++;
}
}
void init_curses() {
initscr();
mainwin = newwin(getmaxy(stdscr)-1,getmaxx(stdscr),0,0);
statusbar = newwin(1,getmaxx(stdscr),getmaxy(stdscr)-1,0);
wattrset(statusbar,A_REVERSE);
mvwhline(statusbar,0,0,' ',getmaxx(statusbar));
mvwprintw(statusbar,0,0,"Welcome to Editor!");
wrefresh(statusbar);
noecho();
keypad(stdscr,TRUE);
keypad(mainwin,TRUE);
raw();
}
void end_ncurses() {
endwin(); endwin();
exit(130); exit(130);
} }
int main(int argc, char** argv) { int main(int argc, char** argv) {
signal(SIGINT,sigint_handler);
Buffer* buffer = new_buffer(10); Buffer* buffer = new_buffer(10);
FILE* logfile = fopen("logfile.txt","w"); FILE* logfile = fopen("logfile.txt","w");
@@ -175,14 +236,10 @@ int main(int argc, char** argv) {
num_of_chars++; num_of_chars++;
} }
} else { while (num_of_chars > 0) {
printf("File does not exist.\n"); buffer_left(buffer);
return -10; num_of_chars--;
} }
while (num_of_chars > 0) {
buffer_left(buffer);
num_of_chars--;
} }
} }
@@ -191,7 +248,7 @@ int main(int argc, char** argv) {
int y, x; int y, x;
while (true) { while (true) {
clear(); wclear(mainwin);
int i=index_to_start; int i=index_to_start;
if ((buffer->start != buffer->text) || (buffer->gap_size != buffer->size)) { /* We don't want to print the string, if the if ((buffer->start != buffer->text) || (buffer->gap_size != buffer->size)) { /* We don't want to print the string, if the
@@ -200,44 +257,52 @@ int main(int argc, char** argv) {
while (i < buffer->size) { while (i < buffer->size) {
if ((buffer->start - buffer->text) == i) { /* If we have encountered if ((buffer->start - buffer->text) == i) { /* If we have encountered
the start of the gap */ the start of the gap */
getyx(stdscr,y,x); getyx(mainwin,y,x);
i += buffer->gap_size; i += buffer->gap_size;
} }
if (i >= buffer->size) { if (i >= buffer->size) {
break; break;
} }
addch(*(buffer->text + i));
i++;
fprintf(logfile,"At line %d of %d\n",getcury(stdscr),getmaxy(stdscr)); fprintf(logfile,"At line %d of %d\n",getcury(mainwin),getmaxy(mainwin));
if (*(buffer->text + i) == '\n' && ((getcury(stdscr) + 1) == getmaxy(stdscr))) { if (*(buffer->text + i) == '\n' && ((getcury(mainwin) + 1) == getmaxy(mainwin))) {
fprintf(logfile,"Read newline\n"); fprintf(logfile,"Read newline\n");
break; break;
} }
waddch(mainwin,*(buffer->text + i));
i++;
} }
move(y,x); wmove(mainwin,y,x);
wrefresh(mainwin);
} }
ch = getch(); ch = wgetch(mainwin);
switch(ch) { switch(ch) {
case KEY_BACKSPACE: case KEY_BACKSPACE:
buffer_delete(buffer); buffer_delete_front(buffer);
break;
case KEY_DC:
buffer_delete_back(buffer);
break; break;
case KEY_LEFT: case KEY_LEFT:
buffer_left(buffer); left_key_handler(buffer);
break; break;
case KEY_RIGHT: case KEY_RIGHT:
buffer_right(buffer); right_key_handler(buffer);
break; break;
case 10: /* Enter key */ case 10: /* Enter key */
buffer_insert('\n',buffer); /* Why handle this separately? keypress_handler('\n',buffer); /* Why handle this separately?
Because, by default, curses seems to send '\r\n', Because, by default, curses seems to send '\r\n',
which is technically two characters. I should which is technically two characters. I should
probably add some code to deal with this scenario probably add some code to deal with this scenario
@@ -246,19 +311,32 @@ int main(int argc, char** argv) {
break; break;
case KEY_NPAGE: case KEY_NPAGE:
page_down_handler(buffer); page_down_handler(buffer);
break; break;
case KEY_PPAGE: case KEY_PPAGE:
page_up_handler(buffer); page_up_handler(buffer);
break; break;
case ctrl(KEY_NPAGE):
abort();
case ctrl('s'):
if (argc == 2) {
save_text_helper(buffer,argv[1]);
} else if (argc == 1) {
save_text_helper(buffer,NULL);
}
break;
case ctrl('c'):
end_ncurses();
break;
default: default:
buffer_insert(ch,buffer); keypress_handler(ch,buffer);
} }
continue_while_loop:
} }
endwin(); endwin();