203 lines
4.7 KiB
C
203 lines
4.7 KiB
C
#include <stdbool.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "buffer.h"
|
|
#include "erow.h"
|
|
#include "utils.h"
|
|
|
|
static void buffer_free_rows(struct buffer *buffer);
|
|
static char *buffer_get_string(struct buffer *buffer, size_t *len_p);
|
|
|
|
struct buffer *buffer_create(void) {
|
|
struct buffer *buffer = malloc(sizeof(struct buffer));
|
|
|
|
buffer->filename = NULL;
|
|
|
|
buffer->cx = buffer->cy = buffer->rx = 0;
|
|
buffer->row_off = buffer->col_off = 0;
|
|
|
|
buffer->rows = NULL;
|
|
buffer->n_rows = 0;
|
|
|
|
buffer->modified = false;
|
|
|
|
return buffer;
|
|
}
|
|
|
|
ERRCODE buffer_read_file(struct buffer *buffer, const char *filename) {
|
|
ERRCODE errcode = 0;
|
|
|
|
if (buffer->filename) free(buffer->filename);
|
|
size_t filename_len = strlen(filename);
|
|
buffer->filename = malloc(filename_len);
|
|
memcpy(buffer->filename, filename, filename_len);
|
|
|
|
if (buffer->rows)
|
|
buffer_free_rows(buffer);
|
|
|
|
size_t buf_cap = 64;
|
|
char *buf = malloc(buf_cap);
|
|
|
|
FILE *file = fopen(filename, "r");
|
|
if (file == NULL)
|
|
RETURN(-1);
|
|
|
|
while (true) {
|
|
char c;
|
|
size_t buf_size = 0;
|
|
|
|
while ((c = getc(file)) != '\n' && c != EOF) {
|
|
if (buf_size >= buf_cap)
|
|
buf = realloc(buf, buf_cap *= 2);
|
|
|
|
buf[buf_size++] = c;
|
|
}
|
|
|
|
struct erow* erow = erow_create(buf, buf_size, buffer);
|
|
buffer_insert_row(buffer, erow, buffer->n_rows);
|
|
|
|
if (c == EOF)
|
|
break;
|
|
}
|
|
|
|
if (buffer->rows[buffer->n_rows - 1]->n_chars == 0)
|
|
buffer_delete_row(buffer, buffer->n_rows - 1);
|
|
|
|
END:
|
|
if (file != NULL)
|
|
fclose(file);
|
|
|
|
if (buf != NULL)
|
|
free(buf);
|
|
|
|
buffer->modified = false;
|
|
|
|
return errcode;
|
|
}
|
|
|
|
ERRCODE buffer_write_file(struct buffer *buffer, size_t *bytes_written) {
|
|
ERRCODE errcode = 0;
|
|
|
|
FILE *file = NULL;
|
|
char *write_buffer = NULL;
|
|
|
|
if (buffer->filename == NULL)
|
|
RETURN(-1);
|
|
|
|
size_t n_chars;
|
|
write_buffer = buffer_get_string(buffer, &n_chars);
|
|
|
|
file = fopen(buffer->filename, "w");
|
|
if (file == NULL)
|
|
RETURN(-2);
|
|
|
|
*bytes_written = fwrite(write_buffer, 1, n_chars, file);
|
|
if (*bytes_written != n_chars)
|
|
RETURN(-3);
|
|
|
|
END:
|
|
if (file != NULL)
|
|
fclose(file);
|
|
|
|
if (write_buffer)
|
|
free(write_buffer);
|
|
|
|
if (errcode == 0)
|
|
buffer->modified = false;
|
|
|
|
return errcode;
|
|
}
|
|
|
|
ERRCODE buffer_get_row_chars(struct buffer *buffer, char **chars, size_t *n_chars, int at) {
|
|
if (buffer == NULL)
|
|
return -1;
|
|
|
|
if (!(0 <= at && at <= buffer->n_rows))
|
|
return -2;
|
|
|
|
if (chars) *chars = buffer->rows[at]->chars;
|
|
if (n_chars) *n_chars = buffer->rows[at]->n_chars;
|
|
|
|
return 0;
|
|
}
|
|
|
|
ERRCODE buffer_get_row_rchars(struct buffer *buffer, char **rchars, size_t *n_rchars, int at) {
|
|
if (buffer == NULL)
|
|
return -1;
|
|
|
|
if (!(0 <= at && at <= buffer->n_rows))
|
|
return -2;
|
|
|
|
if (rchars) *rchars = buffer->rows[at]->rchars;
|
|
if (n_rchars) *n_rchars = buffer->rows[at]->n_rchars;
|
|
|
|
return 0;
|
|
}
|
|
|
|
void buffer_insert_row(struct buffer *buffer, struct erow *erow, int at) {
|
|
if (!(0 <= at && at <= buffer->n_rows))
|
|
return;
|
|
|
|
buffer->rows = realloc(buffer->rows, sizeof(struct erow *) * (buffer->n_rows + 1));
|
|
memmove(buffer->rows + at + 1, buffer->rows + at, sizeof(struct erow *) * (buffer->n_rows - at));
|
|
|
|
buffer->rows[at] = erow;
|
|
buffer->n_rows++;
|
|
}
|
|
|
|
void buffer_delete_row(struct buffer *buffer, int at) {
|
|
if (!(0 <= at && at < buffer->n_rows))
|
|
return;
|
|
|
|
erow_free(buffer->rows[at]);
|
|
memmove(buffer->rows + at, buffer->rows + at + 1, sizeof(struct erow *) * (buffer->n_rows - at - 1));
|
|
buffer->n_rows--;
|
|
|
|
buffer->modified = true;
|
|
}
|
|
|
|
struct erow *buffer_get_crow(struct buffer *buffer) {
|
|
return (buffer->cy < buffer->n_rows ? buffer->rows[buffer->cy]: NULL);
|
|
}
|
|
|
|
void buffer_free(struct buffer *buffer) {
|
|
free(buffer->filename);
|
|
|
|
buffer_free_rows(buffer);
|
|
}
|
|
|
|
size_t buffer_get_crow_len(struct buffer *buffer) {
|
|
struct erow *crow = buffer_get_crow(buffer);
|
|
|
|
return crow ? crow->n_chars : 0;
|
|
}
|
|
|
|
static void buffer_free_rows(struct buffer *buffer) {
|
|
for (int i = 0; i < buffer->n_rows; i++)
|
|
erow_free(buffer->rows[i]);
|
|
|
|
free(buffer->rows);
|
|
|
|
buffer->rows = NULL;
|
|
buffer->n_rows = 0;
|
|
}
|
|
|
|
static char *buffer_get_string(struct buffer *buffer, size_t *n_chars) {
|
|
*n_chars = 0;
|
|
|
|
for (int i = 0; i < buffer->n_rows; i++)
|
|
*n_chars += buffer->rows[i]->n_chars + 1;
|
|
|
|
char *write_buffer = malloc(*n_chars);
|
|
for (int i = 0, j = 0; i < buffer->n_rows; i++) {
|
|
struct erow *row = buffer->rows[i];
|
|
|
|
memcpy(write_buffer + j, row->chars, row->n_chars);
|
|
j += row->n_chars;
|
|
write_buffer[j++] = '\n';
|
|
}
|
|
|
|
return write_buffer;
|
|
}
|