1 /*
2 * (c) Copyright 1993, Silicon Graphics, Inc.
3 * ALL RIGHTS RESERVED
4 * Permission to use, copy, modify, and distribute this software for
5 * any purpose and without fee is hereby granted, provided that the above
6 * copyright notice appear in all copies and that both the copyright notice
7 * and this permission notice appear in supporting documentation, and that
8 * the name of Silicon Graphics, Inc. not be used in advertising
9 * or publicity pertaining to distribution of the software without specific,
10 * written prior permission.
11 *
12 * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS"
13 * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE,
14 * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR
15 * FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
16 * GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT,
17 * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY
18 * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION,
19 * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF
20 * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN
21 * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON
22 * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE
23 * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE.
24 *
25 * US Government Users Restricted Rights
26 * Use, duplication, or disclosure by the Government is subject to
27 * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
28 * (c)(1)(ii) of the Rights in Technical Data and Computer Software
29 * clause at DFARS 252.227-7013 and/or in similar or successor
30 * clauses in the FAR or the DOD or NASA FAR Supplement.
31 * Unpublished-- rights reserved under the copyright laws of the
32 * United States. Contractor/manufacturer is Silicon Graphics,
33 * Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311.
34 *
35 * OpenGL(TM) is a trademark of Silicon Graphics, Inc.
36 */
37
38 // Mesa Tweaking by: Mark E. Peterson (markp@ic.mankato.mn.us)
39
40 #include <windows.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include "tk.h"
45 /* #include "gl\wmesa.h" */
46
47 #define static
48
49 #if defined(__cplusplus) || defined(c_plusplus)
50 #define class c_class
51 #endif
52
53 #if DBG
54 #define TKASSERT(x) \
55 if ( !(x) ) { \
56 PrintMessage("%s(%d) Assertion failed %s\n", \
57 __FILE__, __LINE__, #x); \
58 }
59 #else
60 #define TKASSERT(x)
61 #endif /* DBG */
62
63 /******************************************************************************/
64
65 static struct _WINDOWINFO {
66 int x, y;
67 int width, height;
68 GLenum type;
69 GLenum dmPolicy;
70 int ipfd;
71 BOOL bDefPos;
72 } windInfo = {
73 0, 0, 100, 100, TK_INDEX | TK_SINGLE, TK_MINIMUM_CRITERIA, 0, TRUE
74 };
75
76
77 static HWND tkhwnd = NULL;
78 static HDC tkhdc = NULL;
79 static HPALETTE tkhpalette = NULL;
80 GLboolean tkPopupEnable = TRUE;
81
82 // Fixed palette support.
83
84 #define BLACK PALETTERGB(0,0,0)
85 #define WHITE PALETTERGB(255,255,255)
86 #define NUM_STATIC_COLORS (COLOR_BTNHIGHLIGHT - COLOR_SCROLLBAR + 1)
87
88 static void (*ExposeFunc)(int, int) = NULL;
89 static void (*ReshapeFunc)(GLsizei, GLsizei) = NULL;
90 static void (*DisplayFunc)(void) = NULL;
91 static GLenum (*KeyDownFunc)(int, GLenum) = NULL;
92 static GLenum (*MouseDownFunc)(int, int, GLenum) = NULL;
93 static GLenum (*MouseUpFunc)(int, int, GLenum) = NULL;
94 static GLenum (*MouseMoveFunc)(int, int, GLenum) = NULL;
95 static void (*IdleFunc)(void) = NULL;
96
97 static char *lpszClassName = "tkLibWClass";
98 static WCHAR *lpszClassNameW = L"tkLibWClass";
99
100 long FAR PASCAL _export tkWndProc(HWND hWnd, UINT message, DWORD wParam, LONG lParam);
101 static unsigned char ComponentFromIndex(int i, int nbits, int shift );
102 static void PrintMessage( const char *Format, ... );
103 //static PALETTEENTRY *FillRgbPaletteEntries( PIXELFORMATDESCRIPTOR *Pfd, PALETTEENTRY *Entries, UINT Count );
104 static HPALETTE CreateCIPalette( HDC Dc );
105 static HPALETTE CreateRGBPalette( HDC hdc );
106 static void DestroyThisWindow( HWND Window );
107 static void CleanUp( void );
108 static void DelayPaletteRealization( void );
109 static long RealizePaletteNow( HDC Dc, HPALETTE Palette);
110 static void ForceRedraw( HWND Window );
111 static void *AllocateMemory( size_t Size );
112 static void *AllocateZeroedMemory( size_t Size );
113 static void FreeMemory( void *Chunk );
114
115 /*
116 * Prototypes for the debugging functions go here
117 */
118
119 #define DBGFUNC 0
120 #if DBGFUNC
121
122 static void DbgPrintf( const char *Format, ... );
123 static void pwi( void );
124 static void pwr(RECT *pr);
125 //static void ShowPixelFormat(HDC hdc);
126
127 #endif
128 #define NCOLORS 17
129 float tkRGBMap[NCOLORS][3] = {
130 {0,0,0},
131 {0,0,0},
132 {0,0,0},
133 {0,0,0},
134 {0,0,0},
135 {0,0,0},
136 {0,0,0},
137 {0,0,0},
138 {0,0,0},
139 {0,0,0},
140 {1,0,0},
141 {0,1,0},
142 {1,1,0},
143 {0,0,1},
144 {1,0,1},
145 {0,1,1},
146 {1,1,1}
147 };
148
149
150 /***************************************************************
151 * *
152 * Exported Functions go here *
153 * *
154 ***************************************************************/
155
tkErrorPopups(GLboolean bEnable)156 void tkErrorPopups(GLboolean bEnable)
157 {
158 tkPopupEnable = bEnable;
159 }
160
tkCloseWindow(void)161 void tkCloseWindow(void)
162 {
163 DestroyThisWindow(tkhwnd);
164 /* if (w.cMain) {
165 XMesaDestroyContext(w.cMain);
166 }*/
167 WMesaDestroyContext(NULL);
168 }
169
170
tkExec(void)171 void tkExec(void)
172 {
173 MSG Message;
174
175 /*
176 * WM_SIZE gets delivered before we get here!
177 */
178
179 if (ReshapeFunc)
180 {
181 RECT ClientRect;
182
183 GetClientRect(tkhwnd, &ClientRect);
184 (*ReshapeFunc)(ClientRect.right, ClientRect.bottom);
185 }
186
187 while (GL_TRUE)
188 {
189 /*
190 * Process all pending messages
191 */
192
193 while (PeekMessage(&Message, NULL, 0, 0, PM_NOREMOVE) == TRUE)
194 {
195 if (GetMessage(&Message, NULL, 0, 0) )
196 {
197 TranslateMessage(&Message);
198 DispatchMessage(&Message);
199 }
200 else
201 {
202 /*
203 * Nothing else to do here, just return
204 */
205
206 return;
207 }
208 }
209
210 /*
211 * If an idle function was defined, call it
212 */
213
214 if (IdleFunc)
215 {
216 (*IdleFunc)();
217 }
218 }
219 }
220
tkExposeFunc(void (* Func)(int,int))221 void tkExposeFunc(void (*Func)(int, int))
222 {
223 ExposeFunc = Func;
224 }
225
tkReshapeFunc(void (* Func)(GLsizei,GLsizei))226 void tkReshapeFunc(void (*Func)(GLsizei, GLsizei))
227 {
228 ReshapeFunc = Func;
229 }
230
tkDisplayFunc(void (* Func)(void))231 void tkDisplayFunc(void (*Func)(void))
232 {
233 DisplayFunc = Func;
234 }
235
tkKeyDownFunc(GLenum (* Func)(int,GLenum))236 void tkKeyDownFunc(GLenum (*Func)(int, GLenum))
237 {
238 KeyDownFunc = Func;
239 }
240
tkMouseDownFunc(GLenum (* Func)(int,int,GLenum))241 void tkMouseDownFunc(GLenum (*Func)(int, int, GLenum))
242 {
243 MouseDownFunc = Func;
244 }
245
tkMouseUpFunc(GLenum (* Func)(int,int,GLenum))246 void tkMouseUpFunc(GLenum (*Func)(int, int, GLenum))
247 {
248 MouseUpFunc = Func;
249 }
250
tkMouseMoveFunc(GLenum (* Func)(int,int,GLenum))251 void tkMouseMoveFunc(GLenum (*Func)(int, int, GLenum))
252 {
253 MouseMoveFunc = Func;
254 }
255
tkIdleFunc(void (* Func)(void))256 void tkIdleFunc(void (*Func)(void))
257 {
258 IdleFunc = Func;
259 }
260
tkInitPosition(int x,int y,int width,int height)261 void tkInitPosition(int x, int y, int width, int height)
262 {
263 if (x == CW_USEDEFAULT)
264 {
265 x = 0;
266 y = 0;
267 windInfo.bDefPos = TRUE;
268 }
269 else
270 windInfo.bDefPos = FALSE;
271
272 windInfo.x = x + GetSystemMetrics(SM_CXFRAME);
273 windInfo.y = y + GetSystemMetrics(SM_CYCAPTION)
274 - GetSystemMetrics(SM_CYBORDER)
275 + GetSystemMetrics(SM_CYFRAME);
276 windInfo.width = width;
277 windInfo.height = height;
278 }
279
tkInitDisplayMode(GLenum type)280 void tkInitDisplayMode(GLenum type)
281 {
282 windInfo.type = type;
283 }
284
tkInitDisplayModePolicy(GLenum type)285 void tkInitDisplayModePolicy(GLenum type)
286 {
287 windInfo.dmPolicy = type;
288 }
289
tkInitDisplayModeID(GLint ipfd)290 GLenum tkInitDisplayModeID(GLint ipfd)
291 {
292 windInfo.ipfd = ipfd;
293 return GL_TRUE;
294 }
295
tkInitWindowAW(char * title,BOOL bUnicode)296 GLenum tkInitWindowAW(char *title, BOOL bUnicode)
297 {
298 WMesaContext Cur;
299 WNDCLASS wndclass;
300 RECT WinRect;
301 HANDLE hInstance;
302 ATOM aRegister;
303 GLenum Result = GL_FALSE,RGB_Flag=GL_TRUE,DB_Flag=GL_FALSE;
304
305 hInstance = GetModuleHandle(NULL);
306
307 // Must not define CS_CS_PARENTDC style.
308 wndclass.style = CS_HREDRAW | CS_VREDRAW;
309 wndclass.lpfnWndProc = (WNDPROC)tkWndProc;
310 wndclass.cbClsExtra = 0;
311 wndclass.cbWndExtra = 0;
312 wndclass.hInstance = hInstance;
313 wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
314 wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
315 wndclass.hbrBackground = GetStockObject(BLACK_BRUSH);
316 wndclass.lpszMenuName = NULL;
317
318 if (bUnicode)
319 wndclass.lpszClassName = (LPCSTR)lpszClassNameW;
320 else
321 wndclass.lpszClassName = (LPCSTR)lpszClassName;
322
323 if (bUnicode)
324 {
325 aRegister = RegisterClassW((CONST WNDCLASSW *)&wndclass);
326 }
327 else
328 {
329 aRegister = RegisterClass(&wndclass);
330 }
331
332
333 /*
334 * If the window failed to register, then there's no
335 * need to continue further.
336 */
337
338 if(0 == aRegister)
339 {
340 PrintMessage("Failed to register window class\n");
341 return(Result);
342 }
343
344
345 /*
346 * Make window large enough to hold a client area as large as windInfo
347 */
348
349 WinRect.left = windInfo.x;
350 WinRect.right = windInfo.x + windInfo.width;
351 WinRect.top = windInfo.y;
352 WinRect.bottom = windInfo.y + windInfo.height;
353
354 AdjustWindowRect(&WinRect, WS_OVERLAPPEDWINDOW, FALSE);
355
356 /*
357 * Must use WS_CLIPCHILDREN and WS_CLIPSIBLINGS styles.
358 */
359
360 if (bUnicode)
361 {
362 tkhwnd = CreateWindowW(
363 (LPCWSTR)lpszClassNameW,
364 (LPCWSTR)title,
365 WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
366 (windInfo.bDefPos) ? CW_USEDEFAULT : WinRect.left,
367 (windInfo.bDefPos) ? CW_USEDEFAULT : WinRect.top,
368 WinRect.right - WinRect.left,
369 WinRect.bottom - WinRect.top,
370 NULL,
371 NULL,
372 hInstance,
373 NULL);
374 }
375 else
376 {
377 tkhwnd = CreateWindow(
378 lpszClassName,
379 title,
380 WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
381 (windInfo.bDefPos) ? CW_USEDEFAULT : WinRect.left,
382 (windInfo.bDefPos) ? CW_USEDEFAULT : WinRect.top,
383 WinRect.right - WinRect.left,
384 WinRect.bottom - WinRect.top,
385 NULL,
386 NULL,
387 hInstance,
388 NULL);
389 }
390
391 if ( NULL != tkhwnd )
392 {
393 // If default window positioning used, find out window position and fix
394 // up the windInfo position info.
395
396 if (windInfo.bDefPos)
397 {
398 GetWindowRect(tkhwnd, &WinRect);
399 windInfo.x = WinRect.left + GetSystemMetrics(SM_CXFRAME);
400 windInfo.y = WinRect.top + GetSystemMetrics(SM_CYCAPTION)
401 - GetSystemMetrics(SM_CYBORDER)
402 + GetSystemMetrics(SM_CYFRAME);
403 }
404
405 tkhdc = GetDC(tkhwnd);
406
407 if ( NULL != tkhdc )
408 ShowWindow(tkhwnd, SW_SHOWDEFAULT);
409 else
410 PrintMessage("Could not get an HDC for window 0x%08lX\n", tkhwnd );
411 }
412 else
413 PrintMessage("create window failed\n");
414 if (windInfo.type & TK_INDEX)
415 {
416 RGB_Flag=GL_FALSE;
417 tkSetRGBMap(NCOLORS,(float *) tkRGBMap);
418 }
419 if (windInfo.type & TK_DOUBLE)
420 DB_Flag=GL_TRUE;
421 Cur=WMesaCreateContext(tkhwnd,tkhpalette,RGB_Flag,DB_Flag);
422 WMesaMakeCurrent(Cur);
423 return GL_TRUE;
424 }
425
426 // Initialize a window, create a rendering context for that window
tkInitWindow(char * title)427 GLenum tkInitWindow(char *title)
428 {
429 TKASSERT( NULL==tkhwnd );
430 TKASSERT( NULL==tkhdc );
431 TKASSERT( NULL==tkhrc );
432 TKASSERT( NULL==tkhpalette );
433
434 return tkInitWindowAW(title, FALSE);
435 }
436
437
438 /******************************************************************************/
439
440 /*
441 * You cannot just call DestroyWindow() here. The programs do not expect
442 * tkQuit() to return; DestroyWindow() just sends a WM_DESTROY message
443 */
444
tkQuit(void)445 void tkQuit(void)
446 {
447 DestroyThisWindow(tkhwnd);
448 ExitProcess(0);
449 }
450
451 /******************************************************************************/
452
tkSetOneColor(int index,float r,float g,float b)453 void tkSetOneColor(int index, float r, float g, float b)
454 {
455 PALETTEENTRY PalEntry;
456 HPALETTE Palette;
457 if ( NULL != (Palette = CreateCIPalette( tkhdc )) )
458 {
459 PalEntry.peRed = (BYTE)(r*(float)255.0 + (float)0.5);
460 PalEntry.peGreen = (BYTE)(g*(float)255.0 + (float)0.5);
461 PalEntry.peBlue = (BYTE)(b*(float)255.0 + (float)0.5);
462 PalEntry.peFlags = 0;
463 SetPaletteEntries( Palette, index, 1, &PalEntry);
464 DelayPaletteRealization();
465 }
466 }
467
tkSetFogRamp(int density,int startIndex)468 void tkSetFogRamp(int density, int startIndex)
469 {
470 HPALETTE CurrentPal;
471 PALETTEENTRY *pPalEntry;
472 UINT n, i, j, k, intensity, fogValues, colorValues;
473
474 if ( NULL != (CurrentPal = CreateCIPalette(tkhdc)) )
475 {
476 n = GetPaletteEntries( CurrentPal, 0, 0, NULL );
477
478 pPalEntry = AllocateMemory( n * sizeof(PALETTEENTRY) );
479
480 if ( NULL != pPalEntry)
481 {
482 fogValues = 1 << density;
483 colorValues = 1 << startIndex;
484 for (i = 0; i < colorValues; i++) {
485 for (j = 0; j < fogValues; j++) {
486 k = i * fogValues + j;
487
488 intensity = i * fogValues + j * colorValues;
489 //mf: not sure what they're trying to do here
490 //intensity = (intensity << 8) | intensity; ???
491
492 // This is a workaround for a GDI palette "feature". If any of
493 // the static colors are repeated in the palette, those colors
494 // will map to the first occurrence. So, for our case where there
495 // are only two static colors (black and white), if a white
496 // color appears anywhere in the palette other than in the last
497 // entry, the static white will remap to the first white. This
498 // destroys the nice one-to-one mapping we are trying to achieve.
499 //
500 // There are two ways to workaround this. The first is to
501 // simply not allow a pure white anywhere but in the last entry.
502 // Such requests are replaced with an attenuated white of
503 // (0xFE, 0xFE, 0xFE).
504 //
505 // The other way is to mark these extra whites with PC_RESERVED
506 // which will cause GDI to skip these entries when mapping colors.
507 // This way the app gets the actual colors requested, but can
508 // have side effects on other apps.
509 //
510 // Both solutions are included below. The PC_RESERVED solution is
511 // the one currently enabled. It may have side effects, but taking
512 // over the static colors as we are is a really big side effect that
513 // should swamp out the effects of using PC_RESERVED.
514 if (intensity > 0xFF)
515 intensity = 0xFF;
516 pPalEntry[k].peRed =pPalEntry[k].peGreen = pPalEntry[k].peBlue = (BYTE) intensity;
517 pPalEntry[k].peFlags = 0;
518
519 }
520 }
521
522 SetPaletteEntries(CurrentPal, 0, n, pPalEntry);
523 FreeMemory( pPalEntry );
524
525 DelayPaletteRealization();
526 }
527 }
528 }
529
tkSetGreyRamp(void)530 void tkSetGreyRamp(void)
531 {
532 HPALETTE CurrentPal;
533 PALETTEENTRY *Entries;
534 UINT Count, i;
535 float intensity;
536
537 if ( NULL != (CurrentPal = CreateCIPalette( tkhdc )) )
538 {
539 Count = GetPaletteEntries( CurrentPal, 0, 0, NULL );
540 Entries = AllocateMemory( Count * sizeof(PALETTEENTRY) );
541
542 if ( NULL != Entries )
543 {
544 for (i = 0; i < Count; i++)
545 {
546 intensity = (float)(((double)i / (double)(Count-1)) * (double)255.0 + (double)0.5);
547 Entries[i].peRed =
548 Entries[i].peGreen =
549 Entries[i].peBlue = (BYTE) intensity;
550 Entries[i].peFlags = 0;
551 }
552 SetPaletteEntries( CurrentPal, 0, Count, Entries );
553 FreeMemory( Entries );
554
555 DelayPaletteRealization();
556 }
557 }
558 }
559
tkSetRGBMap(int Size,float * Values)560 void tkSetRGBMap( int Size, float *Values )
561 {
562 HPALETTE CurrentPal;
563 int i;
564 if ( NULL != (CurrentPal = CreateCIPalette( tkhdc )) )
565 {
566 for (i=0; i<Size; i++)
567 tkSetOneColor(i,Values[i*3],Values[i*3+1],Values[i*3+2]);
568 }
569 }
570
571 /******************************************************************************/
572
tkSwapBuffers(void)573 void tkSwapBuffers(void)
574 {
575 WMesaSwapBuffers();
576 }
577
578 /******************************************************************************/
579
tkGetColorMapSize(void)580 GLint tkGetColorMapSize(void)
581 {
582 CreateCIPalette( tkhdc );
583
584 if ( NULL == tkhpalette )
585 return( 0 );
586
587 return( GetPaletteEntries( tkhpalette, 0, 0, NULL ) );
588 }
589
tkGetMouseLoc(int * x,int * y)590 void tkGetMouseLoc(int *x, int *y)
591 {
592 POINT Point;
593
594 *x = 0;
595 *y = 0;
596
597 GetCursorPos(&Point);
598
599 /*
600 * GetCursorPos returns screen coordinates,
601 * we want window coordinates
602 */
603
604 *x = Point.x - windInfo.x;
605 *y = Point.y - windInfo.y;
606 }
607
tkGetHWND(void)608 HWND tkGetHWND(void)
609 {
610 return tkhwnd;
611 }
612
tkGetHDC(void)613 HDC tkGetHDC(void)
614 {
615 return tkhdc;
616 }
tkGetDisplayModePolicy(void)617 GLenum tkGetDisplayModePolicy(void)
618 {
619 return windInfo.dmPolicy;
620 }
621
tkGetDisplayModeID(void)622 GLint tkGetDisplayModeID(void)
623 {
624 return windInfo.ipfd;
625 }
626
tkGetDisplayMode(void)627 GLenum tkGetDisplayMode(void)
628 {
629 return windInfo.type;
630 }
631
632
633 /***********************************************************************
634 * *
635 * The Following functions are for our own use only. (ie static) *
636 * *
637 ***********************************************************************/
638
639 long FAR PASCAL _export
tkWndProc(HWND hWnd,UINT message,DWORD wParam,LONG lParam)640 tkWndProc(HWND hWnd, UINT message, DWORD wParam, LONG lParam)
641 {
642 int key;
643 PAINTSTRUCT paint;
644 HDC hdc;
645
646 switch (message)
647 {
648
649 case WM_USER:
650
651 if ( RealizePaletteNow( tkhdc, tkhpalette) > 0 )
652 ForceRedraw( hWnd );
653 return(0);
654
655 case WM_SIZE:
656 windInfo.width = LOWORD(lParam);
657 windInfo.height = HIWORD(lParam);
658
659 if (ReshapeFunc)
660 {
661 (*ReshapeFunc)(windInfo.width, windInfo.height);
662
663 ForceRedraw( hWnd );
664 }
665 return (0);
666
667 case WM_MOVE:
668 windInfo.x = LOWORD(lParam);
669 windInfo.y = HIWORD(lParam);
670 return (0);
671
672 case WM_PAINT:
673
674 /*
675 * Validate the region even if there are no DisplayFunc.
676 * Otherwise, USER will not stop sending WM_PAINT messages.
677 */
678
679 hdc = BeginPaint(tkhwnd, &paint);
680
681 if (DisplayFunc)
682 {
683 (*DisplayFunc)();
684 }
685
686 EndPaint(tkhwnd, &paint);
687 return (0);
688
689 case WM_PALETTECHANGED:
690 if ( hWnd != (HWND) wParam )
691 RealizePaletteNow(tkhdc,tkhpalette);
692 return (0);
693 case WM_QUERYNEWPALETTE:
694
695 // In the foreground! Let RealizePaletteNow do the work--
696 // if management of the static system color usage is needed,
697 // RealizePaletteNow will take care of it.
698
699 if ( NULL != tkhpalette )
700 {
701 if ( RealizePaletteNow(tkhdc, tkhpalette) > 0 )
702 ForceRedraw( hWnd );
703
704 return (1);
705 }
706
707 return (0);
708
709 case WM_ACTIVATE:
710
711 // If the window is going inactive, the palette must be realized to
712 // the background. Cannot depend on WM_PALETTECHANGED to be sent since
713 // the window that comes to the foreground may or may not be palette
714 // managed.
715
716 if ( LOWORD(wParam) == WA_INACTIVE )
717 {
718 if ( NULL != tkhpalette )
719 {
720 // Realize as a background palette. Need to call
721 // RealizePaletteNow rather than RealizePalette directly to
722 // because it may be necessary to release usage of the static
723 // system colors.
724
725 if ( RealizePaletteNow( tkhdc, tkhpalette) > 0 )
726 ForceRedraw( hWnd );
727 }
728 }
729
730 // Allow DefWindowProc() to finish the default processing (which includes
731 // changing the keyboard focus).
732
733 break;
734
735 case WM_MOUSEMOVE:
736
737 if (MouseMoveFunc)
738 {
739 GLenum mask;
740
741 mask = 0;
742 if (wParam & MK_LBUTTON) {
743 mask |= TK_LEFTBUTTON;
744 }
745 if (wParam & MK_MBUTTON) {
746 mask |= TK_MIDDLEBUTTON;
747 }
748 if (wParam & MK_RBUTTON) {
749 mask |= TK_RIGHTBUTTON;
750 }
751
752 if ((*MouseMoveFunc)( LOWORD(lParam), HIWORD(lParam), mask ))
753 {
754 ForceRedraw( hWnd );
755 }
756 }
757 return (0);
758
759 case WM_LBUTTONDOWN:
760
761 SetCapture(hWnd);
762
763 if (MouseDownFunc)
764 {
765 if ( (*MouseDownFunc)(LOWORD(lParam), HIWORD(lParam),
766 TK_LEFTBUTTON) )
767 {
768 ForceRedraw( hWnd );
769 }
770 }
771 return (0);
772
773 case WM_LBUTTONUP:
774
775 ReleaseCapture();
776
777 if (MouseUpFunc)
778 {
779 if ((*MouseUpFunc)(LOWORD(lParam), HIWORD(lParam), TK_LEFTBUTTON))
780 {
781 ForceRedraw( hWnd );
782 }
783 }
784 return (0);
785
786 case WM_MBUTTONDOWN:
787
788 SetCapture(hWnd);
789
790 if (MouseDownFunc)
791 {
792 if ((*MouseDownFunc)(LOWORD(lParam), HIWORD(lParam),
793 TK_MIDDLEBUTTON))
794 {
795 ForceRedraw( hWnd );
796 }
797 }
798 return (0);
799
800 case WM_MBUTTONUP:
801
802 ReleaseCapture();
803
804 if (MouseUpFunc)
805 {
806 if ((*MouseUpFunc)(LOWORD(lParam), HIWORD(lParam),
807 TK_MIDDLEBUTTON))
808 {
809 ForceRedraw( hWnd );
810 }
811 }
812 return (0);
813
814 case WM_RBUTTONDOWN:
815
816 SetCapture(hWnd);
817
818 if (MouseDownFunc)
819 {
820 if ((*MouseDownFunc)(LOWORD(lParam), HIWORD(lParam),
821 TK_RIGHTBUTTON))
822 {
823 ForceRedraw( hWnd );
824 }
825 }
826 return (0);
827
828 case WM_RBUTTONUP:
829
830 ReleaseCapture();
831
832 if (MouseUpFunc)
833 {
834 if ((*MouseUpFunc)(LOWORD(lParam), HIWORD(lParam),
835 TK_RIGHTBUTTON))
836 {
837 ForceRedraw( hWnd );
838 }
839 }
840 return (0);
841
842 case WM_KEYDOWN:
843 switch (wParam) {
844 case VK_SPACE: key = TK_SPACE; break;
845 case VK_RETURN: key = TK_RETURN; break;
846 case VK_ESCAPE: key = TK_ESCAPE; break;
847 case VK_LEFT: key = TK_LEFT; break;
848 case VK_UP: key = TK_UP; break;
849 case VK_RIGHT: key = TK_RIGHT; break;
850 case VK_DOWN: key = TK_DOWN; break;
851 default: key = GL_FALSE; break;
852 }
853
854 if (key && KeyDownFunc)
855 {
856 GLenum mask;
857
858 mask = 0;
859 if (GetKeyState(VK_CONTROL)) {
860 mask |= TK_CONTROL;
861 }
862
863 if (GetKeyState(VK_SHIFT)) {
864
865 mask |= TK_SHIFT;
866 }
867
868 if ( (*KeyDownFunc)(key, mask) )
869 {
870 ForceRedraw( hWnd );
871 }
872 }
873 return (0);
874
875 case WM_CHAR:
876 if (('0' <= wParam && wParam <= '9') ||
877 ('a' <= wParam && wParam <= 'z') ||
878 ('A' <= wParam && wParam <= 'Z')) {
879
880 key = wParam;
881 } else {
882 key = GL_FALSE;
883 }
884
885 if (key && KeyDownFunc) {
886 GLenum mask;
887
888 mask = 0;
889
890 if (GetKeyState(VK_CONTROL)) {
891 mask |= TK_CONTROL;
892 }
893
894 if (GetKeyState(VK_SHIFT)) {
895 mask |= TK_SHIFT;
896 }
897
898 if ( (*KeyDownFunc)(key, mask) )
899 {
900 ForceRedraw( hWnd );
901 }
902 }
903 return (0);
904
905 case WM_CLOSE:
906 DestroyWindow(tkhwnd);
907 return(0);
908
909 case WM_DESTROY:
910 CleanUp();
911 PostQuitMessage(TRUE);
912 return 0;
913 }
914 return(DefWindowProc( hWnd, message, wParam, lParam));
915 }
CreateCIPalette(HDC Dc)916 static HPALETTE CreateCIPalette( HDC Dc )
917 {
918 LOGPALETTE *LogicalPalette;
919 HPALETTE StockPalette;
920 UINT PaletteSize, StockPaletteSize, EntriesToCopy;
921
922 if ( (Dc != NULL) && (NULL == tkhpalette) )
923 {
924 PaletteSize = 256; //(Pfd.cColorBits >= 8) ? 256 : (1 << Pfd.cColorBits);
925
926 LogicalPalette = AllocateZeroedMemory( sizeof(LOGPALETTE) +
927 (PaletteSize * sizeof(PALETTEENTRY)) );
928
929 if ( NULL != LogicalPalette )
930 {
931 LogicalPalette->palVersion = 0x300;
932 LogicalPalette->palNumEntries = PaletteSize;
933
934 StockPalette = GetStockObject(DEFAULT_PALETTE);
935 StockPaletteSize = GetPaletteEntries( StockPalette, 0, 0, NULL );
936
937 /*
938 * start by copying default palette into new one
939 */
940
941 EntriesToCopy = StockPaletteSize < PaletteSize ?
942 StockPaletteSize : PaletteSize;
943
944 GetPaletteEntries( StockPalette, 0, EntriesToCopy,
945 LogicalPalette->palPalEntry );
946
947 /*
948 * If we are taking possession of the system colors,
949 * must guarantee that 0 and 255 are black and white
950 * (respectively).
951 */
952
953 tkhpalette = CreatePalette(LogicalPalette);
954
955 FreeMemory(LogicalPalette);
956
957 RealizePaletteNow( Dc, tkhpalette);
958 }
959 }
960 return( tkhpalette );
961 }
962 static void
PrintMessage(const char * Format,...)963 PrintMessage( const char *Format, ... )
964 {
965 va_list ArgList;
966 char Buffer[256];
967
968 va_start(ArgList, Format);
969 vsprintf(Buffer, Format, ArgList);
970 va_end(ArgList);
971
972 MessageBox(GetFocus(), Buffer, "Error", MB_OK);
973 }
974
975 static void
DelayPaletteRealization(void)976 DelayPaletteRealization( void )
977 {
978 MSG Message;
979
980 TKASSERT(NULL!=tkhwnd);
981
982 /*
983 * Add a WM_USER message to the queue, if there isn't one there already.
984 */
985
986 if (!PeekMessage(&Message, tkhwnd, WM_USER, WM_USER, PM_NOREMOVE) )
987 {
988 PostMessage( tkhwnd, WM_USER, 0, 0);
989 }
990 }
991
992 /******************************Public*Routine******************************\
993 * RealizePaletteNow
994 *
995 * Select the given palette in background or foreground mode (as specified
996 * by the bForceBackground flag), and realize the palette.
997 *
998 * If static system color usage is set, the system colors are replaced.
999 *
1000 * History:
1001 * 26-Apr-1994 -by- Gilman Wong [gilmanw]
1002 * Wrote it.
1003 \**************************************************************************/
1004
RealizePaletteNow(HDC Dc,HPALETTE Palette)1005 static long RealizePaletteNow( HDC Dc, HPALETTE Palette)
1006 {
1007 long Result = -1;
1008 TKASSERT( NULL!=Dc );
1009 TKASSERT( NULL!=Palette );
1010 if ( NULL != SelectPalette( Dc, Palette, FALSE ) )
1011 {
1012 Result = RealizePalette( Dc );
1013 WMesaPaletteChange(Palette);
1014 }
1015 return( Result );
1016 }
1017
1018 static void
ForceRedraw(HWND Window)1019 ForceRedraw( HWND Window )
1020 {
1021 MSG Message;
1022
1023 if (!PeekMessage(&Message, Window, WM_PAINT, WM_PAINT, PM_NOREMOVE) )
1024 {
1025 InvalidateRect( Window, NULL, FALSE );
1026 }
1027 }
1028 static void
DestroyThisWindow(HWND Window)1029 DestroyThisWindow( HWND Window )
1030 {
1031 if ( NULL != Window )
1032 {
1033 DestroyWindow( Window );
1034 }
1035 }
1036
1037 /*
1038 * This Should be called in response to a WM_DESTROY message
1039 */
1040
1041 static void
CleanUp(void)1042 CleanUp( void )
1043 {
1044 HPALETTE hStock;
1045
1046 // Cleanup the palette.
1047
1048 if ( NULL != tkhpalette )
1049 {
1050 // If static system color usage is set, restore the system colors.
1051
1052 if ((hStock = GetStockObject( DEFAULT_PALETTE ))!=NULL)
1053 SelectPalette( tkhdc, hStock, FALSE );
1054 DeleteObject( tkhpalette );
1055 }
1056
1057 // Cleanup the DC.
1058
1059 if ( NULL != tkhdc )
1060 ReleaseDC( tkhwnd, tkhdc );
1061 // Be really nice and reset global values.
1062 tkhwnd = NULL;
1063 tkhdc = NULL;
1064 tkhpalette = NULL;
1065
1066 ExposeFunc = NULL;
1067 ReshapeFunc = NULL;
1068 IdleFunc = NULL;
1069 DisplayFunc = NULL;
1070 KeyDownFunc = NULL;
1071 MouseDownFunc = NULL;
1072 MouseUpFunc = NULL;
1073 MouseMoveFunc = NULL;
1074 }
1075
1076 static void *
AllocateMemory(size_t Size)1077 AllocateMemory( size_t Size )
1078 {
1079 return( LocalAlloc( LMEM_FIXED, Size ) );
1080 }
1081
1082 static void *
AllocateZeroedMemory(size_t Size)1083 AllocateZeroedMemory( size_t Size )
1084 {
1085 return( LocalAlloc( LMEM_FIXED | LMEM_ZEROINIT, Size ) );
1086 }
1087
1088
1089 static void
FreeMemory(void * Chunk)1090 FreeMemory( void *Chunk )
1091 {
1092 TKASSERT( NULL!=Chunk );
1093
1094 LocalFree( Chunk );
1095 }
1096