package cliprdr import ( "fmt" "strings" ) // Windows "HTML Format" 剪贴板编解码(MS-Doc: HTML Clipboard Format)。 // // 字节流 = 固定文本头 + HTML 文档。头共 5 行、每行 \r\n 结尾: // // Version:0.9\r\n (13 字节) // StartHTML:0000000105\r\n (22 字节) // EndHTML:0000000256\r\n (20 字节) // StartFragment:0000000139\r\n (26 字节) // EndFragment:0000000222\r\n (24 字节) // // 偏移为 10 位零填充的十进制**字节**偏移(UTF-8)。固定头总长 105 字节。 const cfHTMLHeaderLen = 13 + 22 + 20 + 26 + 24 // 105 const cfHTMLWrapPrefix = "" const cfHTMLWrapSuffix = "" // EncodeCFHTML 把 HTML 片段(fragment)包装成 "HTML Format" 剪贴板字节流。 func EncodeCFHTML(fragment string) []byte { startHTML := cfHTMLHeaderLen startFragment := startHTML + len(cfHTMLWrapPrefix) endFragment := startFragment + len(fragment) endHTML := endFragment + len(cfHTMLWrapSuffix) head := fmt.Sprintf("Version:0.9\r\nStartHTML:%010d\r\nEndHTML:%010d\r\nStartFragment:%010d\r\nEndFragment:%010d\r\n", startHTML, endHTML, startFragment, endFragment) doc := cfHTMLWrapPrefix + fragment + cfHTMLWrapSuffix return []byte(head + doc) } // DecodeCFHTML 从 "HTML Format" 剪贴板字节流中提取 StartFragment 到 // EndFragment 之间的 HTML 内容。头部解析失败时回退为整段字符串。 func DecodeCFHTML(data []byte) string { s := string(data) lines := strings.Split(s, "\r\n") var startFragment, endFragment int = -1, -1 // 头最多 5 行;解析到两个 Fragment 偏移即可停止。 for i, ln := range lines { if i >= 5 { break } if v, ok := parseOffsetLine(ln, "StartFragment:"); ok { startFragment = v } else if v, ok := parseOffsetLine(ln, "EndFragment:"); ok { endFragment = v } if startFragment >= 0 && endFragment > startFragment && endFragment <= len(data) { break } } if startFragment < 0 || endFragment <= startFragment || endFragment > len(data) { // 回退:无有效偏移时原样返回(去除首行头部不可行,尽力而为) return s } return s[startFragment:endFragment] } func parseOffsetLine(line, key string) (int, bool) { if !strings.HasPrefix(line, key) { return 0, false } v := 0 for _, c := range line[len(key):] { if c < '0' || c > '9' { return 0, false } v = v*10 + int(c-'0') } return v, true }