/* Copyright (C) 2008 Emmanuel Varoquaux This file is part of XOS. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "line.h" #include "xmalloc.h" #include #include #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; /* linebuf */ 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); } /* line */ 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); }