int default_char2int(SCR *sp, const char * str, ssize_t len, CONVWIN *cw, size_t *tolen, CHAR_T **dst, char *enc) { int i = 0, j; CHAR_T **tostr = (CHAR_T **)&cw->bp1; size_t *blen = &cw->blen1; mbstate_t mbs; size_t n; ssize_t nlen = len; char *src = (char *)str; iconv_t id = (iconv_t)-1; char buffer[CONV_BUFFER_SIZE]; size_t left = len; int error = 1; MEMSET(&mbs, 0, 1); BINC_RETW(NULL, *tostr, *blen, nlen); #ifdef USE_ICONV if (strcmp(nl_langinfo(CODESET), enc)) { id = iconv_open(nl_langinfo(CODESET), enc); if (id == (iconv_t)-1) goto err; CONVERT(str, left, src, len); } #endif for (i = 0, j = 0; j < len; ) { n = mbrtowc((*tostr)+i, src+j, len-j, &mbs); /* NULL character converted */ if (n == -2) error = -(len-j); if (n == -1 || n == -2) goto err; if (n == 0) n = 1; j += n; if (++i >= *blen) { nlen += 256; BINC_RETW(NULL, *tostr, *blen, nlen); } if (id != (iconv_t)-1 && j == len && left) { CONVERT(str, left, src, len); j = 0; } } *tolen = i; if (id != (iconv_t)-1) iconv_close(id); *dst = cw->bp1; return 0; err: *tolen = i; if (id != (iconv_t)-1) iconv_close(id); *dst = cw->bp1; return error; }
/* * v_curword -- * Get the word (tagstring, actually) the cursor is on. * * PUBLIC: int v_curword __P((SCR *)); */ int v_curword(SCR *sp) { VI_PRIVATE *vip; size_t beg, end, len; int moved; CHAR_T *p; if (db_get(sp, sp->lno, DBG_FATAL, &p, &len)) return (1); /* * !!! * Historically, tag commands skipped over any leading whitespace * characters. Make this true in general when using cursor words. * If movement, getting a cursor word implies moving the cursor to * its beginning. Refresh now. * * !!! * Find the beginning/end of the keyword. Keywords are currently * used for cursor-word searching and for tags. Historical vi * only used the word in a tag search from the cursor to the end * of the word, i.e. if the cursor was on the 'b' in " abc ", the * tag was "bc". For consistency, we make cursor word searches * follow the same rule. */ for (moved = 0, beg = sp->cno; beg < len && ISSPACE(p[beg]); moved = 1, ++beg); if (beg >= len) { msgq(sp, M_BERR, "212|Cursor not in a word"); return (1); } if (moved) { sp->cno = beg; (void)vs_refresh(sp, 0); } /* * Find the end of the word. * * !!! * Historically, vi accepted any non-blank as initial character * when building up a tagstring. Required by IEEE 1003.1-2001. */ for (end = beg; ++end < len && inword(p[end]);); vip = VIP(sp); vip->klen = len = (end - beg); BINC_RETW(sp, vip->keyw, vip->keywlen, len+1); MEMMOVE(vip->keyw, p + beg, len); vip->keyw[len] = '\0'; /* XXX */ return (0); }
/* * txt_dent -- * Handle ^D outdents. * * Ex version of vi/v_ntext.c:txt_dent(). See that code for the (usual) * ranting and raving. This is a fair bit simpler as ^T isn't special. */ static int txt_dent(SCR *sp, TEXT *tp) { u_long sw, ts; size_t cno, off, scno, spaces, tabs; ts = O_VAL(sp, O_TABSTOP); sw = O_VAL(sp, O_SHIFTWIDTH); /* Get the current screen column. */ for (off = scno = 0; off < tp->len; ++off) if (tp->lb[off] == '\t') scno += COL_OFF(scno, ts); else ++scno; /* Get the previous shiftwidth column. */ cno = scno--; scno -= scno % sw; /* * Since we don't know what comes before the character(s) being * deleted, we have to resolve the autoindent characters . The * example is a <tab>, which doesn't take up a full shiftwidth * number of columns because it's preceded by <space>s. This is * easy to get if the user sets shiftwidth to a value less than * tabstop, and then uses ^T to indent, and ^D to outdent. * * Count up spaces/tabs needed to get to the target. */ for (cno = 0, tabs = 0; cno + COL_OFF(cno, ts) <= scno; ++tabs) cno += COL_OFF(cno, ts); spaces = scno - cno; /* Make sure there's enough room. */ BINC_RETW(sp, tp->lb, tp->lb_len, tabs + spaces + 1); /* Adjust the final ai character count. */ tp->ai = tabs + spaces; /* Enter the replacement characters. */ for (tp->len = 0; tabs > 0; --tabs) tp->lb[tp->len++] = '\t'; for (; spaces > 0; --spaces) tp->lb[tp->len++] = ' '; return (0); }
static int raw2int(SCR *sp, const char * str, ssize_t len, CONVWIN *cw, size_t *tolen, const CHAR_T **dst) { int i; CHAR_T **tostr = (CHAR_T **)(void *)&cw->bp1; size_t *blen = &cw->blen1; BINC_RETW(NULL, *tostr, *blen, len); *tolen = len; for (i = 0; i < len; ++i) (*tostr)[i] = (u_char) str[i]; *dst = cw->bp1; return 0; }
/* * ex_move -- :[line [,line]] mo[ve] line * Move selected lines. * * PUBLIC: int ex_move __P((SCR *, EXCMD *)); */ int ex_move(SCR *sp, EXCMD *cmdp) { LMARK *lmp; MARK fm1, fm2; db_recno_t cnt, diff, fl, tl, mfl, mtl; size_t blen, len; int mark_reset; CHAR_T *bp; CHAR_T *p; NEEDFILE(sp, cmdp); /* * It's not possible to move things into the area that's being * moved. */ fm1 = cmdp->addr1; fm2 = cmdp->addr2; if (cmdp->lineno >= fm1.lno && cmdp->lineno <= fm2.lno) { msgq(sp, M_ERR, "139|Destination line is inside move range"); return (1); } /* * Log the positions of any marks in the to-be-deleted lines. This * has to work with the logging code. What happens is that we log * the old mark positions, make the changes, then log the new mark * positions. Then the marks end up in the right positions no matter * which way the log is traversed. * * XXX * Reset the MARK_USERSET flag so that the log can undo the mark. * This isn't very clean, and should probably be fixed. */ fl = fm1.lno; tl = cmdp->lineno; /* Log the old positions of the marks. */ mark_reset = 0; LIST_FOREACH(lmp, &sp->ep->marks, q) if (lmp->name != ABSMARK1 && lmp->lno >= fl && lmp->lno <= tl) { mark_reset = 1; F_CLR(lmp, MARK_USERSET); (void)log_mark(sp, lmp); } /* Get memory for the copy. */ GET_SPACE_RETW(sp, bp, blen, 256); /* Move the lines. */ diff = (fm2.lno - fm1.lno) + 1; if (tl > fl) { /* Destination > source. */ mfl = tl - diff; mtl = tl; for (cnt = diff; cnt--;) { if (db_get(sp, fl, DBG_FATAL, &p, &len)) return (1); BINC_RETW(sp, bp, blen, len); MEMCPYW(bp, p, len); if (db_append(sp, 1, tl, bp, len)) return (1); if (mark_reset) LIST_FOREACH(lmp, &sp->ep->marks, q) if (lmp->name != ABSMARK1 && lmp->lno == fl) lmp->lno = tl + 1; if (db_delete(sp, fl)) return (1); } } else { /* Destination < source. */