Add new settings from j3270
Build and Test a3270 / Build Android APK (push) Failing after 26s

This commit is contained in:
2026-09-15 23:40:22 +00:00
parent b71f0f5ba4
commit c941fd3a2a
6 changed files with 171 additions and 2 deletions
@@ -528,6 +528,7 @@ fun MainScreen(
val isCrosshairRuler by viewModel.isCrosshairRuler.collectAsState() val isCrosshairRuler by viewModel.isCrosshairRuler.collectAsState()
val cursorStyle by viewModel.cursorStyle.collectAsState() val cursorStyle by viewModel.cursorStyle.collectAsState()
val blockSelectMode by viewModel.blockSelectMode.collectAsState() val blockSelectMode by viewModel.blockSelectMode.collectAsState()
val blockPaste by viewModel.blockPaste.collectAsState()
val uiTheme by viewModel.uiTheme.collectAsState() val uiTheme by viewModel.uiTheme.collectAsState()
val isInsertMode by viewModel.isInsertMode.collectAsState() val isInsertMode by viewModel.isInsertMode.collectAsState()
val isDocMode by viewModel.isDocMode.collectAsState() val isDocMode by viewModel.isDocMode.collectAsState()
@@ -660,6 +661,9 @@ fun MainScreen(
cursorStyle = cursorStyle, cursorStyle = cursorStyle,
isInsertMode = isInsertMode, isInsertMode = isInsertMode,
blockSelectMode = blockSelectMode, blockSelectMode = blockSelectMode,
blockPaste = blockPaste,
onToggleBlockSelectMode = { viewModel.setBlockSelectMode(!blockSelectMode) },
onToggleBlockPaste = { viewModel.setBlockPaste(!blockPaste) },
fourColorOverride = fourColorOverride, fourColorOverride = fourColorOverride,
onPasteLineWrap = { text, wrapCol, wordWrap -> onPasteLineWrap = { text, wrapCol, wordWrap ->
viewModel.pasteLineWrap(text, wrapCol, wordWrap) viewModel.pasteLineWrap(text, wrapCol, wordWrap)
@@ -897,6 +901,7 @@ fun MainScreen(
initialCrosshairRuler = isCrosshairRuler, initialCrosshairRuler = isCrosshairRuler,
initialCursorStyle = cursorStyle, initialCursorStyle = cursorStyle,
initialBlockSelectMode = blockSelectMode, initialBlockSelectMode = blockSelectMode,
initialBlockPaste = blockPaste,
initialStartupBehavior = AppSettings.getStartupBehavior(context).name, initialStartupBehavior = AppSettings.getStartupBehavior(context).name,
initialDynamicRows = AppSettings.getDynamicRows(context), initialDynamicRows = AppSettings.getDynamicRows(context),
initialDynamicCols = AppSettings.getDynamicCols(context), initialDynamicCols = AppSettings.getDynamicCols(context),
@@ -915,7 +920,7 @@ fun MainScreen(
showSettingsDialog = false showSettingsDialog = false
terminalInputViewRef?.showSoftKeyboard() terminalInputViewRef?.showSoftKeyboard()
}, },
onSave = { mask, blink, haptic, verify, gfx, defaultCp, theme, crosshair, style, blockSel, startup, dynRows, dynCols, onSave = { mask, blink, haptic, verify, gfx, defaultCp, theme, crosshair, style, blockSel, blockPst, startup, dynRows, dynCols,
doc, wrap, startCol, endCol, bell, bellCol, tabs, resetIns, fourCol, numLk, autoSk -> doc, wrap, startCol, endCol, bell, bellCol, tabs, resetIns, fourCol, numLk, autoSk ->
showSettingsDialog = false showSettingsDialog = false
viewModel.updateSettings(mask, blink, haptic, verify, gfx, defaultCp) viewModel.updateSettings(mask, blink, haptic, verify, gfx, defaultCp)
@@ -923,6 +928,7 @@ fun MainScreen(
viewModel.setCrosshairRuler(crosshair) viewModel.setCrosshairRuler(crosshair)
viewModel.setCursorStyle(style) viewModel.setCursorStyle(style)
viewModel.setBlockSelectMode(blockSel) viewModel.setBlockSelectMode(blockSel)
viewModel.setBlockPaste(blockPst)
AppSettings.setStartupBehavior(context, AppSettings.StartupBehavior.valueOf(startup)) AppSettings.setStartupBehavior(context, AppSettings.StartupBehavior.valueOf(startup))
AppSettings.setDynamicRows(context, dynRows) AppSettings.setDynamicRows(context, dynRows)
AppSettings.setDynamicCols(context, dynCols) AppSettings.setDynamicCols(context, dynCols)
@@ -61,6 +61,7 @@ sealed interface TerminalInputAction {
data class SetAplMode(val enabled: Boolean) : TerminalInputAction data class SetAplMode(val enabled: Boolean) : TerminalInputAction
data class SetCursor(val baddr: Int) : TerminalInputAction data class SetCursor(val baddr: Int) : TerminalInputAction
data class LightPenSelect(val baddr: Int) : TerminalInputAction data class LightPenSelect(val baddr: Int) : TerminalInputAction
data class PasteText(val text: String) : TerminalInputAction
} }
data class UntrustedCertPromptState( data class UntrustedCertPromptState(
@@ -161,6 +162,9 @@ class TerminalViewModel(application: Application) : AndroidViewModel(application
private val _blockSelectMode = MutableStateFlow(AppSettings.isBlockSelectModeEnabled(application)) private val _blockSelectMode = MutableStateFlow(AppSettings.isBlockSelectModeEnabled(application))
val blockSelectMode: StateFlow<Boolean> = _blockSelectMode.asStateFlow() val blockSelectMode: StateFlow<Boolean> = _blockSelectMode.asStateFlow()
private val _blockPaste = MutableStateFlow(AppSettings.isBlockPasteEnabled(application))
val blockPaste: StateFlow<Boolean> = _blockPaste.asStateFlow()
private val _uiTheme = MutableStateFlow(AppSettings.getUiTheme(application)) private val _uiTheme = MutableStateFlow(AppSettings.getUiTheme(application))
val uiTheme: StateFlow<String> = _uiTheme.asStateFlow() val uiTheme: StateFlow<String> = _uiTheme.asStateFlow()
@@ -206,6 +210,17 @@ class TerminalViewModel(application: Application) : AndroidViewModel(application
_blockSelectMode.value = enabled _blockSelectMode.value = enabled
} }
fun setBlockPaste(enabled: Boolean) {
val app = getApplication<Application>()
AppSettings.setBlockPasteEnabled(app, enabled)
_blockPaste.value = enabled
applyModeSettings()
}
fun toggleBlockPaste() {
setBlockPaste(!_blockPaste.value)
}
fun setUiTheme(theme: String) { fun setUiTheme(theme: String) {
AppSettings.setUiTheme(getApplication(), theme) AppSettings.setUiTheme(getApplication(), theme)
_uiTheme.value = theme _uiTheme.value = theme
@@ -270,7 +285,9 @@ class TerminalViewModel(application: Application) : AndroidViewModel(application
ip.isInsertOffOnAid = AppSettings.getInsertOffOnAid(app) ip.isInsertOffOnAid = AppSettings.getInsertOffOnAid(app)
ip.isNumericFieldLock = AppSettings.getNumericFieldLock(app) ip.isNumericFieldLock = AppSettings.getNumericFieldLock(app)
ip.isAutoSkipEnabled = AppSettings.getAutoSkipEnabled(app) ip.isAutoSkipEnabled = AppSettings.getAutoSkipEnabled(app)
ip.isBlockPaste = AppSettings.isBlockPasteEnabled(app)
} }
c.ps?.isBlockPaste = AppSettings.isBlockPasteEnabled(app)
_fourColorOverride.value = AppSettings.getFourColorOverride(app) _fourColorOverride.value = AppSettings.getFourColorOverride(app)
_isDocMode.value = c.isDocMode _isDocMode.value = c.isDocMode
_isWordWrap.value = c.isWordWrap _isWordWrap.value = c.isWordWrap
@@ -290,6 +307,7 @@ class TerminalViewModel(application: Application) : AndroidViewModel(application
_isCrosshairRuler.value = AppSettings.isCrosshairRulerEnabled(app) _isCrosshairRuler.value = AppSettings.isCrosshairRulerEnabled(app)
_cursorStyle.value = AppSettings.getCursorStyle(app) _cursorStyle.value = AppSettings.getCursorStyle(app)
_blockSelectMode.value = AppSettings.isBlockSelectModeEnabled(app) _blockSelectMode.value = AppSettings.isBlockSelectModeEnabled(app)
_blockPaste.value = AppSettings.isBlockPasteEnabled(app)
_uiTheme.value = AppSettings.getUiTheme(app) _uiTheme.value = AppSettings.getUiTheme(app)
_fourColorOverride.value = AppSettings.getFourColorOverride(app) _fourColorOverride.value = AppSettings.getFourColorOverride(app)
applyModeSettings() applyModeSettings()
@@ -391,6 +409,24 @@ class TerminalViewModel(application: Application) : AndroidViewModel(application
} }
} }
} }
is TerminalInputAction.PasteText -> {
log.info("PasteText: len=${action.text.length}, curAddr=${buf.cursorAddress}, formatted=${buf.isFormatted}, isNvt=$isNvt")
ip.isKeyboardLocked = false
if (isNvt) {
for (ch in action.text) {
if (ch == '\n' || ch == '\r') {
c.sendNVTString("\r\n")
} else {
c.sendNVTChar(ch)
}
}
} else {
val app = getApplication<Application>()
val blockPaste = AppSettings.isBlockPasteEnabled(app)
ip.pasteText(action.text, true, false, blockPaste)
_screenVersion.value = System.currentTimeMillis()
}
}
is TerminalInputAction.SendAid -> { is TerminalInputAction.SendAid -> {
if (isNvt) { if (isNvt) {
if (action.aidCode == AID_ENTER) { if (action.aidCode == AID_ENTER) {
@@ -1103,7 +1139,7 @@ class TerminalViewModel(application: Application) : AndroidViewModel(application
fun pasteString(text: String) { fun pasteString(text: String) {
if (text.isNotEmpty()) { if (text.isNotEmpty()) {
inputChannel.trySend(TerminalInputAction.TypeText(text)) inputChannel.trySend(TerminalInputAction.PasteText(text))
} }
} }
@@ -25,6 +25,7 @@ object AppSettings {
private const val KEY_CROSSHAIR_RULER = "crosshair_ruler" private const val KEY_CROSSHAIR_RULER = "crosshair_ruler"
private const val KEY_CURSOR_STYLE = "cursor_style" private const val KEY_CURSOR_STYLE = "cursor_style"
private const val KEY_BLOCK_SELECT_MODE = "block_select_mode" private const val KEY_BLOCK_SELECT_MODE = "block_select_mode"
private const val KEY_BLOCK_PASTE = "block_paste"
private const val KEY_STARTUP_BEHAVIOR = "startup_behavior" private const val KEY_STARTUP_BEHAVIOR = "startup_behavior"
private const val KEY_DYNAMIC_ROWS = "dynamic_rows" private const val KEY_DYNAMIC_ROWS = "dynamic_rows"
private const val KEY_DYNAMIC_COLS = "dynamic_cols" private const val KEY_DYNAMIC_COLS = "dynamic_cols"
@@ -137,6 +138,15 @@ object AppSettings {
getPrefs(context).edit().putBoolean(KEY_BLOCK_SELECT_MODE, enabled).apply() getPrefs(context).edit().putBoolean(KEY_BLOCK_SELECT_MODE, enabled).apply()
} }
// ========== Block Paste Mode ==========
fun isBlockPasteEnabled(context: Context): Boolean {
return getPrefs(context).getBoolean(KEY_BLOCK_PASTE, true)
}
fun setBlockPasteEnabled(context: Context, enabled: Boolean) {
getPrefs(context).edit().putBoolean(KEY_BLOCK_PASTE, enabled).apply()
}
// ========== Startup Behavior ========== // ========== Startup Behavior ==========
fun getStartupBehavior(context: Context): StartupBehavior { fun getStartupBehavior(context: Context): StartupBehavior {
val s = getPrefs(context).getString(KEY_STARTUP_BEHAVIOR, StartupBehavior.SHOW_CONNECT.name) val s = getPrefs(context).getString(KEY_STARTUP_BEHAVIOR, StartupBehavior.SHOW_CONNECT.name)
@@ -302,6 +312,7 @@ object AppSettings {
p.println("dynamicRows = ${getDynamicRows(context)}") p.println("dynamicRows = ${getDynamicRows(context)}")
p.println("dynamicCols = ${getDynamicCols(context)}") p.println("dynamicCols = ${getDynamicCols(context)}")
p.println("blockSelectMode = ${isBlockSelectModeEnabled(context)}") p.println("blockSelectMode = ${isBlockSelectModeEnabled(context)}")
p.println("blockPaste = ${isBlockPasteEnabled(context)}")
p.println() p.println()
p.println("[entryassist]") p.println("[entryassist]")
@@ -369,6 +380,12 @@ object AppSettings {
"dynamicrows", "dynamic_rows" -> value.toIntOrNull()?.let { setDynamicRows(context, it) } "dynamicrows", "dynamic_rows" -> value.toIntOrNull()?.let { setDynamicRows(context, it) }
"dynamiccols", "dynamic_cols" -> value.toIntOrNull()?.let { setDynamicCols(context, it) } "dynamiccols", "dynamic_cols" -> value.toIntOrNull()?.let { setDynamicCols(context, it) }
"blockselectmode" -> setBlockSelectModeEnabled(context, value.toBoolean()) "blockselectmode" -> setBlockSelectModeEnabled(context, value.toBoolean())
"blockpaste", "blockpastemode" -> setBlockPasteEnabled(context, value.toBoolean())
}
}
"clipboard" -> {
when (key.lowercase(Locale.US)) {
"blockpaste", "blockpastemode" -> setBlockPasteEnabled(context, value.toBoolean())
} }
} }
"entryassist" -> { "entryassist" -> {
@@ -30,6 +30,7 @@ fun SettingsDialog(
initialCrosshairRuler: Boolean = false, initialCrosshairRuler: Boolean = false,
initialCursorStyle: String = "BLOCK", initialCursorStyle: String = "BLOCK",
initialBlockSelectMode: Boolean = false, initialBlockSelectMode: Boolean = false,
initialBlockPaste: Boolean = true,
initialStartupBehavior: String = "SHOW_CONNECT", initialStartupBehavior: String = "SHOW_CONNECT",
initialDynamicRows: Int = 62, initialDynamicRows: Int = 62,
initialDynamicCols: Int = 160, initialDynamicCols: Int = 160,
@@ -56,6 +57,7 @@ fun SettingsDialog(
crosshairRuler: Boolean, crosshairRuler: Boolean,
cursorStyle: String, cursorStyle: String,
blockSelectMode: Boolean, blockSelectMode: Boolean,
blockPaste: Boolean,
startupBehavior: String, startupBehavior: String,
dynamicRows: Int, dynamicRows: Int,
dynamicCols: Int, dynamicCols: Int,
@@ -86,6 +88,7 @@ fun SettingsDialog(
var crosshairRuler by remember { mutableStateOf(initialCrosshairRuler) } var crosshairRuler by remember { mutableStateOf(initialCrosshairRuler) }
var cursorStyle by remember { mutableStateOf(initialCursorStyle) } var cursorStyle by remember { mutableStateOf(initialCursorStyle) }
var blockSelectMode by remember { mutableStateOf(initialBlockSelectMode) } var blockSelectMode by remember { mutableStateOf(initialBlockSelectMode) }
var blockPaste by remember { mutableStateOf(initialBlockPaste) }
var startupBehavior by remember { mutableStateOf(initialStartupBehavior) } var startupBehavior by remember { mutableStateOf(initialStartupBehavior) }
var dynamicRowsStr by remember { mutableStateOf(initialDynamicRows.toString()) } var dynamicRowsStr by remember { mutableStateOf(initialDynamicRows.toString()) }
var dynamicColsStr by remember { mutableStateOf(initialDynamicCols.toString()) } var dynamicColsStr by remember { mutableStateOf(initialDynamicCols.toString()) }
@@ -262,6 +265,25 @@ fun SettingsDialog(
Spacer(modifier = Modifier.height(10.dp)) Spacer(modifier = Modifier.height(10.dp))
// Block Paste Mode
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween
) {
Column(modifier = Modifier.weight(1f).padding(end = 12.dp)) {
Text("Block Paste Mode", fontSize = 14.sp, fontWeight = FontWeight.SemiBold, color = Color.White)
Text("Align multi-line clipboard pastes with cursor start column.", fontSize = 12.sp, color = Color.LightGray)
}
Switch(
checked = blockPaste,
onCheckedChange = { blockPaste = it },
colors = SwitchDefaults.colors(checkedThumbColor = Color.White, checkedTrackColor = Color(0xFF2B8A3E))
)
}
Spacer(modifier = Modifier.height(10.dp))
// Haptic Feedback // Haptic Feedback
Row( Row(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
@@ -707,6 +729,7 @@ fun SettingsDialog(
crosshairRuler, crosshairRuler,
cursorStyle, cursorStyle,
blockSelectMode, blockSelectMode,
blockPaste,
startupBehavior, startupBehavior,
dRows, dRows,
dCols, dCols,
@@ -760,6 +783,7 @@ fun SettingsDialog(
crosshairRuler = haus.nightmare.a3270.storage.AppSettings.isCrosshairRulerEnabled(context) crosshairRuler = haus.nightmare.a3270.storage.AppSettings.isCrosshairRulerEnabled(context)
cursorStyle = haus.nightmare.a3270.storage.AppSettings.getCursorStyle(context) cursorStyle = haus.nightmare.a3270.storage.AppSettings.getCursorStyle(context)
blockSelectMode = haus.nightmare.a3270.storage.AppSettings.isBlockSelectModeEnabled(context) blockSelectMode = haus.nightmare.a3270.storage.AppSettings.isBlockSelectModeEnabled(context)
blockPaste = haus.nightmare.a3270.storage.AppSettings.isBlockPasteEnabled(context)
startupBehavior = haus.nightmare.a3270.storage.AppSettings.getStartupBehavior(context).name startupBehavior = haus.nightmare.a3270.storage.AppSettings.getStartupBehavior(context).name
dynamicRowsStr = haus.nightmare.a3270.storage.AppSettings.getDynamicRows(context).toString() dynamicRowsStr = haus.nightmare.a3270.storage.AppSettings.getDynamicRows(context).toString()
dynamicColsStr = haus.nightmare.a3270.storage.AppSettings.getDynamicCols(context).toString() dynamicColsStr = haus.nightmare.a3270.storage.AppSettings.getDynamicCols(context).toString()
@@ -70,6 +70,7 @@ fun TerminalView(
cursorStyle: String = "BLOCK", cursorStyle: String = "BLOCK",
isInsertMode: Boolean = false, isInsertMode: Boolean = false,
blockSelectMode: Boolean = false, blockSelectMode: Boolean = false,
blockPaste: Boolean = true,
fourColorOverride: Boolean = false, fourColorOverride: Boolean = false,
searchHighlightAddr: Int = -1, searchHighlightAddr: Int = -1,
searchHighlightLen: Int = 0, searchHighlightLen: Int = 0,
@@ -78,6 +79,8 @@ fun TerminalView(
onGraphicTouch: ((Int, Int, Int) -> Unit)? = null, onGraphicTouch: ((Int, Int, Int) -> Unit)? = null,
onPasteText: (String) -> Unit = {}, onPasteText: (String) -> Unit = {},
onPasteLineWrap: ((String, Int, Boolean) -> Unit)? = null, onPasteLineWrap: ((String, Int, Boolean) -> Unit)? = null,
onToggleBlockSelectMode: (() -> Unit)? = null,
onToggleBlockPaste: (() -> Unit)? = null,
modifier: Modifier = Modifier modifier: Modifier = Modifier
) { ) {
val context = LocalContext.current val context = LocalContext.current
@@ -569,6 +572,26 @@ fun TerminalView(
showPasteWrapDialog = true showPasteWrapDialog = true
} }
) )
if (onToggleBlockSelectMode != null) {
DropdownMenuItem(
text = { Text(if (blockSelectMode) "✓ Block Select Mode" else " Block Select Mode") },
onClick = {
showContextMenu = false
onToggleBlockSelectMode()
}
)
}
if (onToggleBlockPaste != null) {
DropdownMenuItem(
text = { Text(if (blockPaste) "✓ Block Paste" else " Block Paste") },
onClick = {
showContextMenu = false
onToggleBlockPaste()
}
)
}
} }
if (showPasteWrapDialog) { if (showPasteWrapDialog) {
@@ -4,6 +4,7 @@ import haus.nightmare.lib3270j.TerminalModel
import haus.nightmare.lib3270j.charset.EbcdicTranslator import haus.nightmare.lib3270j.charset.EbcdicTranslator
import haus.nightmare.lib3270j.ecl.ECLConstants import haus.nightmare.lib3270j.ecl.ECLConstants
import haus.nightmare.lib3270j.ecl.ECLOIA import haus.nightmare.lib3270j.ecl.ECLOIA
import haus.nightmare.lib3270j.ecl.ECLPS
import haus.nightmare.lib3270j.input.InputProcessor import haus.nightmare.lib3270j.input.InputProcessor
import haus.nightmare.lib3270j.protocol.DS3270Constants.* import haus.nightmare.lib3270j.protocol.DS3270Constants.*
import haus.nightmare.lib3270j.screen.ScreenBuffer import haus.nightmare.lib3270j.screen.ScreenBuffer
@@ -191,6 +192,13 @@ class EntryAssistAndModesTest {
@Test @Test
fun testIniSectionSyntaxMatchingJ3270() { fun testIniSectionSyntaxMatchingJ3270() {
val sampleIni = """ val sampleIni = """
[behavior]
blockSelectMode = false
blockPaste = true
[clipboard]
blockPasteMode = true
[entryassist] [entryassist]
docMode = true docMode = true
wordWrap = true wordWrap = true
@@ -223,6 +231,10 @@ class EntryAssistAndModesTest {
} }
} }
assertEquals("false", parsed["behavior.blockselectmode"])
assertEquals("true", parsed["behavior.blockpaste"])
assertEquals("true", parsed["clipboard.blockpastemode"])
assertEquals("true", parsed["entryassist.docmode"]) assertEquals("true", parsed["entryassist.docmode"])
assertEquals("true", parsed["entryassist.wordwrap"]) assertEquals("true", parsed["entryassist.wordwrap"])
assertEquals("5", parsed["entryassist.startcol"]) assertEquals("5", parsed["entryassist.startcol"])
@@ -237,6 +249,57 @@ class EntryAssistAndModesTest {
assertEquals("true", parsed["modes.autoskip"]) assertEquals("true", parsed["modes.autoskip"])
} }
@Test
fun testBlockPasteMultiLineAlignment() {
val translator = EbcdicTranslator()
val screen = ScreenBuffer(TerminalModel.IBM_3278_2, translator)
val input = InputProcessor(screen, translator, null)
val ps = ECLPS(screen, input, translator)
// Verify default blockPaste is true
assertTrue(input.isBlockPaste)
assertTrue(ps.isBlockPaste)
// 1. Unformatted screen: verify start column 15 is preserved across newlines
screen.erase(false)
val startPos = screen.rowColToAddress(0, 15)
screen.cursorAddress = startPos
val multilineText = "FIRST\nSECOND\nTHIRD"
val pasted = input.pasteText(multilineText, true, false, true)
assertEquals(16, pasted)
assertEquals("FIRST", ps.getString(startPos, 5))
val row1Col15 = screen.rowColToAddress(1, 15)
assertEquals("SECOND", ps.getString(row1Col15, 6))
val row2Col15 = screen.rowColToAddress(2, 15)
assertEquals("THIRD", ps.getString(row2Col15, 5))
// 2. Formatted screen with blockPaste = true
screen.erase(false)
screen.setFieldAttribute(0, FA_PRINTABLE.toByte())
screen.setFieldAttribute(80, FA_PRINTABLE.toByte())
screen.setFieldAttribute(160, FA_PRINTABLE.toByte())
screen.cursorAddress = screen.rowColToAddress(0, 25)
val pastedFormatted = input.pasteText("ALPHA\r\nBETA\r\nGAMMA", true, false, true)
assertEquals(14, pastedFormatted)
assertEquals("ALPHA", ps.getString(screen.rowColToAddress(0, 25), 5))
assertEquals("BETA", ps.getString(screen.rowColToAddress(1, 25), 4))
assertEquals("GAMMA", ps.getString(screen.rowColToAddress(2, 25), 5))
// 3. Formatted screen with blockPaste = false: reverts to first unprotected field on next row (pos 81)
screen.erase(false)
screen.setFieldAttribute(0, FA_PRINTABLE.toByte())
screen.setFieldAttribute(80, FA_PRINTABLE.toByte())
screen.cursorAddress = screen.rowColToAddress(0, 25)
input.pasteText("LINE1\nLINE2", true, false, false)
assertEquals("LINE1", ps.getString(screen.rowColToAddress(0, 25), 5))
assertEquals("LINE2", ps.getString(81, 5))
}
@Test @Test
fun testCmsFilenameFormatting() { fun testCmsFilenameFormatting() {
// Upload (local -> host) // Upload (local -> host)