📄 v_text.c
字号:
* Change line command. */intv_Change(sp, ep, vp) SCR *sp; EXF *ep; VICMDARG *vp;{ return (v_CS(sp, ep, vp, 0));}/* * v_Subst -- [buffer][count]S * Line substitute command. */intv_Subst(sp, ep, vp) SCR *sp; EXF *ep; VICMDARG *vp;{ u_int flags; /* * The S command is the same as a 'C' command from the beginning * of the line. This is hard to do in the parser, so do it here. * * If autoindent is on, the change is from the first *non-blank* * character of the line, not the first character. And, to make * it just a bit more exciting, the initial space is handled as * auto-indent characters. */ LF_INIT(0); if (O_ISSET(sp, O_AUTOINDENT)) { vp->m_start.cno = 0; if (nonblank(sp, ep, vp->m_start.lno, &vp->m_start.cno)) return (1); LF_SET(TXT_AICHARS); } else vp->m_start.cno = 0; sp->cno = vp->m_start.cno; return (v_CS(sp, ep, vp, flags));}/* * v_CS -- * C and S commands. */static intv_CS(sp, ep, vp, iflags) SCR *sp; EXF *ep; VICMDARG *vp; u_int iflags;{ MARK *tm; recno_t lno; size_t len; char *p; u_int flags; flags = set_txt_std(sp, vp, iflags); /* * There are two cases -- if a count is supplied, we do a line * mode change where we delete the lines and then insert text * into a new line. Otherwise, we replace the current line. */ vp->m_stop.lno = vp->m_start.lno + (F_ISSET(vp, VC_C1SET) ? vp->count - 1 : 0); if (vp->m_start.lno != vp->m_stop.lno) { /* Make sure that the to line is real. */ if (file_gline(sp, ep, vp->m_stop.lno, &vp->m_stop.cno) == NULL) { v_eof(sp, ep, &vp->m_start); return (1); } if (vp->m_stop.cno != 0) --vp->m_stop.cno; /* Cut the lines. */ if (cut(sp, ep, NULL, F_ISSET(vp, VC_BUFFER) ? &vp->buffer : NULL, &vp->m_start, &vp->m_stop, CUT_LINEMODE)) return (1); /* Insert a line while we still can... */ if (file_iline(sp, ep, vp->m_start.lno, "", 0)) return (1); ++vp->m_start.lno; ++vp->m_stop.lno; /* Delete the lines. */ if (delete(sp, ep, &vp->m_start, &vp->m_stop, 1)) return (1); /* Get the inserted line. */ if ((p = file_gline(sp, ep, --vp->m_start.lno, &len)) == NULL) { GETLINE_ERR(sp, vp->m_start.lno); return (1); } tm = NULL; sp->lno = vp->m_start.lno; sp->cno = 0; LF_SET(TXT_APPENDEOL); } else { /* The line may be empty, but that's okay. */ if ((p = file_gline(sp, ep, vp->m_start.lno, &len)) == NULL) { if (file_lline(sp, ep, &lno)) return (1); if (lno != 0) { GETLINE_ERR(sp, vp->m_start.lno); return (1); } vp->m_stop.cno = len = 0; LF_SET(TXT_APPENDEOL); } else { if (len == 0) { vp->m_stop.cno = 0; LF_SET(TXT_APPENDEOL); } else vp->m_stop.cno = len - 1; if (cut(sp, ep, NULL, F_ISSET(vp, VC_BUFFER) ? &vp->buffer : NULL, &vp->m_start, &vp->m_stop, CUT_LINEMODE)) return (1); LF_SET(TXT_EMARK | TXT_OVERWRITE); } tm = &vp->m_stop; } /* Correct logging for implied cursor motion. */ LOG_CORRECT; return (v_ntext(sp, ep, sp->tiqp, tm, p, len, &vp->m_final, 0, OOBLNO, flags));}/* * v_change -- [buffer][count]c[count]motion * Change command. */intv_change(sp, ep, vp) SCR *sp; EXF *ep; VICMDARG *vp;{ recno_t lno; size_t blen, len; u_int flags; int lmode, rval; char *bp, *p; flags = set_txt_std(sp, vp, 0); /* * Move the cursor to the start of the change. Note, if autoindent * is turned on, the cc command in line mode changes from the first * *non-blank* character of the line, not the first character. And, * to make it just a bit more exciting, the initial space is handled * as auto-indent characters. */ lmode = F_ISSET(vp, VM_LMODE) ? CUT_LINEMODE : 0; if (lmode) { vp->m_start.cno = 0; if (O_ISSET(sp, O_AUTOINDENT)) { if (nonblank(sp, ep, vp->m_start.lno, &vp->m_start.cno)) return (1); LF_SET(TXT_AICHARS); } } sp->lno = vp->m_start.lno; sp->cno = vp->m_start.cno; /* Correct logging for implied cursor motion. */ LOG_CORRECT; /* * If changing within a single line, the line either currently has * text or it doesn't. If it doesn't, just insert text. Otherwise, * copy it and overwrite it. */ if (vp->m_start.lno == vp->m_stop.lno) { if ((p = file_gline(sp, ep, vp->m_start.lno, &len)) == NULL) { if (p == NULL) { if (file_lline(sp, ep, &lno)) return (1); if (lno != 0) { GETLINE_ERR(sp, vp->m_start.lno); return (1); } } vp->m_stop.cno = len = 0; LF_SET(TXT_APPENDEOL); } else { if (cut(sp, ep, NULL, F_ISSET(vp, VC_BUFFER) ? &vp->buffer : NULL, &vp->m_start, &vp->m_stop, lmode)) return (1); if (len == 0) LF_SET(TXT_APPENDEOL); LF_SET(TXT_EMARK | TXT_OVERWRITE); } return (v_ntext(sp, ep, sp->tiqp, &vp->m_stop, p, len, &vp->m_final, 0, OOBLNO, flags)); } /* * It's trickier if changing over multiple lines. If we're in * line mode we delete all of the lines and insert a replacement * line which the user edits. If there was leading whitespace * in the first line being changed, we copy it and use it as the * replacement. If we're not in line mode, we just delete the * text and start inserting. * * Copy the text. */ if (cut(sp, ep, NULL, F_ISSET(vp, VC_BUFFER) ? &vp->buffer : NULL, &vp->m_start, &vp->m_stop, lmode)) return (1); /* If replacing entire lines and there's leading text. */ if (lmode && vp->m_start.cno) { /* Get a copy of the first line changed. */ if ((p = file_gline(sp, ep, vp->m_start.lno, &len)) == NULL) { GETLINE_ERR(sp, vp->m_start.lno); return (1); } /* Copy the leading text elsewhere. */ GET_SPACE_RET(sp, bp, blen, vp->m_start.cno); memmove(bp, p, vp->m_start.cno); } else bp = NULL; /* Delete the text. */ if (delete(sp, ep, &vp->m_start, &vp->m_stop, lmode)) return (1); /* If replacing entire lines, insert a replacement line. */ if (lmode) { if (file_iline(sp, ep, vp->m_start.lno, bp, vp->m_start.cno)) return (1); sp->lno = vp->m_start.lno; len = sp->cno = vp->m_start.cno; } /* Get the line we're editing. */ if ((p = file_gline(sp, ep, vp->m_start.lno, &len)) == NULL) { if (file_lline(sp, ep, &lno)) return (1); if (lno != 0) { GETLINE_ERR(sp, vp->m_start.lno); return (1); } len = 0; } /* Check to see if we're appending to the line. */ if (vp->m_start.cno >= len) LF_SET(TXT_APPENDEOL); rval = v_ntext(sp, ep, sp->tiqp, NULL, p, len, &vp->m_final, 0, OOBLNO, flags); if (bp != NULL) FREE_SPACE(sp, bp, blen); return (rval);}/* * v_Replace -- [count]R * Overwrite multiple characters. */intv_Replace(sp, ep, vp) SCR *sp; EXF *ep; VICMDARG *vp;{ recno_t lno; u_long cnt; size_t len; u_int flags; char *p; flags = set_txt_std(sp, vp, 0); cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1; if ((p = file_gline(sp, ep, vp->m_start.lno, &len)) == NULL) { if (file_lline(sp, ep, &lno)) return (1); if (lno != 0) { GETLINE_ERR(sp, vp->m_start.lno); return (1); } len = 0; LF_SET(TXT_APPENDEOL); } else { if (len == 0) LF_SET(TXT_APPENDEOL); LF_SET(TXT_OVERWRITE | TXT_REPLACE); } vp->m_stop.lno = vp->m_start.lno; vp->m_stop.cno = len ? len - 1 : 0; if (v_ntext(sp, ep, sp->tiqp, &vp->m_stop, p, len, &vp->m_final, 0, OOBLNO, flags)) return (1); if (F_ISSET(sp, S_INTERRUPTED)) return (0); /* * Special case. The historic vi handled [count]R badly, in that R * would replace some number of characters, and then the count would * append count-1 copies of the replacing chars to the replaced space. * This seems wrong, so this version counts R commands. There is some * trickiness in moving back to where the user stopped replacing after * each R command. Basically, if the user ended with a newline, we * want to use vp->m_final.cno (which will be 0). Otherwise, use the * column after the returned cursor, unless it would be past the end of * the line, in which case we append to the line. */ while (--cnt) { if ((p = file_gline(sp, ep, vp->m_final.lno, &len)) == NULL) GETLINE_ERR(sp, vp->m_final.lno); flags = set_txt_std(sp, vp, TXT_REPLAY); sp->lno = vp->m_final.lno; if (len == 0 || vp->m_final.cno == len - 1) { sp->cno = len; LF_SET(TXT_APPENDEOL); } else { sp->cno = vp->m_final.cno; if (vp->m_final.cno != 0) ++sp->cno; LF_SET(TXT_OVERWRITE | TXT_REPLACE); } vp->m_stop.lno = sp->lno; vp->m_stop.cno = sp->cno; if (v_ntext(sp, ep, sp->tiqp, &vp->m_stop, p, len, &vp->m_final, 0, OOBLNO, flags)) return (1); if (F_ISSET(sp, S_INTERRUPTED)) break; } return (0);}/* * v_subst -- [buffer][count]s * Substitute characters. */intv_subst(sp, ep, vp) SCR *sp; EXF *ep; VICMDARG *vp;{ recno_t lno; size_t len; u_int flags; char *p; flags = set_txt_std(sp, vp, 0); if ((p = file_gline(sp, ep, vp->m_start.lno, &len)) == NULL) { if (file_lline(sp, ep, &lno)) return (1); if (lno != 0) { GETLINE_ERR(sp, vp->m_start.lno); return (1); } len = 0; LF_SET(TXT_APPENDEOL); } else { if (len == 0) LF_SET(TXT_APPENDEOL); LF_SET(TXT_EMARK | TXT_OVERWRITE); } vp->m_stop.lno = vp->m_start.lno; vp->m_stop.cno = vp->m_start.cno + (F_ISSET(vp, VC_C1SET) ? vp->count - 1 : 0); if (vp->m_stop.cno > len - 1) vp->m_stop.cno = len - 1; if (p != NULL && cut(sp, ep, NULL, F_ISSET(vp, VC_BUFFER) ? &vp->buffer : NULL, &vp->m_start, &vp->m_stop, 0)) return (1); return (v_ntext(sp, ep, sp->tiqp, &vp->m_stop, p, len, &vp->m_final, 0, OOBLNO, flags));}/* * set_txt_std -- * Initialize text processing flags. */static u_intset_txt_std(sp, vp, init) SCR *sp; VICMDARG *vp; u_int init;{ u_int flags; /* Text operations are all interruptible. */ F_SET(sp, S_INTERRUPTIBLE); LF_INIT(init); LF_SET(TXT_CNTRLT | TXT_ESCAPE | TXT_MAPINPUT | TXT_RECORD | TXT_RESOLVE); if (O_ISSET(sp, O_ALTWERASE)) LF_SET(TXT_ALTWERASE); if (O_ISSET(sp, O_AUTOINDENT)) LF_SET(TXT_AUTOINDENT); if (O_ISSET(sp, O_BEAUTIFY)) LF_SET(TXT_BEAUTIFY); if (O_ISSET(sp, O_SHOWMATCH)) LF_SET(TXT_SHOWMATCH); if (O_ISSET(sp, O_WRAPMARGIN)) LF_SET(TXT_WRAPMARGIN); if (F_ISSET(sp, S_SCRIPT)) LF_SET(TXT_CR); if (O_ISSET(sp, O_TTYWERASE)) LF_SET(TXT_TTYWERASE); if (F_ISSET(vp, VC_ISDOT)) LF_SET(TXT_REPLAY); return (flags);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -