Exemplo n.º 1
0
///
/// Return length of line "lnum" for horizontal scrolling.
///
static colnr_T scroll_line_len(linenr_T lnum)
{
  colnr_T col = 0;
  char_u *line = ml_get(lnum);
  if (*line != NUL) {
    for (;;) {
      int numchar = chartabsize(line, col);
      mb_ptr_adv(line);
      if (*line == NUL) {    // don't count the last character
        break;
      }
      col += numchar;
    }
  }
  return col;
}
Exemplo n.º 2
0
/// Adjusts the clicked column position when 'conceallevel' > 0
static int mouse_adjust_click(win_T *wp, int row, int col)
{
  if (!(wp->w_p_cole > 0 && curbuf->b_p_smc > 0
        && wp->w_leftcol < curbuf->b_p_smc && conceal_cursor_line(wp))) {
    return col;
  }

  // `col` is the position within the current line that is highlighted by the
  // cursor without consideration for concealed characters.  The current line is
  // scanned *up to* `col`, nudging it left or right when concealed characters
  // are encountered.
  //
  // chartabsize() is used to keep track of the virtual column position relative
  // to the line's bytes.  For example: if col == 9 and the line starts with a
  // tab that's 8 columns wide, we would want the cursor to be highlighting the
  // second byte, not the ninth.

  linenr_T lnum = wp->w_cursor.lnum;
  char_u *line = ml_get(lnum);
  char_u *ptr = line;
  char_u *ptr_end = line;
  char_u *ptr_row_offset = line;  // Where we begin adjusting `ptr_end`

  // Find the offset where scanning should begin.
  int offset = wp->w_leftcol;
  if (row > 0) {
    offset += row * (wp->w_width - win_col_off(wp) - win_col_off2(wp) -
                     wp->w_leftcol + wp->w_skipcol);
  }

  int vcol;

  if (offset) {
    // Skip everything up to an offset since nvim takes care of displaying the
    // correct portion of the line when horizontally scrolling.
    // When 'wrap' is enabled, only the row (of the wrapped line) needs to be
    // checked for concealed characters.
    vcol = 0;
    while (vcol < offset && *ptr != NUL) {
      vcol += chartabsize(ptr, vcol);
      ptr += utfc_ptr2len(ptr);
    }

    ptr_row_offset = ptr;
  }

  // Align `ptr_end` with `col`
  vcol = offset;
  ptr_end = ptr_row_offset;
  while (vcol < col && *ptr_end != NUL) {
    vcol += chartabsize(ptr_end, vcol);
    ptr_end += utfc_ptr2len(ptr_end);
  }

  int matchid;
  int prev_matchid;
  int nudge = 0;
  int cwidth = 0;

  vcol = offset;

#define incr() nudge++; ptr_end += utfc_ptr2len(ptr_end)
#define decr() nudge--; ptr_end -= utfc_ptr2len(ptr_end)

  while (ptr < ptr_end && *ptr != NUL) {
    cwidth = chartabsize(ptr, vcol);
    vcol += cwidth;
    if (cwidth > 1 && *ptr == '\t' && nudge > 0) {
      // A tab will "absorb" any previous adjustments.
      cwidth = MIN(cwidth, nudge);
      while (cwidth > 0) {
        decr();
        cwidth--;
      }
    }

    matchid = syn_get_concealed_id(wp, lnum, (colnr_T)(ptr - line));
    if (matchid != 0) {
      if (wp->w_p_cole == 3) {
        incr();
      } else {
        if (!(row > 0 && ptr == ptr_row_offset)
            && (wp->w_p_cole == 1 || (wp->w_p_cole == 2
                                      && (lcs_conceal != NUL
                                          || syn_get_sub_char() != NUL)))) {
          // At least one placeholder character will be displayed.
          decr();
        }

        prev_matchid = matchid;

        while (prev_matchid == matchid && *ptr != NUL) {
          incr();
          ptr += utfc_ptr2len(ptr);
          matchid = syn_get_concealed_id(wp, lnum, (colnr_T)(ptr - line));
        }

        continue;
      }
    }

    ptr += utfc_ptr2len(ptr);
  }

  return col + nudge;
}