225 lines
4.1 KiB
C++
225 lines
4.1 KiB
C++
#include <ncurses.h>
|
|
#include <curses.h>
|
|
#include <string>
|
|
#include <vector>
|
|
#include <fstream>
|
|
|
|
#include "treap.hpp"
|
|
|
|
using std::string;
|
|
using std::vector;
|
|
|
|
#define ESC 27
|
|
#define ENTER 10
|
|
#define BS 127
|
|
#define adds(s) addstr(s.c_str())
|
|
enum mode_type { insert, normal };
|
|
|
|
|
|
// Global variables
|
|
treap file;
|
|
int row = 0, col = 0;
|
|
int file_offset = 0;
|
|
|
|
// Accessing the file
|
|
string get_line(int r) {
|
|
string line = (*file.find(file_offset+r)).text;
|
|
for(int i = 0; i < line.size(); ++i)
|
|
if(line[i] == '\t')
|
|
line[i] = ' ';
|
|
return line;
|
|
}
|
|
char get(int r, int s) { return get_line(file_offset+r)[s]; }
|
|
void set(int r, int s, char ch) { file.find(file_offset+r)->text[s] = ch; }
|
|
void insert_line(int r, string text = "") { file.insert(file_offset+r, text); }
|
|
void insert_char(int r, int s, char ch) { file.find(file_offset+r)->text.insert(s, string{ch}); }
|
|
void remove_char(int r, int s, int len=1) { file.find(file_offset+r)->text.erase(s,len); }
|
|
void remove_line(int r) { file.remove(file_offset+r); }
|
|
|
|
|
|
// Load file to buffer
|
|
bool load(string filename) {
|
|
std::ifstream infile(filename);
|
|
if(!infile.good())
|
|
return 1;
|
|
|
|
string line;
|
|
while (std::getline(infile, line))
|
|
file.insert(file.size(), line);
|
|
return 0;
|
|
}
|
|
// Save file from buffer
|
|
bool save(string filename) {
|
|
std::ofstream outfile(filename);
|
|
if(!outfile.good())
|
|
return 1;
|
|
|
|
for(int i = 0; i < file.size(); ++i)
|
|
outfile << get_line(i-file_offset) << std::endl;
|
|
return 0;
|
|
}
|
|
|
|
|
|
// Clear line
|
|
void clear_line(int pos) {
|
|
move(pos, 0);
|
|
clrtoeol();
|
|
}
|
|
// Print line
|
|
void print_line(int pos) {
|
|
clear_line(pos);
|
|
move(pos, 0);
|
|
adds(get_line(pos));
|
|
}
|
|
// Print file content
|
|
void print_file(int start = 0) {
|
|
for(int i = start; i < LINES; i++)
|
|
if(file_offset+i < file.size())
|
|
print_line(i);
|
|
else
|
|
clear_line(i);
|
|
}
|
|
// Splitting lines
|
|
string split_line(int r, int s) {
|
|
string line = get_line(r);
|
|
string ret = line.substr(s, line.size());
|
|
remove_char(r, s, line.size()-s);
|
|
return ret;
|
|
}
|
|
|
|
|
|
// TODO skoky a přesuny
|
|
// TODO kopirování
|
|
// TODO hledání a nahrazování
|
|
// TODO undo
|
|
|
|
|
|
// Jump to end of line
|
|
void jump_line_end() {
|
|
int line_size = get_line(row).size();
|
|
if(col > line_size)
|
|
col = line_size;
|
|
}
|
|
// Cursor movement
|
|
void move_cursor(char ch) {
|
|
switch(ch) {
|
|
case 'h':
|
|
if(col > 0)
|
|
move(row, --col);
|
|
break;
|
|
|
|
case 'j':
|
|
if(file_offset + row >= file.size()-1) break;
|
|
if(row < LINES-1) {
|
|
move(++row, col);
|
|
jump_line_end();
|
|
}
|
|
else if(row == LINES-1) {
|
|
file_offset++;
|
|
jump_line_end();
|
|
print_file();
|
|
}
|
|
break;
|
|
|
|
case 'k':
|
|
if(row > 0) {
|
|
move(--row, col);
|
|
jump_line_end();
|
|
}
|
|
else if(file_offset > 0) {
|
|
file_offset--;
|
|
jump_line_end();
|
|
print_file();
|
|
}
|
|
break;
|
|
|
|
case 'l':
|
|
if(col < get_line(row).size())
|
|
move(row, ++col);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
int main(int argc, char* argv[]) {
|
|
|
|
// Check valid filename and load
|
|
if(argc <= 1)
|
|
return 1;
|
|
string filename = argv[1];
|
|
if(load(filename))
|
|
return 1;
|
|
|
|
// Init
|
|
initscr();
|
|
refresh();
|
|
print_file();
|
|
|
|
mode_type mode = normal;
|
|
|
|
// Main loop
|
|
bool run = true;
|
|
while(run) {
|
|
move(row, col);
|
|
char ch = getch();
|
|
switch(mode) {
|
|
case normal:
|
|
print_line(row);
|
|
switch(ch) {
|
|
case 'h': case 'j': case 'k': case 'l':
|
|
move_cursor(ch);
|
|
break;
|
|
case 'd':
|
|
remove_line(row);
|
|
print_file(row);
|
|
break;
|
|
case 'x':
|
|
remove_char(row, col);
|
|
print_line(row);
|
|
break;
|
|
case 'o':
|
|
insert_line(row);
|
|
print_file(row);
|
|
break;
|
|
case 'q':
|
|
run = false;
|
|
break;
|
|
case 'w':
|
|
save(filename);
|
|
break;
|
|
case 'i':
|
|
mode = insert;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case insert:
|
|
switch(ch) {
|
|
case ESC:
|
|
mode = normal;
|
|
print_line(row);
|
|
break;
|
|
case BS:
|
|
if(col>0)
|
|
remove_char(row, --col);
|
|
print_line(row);
|
|
break;
|
|
case ENTER:
|
|
insert_line(row+1, split_line(row, col));
|
|
print_file(row++);
|
|
jump_line_end();
|
|
break;
|
|
default:
|
|
insert_char(row, col++, ch);
|
|
print_line(row);
|
|
break;
|
|
}
|
|
}
|
|
refresh();
|
|
}
|
|
|
|
// End
|
|
endwin();
|
|
return 0;
|
|
}
|