1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
|
#include <iostream>
#include <ncurses.h>
#include <unistd.h>
#include <cctype>
using namespace std;
struct Node {
char data;
Node* next;
Node* prev;
};
class Line {
private:
Node* head;
Node* tail;
Node* cursor;
public:
// start with a Line that only contains a node of ' '
Line() {
Node* start = new Node; //start node
head = start; //head, tail, cursor are the same place
tail = start;
cursor = start;
start->data = ' '; //making it empty
start->prev = NULL; //setting nulls on both ends
start->next = NULL;
}
// same as above, but load str into the list also
Line(string str) {
Node* first = new Node; //making the first node
head = first; //head, tail, cursor are all at first
tail = first;
cursor = first;
first->data = ' '; //making first empty
first->prev = NULL; //setting nulls on both ends
first->next = NULL;
for(int i=0; i<= str.length(); i++) { //using a for loop on the string
if(i == 1 ) {
cursor->prev = head;
head->prev = NULL;
}
add(str[i]); //add function to add new nodes
}
}
// add the new node before the cursor
void add(char key) {
Node* findFront = cursor; //node pointer to position head
Node* findBack = cursor; //node pointer to position tail
Node* addMe = new Node; //new node to add
addMe->data = key; //key is data in addMe node
addMe->next = NULL;
addMe->prev = NULL;
if(!cursor->prev) { //if the list is empty
addMe->prev = NULL; //the added node's prev is null
addMe->next = cursor; //addMe next is the cursor
cursor->prev = addMe; //cursor prev = addM
head = addMe;
}
if(cursor->prev) { //if the list is not empty
cursor->prev->next = addMe; //the node behind the cursor not points at addMe
addMe->next = cursor; //addMe next is now the cursor
addMe->prev = cursor->prev; //addMe prev is the node that was behind the cursor
cursor->prev = addMe; //cursor prev is now addMe
}
/* //this is probably overkill
while(findFront->prev != NULL) { //while findFront exits
findFront = findFront->prev; //traverse to the beginning of list
}
head = findFront; //head is the first node
delete findFront; //delete temp node pointer
while(findBack) { //while findBack exists
findBack = findBack->next; //traverse to end of list
}
tail = findBack; //tail is end of the list
*/// delete findBack; //delete temp node pointer
}
// remove the node before the cursor
void remove() {
while(cursor->prev) { //while there is something to delete
Node* toDelete = cursor->prev; //creating temp node to delete
if (!cursor->prev->prev) { //if you are deleting the only thing in the list
cursor->prev = NULL; // cursor prev is now null
delete toDelete; //deleting offending node
}
if (cursor->prev->prev) { //if you are deleting a thing in the list
cursor->prev->prev->next = cursor; //the node behind the node behind cursor now points at cursor
cursor->prev = cursor->prev->prev; //cursor now points at the node two back from cursor
delete toDelete; //delete the offendind node
}
}
}
// print the line
void print() {
if(head == NULL) {
cout << "There is nothing here! This should never happen!" << endl;
}
Node* temp = head; //creating temp node for iteration set to head
int counter = 0; //counter so ncurses can highlight the cursor
while(temp != NULL) { //while the list exists
if(temp == cursor) { //if temp and cursor are the same
attron(COLOR_PAIR(1)); //invert colors
mvaddch(5,counter,temp->data); //add color effect
// cout << (*temp).data;
attroff(COLOR_PAIR(1)); //return colors
} else {
cout << temp->data; //otherwise cout data
temp = temp->next; //iterate through
counter++; //increase counter
}
}
// recall to print the cursor, that to turn use color
// the code looks like this:
// attron(COLOR_PAIR(1));
// mvaddch(row, col, char);
// attroff(COLOR_PAIR(1));
}
// move the cursor left or right
void moveCursor(char input) {
if(input == 'l' && cursor->prev != NULL ) { //if left arrow key is pressed and there is a node before the cursor
cursor = cursor->prev; //move the cursor
}
if(input == 'r' && cursor->next != NULL ) { //if right arrow is pressed and there is a node after the cursor
cursor = cursor->next; //move the cursor
}
}
// destructor deletes all nodes in the list
~Line() {
Node* check = head; //temp nodes for distruction
Node* destroy = head;
while(!tail) { //while not at the end
check = check->next; //iterate check
delete destroy; //destroy destroy
destroy = check; //set destroy to check
}
if(tail){ //at the end
delete destroy; //delete temp nodes
delete check;
}
}
};
int main() {
// set up ncurses stuff
initscr();
keypad(stdscr, TRUE); // lets the arrow keys work
start_color();
init_pair(1, COLOR_BLACK, COLOR_WHITE);
noecho(); // makes the keystroke NOT be printed
nodelay(stdscr, TRUE); // makes getch NOT WAIT for input
curs_set(0); // turn off the regular cursor
// declare line
Line l("start with this text"); // construct the starting line
int input = 'a';
// modification loop
while(input != 27) { // 27 is the escape key
// get input
input = getch();
// put the input into the line or move the cursor
if(isalpha(input) || input == ' ') {
l.add(input);
} else if(input == KEY_LEFT) {
l.moveCursor('l');
} else if(input == KEY_RIGHT) {
l.moveCursor('r');
} else if(input == KEY_BACKSPACE) { // backspace
l.remove();
}
// display line with cursor and pause
l.print();
refresh();
usleep(10000);
}
// exit
endwin();
return 0;
}
|