To: vim-dev@vim.org Subject: Patch 6.2.184 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit ------------ Patch 6.2.184 Problem: With 'formatoptions' set to "1aw" inserting text may cause the paragraph to be ended. (Alan Schmitt) Solution: Temporarily add an extra space to make the paragraph continue after moving the word after the cursor to the next line. Also format when pressing Esc. Files: src/edit.c, src/normal.c, src/proto/edit.pro *** ../vim-6.2.183/src/edit.c Sun Nov 9 20:26:53 2003 --- src/edit.c Sun Jan 18 20:23:49 2004 *************** *** 121,132 **** static void ins_ctrl_v __ARGS((void)); static void undisplay_dollar __ARGS((void)); static void insert_special __ARGS((int, int, 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)); static int echeck_abbr __ARGS((int)); static void replace_push_off __ARGS((int c)); static int replace_pop __ARGS((void)); --- 121,133 ---- static void ins_ctrl_v __ARGS((void)); 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)); static int echeck_abbr __ARGS((int)); static void replace_push_off __ARGS((int c)); static int replace_pop __ARGS((void)); *************** *** 195,204 **** static int old_indent = 0; /* for ^^D command in insert mode */ #ifdef FEAT_RIGHTLEFT ! int revins_on; /* reverse insert mode on */ ! int revins_chars; /* how much to skip after edit */ ! int revins_legal; /* was the last char 'legal'? */ ! int revins_scol; /* start column of revins session */ #endif #if defined(FEAT_MBYTE) && defined(MACOS_CLASSIC) --- 196,205 ---- static int old_indent = 0; /* for ^^D command in insert mode */ #ifdef FEAT_RIGHTLEFT ! int revins_on; /* reverse insert mode on */ ! int revins_chars; /* how much to skip after edit */ ! int revins_legal; /* was the last char 'legal'? */ ! int revins_scol; /* start column of revins session */ #endif #if defined(FEAT_MBYTE) && defined(MACOS_CLASSIC) *************** *** 209,214 **** --- 210,218 ---- char. Set when edit() is called. after that arrow_used is used. */ + static int did_add_space = FALSE; /* auto_format() added an extra space + under the cursor */ + /* * edit(): Start inserting text. * *************** *** 866,872 **** /* insert the contents of a register */ case Ctrl_R: ins_reg(); ! auto_format(); inserted_space = FALSE; break; --- 870,876 ---- /* insert the contents of a register */ case Ctrl_R: ins_reg(); ! auto_format(FALSE); inserted_space = FALSE; break; *************** *** 961,967 **** } # endif ins_shift(c, lastc); ! auto_format(); inserted_space = FALSE; break; --- 965,971 ---- } # endif ins_shift(c, lastc); ! auto_format(FALSE); inserted_space = FALSE; break; *************** *** 969,994 **** case K_DEL: case K_KDEL: ins_del(); ! auto_format(); break; /* delete character before the cursor */ case K_BS: case Ctrl_H: did_backspace = ins_bs(c, BACKSPACE_CHAR, &inserted_space); ! auto_format(); break; /* delete word before the cursor */ case Ctrl_W: did_backspace = ins_bs(c, BACKSPACE_WORD, &inserted_space); ! auto_format(); break; /* delete all inserted text in current line */ case Ctrl_U: did_backspace = ins_bs(c, BACKSPACE_LINE, &inserted_space); ! auto_format(); inserted_space = FALSE; break; --- 973,998 ---- 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; *************** *** 1111,1117 **** inserted_space = FALSE; if (ins_tab()) goto normalchar; /* insert TAB as a normal char */ ! auto_format(); break; case K_KENTER: --- 1115,1121 ---- inserted_space = FALSE; if (ins_tab()) goto normalchar; /* insert TAB as a normal char */ ! auto_format(FALSE); break; case K_KENTER: *************** *** 1138,1144 **** #endif if (ins_eol(c) && !p_im) goto doESCkey; /* out of memory */ ! auto_format(); inserted_space = FALSE; break; --- 1142,1148 ---- #endif if (ins_eol(c) && !p_im) goto doESCkey; /* out of memory */ ! auto_format(FALSE); inserted_space = FALSE; break; *************** *** 1252,1258 **** revins_legal++; #endif c = Ctrl_V; /* pretend CTRL-V is last character */ ! auto_format(); } } break; --- 1256,1262 ---- revins_legal++; #endif c = Ctrl_V; /* pretend CTRL-V is last character */ ! auto_format(FALSE); } } break; *************** *** 1299,1305 **** #endif } ! auto_format(); #ifdef FEAT_FOLDING /* When inserting a character the cursor line must never be in a --- 1303,1309 ---- #endif } ! auto_format(FALSE); #ifdef FEAT_FOLDING /* When inserting a character the cursor line must never be in a *************** *** 2489,2495 **** curwin->w_cursor.col++; } ! auto_format(); ins_compl_free(); started_completion = FALSE; --- 2504,2510 ---- curwin->w_cursor.col++; } ! auto_format(FALSE); ins_compl_free(); started_completion = FALSE; *************** *** 4346,4357 **** * saved here. */ void ! auto_format() { pos_T pos; colnr_T len; char_u *old, *pold; char_u *new, *pnew; if (!has_format_option(FO_AUTO)) return; --- 4361,4374 ---- * 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; if (!has_format_option(FO_AUTO)) return; *************** *** 4359,4370 **** pos = curwin->w_cursor; old = ml_get_curline(); /* Don't format in Insert mode when the cursor is on a trailing blank, the * user might insert normal text next. Also skip formatting when "1" is * in 'formatoptions' and there is a single character before the cursor. * Otherwise the line would be broken and when typing another non-white * next they are not joined back together. */ ! if (*old != NUL && pos.col == STRLEN(old)) { dec_cursor(); if (!WHITECHAR(gchar_cursor()) --- 4376,4391 ---- pos = curwin->w_cursor; old = ml_get_curline(); + /* may remove added space */ + check_auto_format(FALSE); + /* Don't format in Insert mode when the cursor is on a trailing blank, the * user might insert normal text next. Also skip formatting when "1" is * in 'formatoptions' and there is a single character before the cursor. * Otherwise the line would be broken and when typing another non-white * next they are not joined back together. */ ! wasatend = (pos.col == STRLEN(old)); ! if (*old != NUL && !trailblank && wasatend) { dec_cursor(); if (!WHITECHAR(gchar_cursor()) *************** *** 4426,4432 **** len = (colnr_T)STRLEN(pnew); if ((pold - old) + len >= pos.col) { ! curwin->w_cursor.col = pos.col - (pold - old) + (pnew - new); break; } /* Cursor wraps to next line */ --- 4447,4477 ---- 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 */ *************** *** 4437,4442 **** --- 4482,4521 ---- vim_free(old); } + /* + * When an extra space was added to continue a paragraph for auto-formatting, + * delete it now. The space must be under the cursor, just after the insert + * position. + */ + static void + check_auto_format(end_insert) + int end_insert; /* TRUE when ending Insert mode */ + { + int c = ' '; + + if (did_add_space) + { + if (!WHITECHAR(gchar_cursor())) + /* Somehow the space was removed already. */ + did_add_space = FALSE; + else + { + if (!end_insert) + { + inc_cursor(); + c = gchar_cursor(); + dec_cursor(); + } + if (c != NUL) + { + /* The space is no longer at the end of the line, delete it. */ + del_char(FALSE); + did_add_space = FALSE; + } + } + } + } + #ifdef FEAT_COMMENTS /* * Return the number of bytes for which strings "s1" and "s2" are equal. *************** *** 4536,4543 **** if (!arrow_used) /* something has been inserted */ { AppendToRedobuff(ESC_STR); arrow_used = TRUE; /* this means we stopped the current insert */ - stop_insert(end_insert_pos); } } --- 4615,4622 ---- if (!arrow_used) /* something has been inserted */ { AppendToRedobuff(ESC_STR); + stop_insert(end_insert_pos, FALSE); arrow_used = TRUE; /* this means we stopped the current insert */ } } *************** *** 4587,4594 **** * do a few things to stop inserting */ static void ! stop_insert(end_insert_pos) pos_T *end_insert_pos; /* where insert ended */ { int cc; --- 4666,4674 ---- * do a few things to stop inserting */ static void ! stop_insert(end_insert_pos, esc) pos_T *end_insert_pos; /* where insert ended */ + int esc; /* called by ins_esc() */ { int cc; *************** *** 4602,4635 **** last_insert = get_inserted(); last_insert_skip = new_insert_skip; ! /* ! * If we just did an auto-indent, remove the white space from the end of ! * the line, and put the cursor back. ! */ ! if (did_ai && !arrow_used) { ! if (gchar_cursor() == NUL && curwin->w_cursor.col > 0) ! --curwin->w_cursor.col; ! while (cc = gchar_cursor(), vim_iswhite(cc)) ! (void)del_char(TRUE); ! if (cc != NUL) ! ++curwin->w_cursor.col; /* put cursor back on the NUL */ #ifdef FEAT_VISUAL ! /* may have started Visual mode, adjust the position for ! * deleted characters. */ ! if (VIsual_active && VIsual.lnum == curwin->w_cursor.lnum) ! { ! cc = STRLEN(ml_get_curline()); ! if (VIsual.col > (colnr_T)cc) { ! VIsual.col = cc; # ifdef FEAT_VIRTUALEDIT ! VIsual.coladd = 0; # endif } - } #endif } did_ai = FALSE; #ifdef FEAT_SMARTINDENT --- 4682,4726 ---- last_insert = get_inserted(); last_insert_skip = new_insert_skip; ! if (!arrow_used) { ! /* Auto-format now. It may seem strange to do this when stopping an ! * insertion (or moving the cursor), but it's required when appending ! * 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); ! ! /* If we just did an auto-indent, remove the white space from the end ! * of the line, and put the cursor back. */ ! if (did_ai && esc) ! { ! if (gchar_cursor() == NUL && curwin->w_cursor.col > 0) ! --curwin->w_cursor.col; ! while (cc = gchar_cursor(), vim_iswhite(cc)) ! (void)del_char(TRUE); ! if (cc != NUL) ! ++curwin->w_cursor.col; /* put cursor back on the NUL */ #ifdef FEAT_VISUAL ! /* may have started Visual mode, adjust the position for ! * deleted characters. */ ! if (VIsual_active && VIsual.lnum == curwin->w_cursor.lnum) { ! cc = STRLEN(ml_get_curline()); ! if (VIsual.col > (colnr_T)cc) ! { ! VIsual.col = cc; # ifdef FEAT_VIRTUALEDIT ! VIsual.coladd = 0; # endif + } } #endif + } } did_ai = FALSE; #ifdef FEAT_SMARTINDENT *************** *** 5988,5994 **** disabled_redraw = TRUE; return FALSE; /* repeat the insert */ } ! stop_insert(&curwin->w_cursor); undisplay_dollar(); } --- 6079,6085 ---- disabled_redraw = TRUE; return FALSE; /* repeat the insert */ } ! stop_insert(&curwin->w_cursor, TRUE); undisplay_dollar(); } *** ../vim-6.2.183/src/normal.c Sun Jan 18 20:17:41 2004 --- src/normal.c Sun Jan 18 18:49:04 2004 *************** *** 1753,1759 **** oap->is_VIsual ? (int)cap->count1 : #endif 1); ! auto_format(); break; case OP_JOIN_NS: --- 1753,1759 ---- oap->is_VIsual ? (int)cap->count1 : #endif 1); ! auto_format(FALSE); break; case OP_JOIN_NS: *************** *** 1766,1772 **** else { do_do_join(oap->line_count, oap->op_type == OP_JOIN); ! auto_format(); } break; --- 1766,1772 ---- else { do_do_join(oap->line_count, oap->op_type == OP_JOIN); ! auto_format(FALSE); } break; *************** *** 1781,1787 **** (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(); } break; --- 1781,1787 ---- (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; *************** *** 1896,1902 **** /* TODO: when inserting in several lines, should format all * the lines. */ ! auto_format(); if (restart_edit == 0) restart_edit = restart_edit_save; --- 1896,1902 ---- /* TODO: when inserting in several lines, should format all * the lines. */ ! auto_format(FALSE); if (restart_edit == 0) restart_edit = restart_edit_save; *************** *** 8193,8199 **** if (reg2 != NULL) put_register(regname, reg2); #endif ! auto_format(); } } --- 8205,8211 ---- if (reg2 != NULL) put_register(regname, reg2); #endif ! auto_format(FALSE); } } *** ../vim-6.2.183/src/proto/edit.pro Sun Jun 1 12:26:07 2003 --- src/proto/edit.pro Thu Jan 15 20:57:54 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((void)); 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 comp_textwidth __ARGS((int ff)); int stop_arrow __ARGS((void)); void set_last_insert __ARGS((int c)); *** ../vim-6.2.183/src/version.c Sun Jan 18 20:17:41 2004 --- src/version.c Sun Jan 18 20:19:10 2004 *************** *** 639,640 **** --- 639,642 ---- { /* Add new patch number below this line */ + /**/ + 184, /**/ -- [clop clop] MORTICIAN: Who's that then? CUSTOMER: I don't know. MORTICIAN: Must be a king. CUSTOMER: Why? MORTICIAN: He hasn't got shit all over him. The Quest for the Holy Grail (Monty Python) /// 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 /// \\\ Help AIDS victims, buy here: http://ICCF-Holland.org/click1.html ///