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 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include "tk.h"
41 #include "windows.h"
42 
43 #if(WINVER < 0x0400)
44 // Ordinarily not defined for versions before 4.00.
45 #define COLOR_3DDKSHADOW        21
46 #define COLOR_3DLIGHT           22
47 #define COLOR_INFOTEXT          23
48 #define COLOR_INFOBK            24
49 #endif
50 
51 #define static
52 
53 #if defined(__cplusplus) || defined(c_plusplus)
54 #define class c_class
55 #endif
56 
57 #if DBG
58 #define TKASSERT(x)                                     \
59 if ( !(x) ) {                                           \
60     PrintMessage("%s(%d) Assertion failed %s\n",        \
61         __FILE__, __LINE__, #x);                        \
62 }
63 #else
64 #define TKASSERT(x)
65 #endif  /* DBG */
66 
67 /******************************************************************************/
68 
69 static struct _WINDOWINFO {
70     int x, y;
71     int width, height;
72     GLenum type;
73     GLenum dmPolicy;
74     int ipfd;
75     BOOL bDefPos;
76 } windInfo = {
77     0, 0, 100, 100, TK_INDEX | TK_SINGLE, TK_MINIMUM_CRITERIA, 0, TRUE
78 };
79 
80 
81 static HWND     tkhwnd     = NULL;
82 static HDC      tkhdc      = NULL;
83 static HGLRC    tkhrc      = NULL;
84 static HPALETTE tkhpalette = NULL;
85 static OSVERSIONINFO tkOSVerInfo;
86 GLboolean tkPopupEnable = TRUE;
87 
88 // Fixed palette support.
89 
90 #define BLACK   PALETTERGB(0,0,0)
91 #define WHITE   PALETTERGB(255,255,255)
92 #define MAX_STATIC_COLORS   (COLOR_INFOBK - COLOR_SCROLLBAR + 1)
93 static int tkNumStaticColors = MAX_STATIC_COLORS;
94 
95 // TRUE if app wants to take over palette
96 static BOOL tkUseStaticColors = FALSE;
97 
98 // TRUE if static system color settings have been replaced with B&W settings.
99 static BOOL tkSystemColorsInUse = FALSE;
100 
101 // TRUE if original static colors saved
102 static BOOL tkStaticColorsSaved = FALSE;
103 
104 // saved system static colors (initialize with default colors)
105 static COLORREF gacrSave[MAX_STATIC_COLORS];
106 
107 // new B&W system static colors
108 static COLORREF gacrBlackAndWhite[] = {
109     WHITE,  // COLOR_SCROLLBAR
110     BLACK,  // COLOR_BACKGROUND
111     BLACK,  // COLOR_ACTIVECAPTION
112     WHITE,  // COLOR_INACTIVECAPTION
113     WHITE,  // COLOR_MENU
114     WHITE,  // COLOR_WINDOW
115     BLACK,  // COLOR_WINDOWFRAME
116     BLACK,  // COLOR_MENUTEXT
117     BLACK,  // COLOR_WINDOWTEXT
118     WHITE,  // COLOR_CAPTIONTEXT
119     WHITE,  // COLOR_ACTIVEBORDER
120     WHITE,  // COLOR_INACTIVEBORDER
121     WHITE,  // COLOR_APPWORKSPACE
122     BLACK,  // COLOR_HIGHLIGHT
123     WHITE,  // COLOR_HIGHLIGHTTEXT
124     WHITE,  // COLOR_BTNFACE
125     BLACK,  // COLOR_BTNSHADOW
126     BLACK,  // COLOR_GRAYTEXT
127     BLACK,  // COLOR_BTNTEXT
128     BLACK,  // COLOR_INACTIVECAPTIONTEXT
129     BLACK,  // COLOR_BTNHIGHLIGHT
130     BLACK,  // COLOR_3DDKSHADOW
131     WHITE,  // COLOR_3DLIGHT
132     BLACK,  // COLOR_INFOTEXT
133     WHITE   // COLOR_INFOBK
134     };
135 static INT gaiStaticIndex[] = {
136     COLOR_SCROLLBAR          ,
137     COLOR_BACKGROUND         ,
138     COLOR_ACTIVECAPTION      ,
139     COLOR_INACTIVECAPTION    ,
140     COLOR_MENU               ,
141     COLOR_WINDOW             ,
142     COLOR_WINDOWFRAME        ,
143     COLOR_MENUTEXT           ,
144     COLOR_WINDOWTEXT         ,
145     COLOR_CAPTIONTEXT        ,
146     COLOR_ACTIVEBORDER       ,
147     COLOR_INACTIVEBORDER     ,
148     COLOR_APPWORKSPACE       ,
149     COLOR_HIGHLIGHT          ,
150     COLOR_HIGHLIGHTTEXT      ,
151     COLOR_BTNFACE            ,
152     COLOR_BTNSHADOW          ,
153     COLOR_GRAYTEXT           ,
154     COLOR_BTNTEXT            ,
155     COLOR_INACTIVECAPTIONTEXT,
156     COLOR_BTNHIGHLIGHT       ,
157     COLOR_3DDKSHADOW         ,
158     COLOR_3DLIGHT            ,
159     COLOR_INFOTEXT           ,
160     COLOR_INFOBK
161     };
162 
163 static BOOL GrabStaticEntries(HDC);
164 static BOOL ReleaseStaticEntries(HDC);
165 
166 #define RESTORE_FROM_REGISTRY   1
167 #if RESTORE_FROM_REGISTRY
168 // Registry names for the system colors.
169 CHAR *gaszSysClrNames[] = {
170     "Scrollbar",      // COLOR_SCROLLBAR              0
171     "Background",     // COLOR_BACKGROUND             1   (also COLOR_DESKTOP)
172     "ActiveTitle",    // COLOR_ACTIVECAPTION          2
173     "InactiveTitle",  // COLOR_INACTIVECAPTION        3
174     "Menu",           // COLOR_MENU                   4
175     "Window",         // COLOR_WINDOW                 5
176     "WindowFrame",    // COLOR_WINDOWFRAME            6
177     "MenuText",       // COLOR_MENUTEXT               7
178     "WindowText",     // COLOR_WINDOWTEXT             8
179     "TitleText",      // COLOR_CAPTIONTEXT            9
180     "ActiveBorder",   // COLOR_ACTIVEBORDER          10
181     "InactiveBorder", // COLOR_INACTIVEBORDER        11
182     "AppWorkspace",   // COLOR_APPWORKSPACE          12
183     "Hilight",        // COLOR_HIGHLIGHT             13
184     "HilightText",    // COLOR_HIGHLIGHTTEXT         14
185     "ButtonFace",     // COLOR_BTNFACE               15   (also COLOR_3DFACE)
186     "ButtonShadow",   // COLOR_BTNSHADOW             16   (also COLOR_3DSHADOW)
187     "GrayText",       // COLOR_GRAYTEXT              17
188     "ButtonText",     // COLOR_BTNTEXT               18
189     "InactiveTitleText", // COLOR_INACTIVECAPTIONTEXT   19
190     "ButtonHilight",  // COLOR_BTNHIGHLIGHT          20   (also COLOR_3DHILIGHT)
191     "ButtonDkShadow", // COLOR_3DDKSHADOW            21
192     "ButtonLight",    // COLOR_3DLIGHT               22
193     "InfoText",       // COLOR_INFOTEXT              23
194     "InfoWindow"      // COLOR_INFOBK                24
195 };
196 
197 static BOOL GetRegistrySysColors(COLORREF *, int);
198 #endif
199 
200 static void (*ExposeFunc)(int, int)              = NULL;
201 static void (*ReshapeFunc)(GLsizei, GLsizei)     = NULL;
202 static void (*DisplayFunc)(void)                 = NULL;
203 static GLenum (*KeyDownFunc)(int, GLenum)        = NULL;
204 static GLenum (*MouseDownFunc)(int, int, GLenum) = NULL;
205 static GLenum (*MouseUpFunc)(int, int, GLenum)   = NULL;
206 static GLenum (*MouseMoveFunc)(int, int, GLenum) = NULL;
207 static void (*IdleFunc)(void)                    = NULL;
208 
209 static char     *lpszClassName = "tkLibWClass";
210 static WCHAR    *lpszClassNameW = L"tkLibWClass";
211 
212 static long tkWndProc(HWND hWnd, UINT message, DWORD wParam, LONG lParam);
213 static unsigned char ComponentFromIndex(int i, int nbits, int shift );
214 static void PrintMessage( const char *Format, ... );
215 static PALETTEENTRY *FillRgbPaletteEntries( PIXELFORMATDESCRIPTOR *Pfd, PALETTEENTRY *Entries, UINT Count );
216 static HPALETTE CreateCIPalette( HDC Dc );
217 static HPALETTE CreateRGBPalette( HDC hdc );
218 static void DestroyThisWindow( HWND Window );
219 static void CleanUp( void );
220 static void DelayPaletteRealization( void );
221 static long RealizePaletteNow( HDC Dc, HPALETTE Palette, BOOL bForceBackground );
222 static void ForceRedraw( HWND Window );
223 static BOOL FindPixelFormat(HDC hdc, GLenum type);
224 static int FindBestPixelFormat(HDC hdc, GLenum type, PIXELFORMATDESCRIPTOR *ppfd);
225 static int FindExactPixelFormat(HDC hdc, GLenum type, PIXELFORMATDESCRIPTOR *ppfd);
226 static BOOL IsPixelFormatValid(HDC hdc, int ipfd, PIXELFORMATDESCRIPTOR *ppfd);
227 static int PixelFormatDescriptorFromDc( HDC Dc, PIXELFORMATDESCRIPTOR *Pfd );
228 static void *AllocateMemory( size_t Size );
229 static void *AllocateZeroedMemory( size_t Size );
230 static void FreeMemory( void *Chunk );
231 
232 /*
233  *  Prototypes for the debugging functions go here
234  */
235 
236 #define DBGFUNC 0
237 #if DBGFUNC
238 
239 static void DbgPrintf( const char *Format, ... );
240 static void pwi( void );
241 static void pwr(RECT *pr);
242 static void ShowPixelFormat(HDC hdc);
243 
244 #endif
245 
246 static float colorMaps[] = {
247     0.000000F, 1.000000F, 0.000000F, 1.000000F, 0.000000F, 1.000000F,
248     0.000000F, 1.000000F, 0.333333F, 0.776471F, 0.443137F, 0.556863F,
249     0.443137F, 0.556863F, 0.219608F, 0.666667F, 0.666667F, 0.333333F,
250     0.666667F, 0.333333F, 0.666667F, 0.333333F, 0.666667F, 0.333333F,
251     0.666667F, 0.333333F, 0.666667F, 0.333333F, 0.666667F, 0.333333F,
252     0.666667F, 0.333333F, 0.039216F, 0.078431F, 0.117647F, 0.156863F,
253     0.200000F, 0.239216F, 0.278431F, 0.317647F, 0.356863F, 0.400000F,
254     0.439216F, 0.478431F, 0.517647F, 0.556863F, 0.600000F, 0.639216F,
255     0.678431F, 0.717647F, 0.756863F, 0.800000F, 0.839216F, 0.878431F,
256     0.917647F, 0.956863F, 0.000000F, 0.000000F, 0.000000F, 0.000000F,
257     0.000000F, 0.000000F, 0.000000F, 0.000000F, 0.247059F, 0.247059F,
258     0.247059F, 0.247059F, 0.247059F, 0.247059F, 0.247059F, 0.247059F,
259     0.498039F, 0.498039F, 0.498039F, 0.498039F, 0.498039F, 0.498039F,
260     0.498039F, 0.498039F, 0.749020F, 0.749020F, 0.749020F, 0.749020F,
261     0.749020F, 0.749020F, 0.749020F, 0.749020F, 1.000000F, 1.000000F,
262     1.000000F, 1.000000F, 1.000000F, 1.000000F, 1.000000F, 1.000000F,
263     0.000000F, 0.000000F, 0.000000F, 0.000000F, 0.000000F, 0.000000F,
264     0.000000F, 0.000000F, 0.247059F, 0.247059F, 0.247059F, 0.247059F,
265     0.247059F, 0.247059F, 0.247059F, 0.247059F, 0.498039F, 0.498039F,
266     0.498039F, 0.498039F, 0.498039F, 0.498039F, 0.498039F, 0.498039F,
267     0.749020F, 0.749020F, 0.749020F, 0.749020F, 0.749020F, 0.749020F,
268     0.749020F, 0.749020F, 1.000000F, 1.000000F, 1.000000F, 1.000000F,
269     1.000000F, 1.000000F, 1.000000F, 1.000000F, 0.000000F, 0.000000F,
270     0.000000F, 0.000000F, 0.000000F, 0.000000F, 0.000000F, 0.000000F,
271     0.247059F, 0.247059F, 0.247059F, 0.247059F, 0.247059F, 0.247059F,
272     0.247059F, 0.247059F, 0.498039F, 0.498039F, 0.498039F, 0.498039F,
273     0.498039F, 0.498039F, 0.498039F, 0.498039F, 0.749020F, 0.749020F,
274     0.749020F, 0.749020F, 0.749020F, 0.749020F, 0.749020F, 0.749020F,
275     1.000000F, 1.000000F, 1.000000F, 1.000000F, 1.000000F, 1.000000F,
276     1.000000F, 1.000000F, 0.000000F, 0.000000F, 0.000000F, 0.000000F,
277     0.000000F, 0.000000F, 0.000000F, 0.000000F, 0.247059F, 0.247059F,
278     0.247059F, 0.247059F, 0.247059F, 0.247059F, 0.247059F, 0.247059F,
279     0.498039F, 0.498039F, 0.498039F, 0.498039F, 0.498039F, 0.498039F,
280     0.498039F, 0.498039F, 0.749020F, 0.749020F, 0.749020F, 0.749020F,
281     0.749020F, 0.749020F, 0.749020F, 0.749020F, 1.000000F, 1.000000F,
282     1.000000F, 1.000000F, 1.000000F, 1.000000F, 1.000000F, 1.000000F,
283     0.000000F, 0.000000F, 0.000000F, 0.000000F, 0.000000F, 0.000000F,
284     0.000000F, 0.000000F, 0.247059F, 0.247059F, 0.247059F, 0.247059F,
285     0.247059F, 0.247059F, 0.247059F, 0.247059F, 0.498039F, 0.498039F,
286     0.498039F, 0.498039F, 0.498039F, 0.498039F, 0.498039F, 0.498039F,
287     0.749020F, 0.749020F, 0.749020F, 0.749020F, 0.749020F, 0.749020F,
288     0.749020F, 0.749020F, 1.000000F, 1.000000F, 1.000000F, 1.000000F,
289     1.000000F, 1.000000F, 1.000000F, 1.000000F, 0.000000F, 0.000000F,
290     1.000000F, 1.000000F, 0.000000F, 0.000000F, 1.000000F, 1.000000F,
291     0.333333F, 0.443137F, 0.776471F, 0.556863F, 0.443137F, 0.219608F,
292     0.556863F, 0.666667F, 0.666667F, 0.333333F, 0.666667F, 0.333333F,
293     0.666667F, 0.333333F, 0.666667F, 0.333333F, 0.666667F, 0.333333F,
294     0.666667F, 0.333333F, 0.666667F, 0.333333F, 0.666667F, 0.333333F,
295     0.039216F, 0.078431F, 0.117647F, 0.156863F, 0.200000F, 0.239216F,
296     0.278431F, 0.317647F, 0.356863F, 0.400000F, 0.439216F, 0.478431F,
297     0.517647F, 0.556863F, 0.600000F, 0.639216F, 0.678431F, 0.717647F,
298     0.756863F, 0.800000F, 0.839216F, 0.878431F, 0.917647F, 0.956863F,
299     0.000000F, 0.141176F, 0.282353F, 0.427451F, 0.568627F, 0.713726F,
300     0.854902F, 1.000000F, 0.000000F, 0.141176F, 0.282353F, 0.427451F,
301     0.568627F, 0.713726F, 0.854902F, 1.000000F, 0.000000F, 0.141176F,
302     0.282353F, 0.427451F, 0.568627F, 0.713726F, 0.854902F, 1.000000F,
303     0.000000F, 0.141176F, 0.282353F, 0.427451F, 0.568627F, 0.713726F,
304     0.854902F, 1.000000F, 0.000000F, 0.141176F, 0.282353F, 0.427451F,
305     0.568627F, 0.713726F, 0.854902F, 1.000000F, 0.000000F, 0.141176F,
306     0.282353F, 0.427451F, 0.568627F, 0.713726F, 0.854902F, 1.000000F,
307     0.000000F, 0.141176F, 0.282353F, 0.427451F, 0.568627F, 0.713726F,
308     0.854902F, 1.000000F, 0.000000F, 0.141176F, 0.282353F, 0.427451F,
309     0.568627F, 0.713726F, 0.854902F, 1.000000F, 0.000000F, 0.141176F,
310     0.282353F, 0.427451F, 0.568627F, 0.713726F, 0.854902F, 1.000000F,
311     0.000000F, 0.141176F, 0.282353F, 0.427451F, 0.568627F, 0.713726F,
312     0.854902F, 1.000000F, 0.000000F, 0.141176F, 0.282353F, 0.427451F,
313     0.568627F, 0.713726F, 0.854902F, 1.000000F, 0.000000F, 0.141176F,
314     0.282353F, 0.427451F, 0.568627F, 0.713726F, 0.854902F, 1.000000F,
315     0.000000F, 0.141176F, 0.282353F, 0.427451F, 0.568627F, 0.713726F,
316     0.854902F, 1.000000F, 0.000000F, 0.141176F, 0.282353F, 0.427451F,
317     0.568627F, 0.713726F, 0.854902F, 1.000000F, 0.000000F, 0.141176F,
318     0.282353F, 0.427451F, 0.568627F, 0.713726F, 0.854902F, 1.000000F,
319     0.000000F, 0.141176F, 0.282353F, 0.427451F, 0.568627F, 0.713726F,
320     0.854902F, 1.000000F, 0.000000F, 0.141176F, 0.282353F, 0.427451F,
321     0.568627F, 0.713726F, 0.854902F, 1.000000F, 0.000000F, 0.141176F,
322     0.282353F, 0.427451F, 0.568627F, 0.713726F, 0.854902F, 1.000000F,
323     0.000000F, 0.141176F, 0.282353F, 0.427451F, 0.568627F, 0.713726F,
324     0.854902F, 1.000000F, 0.000000F, 0.141176F, 0.282353F, 0.427451F,
325     0.568627F, 0.713726F, 0.854902F, 1.000000F, 0.000000F, 0.141176F,
326     0.282353F, 0.427451F, 0.568627F, 0.713726F, 0.854902F, 1.000000F,
327     0.000000F, 0.141176F, 0.282353F, 0.427451F, 0.568627F, 0.713726F,
328     0.854902F, 1.000000F, 0.000000F, 0.141176F, 0.282353F, 0.427451F,
329     0.568627F, 0.713726F, 0.854902F, 1.000000F, 0.000000F, 0.141176F,
330     0.282353F, 0.427451F, 0.568627F, 0.713726F, 0.854902F, 1.000000F,
331     0.000000F, 0.141176F, 0.282353F, 0.427451F, 0.568627F, 0.713726F,
332     0.854902F, 1.000000F, 0.000000F, 0.000000F, 0.000000F, 0.000000F,
333     1.000000F, 1.000000F, 1.000000F, 1.000000F, 0.333333F, 0.443137F,
334     0.443137F, 0.219608F, 0.776471F, 0.556863F, 0.556863F, 0.666667F,
335     0.666667F, 0.333333F, 0.666667F, 0.333333F, 0.666667F, 0.333333F,
336     0.666667F, 0.333333F, 0.666667F, 0.333333F, 0.666667F, 0.333333F,
337     0.666667F, 0.333333F, 0.666667F, 0.333333F, 0.039216F, 0.078431F,
338     0.117647F, 0.156863F, 0.200000F, 0.239216F, 0.278431F, 0.317647F,
339     0.356863F, 0.400000F, 0.439216F, 0.478431F, 0.517647F, 0.556863F,
340     0.600000F, 0.639216F, 0.678431F, 0.717647F, 0.756863F, 0.800000F,
341     0.839216F, 0.878431F, 0.917647F, 0.956863F, 0.000000F, 0.000000F,
342     0.000000F, 0.000000F, 0.000000F, 0.000000F, 0.000000F, 0.000000F,
343     0.000000F, 0.000000F, 0.000000F, 0.000000F, 0.000000F, 0.000000F,
344     0.000000F, 0.000000F, 0.000000F, 0.000000F, 0.000000F, 0.000000F,
345     0.000000F, 0.000000F, 0.000000F, 0.000000F, 0.000000F, 0.000000F,
346     0.000000F, 0.000000F, 0.000000F, 0.000000F, 0.000000F, 0.000000F,
347     0.000000F, 0.000000F, 0.000000F, 0.000000F, 0.000000F, 0.000000F,
348     0.000000F, 0.000000F, 0.247059F, 0.247059F, 0.247059F, 0.247059F,
349     0.247059F, 0.247059F, 0.247059F, 0.247059F, 0.247059F, 0.247059F,
350     0.247059F, 0.247059F, 0.247059F, 0.247059F, 0.247059F, 0.247059F,
351     0.247059F, 0.247059F, 0.247059F, 0.247059F, 0.247059F, 0.247059F,
352     0.247059F, 0.247059F, 0.247059F, 0.247059F, 0.247059F, 0.247059F,
353     0.247059F, 0.247059F, 0.247059F, 0.247059F, 0.247059F, 0.247059F,
354     0.247059F, 0.247059F, 0.247059F, 0.247059F, 0.247059F, 0.247059F,
355     0.498039F, 0.498039F, 0.498039F, 0.498039F, 0.498039F, 0.498039F,
356     0.498039F, 0.498039F, 0.498039F, 0.498039F, 0.498039F, 0.498039F,
357     0.498039F, 0.498039F, 0.498039F, 0.498039F, 0.498039F, 0.498039F,
358     0.498039F, 0.498039F, 0.498039F, 0.498039F, 0.498039F, 0.498039F,
359     0.498039F, 0.498039F, 0.498039F, 0.498039F, 0.498039F, 0.498039F,
360     0.498039F, 0.498039F, 0.498039F, 0.498039F, 0.498039F, 0.498039F,
361     0.498039F, 0.498039F, 0.498039F, 0.498039F, 0.749020F, 0.749020F,
362     0.749020F, 0.749020F, 0.749020F, 0.749020F, 0.749020F, 0.749020F,
363     0.749020F, 0.749020F, 0.749020F, 0.749020F, 0.749020F, 0.749020F,
364     0.749020F, 0.749020F, 0.749020F, 0.749020F, 0.749020F, 0.749020F,
365     0.749020F, 0.749020F, 0.749020F, 0.749020F, 0.749020F, 0.749020F,
366     0.749020F, 0.749020F, 0.749020F, 0.749020F, 0.749020F, 0.749020F,
367     0.749020F, 0.749020F, 0.749020F, 0.749020F, 0.749020F, 0.749020F,
368     0.749020F, 0.749020F, 1.000000F, 1.000000F, 1.000000F, 1.000000F,
369     1.000000F, 1.000000F, 1.000000F, 1.000000F, 1.000000F, 1.000000F,
370     1.000000F, 1.000000F, 1.000000F, 1.000000F, 1.000000F, 1.000000F,
371     1.000000F, 1.000000F, 1.000000F, 1.000000F, 1.000000F, 1.000000F,
372     1.000000F, 1.000000F, 1.000000F, 1.000000F, 1.000000F, 1.000000F,
373     1.000000F, 1.000000F, 1.000000F, 1.000000F, 1.000000F, 1.000000F,
374     1.000000F, 1.000000F, 1.000000F, 1.000000F, 1.000000F, 1.000000F,
375 };
376 
377 /* Default Palette */
378 float auxRGBMap[20][3] = {
379     { 0.0F, 0.0F, 0.0F },                               /* 0: black */
380     { 0x80/255.0F, 0.0F, 0.0F },                        /* 1: Half red */
381     { 0.0F, 0x80/255.0F, 0.0F },                        /* 2: Half green */
382     { 0x80/255.0F, 0x80/255.0F, 0.0F },                 /* 3: Half yellow */
383     { 0.0F, 0.0F, 0x80/255.0F },                        /* 4: Half blue */
384     { 0x80/255.0F, 0.0F, 0x80/255.0F },                 /* 5: Half magenta */
385     { 0.0F, 0x80/255.0F, 0x80/255.0F },                 /* 6: Half cyan */
386     { 0xC0/255.0F, 0xC0/255.0F, 0xC0/255.0F },          /* 7: Light gray */
387     { 0xC0/255.0F, 0xDC/255.0F, 0xC0/255.0F },          /* 8: Green gray */
388     { 0xA6/255.0F, 0xCA/255.0F, 0xF0/255.0F },          /* 9: Half gray */
389     { 1.0F, 0xFB/255.0F, 0xF0/255.0F },                 /* 10: Pale */
390     { 0xA0/255.0F, 0xA0/255.0F, 0xA4/255.0F },          /* 11: Med gray */
391     { 0x80/255.0F, 0x80/255.0F, 0x80/255.0F },          /* 12: Dark gray */
392     { 1.0F, 0.0F, 0.0F },                               /* 13: red */
393     { 0.0F, 1.0F, 0.0F },                               /* 14: green */
394     { 1.0F, 1.0F, 0.0F },                               /* 15: yellow */
395     { 0.0F, 0.0F, 1.0F },                               /* 16: blue */
396     { 1.0F, 0.0F, 1.0F },                               /* 17: magenta */
397     { 0.0F, 1.0F, 1.0F },                               /* 18: cyan */
398     { 1.0F, 1.0F, 1.0F },                               /* 19: white */
399 };
400 
401 /***************************************************************
402  *                                                             *
403  *  Exported Functions go here                                 *
404  *                                                             *
405  ***************************************************************/
406 
tkErrorPopups(GLboolean bEnable)407 void tkErrorPopups(GLboolean bEnable)
408 {
409     tkPopupEnable = bEnable;
410 }
411 
tkCloseWindow(void)412 void tkCloseWindow(void)
413 {
414     DestroyThisWindow(tkhwnd);
415 }
416 
417 
tkExec(void)418 void tkExec(void)
419 {
420     MSG Message;
421 
422     /*
423      *  WM_SIZE gets delivered before we get here!
424      */
425 
426     if (ReshapeFunc)
427     {
428         RECT ClientRect;
429 
430         GetClientRect(tkhwnd, &ClientRect);
431         (*ReshapeFunc)(ClientRect.right, ClientRect.bottom);
432     }
433 
434     while (GL_TRUE)
435     {
436         /*
437          *  Process all pending messages
438          */
439 
440         if (IdleFunc) {
441             while (PeekMessage(&Message, NULL, 0, 0, PM_NOREMOVE) == TRUE) {
442                 if (GetMessage(&Message, NULL, 0, 0) ) {
443                     TranslateMessage(&Message);
444                     DispatchMessage(&Message);
445                 } else {
446                     /*
447                      *  Nothing else to do here, just return
448                      */
449 
450                     return;
451                 }
452             }
453 
454             /*
455              *  If an idle function was defined, call it
456              */
457 
458             if (IdleFunc) {
459                 (*IdleFunc)();
460             }
461         } else {
462             if (GetMessage(&Message, NULL, 0, 0)) {
463                 TranslateMessage(&Message);
464                 DispatchMessage(&Message);
465             } else {
466                 return;
467             }
468         }
469     }
470 }
471 
tkExposeFunc(void (* Func)(int,int))472 void tkExposeFunc(void (*Func)(int, int))
473 {
474     ExposeFunc = Func;
475 }
476 
tkReshapeFunc(void (* Func)(GLsizei,GLsizei))477 void tkReshapeFunc(void (*Func)(GLsizei, GLsizei))
478 {
479     ReshapeFunc = Func;
480 }
481 
tkDisplayFunc(void (* Func)(void))482 void tkDisplayFunc(void (*Func)(void))
483 {
484     DisplayFunc = Func;
485 }
486 
tkKeyDownFunc(GLenum (* Func)(int,GLenum))487 void tkKeyDownFunc(GLenum (*Func)(int, GLenum))
488 {
489     KeyDownFunc = Func;
490 }
491 
tkMouseDownFunc(GLenum (* Func)(int,int,GLenum))492 void tkMouseDownFunc(GLenum (*Func)(int, int, GLenum))
493 {
494     MouseDownFunc = Func;
495 }
496 
tkMouseUpFunc(GLenum (* Func)(int,int,GLenum))497 void tkMouseUpFunc(GLenum (*Func)(int, int, GLenum))
498 {
499     MouseUpFunc = Func;
500 }
501 
tkMouseMoveFunc(GLenum (* Func)(int,int,GLenum))502 void tkMouseMoveFunc(GLenum (*Func)(int, int, GLenum))
503 {
504     MouseMoveFunc = Func;
505 }
506 
tkIdleFunc(void (* Func)(void))507 void tkIdleFunc(void (*Func)(void))
508 {
509     IdleFunc = Func;
510 }
511 
tkInitPosition(int x,int y,int width,int height)512 void tkInitPosition(int x, int y, int width, int height)
513 {
514     if (x == CW_USEDEFAULT)
515     {
516         x = 0;
517         y = 0;
518         windInfo.bDefPos = TRUE;
519     }
520     else
521         windInfo.bDefPos = FALSE;
522 
523     windInfo.x = x + GetSystemMetrics(SM_CXFRAME);
524     windInfo.y = y + GetSystemMetrics(SM_CYCAPTION)
525                  - GetSystemMetrics(SM_CYBORDER)
526                  + GetSystemMetrics(SM_CYFRAME);
527     windInfo.width = width;
528     windInfo.height = height;
529 }
530 
tkInitDisplayMode(GLenum type)531 void tkInitDisplayMode(GLenum type)
532 {
533     windInfo.type = type;
534 }
535 
tkInitDisplayModePolicy(GLenum type)536 void tkInitDisplayModePolicy(GLenum type)
537 {
538     windInfo.dmPolicy = type;
539 }
540 
tkInitDisplayModeID(GLint ipfd)541 GLenum tkInitDisplayModeID(GLint ipfd)
542 {
543     windInfo.ipfd = ipfd;
544     return GL_TRUE;
545 }
546 
547 // Initialize a window, create a rendering context for that window
tkInitWindow(char * title)548 GLenum tkInitWindow(char *title)
549 {
550     TKASSERT( NULL==tkhwnd      );
551     TKASSERT( NULL==tkhdc       );
552     TKASSERT( NULL==tkhrc       );
553     TKASSERT( NULL==tkhpalette  );
554 
555     return tkInitWindowAW(title, FALSE);
556 }
557 
tkInitWindowAW(char * title,BOOL bUnicode)558 GLenum tkInitWindowAW(char *title, BOOL bUnicode)
559 {
560     WNDCLASS wndclass;
561     RECT     WinRect;
562     HANDLE   hInstance;
563     ATOM     aRegister;
564     GLenum   Result = GL_FALSE;
565     BOOL     bGetVersionExRet;
566 
567     hInstance = GetModuleHandle(NULL);
568 
569     tkOSVerInfo.dwOSVersionInfoSize = sizeof(tkOSVerInfo);
570     bGetVersionExRet = GetVersionEx(&tkOSVerInfo);
571     TKASSERT(bGetVersionExRet);
572     if ( tkOSVerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT &&
573          tkOSVerInfo.dwMajorVersion == 3 &&
574          (tkOSVerInfo.dwMinorVersion == 5 || tkOSVerInfo.dwMinorVersion == 51) )
575         tkNumStaticColors = COLOR_BTNHIGHLIGHT - COLOR_SCROLLBAR + 1;
576     else
577         tkNumStaticColors = COLOR_INFOBK - COLOR_SCROLLBAR + 1;
578 
579     // Must not define CS_PARENTDC style.
580     wndclass.style         = CS_HREDRAW | CS_VREDRAW;
581     wndclass.lpfnWndProc   = (WNDPROC)tkWndProc;
582     wndclass.cbClsExtra    = 0;
583     wndclass.cbWndExtra    = 0;
584     wndclass.hInstance     = hInstance;
585     wndclass.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
586     wndclass.hCursor       = LoadCursor(NULL, IDC_ARROW);
587     wndclass.hbrBackground = GetStockObject(BLACK_BRUSH);
588     wndclass.lpszMenuName  = NULL;
589 
590     if (bUnicode)
591         wndclass.lpszClassName = (LPCSTR)lpszClassNameW;
592     else
593         wndclass.lpszClassName = (LPCSTR)lpszClassName;
594 
595     if (bUnicode)
596     {
597         aRegister = RegisterClassW((CONST WNDCLASSW *)&wndclass);
598     }
599     else
600     {
601         aRegister = RegisterClass(&wndclass);
602     }
603 
604 
605     /*
606      *  If the window failed to register, then there's no
607      *  need to continue further.
608      */
609 
610     if(0 == aRegister)
611     {
612         PrintMessage("Failed to register window class\n");
613         return(Result);
614     }
615 
616 
617     /*
618      *  Make window large enough to hold a client area as large as windInfo
619      */
620 
621     WinRect.left   = windInfo.x;
622     WinRect.right  = windInfo.x + windInfo.width;
623     WinRect.top    = windInfo.y;
624     WinRect.bottom = windInfo.y + windInfo.height;
625 
626     AdjustWindowRect(&WinRect, WS_OVERLAPPEDWINDOW, FALSE);
627 
628     /*
629      *  Must use WS_CLIPCHILDREN and WS_CLIPSIBLINGS styles.
630      */
631 
632     if (bUnicode)
633     {
634         tkhwnd = CreateWindowW(
635                     (LPCWSTR)lpszClassNameW,
636                     (LPCWSTR)title,
637                     WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
638                     (windInfo.bDefPos) ? CW_USEDEFAULT : WinRect.left,
639                     (windInfo.bDefPos) ? CW_USEDEFAULT : WinRect.top,
640                     WinRect.right - WinRect.left,
641                     WinRect.bottom - WinRect.top,
642                     NULL,
643                     NULL,
644                     hInstance,
645                     NULL);
646     }
647     else
648     {
649         tkhwnd = CreateWindow(
650                     lpszClassName,
651                     title,
652                     WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
653                     (windInfo.bDefPos) ? CW_USEDEFAULT : WinRect.left,
654                     (windInfo.bDefPos) ? CW_USEDEFAULT : WinRect.top,
655                     WinRect.right - WinRect.left,
656                     WinRect.bottom - WinRect.top,
657                     NULL,
658                     NULL,
659                     hInstance,
660                     NULL);
661     }
662 
663     if ( NULL != tkhwnd )
664     {
665         // If default window positioning used, find out window position and fix
666         // up the windInfo position info.
667 
668         if (windInfo.bDefPos)
669         {
670             GetWindowRect(tkhwnd, &WinRect);
671             windInfo.x = WinRect.left + GetSystemMetrics(SM_CXFRAME);
672             windInfo.y = WinRect.top  + GetSystemMetrics(SM_CYCAPTION)
673                          - GetSystemMetrics(SM_CYBORDER)
674                          + GetSystemMetrics(SM_CYFRAME);
675         }
676 
677         tkhdc = GetDC(tkhwnd);
678 
679         if ( NULL != tkhdc )
680         {
681             ShowWindow(tkhwnd, SW_SHOWDEFAULT);
682 
683             if ( FindPixelFormat(tkhdc, windInfo.type) )
684             {
685                 /*
686                  *  Create a Rendering Context
687                  */
688 
689                 tkhrc = wglCreateContext(tkhdc);
690 
691                 if ( NULL != tkhrc )
692                 {
693                     /*
694                      *  Make it Current
695                      */
696 
697                     if ( wglMakeCurrent(tkhdc, tkhrc) )
698                     {
699                         Result = GL_TRUE;
700                     }
701                     else
702                     {
703                         PrintMessage("wglMakeCurrent Failed\n");
704                     }
705                 }
706                 else
707                 {
708                     PrintMessage("wglCreateContext Failed\n");
709                 }
710             }
711         }
712         else
713         {
714             PrintMessage("Could not get an HDC for window 0x%08lX\n", tkhwnd );
715         }
716     }
717     else
718     {
719         PrintMessage("create window failed\n");
720     }
721 
722     if ( GL_FALSE == Result )
723     {
724         DestroyThisWindow(tkhwnd);  // Something Failed, Destroy this window
725     }
726     return( Result );
727 }
728 
729 /******************************************************************************/
730 
731 /*
732  * You cannot just call DestroyWindow() here.  The programs do not expect
733  * tkQuit() to return;  DestroyWindow() just sends a WM_DESTROY message
734  */
735 
tkQuit(void)736 void tkQuit(void)
737 {
738     DestroyThisWindow(tkhwnd);
739     ExitProcess(0);
740 }
741 
742 /******************************************************************************/
743 
tkSetOneColor(int index,float r,float g,float b)744 void tkSetOneColor(int index, float r, float g, float b)
745 {
746     PALETTEENTRY PalEntry;
747     HPALETTE Palette;
748 
749     if ( NULL != (Palette = CreateCIPalette( tkhdc )) )
750     {
751         if ( tkUseStaticColors && ( index == 0 || index == 255 ) )
752             return;
753 
754         PalEntry.peRed   = (BYTE)(r*(float)255.0 + (float)0.5);
755         PalEntry.peGreen = (BYTE)(g*(float)255.0 + (float)0.5);
756         PalEntry.peBlue  = (BYTE)(b*(float)255.0 + (float)0.5);
757         PalEntry.peFlags = ( tkUseStaticColors ) ? PC_NOCOLLAPSE : 0;
758 
759         // This is a workaround for a GDI palette "feature".  If any of
760         // the static colors are repeated in the palette, those colors
761         // will map to the first occurrence.  So, for our case where there
762         // are only two static colors (black and white), if a white
763         // color appears anywhere in the palette other than in the last
764         // entry, the static white will remap to the first white.  This
765         // destroys the nice one-to-one mapping we are trying to achieve.
766         //
767         // There are two ways to workaround this.  The first is to
768         // simply not allow a pure white anywhere but in the last entry.
769         // Such requests are replaced with an attenuated white of
770         // (0xFE, 0xFE, 0xFE).
771         //
772         // The other way is to mark these extra whites with PC_RESERVED
773         // which will cause GDI to skip these entries when mapping colors.
774         // This way the app gets the actual colors requested, but can
775         // have side effects on other apps.
776         //
777         // Both solutions are included below.  The PC_RESERVED solution is
778         // the one currently enabled.  It may have side effects, but taking
779         // over the static colors as we are is a really big side effect that
780         // should swamp out the effects of using PC_RESERVED.
781 
782         if ( tkUseStaticColors )
783         {
784             if ( PalEntry.peRed   == 0xFF &&
785                  PalEntry.peGreen == 0xFF &&
786                  PalEntry.peBlue  == 0xFF )
787             {
788             #define USE_PC_RESERVED_WORKAROUND  1
789             #if USE_PC_RESERVED_WORKAROUND
790                 PalEntry.peFlags |= PC_RESERVED;
791             #else
792                 PalEntry.peRed   =
793                 PalEntry.peGreen =
794                 PalEntry.peBlue  = 0xFE;
795             #endif
796             }
797         }
798 
799         SetPaletteEntries( Palette, index, 1, &PalEntry);
800 
801         DelayPaletteRealization();
802     }
803 }
804 
tkSetFogRamp(int density,int startIndex)805 void tkSetFogRamp(int density, int startIndex)
806 {
807     HPALETTE CurrentPal;
808     PALETTEENTRY *pPalEntry;
809     UINT n, i, j, k, intensity, fogValues, colorValues;
810 
811     if ( NULL != (CurrentPal = CreateCIPalette(tkhdc)) )
812     {
813         n = GetPaletteEntries( CurrentPal, 0, 0, NULL );
814 
815         pPalEntry = AllocateMemory( n * sizeof(PALETTEENTRY) );
816 
817         if ( NULL != pPalEntry)
818         {
819             fogValues = 1 << density;
820             colorValues = 1 << startIndex;
821             for (i = 0; i < colorValues; i++) {
822                 for (j = 0; j < fogValues; j++) {
823                     k = i * fogValues + j;
824 
825                     intensity = i * fogValues + j * colorValues;
826                     //mf: not sure what they're trying to do here
827                     //intensity = (intensity << 8) | intensity; ???
828 
829                 // This is a workaround for a GDI palette "feature".  If any of
830                 // the static colors are repeated in the palette, those colors
831                 // will map to the first occurrence.  So, for our case where there
832                 // are only two static colors (black and white), if a white
833                 // color appears anywhere in the palette other than in the last
834                 // entry, the static white will remap to the first white.  This
835                 // destroys the nice one-to-one mapping we are trying to achieve.
836                 //
837                 // There are two ways to workaround this.  The first is to
838                 // simply not allow a pure white anywhere but in the last entry.
839                 // Such requests are replaced with an attenuated white of
840                 // (0xFE, 0xFE, 0xFE).
841                 //
842                 // The other way is to mark these extra whites with PC_RESERVED
843                 // which will cause GDI to skip these entries when mapping colors.
844                 // This way the app gets the actual colors requested, but can
845                 // have side effects on other apps.
846                 //
847                 // Both solutions are included below.  The PC_RESERVED solution is
848                 // the one currently enabled.  It may have side effects, but taking
849                 // over the static colors as we are is a really big side effect that
850                 // should swamp out the effects of using PC_RESERVED.
851 
852                 #if USE_PC_RESERVED_WORKAROUND
853                     if (intensity > 0xFF)
854                         intensity = 0xFF;
855                 #else
856                     if (intensity >= 0xFF)
857                         intensity = ( tkUseStaticColors && k != 255) ? 0xFE : 0xFF;
858                 #endif
859 
860                     pPalEntry[k].peRed =
861                     pPalEntry[k].peGreen =
862                     pPalEntry[k].peBlue = (BYTE) intensity;
863                     pPalEntry[k].peFlags = ( tkUseStaticColors && k != 0 && k != 255 )
864                                            ? PC_NOCOLLAPSE : 0;
865 
866                 #if USE_PC_RESERVED_WORKAROUND
867                     if (tkUseStaticColors && intensity == 0xFF
868                         && k != 0 && k!= 255)
869                         pPalEntry[k].peFlags |= PC_RESERVED;
870                 #endif
871                 }
872             }
873 
874             SetPaletteEntries(CurrentPal, 0, n, pPalEntry);
875             FreeMemory( pPalEntry );
876 
877             DelayPaletteRealization();
878         }
879     }
880 }
881 
tkSetGreyRamp(void)882 void tkSetGreyRamp(void)
883 {
884     HPALETTE CurrentPal;
885     PALETTEENTRY *Entries;
886     UINT Count, i;
887     float intensity;
888 
889     if ( NULL != (CurrentPal = CreateCIPalette( tkhdc )) )
890     {
891         Count   = GetPaletteEntries( CurrentPal, 0, 0, NULL );
892         Entries = AllocateMemory( Count * sizeof(PALETTEENTRY) );
893 
894         if ( NULL != Entries )
895         {
896             for (i = 0; i < Count; i++)
897             {
898                 intensity = (float)(((double)i / (double)(Count-1)) * (double)255.0 + (double)0.5);
899                 Entries[i].peRed =
900                 Entries[i].peGreen =
901                 Entries[i].peBlue = (BYTE) intensity;
902                 Entries[i].peFlags = ( tkUseStaticColors && i != 0 && i != 255 )
903                                      ? PC_NOCOLLAPSE : 0;
904             }
905             SetPaletteEntries( CurrentPal, 0, Count, Entries );
906             FreeMemory( Entries );
907 
908             DelayPaletteRealization();
909         }
910     }
911 }
912 
tkSetRGBMap(int Size,float * Values)913 void tkSetRGBMap( int Size, float *Values )
914 {
915     HPALETTE CurrentPal;
916     PIXELFORMATDESCRIPTOR Pfd, *pPfd;
917     PALETTEENTRY *Entries;
918     UINT Count;
919 
920     if ( NULL != (CurrentPal = CreateCIPalette( tkhdc )) )
921     {
922         pPfd = &Pfd;
923 
924         if ( PixelFormatDescriptorFromDc( tkhdc, pPfd ) )
925         {
926             Count    = 1 << pPfd->cColorBits;
927             Entries  = AllocateMemory( Count * sizeof(PALETTEENTRY) );
928 
929             if ( NULL != Entries )
930             {
931                 FillRgbPaletteEntries( pPfd, Entries, Count );
932                 SetPaletteEntries( CurrentPal, 0, Count, Entries );
933                 FreeMemory(Entries);
934 
935                 RealizePaletteNow( tkhdc, tkhpalette, FALSE );
936             }
937         }
938     }
939 }
940 
941 /******************************************************************************/
942 
tkSwapBuffers(void)943 void tkSwapBuffers(void)
944 {
945     SwapBuffers(tkhdc);
946 }
947 
948 /******************************************************************************/
949 
tkGetColorMapSize(void)950 GLint tkGetColorMapSize(void)
951 {
952     CreateCIPalette( tkhdc );
953 
954     if ( NULL == tkhpalette )
955         return( 0 );
956 
957     return( GetPaletteEntries( tkhpalette, 0, 0, NULL ) );
958 }
959 
tkGetMouseLoc(int * x,int * y)960 void tkGetMouseLoc(int *x, int *y)
961 {
962     POINT Point;
963 
964     *x = 0;
965     *y = 0;
966 
967     GetCursorPos(&Point);
968 
969     /*
970      *  GetCursorPos returns screen coordinates,
971      *  we want window coordinates
972      */
973 
974     *x = Point.x - windInfo.x;
975     *y = Point.y - windInfo.y;
976 }
977 
tkGetHWND(void)978 HWND tkGetHWND(void)
979 {
980     return tkhwnd;
981 }
982 
tkGetHDC(void)983 HDC tkGetHDC(void)
984 {
985     return tkhdc;
986 }
987 
tkGetHRC(void)988 HGLRC tkGetHRC(void)
989 {
990     return tkhrc;
991 }
992 
tkGetDisplayModePolicy(void)993 GLenum tkGetDisplayModePolicy(void)
994 {
995     return windInfo.dmPolicy;
996 }
997 
tkGetDisplayModeID(void)998 GLint tkGetDisplayModeID(void)
999 {
1000     return windInfo.ipfd;
1001 }
1002 
tkGetDisplayMode(void)1003 GLenum tkGetDisplayMode(void)
1004 {
1005     return windInfo.type;
1006 }
1007 
1008 
1009 /***********************************************************************
1010  *                                                                     *
1011  *  The Following functions are for our own use only. (ie static)      *
1012  *                                                                     *
1013  ***********************************************************************/
1014 
1015 static long
tkWndProc(HWND hWnd,UINT message,DWORD wParam,LONG lParam)1016 tkWndProc(HWND hWnd, UINT message, DWORD wParam, LONG lParam)
1017 {
1018     int key;
1019     PAINTSTRUCT paint;
1020     HDC hdc;
1021     PIXELFORMATDESCRIPTOR pfd;
1022 
1023     switch (message) {
1024 
1025     case WM_USER:
1026         if ( RealizePaletteNow( tkhdc, tkhpalette, FALSE ) > 0 )
1027         {
1028             ForceRedraw( hWnd );
1029         }
1030         return(0);
1031 
1032     case WM_SIZE:
1033         windInfo.width  = LOWORD(lParam);
1034         windInfo.height = HIWORD(lParam);
1035 
1036         if (ReshapeFunc)
1037         {
1038             (*ReshapeFunc)(windInfo.width, windInfo.height);
1039 
1040             ForceRedraw( hWnd );
1041         }
1042         return (0);
1043 
1044     case WM_MOVE:
1045         windInfo.x = LOWORD(lParam);
1046         windInfo.y = HIWORD(lParam);
1047         return (0);
1048 
1049     case WM_PAINT:
1050         /*
1051          *  Validate the region even if there are no DisplayFunc.
1052          *  Otherwise, USER will not stop sending WM_PAINT messages.
1053          */
1054 
1055         hdc = BeginPaint(tkhwnd, &paint);
1056 
1057         if (DisplayFunc)
1058         {
1059             (*DisplayFunc)();
1060         }
1061 
1062         EndPaint(tkhwnd, &paint);
1063         return (0);
1064 
1065     case WM_QUERYNEWPALETTE:
1066 
1067     // We don't actually realize the palette here (we do it at WM_ACTIVATE
1068     // time), but we need the system to think that we have so that a
1069     // WM_PALETTECHANGED message is generated.
1070 
1071         return (1);
1072 
1073     case WM_PALETTECHANGED:
1074 
1075     // Respond to this message only if the window that changed the palette
1076     // is not this app's window.
1077 
1078     // We are not the foreground window, so realize palette in the
1079     // background.  We cannot call RealizePaletteNow to do this because
1080     // we should not do any of the tkUseStaticColors processing while
1081     // in background.
1082 
1083         if ( hWnd != (HWND) wParam )
1084         {
1085             if ( !tkSystemColorsInUse &&
1086                  NULL != tkhpalette &&
1087                  NULL != SelectPalette( tkhdc, tkhpalette, TRUE ) )
1088                 RealizePalette( tkhdc );
1089         }
1090 
1091         return (0);
1092 
1093     case WM_SYSCOLORCHANGE:
1094 
1095     // If the system colors have changed and we have a palette
1096     // for an RGB surface then we need to recompute the static
1097     // color mapping because they might have been changed in
1098     // the process of changing the system colors.
1099 
1100         if (tkhdc != NULL && tkhpalette != NULL &&
1101             PixelFormatDescriptorFromDc(tkhdc, &pfd) &&
1102             (pfd.dwFlags & PFD_NEED_PALETTE) &&
1103             pfd.iPixelType == PFD_TYPE_RGBA)
1104         {
1105             HPALETTE hpalTmp;
1106 
1107             hpalTmp = tkhpalette;
1108             tkhpalette = NULL;
1109             if (CreateRGBPalette(tkhdc) != NULL)
1110             {
1111                 DeleteObject(hpalTmp);
1112                 ForceRedraw(hWnd);
1113             }
1114             else
1115             {
1116                 tkhpalette = hpalTmp;
1117             }
1118         }
1119         break;
1120 
1121     case WM_ACTIVATE:
1122 
1123     // If the window is going inactive, the palette must be realized to
1124     // the background.  Cannot depend on WM_PALETTECHANGED to be sent since
1125     // the window that comes to the foreground may or may not be palette
1126     // managed.
1127 
1128         if ( LOWORD(wParam) == WA_INACTIVE )
1129         {
1130             if ( NULL != tkhpalette )
1131             {
1132             // Realize as a background palette.  Need to call
1133             // RealizePaletteNow rather than RealizePalette directly to
1134             // because it may be necessary to release usage of the static
1135             // system colors.
1136 
1137                 if ( RealizePaletteNow( tkhdc, tkhpalette, TRUE ) > 0 )
1138                     ForceRedraw( hWnd );
1139             }
1140         }
1141 
1142     // Window is going active.  If we are not iconized, realize palette
1143     // to the foreground.  If management of the system static colors is
1144     // needed, RealizePaletteNow will take care of it.
1145 
1146         else if ( HIWORD(wParam) == 0 )
1147         {
1148             if ( NULL != tkhpalette )
1149             {
1150                 if ( RealizePaletteNow( tkhdc, tkhpalette, FALSE ) > 0 )
1151                     ForceRedraw( hWnd );
1152 
1153                 return (1);
1154             }
1155         }
1156 
1157     // Allow DefWindowProc() to finish the default processing (which includes
1158     // changing the keyboard focus).
1159 
1160         break;
1161 
1162     case WM_MOUSEMOVE:
1163 
1164         if (MouseMoveFunc)
1165         {
1166             GLenum mask;
1167 
1168             mask = 0;
1169             if (wParam & MK_LBUTTON) {
1170                 mask |= TK_LEFTBUTTON;
1171             }
1172             if (wParam & MK_MBUTTON) {
1173                 mask |= TK_MIDDLEBUTTON;
1174             }
1175             if (wParam & MK_RBUTTON) {
1176                 mask |= TK_RIGHTBUTTON;
1177             }
1178 
1179             if ((*MouseMoveFunc)( LOWORD(lParam), HIWORD(lParam), mask ))
1180             {
1181                 ForceRedraw( hWnd );
1182             }
1183         }
1184         return (0);
1185 
1186     case WM_LBUTTONDOWN:
1187 
1188         SetCapture(hWnd);
1189 
1190         if (MouseDownFunc)
1191         {
1192             if ( (*MouseDownFunc)(LOWORD(lParam), HIWORD(lParam),
1193                  TK_LEFTBUTTON) )
1194             {
1195                 ForceRedraw( hWnd );
1196             }
1197         }
1198         return (0);
1199 
1200     case WM_LBUTTONUP:
1201 
1202         ReleaseCapture();
1203 
1204         if (MouseUpFunc)
1205         {
1206             if ((*MouseUpFunc)(LOWORD(lParam), HIWORD(lParam), TK_LEFTBUTTON))
1207             {
1208                 ForceRedraw( hWnd );
1209             }
1210         }
1211         return (0);
1212 
1213     case WM_MBUTTONDOWN:
1214 
1215         SetCapture(hWnd);
1216 
1217         if (MouseDownFunc)
1218         {
1219             if ((*MouseDownFunc)(LOWORD(lParam), HIWORD(lParam),
1220                     TK_MIDDLEBUTTON))
1221             {
1222                 ForceRedraw( hWnd );
1223             }
1224         }
1225         return (0);
1226 
1227     case WM_MBUTTONUP:
1228 
1229         ReleaseCapture();
1230 
1231         if (MouseUpFunc)
1232         {
1233             if ((*MouseUpFunc)(LOWORD(lParam), HIWORD(lParam),
1234                 TK_MIDDLEBUTTON))
1235             {
1236                 ForceRedraw( hWnd );
1237             }
1238         }
1239         return (0);
1240 
1241     case WM_RBUTTONDOWN:
1242 
1243         SetCapture(hWnd);
1244 
1245         if (MouseDownFunc)
1246         {
1247             if ((*MouseDownFunc)(LOWORD(lParam), HIWORD(lParam),
1248                 TK_RIGHTBUTTON))
1249             {
1250                 ForceRedraw( hWnd );
1251             }
1252         }
1253         return (0);
1254 
1255     case WM_RBUTTONUP:
1256 
1257         ReleaseCapture();
1258 
1259         if (MouseUpFunc)
1260         {
1261             if ((*MouseUpFunc)(LOWORD(lParam), HIWORD(lParam),
1262                 TK_RIGHTBUTTON))
1263             {
1264                 ForceRedraw( hWnd );
1265             }
1266         }
1267         return (0);
1268 
1269     case WM_KEYDOWN:
1270         switch (wParam) {
1271         case VK_SPACE:          key = TK_SPACE;         break;
1272         case VK_RETURN:         key = TK_RETURN;        break;
1273         case VK_ESCAPE:         key = TK_ESCAPE;        break;
1274         case VK_LEFT:           key = TK_LEFT;          break;
1275         case VK_UP:             key = TK_UP;            break;
1276         case VK_RIGHT:          key = TK_RIGHT;         break;
1277         case VK_DOWN:           key = TK_DOWN;          break;
1278         default:                key = GL_FALSE;         break;
1279         }
1280 
1281         if (key && KeyDownFunc)
1282         {
1283             GLenum mask;
1284 
1285             mask = 0;
1286             if (GetKeyState(VK_CONTROL)) {
1287                 mask |= TK_CONTROL;
1288             }
1289 
1290             if (GetKeyState(VK_SHIFT)) {
1291 
1292                 mask |= TK_SHIFT;
1293             }
1294 
1295             if ( (*KeyDownFunc)(key, mask) )
1296             {
1297                 ForceRedraw( hWnd );
1298             }
1299         }
1300         return (0);
1301 
1302     case WM_CHAR:
1303         if (('0' <= wParam && wParam <= '9') ||
1304             ('a' <= wParam && wParam <= 'z') ||
1305             ('A' <= wParam && wParam <= 'Z')) {
1306 
1307             key = wParam;
1308         } else {
1309             key = GL_FALSE;
1310         }
1311 
1312         if (key && KeyDownFunc) {
1313             GLenum mask;
1314 
1315             mask = 0;
1316 
1317             if (GetKeyState(VK_CONTROL)) {
1318                 mask |= TK_CONTROL;
1319             }
1320 
1321             if (GetKeyState(VK_SHIFT)) {
1322                 mask |= TK_SHIFT;
1323             }
1324 
1325             if ( (*KeyDownFunc)(key, mask) )
1326             {
1327                 ForceRedraw( hWnd );
1328             }
1329         }
1330         return (0);
1331 
1332     case WM_CLOSE:
1333         DestroyWindow(tkhwnd);
1334         return(0);
1335 
1336     case WM_DESTROY:
1337         CleanUp();
1338         PostQuitMessage(TRUE);
1339         return 0;
1340     }
1341     return(DefWindowProc( hWnd, message, wParam, lParam));
1342 }
1343 
1344 #if RESTORE_FROM_REGISTRY
1345 /******************************Public*Routine******************************\
1346 * GetRegistrySysColors
1347 *
1348 * Reads the Control Panel's color settings from the registry and stores
1349 * those values in pcr.  If we fail to get any value, then the corresponding
1350 * entry in pcr is not modified.
1351 *
1352 * History:
1353 *  12-Apr-1995 -by- Gilman Wong [gilmanw]
1354 * Wrote it.
1355 \**************************************************************************/
1356 
GetRegistrySysColors(COLORREF * pcr,int nColors)1357 static BOOL GetRegistrySysColors(COLORREF *pcr, int nColors)
1358 {
1359     BOOL bRet = FALSE;
1360     long lRet;
1361     HKEY hkSysColors = (HKEY) NULL;
1362     int i;
1363     DWORD dwDataType;
1364     char achColor[64];
1365     DWORD cjColor;
1366 
1367     TKASSERT(nColors <= tkNumStaticColors);
1368 
1369 // Open the key for the system color settings.
1370 
1371     lRet = RegOpenKeyExA(HKEY_CURRENT_USER,
1372                          "Control Panel\\Colors",
1373                          0,
1374                          KEY_QUERY_VALUE,
1375                          &hkSysColors);
1376 
1377     if ( lRet != ERROR_SUCCESS )
1378     {
1379         goto GetRegistrySysColors_exit;
1380     }
1381 
1382 // Read each system color value.  The names are stored in the global
1383 // array of char *, gaszSysClrNames.
1384 
1385     for (i = 0; i < nColors; i++)
1386     {
1387         cjColor = sizeof(achColor);
1388         lRet = RegQueryValueExA(hkSysColors,
1389                                 (LPSTR) gaszSysClrNames[i],
1390                                 (LPDWORD) NULL,
1391                                 &dwDataType,
1392                                 (LPBYTE) achColor,
1393                                 &cjColor);
1394 
1395         TKASSERT(lRet != ERROR_MORE_DATA);
1396 
1397         if ( lRet == ERROR_SUCCESS && dwDataType == REG_SZ )
1398         {
1399             DWORD r, g, b;
1400 
1401             sscanf(achColor, "%ld %ld %ld", &r, &g, &b);
1402             pcr[i] = RGB(r, g, b);
1403         }
1404     }
1405 
1406     bRet = TRUE;
1407 
1408 GetRegistrySysColors_exit:
1409     if (hkSysColors)
1410         RegCloseKey(hkSysColors);
1411 
1412     return bRet;
1413 }
1414 #endif
1415 
1416 /******************************Public*Routine******************************\
1417 * GrabStaticEntries
1418 *
1419 * Support routine for RealizePaletteNow to manage the static system color
1420 * usage.
1421 *
1422 * This function will save the current static system color usage state.
1423 * It will fail if:
1424 *
1425 *   1.  TK is not in "sys color in use state but system palette is in
1426 *       SYSPAL_NOSTATIC mode.  This means that another app still possesses
1427 *       the static system colors.  This this happens, GrabStaticEntries
1428 *       will post a message to cause TK to try again (by calling
1429 *       DelayPaletteRealization).
1430 *
1431 * Side effect:
1432 *   If system colors are changed, then WM_SYSCOLORCHANGE message is
1433 *   broadcast to all top level windows.
1434 *
1435 *   DelayPaletteRealization may be called in case 2 above, resulting in
1436 *   a WM_USER message being posted to our message queue.
1437 *
1438 * Returns:
1439 *   TRUE if successful, FALSE otherwise (see above).
1440 *
1441 * History:
1442 *  26-Apr-1994 -by- Gilman Wong [gilmanw]
1443 * Wrote it.
1444 \**************************************************************************/
1445 
GrabStaticEntries(HDC hdc)1446 static BOOL GrabStaticEntries(HDC hdc)
1447 {
1448     int i;
1449     BOOL bRet = FALSE;
1450 
1451 // Do nothing if sys colors already in use.
1452 
1453     if ( !tkSystemColorsInUse )
1454     {
1455     // Take possession only if no other app has the static colors.
1456     // How can we tell?  If the return from SetSystemPaletteUse is
1457     // SYSPAL_STATIC, then no other app has the statics.  If it is
1458     // SYSPAL_NOSTATIC, someone else has them and we must fail.
1459     //
1460     // SetSystemPaletteUse is properly synchronized internally
1461     // so that it is atomic.
1462     //
1463     // Because we are relying on SetSystemPaletteUse to synchronize TK,
1464     // it is important to observe the following order for grabbing and
1465     // releasing:
1466     //
1467     //      Grab        call SetSystemPaletteUse and check for SYSPAL_STATIC
1468     //                  save sys color settings
1469     //                  set new sys color settings
1470     //
1471     //      Release     restore sys color settings
1472     //                  call SetSystemPaletteUse
1473 
1474         if ( SetSystemPaletteUse( hdc, SYSPAL_NOSTATIC ) == SYSPAL_STATIC )
1475         {
1476         // Save current sys color settings.
1477 
1478             for (i = COLOR_SCROLLBAR; i <= COLOR_BTNHIGHLIGHT; i++)
1479                 gacrSave[i - COLOR_SCROLLBAR] = GetSysColor(i);
1480 
1481         // Set b&w sys color settings.  Put TK in "sys colors in use" state.
1482 
1483             SetSysColors(tkNumStaticColors, gaiStaticIndex, gacrBlackAndWhite);
1484             tkSystemColorsInUse = TRUE;
1485 
1486         // Inform all other top-level windows of the system color change.
1487 
1488             PostMessage(HWND_BROADCAST, WM_SYSCOLORCHANGE, 0, 0);
1489 
1490             bRet = TRUE;
1491         }
1492 
1493     // Sleep a little and then post message to try palette realization again
1494     // later.
1495 
1496         else
1497         {
1498             Sleep(0L);
1499             DelayPaletteRealization();
1500         }
1501     }
1502     else
1503         bRet = TRUE;
1504 
1505     return bRet;
1506 }
1507 
1508 /******************************Public*Routine******************************\
1509 * ReleaseStaticEntries
1510 *
1511 * Support routine for RealizePaletteNow to manage the static system color
1512 * usage.
1513 *
1514 * This function will reset the current static system color usage state.
1515 * It will fail if:
1516 *
1517 *   1.  TK is not in a "sys colors in use" state.  If we are in this case,
1518 *       then the static system colors do not need to be released.
1519 *
1520 * Side effect:
1521 *   If system colors are changed, then WM_SYSCOLORCHANGE message is
1522 *   broadcast to all top level windows.
1523 *
1524 * Returns:
1525 *   TRUE if successful, FALSE otherwise (see above).
1526 *
1527 * History:
1528 *  21-Jul-1994 -by- Gilman Wong [gilmanw]
1529 * Wrote it.
1530 \**************************************************************************/
1531 
ReleaseStaticEntries(HDC hdc)1532 static BOOL ReleaseStaticEntries(HDC hdc)
1533 {
1534     BOOL bRet = FALSE;
1535 
1536 // Do nothing if sys colors not in use.
1537 
1538     if ( tkSystemColorsInUse )
1539     {
1540 #if RESTORE_FROM_REGISTRY
1541     // Replace saved system colors with registry values.  We do it now
1542     // rather than earlier because someone may have changed registry while
1543     // TK app was running in the foreground (very unlikely, but it could
1544     // happen).
1545     //
1546     // Also, we still try to save current setting in GrabStaticEntries so
1547     // that if for some reason we fail to grab one or more of the colors
1548     // from the registry, we can still fall back on what we grabbed via
1549     // GetSysColors (even though there is a chance its the wrong color).
1550 
1551         GetRegistrySysColors(gacrSave, tkNumStaticColors);
1552 #endif
1553 
1554     // Restore the saved system color settings.
1555 
1556         SetSysColors(tkNumStaticColors, gaiStaticIndex, gacrSave);
1557 
1558     // Return the system palette to SYSPAL_STATIC.
1559 
1560         SetSystemPaletteUse( hdc, SYSPAL_STATIC );
1561 
1562     // Inform all other top-level windows of the system color change.
1563 
1564         PostMessage(HWND_BROADCAST, WM_SYSCOLORCHANGE, 0, 0);
1565 
1566     // Reset the "sys colors in use" state and return success.
1567 
1568         tkSystemColorsInUse = FALSE;
1569         bRet = TRUE;
1570     }
1571 
1572     return bRet;
1573 }
1574 
1575 // Default palette entry flags
1576 #define PALETTE_FLAGS PC_NOCOLLAPSE
1577 
1578 // Gamma correction factor * 10
1579 #define GAMMA_CORRECTION 14
1580 
1581 // Maximum color distance with 8-bit components
1582 #define MAX_COL_DIST (3*256*256L)
1583 
1584 // Number of static colors
1585 #define STATIC_COLORS 20
1586 
1587 // Flags used when matching colors
1588 #define EXACT_MATCH 1
1589 #define COLOR_USED 1
1590 
1591 // Conversion tables for n bits to eight bits
1592 
1593 #if GAMMA_CORRECTION == 10
1594 // These tables are corrected for a gamma of 1.0
1595 static unsigned char abThreeToEight[8] =
1596 {
1597     0, 0111 >> 1, 0222 >> 1, 0333 >> 1, 0444 >> 1, 0555 >> 1, 0666 >> 1, 0377
1598 };
1599 static unsigned char abTwoToEight[4] =
1600 {
1601     0, 0x55, 0xaa, 0xff
1602 };
1603 static unsigned char abOneToEight[2] =
1604 {
1605     0, 255
1606 };
1607 #else
1608 // These tables are corrected for a gamma of 1.4
1609 static unsigned char abThreeToEight[8] =
1610 {
1611     0, 63, 104, 139, 171, 200, 229, 255
1612 };
1613 static unsigned char abTwoToEight[4] =
1614 {
1615     0, 116, 191, 255
1616 };
1617 static unsigned char abOneToEight[2] =
1618 {
1619     0, 255
1620 };
1621 #endif
1622 
1623 // Table which indicates which colors in a 3-3-2 palette should be
1624 // replaced with the system default colors
1625 #if GAMMA_CORRECTION == 10
1626 static int aiDefaultOverride[STATIC_COLORS] =
1627 {
1628     0, 4, 32, 36, 128, 132, 160, 173, 181, 245,
1629     247, 164, 156, 7, 56, 63, 192, 199, 248, 255
1630 };
1631 #else
1632 static int aiDefaultOverride[STATIC_COLORS] =
1633 {
1634     0, 3, 24, 27, 64, 67, 88, 173, 181, 236,
1635     247, 164, 91, 7, 56, 63, 192, 199, 248, 255
1636 };
1637 #endif
1638 
1639 static unsigned char
ComponentFromIndex(int i,int nbits,int shift)1640 ComponentFromIndex(int i, int nbits, int shift)
1641 {
1642     unsigned char val;
1643 
1644     TKASSERT(nbits >= 1 && nbits <= 3);
1645 
1646     val = i >> shift;
1647     switch (nbits)
1648     {
1649     case 1:
1650         return abOneToEight[val & 1];
1651 
1652     case 2:
1653         return abTwoToEight[val & 3];
1654 
1655     case 3:
1656         return abThreeToEight[val & 7];
1657     }
1658 	return 0;	// 02/21/03 GTC added just to avoid compiler warning
1659 }
1660 
1661 // System default colors
1662 static PALETTEENTRY apeDefaultPalEntry[STATIC_COLORS] =
1663 {
1664     { 0,   0,   0,    0 },
1665     { 0x80,0,   0,    0 },
1666     { 0,   0x80,0,    0 },
1667     { 0x80,0x80,0,    0 },
1668     { 0,   0,   0x80, 0 },
1669     { 0x80,0,   0x80, 0 },
1670     { 0,   0x80,0x80, 0 },
1671     { 0xC0,0xC0,0xC0, 0 },
1672 
1673     { 192, 220, 192,  0 },
1674     { 166, 202, 240,  0 },
1675     { 255, 251, 240,  0 },
1676     { 160, 160, 164,  0 },
1677 
1678     { 0x80,0x80,0x80, 0 },
1679     { 0xFF,0,   0,    0 },
1680     { 0,   0xFF,0,    0 },
1681     { 0xFF,0xFF,0,    0 },
1682     { 0,   0,   0xFF, 0 },
1683     { 0xFF,0,   0xFF, 0 },
1684     { 0,   0xFF,0xFF, 0 },
1685     { 0xFF,0xFF,0xFF, 0 }
1686 };
1687 
1688 /******************************Public*Routine******************************\
1689 *
1690 * UpdateStaticMapping
1691 *
1692 * Computes the best match between the current system static colors
1693 * and a 3-3-2 palette
1694 *
1695 * History:
1696 *  Tue Aug 01 18:18:12 1995	-by-	Drew Bliss [drewb]
1697 *   Created
1698 *
1699 \**************************************************************************/
1700 
1701 static void
UpdateStaticMapping(PALETTEENTRY * pe332Palette)1702 UpdateStaticMapping(PALETTEENTRY *pe332Palette)
1703 {
1704     HPALETTE hpalStock;
1705     int iStatic, i332;
1706     int iMinDist, iDist;
1707     int iDelta;
1708     int iMinEntry;
1709     PALETTEENTRY *peStatic, *pe332;
1710 
1711     hpalStock = GetStockObject(DEFAULT_PALETTE);
1712 
1713     // The system should always have one of these
1714     TKASSERT(hpalStock != NULL);
1715     // Make sure there's the correct number of entries
1716     TKASSERT(GetPaletteEntries(hpalStock, 0, 0, NULL) == STATIC_COLORS);
1717 
1718     // Get the current static colors
1719     GetPaletteEntries(hpalStock, 0, STATIC_COLORS, apeDefaultPalEntry);
1720 
1721     // Zero the flags in the static colors because they are used later
1722     peStatic = apeDefaultPalEntry;
1723     for (iStatic = 0; iStatic < STATIC_COLORS; iStatic++)
1724     {
1725         peStatic->peFlags = 0;
1726         peStatic++;
1727     }
1728 
1729     // Zero the flags in the incoming palette because they are used later
1730     pe332 = pe332Palette;
1731     for (i332 = 0; i332 < 256; i332++)
1732     {
1733         pe332->peFlags = 0;
1734         pe332++;
1735     }
1736 
1737     // Try to match each static color exactly
1738     // This saves time by avoiding the least-squares match for each
1739     // exact match
1740     peStatic = apeDefaultPalEntry;
1741     for (iStatic = 0; iStatic < STATIC_COLORS; iStatic++)
1742     {
1743         pe332 = pe332Palette;
1744         for (i332 = 0; i332 < 256; i332++)
1745         {
1746             if (peStatic->peRed == pe332->peRed &&
1747                 peStatic->peGreen == pe332->peGreen &&
1748                 peStatic->peBlue == pe332->peBlue)
1749             {
1750                 TKASSERT(pe332->peFlags != COLOR_USED);
1751 
1752                 peStatic->peFlags = EXACT_MATCH;
1753                 pe332->peFlags = COLOR_USED;
1754                 aiDefaultOverride[iStatic] = i332;
1755 
1756                 break;
1757             }
1758 
1759             pe332++;
1760         }
1761 
1762         peStatic++;
1763     }
1764 
1765     // Match each static color as closely as possible to an entry
1766     // in the 332 palette by minimized the square of the distance
1767     peStatic = apeDefaultPalEntry;
1768     for (iStatic = 0; iStatic < STATIC_COLORS; iStatic++)
1769     {
1770         // Skip colors already matched exactly
1771         if (peStatic->peFlags == EXACT_MATCH)
1772         {
1773             peStatic++;
1774             continue;
1775         }
1776 
1777         iMinDist = MAX_COL_DIST+1;
1778 #if DBG
1779         iMinEntry = -1;
1780 #endif
1781 
1782         pe332 = pe332Palette;
1783         for (i332 = 0; i332 < 256; i332++)
1784         {
1785             // Skip colors already used
1786             if (pe332->peFlags == COLOR_USED)
1787             {
1788                 pe332++;
1789                 continue;
1790             }
1791 
1792             // Compute Euclidean distance squared
1793             iDelta = pe332->peRed-peStatic->peRed;
1794             iDist = iDelta*iDelta;
1795             iDelta = pe332->peGreen-peStatic->peGreen;
1796             iDist += iDelta*iDelta;
1797             iDelta = pe332->peBlue-peStatic->peBlue;
1798             iDist += iDelta*iDelta;
1799 
1800             if (iDist < iMinDist)
1801             {
1802                 iMinDist = iDist;
1803                 iMinEntry = i332;
1804             }
1805 
1806             pe332++;
1807         }
1808 
1809         TKASSERT(iMinEntry != -1);
1810 
1811         // Remember the best match
1812         aiDefaultOverride[iStatic] = iMinEntry;
1813         pe332Palette[iMinEntry].peFlags = COLOR_USED;
1814 
1815         peStatic++;
1816     }
1817 
1818     // Zero the flags in the static colors because they may have been
1819     // set.  We want them to be zero so the colors can be remapped
1820     peStatic = apeDefaultPalEntry;
1821     for (iStatic = 0; iStatic < STATIC_COLORS; iStatic++)
1822     {
1823         peStatic->peFlags = 0;
1824         peStatic++;
1825     }
1826 
1827     // Reset the 332 flags because we may have set them
1828     pe332 = pe332Palette;
1829     for (i332 = 0; i332 < 256; i332++)
1830     {
1831         pe332->peFlags = PALETTE_FLAGS;
1832         pe332++;
1833     }
1834 
1835 #if 0
1836     for (iStatic = 0; iStatic < STATIC_COLORS; iStatic++)
1837     {
1838         PrintMessage("Static color %2d maps to %d\n",
1839                      iStatic, aiDefaultOverride[iStatic]);
1840     }
1841 #endif
1842 }
1843 
1844 /******************************Public*Routine******************************\
1845 * FillRgbPaletteEntries
1846 *
1847 * Fills a PALETTEENTRY array with values required for a logical rgb palette.
1848 * If tkSetStaticColorUsage has been called with TRUE, the static system
1849 * colors will be overridden.  Otherwise, the PALETTEENTRY array will be
1850 * fixed up to contain the default static system colors.
1851 *
1852 * History:
1853 *  26-Apr-1994 -by- Gilman Wong [gilmanw]
1854 * Wrote it.
1855 \**************************************************************************/
1856 
1857 static PALETTEENTRY *
FillRgbPaletteEntries(PIXELFORMATDESCRIPTOR * Pfd,PALETTEENTRY * Entries,UINT Count)1858 FillRgbPaletteEntries(  PIXELFORMATDESCRIPTOR *Pfd,
1859                         PALETTEENTRY *Entries,
1860                         UINT Count
1861                      )
1862 {
1863     PALETTEENTRY *Entry;
1864     UINT i;
1865 
1866     if ( NULL != Entries )
1867     {
1868         for ( i = 0, Entry = Entries ; i < Count ; i++, Entry++ )
1869         {
1870             Entry->peRed   = ComponentFromIndex(i, Pfd->cRedBits,
1871                                     Pfd->cRedShift);
1872             Entry->peGreen = ComponentFromIndex(i, Pfd->cGreenBits,
1873                                     Pfd->cGreenShift);
1874             Entry->peBlue  = ComponentFromIndex(i, Pfd->cBlueBits,
1875                                     Pfd->cBlueShift);
1876             Entry->peFlags = PALETTE_FLAGS;
1877         }
1878 
1879         if ( 256 == Count)
1880         {
1881         // If app set static system color usage for fixed palette support,
1882         // setup to take over the static colors.  Otherwise, fixup the
1883         // static system colors.
1884 
1885             if ( tkUseStaticColors )
1886             {
1887             // Black and white already exist as the only remaining static
1888             // colors.  Let those remap.  All others should be put into
1889             // the palette (i.e., set PC_NOCOLLAPSE).
1890 
1891                 Entries[0].peFlags = 0;
1892                 Entries[255].peFlags = 0;
1893             }
1894             else
1895             {
1896             // The defaultOverride array is computed assuming a 332
1897             // palette where red has zero shift, etc.
1898 
1899                 if ( (3 == Pfd->cRedBits)   && (0 == Pfd->cRedShift)   &&
1900                      (3 == Pfd->cGreenBits) && (3 == Pfd->cGreenShift) &&
1901                      (2 == Pfd->cBlueBits)  && (6 == Pfd->cBlueShift) )
1902                 {
1903                     UpdateStaticMapping(Entries);
1904 
1905                     for ( i = 0 ; i < STATIC_COLORS ; i++)
1906                     {
1907                         Entries[aiDefaultOverride[i]] = apeDefaultPalEntry[i];
1908                     }
1909                 }
1910             }
1911         }
1912     }
1913     return( Entries );
1914 }
1915 
1916 static HPALETTE
CreateRGBPalette(HDC Dc)1917 CreateRGBPalette( HDC Dc )
1918 {
1919     PIXELFORMATDESCRIPTOR Pfd, *pPfd;
1920     LOGPALETTE *LogPalette;
1921     UINT Count;
1922 
1923     if ( NULL == tkhpalette )
1924     {
1925         pPfd = &Pfd;
1926 
1927         if ( PixelFormatDescriptorFromDc( Dc, pPfd ) )
1928         {
1929             /*
1930              *  Make sure we need a palette
1931              */
1932 
1933             if ( (pPfd->iPixelType == PFD_TYPE_RGBA) &&
1934                  (pPfd->dwFlags & PFD_NEED_PALETTE) )
1935             {
1936                 /*
1937                  *  Note how palette is to be realized.  Take over the
1938                  *  system colors if either the pixel format requires it
1939                  *  or the app wants it.
1940                  */
1941                 tkUseStaticColors = ( pPfd->dwFlags & PFD_NEED_SYSTEM_PALETTE )
1942                                     || TK_USE_FIXED_332_PAL(windInfo.type);
1943 
1944                 Count       = 1 << pPfd->cColorBits;
1945                 LogPalette  = AllocateMemory( sizeof(LOGPALETTE) +
1946                                 Count * sizeof(PALETTEENTRY));
1947 
1948                 if ( NULL != LogPalette )
1949                 {
1950                     LogPalette->palVersion    = 0x300;
1951                     LogPalette->palNumEntries = Count;
1952 
1953                     FillRgbPaletteEntries( pPfd,
1954                                            &LogPalette->palPalEntry[0],
1955                                            Count );
1956 
1957                     tkhpalette = CreatePalette(LogPalette);
1958                     FreeMemory(LogPalette);
1959 
1960                     RealizePaletteNow( Dc, tkhpalette, FALSE );
1961                 }
1962             }
1963         }
1964     }
1965     return( tkhpalette );
1966 }
1967 
1968 static HPALETTE
CreateCIPalette(HDC Dc)1969 CreateCIPalette( HDC Dc )
1970 {
1971     PIXELFORMATDESCRIPTOR Pfd;
1972     LOGPALETTE *LogicalPalette;
1973     HPALETTE StockPalette;
1974     UINT PaletteSize, StockPaletteSize, EntriesToCopy;
1975 
1976     if ( (Dc != NULL) && (NULL == tkhpalette) )
1977     {
1978         if ( PixelFormatDescriptorFromDc( Dc, &Pfd ) )
1979         {
1980             if ( Pfd.iPixelType == PFD_TYPE_COLORINDEX )
1981             {
1982                 /*
1983                  *  Note how palette is to be realized (Is this the correct place to do this?)
1984                  */
1985                 tkUseStaticColors = ( Pfd.dwFlags & PFD_NEED_SYSTEM_PALETTE )
1986                                     || TK_USE_FIXED_332_PAL(windInfo.type);
1987 
1988                 /*
1989                  *  Limit the size of the palette to 256 colors.
1990                  *  Why? Because this is what was decided.
1991                  */
1992 
1993                 PaletteSize = (Pfd.cColorBits >= 8) ? 256 : (1 << Pfd.cColorBits);
1994 
1995                 LogicalPalette = AllocateZeroedMemory( sizeof(LOGPALETTE) +
1996                                         (PaletteSize * sizeof(PALETTEENTRY)) );
1997 
1998                 if ( NULL != LogicalPalette )
1999                 {
2000                     LogicalPalette->palVersion    = 0x300;
2001                     LogicalPalette->palNumEntries = PaletteSize;
2002 
2003                     StockPalette     = GetStockObject(DEFAULT_PALETTE);
2004                     StockPaletteSize = GetPaletteEntries( StockPalette, 0, 0, NULL );
2005 
2006                     /*
2007                      *  start by copying default palette into new one
2008                      */
2009 
2010                     EntriesToCopy = StockPaletteSize < PaletteSize ?
2011                                         StockPaletteSize : PaletteSize;
2012 
2013                     GetPaletteEntries( StockPalette, 0, EntriesToCopy,
2014                                         LogicalPalette->palPalEntry );
2015 
2016                     /*
2017                      *  If we are taking possession of the system colors,
2018                      *  must guarantee that 0 and 255 are black and white
2019                      *  (respectively).
2020                      */
2021 
2022                     if ( tkUseStaticColors && PaletteSize == 256 )
2023                     {
2024                         int i;
2025 
2026                         LogicalPalette->palPalEntry[0].peRed =
2027                         LogicalPalette->palPalEntry[0].peGreen =
2028                         LogicalPalette->palPalEntry[0].peBlue = 0x00;
2029 
2030                         LogicalPalette->palPalEntry[255].peRed =
2031                         LogicalPalette->palPalEntry[255].peGreen =
2032                         LogicalPalette->palPalEntry[255].peBlue = 0xFF;
2033 
2034                         LogicalPalette->palPalEntry[0].peFlags =
2035                         LogicalPalette->palPalEntry[255].peFlags = 0;
2036 
2037                         /*
2038                          *  All other entries should be remappable,
2039                          *  so mark them as PC_NOCOLLAPSE.
2040                          */
2041                         for ( i = 1; i < 255; i++ )
2042                             LogicalPalette->palPalEntry[i].peFlags = PC_NOCOLLAPSE;
2043                     }
2044 
2045                     tkhpalette = CreatePalette(LogicalPalette);
2046 
2047                     FreeMemory(LogicalPalette);
2048 
2049                     RealizePaletteNow( Dc, tkhpalette, FALSE );
2050                 }
2051             }
2052         }
2053     }
2054     return( tkhpalette );
2055 }
2056 
2057 static BOOL
FindPixelFormat(HDC hdc,GLenum type)2058 FindPixelFormat(HDC hdc, GLenum type)
2059 {
2060     PIXELFORMATDESCRIPTOR pfd;
2061     int PfdIndex;
2062     BOOL Result = FALSE;
2063 
2064     if ( TK_MINIMUM_CRITERIA == windInfo.dmPolicy )
2065         PfdIndex = FindBestPixelFormat(hdc, type, &pfd);
2066     else if ( TK_EXACT_MATCH == windInfo.dmPolicy )
2067         PfdIndex = FindExactPixelFormat(hdc, type, &pfd);
2068     else if ( IsPixelFormatValid(hdc, windInfo.ipfd, &pfd) )
2069         PfdIndex = windInfo.ipfd;
2070     else
2071         PfdIndex = 0;
2072 
2073     if ( PfdIndex )
2074     {
2075         if ( SetPixelFormat(hdc, PfdIndex, &pfd) )
2076         {
2077             /*
2078              *  If this pixel format requires a palette do it now.
2079              *  In colorindex mode, create a logical palette only
2080              *  if the application needs to modify it.
2081              */
2082 
2083             CreateRGBPalette( hdc );
2084             Result = TRUE;
2085         }
2086         else
2087         {
2088             PrintMessage("SetPixelFormat failed\n");
2089         }
2090     }
2091     else
2092     {
2093         PrintMessage("Selecting a pixel format failed\n");
2094     }
2095     return(Result);
2096 }
2097 
2098 static int
FindBestPixelFormat(HDC hdc,GLenum type,PIXELFORMATDESCRIPTOR * ppfd)2099 FindBestPixelFormat(HDC hdc, GLenum type, PIXELFORMATDESCRIPTOR *ppfd)
2100 {
2101     PIXELFORMATDESCRIPTOR pfd;
2102 
2103     pfd.nSize       = sizeof(pfd);
2104     pfd.nVersion    = 1;
2105     pfd.dwFlags     = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
2106 
2107     if (TK_IS_DOUBLE(type))
2108         pfd.dwFlags |= PFD_DOUBLEBUFFER;
2109 
2110     if (TK_IS_INDEX(type)) {
2111         pfd.iPixelType = PFD_TYPE_COLORINDEX;
2112         pfd.cColorBits = 8;
2113     } else {
2114         pfd.iPixelType = PFD_TYPE_RGBA;
2115         pfd.cColorBits = 24;
2116     }
2117 
2118     if (TK_HAS_ALPHA(type))
2119         pfd.cAlphaBits = 8;
2120     else
2121         pfd.cAlphaBits = 0;
2122 
2123     if (TK_HAS_ACCUM(type))
2124         pfd.cAccumBits = pfd.cColorBits + pfd.cAlphaBits;
2125     else
2126         pfd.cAccumBits = 0;
2127 
2128     if (TK_HAS_DEPTH(type)) {
2129         if (TK_IS_DEPTH16(type))
2130             pfd.cDepthBits = 16;
2131         else
2132             pfd.cDepthBits = 32;
2133     } else {
2134         pfd.cDepthBits = 0;
2135     }
2136 
2137     if (TK_HAS_STENCIL(type))
2138         pfd.cStencilBits = 4;
2139     else
2140         pfd.cStencilBits = 0;
2141 
2142     pfd.cAuxBuffers = 0;
2143     pfd.iLayerType  = PFD_MAIN_PLANE;
2144     *ppfd = pfd;
2145 
2146     return ( ChoosePixelFormat(hdc, &pfd) );
2147 }
2148 
2149 static int
FindExactPixelFormat(HDC hdc,GLenum type,PIXELFORMATDESCRIPTOR * ppfd)2150 FindExactPixelFormat(HDC hdc, GLenum type, PIXELFORMATDESCRIPTOR *ppfd)
2151 {
2152     int i, MaxPFDs, Score, BestScore, BestPFD;
2153     PIXELFORMATDESCRIPTOR pfd;
2154 
2155     i = 1;
2156     BestPFD = BestScore = 0;
2157     do
2158     {
2159         MaxPFDs = DescribePixelFormat(hdc, i, sizeof(pfd), &pfd);
2160         if ( MaxPFDs <= 0 )
2161             return ( 0 );
2162 
2163         Score = 0;
2164         if ( !( ( pfd.dwFlags & PFD_DRAW_TO_WINDOW ) &&
2165                 ( pfd.dwFlags & PFD_SUPPORT_OPENGL ) ) )
2166             continue;
2167         if ( pfd.iLayerType != PFD_MAIN_PLANE )
2168             continue;
2169         if ( ( pfd.iPixelType == PFD_TYPE_RGBA ) && ( TK_IS_INDEX(type) ) )
2170             continue;
2171         if ( ( pfd.iPixelType == PFD_TYPE_COLORINDEX ) && ( TK_IS_RGB(type) ) )
2172             continue;
2173         if ( ( pfd.dwFlags & PFD_DOUBLEBUFFER ) && ( TK_IS_SINGLE(type) ) )
2174             continue;
2175         if ( !( pfd.dwFlags & PFD_DOUBLEBUFFER ) && ( TK_IS_DOUBLE(type) ) )
2176             continue;
2177 
2178 /* If accum requested then accum rgb size must be > 0 */
2179 /* If alpha requested then alpha size must be > 0 */
2180 /* if accum & alpha requested then accum alpha size must be > 0 */
2181         if ( TK_IS_RGB(type) )
2182         {
2183             if ( TK_HAS_ACCUM(type) )
2184             {
2185                 if (  pfd.cAccumBits <= 0 )
2186                     continue;
2187             }
2188             else
2189             {
2190                 if ( pfd.cAccumBits > 0 )
2191                     continue;
2192             }
2193 
2194             if ( TK_HAS_ALPHA(type) )
2195             {
2196                 if ( pfd.cAlphaBits <= 0 )
2197                     continue;
2198                 if ( TK_HAS_ACCUM(type) && pfd.cAccumAlphaBits <= 0 )
2199                     continue;
2200             }
2201             else
2202             {
2203                 if ( pfd.cAlphaBits > 0 )
2204                     continue;
2205             }
2206         }
2207 
2208         if ( TK_HAS_DEPTH(type) )
2209         {
2210             if ( pfd.cDepthBits <= 0 )
2211                 continue;
2212         }
2213         else
2214         {
2215             if ( pfd.cDepthBits > 0 )
2216                 continue;
2217         }
2218 
2219         if ( TK_HAS_STENCIL(type) )
2220         {
2221             if ( pfd.cStencilBits <= 0 )
2222                 continue;
2223         }
2224         else
2225         {
2226             if ( pfd.cStencilBits > 0 )
2227                 continue;
2228         }
2229 
2230         Score = pfd.cColorBits;
2231 
2232         if (Score > BestScore)
2233         {
2234             BestScore = Score;
2235             BestPFD = i;
2236             *ppfd = pfd;
2237         }
2238     } while (++i <= MaxPFDs);
2239 
2240     return ( BestPFD );
2241 }
2242 
IsPixelFormatValid(HDC hdc,int ipfd,PIXELFORMATDESCRIPTOR * ppfd)2243 static BOOL IsPixelFormatValid(HDC hdc, int ipfd, PIXELFORMATDESCRIPTOR *ppfd)
2244 {
2245     if ( ipfd > 0 )
2246     {
2247         if ( ipfd <= DescribePixelFormat(hdc, ipfd, sizeof(*ppfd), ppfd) )
2248         {
2249             if ( ( ppfd->dwFlags & PFD_DRAW_TO_WINDOW ) &&
2250                  ( ppfd->dwFlags & PFD_SUPPORT_OPENGL ) )
2251             {
2252                 return ( TRUE );
2253             }
2254         }
2255     }
2256     return ( FALSE );
2257 }
2258 
2259 
2260 static void
PrintMessage(const char * Format,...)2261 PrintMessage( const char *Format, ... )
2262 {
2263     va_list ArgList;
2264     char Buffer[256];
2265 
2266     va_start(ArgList, Format);
2267     vsprintf(Buffer, Format, ArgList);
2268     va_end(ArgList);
2269 
2270     MESSAGEBOX(GetFocus(), Buffer, "Error", MB_OK);
2271 }
2272 
2273 static void
DelayPaletteRealization(void)2274 DelayPaletteRealization( void )
2275 {
2276     MSG Message;
2277 
2278     TKASSERT(NULL!=tkhwnd);
2279 
2280     /*
2281      *  Add a WM_USER message to the queue, if there isn't one there already.
2282      */
2283 
2284     if (!PeekMessage(&Message, tkhwnd, WM_USER, WM_USER, PM_NOREMOVE) )
2285     {
2286         PostMessage( tkhwnd, WM_USER, 0, 0);
2287     }
2288 }
2289 
2290 /******************************Public*Routine******************************\
2291 * RealizePaletteNow
2292 *
2293 * Select the given palette in background or foreground mode (as specified
2294 * by the bForceBackground flag), and realize the palette.
2295 *
2296 * If static system color usage is set, the system colors are replaced.
2297 *
2298 * History:
2299 *  26-Apr-1994 -by- Gilman Wong [gilmanw]
2300 * Wrote it.
2301 \**************************************************************************/
2302 
2303 static long
RealizePaletteNow(HDC Dc,HPALETTE Palette,BOOL bForceBackground)2304 RealizePaletteNow( HDC Dc, HPALETTE Palette, BOOL bForceBackground )
2305 {
2306     long Result = -1;
2307     BOOL bHaveSysPal = TRUE;
2308 
2309     TKASSERT( NULL!=Dc      );
2310     TKASSERT( NULL!=Palette );
2311 
2312 // If static system color usage is set, prepare to take over the
2313 // system palette.
2314 
2315     if ( tkUseStaticColors )
2316     {
2317     // If foreground, take over the static colors.  If background, release
2318     // the static colors.
2319 
2320         if ( !bForceBackground )
2321         {
2322         // If GrabStaticEntries succeeds, then it is OK to take over the
2323         // static colors.  If not, then GrabStaticEntries will have
2324         // posted a WM_USER message for us to try again later.
2325 
2326             bHaveSysPal = GrabStaticEntries( Dc );
2327         }
2328         else
2329         {
2330         // If we are currently using the system colors (tkSystemColorsInUse)
2331         // and RealizePaletteNow was called with bForceBackground set, we
2332         // are being deactivated and must release the static system colors.
2333 
2334             ReleaseStaticEntries( Dc );
2335         }
2336 
2337     // Rerealize the palette.
2338     //
2339     // If set to TRUE, bForceBackground will force the palette to be realized
2340     // as a background palette, regardless of focus.  This will happen anyway
2341     // if the TK window does not have the keyboard focus.
2342 
2343         if ( (bForceBackground || bHaveSysPal) &&
2344              UnrealizeObject( Palette ) &&
2345              NULL != SelectPalette( Dc, Palette, bForceBackground ) )
2346         {
2347             Result = RealizePalette( Dc );
2348         }
2349     }
2350     else
2351     {
2352         if ( NULL != SelectPalette( Dc, Palette, FALSE ) )
2353         {
2354             Result = RealizePalette( Dc );
2355         }
2356     }
2357 
2358     return( Result );
2359 }
2360 
2361 static void
ForceRedraw(HWND Window)2362 ForceRedraw( HWND Window )
2363 {
2364     MSG Message;
2365 
2366     if (!PeekMessage(&Message, Window, WM_PAINT, WM_PAINT, PM_NOREMOVE) )
2367     {
2368         InvalidateRect( Window, NULL, FALSE );
2369     }
2370 }
2371 
2372 static int
PixelFormatDescriptorFromDc(HDC Dc,PIXELFORMATDESCRIPTOR * Pfd)2373 PixelFormatDescriptorFromDc( HDC Dc, PIXELFORMATDESCRIPTOR *Pfd )
2374 {
2375     int PfdIndex;
2376 
2377     if ( 0 < (PfdIndex = GetPixelFormat( Dc )) )
2378     {
2379         if ( 0 < DescribePixelFormat( Dc, PfdIndex, sizeof(*Pfd), Pfd ) )
2380         {
2381             return(PfdIndex);
2382         }
2383         else
2384         {
2385             PrintMessage("Could not get a description of pixel format %d\n",
2386                 PfdIndex );
2387         }
2388     }
2389     else
2390     {
2391         PrintMessage("Could not get pixel format for Dc 0x%08lX\n", Dc );
2392     }
2393     return( 0 );
2394 }
2395 
2396 static void
DestroyThisWindow(HWND Window)2397 DestroyThisWindow( HWND Window )
2398 {
2399     if ( NULL != Window )
2400     {
2401         DestroyWindow( Window );
2402     }
2403 }
2404 
2405 /*
2406  *  This Should be called in response to a WM_DESTROY message
2407  */
2408 
2409 static void
CleanUp(void)2410 CleanUp( void )
2411 {
2412     HPALETTE hStock;
2413 
2414 // Cleanup the palette.
2415 
2416     if ( NULL != tkhpalette )
2417     {
2418     // If static system color usage is set, restore the system colors.
2419 
2420         if ( tkUseStaticColors )
2421         {
2422             RealizePaletteNow( tkhdc, GetStockObject(DEFAULT_PALETTE), TRUE );
2423         }
2424         else
2425         {
2426             if ( hStock = GetStockObject( DEFAULT_PALETTE ) )
2427                 SelectPalette( tkhdc, hStock, FALSE );
2428         }
2429 
2430         DeleteObject( tkhpalette );
2431     }
2432 
2433 // Cleanup the RC.
2434 
2435     if ( NULL != tkhrc )
2436     {
2437         wglMakeCurrent( tkhdc, NULL );  // Release first...
2438         wglDeleteContext( tkhrc );      // then delete.
2439     }
2440 
2441 // Cleanup the DC.
2442 
2443     if ( NULL != tkhdc )
2444     {
2445         ReleaseDC( tkhwnd, tkhdc );
2446     }
2447 
2448 // Be really nice and reset global values.
2449 
2450     tkhwnd        = NULL;
2451     tkhdc         = NULL;
2452     tkhrc         = NULL;
2453     tkhpalette    = NULL;
2454 
2455     ExposeFunc    = NULL;
2456     ReshapeFunc   = NULL;
2457     IdleFunc      = NULL;
2458     DisplayFunc   = NULL;
2459     KeyDownFunc   = NULL;
2460     MouseDownFunc = NULL;
2461     MouseUpFunc   = NULL;
2462     MouseMoveFunc = NULL;
2463 }
2464 
2465 static void *
AllocateMemory(size_t Size)2466 AllocateMemory( size_t Size )
2467 {
2468     return( LocalAlloc( LMEM_FIXED, Size ) );
2469 }
2470 
2471 static void *
AllocateZeroedMemory(size_t Size)2472 AllocateZeroedMemory( size_t Size )
2473 {
2474     return( LocalAlloc( LMEM_FIXED | LMEM_ZEROINIT, Size ) );
2475 }
2476 
2477 
2478 static void
FreeMemory(void * Chunk)2479 FreeMemory( void *Chunk )
2480 {
2481     TKASSERT( NULL!=Chunk );
2482 
2483     LocalFree( Chunk );
2484 }
2485 
2486 
2487 /*******************************************************************
2488  *                                                                 *
2489  *  Debugging functions go here                                    *
2490  *                                                                 *
2491  *******************************************************************/
2492 
2493 #if DBGFUNC
2494 
2495 static void
DbgPrintf(const char * Format,...)2496 DbgPrintf( const char *Format, ... )
2497 {
2498     va_list ArgList;
2499     char Buffer[256];
2500 
2501     va_start(ArgList, Format);
2502     vsprintf(Buffer, Format, ArgList);
2503     va_end(ArgList);
2504 
2505     printf("%s", Buffer );
2506     fflush(stdout);
2507 }
2508 
2509 static void
pwi(void)2510 pwi( void )
2511 {
2512     DbgPrintf("windInfo: x %d, y %d, w %d, h %d\n", windInfo.x, windInfo.y, windInfo.width, windInfo.height);
2513 }
2514 
2515 static void
pwr(RECT * pr)2516 pwr(RECT *pr)
2517 {
2518     DbgPrintf("Rect: left %d, top %d, right %d, bottom %d\n", pr->left, pr->top, pr->right, pr->bottom);
2519 }
2520 
2521 static void
ShowPixelFormat(HDC hdc)2522 ShowPixelFormat(HDC hdc)
2523 {
2524     PIXELFORMATDESCRIPTOR pfd, *ppfd;
2525     int format;
2526 
2527     ppfd   = &pfd;
2528     format = PixelFormatDescriptorFromDc( hdc, ppfd );
2529 
2530     DbgPrintf("Pixel format %d\n", format);
2531     DbgPrintf("  dwFlags - 0x%x", ppfd->dwFlags);
2532         if (ppfd->dwFlags & PFD_DOUBLEBUFFER) DbgPrintf("PFD_DOUBLEBUFFER ");
2533         if (ppfd->dwFlags & PFD_STEREO) DbgPrintf("PFD_STEREO ");
2534         if (ppfd->dwFlags & PFD_DRAW_TO_WINDOW) DbgPrintf("PFD_DRAW_TO_WINDOW ");
2535         if (ppfd->dwFlags & PFD_DRAW_TO_BITMAP) DbgPrintf("PFD_DRAW_TO_BITMAP ");
2536         if (ppfd->dwFlags & PFD_SUPPORT_GDI) DbgPrintf("PFD_SUPPORT_GDI ");
2537         if (ppfd->dwFlags & PFD_SUPPORT_OPENGL) DbgPrintf("PFD_SUPPORT_OPENGL ");
2538         if (ppfd->dwFlags & PFD_GENERIC_FORMAT) DbgPrintf("PFD_GENERIC_FORMAT ");
2539         if (ppfd->dwFlags & PFD_NEED_PALETTE) DbgPrintf("PFD_NEED_PALETTE ");
2540         if (ppfd->dwFlags & PFD_NEED_SYSTEM_PALETTE) DbgPrintf("PFD_NEED_SYSTEM_PALETTE ");
2541         DbgPrintf("\n");
2542     DbgPrintf("  iPixelType - %d", ppfd->iPixelType);
2543         if (ppfd->iPixelType == PFD_TYPE_RGBA) DbgPrintf("PGD_TYPE_RGBA\n");
2544         if (ppfd->iPixelType == PFD_TYPE_COLORINDEX) DbgPrintf("PGD_TYPE_COLORINDEX\n");
2545     DbgPrintf("  cColorBits - %d\n", ppfd->cColorBits);
2546     DbgPrintf("  cRedBits - %d\n", ppfd->cRedBits);
2547     DbgPrintf("  cRedShift - %d\n", ppfd->cRedShift);
2548     DbgPrintf("  cGreenBits - %d\n", ppfd->cGreenBits);
2549     DbgPrintf("  cGreenShift - %d\n", ppfd->cGreenShift);
2550     DbgPrintf("  cBlueBits - %d\n", ppfd->cBlueBits);
2551     DbgPrintf("  cBlueShift - %d\n", ppfd->cBlueShift);
2552     DbgPrintf("  cAlphaBits - %d\n", ppfd->cAlphaBits);
2553     DbgPrintf("  cAlphaShift - 0x%x\n", ppfd->cAlphaShift);
2554     DbgPrintf("  cAccumBits - %d\n", ppfd->cAccumBits);
2555     DbgPrintf("  cAccumRedBits - %d\n", ppfd->cAccumRedBits);
2556     DbgPrintf("  cAccumGreenBits - %d\n", ppfd->cAccumGreenBits);
2557     DbgPrintf("  cAccumBlueBits - %d\n", ppfd->cAccumBlueBits);
2558     DbgPrintf("  cAccumAlphaBits - %d\n", ppfd->cAccumAlphaBits);
2559     DbgPrintf("  cDepthBits - %d\n", ppfd->cDepthBits);
2560     DbgPrintf("  cStencilBits - %d\n", ppfd->cStencilBits);
2561     DbgPrintf("  cAuxBuffers - %d\n", ppfd->cAuxBuffers);
2562     DbgPrintf("  iLayerType - %d\n", ppfd->iLayerType);
2563     DbgPrintf("  bReserved - %d\n", ppfd->bReserved);
2564     DbgPrintf("  dwLayerMask - 0x%x\n", ppfd->dwLayerMask);
2565     DbgPrintf("  dwVisibleMask - 0x%x\n", ppfd->dwVisibleMask);
2566     DbgPrintf("  dwDamageMask - 0x%x\n", ppfd->dwDamageMask);
2567 
2568 }
2569 
2570 #endif  /* DBG */
2571