Did everything I wanted

This commit is contained in:
Mazar Farran 2014-09-30 16:56:16 -07:00
parent 4f8851bafd
commit 00cd082403
8 changed files with 166 additions and 58 deletions

8
README.md Normal file
View File

@ -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.

6
line.c
View File

@ -1,5 +1,11 @@
#include "line.h" #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. // Insert char into string.
void insert_char(LINE *s, char c, int index) void insert_char(LINE *s, char c, int index)
{ {

4
line.h
View File

@ -5,12 +5,16 @@
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#define LINE_SIZE 128 /* Max characters in a line. Expandable */
typedef struct typedef struct
{ {
char *line; char *line;
int tabs; // keeps track of tabs so we can offset
int size; // size of array, not string int size; // size of array, not string
} LINE; } LINE;
void init_line(LINE *s);
void insert_char(LINE *s, char c, int index); // inserts char to string void insert_char(LINE *s, char c, int index); // inserts char to string
void remove_char(LINE *s, int index); void remove_char(LINE *s, int index);
void expand(LINE *s); // doubles the size of the line void expand(LINE *s); // doubles the size of the line

View File

@ -1,19 +1,18 @@
# makefile for text.c # makefile for text.c
CXX=gcc CC=gcc
CFLAGS=-Wall -g CFLAGS=-Wall -g
OBJS=line.o page.o OBJS=line.o page.o
LIBS=-lncurses LIBS=-lncurses
text: text.c text.h $(OBJS) 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 line.o: line.c line.h
$(CXX) $(CFLAGS) -c line.c $(CC) $(CFLAGS) -c line.c
page.o: page.c page.h line.h page.o: page.c page.h line.h
$(CXX) $(CFLAGS) -c page.c $(CC) $(CFLAGS) -c page.c
clean: clean:
rm -f $(OBJS) text rm -f $(OBJS) text

45
page.c
View File

@ -1,16 +1,16 @@
#include "page.h" #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; 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)); init_line(p->text + i);
p->text[i].size = LINE_SIZE;
} }
p->numlines = 0; p->numlines = 0;
p->size = size;
} // init_page } // init_page
void dest_page(PAGE *p) void dest_page(PAGE *p)
@ -18,18 +18,20 @@ void dest_page(PAGE *p)
int i; int i;
for(i = 0; i < p->numlines; 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); free(p->text);
} // dest_page } // 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) void insert_line(PAGE *p, int index)
{ {
if( p->numlines >= p->size ) expand_page(p);
LINE newline; LINE newline;
newline.line = (char *)malloc(LINE_SIZE * sizeof(char)); init_line(&newline);
newline.line[0] = '\0'; newline.line[0] = '\0';
int i; int i;
@ -38,13 +40,14 @@ void insert_line(PAGE *p, int index)
p->text[i + 1] = p->text[i]; p->text[i + 1] = p->text[i];
p->text[index] = newline; p->text[index] = newline;
(p->numlines)++;
} // insert_line } // insert_line
void remove_line(PAGE *p, int index) void remove_line(PAGE *p, int index)
{ {
if( p->numlines > 0 ) if( p->numlines > 1 )
{ {
free(p->text[index].line); free(p->text[index].line);
@ -57,15 +60,31 @@ void remove_line(PAGE *p, int index)
} }
} // remove_line } // 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) void print_page(const PAGE *p, int start, int end)
{ {
int i; int i, line;
for(i = start; i < p->numlines && i < end; i++) for(i = start, line = 0; i < p->numlines && i < end; i++, line++)
{ {
move(i, 1); move(line, 0);
clrtoeol(); clrtoeol();
printw(" %s", p->text[i].line); printw(" %s", p->text[i].line);
} }
refresh(); refresh();
} } // print_page

7
page.h
View File

@ -6,19 +6,20 @@
#include "line.h" #include "line.h"
#define PAGE_SIZE 500 /* Max number of lines. Currently not expandable. */ #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 typedef struct
{ {
LINE *text; // lines of text LINE *text; // lines of text
int numlines; int numlines;
int size; // size of array
} PAGE; } PAGE;
void init_page(PAGE *p); void init_page(PAGE *p, int size);
void dest_page(PAGE *p); void dest_page(PAGE *p);
void insert_line(PAGE *p, int index); void insert_line(PAGE *p, int index);
void remove_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); void print_page(const PAGE *p, int start, int end);
#endif #endif

132
text.c
View File

@ -8,12 +8,23 @@
* -Loading * -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[]) int main(int argc, char *argv[])
{ {
PAGE page; PAGE page;
init_page(&page);
if(argc > 1) if(argc > 1)
{ {
@ -21,6 +32,7 @@ int main(int argc, char *argv[])
} }
else // initialize else // initialize
{ {
init_page(&page, PAGE_SIZE);
page.text[0].line[0] = '\0'; page.text[0].line[0] = '\0';
page.numlines = 1; page.numlines = 1;
} }
@ -30,76 +42,99 @@ int main(int argc, char *argv[])
noecho(); noecho();
keypad(stdscr, true); keypad(stdscr, true);
attron(A_REVERSE); int beg = 0;
mvprintw(LINES - 1, 0, "Press F4 to quit."); int end = WIN_SIZE;
attroff(A_REVERSE); int y, x; // position on screen
print_page(&page, 0, WIN_SIZE);
int y, x; update_status("Press F4 to quit");
print_page(&page, beg, end);
getyx(stdscr, y, x); getyx(stdscr, y, x);
//int yoffset = 0; // offset to account for screen scroll
while(true) while(true)
{ {
beg = 0 + y_offset;
end = WIN_SIZE + y_offset;
int ch = getch(); int ch = getch();
update_status("Press F4 to quit"); // default text
switch(ch) switch(ch)
{ {
case KEY_F(4): case KEY_F(4):
goto end; goto endnc;
break; break;
case KEY_F(5): case KEY_F(5):
save_file(argc, argv, &page); save_file(argc, argv, &page);
update_status("Saved as \'save.txt\'");
break; break;
case KEY_UP: case KEY_UP:
move_up(&page, &x, &y); move_up(&page, &x, &y);
print_loc(x, y);
break; break;
case KEY_DOWN: case KEY_DOWN:
move_down(&page, &x, &y); move_down(&page, &x, &y);
print_loc(x, y);
break; break;
case KEY_LEFT: case KEY_LEFT:
move_left(&x, &y); move_left(&x, &y);
print_loc(x, y);
break; break;
case KEY_RIGHT: case KEY_RIGHT:
move_right(&page, &x, &y); move_right(&page, &x, &y);
print_loc(x, y);
break; break;
case KEY_DC: case KEY_DC:
case 127: // backspace key... case 127: // backspace key...
case KEY_BACKSPACE: case KEY_BACKSPACE:
if(page.text[y].line[x - 2] == '\0') if(strlen(page.text[y + y_offset].line) == 0)
{ { // can only delete blank lines for now
remove_line(&page, y); remove_line(&page, y + y_offset);
move_up(&page, &x, &y); move_up(&page, &x, &y);
} }
else else if( x > 1 )
{ {
remove_char(&page.text[y], x - 2); // why 2? remove_char(&page.text[y + y_offset], x - 2); // delete
move_left(&x, &y); move_left(&x, &y); // char behind cursor
} }
print_page(&page, 0, WIN_SIZE); print_page(&page, beg, end);
move(y, x); move(y, x);
break; break;
case '\n': // newline case '\n': // newline
insert_line(&page, y + 1); insert_line(&page, y + y_offset + 1);
print_page(&page, 0, WIN_SIZE); print_page(&page, beg, end);
move_down(&page, &x, &y); move_down(&page, &x, &y);
break; break;
default: // all other chars default: // all other chars
if( isprint(ch) ) if( isprint(ch) )
{ {
insert_char(&page.text[y], ch, x - 1); insert_char(&page.text[y + y_offset], ch, x - 1);
print_page(&page, 0, WIN_SIZE); print_page(&page, beg, end);
move_right(&page, &x, &y); move_right(&page, &x, &y);
} }
} }
} }
end: endwin(); endnc: endwin();
/* end curses */ /* end curses */
dest_page(&page); dest_page(&page);
return EXIT_SUCCESS; return EXIT_SUCCESS;
} // main } // 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) void move_left(int *x, int *y)
{ {
if(*x - 1 > 0) move(*y, --(*x)); 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) 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) void move_up(PAGE *p, int *x, int *y)
{ {
if( *y > 0 ) --(*y); if( *y > 0 )
if( *x > strlen(p->text[*y].line) + 1 ) // cursor adjusts {
*x = strlen(p->text[*y].line) + 1; // to smaller lines --(*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); move(*y, *x);
} }
void move_down(PAGE *p, int *x, int *y) void move_down(PAGE *p, int *x, int *y)
{ {
if( *y < WIN_SIZE ) ++(*y); if( *y < WIN_SIZE - 1 && *y < p->numlines - 1 )
if( *x > strlen(p->text[*y].line) + 1 ) {
*x = strlen(p->text[*y].line) + 1; ++(*y);
move(*y, *x); }
}; 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) void load_file(int argc, char **argv, PAGE *p)
{ {
FILE *fp = fopen(argv[1], "r"); FILE *fp = fopen(argv[1], "r");
char ch = 0; int size = count_lines(argc, argv) * 2;
char ch = '\0';
int line, col; int line, col;
init_page(p, size);
for(line = 0; line < PAGE_SIZE && ch != EOF; line++) 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('\n', fp);
} }
fputc(EOF, fp);
fclose(fp); fclose(fp);
} // save_file } // save_file
/* saving and loading */

3
text.h
View File

@ -9,6 +9,9 @@
#include "page.h" #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 load_file(int argc, char **argv, PAGE *p);
void save_file(int argc, char **argv, PAGE *p); void save_file(int argc, char **argv, PAGE *p);