Include keyboard.h before frame.h.
[bpt/emacs.git] / src / w32xfns.c
CommitLineData
e9e23e23 1/* Functions taken directly from X sources for use with the Microsoft W32 API.
68c45bf0 2 Copyright (C) 1989, 1992, 1993, 1994, 1995, 1999 Free Software Foundation.
ee78dc32
GV
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
3b7ad313
EN
18the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
ee78dc32 20
ee78dc32 21#include <config.h>
68c45bf0 22#include <signal.h>
ee78dc32
GV
23#include <stdio.h>
24#include "lisp.h"
3e4731a3 25#include "keyboard.h"
97aab3a2 26#include "frame.h"
bd6bb544
GV
27#include "charset.h"
28#include "fontset.h"
ee78dc32
GV
29#include "blockinput.h"
30#include "w32term.h"
31#include "windowsx.h"
32
33#define myalloc(cb) GlobalAllocPtr (GPTR, cb)
34#define myfree(lp) GlobalFreePtr (lp)
35
dd118a07 36CRITICAL_SECTION critsect;
ee78dc32 37extern HANDLE keyboard_handle;
97aab3a2 38HANDLE input_available = NULL;
1ce3dc2b 39HANDLE interrupt_handle = NULL;
ee78dc32
GV
40
41void
42init_crit ()
43{
dd118a07 44 InitializeCriticalSection (&critsect);
ee78dc32 45
97aab3a2
GV
46 /* For safety, input_available should only be reset by get_next_msg
47 when the input queue is empty, so make it a manual reset event. */
48 keyboard_handle = input_available = CreateEvent (NULL, TRUE, FALSE, NULL);
1ce3dc2b
RS
49
50 /* interrupt_handle is signalled when quit (C-g) is detected, so that
51 blocking system calls can be interrupted. We make it a manual
52 reset event, so that if we should ever have multiple threads
53 performing system calls, they will all be interrupted (I'm guessing
54 that would the right response). Note that we use PulseEvent to
55 signal this event, so that it never remains signalled. */
56 interrupt_handle = CreateEvent (NULL, TRUE, FALSE, NULL);
ee78dc32
GV
57}
58
dd118a07 59void
97aab3a2 60delete_crit ()
ee78dc32 61{
97aab3a2
GV
62 DeleteCriticalSection (&critsect);
63
64 if (input_available)
65 {
66 CloseHandle (input_available);
67 input_available = NULL;
68 }
1ce3dc2b
RS
69 if (interrupt_handle)
70 {
71 CloseHandle (interrupt_handle);
72 interrupt_handle = NULL;
73 }
74}
75
76void
77signal_quit ()
78{
79 /* Make sure this event never remains signalled; if the main thread
80 isn't in a blocking call, then this should do nothing. */
81 PulseEvent (interrupt_handle);
d484dc55
GV
82}
83
97aab3a2
GV
84void
85select_palette (FRAME_PTR f, HDC hdc)
d484dc55 86{
fbd6baed
GV
87 if (!NILP (Vw32_enable_palette))
88 f->output_data.w32->old_palette =
89 SelectPalette (hdc, one_w32_display_info.palette, FALSE);
97aab3a2 90 else
fbd6baed 91 f->output_data.w32->old_palette = NULL;
97aab3a2
GV
92
93 if (RealizePalette (hdc))
94 {
95 Lisp_Object frame, framelist;
96 FOR_EACH_FRAME (framelist, frame)
dd118a07 97 {
97aab3a2 98 SET_FRAME_GARBAGED (XFRAME (frame));
dd118a07 99 }
97aab3a2
GV
100 }
101}
102
103void
104deselect_palette (FRAME_PTR f, HDC hdc)
105{
fbd6baed
GV
106 if (f->output_data.w32->old_palette)
107 SelectPalette (hdc, f->output_data.w32->old_palette, FALSE);
97aab3a2
GV
108}
109
110/* Get a DC for frame and select palette for drawing; force an update of
111 all frames if palette's mapping changes. */
112HDC
113get_frame_dc (FRAME_PTR f)
114{
115 HDC hdc;
116
117 enter_crit ();
118
fbd6baed 119 hdc = GetDC (f->output_data.w32->window_desc);
97aab3a2
GV
120 select_palette (f, hdc);
121
122 return hdc;
123}
124
125int
126release_frame_dc (FRAME_PTR f, HDC hdc)
127{
128 int ret;
129
130 deselect_palette (f, hdc);
fbd6baed 131 ret = ReleaseDC (f->output_data.w32->window_desc, hdc);
97aab3a2
GV
132
133 leave_crit ();
134
135 return ret;
ee78dc32
GV
136}
137
138typedef struct int_msg
139{
fbd6baed 140 W32Msg w32msg;
ee78dc32
GV
141 struct int_msg *lpNext;
142} int_msg;
143
144int_msg *lpHead = NULL;
145int_msg *lpTail = NULL;
146int nQueue = 0;
147
148BOOL
149get_next_msg (lpmsg, bWait)
fbd6baed 150 W32Msg * lpmsg;
ee78dc32
GV
151 BOOL bWait;
152{
153 BOOL bRet = FALSE;
154
dd118a07 155 enter_crit ();
ee78dc32
GV
156
157 /* The while loop takes care of multiple sets */
158
159 while (!nQueue && bWait)
160 {
dd118a07 161 leave_crit ();
97aab3a2 162 WaitForSingleObject (input_available, INFINITE);
dd118a07 163 enter_crit ();
ee78dc32
GV
164 }
165
166 if (nQueue)
167 {
fbd6baed 168 bcopy (&(lpHead->w32msg), lpmsg, sizeof (W32Msg));
ee78dc32
GV
169
170 {
171 int_msg * lpCur = lpHead;
172
173 lpHead = lpHead->lpNext;
174
175 myfree (lpCur);
176 }
177
178 nQueue--;
179
180 bRet = TRUE;
181 }
97aab3a2
GV
182
183 if (nQueue == 0)
184 ResetEvent (input_available);
ee78dc32 185
dd118a07 186 leave_crit ();
ee78dc32
GV
187
188 return (bRet);
189}
190
191BOOL
192post_msg (lpmsg)
fbd6baed 193 W32Msg * lpmsg;
ee78dc32
GV
194{
195 int_msg * lpNew = (int_msg *) myalloc (sizeof (int_msg));
196
97aab3a2
GV
197 if (!lpNew)
198 return (FALSE);
ee78dc32 199
fbd6baed 200 bcopy (lpmsg, &(lpNew->w32msg), sizeof (W32Msg));
ee78dc32
GV
201 lpNew->lpNext = NULL;
202
dd118a07 203 enter_crit ();
ee78dc32
GV
204
205 if (nQueue++)
dd118a07
GV
206 {
207 lpTail->lpNext = lpNew;
208 }
ee78dc32 209 else
dd118a07
GV
210 {
211 lpHead = lpNew;
dd118a07 212 }
ee78dc32
GV
213
214 lpTail = lpNew;
97aab3a2 215 SetEvent (input_available);
ee78dc32 216
dd118a07 217 leave_crit ();
ee78dc32
GV
218
219 return (TRUE);
220}
221
7c69181b 222BOOL
fbd6baed 223prepend_msg (W32Msg *lpmsg)
7c69181b
GV
224{
225 int_msg * lpNew = (int_msg *) myalloc (sizeof (int_msg));
226
227 if (!lpNew)
228 return (FALSE);
229
fbd6baed 230 bcopy (lpmsg, &(lpNew->w32msg), sizeof (W32Msg));
7c69181b
GV
231
232 enter_crit ();
233
234 nQueue++;
235 lpNew->lpNext = lpHead;
236 lpHead = lpNew;
237
238 leave_crit ();
239
240 return (TRUE);
241}
242
716490f0
AI
243/* Process all messages in the current thread's queue. */
244void
245drain_message_queue ()
246{
247 MSG msg;
248 while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
249 {
250 TranslateMessage (&msg);
251 DispatchMessage (&msg);
252 }
253}
254
255
ee78dc32
GV
256/*
257 * XParseGeometry parses strings of the form
258 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
259 * width, height, xoffset, and yoffset are unsigned integers.
260 * Example: "=80x24+300-49"
261 * The equal sign is optional.
262 * It returns a bitmask that indicates which of the four values
263 * were actually found in the string. For each value found,
264 * the corresponding argument is updated; for each value
265 * not found, the corresponding argument is left unchanged.
266 */
267
268static int
269read_integer (string, NextString)
270 register char *string;
271 char **NextString;
272{
273 register int Result = 0;
274 int Sign = 1;
275
276 if (*string == '+')
277 string++;
278 else if (*string == '-')
279 {
280 string++;
281 Sign = -1;
282 }
283 for (; (*string >= '0') && (*string <= '9'); string++)
284 {
285 Result = (Result * 10) + (*string - '0');
286 }
287 *NextString = string;
288 if (Sign >= 0)
289 return (Result);
290 else
291 return (-Result);
292}
293
294int
295XParseGeometry (string, x, y, width, height)
296 char *string;
297 int *x, *y;
298 unsigned int *width, *height; /* RETURN */
299{
300 int mask = NoValue;
301 register char *strind;
302 unsigned int tempWidth, tempHeight;
303 int tempX, tempY;
304 char *nextCharacter;
305
306 if ((string == NULL) || (*string == '\0')) return (mask);
307 if (*string == '=')
308 string++; /* ignore possible '=' at beg of geometry spec */
309
310 strind = (char *)string;
311 if (*strind != '+' && *strind != '-' && *strind != 'x')
312 {
313 tempWidth = read_integer (strind, &nextCharacter);
314 if (strind == nextCharacter)
315 return (0);
316 strind = nextCharacter;
317 mask |= WidthValue;
318 }
319
320 if (*strind == 'x' || *strind == 'X')
321 {
322 strind++;
323 tempHeight = read_integer (strind, &nextCharacter);
324 if (strind == nextCharacter)
325 return (0);
326 strind = nextCharacter;
327 mask |= HeightValue;
328 }
329
330 if ((*strind == '+') || (*strind == '-'))
331 {
332 if (*strind == '-')
333 {
334 strind++;
335 tempX = -read_integer (strind, &nextCharacter);
336 if (strind == nextCharacter)
337 return (0);
338 strind = nextCharacter;
339 mask |= XNegative;
340
341 }
342 else
343 {
344 strind++;
345 tempX = read_integer (strind, &nextCharacter);
346 if (strind == nextCharacter)
347 return (0);
348 strind = nextCharacter;
349 }
350 mask |= XValue;
351 if ((*strind == '+') || (*strind == '-'))
352 {
353 if (*strind == '-')
354 {
355 strind++;
356 tempY = -read_integer (strind, &nextCharacter);
357 if (strind == nextCharacter)
358 return (0);
359 strind = nextCharacter;
360 mask |= YNegative;
361
362 }
363 else
364 {
365 strind++;
366 tempY = read_integer (strind, &nextCharacter);
367 if (strind == nextCharacter)
368 return (0);
369 strind = nextCharacter;
370 }
371 mask |= YValue;
372 }
373 }
374
375 /* If strind isn't at the end of the string the it's an invalid
376 geometry specification. */
377
378 if (*strind != '\0') return (0);
379
380 if (mask & XValue)
381 *x = tempX;
382 if (mask & YValue)
383 *y = tempY;
384 if (mask & WidthValue)
385 *width = tempWidth;
386 if (mask & HeightValue)
387 *height = tempHeight;
388 return (mask);
389}
390
fbd6baed 391/* x_sync is a no-op on W32. */
ee78dc32
GV
392void
393x_sync (f)
394 void *f;
395{
396}