Example #1
0
Filerange text_range_linewise(Text *txt, Filerange *rin) {
	Filerange rout = *rin;
	rout.start = text_line_begin(txt, rin->start);
	if (rin->end != text_line_begin(txt, rin->end))
		rout.end = text_line_next(txt, rin->end);
	return rout;
}
Example #2
0
static size_t op_shift_left(Vis *vis, Text *txt, OperatorContext *c) {
	size_t pos = text_line_begin(txt, c->range.end), prev_pos;
	size_t tabwidth = vis->tabwidth, tablen;
	size_t deleted = 0;

	/* if range ends at the begin of a line, skip line break */
	if (pos == c->range.end)
		pos = text_line_prev(txt, pos);

	do {
		char c;
		size_t len = 0;
		prev_pos = pos = text_line_begin(txt, pos);
		Iterator it = text_iterator_get(txt, pos);
		if (text_iterator_byte_get(&it, &c) && c == '\t') {
			len = 1;
		} else {
			for (len = 0; text_iterator_byte_get(&it, &c) && c == ' '; len++)
				text_iterator_byte_next(&it, NULL);
		}
		tablen = MIN(len, tabwidth);
		text_delete(txt, pos, tablen);
		pos = text_line_prev(txt, pos);
		deleted += tablen;
	}  while (pos >= c->range.start && pos != prev_pos);

	return c->pos - deleted;
}
Example #3
0
Filerange text_object_indentation(Text *txt, size_t pos) {
    char c;
    size_t bol = text_line_begin(txt, pos);
    size_t sol = text_line_start(txt, bol);
    size_t start = bol;
    size_t end = text_line_next(txt, bol);
    size_t line_indent = sol - bol;
    bool line_empty = text_byte_get(txt, bol, &c) && (c == '\r' || c == '\n');

    char *buf = text_bytes_alloc0(txt, bol, line_indent);
    char *tmp = malloc(line_indent);

    if (!buf || !tmp) {
        free(buf);
        free(tmp);
        return text_range_empty();
    }

    while ((bol = text_line_begin(txt, text_line_prev(txt, start))) != start) {
        sol = text_line_start(txt, bol);
        size_t indent = sol - bol;
        if (indent < line_indent)
            break;
        bool empty = text_byte_get(txt, bol, &c) && (c == '\r' || c == '\n');
        if (line_empty && !empty)
            break;
        if (line_indent == 0 && empty)
            break;
        text_bytes_get(txt, bol, line_indent, tmp);
        if (memcmp(buf, tmp, line_indent))
            break;
        start = bol;
    }

    do {
        bol = end;
        sol = text_line_start(txt, bol);
        size_t indent = sol - bol;
        if (indent < line_indent)
            break;
        bool empty = text_byte_get(txt, bol, &c) && (c == '\r' || c == '\n');
        if (line_empty && !empty)
            break;
        if (line_indent == 0 && empty)
            break;
        text_bytes_get(txt, bol, line_indent, tmp);
        if (memcmp(buf, tmp, line_indent))
            break;
        end = text_line_next(txt, bol);
    } while (bol != end);

    free(buf);
    free(tmp);
    return text_range_new(start, end);
}
Example #4
0
size_t text_range_line_last(Text *txt, Filerange *r) {
	if (!text_range_valid(r))
		return EPOS;
	size_t pos = text_line_begin(txt, r->end);
	if (pos == r->end) {
		/* range ends at a begin of a line, skip last line ending */
		pos = text_line_prev(txt, pos);
		pos = text_line_begin(txt, pos);
	}
	return r->start <= pos ? pos : r->start;
}
Example #5
0
static size_t op_join(Vis *vis, Text *txt, OperatorContext *c) {
	size_t pos = text_line_begin(txt, c->range.end), prev_pos;
	Mark mark = NULL;

	/* if operator and range are both linewise, skip last line break */
	if (c->linewise && text_range_is_linewise(txt, &c->range)) {
		size_t line_prev = text_line_prev(txt, pos);
		size_t line_prev_prev = text_line_prev(txt, line_prev);
		if (line_prev_prev >= c->range.start)
			pos = line_prev;
	}

	size_t len = c->arg->s ? strlen(c->arg->s) : 0;

	do {
		prev_pos = pos;
		size_t end = text_line_start(txt, pos);
		pos = text_line_prev(txt, end);
		if (pos < c->range.start || end <= pos)
			break;
		text_delete(txt, pos, end - pos);
		char prev, next;
		if (text_byte_get(txt, pos-1, &prev) && !isspace((unsigned char)prev) &&
		    text_byte_get(txt, pos, &next) && next != '\r' && next != '\n')
			text_insert(txt, pos, c->arg->s, len);
		if (!mark)
			mark = text_mark_set(txt, pos);
	} while (pos != prev_pos);

	size_t newpos = text_mark_get(txt, mark);
	return newpos != EPOS ? newpos : c->range.start;
}
Example #6
0
static size_t op_join(Vis *vis, Text *txt, OperatorContext *c) {
	size_t pos = text_line_begin(txt, c->range.end), prev_pos;
	Mark mark = NULL;

	/* if operator and range are both linewise, skip last line break */
	if (c->linewise && text_range_is_linewise(txt, &c->range)) {
		size_t line_prev = text_line_prev(txt, pos);
		size_t line_prev_prev = text_line_prev(txt, line_prev);
		if (line_prev_prev >= c->range.start)
			pos = line_prev;
	}

	do {
		prev_pos = pos;
		size_t end = text_line_start(txt, pos);
		pos = text_char_next(txt, text_line_finish(txt, text_line_prev(txt, end)));
		if (pos >= c->range.start && end > pos) {
			text_delete(txt, pos, end - pos);
			text_insert(txt, pos, " ", 1);
			if (!mark)
				mark = text_mark_set(txt, pos);
		} else {
			break;
		}
	} while (pos != prev_pos);

	size_t newpos = text_mark_get(txt, mark);
	return newpos != EPOS ? newpos : c->range.start;
}
Example #7
0
size_t text_line_start(Text *txt, size_t pos) {
	char c;
	Iterator it = text_iterator_get(txt, text_line_begin(txt, pos));
	while (text_iterator_byte_get(&it, &c) && c != '\n' && space(c))
		text_iterator_byte_next(&it, NULL);
	return it.pos;
}
Example #8
0
File: view.c Project: mulianov/vis
/* move the cursor to the character at pos bytes from the begining of the file.
 * if pos is not in the current viewport, redraw the view to make it visible */
void view_cursor_to(View *view, size_t pos) {
	size_t max = text_size(view->text);

	if (pos > max)
		pos = max > 0 ? max - 1 : 0;

	if (pos == max && view->end != max) {
		/* do not display an empty screen when shoviewg the end of the file */
		view->start = max - 1;
		view_viewport_up(view, view->height / 2);
	} else {
		/* set the start of the viewable region to the start of the line on which
		 * the cursor should be placed. if this line requires more space than
		 * available in the view then simply start displaying text at the new
		 * cursor position */
		for (int i = 0;  i < 2 && (pos < view->start || pos > view->end); i++) {
			view->start = i == 0 ? text_line_begin(view->text, pos) : pos;
			view_draw(view);
		}
	}

	view->cursor.pos = pos;
	view_cursor_sync(view);
	view_cursor_update(view);
}
Example #9
0
size_t text_line_char_set(Text *txt, size_t pos, int count) {
	char c;
	size_t bol = text_line_begin(txt, pos);
	Iterator it = text_iterator_get(txt, bol);
	while (count-- > 0 && text_iterator_byte_get(&it, &c) && c != '\r' && c != '\n')
		text_iterator_char_next(&it, NULL);
	return it.pos;
}
Example #10
0
size_t text_line_offset(Text *txt, size_t pos, size_t off) {
	char c;
	size_t bol = text_line_begin(txt, pos);
	Iterator it = text_iterator_get(txt, bol);
	while (off-- > 0 && text_iterator_byte_get(&it, &c) && c != '\r' && c != '\n')
		text_iterator_byte_next(&it, NULL);
	return it.pos;
}
Example #11
0
static size_t op_delete(Vis *vis, Text *txt, OperatorContext *c) {
	c->reg->linewise = c->linewise;
	register_put_range(vis, c->reg, txt, &c->range);
	text_delete_range(txt, &c->range);
	size_t pos = c->range.start;
	if (c->linewise && pos == text_size(txt))
		pos = text_line_begin(txt, text_line_prev(txt, pos));
	return pos;
}
Example #12
0
static size_t op_put(Vis *vis, Text *txt, OperatorContext *c) {
	size_t pos = c->pos;
	bool sel = text_range_size(&c->range) > 0;
	bool sel_linewise = sel && text_range_is_linewise(txt, &c->range);
	if (sel) {
		text_delete_range(txt, &c->range);
		pos = c->pos = c->range.start;
	}
	switch (c->arg->i) {
	case VIS_OP_PUT_AFTER:
	case VIS_OP_PUT_AFTER_END:
		if (c->reg->linewise && !sel_linewise)
			pos = text_line_next(txt, pos);
		else if (!sel)
			pos = text_char_next(txt, pos);
		break;
	case VIS_OP_PUT_BEFORE:
	case VIS_OP_PUT_BEFORE_END:
		if (c->reg->linewise)
			pos = text_line_begin(txt, pos);
		break;
	}

	size_t len;
	const char *data = register_get(vis, c->reg, &len);

	for (int i = 0; i < c->count; i++) {
		text_insert(txt, pos, data, len);
		pos += len;
	}

	if (c->reg->linewise) {
		switch (c->arg->i) {
		case VIS_OP_PUT_BEFORE_END:
		case VIS_OP_PUT_AFTER_END:
			pos = text_line_start(txt, pos);
			break;
		case VIS_OP_PUT_AFTER:
			pos = text_line_start(txt, text_line_next(txt, c->pos));
			break;
		case VIS_OP_PUT_BEFORE:
			pos = text_line_start(txt, c->pos);
			break;
		}
	} else {
		switch (c->arg->i) {
		case VIS_OP_PUT_AFTER:
		case VIS_OP_PUT_BEFORE:
			pos = text_char_prev(txt, pos);
			break;
		}
	}

	return pos;
}
Example #13
0
int text_line_char_get(Text *txt, size_t pos) {
	char c;
	int count = 0;
	size_t bol = text_line_begin(txt, pos);
	Iterator it = text_iterator_get(txt, bol);
	while (text_iterator_byte_get(&it, &c) && it.pos < pos && c != '\r' && c != '\n') {
		text_iterator_char_next(&it, NULL);
		count++;
	}
	return count;
}
Example #14
0
static size_t op_shift_right(Vis *vis, Text *txt, OperatorContext *c) {
	char spaces[9] = "         ";
	spaces[MIN(vis->tabwidth, LENGTH(spaces) - 1)] = '\0';
	const char *tab = vis->expandtab ? spaces : "\t";
	size_t tablen = strlen(tab);
	size_t pos = text_line_begin(txt, c->range.end), prev_pos;
	size_t inserted = 0;

	/* if range ends at the begin of a line, skip line break */
	if (pos == c->range.end)
		pos = text_line_prev(txt, pos);

	do {
		prev_pos = pos = text_line_begin(txt, pos);
		text_insert(txt, pos, tab, tablen);
		pos = text_line_prev(txt, pos);
		inserted += tablen;
	}  while (pos >= c->range.start && pos != prev_pos);

	return c->pos + inserted;
}
Example #15
0
size_t text_line_width_set(Text *txt, size_t pos, int width) {
	int cur_width = 0;
	mbstate_t ps = { 0 };
	size_t bol = text_line_begin(txt, pos);
	Iterator it = text_iterator_get(txt, bol);

	for (;;) {
		char buf[MB_CUR_MAX];
		size_t len = text_bytes_get(txt, it.pos, sizeof buf, buf);
		if (len == 0 || buf[0] == '\r' || buf[0] == '\n')
			break;
		wchar_t wc;
		size_t wclen = mbrtowc(&wc, buf, len, &ps);
		if (wclen == (size_t)-1 && errno == EILSEQ) {
			/* assume a replacement symbol will be displayed */
			cur_width++;
		} else if (wclen == (size_t)-2) {
			/* do nothing, advance to next character */
		} else if (wclen == 0) {
			/* assume NUL byte will be displayed as ^@ */
			cur_width += 2;
		} else if (buf[0] == '\t') {
			cur_width++;
		} else {
			int w = wcwidth(wc);
			if (w == -1)
				w = 2; /* assume non-printable will be displayed as ^{char} */
			cur_width += w;
		}

		if (cur_width >= width || !text_iterator_codepoint_next(&it, NULL))
			break;
	}

	return it.pos;
}
Example #16
0
size_t text_range_line_prev(Text *txt, Filerange *r, size_t pos) {
	if (!text_range_contains(r, pos))
		return EPOS;
	size_t newpos = text_line_begin(txt, text_line_prev(txt, pos));
	return newpos != pos && r->start <= newpos ? newpos : EPOS;
}
Example #17
0
Filerange text_object_line(Text *txt, size_t pos) {
	Filerange r;
	r.start = text_line_begin(txt, pos);
	r.end = text_line_next(txt, pos);
	return r;
}
Example #18
0
bool text_range_is_linewise(Text *txt, Filerange *r) {
	return text_range_valid(r) &&
	       r->start == text_line_begin(txt, r->start) &&
	       r->end == text_line_begin(txt, r->end);
}