Fix conflicting declarations of x_get_keysym_name
[bpt/emacs.git] / src / w32xfns.c
CommitLineData
e9e23e23 1/* Functions taken directly from X sources for use with the Microsoft W32 API.
429ab54e 2 Copyright (C) 1989, 1992, 1993, 1994, 1995, 1999, 2001, 2002, 2003,
114f9c96 3 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
ee78dc32
GV
4
5This file is part of GNU Emacs.
6
9ec0b715 7GNU Emacs is free software: you can redistribute it and/or modify
ee78dc32 8it under the terms of the GNU General Public License as published by
9ec0b715
GM
9the Free Software Foundation, either version 3 of the License, or
10(at your option) any later version.
ee78dc32
GV
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
9ec0b715 18along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
ee78dc32 19
ee78dc32 20#include <config.h>
68c45bf0 21#include <signal.h>
ee78dc32 22#include <stdio.h>
d7306fe6 23#include <setjmp.h>
ee78dc32 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 40
177c0ea7 41void
ee78dc32
GV
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 49
04bf5b65 50 /* interrupt_handle is signaled when quit (C-g) is detected, so that
1ce3dc2b
RS
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
04bf5b65 55 signal this event, so that it never remains signaled. */
1ce3dc2b 56 interrupt_handle = CreateEvent (NULL, TRUE, FALSE, NULL);
ee78dc32
GV
57}
58
177c0ea7 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{
04bf5b65 79 /* Make sure this event never remains signaled; if the main thread
1ce3dc2b
RS
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{
90f4a9f8
AI
87 struct w32_display_info *display_info = FRAME_W32_DISPLAY_INFO (f);
88
89 if (!display_info->has_palette)
90 return;
91
92 if (display_info->palette == 0)
a8370d72 93 return;
90f4a9f8 94
fbd6baed
GV
95 if (!NILP (Vw32_enable_palette))
96 f->output_data.w32->old_palette =
90f4a9f8 97 SelectPalette (hdc, display_info->palette, FALSE);
97aab3a2 98 else
fbd6baed 99 f->output_data.w32->old_palette = NULL;
97aab3a2
GV
100
101 if (RealizePalette (hdc))
102 {
103 Lisp_Object frame, framelist;
104 FOR_EACH_FRAME (framelist, frame)
dd118a07 105 {
97aab3a2 106 SET_FRAME_GARBAGED (XFRAME (frame));
dd118a07 107 }
97aab3a2
GV
108 }
109}
110
111void
112deselect_palette (FRAME_PTR f, HDC hdc)
113{
fbd6baed
GV
114 if (f->output_data.w32->old_palette)
115 SelectPalette (hdc, f->output_data.w32->old_palette, FALSE);
97aab3a2
GV
116}
117
118/* Get a DC for frame and select palette for drawing; force an update of
119 all frames if palette's mapping changes. */
120HDC
121get_frame_dc (FRAME_PTR f)
122{
123 HDC hdc;
124
56c16321
AI
125 if (f->output_method != output_w32)
126 abort ();
127
97aab3a2
GV
128 enter_crit ();
129
fbd6baed 130 hdc = GetDC (f->output_data.w32->window_desc);
86d1db20
JR
131
132 /* If this gets called during startup before the frame is valid,
133 there is a chance of corrupting random data or crashing. */
134 if (hdc)
135 select_palette (f, hdc);
97aab3a2
GV
136
137 return hdc;
138}
139
140int
141release_frame_dc (FRAME_PTR f, HDC hdc)
142{
143 int ret;
144
145 deselect_palette (f, hdc);
fbd6baed 146 ret = ReleaseDC (f->output_data.w32->window_desc, hdc);
97aab3a2
GV
147
148 leave_crit ();
149
150 return ret;
ee78dc32
GV
151}
152
153typedef struct int_msg
154{
fbd6baed 155 W32Msg w32msg;
ee78dc32
GV
156 struct int_msg *lpNext;
157} int_msg;
158
159int_msg *lpHead = NULL;
160int_msg *lpTail = NULL;
161int nQueue = 0;
162
177c0ea7 163BOOL
ee78dc32 164get_next_msg (lpmsg, bWait)
fbd6baed 165 W32Msg * lpmsg;
ee78dc32
GV
166 BOOL bWait;
167{
168 BOOL bRet = FALSE;
177c0ea7 169
dd118a07 170 enter_crit ();
177c0ea7 171
ee78dc32 172 /* The while loop takes care of multiple sets */
177c0ea7 173
ee78dc32
GV
174 while (!nQueue && bWait)
175 {
dd118a07 176 leave_crit ();
97aab3a2 177 WaitForSingleObject (input_available, INFINITE);
dd118a07 178 enter_crit ();
ee78dc32 179 }
177c0ea7 180
ee78dc32
GV
181 if (nQueue)
182 {
fbd6baed 183 bcopy (&(lpHead->w32msg), lpmsg, sizeof (W32Msg));
ee78dc32
GV
184
185 {
186 int_msg * lpCur = lpHead;
177c0ea7 187
ee78dc32 188 lpHead = lpHead->lpNext;
177c0ea7 189
ee78dc32
GV
190 myfree (lpCur);
191 }
192
193 nQueue--;
b668cc18
JR
194 /* Consolidate WM_PAINT messages to optimise redrawing. */
195 if (lpmsg->msg.message == WM_PAINT && nQueue)
196 {
197 int_msg * lpCur = lpHead;
198 int_msg * lpPrev = NULL;
199 int_msg * lpNext = NULL;
200
201 while (lpCur && nQueue)
202 {
203 lpNext = lpCur->lpNext;
204 if (lpCur->w32msg.msg.message == WM_PAINT)
205 {
206 /* Remove this message from the queue. */
207 if (lpPrev)
208 lpPrev->lpNext = lpNext;
209 else
210 lpHead = lpNext;
211
212 if (lpCur == lpTail)
213 lpTail = lpPrev;
214
215 /* Adjust clip rectangle to cover both. */
216 if (!UnionRect (&(lpmsg->rect), &(lpmsg->rect),
217 &(lpCur->w32msg.rect)))
218 {
219 SetRectEmpty(&(lpmsg->rect));
220 }
221
222 myfree (lpCur);
223
224 nQueue--;
225
226 lpCur = lpNext;
227 }
228 else
229 {
230 lpPrev = lpCur;
231 lpCur = lpNext;
232 }
233 }
234 }
ee78dc32
GV
235
236 bRet = TRUE;
237 }
97aab3a2
GV
238
239 if (nQueue == 0)
240 ResetEvent (input_available);
177c0ea7 241
dd118a07 242 leave_crit ();
177c0ea7 243
ee78dc32
GV
244 return (bRet);
245}
246
177c0ea7 247BOOL
ee78dc32 248post_msg (lpmsg)
fbd6baed 249 W32Msg * lpmsg;
ee78dc32
GV
250{
251 int_msg * lpNew = (int_msg *) myalloc (sizeof (int_msg));
252
97aab3a2
GV
253 if (!lpNew)
254 return (FALSE);
ee78dc32 255
fbd6baed 256 bcopy (lpmsg, &(lpNew->w32msg), sizeof (W32Msg));
ee78dc32
GV
257 lpNew->lpNext = NULL;
258
dd118a07 259 enter_crit ();
ee78dc32
GV
260
261 if (nQueue++)
dd118a07
GV
262 {
263 lpTail->lpNext = lpNew;
264 }
177c0ea7 265 else
dd118a07
GV
266 {
267 lpHead = lpNew;
dd118a07 268 }
ee78dc32
GV
269
270 lpTail = lpNew;
97aab3a2 271 SetEvent (input_available);
177c0ea7 272
dd118a07 273 leave_crit ();
ee78dc32
GV
274
275 return (TRUE);
276}
277
7c69181b 278BOOL
fbd6baed 279prepend_msg (W32Msg *lpmsg)
7c69181b
GV
280{
281 int_msg * lpNew = (int_msg *) myalloc (sizeof (int_msg));
282
283 if (!lpNew)
284 return (FALSE);
285
fbd6baed 286 bcopy (lpmsg, &(lpNew->w32msg), sizeof (W32Msg));
7c69181b
GV
287
288 enter_crit ();
289
290 nQueue++;
291 lpNew->lpNext = lpHead;
292 lpHead = lpNew;
293
294 leave_crit ();
295
296 return (TRUE);
297}
298
716490f0
AI
299/* Process all messages in the current thread's queue. */
300void
301drain_message_queue ()
302{
303 MSG msg;
304 while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
305 {
306 TranslateMessage (&msg);
307 DispatchMessage (&msg);
308 }
309}
310
311
ee78dc32
GV
312/*
313 * XParseGeometry parses strings of the form
314 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
315 * width, height, xoffset, and yoffset are unsigned integers.
316 * Example: "=80x24+300-49"
317 * The equal sign is optional.
318 * It returns a bitmask that indicates which of the four values
319 * were actually found in the string. For each value found,
320 * the corresponding argument is updated; for each value
177c0ea7 321 * not found, the corresponding argument is left unchanged.
ee78dc32
GV
322 */
323
324static int
325read_integer (string, NextString)
326 register char *string;
327 char **NextString;
328{
329 register int Result = 0;
330 int Sign = 1;
177c0ea7 331
ee78dc32
GV
332 if (*string == '+')
333 string++;
334 else if (*string == '-')
335 {
336 string++;
337 Sign = -1;
338 }
339 for (; (*string >= '0') && (*string <= '9'); string++)
340 {
341 Result = (Result * 10) + (*string - '0');
342 }
343 *NextString = string;
344 if (Sign >= 0)
345 return (Result);
346 else
347 return (-Result);
348}
349
177c0ea7 350int
ee78dc32
GV
351XParseGeometry (string, x, y, width, height)
352 char *string;
353 int *x, *y;
354 unsigned int *width, *height; /* RETURN */
355{
356 int mask = NoValue;
357 register char *strind;
358 unsigned int tempWidth, tempHeight;
359 int tempX, tempY;
360 char *nextCharacter;
177c0ea7 361
ee78dc32
GV
362 if ((string == NULL) || (*string == '\0')) return (mask);
363 if (*string == '=')
364 string++; /* ignore possible '=' at beg of geometry spec */
177c0ea7 365
ee78dc32 366 strind = (char *)string;
177c0ea7 367 if (*strind != '+' && *strind != '-' && *strind != 'x')
ee78dc32
GV
368 {
369 tempWidth = read_integer (strind, &nextCharacter);
177c0ea7 370 if (strind == nextCharacter)
ee78dc32
GV
371 return (0);
372 strind = nextCharacter;
373 mask |= WidthValue;
374 }
177c0ea7
JB
375
376 if (*strind == 'x' || *strind == 'X')
377 {
ee78dc32
GV
378 strind++;
379 tempHeight = read_integer (strind, &nextCharacter);
380 if (strind == nextCharacter)
381 return (0);
382 strind = nextCharacter;
383 mask |= HeightValue;
384 }
177c0ea7
JB
385
386 if ((*strind == '+') || (*strind == '-'))
ee78dc32 387 {
177c0ea7 388 if (*strind == '-')
ee78dc32
GV
389 {
390 strind++;
391 tempX = -read_integer (strind, &nextCharacter);
392 if (strind == nextCharacter)
393 return (0);
394 strind = nextCharacter;
395 mask |= XNegative;
396
397 }
398 else
177c0ea7 399 {
ee78dc32
GV
400 strind++;
401 tempX = read_integer (strind, &nextCharacter);
402 if (strind == nextCharacter)
403 return (0);
404 strind = nextCharacter;
405 }
406 mask |= XValue;
177c0ea7 407 if ((*strind == '+') || (*strind == '-'))
ee78dc32 408 {
177c0ea7 409 if (*strind == '-')
ee78dc32
GV
410 {
411 strind++;
412 tempY = -read_integer (strind, &nextCharacter);
413 if (strind == nextCharacter)
414 return (0);
415 strind = nextCharacter;
416 mask |= YNegative;
417
418 }
419 else
420 {
421 strind++;
422 tempY = read_integer (strind, &nextCharacter);
423 if (strind == nextCharacter)
424 return (0);
425 strind = nextCharacter;
426 }
427 mask |= YValue;
428 }
429 }
177c0ea7 430
ee78dc32
GV
431 /* If strind isn't at the end of the string the it's an invalid
432 geometry specification. */
177c0ea7 433
ee78dc32 434 if (*strind != '\0') return (0);
177c0ea7 435
ee78dc32
GV
436 if (mask & XValue)
437 *x = tempX;
438 if (mask & YValue)
439 *y = tempY;
440 if (mask & WidthValue)
441 *width = tempWidth;
442 if (mask & HeightValue)
443 *height = tempHeight;
444 return (mask);
445}
446
fbd6baed 447/* x_sync is a no-op on W32. */
ee78dc32
GV
448void
449x_sync (f)
450 void *f;
451{
452}
ab5796a9
MB
453
454/* arch-tag: 4fab3695-4ad3-4cc6-a2b1-fd2c67dc46be
455 (do not change this comment) */