#include "line.h"
#include "xmalloc.h"
#include <string.h>
#include <stdlib.h>
#define LINEBUF_GROW_SIZE 256
#define max(a, b) ((a) > (b) ? (a) : (b))
static struct linebuf_struct *current_linebuf;
char *line;
int line_end;
int point;
int mark;
static void alloc_linebuf(struct linebuf_struct *linebuf, size_t size)
{
linebuf->buf = xmalloc(size);
linebuf->size = size;
}
static void resize_linebuf(struct linebuf_struct *linebuf, size_t newsize)
{
current_linebuf->buf = xrealloc(current_linebuf->buf, newsize);
current_linebuf->size = newsize;
}
static void free_linebuf(struct linebuf_struct *linebuf)
{
free(linebuf->buf);
}
void linebuf_init(struct linebuf_struct *linebuf, const char *s)
{
alloc_linebuf(linebuf, strlen(s) + 1);
strcpy(linebuf->buf, s);
}
void linebuf_destroy(struct linebuf_struct *linebuf)
{
free_linebuf(linebuf);
}
static void shift(int from, int to)
{
int n;
n = to - from;
if (line_end + n > ((int)current_linebuf->size - 1)) {
resize_linebuf(current_linebuf, current_linebuf->size + max(LINEBUF_GROW_SIZE, n));
line = current_linebuf->buf;
}
memmove(line + to, line + from, line_end - from + 1);
line_end += n;
}
void line_set(struct linebuf_struct *linebuf)
{
current_linebuf = linebuf;
line = linebuf->buf;
line_end = strlen(line);
point = line_end;
mark = 0;
}
void line_replace_region_with_char(int start, int end, char c)
{
if (start + 1 != end)
shift(end, start + 1);
line[start] = c;
point = start + 1;
}
void line_replace_region_with_text(int start, int end, const char *text)
{
int n;
n = strlen(text);
if (start + n != end)
shift(end, start + n);
memcpy(line + start, text, n);
point = start + n;
}
void line_erase_region(int start, int end)
{
if (start != end)
memset(line + start, ' ', end - start);
point = start;
}
void line_delete_region(int start, int end)
{
if (start != end)
shift(end, start);
point = start;
}
void line_set_point(int newpoint)
{
point = newpoint;
}
void line_set_mark(int newmark)
{
mark = newmark;
}
void line_discard()
{
current_linebuf = NULL;
line = NULL;
}
void line_release()
{
if (line)
line = xstrdup(line);
}