Begin re-write of basic display functions in scheme
[texed.git] / buffer.c
blobd2eadb61b98134a7dfb8b4221c302c52c3f919d3
2 #include "buffer.h"
4 buffer_t buffer_init()
6 char* buffer = calloc(sizeof(char), 80); // start at 80 chars per line
7 int* indices = calloc(sizeof(int), 40);
9 if (!buffer)
11 fputs("Out of memory, buffer_init()\n", stderr);
12 exit(1);
15 return (buffer_t)
17 .buf = buffer,
18 .size = 80,
19 .gap_start = 0,
20 .gap_end = 79,
21 .line_indices = indices,
22 .num_lines = 1,
23 .name = "untitled",
24 .cursor = (position_t) {0,0}
28 buffer_t* buffer_init_point ()
30 buffer_t* result = calloc(sizeof(buffer_t), 1);
31 char* buffer = calloc(sizeof(char), 80); // start at 80 chars per line
32 int* indices = calloc(sizeof(int), 40);
34 if (!buffer || !result)
36 fputs("Out of memory, buffer_init()\n", stderr);
37 exit(1);
40 result->buf = buffer;
41 result->size = 80;
42 result->gap_start = 0;
43 result->gap_end = 79;
44 result->line_indices = indices;
45 result->num_lines = 1;
46 result->name = "untitled";
47 result->cursor = (position_t) {0,0};
49 return result;
52 void buffer_free (buffer_t* buffer)
54 free(buffer->buf);
55 buffer->size = 0;
56 buffer->gap_start = 0;
57 buffer->gap_end = 0;
60 void buffer_inspect (buffer_t buffer)
62 printf("BUFFER DETAILS\n"
63 "--------------\n"
64 "NAME : %s\n"
65 "SIZE : %d\n"
66 "GAP_START : INDEX %d\n"
67 "GAP_END : INDEX %d\n"
68 "NUM_LINES : %d\n"
69 "CURSOR POS : y(%d), x(%d)\n"
70 "LINE INDICES: [",
71 buffer.name, buffer.size,
72 buffer.gap_start, buffer.gap_end,
73 buffer.num_lines, buffer.cursor.y,
74 buffer.cursor.x);
76 for (int i = 0; i < buffer.num_lines; i++)
78 printf("%d, ", buffer.line_indices[i]);
81 puts("]\n\n"
82 "BUFFER CONTENTS\n"
83 "---------------\n");
85 for (int i = 0; i < (int) buffer.size; i++)
87 if (buffer.buf[i] == '\n')
88 puts("\\n, ");
89 else if (buffer.buf[i] == '\0')
90 printf("\\0, ");
91 else
92 printf("%c, ", buffer.buf[i]);
94 puts("\n");
97 void buffer_print (buffer_t buffer)
99 char* head = calloc(sizeof(char), buffer.gap_start + 1);
100 char* tail = calloc(sizeof(char), (buffer.size - buffer.gap_end) + 1);
102 for (int i = 0; i < buffer.gap_start; i++)
104 head[i] = buffer.buf[i];
107 int count = 0;
108 for (int i = buffer.gap_end + 1; i < (int) buffer.size; i++)
110 tail[count] = buffer.buf[i];
111 count++;
114 printf("BUFFER DETAILS\n"
115 "--------------\n"
116 "NAME : %s\n"
117 "SIZE : %d\n"
118 "GAP_START : INDEX %d\n"
119 "GAP_END : INDEX %d\n"
120 "NUM_LINES : %d\n"
121 "CURSOR POS : y(%d), x(%d)\n"
122 "LINE INDICES: [",
123 buffer.name, buffer.size,
124 buffer.gap_start, buffer.gap_end,
125 buffer.num_lines, buffer.cursor.y,
126 buffer.cursor.x);
128 for (int i = 0; i < buffer.num_lines; i++)
130 printf("%d, ", buffer.line_indices[i]);
133 printf("]\n\n"
134 "BUFFER CONTENTS\n"
135 "---------------\n"
136 "%s<C>%s\n\n", head, tail);
138 free(head);
139 free(tail);
142 void buffer_grow (buffer_t* buffer, unsigned int add)
144 char* new_buf = calloc(sizeof(char), buffer->size + add);
145 int* new_indices = calloc(sizeof(int), buffer->size);
146 int new_end = buffer->gap_end + add;
147 int new_size = buffer->size + add;
149 for (int i = 0; i < buffer->gap_start; i++)
150 new_buf[i] = buffer->buf[i];
152 for (int i = new_end; i < new_size; i++)
153 new_buf[i] = buffer->buf[i - add];
155 for (int i = 0; i < buffer->num_lines; i++)
156 new_indices[i] = buffer->line_indices[i];
158 free(buffer->buf);
159 free(buffer->line_indices);
160 buffer->buf = new_buf;
161 buffer->line_indices = new_indices;
162 buffer->gap_end = new_end;
163 buffer->size = new_size;
167 void buffer_insert_char (buffer_t* buffer, char new)
169 int gap_length = buffer->gap_end - buffer->gap_start;
171 if (gap_length < 5)
172 buffer_grow(buffer, buffer->size + buffer->size);
174 buffer->buf[buffer->gap_start] = new;
175 if (new == '\n')
177 buffer->line_indices[buffer->num_lines] = buffer->gap_start;
178 buffer->cursor.x = 0;
179 buffer->cursor.y++;
180 buffer->num_lines++;
182 else
184 /* buffer->line_indices[buffer->cursor.y + 1]++; */
185 buffer->cursor.x++;
188 buffer->gap_start++;
191 void buffer_backspace (buffer_t* buffer)
193 char to_erase = buffer->buf[buffer->gap_start - 1];
194 if (to_erase == '\n')
196 int current_index = buffer->line_indices[buffer->cursor.y];
197 int x_pos = buffer->gap_start - current_index;
198 buffer->cursor.y--;
199 buffer->cursor.x = x_pos;
201 else
202 buffer->cursor.x--;
204 buffer->buf[buffer->gap_start - 1] = '\0';
205 buffer->gap_start--;
208 void buffer_left (buffer_t* buffer)
210 if (buffer->gap_start == 0)
211 return;
213 char to_move = buffer->buf[buffer->gap_start - 1];
214 if (to_move == '\n')
216 int current_line_index = buffer->line_indices[buffer->cursor.y];
217 int prev_line_index = buffer->line_indices[buffer->cursor.y - 1];
218 unsigned int prev_line_length = current_line_index - prev_line_index;
219 buffer->cursor.y--;
220 buffer->cursor.x = (int) prev_line_length - 1;
222 else
223 buffer->cursor.x--;
225 buffer->buf[buffer->gap_end] = to_move;
226 buffer->buf[buffer->gap_start - 1] = '\0';
228 buffer->gap_start--;
229 buffer->gap_end--;
232 void buffer_right (buffer_t* buffer)
234 if (buffer->gap_end == (int) buffer->size - 1)
235 return;
237 char to_move = buffer->buf[buffer->gap_end + 1];
238 if (to_move == '\n')
240 buffer->cursor.x = 0;
241 buffer->cursor.y++;
243 else
244 buffer->cursor.x++;
246 buffer->buf[buffer->gap_start] = to_move;
247 buffer->buf[buffer->gap_end + 1] = '\0';
249 buffer->gap_start++;
250 buffer->gap_end++;
253 void buffer_up (buffer_t* buffer)
255 int x_pos = buffer->cursor.x;
256 int current_line_index = buffer->line_indices[buffer->cursor.y];
258 if (buffer->cursor.y == 0)
259 return;
261 int prev_line_index = buffer->line_indices[buffer->cursor.y - 1];
262 int prev_line_length = current_line_index - prev_line_index;
264 if (x_pos > prev_line_length)
266 for (int i = 0; i < (x_pos + 1); i++)
267 buffer_left(buffer);
269 else
271 int to_move = prev_line_length;
272 for (int i = 0; i < to_move; i++)
273 buffer_left(buffer);
277 void buffer_down (buffer_t* buffer)
279 int x_pos = buffer->cursor.x;
281 int next_line_start = buffer->line_indices[buffer->cursor.y + 1];
282 int next_line_end = buffer->line_indices[buffer->cursor.y + 2];
283 int next_line_length = next_line_end - next_line_start;
285 int current_line_index = buffer->line_indices[buffer->cursor.y];
286 int current_line_length = next_line_start - current_line_index;
288 int to_move = 0;
289 if (!next_line_start || !next_line_end)
291 int gap_length = buffer->gap_end - buffer->gap_start;
292 int occupied = buffer->size - gap_length;
293 next_line_length = occupied - next_line_start;
296 if (x_pos > next_line_length) //account for zero-indexing
297 to_move = (current_line_length - x_pos) + next_line_length - 1;
299 else
300 to_move = current_line_length;
302 for (int i = 0; i < to_move; i++)
303 buffer_right(buffer);
306 void buffer_set_contents (buffer_t* buffer, char string[])
308 int length = strlen(string);
309 for (int i = 0; i < length; i++)
310 buffer_insert_char(buffer, string[i]);
313 char* buffer_to_string (buffer_t buffer)
315 int occupied = buffer.size - (buffer.gap_end - buffer.gap_start);
316 char* head = calloc(sizeof(char), buffer.gap_start + 1);
317 char* tail = calloc(sizeof(char), (buffer.size - buffer.gap_end) + 1);
318 char* result = calloc(sizeof(char), occupied + 1);
320 for (int i = 0; i < buffer.gap_start; i++)
322 head[i] = buffer.buf[i];
325 int count = 0;
326 for (int i = buffer.gap_end + 1; i < (int) buffer.size; i++)
328 tail[count] = buffer.buf[i];
329 count++;
332 strcat(result, head);
333 strcat(result, tail);
334 free(head);
335 free(tail);
337 return result;
340 void buffer_jump_word (buffer_t* buffer, char delim, int dir)
342 int quit = 0;
343 char to_move;
345 while (!quit)
347 if (dir == 0)
349 to_move = buffer->buf[buffer->gap_end + 1];
350 buffer_right(buffer);
352 else
354 to_move = buffer->buf[buffer->gap_start - 1];
355 buffer_left(buffer);
358 if ((to_move == delim) ||
359 (buffer->gap_start == 0) ||
360 (buffer->gap_end == (int) (buffer->size - 1)))
361 quit = 1;