Generalize positions and count-type

This commit is contained in:
Matúš Púll 2025-04-16 12:44:33 +02:00
parent 76eac35213
commit 1e7ea2b5a2

177
main.cpp
View file

@ -13,32 +13,33 @@ using std::string;
#define adds(s) addstr(s.c_str()) #define adds(s) addstr(s.c_str())
enum mode_type { INSERT, NORMAL, SELECT }; enum mode_type { INSERT, NORMAL, SELECT };
struct position { count_type r, c; };
// Global variables // Global variables
treap file; treap file;
int row = 0, col = 0; position cur = {0, 0};
int file_offset = 0; count_type file_offset = 0;
int clp_r, clp_c; position clp;
treap selection; treap selection;
// Accessing the file // Accessing the file
string get_line(int r) { string get_line(count_type r) {
string line = (*file.find(file_offset+r)).text; string line = (*file.find(file_offset+r)).text;
for(int i = 0; i < line.size(); ++i) for(count_type i = 0; i < line.size(); ++i)
if(line[i] == '\t') if(line[i] == '\t')
line[i] = ' '; line[i] = ' ';
return line; return line;
} }
char get(int r, int s) { return get_line(file_offset+r)[s]; } char get(position p) { return get_line(file_offset+p.r)[p.c]; }
void set(int r, int s, char ch) { file.find(file_offset+r)->text[s] = ch; } void set(position p, char ch) { file.find(file_offset+p.r)->text[p.c] = ch; }
void new_line(int r, string text = "") { file.insert(file_offset+r, text); } void new_line(count_type r, string text = "") { file.insert(file_offset+r, text); }
void insert(int r, int s, string t) { file.find(file_offset+r)->text.insert(s, t); } void insert(position p, string t) { file.find(file_offset+p.r)->text.insert(p.c, t); }
void insert(int r, int s, char ch) { insert(r, s, string{ch}); } void insert(position p, char ch) { insert(p, string{ch}); }
void append(string t) { file.append(t); } void append(string t) { file.append(t); }
void remove(int r, int s, int len=1) { file.find(file_offset+r)->text.erase(s,len); } void remove(position p, count_type len=1) { file.find(file_offset+p.r)->text.erase(p.c,len); }
void remove(int r) { file.remove(file_offset+r); } void remove(count_type r) { file.remove(file_offset+r); }
int get_number() { count_type get_number() {
char ch = '0'; char ch = '0';
string s = ""; string s = "";
while(ch >= '0' && ch <= '9') { while(ch >= '0' && ch <= '9') {
@ -65,82 +66,82 @@ bool save(string filename) {
if(!outfile.good()) if(!outfile.good())
return 1; return 1;
for(int i = 0; i < file.size(); ++i) for(count_type i = 0; i < file.size(); ++i)
outfile << get_line(i-file_offset) << std::endl; outfile << get_line(i-file_offset) << std::endl;
return 0; return 0;
} }
// Clear line // Clear line
void clear_line(int pos) { void clear_line(count_type r) {
move(pos, 0); move(r, 0);
clrtoeol(); clrtoeol();
} }
// Print line // Print line
void print_line(int pos) { void print_line(count_type r) {
clear_line(pos); clear_line(r);
move(pos, 0); move(r, 0);
adds(get_line(pos)); adds(get_line(r));
} }
// Print file content // Print file content
void print_file(int start = 0) { void print_file(count_type start = 0) {
for(int i = start; i < LINES; i++) for(count_type i = start; i < LINES; i++)
if(file_offset+i < file.size()) if(file_offset+i < file.size())
print_line(i); print_line(i);
else else
clear_line(i); clear_line(i);
} }
// Splitting lines // Splitting lines
void split_line(int r, int s) { void split_line(position p) {
string line = get_line(r); string line = get_line(p.r);
string newline = line.substr(s, line.size()); string newline = line.substr(p.c, line.size());
remove(r, s, line.size()-s); remove(p, line.size()-p.c);
new_line(r+1, newline); new_line(p.r+1, newline);
} }
// Copying // Copying
void copy_selection() { void copy_selection() {
// Determine first and last selected position // Determine first and last selected position
int start_r = row, start_c = col, end_r = clp_r, end_c = clp_c; position start = cur, end = clp;
if(clp_r < row || (clp_r == row && clp_c < col)) if(clp.r < cur.r || (clp.r == cur.r && clp.c < cur.c))
start_r = clp_r, start_c = clp_c, end_r = row, end_c = col; start = clp, end = cur;
// Clear previous selection // Clear previous selection
selection.clear(); selection.clear();
// Add all complete lines in between // Add all complete lines in between
for(int r = start_r+1; r < end_r; ++r) for(count_type r = start.r+1; r < end.r; ++r)
selection.append(get_line(r)); selection.append(get_line(r));
// Add first line end // Add first line end
string start_line = get_line(start_r); string start_line = get_line(start.r);
int size = ((start_r == end_r) ? end_c+1 : start_line.size()) - start_c; count_type size = ((start.r == end.r) ? end.c+1 : start_line.size()) - start.c;
string start = start_line.substr(start_c, size); string start_text = start_line.substr(start.c, size);
selection.insert(0, start); selection.insert(0, start_text);
// Add last line start // Add last line start
if(start_r < end_r) { if(start.r < end.r) {
string end_line = get_line(end_r); string end_line = get_line(end.r);
string end = end_line.substr(0, end_c+1); string end_text = end_line.substr(0, end.c+1);
selection.append(end); selection.append(end_text);
} }
} }
// Pasting // Pasting
void paste_selection() { void paste_selection(position p = cur) {
if(selection.size() == 0) return; if(selection.size() == 0) return;
// Insert last line inside of this // Insert last line inside of this
insert(row, col, selection.find(selection.size()-1)->text); insert(p, selection.find(selection.size()-1)->text);
if(selection.size() == 1) return; if(selection.size() == 1) return;
// Insert first line in front and split // Insert first line in front and split
split_line(row, col); split_line(p);
insert(row, col, selection.find(0)->text); insert(p, selection.find(0)->text);
if(selection.size() == 2) return; if(selection.size() == 2) return;
// Insert lines // Insert lines
for(int i = selection.size()-2; i > 0; --i) for(count_type i = selection.size()-2; i > 0; --i)
new_line(row, selection.find(i)->text); new_line(p.r, selection.find(i)->text);
} }
// TODO hledání a nahrazování // TODO hledání a nahrazování
@ -149,25 +150,30 @@ void paste_selection() {
// Jump to end of line // Jump to end of line
void jump_line_end() { void jump_line_end() {
int line_size = get_line(row).size(); count_type line_size = get_line(cur.r).size();
if(col > line_size) if(cur.c > line_size)
col = line_size; cur.c = line_size;
}
// Move cursor within window
void move(position p) {
move(p.r, p.c);
} }
// Cursor movement // Cursor movement
void move_cursor(char ch) { void move_cursor(char ch) {
switch(ch) { switch(ch) {
case 'h': case 'h':
if(col > 0) if(cur.c > 0)
move(row, --col); move(cur.r, --cur.c);
break; break;
case 'j': case 'j':
if(file_offset + row >= file.size()-1) break; if(file_offset + cur.r >= file.size()-1) break;
if(row < LINES-1) { if(cur.r < LINES-1) {
move(++row, col); cur.r += 1;
move(cur);
jump_line_end(); jump_line_end();
} }
else if(row == LINES-1) { else if(cur.r == LINES-1) {
file_offset++; file_offset++;
jump_line_end(); jump_line_end();
print_file(); print_file();
@ -175,8 +181,9 @@ void move_cursor(char ch) {
break; break;
case 'k': case 'k':
if(row > 0) { if(cur.r > 0) {
move(--row, col); cur.r -= 1;
move(cur);
jump_line_end(); jump_line_end();
} }
else if(file_offset > 0) { else if(file_offset > 0) {
@ -187,15 +194,22 @@ void move_cursor(char ch) {
break; break;
case 'l': case 'l':
if(col < get_line(row).size()) if(cur.c < get_line(cur.r).size()) {
move(row, ++col); cur.c += 1;
move(cur);
}
break; break;
} }
} }
// Skoky a přesuny // Skoky a přesuny
void jump(int r) { void jump(count_type r) {
file_offset = std::min(r, std::max((int)(file.size()-LINES), 0)); count_type last_start = file.size()-LINES;
row = 0; if(last_start < 0)
last_start = 0;
file_offset = r;
if(file_offset > last_start)
file_offset = last_start;
cur.r = 0;
jump_line_end(); jump_line_end();
} }
@ -219,11 +233,11 @@ int main(int argc, char* argv[]) {
// Main loop // Main loop
bool run = true; bool run = true;
while(run) { while(run) {
move(row, col); move(cur);
char ch = getch(); char ch = getch();
switch(mode) { switch(mode) {
case NORMAL: case NORMAL:
print_line(row); print_line(cur.r);
switch(ch) { switch(ch) {
case 'h': case 'j': case 'k': case 'l': case 'h': case 'j': case 'k': case 'l':
move_cursor(ch); move_cursor(ch);
@ -233,16 +247,16 @@ int main(int argc, char* argv[]) {
print_file(); print_file();
break; break;
case 'd': case 'd':
remove(row); remove(cur.r);
print_file(row); print_file(cur.r);
break; break;
case 'x': case 'x':
remove(row, col); remove(cur);
print_line(row); print_line(cur.r);
break; break;
case 'o': case 'o':
new_line(row); new_line(cur.r);
print_file(row); print_file(cur.r);
break; break;
case 'q': case 'q':
run = false; run = false;
@ -255,11 +269,11 @@ int main(int argc, char* argv[]) {
break; break;
case 'v': case 'v':
mode = SELECT; mode = SELECT;
clp_r = row, clp_c = col; clp = cur;
break; break;
case 'p': case 'p':
paste_selection(); paste_selection();
print_file(row); print_file(cur.r);
break; break;
default: default:
break; break;
@ -269,26 +283,29 @@ int main(int argc, char* argv[]) {
switch(ch) { switch(ch) {
case ESC: case ESC:
mode = NORMAL; mode = NORMAL;
print_line(row); print_line(cur.r);
break; break;
case BS: case BS:
if(col>0) if(cur.c > 0) {
remove(row, --col); cur.c -= 1;
print_line(row); remove(cur);
}
print_line(cur.r);
break; break;
case ENTER: case ENTER:
split_line(row, col); split_line(cur);
print_file(row++); print_file(cur.r++);
jump_line_end(); jump_line_end();
break; break;
default: default:
insert(row, col++, ch); insert(cur, ch);
print_line(row); cur.c += 1;
print_line(cur.r);
break; break;
} }
break; break;
case SELECT: case SELECT:
print_line(row); print_line(cur.r);
switch(ch) { switch(ch) {
case 'h': case 'j': case 'k': case 'l': case 'h': case 'j': case 'k': case 'l':
move_cursor(ch); move_cursor(ch);