Began the drudgery of converting all the Windows code to use cgo, because I'm not going to wait to debug this smashed stack.

This commit is contained in:
Pietro Gagliardi 2014-07-17 19:36:24 -04:00
parent 257fd8f07c
commit 0adac4d3ca
4 changed files with 131 additions and 65 deletions

View File

@ -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

78
redo/uitask_windows.c Normal file
View File

@ -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;
}

View File

@ -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)
}

27
redo/winapi_windows.h Normal file
View File

@ -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 **);