From ed5a6bde427cc4923961ccb0b80c5b2987d957f3 Mon Sep 17 00:00:00 2001 From: Kien Nguyen Date: Tue, 1 May 2018 04:14:56 +0900 Subject: [PATCH 1/5] Allow to set multiple clipboard type in windows --- clipboard.go | 17 ++++++++ clipboard_test.go | 4 +- clipboard_windows.go | 78 ++++++++++++++++++++++++++-------- cmd/goclipboard/.gitignore | 3 ++ cmd/goclipboard/goclipboard.go | 66 ++++++++++++++++++++++++++++ example_test.go | 8 ++-- 6 files changed, 151 insertions(+), 25 deletions(-) create mode 100644 cmd/goclipboard/.gitignore create mode 100644 cmd/goclipboard/goclipboard.go diff --git a/clipboard.go b/clipboard.go index d7907d3..35f6067 100644 --- a/clipboard.go +++ b/clipboard.go @@ -10,11 +10,28 @@ func ReadAll() (string, error) { return readAll() } +func ReadAllWithFormat(cf uintptr) (string, error) { + return readAllWithFormat(cf) +} + // WriteAll write string to clipboard func WriteAll(text string) error { return writeAll(text) } +// WriteAllWithFormat write string to clipboard with format +func WriteAllWithFormat(text string, cf uintptr) error { + return writeAllWithFormat(text, cf) +} + +func ClearClipboard() error { + return clearClipboard() +} + +func GetClipboardFormat(format string) (uintptr, error) { + return getClipboardFormat(format) +} + // Unsupported might be set true during clipboard init, to help callers decide // whether or not to offer clipboard options. var Unsupported bool diff --git a/clipboard_test.go b/clipboard_test.go index 075e657..5883969 100644 --- a/clipboard_test.go +++ b/clipboard_test.go @@ -2,12 +2,10 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package clipboard_test +package clipboard import ( "testing" - - . "github.com/atotto/clipboard" ) func TestCopyAndPaste(t *testing.T) { diff --git a/clipboard_windows.go b/clipboard_windows.go index 4b4aedb..4fc65fc 100644 --- a/clipboard_windows.go +++ b/clipboard_windows.go @@ -14,23 +14,26 @@ import ( const ( cfUnicodetext = 13 + cfText = 1 gmemMoveable = 0x0002 ) var ( - user32 = syscall.MustLoadDLL("user32") - openClipboard = user32.MustFindProc("OpenClipboard") - closeClipboard = user32.MustFindProc("CloseClipboard") - emptyClipboard = user32.MustFindProc("EmptyClipboard") - getClipboardData = user32.MustFindProc("GetClipboardData") - setClipboardData = user32.MustFindProc("SetClipboardData") + user32 = syscall.MustLoadDLL("user32") + openClipboard = user32.MustFindProc("OpenClipboard") + closeClipboard = user32.MustFindProc("CloseClipboard") + emptyClipboard = user32.MustFindProc("EmptyClipboard") + getClipboardData = user32.MustFindProc("GetClipboardData") + setClipboardData = user32.MustFindProc("SetClipboardData") + registerClipboardFormat = user32.MustFindProc("RegisterClipboardFormatW") kernel32 = syscall.NewLazyDLL("kernel32") globalAlloc = kernel32.NewProc("GlobalAlloc") globalFree = kernel32.NewProc("GlobalFree") + globalSize = kernel32.NewProc("GlobalSize") globalLock = kernel32.NewProc("GlobalLock") globalUnlock = kernel32.NewProc("GlobalUnlock") - lstrcpy = kernel32.NewProc("lstrcpyW") + strcpy = kernel32.NewProc("lstrcpyA") ) // waitOpenClipboard opens the clipboard, waiting for up to a second to do so. @@ -50,26 +53,37 @@ func waitOpenClipboard() error { } func readAll() (string, error) { + return readAllWithFormat(cfText) +} + +func readAllWithFormat(cf uintptr) (string, error) { err := waitOpenClipboard() if err != nil { return "", err } defer closeClipboard.Call() - h, _, err := getClipboardData.Call(cfUnicodetext) + h, _, err := getClipboardData.Call(cf) if h == 0 { return "", err } + size, _, err := globalSize.Call(h) + if size == 0 { + return "", err + } + l, _, err := globalLock.Call(h) if l == 0 { + panic(err) return "", err } - text := syscall.UTF16ToString((*[1 << 20]uint16)(unsafe.Pointer(l))[:]) + text := string((*[1 << 20]byte)(unsafe.Pointer(l))[:(size - 1)]) r, _, err := globalUnlock.Call(h) if r == 0 { + panic(err) return "", err } @@ -77,18 +91,17 @@ func readAll() (string, error) { } func writeAll(text string) error { + return writeAllWithFormat(text, cfText) +} + +func writeAllWithFormat(text string, cf uintptr) error { err := waitOpenClipboard() if err != nil { return err } defer closeClipboard.Call() - r, _, err := emptyClipboard.Call(0) - if r == 0 { - return err - } - - data := syscall.StringToUTF16(text) + data := syscall.StringByteSlice(text) // "If the hMem parameter identifies a memory object, the object must have // been allocated using the function with the GMEM_MOVEABLE flag." @@ -96,6 +109,7 @@ func writeAll(text string) error { if h == 0 { return err } + defer func() { if h != 0 { globalFree.Call(h) @@ -107,7 +121,7 @@ func writeAll(text string) error { return err } - r, _, err = lstrcpy.Call(l, uintptr(unsafe.Pointer(&data[0]))) + r, _, err := strcpy.Call(l, uintptr(unsafe.Pointer(&data[0]))) if r == 0 { return err } @@ -119,10 +133,40 @@ func writeAll(text string) error { } } - r, _, err = setClipboardData.Call(cfUnicodetext, h) + r, _, err = setClipboardData.Call(cf, h) if r == 0 { return err } + h = 0 // suppress deferred cleanup return nil } + +func getClipboardFormat(text string) (uintptr, error) { + ptr, err := syscall.UTF16PtrFromString(text) + if err != nil { + return 0, err + } + + cf, _, err := registerClipboardFormat.Call(uintptr(unsafe.Pointer(ptr))) + if cf == 0 { + return 0, err + } + + return cf, nil +} + +func clearClipboard() error { + err := waitOpenClipboard() + if err != nil { + return err + } + defer closeClipboard.Call() + + r, _, err := emptyClipboard.Call() + if r == 0 { + return err + } + + return nil +} diff --git a/cmd/goclipboard/.gitignore b/cmd/goclipboard/.gitignore new file mode 100644 index 0000000..27a81e7 --- /dev/null +++ b/cmd/goclipboard/.gitignore @@ -0,0 +1,3 @@ +bin +goclipboard +goclipboard.exe \ No newline at end of file diff --git a/cmd/goclipboard/goclipboard.go b/cmd/goclipboard/goclipboard.go new file mode 100644 index 0000000..df0f65d --- /dev/null +++ b/cmd/goclipboard/goclipboard.go @@ -0,0 +1,66 @@ +package main + +import ( + "flag" + "fmt" + "github.com/kiennq/clipboard" +) + +const ( + HtmlMarkerBlock = "Version:0.9\n" + + "StartHTML:%010d\n" + + "EndHTML:%010d\n" + + "StartFragment:%010d\n" + + "EndFragment:%010d\n" + + HtmlHeader = "\n\n" + HtmlFooter = "\n\n\n" +) + +var ( + cfText uintptr = 1 + cfHtml = getHtmlClipboard() +) + +func getHtmlBlock(htmlText string) string { + testPrefix := fmt.Sprintf(HtmlMarkerBlock, 0, 0, 0, 0) + markerBlockLen := len(testPrefix) // Should be always 100, can be optimized + headerLen := len(HtmlHeader) + footerLen := len(HtmlFooter) + prefix := fmt.Sprintf(HtmlMarkerBlock, + markerBlockLen, + markerBlockLen+headerLen+len(htmlText)+footerLen, + markerBlockLen+headerLen, + markerBlockLen+headerLen+len(htmlText)) + return prefix + HtmlHeader + htmlText + HtmlFooter +} + +func getHtmlClipboard() uintptr { + cf, err := clipboard.GetClipboardFormat("HTML Format") + if err != nil { + panic(err) + } + + return cf +} + +func main() { + htmlText := flag.String("html", "", "html format text") + text := flag.String("text", "", "text") + + flag.Parse() + + htmlBlock := getHtmlBlock(*htmlText) + + if err := clipboard.ClearClipboard(); err != nil { + panic(err) + } + + if err := clipboard.WriteAllWithFormat(htmlBlock, cfHtml); err != nil { + panic(err) + } + + if err := clipboard.WriteAllWithFormat(*text, cfText); err != nil { + panic(err) + } +} diff --git a/example_test.go b/example_test.go index 0f970a0..54a1ae0 100644 --- a/example_test.go +++ b/example_test.go @@ -1,14 +1,12 @@ -package clipboard_test +package clipboard import ( "fmt" - - "github.com/atotto/clipboard" ) func Example() { - clipboard.WriteAll("日本語") - text, _ := clipboard.ReadAll() + WriteAll("日本語") + text, _ := ReadAll() fmt.Println(text) // Output: From 14a35dcd7c307e24654839caa2480c3ea6811a22 Mon Sep 17 00:00:00 2001 From: Kien Nguyen Date: Wed, 16 May 2018 20:34:19 +0900 Subject: [PATCH 2/5] add various flag --- cmd/goclipboard/goclipboard.go | 40 +++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/cmd/goclipboard/goclipboard.go b/cmd/goclipboard/goclipboard.go index df0f65d..02af6e5 100644 --- a/cmd/goclipboard/goclipboard.go +++ b/cmd/goclipboard/goclipboard.go @@ -4,6 +4,8 @@ import ( "flag" "fmt" "github.com/kiennq/clipboard" + "io/ioutil" + "os" ) const ( @@ -14,7 +16,7 @@ const ( "EndFragment:%010d\n" HtmlHeader = "\n\n" - HtmlFooter = "\n\n\n" + HtmlFooter = "\n\n" ) var ( @@ -45,22 +47,40 @@ func getHtmlClipboard() uintptr { } func main() { - htmlText := flag.String("html", "", "html format text") - text := flag.String("text", "", "text") + htmlVal := flag.String("html", "", "html format text") + text := flag.String("text", "", "normal text") + stdinAsHtml := flag.Bool("in-html", false, "using stdin as html") + doClear := flag.Bool("clear", true, "clear previous clipboard") flag.Parse() - htmlBlock := getHtmlBlock(*htmlText) + htmlText := *htmlVal + if *stdinAsHtml { + in, err := ioutil.ReadAll(os.Stdin) + if err != nil { + panic(err) + } - if err := clipboard.ClearClipboard(); err != nil { - panic(err) + htmlText = string(in) } - if err := clipboard.WriteAllWithFormat(htmlBlock, cfHtml); err != nil { - panic(err) + htmlBlock := getHtmlBlock(htmlText) + + if *doClear { + if err := clipboard.ClearClipboard(); err != nil { + panic(err) + } } - if err := clipboard.WriteAllWithFormat(*text, cfText); err != nil { - panic(err) + if htmlText != "" { + if err := clipboard.WriteAllWithFormat(htmlBlock, cfHtml); err != nil { + panic(err) + } + } + + if *text != "" { + if err := clipboard.WriteAllWithFormat(*text, cfText); err != nil { + panic(err) + } } } From c1c9ade507fcc486b3e857311b1fdc6c960862e2 Mon Sep 17 00:00:00 2001 From: Kien Nguyen Date: Wed, 16 May 2018 22:07:06 +0900 Subject: [PATCH 3/5] support input using stdin with json format --- cmd/goclipboard/goclipboard.go | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/cmd/goclipboard/goclipboard.go b/cmd/goclipboard/goclipboard.go index 02af6e5..da5b1c4 100644 --- a/cmd/goclipboard/goclipboard.go +++ b/cmd/goclipboard/goclipboard.go @@ -4,8 +4,9 @@ import ( "flag" "fmt" "github.com/kiennq/clipboard" - "io/ioutil" "os" + "encoding/json" + "io" ) const ( @@ -48,20 +49,27 @@ func getHtmlClipboard() uintptr { func main() { htmlVal := flag.String("html", "", "html format text") - text := flag.String("text", "", "normal text") - stdinAsHtml := flag.Bool("in-html", false, "using stdin as html") + textVal := flag.String("text", "", "normal text") + useStdin := flag.Bool("in", false, "using stdin as input, the input format is json {text:, htmlText:}") doClear := flag.Bool("clear", true, "clear previous clipboard") flag.Parse() htmlText := *htmlVal - if *stdinAsHtml { - in, err := ioutil.ReadAll(os.Stdin) - if err != nil { + text := *textVal + if *useStdin { + type Message struct { + Text, HtmlText string + } + + dec := json.NewDecoder(os.Stdin) + var m Message + if err := dec.Decode(&m); err != nil && err != io.EOF { panic(err) } - htmlText = string(in) + htmlText = m.HtmlText + text = m.Text } htmlBlock := getHtmlBlock(htmlText) @@ -78,8 +86,8 @@ func main() { } } - if *text != "" { - if err := clipboard.WriteAllWithFormat(*text, cfText); err != nil { + if text != "" { + if err := clipboard.WriteAllWithFormat(text, cfText); err != nil { panic(err) } } From 1c392de79bfb3c0a7e65ad934598a704ae5e765d Mon Sep 17 00:00:00 2001 From: Kien Nguyen Date: Thu, 17 May 2018 05:28:55 +0900 Subject: [PATCH 4/5] refactoring, add copy and paste command --- clipboard_test.go | 2 +- clipboard_windows.go | 14 ++-- cmd/goclip/.gitignore | 3 + cmd/goclip/goclip.go | 140 +++++++++++++++++++++++++++++++++ cmd/goclipboard/.gitignore | 3 - cmd/goclipboard/goclipboard.go | 94 ---------------------- 6 files changed, 152 insertions(+), 104 deletions(-) create mode 100644 cmd/goclip/.gitignore create mode 100644 cmd/goclip/goclip.go delete mode 100644 cmd/goclipboard/.gitignore delete mode 100644 cmd/goclipboard/goclipboard.go diff --git a/clipboard_test.go b/clipboard_test.go index 5883969..fc4dce4 100644 --- a/clipboard_test.go +++ b/clipboard_test.go @@ -9,7 +9,7 @@ import ( ) func TestCopyAndPaste(t *testing.T) { - expected := "日本語" + expected := "日本語\n" err := WriteAll(expected) if err != nil { diff --git a/clipboard_windows.go b/clipboard_windows.go index 4fc65fc..c0314c2 100644 --- a/clipboard_windows.go +++ b/clipboard_windows.go @@ -33,7 +33,7 @@ var ( globalSize = kernel32.NewProc("GlobalSize") globalLock = kernel32.NewProc("GlobalLock") globalUnlock = kernel32.NewProc("GlobalUnlock") - strcpy = kernel32.NewProc("lstrcpyA") + memcpy = kernel32.NewProc("RtlCopyMemory") ) // waitOpenClipboard opens the clipboard, waiting for up to a second to do so. @@ -65,7 +65,11 @@ func readAllWithFormat(cf uintptr) (string, error) { h, _, err := getClipboardData.Call(cf) if h == 0 { - return "", err + if err != syscall.Errno(0) { + return "", err + } + + return "", nil } size, _, err := globalSize.Call(h) @@ -75,7 +79,6 @@ func readAllWithFormat(cf uintptr) (string, error) { l, _, err := globalLock.Call(h) if l == 0 { - panic(err) return "", err } @@ -83,7 +86,6 @@ func readAllWithFormat(cf uintptr) (string, error) { r, _, err := globalUnlock.Call(h) if r == 0 { - panic(err) return "", err } @@ -105,7 +107,7 @@ func writeAllWithFormat(text string, cf uintptr) error { // "If the hMem parameter identifies a memory object, the object must have // been allocated using the function with the GMEM_MOVEABLE flag." - h, _, err := globalAlloc.Call(gmemMoveable, uintptr(len(data)*int(unsafe.Sizeof(data[0])))) + h, _, err := globalAlloc.Call(gmemMoveable, uintptr(len(data))) if h == 0 { return err } @@ -121,7 +123,7 @@ func writeAllWithFormat(text string, cf uintptr) error { return err } - r, _, err := strcpy.Call(l, uintptr(unsafe.Pointer(&data[0]))) + r, _, err := memcpy.Call(l, uintptr(unsafe.Pointer(&data[0])), uintptr(len(data))) if r == 0 { return err } diff --git a/cmd/goclip/.gitignore b/cmd/goclip/.gitignore new file mode 100644 index 0000000..87b5ffc --- /dev/null +++ b/cmd/goclip/.gitignore @@ -0,0 +1,3 @@ +bin +goclip +goclip.exe diff --git a/cmd/goclip/goclip.go b/cmd/goclip/goclip.go new file mode 100644 index 0000000..7f3a4a6 --- /dev/null +++ b/cmd/goclip/goclip.go @@ -0,0 +1,140 @@ +package main + +import ( + "encoding/json" + "flag" + "fmt" + "github.com/kiennq/clipboard" + "io/ioutil" + "os" + "strconv" +) + +const ( + HtmlMarkerBlock = "Version:0.9\n" + + "StartHTML:%010d\n" + + "EndHTML:%010d\n" + + "StartFragment:%010d\n" + + "EndFragment:%010d\n" + + HtmlHeader = "\n\n" + HtmlFooter = "\n\n" +) + +var ( + cfText uintptr = 1 +) + +func getHtmlBlock(htmlText string) string { + testPrefix := fmt.Sprintf(HtmlMarkerBlock, 0, 0, 0, 0) + markerBlockLen := len(testPrefix) // Should be always 100, can be optimized + headerLen := len(HtmlHeader) + footerLen := len(HtmlFooter) + prefix := fmt.Sprintf(HtmlMarkerBlock, + markerBlockLen, + markerBlockLen+headerLen+len(htmlText)+footerLen, + markerBlockLen+headerLen, + markerBlockLen+headerLen+len(htmlText)) + return prefix + HtmlHeader + htmlText + HtmlFooter +} + +func getHtmlClipboard() uintptr { + cf, err := clipboard.GetClipboardFormat("HTML Format") + if err != nil { + panic(err) + } + + return cf +} + +func getCfFromString(format string) uintptr { + cf := cfText + if format != "" { + atoiCf, err := strconv.Atoi(format) + cf = uintptr(atoiCf) + if err != nil { + // not integer, register new clipboard format + if cf, err = clipboard.GetClipboardFormat(format); err != nil { + panic(err) + } + } + } + + return cf +} + +func doCopy(dontClear bool) { + if !dontClear { + if err := clipboard.ClearClipboard(); err != nil { + panic(err) + } + } + + type Message struct { + Cf, Data string + } + + data, err := ioutil.ReadAll(os.Stdin) + if err != nil { + panic(err) + } + + var m []Message + if err := json.Unmarshal(data, &m); err != nil { + m = []Message{{"", string(data)}} + } + + for _, d := range m { + cf := getCfFromString(d.Cf) + if d.Data != "" { + switch d.Cf { + case "HTML Format": + d.Data = getHtmlBlock(d.Data) + } + + if err := clipboard.WriteAllWithFormat(d.Data, cf); err != nil { + panic(err) + } + } + } +} + +func doPaste(format string) { + cf := getCfFromString(format) + out, err := clipboard.ReadAllWithFormat(cf) + if err != nil { + panic(err) + } + + fmt.Println(out) +} + +func usage() { + fmt.Println("usage: goclip []") + fmt.Println("Available commands are:") + fmt.Println(" copy Copy to clipboard through stdin. The json format is [{cf:, data:},]") + fmt.Println(" paste Read from clipboard") +} + +func main() { + copyCmd := flag.NewFlagSet("copy", flag.ExitOnError) + dontClear := copyCmd.Bool("no-clear", false, "don't clear previous clipboard") + + pasteCmd := flag.NewFlagSet("paste", flag.ExitOnError) + format := pasteCmd.String("format", "", "paste from clipboard format. Can be string or integer.") + + flag.Usage = usage + flag.Parse() + + switch flag.Arg(0) { + case "copy": + copyCmd.Parse(os.Args[2:]) + doCopy(*dontClear) + case "paste": + pasteCmd.Parse(os.Args[2:]) + doPaste(*format) + default: + usage() + os.Exit(2) + } +} diff --git a/cmd/goclipboard/.gitignore b/cmd/goclipboard/.gitignore deleted file mode 100644 index 27a81e7..0000000 --- a/cmd/goclipboard/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -bin -goclipboard -goclipboard.exe \ No newline at end of file diff --git a/cmd/goclipboard/goclipboard.go b/cmd/goclipboard/goclipboard.go deleted file mode 100644 index da5b1c4..0000000 --- a/cmd/goclipboard/goclipboard.go +++ /dev/null @@ -1,94 +0,0 @@ -package main - -import ( - "flag" - "fmt" - "github.com/kiennq/clipboard" - "os" - "encoding/json" - "io" -) - -const ( - HtmlMarkerBlock = "Version:0.9\n" + - "StartHTML:%010d\n" + - "EndHTML:%010d\n" + - "StartFragment:%010d\n" + - "EndFragment:%010d\n" - - HtmlHeader = "\n\n" - HtmlFooter = "\n\n" -) - -var ( - cfText uintptr = 1 - cfHtml = getHtmlClipboard() -) - -func getHtmlBlock(htmlText string) string { - testPrefix := fmt.Sprintf(HtmlMarkerBlock, 0, 0, 0, 0) - markerBlockLen := len(testPrefix) // Should be always 100, can be optimized - headerLen := len(HtmlHeader) - footerLen := len(HtmlFooter) - prefix := fmt.Sprintf(HtmlMarkerBlock, - markerBlockLen, - markerBlockLen+headerLen+len(htmlText)+footerLen, - markerBlockLen+headerLen, - markerBlockLen+headerLen+len(htmlText)) - return prefix + HtmlHeader + htmlText + HtmlFooter -} - -func getHtmlClipboard() uintptr { - cf, err := clipboard.GetClipboardFormat("HTML Format") - if err != nil { - panic(err) - } - - return cf -} - -func main() { - htmlVal := flag.String("html", "", "html format text") - textVal := flag.String("text", "", "normal text") - useStdin := flag.Bool("in", false, "using stdin as input, the input format is json {text:, htmlText:}") - doClear := flag.Bool("clear", true, "clear previous clipboard") - - flag.Parse() - - htmlText := *htmlVal - text := *textVal - if *useStdin { - type Message struct { - Text, HtmlText string - } - - dec := json.NewDecoder(os.Stdin) - var m Message - if err := dec.Decode(&m); err != nil && err != io.EOF { - panic(err) - } - - htmlText = m.HtmlText - text = m.Text - } - - htmlBlock := getHtmlBlock(htmlText) - - if *doClear { - if err := clipboard.ClearClipboard(); err != nil { - panic(err) - } - } - - if htmlText != "" { - if err := clipboard.WriteAllWithFormat(htmlBlock, cfHtml); err != nil { - panic(err) - } - } - - if text != "" { - if err := clipboard.WriteAllWithFormat(text, cfText); err != nil { - panic(err) - } - } -} From ac0d6b7d5d66eb26403b3cb77acc36a4e10b03ec Mon Sep 17 00:00:00 2001 From: Kien Nguyen Date: Thu, 14 Jun 2018 00:55:51 +0900 Subject: [PATCH 5/5] make linux and darwin compilable with new interface --- clipboard_darwin.go | 16 ++++++++++++++++ clipboard_unix.go | 16 ++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/clipboard_darwin.go b/clipboard_darwin.go index 6f33078..1845af9 100644 --- a/clipboard_darwin.go +++ b/clipboard_darwin.go @@ -32,6 +32,10 @@ func readAll() (string, error) { return string(out), nil } +func readAllWithFormat(_ uintptr) (string, error) { + return readAll() +} + func writeAll(text string) error { copyCmd := getCopyCommand() in, err := copyCmd.StdinPipe() @@ -50,3 +54,15 @@ func writeAll(text string) error { } return copyCmd.Wait() } + +func writeAllWithFormat(text string, _ uintptr) error { + return writeAll(text) +} + +func clearClipboard() error { + return nil +} + +func getClipboardFormat(_ string) (uintptr, error) { + return 0, nil +} diff --git a/clipboard_unix.go b/clipboard_unix.go index 0acd5fa..2b74e27 100644 --- a/clipboard_unix.go +++ b/clipboard_unix.go @@ -75,6 +75,10 @@ func readAll() (string, error) { return string(out), nil } +func readAllWithFormat(_ uintptr) (string, error) { + return readAll() +} + func writeAll(text string) error { if Unsupported { return missingCommands @@ -96,3 +100,15 @@ func writeAll(text string) error { } return copyCmd.Wait() } + +func writeAllWithFormat(text string, _ uintptr) error { + return writeAll(text) +} + +func clearClipboard() error { + return nil +} + +func getClipboardFormat(_ string) (uintptr, error) { + return 0, nil +}