1 /* $Id$ $Revision$ */
2 /* vim:set shiftwidth=4 ts=8: */
3
4 /*************************************************************************
5 * Copyright (c) 2011 AT&T Intellectual Property
6 * All rights reserved. This program and the accompanying materials
7 * are made available under the terms of the Eclipse Public License v1.0
8 * which accompanies this distribution, and is available at
9 * http://www.eclipse.org/legal/epl-v10.html
10 *
11 * Contributors: See CVS logs. Details at http://www.graphviz.org/
12 *************************************************************************/
13
14 /* Lefteris Koutsofios - AT&T Labs Research */
15
16 #include "common.h"
17 #include "g.h"
18 #include "gcommon.h"
19 #include "mem.h"
20
21 #define WCU widget->u.c
22 #define WVU widget->u.v
23
24 FILE *Gxfp;
25 int Gxfd;
26 int Gpopdownflag;
27 int Gdepth;
28 int Gnocallbacks;
29 int menuselected;
30 int menupoped;
31
32 char *Gbufp = NULL;
33 int Gbufn = 0, Gbufi = 0;
34
35 PIXpoint_t *Gppp;
36 int Gppn, Gppi;
37
38 Gfont_t *Gfontp;
39 int Gfontn;
40
41 static HFONT deffont;
42 static int twobmouse;
43 static HWND palettechanged;
44
45 LRESULT CALLBACK LeftyWndProc (HWND, UINT, WPARAM, LPARAM);
46 LRESULT CALLBACK ArrayWndProc (HWND, UINT, WPARAM, LPARAM);
47 LRESULT CALLBACK CanvasWndProc (HWND, UINT, WPARAM, LPARAM);
48 LRESULT CALLBACK LabelWndProc (HWND, UINT, WPARAM, LPARAM);
49 LRESULT CALLBACK ScrollWndProc (HWND, UINT, WPARAM, LPARAM);
50
51 static void processcommand (Gwidget_t *, WPARAM, LPARAM);
52 static void handleresize (Gwidget_t *);
53
Ginitgraphics(void)54 int Ginitgraphics (void) {
55 WNDCLASS wc;
56 HDC hdc;
57 ATOM rtn;
58
59 if (!hprevinstance) {
60 wc.style = NULL;
61 wc.lpfnWndProc = LeftyWndProc;
62 wc.cbClsExtra = 0;
63 wc.cbWndExtra = 0;
64 wc.hInstance = hinstance;
65 wc.hIcon = LoadIcon ((HINSTANCE) NULL, IDI_APPLICATION);
66 wc.hCursor = LoadCursor ((HINSTANCE) NULL, IDC_ARROW);
67 wc.hbrBackground = GetStockObject (WHITE_BRUSH);
68 wc.lpszMenuName = 0;
69 wc.lpszClassName = "LeftyClass";
70 if (!(rtn = RegisterClass (&wc)))
71 panic1 (POS, "GXinit", "register class rtn = %d", (int) rtn);
72
73 wc.style = NULL;
74 wc.lpfnWndProc = ArrayWndProc;
75 wc.cbClsExtra = 0;
76 wc.cbWndExtra = 0;
77 wc.hInstance = hinstance;
78 wc.hIcon = LoadIcon ((HINSTANCE) NULL, IDI_APPLICATION);
79 wc.hCursor = LoadCursor ((HINSTANCE) NULL, IDC_ARROW);
80 wc.hbrBackground = GetStockObject (WHITE_BRUSH);
81 wc.lpszMenuName = 0;
82 wc.lpszClassName = "ArrayClass";
83 if (!(rtn = RegisterClass (&wc)))
84 panic1 (POS, "GXinit", "register class rtn = %d", (int) rtn);
85
86 wc.style = CS_OWNDC;
87 wc.lpfnWndProc = CanvasWndProc;
88 wc.cbClsExtra = 0;
89 wc.cbWndExtra = 0;
90 wc.hInstance = hinstance;
91 wc.hIcon = LoadIcon ((HINSTANCE) NULL, IDI_APPLICATION);
92 wc.hCursor = NULL;
93 wc.hbrBackground = GetStockObject (WHITE_BRUSH);
94 wc.lpszMenuName = 0;
95 wc.lpszClassName = "CanvasClass";
96 if (!(rtn = RegisterClass (&wc)))
97 panic1 (POS, "GXinit", "register class rtn = %d", (int) rtn);
98
99 wc.style = NULL;
100 wc.lpfnWndProc = ScrollWndProc;
101 wc.cbClsExtra = 0;
102 wc.cbWndExtra = 0;
103 wc.hInstance = hinstance;
104 wc.hIcon = LoadIcon ((HINSTANCE) NULL, IDI_APPLICATION);
105 wc.hCursor = LoadCursor ((HINSTANCE) NULL, IDC_ARROW);
106 wc.hbrBackground = GetStockObject (WHITE_BRUSH);
107 wc.lpszMenuName = 0;
108 wc.lpszClassName = "ScrollClass";
109 if (!(rtn = RegisterClass (&wc)))
110 panic1 (POS, "GXinit", "register class rtn = %d", (int) rtn);
111
112 wc.style = NULL;
113 wc.lpfnWndProc = LabelWndProc;
114 wc.cbClsExtra = 0;
115 wc.cbWndExtra = 0;
116 wc.hInstance = hinstance;
117 wc.hIcon = LoadIcon ((HINSTANCE) NULL, IDI_APPLICATION);
118 wc.hCursor = LoadCursor ((HINSTANCE) NULL, IDC_ARROW);
119 wc.hbrBackground = GetStockObject (WHITE_BRUSH);
120 wc.lpszMenuName = 0;
121 wc.lpszClassName = "LabelClass";
122 if (!(rtn = RegisterClass (&wc)))
123 panic1 (POS, "GXinit", "register class rtn = %d", (int) rtn);
124 }
125 if (getenv ("LEFTY3BMOUSE"))
126 twobmouse = FALSE;
127 else
128 twobmouse = TRUE;
129 hdc = GetDC ((HWND) NULL);
130 Gdepth = GetDeviceCaps (hdc, BITSPIXEL);
131 deffont = GetStockObject (SYSTEM_FONT);
132 #ifndef FEATURE_MS
133 if (!(Gxfp = fopen ("/dev/windows", "r")))
134 panic1 (POS, "GXinit", "cannot open windows device");
135 Gxfd = fileno (Gxfp);
136 #endif
137 Gpopdownflag = FALSE;
138 Gbufp = Marrayalloc ((long) BUFINCR * BUFSIZE);
139 Gbufn = BUFINCR;
140 Gppp = Marrayalloc ((long) PPINCR * PPSIZE);
141 Gppn = PPINCR;
142 Gfontp = Marrayalloc ((long) FONTSIZE);
143 Gfontn = 1;
144 Gfontp[0].name = strdup ("default");
145 if (!Gdefaultfont)
146 Gfontp[0].font = deffont;
147 else if (Gdefaultfont[0] != '\000')
148 Gfontp[0].font = CreateFont (
149 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Gdefaultfont
150 );
151 else
152 Gfontp[0].font = NULL;
153 ReleaseDC ((HWND) NULL, hdc);
154 Gnocallbacks = FALSE;
155 return 0;
156 }
157
Gtermgraphics(void)158 int Gtermgraphics (void) {
159 int fi;
160
161 for (fi = 0; fi < Gfontn; fi++)
162 free (Gfontp[fi].name);
163 Marrayfree (Gfontp), Gfontp = NULL, Gfontn = 0;
164 Marrayfree (Gppp), Gppp = NULL, Gppn = 0;
165 Marrayfree (Gbufp), Gbufp = NULL, Gbufn = 0;
166 return 0;
167 }
168
Gsync(void)169 int Gsync (void) {
170 return 0;
171 }
172
Gresetbstate(int wi)173 int Gresetbstate (int wi) {
174 Gcw_t *cw;
175 int bn;
176
177 cw = Gwidgets[wi].u.c;
178 bn = cw->bstate[0] + cw->bstate[1] + cw->bstate[2];
179 cw->bstate[0] = cw->bstate[1] = cw->bstate[2] = 0;
180 cw->buttonsdown -= bn;
181 Gbuttonsdown -= bn;
182 return 0;
183 }
184
Gprocessevents(int waitflag,int mode)185 int Gprocessevents (int waitflag, int mode) {
186 MSG msg;
187 int rtn;
188
189 rtn = 0;
190 switch (waitflag) {
191 case TRUE:
192 if (!GetMessage(&msg, (HWND) NULL, (UINT) NULL, (UINT) NULL))
193 exit (msg.wParam);
194 TranslateMessage(&msg);
195 DispatchMessage(&msg);
196 if (mode == G_ONEEVENT)
197 return 1;
198 rtn = 1;
199 /* FALL THROUGH */
200 case FALSE:
201 while (PeekMessage(&msg, (HWND) 0, (UINT) 0, (UINT) 0, PM_REMOVE)) {
202 if (msg.message == WM_QUIT)
203 exit (msg.wParam);
204 TranslateMessage(&msg);
205 DispatchMessage(&msg);
206 if (mode == G_ONEEVENT)
207 return 1;
208 rtn = 1;
209 }
210 break;
211 }
212 return rtn;
213 }
214
LeftyWndProc(HWND hwnd,UINT message,WPARAM wparam,LPARAM lparam)215 LRESULT CALLBACK LeftyWndProc (
216 HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam
217 ) {
218 Gwidget_t *widget;
219 WINDOWPOS *wpos;
220 Gevent_t gev;
221
222 widget = findwidget (hwnd, G_VIEWWIDGET);
223 switch (message) {
224 case WM_WINDOWPOSCHANGED:
225 if (Gnocallbacks || !widget)
226 return (DefWindowProc(hwnd, message, wparam, lparam));
227 wpos = (WINDOWPOS *) lparam;
228 if (!(wpos->flags & SWP_NOSIZE))
229 handleresize (widget);
230 break;
231 case WM_COMMAND:
232 if (Gnocallbacks || !widget)
233 return (DefWindowProc(hwnd, message, wparam, lparam));
234 processcommand (widget, wparam, lparam);
235 break;
236 case WM_CLOSE:
237 if (!widget)
238 exit (0);
239 if (WVU->closing)
240 DestroyWindow (hwnd);
241 if (Gnocallbacks)
242 exit (0);
243 gev.type = 0, gev.code = 0, gev.data = 0;
244 gev.wi = widget - &Gwidgets[0];
245 if (WVU->func)
246 (*WVU->func) (&gev);
247 else
248 exit (0);
249 break;
250 case WM_PALETTECHANGED:
251 palettechanged = (HWND) wparam;
252 break;
253 default:
254 return (DefWindowProc(hwnd, message, wparam, lparam));
255 }
256 return 0;
257 }
258
ArrayWndProc(HWND hwnd,UINT message,WPARAM wparam,LPARAM lparam)259 LRESULT CALLBACK ArrayWndProc (
260 HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam
261 ) {
262 Gwidget_t *widget;
263 WINDOWPOS *wpos;
264
265 if (Gnocallbacks || !(widget = findwidget (hwnd, G_ARRAYWIDGET)))
266 return (DefWindowProc(hwnd, message, wparam, lparam));
267 switch (message) {
268 case WM_WINDOWPOSCHANGED:
269 wpos = (WINDOWPOS *) lparam;
270 if (!(wpos->flags & SWP_NOSIZE))
271 handleresize (widget);
272 break;
273 case WM_COMMAND:
274 processcommand (widget, wparam, lparam);
275 break;
276 default:
277 return (DefWindowProc (hwnd, message, wparam, lparam));
278 }
279 return 0;
280 }
281
CanvasWndProc(HWND hwnd,UINT message,WPARAM wparam,LPARAM lparam)282 LRESULT CALLBACK CanvasWndProc (
283 HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam
284 ) {
285 Gwidget_t *widget;
286 WINDOWPOS *wpos;
287 PIXpoint_t pp;
288 Gevent_t gev;
289 POINT p;
290 int wi, bn;
291
292 static int cntlflag;
293
294 if (Gnocallbacks || !(widget = findwidget (hwnd, G_CANVASWIDGET)))
295 return (DefWindowProc(hwnd, message, wparam, lparam));
296 Gpopdownflag = FALSE;
297 switch (message) {
298 case WM_PAINT:
299 if (palettechanged != hwnd)
300 RealizePalette (widget->u.c->gc);
301 Gneedredraw = widget->u.c->needredraw = TRUE;
302 Gadjustclip (widget);
303 return (DefWindowProc(hwnd, message, wparam, lparam));
304 case WM_WINDOWPOSCHANGED:
305 wpos = (WINDOWPOS *) lparam;
306 if (!(wpos->flags & SWP_NOSIZE))
307 handleresize (widget);
308 return 0;
309 case WM_MOUSEACTIVATE:
310 SetFocus (widget->w);
311 return (DefWindowProc(hwnd, message, wparam, lparam));
312 case WM_COMMAND:
313 processcommand (widget, wparam, lparam);
314 return 0;
315 case WM_CHAR:
316 gev.type = G_KEYBD;
317 gev.code = G_DOWN; /* I don't know how to get up events so I make */
318 Gpopdownflag = TRUE; /* the code after this switch send the up event */
319 gev.data = wparam;
320 GetCursorPos (&p);
321 ScreenToClient (widget->w, &p);
322 pp.x = p.x, pp.y = p.y;
323 gev.p = ppixtodraw (widget, pp);
324 /* continues after the end of this switch */
325 break;
326 case WM_LBUTTONDOWN:
327 case WM_LBUTTONUP:
328 case WM_MBUTTONDOWN:
329 case WM_MBUTTONUP:
330 case WM_RBUTTONDOWN:
331 case WM_RBUTTONUP:
332 gev.type = G_MOUSE;
333 if (twobmouse) {
334 if (message == WM_LBUTTONDOWN && (wparam & MK_CONTROL))
335 message = WM_MBUTTONDOWN, cntlflag = TRUE;
336 if (message == WM_LBUTTONUP && cntlflag)
337 message = WM_MBUTTONUP, cntlflag = FALSE;
338 }
339 switch (message) {
340 case WM_LBUTTONDOWN: gev.code = G_DOWN, gev.data = G_LEFT; break;
341 case WM_LBUTTONUP: gev.code = G_UP, gev.data = G_LEFT; break;
342 case WM_MBUTTONDOWN: gev.code = G_DOWN, gev.data = G_MIDDLE; break;
343 case WM_MBUTTONUP: gev.code = G_UP, gev.data = G_MIDDLE; break;
344 case WM_RBUTTONDOWN: gev.code = G_DOWN, gev.data = G_RIGHT; break;
345 case WM_RBUTTONUP: gev.code = G_UP, gev.data = G_RIGHT; break;
346 }
347 pp.x = LOWORD (lparam), pp.y = HIWORD (lparam);
348 gev.p = ppixtodraw (widget, pp);
349 bn = WCU->bstate[gev.data];
350 WCU->bstate[gev.data] = (gev.code == G_DOWN) ? 1 : 0;
351 bn = WCU->bstate[gev.data] - bn;
352 widget->u.c->buttonsdown += bn;
353 Gbuttonsdown += bn;
354 /* continues after the end of this switch */
355 break;
356 default:
357 return (DefWindowProc(hwnd, message, wparam, lparam));
358 }
359 wi = gev.wi = widget - &Gwidgets[0];
360 if (widget->u.c->func)
361 (*widget->u.c->func) (&gev);
362 if (Gpopdownflag) {
363 Gpopdownflag = FALSE;
364 if (gev.code == G_DOWN) {
365 gev.code = G_UP;
366 widget = &Gwidgets[wi];
367 WCU->bstate[gev.data] = 0;
368 widget->u.c->buttonsdown--;
369 Gbuttonsdown--;
370 if (widget->inuse && widget->u.c->func)
371 (*widget->u.c->func) (&gev);
372 }
373 }
374 return 0;
375 }
376
LabelWndProc(HWND hwnd,UINT message,WPARAM wparam,LPARAM lparam)377 LRESULT CALLBACK LabelWndProc (
378 HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam
379 ) {
380 Gwidget_t *widget;
381 PAINTSTRUCT paintstruct;
382 WINDOWPOS *wpos;
383 Gevent_t gev;
384 RECT r;
385 HDC hdc;
386 int wi;
387
388 if (Gnocallbacks || !(widget = findwidget (hwnd, G_LABELWIDGET)))
389 return (DefWindowProc(hwnd, message, wparam, lparam));
390 switch (message) {
391 case WM_PAINT:
392 hdc = BeginPaint (widget->w, &paintstruct);
393 GetWindowText (widget->w, &Gbufp[0], Gbufn);
394 GetClientRect (widget->w, &r);
395 DrawText (hdc, (LPCSTR) &Gbufp[0], strlen (Gbufp), &r, DT_LEFT);
396 EndPaint (widget->w, &paintstruct);
397 return (DefWindowProc(hwnd, message, wparam, lparam));
398 case WM_WINDOWPOSCHANGED:
399 wpos = (WINDOWPOS *) lparam;
400 if (!(wpos->flags & SWP_NOSIZE))
401 handleresize (widget);
402 return 0;
403 case WM_COMMAND:
404 processcommand (widget, wparam, lparam);
405 return 0;
406 case WM_KEYDOWN:
407 case WM_KEYUP:
408 gev.type = G_KEYBD;
409 gev.code = (message == WM_KEYDOWN) ? G_DOWN : G_UP;
410 gev.data = wparam;
411 /* continues after the end of this switch */
412 break;
413 case WM_LBUTTONDOWN:
414 case WM_LBUTTONUP:
415 case WM_MBUTTONDOWN:
416 case WM_MBUTTONUP:
417 case WM_RBUTTONDOWN:
418 case WM_RBUTTONUP:
419 gev.type = G_MOUSE;
420 if (wparam & MK_CONTROL) {
421 if (message == WM_LBUTTONDOWN)
422 message = WM_MBUTTONDOWN;
423 else if (message == WM_LBUTTONUP)
424 message = WM_MBUTTONUP;
425 }
426 switch (message) {
427 case WM_LBUTTONDOWN: gev.code = G_DOWN, gev.data = G_LEFT; break;
428 case WM_LBUTTONUP: gev.code = G_UP, gev.data = G_LEFT; break;
429 case WM_MBUTTONDOWN: gev.code = G_DOWN, gev.data = G_MIDDLE; break;
430 case WM_MBUTTONUP: gev.code = G_UP, gev.data = G_MIDDLE; break;
431 case WM_RBUTTONDOWN: gev.code = G_DOWN, gev.data = G_RIGHT; break;
432 case WM_RBUTTONUP: gev.code = G_UP, gev.data = G_RIGHT; break;
433 }
434 /* continues after the end of this switch */
435 break;
436 default:
437 return (DefWindowProc(hwnd, message, wparam, lparam));
438 }
439 wi = gev.wi = widget - &Gwidgets[0];
440 if (widget->u.l->func)
441 (*widget->u.l->func) (&gev);
442 if (Gpopdownflag) {
443 Gpopdownflag = FALSE;
444 if (gev.type == G_MOUSE && gev.code == G_DOWN) {
445 gev.code = G_UP;
446 widget = &Gwidgets[wi];
447 if (widget->inuse && widget->u.l->func)
448 (*widget->u.l->func) (&gev);
449 }
450 }
451 return 0;
452 }
453
ScrollWndProc(HWND hwnd,UINT message,WPARAM wparam,LPARAM lparam)454 LRESULT CALLBACK ScrollWndProc (
455 HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam
456 ) {
457 Gwidget_t *widget, *child;
458 WINDOWPOS *wpos;
459 PIXpoint_t po;
460 RECT r;
461 int dummy, dx, dy, wi;
462
463 if (Gnocallbacks || !(widget = findwidget (hwnd, G_SCROLLWIDGET)))
464 return (DefWindowProc(hwnd, message, wparam, lparam));
465 switch (message) {
466 case WM_WINDOWPOSCHANGED:
467 wpos = (WINDOWPOS *) lparam;
468 if (!(wpos->flags & SWP_NOSIZE))
469 handleresize (widget);
470 break;
471 case WM_HSCROLL:
472 case WM_VSCROLL:
473 for (wi = 0; wi < Gwidgetn; wi++) {
474 child = &Gwidgets[wi];
475 if (child->inuse && child->pwi == widget - &Gwidgets[0])
476 break;
477 }
478 if (wi == Gwidgetn)
479 return (DefWindowProc(hwnd, message, wparam, lparam));
480 GetClientRect (widget->w, &r);
481 GetScrollRange (widget->w, SB_HORZ, &dummy, &dx);
482 GetScrollRange (widget->w, SB_VERT, &dummy, &dy);
483 po.x = GetScrollPos (widget->w, SB_HORZ);
484 po.y = GetScrollPos (widget->w, SB_VERT);
485 switch (message) {
486 case WM_HSCROLL:
487 switch (LOWORD (wparam)) {
488 case SB_BOTTOM: po.x = dx; break;
489 case SB_LINEDOWN: po.x += 10; break;
490 case SB_LINEUP: po.x -= 10; break;
491 case SB_PAGEDOWN: po.x += (r.right - r.left); break;
492 case SB_PAGEUP: po.x -= (r.right - r.left); break;
493 case SB_THUMBPOSITION: po.x = HIWORD (wparam); break;
494 case SB_THUMBTRACK: po.x = HIWORD (wparam); break;
495 case SB_TOP: po.x = 0; break;
496 }
497 po.x = min (po.x, dx);
498 po.x = max (po.x, 0);
499 SetScrollPos (widget->w, SB_HORZ, po.x, TRUE);
500 SetWindowPos (
501 child->w, (HWND) NULL, -po.x, -po.y, 0, 0,
502 SWP_NOSIZE | SWP_NOZORDER
503 );
504 break;
505 case WM_VSCROLL:
506 switch (LOWORD (wparam)) {
507 case SB_BOTTOM: po.y = dy; break;
508 case SB_LINEDOWN: po.y += 10; break;
509 case SB_LINEUP: po.y -= 10; break;
510 case SB_PAGEDOWN: po.y += (r.bottom - r.top); break;
511 case SB_PAGEUP: po.y -= (r.bottom - r.top); break;
512 case SB_THUMBPOSITION: po.y = HIWORD (wparam); break;
513 case SB_THUMBTRACK: po.y = HIWORD (wparam); break;
514 case SB_TOP: po.y = 0; break;
515 }
516 po.y = min (po.y, dy);
517 po.y = max (po.y, 0);
518 SetScrollPos (widget->w, SB_VERT, po.y, TRUE);
519 SetWindowPos (
520 child->w, (HWND) NULL, -po.x, -po.y, 0, 0,
521 SWP_NOSIZE | SWP_NOZORDER
522 );
523 break;
524 }
525 break;
526 default:
527 return (DefWindowProc (hwnd, message, wparam, lparam));
528 }
529 return 0;
530 }
531
processcommand(Gwidget_t * widget,WPARAM wparam,LPARAM lparam)532 static void processcommand (Gwidget_t *widget, WPARAM wparam, LPARAM lparam) {
533 Gwidget_t *child;
534 WORD l;
535 int n;
536
537 if (lparam == 0) { /* it's a menu */
538 if (LOWORD (wparam) != 999)
539 menuselected = LOWORD (wparam);
540 menupoped = FALSE;
541 return;
542 }
543 if (!(LOWORD (wparam) > 0 && LOWORD (wparam) < Gwidgetn))
544 return;
545 child = &Gwidgets[LOWORD (wparam)];
546 if (!child->inuse)
547 return;
548
549 switch (child->type) {
550 case G_TEXTWIDGET:
551 if (HIWORD (wparam) == EN_CHANGE) { /* it's a text widget message */
552 if ((n = SendMessage (child->w, EM_GETLINECOUNT, 0, 0L)) < 2)
553 return;
554 *((WORD *) &Gbufp[0]) = Gbufn - 1;
555 l = SendMessage (
556 child->w, EM_GETLINE, n - 1, (LPARAM) (LPSTR) &Gbufp[0]
557 );
558 if (l != 0)
559 return; /* no carriage return yet */
560 *((WORD *) &Gbufp[0]) = Gbufn - 1;
561 l = SendMessage (
562 child->w, EM_GETLINE, n - 2, (LPARAM) (LPSTR) &Gbufp[0]
563 );
564 Gbufp[l] = 0;
565 if (l > 0 && child->u.t->func)
566 (*child->u.t->func) (child - &Gwidgets[0], &Gbufp[0]);
567 }
568 break;
569 case G_BUTTONWIDGET:
570 if (child->u.b->func)
571 (*child->u.b->func) (child - &Gwidgets[0], child->udata);
572 break;
573 }
574 }
575
Gadjustwrect(Gwidget_t * parent,PIXsize_t * psp)576 void Gadjustwrect (Gwidget_t *parent, PIXsize_t *psp) {
577 RECT r;
578
579 GetClientRect (parent->w, &r);
580 switch (parent->type) {
581 case G_ARRAYWIDGET:
582 if (parent->u.a->data.type == G_AWHARRAY)
583 psp->y = r.bottom - r.top;
584 else
585 psp->x = r.right - r.left;
586 break;
587 case G_SCROLLWIDGET:
588 psp->x = max (psp->x, r.right - r.left);
589 psp->y = max (psp->y, r.bottom - r.top);
590 break;
591 case G_VIEWWIDGET:
592 case G_QUERYWIDGET:
593 psp->x = r.right - r.left;
594 psp->y = r.bottom - r.top;
595 break;
596 }
597 }
598
handleresize(Gwidget_t * widget)599 static void handleresize (Gwidget_t *widget) {
600 Gwidget_t *parent, *child;
601 PIXsize_t ps1, ps2;
602 PIXpoint_t po;
603 DWORD wflags1, wflags2;
604 RECT r;
605 int dx, dy, wi, i;
606
607 wflags1 = SWP_NOMOVE | SWP_NOZORDER;
608 wflags2 = SWP_NOSIZE | SWP_NOZORDER;
609 GetWindowRect (widget->w, &r);
610 ps1.x = r.right - r.left, ps1.y = r.bottom - r.top;
611 ps2 = ps1;
612 /* first, take care of parent */
613 parent = (widget->pwi == -1) ? NULL : &Gwidgets[widget->pwi];
614 if (!parent)
615 goto handlechildren;
616 switch (parent->type) {
617 case G_VIEWWIDGET:
618 Gadjustwrect (parent, &ps1);
619 if (ps1.x != ps2.x || ps1.y != ps2.y) {
620 Gnocallbacks = TRUE;
621 SetWindowPos (widget->w, (HWND) NULL, 0, 0, ps1.x, ps1.y, wflags1);
622 Gnocallbacks = FALSE;
623 }
624 break;
625 case G_ARRAYWIDGET:
626 Gnocallbacks = TRUE;
627 Gawresize (parent);
628 Gnocallbacks = FALSE;
629 break;
630 case G_SCROLLWIDGET:
631 Gnocallbacks = TRUE;
632 for (i = 0; i < 2; i++) {
633 Gadjustwrect (parent, &ps1);
634 if (ps1.x > ps2.x || ps1.y > ps2.y)
635 SetWindowPos (
636 widget->w, (HWND) NULL, 0, 0, ps1.x, ps1.y, wflags1
637 );
638 GetClientRect (parent->w, &r);
639 ps2.x = r.right - r.left, ps2.y = r.bottom - r.top;
640 dx = max (0, ps1.x - ps2.x);
641 dy = max (0, ps1.y - ps2.y);
642 SetScrollRange (parent->w, SB_HORZ, 0, dx, TRUE);
643 SetScrollRange (parent->w, SB_VERT, 0, dy, TRUE);
644 po.x = GetScrollPos (parent->w, SB_HORZ);
645 po.y = GetScrollPos (parent->w, SB_VERT);
646 po.x = min (po.x, dx);
647 po.x = max (po.x, 0);
648 SetScrollPos (parent->w, SB_HORZ, po.x, TRUE);
649 po.y = min (po.y, dy);
650 po.y = max (po.y, 0);
651 SetScrollPos (parent->w, SB_VERT, po.y, TRUE);
652 SetWindowPos (widget->w, (HWND) NULL, -po.x, -po.y, 0, 0, wflags2);
653 ps2 = ps1;
654 }
655 Gnocallbacks = FALSE;
656 break;
657 }
658
659 handlechildren:
660 for (wi = 0; wi < Gwidgetn; wi++) {
661 child = &Gwidgets[wi];
662 if (child->inuse && child->pwi == widget - &Gwidgets[0])
663 break;
664 }
665 if (wi == Gwidgetn)
666 return;
667 GetWindowRect (child->w, &r);
668 ps1.x = r.right - r.left, ps1.y = r.bottom - r.top;
669 ps2 = ps1;
670 switch (widget->type) {
671 case G_VIEWWIDGET:
672 Gadjustwrect (widget, &ps1);
673 if (ps1.x != ps2.x || ps1.y != ps2.y)
674 SetWindowPos (child->w, (HWND) NULL, 0, 0, ps1.x, ps1.y, wflags1);
675 break;
676 case G_ARRAYWIDGET:
677 Gawresize (widget);
678 break;
679 case G_SCROLLWIDGET:
680 Gadjustwrect (widget, &ps1);
681 if (ps1.x > ps2.x || ps1.y > ps2.y)
682 SetWindowPos (child->w, (HWND) NULL, 0, 0, ps1.x, ps1.y, wflags1);
683 GetClientRect (widget->w, &r);
684 ps2.x = r.right - r.left, ps2.y = r.bottom - r.top;
685 dx = max (0, ps1.x - ps2.x);
686 dy = max (0, ps1.y - ps2.y);
687 SetScrollRange (widget->w, SB_HORZ, 0, dx, TRUE);
688 SetScrollRange (widget->w, SB_VERT, 0, dy, TRUE);
689 po.x = GetScrollPos (widget->w, SB_HORZ);
690 po.y = GetScrollPos (widget->w, SB_VERT);
691 po.x = min (po.x, dx);
692 po.x = max (po.x, 0);
693 SetScrollPos (widget->w, SB_HORZ, po.x, TRUE);
694 po.y = min (po.y, dy);
695 po.y = max (po.y, 0);
696 SetScrollPos (widget->w, SB_VERT, po.y, TRUE);
697 SetWindowPos (child->w, (HWND) NULL, -po.x, -po.y, 0, 0, wflags2);
698 break;
699 }
700 }
701