This commit is contained in:
@@ -528,6 +528,7 @@ fun MainScreen(
|
||||
val isCrosshairRuler by viewModel.isCrosshairRuler.collectAsState()
|
||||
val cursorStyle by viewModel.cursorStyle.collectAsState()
|
||||
val blockSelectMode by viewModel.blockSelectMode.collectAsState()
|
||||
val blockPaste by viewModel.blockPaste.collectAsState()
|
||||
val uiTheme by viewModel.uiTheme.collectAsState()
|
||||
val isInsertMode by viewModel.isInsertMode.collectAsState()
|
||||
val isDocMode by viewModel.isDocMode.collectAsState()
|
||||
@@ -660,6 +661,9 @@ fun MainScreen(
|
||||
cursorStyle = cursorStyle,
|
||||
isInsertMode = isInsertMode,
|
||||
blockSelectMode = blockSelectMode,
|
||||
blockPaste = blockPaste,
|
||||
onToggleBlockSelectMode = { viewModel.setBlockSelectMode(!blockSelectMode) },
|
||||
onToggleBlockPaste = { viewModel.setBlockPaste(!blockPaste) },
|
||||
fourColorOverride = fourColorOverride,
|
||||
onPasteLineWrap = { text, wrapCol, wordWrap ->
|
||||
viewModel.pasteLineWrap(text, wrapCol, wordWrap)
|
||||
@@ -897,6 +901,7 @@ fun MainScreen(
|
||||
initialCrosshairRuler = isCrosshairRuler,
|
||||
initialCursorStyle = cursorStyle,
|
||||
initialBlockSelectMode = blockSelectMode,
|
||||
initialBlockPaste = blockPaste,
|
||||
initialStartupBehavior = AppSettings.getStartupBehavior(context).name,
|
||||
initialDynamicRows = AppSettings.getDynamicRows(context),
|
||||
initialDynamicCols = AppSettings.getDynamicCols(context),
|
||||
@@ -915,7 +920,7 @@ fun MainScreen(
|
||||
showSettingsDialog = false
|
||||
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 ->
|
||||
showSettingsDialog = false
|
||||
viewModel.updateSettings(mask, blink, haptic, verify, gfx, defaultCp)
|
||||
@@ -923,6 +928,7 @@ fun MainScreen(
|
||||
viewModel.setCrosshairRuler(crosshair)
|
||||
viewModel.setCursorStyle(style)
|
||||
viewModel.setBlockSelectMode(blockSel)
|
||||
viewModel.setBlockPaste(blockPst)
|
||||
AppSettings.setStartupBehavior(context, AppSettings.StartupBehavior.valueOf(startup))
|
||||
AppSettings.setDynamicRows(context, dynRows)
|
||||
AppSettings.setDynamicCols(context, dynCols)
|
||||
|
||||
@@ -61,6 +61,7 @@ sealed interface TerminalInputAction {
|
||||
data class SetAplMode(val enabled: Boolean) : TerminalInputAction
|
||||
data class SetCursor(val baddr: Int) : TerminalInputAction
|
||||
data class LightPenSelect(val baddr: Int) : TerminalInputAction
|
||||
data class PasteText(val text: String) : TerminalInputAction
|
||||
}
|
||||
|
||||
data class UntrustedCertPromptState(
|
||||
@@ -161,6 +162,9 @@ class TerminalViewModel(application: Application) : AndroidViewModel(application
|
||||
private val _blockSelectMode = MutableStateFlow(AppSettings.isBlockSelectModeEnabled(application))
|
||||
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))
|
||||
val uiTheme: StateFlow<String> = _uiTheme.asStateFlow()
|
||||
|
||||
@@ -206,6 +210,17 @@ class TerminalViewModel(application: Application) : AndroidViewModel(application
|
||||
_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) {
|
||||
AppSettings.setUiTheme(getApplication(), theme)
|
||||
_uiTheme.value = theme
|
||||
@@ -270,7 +285,9 @@ class TerminalViewModel(application: Application) : AndroidViewModel(application
|
||||
ip.isInsertOffOnAid = AppSettings.getInsertOffOnAid(app)
|
||||
ip.isNumericFieldLock = AppSettings.getNumericFieldLock(app)
|
||||
ip.isAutoSkipEnabled = AppSettings.getAutoSkipEnabled(app)
|
||||
ip.isBlockPaste = AppSettings.isBlockPasteEnabled(app)
|
||||
}
|
||||
c.ps?.isBlockPaste = AppSettings.isBlockPasteEnabled(app)
|
||||
_fourColorOverride.value = AppSettings.getFourColorOverride(app)
|
||||
_isDocMode.value = c.isDocMode
|
||||
_isWordWrap.value = c.isWordWrap
|
||||
@@ -290,6 +307,7 @@ class TerminalViewModel(application: Application) : AndroidViewModel(application
|
||||
_isCrosshairRuler.value = AppSettings.isCrosshairRulerEnabled(app)
|
||||
_cursorStyle.value = AppSettings.getCursorStyle(app)
|
||||
_blockSelectMode.value = AppSettings.isBlockSelectModeEnabled(app)
|
||||
_blockPaste.value = AppSettings.isBlockPasteEnabled(app)
|
||||
_uiTheme.value = AppSettings.getUiTheme(app)
|
||||
_fourColorOverride.value = AppSettings.getFourColorOverride(app)
|
||||
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 -> {
|
||||
if (isNvt) {
|
||||
if (action.aidCode == AID_ENTER) {
|
||||
@@ -1103,7 +1139,7 @@ class TerminalViewModel(application: Application) : AndroidViewModel(application
|
||||
|
||||
fun pasteString(text: String) {
|
||||
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_CURSOR_STYLE = "cursor_style"
|
||||
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_DYNAMIC_ROWS = "dynamic_rows"
|
||||
private const val KEY_DYNAMIC_COLS = "dynamic_cols"
|
||||
@@ -137,6 +138,15 @@ object AppSettings {
|
||||
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 ==========
|
||||
fun getStartupBehavior(context: Context): StartupBehavior {
|
||||
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("dynamicCols = ${getDynamicCols(context)}")
|
||||
p.println("blockSelectMode = ${isBlockSelectModeEnabled(context)}")
|
||||
p.println("blockPaste = ${isBlockPasteEnabled(context)}")
|
||||
p.println()
|
||||
|
||||
p.println("[entryassist]")
|
||||
@@ -369,6 +380,12 @@ object AppSettings {
|
||||
"dynamicrows", "dynamic_rows" -> value.toIntOrNull()?.let { setDynamicRows(context, it) }
|
||||
"dynamiccols", "dynamic_cols" -> value.toIntOrNull()?.let { setDynamicCols(context, it) }
|
||||
"blockselectmode" -> setBlockSelectModeEnabled(context, value.toBoolean())
|
||||
"blockpaste", "blockpastemode" -> setBlockPasteEnabled(context, value.toBoolean())
|
||||
}
|
||||
}
|
||||
"clipboard" -> {
|
||||
when (key.lowercase(Locale.US)) {
|
||||
"blockpaste", "blockpastemode" -> setBlockPasteEnabled(context, value.toBoolean())
|
||||
}
|
||||
}
|
||||
"entryassist" -> {
|
||||
|
||||
@@ -30,6 +30,7 @@ fun SettingsDialog(
|
||||
initialCrosshairRuler: Boolean = false,
|
||||
initialCursorStyle: String = "BLOCK",
|
||||
initialBlockSelectMode: Boolean = false,
|
||||
initialBlockPaste: Boolean = true,
|
||||
initialStartupBehavior: String = "SHOW_CONNECT",
|
||||
initialDynamicRows: Int = 62,
|
||||
initialDynamicCols: Int = 160,
|
||||
@@ -56,6 +57,7 @@ fun SettingsDialog(
|
||||
crosshairRuler: Boolean,
|
||||
cursorStyle: String,
|
||||
blockSelectMode: Boolean,
|
||||
blockPaste: Boolean,
|
||||
startupBehavior: String,
|
||||
dynamicRows: Int,
|
||||
dynamicCols: Int,
|
||||
@@ -86,6 +88,7 @@ fun SettingsDialog(
|
||||
var crosshairRuler by remember { mutableStateOf(initialCrosshairRuler) }
|
||||
var cursorStyle by remember { mutableStateOf(initialCursorStyle) }
|
||||
var blockSelectMode by remember { mutableStateOf(initialBlockSelectMode) }
|
||||
var blockPaste by remember { mutableStateOf(initialBlockPaste) }
|
||||
var startupBehavior by remember { mutableStateOf(initialStartupBehavior) }
|
||||
var dynamicRowsStr by remember { mutableStateOf(initialDynamicRows.toString()) }
|
||||
var dynamicColsStr by remember { mutableStateOf(initialDynamicCols.toString()) }
|
||||
@@ -262,6 +265,25 @@ fun SettingsDialog(
|
||||
|
||||
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
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
@@ -707,6 +729,7 @@ fun SettingsDialog(
|
||||
crosshairRuler,
|
||||
cursorStyle,
|
||||
blockSelectMode,
|
||||
blockPaste,
|
||||
startupBehavior,
|
||||
dRows,
|
||||
dCols,
|
||||
@@ -760,6 +783,7 @@ fun SettingsDialog(
|
||||
crosshairRuler = haus.nightmare.a3270.storage.AppSettings.isCrosshairRulerEnabled(context)
|
||||
cursorStyle = haus.nightmare.a3270.storage.AppSettings.getCursorStyle(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
|
||||
dynamicRowsStr = haus.nightmare.a3270.storage.AppSettings.getDynamicRows(context).toString()
|
||||
dynamicColsStr = haus.nightmare.a3270.storage.AppSettings.getDynamicCols(context).toString()
|
||||
|
||||
@@ -70,6 +70,7 @@ fun TerminalView(
|
||||
cursorStyle: String = "BLOCK",
|
||||
isInsertMode: Boolean = false,
|
||||
blockSelectMode: Boolean = false,
|
||||
blockPaste: Boolean = true,
|
||||
fourColorOverride: Boolean = false,
|
||||
searchHighlightAddr: Int = -1,
|
||||
searchHighlightLen: Int = 0,
|
||||
@@ -78,6 +79,8 @@ fun TerminalView(
|
||||
onGraphicTouch: ((Int, Int, Int) -> Unit)? = null,
|
||||
onPasteText: (String) -> Unit = {},
|
||||
onPasteLineWrap: ((String, Int, Boolean) -> Unit)? = null,
|
||||
onToggleBlockSelectMode: (() -> Unit)? = null,
|
||||
onToggleBlockPaste: (() -> Unit)? = null,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
@@ -569,6 +572,26 @@ fun TerminalView(
|
||||
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) {
|
||||
|
||||
Reference in New Issue
Block a user