Here is my fix. It seems to work manually testing it with a few cases. Here is the timing of vim installed with my Ubuntu: % yes | head -100000 > yes.tmp % time vim -u NONE -c '%join|q!' yes.tmp 17.2u 0.0s 0:17.24 99.8% 0+0k 0+8io 0pf+0w
And with my patch: % time ./vim -u NONE -c '%join|q!' yes.tmp 0.2u 0.0s 0:00.29 96.5% 0+0k 0+8io 0pf+0w Below is the patch (a diff of ops_orig.c and ops.c). It needs a bit of cleaning up (eg putting the function prototype where it belongs) and checking that the error handling is done in a correct way (I've tried to be consistent with existing code but don't really understand how it all works, eg with the magic of undo). lee P.S. I posted something else which hasn't shown up yet - maybe due to moderation. I'm doing this via e-mail as I have not yet handed over all my personal details to Google. *** ops_orig.c 2008-12-10 15:15:08.000000000 +1100 --- ops.c 2008-12-11 17:10:15.000000000 +1100 *************** *** 4102,4107 **** --- 4102,4109 ---- ui_breakcheck(); } + int do_do_join_rec(long, int); /* MOVE/FIX this */ + /* * join 'count' lines (minimal 2), including u_save() */ *************** *** 4110,4130 **** long count; int insert_space; { colnr_T col = MAXCOL; if (u_save((linenr_T)(curwin->w_cursor.lnum - 1), (linenr_T)(curwin->w_cursor.lnum + count)) == FAIL) return; ! while (--count > 0) { line_breakcheck(); if (got_int || do_join(insert_space) == FAIL) { beep_flush(); ! break; ! } ! if (col == MAXCOL && vim_strchr(p_cpo, CPO_JOINCOL) != NULL) col = curwin->w_cursor.col; } --- 4112,4140 ---- long count; int insert_space; { + int failflag = OK; colnr_T col = MAXCOL; if (u_save((linenr_T)(curwin->w_cursor.lnum - 1), (linenr_T)(curwin->w_cursor.lnum + count)) == FAIL) return; ! /* Its simplest to call do_join() count-1 times in a while loop ! * but this leads to O(count^2) complexity. ! * Better to use a divide and conquer strategy, leading to ! * O(count log count) complexity. Here we use D&Q for first ! * count-1 lines (count-2 joins); the last join is done separately ! * so we can set the new column for the cursor correctly. ! */ ! if (count > 2) ! failflag = do_do_join_rec(count-2, insert_space); ! if (failflag == OK) { line_breakcheck(); if (got_int || do_join(insert_space) == FAIL) { beep_flush(); ! } else if (col == MAXCOL && vim_strchr(p_cpo, CPO_JOINCOL) != NULL) col = curwin->w_cursor.col; } *************** *** 4142,4147 **** --- 4152,4192 ---- } /* + * join 'count'+1 lines ('count' join ops), using recursive divide + * and conquer strategy + */ + int + do_do_join_rec(count, insert_space) + long count; + int insert_space; + { + if (count == 0) + /* base case: nothing to do */ + return OK; + else { + + /* join all lines in first ~half */ + if (got_int || do_do_join_rec((count-1)/2, insert_space) == FAIL) + return FAIL; + + /* go to next line and join all lines in second ~half; + * we want a total of count-1 joins at this point + */ + ++curwin->w_cursor.lnum; + if (got_int || + do_do_join_rec(count-1-(count-1)/2, insert_space) == FAIL) + return FAIL; + + /* go back to first (joined) line and join with the second */ + --curwin->w_cursor.lnum; + line_breakcheck(); + if (got_int || do_join(insert_space) == FAIL) + return FAIL; + return OK; + } + } + + /* * Join two lines at the cursor position. * "redraw" is TRUE when the screen should be updated. * Caller must have setup for undo. --~--~---------~--~----~------------~-------~--~----~ You received this message from the "vim_dev" maillist. For more information, visit http://www.vim.org/maillist.php -~----------~----~----~----~------~----~------~--~---