2
/* Lefteris Koutsofios - AT&T Bell Laboratories */
9
#define WCU widget->u.c
10
#define WVU widget->u.v
21
int Gbufn = 0, Gbufi = 0;
31
static HWND palettechanged;
33
LRESULT CALLBACK LeftyWndProc (HWND, UINT, WPARAM, LPARAM);
34
LRESULT CALLBACK ArrayWndProc (HWND, UINT, WPARAM, LPARAM);
35
LRESULT CALLBACK CanvasWndProc (HWND, UINT, WPARAM, LPARAM);
36
LRESULT CALLBACK LabelWndProc (HWND, UINT, WPARAM, LPARAM);
37
LRESULT CALLBACK ScrollWndProc (HWND, UINT, WPARAM, LPARAM);
39
static void processcommand (Gwidget_t *, WPARAM, LPARAM);
40
static void handleresize (Gwidget_t *);
42
int Ginitgraphics (void) {
49
wc.lpfnWndProc = LeftyWndProc;
52
wc.hInstance = hinstance;
53
wc.hIcon = LoadIcon ((HINSTANCE) NULL, IDI_APPLICATION);
54
wc.hCursor = LoadCursor ((HINSTANCE) NULL, IDC_ARROW);
55
wc.hbrBackground = GetStockObject (WHITE_BRUSH);
57
wc.lpszClassName = "LeftyClass";
58
if (!(rtn = RegisterClass (&wc)))
59
panic (POS, "GXinit", "register class rtn = %d", (int) rtn);
62
wc.lpfnWndProc = ArrayWndProc;
65
wc.hInstance = hinstance;
66
wc.hIcon = LoadIcon ((HINSTANCE) NULL, IDI_APPLICATION);
67
wc.hCursor = LoadCursor ((HINSTANCE) NULL, IDC_ARROW);
68
wc.hbrBackground = GetStockObject (WHITE_BRUSH);
70
wc.lpszClassName = "ArrayClass";
71
if (!(rtn = RegisterClass (&wc)))
72
panic (POS, "GXinit", "register class rtn = %d", (int) rtn);
75
wc.lpfnWndProc = CanvasWndProc;
78
wc.hInstance = hinstance;
79
wc.hIcon = LoadIcon ((HINSTANCE) NULL, IDI_APPLICATION);
81
wc.hbrBackground = GetStockObject (WHITE_BRUSH);
83
wc.lpszClassName = "CanvasClass";
84
if (!(rtn = RegisterClass (&wc)))
85
panic (POS, "GXinit", "register class rtn = %d", (int) rtn);
88
wc.lpfnWndProc = ScrollWndProc;
91
wc.hInstance = hinstance;
92
wc.hIcon = LoadIcon ((HINSTANCE) NULL, IDI_APPLICATION);
93
wc.hCursor = LoadCursor ((HINSTANCE) NULL, IDC_ARROW);
94
wc.hbrBackground = GetStockObject (WHITE_BRUSH);
96
wc.lpszClassName = "ScrollClass";
97
if (!(rtn = RegisterClass (&wc)))
98
panic (POS, "GXinit", "register class rtn = %d", (int) rtn);
101
wc.lpfnWndProc = LabelWndProc;
104
wc.hInstance = hinstance;
105
wc.hIcon = LoadIcon ((HINSTANCE) NULL, IDI_APPLICATION);
106
wc.hCursor = LoadCursor ((HINSTANCE) NULL, IDC_ARROW);
107
wc.hbrBackground = GetStockObject (WHITE_BRUSH);
109
wc.lpszClassName = "LabelClass";
110
if (!(rtn = RegisterClass (&wc)))
111
panic (POS, "GXinit", "register class rtn = %d", (int) rtn);
113
if (getenv ("LEFTY3BMOUSE"))
117
hdc = GetDC ((HWND) NULL);
118
Gdepth = GetDeviceCaps (hdc, BITSPIXEL);
119
deffont = GetStockObject (SYSTEM_FONT);
121
if (!(Gxfp = fopen ("/dev/windows", "r")))
122
panic (POS, "GXinit", "cannot open windows device");
123
Gxfd = fileno (Gxfp);
125
Gpopdownflag = FALSE;
126
Gbufp = Marrayalloc ((long) BUFINCR * BUFSIZE);
128
Gppp = Marrayalloc ((long) PPINCR * PPSIZE);
130
Gfontp = Marrayalloc ((long) FONTSIZE);
132
Gfontp[0].name = strdup ("default");
134
Gfontp[0].font = deffont;
135
else if (Gdefaultfont[0] != '\000')
136
Gfontp[0].font = CreateFont (0, 0, 0, 0, 0,
137
0, 0, 0, 0, 0, 0, 0, 0, Gdefaultfont);
139
Gfontp[0].font = NULL;
140
ReleaseDC ((HWND) NULL, hdc);
141
Gnocallbacks = FALSE;
145
int Gtermgraphics (void) {
148
for (fi = 0; fi < Gfontn; fi++)
149
free (Gfontp[fi].name);
150
Marrayfree (Gfontp), Gfontp = NULL, Gfontn = 0;
151
Marrayfree (Gppp), Gppp = NULL, Gppn = 0;
152
Marrayfree (Gbufp), Gbufp = NULL, Gbufn = 0;
160
int Gresetbstate (int wi) {
164
cw = Gwidgets[wi].u.c;
165
bn = cw->bstate[0] + cw->bstate[1] + cw->bstate[2];
166
cw->bstate[0] = cw->bstate[1] = cw->bstate[2] = 0;
167
cw->buttonsdown -= bn;
172
int Gprocessevents (int waitflag, Geventmode_t mode) {
179
if (!GetMessage(&msg, (HWND) NULL, (UINT) NULL, (UINT) NULL))
181
TranslateMessage(&msg);
182
DispatchMessage(&msg);
183
if (mode == G_ONEEVENT)
188
while (PeekMessage(&msg, (HWND) 0, (UINT) 0, (UINT) 0, PM_REMOVE)) {
189
if (msg.message == WM_QUIT)
191
TranslateMessage(&msg);
192
DispatchMessage(&msg);
193
if (mode == G_ONEEVENT)
202
LRESULT CALLBACK LeftyWndProc (HWND hwnd,
203
UINT message, WPARAM wparam, LPARAM lparam) {
208
widget = findwidget (hwnd, G_VIEWWIDGET);
210
case WM_WINDOWPOSCHANGED:
211
if (Gnocallbacks || !widget)
212
return (DefWindowProc(hwnd, message, wparam, lparam));
213
wpos = (WINDOWPOS *) lparam;
214
if (!(wpos->flags & SWP_NOSIZE))
215
handleresize (widget);
218
if (Gnocallbacks || !widget)
219
return (DefWindowProc(hwnd, message, wparam, lparam));
220
processcommand (widget, wparam, lparam);
226
DestroyWindow (hwnd);
229
gev.type = 0, gev.code = 0, gev.data = 0;
230
gev.wi = widget - &Gwidgets[0];
236
case WM_PALETTECHANGED:
237
palettechanged = (HWND) wparam;
240
return (DefWindowProc(hwnd, message, wparam, lparam));
245
LRESULT CALLBACK ArrayWndProc (HWND hwnd,
246
UINT message, WPARAM wparam, LPARAM lparam) {
250
if (Gnocallbacks || !(widget = findwidget (hwnd, G_ARRAYWIDGET)))
251
return (DefWindowProc(hwnd, message, wparam, lparam));
253
case WM_WINDOWPOSCHANGED:
254
wpos = (WINDOWPOS *) lparam;
255
if (!(wpos->flags & SWP_NOSIZE))
256
handleresize (widget);
259
processcommand (widget, wparam, lparam);
262
return (DefWindowProc (hwnd, message, wparam, lparam));
267
LRESULT CALLBACK CanvasWndProc (HWND hwnd,
268
UINT message, WPARAM wparam, LPARAM lparam) {
276
if (Gnocallbacks || !(widget = findwidget (hwnd, G_CANVASWIDGET)))
277
return (DefWindowProc(hwnd, message, wparam, lparam));
278
Gpopdownflag = FALSE;
281
if (palettechanged != hwnd)
282
RealizePalette (widget->u.c->gc);
283
Gneedredraw = widget->u.c->needredraw = TRUE;
284
Gadjustclip (widget);
285
return (DefWindowProc(hwnd, message, wparam, lparam));
286
case WM_WINDOWPOSCHANGED:
287
wpos = (WINDOWPOS *) lparam;
288
if (!(wpos->flags & SWP_NOSIZE))
289
handleresize (widget);
291
case WM_MOUSEACTIVATE:
292
SetFocus (widget->w);
293
return (DefWindowProc(hwnd, message, wparam, lparam));
295
processcommand (widget, wparam, lparam);
299
gev.code = G_DOWN; /* I don't know how to get up events so I make */
300
Gpopdownflag = TRUE; /* the code after this switch send the up event */
303
ScreenToClient (widget->w, &p);
304
pp.x = p.x, pp.y = p.y;
305
gev.p = ppixtodraw (widget, pp);
306
/* continues after the end of this switch */
316
if (message == WM_LBUTTONDOWN && (wparam & MK_CONTROL))
317
message = WM_MBUTTONDOWN;
318
if (message == WM_LBUTTONUP && (wparam & MK_CONTROL))
319
message = WM_MBUTTONUP;
322
case WM_LBUTTONDOWN: gev.code = G_DOWN, gev.data = G_LEFT; break;
323
case WM_LBUTTONUP: gev.code = G_UP, gev.data = G_LEFT; break;
324
case WM_MBUTTONDOWN: gev.code = G_DOWN, gev.data = G_MIDDLE; break;
325
case WM_MBUTTONUP: gev.code = G_UP, gev.data = G_MIDDLE; break;
326
case WM_RBUTTONDOWN: gev.code = G_DOWN, gev.data = G_RIGHT; break;
327
case WM_RBUTTONUP: gev.code = G_UP, gev.data = G_RIGHT; break;
329
pp.x = LOWORD (lparam), pp.y = HIWORD (lparam);
330
gev.p = ppixtodraw (widget, pp);
331
bn = WCU->bstate[gev.data];
332
WCU->bstate[gev.data] = (gev.code == G_DOWN) ? 1 : 0;
333
bn = WCU->bstate[gev.data] - bn;
334
widget->u.c->buttonsdown += bn;
336
/* continues after the end of this switch */
339
return (DefWindowProc(hwnd, message, wparam, lparam));
341
wi = gev.wi = widget - &Gwidgets[0];
342
if (widget->u.c->func)
343
(*widget->u.c->func) (&gev);
345
Gpopdownflag = FALSE;
346
if (gev.code == G_DOWN) {
348
widget = &Gwidgets[wi];
349
WCU->bstate[gev.data] = 0;
350
widget->u.c->buttonsdown--;
352
if (widget->inuse && widget->u.c->func)
353
(*widget->u.c->func) (&gev);
359
LRESULT CALLBACK LabelWndProc (HWND hwnd,
360
UINT message, WPARAM wparam, LPARAM lparam) {
362
PAINTSTRUCT paintstruct;
369
if (Gnocallbacks || !(widget = findwidget (hwnd, G_LABELWIDGET)))
370
return (DefWindowProc(hwnd, message, wparam, lparam));
373
hdc = BeginPaint (widget->w, &paintstruct);
374
GetWindowText (widget->w, &Gbufp[0], Gbufn);
375
GetClientRect (widget->w, &r);
376
DrawText (hdc, (LPCSTR) &Gbufp[0], strlen (Gbufp), &r, DT_LEFT);
377
EndPaint (widget->w, &paintstruct);
378
return (DefWindowProc(hwnd, message, wparam, lparam));
379
case WM_WINDOWPOSCHANGED:
380
wpos = (WINDOWPOS *) lparam;
381
if (!(wpos->flags & SWP_NOSIZE))
382
handleresize (widget);
385
processcommand (widget, wparam, lparam);
390
gev.code = (message == WM_KEYDOWN) ? G_DOWN : G_UP;
392
/* continues after the end of this switch */
401
if (wparam & MK_CONTROL) {
402
if (message == WM_LBUTTONDOWN)
403
message = WM_MBUTTONDOWN;
404
else if (message == WM_LBUTTONUP)
405
message = WM_MBUTTONUP;
408
case WM_LBUTTONDOWN: gev.code = G_DOWN, gev.data = G_LEFT; break;
409
case WM_LBUTTONUP: gev.code = G_UP, gev.data = G_LEFT; break;
410
case WM_MBUTTONDOWN: gev.code = G_DOWN, gev.data = G_MIDDLE; break;
411
case WM_MBUTTONUP: gev.code = G_UP, gev.data = G_MIDDLE; break;
412
case WM_RBUTTONDOWN: gev.code = G_DOWN, gev.data = G_RIGHT; break;
413
case WM_RBUTTONUP: gev.code = G_UP, gev.data = G_RIGHT; break;
415
/* continues after the end of this switch */
418
return (DefWindowProc(hwnd, message, wparam, lparam));
420
wi = gev.wi = widget - &Gwidgets[0];
421
if (widget->u.l->func)
422
(*widget->u.l->func) (&gev);
424
Gpopdownflag = FALSE;
425
if (gev.type == G_MOUSE && gev.code == G_DOWN) {
427
widget = &Gwidgets[wi];
428
if (widget->inuse && widget->u.l->func)
429
(*widget->u.l->func) (&gev);
435
LRESULT CALLBACK ScrollWndProc (HWND hwnd,
436
UINT message, WPARAM wparam, LPARAM lparam) {
437
Gwidget_t *widget, *child;
441
int dummy, dx, dy, wi;
443
if (Gnocallbacks || !(widget = findwidget (hwnd, G_SCROLLWIDGET)))
444
return (DefWindowProc(hwnd, message, wparam, lparam));
446
case WM_WINDOWPOSCHANGED:
447
wpos = (WINDOWPOS *) lparam;
448
if (!(wpos->flags & SWP_NOSIZE))
449
handleresize (widget);
453
for (wi = 0; wi < Gwidgetn; wi++) {
454
child = &Gwidgets[wi];
455
if (child->inuse && child->pwi == widget - &Gwidgets[0])
459
return (DefWindowProc(hwnd, message, wparam, lparam));
460
GetClientRect (widget->w, &r);
461
GetScrollRange (widget->w, SB_HORZ, &dummy, &dx);
462
GetScrollRange (widget->w, SB_VERT, &dummy, &dy);
463
po.x = GetScrollPos (widget->w, SB_HORZ);
464
po.y = GetScrollPos (widget->w, SB_VERT);
467
switch (LOWORD (wparam)) {
468
case SB_BOTTOM: po.x = dx; break;
469
case SB_LINEDOWN: po.x += 10; break;
470
case SB_LINEUP: po.x -= 10; break;
471
case SB_PAGEDOWN: po.x += (r.right - r.left); break;
472
case SB_PAGEUP: po.x -= (r.right - r.left); break;
473
case SB_THUMBPOSITION: po.x = HIWORD (wparam); break;
474
case SB_THUMBTRACK: po.x = HIWORD (wparam); break;
475
case SB_TOP: po.x = 0; break;
477
po.x = min (po.x, dx);
478
po.x = max (po.x, 0);
479
SetScrollPos (widget->w, SB_HORZ, po.x, TRUE);
480
SetWindowPos (child->w, (HWND) NULL, -po.x, -po.y, 0, 0,
481
SWP_NOSIZE | SWP_NOZORDER);
484
switch (LOWORD (wparam)) {
485
case SB_BOTTOM: po.y = dy; break;
486
case SB_LINEDOWN: po.y += 10; break;
487
case SB_LINEUP: po.y -= 10; break;
488
case SB_PAGEDOWN: po.y += (r.bottom - r.top); break;
489
case SB_PAGEUP: po.y -= (r.bottom - r.top); break;
490
case SB_THUMBPOSITION: po.y = HIWORD (wparam); break;
491
case SB_THUMBTRACK: po.y = HIWORD (wparam); break;
492
case SB_TOP: po.y = 0; break;
494
po.y = min (po.y, dy);
495
po.y = max (po.y, 0);
496
SetScrollPos (widget->w, SB_VERT, po.y, TRUE);
497
SetWindowPos (child->w, (HWND) NULL, -po.x, -po.y, 0, 0,
498
SWP_NOSIZE | SWP_NOZORDER);
503
return (DefWindowProc(hwnd, message, wparam, lparam));
508
static void processcommand (Gwidget_t *widget, WPARAM wparam, LPARAM lparam) {
513
if (lparam == 0) { /* it's a menu */
514
if (LOWORD (wparam) != 999)
515
menuselected = LOWORD (wparam);
519
if (!(LOWORD (wparam) > 0 && LOWORD (wparam) < Gwidgetn))
521
child = &Gwidgets[LOWORD (wparam)];
525
switch (child->type) {
527
if (HIWORD (wparam) == EN_CHANGE) { /* it's a text widget message */
528
if ((n = SendMessage (child->w, EM_GETLINECOUNT, 0, 0L)) < 2)
530
*((WORD *) &Gbufp[0]) = Gbufn - 1;
531
l = SendMessage (child->w, EM_GETLINE, n - 1,
532
(LPARAM) (LPSTR) &Gbufp[0]);
534
return; /* no carriage return yet */
535
*((WORD *) &Gbufp[0]) = Gbufn - 1;
536
l = SendMessage (child->w, EM_GETLINE, n - 2,
537
(LPARAM) (LPSTR) &Gbufp[0]);
539
if (l > 0 && child->u.t->func)
540
(*child->u.t->func) (child - &Gwidgets[0], &Gbufp[0]);
544
if (child->u.b->func)
545
(*child->u.b->func) (child - &Gwidgets[0], child->udata);
550
void Gadjustwrect (Gwidget_t *parent, PIXsize_t *psp) {
553
GetClientRect (parent->w, &r);
554
switch (parent->type) {
556
if (parent->u.a->data.type == G_AWHARRAY)
557
psp->y = r.bottom - r.top;
559
psp->x = r.right - r.left;
562
psp->x = max (psp->x, r.right - r.left);
563
psp->y = max (psp->y, r.bottom - r.top);
567
psp->x = r.right - r.left;
568
psp->y = r.bottom - r.top;
573
static void handleresize (Gwidget_t *widget) {
574
Gwidget_t *parent, *child;
577
DWORD wflags1, wflags2;
581
wflags1 = SWP_NOMOVE | SWP_NOZORDER;
582
wflags2 = SWP_NOSIZE | SWP_NOZORDER;
583
GetWindowRect (widget->w, &r);
584
ps1.x = r.right - r.left, ps1.y = r.bottom - r.top;
586
/* first, take care of parent */
587
parent = (widget->pwi == -1) ? NULL : &Gwidgets[widget->pwi];
590
switch (parent->type) {
592
Gadjustwrect (parent, &ps1);
593
if (ps1.x != ps2.x || ps1.y != ps2.y) {
595
SetWindowPos (widget->w, (HWND) NULL, 0, 0, ps1.x, ps1.y, wflags1);
596
Gnocallbacks = FALSE;
602
Gnocallbacks = FALSE;
606
for (i = 0; i < 2; i++) {
607
Gadjustwrect (parent, &ps1);
608
if (ps1.x > ps2.x || ps1.y > ps2.y)
609
SetWindowPos (widget->w, (HWND) NULL, 0, 0, ps1.x, ps1.y,
611
GetClientRect (parent->w, &r);
612
ps2.x = r.right - r.left, ps2.y = r.bottom - r.top;
613
dx = max (0, ps1.x - ps2.x);
614
dy = max (0, ps1.y - ps2.y);
615
SetScrollRange (parent->w, SB_HORZ, 0, dx, TRUE);
616
SetScrollRange (parent->w, SB_VERT, 0, dy, TRUE);
617
po.x = GetScrollPos (parent->w, SB_HORZ);
618
po.y = GetScrollPos (parent->w, SB_VERT);
619
po.x = min (po.x, dx);
620
po.x = max (po.x, 0);
621
SetScrollPos (parent->w, SB_HORZ, po.x, TRUE);
622
po.y = min (po.y, dy);
623
po.y = max (po.y, 0);
624
SetScrollPos (parent->w, SB_VERT, po.y, TRUE);
625
SetWindowPos (widget->w, (HWND) NULL, -po.x, -po.y, 0, 0, wflags2);
628
Gnocallbacks = FALSE;
633
for (wi = 0; wi < Gwidgetn; wi++) {
634
child = &Gwidgets[wi];
635
if (child->inuse && child->pwi == widget - &Gwidgets[0])
640
GetWindowRect (child->w, &r);
641
ps1.x = r.right - r.left, ps1.y = r.bottom - r.top;
643
switch (widget->type) {
645
Gadjustwrect (widget, &ps1);
646
if (ps1.x != ps2.x || ps1.y != ps2.y)
647
SetWindowPos (child->w, (HWND) NULL, 0, 0, ps1.x, ps1.y, wflags1);
653
Gadjustwrect (widget, &ps1);
654
if (ps1.x > ps2.x || ps1.y > ps2.y)
655
SetWindowPos (child->w, (HWND) NULL, 0, 0, ps1.x, ps1.y, wflags1);
656
GetClientRect (widget->w, &r);
657
ps2.x = r.right - r.left, ps2.y = r.bottom - r.top;
658
dx = max (0, ps1.x - ps2.x);
659
dy = max (0, ps1.y - ps2.y);
660
SetScrollRange (widget->w, SB_HORZ, 0, dx, TRUE);
661
SetScrollRange (widget->w, SB_VERT, 0, dy, TRUE);
662
po.x = GetScrollPos (widget->w, SB_HORZ);
663
po.y = GetScrollPos (widget->w, SB_VERT);
664
po.x = min (po.x, dx);
665
po.x = max (po.x, 0);
666
SetScrollPos (widget->w, SB_HORZ, po.x, TRUE);
667
po.y = min (po.y, dy);
668
po.y = max (po.y, 0);
669
SetScrollPos (widget->w, SB_VERT, po.y, TRUE);
670
SetWindowPos (child->w, (HWND) NULL, -po.x, -po.y, 0, 0, wflags2);