From f5c4671bfbad96bf346bd7e9a21fc4317b4959df Mon Sep 17 00:00:00 2001 From: Indrajith K L Date: Sat, 3 Dec 2022 17:00:20 +0530 Subject: Adds most of the tools --- v_windows/v/vlib/clipboard/clipboard_windows.c.v | 186 +++++++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 v_windows/v/vlib/clipboard/clipboard_windows.c.v (limited to 'v_windows/v/vlib/clipboard/clipboard_windows.c.v') diff --git a/v_windows/v/vlib/clipboard/clipboard_windows.c.v b/v_windows/v/vlib/clipboard/clipboard_windows.c.v new file mode 100644 index 0000000..9ae42d1 --- /dev/null +++ b/v_windows/v/vlib/clipboard/clipboard_windows.c.v @@ -0,0 +1,186 @@ +module clipboard + +import time + +#include +#flag -luser32 + +struct WndClassEx { + cb_size u32 + style u32 + lpfn_wnd_proc voidptr + cb_cls_extra int + cb_wnd_extra int + h_instance C.HINSTANCE + h_icon C.HICON + h_cursor C.HCURSOR + hbr_background C.HBRUSH + lpsz_menu_name &u16 // LPCWSTR + lpsz_class_name &u16 + h_icon_sm &u16 +} + +fn C.RegisterClassEx(class &WndClassEx) int + +fn C.GetClipboardOwner() &C.HWND + +fn C.CreateWindowEx(dwExStyle i64, lpClassName &u16, lpWindowName &u16, dwStyle i64, x int, y int, nWidth int, nHeight int, hWndParent i64, hMenu voidptr, h_instance voidptr, lpParam voidptr) &C.HWND + +// fn C.MultiByteToWideChar(CodePage u32, dw_flags u16, lpMultiByteStr byteptr, cbMultiByte int, lpWideCharStr u16, cchWideChar int) int +fn C.EmptyClipboard() + +fn C.CloseClipboard() + +fn C.GlobalAlloc(uFlag u32, size i64) C.HGLOBAL + +fn C.GlobalFree(buf C.HGLOBAL) + +fn C.GlobalLock(buf C.HGLOBAL) voidptr + +fn C.GlobalUnlock(buf C.HGLOBAL) bool + +fn C.SetClipboardData(uFormat u32, data voidptr) C.HANDLE + +fn C.GetClipboardData(uFormat u32) C.HANDLE + +fn C.DefWindowProc(hwnd C.HWND, msg u32, wParam C.WPARAM, lParam C.LPARAM) C.LRESULT + +fn C.SetLastError(error i64) + +fn C.OpenClipboard(hwnd C.HWND) int + +fn C.DestroyWindow(hwnd C.HWND) + +struct Clipboard { + max_retries int + retry_delay int +mut: + hwnd C.HWND + foo int // TODO remove +} + +fn (cb &Clipboard) get_clipboard_lock() bool { + mut retries := cb.max_retries + mut last_error := u32(0) + for { + retries-- + if retries < 0 { + break + } + last_error = C.GetLastError() + if C.OpenClipboard(cb.hwnd) > 0 { + return true + } else if last_error != u32(C.ERROR_ACCESS_DENIED) { + return false + } + time.sleep(cb.retry_delay * time.second) + } + C.SetLastError(last_error) + return false +} + +fn new_clipboard() &Clipboard { + mut cb := &Clipboard{ + max_retries: 5 + retry_delay: 5 + } + class_name := 'clipboard' + wndclass := WndClassEx{ + cb_size: sizeof(WndClassEx) + lpfn_wnd_proc: voidptr(&C.DefWindowProc) + lpsz_class_name: class_name.to_wide() + lpsz_menu_name: 0 + h_icon_sm: 0 + } + if C.RegisterClassEx(&wndclass) == 0 && C.GetLastError() != u32(C.ERROR_CLASS_ALREADY_EXISTS) { + println('Failed registering class.') + } + hwnd := C.CreateWindowEx(0, wndclass.lpsz_class_name, wndclass.lpsz_class_name, 0, + 0, 0, 0, 0, C.HWND_MESSAGE, C.NULL, C.NULL, C.NULL) + if hwnd == C.NULL { + println('Error creating window!') + } + cb.hwnd = hwnd + return cb +} + +pub fn (cb &Clipboard) check_availability() bool { + return cb.hwnd != C.HWND(C.NULL) +} + +pub fn (cb &Clipboard) has_ownership() bool { + return C.GetClipboardOwner() == cb.hwnd +} + +pub fn (mut cb Clipboard) clear() { + if !cb.get_clipboard_lock() { + return + } + C.EmptyClipboard() + C.CloseClipboard() + cb.foo = 0 +} + +pub fn (mut cb Clipboard) free() { + C.DestroyWindow(cb.hwnd) + cb.foo = 0 +} + +// the string.to_wide doesn't work with SetClipboardData, don't know why +fn to_wide(text string) C.HGLOBAL { + len_required := C.MultiByteToWideChar(C.CP_UTF8, C.MB_ERR_INVALID_CHARS, text.str, + text.len + 1, C.NULL, 0) + buf := C.GlobalAlloc(C.GMEM_MOVEABLE, i64(sizeof(u16)) * len_required) + if buf != C.HGLOBAL(C.NULL) { + mut locked := &u16(C.GlobalLock(buf)) + C.MultiByteToWideChar(C.CP_UTF8, C.MB_ERR_INVALID_CHARS, text.str, text.len + 1, + locked, len_required) + unsafe { + locked[len_required - 1] = u16(0) + } + C.GlobalUnlock(buf) + } + return buf +} + +pub fn (mut cb Clipboard) set_text(text string) bool { + cb.foo = 0 + buf := to_wide(text) + if !cb.get_clipboard_lock() { + C.GlobalFree(buf) + return false + } else { + // EmptyClipboard must be called to properly update clipboard ownership + C.EmptyClipboard() + if C.SetClipboardData(C.CF_UNICODETEXT, buf) == C.HANDLE(C.NULL) { + println('SetClipboardData: Failed.') + C.CloseClipboard() + C.GlobalFree(buf) + return false + } + } + // CloseClipboard appears to change the sequence number... + C.CloseClipboard() + return true +} + +pub fn (mut cb Clipboard) get_text() string { + cb.foo = 0 + if !cb.get_clipboard_lock() { + return '' + } + h_data := C.GetClipboardData(C.CF_UNICODETEXT) + if h_data == C.HANDLE(C.NULL) { + C.CloseClipboard() + return '' + } + str := unsafe { string_from_wide(&u16(C.GlobalLock(C.HGLOBAL(h_data)))) } + C.GlobalUnlock(C.HGLOBAL(h_data)) + return str +} + +// new_primary returns a new X11 `PRIMARY` type `Clipboard` instance allocated on the heap. +// Please note: new_primary only works on X11 based systems. +pub fn new_primary() &Clipboard { + panic('Primary clipboard is not supported on non-Linux systems.') +} -- cgit v1.2.3