diff --git a/build.gradle b/build.gradle index 3057998..b4cdbfc 100644 --- a/build.gradle +++ b/build.gradle @@ -12,7 +12,7 @@ android { minSdk 24 targetSdk 34 versionCode 10 - versionName "1.3.0" + versionName "1.2.5" } buildTypes { diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml index f1ca386..3814c80 100644 --- a/src/main/AndroidManifest.xml +++ b/src/main/AndroidManifest.xml @@ -1,7 +1,7 @@ + android:versionName="1.2.5"> diff --git a/src/main/java/haus/nightmare/a3270/ui/FileTransferDialog.kt b/src/main/java/haus/nightmare/a3270/ui/FileTransferDialog.kt index 1a19d29..4a6ad3f 100644 --- a/src/main/java/haus/nightmare/a3270/ui/FileTransferDialog.kt +++ b/src/main/java/haus/nightmare/a3270/ui/FileTransferDialog.kt @@ -508,9 +508,14 @@ fun FileTransferDialog( } } - // TSO Send Options - if (!isReceive && hostType == FTConfig.HostType.TSO) { - Text("TSO Dataset Allocation:", fontSize = 12.sp, fontWeight = FontWeight.Bold, color = Color.Gray) + // TSO / CMS Allocation & Record Format Options + if (!isReceive && (hostType == FTConfig.HostType.TSO || hostType == FTConfig.HostType.CMS)) { + Text( + if (hostType == FTConfig.HostType.TSO) "TSO Dataset Allocation:" else "VM/CMS File Format:", + fontSize = 12.sp, + fontWeight = FontWeight.Bold, + color = Color.Gray + ) Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween, @@ -542,64 +547,70 @@ fun FileTransferDialog( onValueChange = { lreclStr = it.filter { c -> c.isDigit() } }, label = { Text("LRECL", fontSize = 11.sp) }, singleLine = true, - keyboardOptions = TerminalKeyboardOptions.copy(imeAction = ImeAction.Next), - modifier = Modifier.weight(1f) + keyboardOptions = TerminalKeyboardOptions.copy( + imeAction = if (hostType == FTConfig.HostType.TSO) ImeAction.Next else ImeAction.Done + ), + modifier = if (hostType == FTConfig.HostType.TSO) Modifier.weight(1f) else Modifier.fillMaxWidth() ) - OutlinedTextField( - value = blksizeStr, - onValueChange = { blksizeStr = it.filter { c -> c.isDigit() } }, - label = { Text("BLKSIZE", fontSize = 11.sp) }, - singleLine = true, - keyboardOptions = TerminalKeyboardOptions.copy(imeAction = ImeAction.Next), - modifier = Modifier.weight(1f) - ) - } - - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically - ) { - Text("Units:", fontSize = 11.sp) - Row { - listOf( - FTConfig.AllocationUnit.TRACKS to "Tracks", - FTConfig.AllocationUnit.CYLINDERS to "Cylinders", - FTConfig.AllocationUnit.AVBLOCK to "Avblock", - FTConfig.AllocationUnit.DEFAULT to "Default" - ).forEach { (u, label) -> - FilterChip( - selected = (units == u), - onClick = { units = u }, - label = { Text(label, fontSize = 11.sp) } - ) - Spacer(modifier = Modifier.width(4.dp)) - } + if (hostType == FTConfig.HostType.TSO) { + OutlinedTextField( + value = blksizeStr, + onValueChange = { blksizeStr = it.filter { c -> c.isDigit() } }, + label = { Text("BLKSIZE", fontSize = 11.sp) }, + singleLine = true, + keyboardOptions = TerminalKeyboardOptions.copy(imeAction = ImeAction.Next), + modifier = Modifier.weight(1f) + ) } } - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.spacedBy(8.dp) - ) { - OutlinedTextField( - value = spaceStr, - onValueChange = { spaceStr = it }, - label = { Text("SPACE (Pri, Sec)", fontSize = 11.sp) }, - placeholder = { Text("e.g. 5,2 or 1,1") }, - singleLine = true, - keyboardOptions = TerminalKeyboardOptions.copy(imeAction = ImeAction.Next), - modifier = Modifier.weight(0.62f) - ) - OutlinedTextField( - value = dirBlocks, - onValueChange = { dirBlocks = it.filter { c -> c.isDigit() } }, - label = { Text("Dir (PDS)", fontSize = 11.sp) }, - placeholder = { Text("e.g. 10") }, - singleLine = true, - keyboardOptions = TerminalKeyboardOptions.copy(imeAction = ImeAction.Done), - modifier = Modifier.weight(0.38f) - ) + if (hostType == FTConfig.HostType.TSO) { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Text("Units:", fontSize = 11.sp) + Row { + listOf( + FTConfig.AllocationUnit.TRACKS to "Tracks", + FTConfig.AllocationUnit.CYLINDERS to "Cylinders", + FTConfig.AllocationUnit.AVBLOCK to "Avblock", + FTConfig.AllocationUnit.DEFAULT to "Default" + ).forEach { (u, label) -> + FilterChip( + selected = (units == u), + onClick = { units = u }, + label = { Text(label, fontSize = 11.sp) } + ) + Spacer(modifier = Modifier.width(4.dp)) + } + } + } + + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + OutlinedTextField( + value = spaceStr, + onValueChange = { spaceStr = it }, + label = { Text("SPACE (Pri, Sec)", fontSize = 11.sp) }, + placeholder = { Text("e.g. 5,2 or 1,1") }, + singleLine = true, + keyboardOptions = TerminalKeyboardOptions.copy(imeAction = ImeAction.Next), + modifier = Modifier.weight(0.62f) + ) + OutlinedTextField( + value = dirBlocks, + onValueChange = { dirBlocks = it.filter { c -> c.isDigit() } }, + label = { Text("Dir (PDS)", fontSize = 11.sp) }, + placeholder = { Text("e.g. 10") }, + singleLine = true, + keyboardOptions = TerminalKeyboardOptions.copy(imeAction = ImeAction.Done), + modifier = Modifier.weight(0.38f) + ) + } } } @@ -637,13 +648,17 @@ fun FileTransferDialog( setTransferMode(if (isAscii) FTConfig.TransferMode.ASCII else FTConfig.TransferMode.BINARY) setHostType(hostType) setExistAction(if (overwrite) FTConfig.ExistAction.REPLACE else FTConfig.ExistAction.KEEP) - if (!isReceive && hostType == FTConfig.HostType.TSO) { - setRecfm(recfm) - lreclStr.trim().toIntOrNull()?.let { setLrecl(it) } - blksizeStr.trim().toIntOrNull()?.let { setBlksize(it) } - setUnits(units) - if (spaceStr.isNotBlank()) setSpace(spaceStr.trim()) - if (dirBlocks.isNotBlank()) setDirectoryBlocks(dirBlocks.trim()) + if (!isReceive) { + if (hostType == FTConfig.HostType.TSO || hostType == FTConfig.HostType.CMS) { + setRecfm(recfm) + lreclStr.trim().toIntOrNull()?.let { setLrecl(it) } + } + if (hostType == FTConfig.HostType.TSO) { + blksizeStr.trim().toIntOrNull()?.let { setBlksize(it) } + setUnits(units) + if (spaceStr.isNotBlank()) setSpace(spaceStr.trim()) + if (dirBlocks.isNotBlank()) setDirectoryBlocks(dirBlocks.trim()) + } } if (hostType == FTConfig.HostType.CMS && cmsOptions.isNotBlank()) { setOptions(cmsOptions.trim()) diff --git a/src/test/java/haus/nightmare/a3270/ConnectionAndHostDirectoryTest.kt b/src/test/java/haus/nightmare/a3270/ConnectionAndHostDirectoryTest.kt index e7b1455..f0e43a6 100644 --- a/src/test/java/haus/nightmare/a3270/ConnectionAndHostDirectoryTest.kt +++ b/src/test/java/haus/nightmare/a3270/ConnectionAndHostDirectoryTest.kt @@ -229,6 +229,25 @@ class ConnectionAndHostDirectoryTest { assertEquals(FTConfig.HostType.CMS, state.hostType) } + @Test + fun testCmsFileTransferCommandGeneration() { + val cfg = FTConfig().apply { + setHostFilename("PROFILE EXEC A") + setLocalFilename("/tmp/profile.exec") + setDirection(FTConfig.Direction.SEND) + setTransferMode(FTConfig.TransferMode.ASCII) + setHostType(FTConfig.HostType.CMS) + setExistAction(FTConfig.ExistAction.REPLACE) + setRecfm(FTConfig.RecordFormat.FIXED) + setLrecl(80) + } + val cmd = cfg.buildCommand() + assertTrue("CMS command must contain RECFM F", cmd.contains("RECFM F")) + assertTrue("CMS command must contain LRECL 80", cmd.contains("LRECL 80")) + assertFalse("CMS command must not contain REPLACE keyword", cmd.contains("REPLACE")) + assertFalse("CMS command must not contain BLOCK keyword", cmd.contains("BLOCK")) + } + @Test fun testConnectChoiceEnum() { val choices = ConnectChoice.values()