/* vi:set ts=8 sts=4 sw=4: * * VIM - Vi IMproved by Bram Moolenaar * * Do ":help uganda" in Vim to read copying and usage conditions. * Do ":help credits" in Vim to see a list of people who contributed. * See README.txt for an overview of the Vim source code. */ /* * misc2.c: Various functions. */#include "vim.h" #ifdef HAVE_FCNTL_H# include <fcntl.h> /* for chdir() */#endif static char_u *username = NULL; /* cached result of mch_get_user_name() */ static char_u *ff_expand_buffer = NULL; /* used for expanding filenames */ #if defined(FEAT_VIRTUALEDIT) || defined(PROTO)static int coladvance2 __ARGS((pos_T *pos, int addspaces, int finetune, colnr_T wcol)); /* * Return TRUE if in the current mode we need to use virtual. */ intvirtual_active(){ /* While an operator is being executed we return "virtual_op", because * VIsual_active has already been reset, thus we can't check for "block" * being used. */ if (virtual_op != MAYBE) return virtual_op; return (ve_flags == VE_ALL# ifdef FEAT_VISUAL || ((ve_flags & VE_BLOCK) && VIsual_active && VIsual_mode == Ctrl_V)# endif || ((ve_flags & VE_INSERT) && (State & INSERT)));} /* * Get the screen position of the cursor. */ intgetviscol(){ colnr_T x; getvvcol(curwin, &curwin->w_cursor, &x, NULL, NULL); return (int)x;} /* * Get the screen position of character col with a coladd in the cursor line. */ intgetviscol2(col, coladd) colnr_T col; colnr_T coladd;{ colnr_T x; pos_T pos; pos.lnum = curwin->w_cursor.lnum; pos.col = col; pos.coladd = coladd; getvvcol(curwin, &pos, &x, NULL, NULL); return (int)x;} /* * Go to column "wcol", and add/insert white space as necessary to get the * cursor in that column. * The caller must have saved the cursor line for undo! */ intcoladvance_force(wcol) colnr_T wcol;{ int rc = coladvance2(&curwin->w_cursor, TRUE, FALSE, wcol); if (wcol == MAXCOL) curwin->w_valid &= ~VALID_VIRTCOL; else { /* Virtcol is valid */ curwin->w_valid |= VALID_VIRTCOL; curwin->w_virtcol = wcol; } return rc;}#endif /* * Try to advance the Cursor to the specified screen column. * If virtual editing: fine tune the cursor position. * Note that all virtual positions off the end of a line should share * a curwin->w_cursor.col value (n.b. this is equal to STRLEN(line)), * beginning at coladd 0. * * return OK if desired column is reached, FAIL if not */ intcoladvance(wcol) colnr_T wcol;{ int rc = getvpos(&curwin->w_cursor, wcol); if (wcol == MAXCOL || rc == FAIL) curwin->w_valid &= ~VALID_VIRTCOL; else if (*ml_get_cursor() != TAB) { /* Virtcol is valid when not on a TAB */ curwin->w_valid |= VALID_VIRTCOL; curwin->w_virtcol = wcol; } return rc;} /* * Return in "pos" the position of the cursor advanced to screen column "wcol". * return OK if desired column is reached, FAIL if not */ intgetvpos(pos, wcol) pos_T *pos; colnr_T wcol;{#ifdef FEAT_VIRTUALEDIT return coladvance2(pos, FALSE, virtual_active(), wcol);} static intcoladvance2(pos, addspaces, finetune, wcol) pos_T *pos; int addspaces; /* change the text to achieve our goal? */ int finetune; /* change char offset for the exact column */ colnr_T wcol; /* column to move to */{#endif int idx; char_u *ptr; char_u *line; colnr_T col = 0; int csize = 0; int one_more;#ifdef FEAT_LINEBREAK int head = 0;#endif one_more = (State & INSERT) || restart_edit != NUL#ifdef FEAT_VISUAL || (VIsual_active && *p_sel != 'o')#endif#ifdef FEAT_VIRTUALEDIT || ((ve_flags & VE_ONEMORE) && wcol < MAXCOL)#endif ; line = ml_get_curline(); if (wcol >= MAXCOL) { idx = (int)STRLEN(line) - 1 + one_more; col = wcol; #ifdef FEAT_VIRTUALEDIT if ((addspaces || finetune) && !VIsual_active) { curwin->w_curswant = linetabsize(line) + one_more; if (curwin->w_curswant > 0) --curwin->w_curswant; }#endif } else {#ifdef FEAT_VIRTUALEDIT int width = W_WIDTH(curwin) - win_col_off(curwin); if (finetune && curwin->w_p_wrap# ifdef FEAT_VERTSPLIT && curwin->w_width != 0# endif && wcol >= (colnr_T)width) { csize = linetabsize(line); if (csize > 0) csize--; if (wcol / width > (colnr_T)csize / width && ((State & INSERT) == 0 || (int)wcol > csize + 1)) { /* In case of line wrapping don't move the cursor beyond the * right screen edge. In Insert mode allow going just beyond * the last character (like what happens when typing and * reaching the right window edge). */ wcol = (csize / width + 1) * width - 1; } }#endif idx = -1; ptr = line; while (col <= wcol && *ptr != NUL) { /* Count a tab for what it's worth (if list mode not on) */#ifdef FEAT_LINEBREAK csize = win_lbr_chartabsize(curwin, ptr, col, &head); mb_ptr_adv(ptr);#else csize = lbr_chartabsize_adv(&ptr, col);#endif col += csize; } idx = (int)(ptr - line); /* * Handle all the special cases. The virtual_active() check * is needed to ensure that a virtual position off the end of * a line has the correct indexing. The one_more comparison * replaces an explicit add of one_more later on. */ if (col > wcol || (!virtual_active() && one_more == 0)) { idx -= 1;# ifdef FEAT_LINEBREAK /* Don't count the chars from 'showbreak'. */ csize -= head;# endif col -= csize; } #ifdef FEAT_VIRTUALEDIT if (virtual_active() && addspaces && ((col != wcol && col != wcol + 1) || csize > 1)) { /* 'virtualedit' is set: The difference between wcol and col is * filled with spaces. */ if (line[idx] == NUL) { /* Append spaces */ int correct = wcol - col; char_u *newline = alloc(idx + correct + 1); int t; if (newline == NULL) return FAIL; for (t = 0; t < idx; ++t) newline[t] = line[t]; for (t = 0; t < correct; ++t) newline[t + idx] = ' '; newline[idx + correct] = NUL; ml_replace(pos->lnum, newline, FALSE); changed_bytes(pos->lnum, (colnr_T)idx); idx += correct; col = wcol; } else { /* Break a tab */ int linelen = (int)STRLEN(line); int correct = wcol - col - csize + 1; /* negative!! */ char_u *newline; int t, s = 0; int v; if (-correct > csize) return FAIL; newline = alloc(linelen + csize); if (newline == NULL) return FAIL; for (t = 0; t < linelen; t++) { if (t != idx) newline[s++] = line[t]; else for (v = 0; v < csize; v++) newline[s++] = ' '; } newline[linelen + csize - 1] = NUL; ml_replace(pos->lnum, newline, FALSE); changed_bytes(pos->lnum, idx); idx += (csize - 1 + correct); col += correct; } }#endif } if (idx < 0) pos->col = 0; else pos->col = idx; #ifdef FEAT_VIRTUALEDIT pos->coladd = 0; if (finetune) { if (wcol == MAXCOL) { /* The width of the last character is used to set coladd. */ if (!one_more) { colnr_T scol, ecol; getvcol(curwin, pos, &scol, NULL, &ecol); pos->coladd = ecol - scol; } } else { int b = (int)wcol - (int)col; /* The difference between wcol and col is used to set coladd. */ if (b > 0 && b < (MAXCOL - 2 * W_WIDTH(curwin))) pos->coladd = b; col += b; } }#endif #ifdef FEAT_MBYTE /* prevent cursor from moving on the trail byte */ if (has_mbyte) mb_adjust_cursor();#endif if (col < wcol) return FAIL; return OK;} /* * inc(p) * * Increment the line pointer 'p' crossing line boundaries as necessary. * Return 1 when going to the next line. * Return 2 when moving forward onto a NUL at the end of the line). * Return -1 when at the end of file. * Return 0 otherwise. */ intinc_cursor(){ return inc(&curwin->w_cursor);} intinc(lp) pos_T *lp;{ char_u *p = ml_get_pos(lp); if (*p != NUL) /* still within line, move to next char (may be NUL) */ {#ifdef FEAT_MBYTE if (has_mbyte) { int l = (*mb_ptr2len)(p); lp->col += l; return ((p[l] != NUL) ? 0 : 2); }#endif lp->col++;#ifdef FEAT_VIRTUALEDIT lp->coladd = 0;#endif return ((p[1] != NUL) ? 0 : 2); } if (lp->lnum != curbuf->b_ml.ml_line_count) /* there is a next line */ { lp->col = 0; lp->lnum++;#ifdef FEAT_VIRTUALEDIT lp->coladd = 0;#endif return 1; } return -1;} /* * incl(lp): same as inc(), but skip the NUL at the end of non-empty lines */ intincl(lp) pos_T *lp;{ int r; if ((r = inc(lp)) >= 1 && lp->col) r = inc(lp); return r;} /* * dec(p) * * Decrement the line pointer 'p' crossing line boundaries as necessary. * Return 1 when crossing a line, -1 when at start of file, 0 otherwise. */ intdec_cursor(){ return dec(&curwin->w_cursor);} intdec(lp) pos_T *lp;{ char_u *p; #ifdef FEAT_VIRTUALEDIT lp->coladd = 0;#endif if (lp->col > 0) /* still within line */ { lp->col--;#ifdef FEAT_MBYTE if (has_mbyte) { p = ml_get(lp->lnum); lp->col -= (*mb_head_off)(p, p + lp->col); }#endif return 0; } if (lp->lnum > 1) /* there is a prior line */ { lp->lnum--; p = ml_get(lp->lnum); lp->col = (colnr_T)STRLEN(p);#ifdef FEAT_MBYTE if (has_mbyte) lp->col -= (*mb_head_off)(p, p + lp->col);#endif return 1; } return -1; /* at start of file */} /* * decl(lp): same as dec(), but skip the NUL at the end of non-empty lines */ intdecl(lp) pos_T *lp;{ int r; if ((r = dec(lp)) == 1 && lp->col) r = dec(lp); return r;} /* * Make sure curwin->w_cursor.lnum is valid. */ voidcheck_cursor_lnum(){ if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count) {#ifdef FEAT_FOLDING /* If there is a closed fold at the end of the file, put the cursor in * its first line. Otherwise in the last line. */ if (!hasFolding(curbuf->b_ml.ml_line_count, &curwin->w_cursor.lnum, NULL))#endif curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count; } if (curwin->w_cursor.lnum <= 0) curwin->w_cursor.lnum = 1;} /* * Make sure curwin->w_cursor.col is valid. */ voidcheck_cursor_col(){ colnr_T len;Lines 1–500 of 5948. Load more
/* vi:set ts=8 sts=4 sw=4: * * VIM - Vi IMproved by Bram Moolenaar * * Do ":help uganda" in Vim to read copying and usage conditions. * Do ":help credits" in Vim to see a list of people who contributed. * See README.txt for an overview of the Vim source code. */ /* * misc2.c: Various functions. */ #include "vim.h" #ifdef HAVE_FCNTL_H # include <fcntl.h> /* for chdir() */ #endif static char_u *username = NULL; /* cached result of mch_get_user_name() */ static char_u *ff_expand_buffer = NULL; /* used for expanding filenames */ #if defined(FEAT_VIRTUALEDIT) || defined(PROTO) static int coladvance2 __ARGS((pos_T *pos, int addspaces, int finetune, colnr_T wcol)); /* * Return TRUE if in the current mode we need to use virtual. */ int virtual_active() { /* While an operator is being executed we return "virtual_op", because * VIsual_active has already been reset, thus we can't check for "block" * being used. */ if (virtual_op != MAYBE) return virtual_op; return (ve_flags == VE_ALL # ifdef FEAT_VISUAL || ((ve_flags & VE_BLOCK) && VIsual_active && VIsual_mode == Ctrl_V) # endif || ((ve_flags & VE_INSERT) && (State & INSERT))); } /* * Get the screen position of the cursor. */ int getviscol() { colnr_T x; getvvcol(curwin, &curwin->w_cursor, &x, NULL, NULL); return (int)x; } /* * Get the screen position of character col with a coladd in the cursor line. */ int getviscol2(col, coladd) colnr_T col; colnr_T coladd; { colnr_T x; pos_T pos; pos.lnum = curwin->w_cursor.lnum; pos.col = col; pos.coladd = coladd; getvvcol(curwin, &pos, &x, NULL, NULL); return (int)x; } /* * Go to column "wcol", and add/insert white space as necessary to get the * cursor in that column. * The caller must have saved the cursor line for undo! */ int coladvance_force(wcol) colnr_T wcol; { int rc = coladvance2(&curwin->w_cursor, TRUE, FALSE, wcol); if (wcol == MAXCOL) curwin->w_valid &= ~VALID_VIRTCOL; else { /* Virtcol is valid */ curwin->w_valid |= VALID_VIRTCOL; curwin->w_virtcol = wcol; } return rc; } #endif /* * Try to advance the Cursor to the specified screen column. * If virtual editing: fine tune the cursor position. * Note that all virtual positions off the end of a line should share * a curwin->w_cursor.col value (n.b. this is equal to STRLEN(line)), * beginning at coladd 0. * * return OK if desired column is reached, FAIL if not */ int coladvance(wcol) colnr_T wcol; { int rc = getvpos(&curwin->w_cursor, wcol); if (wcol == MAXCOL || rc == FAIL) curwin->w_valid &= ~VALID_VIRTCOL; else if (*ml_get_cursor() != TAB) { /* Virtcol is valid when not on a TAB */ curwin->w_valid |= VALID_VIRTCOL; curwin->w_virtcol = wcol; } return rc; } /* * Return in "pos" the position of the cursor advanced to screen column "wcol". * return OK if desired column is reached, FAIL if not */ int getvpos(pos, wcol) pos_T *pos; colnr_T wcol; { #ifdef FEAT_VIRTUALEDIT return coladvance2(pos, FALSE, virtual_active(), wcol); } static int coladvance2(pos, addspaces, finetune, wcol) pos_T *pos; int addspaces; /* change the text to achieve our goal? */ int finetune; /* change char offset for the exact column */ colnr_T wcol; /* column to move to */ { #endif int idx; char_u *ptr; char_u *line; colnr_T col = 0; int csize = 0; int one_more; #ifdef FEAT_LINEBREAK int head = 0; #endif one_more = (State & INSERT) || restart_edit != NUL #ifdef FEAT_VISUAL || (VIsual_active && *p_sel != 'o') #endif #ifdef FEAT_VIRTUALEDIT || ((ve_flags & VE_ONEMORE) && wcol < MAXCOL) #endif ; line = ml_get_curline(); if (wcol >= MAXCOL) { idx = (int)STRLEN(line) - 1 + one_more; col = wcol; #ifdef FEAT_VIRTUALEDIT if ((addspaces || finetune) && !VIsual_active) { curwin->w_curswant = linetabsize(line) + one_more; if (curwin->w_curswant > 0) --curwin->w_curswant; } #endif } else { #ifdef FEAT_VIRTUALEDIT int width = W_WIDTH(curwin) - win_col_off(curwin); if (finetune && curwin->w_p_wrap # ifdef FEAT_VERTSPLIT && curwin->w_width != 0 # endif && wcol >= (colnr_T)width) { csize = linetabsize(line); if (csize > 0) csize--; if (wcol / width > (colnr_T)csize / width && ((State & INSERT) == 0 || (int)wcol > csize + 1)) { /* In case of line wrapping don't move the cursor beyond the * right screen edge. In Insert mode allow going just beyond * the last character (like what happens when typing and * reaching the right window edge). */ wcol = (csize / width + 1) * width - 1; } } #endif idx = -1; ptr = line; while (col <= wcol && *ptr != NUL) { /* Count a tab for what it's worth (if list mode not on) */ #ifdef FEAT_LINEBREAK csize = win_lbr_chartabsize(curwin, ptr, col, &head); mb_ptr_adv(ptr); #else csize = lbr_chartabsize_adv(&ptr, col); #endif col += csize; } idx = (int)(ptr - line); /* * Handle all the special cases. The virtual_active() check * is needed to ensure that a virtual position off the end of * a line has the correct indexing. The one_more comparison * replaces an explicit add of one_more later on. */ if (col > wcol || (!virtual_active() && one_more == 0)) { idx -= 1; # ifdef FEAT_LINEBREAK /* Don't count the chars from 'showbreak'. */ csize -= head; # endif col -= csize; } #ifdef FEAT_VIRTUALEDIT if (virtual_active() && addspaces && ((col != wcol && col != wcol + 1) || csize > 1)) { /* 'virtualedit' is set: The difference between wcol and col is * filled with spaces. */ if (line[idx] == NUL) { /* Append spaces */ int correct = wcol - col; char_u *newline = alloc(idx + correct + 1); int t; if (newline == NULL) return FAIL; for (t = 0; t < idx; ++t) newline[t] = line[t]; for (t = 0; t < correct; ++t) newline[t + idx] = ' '; newline[idx + correct] = NUL; ml_replace(pos->lnum, newline, FALSE); changed_bytes(pos->lnum, (colnr_T)idx); idx += correct; col = wcol; } else { /* Break a tab */ int linelen = (int)STRLEN(line); int correct = wcol - col - csize + 1; /* negative!! */ char_u *newline; int t, s = 0; int v; if (-correct > csize) return FAIL; newline = alloc(linelen + csize); if (newline == NULL) return FAIL; for (t = 0; t < linelen; t++) { if (t != idx) newline[s++] = line[t]; else for (v = 0; v < csize; v++) newline[s++] = ' '; } newline[linelen + csize - 1] = NUL; ml_replace(pos->lnum, newline, FALSE); changed_bytes(pos->lnum, idx); idx += (csize - 1 + correct); col += correct; } } #endif } if (idx < 0) pos->col = 0; else pos->col = idx; #ifdef FEAT_VIRTUALEDIT pos->coladd = 0; if (finetune) { if (wcol == MAXCOL) { /* The width of the last character is used to set coladd. */ if (!one_more) { colnr_T scol, ecol; getvcol(curwin, pos, &scol, NULL, &ecol); pos->coladd = ecol - scol; } } else { int b = (int)wcol - (int)col; /* The difference between wcol and col is used to set coladd. */ if (b > 0 && b < (MAXCOL - 2 * W_WIDTH(curwin))) pos->coladd = b; col += b; } } #endif #ifdef FEAT_MBYTE /* prevent cursor from moving on the trail byte */ if (has_mbyte) mb_adjust_cursor(); #endif if (col < wcol) return FAIL; return OK; } /* * inc(p) * * Increment the line pointer 'p' crossing line boundaries as necessary. * Return 1 when going to the next line. * Return 2 when moving forward onto a NUL at the end of the line). * Return -1 when at the end of file. * Return 0 otherwise. */ int inc_cursor() { return inc(&curwin->w_cursor); } int inc(lp) pos_T *lp; { char_u *p = ml_get_pos(lp); if (*p != NUL) /* still within line, move to next char (may be NUL) */ { #ifdef FEAT_MBYTE if (has_mbyte) { int l = (*mb_ptr2len)(p); lp->col += l; return ((p[l] != NUL) ? 0 : 2); } #endif lp->col++; #ifdef FEAT_VIRTUALEDIT lp->coladd = 0; #endif return ((p[1] != NUL) ? 0 : 2); } if (lp->lnum != curbuf->b_ml.ml_line_count) /* there is a next line */ { lp->col = 0; lp->lnum++; #ifdef FEAT_VIRTUALEDIT lp->coladd = 0; #endif return 1; } return -1; } /* * incl(lp): same as inc(), but skip the NUL at the end of non-empty lines */ int incl(lp) pos_T *lp; { int r; if ((r = inc(lp)) >= 1 && lp->col) r = inc(lp); return r; } /* * dec(p) * * Decrement the line pointer 'p' crossing line boundaries as necessary. * Return 1 when crossing a line, -1 when at start of file, 0 otherwise. */ int dec_cursor() { return dec(&curwin->w_cursor); } int dec(lp) pos_T *lp; { char_u *p; #ifdef FEAT_VIRTUALEDIT lp->coladd = 0; #endif if (lp->col > 0) /* still within line */ { lp->col--; #ifdef FEAT_MBYTE if (has_mbyte) { p = ml_get(lp->lnum); lp->col -= (*mb_head_off)(p, p + lp->col); } #endif return 0; } if (lp->lnum > 1) /* there is a prior line */ { lp->lnum--; p = ml_get(lp->lnum); lp->col = (colnr_T)STRLEN(p); #ifdef FEAT_MBYTE if (has_mbyte) lp->col -= (*mb_head_off)(p, p + lp->col); #endif return 1; } return -1; /* at start of file */ } /* * decl(lp): same as dec(), but skip the NUL at the end of non-empty lines */ int decl(lp) pos_T *lp; { int r; if ((r = dec(lp)) == 1 && lp->col) r = dec(lp); return r; } /* * Make sure curwin->w_cursor.lnum is valid. */ void check_cursor_lnum() { if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count) { #ifdef FEAT_FOLDING /* If there is a closed fold at the end of the file, put the cursor in * its first line. Otherwise in the last line. */ if (!hasFolding(curbuf->b_ml.ml_line_count, &curwin->w_cursor.lnum, NULL)) #endif curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count; } if (curwin->w_cursor.lnum <= 0) curwin->w_cursor.lnum = 1; } /* * Make sure curwin->w_cursor.col is valid. */ void check_cursor_col() { colnr_T len;