import {
CellWidth,
cellAtIndex,
type Screen,
type StylePool,
setCellStyleId,
} from './screen.js';
export function applySearchHighlight(
screen: Screen,
query: string,
stylePool: StylePool,
): boolean {
if (!query) return false;
const needle = query.toLowerCase();
const needleLen = needle.length;
const width = screen.width;
const height = screen.height;
const { noSelect } = screen;
let highlighted = false;
for (let row = 0; row < height; row++) {
const rowOffset = row * width;
let lowerText = '';
const colByCellIndex: number[] = [];
const codeUnitToCell: number[] = [];
for (let col = 0; col < width; col++) {
const idx = rowOffset + col;
const cell = cellAtIndex(screen, idx);
if (
cell.width === CellWidth.SpacerTail ||
cell.width === CellWidth.SpacerHead ||
noSelect[idx] === 1
) {
continue;
}
const lower = cell.char.toLowerCase();
const cellIndex = colByCellIndex.length;
for (let i = 0; i < lower.length; i++) {
codeUnitToCell.push(cellIndex);
}
lowerText += lower;
colByCellIndex.push(col);
}
let pos = lowerText.indexOf(needle);
while (pos >= 0) {
highlighted = true;
const startCell = codeUnitToCell[pos]!;
const endCell = codeUnitToCell[pos + needleLen - 1]!;
for (let cellIdx = startCell; cellIdx <= endCell; cellIdx++) {
const col = colByCellIndex[cellIdx]!;
const cell = cellAtIndex(screen, rowOffset + col);
setCellStyleId(screen, col, row, stylePool.withInverse(cell.styleId));
}
pos = lowerText.indexOf(needle, pos + needleLen);
}
}
return highlighted;
}