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