From ecf91607ac7ab0c711480ddb1ac4bf60756891a1 Mon Sep 17 00:00:00 2001 From: Nathan Vegdahl Date: Sun, 15 Feb 2015 23:09:13 -0800 Subject: [PATCH] WIP long line support. Got index_offset_vertical_v2d() partially working. Still seems to be a tad buggy, though. --- src/formatter.rs | 59 ++++++++++++++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 22 deletions(-) diff --git a/src/formatter.rs b/src/formatter.rs index eb34050..26b7b19 100644 --- a/src/formatter.rs +++ b/src/formatter.rs @@ -44,16 +44,11 @@ pub trait LineFormatter { let line = buf.get_line(line_i); // Find the right block in the line, and the index within that block - let mut index: usize = col_i; - let mut line_block: usize = 0; - while col_i >= LINE_BLOCK_LENGTH { - line_block += 1; - index -= LINE_BLOCK_LENGTH; - } + let (line_block, col_i_adjusted) = block_index_and_offset(col_i); // Get an iter into the right block let g_iter = line.grapheme_iter_at_index(line_block * LINE_BLOCK_LENGTH); - return self.index_to_v2d(g_iter, index).1; + return self.index_to_v2d(g_iter, col_i_adjusted).1; } @@ -62,15 +57,22 @@ pub trait LineFormatter { fn index_offset_vertical_v2d(&self, buf: &Buffer, index: usize, offset: isize, rounding: (RoundingBehavior, RoundingBehavior)) -> usize { // TODO: handle rounding modes // TODO: do this with bidirectional line iterator + + // Get the line and block index of the given index let (mut line_i, mut col_i) = buf.index_to_line_col(index); - let (mut y, x) = self.index_to_v2d(buf.get_line(line_i).grapheme_iter(), col_i); + + // Find the right block in the line, and the index within that block + let (line_block, col_i_adjusted) = block_index_and_offset(col_i); + + let (mut y, x) = self.index_to_v2d(buf.get_line(line_i).grapheme_iter_at_index(line_block*LINE_BLOCK_LENGTH), col_i_adjusted); let mut new_y = y as isize + offset; // First, find the right line while keeping track of the vertical offset let mut line; + let mut block_index: usize = line_block; loop { line = buf.get_line(line_i); - let (h, _) = self.dimensions(line.grapheme_iter()); + let (h, _) = self.dimensions(line.grapheme_iter_at_index(line_block*LINE_BLOCK_LENGTH)); if new_y >= 0 && new_y < h as isize { y = new_y as usize; @@ -78,23 +80,37 @@ pub trait LineFormatter { } else { if new_y > 0 { + let last_block = block_index >= (line.grapheme_count() / LINE_BLOCK_LENGTH); + // Check for off-the-end - if (line_i + 1) >= buf.line_count() { + if last_block && (line_i + 1) >= buf.line_count() { return buf.grapheme_count(); } - line_i += 1; + if last_block { + line_i += 1; + block_index = 0; + } + else { + block_index += 1; + } new_y -= h as isize; } else if new_y < 0 { // Check for off-the-end - if line_i == 0 { + if block_index == 0 && line_i == 0 { return 0; } - line_i -= 1; - line = buf.get_line(line_i); - let (h, _) = self.dimensions(line.grapheme_iter()); + if block_index == 0 { + line_i -= 1; + line = buf.get_line(line_i); + block_index = line.grapheme_count() / LINE_BLOCK_LENGTH; + } + else { + block_index -= 1; + } + let (h, _) = self.dimensions(line.grapheme_iter_at_index(line_block*LINE_BLOCK_LENGTH)); new_y += h as isize; } else { @@ -105,7 +121,7 @@ pub trait LineFormatter { // Next, convert the resulting coordinates back into buffer-wide // coordinates. - col_i = self.v2d_to_index(line.grapheme_iter(), (y, x), rounding); + col_i = (block_index * LINE_BLOCK_LENGTH) + self.v2d_to_index(line.grapheme_iter_at_index(block_index*LINE_BLOCK_LENGTH), (y, x), rounding); return buf.line_col_to_index((line_i, col_i)); } @@ -116,12 +132,7 @@ pub trait LineFormatter { let line = buf.get_line(line_i); // Find the right block in the line, and the index within that block - let mut col_i_adjusted: usize = col_i; - let mut line_block: usize = 0; - while col_i >= LINE_BLOCK_LENGTH { - line_block += 1; - col_i_adjusted -= LINE_BLOCK_LENGTH; - } + let (line_block, col_i_adjusted) = block_index_and_offset(col_i); let start_index = line_block * LINE_BLOCK_LENGTH; // Calculate the horizontal position @@ -140,3 +151,7 @@ pub trait LineFormatter { } } + +fn block_index_and_offset(index: usize) -> (usize, usize) { + (index / LINE_BLOCK_LENGTH, index % LINE_BLOCK_LENGTH) +}