Did everything I wanted
This commit is contained in:
parent
4f8851bafd
commit
00cd082403
8
README.md
Normal file
8
README.md
Normal 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
6
line.c
@ -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
4
line.h
@ -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
|
||||||
|
9
makefile
9
makefile
@ -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
45
page.c
@ -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
7
page.h
@ -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
132
text.c
@ -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
3
text.h
@ -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);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user