To: vim-dev@vim.org Subject: Patch 6.1.237 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit ------------ Patch 6.1.237 Problem: Putting in Visual block mode does not work correctly when "$" was used or when the first line is short. (Christian Michon) Solution: First delete the selected text and then put the new text. Save and restore registers as necessary. Files: src/globals.h, src/normal.c, src/ops.c, src/proto/ops.pro, src/vim.h *** ../vim61.236/src/globals.h Sun Oct 13 18:48:35 2002 --- src/globals.h Sun Oct 27 18:31:36 2002 *************** *** 453,459 **** EXTERN int redo_VIsual_busy INIT(= FALSE); /* TRUE when redoing Visual */ - EXTERN int did_visual_put INIT(= FALSE); /* TRUE after Visual mode "p" */ #endif #ifdef FEAT_MOUSE --- 453,458 ---- *** ../vim61.236/src/normal.c Thu Oct 17 20:11:44 2002 --- src/normal.c Sun Oct 27 20:29:45 2002 *************** *** 1138,1146 **** normal_end: msg_nowait = FALSE; - #ifdef FEAT_VISUAL - did_visual_put = FALSE; - #endif /* Reset finish_op, in case it was set */ #ifdef CURSOR_SHAPE --- 1138,1143 ---- *************** *** 7928,7935 **** cmdarg_T *cap; { #ifdef FEAT_VISUAL ! pos_T curpos; ! colnr_T left, right; #endif int dir; int flags = 0; --- 7925,7932 ---- cmdarg_T *cap; { #ifdef FEAT_VISUAL ! int regname; ! void *reg1 = NULL, *reg2 = NULL; #endif int dir; int flags = 0; *************** *** 7952,8027 **** dir = (cap->cmdchar == 'P' || (cap->cmdchar == 'g' && cap->nchar == 'P')) ? BACKWARD : FORWARD; - #ifdef FEAT_VISUAL - if (VIsual_active) - { - /* Putting in Visual mode: The put text replaces the selected - * text. First put the register at the end of the Visual - * selection, then delete the selected text. In some cases the - * register is put before the Visual selection. */ - if (lt(VIsual, curwin->w_cursor)) - { - curbuf->b_visual_start = VIsual; - curbuf->b_visual_end = curwin->w_cursor; - } - else - { - curbuf->b_visual_start = curwin->w_cursor; - curbuf->b_visual_end = VIsual; - } - curpos = curwin->w_cursor; - if (VIsual_mode == Ctrl_V) - { - getvcols(curwin, &curwin->w_cursor, &VIsual, &left, &right); - curwin->w_cursor = curbuf->b_visual_start; - coladvance(right); - } - else - curwin->w_cursor = curbuf->b_visual_end; - if (VIsual_mode == 'v' && *p_sel == 'e') - dir = BACKWARD; - else - { - /* Put linewise text above a characterwise or blockwise - * selected Visual area; handled in do_put(). */ - if (dir == BACKWARD && VIsual_mode != 'V') - flags |= PUT_LINE_BACKWARD; - dir = FORWARD; - } - /* When deleting a linewise Visual area, must put the register as - * lines to avoid it being deleted. */ - if (VIsual_mode == 'V') - flags |= PUT_LINE; - } - #endif prep_redo_cmd(cap); if (cap->cmdchar == 'g') flags |= PUT_CURSEND; - do_put(cap->oap->regname, dir, cap->count1, flags); #ifdef FEAT_VISUAL if (VIsual_active) { ! /* If linewise text was put above the Visual area, need to correct ! * the line numbers to shift the Visual area down. */ ! if ((flags & PUT_LINE_BACKWARD) ! && curbuf->b_visual_start.lnum > curbuf->b_op_end.lnum) ! { ! linenr_T l; ! ! l = curbuf->b_op_end.lnum - curbuf->b_op_start.lnum + 1; ! curpos.lnum += l; ! VIsual.lnum += l; } /* Now delete the selected text. */ cap->cmdchar = 'd'; cap->nchar = NUL; cap->oap->regname = NUL; - curwin->w_cursor = curpos; nv_operator(cap); ! did_visual_put = TRUE; /* tell op_delete() to correct '] mark */ } #endif auto_format(); } --- 7949,8017 ---- dir = (cap->cmdchar == 'P' || (cap->cmdchar == 'g' && cap->nchar == 'P')) ? BACKWARD : FORWARD; prep_redo_cmd(cap); if (cap->cmdchar == 'g') flags |= PUT_CURSEND; #ifdef FEAT_VISUAL if (VIsual_active) { ! /* Putting in Visual mode: The put text replaces the selected ! * text. First delete the selected text, then put the new text. ! * Need to save and restore the registers that the delete ! * overwrites if the old contents is being put. ! */ ! regname = cap->oap->regname; ! # ifdef FEAT_CLIPBOARD ! adjust_clip_reg(®name); ! # endif ! if (regname == 0 || isdigit(regname)) ! { ! /* the delete is going to overwrite the register we want to ! * put, save it first. */ ! reg1 = get_register(regname, TRUE); } /* Now delete the selected text. */ cap->cmdchar = 'd'; cap->nchar = NUL; cap->oap->regname = NUL; nv_operator(cap); ! do_pending_operator(cap, 0, FALSE); ! ! /* delete PUT_LINE_BACKWARD; */ ! cap->oap->regname = regname; ! ! if (reg1 != NULL) ! { ! /* Delete probably changed the register we want to put, save ! * it first. Then put back what was there before the delete. */ ! reg2 = get_register(regname, FALSE); ! put_register(regname, reg1); ! } ! ! /* When deleted a linewise Visual area, put the register as ! * lines to avoid it joined with the next line. When deletion was ! * characterwise, split a line when putting lines. */ ! if (VIsual_mode == 'V') ! flags |= PUT_LINE; ! else if (VIsual_mode == 'v') ! flags |= PUT_LINE_SPLIT; ! if (VIsual_mode == Ctrl_V && dir == FORWARD) ! flags |= PUT_LINE_FORWARD; ! dir = BACKWARD; ! if (VIsual_mode != 'V' ! && curwin->w_cursor.col < curbuf->b_op_start.col) ! /* cursor is at the end of the line, put forward. */ ! dir = FORWARD; } + #endif + do_put(cap->oap->regname, dir, cap->count1, flags); + + #ifdef FEAT_VISUAL + /* If a register was saved, put it back now. */ + if (reg2 != NULL) + put_register(regname, reg2); #endif auto_format(); } *** ../vim61.236/src/ops.c Thu Aug 1 20:47:28 2002 --- src/ops.c Sun Oct 27 20:29:17 2002 *************** *** 847,852 **** --- 847,900 ---- y_previous = y_current; } + #if defined(FEAT_VISUAL) || defined(PROTO) + /* + * Obtain the contents of a "normal" register. The register is made empty. + * The returned pointer has allocated memory, use put_register() later. + */ + void * + get_register(name, copy) + int name; + int copy; /* make a copy, if FALSE make register empty. */ + { + static struct yankreg *reg; + int i; + + get_yank_register(name, 0); + reg = (struct yankreg *)alloc((unsigned)sizeof(struct yankreg)); + if (reg != NULL) + { + *reg = *y_current; + if (copy) + { + /* If we run out of memory some or all of the lines are empty. */ + reg->y_array = (char_u **)alloc((unsigned)sizeof(char_u *)); + if (reg->y_array != NULL) + { + for (i = 0; i < reg->y_size; ++i) + reg->y_array[i] = vim_strsave(y_current->y_array[i]); + } + } + else + y_current->y_array = NULL; + } + return (void *)reg; + } + + /* + * Put "reg" into register "name". Free any previous contents. + */ + void + put_register(name, reg) + int name; + void *reg; + { + get_yank_register(name, 0); + free_yank_all(); + *y_current = *(struct yankreg *)reg; + } + #endif + #if defined(FEAT_MOUSE) || defined(PROTO) /* * return TRUE if the current yank register has type MLINE *************** *** 1403,1408 **** --- 1457,1481 ---- } } + #if defined(FEAT_CLIPBOARD) || defined(PROTO) + /* + * Adjust the register name pointed to with "rp" for the clipboard being + * used always and the clipboard being available. + */ + void + adjust_clip_reg(rp) + int *rp; + { + /* If no reg. specified, and "unnamed" is in 'clipboard', use '*' reg. */ + if (*rp == 0 && clip_unnamed) + *rp = '*'; + if (!clip_star.available && *rp == '*') + *rp = 0; + if (!clip_plus.available && *rp == '+') + *rp = 0; + } + #endif + /* * op_delete - handle a delete operation * *************** *** 1436,1448 **** } #ifdef FEAT_CLIPBOARD ! /* If no reg. specified, and "unnamed" is in 'clipboard', use '*' reg. */ ! if (oap->regname == 0 && clip_unnamed) ! oap->regname = '*'; ! if (!clip_star.available && oap->regname == '*') ! oap->regname = 0; ! if (!clip_plus.available && oap->regname == '+') ! oap->regname = 0; #endif #ifdef FEAT_MBYTE --- 1509,1515 ---- } #ifdef FEAT_CLIPBOARD ! adjust_clip_reg(&oap->regname); #endif #ifdef FEAT_MBYTE *************** *** 1754,1799 **** msgmore(curbuf->b_ml.ml_line_count - old_lcount); #ifdef FEAT_VISUAL ! /* ! * Set "'[" and "']" marks. ! */ ! if (did_visual_put) { ! /* "p" in Visual mode: The '] mark is at the end of the inserted text, ! * correct it for the deleted text. */ ! if (oap->block_mode) ! { ! if (curbuf->b_op_end.lnum <= oap->end.lnum) ! curbuf->b_op_end.col -= bd.textlen ! - bd.startspaces - bd.endspaces; ! } ! else if (oap->motion_type == MLINE) ! curbuf->b_op_end.lnum -= oap->line_count; ! else ! { ! if (curbuf->b_op_end.lnum == curbuf->b_op_start.lnum) ! { ! if (oap->line_count == 1) ! curbuf->b_op_end.col -= oap->end.col - oap->start.col + 1; ! else ! curbuf->b_op_end.col -= oap->end.col - 1; ! } ! curbuf->b_op_end.lnum -= oap->line_count - 1; ! } } else #endif ! { ! #ifdef FEAT_VISUAL ! if (oap->block_mode) ! { ! curbuf->b_op_end.lnum = oap->end.lnum; ! curbuf->b_op_end.col = oap->start.col; ! } ! else ! #endif ! curbuf->b_op_end = oap->start; ! } curbuf->b_op_start = oap->start; return OK; --- 1821,1834 ---- msgmore(curbuf->b_ml.ml_line_count - old_lcount); #ifdef FEAT_VISUAL ! if (oap->block_mode) { ! curbuf->b_op_end.lnum = oap->end.lnum; ! curbuf->b_op_end.col = oap->start.col; } else #endif ! curbuf->b_op_end = oap->start; curbuf->b_op_start = oap->start; return OK; *************** *** 2759,2771 **** /* * Set "'[" and "']" marks. */ ! #ifdef FEAT_VISUAL ! if (!did_visual_put) ! #endif ! { ! curbuf->b_op_start = oap->start; ! curbuf->b_op_end = oap->end; ! } #ifdef FEAT_CLIPBOARD /* --- 2794,2801 ---- /* * Set "'[" and "']" marks. */ ! curbuf->b_op_start = oap->start; ! curbuf->b_op_end = oap->end; #ifdef FEAT_CLIPBOARD /* *************** *** 2909,2931 **** long cnt; #ifdef FEAT_CLIPBOARD ! /* If no register specified, and "unnamed" in 'clipboard', use + register */ ! if (regname == 0 && clip_unnamed) ! regname = '*'; if (regname == '*') ! { ! if (!clip_star.available) ! regname = 0; ! else ! clip_get_selection(&clip_star); ! } else if (regname == '+') ! { ! if (!clip_plus.available) ! regname = 0; ! else ! clip_get_selection(&clip_plus); ! } #endif if (flags & PUT_FIXINDENT) --- 2939,2950 ---- long cnt; #ifdef FEAT_CLIPBOARD ! /* Adjust register name for "unnamed" in 'clipboard'. */ ! adjust_clip_reg(®name); if (regname == '*') ! clip_get_selection(&clip_star); else if (regname == '+') ! clip_get_selection(&clip_plus); #endif if (flags & PUT_FIXINDENT) *************** *** 3021,3046 **** #ifdef FEAT_VISUAL if (y_type == MLINE) { ! if (flags & PUT_LINE_BACKWARD) { ! /* "P" in Visual mode: Put before the Visual area instead of after ! * it. It's OK to change the cursor position here (special ! * case!). */ ! dir = BACKWARD; ! curwin->w_cursor = curbuf->b_visual_start; } ! else if (VIsual_active && VIsual_mode == Ctrl_V) { ! /* "p" in Visual block mode with linewise text: put below the ! * block. */ curwin->w_cursor = curbuf->b_visual_end; } curbuf->b_op_start = curwin->w_cursor; /* default for '[ mark */ curbuf->b_op_end = curwin->w_cursor; /* default for '] mark */ } #endif ! if (flags & PUT_LINE) /* :put command */ y_type = MLINE; if (y_size == 0 || y_array == NULL) --- 3040,3076 ---- #ifdef FEAT_VISUAL if (y_type == MLINE) { ! if (flags & PUT_LINE_SPLIT) { ! /* "p" or "P" in Visual mode: split the lines to put the text in ! * between. */ ! if (u_save_cursor() == FAIL) ! goto end; ! ptr = vim_strsave(ml_get_cursor()); ! if (ptr == NULL) ! goto end; ! ml_append(curwin->w_cursor.lnum, ptr, (colnr_T)0, FALSE); ! vim_free(ptr); ! ! ptr = vim_strnsave(ml_get_curline(), curwin->w_cursor.col); ! if (ptr == NULL) ! goto end; ! ml_replace(curwin->w_cursor.lnum, ptr, FALSE); ! ++nr_lines; ! dir = FORWARD; } ! if (flags & PUT_LINE_FORWARD) { ! /* Must be "p" for a Visual block, put lines below the block. */ curwin->w_cursor = curbuf->b_visual_end; + dir = FORWARD; } curbuf->b_op_start = curwin->w_cursor; /* default for '[ mark */ curbuf->b_op_end = curwin->w_cursor; /* default for '] mark */ } #endif ! if (flags & PUT_LINE) /* :put command or "p" in Visual line mode. */ y_type = MLINE; if (y_size == 0 || y_array == NULL) *************** *** 3360,3366 **** else { /* ! * Insert at least one one. When y_type is MCHAR, break the first * line in two. */ for (cnt = 1; cnt <= count; ++cnt) --- 3390,3396 ---- else { /* ! * Insert at least one line. When y_type is MCHAR, break the first * line in two. */ for (cnt = 1; cnt <= count; ++cnt) *** ../vim61.236/src/proto/ops.pro Sun Jul 28 22:02:42 2002 --- src/proto/ops.pro Sun Oct 27 18:03:58 2002 *************** *** 9,19 **** --- 9,22 ---- int get_expr_register __ARGS((void)); void set_expr_line __ARGS((char_u *new_line)); int valid_yank_reg __ARGS((int regname, int writing)); + void *get_register __ARGS((int name, int copy)); + void put_register __ARGS((int name, void *reg)); int yank_register_mline __ARGS((int regname)); int do_record __ARGS((int c)); int do_execreg __ARGS((int regname, int colon, int addcr)); int insert_reg __ARGS((int regname, int literally)); int cmdline_paste __ARGS((int regname, int literally)); + void adjust_clip_reg __ARGS((int *rp)); int op_delete __ARGS((oparg_T *oap)); int op_replace __ARGS((oparg_T *oap, int c)); void op_tilde __ARGS((oparg_T *oap)); *** ../vim61.236/src/version.c Sun Oct 27 19:31:44 2002 --- src/version.c Sun Oct 27 20:21:01 2002 *************** *** 608,609 **** --- 608,611 ---- { /* Add new patch number below this line */ + /**/ + 237, /**/ -- ARTHUR: I did say sorry about the `old woman,' but from the behind you looked-- DENNIS: What I object to is you automatically treat me like an inferior! ARTHUR: Well, I AM king... The Quest for the Holy Grail (Monty Python) /// Bram Moolenaar -- Bram@moolenaar.net -- http://www.moolenaar.net \\\ /// Creator of Vim - Vi IMproved -- http://www.vim.org \\\ \\\ Project leader for A-A-P -- http://www.a-a-p.org /// \\\ Lord Of The Rings helps Uganda - http://iccf-holland.org/lotr.html ///