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