(compose-mail): Run switch-function after setting up the mail buffer.
[emacs.git] / src / w32xfns.c
blobb87cc28f0570b6ff1eca0b0c773b255b06609329
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 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 2, 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--;
196 bRet = TRUE;
199 if (nQueue == 0)
200 ResetEvent (input_available);
202 leave_crit ();
204 return (bRet);
207 BOOL
208 post_msg (lpmsg)
209 W32Msg * lpmsg;
211 int_msg * lpNew = (int_msg *) myalloc (sizeof (int_msg));
213 if (!lpNew)
214 return (FALSE);
216 bcopy (lpmsg, &(lpNew->w32msg), sizeof (W32Msg));
217 lpNew->lpNext = NULL;
219 enter_crit ();
221 if (nQueue++)
223 lpTail->lpNext = lpNew;
225 else
227 lpHead = lpNew;
230 lpTail = lpNew;
231 SetEvent (input_available);
233 leave_crit ();
235 return (TRUE);
238 BOOL
239 prepend_msg (W32Msg *lpmsg)
241 int_msg * lpNew = (int_msg *) myalloc (sizeof (int_msg));
243 if (!lpNew)
244 return (FALSE);
246 bcopy (lpmsg, &(lpNew->w32msg), sizeof (W32Msg));
248 enter_crit ();
250 nQueue++;
251 lpNew->lpNext = lpHead;
252 lpHead = lpNew;
254 leave_crit ();
256 return (TRUE);
259 /* Process all messages in the current thread's queue. */
260 void
261 drain_message_queue ()
263 MSG msg;
264 while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
266 TranslateMessage (&msg);
267 DispatchMessage (&msg);
273 * XParseGeometry parses strings of the form
274 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
275 * width, height, xoffset, and yoffset are unsigned integers.
276 * Example: "=80x24+300-49"
277 * The equal sign is optional.
278 * It returns a bitmask that indicates which of the four values
279 * were actually found in the string. For each value found,
280 * the corresponding argument is updated; for each value
281 * not found, the corresponding argument is left unchanged.
284 static int
285 read_integer (string, NextString)
286 register char *string;
287 char **NextString;
289 register int Result = 0;
290 int Sign = 1;
292 if (*string == '+')
293 string++;
294 else if (*string == '-')
296 string++;
297 Sign = -1;
299 for (; (*string >= '0') && (*string <= '9'); string++)
301 Result = (Result * 10) + (*string - '0');
303 *NextString = string;
304 if (Sign >= 0)
305 return (Result);
306 else
307 return (-Result);
311 XParseGeometry (string, x, y, width, height)
312 char *string;
313 int *x, *y;
314 unsigned int *width, *height; /* RETURN */
316 int mask = NoValue;
317 register char *strind;
318 unsigned int tempWidth, tempHeight;
319 int tempX, tempY;
320 char *nextCharacter;
322 if ((string == NULL) || (*string == '\0')) return (mask);
323 if (*string == '=')
324 string++; /* ignore possible '=' at beg of geometry spec */
326 strind = (char *)string;
327 if (*strind != '+' && *strind != '-' && *strind != 'x')
329 tempWidth = read_integer (strind, &nextCharacter);
330 if (strind == nextCharacter)
331 return (0);
332 strind = nextCharacter;
333 mask |= WidthValue;
336 if (*strind == 'x' || *strind == 'X')
338 strind++;
339 tempHeight = read_integer (strind, &nextCharacter);
340 if (strind == nextCharacter)
341 return (0);
342 strind = nextCharacter;
343 mask |= HeightValue;
346 if ((*strind == '+') || (*strind == '-'))
348 if (*strind == '-')
350 strind++;
351 tempX = -read_integer (strind, &nextCharacter);
352 if (strind == nextCharacter)
353 return (0);
354 strind = nextCharacter;
355 mask |= XNegative;
358 else
360 strind++;
361 tempX = read_integer (strind, &nextCharacter);
362 if (strind == nextCharacter)
363 return (0);
364 strind = nextCharacter;
366 mask |= XValue;
367 if ((*strind == '+') || (*strind == '-'))
369 if (*strind == '-')
371 strind++;
372 tempY = -read_integer (strind, &nextCharacter);
373 if (strind == nextCharacter)
374 return (0);
375 strind = nextCharacter;
376 mask |= YNegative;
379 else
381 strind++;
382 tempY = read_integer (strind, &nextCharacter);
383 if (strind == nextCharacter)
384 return (0);
385 strind = nextCharacter;
387 mask |= YValue;
391 /* If strind isn't at the end of the string the it's an invalid
392 geometry specification. */
394 if (*strind != '\0') return (0);
396 if (mask & XValue)
397 *x = tempX;
398 if (mask & YValue)
399 *y = tempY;
400 if (mask & WidthValue)
401 *width = tempWidth;
402 if (mask & HeightValue)
403 *height = tempHeight;
404 return (mask);
407 /* x_sync is a no-op on W32. */
408 void
409 x_sync (f)
410 void *f;
414 /* arch-tag: 4fab3695-4ad3-4cc6-a2b1-fd2c67dc46be
415 (do not change this comment) */