Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/api.txt
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ package org.connectbot.terminal {
method @InaccessibleFromKotlin public boolean getBoldAsBright();
method @InaccessibleFromKotlin public org.connectbot.terminal.TerminalDimensions getDimensions();
method public String? getLastCommandOutput();
method public java.util.List<java.lang.String> getSnapshotLineTexts();
method public java.util.List<org.connectbot.terminal.TerminalUrl> getUrls(optional org.connectbot.terminal.UrlScanScope scope);
method public void resize(int newRows, int newCols);
method public int setAnsiPalette(int[] ansiColors);
Expand Down
11 changes: 11 additions & 0 deletions lib/src/main/java/org/connectbot/terminal/TerminalEmulator.kt
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,15 @@ sealed interface TerminalEmulator {
* While the alternate screen is active, primary scrollback is not scanned.
*/
fun getUrls(scope: UrlScanScope = UrlScanScope.CurrentView): List<TerminalUrl>

/**
* Plain-text lines of the current terminal snapshot. Public accessor
* so consumers outside this module (notably Haven's SelectionToolbar
* for smart copy and word expansion) can read line text without
* reflecting into the internal `snapshot` StateFlow. Returns a fresh
* list at call time.
*/
fun getSnapshotLineTexts(): List<String>
}

class TerminalEmulatorFactory {
Expand Down Expand Up @@ -322,6 +331,8 @@ internal class TerminalEmulatorImpl(
)
internal val snapshot: StateFlow<TerminalSnapshot> = _snapshot.asStateFlow()

override fun getSnapshotLineTexts(): List<String> = _snapshot.value.lines.map { it.text }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This exposes raw TerminalLine.text, so untouched/placeholder rows can leak '\u0000' characters because TerminalLine.empty() initializes cells with NUL. That makes the new public “plain-text lines” API return strings that are not really plain text.

Two reasonable fixes:

  1. Sanitize only this accessor:
    _snapshot.value.lines.map { it.text.replace('\u0000', ' ') }

  2. Fix the source invariant in TerminalLine.empty() by initializing empty cells with ' ' instead of '\u0000'. This is broader, but it seems consistent with updateLine(), which already fills blank cells with spaces, and with rendering/selection treating these cells as blank.

I slightly prefer option 2 if no code (I could not find any such codes but possibly @kruton knows that if exists) depends on distinguishing “uninitialized” cells from normal blank cells. If that sentinel distinction is intentional, option 1 is the safer localized fix.


// Sequence number for ordering snapshots
private var sequenceNumber = 0L

Expand Down
2 changes: 1 addition & 1 deletion lib/src/main/java/org/connectbot/terminal/TerminalLine.kt
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ internal data class TerminalLine(
row = row,
cells = List(cols) {
Cell(
char = '\u0000',
char = ' ',
fgColor = defaultFg,
bgColor = defaultBg,
)
Expand Down
Loading