/// /// Do a horizontal scroll. Return TRUE if the cursor moved, FALSE otherwise. /// bool mouse_scroll_horiz(int dir) { if (curwin->w_p_wrap) { return false; } int step = 6; if (mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL)) { step = curwin->w_width; } int leftcol = curwin->w_leftcol + (dir == MSCR_RIGHT ? -step : +step); if (leftcol < 0) { leftcol = 0; } if (curwin->w_leftcol == leftcol) { return false; } curwin->w_leftcol = (colnr_T)leftcol; // When the line of the cursor is too short, move the cursor to the // longest visible line. if (!virtual_active() && (colnr_T)leftcol > scroll_line_len(curwin->w_cursor.lnum)) { curwin->w_cursor.lnum = find_longest_lnum(); curwin->w_cursor.col = 0; } return leftcol_changed(); }
/// Make sure win->w_cursor.col is valid. Special handling of insert-mode. /// @see mb_check_adjust_col void check_cursor_col_win(win_T *win) { colnr_T len; colnr_T oldcol = win->w_cursor.col; colnr_T oldcoladd = win->w_cursor.col + win->w_cursor.coladd; len = (colnr_T)STRLEN(ml_get_buf(win->w_buffer, win->w_cursor.lnum, false)); if (len == 0) { win->w_cursor.col = 0; } else if (win->w_cursor.col >= len) { /* Allow cursor past end-of-line when: * - in Insert mode or restarting Insert mode * - in Visual mode and 'selection' isn't "old" * - 'virtualedit' is set */ if ((State & INSERT) || restart_edit || (VIsual_active && *p_sel != 'o') || (ve_flags & VE_ONEMORE) || virtual_active()) { win->w_cursor.col = len; } else { win->w_cursor.col = len - 1; // Move the cursor to the head byte. if (has_mbyte) { mark_mb_adjustpos(win->w_buffer, &win->w_cursor); } } } else if (win->w_cursor.col < 0) { win->w_cursor.col = 0; } // If virtual editing is on, we can leave the cursor on the old position, // only we must set it to virtual. But don't do it when at the end of the // line. if (oldcol == MAXCOL) { win->w_cursor.coladd = 0; } else if (ve_flags == VE_ALL) { if (oldcoladd > win->w_cursor.col) { win->w_cursor.coladd = oldcoladd - win->w_cursor.col; // Make sure that coladd is not more than the char width. // Not for the last character, coladd is then used when the cursor // is actually after the last character. if (win->w_cursor.col + 1 < len && win->w_cursor.coladd > 0) { int cs, ce; getvcol(win, &win->w_cursor, &cs, NULL, &ce); if (win->w_cursor.coladd > ce - cs) { win->w_cursor.coladd = ce - cs; } } } else { // avoid weird number when there is a miscalculation or overflow win->w_cursor.coladd = 0; } } }
/* * Make sure win->w_cursor.col is valid. */ void check_cursor_col_win(win_T *win) { colnr_T len; colnr_T oldcol = win->w_cursor.col; colnr_T oldcoladd = win->w_cursor.col + win->w_cursor.coladd; len = (colnr_T)STRLEN(ml_get_buf(win->w_buffer, win->w_cursor.lnum, false)); if (len == 0) { win->w_cursor.col = 0; } else if (win->w_cursor.col >= len) { /* Allow cursor past end-of-line when: * - in Insert mode or restarting Insert mode * - in Visual mode and 'selection' isn't "old" * - 'virtualedit' is set */ if ((State & INSERT) || restart_edit || (VIsual_active && *p_sel != 'o') || (ve_flags & VE_ONEMORE) || virtual_active()) { win->w_cursor.col = len; } else { win->w_cursor.col = len - 1; /* Move the cursor to the head byte. */ if (has_mbyte) mb_adjustpos(win->w_buffer, &win->w_cursor); } } else if (win->w_cursor.col < 0) { win->w_cursor.col = 0; } /* If virtual editing is on, we can leave the cursor on the old position, * only we must set it to virtual. But don't do it when at the end of the * line. */ if (oldcol == MAXCOL) win->w_cursor.coladd = 0; else if (ve_flags == VE_ALL) { if (oldcoladd > win->w_cursor.col) win->w_cursor.coladd = oldcoladd - win->w_cursor.col; else /* avoid weird number when there is a miscalculation or overflow */ win->w_cursor.coladd = 0; } }
static int coladvance2( pos_T *pos, bool addspaces, /* change the text to achieve our goal? */ bool finetune, /* change char offset for the exact column */ colnr_T wcol /* column to move to */ ) { int idx; char_u *ptr; char_u *line; colnr_T col = 0; int csize = 0; int one_more; int head = 0; one_more = (State & INSERT) || restart_edit != NUL || (VIsual_active && *p_sel != 'o') || ((ve_flags & VE_ONEMORE) && wcol < MAXCOL); line = ml_get_buf(curbuf, pos->lnum, false); if (wcol >= MAXCOL) { idx = (int)STRLEN(line) - 1 + one_more; col = wcol; if ((addspaces || finetune) && !VIsual_active) { curwin->w_curswant = linetabsize(line) + one_more; if (curwin->w_curswant > 0) --curwin->w_curswant; } } else { int width = curwin->w_width - win_col_off(curwin); if (finetune && curwin->w_p_wrap && curwin->w_width != 0 && 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; } } ptr = line; while (col <= wcol && *ptr != NUL) { /* Count a tab for what it's worth (if list mode not on) */ csize = win_lbr_chartabsize(curwin, line, ptr, col, &head); MB_PTR_ADV(ptr); 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; /* Don't count the chars from 'showbreak'. */ csize -= head; col -= csize; } 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 = xmallocz((size_t)(idx + correct)); memcpy(newline, line, (size_t)idx); memset(newline + idx, ' ', (size_t)correct); 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; if (-correct > csize) return FAIL; newline = xmallocz((size_t)(linelen - 1 + csize)); // Copy first idx chars memcpy(newline, line, (size_t)idx); // Replace idx'th char with csize spaces memset(newline + idx, ' ', (size_t)csize); // Copy the rest of the line memcpy(newline + idx + csize, line + idx + 1, (size_t)(linelen - idx - 1)); ml_replace(pos->lnum, newline, false); changed_bytes(pos->lnum, idx); idx += (csize - 1 + correct); col += correct; } } } if (idx < 0) pos->col = 0; else pos->col = idx; 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 * curwin->w_width)) pos->coladd = b; col += b; } } // Prevent from moving onto a trail byte. if (has_mbyte) { mark_mb_adjustpos(curbuf, pos); } if (col < wcol) return FAIL; return OK; }
/* * 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_T *pos, colnr_T wcol) { return coladvance2(pos, false, virtual_active(), wcol); }