Splitting the X11-specific "freeglut_gamemode.c" code into its own file
[freeglut] / src / mswin / freeglut_init_mswin.c
1 /*\r
2  * freeglut_init_mswin.c\r
3  *\r
4  * The Windows-specific mouse cursor related stuff.\r
5  *\r
6  * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved.\r
7  * Written by John F. Fay, <fayjf@sourceforge.net>\r
8  * Creation date: Thu Jan 19, 2012\r
9  *\r
10  * Permission is hereby granted, free of charge, to any person obtaining a\r
11  * copy of this software and associated documentation files (the "Software"),\r
12  * to deal in the Software without restriction, including without limitation\r
13  * the rights to use, copy, modify, merge, publish, distribute, sublicense,\r
14  * and/or sell copies of the Software, and to permit persons to whom the\r
15  * Software is furnished to do so, subject to the following conditions:\r
16  *\r
17  * The above copyright notice and this permission notice shall be included\r
18  * in all copies or substantial portions of the Software.\r
19  *\r
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS\r
21  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
22  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL\r
23  * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
24  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
25  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
26  */\r
27 \r
28 #define FREEGLUT_BUILDING_LIB\r
29 #include <GL/freeglut.h>\r
30 #include "../Common/freeglut_internal.h"\r
31 \r
32 \r
33 \r
34 extern LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg,\r
35                                WPARAM wParam, LPARAM lParam );\r
36 \r
37 \r
38 /*\r
39  * A call to this function should initialize all the display stuff...\r
40  */\r
41 void fgPlatformInitialize( const char* displayName )\r
42 {\r
43     WNDCLASS wc;\r
44     ATOM atom;\r
45 \r
46     /* What we need to do is to initialize the fgDisplay global structure here. */\r
47     fgDisplay.pDisplay.Instance = GetModuleHandle( NULL );\r
48     fgDisplay.pDisplay.DisplayName= displayName ? strdup(displayName) : 0 ;\r
49     atom = GetClassInfo( fgDisplay.pDisplay.Instance, _T("FREEGLUT"), &wc );\r
50 \r
51     if( atom == 0 )\r
52     {\r
53         ZeroMemory( &wc, sizeof(WNDCLASS) );\r
54 \r
55         /*\r
56          * Each of the windows should have its own device context, and we\r
57          * want redraw events during Vertical and Horizontal Resizes by\r
58          * the user.\r
59          *\r
60          * XXX Old code had "| CS_DBCLCKS" commented out.  Plans for the\r
61          * XXX future?  Dead-end idea?\r
62          */\r
63         wc.lpfnWndProc    = fgPlatformWindowProc;\r
64         wc.cbClsExtra     = 0;\r
65         wc.cbWndExtra     = 0;\r
66         wc.hInstance      = fgDisplay.pDisplay.Instance;\r
67         wc.hIcon          = LoadIcon( fgDisplay.pDisplay.Instance, _T("GLUT_ICON") );\r
68 \r
69 #if defined(_WIN32_WCE)\r
70         wc.style          = CS_HREDRAW | CS_VREDRAW;\r
71 #else\r
72         wc.style          = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;\r
73         if (!wc.hIcon)\r
74           wc.hIcon        = LoadIcon( NULL, IDI_WINLOGO );\r
75 #endif\r
76 \r
77         wc.hCursor        = LoadCursor( NULL, IDC_ARROW );\r
78         wc.hbrBackground  = NULL;\r
79         wc.lpszMenuName   = NULL;\r
80         wc.lpszClassName  = _T("FREEGLUT");\r
81 \r
82         /* Register the window class */\r
83         atom = RegisterClass( &wc );\r
84         FREEGLUT_INTERNAL_ERROR_EXIT ( atom, "Window Class Not Registered", "fgPlatformInitialize" );\r
85     }\r
86 \r
87     /* The screen dimensions can be obtained via GetSystemMetrics() calls */\r
88     fgDisplay.ScreenWidth  = GetSystemMetrics( SM_CXSCREEN );\r
89     fgDisplay.ScreenHeight = GetSystemMetrics( SM_CYSCREEN );\r
90 \r
91     {\r
92         HWND desktop = GetDesktopWindow( );\r
93         HDC  context = GetDC( desktop );\r
94 \r
95         fgDisplay.ScreenWidthMM  = GetDeviceCaps( context, HORZSIZE );\r
96         fgDisplay.ScreenHeightMM = GetDeviceCaps( context, VERTSIZE );\r
97 \r
98         ReleaseDC( desktop, context );\r
99     }\r
100     /* If we have a DisplayName try to use it for metrics */\r
101     if( fgDisplay.pDisplay.DisplayName )\r
102     {\r
103         HDC context = CreateDC(fgDisplay.pDisplay.DisplayName,0,0,0);\r
104         if( context )\r
105         {\r
106             fgDisplay.ScreenWidth  = GetDeviceCaps( context, HORZRES );\r
107             fgDisplay.ScreenHeight = GetDeviceCaps( context, VERTRES );\r
108             fgDisplay.ScreenWidthMM  = GetDeviceCaps( context, HORZSIZE );\r
109             fgDisplay.ScreenHeightMM = GetDeviceCaps( context, VERTSIZE );\r
110             DeleteDC(context);\r
111         }\r
112         else\r
113             fgWarning("fgPlatformInitialize: "\r
114                       "CreateDC failed, Screen size info may be incorrect\n"\r
115           "This is quite likely caused by a bad '-display' parameter");\r
116       \r
117     }\r
118     /* Set the timer granularity to 1 ms */\r
119     timeBeginPeriod ( 1 );\r
120 \r
121 \r
122     fgState.Initialised = GL_TRUE;\r
123 \r
124     /* Avoid registering atexit callback on Win32 as it results in an access\r
125      * violation due to calling into a module which has been unloaded.\r
126      * Any cleanup isn't needed on Windows anyway, the OS takes care of it.c\r
127      * see: http://blogs.msdn.com/b/oldnewthing/archive/2012/01/05/10253268.aspx\r
128      */\r
129 /*    atexit(fgDeinitialize); */\r
130 \r
131     /* InputDevice uses GlutTimerFunc(), so fgState.Initialised must be TRUE */\r
132     fgInitialiseInputDevices();\r
133 }\r
134 \r
135 \r
136 \r
137 /* Platform-Specific Deinitialization Functions: */\r
138 extern void fghCloseInputDevices ( void );\r
139 \r
140 void fgPlatformDeinitialiseInputDevices ( void )\r
141 {\r
142 #if !defined(_WIN32_WCE)\r
143         fghCloseInputDevices ();\r
144 #endif /* !defined(_WIN32_WCE) */\r
145     fgState.JoysticksInitialised = GL_FALSE;\r
146     fgState.InputDevsInitialised = GL_FALSE;\r
147 }\r
148 \r
149 void fgPlatformCloseDisplay ( void )\r
150 {\r
151     if( fgDisplay.pDisplay.DisplayName )\r
152     {\r
153         free( fgDisplay.pDisplay.DisplayName );\r
154         fgDisplay.pDisplay.DisplayName = NULL;\r
155     }\r
156 \r
157     /* Reset the timer granularity */\r
158     timeEndPeriod ( 1 );\r
159 }\r
160 \r
161 \r
162 \r
163 /*\r
164  * Everything down to the end of the next two functions is copied from the X sources.\r
165  */\r
166 \r
167 /*\r
168 \r
169 Copyright 1985, 1986, 1987,1998  The Open Group\r
170 \r
171 Permission to use, copy, modify, distribute, and sell this software and its\r
172 documentation for any purpose is hereby granted without fee, provided that\r
173 the above copyright notice appear in all copies and that both that\r
174 copyright notice and this permission notice appear in supporting\r
175 documentation.\r
176 \r
177 The above copyright notice and this permission notice shall be included\r
178 in all copies or substantial portions of the Software.\r
179 \r
180 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS\r
181 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
182 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\r
183 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR\r
184 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\r
185 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\r
186 OTHER DEALINGS IN THE SOFTWARE.\r
187 \r
188 Except as contained in this notice, the name of The Open Group shall\r
189 not be used in advertising or otherwise to promote the sale, use or\r
190 other dealings in this Software without prior written authorization\r
191 from The Open Group.\r
192 \r
193 */\r
194 \r
195 #define NoValue         0x0000\r
196 #define XValue          0x0001\r
197 #define YValue          0x0002\r
198 #define WidthValue      0x0004\r
199 #define HeightValue     0x0008\r
200 #define AllValues       0x000F\r
201 #define XNegative       0x0010\r
202 #define YNegative       0x0020\r
203 \r
204 /*\r
205  *    XParseGeometry parses strings of the form\r
206  *   "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where\r
207  *   width, height, xoffset, and yoffset are unsigned integers.\r
208  *   Example:  "=80x24+300-49"\r
209  *   The equal sign is optional.\r
210  *   It returns a bitmask that indicates which of the four values\r
211  *   were actually found in the string.  For each value found,\r
212  *   the corresponding argument is updated;  for each value\r
213  *   not found, the corresponding argument is left unchanged.\r
214  */\r
215 \r
216 static int\r
217 ReadInteger(char *string, char **NextString)\r
218 {\r
219     register int Result = 0;\r
220     int Sign = 1;\r
221 \r
222     if (*string == '+')\r
223         string++;\r
224     else if (*string == '-')\r
225     {\r
226         string++;\r
227         Sign = -1;\r
228     }\r
229     for (; (*string >= '0') && (*string <= '9'); string++)\r
230     {\r
231         Result = (Result * 10) + (*string - '0');\r
232     }\r
233     *NextString = string;\r
234     if (Sign >= 0)\r
235         return Result;\r
236     else\r
237         return -Result;\r
238 }\r
239 \r
240 int XParseGeometry (\r
241     const char *string,\r
242     int *x,\r
243     int *y,\r
244     unsigned int *width,    /* RETURN */\r
245     unsigned int *height)    /* RETURN */\r
246 {\r
247     int mask = NoValue;\r
248     register char *strind;\r
249     unsigned int tempWidth = 0, tempHeight = 0;\r
250     int tempX = 0, tempY = 0;\r
251     char *nextCharacter;\r
252 \r
253     if ( (string == NULL) || (*string == '\0'))\r
254       return mask;\r
255     if (*string == '=')\r
256         string++;  /* ignore possible '=' at beg of geometry spec */\r
257 \r
258     strind = (char *)string;\r
259     if (*strind != '+' && *strind != '-' && *strind != 'x') {\r
260         tempWidth = ReadInteger(strind, &nextCharacter);\r
261         if (strind == nextCharacter)\r
262             return 0;\r
263         strind = nextCharacter;\r
264         mask |= WidthValue;\r
265     }\r
266 \r
267     if (*strind == 'x' || *strind == 'X') {\r
268         strind++;\r
269         tempHeight = ReadInteger(strind, &nextCharacter);\r
270         if (strind == nextCharacter)\r
271             return 0;\r
272         strind = nextCharacter;\r
273         mask |= HeightValue;\r
274     }\r
275 \r
276     if ((*strind == '+') || (*strind == '-')) {\r
277         if (*strind == '-') {\r
278             strind++;\r
279             tempX = -ReadInteger(strind, &nextCharacter);\r
280             if (strind == nextCharacter)\r
281                 return 0;\r
282             strind = nextCharacter;\r
283             mask |= XNegative;\r
284         }\r
285         else\r
286         {\r
287             strind++;\r
288             tempX = ReadInteger(strind, &nextCharacter);\r
289             if (strind == nextCharacter)\r
290                 return 0;\r
291             strind = nextCharacter;\r
292         }\r
293         mask |= XValue;\r
294         if ((*strind == '+') || (*strind == '-')) {\r
295             if (*strind == '-') {\r
296                 strind++;\r
297                 tempY = -ReadInteger(strind, &nextCharacter);\r
298                 if (strind == nextCharacter)\r
299                     return 0;\r
300                 strind = nextCharacter;\r
301                 mask |= YNegative;\r
302             }\r
303             else\r
304             {\r
305                 strind++;\r
306                 tempY = ReadInteger(strind, &nextCharacter);\r
307                 if (strind == nextCharacter)\r
308                     return 0;\r
309                 strind = nextCharacter;\r
310             }\r
311             mask |= YValue;\r
312         }\r
313     }\r
314 \r
315     /* If strind isn't at the end of the string the it's an invalid\r
316        geometry specification. */\r
317 \r
318     if (*strind != '\0') return 0;\r
319 \r
320     if (mask & XValue)\r
321         *x = tempX;\r
322     if (mask & YValue)\r
323         *y = tempY;\r
324     if (mask & WidthValue)\r
325         *width = tempWidth;\r
326     if (mask & HeightValue)\r
327         *height = tempHeight;\r
328     return mask;\r
329 }\r
330 \r
331 \r
332 \r
333 /* -- PLATFORM-SPECIFIC INTERFACE FUNCTION -------------------------------------------------- */\r
334 \r
335 void (__cdecl *__glutExitFunc)( int return_value ) = NULL;\r
336 \r
337 void FGAPIENTRY __glutInitWithExit( int *pargc, char **argv, void (__cdecl *exit_function)(int) )\r
338 {\r
339   __glutExitFunc = exit_function;\r
340   glutInit(pargc, argv);\r
341 }\r
342 \r