Tom Tromey <tromey at redhat.com>
[emacs.git] / src / w32xfns.c
blob7f50ab5ba62def81e512f1d4bc23b2997f78dc58
1 /* Functions taken directly from X sources for use with the Microsoft W32 API.
2 Copyright (C) 1989, 1992, 1993, 1994, 1995, 1999, 2001, 2002, 2003,
3 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA. */
22 #include <config.h>
23 #include <signal.h>
24 #include <stdio.h>
25 #include "lisp.h"
26 #include "keyboard.h"
27 #include "frame.h"
28 #include "charset.h"
29 #include "fontset.h"
30 #include "blockinput.h"
31 #include "w32term.h"
32 #include "windowsx.h"
34 #define myalloc(cb) GlobalAllocPtr (GPTR, cb)
35 #define myfree(lp) GlobalFreePtr (lp)
37 CRITICAL_SECTION critsect;
38 extern HANDLE keyboard_handle;
39 HANDLE input_available = NULL;
40 HANDLE interrupt_handle = NULL;
42 void
43 init_crit ()
45 InitializeCriticalSection (&critsect);
47 /* For safety, input_available should only be reset by get_next_msg
48 when the input queue is empty, so make it a manual reset event. */
49 keyboard_handle = input_available = CreateEvent (NULL, TRUE, FALSE, NULL);
51 /* interrupt_handle is signalled when quit (C-g) is detected, so that
52 blocking system calls can be interrupted. We make it a manual
53 reset event, so that if we should ever have multiple threads
54 performing system calls, they will all be interrupted (I'm guessing
55 that would the right response). Note that we use PulseEvent to
56 signal this event, so that it never remains signalled. */
57 interrupt_handle = CreateEvent (NULL, TRUE, FALSE, NULL);
60 void
61 delete_crit ()
63 DeleteCriticalSection (&critsect);
65 if (input_available)
67 CloseHandle (input_available);
68 input_available = NULL;
70 if (interrupt_handle)
72 CloseHandle (interrupt_handle);
73 interrupt_handle = NULL;
77 void
78 signal_quit ()
80 /* Make sure this event never remains signalled; if the main thread
81 isn't in a blocking call, then this should do nothing. */
82 PulseEvent (interrupt_handle);
85 void
86 select_palette (FRAME_PTR f, HDC hdc)
88 struct w32_display_info *display_info = FRAME_W32_DISPLAY_INFO (f);
90 if (!display_info->has_palette)
91 return;
93 if (display_info->palette == 0)
94 return;
96 if (!NILP (Vw32_enable_palette))
97 f->output_data.w32->old_palette =
98 SelectPalette (hdc, display_info->palette, FALSE);
99 else
100 f->output_data.w32->old_palette = NULL;
102 if (RealizePalette (hdc))
104 Lisp_Object frame, framelist;
105 FOR_EACH_FRAME (framelist, frame)
107 SET_FRAME_GARBAGED (XFRAME (frame));
112 void
113 deselect_palette (FRAME_PTR f, HDC hdc)
115 if (f->output_data.w32->old_palette)
116 SelectPalette (hdc, f->output_data.w32->old_palette, FALSE);
119 /* Get a DC for frame and select palette for drawing; force an update of
120 all frames if palette's mapping changes. */
122 get_frame_dc (FRAME_PTR f)
124 HDC hdc;
126 if (f->output_method != output_w32)
127 abort ();
129 enter_crit ();
131 hdc = GetDC (f->output_data.w32->window_desc);
133 /* If this gets called during startup before the frame is valid,
134 there is a chance of corrupting random data or crashing. */
135 if (hdc)
136 select_palette (f, hdc);
138 return hdc;
142 release_frame_dc (FRAME_PTR f, HDC hdc)
144 int ret;
146 deselect_palette (f, hdc);
147 ret = ReleaseDC (f->output_data.w32->window_desc, hdc);
149 leave_crit ();
151 return ret;
154 typedef struct int_msg
156 W32Msg w32msg;
157 struct int_msg *lpNext;
158 } int_msg;
160 int_msg *lpHead = NULL;
161 int_msg *lpTail = NULL;
162 int nQueue = 0;
164 BOOL
165 get_next_msg (lpmsg, bWait)
166 W32Msg * lpmsg;
167 BOOL bWait;
169 BOOL bRet = FALSE;
171 enter_crit ();
173 /* The while loop takes care of multiple sets */
175 while (!nQueue && bWait)
177 leave_crit ();
178 WaitForSingleObject (input_available, INFINITE);
179 enter_crit ();
182 if (nQueue)
184 bcopy (&(lpHead->w32msg), lpmsg, sizeof (W32Msg));
187 int_msg * lpCur = lpHead;
189 lpHead = lpHead->lpNext;
191 myfree (lpCur);
194 nQueue--;
195 /* Consolidate WM_PAINT messages to optimise redrawing. */
196 if (lpmsg->msg.message == WM_PAINT && nQueue)
198 int_msg * lpCur = lpHead;
199 int_msg * lpPrev = NULL;
200 int_msg * lpNext = NULL;
202 while (lpCur && nQueue)
204 lpNext = lpCur->lpNext;
205 if (lpCur->w32msg.msg.message == WM_PAINT)
207 /* Remove this message from the queue. */
208 if (lpPrev)
209 lpPrev->lpNext = lpNext;
210 else
211 lpHead = lpNext;
213 if (lpCur == lpTail)
214 lpTail = lpPrev;
216 /* Adjust clip rectangle to cover both. */
217 if (!UnionRect (&(lpmsg->rect), &(lpmsg->rect),
218 &(lpCur->w32msg.rect)))
220 SetRectEmpty(&(lpmsg->rect));
223 myfree (lpCur);
225 nQueue--;
227 lpCur = lpNext;
229 else
231 lpPrev = lpCur;
232 lpCur = lpNext;
237 bRet = TRUE;
240 if (nQueue == 0)
241 ResetEvent (input_available);
243 leave_crit ();
245 return (bRet);
248 BOOL
249 post_msg (lpmsg)
250 W32Msg * lpmsg;
252 int_msg * lpNew = (int_msg *) myalloc (sizeof (int_msg));
254 if (!lpNew)
255 return (FALSE);
257 bcopy (lpmsg, &(lpNew->w32msg), sizeof (W32Msg));
258 lpNew->lpNext = NULL;
260 enter_crit ();
262 if (nQueue++)
264 lpTail->lpNext = lpNew;
266 else
268 lpHead = lpNew;
271 lpTail = lpNew;
272 SetEvent (input_available);
274 leave_crit ();
276 return (TRUE);
279 BOOL
280 prepend_msg (W32Msg *lpmsg)
282 int_msg * lpNew = (int_msg *) myalloc (sizeof (int_msg));
284 if (!lpNew)
285 return (FALSE);
287 bcopy (lpmsg, &(lpNew->w32msg), sizeof (W32Msg));
289 enter_crit ();
291 nQueue++;
292 lpNew->lpNext = lpHead;
293 lpHead = lpNew;
295 leave_crit ();
297 return (TRUE);
300 /* Process all messages in the current thread's queue. */
301 void
302 drain_message_queue ()
304 MSG msg;
305 while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
307 TranslateMessage (&msg);
308 DispatchMessage (&msg);
314 * XParseGeometry parses strings of the form
315 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
316 * width, height, xoffset, and yoffset are unsigned integers.
317 * Example: "=80x24+300-49"
318 * The equal sign is optional.
319 * It returns a bitmask that indicates which of the four values
320 * were actually found in the string. For each value found,
321 * the corresponding argument is updated; for each value
322 * not found, the corresponding argument is left unchanged.
325 static int
326 read_integer (string, NextString)
327 register char *string;
328 char **NextString;
330 register int Result = 0;
331 int Sign = 1;
333 if (*string == '+')
334 string++;
335 else if (*string == '-')
337 string++;
338 Sign = -1;
340 for (; (*string >= '0') && (*string <= '9'); string++)
342 Result = (Result * 10) + (*string - '0');
344 *NextString = string;
345 if (Sign >= 0)
346 return (Result);
347 else
348 return (-Result);
352 XParseGeometry (string, x, y, width, height)
353 char *string;
354 int *x, *y;
355 unsigned int *width, *height; /* RETURN */
357 int mask = NoValue;
358 register char *strind;
359 unsigned int tempWidth, tempHeight;
360 int tempX, tempY;
361 char *nextCharacter;
363 if ((string == NULL) || (*string == '\0')) return (mask);
364 if (*string == '=')
365 string++; /* ignore possible '=' at beg of geometry spec */
367 strind = (char *)string;
368 if (*strind != '+' && *strind != '-' && *strind != 'x')
370 tempWidth = read_integer (strind, &nextCharacter);
371 if (strind == nextCharacter)
372 return (0);
373 strind = nextCharacter;
374 mask |= WidthValue;
377 if (*strind == 'x' || *strind == 'X')
379 strind++;
380 tempHeight = read_integer (strind, &nextCharacter);
381 if (strind == nextCharacter)
382 return (0);
383 strind = nextCharacter;
384 mask |= HeightValue;
387 if ((*strind == '+') || (*strind == '-'))
389 if (*strind == '-')
391 strind++;
392 tempX = -read_integer (strind, &nextCharacter);
393 if (strind == nextCharacter)
394 return (0);
395 strind = nextCharacter;
396 mask |= XNegative;
399 else
401 strind++;
402 tempX = read_integer (strind, &nextCharacter);
403 if (strind == nextCharacter)
404 return (0);
405 strind = nextCharacter;
407 mask |= XValue;
408 if ((*strind == '+') || (*strind == '-'))
410 if (*strind == '-')
412 strind++;
413 tempY = -read_integer (strind, &nextCharacter);
414 if (strind == nextCharacter)
415 return (0);
416 strind = nextCharacter;
417 mask |= YNegative;
420 else
422 strind++;
423 tempY = read_integer (strind, &nextCharacter);
424 if (strind == nextCharacter)
425 return (0);
426 strind = nextCharacter;
428 mask |= YValue;
432 /* If strind isn't at the end of the string the it's an invalid
433 geometry specification. */
435 if (*strind != '\0') return (0);
437 if (mask & XValue)
438 *x = tempX;
439 if (mask & YValue)
440 *y = tempY;
441 if (mask & WidthValue)
442 *width = tempWidth;
443 if (mask & HeightValue)
444 *height = tempHeight;
445 return (mask);
448 /* x_sync is a no-op on W32. */
449 void
450 x_sync (f)
451 void *f;
455 /* arch-tag: 4fab3695-4ad3-4cc6-a2b1-fd2c67dc46be
456 (do not change this comment) */