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