To: vim-dev@vim.org Subject: Patch 6.2.327 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit ------------ Patch 6.2.327 Problem: When formatting text all marks in the formatted lines are lost. A word is not joined to a previous line when this would be possible. (Mikolaj Machowski) Solution: Try to keep marks in the same position as much as possible. Also keep mark positions when joining lines. Start auto-formatting in the previous line when appropriate. Add the "gw" operator: Like "gq" but keep the cursor where it is. Files: runtime/doc/change.txt, src/edit.c, src/globals.h, src/mark.c, src/misc1.c, src/normal.c, src/ops.c, src/proto/edit.pro, src/proto/mark.pro, src/proto/ops.pro, src/structs.h, src/vim.h *** ../vim-6.2.326/runtime/doc/change.txt Sun Jun 1 12:20:31 2003 --- runtime/doc/change.txt Thu Mar 4 23:02:55 2004 *************** *** 1,4 **** ! *change.txt* For Vim version 6.2. Last change: 2003 May 24 VIM REFERENCE MANUAL by Bram Moolenaar --- 1,4 ---- ! *change.txt* For Vim version 6.2. Last change: 2004 Mar 04 VIM REFERENCE MANUAL by Bram Moolenaar *************** *** 1104,1110 **** {Visual}gq Format the highlighted text. (for {Visual} see |Visual-mode|). {not in Vi} ! Example: To format the current paragraph use: > gqap The "gq" command leaves the cursor in the line where the motion command takes --- 1128,1140 ---- {Visual}gq Format the highlighted text. (for {Visual} see |Visual-mode|). {not in Vi} ! *gw* ! gw{motion} Format the lines that {motion} moves over. Similar to ! |gq| but puts the cursor back at the same position in ! the text. However, 'formatprg' is not used. ! {not in Vi} ! ! Example: To format the current paragraph use: *gqap* > gqap The "gq" command leaves the cursor in the line where the motion command takes *************** *** 1112,1117 **** --- 1142,1152 ---- works well with "gqj" (format current and next line) and "gq}" (format until end of paragraph). Note: When 'formatprg' is set, "gq" leaves the cursor on the first formatted line (as with using a filter command). + + If you want to format the current paragraph and continue where you were, use: > + gwap + If you always want to keep paragraphs formatted you may want to add the 'a' + flag to 'formatoptions'. See |auto-format|. If the 'autoindent' option is on, Vim uses the indent of the first line for the following lines. *** ../vim-6.2.326/src/edit.c Tue Mar 2 14:59:39 2004 --- src/edit.c Mon Mar 8 11:55:50 2004 *************** *** 122,130 **** static void undisplay_dollar __ARGS((void)); static void insert_special __ARGS((int, int, int)); static void check_auto_format __ARGS((int)); - #ifdef FEAT_COMMENTS - static int cmplen __ARGS((char_u *s1, char_u *s2)); - #endif static void redo_literal __ARGS((int c)); static void start_arrow __ARGS((pos_T *end_insert_pos)); static void stop_insert __ARGS((pos_T *end_insert_pos, int esc)); --- 122,127 ---- *************** *** 874,880 **** /* insert the contents of a register */ case Ctrl_R: ins_reg(); ! auto_format(FALSE); inserted_space = FALSE; break; --- 871,877 ---- /* insert the contents of a register */ case Ctrl_R: ins_reg(); ! auto_format(FALSE, TRUE); inserted_space = FALSE; break; *************** *** 969,975 **** } # endif ins_shift(c, lastc); ! auto_format(FALSE); inserted_space = FALSE; break; --- 966,972 ---- } # endif ins_shift(c, lastc); ! auto_format(FALSE, TRUE); inserted_space = FALSE; break; *************** *** 977,1002 **** case K_DEL: case K_KDEL: ins_del(); ! auto_format(FALSE); break; /* delete character before the cursor */ case K_BS: case Ctrl_H: did_backspace = ins_bs(c, BACKSPACE_CHAR, &inserted_space); ! auto_format(FALSE); break; /* delete word before the cursor */ case Ctrl_W: did_backspace = ins_bs(c, BACKSPACE_WORD, &inserted_space); ! auto_format(FALSE); break; /* delete all inserted text in current line */ case Ctrl_U: did_backspace = ins_bs(c, BACKSPACE_LINE, &inserted_space); ! auto_format(FALSE); inserted_space = FALSE; break; --- 974,999 ---- case K_DEL: case K_KDEL: ins_del(); ! auto_format(FALSE, TRUE); break; /* delete character before the cursor */ case K_BS: case Ctrl_H: did_backspace = ins_bs(c, BACKSPACE_CHAR, &inserted_space); ! auto_format(FALSE, TRUE); break; /* delete word before the cursor */ case Ctrl_W: did_backspace = ins_bs(c, BACKSPACE_WORD, &inserted_space); ! auto_format(FALSE, TRUE); break; /* delete all inserted text in current line */ case Ctrl_U: did_backspace = ins_bs(c, BACKSPACE_LINE, &inserted_space); ! auto_format(FALSE, TRUE); inserted_space = FALSE; break; *************** *** 1119,1125 **** inserted_space = FALSE; if (ins_tab()) goto normalchar; /* insert TAB as a normal char */ ! auto_format(FALSE); break; case K_KENTER: --- 1116,1122 ---- inserted_space = FALSE; if (ins_tab()) goto normalchar; /* insert TAB as a normal char */ ! auto_format(FALSE, TRUE); break; case K_KENTER: *************** *** 1146,1152 **** #endif if (ins_eol(c) && !p_im) goto doESCkey; /* out of memory */ ! auto_format(FALSE); inserted_space = FALSE; break; --- 1143,1149 ---- #endif if (ins_eol(c) && !p_im) goto doESCkey; /* out of memory */ ! auto_format(FALSE, FALSE); inserted_space = FALSE; break; *************** *** 1260,1266 **** revins_legal++; #endif c = Ctrl_V; /* pretend CTRL-V is last character */ ! auto_format(FALSE); } } break; --- 1257,1263 ---- revins_legal++; #endif c = Ctrl_V; /* pretend CTRL-V is last character */ ! auto_format(FALSE, TRUE); } } break; *************** *** 1307,1313 **** #endif } ! auto_format(FALSE); #ifdef FEAT_FOLDING /* When inserting a character the cursor line must never be in a --- 1304,1310 ---- #endif } ! auto_format(FALSE, TRUE); #ifdef FEAT_FOLDING /* When inserting a character the cursor line must never be in a *************** *** 1767,1774 **** if (State & VREPLACE_FLAG) { /* If orig_line didn't allocate, just return. At least we did the job, ! * even if you can't backspace. ! */ if (orig_line == NULL) return; --- 1764,1770 ---- if (State & VREPLACE_FLAG) { /* If orig_line didn't allocate, just return. At least we did the job, ! * even if you can't backspace. */ if (orig_line == NULL) return; *************** *** 2509,2515 **** curwin->w_cursor.col++; } ! auto_format(FALSE); ins_compl_free(); started_completion = FALSE; --- 2505,2511 ---- curwin->w_cursor.col++; } ! auto_format(FALSE, TRUE); ins_compl_free(); started_completion = FALSE; *************** *** 4114,4120 **** * Split the line just before the margin. * Only insert/delete lines, but don't really redraw the window. */ ! open_line(FORWARD, OPENLINE_DELSPACES + (fo_white_par ? OPENLINE_KEEPTRAIL : 0) #ifdef FEAT_COMMENTS + (do_comments ? OPENLINE_DO_COM : 0) --- 4110,4116 ---- * Split the line just before the margin. * Only insert/delete lines, but don't really redraw the window. */ ! open_line(FORWARD, OPENLINE_DELSPACES + OPENLINE_MARKFIX + (fo_white_par ? OPENLINE_KEEPTRAIL : 0) #ifdef FEAT_COMMENTS + (do_comments ? OPENLINE_DO_COM : 0) *************** *** 4366,4377 **** * saved here. */ void ! auto_format(trailblank) int trailblank; /* when TRUE also format with trailing blank */ { pos_T pos; colnr_T len; ! char_u *old, *pold; char_u *new, *pnew; int wasatend; --- 4362,4374 ---- * saved here. */ void ! auto_format(trailblank, prev_line) int trailblank; /* when TRUE also format with trailing blank */ + int prev_line; /* may start in previous line */ { pos_T pos; colnr_T len; ! char_u *old; char_u *new, *pnew; int wasatend; *************** *** 4413,4490 **** return; #endif ! old = vim_strsave(old); ! format_lines((linenr_T)-1); ! /* Advance to the same text position again. This is tricky, indents ! * may have changed and comment leaders may have been inserted. */ ! curwin->w_cursor.lnum = pos.lnum; ! curwin->w_cursor.col = 0; ! pold = old; ! while (1) ! { ! if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count) ! { ! curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count; ! curwin->w_cursor.col = MAXCOL; ! break; ! } ! /* Make "pold" and "pnew" point to the start of the line, ignoring ! * indent and comment leader. */ ! pold = skipwhite(pold); ! new = ml_get_curline(); ! pnew = skipwhite(new); ! #ifdef FEAT_COMMENTS ! len = get_leader_len(new, NULL, FALSE); ! if (len > 0) ! { ! char_u *p; ! /* Skip the leader if the old text matches after it, ignoring ! * white space. Keep in mind that the leader may appear in ! * the text! */ ! p = skipwhite(new + len); ! if (cmplen(pold, pnew) < cmplen(pold, p)) ! pnew = p; ! } ! #endif ! len = (colnr_T)STRLEN(pnew); ! if ((pold - old) + len >= pos.col) { ! if (pos.col <= (colnr_T)(pold - old)) ! curwin->w_cursor.col = (pnew - new); ! else ! curwin->w_cursor.col = pos.col - (pold - old) + (pnew - new); ! ! /* Insert mode: If the cursor is now after the end of the line ! * while it previously wasn't, the line was broken. Because of ! * the rule above we need to add a space when 'w' is in ! * 'formatoptions' to keep a paragraph formatted. */ ! if (!wasatend && has_format_option(FO_WHITE_PAR)) ! { ! len = STRLEN(new); ! if (curwin->w_cursor.col == len) ! { ! pnew = vim_strnsave(new, len + 2); ! pnew[len] = ' '; ! pnew[len + 1] = NUL; ! ml_replace(curwin->w_cursor.lnum, pnew, FALSE); ! /* remove the space later */ ! did_add_space = TRUE; ! } ! else ! /* may remove added space */ ! check_auto_format(FALSE); ! } ! break; } ! /* Cursor wraps to next line */ ! ++curwin->w_cursor.lnum; ! pold += len; } check_cursor(); - vim_free(old); } /* --- 4410,4468 ---- return; #endif ! /* ! * May start formatting in a previous line, so that after "x" a word is ! * moved to the previous line if it fits there now. Only when this is not ! * the start of a paragraph. ! */ ! if (prev_line && !paragraph_start(curwin->w_cursor.lnum)) ! { ! --curwin->w_cursor.lnum; ! if (u_save_cursor() == FAIL) ! return; ! } ! /* ! * Do the formatting and restore the cursor position. "saved_cursor" will ! * be adjusted for the text formatting. ! */ ! saved_cursor = pos; ! format_lines((linenr_T)-1); ! curwin->w_cursor = saved_cursor; ! saved_cursor.lnum = 0; ! if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count) ! { ! /* "cannot happen" */ ! curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count; ! coladvance((colnr_T)MAXCOL); ! } ! else ! check_cursor_col(); ! /* Insert mode: If the cursor is now after the end of the line while it ! * previously wasn't, the line was broken. Because of the rule above we ! * need to add a space when 'w' is in 'formatoptions' to keep a paragraph ! * formatted. */ ! if (!wasatend && has_format_option(FO_WHITE_PAR)) ! { ! new = ml_get_curline(); ! len = STRLEN(new); ! if (curwin->w_cursor.col == len) { ! pnew = vim_strnsave(new, len + 2); ! pnew[len] = ' '; ! pnew[len + 1] = NUL; ! ml_replace(curwin->w_cursor.lnum, pnew, FALSE); ! /* remove the space later */ ! did_add_space = TRUE; } ! else ! /* may remove added space */ ! check_auto_format(FALSE); } + check_cursor(); } /* *************** *** 4521,4552 **** } } - #ifdef FEAT_COMMENTS - /* - * Return the number of bytes for which strings "s1" and "s2" are equal. - */ - static int - cmplen(s1, s2) - char_u *s1; - char_u *s2; - { - char_u *p1 = s1, *p2 = s2; - - while (*p1 == *p2 && *p1 != NUL) - { - ++p1; - ++p2; - } - return (int)(p1 - s1); - } - #endif - /* * Find out textwidth to be used for formatting: * if 'textwidth' option is set, use it * else if 'wrapmargin' option is set, use W_WIDTH(curwin) - 'wrapmargin' * if invalid value, use 0. ! * Set default to window width (maximum 79) for "Q" command. */ int comp_textwidth(ff) --- 4499,4510 ---- } } /* * Find out textwidth to be used for formatting: * if 'textwidth' option is set, use it * else if 'wrapmargin' option is set, use W_WIDTH(curwin) - 'wrapmargin' * if invalid value, use 0. ! * Set default to window width (maximum 79) for "gq" operator. */ int comp_textwidth(ff) *************** *** 4694,4700 **** * a line and having it end in a space. But only do it when something * was actually inserted, otherwise undo won't work. */ if (!ins_need_undo) ! auto_format(TRUE); /* If a space was inserted for auto-formatting, remove it now. */ check_auto_format(TRUE); --- 4652,4675 ---- * a line and having it end in a space. But only do it when something * was actually inserted, otherwise undo won't work. */ if (!ins_need_undo) ! { ! /* When the cursor is at the end of the line after a space the ! * formatting will move it to the following word. Avoid that by ! * moving the cursor onto the space. */ ! cc = 'x'; ! if (curwin->w_cursor.col > 0 == NUL && gchar_cursor()) ! { ! dec_cursor(); ! cc = gchar_cursor(); ! if (!vim_iswhite(cc)) ! inc_cursor(); ! } ! ! auto_format(TRUE, FALSE); ! ! if (vim_iswhite(cc) && gchar_cursor() != NUL) ! inc_cursor(); ! } /* If a space was inserted for auto-formatting, remove it now. */ check_auto_format(TRUE); *** ../vim-6.2.326/src/globals.h Sat Mar 6 21:10:59 2004 --- src/globals.h Sat Mar 6 15:13:54 2004 *************** *** 608,613 **** --- 608,619 ---- EXTERN int can_si_back INIT(= FALSE); #endif + EXTERN pos_T saved_cursor /* w_cursor before formatting text. */ + # ifdef DO_INIT + = INIT_POS_T + # endif + ; + /* * Stuff for insert mode. */ *** ../vim-6.2.326/src/mark.c Tue Mar 2 16:04:09 2004 --- src/mark.c Thu Mar 4 13:50:05 2004 *************** *** 923,928 **** --- 923,932 ---- /* previous pcmark */ one_adjust(&(curwin->w_prev_pcmark.lnum)); + /* saved cursor for formatting */ + if (saved_cursor.lnum != 0) + one_adjust_nodel(&(saved_cursor.lnum)); + /* * Adjust items in all windows related to the current buffer. */ *************** *** 1008,1013 **** --- 1012,1117 ---- /* adjust diffs */ diff_mark_adjust(line1, line2, amount, amount_after); #endif + } + + /* This code is used often, needs to be fast. */ + #define col_adjust(pp) \ + { \ + posp = pp; \ + if (posp->lnum == lnum && posp->col >= mincol) \ + { \ + posp->lnum += lnum_amount; \ + if (col_amount < 0 && posp->col <= (colnr_T)-col_amount) \ + posp->col = 0; \ + else \ + posp->col += col_amount; \ + } \ + } + + /* + * Adjust marks in line "lnum" at column "mincol" and further: add + * "lnum_amount" to the line number and add "col_amount" to the column + * position. + */ + void + mark_col_adjust(lnum, mincol, lnum_amount, col_amount) + linenr_T lnum; + colnr_T mincol; + long lnum_amount; + long col_amount; + { + int i; + int fnum = curbuf->b_fnum; + win_T *win; + pos_T *posp; + + if ((col_amount == 0L && lnum_amount == 0L) || cmdmod.lockmarks) + return; /* nothing to do */ + + /* named marks, lower case and upper case */ + for (i = 0; i < NMARKS; i++) + { + col_adjust(&(curbuf->b_namedm[i])); + if (namedfm[i].fmark.fnum == fnum) + col_adjust(&(namedfm[i].fmark.mark)); + } + for (i = NMARKS; i < NMARKS + EXTRA_MARKS; i++) + { + if (namedfm[i].fmark.fnum == fnum) + col_adjust(&(namedfm[i].fmark.mark)); + } + + /* last Insert position */ + col_adjust(&(curbuf->b_last_insert)); + + /* last change position */ + col_adjust(&(curbuf->b_last_change)); + + #ifdef FEAT_JUMPLIST + /* list of change positions */ + for (i = 0; i < curbuf->b_changelistlen; ++i) + col_adjust(&(curbuf->b_changelist[i])); + #endif + + #ifdef FEAT_VISUAL + /* Visual area */ + col_adjust(&(curbuf->b_visual_start)); + col_adjust(&(curbuf->b_visual_end)); + #endif + + /* previous context mark */ + col_adjust(&(curwin->w_pcmark)); + + /* previous pcmark */ + col_adjust(&(curwin->w_prev_pcmark)); + + /* saved cursor for formatting */ + col_adjust(&saved_cursor); + + /* + * Adjust items in all windows related to the current buffer. + */ + FOR_ALL_WINDOWS(win) + { + #ifdef FEAT_JUMPLIST + /* marks in the jumplist */ + for (i = 0; i < win->w_jumplistlen; ++i) + if (win->w_jumplist[i].fmark.fnum == fnum) + col_adjust(&(win->w_jumplist[i].fmark.mark)); + #endif + + if (win->w_buffer == curbuf) + { + /* marks in the tag stack */ + for (i = 0; i < win->w_tagstacklen; i++) + if (win->w_tagstack[i].fmark.fnum == fnum) + col_adjust(&(win->w_tagstack[i].fmark.mark)); + + /* cursor position for other windows with the same buffer */ + if (win != curwin) + col_adjust(&win->w_cursor); + } + } } #ifdef FEAT_JUMPLIST *** ../vim-6.2.326/src/misc1.c Sun Mar 7 15:21:39 2004 --- src/misc1.c Mon Mar 8 10:27:17 2004 *************** *** 95,101 **** int flags; { char_u *p; ! char_u *line; char_u *s; int todo; int ind_len; --- 95,102 ---- int flags; { char_u *p; ! char_u *newline; ! char_u *oldline; char_u *s; int todo; int ind_len; *************** *** 110,116 **** */ todo = size; ind_len = 0; ! p = ml_get_curline(); /* Calculate the buffer size for the new indent, and check to see if it * isn't already set */ --- 111,117 ---- */ todo = size; ind_len = 0; ! p = oldline = ml_get_curline(); /* Calculate the buffer size for the new indent, and check to see if it * isn't already set */ *************** *** 188,203 **** /* Allocate memory for the new line. */ if (flags & SIN_INSERT) ! p = ml_get_curline(); else p = skipwhite(p); line_len = (int)STRLEN(p) + 1; ! line = alloc(ind_len + line_len); ! if (line == NULL) return FALSE; /* Put the characters in the new line. */ ! s = line; todo = size; /* if 'expandtab' isn't set: use TABs */ if (!curbuf->b_p_et) --- 189,204 ---- /* Allocate memory for the new line. */ if (flags & SIN_INSERT) ! p = oldline; else p = skipwhite(p); line_len = (int)STRLEN(p) + 1; ! newline = alloc(ind_len + line_len); ! if (newline == NULL) return FALSE; /* Put the characters in the new line. */ ! s = newline; todo = size; /* if 'expandtab' isn't set: use TABs */ if (!curbuf->b_p_et) *************** *** 206,212 **** * the existing indent structure for the new indent */ if (!(flags & SIN_INSERT) && curbuf->b_p_pi) { ! p = ml_get_curline(); ind_done = 0; while (todo > 0 && vim_iswhite(*p)) --- 207,213 ---- * the existing indent structure for the new indent */ if (!(flags & SIN_INSERT) && curbuf->b_p_pi) { ! p = oldline; ind_done = 0; while (todo > 0 && vim_iswhite(*p)) *************** *** 256,267 **** /* Replace the line (unless undo fails). */ if (!(flags & SIN_UNDO) || u_savesub(curwin->w_cursor.lnum) == OK) { ! ml_replace(curwin->w_cursor.lnum, line, FALSE); if (flags & SIN_CHANGED) changed_bytes(curwin->w_cursor.lnum, 0); } else ! vim_free(line); curwin->w_cursor.col = ind_len; return TRUE; --- 257,272 ---- /* Replace the line (unless undo fails). */ if (!(flags & SIN_UNDO) || u_savesub(curwin->w_cursor.lnum) == OK) { ! ml_replace(curwin->w_cursor.lnum, newline, FALSE); if (flags & SIN_CHANGED) changed_bytes(curwin->w_cursor.lnum, 0); + /* Correct saved cursor position if it's after the indent. */ + if (saved_cursor.lnum == curwin->w_cursor.lnum + && saved_cursor.col >= (colnr_T)(p - oldline)) + saved_cursor.col += ind_len - (p - oldline); } else ! vim_free(newline); curwin->w_cursor.col = ind_len; return TRUE; *************** *** 373,379 **** /* * Return the indent of the current line after a number. Return -1 if no ! * number was found. Used for '1' in 'formatoptions': numbered list. */ int get_number_indent(lnum) --- 378,384 ---- /* * Return the indent of the current line after a number. Return -1 if no ! * number was found. Used for 'n' in 'formatoptions': numbered list. */ int get_number_indent(lnum) *************** *** 449,466 **** * Caller must take care of undo. Since VREPLACE may affect any number of * lines however, it may call u_save_cursor() again when starting to change a * new line. * * Return TRUE for success, FALSE for failure */ int open_line(dir, flags, old_indent) int dir; /* FORWARD or BACKWARD */ ! int flags; /* OPENLINE_DELSPACES and OPENLINE_DO_COM */ int old_indent; /* indent for after ^^D in Insert mode */ { char_u *saved_line; /* copy of the original line */ char_u *next_line = NULL; /* copy of the next line */ char_u *p_extra = NULL; /* what goes to next line */ pos_T old_cursor; /* old cursor position */ int newcol = 0; /* new cursor column */ int newindent = 0; /* auto-indent of the new line */ --- 454,477 ---- * Caller must take care of undo. Since VREPLACE may affect any number of * lines however, it may call u_save_cursor() again when starting to change a * new line. + * "flags": OPENLINE_DELSPACES delete spaces after cursor + * OPENLINE_DO_COM format comments + * OPENLINE_KEEPTRAIL keep trailing spaces + * OPENLINE_MARKFIX adjust mark positions after the line break * * Return TRUE for success, FALSE for failure */ int open_line(dir, flags, old_indent) int dir; /* FORWARD or BACKWARD */ ! int flags; int old_indent; /* indent for after ^^D in Insert mode */ { char_u *saved_line; /* copy of the original line */ char_u *next_line = NULL; /* copy of the next line */ char_u *p_extra = NULL; /* what goes to next line */ + int less_cols = 0; /* less columns for mark in new line */ + int less_cols_off = 0; /* columns to skip for mark adjust */ pos_T old_cursor; /* old cursor position */ int newcol = 0; /* new cursor column */ int newindent = 0; /* auto-indent of the new line */ *************** *** 1138,1147 **** --- 1149,1162 ---- if (REPLACE_NORMAL(State)) replace_push(*p_extra); ++p_extra; + ++less_cols_off; } } if (*p_extra != NUL) did_ai = FALSE; /* append some text, don't truncate now */ + + /* columns for marks adjusted for removed columns */ + less_cols = (int)(p_extra - saved_line); } if (p_extra == NULL) *************** *** 1154,1159 **** --- 1169,1175 ---- STRCAT(leader, p_extra); p_extra = leader; did_ai = TRUE; /* So truncating blanks works with comments */ + less_cols -= lead_len; } else end_comment_pending = NUL; /* turns out there was no leader */ *************** *** 1225,1230 **** --- 1241,1247 ---- } else (void)set_indent(newindent, SIN_INSERT); + less_cols -= curwin->w_cursor.col; ai_col = curwin->w_cursor.col; *************** *** 1270,1275 **** --- 1287,1298 ---- changed_lines(curwin->w_cursor.lnum, curwin->w_cursor.col, curwin->w_cursor.lnum + 1, 1L); did_append = FALSE; + + /* Move marks after the line break to the new line. */ + if (flags & OPENLINE_MARKFIX) + mark_col_adjust(curwin->w_cursor.lnum, + curwin->w_cursor.col + less_cols_off, + 1L, (long)-less_cols); } else changed_bytes(curwin->w_cursor.lnum, curwin->w_cursor.col); *************** *** 2309,2318 **** void changed() { - int save_msg_scroll = msg_scroll; - if (!curbuf->b_changed) { change_warning(0); /* Create a swap file if that is wanted. * Don't do this for "nofile" and "nowrite" buffer types. */ --- 2332,2341 ---- void changed() { if (!curbuf->b_changed) { + int save_msg_scroll = msg_scroll; + change_warning(0); /* Create a swap file if that is wanted. * Don't do this for "nofile" and "nowrite" buffer types. */ *** ../vim-6.2.326/src/normal.c Fri Mar 5 12:12:37 2004 --- src/normal.c Mon Mar 8 10:11:06 2004 *************** *** 1792,1798 **** oap->is_VIsual ? (int)cap->count1 : #endif 1); ! auto_format(FALSE); break; case OP_JOIN_NS: --- 1792,1798 ---- oap->is_VIsual ? (int)cap->count1 : #endif 1); ! auto_format(FALSE, TRUE); break; case OP_JOIN_NS: *************** *** 1805,1811 **** else { do_do_join(oap->line_count, oap->op_type == OP_JOIN); ! auto_format(FALSE); } break; --- 1805,1811 ---- else { do_do_join(oap->line_count, oap->op_type == OP_JOIN); ! auto_format(FALSE, TRUE); } break; *************** *** 1820,1826 **** (void)op_delete(oap); if (oap->motion_type == MLINE && has_format_option(FO_AUTO)) u_save_cursor(); /* cursor line wasn't saved yet */ ! auto_format(FALSE); } break; --- 1820,1826 ---- (void)op_delete(oap); if (oap->motion_type == MLINE && has_format_option(FO_AUTO)) u_save_cursor(); /* cursor line wasn't saved yet */ ! auto_format(FALSE, TRUE); } break; *************** *** 1912,1918 **** if (*p_fp != NUL) op_colon(oap); /* use external command */ else ! op_format(oap); /* use internal function */ break; case OP_INSERT: --- 1912,1922 ---- if (*p_fp != NUL) op_colon(oap); /* use external command */ else ! op_format(oap, FALSE); /* use internal function */ ! break; ! ! case OP_FORMAT2: ! op_format(oap, TRUE); /* use internal function */ break; case OP_INSERT: *************** *** 1935,1941 **** /* TODO: when inserting in several lines, should format all * the lines. */ ! auto_format(FALSE); if (restart_edit == 0) restart_edit = restart_edit_save; --- 1939,1945 ---- /* TODO: when inserting in several lines, should format all * the lines. */ ! auto_format(FALSE, TRUE); if (restart_edit == 0) restart_edit = restart_edit_save; *************** *** 7278,7289 **** --- 7285,7298 ---- /* * Two-character operators: * "gq" Format text + * "gw" Format text and keep cursor position * "g~" Toggle the case of the text. * "gu" Change text to lower case. * "gU" Change text to upper case. * "g?" rot13 encoding */ case 'q': + case 'w': case '~': case 'u': case 'U': *************** *** 8298,8304 **** if (reg2 != NULL) put_register(regname, reg2); #endif ! auto_format(FALSE); } } --- 8307,8313 ---- if (reg2 != NULL) put_register(regname, reg2); #endif ! auto_format(FALSE, TRUE); } } *** ../vim-6.2.326/src/ops.c Wed Mar 3 23:01:29 2004 --- src/ops.c Thu Mar 4 22:54:41 2004 *************** *** 163,168 **** --- 163,169 ---- {'z', 'C', TRUE}, /* OP_FOLDCLOSEREC */ {'z', 'd', TRUE}, /* OP_FOLDDEL */ {'z', 'D', TRUE}, /* OP_FOLDDELREC */ + {'g', 'w', TRUE}, /* OP_FORMAT2 */ }; /* *************** *** 3845,3851 **** int insert_space; { char_u *curr; ! char_u *next; char_u *newp; int endcurr1, endcurr2; int currsize; /* size of the current line */ --- 3846,3852 ---- int insert_space; { char_u *curr; ! char_u *next, *next_start; char_u *newp; int endcurr1, endcurr2; int currsize; /* size of the current line */ *************** *** 3883,3889 **** } } ! next = ml_get((linenr_T)(curwin->w_cursor.lnum + 1)); spaces = 0; if (insert_space) { --- 3884,3890 ---- } } ! next = next_start = ml_get((linenr_T)(curwin->w_cursor.lnum + 1)); spaces = 0; if (insert_space) { *************** *** 3939,3946 **** --- 3940,3953 ---- * Delete the following line. To do this we move the cursor there * briefly, and then move it back. After del_lines() the cursor may * have moved up (last line deleted), so the current lnum is kept in t. + * + * Move marks from the deleted line to the joined line, adjusting the + * column. This is not Vi compatible, but Vi deletes the marks, thus that + * should not really be a problem. */ t = curwin->w_cursor.lnum; + mark_col_adjust(t + 1, (colnr_T)0, (linenr_T)-1, + (long)(currsize + spaces - (next - next_start))); ++curwin->w_cursor.lnum; del_lines(1L, FALSE); curwin->w_cursor.lnum = t; *************** *** 4039,4046 **** * implementation of the format operator 'gq' */ void ! op_format(oap) oparg_T *oap; { long old_line_count = curbuf->b_ml.ml_line_count; --- 4046,4054 ---- * implementation of the format operator 'gq' */ void ! op_format(oap, keep_cursor) oparg_T *oap; + int keep_cursor; /* keep cursor on same text char */ { long old_line_count = curbuf->b_ml.ml_line_count; *************** *** 4057,4062 **** --- 4065,4073 ---- /* Set '[ mark at the start of the formatted area */ curbuf->b_op_start = oap->start; + if (keep_cursor) + saved_cursor = curwin->w_cursor; + format_lines(oap->line_count); /* *************** *** 4073,4078 **** --- 4084,4095 ---- /* put '] mark on the end of the formatted area */ curbuf->b_op_end = curwin->w_cursor; + if (keep_cursor) + { + curwin->w_cursor = saved_cursor; + saved_cursor.lnum = 0; + } + #ifdef FEAT_VISUAL if (oap->is_VIsual) { *************** *** 4301,4306 **** --- 4318,4326 ---- break; #ifdef FEAT_COMMENTS (void)del_bytes((long)next_leader_len, FALSE); + if (next_leader_len > 0) + mark_col_adjust(curwin->w_cursor.lnum, (colnr_T)0, 0L, + (long)-next_leader_len); #endif curwin->w_cursor.lnum--; if (do_join(TRUE) == FAIL) *************** *** 4385,4390 **** --- 4405,4466 ---- return (*skipwhite(ml_get(lnum)) == NUL || startPS(lnum, NUL, FALSE)); } #endif + + /* + * Return TRUE when a paragraph starts in line "lnum". Return FALSE when the + * previous line is in the same paragraph. Used for auto-formatting. + */ + int + paragraph_start(lnum) + linenr_T lnum; + { + char_u *p; + #ifdef FEAT_COMMENTS + int leader_len = 0; /* leader len of current line */ + char_u *leader_flags = NULL; /* flags for leader of current line */ + int next_leader_len; /* leader len of next line */ + char_u *next_leader_flags; /* flags for leader of next line */ + int do_comments; /* format comments */ + #endif + + if (lnum <= 1) + return TRUE; /* start of the file */ + + p = ml_get(lnum - 1); + if (*p == NUL) + return TRUE; /* after empty line */ + + #ifdef FEAT_COMMENTS + do_comments = has_format_option(FO_Q_COMS); + #endif + if (fmt_check_par(lnum - 1 + #ifdef FEAT_COMMENTS + , &leader_len, &leader_flags, do_comments + #endif + )) + return TRUE; /* after non-paragraph line */ + + if (fmt_check_par(lnum + #ifdef FEAT_COMMENTS + , &next_leader_len, &next_leader_flags, do_comments + #endif + )) + return TRUE; /* "lnum" is not a paragraph line */ + + if (has_format_option(FO_WHITE_PAR) && !ends_in_white(lnum - 1)) + return TRUE; /* missing trailing space in previous line. */ + + if (has_format_option(FO_Q_NUMBER) && (get_number_indent(lnum) > 0)) + return TRUE; /* numbered item starts in "lnum". */ + + #ifdef FEAT_COMMENTS + if (!same_leader(leader_len, leader_flags, + next_leader_len, next_leader_flags)) + return TRUE; /* change of comment leader. */ + #endif + + return FALSE; + } #ifdef FEAT_VISUAL /* *** ../vim-6.2.326/src/proto/edit.pro Sun Jan 18 20:28:27 2004 --- src/proto/edit.pro Mon Mar 8 10:11:10 2004 *************** *** 13,19 **** void ins_compl_check_keys __ARGS((void)); int get_literal __ARGS((void)); void insertchar __ARGS((int c, int flags, int second_indent)); ! void auto_format __ARGS((int trailblank)); int comp_textwidth __ARGS((int ff)); int stop_arrow __ARGS((void)); void set_last_insert __ARGS((int c)); --- 13,19 ---- void ins_compl_check_keys __ARGS((void)); int get_literal __ARGS((void)); void insertchar __ARGS((int c, int flags, int second_indent)); ! void auto_format __ARGS((int trailblank, int prev_line)); int comp_textwidth __ARGS((int ff)); int stop_arrow __ARGS((void)); void set_last_insert __ARGS((int c)); *** ../vim-6.2.326/src/proto/mark.pro Sun Feb 29 20:46:43 2004 --- src/proto/mark.pro Tue Mar 2 21:23:55 2004 *************** *** 14,19 **** --- 14,20 ---- void ex_jumps __ARGS((exarg_T *eap)); void ex_changes __ARGS((exarg_T *eap)); void mark_adjust __ARGS((linenr_T line1, linenr_T line2, long amount, long amount_after)); + void mark_col_adjust __ARGS((linenr_T lnum, colnr_T mincol, long lnum_amount, long col_amount)); void copy_jumplist __ARGS((win_T *from, win_T *to)); void free_jumplist __ARGS((win_T *wp)); void set_last_cursor __ARGS((win_T *win)); *** ../vim-6.2.326/src/proto/ops.pro Sun Jun 1 12:26:17 2003 --- src/proto/ops.pro Thu Mar 4 22:51:23 2004 *************** *** 31,38 **** void ex_display __ARGS((exarg_T *eap)); void do_do_join __ARGS((long count, int insert_space)); int do_join __ARGS((int insert_space)); ! void op_format __ARGS((oparg_T *oap)); void format_lines __ARGS((linenr_T line_count)); int do_addsub __ARGS((int command, linenr_T Prenum1)); int read_viminfo_register __ARGS((vir_T *virp, int force)); void write_viminfo_registers __ARGS((FILE *fp)); --- 31,39 ---- void ex_display __ARGS((exarg_T *eap)); void do_do_join __ARGS((long count, int insert_space)); int do_join __ARGS((int insert_space)); ! void op_format __ARGS((oparg_T *oap, int keep_cursor)); void format_lines __ARGS((linenr_T line_count)); + int paragraph_start __ARGS((linenr_T lnum)); int do_addsub __ARGS((int command, linenr_T Prenum1)); int read_viminfo_register __ARGS((vir_T *virp, int force)); void write_viminfo_registers __ARGS((FILE *fp)); *** ../vim-6.2.326/src/structs.h Mon Mar 1 17:11:04 2004 --- src/structs.h Thu Mar 4 13:44:30 2004 *************** *** 32,37 **** --- 32,43 ---- #endif } pos_T; + #ifdef FEAT_VIRTUALEDIT + # define INIT_POS_T {0, 0, 0} + #else + # define INIT_POS_T {0, 0} + #endif + /* * Same, but without coladd. */ *** ../vim-6.2.326/src/vim.h Mon Mar 1 17:11:04 2004 --- src/vim.h Thu Mar 4 22:50:17 2004 *************** *** 848,853 **** --- 848,854 ---- #define OPENLINE_DELSPACES 1 /* delete spaces after cursor */ #define OPENLINE_DO_COM 2 /* format comments */ #define OPENLINE_KEEPTRAIL 4 /* keep trailing spaces */ + #define OPENLINE_MARKFIX 8 /* fix mark positions */ /* * There are four history tables: *************** *** 1118,1123 **** --- 1119,1125 ---- #define OP_FOLDCLOSEREC 23 /* "zC" close folds recursively */ #define OP_FOLDDEL 24 /* "zd" delete folds */ #define OP_FOLDDELREC 25 /* "zD" delete folds recursively */ + #define OP_FORMAT2 26 /* "gw" format operator, keeps cursor pos */ /* * Motion types, used for operators and for yank/delete registers. *** ../vim-6.2.326/src/version.c Sun Mar 7 19:33:55 2004 --- src/version.c Mon Mar 8 12:12:35 2004 *************** *** 639,640 **** --- 639,642 ---- { /* Add new patch number below this line */ + /**/ + 327, /**/ -- A fool must search for a greater fool to find admiration. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// Sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ Project leader for A-A-P -- http://www.A-A-P.org /// \\\ Buy at Amazon and help AIDS victims -- http://ICCF.nl/click1.html ///