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