Alter last change to be compatible with Emacs 23.
[emacs.git] / src / w32xfns.c
blob33f40fc7c019af0acca18e009d7620b04b5c3fb2
1 /* Functions taken directly from X sources for use with the Microsoft Windows API.
2 Copyright (C) 1989, 1992-1995, 1999, 2001-2012 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
19 #include <config.h>
20 #include <signal.h>
21 #include <stdio.h>
22 #include "lisp.h"
23 #include "keyboard.h"
24 #include "frame.h"
25 #include "charset.h"
26 #include "fontset.h"
27 #include "blockinput.h"
28 #include "w32term.h"
29 #include "windowsx.h"
31 #define myalloc(cb) GlobalAllocPtr (GPTR, cb)
32 #define myfree(lp) GlobalFreePtr (lp)
34 CRITICAL_SECTION critsect;
35 extern HANDLE keyboard_handle;
36 HANDLE input_available = NULL;
37 HANDLE interrupt_handle = NULL;
39 void
40 init_crit (void)
42 InitializeCriticalSection (&critsect);
44 /* For safety, input_available should only be reset by get_next_msg
45 when the input queue is empty, so make it a manual reset event. */
46 keyboard_handle = input_available = CreateEvent (NULL, TRUE, FALSE, NULL);
48 /* interrupt_handle is signaled when quit (C-g) is detected, so that
49 blocking system calls can be interrupted. We make it a manual
50 reset event, so that if we should ever have multiple threads
51 performing system calls, they will all be interrupted (I'm guessing
52 that would the right response). Note that we use PulseEvent to
53 signal this event, so that it never remains signaled. */
54 interrupt_handle = CreateEvent (NULL, TRUE, FALSE, NULL);
57 void
58 delete_crit (void)
60 DeleteCriticalSection (&critsect);
62 if (input_available)
64 CloseHandle (input_available);
65 input_available = NULL;
67 if (interrupt_handle)
69 CloseHandle (interrupt_handle);
70 interrupt_handle = NULL;
74 void
75 signal_quit (void)
77 /* Make sure this event never remains signaled; if the main thread
78 isn't in a blocking call, then this should do nothing. */
79 PulseEvent (interrupt_handle);
82 void
83 select_palette (FRAME_PTR f, HDC hdc)
85 struct w32_display_info *display_info = FRAME_W32_DISPLAY_INFO (f);
87 if (!display_info->has_palette)
88 return;
90 if (display_info->palette == 0)
91 return;
93 if (!NILP (Vw32_enable_palette))
94 f->output_data.w32->old_palette =
95 SelectPalette (hdc, display_info->palette, FALSE);
96 else
97 f->output_data.w32->old_palette = NULL;
99 if (RealizePalette (hdc) != GDI_ERROR)
101 Lisp_Object frame, framelist;
102 FOR_EACH_FRAME (framelist, frame)
104 SET_FRAME_GARBAGED (XFRAME (frame));
109 void
110 deselect_palette (FRAME_PTR f, HDC hdc)
112 if (f->output_data.w32->old_palette)
113 SelectPalette (hdc, f->output_data.w32->old_palette, FALSE);
116 /* Get a DC for frame and select palette for drawing; force an update of
117 all frames if palette's mapping changes. */
119 get_frame_dc (FRAME_PTR f)
121 HDC hdc;
123 if (f->output_method != output_w32)
124 emacs_abort ();
126 enter_crit ();
128 hdc = GetDC (f->output_data.w32->window_desc);
130 /* If this gets called during startup before the frame is valid,
131 there is a chance of corrupting random data or crashing. */
132 if (hdc)
133 select_palette (f, hdc);
135 return hdc;
139 release_frame_dc (FRAME_PTR f, HDC hdc)
141 int ret;
143 deselect_palette (f, hdc);
144 ret = ReleaseDC (f->output_data.w32->window_desc, hdc);
146 leave_crit ();
148 return ret;
151 typedef struct int_msg
153 W32Msg w32msg;
154 struct int_msg *lpNext;
155 } int_msg;
157 int_msg *lpHead = NULL;
158 int_msg *lpTail = NULL;
159 int nQueue = 0;
161 BOOL
162 get_next_msg (W32Msg * lpmsg, BOOL bWait)
164 BOOL bRet = FALSE;
166 enter_crit ();
168 /* The while loop takes care of multiple sets */
170 while (!nQueue && bWait)
172 leave_crit ();
173 WaitForSingleObject (input_available, INFINITE);
174 enter_crit ();
177 if (nQueue)
179 memcpy (lpmsg, &lpHead->w32msg, sizeof (W32Msg));
182 int_msg * lpCur = lpHead;
184 lpHead = lpHead->lpNext;
186 myfree (lpCur);
189 nQueue--;
190 /* Consolidate WM_PAINT messages to optimize redrawing. */
191 if (lpmsg->msg.message == WM_PAINT && nQueue)
193 int_msg * lpCur = lpHead;
194 int_msg * lpPrev = NULL;
195 int_msg * lpNext = NULL;
197 while (lpCur && nQueue)
199 lpNext = lpCur->lpNext;
200 if (lpCur->w32msg.msg.message == WM_PAINT)
202 /* Remove this message from the queue. */
203 if (lpPrev)
204 lpPrev->lpNext = lpNext;
205 else
206 lpHead = lpNext;
208 if (lpCur == lpTail)
209 lpTail = lpPrev;
211 /* Adjust clip rectangle to cover both. */
212 if (!UnionRect (&(lpmsg->rect), &(lpmsg->rect),
213 &(lpCur->w32msg.rect)))
215 SetRectEmpty (&(lpmsg->rect));
218 myfree (lpCur);
220 nQueue--;
222 lpCur = lpNext;
224 else
226 lpPrev = lpCur;
227 lpCur = lpNext;
232 bRet = TRUE;
235 if (nQueue == 0)
236 ResetEvent (input_available);
238 leave_crit ();
240 return (bRet);
243 BOOL
244 post_msg (W32Msg * lpmsg)
246 int_msg * lpNew = (int_msg *) myalloc (sizeof (int_msg));
248 if (!lpNew)
249 return (FALSE);
251 memcpy (&lpNew->w32msg, lpmsg, sizeof (W32Msg));
252 lpNew->lpNext = NULL;
254 enter_crit ();
256 if (nQueue++)
258 lpTail->lpNext = lpNew;
260 else
262 lpHead = lpNew;
265 lpTail = lpNew;
266 SetEvent (input_available);
268 leave_crit ();
270 return (TRUE);
273 BOOL
274 prepend_msg (W32Msg *lpmsg)
276 int_msg * lpNew = (int_msg *) myalloc (sizeof (int_msg));
278 if (!lpNew)
279 return (FALSE);
281 memcpy (&lpNew->w32msg, lpmsg, sizeof (W32Msg));
283 enter_crit ();
285 nQueue++;
286 lpNew->lpNext = lpHead;
287 lpHead = lpNew;
289 leave_crit ();
291 return (TRUE);
294 /* Process all messages in the current thread's queue. */
295 void
296 drain_message_queue (void)
298 MSG msg;
299 while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
301 TranslateMessage (&msg);
302 DispatchMessage (&msg);
308 * XParseGeometry parses strings of the form
309 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
310 * width, height, xoffset, and yoffset are unsigned integers.
311 * Example: "=80x24+300-49"
312 * The equal sign is optional.
313 * It returns a bitmask that indicates which of the four values
314 * were actually found in the string. For each value found,
315 * the corresponding argument is updated; for each value
316 * not found, the corresponding argument is left unchanged.
319 static int
320 read_integer (register char *string, char **NextString)
322 register int Result = 0;
323 int Sign = 1;
325 if (*string == '+')
326 string++;
327 else if (*string == '-')
329 string++;
330 Sign = -1;
332 for (; (*string >= '0') && (*string <= '9'); string++)
334 Result = (Result * 10) + (*string - '0');
336 *NextString = string;
337 if (Sign >= 0)
338 return (Result);
339 else
340 return (-Result);
344 XParseGeometry (char *string,
345 int *x, int *y,
346 unsigned int *width, unsigned int *height)
348 int mask = NoValue;
349 register char *strind;
350 unsigned int tempWidth, tempHeight;
351 int tempX, tempY;
352 char *nextCharacter;
354 if ((string == NULL) || (*string == '\0')) return (mask);
355 if (*string == '=')
356 string++; /* ignore possible '=' at beg of geometry spec */
358 strind = (char *)string;
359 if (*strind != '+' && *strind != '-' && *strind != 'x')
361 tempWidth = read_integer (strind, &nextCharacter);
362 if (strind == nextCharacter)
363 return (0);
364 strind = nextCharacter;
365 mask |= WidthValue;
368 if (*strind == 'x' || *strind == 'X')
370 strind++;
371 tempHeight = read_integer (strind, &nextCharacter);
372 if (strind == nextCharacter)
373 return (0);
374 strind = nextCharacter;
375 mask |= HeightValue;
378 if ((*strind == '+') || (*strind == '-'))
380 if (*strind == '-')
382 strind++;
383 tempX = -read_integer (strind, &nextCharacter);
384 if (strind == nextCharacter)
385 return (0);
386 strind = nextCharacter;
387 mask |= XNegative;
390 else
392 strind++;
393 tempX = read_integer (strind, &nextCharacter);
394 if (strind == nextCharacter)
395 return (0);
396 strind = nextCharacter;
398 mask |= XValue;
399 if ((*strind == '+') || (*strind == '-'))
401 if (*strind == '-')
403 strind++;
404 tempY = -read_integer (strind, &nextCharacter);
405 if (strind == nextCharacter)
406 return (0);
407 strind = nextCharacter;
408 mask |= YNegative;
410 else
412 strind++;
413 tempY = read_integer (strind, &nextCharacter);
414 if (strind == nextCharacter)
415 return (0);
416 strind = nextCharacter;
418 mask |= YValue;
422 /* If strind isn't at the end of the string then it's an invalid
423 geometry specification. */
425 if (*strind != '\0') return (0);
427 if (mask & XValue)
428 *x = tempX;
429 if (mask & YValue)
430 *y = tempY;
431 if (mask & WidthValue)
432 *width = tempWidth;
433 if (mask & HeightValue)
434 *height = tempHeight;
435 return (mask);
438 /* x_sync is a no-op on W32. */
439 void
440 x_sync (struct frame *f)