HelenOS sources
This source file includes following definitions.
- sheet_create
- sheet_destroy
- sheet_insert
- sheet_delete
- sheet_copy_out
- sheet_get_cell_pt
- sheet_get_row_width
- sheet_get_num_rows
- spt_get_coord
- spt_equal
- spt_next_char
- spt_prev_char
- sheet_place_tag
- sheet_remove_tag
- tag_get_pt
#include <stdlib.h>
#include <str.h>
#include <errno.h>
#include <adt/list.h>
#include <align.h>
#include <macros.h>
#include "sheet.h"
#include "sheet_impl.h"
enum {
TAB_WIDTH = 8,
INITIAL_SIZE = 32
};
errno_t sheet_create(sheet_t **rsh)
{
sheet_t *sh;
sh = calloc(1, sizeof(sheet_t));
if (sh == NULL)
return ENOMEM;
sh->dbuf_size = INITIAL_SIZE;
sh->text_size = 0;
sh->data = malloc(sh->dbuf_size);
if (sh->data == NULL) {
free(sh);
return ENOMEM;
}
list_initialize(&sh->tags);
*rsh = sh;
return EOK;
}
void sheet_destroy(sheet_t *sh)
{
free(sh->data);
free(sh);
}
errno_t sheet_insert(sheet_t *sh, spt_t *pos, enum dir_spec dir, char *str)
{
char *ipp;
size_t sz;
char *newp;
sz = str_size(str);
if (sh->text_size + sz > sh->dbuf_size) {
newp = realloc(sh->data, sh->dbuf_size * 2);
if (newp == NULL)
return ELIMIT;
sh->data = newp;
sh->dbuf_size = sh->dbuf_size * 2;
}
ipp = sh->data + pos->b_off;
memmove(ipp + sz, ipp, sh->text_size - pos->b_off);
memcpy(ipp, str, sz);
sh->text_size += sz;
list_foreach(sh->tags, link, tag_t, tag) {
if (tag->b_off > pos->b_off)
tag->b_off += sz;
else if (tag->b_off == pos->b_off && dir == dir_before)
tag->b_off += sz;
}
return EOK;
}
errno_t sheet_delete(sheet_t *sh, spt_t *spos, spt_t *epos)
{
char *spp;
size_t sz;
char *newp;
size_t shrink_size;
spp = sh->data + spos->b_off;
sz = epos->b_off - spos->b_off;
memmove(spp, spp + sz, sh->text_size - (spos->b_off + sz));
sh->text_size -= sz;
list_foreach(sh->tags, link, tag_t, tag) {
if (tag->b_off >= epos->b_off)
tag->b_off -= sz;
else if (tag->b_off >= spos->b_off)
tag->b_off = spos->b_off;
}
shrink_size = max(sh->dbuf_size / 4, INITIAL_SIZE);
if (sh->text_size <= shrink_size && sh->dbuf_size > INITIAL_SIZE) {
newp = realloc(sh->data, shrink_size);
if (newp == NULL) {
return EOK;
}
sh->data = newp;
sh->dbuf_size = shrink_size;
}
return EOK;
}
void sheet_copy_out(sheet_t *sh, spt_t const *spos, spt_t const *epos,
char *buf, size_t bufsize, spt_t *fpos)
{
char *spp;
size_t range_sz;
size_t copy_sz;
size_t off, prev;
char32_t c;
spp = sh->data + spos->b_off;
range_sz = epos->b_off - spos->b_off;
copy_sz = (range_sz < bufsize - 1) ? range_sz : bufsize - 1;
prev = off = 0;
do {
prev = off;
c = str_decode(spp, &off, copy_sz);
} while (c != '\0');
copy_sz = prev;
memcpy(buf, spp, copy_sz);
buf[copy_sz] = '\0';
fpos->b_off = spos->b_off + copy_sz;
fpos->sh = sh;
}
void sheet_get_cell_pt(sheet_t *sh, coord_t const *coord, enum dir_spec dir,
spt_t *pt)
{
size_t cur_pos, prev_pos;
char32_t c;
coord_t cc;
cc.row = cc.column = 1;
cur_pos = prev_pos = 0;
while (true) {
if (prev_pos >= sh->text_size) {
break;
}
if ((cc.row >= coord->row && cc.column > coord->column) ||
cc.row > coord->row) {
break;
}
prev_pos = cur_pos;
c = str_decode(sh->data, &cur_pos, sh->text_size);
if (c == '\n') {
++cc.row;
cc.column = 1;
} else if (c == '\t') {
cc.column = 1 + ALIGN_UP(cc.column, TAB_WIDTH);
} else {
++cc.column;
}
}
pt->sh = sh;
pt->b_off = (dir == dir_before) ? prev_pos : cur_pos;
}
void sheet_get_row_width(sheet_t *sh, int row, int *length)
{
coord_t coord;
spt_t pt;
coord.row = row;
coord.column = 65536;
sheet_get_cell_pt(sh, &coord, dir_before, &pt);
spt_get_coord(&pt, &coord);
*length = coord.column;
}
void sheet_get_num_rows(sheet_t *sh, int *rows)
{
int cnt;
size_t bo;
cnt = 1;
for (bo = 0; bo < sh->dbuf_size; ++bo) {
if (sh->data[bo] == '\n')
cnt += 1;
}
*rows = cnt;
}
void spt_get_coord(spt_t const *pos, coord_t *coord)
{
size_t off;
coord_t cc;
char32_t c;
sheet_t *sh;
sh = pos->sh;
cc.row = cc.column = 1;
off = 0;
while (off < pos->b_off && off < sh->text_size) {
c = str_decode(sh->data, &off, sh->text_size);
if (c == '\n') {
++cc.row;
cc.column = 1;
} else if (c == '\t') {
cc.column = 1 + ALIGN_UP(cc.column, TAB_WIDTH);
} else {
++cc.column;
}
}
*coord = cc;
}
bool spt_equal(spt_t const *a, spt_t const *b)
{
return a->b_off == b->b_off;
}
char32_t spt_next_char(spt_t spt, spt_t *next)
{
char32_t ch = str_decode(spt.sh->data, &spt.b_off, spt.sh->text_size);
if (next)
*next = spt;
return ch;
}
char32_t spt_prev_char(spt_t spt, spt_t *prev)
{
char32_t ch = str_decode_reverse(spt.sh->data, &spt.b_off, spt.sh->text_size);
if (prev)
*prev = spt;
return ch;
}
void sheet_place_tag(sheet_t *sh, spt_t const *pt, tag_t *tag)
{
tag->b_off = pt->b_off;
tag->sh = sh;
list_append(&tag->link, &sh->tags);
}
void sheet_remove_tag(sheet_t *sh, tag_t *tag)
{
list_remove(&tag->link);
}
void tag_get_pt(tag_t const *tag, spt_t *pt)
{
pt->b_off = tag->b_off;
pt->sh = tag->sh;
}
HelenOS homepage, sources at GitHub