summaryrefslogtreecommitdiff
path: root/redo
diff options
context:
space:
mode:
Diffstat (limited to 'redo')
-rw-r--r--redo/area_windows.c58
-rw-r--r--redo/area_windows.go19
-rw-r--r--redo/winapi_windows.h6
3 files changed, 69 insertions, 14 deletions
diff --git a/redo/area_windows.c b/redo/area_windows.c
index 58d8c56..9fc56ba 100644
--- a/redo/area_windows.c
+++ b/redo/area_windows.c
@@ -233,6 +233,26 @@ static void scrollArea(HWND hwnd, void *data, WPARAM wParam, int which)
dx = 0;
dy = delta;
}
+
+ // first move the edit control, if any, to avoid artifacting
+ if ((HWND) GetWindowLongPtrW(hwnd, 0) != NULL) {
+ HWND edit;
+ int x, y;
+
+ edit = (HWND) GetWindowLongPtrW(hwnd, 0);
+ x = (int) GetWindowLongPtrW(hwnd, sizeof (LONG_PTR));
+ y = (int) GetWindowLongPtrW(hwnd, 2 * sizeof (LONG_PTR));
+ x += dx;
+ y += dy;
+ if (SetWindowPos(edit, NULL, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER) == 0)
+ xpanic("error moving Area TextField in response to scroll", GetLastError());
+ SetWindowLongPtrW(hwnd, sizeof (LONG_PTR), (LONG_PTR) x);
+ SetWindowLongPtrW(hwnd, 2 * sizeof (LONG_PTR), (LONG_PTR) y);
+ // TODO doesn't work?
+ if (InvalidateRect(edit, NULL, TRUE) == 0)
+ xpanic("error marking Area TextField as needing redraw", GetLastError());
+ }
+
if (ScrollWindowEx(hwnd,
(int) dx, (int) dy,
// these four change what is scrolled and record info about the scroll; we're scrolling the whole client area and don't care about the returned information here
@@ -253,6 +273,9 @@ static void scrollArea(HWND hwnd, void *data, WPARAM wParam, int which)
// NOW redraw it
if (UpdateWindow(hwnd) == 0)
xpanic("error updating Area after scrolling", GetLastError());
+ if ((HWND) GetWindowLongPtrW(hwnd, 0) != NULL)
+ if (UpdateWindow((HWND) GetWindowLongPtrW(hwnd, 0)) == 0)
+ xpanic("error updating Area TextField after scrolling", GetLastError());
}
static void adjustAreaScrollbars(HWND hwnd, void *data)
@@ -411,7 +434,8 @@ DWORD makeAreaWindowClass(char **errmsg)
wc.hInstance = hInstance;
wc.hIcon = hDefaultIcon;
wc.hCursor = hArrowCursor,
- wc.hbrBackground = NULL; // no brush; we handle WM_ERASEBKGND
+ wc.hbrBackground = NULL; // no brush; we handle WM_ERASEBKGND
+ wc.cbWndExtra = 3 * sizeof (LONG_PTR); // text field handle, text field current x, text field current y
if (RegisterClassW(&wc) == 0) {
*errmsg = "error registering Area window class";
return GetLastError();
@@ -440,6 +464,7 @@ static LRESULT CALLBACK areaTextFieldSubProc(HWND hwnd, UINT uMsg, WPARAM wParam
switch (uMsg) {
case WM_KILLFOCUS:
ShowWindow(hwnd, SW_HIDE);
+ areaTextFieldDone((void *) data);
return (*fv_DefSubclassProc)(hwnd, uMsg, wParam, lParam);
case WM_NCDESTROY:
if ((*fv_RemoveWindowSubclass)(hwnd, areaTextFieldSubProc, id) == FALSE)
@@ -452,7 +477,7 @@ static LRESULT CALLBACK areaTextFieldSubProc(HWND hwnd, UINT uMsg, WPARAM wParam
return 0; // unreached
}
-HWND newAreaTextField(HWND area)
+HWND newAreaTextField(HWND area, void *goarea)
{
HWND tf;
@@ -460,11 +485,34 @@ HWND newAreaTextField(HWND area)
L"edit", L"",
textfieldStyle | WS_CHILD,
0, 0, 0, 0,
- area, // owner window
- NULL, hInstance, NULL);
+ area, NULL, hInstance, NULL);
if (tf == NULL)
xpanic("error making Area TextField", GetLastError());
- if ((*fv_SetWindowSubclass)(tf, areaTextFieldSubProc, 0, (DWORD_PTR) NULL) == FALSE)
+ if ((*fv_SetWindowSubclass)(tf, areaTextFieldSubProc, 0, (DWORD_PTR) goarea) == FALSE)
xpanic("error subclassing Area TextField to give it its own WM_KILLFOCUS handler", GetLastError());
return tf;
}
+
+void areaOpenTextField(HWND area, HWND textfield, int x, int y, int width, int height)
+{
+ int sx, sy;
+ int baseX, baseY;
+ LONG unused;
+
+ getScrollPos(area, &sx, &sy);
+ x += sx;
+ y += sy;
+ calculateBaseUnits(textfield, &baseX, &baseY, &unused);
+ width = MulDiv(width, baseX, 4);
+ height = MulDiv(height, baseY, 8);
+ if (MoveWindow(textfield, x, y, width, height, TRUE) == 0)
+ xpanic("error moving Area TextField in Area.OpenTextFieldAt()", GetLastError());
+ ShowWindow(textfield, SW_SHOW);
+ if (SetFocus(textfield) == NULL)
+ xpanic("error giving Area TextField focus", GetLastError());
+}
+
+void areaMarkTextFieldDone(HWND area)
+{
+ SetWindowLongPtrW(area, 0, (LONG_PTR) NULL);
+}
diff --git a/redo/area_windows.go b/redo/area_windows.go
index e2f4fb6..276a69e 100644
--- a/redo/area_windows.go
+++ b/redo/area_windows.go
@@ -20,6 +20,7 @@ type area struct {
clickCounter *clickCounter
textfield C.HWND
+ textfielddone *event
}
func makeAreaWindowClass() error {
@@ -36,10 +37,11 @@ func newArea(ab *areabase) Area {
a := &area{
areabase: ab,
clickCounter: new(clickCounter),
+ textfielddone: newEvent(),
}
a._hwnd = C.newArea(unsafe.Pointer(a))
a.SetSize(a.width, a.height)
- a.textfield = C.newAreaTextField(a._hwnd)
+ a.textfield = C.newAreaTextField(a._hwnd, unsafe.Pointer(a))
C.controlSetControlFont(a.textfield)
return a
}
@@ -76,9 +78,7 @@ func (a *area) OpenTextFieldAt(x, y int) {
if x < 0 || x >= a.width || y < 0 || y >= a.height {
panic(fmt.Errorf("point (%d,%d) outside Area in Area.OpenTextFieldAt()", x, y))
}
- C.moveWindow(a.textfield, C.int(x), C.int(y), C.int(200), C.int(20))
- C.ShowWindow(a.textfield, C.SW_SHOW)
- // TODO SetFocus
+ C.areaOpenTextField(a._hwnd, a.textfield, C.int(x), C.int(y), textfieldWidth, textfieldHeight)
}
func (a *area) TextFieldText() string {
@@ -88,12 +88,17 @@ func (a *area) TextFieldText() string {
func (a *area) SetTextFieldText(text string) {
t := toUTF16(text)
C.setWindowText(a.textfield, t)
- // TODO
-// c.settextlen(C.controlTextLength(hwnd, t))
}
func (a *area) OnTextFieldDismissed(f func()) {
- // TODO
+ a.textfielddone.set(f)
+}
+
+//export areaTextFieldDone
+func areaTextFieldDone(data unsafe.Pointer) {
+ a := (*area)(data)
+ C.areaMarkTextFieldDone(a._hwnd)
+ a.textfielddone.fire()
}
//export doPaint
diff --git a/redo/winapi_windows.h b/redo/winapi_windows.h
index e92cca3..ed7caa0 100644
--- a/redo/winapi_windows.h
+++ b/redo/winapi_windows.h
@@ -124,12 +124,14 @@ extern DWORD makeContainerWindowClass(char **);
extern HWND newContainer(void *);
extern void calculateBaseUnits(HWND, int *, int *, LONG *);
-// area_window.c
+// area_windows.c
#define areaWindowClass L"gouiarea"
extern void repaintArea(HWND, RECT *);
extern DWORD makeAreaWindowClass(char **);
extern HWND newArea(void *);
-extern HWND newAreaTextField(HWND);
+extern HWND newAreaTextField(HWND, void *);
+extern void areaOpenTextField(HWND, HWND, int, int, int, int);
+extern void areaMarkTextFieldDone(HWND);
// imagelist_windows.c
extern HBITMAP unscaledBitmap(void *, intptr_t, intptr_t);