Example #1
0
File: buffer.c Project: dmt4/ne
int delete_one_line(buffer * const b, line_desc * const ld, const int64_t line) {
	assert_line_desc(ld, b->encoding);
	assert_buffer(b);

	block_signals();

	if (ld->line_len && (b->last_deleted = reset_stream(b->last_deleted))) add_to_stream(b->last_deleted, ld->line, ld->line_len);

	/* We delete a line by delete_stream()ing its length plus one. However, if
		we are on the last line of text, there is no terminating line feed. */

	const int error = delete_stream(b, ld, line, 0, ld->line_len + (ld->ld_node.next->next ? 1 : 0));
	release_signals();

	return error;
}
Example #2
0
File: edit.c Project: vigna/ne
int auto_indent_line(buffer * const b, const int64_t line, line_desc * const ld, const int64_t up_to_col) {

	line_desc * const prev_ld = (line_desc *)ld->ld_node.prev;

	if (!prev_ld->ld_node.prev || prev_ld->line_len == 0) return 0;
	assert_line_desc(prev_ld, b->encoding);

	int c;
	int64_t pos = 0;
	for(int64_t col = 0; pos < prev_ld->line_len && ne_isspace(c = get_char(&prev_ld->line[pos], b->encoding), b->encoding); ) {
		col += (c == '\t' ? b->opt.tab_size - col % b->opt.tab_size : 1);
		if (col > up_to_col) break;
		pos = next_pos(prev_ld->line, pos, b->encoding);
	}
	if (pos) insert_stream(b, ld, line, 0, prev_ld->line, pos);
	return pos;
}
Example #3
0
File: buffer.c Project: dmt4/ne
int insert_stream(buffer * const b, line_desc * ld, int64_t line, int64_t pos, const char * const stream, const int64_t stream_len) {
	if (!b || !ld || !stream || stream_len < 1 || pos > ld->line_len) return ERROR;

	assert_line_desc(ld, b->encoding);
	assert_buffer(b);

	block_signals();

	if (b->opt.do_undo && !(b->undoing || b->redoing)) {
		const int error = add_undo_step(b, line, pos, -stream_len);
		if (error) {
			release_signals();
			return error;
		}
	}

	const char *s = stream;
	while(s - stream < stream_len) {
		int64_t const len = strnlen_ne(s, stream_len - (s - stream));
		if (len) {

			/* First case; there is no character allocated on this line. We
			have to freshly allocate the line. */

			if (!ld->line) {
				if (ld->line = alloc_chars(b, len)) {
					memcpy(ld->line, s, len);
					ld->line_len = len;
				}
				else {
					release_signals();
					return OUT_OF_MEMORY;
				}
			}


			/* Second case. There are not enough characters around ld->line. Note
			that the value of the check_first_before parameter depends on
			the position at which the insertion will be done, and it is chosen
			in such a way to minimize the number of characters to move. */

			else {
				const int64_t result = alloc_chars_around(b, ld, len, pos < ld->line_len / 2);
				if (result < 0) {
					char * const p = alloc_chars(b, ld->line_len + len);
					if (p) {
						memcpy(p, ld->line, pos);
						memcpy(&p[pos], s, len);
						memcpy(&p[pos + len], ld->line + pos, ld->line_len - pos);
						free_chars(b, ld->line, ld->line_len);
						ld->line = p;
						ld->line_len += len;
					}
					else {
						release_signals();
						return OUT_OF_MEMORY;
					}
				}
				else { /* Third case. There are enough free characters around ld->line. */
					if (len - result) memmove(ld->line - (len - result), ld->line, pos);
					if (result) memmove(ld->line + pos + result, ld->line + pos, ld->line_len - pos);
					memcpy(ld->line - (len - result) + pos, s, len);
	
					ld->line -= (len - result);
					ld->line_len += len;
				}
			}
			b->is_modified = 1;

			/* We just inserted len chars at (line,pos); adjust bookmarks and mark accordingly. */
			if (b->marking && b->block_start_line == line && b->block_start_pos > pos) b->block_start_pos += len;

			for (int i = 0, mask = b->bookmark_mask; mask; i++, mask >>= 1) 
				if ((mask & 1) && b->bookmark[i].line == line && b->bookmark[i].pos > pos) b->bookmark[i].pos += len;
		}

		/* If the string we have inserted has a NULL at the end, we create a new
			line under the current one and set ld to point to it. */

		if (len + (s - stream) < stream_len) {
			line_desc *new_ld;

			if (new_ld = alloc_line_desc(b)) {

				add(&new_ld->ld_node, &ld->ld_node);
				b->num_lines++;

				if (pos + len < ld->line_len) {
					new_ld->line_len = ld->line_len - pos - len;
					new_ld->line = &ld->line[pos + len];
					ld->line_len = pos + len;
					if (pos + len == 0) ld->line = NULL;
				}

				b->is_modified = 1;
				ld = new_ld;

				/* We just inserted a line break at (line,pos);
				   adjust the buffer bookmarks and mark accordingly. */
				if (b->marking) {
					if (b->block_start_line == line && b->block_start_pos > pos) {
						b->block_start_pos -= pos;
						b->block_start_line++;
					}
					else if (b->block_start_line > line) b->block_start_line++;
				}
				for (int i = 0, mask=b->bookmark_mask; mask; i++, mask >>= 1) {
					if (mask & 1) {
						if (b->bookmark[i].line == line && b->bookmark[i].pos > pos) {
							b->bookmark[i].pos -= pos;
							b->bookmark[i].line++;
						}
						else if (b->bookmark[i].line > line) b->bookmark[i].line++;
					}
				}
				pos = 0;
				line++;
			}
			else {