From 00cd082403f992d6fac77ba50dd26e7495b5ca64 Mon Sep 17 00:00:00 2001 From: Mazar Farran Date: Tue, 30 Sep 2014 16:56:16 -0700 Subject: [PATCH] Did everything I wanted --- README.md | 8 ++++ line.c | 6 +++ line.h | 4 ++ makefile | 9 ++-- page.c | 47 ++++++++++++------ page.h | 7 +-- text.c | 140 ++++++++++++++++++++++++++++++++++++++++-------------- text.h | 3 ++ 8 files changed, 166 insertions(+), 58 deletions(-) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..f1cf96f --- /dev/null +++ b/README.md @@ -0,0 +1,8 @@ +Text Editor +=========== + +I learned ncurses and figured why not. +Posting this now (9/30) because school is starting +so I don't plan on working on it anymore. + +Probably the most well-developed program I made this summer. diff --git a/line.c b/line.c index 81690c0..d9e1a37 100644 --- a/line.c +++ b/line.c @@ -1,5 +1,11 @@ #include "line.h" +void init_line(LINE *s) +{ + s->size = LINE_SIZE; + s->line = (char *)malloc(LINE_SIZE * sizeof(char)); +} // init_line + // Insert char into string. void insert_char(LINE *s, char c, int index) { diff --git a/line.h b/line.h index 8bfa9bb..08ea37a 100644 --- a/line.h +++ b/line.h @@ -5,12 +5,16 @@ #include #include +#define LINE_SIZE 128 /* Max characters in a line. Expandable */ + typedef struct { char *line; + int tabs; // keeps track of tabs so we can offset int size; // size of array, not string } LINE; +void init_line(LINE *s); void insert_char(LINE *s, char c, int index); // inserts char to string void remove_char(LINE *s, int index); void expand(LINE *s); // doubles the size of the line diff --git a/makefile b/makefile index fd52ff2..40ddb4d 100644 --- a/makefile +++ b/makefile @@ -1,19 +1,18 @@ # makefile for text.c -CXX=gcc +CC=gcc CFLAGS=-Wall -g OBJS=line.o page.o LIBS=-lncurses text: text.c text.h $(OBJS) - $(CXX) $(CFLAGS) -o text text.c $(OBJS) $(LIBS) + $(CC) $(CFLAGS) -o text text.c $(OBJS) $(LIBS) line.o: line.c line.h - $(CXX) $(CFLAGS) -c line.c + $(CC) $(CFLAGS) -c line.c page.o: page.c page.h line.h - $(CXX) $(CFLAGS) -c page.c + $(CC) $(CFLAGS) -c page.c clean: rm -f $(OBJS) text - diff --git a/page.c b/page.c index 7369a62..bd677e6 100644 --- a/page.c +++ b/page.c @@ -1,16 +1,16 @@ #include "page.h" -void init_page(PAGE *p) +void init_page(PAGE *p, int size) { - p->text = (LINE *)malloc(PAGE_SIZE * sizeof(LINE)); + p->text = (LINE *)malloc(size * sizeof(LINE)); int i; - for(i = 0; i < PAGE_SIZE; i++) + for(i = 0; i < size; i++) { - p->text[i].line = (char *)malloc(LINE_SIZE * sizeof(char)); - p->text[i].size = LINE_SIZE; + init_line(p->text + i); } p->numlines = 0; + p->size = size; } // init_page void dest_page(PAGE *p) @@ -18,18 +18,20 @@ void dest_page(PAGE *p) int i; for(i = 0; i < p->numlines; i++) { - free(p->text[i].line); + free(p->text[i].line); // maybe replace with dest_line() } free(p->text); } // dest_page -// WARNING: Will not expand once the limit of 500 lines reached +// WARNING: Expansion function implemented but not tested void insert_line(PAGE *p, int index) { + if( p->numlines >= p->size ) expand_page(p); + LINE newline; - newline.line = (char *)malloc(LINE_SIZE * sizeof(char)); + init_line(&newline); newline.line[0] = '\0'; int i; @@ -38,13 +40,14 @@ void insert_line(PAGE *p, int index) p->text[i + 1] = p->text[i]; p->text[index] = newline; + (p->numlines)++; } // insert_line void remove_line(PAGE *p, int index) { - if( p->numlines > 0 ) + if( p->numlines > 1 ) { free(p->text[index].line); @@ -57,15 +60,31 @@ void remove_line(PAGE *p, int index) } } // remove_line +void expand_page(PAGE *p) +{ + int newsize = p->size * 2; + LINE *newline = malloc(newsize * sizeof(LINE)); + + int i; + for(i = 0; i < p->size; i++) // copy old lines + newline[i] = p->text[i]; + for(i = p->size; i < newsize; i++) // init new lines + init_line(newline + i); + + p->text = newline; + p->size = newsize; +} // expand_page + +// NOTE: This moves the cursor to the end of the displayed text void print_page(const PAGE *p, int start, int end) { - int i; - for(i = start; i < p->numlines && i < end; i++) + int i, line; + for(i = start, line = 0; i < p->numlines && i < end; i++, line++) { - move(i, 1); + move(line, 0); clrtoeol(); - printw("%s", p->text[i].line); + printw(" %s", p->text[i].line); } refresh(); -} +} // print_page diff --git a/page.h b/page.h index ed99627..e1e800f 100644 --- a/page.h +++ b/page.h @@ -6,19 +6,20 @@ #include "line.h" #define PAGE_SIZE 500 /* Max number of lines. Currently not expandable. */ -#define LINE_SIZE 128 /* Max characters in a line. Expandable */ -#define WIN_SIZE LINES - 2 /* Size of window, making room for bottom prompt */ +#define WIN_SIZE (LINES - 2) /* Size of window, making room for bottom prompt */ typedef struct { LINE *text; // lines of text int numlines; + int size; // size of array } PAGE; -void init_page(PAGE *p); +void init_page(PAGE *p, int size); void dest_page(PAGE *p); void insert_line(PAGE *p, int index); void remove_line(PAGE *p, int index); +void expand_page(PAGE *p); void print_page(const PAGE *p, int start, int end); #endif diff --git a/text.c b/text.c index e3c21bd..843bec1 100644 --- a/text.c +++ b/text.c @@ -7,13 +7,24 @@ * -Saving * -Loading **/ - - // TODO: Create move_up, down, left, right functions + +int y_offset = 0; // TODO: move to local scope + +#define DEBUG + +void print_loc(int x, int y) +{ + #ifdef DEBUG + int oldx, oldy; + getyx(stdscr, oldy, oldx); + mvprintw(0, COLS - 20, "x: %d y: %d o: %d", x, y, y_offset); + move(oldy, oldx); + #endif +} int main(int argc, char *argv[]) -{ +{ PAGE page; - init_page(&page); if(argc > 1) { @@ -21,6 +32,7 @@ int main(int argc, char *argv[]) } else // initialize { + init_page(&page, PAGE_SIZE); page.text[0].line[0] = '\0'; page.numlines = 1; } @@ -29,77 +41,100 @@ int main(int argc, char *argv[]) initscr(); noecho(); keypad(stdscr, true); + + int beg = 0; + int end = WIN_SIZE; + int y, x; // position on screen + - attron(A_REVERSE); - mvprintw(LINES - 1, 0, "Press F4 to quit."); - attroff(A_REVERSE); - - print_page(&page, 0, WIN_SIZE); - - int y, x; + update_status("Press F4 to quit"); + + print_page(&page, beg, end); getyx(stdscr, y, x); - //int yoffset = 0; // offset to account for screen scroll while(true) { + beg = 0 + y_offset; + end = WIN_SIZE + y_offset; int ch = getch(); + update_status("Press F4 to quit"); // default text switch(ch) { case KEY_F(4): - goto end; + goto endnc; break; case KEY_F(5): save_file(argc, argv, &page); + update_status("Saved as \'save.txt\'"); break; case KEY_UP: move_up(&page, &x, &y); + print_loc(x, y); break; case KEY_DOWN: move_down(&page, &x, &y); + print_loc(x, y); break; case KEY_LEFT: move_left(&x, &y); + print_loc(x, y); break; case KEY_RIGHT: move_right(&page, &x, &y); + print_loc(x, y); break; case KEY_DC: case 127: // backspace key... case KEY_BACKSPACE: - if(page.text[y].line[x - 2] == '\0') - { - remove_line(&page, y); + if(strlen(page.text[y + y_offset].line) == 0) + { // can only delete blank lines for now + remove_line(&page, y + y_offset); move_up(&page, &x, &y); } - else + else if( x > 1 ) { - remove_char(&page.text[y], x - 2); // why 2? - move_left(&x, &y); + remove_char(&page.text[y + y_offset], x - 2); // delete + move_left(&x, &y); // char behind cursor } - print_page(&page, 0, WIN_SIZE); + print_page(&page, beg, end); move(y, x); break; case '\n': // newline - insert_line(&page, y + 1); - print_page(&page, 0, WIN_SIZE); + insert_line(&page, y + y_offset + 1); + print_page(&page, beg, end); move_down(&page, &x, &y); break; default: // all other chars if( isprint(ch) ) { - insert_char(&page.text[y], ch, x - 1); - print_page(&page, 0, WIN_SIZE); + insert_char(&page.text[y + y_offset], ch, x - 1); + print_page(&page, beg, end); move_right(&page, &x, &y); } } } -end: endwin(); +endnc: endwin(); /* end curses */ dest_page(&page); return EXIT_SUCCESS; } // main +// prints a message at the bottom of the window +void update_status(char *info) +{ + int oldy, oldx; getyx(stdscr, oldy, oldx); + + attron(A_REVERSE); + move(LINES - 1, 0); + clrtoeol(); + printw(info); + attroff(A_REVERSE); + + move(oldy, oldx); +} // update_status + +/* movement */ void move_left(int *x, int *y) { if(*x - 1 > 0) move(*y, --(*x)); @@ -108,29 +143,62 @@ void move_left(int *x, int *y) void move_right(PAGE *p, int *x, int *y) { - if(*x <= strlen(p->text[*y].line)) move(*y, ++(*x)); + if(*x <= strlen(p->text[*y + y_offset].line)) move(*y, ++(*x)); } void move_up(PAGE *p, int *x, int *y) { - if( *y > 0 ) --(*y); - if( *x > strlen(p->text[*y].line) + 1 ) // cursor adjusts - *x = strlen(p->text[*y].line) + 1; // to smaller lines + if( *y > 0 ) + { + --(*y); + } + else if (y_offset > 0) + { + --(y_offset); + print_page(p, 0 + y_offset, WIN_SIZE + y_offset); + } + if( *x > strlen(p->text[*y + y_offset].line) + 1 ) // cursor adjusts + *x = strlen(p->text[*y + y_offset].line) + 1; // to smaller lines move(*y, *x); } void move_down(PAGE *p, int *x, int *y) { - if( *y < WIN_SIZE ) ++(*y); - if( *x > strlen(p->text[*y].line) + 1 ) - *x = strlen(p->text[*y].line) + 1; - move(*y, *x); -}; + if( *y < WIN_SIZE - 1 && *y < p->numlines - 1 ) + { + ++(*y); + } + else if ( *y + y_offset < p->numlines - 1 ) + { + ++(y_offset); + print_page(p, 0 + y_offset, WIN_SIZE + y_offset); + } + if( *x > strlen(p->text[*y + y_offset].line) + 1 ) + *x = strlen(p->text[*y + y_offset].line) + 1; + move(*y, *x); +} +/* movement */ + +int count_lines(int argc, char **argv) +{ + FILE *fp = fopen(argv[1], "r"); + char ch = '\0'; + int count = 0; + while((ch = fgetc(fp)) != EOF) + if( ch == '\n' ) + count++; + + return count; +} // count_lines + +/* saving and loading */ void load_file(int argc, char **argv, PAGE *p) { FILE *fp = fopen(argv[1], "r"); - char ch = 0; + int size = count_lines(argc, argv) * 2; + char ch = '\0'; int line, col; + init_page(p, size); for(line = 0; line < PAGE_SIZE && ch != EOF; line++) { @@ -161,8 +229,8 @@ void save_file(int argc, char **argv, PAGE *p) } fputc('\n', fp); } - fputc(EOF, fp); fclose(fp); } // save_file +/* saving and loading */ diff --git a/text.h b/text.h index 630ebba..bdc38e3 100644 --- a/text.h +++ b/text.h @@ -9,6 +9,9 @@ #include "page.h" +void update_status(char *info); + +int count_lines(int argc, char **argv); void load_file(int argc, char **argv, PAGE *p); void save_file(int argc, char **argv, PAGE *p);