Esempio n. 1
0
File: search.c Progetto: dmt4/ne
int replace(buffer * const b, const int n, const char * const string) {

	int64_t len;

	assert(string != NULL);

	last_replace_empty_match = false;

	len = strlen(string);

	start_undo_chain(b);

	delete_stream(b, b->cur_line_desc, b->cur_line, b->cur_pos, n);

	if (len) insert_stream(b, b->cur_line_desc, b->cur_line, b->cur_pos, string, len);

	end_undo_chain(b);

	if (! b->opt.search_back) goto_pos(b, b->cur_pos + len);

	return OK;
}
Esempio n. 2
0
File: search.c Progetto: dmt4/ne
int replace_regexp(buffer * const b, const char * const string) {
	assert(string != NULL);

	bool reg_used = false;
	char *p, *q, *t = NULL;
	if (q = p = str_dup(string)) {

		int len = strlen(p);

		while(true) {
			while(*q && *q != '\\') q++;

			if (!*q) break;

			int i = *(q + 1) - '0';

			if (*(q + 1) == '\\') {
				memmove(q, q + 1, strlen(q + 1) + 1);
				q++;
				len--;
			}
			else if (i >= 0 && i < RE_NREGS && re_reg.start[i] >= 0) {
				if (b->encoding == ENC_UTF8) {
					/* In the UTF-8 case, the replacement group index must be
						mapped through map_group to recover the real group. */
					if ((i = map_group[i]) >= RE_NREGS) {
						free(p);
						return GROUP_NOT_AVAILABLE;
					}
				}
				*q++ = 0;
				*q++ = i;
				reg_used = true;
			}
			else {
				free(p);
				return WRONG_CHAR_AFTER_BACKSLASH;
			}
		}

		if (reg_used) {
			if (t = malloc(re_reg.end[0] - re_reg.start[0] + 1)) {
				memcpy(t, b->cur_line_desc->line + re_reg.start[0], re_reg.end[0] - re_reg.start[0]);
				t[re_reg.end[0] - re_reg.start[0]] = 0;
			}
			else {
				free(p);
				return OUT_OF_MEMORY;
			}
		}

		for(int i = re_reg.num_regs; i-- != 0;) {
			re_reg.end[i] -= re_reg.start[0];
			re_reg.start[i] -= re_reg.start[0];
		}

		start_undo_chain(b);

		delete_stream(b, b->cur_line_desc, b->cur_line, b->cur_pos, re_reg.end[0]);

		q = p;
		int64_t pos = 0;

		while(true) {
			if (strlen(q)) {
				insert_stream(b, b->cur_line_desc, b->cur_line, b->cur_pos + pos, q, strlen(q));
				pos += strlen(q);
			}

			q += strlen(q) + 1;

			if (q - p > len) break;

			assert(*q < RE_NREGS);

			if (re_reg.end[*(unsigned char *)q] - re_reg.start[*(unsigned char *)q]) {

				char c = t[re_reg.end[*(unsigned char *)q]];
				t[re_reg.end[*(unsigned char *)q]] = 0;

				insert_stream(b, b->cur_line_desc, b->cur_line, b->cur_pos + pos, t + re_reg.start[*(unsigned char *)q], re_reg.end[*(unsigned char *)q] - re_reg.start[*(unsigned char *)q]);

				t[re_reg.end[*(unsigned char *)q]] = c;

				pos += re_reg.end[*(unsigned char *)q] - re_reg.start[*(unsigned char *)q];
			}

			q++;
		}

		end_undo_chain(b);

		if (! b->opt.search_back) goto_pos(b, b->cur_pos + pos);

		free(t);
		free(p);
	}
	else return OUT_OF_MEMORY;

	last_replace_empty_match = re_reg.start[0] == re_reg.end[0];
	return OK;
}
Esempio n. 3
0
File: edit.c Progetto: vigna/ne
int paragraph(buffer * const b) {
	line_desc *ld = b->cur_line_desc, *start_line_desc = ld;

	if (!ld->line) return line_down(b);

	/* Establish appropriate leading space. This will be taken from the line
      following the current line if it is non-blank. Otherwise it will be
      taken from the current line. Save a copy of it for later as space[]. **/

	if ( !(    (ld->ld_node.next->next && save_space((line_desc *)ld->ld_node.next, b->opt.tab_size, b->encoding))
	        || save_space(ld, b->opt.tab_size, b->encoding) )
	   ) return line_down(b);

	int64_t pos = b->cur_pos;
	b->cur_pos = -1;

	start_undo_chain(b);

	/* This insertion and deletion of a single character ensures
	   that the cursor ends up here after an undo. */
	int64_t line = b->cur_line;
	insert_one_char(b, ld, line, 0, ' ');
	delete_stream(b, ld, line, 0, 1);

	const int right_margin = b->opt.right_margin ? b->opt.right_margin : ne_columns;
	bool done;

	do {
		done = true; /* set this to false if we do any work in the loop. */

		trim_trailing_space(b, ld, line, b->encoding);

		/* Suck up subsequent lines until this one is long enough to need splitting */
		while ((calc_width(ld, ld->line_len, b->opt.tab_size, b->encoding) <= right_margin) &&
		       ld->ld_node.next->next && is_part_of_paragraph((line_desc *)ld->ld_node.next, b->opt.tab_size, &pos, b->encoding)) {
			line_desc *ld_next = (line_desc *)ld->ld_node.next;
			insert_one_char(b, ld, line, ld->line_len, ' ');
			if (pos) delete_stream(b, ld_next, line + 1, 0, pos); /* pos was set by is_part_of_paragraph() above. */
			delete_stream(b, ld, line, ld->line_len, 1);          /* joins next line to this one */
			trim_trailing_space(b, ld, line, b->encoding);
			done = false;
		}

		if (calc_width(ld, ld->line_len, b->opt.tab_size, b->encoding) > right_margin) {
			int64_t spaces;
			int64_t split_pos;
			/* Skip past leading spaces... */
			pos = 0;
			while(pos < ld->line_len && isasciispace(ld->line[pos]))
				pos = next_pos(ld->line, pos, b->encoding);

			/* Find the split point */
			split_pos = spaces = 0;
			while (pos < ld->line_len && (calc_width(ld, pos, b->opt.tab_size, b->encoding) < right_margin || ! split_pos)) {
				if (isasciispace(ld->line[pos])) {
					split_pos = pos;
					spaces = 0;
					while (pos < ld->line_len && isasciispace(ld->line[pos])) {
						pos = next_pos(ld->line, pos, b->encoding);
						spaces++;
					}
				}
				else pos = next_pos(ld->line, pos, b->encoding);
			}
			if (split_pos) {
				done = false;
				/* Remove any space at the split point. */
				if (spaces) delete_stream(b, ld, line, split_pos, spaces);

				/* Split the line at the split point.  (We are done with this line) */
				insert_one_line(b, ld, line, split_pos);

				/* Make the new next line the current line **/
				if (ld->ld_node.next->next) {
					ld = (line_desc *)ld->ld_node.next;
					line++;
					if (pa_space && pa_space_len && pa_space_pos)
						insert_stream(b, ld, line, 0, pa_space, pa_space_pos);
					trim_trailing_space(b, ld, line, b->encoding);
				}
			} else { /* Line not split; is there a next one in the paragraph? */
				if ( ld->ld_node.next->next && is_part_of_paragraph((line_desc *)ld->ld_node.next, b->opt.tab_size, &pos, b->encoding) ) {
					ld = (line_desc *)ld->ld_node.next;
					line++;
					done = false;
				}
			}
		}
	} while (!stop && !done);

	end_undo_chain(b);

	if (pa_space) {
		free(pa_space);
		pa_space = NULL;
	}

	if (b->syn) {
		b->attr_len = -1;
		need_attr_update = true;
		update_syntax_states(b, -1, start_line_desc, (line_desc *)ld->ld_node.next);
	}
	update_window_lines(b, b->cur_line_desc, b->cur_y, ne_lines - 2, false);

	goto_line_pos(b, line, pos);
	if (stop || line_down(b) == ERROR) return stop ? STOPPED : ERROR;

	/* Try to find the first non-blank starting with this line. */
	ld = b->cur_line_desc;
	line = b->cur_line;

	do {
		if (ld->line) {
			for (pos = 0; pos < ld->line_len; pos = next_pos(ld->line, pos, b->encoding)) {
				if (!isasciispace(ld->line[pos])) {
					goto_line_pos(b, line, pos);
					return ld->ld_node.next ? OK : ERROR;
				}
			}
		}
		ld = (line_desc *)ld->ld_node.next;
		line++;
	} while (ld->ld_node.next);

	return b->cur_line_desc->ld_node.next ? OK : ERROR;
}
Esempio n. 4
0
File: buffer.c Progetto: dmt4/ne
int insert_one_line(buffer * const b, line_desc * const ld, const int64_t line, const int64_t pos) {	
	return insert_stream(b, ld, line, pos, "", 1);
}
Esempio n. 5
0
File: edit.c Progetto: vigna/ne
static int to_something(buffer *b, int (to_first)(int), int (to_rest)(int)) {
	assert_buffer(b);

	/* If we are after the end of the line, just return ERROR. */

	if (b->cur_line == b->num_lines -1 && b->cur_pos >= b->cur_line_desc->line_len) return ERROR;

	int64_t pos = b->cur_pos;
	int c;
	/* First of all, we search for the word start, if we're not over it. */
	if (pos >= b->cur_line_desc->line_len || !ne_isword(c = get_char(&b->cur_line_desc->line[pos], b->encoding), b->encoding))
		if (search_word(b, 1) != OK)
			return ERROR;

	bool changed = false;
	int64_t new_len = 0;
	pos = b->cur_pos;
	const int64_t cur_char = b->cur_char;
	const int cur_x = b->cur_x;
	/* Then, we compute the word position extremes, length of the result (which
		may change because of casing). */
	while (pos < b->cur_line_desc->line_len && ne_isword(c = get_char(&b->cur_line_desc->line[pos], b->encoding), b->encoding)) {
		const int new_c = new_len ? to_rest(c) : to_first(c);
		changed |= (c != new_c);

		if (b->encoding == ENC_UTF8) new_len += utf8seqlen(new_c);
		else new_len++;

		pos = next_pos(b->cur_line_desc->line, pos, b->encoding);
	}

	const int64_t len = pos - b->cur_pos;
	if (!len) {
		char_right(b);
		return OK;
	}

	if (changed) {
		/* We actually perform changes only if some character was case folded. */
		char * word = malloc(new_len * sizeof *word);
		if (!word) return OUT_OF_MEMORY;

		pos = b->cur_pos;
		new_len = 0;
		/* Second pass: we actually build the transformed word. */
		while (pos < b->cur_line_desc->line_len && ne_isword(c = get_char(&b->cur_line_desc->line[pos], b->encoding), b->encoding)) {
			if (b->encoding == ENC_UTF8) new_len += utf8str(new_len ? to_rest(c) : to_first(c), word + new_len);
			else {
				word[new_len] = new_len ? to_rest(c) : to_first(c);
				new_len++;
			}

			pos = next_pos(b->cur_line_desc->line, pos, b->encoding);
		}

		start_undo_chain(b);

		delete_stream(b, b->cur_line_desc, b->cur_line, b->cur_pos, len);
		if (new_len) insert_stream(b, b->cur_line_desc, b->cur_line, b->cur_pos, word, new_len);

		free(word);

		end_undo_chain(b);

		if (cur_char < b->attr_len) b->attr_len = cur_char;
		update_line(b, b->cur_line_desc, b->cur_y, cur_x, false);
		need_attr_update = true;
	}

	return search_word(b, 1);
}