Browse Source

Merge pull request #4158 from sqrt-negativeone/master

Win32 clipboard procedures
Jeroen van Rijn 11 months ago
parent
commit
17d10b72d5

+ 3 - 0
core/sys/windows/kernel32.odin

@@ -400,6 +400,9 @@ foreign kernel32 {
 	GlobalAlloc :: proc(flags: UINT, bytes: SIZE_T) -> LPVOID ---
 	GlobalReAlloc :: proc(mem: LPVOID, bytes: SIZE_T, flags: UINT) -> LPVOID ---
 	GlobalFree :: proc(mem: LPVOID) -> LPVOID ---
+	
+	GlobalLock :: proc(hMem: HGLOBAL) -> LPVOID ---
+	GlobalUnlock :: proc(hMem: HGLOBAL) -> BOOL ---
 
 	ReadDirectoryChangesW :: proc(
 		hDirectory: HANDLE,

+ 35 - 0
core/sys/windows/user32.odin

@@ -305,6 +305,13 @@ foreign user32 {
 
 	GetProcessWindowStation :: proc() -> HWINSTA ---
 	GetUserObjectInformationW :: proc(hObj: HANDLE, nIndex: GetUserObjectInformationFlags, pvInfo: PVOID, nLength: DWORD, lpnLengthNeeded: LPDWORD) -> BOOL ---
+	
+	OpenClipboard :: proc(hWndNewOwner: HWND) -> BOOL ---
+	CloseClipboard :: proc() -> BOOL ---
+	GetClipboardData :: proc(uFormat: UINT) -> HANDLE ---
+	SetClipboardData :: proc(uFormat: UINT, hMem: HANDLE) -> HANDLE ---
+	IsClipboardFormatAvailable :: proc(format: UINT) -> BOOL ---
+	EmptyClipboard :: proc() -> BOOL ---
 }
 
 CreateWindowW :: #force_inline proc "system" (
@@ -746,3 +753,31 @@ WinEventFlag :: enum DWORD {
 	SKIPOWNPROCESS = 1,
 	INCONTEXT      = 2,
 }
+
+// Standard Clipboard Formats
+CF_TEXT            :: 1
+CF_BITMAP          :: 2
+CF_METAFILEPICT    :: 3
+CF_SYLK            :: 4
+CF_DIF             :: 5
+CF_TIFF            :: 6
+CF_OEMTEXT         :: 7
+CF_DIB             :: 8
+CF_PALETTE         :: 9
+CF_PENDATA         :: 10
+CF_RIFF            :: 11
+CF_WAVE            :: 12
+CF_UNICODETEXT     :: 13
+CF_ENHMETAFILE     :: 14
+CF_HDROP           :: 15
+CF_LOCALE          :: 16
+CF_DIBV5           :: 17
+CF_DSPBITMAP       :: 0x0082
+CF_DSPENHMETAFILE  :: 0x008E
+CF_DSPMETAFILEPICT :: 0x0083
+CF_DSPTEXT         :: 0x0081
+CF_GDIOBJFIRST     :: 0x0300
+CF_GDIOBJLAST      :: 0x03FF
+CF_OWNERDISPLAY    :: 0x0080
+CF_PRIVATEFIRST    :: 0x0200
+CF_PRIVATELAST     :: 0x02FF

+ 55 - 0
tests/core/sys/windows/test_clipboard.odin

@@ -0,0 +1,55 @@
+//+build windows
+package test_core_sys_windows
+
+import "core:testing"
+import win32 "core:sys/windows"
+import "base:runtime"
+import "core:strings"
+import "core:mem"
+
+read_from_clipboard :: proc(wnd_handle: win32.HWND, allocator: runtime.Allocator) -> (result: string, ok: win32.BOOL) {
+	win32.IsClipboardFormatAvailable(win32.CF_TEXT) or_return
+	
+	win32.OpenClipboard(wnd_handle) or_return
+	defer win32.CloseClipboard()
+	
+	clipboard_data := win32.GetClipboardData(win32.CF_TEXT)
+	if clipboard_data != nil {
+		if cstr := cstring(win32.GlobalLock(win32.HGLOBAL(clipboard_data))); cstr != nil {
+			result = strings.clone_from_cstring(cstr, allocator)
+		ok = true
+		}
+		win32.GlobalUnlock(win32.HGLOBAL(clipboard_data))
+	}
+	return
+}
+
+write_to_clipboard :: proc(wnd_handle: win32.HWND, text: string) -> win32.BOOL {
+	win32.OpenClipboard(wnd_handle) or_return
+	defer win32.CloseClipboard()
+	win32.EmptyClipboard()
+	
+	h_mem := win32.HGLOBAL(win32.GlobalAlloc(win32.GMEM_MOVEABLE, len(text) + 1))
+	if h_mem == nil {return false}
+	
+	cstr_dst := cast([^]u8)win32.GlobalLock(h_mem)
+	defer win32.GlobalUnlock(h_mem)
+	if cstr_dst == nil {return false}
+	
+	mem.copy(rawptr(cstr_dst), raw_data(text), len(text))
+	cstr_dst[len(text)] = 0
+	
+	win32.SetClipboardData(win32.CF_TEXT, win32.HANDLE(h_mem))
+	return true
+}
+
+
+@(test)
+verify_win32_clipboard :: proc(t: ^testing.T) {
+	ok1 := write_to_clipboard(nil, "Hello everynyan! OH MY GAH")
+	testing.expect_value(t, ok1, true)
+	
+	clipboard_content, ok2 := read_from_clipboard(nil, context.temp_allocator)
+	testing.expect_value(t, ok2, true)
+	testing.expect_value(t, clipboard_content, "Hello everynyan! OH MY GAH")
+}