-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtextops.h
More file actions
234 lines (221 loc) · 7.72 KB
/
textops.h
File metadata and controls
234 lines (221 loc) · 7.72 KB
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
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
#define ESCAPE '\e'
#define NEWLINE '\n'
void insert_to_list(buffer *buff, char input) {
dNode *new_node=malloc(sizeof(dNode));
buff->curr_line->size+=1;
if(input=='\t') buff->curr_line->width+=8;
else buff->curr_line->width+=1;
if((buff->curr_node)->prev==NULL) { // if current node is at the start of a line
new_node->prev=NULL;
buff->curr_line->start=new_node;
}
else { // else it's at the middle or end of a line
new_node->prev=(buff->curr_node)->prev;
(buff->curr_node)->prev->next=new_node;
}
new_node->next=(buff->curr_node);
new_node->ch=input;
(buff->curr_node)->prev=new_node; // update current node's previous
}
void backspace(buffer *buff) {
if((buff->curr_node)->prev==NULL) { // if current node is at start of line
if((buff->curr_line)->prev_line==NULL) return; // if current line is at the beginning of a file do nothing
line *temp_line=buff->curr_line;
buff->curr_line=(buff->curr_line)->prev_line;
if(temp_line->next_line!=NULL) temp_line->next_line->prev_line=buff->curr_line; // sets the next line of temp line to prev line
(buff->curr_line)->next_line=temp_line->next_line;
(buff->curr_line)->width+=temp_line->width;
(buff->curr_line)->size+=temp_line->size; // update size of current line
(buff->curr_node)->prev=(buff->curr_line)->end; // set the prev node of current node to previous line's end
if ((buff->curr_line)->end==NULL) (buff->curr_line)->start=temp_line->start; // if current line was empty just swap its start
else (buff->curr_line)->end->next=temp_line->start; // replace current line's end with old line's start
(buff->curr_line)->end=temp_line->end; // update current line's end
free(temp_line);
}
else {
if(buff->curr_node->ch=='\t') buff->curr_line->width-=8;
else buff->curr_line->width-=1;
dNode *temp=(buff->curr_node)->prev;
(buff->curr_node)->prev=temp->prev;
if((buff->curr_node)->next==NULL) (buff->curr_line)->end==temp->prev; // if current node is the end of a line, change line end
if(temp->prev==NULL) (buff->curr_line)->start=buff->curr_node; //if no node before temp assign current as start
else temp->prev->next=buff->curr_node;
(buff->curr_line)->size-=1;
free(temp);
}
}
int count_width(dNode *head) {
int width=0;
while(head->ch!='\n') {
if(head->ch=='\t') width+=8;
else width++;
head=head->next;
}
return width;
}
int count_size(dNode *head) {
int size=0;
while(head->ch!='\n') {
size++;
head=head->next;
}
return size;
}
void insert_newline(buffer *buff) {
line *new_line=malloc(sizeof(line));
if((buff->curr_line)->prev_line==NULL){
new_line->prev_line=NULL; // if current line's is at the beginning of file
buff->head=new_line;
}
else {
new_line->prev_line=(buff->curr_line)->prev_line;
(buff->curr_line)->prev_line->next_line=new_line;
}
if(buff->curr_line==buff->top) { //if current line is at the top of the display
buff->top=new_line;
}
dNode *new_node=malloc(sizeof(dNode));
new_node->ch='\n';
new_node->next=NULL;
if((buff->curr_node)->prev==NULL) { //if at the start of a line
new_line->start=new_node;
new_line->end=new_node->prev=NULL;
}
else {
new_line->start=(buff->curr_line)->start;
new_line->end=(buff->curr_node)->prev;
new_line->end->next=new_node;
(buff->curr_line)->start=buff->curr_node;
(buff->curr_node)->prev=NULL;
}
new_line->next_line=(buff->curr_line);
(buff->curr_line)->prev_line=new_line;
new_line->width=count_width(new_line->start); //update new line and current line's width and size
(buff->curr_line)->width-=new_line->width;
new_line->size=count_size(new_line->start);
(buff->curr_line)->size-=new_line->size;
}
void append(buffer *buff) {
if(buff->curr_node->ch=='\n') return;
else if(buff->curr_node->next->ch=='\n') {
buff->curr_node=buff->curr_node->next;
if(buff->col==(buff->max_col-1)) {
buff->col=0;
buff->row+=1;
}
else buff->col+=1;
move(buff->row, buff->col);
}
else mv_right(buff);
}
void insert_mode(buffer *buff) {
unsigned int key; // vairable is unsigned int to increase range, since characters like backspace are greater than sizeof(char)
while((key=getch())!=ESCAPE) {
switch(key) {
case KEY_UP: mv_up(buff); break;
case KEY_DOWN: mv_down(buff); break;
case KEY_LEFT: mv_left(buff); break;
case KEY_RIGHT: append(buff); break;
case KEY_BACKSPACE:
if((buff->curr_line)->prev_line==NULL && (buff->curr_node)->prev==NULL) break; // if we are at the beginning of a file do nothing
if((buff->curr_node)->prev==NULL) { // if at beginning of line
buff->col=(buff->curr_line->prev_line->width)%(buff->max_col);
move(--(buff->row), 0);
}
else {
if(buff->curr_node->prev->ch=='\t') buff->col-=8;
else buff->col-=1;
}
backspace(buff);
update_syntax(buff);
display(buff);
move(buff->row, buff->col);
break;
case NEWLINE:
insert_newline(buff);
clrtobot();
update_syntax(buff);
display(buff);
buff->col=0; // update column
move(++(buff->row), buff->col);
break;
default:
if((key>126 || key<32) && key!='\t') continue; // if ch is not in range of printable ascii characters, do nothing
insert_to_list(buff, key);
update_syntax(buff);
display(buff);
if(key=='\t') buff->col+=8;
else buff->col++;
if((buff->col)==(buff->max_col)-1) {
buff->col=0;
(buff->row)++;
}
move(buff->row, buff->col);
}
}
if((buff->curr_node)->ch=='\n') mv_left(buff);
}
void delete_char(buffer *buff) {
if(buff->curr_node->ch=='\n') return; // If line is empty do nothing
dNode *temp=buff->curr_node;
buff->curr_node=buff->curr_node->next;
buff->curr_node->prev=temp->prev;
if(temp->ch=='\t') buff->curr_line->width-=8;
else buff->curr_line->width-=1;
if(temp->prev==NULL) buff->curr_line->start=buff->curr_node; //if deleting a node brings us to start of line, update start
else temp->prev->next=buff->curr_node;
free(temp);
update_syntax(buff);
display(buff);
move(buff->row, buff->col);
}
void delete_line(buffer *buff) {
if(buff->curr_line->prev_line==NULL && buff->curr_line->next_line==NULL) { // if we are at start of file and last line
if(buff->curr_line->start->ch=='\n') return; //if file is empty do nothing
dNode *temp_node=buff->curr_line->start;
while(temp_node->ch!='\n') { //if current line contains something, empty it
temp_node=temp_node->next;
free(temp_node->prev);
}
buff->curr_line->start=buff->curr_node=temp_node;
buff->curr_node->next=buff->curr_node->prev=NULL;
update_syntax(buff);
display(buff);
move(0,0);
return;
}
line *temp=buff->curr_line;
int dist=count_char_dist(buff), count=0;
if(temp->next_line==NULL) {
buff->curr_line=buff->curr_line->prev_line;
buff->curr_line->next_line=NULL;
buff->row-=1;
}
else {
buff->curr_line=buff->curr_line->next_line;
if(temp==buff->top) buff->top=buff->curr_line; // update top if deleted temp is top
if(temp==buff->head) buff->head=buff->curr_line; // if we were at head of buffer, update buffer head
else temp->prev_line->next_line=buff->curr_line;
buff->curr_line->prev_line=temp->prev_line;
}
buff->curr_node=buff->curr_line->start;
while(count<buff->col && buff->curr_node->next->ch!='\n') { //jump to the same node from same column of deleted line
if(buff->curr_node->ch=='\t') count+=8;
else count++;
buff->curr_node=buff->curr_node->next;
}
if(count<buff->col) buff->col=count; // update col if jumped line<deleted line
if(dist>buff->max_col) { //accounting for wrapped lines
buff->row-=(dist/buff->max_col);
if(dist%buff->max_col==0) buff->row+=1;
}
dNode *temp_node=temp->start;
while(temp_node->ch!='\n') { //delete all nodes contained in the line
temp_node=temp_node->next;
free(temp_node->prev);
} free(temp_node); //free final node
free(temp); //finally, free line
update_syntax(buff);
display(buff);
move(buff->row,buff->col);
}