1 /* ---------------------------------------------------------------------- *
2 * winmain.c
3 * This file is part of lincity.
4 * Lincity is copyright (c) I J Peters 1995-1997, (c) Greg Sharp 1997-2001.
5 * ---------------------------------------------------------------------- */
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <math.h>
9 #include <malloc.h>
10 #include <memory.h>
11 #include "lcstring.h"
12 #include "lin-city.h"
13 #include "common.h"
14 #include "generic.h"
15 #include "mouse.h"
16 #include "lchelp.h"
17 #include "module_buttons.h"
18
19 // Define this to use DIB's instead of DDB's
20 // GCS: WIN32_USEDIB will no longer work, since I didn't update the
21 // window resizing code for DIB's.
22 //#define WIN32_USEDIB
23
24 // Global Variables
25 static char szClassNameWithMenu[] = APPNAME " (with menu)";
26 static char szClassNameWithoutMenu[] = APPNAME " (without menu)";
27 static char szAppName[] = APPNAME; // The name of this application
28 static char szTitle[] = APPNAME; // The title bar text
29 static HBRUSH hbrBackground = 0;
30
31 int pending_mouse_event = 0;
32 int pending_mouse_x = 0;
33 int pending_mouse_y = 0;
34
35 int pending_resize_event = 0;
36 int pending_resize_w = 0;
37 int pending_resize_h = 0;
38
39 // Private Function Prototypes
40 static ATOM MyRegisterClass (CONST WNDCLASS *);
41 static BOOL InitApplication (HINSTANCE);
42 static BOOL InitInstance (HINSTANCE, int);
43 static LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
44 static LRESULT CALLBACK About (HWND, UINT, WPARAM, LPARAM);
45 static BOOL CenterWindow (HWND, HWND);
46 static void InitializeBackingStore (HWND);
47 static BOOL CopyBackingStoreToScreen (HDC, HWND, LPPAINTSTRUCT);
48 static void CreateDDB (HWND hWnd);
49 static void CreateDIB (void);
50 static void InitializePalette (void);
51 static void DoSquareMouse (HDC hdc);
52 static void ResizeBackingStore (HWND hWnd);
53 static void ResizeDDB (HWND hWnd);
54
55
56 //----------------------------------------------------------------------------
57 // FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
58 //
59 // PURPOSE: Entry point for the application.
60 //
61 // COMMENTS:
62 //
63 // This function initializes the application and processes the
64 // message loop.
65 //----------------------------------------------------------------------------
66 int WINAPI
WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)67 WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
68 {
69 char *args[] = {"wlincity"};
70
71 if (!hPrevInstance) {
72 // Perform instance initialization:
73 if (!InitApplication (hInstance)) {
74 return (FALSE);
75 }
76 }
77
78 // Perform application initialization, including creating the
79 // Lin-City main window.
80 if (!InitInstance (hInstance, nCmdShow)) {
81 return (FALSE);
82 }
83
84 // Load keyboard accelerators (shortkut keys)
85 display.hAccelTable = LoadAccelerators (hInstance, szAppName);
86
87 // Take care of any outstanding messages
88 ProcessPendingEvents ();
89
90 // lincity_main() contains main message loop
91 lincity_main (1, args);
92
93 // Take care of any outstanding messages after main() finishes.
94 ProcessPendingEvents ();
95
96 return 0;
97 lpCmdLine; // This prevents 'unused formal parameter' warnings
98 }
99
100
101
102 //----------------------------------------------------------------------------
103 // FUNCTION: MyRegisterClass(CONST WNDCLASS*)
104 //
105 // PURPOSE: Registers the window class.
106 //
107 // COMMENTS:
108 //
109 // This function and its usage is only necessary if you want this code
110 // to be compatible with Win32 systems prior to the 'RegisterClassEx'
111 // function that was added to Windows 95. It is important to call this function
112 // so that the application will get 'well formed' small icons associated
113 // with it.
114 //----------------------------------------------------------------------------
MyRegisterClass(CONST WNDCLASS * lpwc)115 ATOM MyRegisterClass (CONST WNDCLASS * lpwc)
116 {
117 HANDLE hMod;
118 FARPROC proc;
119 WNDCLASSEX wcex;
120
121 hMod = GetModuleHandle ("USER32");
122 if (hMod != NULL) {
123 #if defined (UNICODE)
124 proc = GetProcAddress ((HMODULE) hMod, "RegisterClassExW");
125 #else /* */
126 proc = GetProcAddress ((HMODULE) hMod, "RegisterClassExA");
127 #endif /* */
128 if (proc != NULL) {
129 // GCS: This typedef is for the typecast in the return stmt below
130 typedef int (FAR WINAPI * my_FARPROC) (WNDCLASSEX *);
131
132 wcex.style = lpwc->style;
133 wcex.lpfnWndProc = lpwc->lpfnWndProc;
134 wcex.cbClsExtra = lpwc->cbClsExtra;
135 wcex.cbWndExtra = lpwc->cbWndExtra;
136 wcex.hInstance = lpwc->hInstance;
137 wcex.hIcon = lpwc->hIcon;
138 wcex.hCursor = lpwc->hCursor;
139 wcex.hbrBackground = lpwc->hbrBackground;
140 wcex.lpszMenuName = lpwc->lpszMenuName;
141 wcex.lpszClassName = lpwc->lpszClassName;
142
143 // Added elements for Windows 95:
144 wcex.cbSize = sizeof (WNDCLASSEX);
145 wcex.hIconSm = LoadIcon (wcex.hInstance, "SMALL");
146
147 return (*((my_FARPROC) (proc))) (&wcex);
148 }
149 }
150 return (RegisterClass (lpwc));
151 }
152
153
154 //----------------------------------------------------------------------------
155 // FUNCTION: InitApplication(HANDLE)
156 //
157 // PURPOSE: Initializes window data and registers window classes
158 //
159 // COMMENTS:
160 // We need two classes -- one which has a menu, one without a menu
161 // (for full-screen). This is registered by calling RegisterClass
162 // for Win 3.1/NT, or MyRegisterClass for Win 95.
163 //----------------------------------------------------------------------------
InitApplication(HINSTANCE hInstance)164 BOOL InitApplication (HINSTANCE hInstance)
165 {
166 WNDCLASS wcWithMenu;
167 WNDCLASS wcWithoutMenu;
168 // If Lin City is already running, focus existing process.
169 // Win32 always sets hPrevInstance to NULL, so check w/ FindWindow()
170 HWND hwnd = FindWindow (szClassNameWithMenu, NULL);
171
172 if (!hwnd)
173 hwnd = FindWindow (szClassNameWithoutMenu, NULL);
174 if (hwnd) {
175 // We found another version of ourself. Lets defer to it:
176 if (IsIconic (hwnd)) {
177 ShowWindow (hwnd, SW_RESTORE);
178 }
179 SetForegroundWindow (hwnd);
180 return FALSE;
181 }
182
183 // Create brush for background: Nasty Brown (Lin City color # 105)
184 hbrBackground = CreateSolidBrush (RGB (0x4C, 0x4C, 0));
185
186 // Fill in WNDCLASS for class WITH MENU.
187 wcWithMenu.style = 0;
188 wcWithMenu.lpfnWndProc = (WNDPROC) WndProc;
189 wcWithMenu.cbClsExtra = 0;
190 wcWithMenu.cbWndExtra = 0;
191 wcWithMenu.hInstance = hInstance;
192 wcWithMenu.hIcon = LoadIcon (hInstance, szAppName);
193 wcWithMenu.hCursor = LoadCursor (NULL, IDC_ARROW);
194 wcWithMenu.hbrBackground = hbrBackground;
195
196 // Windows95 has different recommended help menu format.
197 #if defined (USE_WIN32_MENU)
198 if (IS_WIN95) {
199 wcWithMenu.lpszMenuName = "WIN95";
200 } else {
201 wcWithMenu.lpszMenuName = szAppName;
202 }
203 wcWithMenu.lpszClassName = szClassNameWithMenu;
204 #else
205 wcWithMenu.lpszMenuName = "";
206 wcWithMenu.lpszClassName = szClassNameWithMenu;
207 #endif
208
209 // Fill in WNDCLASS for class WITHOUT MENU.
210 wcWithoutMenu.style = 0;
211 wcWithoutMenu.lpfnWndProc = (WNDPROC) WndProc;
212 wcWithoutMenu.cbClsExtra = 0;
213 wcWithoutMenu.cbWndExtra = 0;
214 wcWithoutMenu.hInstance = hInstance;
215 wcWithoutMenu.hIcon = LoadIcon (hInstance, szAppName);
216 wcWithoutMenu.hCursor = LoadCursor (NULL, IDC_ARROW);
217 wcWithoutMenu.hbrBackground = hbrBackground;
218 wcWithoutMenu.lpszMenuName = "";
219 wcWithoutMenu.lpszClassName = szClassNameWithoutMenu;
220
221 // Register the window classes and return success/failure code.
222 if (IS_WIN95) {
223 BOOL rv;
224 rv = MyRegisterClass (&wcWithMenu);
225 if (!rv)
226 return rv;
227 rv = MyRegisterClass (&wcWithoutMenu);
228 return rv;
229 } else {
230 BOOL rv;
231 rv = RegisterClass (&wcWithMenu);
232 if (!rv)
233 return rv;
234 rv = RegisterClass (&wcWithoutMenu);
235 return rv;
236 }
237 }
238
239
240 //----------------------------------------------------------------------------
241 // CheckClientSize (int width, int height, int with_menus)
242 // --
243 // Return 1 if the screen can support a client of this size
244 //----------------------------------------------------------------------------
245 void
CheckClientSize(int width,int height,int with_menus)246 CheckClientSize (int width, int height, int with_menus)
247 {
248 display.screenW = GetSystemMetrics (SM_CXSCREEN);
249 display.screenH = GetSystemMetrics (SM_CYSCREEN);
250 }
251
252 //----------------------------------------------------------------------------
253 // FUNCTION: InitInstance(HANDLE, int)
254 //
255 // PURPOSE: Creates main window
256 //----------------------------------------------------------------------------
257 BOOL
InitInstance(HINSTANCE hInstance,int nCmdShow)258 InitInstance (HINSTANCE hInstance, int nCmdShow)
259 {
260 HDC hDCGlobal = GetDC (NULL);
261 INT iRasterCaps;
262 char *szClassName = 0;
263 DWORD dwStyle;
264 RECT client_size;
265
266 // Determine graphics capabilities
267 iRasterCaps = GetDeviceCaps (hDCGlobal, RASTERCAPS);
268 if (iRasterCaps & RC_PALETTE) {
269 display.hasPalette = TRUE;
270 display.paletteSize = GetDeviceCaps (hDCGlobal, SIZEPALETTE);
271 display.defaultPaletteSize = GetDeviceCaps (hDCGlobal, NUMCOLORS);
272 } else {
273 display.hasPalette = FALSE;
274 }
275
276 display.colorDepth = GetDeviceCaps (hDCGlobal, BITSPIXEL);
277 ReleaseDC (NULL, hDCGlobal);
278
279 // Decide whether to use DIB's or DDB's
280 #if defined (WIN32_USEDIB)
281 if (display.colorDepth == 8) // Only use DIB for 256 colors
282 display.useDIB = TRUE;
283 else
284 display.useDIB = FALSE;
285 #else /* */
286 display.useDIB = FALSE;
287 #endif /* */
288
289 // Do some global initializations
290 display.hInst = hInstance;
291 display.fullscreen = FALSE;
292 //display.fullscreen = TRUE;
293 display.screenW = GetSystemMetrics (SM_CXSCREEN);
294 display.screenH = GetSystemMetrics (SM_CYSCREEN);
295 display.winFullscreenClientW = (INT) GetSystemMetrics (SM_CXFULLSCREEN);
296 display.winFullscreenClientH = (INT) GetSystemMetrics (SM_CYFULLSCREEN);
297 InitializePalette ();
298
299 // Choose one of Lin City window types
300 // a) no pix doubling, no border
301 // b) no pix doubling, 30 pixel border
302 // c) pix doubling, no border
303 // GCS FIX: This doesn't work. I need to call AdjustWindowRect on these values (?)
304 if ((display.screenW >= 2*WINWIDTH + 2*BORDERX) &&
305 (display.screenH >= 2*WINHEIGHT + 2*BORDERY)) {
306 pix_double = 1;
307 borderx = 1;
308 bordery = 1;
309 }
310 else if ((display.screenW >= 2*WINWIDTH) &&
311 (display.screenH >= 2*WINHEIGHT)) {
312 pix_double = 1;
313 borderx = 0;
314 bordery = 0;
315 }
316 else if ((display.screenW >= WINWIDTH + (2 * BORDERX))
317 &&(display.screenH >= WINHEIGHT + (2 * BORDERY))) {
318 pix_double = 0;
319 borderx = BORDERX;
320 bordery = BORDERY;
321 } else {
322 pix_double = 0;
323 borderx = 0;
324 bordery = 0;
325 }
326 display.clientW = ((pix_double + 1) * WINWIDTH) + (2 * borderx);
327 display.clientH = ((pix_double + 1) * WINHEIGHT) + (2 * bordery);
328
329 // Choose one of three client window types
330 // a) full screen
331 // b) maximized window
332 // c) regular window
333 // Prefer regular over maximized over full screen
334 dwStyle = WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SIZEBOX;
335 client_size.left = 0;
336 client_size.top = 0;
337 client_size.right = display.clientW;
338 client_size.bottom = display.clientH;
339 AdjustWindowRect (&client_size, dwStyle, TRUE);
340
341 if (((client_size.right - client_size.left) <= display.screenW)
342 &&((client_size.bottom - client_size.top) <= display.screenH))
343 {
344 // Use regular (overlapped) window
345 szClassName = szClassNameWithMenu;
346 if (client_size.left < 0) {
347 client_size.right -= client_size.left;
348 client_size.left = CW_USEDEFAULT;
349 }
350 if (client_size.top < 0) {
351 client_size.bottom -= client_size.top;
352 client_size.top = CW_USEDEFAULT;
353 }
354 } else {
355 // Check maximized by subtracting out the DLGFRAME size.
356 // Note that the "obvious" method of calling AdjustWindowRect()
357 // with style WS_MAXIMIZE doesn't work!
358 int win_border_x = GetSystemMetrics (SM_CXDLGFRAME);
359 int win_border_y = GetSystemMetrics (SM_CYDLGFRAME);
360 if (((client_size.right - client_size.left - 2 * win_border_x) <= display.screenW)
361 &&((client_size.bottom - client_size.top - 2 * win_border_y) <= display.screenH))
362 {
363 // Use maximized window
364 szClassName = szClassNameWithMenu;
365 // dwStyle |= WS_MAXIMIZE;
366 if (client_size.left < 0) {
367 client_size.right -= client_size.left;
368 client_size.left = CW_USEDEFAULT;
369 }
370 if (client_size.top < 0) {
371 client_size.bottom -= client_size.top;
372 client_size.top = CW_USEDEFAULT;
373 }
374 nCmdShow = SW_SHOWMAXIMIZED;
375 } else {
376 // Need fullsize window
377 szClassName = szClassNameWithoutMenu;
378 dwStyle = WS_POPUP;
379 client_size.left = 0;
380 client_size.top = 0;
381 client_size.right = display.screenW;
382 client_size.bottom = display.screenH;
383 }
384 }
385
386 display.min_h = client_size.bottom - client_size.top;
387 display.min_w = client_size.right - client_size.left;
388
389 // Create the window
390 display.hWnd = CreateWindow (szClassName, // Class name
391 szTitle, // Caption
392 dwStyle, // Style
393 client_size.left, client_size.top, // Position
394 client_size.right, client_size.bottom, // Size
395 (HWND) NULL, // Parent window (no parent)
396 (HMENU) NULL, // use class menu
397 (HINSTANCE) hInstance, // handle to window instance
398 (LPVOID) NULL // no params to pass on
399 );
400
401 if (!display.hWnd) {
402 return (FALSE);
403 }
404
405 // Display the window
406 ShowWindow (display.hWnd, nCmdShow);
407 UpdateWindow (display.hWnd);
408
409 return (TRUE);
410 }
411
412
413 //----------------------------------------------------------------------------
414 // FUNCTION: ProcessNextEvent ()
415 // Wait for a message if necessary,
416 // then process all messages.
417 //----------------------------------------------------------------------------
418 void
ProcessNextEvent(void)419 ProcessNextEvent (void)
420 {
421
422 MSG msg;
423 if (GetMessage (&msg, NULL, 0, 0)) {
424 if (!TranslateAccelerator (msg.hwnd, (HACCEL) display.hAccelTable,
425 &msg)) {
426 TranslateMessage (&msg);
427 DispatchMessage (&msg);
428 }
429 }
430 ProcessPendingEvents ();
431 }
432
433
434
435 //----------------------------------------------------------------------------
436 // FUNCTION: ProcessPendingEvents ()
437 // Process all outstanding messages.
438 //----------------------------------------------------------------------------
439 void
ProcessPendingEvents(void)440 ProcessPendingEvents (void)
441 {
442 MSG msg;
443 while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) {
444 if (!TranslateAccelerator (msg.hwnd, (HACCEL) display.hAccelTable,
445 &msg)) {
446 TranslateMessage (&msg);
447 DispatchMessage (&msg);
448 }
449 }
450 }
451
452
453
454 //----------------------------------------------------------------------------
455 // FUNCTION: EnableWindowsMenuItems ()
456 // FUNCTION: DisableWindowsMenuItems ()
457 // Enable and Disable "Load" and "Save" items
458 //----------------------------------------------------------------------------
459 void
EnableWindowsMenuItems(void)460 EnableWindowsMenuItems (void)
461 {
462 #if defined (USE_WIN32_MENU)
463 HMENU hMenu = GetMenu (display.hWnd);
464 EnableMenuItem (hMenu, IDM_OPEN, MF_BYCOMMAND | MF_ENABLED);
465 EnableMenuItem (hMenu, IDM_SAVE, MF_BYCOMMAND | MF_ENABLED);
466 EnableMenuItem (hMenu, IDM_HELPCONTENTS, MF_BYCOMMAND | MF_ENABLED);
467 #endif
468 }
469
470
471 void
DisableWindowsMenuItems(void)472 DisableWindowsMenuItems (void)
473 {
474 #if defined (USE_WIN32_MENU)
475 HMENU hMenu = GetMenu (display.hWnd);
476 EnableMenuItem (hMenu, IDM_OPEN, MF_BYCOMMAND | MF_GRAYED);
477 EnableMenuItem (hMenu, IDM_SAVE, MF_BYCOMMAND | MF_GRAYED);
478 EnableMenuItem (hMenu, IDM_HELPCONTENTS, MF_BYCOMMAND | MF_GRAYED);
479 #endif
480 }
481
482
483
484 //----------------------------------------------------------------------------
485 // FUNCTION: HandleMouse ()
486 //----------------------------------------------------------------------------
487 void
HandleMouse()488 HandleMouse ()
489 {
490 MSG msg;
491 /* Process queued events, ignoring mouse moves. */
492 while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) {
493 if (!TranslateAccelerator (msg.hwnd, (HACCEL) display.hAccelTable,
494 &msg)) {
495 pending_mouse_x = cs_mouse_x;
496 pending_mouse_y = cs_mouse_y;
497 pending_mouse_event = 0;
498 pending_resize_event = 0;
499 TranslateMessage (&msg);
500 DispatchMessage (&msg);
501 if (pending_mouse_event)
502 cs_mouse_handler (pending_mouse_event,
503 pending_mouse_x - cs_mouse_x,
504 pending_mouse_y - cs_mouse_y);
505 if (pending_resize_event) {
506 /* Force resize, because I can't tell difference between
507 size change and restoring a minimized window. Ideally,
508 this would simply redraw. */
509 display.winW = 0;
510 resize_geometry (pending_resize_w, pending_resize_h);
511 }
512 }
513 }
514
515 /* Now move the mouse if necessary. */
516 if (pending_mouse_x != cs_mouse_x
517 || pending_mouse_y != cs_mouse_y)
518 cs_mouse_handler (0, pending_mouse_x - cs_mouse_x,
519 pending_mouse_y - cs_mouse_y);
520 }
521
522
523
524 //----------------------------------------------------------------------------
525 // FUNCTION: GetKeystroke ()
526 //----------------------------------------------------------------------------
527 char
GetKeystroke()528 GetKeystroke ()
529 {
530 char key;
531 /* GCS 02/02/2003 I found out that sometimes the mouse events were
532 getting lost here. */
533 HandleMouse ();
534 // ProcessPendingEvents ();
535 key = x_key_value;
536 x_key_value = 0;
537 return key;
538 }
539
540
541
542 //----------------------------------------------------------------------------
543 // FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
544 //
545 // PURPOSE: Processes messages for the main window.
546 //----------------------------------------------------------------------------
WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)547 LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
548 {
549 #if defined (USE_WIN32_MENU)
550 int wmId, wmEvent;
551 #endif
552
553 switch (message)
554 {
555 #if defined (USE_WIN32_MENU)
556 case WM_COMMAND: {
557 wmId = LOWORD (wParam);
558 wmEvent = HIWORD (wParam);
559
560 //Parse the menu selections:
561 switch (wmId)
562 {
563
564 case IDM_OPEN:
565 load_flag = 1;
566 DisableWindowsMenuItems ();
567 break;
568
569 case IDM_SAVE:
570 save_flag = 1;
571 DisableWindowsMenuItems ();
572 break;
573
574 case IDM_EXIT:
575 // GCS FIX: I'm still not quite satisfied with this...
576 // x_key_value = 'q';
577 DestroyWindow (hWnd);
578 break;
579
580 case IDM_ABOUT:
581 DialogBox (display.hInst, "AboutBox", hWnd, (DLGPROC) About);
582 break;
583
584 case IDM_HELPCONTENTS:
585 help_flag = 1;
586 DisableWindowsMenuItems ();
587 activate_help ("index.hlp");
588 break;
589
590 default:
591 return (DefWindowProc (hWnd, message, wParam, lParam));
592 }
593 }
594 break;
595 #endif
596
597 case WM_KEYDOWN: {
598 int nVirtKey = (int) wParam;
599 x_key_shifted = (GetKeyState (VK_SHIFT) & 0x80000000) ? TRUE : FALSE;
600 switch (nVirtKey)
601 {
602 case VK_LEFT:
603 x_key_value = 1;
604 break;
605
606 case VK_DOWN:
607 x_key_value = 2;
608 break;
609
610 case VK_UP:
611 x_key_value = 3;
612 break;
613
614 case VK_RIGHT:
615 x_key_value = 4;
616 break;
617
618 case VK_ESCAPE:
619 x_key_value = 5;
620 break;
621 }
622 }
623 break;
624
625 case WM_CHAR: {
626 TCHAR chCharCode = (TCHAR) wParam; // character code
627 LPARAM lKeyData = lParam; // key data
628 if (chCharCode == 8) { // Fix backspace
629 chCharCode = 127;
630 } else if (chCharCode == VK_ESCAPE) { // Fix escape
631 chCharCode = 5;
632 }
633 x_key_value = chCharCode;
634 }
635 break;
636
637 // RightClick on windows non-client area
638 case WM_NCRBUTTONUP:
639 if (IS_WIN95 && SendMessage (hWnd, WM_NCHITTEST, 0, lParam) == HTSYSMENU)
640 {
641 // The user has clicked the right button on the applications
642 // 'System Menu'. Here is where you would alter the default
643 // system menu to reflect your application. Notice how the
644 // explorer deals with this. For this app, we aren't doing
645 // anything
646 return (DefWindowProc (hWnd, message, wParam, lParam));
647 } else {
648 // Nothing we are interested in, allow default handling...
649 return (DefWindowProc (hWnd, message, wParam, lParam));
650 }
651 break;
652
653 // RightClick in windows client area
654 case WM_RBUTTONDOWN:
655 pending_mouse_x = UnAdjustX (LOWORD (lParam));
656 pending_mouse_y = UnAdjustY (HIWORD (lParam));
657 pending_mouse_event = LC_MOUSE_RIGHTBUTTON | LC_MOUSE_PRESS;
658 cs_mouse_shifted = (wParam & MK_SHIFT) ? 1 : 0;
659 break;
660
661 // Left Click in windows client area
662 case WM_LBUTTONDOWN:
663 pending_mouse_x = UnAdjustX (LOWORD (lParam));
664 pending_mouse_y = UnAdjustY (HIWORD (lParam));
665 pending_mouse_event = LC_MOUSE_LEFTBUTTON | LC_MOUSE_PRESS;
666 cs_mouse_shifted = (wParam & MK_SHIFT) ? 1 : 0;
667 break;
668
669 case WM_RBUTTONUP:
670 pending_mouse_x = UnAdjustX (LOWORD (lParam));
671 pending_mouse_y = UnAdjustY (HIWORD (lParam));
672 pending_mouse_event = LC_MOUSE_RIGHTBUTTON | LC_MOUSE_RELEASE;
673 cs_mouse_shifted = (wParam & MK_SHIFT) ? 1 : 0;
674 break;
675
676 case WM_LBUTTONUP:
677 pending_mouse_x = UnAdjustX (LOWORD (lParam));
678 pending_mouse_y = UnAdjustY (HIWORD (lParam));
679 pending_mouse_event = LC_MOUSE_LEFTBUTTON | LC_MOUSE_RELEASE;
680 cs_mouse_shifted = (wParam & MK_SHIFT) ? 1 : 0;
681 break;
682
683 case WM_MOUSEMOVE:
684 pending_mouse_x = UnAdjustX (LOWORD (lParam));
685 pending_mouse_y = UnAdjustY (HIWORD (lParam));
686 cs_mouse_shifted = (wParam & MK_SHIFT) ? 1 : 0;
687 break;
688
689 // Only comes through on plug'n'play systems
690 case WM_DISPLAYCHANGE: {
691 SIZE szScreen;
692 BOOL fChanged = (BOOL) wParam;
693
694 szScreen.cx = LOWORD (lParam);
695 szScreen.cy = HIWORD (lParam);
696
697 if (fChanged) {
698 // The display 'has' changed. szScreen reflects the
699 // new size.
700 MessageBox (GetFocus (), "Display Changed", szAppName, 0);
701 } else {
702 // The display 'is' changing. szScreen reflects the
703 // original size.
704 MessageBeep (0);
705 }
706 }
707 break;
708
709 case WM_PAINT: {
710 PAINTSTRUCT ps;
711 HDC hdc;
712
713 hdc = BeginPaint (hWnd, &ps);
714 CopyBackingStoreToScreen (hdc, hWnd, &ps);
715 EndPaint (hWnd, &ps);
716 }
717 break;
718
719 // Create client area
720 case WM_CREATE:
721 InitializeBackingStore (hWnd);
722 break;
723
724 case WM_DESTROY:
725 // PostQuitMessage(0);
726 exit (0); // OK??
727 break;
728
729 case WM_SIZE:
730 // Resize window
731 if (wParam != SIZE_MINIMIZED) {
732 pending_resize_event = 1;
733 pending_resize_w = LOWORD (lParam);
734 pending_resize_h = HIWORD (lParam);
735 ResizeBackingStore (hWnd);
736 }
737 break;
738
739 case WM_GETMINMAXINFO: {
740 /* GCS FIX */
741 /* This needs to include client menu */
742 /* To do this, I need to call AdjustWindowRect, but
743 probably I need consider that the window might be POPUP... */
744 LPMINMAXINFO lpmmi = (LPMINMAXINFO) lParam;
745 #if defined (commentout)
746 lpmmi->ptMinTrackSize.x = (640 << pix_double) + 2 * borderx;
747 lpmmi->ptMinTrackSize.y = (480 << pix_double) + 2 * bordery;
748 #endif
749 lpmmi->ptMinTrackSize.x = display.min_w;
750 lpmmi->ptMinTrackSize.y = display.min_h;
751 break;
752 }
753
754 default:
755 return (DefWindowProc (hWnd, message, wParam, lParam));
756 }
757 return (0);
758 }
759
760
761
762 //----------------------------------------------------------------------------
763 // FUNCTION: InitializeBackingStore ()
764 //----------------------------------------------------------------------------
765 void
InitializeBackingStore(HWND hWnd)766 InitializeBackingStore (HWND hWnd)
767 {
768 RECT rc;
769
770 GetClientRect (hWnd, &rc);
771 display.winW = rc.right - rc.left;
772 display.winH = rc.bottom - rc.top;
773
774 InitializePalette ();
775 CreateDDB (hWnd);
776 if (display.useDIB) {
777 CreateDIB ();
778 }
779 display.hSaveUnderHdc = 0;
780 display.hSaveUnderBitmap = 0;
781 }
782
783 void
ResizeBackingStore(HWND hWnd)784 ResizeBackingStore (HWND hWnd)
785 {
786 ResizeDDB (hWnd);
787 if (display.useDIB) {
788 // This had better be false
789 exit(-1);
790 }
791 }
792
793
794
795 //----------------------------------------------------------------------------
796 // FUNCTION: InitializePalette ()
797 //----------------------------------------------------------------------------
798 void
InitializePalette(void)799 InitializePalette (void)
800 {
801 INT iLoop;
802
803 display.hPal = 0;
804 display.pLogPal = 0;
805 // Clear out palette arrays
806 for (iLoop = 0; iLoop < 256; iLoop++) {
807 display.colorrefPal[iLoop] = 0;
808 display.brushPal[iLoop] = 0;
809 }
810
811 // If the device uses a palette (e.g. 8 bit display),
812 // we need to create an HPALETTE for the HDC.
813 if (display.hasPalette) {
814 // Allocate memory for LOGPALETTE
815 display.pLogPal = (NPLOGPALETTE) LocalAlloc (LMEM_FIXED,
816 (sizeof (LOGPALETTE) +
817 (sizeof (PALETTEENTRY) * (display.paletteSize))));
818 if (!display.pLogPal) {
819 MessageBox (display.hWnd, "Not enough memory for logical palette.", NULL, MB_OK | MB_ICONHAND);
820 PostQuitMessage (0);
821 exit (-1);
822 }
823 display.pLogPal->palVersion = 0x300;
824 display.pLogPal->palNumEntries = display.paletteSize;
825
826 // Fill palette with system colors by default
827 for (iLoop = 0; iLoop < display.paletteSize; iLoop++) {
828 *((WORD *) (&display.pLogPal->palPalEntry[iLoop].peRed)) = (WORD) iLoop;
829 display.pLogPal->palPalEntry[iLoop].peBlue = 0;
830 display.pLogPal->palPalEntry[iLoop].peFlags = PC_EXPLICIT;
831 }
832
833 // Convert LOGPALETTE into HPALETTE
834 display.hPal = CreatePalette ((LPLOGPALETTE) display.pLogPal);
835 }
836 }
837
838
839 //----------------------------------------------------------------------------
840 // FUNCTION: CreateDIB ()
841 //----------------------------------------------------------------------------
842 void
CreateDIB(void)843 CreateDIB (void)
844 {
845 // Let's create a 256 color DIB, just for testing!
846 ULONG sizBMI;
847 INT iNumClr = 256;
848 INT iLoop;
849
850 // Get memory for 256 color BITMAPINFO
851 sizBMI = sizeof (BITMAPINFOHEADER) + sizeof (RGBQUAD) * iNumClr;
852 if ((display.pbminfo = (PBITMAPINFO) GlobalAlloc (GMEM_FIXED | GMEM_ZEROINIT, sizBMI)) == NULL) {
853 MessageBox (display.hWnd, "Failed in Memory Allocation for bminfo!", "Error", MB_OK);
854 exit (-1);
855 }
856
857 // Fill in bitmap info
858 display.pbminfo->bmiHeader.biSize = 0x28; // GDI needs this to work
859 display.pbminfo->bmiHeader.biWidth = display.winW;
860 display.pbminfo->bmiHeader.biHeight = display.winH;
861 display.pbminfo->bmiHeader.biPlanes = 1;
862 display.pbminfo->bmiHeader.biBitCount = 8;
863 display.pbminfo->bmiHeader.biCompression = BI_RGB;
864 // this choice for biSizeImage reflects one byte per pixel
865 display.pbminfo->bmiHeader.biSizeImage = display.winW * display.winH;
866 display.pbminfo->bmiHeader.biXPelsPerMeter = 0;
867 display.pbminfo->bmiHeader.biYPelsPerMeter = 0;
868 display.pbminfo->bmiHeader.biClrUsed = 0;
869 display.pbminfo->bmiHeader.biClrImportant = 0;
870
871 // Fill in colormap w/ black
872 for (iLoop = 0; iNumClr; iLoop++) {
873 display.pbminfo->bmiColors[iLoop].rgbRed = 0;
874 display.pbminfo->bmiColors[iLoop].rgbGreen = 0;
875 display.pbminfo->bmiColors[iLoop].rgbBlue = 0;
876 display.pbminfo->bmiColors[iLoop].rgbReserved = 0;
877 }
878
879 // CreateDIBSection() will allocate the pBits.
880 display.hDIB = CreateDIBSection (display.hdcMem, display.pbminfo,
881 DIB_RGB_COLORS,
882 (void **) (&display.pBits), NULL, 0);
883 }
884
885
886
887 //----------------------------------------------------------------------------
888 // FUNCTION: CreateDDB ()
889 //----------------------------------------------------------------------------
890 void
CreateDDB(HWND hWnd)891 CreateDDB (HWND hWnd)
892 {
893 HDC hdc;
894 HBITMAP hBitmapOri;
895 HPALETTE hPalOld;
896 RECT rect;
897 HBRUSH hbr, hbrOld;
898
899 hdc = GetDC (hWnd);
900 if (display.hasPalette) {
901 hPalOld = SelectPalette (hdc, (HPALETTE) display.hPal, FALSE);
902 if (RealizePalette (hdc)) {
903 UpdateColors (hdc);
904 }
905 }
906
907 // Before an application can use a memory device
908 // context for drawing operations, it must select
909 // a bitmap of the correct width and height into
910 // the device context. Once a bitmap has been selected,
911 // the device context can be used to prepare images
912 // that will be copied to the screen or printed.
913 display.hdcMem = CreateCompatibleDC (hdc);
914 if (display.hasPalette) {
915 display.hPaletteMemOri = SelectPalette (display.hdcMem, (HPALETTE) display.hPal, FALSE);
916 RealizePalette (display.hdcMem);
917 }
918 display.hBitmap = CreateCompatibleBitmap (hdc, display.winW, display.winH);
919 hBitmapOri = (HBITMAP) SelectObject (display.hdcMem, display.hBitmap);
920
921 // Write that nasty brown color into the backing store
922 rect.left = 0;
923 rect.top = 0;
924 rect.right = display.winW;
925 rect.bottom = display.winH;
926 hbr = hbrBackground;
927 hbrOld = (HBRUSH) SelectObject (hdc, hbr); // Select brush
928 FillRect (display.hdcMem, &rect, (HBRUSH) hbr); // Draw rectangle
929 hbr = (HBRUSH) SelectObject (display.hdcMem, hbrOld); // Unselect brush
930
931 #if defined (commentout)
932 // GCS: For now, just keep the old bitmap around.
933 // I'll use it to swap out the full-sized color bitmap
934 // when I do a SetDIBits/GetDIBits.
935 display.hBitmapOri = hBitmapOri;
936 #endif /* */
937
938 #if defined (commentout)
939 // GCS: Instead of reselecting the default bitmap back into the hdc,
940 // I'm gonna delete it. Any problems with this??
941 DeleteObject (hBitmapOri);
942 #endif /* */
943
944 ReleaseDC (hWnd, hdc);
945 }
946
947
948 void
ResizeDDB(HWND hWnd)949 ResizeDDB (HWND hWnd)
950 {
951 RECT rect;
952 HDC hdc;
953 HBRUSH hbr, hbrOld;
954
955 hdc = GetDC (hWnd);
956 DeleteObject (display.hBitmap);
957 display.hBitmap = CreateCompatibleBitmap (hdc, pending_resize_w, pending_resize_h);
958 SelectObject (display.hdcMem, display.hBitmap);
959
960 rect.left = 0;
961 rect.top = 0;
962 rect.right = pending_resize_w;
963 rect.bottom = pending_resize_h;
964 hbr = hbrBackground;
965 hbrOld = (HBRUSH) SelectObject (hdc, hbr); // Select brush
966 FillRect (display.hdcMem, &rect, (HBRUSH) hbr); // Draw rectangle
967 hbr = (HBRUSH) SelectObject (display.hdcMem, hbrOld); // Unselect brush
968
969 ReleaseDC (hWnd, hdc);
970 }
971
972 //----------------------------------------------------------------------------
973 // FUNCTION: CopyBackingStoreToScreen ()
974 //----------------------------------------------------------------------------
CopyBackingStoreToScreen(HDC hdc,HWND hWnd,LPPAINTSTRUCT ps)975 BOOL CopyBackingStoreToScreen (HDC hdc, HWND hWnd, LPPAINTSTRUCT ps)
976 {
977 HPALETTE hPalOld, hPalOldMem;
978
979 // Is this necessary???
980 if (display.hasPalette) {
981 hPalOldMem = SelectPalette (display.hdcMem, (HPALETTE) display.hPal, FALSE);
982 RealizePalette (display.hdcMem);
983 hPalOld = SelectPalette (hdc, (HPALETTE) display.hPal, FALSE);
984 RealizePalette (hdc);
985 }
986
987 // Copy DIB into DDB
988 if (display.useDIB) {
989 if (SetDIBits (display.hdcMem, display.hBitmap, 0,
990 display.pbminfo->bmiHeader.biHeight, (LPSTR) display.pBits,
991 display.pbminfo, DIB_RGB_COLORS) == 0)
992 {
993 MessageBox (display.hWnd, "Failed in SetDIBits!", "Error", MB_OK);
994 exit (-1);
995 }
996 }
997
998 // Blast DDB onto screen
999 if (!BitBlt (hdc, ps->rcPaint.left, ps->rcPaint.top,
1000 (int) ps->rcPaint.right - ps->rcPaint.left,
1001 (int) ps->rcPaint.bottom - ps->rcPaint.top,
1002 display.hdcMem, ps->rcPaint.left,
1003 ps->rcPaint.top, SRCCOPY))
1004 {
1005 MessageBox (NULL, "BitBlt failed!", "Failure!", MB_OK);
1006 }
1007
1008
1009 // Draw square mouse
1010 if (cs_square_mouse_visible) {
1011 DoSquareMouse (hdc);
1012 }
1013
1014 if (display.hasPalette) {
1015 display.hPal = SelectPalette (display.hdcMem, hPalOldMem, FALSE);
1016 display.hPal = SelectPalette (hdc, hPalOld, FALSE);
1017 }
1018 return TRUE;
1019 }
1020
1021
1022 //----------------------------------------------------------------------------
1023 // FUNCTION: DoSquareMouse ()
1024 //----------------------------------------------------------------------------
1025 void
DoSquareMouse(HDC hdc)1026 DoSquareMouse (HDC hdc)
1027 {
1028 RECT rect;
1029 int size;
1030 HBRUSH hbr, hbrOld;
1031
1032 size = (main_groups[selected_module_group].size) * 16;
1033
1034 // Select Brush
1035 hbr = GetPaletteBrush (white (31));
1036 hbrOld = (HBRUSH) SelectObject (hdc, hbr);
1037
1038 // Top rectangle
1039 rect.left = AdjustX (omx - 2);
1040 rect.top = AdjustY (omy - 2);
1041 rect.right = AdjustX (omx + size + 1);
1042 rect.bottom = AdjustY (omy - 1);
1043 FillRect (hdc, &rect, hbr);
1044
1045
1046 // Left rectangle
1047 rect.left = AdjustX (omx - 2);
1048 rect.top = AdjustY (omy);
1049 rect.right = AdjustX (omx - 1);
1050 rect.bottom = AdjustY (omy + size - 1);
1051 FillRect (hdc, &rect, hbr);
1052
1053 // Right rectangle
1054 rect.left = AdjustX (omx + size);
1055 rect.top = AdjustY (omy);
1056 rect.right = AdjustX (omx + size + 1);
1057 rect.bottom = AdjustY (omy + size - 1);
1058 FillRect (hdc, &rect, hbr);
1059
1060 // Bottom rectangle
1061 rect.left = AdjustX (omx - 2);
1062 rect.top = AdjustY (omy + size);
1063 rect.right = AdjustX (omx + size + 1);
1064 rect.bottom = AdjustY (omy + size + 1);
1065 FillRect (hdc, &rect, hbr);
1066
1067 // Unselect brush
1068 hbr = (HBRUSH) SelectObject (display.hdcMem, hbrOld);
1069 }
1070
1071
1072 //----------------------------------------------------------------------------
1073 // FUNCTION: CopyPixmapToScreen ()
1074 //----------------------------------------------------------------------------
1075 #if defined (USE_PIXMAPS)
1076 void
CopyPixmapToScreen(int t2,int src_x,int src_y,int width,int height,int dst_x,int dst_y)1077 CopyPixmapToScreen (int t2, int src_x, int src_y, int width, int height,
1078 int dst_x, int dst_y)
1079 {
1080 HDC hdcPixmap;
1081 RECT rect;
1082
1083 // Calculate update rectangle
1084 rect.left = AdjustX (dst_x);
1085 rect.top = AdjustY (dst_y);
1086 rect.right = AdjustX (dst_x + width + 1);
1087 rect.bottom = AdjustY (dst_y + height + 1);
1088
1089 // Copy bitmap
1090 if (display.useDIB) {
1091 HBITMAP hOldBitmap, hOldBitmapMem;
1092 hdcPixmap = CreateCompatibleDC (display.hdcMem);
1093 hOldBitmap = (HBITMAP) SelectObject (hdcPixmap, icon_pixmap[t2]);
1094 hOldBitmapMem = (HBITMAP) SelectObject (display.hdcMem, display.hDIB);
1095 BitBlt (display.hdcMem, dst_x, dst_y, width, height, hdcPixmap,
1096 src_x, src_y, SRCCOPY);
1097 icon_pixmap[t2] = (HBITMAP) SelectObject (hdcPixmap, hOldBitmap);
1098 display.hDIB = (HBITMAP) SelectObject (display.hdcMem, hOldBitmapMem);
1099 DeleteDC (hdcPixmap);
1100 } else {
1101 HBITMAP hOldBitmap;
1102 hdcPixmap = CreateCompatibleDC (display.hdcMem);
1103 hOldBitmap = (HBITMAP) SelectObject (hdcPixmap, icon_pixmap[t2]);
1104 BitBlt (display.hdcMem, AdjustX (dst_x), AdjustY (dst_y),
1105 width << pix_double, height << pix_double, hdcPixmap,
1106 src_x << pix_double, src_y << pix_double, SRCCOPY);
1107 icon_pixmap[t2] = (HBITMAP) SelectObject (hdcPixmap, hOldBitmap);
1108 DeleteDC (hdcPixmap);
1109 }
1110
1111 // Queue up refresh
1112 InvalidateRect (display.hWnd, &rect, FALSE);
1113 }
1114 #endif /* */
1115
1116
1117 //----------------------------------------------------------------------------
1118 // FUNCTION: About(HWND, unsigned, WORD, LONG)
1119 //
1120 // PURPOSE: Processes messages for "About" dialog box
1121 // This version allows greater flexibility over the contents of the 'About' box,
1122 // by pulling out values from the 'Version' resource.
1123 //
1124 // MESSAGES:
1125 //
1126 // WM_INITDIALOG - initialize dialog box
1127 // WM_COMMAND - Input received
1128 //
1129 //----------------------------------------------------------------------------
1130 #if defined (USE_WIN32_MENU)
About(HWND hDlg,UINT message,WPARAM wParam,LPARAM lParam)1131 LRESULT CALLBACK About (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
1132 {
1133 static HFONT hfontDlg; // Font for dialog text
1134 static HFONT hFinePrint; // Font for 'fine print' in dialog
1135 DWORD dwVerInfoSize; // Size of version information block
1136 LPSTR lpVersion; // String pointer to 'version' text
1137 DWORD dwVerHnd = 0; // An 'ignored' parameter, always '0'
1138 UINT uVersionLen;
1139 WORD wRootLen;
1140 BOOL bRetCode;
1141 int i;
1142 char szFullPath[256];
1143 char szResult[256];
1144 char szGetName[256];
1145 DWORD dwVersion;
1146 char szVersion[40];
1147 DWORD dwResult;
1148
1149 switch (message)
1150 {
1151 case WM_INITDIALOG:
1152 ShowWindow (hDlg, SW_HIDE);
1153 hfontDlg = CreateFont (16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1154 VARIABLE_PITCH | FF_SWISS, "");
1155 hFinePrint = CreateFont (16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1156 VARIABLE_PITCH | FF_SWISS, "");
1157 CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));
1158 GetModuleFileName (display.hInst, szFullPath, sizeof (szFullPath));
1159
1160 // Now lets dive in and pull out the version information:
1161 dwVerInfoSize = GetFileVersionInfoSize (szFullPath, &dwVerHnd);
1162 if (dwVerInfoSize) {
1163 LPSTR lpstrVffInfo;
1164 HANDLE hMem;
1165 hMem = GlobalAlloc (GMEM_MOVEABLE, dwVerInfoSize);
1166 lpstrVffInfo = (char *) GlobalLock (hMem);
1167 GetFileVersionInfo (szFullPath, dwVerHnd, dwVerInfoSize, lpstrVffInfo);
1168
1169 // The below 'hex' value looks a little confusing, but
1170 // essentially what it is, is the hexidecimal representation
1171 // of a couple different values that represent the language
1172 // and character set that we are wanting string values for.
1173 // 040904E4 is a very common one, because it means:
1174 // US English, Windows MultiLingual characterset
1175 // Or to pull it all apart:
1176 // 04------ = SUBLANG_ENGLISH_USA
1177 // --09---- = LANG_ENGLISH
1178 // ----04E4 = 1252 = Codepage for Windows:Multilingual
1179 lstrcpy (szGetName, "\\StringFileInfo\\040904E4\\");
1180 wRootLen = lstrlen (szGetName); // Save this position
1181
1182 // Set the title of the dialog:
1183 lstrcat (szGetName, "ProductName");
1184 bRetCode = VerQueryValue ((LPVOID) lpstrVffInfo,
1185 (LPSTR) szGetName,
1186 (LPVOID *) & lpVersion,
1187 (UINT *) & uVersionLen);
1188 lstrcpy (szResult, "About ");
1189 lstrcat (szResult, lpVersion);
1190 SetWindowText (hDlg, szResult);
1191
1192 // Walk through the dialog items that we want to replace:
1193 for (i = DLG_VERFIRST; i <= DLG_VERLAST; i++) {
1194 GetDlgItemText (hDlg, i, szResult, sizeof (szResult));
1195 szGetName[wRootLen] = (char) 0;
1196 lstrcat (szGetName, szResult);
1197 uVersionLen = 0;
1198 lpVersion = NULL;
1199 bRetCode = VerQueryValue ((LPVOID) lpstrVffInfo,
1200 (LPSTR) szGetName,
1201 (LPVOID *) & lpVersion,
1202 (UINT *) & uVersionLen);
1203
1204 if (bRetCode && uVersionLen && lpVersion) {
1205 // Replace dialog item text with version info
1206 lstrcpy (szResult, lpVersion);
1207 SetDlgItemText (hDlg, i, szResult);
1208 } else {
1209 dwResult = GetLastError ();
1210 wsprintf (szResult, "Error %lu", dwResult);
1211 SetDlgItemText (hDlg, i, szResult);
1212 }
1213 SendMessage (GetDlgItem (hDlg, i), WM_SETFONT,
1214 (UINT) ((i == DLG_VERLAST) ? hFinePrint : hfontDlg),
1215 TRUE);
1216 }
1217 GlobalUnlock (hMem);
1218 GlobalFree (hMem);
1219 } else {
1220 // No version information available.
1221 }
1222 SendMessage (GetDlgItem (hDlg, IDC_LABEL), WM_SETFONT,
1223 (WPARAM) hfontDlg, (LPARAM) TRUE);
1224
1225 // We are using GetVersion rather then GetVersionEx
1226 // because earlier versions of Windows NT and Win32s
1227 // didn't include GetVersionEx:
1228 dwVersion = GetVersion ();
1229 if (dwVersion < 0x80000000) {
1230 // Windows NT
1231 wsprintf (szVersion, "Microsoft Windows NT %u.%u (Build: %u)",
1232 (DWORD) (LOBYTE (LOWORD (dwVersion))),
1233 (DWORD) (HIBYTE (LOWORD (dwVersion))),
1234 (DWORD) (HIWORD (dwVersion)));
1235
1236 } else if (LOBYTE (LOWORD (dwVersion)) < 4) {
1237 // Win32s
1238 wsprintf (szVersion, "Microsoft Win32s %u.%u (Build: %u)",
1239 (DWORD) (LOBYTE (LOWORD (dwVersion))),
1240 (DWORD) (HIBYTE (LOWORD (dwVersion))),
1241 (DWORD) (HIWORD (dwVersion) & ~0x8000));
1242 } else {
1243 // Windows 95
1244 wsprintf (szVersion, "Microsoft Windows 95 %u.%u",
1245 (DWORD) (LOBYTE (LOWORD (dwVersion))),
1246 (DWORD) (HIBYTE (LOWORD (dwVersion))));
1247 }
1248 SetWindowText (GetDlgItem (hDlg, IDC_OSVERSION), szVersion);
1249 ShowWindow (hDlg, SW_SHOW);
1250 return (TRUE);
1251
1252 case WM_COMMAND:
1253 if (LOWORD (wParam) == IDOK || LOWORD (wParam) == IDCANCEL) {
1254 EndDialog (hDlg, TRUE);
1255 DeleteObject (hfontDlg);
1256 DeleteObject (hFinePrint);
1257 return (TRUE);
1258 }
1259 break;
1260 }
1261 return FALSE;
1262 }
1263
1264
1265
1266 //----------------------------------------------------------------------------
1267 // FUNCTION: CenterWindow(HWND, HWND)
1268 //
1269 // PURPOSE: Centers one window over another.
1270 //
1271 // COMMENTS:
1272 //
1273 // In this function, we save the instance handle in a global variable and
1274 // create and display the main program window.
1275 //
1276 // This functionwill center one window over another ensuring that
1277 // the placement of the window is within the 'working area', meaning
1278 // that it is both within the display limits of the screen, and not
1279 // obscured by the tray or other framing elements of the desktop.
1280 //----------------------------------------------------------------------------
CenterWindow(HWND hwndChild,HWND hwndParent)1281 BOOL CenterWindow (HWND hwndChild, HWND hwndParent)
1282 {
1283 RECT rChild, rParent, rWorkArea;
1284 int wChild, hChild, wParent, hParent;
1285 int xNew, yNew;
1286 BOOL bResult;
1287
1288 // Get the Height and Width of the child window
1289 GetWindowRect (hwndChild, &rChild);
1290 wChild = rChild.right - rChild.left;
1291 hChild = rChild.bottom - rChild.top;
1292
1293 // Get the Height and Width of the parent window
1294 GetWindowRect (hwndParent, &rParent);
1295 wParent = rParent.right - rParent.left;
1296 hParent = rParent.bottom - rParent.top;
1297
1298 // Get the limits of the 'workarea'
1299 bResult = SystemParametersInfo (SPI_GETWORKAREA,
1300 sizeof (RECT),
1301 &rWorkArea,
1302 0);
1303
1304 if (!bResult) {
1305 rWorkArea.left = rWorkArea.top = 0;
1306 rWorkArea.right = GetSystemMetrics (SM_CXSCREEN);
1307 rWorkArea.bottom = GetSystemMetrics (SM_CYSCREEN);
1308 }
1309
1310 // Calculate new X position, then adjust for workarea
1311 xNew = rParent.left + ((wParent - wChild) / 2);
1312
1313 if (xNew < rWorkArea.left) {
1314 xNew = rWorkArea.left;
1315 }
1316 else if ((xNew + wChild) > rWorkArea.right) {
1317 xNew = rWorkArea.right - wChild;
1318 }
1319
1320 // Calculate new Y position, then adjust for workarea
1321 yNew = rParent.top + ((hParent - hChild) / 2);
1322 if (yNew < rWorkArea.top) {
1323 yNew = rWorkArea.top;
1324 } else if ((yNew + hChild) > rWorkArea.bottom) {
1325 yNew = rWorkArea.bottom - hChild;
1326 }
1327
1328 // Set it, and return
1329 return SetWindowPos (hwndChild, NULL, xNew, yNew, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
1330 }
1331 #endif /* USE_WIN32_MENU */
1332
1333
1334 //----------------------------------------------------------------------------
1335 // FUNCTION: AddPaletteEntry ()
1336 //----------------------------------------------------------------------------
1337 void
AddPaletteEntry(int col,int red,int grn,int blu)1338 AddPaletteEntry (int col, int red, int grn, int blu)
1339 {
1340
1341 red = (red * 255) / 62;
1342 if (red > 255)
1343 red = 255;
1344
1345 grn = (grn * 255) / 62;
1346 if (grn > 255)
1347 grn = 255;
1348
1349 blu = (blu * 255) / 62;
1350 if (blu > 255)
1351 blu = 255;
1352
1353 display.colorrefPal[col] = RGB (red, grn, blu);
1354
1355 if (display.brushPal[col]) {
1356 DeleteObject (display.brushPal[col]);
1357 display.brushPal[col] = 0;
1358 }
1359
1360 if (display.hasPalette) {
1361 display.pLogPal->palPalEntry[col].peRed = red;
1362 display.pLogPal->palPalEntry[col].peGreen = grn;
1363 display.pLogPal->palPalEntry[col].peBlue = blu;
1364 display.pLogPal->palPalEntry[col].peFlags = PC_NOCOLLAPSE;
1365 }
1366
1367 if (display.useDIB) {
1368 display.pbminfo->bmiColors[col].rgbRed = red;
1369 display.pbminfo->bmiColors[col].rgbGreen = grn;
1370 display.pbminfo->bmiColors[col].rgbBlue = blu;
1371 display.pbminfo->bmiColors[col].rgbReserved = 0;
1372 }
1373 }
1374
1375
1376 //----------------------------------------------------------------------------
1377 // FUNCTION: UpdatePalette ()
1378 //----------------------------------------------------------------------------
1379 void
UpdatePalette(void)1380 UpdatePalette (void)
1381 {
1382 if (display.hasPalette) {
1383 // Make a new HPALETTE and select to hdcGlobal and hdcMem
1384 HPALETTE hPalNew;
1385 hPalNew = CreatePalette ((LPLOGPALETTE) display.pLogPal);
1386 SelectPalette (display.hdcMem, hPalNew, FALSE);
1387 RealizePalette (display.hdcMem);
1388 DeleteObject (display.hPal);
1389 display.hPal = hPalNew;
1390 }
1391 }
1392
1393