writeString method

  1. @override
void writeString(
  1. int x,
  2. int y,
  3. String text,
  4. Style style,
)
override

Writes styled text to the buffer starting at (x, y).

Newlines (\n) will wrap to y + 1 at the starting column x. Any characters that fall out of bounds are clipped.

Implementation

@override
void writeString(int x, int y, String text, Style style) {
  final startX = x;
  final chars = text.characters;
  var currentX = x;
  var currentY = y;

  for (final char in chars) {
    if (char == '\n') {
      currentX = startX;
      currentY++;
      continue;
    }
    if (currentX >= 0 &&
        currentX < bounds.width &&
        currentY >= 0 &&
        currentY < bounds.height) {
      // Clear potential wide char we are about to overwrite
      final currentChar = parent.getCharacter(
        bounds.x + currentX,
        bounds.y + currentY,
      );
      if (currentChar == '') {
        if (currentX - 1 >= 0) {
          final prevChar = parent.getCharacter(
            bounds.x + currentX - 1,
            bounds.y + currentY,
          );
          if (isWideGrapheme(prevChar)) {
            parent.setAttributes(
              bounds.x + currentX - 1,
              bounds.y + currentY,
              char: ' ',
            );
          }
        }
      } else if (isWideGrapheme(currentChar)) {
        if (currentX + 1 < bounds.width) {
          final nextChar = parent.getCharacter(
            bounds.x + currentX + 1,
            bounds.y + currentY,
          );
          if (nextChar == '') {
            parent.setAttributes(
              bounds.x + currentX + 1,
              bounds.y + currentY,
              char: ' ',
            );
          }
        }
      }

      final isWide = isWideGrapheme(char);
      if (isWide && currentX == bounds.width - 1) {
        // Can't fit wide character in the last column, write a space instead
        final currentBg = parent.getBackground(
          bounds.x + currentX,
          bounds.y + currentY,
        );
        parent.setAttributes(
          bounds.x + currentX,
          bounds.y + currentY,
          char: ' ',
          fg: style.foreground?.argb ?? 0,
          bg: style.background?.argb ?? currentBg,
          modifiers: style.modifiers,
        );
        currentX += 1;
      } else {
        final currentBg = parent.getBackground(
          bounds.x + currentX,
          bounds.y + currentY,
        );
        parent.setAttributes(
          bounds.x + currentX,
          bounds.y + currentY,
          char: char,
          fg: style.foreground?.argb ?? 0,
          bg: style.background?.argb ?? currentBg,
          modifiers: style.modifiers,
        );
        if (isWide) {
          if (currentX + 1 < bounds.width) {
            // Clear potential wide char we are overwriting in the next cell
            final nextChar = parent.getCharacter(
              bounds.x + currentX + 1,
              bounds.y + currentY,
            );
            if (isWideGrapheme(nextChar) && currentX + 2 < bounds.width) {
              final nextNextChar = parent.getCharacter(
                bounds.x + currentX + 2,
                bounds.y + currentY,
              );
              if (nextNextChar == '') {
                parent.setAttributes(
                  bounds.x + currentX + 2,
                  bounds.y + currentY,
                  char: ' ',
                );
              }
            }
            final nextBg = parent.getBackground(
              bounds.x + currentX + 1,
              bounds.y + currentY,
            );
            parent.setAttributes(
              bounds.x + currentX + 1,
              bounds.y + currentY,
              char: '',
              fg: style.foreground?.argb ?? 0,
              bg: style.background?.argb ?? nextBg,
              modifiers: style.modifiers,
            );
          }
          currentX += 2;
        } else {
          currentX += 1;
        }
      }
    } else {
      currentX += 1;
    }
  }
}