To: vim_dev@googlegroups.com Subject: Patch 8.2.4165 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.4165 Problem: The nv_g_cmd() function is too long. Solution: Move code to separate functions. (Yegappan Lakshmanan, closes #9576) Files: src/normal.c *** ../vim-8.2.4164/src/normal.c 2022-01-20 15:25:59.309844687 +0000 --- src/normal.c 2022-01-20 20:17:37.582966682 +0000 *************** *** 5890,5920 **** } /* * Commands starting with "g". */ static void nv_g_cmd(cmdarg_T *cap) { oparg_T *oap = cap->oap; - pos_T tpos; int i; - int flag = FALSE; switch (cap->nchar) { case Ctrl_A: case Ctrl_X: #ifdef MEM_PROFILE ! /* ! * "g^A": dump log of used memory. ! */ if (!VIsual_active && cap->nchar == Ctrl_A) vim_mem_profile_dump(); else #endif ! /* ! * "g^A/g^X": sequentially increment visually selected region ! */ if (VIsual_active) { cap->arg = TRUE; --- 5890,6164 ---- } /* + * "gv": Reselect the previous Visual area. If Visual already active, + * exchange previous and current Visual area. + */ + static void + nv_gv_cmd(cmdarg_T *cap) + { + pos_T tpos; + int i; + + if (checkclearop(cap->oap)) + return; + + if (curbuf->b_visual.vi_start.lnum == 0 + || curbuf->b_visual.vi_start.lnum > curbuf->b_ml.ml_line_count + || curbuf->b_visual.vi_end.lnum == 0) + { + beep_flush(); + return; + } + + // set w_cursor to the start of the Visual area, tpos to the end + if (VIsual_active) + { + i = VIsual_mode; + VIsual_mode = curbuf->b_visual.vi_mode; + curbuf->b_visual.vi_mode = i; + # ifdef FEAT_EVAL + curbuf->b_visual_mode_eval = i; + # endif + i = curwin->w_curswant; + curwin->w_curswant = curbuf->b_visual.vi_curswant; + curbuf->b_visual.vi_curswant = i; + + tpos = curbuf->b_visual.vi_end; + curbuf->b_visual.vi_end = curwin->w_cursor; + curwin->w_cursor = curbuf->b_visual.vi_start; + curbuf->b_visual.vi_start = VIsual; + } + else + { + VIsual_mode = curbuf->b_visual.vi_mode; + curwin->w_curswant = curbuf->b_visual.vi_curswant; + tpos = curbuf->b_visual.vi_end; + curwin->w_cursor = curbuf->b_visual.vi_start; + } + + VIsual_active = TRUE; + VIsual_reselect = TRUE; + + // Set Visual to the start and w_cursor to the end of the Visual + // area. Make sure they are on an existing character. + check_cursor(); + VIsual = curwin->w_cursor; + curwin->w_cursor = tpos; + check_cursor(); + update_topline(); + + // When called from normal "g" command: start Select mode when + // 'selectmode' contains "cmd". When called for K_SELECT, always + // start Select mode. + if (cap->arg) + { + VIsual_select = TRUE; + VIsual_select_reg = 0; + } + else + may_start_select('c'); + setmouse(); + #ifdef FEAT_CLIPBOARD + // Make sure the clipboard gets updated. Needed because start and + // end are still the same, and the selection needs to be owned + clip_star.vmode = NUL; + #endif + redraw_curbuf_later(INVERTED); + showmode(); + } + + /* + * "g0", "g^" : Like "0" and "^" but for screen lines. + * "gm": middle of "g0" and "g$". + */ + static void + nv_g_home_m_cmd(cmdarg_T *cap) + { + int i; + int flag = FALSE; + + if (cap->nchar == '^') + flag = TRUE; + + cap->oap->motion_type = MCHAR; + cap->oap->inclusive = FALSE; + if (curwin->w_p_wrap && curwin->w_width != 0) + { + int width1 = curwin->w_width - curwin_col_off(); + int width2 = width1 + curwin_col_off2(); + + validate_virtcol(); + i = 0; + if (curwin->w_virtcol >= (colnr_T)width1 && width2 > 0) + i = (curwin->w_virtcol - width1) / width2 * width2 + width1; + } + else + i = curwin->w_leftcol; + // Go to the middle of the screen line. When 'number' or + // 'relativenumber' is on and lines are wrapping the middle can be more + // to the left. + if (cap->nchar == 'm') + i += (curwin->w_width - curwin_col_off() + + ((curwin->w_p_wrap && i > 0) + ? curwin_col_off2() : 0)) / 2; + coladvance((colnr_T)i); + if (flag) + { + do + i = gchar_cursor(); + while (VIM_ISWHITE(i) && oneright() == OK); + curwin->w_valid &= ~VALID_WCOL; + } + curwin->w_set_curswant = TRUE; + } + + /* + * "g_": to the last non-blank character in the line or lines + * downward. + */ + static void + nv_g_underscore_cmd(cmdarg_T *cap) + { + char_u *ptr; + + cap->oap->motion_type = MCHAR; + cap->oap->inclusive = TRUE; + curwin->w_curswant = MAXCOL; + if (cursor_down((long)(cap->count1 - 1), + cap->oap->op_type == OP_NOP) == FAIL) + { + clearopbeep(cap->oap); + return; + } + + ptr = ml_get_curline(); + + // In Visual mode we may end up after the line. + if (curwin->w_cursor.col > 0 && ptr[curwin->w_cursor.col] == NUL) + --curwin->w_cursor.col; + + // Decrease the cursor column until it's on a non-blank. + while (curwin->w_cursor.col > 0 + && VIM_ISWHITE(ptr[curwin->w_cursor.col])) + --curwin->w_cursor.col; + curwin->w_set_curswant = TRUE; + adjust_for_sel(cap); + } + + /* + * "g$" : Like "$" but for screen lines. + */ + static void + nv_g_dollar_cmd(cmdarg_T *cap) + { + oparg_T *oap = cap->oap; + int i; + int col_off = curwin_col_off(); + + oap->motion_type = MCHAR; + oap->inclusive = TRUE; + if (curwin->w_p_wrap && curwin->w_width != 0) + { + curwin->w_curswant = MAXCOL; // so we stay at the end + if (cap->count1 == 1) + { + int width1 = curwin->w_width - col_off; + int width2 = width1 + curwin_col_off2(); + + validate_virtcol(); + i = width1 - 1; + if (curwin->w_virtcol >= (colnr_T)width1) + i += ((curwin->w_virtcol - width1) / width2 + 1) + * width2; + coladvance((colnr_T)i); + + // Make sure we stick in this column. + validate_virtcol(); + curwin->w_curswant = curwin->w_virtcol; + curwin->w_set_curswant = FALSE; + if (curwin->w_cursor.col > 0 && curwin->w_p_wrap) + { + // Check for landing on a character that got split at + // the end of the line. We do not want to advance to + // the next screen line. + if (curwin->w_virtcol > (colnr_T)i) + --curwin->w_cursor.col; + } + } + else if (nv_screengo(oap, FORWARD, cap->count1 - 1) == FAIL) + clearopbeep(oap); + } + else + { + if (cap->count1 > 1) + // if it fails, let the cursor still move to the last char + (void)cursor_down(cap->count1 - 1, FALSE); + + i = curwin->w_leftcol + curwin->w_width - col_off - 1; + coladvance((colnr_T)i); + + // if the character doesn't fit move one back + if (curwin->w_cursor.col > 0 + && (*mb_ptr2cells)(ml_get_cursor()) > 1) + { + colnr_T vcol; + + getvvcol(curwin, &curwin->w_cursor, NULL, NULL, &vcol); + if (vcol >= curwin->w_leftcol + curwin->w_width - col_off) + --curwin->w_cursor.col; + } + + // Make sure we stick in this column. + validate_virtcol(); + curwin->w_curswant = curwin->w_virtcol; + curwin->w_set_curswant = FALSE; + } + } + + /* + * "gi": start Insert at the last position. + */ + static void + nv_gi_cmd(cmdarg_T *cap) + { + int i; + + if (curbuf->b_last_insert.lnum != 0) + { + curwin->w_cursor = curbuf->b_last_insert; + check_cursor_lnum(); + i = (int)STRLEN(ml_get_curline()); + if (curwin->w_cursor.col > (colnr_T)i) + { + if (virtual_active()) + curwin->w_cursor.coladd += curwin->w_cursor.col - i; + curwin->w_cursor.col = i; + } + } + cap->cmdchar = 'i'; + nv_edit(cap); + } + + /* * Commands starting with "g". */ static void nv_g_cmd(cmdarg_T *cap) { oparg_T *oap = cap->oap; int i; switch (cap->nchar) { case Ctrl_A: case Ctrl_X: #ifdef MEM_PROFILE ! // "g^A": dump log of used memory. if (!VIsual_active && cap->nchar == Ctrl_A) vim_mem_profile_dump(); else #endif ! // "g^A/g^X": sequentially increment visually selected region if (VIsual_active) { cap->arg = TRUE; *************** *** 5926,5934 **** clearopbeep(oap); break; ! /* ! * "gR": Enter virtual replace mode. ! */ case 'R': cap->arg = TRUE; nv_Replace(cap); --- 6170,6176 ---- clearopbeep(oap); break; ! // "gR": Enter virtual replace mode. case 'R': cap->arg = TRUE; nv_Replace(cap); *************** *** 5942,6032 **** do_cmdline_cmd((char_u *)"%s//~/&"); break; ! /* ! * "gv": Reselect the previous Visual area. If Visual already active, ! * exchange previous and current Visual area. ! */ case 'v': ! if (checkclearop(oap)) ! break; ! ! if ( curbuf->b_visual.vi_start.lnum == 0 ! || curbuf->b_visual.vi_start.lnum > curbuf->b_ml.ml_line_count ! || curbuf->b_visual.vi_end.lnum == 0) ! beep_flush(); ! else ! { ! // set w_cursor to the start of the Visual area, tpos to the end ! if (VIsual_active) ! { ! i = VIsual_mode; ! VIsual_mode = curbuf->b_visual.vi_mode; ! curbuf->b_visual.vi_mode = i; ! # ifdef FEAT_EVAL ! curbuf->b_visual_mode_eval = i; ! # endif ! i = curwin->w_curswant; ! curwin->w_curswant = curbuf->b_visual.vi_curswant; ! curbuf->b_visual.vi_curswant = i; ! ! tpos = curbuf->b_visual.vi_end; ! curbuf->b_visual.vi_end = curwin->w_cursor; ! curwin->w_cursor = curbuf->b_visual.vi_start; ! curbuf->b_visual.vi_start = VIsual; ! } ! else ! { ! VIsual_mode = curbuf->b_visual.vi_mode; ! curwin->w_curswant = curbuf->b_visual.vi_curswant; ! tpos = curbuf->b_visual.vi_end; ! curwin->w_cursor = curbuf->b_visual.vi_start; ! } ! ! VIsual_active = TRUE; ! VIsual_reselect = TRUE; ! ! // Set Visual to the start and w_cursor to the end of the Visual ! // area. Make sure they are on an existing character. ! check_cursor(); ! VIsual = curwin->w_cursor; ! curwin->w_cursor = tpos; ! check_cursor(); ! update_topline(); ! /* ! * When called from normal "g" command: start Select mode when ! * 'selectmode' contains "cmd". When called for K_SELECT, always ! * start Select mode. ! */ ! if (cap->arg) ! { ! VIsual_select = TRUE; ! VIsual_select_reg = 0; ! } ! else ! may_start_select('c'); ! setmouse(); ! #ifdef FEAT_CLIPBOARD ! // Make sure the clipboard gets updated. Needed because start and ! // end are still the same, and the selection needs to be owned ! clip_star.vmode = NUL; ! #endif ! redraw_curbuf_later(INVERTED); ! showmode(); ! } break; ! /* ! * "gV": Don't reselect the previous Visual area after a Select mode ! * mapping of menu. ! */ case 'V': VIsual_reselect = FALSE; break; ! /* ! * "gh": start Select mode. ! * "gH": start Select line mode. ! * "g^H": start Select block mode. ! */ case K_BS: cap->nchar = Ctrl_H; // FALLTHROUGH --- 6184,6204 ---- do_cmdline_cmd((char_u *)"%s//~/&"); break; ! // "gv": Reselect the previous Visual area. If Visual already active, ! // exchange previous and current Visual area. case 'v': ! nv_gv_cmd(cap); break; ! ! // "gV": Don't reselect the previous Visual area after a Select mode ! // mapping of menu. case 'V': VIsual_reselect = FALSE; break; ! // "gh": start Select mode. ! // "gH": start Select line mode. ! // "g^H": start Select block mode. case K_BS: cap->nchar = Ctrl_H; // FALLTHROUGH *************** *** 6053,6062 **** clearopbeep(oap); break; ! /* ! * "gj" and "gk" two new funny movement keys -- up and down ! * movement based on *screen* line rather than *file* line. ! */ case 'j': case K_DOWN: // with 'nowrap' it works just like the normal "j" command. --- 6225,6232 ---- clearopbeep(oap); break; ! // "gj" and "gk" two new funny movement keys -- up and down ! // movement based on *screen* line rather than *file* line. case 'j': case K_DOWN: // with 'nowrap' it works just like the normal "j" command. *************** *** 6085,6139 **** clearopbeep(oap); break; ! /* ! * "gJ": join two lines without inserting a space. ! */ case 'J': nv_join(cap); break; ! /* ! * "g0", "g^" and "g$": Like "0", "^" and "$" but for screen lines. ! * "gm": middle of "g0" and "g$". ! */ case '^': - flag = TRUE; - // FALLTHROUGH - case '0': case 'm': case K_HOME: case K_KHOME: ! oap->motion_type = MCHAR; ! oap->inclusive = FALSE; ! if (curwin->w_p_wrap && curwin->w_width != 0) ! { ! int width1 = curwin->w_width - curwin_col_off(); ! int width2 = width1 + curwin_col_off2(); ! ! validate_virtcol(); ! i = 0; ! if (curwin->w_virtcol >= (colnr_T)width1 && width2 > 0) ! i = (curwin->w_virtcol - width1) / width2 * width2 + width1; ! } ! else ! i = curwin->w_leftcol; ! // Go to the middle of the screen line. When 'number' or ! // 'relativenumber' is on and lines are wrapping the middle can be more ! // to the left. ! if (cap->nchar == 'm') ! i += (curwin->w_width - curwin_col_off() ! + ((curwin->w_p_wrap && i > 0) ! ? curwin_col_off2() : 0)) / 2; ! coladvance((colnr_T)i); ! if (flag) ! { ! do ! i = gchar_cursor(); ! while (VIM_ISWHITE(i) && oneright() == OK); ! curwin->w_valid &= ~VALID_WCOL; ! } ! curwin->w_set_curswant = TRUE; break; case 'M': --- 6255,6273 ---- clearopbeep(oap); break; ! // "gJ": join two lines without inserting a space. case 'J': nv_join(cap); break; ! // "g0", "g^" : Like "0" and "^" but for screen lines. ! // "gm": middle of "g0" and "g$". case '^': case '0': case 'm': case K_HOME: case K_KHOME: ! nv_g_home_m_cmd(cap); break; case 'M': *************** *** 6149,6252 **** } break; case '_': ! // "g_": to the last non-blank character in the line or lines ! // downward. ! cap->oap->motion_type = MCHAR; ! cap->oap->inclusive = TRUE; ! curwin->w_curswant = MAXCOL; ! if (cursor_down((long)(cap->count1 - 1), ! cap->oap->op_type == OP_NOP) == FAIL) ! clearopbeep(cap->oap); ! else ! { ! char_u *ptr = ml_get_curline(); ! ! // In Visual mode we may end up after the line. ! if (curwin->w_cursor.col > 0 && ptr[curwin->w_cursor.col] == NUL) ! --curwin->w_cursor.col; ! ! // Decrease the cursor column until it's on a non-blank. ! while (curwin->w_cursor.col > 0 ! && VIM_ISWHITE(ptr[curwin->w_cursor.col])) ! --curwin->w_cursor.col; ! curwin->w_set_curswant = TRUE; ! adjust_for_sel(cap); ! } break; case '$': case K_END: case K_KEND: ! { ! int col_off = curwin_col_off(); ! ! oap->motion_type = MCHAR; ! oap->inclusive = TRUE; ! if (curwin->w_p_wrap && curwin->w_width != 0) ! { ! curwin->w_curswant = MAXCOL; // so we stay at the end ! if (cap->count1 == 1) ! { ! int width1 = curwin->w_width - col_off; ! int width2 = width1 + curwin_col_off2(); ! ! validate_virtcol(); ! i = width1 - 1; ! if (curwin->w_virtcol >= (colnr_T)width1) ! i += ((curwin->w_virtcol - width1) / width2 + 1) ! * width2; ! coladvance((colnr_T)i); ! ! // Make sure we stick in this column. ! validate_virtcol(); ! curwin->w_curswant = curwin->w_virtcol; ! curwin->w_set_curswant = FALSE; ! if (curwin->w_cursor.col > 0 && curwin->w_p_wrap) ! { ! /* ! * Check for landing on a character that got split at ! * the end of the line. We do not want to advance to ! * the next screen line. ! */ ! if (curwin->w_virtcol > (colnr_T)i) ! --curwin->w_cursor.col; ! } ! } ! else if (nv_screengo(oap, FORWARD, cap->count1 - 1) == FAIL) ! clearopbeep(oap); ! } ! else ! { ! if (cap->count1 > 1) ! // if it fails, let the cursor still move to the last char ! (void)cursor_down(cap->count1 - 1, FALSE); ! ! i = curwin->w_leftcol + curwin->w_width - col_off - 1; ! coladvance((colnr_T)i); ! ! // if the character doesn't fit move one back ! if (curwin->w_cursor.col > 0 ! && (*mb_ptr2cells)(ml_get_cursor()) > 1) ! { ! colnr_T vcol; ! ! getvvcol(curwin, &curwin->w_cursor, NULL, NULL, &vcol); ! if (vcol >= curwin->w_leftcol + curwin->w_width - col_off) ! --curwin->w_cursor.col; ! } ! ! // Make sure we stick in this column. ! validate_virtcol(); ! curwin->w_curswant = curwin->w_virtcol; ! curwin->w_set_curswant = FALSE; ! } ! } break; ! /* ! * "g*" and "g#", like "*" and "#" but without using "\<" and "\>" ! */ case '*': case '#': #if POUND != '#' --- 6283,6302 ---- } break; + // "g_": to the last non-blank character in the line or lines + // downward. case '_': ! nv_g_underscore_cmd(cap); break; + // "g$" : Like "$" but for screen lines. case '$': case K_END: case K_KEND: ! nv_g_dollar_cmd(cap); break; ! // "g*" and "g#", like "*" and "#" but without using "\<" and "\>" case '*': case '#': #if POUND != '#' *************** *** 6257,6265 **** nv_ident(cap); break; ! /* ! * ge and gE: go back to end of word ! */ case 'e': case 'E': oap->motion_type = MCHAR; --- 6307,6313 ---- nv_ident(cap); break; ! // ge and gE: go back to end of word case 'e': case 'E': oap->motion_type = MCHAR; *************** *** 6269,6304 **** clearopbeep(oap); break; ! /* ! * "g CTRL-G": display info about cursor position ! */ case Ctrl_G: cursor_pos_info(NULL); break; ! /* ! * "gi": start Insert at the last position. ! */ case 'i': ! if (curbuf->b_last_insert.lnum != 0) ! { ! curwin->w_cursor = curbuf->b_last_insert; ! check_cursor_lnum(); ! i = (int)STRLEN(ml_get_curline()); ! if (curwin->w_cursor.col > (colnr_T)i) ! { ! if (virtual_active()) ! curwin->w_cursor.coladd += curwin->w_cursor.col - i; ! curwin->w_cursor.col = i; ! } ! } ! cap->cmdchar = 'i'; ! nv_edit(cap); break; ! /* ! * "gI": Start insert in column 1. ! */ case 'I': beginline(0); if (!checkclearopq(oap)) --- 6317,6333 ---- clearopbeep(oap); break; ! // "g CTRL-G": display info about cursor position case Ctrl_G: cursor_pos_info(NULL); break; ! // "gi": start Insert at the last position. case 'i': ! nv_gi_cmd(cap); break; ! // "gI": Start insert in column 1. case 'I': beginline(0); if (!checkclearopq(oap)) *************** *** 6306,6322 **** break; #ifdef FEAT_SEARCHPATH ! /* ! * "gf": goto file, edit file under cursor ! * "]f" and "[f": can also be used. ! */ case 'f': case 'F': nv_gotofile(cap); break; #endif ! // "g'm" and "g`m": jump to mark without setting pcmark case '\'': cap->arg = TRUE; // FALLTHROUGH --- 6335,6349 ---- break; #ifdef FEAT_SEARCHPATH ! // "gf": goto file, edit file under cursor ! // "]f" and "[f": can also be used. case 'f': case 'F': nv_gotofile(cap); break; #endif ! // "g'm" and "g`m": jump to mark without setting pcmark case '\'': cap->arg = TRUE; // FALLTHROUGH *************** *** 6324,6349 **** nv_gomark(cap); break; ! /* ! * "gs": Goto sleep. ! */ case 's': do_sleep(cap->count1 * 1000L, FALSE); break; ! /* ! * "ga": Display the ascii value of the character under the ! * cursor. It is displayed in decimal, hex, and octal. -- webb ! */ case 'a': do_ascii(NULL); break; ! /* ! * "g8": Display the bytes used for the UTF-8 character under the ! * cursor. It is displayed in hex. ! * "8g8" finds illegal byte sequence. ! */ case '8': if (cap->count0 == 8) utf_find_illegal(); --- 6351,6370 ---- nv_gomark(cap); break; ! // "gs": Goto sleep. case 's': do_sleep(cap->count1 * 1000L, FALSE); break; ! // "ga": Display the ascii value of the character under the ! // cursor. It is displayed in decimal, hex, and octal. -- webb case 'a': do_ascii(NULL); break; ! // "g8": Display the bytes used for the UTF-8 character under the ! // cursor. It is displayed in hex. ! // "8g8" finds illegal byte sequence. case '8': if (cap->count0 == 8) utf_find_illegal(); *************** *** 6356,6380 **** show_sb_text(); break; ! /* ! * "gg": Goto the first line in file. With a count it goes to ! * that line number like for "G". -- webb ! */ case 'g': cap->arg = FALSE; nv_goto(cap); break; ! /* ! * 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 ! * "g@" call 'operatorfunc' ! */ case 'q': case 'w': oap->cursor_start = curwin->w_cursor; --- 6377,6397 ---- show_sb_text(); break; ! // "gg": Goto the first line in file. With a count it goes to ! // that line number like for "G". -- webb case 'g': cap->arg = FALSE; nv_goto(cap); break; ! // 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 ! // "g@" call 'operatorfunc' case 'q': case 'w': oap->cursor_start = curwin->w_cursor; *************** *** 6387,6405 **** nv_operator(cap); break; ! /* ! * "gd": Find first occurrence of pattern under the cursor in the ! * current function ! * "gD": idem, but in the current file. ! */ case 'd': case 'D': nv_gd(oap, cap->nchar, (int)cap->count0); break; ! /* ! * g<*Mouse> : ! */ case K_MIDDLEMOUSE: case K_MIDDLEDRAG: case K_MIDDLERELEASE: --- 6404,6418 ---- nv_operator(cap); break; ! // "gd": Find first occurrence of pattern under the cursor in the ! // current function ! // "gD": idem, but in the current file. case 'd': case 'D': nv_gd(oap, cap->nchar, (int)cap->count0); break; ! // g<*Mouse> : case K_MIDDLEMOUSE: case K_MIDDLEDRAG: case K_MIDDLERELEASE: *************** *** 6423,6431 **** case K_IGNORE: break; ! /* ! * "gP" and "gp": same as "P" and "p" but leave cursor just after new text ! */ case 'p': case 'P': nv_put(cap); --- 6436,6442 ---- case K_IGNORE: break; ! // "gP" and "gp": same as "P" and "p" but leave cursor just after new text case 'p': case 'P': nv_put(cap); *** ../vim-8.2.4164/src/version.c 2022-01-20 19:56:45.555663631 +0000 --- src/version.c 2022-01-20 20:15:40.261735477 +0000 *************** *** 752,753 **** --- 752,755 ---- { /* Add new patch number below this line */ + /**/ + 4165, /**/ -- [Autumn changed into Winter ... Winter changed into Spring ... Spring changed back into Autumn and Autumn gave Winter and Spring a miss and went straight on into Summer ... Until one day ...] "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// \\\ \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///