summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPietro Gagliardi <[email protected]>2014-07-17 19:36:24 -0400
committerPietro Gagliardi <[email protected]>2014-07-17 19:36:24 -0400
commit0adac4d3ca1ec91e6364fe11276323803418c2ff (patch)
tree5160d2aa05131638ff2f4662627cb967c3b5407b
parent257fd8f07c821a9dd1f879e94c703cbbb9a2c764 (diff)
Began the drudgery of converting all the Windows code to use cgo, because I'm not going to wait to debug this smashed stack.
-rw-r--r--redo/common_windows.go14
-rw-r--r--redo/uitask_windows.c78
-rw-r--r--redo/uitask_windows.go77
-rw-r--r--redo/winapi_windows.h27
4 files changed, 131 insertions, 65 deletions
diff --git a/redo/common_windows.go b/redo/common_windows.go
index 30c0d75..b1fa0ee 100644
--- a/redo/common_windows.go
+++ b/redo/common_windows.go
@@ -8,8 +8,18 @@ import (
"unsafe"
)
-// TODO get rid of this when we actually use s_POINT somewhere
-var dummyToFoolwinconstgen s_POINT
+// #include "winapi_windows.h"
+import "C"
+
+//export xpanic
+func xpanic(msg *C.char, lasterr C.DWORD) {
+ panic(fmt.Errorf("%s: %s", C.GoString(msg), syscall.Errno(lasterr))
+}
+
+//export xmissedmsg
+func xmissedmsg(purpose *C.char, f *C.char, uMsg C.UINT) {
+ panic(fmt.Errorf("%s window procedure message %d does not return a value (bug in %s)", C.GoString(purpose), uMsg, C.GoString(f)))
+}
func getWindowText(hwnd uintptr) string {
// WM_GETTEXTLENGTH and WM_GETTEXT return the count /without/ the terminating null character
diff --git a/redo/uitask_windows.c b/redo/uitask_windows.c
new file mode 100644
index 0000000..9177e19
--- /dev/null
+++ b/redo/uitask_windows.c
@@ -0,0 +1,78 @@
+/* 17 july 2014 */
+
+#include "winapi_windows.h"
+#include "_cgo_export.h"
+
+void uimsgloop(void)
+{
+ MSG msg;
+ int res;
+
+ for (;;) {
+ SetLastError(0);
+ res = GetMessage(&msg, NULL, 0, 0);
+ if (res < 0)
+ xpanic("error calling GetMessage()", GetLastError());
+ if (res == 0) /* WM_QUIT */
+ break;
+ /* TODO IsDialogMessage() */
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+}
+
+void issue(void *request)
+{
+ SetLastError(0);
+ if (PostMessage(msgwin, msgRequested, 0, (LPARAM) request) == 0)
+ xpanic("error issuing request", GetLastError());
+}
+
+HWND msgwin;
+
+#define msgwinclass L"gouimsgwin"
+
+static LRESULT CALLBACK msgwinproc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch (uMsg) {
+ case WM_COMMAND:
+ return forwardCommand(hwnd, uMsg, wParam, lParam);
+ case msgRequested:
+ xperform((void *) lParam);
+ return 0;
+ default:
+ return DefWindowProc(hwnd, uMsg, wParam, lParam);
+ }
+ xmissedmsg("message-only", "msgwinproc()", uMsg);
+ return 0; /* unreachable */
+}
+
+DWORD makemsgwin(char **errmsg)
+{
+ WNDCLASS wc;
+ HWND hwnd;
+
+ ZeroMemory(&wc, sizeof (WNDCLASS));
+ wc.lpfnWndProc = msgwinproc;
+ wc.hInstance = hInstance;
+ wc.hIcon = hDefaultIcon;
+ wc.hCursor = hArrowCursor;
+ wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1);
+ wc.lpszClassName = msgwinclass;
+ if (RegisterClass(&wc) == 0) {
+ *errmsg = "error registering message-only window classs";
+ return GetLastError();
+ }
+ msgwin = CreateWindowEx(
+ 0,
+ msgwinclass, L"package ui message-only window",
+ 0,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ HWND_MESSAGE, NULL, hInstance, NULL);
+ if (msgwin == NULL) {
+ *errmsg = "error creating message-only window";
+ return GetLastError();
+ }
+ return 0;
+}
diff --git a/redo/uitask_windows.go b/redo/uitask_windows.go
index 15f4048..69d6906 100644
--- a/redo/uitask_windows.go
+++ b/redo/uitask_windows.go
@@ -8,13 +8,11 @@ import (
"unsafe"
)
-// global messages unique to everything
-const (
- msgRequest = c_WM_APP + 1 + iota // + 1 just to be safe
- msgCOMMAND // WM_COMMAND proxy; see forwardCommand() in controls_windows.go
-)
+// #cgo LDFLAGS: -luser32 -lkernel32 -lgdi32
+// #include "winapi_windows.h"
+import "C"
-var msgwin uintptr
+var msgwin C.HWND
func uiinit() error {
if err := initWindows(); err != nil {
@@ -33,20 +31,7 @@ func uiinit() error {
}
func uimsgloop() {
- var msg s_MSG
-
- for {
- res, err := f_GetMessageW(&msg, hNULL, 0, 0)
- if res < 0 {
- panic(fmt.Errorf("error calling GetMessage(): %v", err))
- }
- if res == 0 { // WM_QUIT
- break
- }
- // TODO IsDialogMessage()
- f_TranslateMessage(&msg)
- f_DispatchMessageW(&msg)
- }
+ C.uimsgloop()
}
func uistop() {
@@ -54,55 +39,21 @@ func uistop() {
}
func issue(req *Request) {
- res, err := f_PostMessageW(
- msgwin,
- msgRequest,
- 0,
- t_LPARAM(uintptr(unsafe.Pointer(req))))
- if res == 0 {
- panic(fmt.Errorf("error issuing request: %v", err))
- }
+ C.issue(unsafe.Pointer(req))
}
-const msgwinclass = "gouimsgwin"
-
func makemsgwin() error {
- var wc s_WNDCLASSW
+ var errmsg *C.char
- wc.lpfnWndProc = syscall.NewCallback(msgwinproc)
- wc.hInstance = hInstance
- wc.hIcon = hDefaultIcon
- wc.hCursor = hArrowCursor
- wc.hbrBackground = c_COLOR_BTNFACE + 1
- wc.lpszClassName = syscall.StringToUTF16Ptr(msgwinclass)
- res, err := f_RegisterClassW(&wc)
- if res == 0 {
- return fmt.Errorf("error registering message-only window class: %v", err)
- }
- msgwin, err = f_CreateWindowExW(
- 0,
- wc.lpszClassName,
- syscall.StringToUTF16Ptr("package ui message-only window"),
- 0,
- c_CW_USEDEFAULT, c_CW_USEDEFAULT,
- c_CW_USEDEFAULT, c_CW_USEDEFAULT,
- c_HWND_MESSAGE, hNULL, hInstance, nil)
- if msgwin == hNULL {
- return fmt.Errorf("error creating message-only window: %v", err)
+ err := C.makemsgwin(&errmsg)
+ if err != 0 || errmsg != nil {
+ return fmt.Errorf("%s: %v", C.GoString(errmsg), syscall.Errno(err))
}
return nil
}
-func msgwinproc(hwnd uintptr, uMsg t_UINT, wParam t_WPARAM, lParam t_LPARAM) t_LRESULT {
- switch uMsg {
- case c_WM_COMMAND:
- return forwardCommand(hwnd, uMsg, wParam, lParam)
- case msgRequest:
- req := (*Request)(unsafe.Pointer(uintptr(lParam)))
- perform(req)
- return 0
- default:
- return f_DefWindowProcW(hwnd, uMsg, wParam, lParam)
- }
- panic(fmt.Errorf("message-only window procedure does not return a value for message %d (bug in msgwinproc())", uMsg))
+//export xperform
+func xperform(xreq unsafe.Pointer) {
+ req := (*Request)(xreq)
+ perform(req)
}
diff --git a/redo/winapi_windows.h b/redo/winapi_windows.h
new file mode 100644
index 0000000..59b99fe
--- /dev/null
+++ b/redo/winapi_windows.h
@@ -0,0 +1,27 @@
+/* 17 july 2014 */
+
+#define UNICODE
+#define _UNICODE
+#define STRICT
+#define STRICT_TYPED_ITEMIDS
+/* get Windows version right; right now Windows XP */
+#define WINVER 0x0501
+#define _WIN32_WINNT 0x0501
+#define _WIN32_WINDOWS 0x0501 /* according to Microsoft's winperf.h */
+#define _WIN32_IE 0x0600 /* according to Microsoft's sdkddkver.h */
+#define NTDDI_VERSION 0x05010000 /* according to Microsoft's sdkddkver.h */
+#include <windows.h>
+#include <commctrl.h>
+#include <stdint.h>
+
+/* global messages unique to everything */
+enum {
+ msgRequest = WM_APP + 1, /* + 1 just to be safe */
+ msgCOMMAND, /* WM_COMMAND proxy; see forwardCommand() in controls_windows.go */
+};
+
+/* uitask_windows.c */
+extern void uimsgloop(void);
+extern void issue(void *);
+extern HWND msgwin;
+extern DWORD makemsgwin(char **);