-
Notifications
You must be signed in to change notification settings - Fork 2
/
Head.c
273 lines (213 loc) · 8.38 KB
/
Head.c
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
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
#include "Head.h"
Head genHead() {
Head h = {0, 0, '\0', false};
return h;
}
char moveRight(
Lines* buffer_ptr, Head* curr_head_ptr, uint32_t n
) {
if ( !isLegalPosition(buffer_ptr, curr_head_ptr) ) {
#ifdef _DEBUG
fprintf(stderr, "Illegal position in moveRight\n");
#endif
return EOF;
}
uint32_t to_end = lineEnd(buffer_ptr, curr_head_ptr);
// newline_index actually stores the index before the newline
int32_t newline_index = (int32_t) curr_head_ptr->pos_x+to_end;
// the index after mod addition would look like this
uint32_t index_after = curr_head_ptr->pos_x;
index_after += n;
// if the index after moving would end up
// outside the current line - append the difference
// and set curr_head_ptr->pos_x to the end of the line
if ( index_after > newline_index && curr_head_ptr->destructive ) {
append(
&buffer_ptr->lines[curr_head_ptr->pos_y],
&buffer_ptr->lines_len[curr_head_ptr->pos_y],
' ', index_after-newline_index
);
curr_head_ptr->pos_x = index_after;
return ' ';
// if it's non destructive we'll just put it gently to an eternal sleep
} else if ( index_after > newline_index ) {
fprintf(stderr, "Exit due to moveRight overflow\n");
#define OOF EOF
return OOF;
}
// of course there's always a possibility that we just want to move right
// without going out of line's boundaries
curr_head_ptr->pos_x = index_after;
char next = buffer_ptr->lines[curr_head_ptr->pos_y][curr_head_ptr->pos_x];
return next;
};
char moveLeft(
Lines* buffer_ptr, Head* curr_head_ptr, uint32_t n
) {
if ( !isLegalPosition(buffer_ptr, curr_head_ptr) ) {
#ifdef _DEBUG
fprintf(stderr, "Illegal position in moveLeft\n");
#endif
return EOF;
}
uint32_t to_beginning = lineBeginning(buffer_ptr, curr_head_ptr);
// newline_index actually stores the index after the newline
int32_t newline_index = (int32_t) curr_head_ptr->pos_x-to_beginning;
// the index after mod subtraction would look like this
int32_t index_after = (int32_t) curr_head_ptr->pos_x;
index_after -= n;
// if the index after moving would end up outside the current line
// prepend the difference and set curr_head_ptr->pos_x to newline_index
if ( index_after < newline_index && curr_head_ptr->destructive ) {
insert(
&buffer_ptr->lines[curr_head_ptr->pos_y],
&buffer_ptr->lines_len[curr_head_ptr->pos_y],
' ', newline_index, newline_index-index_after
);
curr_head_ptr->pos_x = newline_index;
return ' ';
// if it's non destructive, well - we have a garotte on hand
} else if ( index_after < newline_index ) {
fprintf(stderr, "Exit due to moveLeft overflow\n");
return EOF;
}
// of course there's always a possibility that we just want to move left
// without going out of line's boundaries
curr_head_ptr->pos_x = index_after;
char next = buffer_ptr->lines[curr_head_ptr->pos_y][curr_head_ptr->pos_x];
return next;
}
char moveDown(Lines* buffer_ptr, Head* curr_head_ptr, uint32_t n) {
if ( !isLegalPosition(buffer_ptr, curr_head_ptr) ) {
#ifdef _DEBUG
fprintf(stderr, "Illegal position in moveDown\n");
#endif
return EOF;
}
uint32_t last_line_index = buffer_ptr->no_lines-1;
// the pos_y after mod addition would look like this
uint32_t pos_y_after = curr_head_ptr->pos_y + n;
// check if lines head is gonna move through are not shorter than the
// current x position; it's gonna be pretty bad otherwise
int32_t check_until = pos_y_after;
if ( check_until >= buffer_ptr->no_lines ) {
check_until = buffer_ptr->no_lines-1;
}
for ( uint32_t y = curr_head_ptr->pos_y; y <= check_until; y++ ) {
if ( buffer_ptr->lines_len[y] <= curr_head_ptr->pos_x ) {
if ( curr_head_ptr->destructive ) {
append(
&buffer_ptr->lines[y], &buffer_ptr->lines_len[y],
' ', curr_head_ptr->pos_x - buffer_ptr->lines_len[y] + 1
);
} else {
// imma end this program's whole career
fprintf(stderr, "Exit due to moveDown overflow(1)\n");
return EOF;
}
}
}
// if the index after moving would end up
// outside the entire buffer - append the difference in lines
// and set curr_head_ptr->pos_y to the last line
if ( pos_y_after > last_line_index && curr_head_ptr->destructive ) {
appendLines(
buffer_ptr, pos_y_after-last_line_index, curr_head_ptr->pos_x+1
);
curr_head_ptr->pos_y = pos_y_after;
return ' ';
// if it's non destructive - just tell me, i have a shotgun somewhere here
} else if ( pos_y_after > last_line_index ) {
fprintf(stderr, "Exit due to moveDown overflow(2)\n");
return EOF;
}
// if the position is going to be legal - just move down dude
curr_head_ptr->pos_y = pos_y_after;
char next = buffer_ptr->lines[curr_head_ptr->pos_y][curr_head_ptr->pos_x];
return next;
}
char moveUp(Lines* buffer_ptr, Head* curr_head_ptr, uint32_t n) {
if ( !isLegalPosition(buffer_ptr, curr_head_ptr) ) {
#ifdef _DEBUG
fprintf(stderr, "Illegal position in moveUp\n");
#endif
return EOF;
}
int32_t first_line_index = 0;
// the pos_y after subtraction addition would look like this
int32_t pos_y_after = (int32_t) curr_head_ptr->pos_y;
pos_y_after -= n;
// check if lines head is gonna move through are not shorter than the
// current x position; yo not DRY at all. ill fix it ok?
int32_t check_until = pos_y_after;
if ( check_until < 0 ) {
check_until = 0;
}
for ( int32_t y = curr_head_ptr->pos_y; y >= check_until; y-- ) {
if ( buffer_ptr->lines_len[y] < curr_head_ptr->pos_x ) {
if ( curr_head_ptr->destructive ) {
append(
&buffer_ptr->lines[y], &buffer_ptr->lines_len[y],
' ', curr_head_ptr->pos_x - buffer_ptr->lines_len[y] + 1
);
} else {
// fuck my shit up
fprintf(stderr, "Exit due to moveUp overflow(1)\n");
return EOF;
}
}
}
// if the index after moving would end up
// outside the entire buffer - insert the difference in lines
// and set curr_head_ptr->pos_y to the first line
if ( pos_y_after < first_line_index && curr_head_ptr->destructive ) {
insertLines(
buffer_ptr, first_line_index, pos_y_after*-1, curr_head_ptr->pos_x+1
);
curr_head_ptr->pos_y = 0;
return ' ';
// if it's non destructive - just tell me, i have a shotgun somewhere here
} else if ( pos_y_after < first_line_index ) {
fprintf(stderr, "Exit due to moveUp overflow(2)\n");
return EOF;
}
// if the position is going to be legal - just move down dude
curr_head_ptr->pos_y = pos_y_after;
char next = buffer_ptr->lines[curr_head_ptr->pos_y][curr_head_ptr->pos_x];
return next;
}
int32_t _lineEdgeCounter(Lines* buffer_ptr, Head* head_ptr, bool direction) {
// testing if the head is out of bounds
if ( !isLegalPosition(buffer_ptr, head_ptr) ) {
fprintf(stderr, "Out of bounds in _lineEdgeCounter\n");
return -1;
}
if ( direction ) {
return head_ptr->pos_x;
}
return buffer_ptr->lines_len[head_ptr->pos_y] - head_ptr->pos_x - 1;
}
bool isLegalPosition(Lines* buffer_ptr, Head* head_ptr) {
return (
head_ptr->pos_y < buffer_ptr->no_lines
&& head_ptr->pos_x < buffer_ptr->lines_len[head_ptr->pos_y]
);
}
bool writeChar(Lines* buffer_ptr, Head* w_head_ptr) {
if ( !isLegalPosition(buffer_ptr, w_head_ptr) ) {
#ifdef _DEBUG
fprintf(stderr, "Illegal position in writeChar\n");
#endif
return false;
}
buffer_ptr->lines[w_head_ptr->pos_y][w_head_ptr->pos_x] = w_head_ptr->mod;
if ( w_head_ptr->pos_x == buffer_ptr->lines_len[w_head_ptr->pos_y]-1 ) {
append(
&buffer_ptr->lines[w_head_ptr->pos_y],
&buffer_ptr->lines_len[w_head_ptr->pos_y],
' ', 1
);
}
w_head_ptr->pos_x++;
return true;
}