* net/dig.el: Add "Keywords: comm", as per net-utils.el. (Bug#4501)
[emacs.git] / src / w32xfns.c
blob5bf39967e85b91a236cbf6452a25a1110ba1e394
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, 2009 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 of the License, or
10 (at your option) 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. If not, see <http://www.gnu.org/licenses/>. */
20 #include <config.h>
21 #include <signal.h>
22 #include <stdio.h>
23 #include "lisp.h"
24 #include "keyboard.h"
25 #include "frame.h"
26 #include "charset.h"
27 #include "fontset.h"
28 #include "blockinput.h"
29 #include "w32term.h"
30 #include "windowsx.h"
32 #define myalloc(cb) GlobalAllocPtr (GPTR, cb)
33 #define myfree(lp) GlobalFreePtr (lp)
35 CRITICAL_SECTION critsect;
36 extern HANDLE keyboard_handle;
37 HANDLE input_available = NULL;
38 HANDLE interrupt_handle = NULL;
40 void
41 init_crit ()
43 InitializeCriticalSection (&critsect);
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);
49 /* interrupt_handle is signaled 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 signaled. */
55 interrupt_handle = CreateEvent (NULL, TRUE, FALSE, NULL);
58 void
59 delete_crit ()
61 DeleteCriticalSection (&critsect);
63 if (input_available)
65 CloseHandle (input_available);
66 input_available = NULL;
68 if (interrupt_handle)
70 CloseHandle (interrupt_handle);
71 interrupt_handle = NULL;
75 void
76 signal_quit ()
78 /* Make sure this event never remains signaled; if the main thread
79 isn't in a blocking call, then this should do nothing. */
80 PulseEvent (interrupt_handle);
83 void
84 select_palette (FRAME_PTR f, HDC hdc)
86 struct w32_display_info *display_info = FRAME_W32_DISPLAY_INFO (f);
88 if (!display_info->has_palette)
89 return;
91 if (display_info->palette == 0)
92 return;
94 if (!NILP (Vw32_enable_palette))
95 f->output_data.w32->old_palette =
96 SelectPalette (hdc, display_info->palette, FALSE);
97 else
98 f->output_data.w32->old_palette = NULL;
100 if (RealizePalette (hdc))
102 Lisp_Object frame, framelist;
103 FOR_EACH_FRAME (framelist, frame)
105 SET_FRAME_GARBAGED (XFRAME (frame));
110 void
111 deselect_palette (FRAME_PTR f, HDC hdc)
113 if (f->output_data.w32->old_palette)
114 SelectPalette (hdc, f->output_data.w32->old_palette, FALSE);
117 /* Get a DC for frame and select palette for drawing; force an update of
118 all frames if palette's mapping changes. */
120 get_frame_dc (FRAME_PTR f)
122 HDC hdc;
124 if (f->output_method != output_w32)
125 abort ();
127 enter_crit ();
129 hdc = GetDC (f->output_data.w32->window_desc);
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);
136 return hdc;
140 release_frame_dc (FRAME_PTR f, HDC hdc)
142 int ret;
144 deselect_palette (f, hdc);
145 ret = ReleaseDC (f->output_data.w32->window_desc, hdc);
147 leave_crit ();
149 return ret;
152 typedef struct int_msg
154 W32Msg w32msg;
155 struct int_msg *lpNext;
156 } int_msg;
158 int_msg *lpHead = NULL;
159 int_msg *lpTail = NULL;
160 int nQueue = 0;
162 BOOL
163 get_next_msg (lpmsg, bWait)
164 W32Msg * lpmsg;
165 BOOL bWait;
167 BOOL bRet = FALSE;
169 enter_crit ();
171 /* The while loop takes care of multiple sets */
173 while (!nQueue && bWait)
175 leave_crit ();
176 WaitForSingleObject (input_available, INFINITE);
177 enter_crit ();
180 if (nQueue)
182 bcopy (&(lpHead->w32msg), lpmsg, sizeof (W32Msg));
185 int_msg * lpCur = lpHead;
187 lpHead = lpHead->lpNext;
189 myfree (lpCur);
192 nQueue--;
193 /* Consolidate WM_PAINT messages to optimise redrawing. */
194 if (lpmsg->msg.message == WM_PAINT && nQueue)
196 int_msg * lpCur = lpHead;
197 int_msg * lpPrev = NULL;
198 int_msg * lpNext = NULL;
200 while (lpCur && nQueue)
202 lpNext = lpCur->lpNext;
203 if (lpCur->w32msg.msg.message == WM_PAINT)
205 /* Remove this message from the queue. */
206 if (lpPrev)
207 lpPrev->lpNext = lpNext;
208 else
209 lpHead = lpNext;
211 if (lpCur == lpTail)
212 lpTail = lpPrev;
214 /* Adjust clip rectangle to cover both. */
215 if (!UnionRect (&(lpmsg->rect), &(lpmsg->rect),
216 &(lpCur->w32msg.rect)))
218 SetRectEmpty(&(lpmsg->rect));
221 myfree (lpCur);
223 nQueue--;
225 lpCur = lpNext;
227 else
229 lpPrev = lpCur;
230 lpCur = lpNext;
235 bRet = TRUE;
238 if (nQueue == 0)
239 ResetEvent (input_available);
241 leave_crit ();
243 return (bRet);
246 BOOL
247 post_msg (lpmsg)
248 W32Msg * lpmsg;
250 int_msg * lpNew = (int_msg *) myalloc (sizeof (int_msg));
252 if (!lpNew)
253 return (FALSE);
255 bcopy (lpmsg, &(lpNew->w32msg), sizeof (W32Msg));
256 lpNew->lpNext = NULL;
258 enter_crit ();
260 if (nQueue++)
262 lpTail->lpNext = lpNew;
264 else
266 lpHead = lpNew;
269 lpTail = lpNew;
270 SetEvent (input_available);
272 leave_crit ();
274 return (TRUE);
277 BOOL
278 prepend_msg (W32Msg *lpmsg)
280 int_msg * lpNew = (int_msg *) myalloc (sizeof (int_msg));
282 if (!lpNew)
283 return (FALSE);
285 bcopy (lpmsg, &(lpNew->w32msg), sizeof (W32Msg));
287 enter_crit ();
289 nQueue++;
290 lpNew->lpNext = lpHead;
291 lpHead = lpNew;
293 leave_crit ();
295 return (TRUE);
298 /* Process all messages in the current thread's queue. */
299 void
300 drain_message_queue ()
302 MSG msg;
303 while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
305 TranslateMessage (&msg);
306 DispatchMessage (&msg);
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
320 * not found, the corresponding argument is left unchanged.
323 static int
324 read_integer (string, NextString)
325 register char *string;
326 char **NextString;
328 register int Result = 0;
329 int Sign = 1;
331 if (*string == '+')
332 string++;
333 else if (*string == '-')
335 string++;
336 Sign = -1;
338 for (; (*string >= '0') && (*string <= '9'); string++)
340 Result = (Result * 10) + (*string - '0');
342 *NextString = string;
343 if (Sign >= 0)
344 return (Result);
345 else
346 return (-Result);
350 XParseGeometry (string, x, y, width, height)
351 char *string;
352 int *x, *y;
353 unsigned int *width, *height; /* RETURN */
355 int mask = NoValue;
356 register char *strind;
357 unsigned int tempWidth, tempHeight;
358 int tempX, tempY;
359 char *nextCharacter;
361 if ((string == NULL) || (*string == '\0')) return (mask);
362 if (*string == '=')
363 string++; /* ignore possible '=' at beg of geometry spec */
365 strind = (char *)string;
366 if (*strind != '+' && *strind != '-' && *strind != 'x')
368 tempWidth = read_integer (strind, &nextCharacter);
369 if (strind == nextCharacter)
370 return (0);
371 strind = nextCharacter;
372 mask |= WidthValue;
375 if (*strind == 'x' || *strind == 'X')
377 strind++;
378 tempHeight = read_integer (strind, &nextCharacter);
379 if (strind == nextCharacter)
380 return (0);
381 strind = nextCharacter;
382 mask |= HeightValue;
385 if ((*strind == '+') || (*strind == '-'))
387 if (*strind == '-')
389 strind++;
390 tempX = -read_integer (strind, &nextCharacter);
391 if (strind == nextCharacter)
392 return (0);
393 strind = nextCharacter;
394 mask |= XNegative;
397 else
399 strind++;
400 tempX = read_integer (strind, &nextCharacter);
401 if (strind == nextCharacter)
402 return (0);
403 strind = nextCharacter;
405 mask |= XValue;
406 if ((*strind == '+') || (*strind == '-'))
408 if (*strind == '-')
410 strind++;
411 tempY = -read_integer (strind, &nextCharacter);
412 if (strind == nextCharacter)
413 return (0);
414 strind = nextCharacter;
415 mask |= YNegative;
418 else
420 strind++;
421 tempY = read_integer (strind, &nextCharacter);
422 if (strind == nextCharacter)
423 return (0);
424 strind = nextCharacter;
426 mask |= YValue;
430 /* If strind isn't at the end of the string the it's an invalid
431 geometry specification. */
433 if (*strind != '\0') return (0);
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);
446 /* x_sync is a no-op on W32. */
447 void
448 x_sync (f)
449 void *f;
453 /* arch-tag: 4fab3695-4ad3-4cc6-a2b1-fd2c67dc46be
454 (do not change this comment) */