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; }
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; }
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; }