Replace bcopy, bzero, bcmp by memcpy, memmove, memset, memcmp
[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
b56ceb92 42init_crit (void)
ee78dc32 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
b56ceb92 60delete_crit (void)
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
b56ceb92 77signal_quit (void)
1ce3dc2b 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
b56ceb92 164get_next_msg (W32Msg * lpmsg, BOOL bWait)
ee78dc32
GV
165{
166 BOOL bRet = FALSE;
177c0ea7 167
dd118a07 168 enter_crit ();
177c0ea7 169
ee78dc32 170 /* The while loop takes care of multiple sets */
177c0ea7 171
ee78dc32
GV
172 while (!nQueue && bWait)
173 {
dd118a07 174 leave_crit ();
97aab3a2 175 WaitForSingleObject (input_available, INFINITE);
dd118a07 176 enter_crit ();
ee78dc32 177 }
177c0ea7 178
ee78dc32
GV
179 if (nQueue)
180 {
72af86bd 181 memcpy (lpmsg, &lpHead->w32msg, sizeof (W32Msg));
ee78dc32
GV
182
183 {
184 int_msg * lpCur = lpHead;
177c0ea7 185
ee78dc32 186 lpHead = lpHead->lpNext;
177c0ea7 187
ee78dc32
GV
188 myfree (lpCur);
189 }
190
191 nQueue--;
b668cc18
JR
192 /* Consolidate WM_PAINT messages to optimise redrawing. */
193 if (lpmsg->msg.message == WM_PAINT && nQueue)
194 {
195 int_msg * lpCur = lpHead;
196 int_msg * lpPrev = NULL;
197 int_msg * lpNext = NULL;
198
199 while (lpCur && nQueue)
200 {
201 lpNext = lpCur->lpNext;
202 if (lpCur->w32msg.msg.message == WM_PAINT)
203 {
204 /* Remove this message from the queue. */
205 if (lpPrev)
206 lpPrev->lpNext = lpNext;
207 else
208 lpHead = lpNext;
209
210 if (lpCur == lpTail)
211 lpTail = lpPrev;
212
213 /* Adjust clip rectangle to cover both. */
214 if (!UnionRect (&(lpmsg->rect), &(lpmsg->rect),
215 &(lpCur->w32msg.rect)))
216 {
ed3751c8 217 SetRectEmpty (&(lpmsg->rect));
b668cc18
JR
218 }
219
220 myfree (lpCur);
221
222 nQueue--;
223
224 lpCur = lpNext;
225 }
226 else
227 {
228 lpPrev = lpCur;
229 lpCur = lpNext;
230 }
231 }
232 }
ee78dc32
GV
233
234 bRet = TRUE;
235 }
97aab3a2
GV
236
237 if (nQueue == 0)
238 ResetEvent (input_available);
177c0ea7 239
dd118a07 240 leave_crit ();
177c0ea7 241
ee78dc32
GV
242 return (bRet);
243}
244
177c0ea7 245BOOL
b56ceb92 246post_msg (W32Msg * lpmsg)
ee78dc32
GV
247{
248 int_msg * lpNew = (int_msg *) myalloc (sizeof (int_msg));
249
97aab3a2
GV
250 if (!lpNew)
251 return (FALSE);
ee78dc32 252
72af86bd 253 memcpy (&lpNew->w32msg, lpmsg, sizeof (W32Msg));
ee78dc32
GV
254 lpNew->lpNext = NULL;
255
dd118a07 256 enter_crit ();
ee78dc32
GV
257
258 if (nQueue++)
dd118a07
GV
259 {
260 lpTail->lpNext = lpNew;
261 }
177c0ea7 262 else
dd118a07
GV
263 {
264 lpHead = lpNew;
dd118a07 265 }
ee78dc32
GV
266
267 lpTail = lpNew;
97aab3a2 268 SetEvent (input_available);
177c0ea7 269
dd118a07 270 leave_crit ();
ee78dc32
GV
271
272 return (TRUE);
273}
274
7c69181b 275BOOL
fbd6baed 276prepend_msg (W32Msg *lpmsg)
7c69181b
GV
277{
278 int_msg * lpNew = (int_msg *) myalloc (sizeof (int_msg));
279
280 if (!lpNew)
281 return (FALSE);
282
72af86bd 283 memcpy (&lpNew->w32msg, lpmsg, sizeof (W32Msg));
7c69181b
GV
284
285 enter_crit ();
286
287 nQueue++;
288 lpNew->lpNext = lpHead;
289 lpHead = lpNew;
290
291 leave_crit ();
292
293 return (TRUE);
294}
295
716490f0
AI
296/* Process all messages in the current thread's queue. */
297void
b56ceb92 298drain_message_queue (void)
716490f0
AI
299{
300 MSG msg;
301 while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
302 {
303 TranslateMessage (&msg);
304 DispatchMessage (&msg);
305 }
306}
307
308
ee78dc32
GV
309/*
310 * XParseGeometry parses strings of the form
311 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
312 * width, height, xoffset, and yoffset are unsigned integers.
313 * Example: "=80x24+300-49"
314 * The equal sign is optional.
315 * It returns a bitmask that indicates which of the four values
316 * were actually found in the string. For each value found,
317 * the corresponding argument is updated; for each value
177c0ea7 318 * not found, the corresponding argument is left unchanged.
ee78dc32
GV
319 */
320
321static int
b56ceb92 322read_integer (register char *string, char **NextString)
ee78dc32
GV
323{
324 register int Result = 0;
325 int Sign = 1;
177c0ea7 326
ee78dc32
GV
327 if (*string == '+')
328 string++;
329 else if (*string == '-')
330 {
331 string++;
332 Sign = -1;
333 }
334 for (; (*string >= '0') && (*string <= '9'); string++)
335 {
336 Result = (Result * 10) + (*string - '0');
337 }
338 *NextString = string;
339 if (Sign >= 0)
340 return (Result);
341 else
342 return (-Result);
343}
344
177c0ea7 345int
b56ceb92
JB
346XParseGeometry (char *string,
347 int *x, int *y,
348 unsigned int *width, unsigned int *height)
ee78dc32
GV
349{
350 int mask = NoValue;
351 register char *strind;
352 unsigned int tempWidth, tempHeight;
353 int tempX, tempY;
354 char *nextCharacter;
177c0ea7 355
ee78dc32
GV
356 if ((string == NULL) || (*string == '\0')) return (mask);
357 if (*string == '=')
358 string++; /* ignore possible '=' at beg of geometry spec */
177c0ea7 359
ee78dc32 360 strind = (char *)string;
177c0ea7 361 if (*strind != '+' && *strind != '-' && *strind != 'x')
ee78dc32
GV
362 {
363 tempWidth = read_integer (strind, &nextCharacter);
177c0ea7 364 if (strind == nextCharacter)
ee78dc32
GV
365 return (0);
366 strind = nextCharacter;
367 mask |= WidthValue;
368 }
177c0ea7
JB
369
370 if (*strind == 'x' || *strind == 'X')
371 {
ee78dc32
GV
372 strind++;
373 tempHeight = read_integer (strind, &nextCharacter);
374 if (strind == nextCharacter)
375 return (0);
376 strind = nextCharacter;
377 mask |= HeightValue;
378 }
177c0ea7
JB
379
380 if ((*strind == '+') || (*strind == '-'))
ee78dc32 381 {
177c0ea7 382 if (*strind == '-')
ee78dc32
GV
383 {
384 strind++;
385 tempX = -read_integer (strind, &nextCharacter);
386 if (strind == nextCharacter)
387 return (0);
388 strind = nextCharacter;
389 mask |= XNegative;
390
391 }
392 else
177c0ea7 393 {
ee78dc32
GV
394 strind++;
395 tempX = read_integer (strind, &nextCharacter);
396 if (strind == nextCharacter)
397 return (0);
398 strind = nextCharacter;
399 }
400 mask |= XValue;
177c0ea7 401 if ((*strind == '+') || (*strind == '-'))
ee78dc32 402 {
177c0ea7 403 if (*strind == '-')
ee78dc32
GV
404 {
405 strind++;
406 tempY = -read_integer (strind, &nextCharacter);
407 if (strind == nextCharacter)
408 return (0);
409 strind = nextCharacter;
410 mask |= YNegative;
411
412 }
413 else
414 {
415 strind++;
416 tempY = read_integer (strind, &nextCharacter);
417 if (strind == nextCharacter)
418 return (0);
419 strind = nextCharacter;
420 }
421 mask |= YValue;
422 }
423 }
177c0ea7 424
ee78dc32
GV
425 /* If strind isn't at the end of the string the it's an invalid
426 geometry specification. */
177c0ea7 427
ee78dc32 428 if (*strind != '\0') return (0);
177c0ea7 429
ee78dc32
GV
430 if (mask & XValue)
431 *x = tempX;
432 if (mask & YValue)
433 *y = tempY;
434 if (mask & WidthValue)
435 *width = tempWidth;
436 if (mask & HeightValue)
437 *height = tempHeight;
438 return (mask);
439}
440
fbd6baed 441/* x_sync is a no-op on W32. */
ee78dc32 442void
b56ceb92 443x_sync (void *f)
ee78dc32
GV
444{
445}
ab5796a9
MB
446
447/* arch-tag: 4fab3695-4ad3-4cc6-a2b1-fd2c67dc46be
448 (do not change this comment) */