2

I'm very new to Kotlin and making a command line .exe, on Windows using Kotlin/Native. The application should read from a text file and print on screen, line by line. When it reaches the last line of the file, it should put it in the clipboard.

aFile.txt looks something like this:

one
two
three
...
...
the last line

and the code read.kt (Kotlin/Native) I have so far is this:

import kotlinx.cinterop.*
import platform.posix.*

fun main(args: Array<String>) {

    if (args.size != 1) {
        println("Usage: read.exe <file.txt>")
        return
    }

    val fileName = args[0]
    val file = fopen(fileName, "r")

    if (file == null) {
        perror("cannot open input file $fileName")
        return
    }

    try {
        memScoped {
            val bufferLength = 64 * 1024
            val buffer = allocArray<ByteVar>(bufferLength)

            do {
                val nextLine = fgets(buffer, bufferLength, file)?.toKString()
                if (nextLine == null || nextLine.isEmpty()) break
                print("${nextLine}")
            } while (true)

        }
    } finally {
        fclose(file)
    }

}


The code above prints each line on the screen, but how do I write the string "the last line" in the computer's clipboard? I'm looking for a native (not Java) solution if that's possible.

Thank you very much.


Update:

Obviously, this is not the solution I was looking for, but I don't understand yet what are they talking about here (https://learn.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-setclipboarddata).

As a temporary fix, I was able to get what I needed using system(), echo and clip with code like this:

system("echo ${nextLine} | clip")
print("${nextLine}")
Alex Baban
  • 11,312
  • 4
  • 30
  • 44

3 Answers3

6

Try the following:

import java.awt.Toolkit
import java.awt.datatransfer.Clipboard
import java.awt.datatransfer.StringSelection

fun setClipboard(s: String) {
    val selection = StringSelection(s)
    val clipboard: Clipboard = Toolkit.getDefaultToolkit().systemClipboard
    clipboard.setContents(selection, selection)
}
Rasmus
  • 231
  • 5
  • 6
3

In Windows, you can work with the Clipboard through WinAPI, as you can see there. The reference says, that you got to use functions from the winuser.h header. This header is included in windows.h, as far as I know, so it is in your platform.windows.* package. You can approve it by checking Kotlin/Native repository files.


To clarify, what I meant, I wrote this small example of platform.windows.* usage. You can add this function to your code, and call it when you got to copy some string.

import platform.windows.*

fun toClipboard(lastLine:String?){
    val len = lastLine!!.length + 1
    val hMem = GlobalAlloc(GMEM_MOVEABLE, len.toULong())
    memcpy(GlobalLock(hMem), lastLine.cstr, len.toULong())
    GlobalUnlock(hMem)
    val hwnd = HWND_TOP
    OpenClipboard(hwnd)
    EmptyClipboard()
    SetClipboardData(CF_TEXT, hMem)
    CloseClipboard()
}
Artyom Degtyarev
  • 2,704
  • 8
  • 23
  • Thank you for your suggestion, but I don't have enough knowledge to even understand it at this point. I was expecting Kotlin to have something similar to `println("string")` like `writeClipboard("string")` or something. – Alex Baban Jun 18 '19 at 13:16
  • You can try to use something from [here](https://stackoverflow.com/questions/1264137/how-to-copy-string-to-clipboard-in-c), it should be provided by the package I mentioned. Import `platform.windows.*` and play around a few. I think it can be easier than it looks, so don't give up so fast. – Artyom Degtyarev Jun 18 '19 at 13:55
  • The sample code you added to your answer works, thanks. With all three imports `import kotlinx.cinterop.*`, `import platform.posix.*` and `import platform.windows.*` I was able to compile. – Alex Baban Jul 04 '19 at 00:32
0

If you want to target other platforms in the future, you can have a look at Compose Multiplatform as well. It is multiplatform, so it would work on Mac, Android, iOS, web too.

Using it is easy:

@Composable
fun Widget(){
    val clipboard: ClipboardManager = LocalClipboardManager.current
    Row(modifier = Modifier.clickable {
        clipboard.setText(AnnotatedString("Some text here"))
    }) {
        Text(text = "Click me")
    }
}
Entreco
  • 12,738
  • 8
  • 75
  • 95