You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

160 lines
3.8 KiB
Go

package clipboard
import (
"b612.me/win32api"
"fmt"
"runtime"
)
var winformat = map[win32api.DWORD]string{
1: "CF_TEXT",
2: "CF_BITMAP",
3: "CF_METAFILEPICT",
4: "CF_SYLK",
5: "CF_DIF",
6: "CF_TIFF",
7: "CF_OEMTEXT",
8: "CF_DIB",
9: "CF_PALETTE",
10: "CF_PENDATA",
11: "CF_RIFF",
12: "CF_WAVE",
13: "CF_UNICODETEXT",
14: "CF_ENHMETAFILE",
15: "CF_HDROP",
16: "CF_LOCALE",
17: "CF_DIBV5",
130: "CF_DSPBITMAP",
129: "CF_DSPTEXT",
131: "CF_DSPMETAFILEPICT",
142: "CF_DSPENHMETAFILE",
0x03FF: "CF_GDIOBJLAST",
0x0200: "CF_PRIVATEFIRST",
}
var formatRank = map[string]int{
"CF_UNICODETEXT": 1,
"CF_DIBV5": 2,
//"CF_DIB": 2,
"PNG": 2,
"HTML Format": 3,
"CF_HDROP": 4,
}
func Get() (Clipboard, error) {
return innerGetClipboard(true)
}
func GetMeta() (Clipboard, error) {
return innerGetClipboard(false)
}
func innerGetClipboard(withFetch bool) (Clipboard, error) {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
var tmpData interface{}
var c = Clipboard{
plateform: "windows",
}
err := win32api.OpenClipboard(0)
if err != nil {
return c, fmt.Errorf("OpenClipboard error: %v", err)
}
defer win32api.CloseClipboard()
formats, err := win32api.GetUpdatedClipboardFormatsAll()
if err != nil {
return c, fmt.Errorf("GetUpdatedClipboardFormatsAll error: %v", err)
}
var firstFormatName, secondFormatName string
var firstFormat, secondFormat int = 65535, 65535
for _, format := range formats {
if d, ok := winformat[format]; ok {
if formatRank[d] > 0 {
if formatRank[d] < firstFormat {
secondFormat = firstFormat
secondFormatName = firstFormatName
firstFormat = formatRank[d]
firstFormatName = d
} else if formatRank[d] != firstFormat && formatRank[d] < secondFormat {
secondFormat = formatRank[d]
secondFormatName = d
}
}
c.winOriginTypes = append(c.winOriginTypes, d)
continue
}
d, e := win32api.GetClipboardFormatName(format)
if e != nil {
continue
}
if formatRank[d] > 0 {
if formatRank[d] < firstFormat {
secondFormat = firstFormat
secondFormatName = firstFormatName
firstFormat = formatRank[d]
firstFormatName = d
} else if formatRank[d] != firstFormat && formatRank[d] < secondFormat {
secondFormat = formatRank[d]
secondFormatName = d
}
}
c.winOriginTypes = append(c.winOriginTypes, d)
}
c.primaryOriType = firstFormatName
switch c.primaryOriType {
case "CF_UNICODETEXT":
c.primaryType = Text
case "HTML Format":
c.primaryType = HTML
case "PNG", "CF_DIBV5", "CF_DIB":
c.primaryType = Image
case "CF_HDROP":
c.primaryType = File
}
if withFetch {
tmpData, err = AutoFetcher(firstFormatName)
if err != nil {
return c, fmt.Errorf("AutoFetcher error: %v", err)
}
c.primaryData = tmpData.([]byte)
c.primarySize = len(c.primaryData)
} else {
c.primarySize, err = ClipSize(firstFormatName)
if err != nil {
return c, fmt.Errorf("ClipSize error: %v", err)
}
}
if secondFormatName != "" {
switch secondFormatName {
case "CF_UNICODETEXT":
c.secondaryType = Text
case "HTML Format":
c.secondaryType = HTML
case "PNG", "CF_DIBV5", "CF_DIB":
c.secondaryType = Image
case "CF_HDROP":
c.secondaryType = File
}
c.secondaryOriType = secondFormatName
if withFetch {
tmpData, err = AutoFetcher(secondFormatName)
if err != nil {
return c, fmt.Errorf("AutoFetcher error: %v", err)
}
c.secondaryData = tmpData.([]byte)
c.secondarySize = len(c.secondaryData)
} else {
c.secondarySize, err = ClipSize(secondFormatName)
if err != nil {
return c, fmt.Errorf("ClipSize error: %v", err)
}
}
if err != nil {
return c, fmt.Errorf("AutoFetcher error: %v", err)
}
}
return c, nil
}