예제 #1
0
파일: edit.c 프로젝트: vigna/ne
int64_t word_wrap(buffer * const b) {
	const int64_t len = b->cur_line_desc->line_len;
	char * const line = b->cur_line_desc->line;
	int64_t pos, first_pos;

	if (!(pos = b->cur_pos)) return ERROR;

	/* Find the first possible position we could break a line on. */
	first_pos = 0;

	/* Skip leading white space */
	while (first_pos < len && ne_isspace(get_char(&line[first_pos], b->encoding), b->encoding)) first_pos = next_pos(line, first_pos, b->encoding);

	/* Skip non_space after leading white space */
	while (first_pos < len && !ne_isspace(get_char(&line[first_pos], b->encoding), b->encoding)) first_pos = next_pos(line, first_pos, b->encoding);

	/* Now we know that the line shouldn't be broken before &line[first_pos]. */

	/* Search left from the current position to find a candidate space to break the line on.*/
	while((pos = prev_pos(line, pos, b->encoding)) && !ne_isspace(get_char(&line[pos], b->encoding), b->encoding));

	if (! pos || pos < first_pos) return ERROR;

	start_undo_chain(b);

	const int64_t result = b->cur_pos - pos - 1;
	if (pos < b->cur_pos) b->cur_pos = -1;
	delete_one_char(b, b->cur_line_desc, b->cur_line, pos);
	insert_one_line(b, b->cur_line_desc, b->cur_line, pos);

	end_undo_chain(b);

	return result;
}
예제 #2
0
파일: buffer.c 프로젝트: dmt4/ne
int undelete_line(buffer * const b) {
	line_desc * const ld = b->cur_line_desc;
	if (!b->last_deleted) return ERROR;
	start_undo_chain(b);
	if (b->cur_pos > ld->line_len) 
		insert_spaces(b, ld, b->cur_line, ld->line_len, b->win_x + b->cur_x - calc_width(ld, ld->line_len, b->opt.tab_size, b->encoding));

	insert_one_line(b, ld, b->cur_line, b->cur_pos);
	insert_stream(b, ld, b->cur_line, b->cur_pos, b->last_deleted->stream, b->last_deleted->len);
	end_undo_chain(b);
	return OK;
}
예제 #3
0
파일: edit.c 프로젝트: 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;
}