use std::collections::HashMap;
use crate::app::App;
use crate::text_width::visual_col_of;
use super::SCROLL_OFF;
use super::diagnostics::RowDiag;
pub(super) fn compute_scroll(
app: &App,
height: usize,
row_diag: &HashMap<usize, RowDiag>,
) -> usize {
let cur = app.editor.cursor.row;
let mut scroll = app.active_doc().scroll.get();
if app.active_doc().pending_center.replace(false) && height > 0 {
let last = app.active_doc().lines.len().saturating_sub(1);
let max_scroll = last.saturating_sub(height.saturating_sub(1));
scroll = cur.saturating_sub(height / 2).min(max_scroll);
app.active_doc().scroll.set(scroll);
app.active_doc().viewport_height.set(height);
return scroll;
}
let off = if height > 2 * SCROLL_OFF + 1 {
SCROLL_OFF
} else {
0
};
if cur < scroll + off {
scroll = cur.saturating_sub(off);
} else if height > 0 {
let effective_height = height.saturating_sub(off);
loop {
if scroll >= cur {
break;
}
let mut consumed: usize = 0;
for row in scroll..cur {
consumed += 1 + row_diag.get(&row).map_or(0, |_| 1);
if consumed >= effective_height {
break;
}
}
if consumed < effective_height {
break;
}
scroll += 1;
}
}
let last_row = app.active_doc().lines.len().saturating_sub(1);
scroll = scroll.min(last_row);
app.active_doc().scroll.set(scroll);
app.active_doc().viewport_height.set(height);
scroll
}
pub(super) fn compute_col_scroll(app: &App, width: usize, tab_width: usize) -> usize {
if width == 0 {
app.active_doc().col_scroll.set(0);
return 0;
}
let line = &app.active_doc().lines[app.editor.cursor.row];
let visual_col = visual_col_of(line, app.editor.cursor.col, tab_width);
let mut col_scroll = app.active_doc().col_scroll.get();
if visual_col < col_scroll {
col_scroll = visual_col;
} else if visual_col >= col_scroll + width {
col_scroll = visual_col + 1 - width;
}
app.active_doc().col_scroll.set(col_scroll);
col_scroll
}