1 /* $Id: winXXPilot.c,v 5.1 2001/04/24 20:40:18 bertg Exp $
2  *
3  * XPilot, a multiplayer gravity war game.  Copyright (C) 1991-2001 by
4  *
5  *      Bj�rn Stabell        <bjoern@xpilot.org>
6  *      Ken Ronny Schouten   <ken@xpilot.org>
7  *      Bert Gijsbers        <bert@xpilot.org>
8  *      Dick Balaska         <dick@xpilot.org>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  */
24 
25 /***************************************************************************\
26 *  winX.c - X11 to Windoze converter										*
27 *																			*
28 *  This file is mostly Win32 translations of the X calls that xpilot uses.	*
29 *  Anything starting with WinX is a special wedge function that i needed	*
30 *																			*
31 *  $Id: winXXPilot.c,v 5.1 2001/04/24 20:40:18 bertg Exp $						*
32 \***************************************************************************/
33 #include "winXXPilot.h"
34 #include "../winX_.h"
35 #include "windows.h"
36 #include "winClient.h"
37 #include "winXThread.h"
38 #include <math.h>
39 
40 #include "../../../src/error.h"
41 #include "../../../src/const.h"
42 #include "../../../src/paint.h"
43 //#include "../../../src/draw.h"
44 #include "../../../src/xinit.h"
45 #include "../../../src/widget.h"
46 #include "../../../src/protoclient.h"
47 
48 int iScaleFactor;
49 
50 // Radar window is updated every RadarDivisor frames.
51 int RadarDivisor;
52 int	ThreadedDraw;
53 
54 extern	Window	draw;		// we only want this one
55 
56 Window	rootWindow = 0;		// The whole screen
57 
58 static  double fTwoPi = 2.0 * PI;
59 
60 HINSTANCE	hInstance;
61 HPALETTE	myPal;
62 LOGPALETTE*	myLogPal;
63 HFONT		hFixedFont;
64 HHOOK		mousehook = NULL;
65 
66 HDC			itemsDC;		// for blitting items onto the screen
67 #define		WINMAXCOLORS	16
68 
69 int			winmaxcolors;
70 int			TotalPens = 0;
71 
72 XIDTYPE	xid[MAX_XIDS];
73 //unsigned int	max_xid = 0;			// point to next free one in array
74 
75 BOOL	bWinNT = 0;				// need this 'cause Win95 can't draw a simple circle
76 BOOL	bHasPal = TRUE;			// Are we palette or colour based?
77 BOOL	drawPending = FALSE;	// try to throttle the deadly frame backup syndrome
78 
79 #ifdef PENS_OF_PLENTY
80 DWORD	dwdashes[NUM_DASHES+1] = { NUM_DASHES, 8, 4 };
81 DWORD	dwcdashes[NUM_CDASHES+1] = { NUM_CDASHES, 3, 9 };
82 winXobj	objs[WINMAXCOLORS];
83 #else
84 int		cur_color;
85 winXobj objs[WINMAXCOLORS+FUNKCOLORS];
86 #endif
87 
88 // We need to parse and setup the colors during Windows screen init which happens
89 // before XPilot window init.
90 extern	COLORREF GetXPilotColor(int which, COLORREF defcolor);
91 extern	int		 GetMaxColors();
92 /*extern	int		 GetScoreFontHeight();*/
93 
WinXSetupRadarWindow()94 static void WinXSetupRadarWindow()
95 {
96 	if (radar)
97 	{
98 		if (instruments & SHOW_SLIDING_RADAR)
99 		{
100 			if (xid[radar].hwnd.hSaveDC != NULL)
101 			{
102 				ReleaseDC(xid[radar].hwnd.hWnd, xid[radar].hwnd.hBmpDC);
103 				xid[radar].hwnd.hBmpDC = xid[radar].hwnd.hSaveDC;
104 				xid[radar].hwnd.hSaveDC = NULL;
105 			}
106 		}
107 		else
108 		{
109 			if (xid[radar].hwnd.hSaveDC == NULL)
110 			{
111 				HDC hNewDC = GetDC(xid[radar].hwnd.hWnd);
112 				xid[radar].hwnd.hSaveDC = xid[radar].hwnd.hBmpDC;
113 				xid[radar].hwnd.hBmpDC = hNewDC;
114 				if (bHasPal)
115 				{
116 					SelectPalette(hNewDC, myPal, FALSE);
117 					RealizePalette(myPal);
118 				}
119 			}
120 		}
121 	}
122 }
123 
WinXDeleteDraw(int xidno)124 static void WinXDeleteDraw(int xidno)
125 {
126 	HDC hSaveDC = xid[xidno].hwnd.hSaveDC;
127 	HDC hBmpDC = xid[xidno].hwnd.hBmpDC;
128 
129 	if (xid[xidno].hwnd.type == DT_2)
130 	{
131 		if (xid[xidno].hwnd.hBmpa[0])
132 			DeleteObject(xid[xidno].hwnd.hBmpa[0]);
133 		if (xid[xidno].hwnd.hBmpa[1])
134 			DeleteObject(xid[xidno].hwnd.hBmpa[1]);
135 		xid[xidno].hwnd.hBmpa[0] = xid[xidno].hwnd.hBmpa[0] = NULL;
136 		if (xid[xidno].hwnd.hBmpDCa[0])
137 			DeleteDC(xid[xidno].hwnd.hBmpDCa[0]);
138 		if (xid[xidno].hwnd.hBmpDCa[1])
139 			DeleteDC(xid[xidno].hwnd.hBmpDCa[1]);
140 		xid[xidno].hwnd.hBmpDCa[0] = xid[xidno].hwnd.hBmpDCa[1] = NULL;
141 
142 	}
143 	else
144 	{
145 		if (xid[xidno].hwnd.hBmp)
146 			DeleteObject(xid[xidno].hwnd.hBmp);
147 	}
148 	xid[xidno].hwnd.hBmp = NULL;
149 	if (hSaveDC)
150 	{
151 		DeleteDC(hSaveDC);
152 		if (hBmpDC)
153 			ReleaseDC(xid[xidno].hwnd.hWnd, hBmpDC);
154 	}
155 	else if (hBmpDC)
156 		DeleteDC(hBmpDC);
157 
158 	xid[xidno].hwnd.hBmpDC = xid[xidno].hwnd.hSaveDC = NULL;
159 	xid[xidno].hwnd.hBmp = NULL;
160 }
161 
162 #if 0
163 static void WinXScaled(HDC hDC, int cx, int cy)
164 {
165 	if (iScaleFactor != SCALEPREC)
166 	{
167 		SetMapMode(hDC, MM_ANISOTROPIC);
168 
169 		SetWindowExtEx(hDC, WinXUnscale(cx), WinXUnscale(cy), NULL);
170 		SetWindowOrgEx(hDC, 0, 0, NULL);
171 		SetViewportExtEx(hDC, cx, cy, NULL);
172 		SetViewportOrgEx(hDC, 0, 0, NULL);
173 	}
174 	else SetMapMode(hDC, MM_TEXT);
175 }
176 
177 static void WinXUnscaled(HDC hDC)
178 {
179 	SetMapMode(hDC, MM_TEXT);
180 }
181 #endif
182 
WinXCreateBitmapForXid(HWND hwnd,XID xidno,int cx,int cy)183 static void WinXCreateBitmapForXid(HWND hwnd, XID xidno, int cx, int cy)
184 {
185 	HDC	hBmpDC, hDC = GetDC(hwnd);
186 	HBITMAP hBmp;
187 	RECT r;
188 
189 	WinXDeleteDraw(xidno);
190 	if (ThreadedDraw && xidno == draw)
191 	{
192 		xid[xidno].hwnd.hBmpa[1] = CreateCompatibleBitmap(hDC, cx, cy);
193 		xid[xidno].hwnd.hBmpa[0] = CreateCompatibleBitmap(hDC, cx, cy);
194 		hBmp = xid[xidno].hwnd.hBmp= xid[xidno].hwnd.hBmpa[0];
195 		xid[xidno].hwnd.hBmpDCa[0] = CreateCompatibleDC(hDC);
196 		xid[xidno].hwnd.hBmpDCa[1] = CreateCompatibleDC(hDC);
197 		xid[xidno].hwnd.hBmpDC = xid[xidno].hwnd.hBmpDCa[0];
198 		xid[xidno].hwnd.filling = 0;
199 		xid[xidno].hwnd.drawtype = DT_2;
200 		SelectObject(xid[xidno].hwnd.hBmpDCa[0], xid[xidno].hwnd.hBmpa[0]);
201 		SelectObject(xid[xidno].hwnd.hBmpDCa[1], xid[xidno].hwnd.hBmpa[1]);
202 		SetBkMode(xid[xidno].hwnd.hBmpDCa[0], TRANSPARENT);
203 		SetBkMode(xid[xidno].hwnd.hBmpDCa[1], TRANSPARENT);
204 		SelectPalette(xid[xidno].hwnd.hBmpDCa[0], myPal, FALSE);
205 		RealizePalette(xid[xidno].hwnd.hBmpDCa[0]);
206 		SelectPalette(xid[xidno].hwnd.hBmpDCa[1], myPal, FALSE);
207 		RealizePalette(xid[xidno].hwnd.hBmpDCa[1]);
208 	}
209 	else
210 	{
211 		xid[xidno].hwnd.hBmp = hBmp = CreateCompatibleBitmap(hDC, cx, cy);
212 		xid[xidno].hwnd.hBmpDC = hBmpDC = CreateCompatibleDC(hDC);
213 		SelectObject(hBmpDC, hBmp);
214 	}
215 //	if (xidno == (int)draw)
216 //		WinXScaled(hBmpDC, cx, cy);
217 
218 
219 	if (bHasPal)
220 	{
221 		SelectPalette(hBmpDC, myPal, FALSE);
222 		RealizePalette(hBmpDC);
223 	}
224 	SetBkMode(hBmpDC, TRANSPARENT);
225 	r.left = 0; r.top = 0;
226 	r.right = cx; r.bottom = cy;
227 	FillRect(hBmpDC, &r, GetStockObject(BLACK_BRUSH));
228 	WinXSetupRadarWindow();
229 	ReleaseDC(hwnd, hDC);
230 }
231 
ChangePalette(HWND hWnd)232 BOOL ChangePalette(HWND hWnd)
233 {
234 	XID i;
235 	HDC hDC;
236 	HPALETTE hOldPal;
237 
238 	for (i = 0; i < MAX_XIDS; i += 1)
239 	{
240 		if (xid[i].type == XIDTYPE_HWND)
241 		{
242 			HWND hwnd = xid[i].hwnd.hWnd;
243 
244 			hDC = xid[i].hwnd.hBmpDC;
245 			hOldPal = SelectPalette(hDC, myPal, FALSE);
246 			RealizePalette(hDC);
247 			SelectPalette(hDC, hOldPal, FALSE);
248 
249 			hDC = GetDC(hwnd);
250 			hOldPal = SelectPalette(hDC, myPal, FALSE);
251 			RealizePalette(hDC);
252 			SelectPalette(hDC, hOldPal, FALSE);
253 			ReleaseDC(hwnd, hDC);
254 
255 			InvalidateRect(hwnd, NULL, FALSE);
256 		}
257 	}
258 
259 	return TRUE;
260 }
261 
WinXwindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)262 LRESULT	CALLBACK	WinXwindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
263 {
264 	switch (uMsg)
265 	{
266 	case WM_CREATE:
267 	{
268 		LPCREATESTRUCT lpcs = (LPCREATESTRUCT)lParam;
269 		int xidno = (int)lpcs->lpCreateParams;
270 
271 		Trace("WM_CREATE %d %d/%d %s:%d\n", xidno, lpcs->cx, lpcs->cy, xid[xidno].any.file, xid[xidno].any.line);
272 		WinXCreateBitmapForXid(hwnd, xidno, lpcs->cx, lpcs->cy);
273 		SetWindowWord(hwnd, 0, (WORD)xidno);
274 		return DefWindowProc(hwnd, uMsg, wParam, lParam);
275 	}
276 
277 	case WM_DESTROY:
278 	{
279 		XID xidno = (int)GetWindowWord(hwnd, 0);
280 
281 		if (Widget_window(motd_viewer) == xidno)
282 			Motd_destroy();
283 		if (Widget_window(keys_viewer) == xidno)
284 			Keys_destroy();
285 		WinXDeleteDraw(xidno);
286 		return DefWindowProc(hwnd, uMsg, wParam, lParam);
287 	}
288 
289 	case WM_SIZE:
290 	{
291 		int xidno = (int)GetWindowWord(hwnd, 0);
292 		if (xidno > 0 && xidno < MAX_XIDS && xid[xidno].hwnd.hBmp)
293 		{
294 			int width = LOWORD(lParam);
295 			int height = HIWORD(lParam);
296 			Trace("WM_SIZE   %d %d/%d %s:%d\n", xidno, width, height, xid[xidno].any.file, xid[xidno].any.line);
297 			WinXCreateBitmapForXid(hwnd, xidno, width, height);
298 		}
299 		return DefWindowProc(hwnd, uMsg, wParam, lParam);
300 	}
301 	case WM_LBUTTONDOWN:
302 	{
303 		int				xidno = (int)GetWindowWord(hwnd, 0);
304 		if (xid[xidno].hwnd.event_mask & ButtonPressMask)
305 		{
306 			XEvent	event;
307 			XButtonEvent*	button = (XButtonEvent*)&event;
308 			POINT			pt;
309 
310 			pt.x = LOWORD(lParam);
311 			pt.y = HIWORD(lParam);
312 			MapWindowPoints(xid[xidno].hwnd.hWnd, xid[top].hwnd.hWnd,
313 							&pt, 1);
314 			button->type	= ButtonPress;
315 			button->window	= xidno;
316 			button->x		= LOWORD(lParam);
317 			button->y		= HIWORD(lParam);
318 			button->x_root	= pt.x;
319 			button->y_root	= pt.y;
320 			button->button	= Button1;
321 			win_xevent(event);
322 		}
323 		return DefWindowProc(hwnd, uMsg, wParam, lParam);
324 	}
325 	case WM_LBUTTONUP:
326 	{
327 		int xidno = (int)GetWindowWord(hwnd, 0);
328 
329 		if (xid[xidno].hwnd.event_mask & ButtonReleaseMask)
330 		{
331 			XEvent	event;
332 			XButtonEvent*	button = (XButtonEvent*)&event;
333 
334 			Trace("ButtonUp in %d %s:%d\n", xidno, xid[xidno].any.file, xid[xidno].any.line);
335 			button->type	= ButtonRelease;
336 			button->window	= xidno;
337 			button->x		= LOWORD(lParam);
338 			button->y		= HIWORD(lParam);
339 			button->button	= Button1;
340 			if (win_xevent(event) == -1)
341 			{
342 				WinXExit();
343 			}
344 			return(0);
345 		}
346 		return DefWindowProc(hwnd, uMsg, wParam, lParam);
347 	}
348 	case WM_MBUTTONDOWN:
349 	{
350 		int				xidno = (int)GetWindowWord(hwnd, 0);
351 		if (xid[xidno].hwnd.event_mask & ButtonPressMask)
352 		{
353 			XEvent	event;
354 			XButtonEvent*	button = (XButtonEvent*)&event;
355 			POINT			pt;
356 
357 			pt.x = LOWORD(lParam);
358 			pt.y = HIWORD(lParam);
359 			MapWindowPoints(xid[xidno].hwnd.hWnd, xid[top].hwnd.hWnd,
360 							&pt, 1);
361 			button->type	= ButtonPress;
362 			button->window	= xidno;
363 			button->x		= LOWORD(lParam);
364 			button->y		= HIWORD(lParam);
365 			button->x_root	= pt.x;
366 			button->y_root	= pt.y;
367 			button->button	= Button2;
368 			win_xevent(event);
369 		}
370 		return DefWindowProc(hwnd, uMsg, wParam, lParam);
371 	}
372 	case WM_MBUTTONUP:
373 	{
374 		int xidno = (int)GetWindowWord(hwnd, 0);
375 
376 		if (xid[xidno].hwnd.event_mask & ButtonReleaseMask)
377 		{
378 			XEvent	event;
379 			XButtonEvent*	button = (XButtonEvent*)&event;
380 
381 			Trace("ButtonUp in %d %s:%d\n", xidno, xid[xidno].any.file, xid[xidno].any.line);
382 			button->type	= ButtonRelease;
383 			button->window	= xidno;
384 			button->x		= LOWORD(lParam);
385 			button->y		= HIWORD(lParam);
386 			button->button	= Button2;
387 			if (win_xevent(event) == -1)
388 			{
389 				WinXExit();
390 			}
391 			return(0);
392 		}
393 		return DefWindowProc(hwnd, uMsg, wParam, lParam);
394 	}
395 	case WM_RBUTTONDOWN:
396 	{
397 		int				xidno = (int)GetWindowWord(hwnd, 0);
398 		if (xid[xidno].hwnd.event_mask & ButtonPressMask)
399 		{
400 			XEvent	event;
401 			XButtonEvent*	button = (XButtonEvent*)&event;
402 			POINT			pt;
403 
404 			pt.x = LOWORD(lParam);
405 			pt.y = HIWORD(lParam);
406 			MapWindowPoints(xid[xidno].hwnd.hWnd, xid[top].hwnd.hWnd,
407 							&pt, 1);
408 			button->type	= ButtonPress;
409 			button->window	= xidno;
410 			button->x		= LOWORD(lParam);
411 			button->y		= HIWORD(lParam);
412 			button->x_root	= pt.x;
413 			button->y_root	= pt.y;
414 			button->button	= Button3;
415 			win_xevent(event);
416 		}
417 		return DefWindowProc(hwnd, uMsg, wParam, lParam);
418 	}
419 	case WM_RBUTTONUP:
420 	{
421 		int xidno = (int)GetWindowWord(hwnd, 0);
422 
423 		if (xid[xidno].hwnd.event_mask & ButtonReleaseMask)
424 		{
425 			XEvent	event;
426 			XButtonEvent*	button = (XButtonEvent*)&event;
427 
428 			Trace("ButtonUp in %d %s:%d\n", xidno, xid[xidno].any.file, xid[xidno].any.line);
429 			button->type	= ButtonRelease;
430 			button->window	= xidno;
431 			button->x		= LOWORD(lParam);
432 			button->y		= HIWORD(lParam);
433 			button->button	= Button3;
434 			if (win_xevent(event) == -1)
435 			{
436 				WinXExit();
437 			}
438 			return(0);
439 		}
440 		return DefWindowProc(hwnd, uMsg, wParam, lParam);
441 	}
442 	case WM_MOUSEMOVE:
443 	{
444 		XID xidno = (int)GetWindowWord(hwnd, 0);
445 		XEvent	event;
446 		XID		i;
447 		XAnyEvent*	enter = (XAnyEvent*)&event;
448 
449 		Trace("MouseMove in %d %d/%d %s:%d\n", xidno,
450 			LOWORD(lParam), HIWORD(lParam), xid[xidno].any.file, xid[xidno].any.line);
451 
452 		enter->type			= LeaveNotify;
453 		for (i=0; i<MAX_XIDS; i++)
454 		{
455 			if (i != xidno && xid[i].type == XIDTYPE_HWND && xid[i].hwnd.mouseover
456 				&& xid[i].hwnd.event_mask & LeaveWindowMask)
457 			{
458 				Trace("LeaveNotify %d %s:%d\n", xidno, xid[xidno].any.file, xid[xidno].any.line);
459 				enter->window = i;
460 				win_xevent(event);
461 				xid[i].hwnd.mouseover = FALSE;
462 			}
463 		}
464 		if (xid[xidno].hwnd.event_mask & PointerMotionMask)
465 		{
466 			XMotionEvent* me = (XMotionEvent*)&event;
467 			me->type = MotionNotify;
468 			me->window = xidno;
469 			me->x = LOWORD(lParam);
470 			me->y = HIWORD(lParam);
471 //			if (me->x != draw_width/2 && me->y != draw_height/2)
472 			{
473 				win_xevent(event);
474 //				SetCursorPos(draw_width/2, draw_height/2);
475 			}
476 		//	return(0);
477 		}
478 		else if (!xid[xidno].hwnd.mouseover) /* PointerMotionMask is only on captured window */
479 		{									 /* so don't do the mouseover event */
480 			if (xid[xidno].hwnd.event_mask & EnterWindowMask)
481 			{
482 				Trace("EnterNotify %d %s:%d\n", xidno, xid[xidno].any.file, xid[xidno].any.line);
483 				enter->type			= EnterNotify;
484 				enter->window		= xidno;
485 				win_xevent(event);
486 			}
487 			xid[xidno].hwnd.mouseover = TRUE;
488 		}
489 
490 		return DefWindowProc(hwnd, uMsg, wParam, lParam);
491 	}
492 
493 	case WM_ERASEBKGND:
494 	{
495 		RECT	rect;
496 		if (GetClientRect(hwnd, &rect))
497 		{
498 			HDC hBmpDC;
499 			XID xidno = (int)GetWindowWord(hwnd, 0);
500 			hBmpDC = xid[xidno].hwnd.hBmpDC;
501 			if (hBmpDC)
502 			{
503 				Trace("WM_ERASEBKGND %d color=%d %d/%d %d/%d\n", xidno, xid[xidno].hwnd.bgcolor, rect.left, rect.top, rect.right, rect.bottom);
504 				FillRect(hBmpDC, &rect, objs[xid[xidno].hwnd.bgcolor].brush);
505 			}
506 		}
507 		return(0);
508 	}
509 	case WM_PAINT:
510 	{
511 		RECT	rect;
512 		if (GetUpdateRect(hwnd, &rect, FALSE))
513 		{
514 			XID xidno = (int)GetWindowWord(hwnd, 0);
515 //			if (xidno == draw)
516 //				return DefWindowProc(hwnd, uMsg, wParam, lParam);
517 			if (xidno >= 0 && xidno < MAX_XIDS)
518 			{
519 				HDC hBmpDC;
520 
521 				hBmpDC = xid[xidno].hwnd.hBmpDC;
522 				if (hBmpDC)
523 				{
524 					PAINTSTRUCT	ps;
525 					HDC	hDC;
526 					XEvent			event;
527 					XExposeEvent*	expose = (XExposeEvent*)&event;
528 
529 					if (ThreadedDraw && xidno == (int)draw)
530 					{
531 						ValidateRect(hwnd, &rect);
532 						winXTDraw(NULL, xidno, &rect);
533 					}
534 					else
535 					{
536 						hDC = BeginPaint(hwnd, &ps);
537 
538 						if (xid[xidno].hwnd.event_mask & ExposureMask)
539 						{
540 							expose->type	= Expose;
541 							expose->window	= xidno;
542 							expose->x		= rect.left;
543 							expose->y		= rect.top;
544 							expose->width	= rect.right-rect.left;
545 							expose->height	= rect.bottom-rect.top;
546 							expose->count	= 0;
547 							Trace("Expose %d %s:%d\n", xidno, xid[xidno].any.file, xid[xidno].any.line);
548 							win_xevent(event);
549 						}
550 						if (bHasPal)
551 						{
552 							SelectPalette(hDC, myPal, FALSE);
553 							RealizePalette(hDC);
554 						}
555 						if (xidno == (int)draw)
556 						{
557 						//	RECT r;
558 						//	WinXUnscaled(hBmpDC);
559 							if (ThreadedDraw)
560 							{
561 								ValidateRect(hwnd, &rect);
562 								winXTDraw(hDC, xidno, &rect);
563 							}
564 							else
565 							{
566 								BitBlt(hDC, rect.left, rect.top, rect.right, rect.bottom,
567 									   hBmpDC, rect.left, rect.top, SRCCOPY);
568 							}
569 						//	GetClientRect(hwnd, &r);
570 						//	WinXScaled(hBmpDC, r.right - r.left, r.bottom - r.top);
571 							drawPending = FALSE;
572 						}
573 						else
574 						{		/* not the main playfield window */
575 							BitBlt(hDC, rect.left, rect.top, rect.right, rect.bottom,
576 								   hBmpDC, rect.left, rect.top, SRCCOPY);
577 						}
578 						EndPaint(hwnd, &ps);
579 					}
580 					return 0;
581 				}
582 			}
583 		}
584 		return DefWindowProc(hwnd, uMsg, wParam, lParam);
585 	}
586 	default:
587 		return DefWindowProc(hwnd, uMsg, wParam, lParam);
588 	}
589 	return 0;
590 }
591 
WinXPColour(int ColourNo)592 COLORREF WinXPColour(int ColourNo)
593 {
594 	if (bHasPal)
595 		return PALETTEINDEX(ColourNo);
596 	return objs[ColourNo].color;
597 }
598 
599 #if 0
600 LRESULT CALLBACK MouseHook(int nCode, WPARAM wParam, LPARAM lParam)
601 {
602 	XEvent event;
603 	XMotionEvent* me = (XMotionEvent*)&event;
604 	if (nCode < 0)
605 		return(CallNextHookEx(mousehook, nCode, wParam, lParam));
606 	if (!pointerControl)
607 		return(0);
608 	me->type = MotionNotify;
609 	me->window = draw;
610 	me->x = ((MOUSEHOOKSTRUCT*)lParam)->pt.x;
611 	me->y = ((MOUSEHOOKSTRUCT*)lParam)->pt.y;
612 	win_xevent(event);
613 
614 	return(1);
615 
616 }
617 #endif
618 
InitWinXClass()619 static void InitWinXClass()
620 {
621 	WNDCLASS wc;
622 
623 	// Fill in window class structure with parameters
624 	wc.style = 0;
625 	wc.lpfnWndProc = WinXwindowProc;
626 	wc.cbClsExtra = 0;
627 	wc.cbWndExtra = sizeof(WORD);		// For the xidno of the window
628 	wc.hInstance = hInstance;
629 	wc.hIcon = NULL;
630 	wc.hCursor = LoadCursor(0, IDC_ARROW);
631 	wc.hbrBackground = GetStockObject(BLACK_BRUSH);
632 	wc.lpszMenuName =  NULL;
633 	wc.lpszClassName = "XPilotWin";
634 
635 	RegisterClass(&wc);
636 }
637 
InitWinX(HWND hWnd)638 void InitWinX(HWND hWnd)
639 {
640 	int		i;
641 	char	s[80];
642 	HDC		tDC = GetDC(hWnd);
643 //	TEXTMETRIC tm;
644 
645 	memset(&xid, 0, sizeof(xid));
646 	InitWinXClass();
647 	xid[0].hwnd.hWnd = hWnd;
648 	xid[0].type = XIDTYPE_HWND;
649 //	max_xid = 1;
650 
651 	itemsDC = NULL;
652 
653 	bWinNT = GetVersion() & 0x80000000 ? FALSE : TRUE;
654 
655 	myLogPal = malloc(sizeof(LOGPALETTE) + sizeof(PALETTEENTRY)*16);
656 	myLogPal->palVersion = 0x300;
657 //    "#000000", "#FFFFFF", "#4E7CFF", "#FF3A27",
658 //    "#33BB44", "#992200", "#BB7700", "#EE9900",
659 //    "#770000", "#CC4400", "#DD8800", "#FFBB11",
660 //    "#9f9f9f", "#5f5f5f", "#dfdfdf", "#202020"
661 	objs[0].color = GetXPilotColor ( 0, RGB(0x00,0x00,0x00));
662 	objs[1].color = GetXPilotColor ( 1, RGB(0xFF,0xFF,0xFF));
663 	objs[2].color = GetXPilotColor ( 2, RGB(0x4E,0x7C,0xFF));
664 	objs[3].color = GetXPilotColor ( 3, RGB(0xFF,0x3A,0x27));
665 	objs[4].color = GetXPilotColor ( 4, RGB(0x33,0xBB,0x44));
666 	objs[5].color = GetXPilotColor ( 5, RGB(0x99,0x22,0x00));
667 	objs[6].color = GetXPilotColor ( 6, RGB(0xBB,0x77,0x00));
668 	objs[7].color = GetXPilotColor ( 7, RGB(0xEE,0x99,0x00));
669 	objs[8].color = GetXPilotColor ( 8, RGB(0x77,0x00,0x00));
670 	objs[9].color = GetXPilotColor ( 9, RGB(0xCC,0x44,0x00));
671 	objs[10].color = GetXPilotColor(10, RGB(0xDD,0x88,0x00));
672 	objs[11].color = GetXPilotColor(11, RGB(0xFF,0xBB,0x11));
673 	objs[12].color = GetXPilotColor(12, RGB(0x9F,0x9F,0x9F));
674 	objs[13].color = GetXPilotColor(13, RGB(0x5F,0x5F,0x5F));
675 	objs[14].color = GetXPilotColor(14, RGB(0xDF,0xDF,0xDF));
676 	objs[15].color = GetXPilotColor(15, RGB(0x20,0x20,0x20));
677 
678 	winmaxcolors = GetMaxColors();
679 	//bHasPal = (GetDeviceCaps(tDC, RASTERCAPS) & RC_PALETTE) != 0;
680 	if (!winmaxcolors)
681 		winmaxcolors = 8;
682 	if (winmaxcolors < 4)
683 		error("I can't allocate 4 (colors or pens or brushes).  XPilot is probably not going to look very nice on this display");
684 	else if (winmaxcolors < 8)
685 		winmaxcolors = 4;
686 	else if (winmaxcolors < 16)
687 		winmaxcolors = 8;
688 	else
689 		winmaxcolors = 16;
690 	maxColors = winmaxcolors;
691 	myLogPal->palNumEntries = winmaxcolors;
692 	for (i=0; i<winmaxcolors; i++)
693 	{
694 		myLogPal->palPalEntry[i].peFlags = PC_RESERVED;
695 //		myLogPal->palPalEntry[i].peFlags = PC_EXPLICIT;
696 		myLogPal->palPalEntry[i].peRed =   GetRValue(objs[i].color);
697 		myLogPal->palPalEntry[i].peGreen = GetGValue(objs[i].color);
698 		myLogPal->palPalEntry[i].peBlue =  GetBValue(objs[i].color);
699 
700 #ifdef PENS_OF_PLENTY
701 		objs[i].brush = CreateSolidBrush(WinXPColour(i));
702 		if (!objs[i].brush)
703 			{ sprintf(s, "maxcolors=%d can't create brush %d", winmaxcolors, i); error(s); }
704 #else
705 		objs[i].pen = CreatePen(PS_SOLID, 1, WinXPColour(i));
706 		if (!objs[i].pen)
707 			{ sprintf(s, "maxcolors=%d can't create pen %d", winmaxcolors, i); error(s); }
708 		objs[i].brush = CreateSolidBrush(WinXPColour(i));
709 		if (!objs[i].brush)
710 			{ sprintf(s, "maxcolors=%d can't create brush %d", winmaxcolors, i); error(s); }
711 		Trace("%d: pen=%08X brush=%08X\n", i, objs[i].pen, objs[i].brush);
712 #endif
713 	}
714 
715 #ifndef PENS_OF_PLENTY
716 	objs[WHITE+CLOAKCOLOROFS].color = objs[WHITE].color;
717 	objs[WHITE+CLOAKCOLOROFS].brush = objs[WHITE].brush;
718 	objs[WHITE+CLOAKCOLOROFS].pen = CreatePen(PS_DOT, 1, WinXPColour(WHITE));
719 	if (!objs[WHITE+CLOAKCOLOROFS].pen)
720 		{ sprintf(s, "maxcolors=%d can't create pen %d", winmaxcolors, WHITE+CLOAKCOLOROFS); error(s); }
721 	objs[BLUE+CLOAKCOLOROFS].color = objs[BLUE].color;
722 	objs[BLUE+CLOAKCOLOROFS].brush = objs[BLUE].brush;
723 	objs[BLUE+CLOAKCOLOROFS].pen = CreatePen(PS_DOT, 1, WinXPColour(BLUE));
724 	if (!objs[BLUE+CLOAKCOLOROFS].pen)
725 		{ sprintf(s, "maxcolors=%d can't create pen %d", winmaxcolors, BLUE+CLOAKCOLOROFS); error(s); }
726 	objs[LASERCOLOR].color = objs[RED].color;
727 	objs[LASERCOLOR].brush = objs[RED].brush;
728 	objs[LASERCOLOR].pen = CreatePen(PS_SOLID, 2, WinXPColour(RED));
729 	if (!objs[LASERCOLOR].pen)
730 		{ sprintf(s, "maxcolors=%d can't create pen %d", winmaxcolors, LASERCOLOR); error(s); }
731 	objs[MISSILECOLOR].color = objs[RED].color;
732 	objs[MISSILECOLOR].brush = objs[RED].brush;
733 	objs[MISSILECOLOR].pen = CreatePen(PS_SOLID, 2, WinXPColour(WHITE));
734 	if (!objs[MISSILECOLOR].pen)
735 		{ sprintf(s, "maxcolors=%d can't create pen %d", winmaxcolors, MISSILECOLOR); error(s); }
736 	objs[LASERTEAMCOLOR].color = objs[BLUE].color;
737 	objs[LASERTEAMCOLOR].brush = objs[BLUE].brush;
738 	objs[LASERTEAMCOLOR].pen = CreatePen(PS_SOLID, 2, WinXPColour(BLUE));
739 	if (!objs[LASERTEAMCOLOR].pen)
740 		{ sprintf(s, "maxcolors=%d can't create pen %d", winmaxcolors, LASERTEAMCOLOR); error(s); }
741 #endif
742 
743 	myPal = CreatePalette(myLogPal);
744 	SelectPalette(tDC, myPal, FALSE);
745 	if (!myPal)
746 		error("Can't create palette");
747 
748     for (i=0; i<NUM_ITEMS; i++)
749 	{
750 		itemBitmaps[i][ITEM_HUD] = XIDTYPE_UNUSED;
751 		itemBitmaps[i][ITEM_PLAYFIELD] = XIDTYPE_UNUSED;
752 	}
753 //	mousehook = SetWindowsHookEx(WH_MOUSE, MouseHook, NULL, GetCurrentThreadId());
754 }
WinXFree(XID i)755 void WinXFree(XID i)
756 {
757 	switch (xid[i].type)
758 	{
759 	case XIDTYPE_FONT:
760 		free(xid[i].font.font);
761 		break;
762 	case XIDTYPE_PIXMAP:
763 		DeleteObject(xid[i].hpix.hbm);
764 		DeleteDC(xid[i].hpix.hDC);
765 		break;
766 	case XIDTYPE_HWND:
767 		WinXDeleteDraw(i);
768 		break;
769 	}
770 	xid[i].type = XIDTYPE_UNUSED;
771 }
772 
WinXShutdown()773 void WinXShutdown()
774 {
775 	XID		i;
776 
777 	if (mousehook)
778 		UnhookWindowsHookEx(mousehook);
779 	free(myLogPal);
780 	for (i=0; i<MAX_XIDS; i++)
781 	{
782 		WinXFree(i);
783 	}
784 
785 	for (i=0; i<(unsigned)maxColors; i++)
786 	{
787 #ifdef PENS_OF_PLENTY
788 		if (objs[i].pen != NULL)
789 			DeleteObject(objs[i].pen);
790 		if (objs[i].dashpen != NULL)
791 			DeleteObject(objs[i].dashpen);
792 		if (objs[i].cdashpen != NULL)
793 			DeleteObject(objs[i].cdashpen);
794 		if (objs[i].fatpen != NULL)
795 			DeleteObject(objs[i].fatpen);
796 		if (objs[i].brush != NULL)
797 			DeleteObject(objs[i].brush);
798 #else
799 		if (objs[i].pen)
800 			DeleteObject(objs[i].pen);
801 		if (objs[i].brush)
802 			DeleteObject(objs[i].brush);
803 
804 #endif
805 	}
806 }
807 
808 #ifdef PENS_OF_PLENTY
WinXMakePen(int cur_color,int Style,int Width)809 static HPEN WinXMakePen(int cur_color, int Style, int Width)
810 {
811 	HPEN	hPen;
812 
813 	if (bWinNT && Style != PS_SOLID)
814 	{
815 		LOGBRUSH lb;
816 		DWORD	*dshs;
817 
818 		lb.lbStyle = BS_SOLID;
819 		lb.lbColor = WinXPColour(cur_color);
820 		lb.lbHatch = 0;
821 
822 		if (Style = PS_DASH)
823 			dshs = dwdashes;
824 		else
825 			dshs = dwcdashes;
826 		hPen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, Width, &lb, dshs[0], &dshs[1]);
827 	}
828 	else hPen = CreatePen(Style, Width, WinXPColour(cur_color));
829 
830 	TotalPens += 1;
831 
832 	return hPen;
833 }
834 
WinXSetPen(int xidno)835 static void WinXSetPen(int xidno)
836 {
837 	HDC		hDC = xid[xidno].hwnd.hBmpDC;
838 	HPEN	hPen = NULL;
839 	int		cur_color = xid[xidno].hwnd.cur_color;
840 
841 	if (xid[xidno].hwnd.line_style == LineSolid)
842 	{
843 		if (xid[xidno].hwnd.line_width > 2)
844 		{
845 			if (objs[cur_color].fatpen == NULL)
846 				objs[cur_color].fatpen = WinXMakePen(WinXPColour(cur_color), PS_SOLID, 3);
847 			hPen = objs[cur_color].fatpen;
848 		}
849 		else
850 		{
851 			if (objs[cur_color].pen == NULL)
852 				objs[cur_color].pen = WinXMakePen(WinXPColour(cur_color), PS_SOLID, 0);
853 			hPen = objs[cur_color].pen;
854 		}
855 	}
856 	else
857 	{
858 		if (xid[xidno].hwnd.nodash)
859 		{
860 			if (objs[cur_color].cdashpen == NULL)
861 				objs[cur_color].cdashpen = WinXMakePen(cur_color, PS_DOT, 0);
862 			hPen = objs[cur_color].cdashpen;
863 		}
864 		else
865 		{
866 			if (objs[cur_color].dashpen == NULL)
867 				objs[cur_color].dashpen = WinXMakePen(cur_color, PS_DASH, 0);
868 			hPen = objs[cur_color].dashpen;
869 		}
870 	}
871 	if (hPen)
872 		SelectObject(hDC, hPen);
873 }
874 #endif
875 
876 ////////////////////////////////////////////////////////
877 // These are for SysInfo, we hide the details from him
WinXGetDrawDC()878 HDC	WinXGetDrawDC()
879 {
880 	return(GetDC(xid[draw].hwnd.hWnd));
881 }
882 
WinXReleaseDrawDC(HDC hDC)883 int	WinXReleaseDrawDC(HDC hDC)
884 {
885 	return(ReleaseDC(xid[draw].hwnd.hWnd, hDC));
886 }
887 
888 ////////////////////////////////////////////////////////
WinXGetWindowRectangle(Window window,XRectangle * rect)889 int	WinXGetWindowRectangle(Window window, XRectangle* rect)
890 {
891 	RECT	r;
892 	GetClientRect(xid[window].hwnd.hWnd, &r);
893 	rect->x = (short)WinXUnscale(r.left);
894 	rect->y = (short)WinXUnscale(r.top);
895 	rect->width = (unsigned short)WinXUnscale(r.right - r.left);
896 	rect->height = (unsigned short)WinXUnscale(r.bottom - r.top);
897 	return(1);
898 }
899 
900 #if 0
901 void WinXSetBackColor(GC gc, unsigned long background)
902 {
903 	HDC hDC = xid[xid[gc].hgc.xidhwnd].hwnd.hBmpDC;
904 	SetBkColor(hDC, background);
905 	SetBkMode(hDC, TRANSPARENT);
906 }
907 #endif
908 
909 // scarfed from a M$ KB article.  Apparently, Win95 doesn't support AngleArc
AngleArc2(HDC hdc,int X,int Y,DWORD dwRadius,double fStartDegrees,double fSweepDegrees,BOOL bFilled)910 BOOL AngleArc2(HDC hdc, int X, int Y, DWORD dwRadius,
911                double fStartDegrees, double fSweepDegrees, BOOL bFilled)
912 {
913   int iXStart, iYStart;  // End point of starting radial line
914   int iXEnd, iYEnd;        // End point of ending radial line
915   double fStartRadians;   // Start angle in radians
916   double fEndRadians;     // End angle in radians
917   BOOL bResult;            // Function result
918 
919   /* Get the starting and ending angle in radians */
920   if (fSweepDegrees > 0.0) {
921     fStartRadians = ((fStartDegrees / 360.0) * fTwoPi);
922     fEndRadians = (((fStartDegrees + fSweepDegrees) / 360.0) * fTwoPi);
923   } else {
924     fStartRadians = (((fStartDegrees + fSweepDegrees)  / 360.0) * fTwoPi);
925     fEndRadians =  ((fStartDegrees / 360.0) * fTwoPi);
926   }
927 
928   /* Calculate a point on the starting radial line via */
929   /* polar -> cartesian conversion */
930   iXStart = X + (int)((double)dwRadius * (double)cos(fStartRadians));
931   iYStart = Y - (int)((double)dwRadius * (double)sin(fStartRadians));
932 
933   /* Calculate a point on the ending radial line via */
934   /* polar -> cartesian conversion */
935   iXEnd = X + (int)((double)dwRadius * (double)cos(fEndRadians));
936   iYEnd = Y - (int)((double)dwRadius * (double)sin(fEndRadians));
937 
938   /* Draw a line to the starting point */
939   LineTo(hdc, iXStart, iYStart);
940 
941   /* Draw the arc */
942   if (bFilled)
943     bResult = Pie(hdc, X - dwRadius, Y - dwRadius,
944 	                   X + dwRadius, Y + dwRadius,
945                        iXStart, iYStart, iXEnd, iYEnd);
946   else
947     bResult = Arc(hdc, X - dwRadius, Y - dwRadius,
948                        X + dwRadius, Y + dwRadius,
949                        iXStart, iYStart, iXEnd, iYEnd);
950 
951   /* Move to the ending point - Arc() wont do this and ArcTo() */
952   /* wont work on Win32s or Win16 */
953   MoveToEx(hdc, iXEnd, iYEnd, NULL);
954 
955   return bResult;
956 }
957 
WinXParseFont(LOGFONT * lf,const char * name)958 void WinXParseFont(LOGFONT* lf, const char* name)
959 {
960 #define	MAX_FFLDS	14
961 	static char sepa[] = "-\n\r";
962 	char*	t[MAX_FFLDS];
963 	char*	s = malloc(strlen(name)+1);
964 	int		i;
965 
966 	strcpy(s, name);
967 
968 	t[0] = strtok(s, sepa);
969 	for (i=1; i<MAX_FFLDS; i++)
970 		t[i] = strtok(NULL, sepa);
971 //	lf->lfHeight = atoi(t[6]) * 100 / iScaleFactor;
972 //	lf->lfHeight = (int)(atoi(t[6]) / scaleFactor);
973 	lf->lfHeight = (int)(atoi(t[6]));
974 	if (!lf->lfHeight)
975 		lf->lfHeight = 14;
976 	lf->lfWeight = *t[2] == 'b' ? FW_BOLD : FW_NORMAL;
977 	lf->lfItalic = *t[3] == 'i' ? TRUE : FALSE;
978 	switch (*t[1])
979 	{
980 	case 't':		/* times */
981 		lf->lfPitchAndFamily = FF_ROMAN;
982 		break;
983 	case 'f':		/* fixed */
984 		lf->lfPitchAndFamily = FIXED_PITCH;
985 		break;
986 	case 'c':		/* courier */
987 		lf->lfPitchAndFamily = FF_MODERN;
988 		break;
989 	}
990 	free(s);
991 #undef	MAX_FFLDS
992 }
993 
WinXLoadFont(const char * name)994 XFontStruct* WinXLoadFont(const char* name)
995 {
996 	XID			txid;
997 	XFontStruct* fs = malloc(sizeof(XFontStruct));
998 	Trace("WinXLoadFont: creating font <%s>\n", name);
999 	memset(fs, 0, sizeof(XFontStruct));
1000 	WinXParseFont(&fs->lf, name);
1001 //	fs->ascent = fs->lf.lfHeight * 100 / iScaleFactor;
1002 //	fs->ascent = (int)(fs->lf.lfHeight / scaleFactor);
1003 	fs->ascent = (int)(fs->lf.lfHeight);
1004 	fs->hFont = CreateFontIndirect(&fs->lf);
1005 
1006 	txid = GetFreeXid();
1007 	xid[txid].type = XIDTYPE_FONT;
1008 	xid[txid].font.font = fs;
1009 	fs->fid = txid;
1010 	return(fs);
1011 }
1012 
1013 
XParseColor(Display * display,Colormap colormap,char * spec,XColor * exact_def_return)1014 XParseColor(Display* display, Colormap colormap, char* spec,
1015 					XColor* exact_def_return)
1016 {
1017 	Trace("Parsing color <%s>\n", spec);
1018 	return(0);
1019 }
1020 
WinXCreateBitmapFromData(Display * dpy,Drawable d,char * data,unsigned int width,unsigned int height,int color)1021 Pixmap WinXCreateBitmapFromData(Display* dpy, Drawable d, char* data,
1022 							  unsigned int width, unsigned int height, int color)
1023 {
1024 	HBITMAP	hbm;
1025 	int		i;
1026 	int		j;
1027 	WORD*	e;
1028 
1029 	BITMAP bm = {
1030 		0,							//   LONG   bmType;
1031 		16,							//   LONG   bmWidth;
1032 		16,							//   LONG   bmHeight;
1033 		4,							//   LONG   bmWidthBytes;
1034 		1,							//   WORD   bmPlanes;
1035 		1,							//   WORD   bmBitsPixel;
1036 		NULL						//   LPVOID bmBits;
1037 	};
1038 	RECT rect = { 0,0,16,16};
1039 
1040 	HDC		hDC = GetDC(xid[d].hwnd.hWnd);
1041 	HDC		hDCb = CreateCompatibleDC(hDC);
1042 
1043 	hbm = CreateCompatibleBitmap(hDC, width, height);
1044 	SelectObject(hDCb, hbm);
1045 	if (bHasPal)
1046 	{
1047 		SelectPalette(hDCb, myPal, FALSE);
1048 		RealizePalette(hDCb);
1049 	}
1050 
1051 	FillRect(hDCb, &rect, GetStockObject(BLACK_BRUSH));
1052 	if (!hbm)
1053 		error("Can't create item bitmaps");
1054 	if (width != 16 || height != 16)
1055 		error("Can only create 16x16 bitmaps");
1056 	e = (WORD*)data;
1057 	for (i=0; i<16; i++)
1058 	{
1059 		WORD	w = *e++;
1060 		WORD	z = 0;
1061 		for (j=0; j<16; j++)					// swap the bits in the bytes
1062 			if (w & (1<<j))
1063 				SetPixelV(hDCb, j, i, WinXPColour(color));
1064 	}
1065 
1066 	DeleteDC(hDCb);
1067 	ReleaseDC(xid[d].hwnd.hWnd, hDC);
1068 	return((Pixmap)hbm);
1069 }
1070 
XResizeWindow(Display * dpy,Window w,unsigned int width,unsigned int height)1071 XResizeWindow(Display* dpy, Window w, unsigned int width, unsigned int height)
1072 {
1073 	HWND	hWnd = xid[w].hwnd.hWnd;
1074 
1075 	SetWindowPos(hWnd, NULL, 0, 0, width, height, SWP_NOMOVE | SWP_NOZORDER);
1076 	return(0);
1077 }
1078 
WinXResize(void)1079 void WinXResize(void)
1080 {
1081 	RECT rect;
1082 
1083 	draw_width  = WinXUnscale(draw_width);
1084 	draw_height = WinXUnscale(draw_height);
1085 
1086 	if (radar && (instruments & SHOW_SLIDING_RADAR))
1087 	{
1088 		GetClientRect(xid[radar].hwnd.hWnd, &rect);
1089 		InvalidateRect(xid[radar].hwnd.hWnd, &rect, FALSE);
1090 	}
1091 	if (draw)
1092 	{
1093 		GetClientRect(xid[draw].hwnd.hWnd, &rect);
1094 		InvalidateRect(xid[draw].hwnd.hWnd, &rect, FALSE);
1095 	}
1096 	if (players)
1097 	{
1098 		GetClientRect(xid[players].hwnd.hWnd, &rect);
1099 		InvalidateRect(xid[players].hwnd.hWnd, &rect, FALSE);
1100 	}
1101 }
1102 
PaintWinClient()1103 void	PaintWinClient()
1104 {
1105 #if 0
1106 	RECT	rect;
1107 	static int updates = 0;
1108 
1109 	if (drawPending)
1110 		return;				// bogus dude.
1111 
1112 	if (!itemsDC)
1113 		itemsDC = CreateCompatibleDC(NULL);
1114 
1115 	WinXSetupRadarWindow();
1116 
1117 //	Paint_frame();
1118 
1119 	GetClientRect(xid[draw].hwnd.hWnd, &rect);
1120 	InvalidateRect(xid[draw].hwnd.hWnd, &rect, FALSE);
1121 	drawPending = TRUE;
1122 
1123 	if (instruments & SHOW_SLIDING_RADAR)
1124 	{
1125 		GetClientRect(xid[radar].hwnd.hWnd, &rect);
1126 		InvalidateRect(xid[radar].hwnd.hWnd, &rect, FALSE);
1127 	}
1128 
1129 	// One time stuff for score window update
1130 	if (updates == 0)
1131 	{
1132 		GetClientRect(xid[players].hwnd.hWnd, &rect);
1133 		InvalidateRect(xid[players].hwnd.hWnd, &rect, FALSE);
1134 		UpdateWindow(xid[players].hwnd.hWnd);
1135 	}
1136 	updates += 1;
1137 #else
1138 	RECT	rect;
1139 	static int updates = 0;
1140 	if (!itemsDC)
1141 		itemsDC = CreateCompatibleDC(NULL);
1142 
1143 	WinXSetupRadarWindow();
1144 
1145 	// One time stuff for score window update
1146 	if (updates == 0)
1147 	{
1148 		GetClientRect(xid[players].hwnd.hWnd, &rect);
1149 		InvalidateRect(xid[players].hwnd.hWnd, &rect, FALSE);
1150 		UpdateWindow(xid[players].hwnd.hWnd);
1151 	}
1152 	updates += 1;
1153 //	SelectPalette(hDC, myPal, FALSE);
1154 //	RealizePalette(hDC);
1155 
1156 //	xid[draw].hwnd.hDC = hDC;
1157 //	if (!itemsDC)
1158 //		itemsDC = CreateCompatibleDC(realDC);
1159 
1160 //	Paint_frame();
1161 //	xid[draw].hwnd.hBmpDC = realDC;
1162 	GetClientRect(xid[draw].hwnd.hWnd, &rect);
1163 	if (ThreadedDraw)
1164 	{
1165 //		FillRect(xid[draw].hwnd.hBmpDC, &rect, GetStockObject(WHITE_BRUSH));
1166 		winXTDraw(NULL, draw, &rect);
1167 	}
1168 	else
1169 	{
1170 		HDC		realDC = GetDC(xid[draw].hwnd.hWnd);
1171 		SelectPalette(realDC, myPal, FALSE);
1172 		RealizePalette(realDC);
1173 		BitBlt(realDC, 0, 0, rect.right, rect.bottom, xid[draw].hwnd.hBmpDC,
1174 			0, 0, SRCCOPY);
1175 		ReleaseDC(xid[draw].hwnd.hWnd, realDC);
1176 	}
1177 #endif
1178 }
1179 
MarkPlayersForRedraw()1180 void MarkPlayersForRedraw()
1181 {
1182 	RECT	rect;
1183 
1184 	GetClientRect(xid[players].hwnd.hWnd, &rect);
1185 	InvalidateRect(xid[players].hwnd.hWnd, &rect, FALSE);
1186 	UpdateWindow(xid[players].hwnd.hWnd);
1187 }
1188 
paintItemSymbol(unsigned char type,Drawable d,GC gc,int x,int y,int color)1189 void paintItemSymbol(unsigned char type, Drawable d, GC gc, int x, int y, int color)
1190 {
1191 	HDC		hDC = xid[d].hwnd.hBmpDC;
1192 
1193 	SelectObject(itemsDC, (HBITMAP)itemBitmaps[type][color]);
1194 	if (bHasPal)
1195 	{
1196 		SelectPalette(itemsDC, myPal, FALSE);
1197 		RealizePalette(itemsDC);
1198 	}
1199 	BitBlt(hDC, x, y, 16, 16, itemsDC, 0, 0, SRCPAINT);
1200 }
1201 
WinXBltPixToWin(Pixmap src,Window dest,int src_x,int src_y,unsigned int width,unsigned int height,int dest_x,int dest_y)1202 void WinXBltPixToWin(Pixmap src, Window dest,
1203 				  int src_x, int src_y, unsigned int width, unsigned int height,
1204 				  int dest_x, int dest_y)
1205 {
1206 	HDC		shDC = xid[src].hpix.hDC;
1207 	HDC		hDC = xid[dest].hwnd.hBmpDC;
1208 
1209 	BitBlt(hDC, dest_x, dest_y, width, height, shDC, src_x, src_y, SRCCOPY);
1210 }
1211 
WinXBltWinToPix(Window src,Pixmap dest,int src_x,int src_y,unsigned int width,unsigned int height,int dest_x,int dest_y)1212 void WinXBltWinToPix(Window src, Pixmap dest,
1213 				  int src_x, int src_y, unsigned int width, unsigned int height,
1214 				  int dest_x, int dest_y)
1215 {
1216 	HDC		hDC = xid[src].hwnd.hBmpDC;
1217 	HBITMAP hbm = xid[dest].hpix.hbm;
1218 
1219 	HDC		hDCd = CreateCompatibleDC(NULL);
1220 	int		ret;
1221 	SelectObject(hDC, hbm);
1222 	if (bHasPal)
1223 	{
1224 		SelectPalette(hDC, myPal, FALSE);
1225 		RealizePalette(hDC);
1226 	}
1227 	ret = BitBlt(hDC, dest_x, dest_y, width, height, hDC, src_x, src_y, BLACKNESS);
1228 	DeleteDC(hDCd);
1229 
1230 }
1231 
1232 #if 0
1233 void WinXPaintPlayers()
1234 {
1235 }
1236 #endif
1237 
WinXFlush(Window w)1238 void WinXFlush(Window w)
1239 {
1240 	RECT	r;
1241 	GetClientRect(xid[w].hwnd.hWnd, &r);
1242 	Trace("Flushing %d (%d/%d %d/%d)\n", w, r.left, r.top, r.right, r.bottom);
1243 	InvalidateRect(xid[w].hwnd.hWnd, &r, TRUE);
1244 }
1245 
WinXExit()1246 void WinXExit()
1247 {
1248 	PostMessage(GetParent(xid[top].hwnd.hWnd), WM_CLOSE, 0, 0);
1249 }
1250 
1251 
WinXSetEventMask(Window w,long mask)1252 void WinXSetEventMask(Window w, long mask)
1253 {
1254 	xid[w].hwnd.event_mask = mask;			/* this could be a macro, */
1255 }										/* but winX_.h is hidden from everyone */
1256 
WinXGetParent(Window w)1257 Window WinXGetParent(Window w)
1258 {
1259 	XID	i;
1260 	XID	txid;
1261 	HWND	hwnd = GetParent(xid[w].hwnd.hWnd);
1262 	if (!hwnd)
1263 		return(top);
1264 	for (i=0; i<MAX_XIDS; i++)
1265 	{
1266 		if (hwnd == xid[i].hwnd.hWnd)
1267 			return(i);
1268 	}
1269 /* create a new "Window" for the parent */
1270 	txid = GetFreeXid();
1271 	xid[txid].hwnd.hBmp = NULL;
1272 	xid[txid].hwnd.hBmpDC = NULL;
1273 	xid[txid].hwnd.hWnd = hwnd;
1274 	xid[txid].hwnd.event_mask = 0;
1275 	xid[txid].hwnd.event_mask = -1;		// hell, let's take em all!
1276 	xid[txid].hwnd.mouseover = 0;		// mouse not over this window
1277 	xid[txid].hwnd.type = XIDTYPE_HWND;
1278 	xid[txid].hwnd.notmine = TRUE;		// we don't destroy this one...
1279 #if 0
1280 	if (++max_xid > MAX_XIDS)
1281 	{
1282 		error("Too many XIDS!\n");
1283 		max_xid--;
1284 	}
1285 	return(max_xid-1);
1286 #endif
1287 	return(txid);
1288 }
1289 
WinXGetWindowRect(Window w,RECT * rect)1290 BOOL WinXGetWindowRect(Window w, RECT* rect)
1291 {
1292 	return(GetWindowRect(xid[w].hwnd.hWnd, rect));
1293 }
1294 
WinXGetWindowPlacement(Window w,WINDOWPLACEMENT * wp)1295 BOOL WinXGetWindowPlacement(Window w, WINDOWPLACEMENT* wp)
1296 {
1297 	return(GetWindowPlacement(xid[w].hwnd.hWnd, wp));
1298 }
1299 
GetFreeXid()1300 XID	GetFreeXid()
1301 {
1302 	int i;
1303 	for (i=0; i<MAX_XIDS; i++)
1304 		if (xid[i].type == XIDTYPE_UNUSED)
1305 			return(i);
1306 	error("No Free XIDs");
1307 	return(MAX_XIDS);
1308 }
1309 
1310 /*------------------------------------------------------*\
1311 * stubs for motd and talk window.  I wrote these Windows *
1312 * dialogs differently... I should revisit these to use   *
1313 * these new APIs.                                        *
1314 \*------------------------------------------------------*/
1315 bool talk_mapped = FALSE;
Talk_resize(void)1316 void Talk_resize(void)
1317 { }
Talk_do_event(XEvent * event)1318 int Talk_do_event(XEvent* event)
1319 { return(FALSE); }
1320 
1321