1 /* Functions taken directly from X sources for use with the Microsoft W32 API.
2 Copyright (C) 1989, 1992-1995, 1999, 2001-2011 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/>. */
28 #include "blockinput.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
;
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
);
61 DeleteCriticalSection (&critsect
);
65 CloseHandle (input_available
);
66 input_available
= NULL
;
70 CloseHandle (interrupt_handle
);
71 interrupt_handle
= NULL
;
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
);
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
)
91 if (display_info
->palette
== 0)
94 if (!NILP (Vw32_enable_palette
))
95 f
->output_data
.w32
->old_palette
=
96 SelectPalette (hdc
, display_info
->palette
, FALSE
);
98 f
->output_data
.w32
->old_palette
= NULL
;
100 if (RealizePalette (hdc
) != GDI_ERROR
)
102 Lisp_Object frame
, framelist
;
103 FOR_EACH_FRAME (framelist
, frame
)
105 SET_FRAME_GARBAGED (XFRAME (frame
));
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
)
124 if (f
->output_method
!= output_w32
)
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. */
134 select_palette (f
, hdc
);
140 release_frame_dc (FRAME_PTR f
, HDC hdc
)
144 deselect_palette (f
, hdc
);
145 ret
= ReleaseDC (f
->output_data
.w32
->window_desc
, hdc
);
152 typedef struct int_msg
155 struct int_msg
*lpNext
;
158 int_msg
*lpHead
= NULL
;
159 int_msg
*lpTail
= NULL
;
163 get_next_msg (W32Msg
* lpmsg
, BOOL bWait
)
169 /* The while loop takes care of multiple sets */
171 while (!nQueue
&& bWait
)
174 WaitForSingleObject (input_available
, INFINITE
);
180 memcpy (lpmsg
, &lpHead
->w32msg
, sizeof (W32Msg
));
183 int_msg
* lpCur
= lpHead
;
185 lpHead
= lpHead
->lpNext
;
191 /* Consolidate WM_PAINT messages to optimise redrawing. */
192 if (lpmsg
->msg
.message
== WM_PAINT
&& nQueue
)
194 int_msg
* lpCur
= lpHead
;
195 int_msg
* lpPrev
= NULL
;
196 int_msg
* lpNext
= NULL
;
198 while (lpCur
&& nQueue
)
200 lpNext
= lpCur
->lpNext
;
201 if (lpCur
->w32msg
.msg
.message
== WM_PAINT
)
203 /* Remove this message from the queue. */
205 lpPrev
->lpNext
= lpNext
;
212 /* Adjust clip rectangle to cover both. */
213 if (!UnionRect (&(lpmsg
->rect
), &(lpmsg
->rect
),
214 &(lpCur
->w32msg
.rect
)))
216 SetRectEmpty (&(lpmsg
->rect
));
237 ResetEvent (input_available
);
245 post_msg (W32Msg
* lpmsg
)
247 int_msg
* lpNew
= (int_msg
*) myalloc (sizeof (int_msg
));
252 memcpy (&lpNew
->w32msg
, lpmsg
, sizeof (W32Msg
));
253 lpNew
->lpNext
= NULL
;
259 lpTail
->lpNext
= lpNew
;
267 SetEvent (input_available
);
275 prepend_msg (W32Msg
*lpmsg
)
277 int_msg
* lpNew
= (int_msg
*) myalloc (sizeof (int_msg
));
282 memcpy (&lpNew
->w32msg
, lpmsg
, sizeof (W32Msg
));
287 lpNew
->lpNext
= lpHead
;
295 /* Process all messages in the current thread's queue. */
297 drain_message_queue (void)
300 while (PeekMessage (&msg
, NULL
, 0, 0, PM_REMOVE
))
302 TranslateMessage (&msg
);
303 DispatchMessage (&msg
);
309 * XParseGeometry parses strings of the form
310 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
311 * width, height, xoffset, and yoffset are unsigned integers.
312 * Example: "=80x24+300-49"
313 * The equal sign is optional.
314 * It returns a bitmask that indicates which of the four values
315 * were actually found in the string. For each value found,
316 * the corresponding argument is updated; for each value
317 * not found, the corresponding argument is left unchanged.
321 read_integer (register char *string
, char **NextString
)
323 register int Result
= 0;
328 else if (*string
== '-')
333 for (; (*string
>= '0') && (*string
<= '9'); string
++)
335 Result
= (Result
* 10) + (*string
- '0');
337 *NextString
= string
;
345 XParseGeometry (char *string
,
347 unsigned int *width
, unsigned int *height
)
350 register char *strind
;
351 unsigned int tempWidth
, tempHeight
;
355 if ((string
== NULL
) || (*string
== '\0')) return (mask
);
357 string
++; /* ignore possible '=' at beg of geometry spec */
359 strind
= (char *)string
;
360 if (*strind
!= '+' && *strind
!= '-' && *strind
!= 'x')
362 tempWidth
= read_integer (strind
, &nextCharacter
);
363 if (strind
== nextCharacter
)
365 strind
= nextCharacter
;
369 if (*strind
== 'x' || *strind
== 'X')
372 tempHeight
= read_integer (strind
, &nextCharacter
);
373 if (strind
== nextCharacter
)
375 strind
= nextCharacter
;
379 if ((*strind
== '+') || (*strind
== '-'))
384 tempX
= -read_integer (strind
, &nextCharacter
);
385 if (strind
== nextCharacter
)
387 strind
= nextCharacter
;
394 tempX
= read_integer (strind
, &nextCharacter
);
395 if (strind
== nextCharacter
)
397 strind
= nextCharacter
;
400 if ((*strind
== '+') || (*strind
== '-'))
405 tempY
= -read_integer (strind
, &nextCharacter
);
406 if (strind
== nextCharacter
)
408 strind
= nextCharacter
;
414 tempY
= read_integer (strind
, &nextCharacter
);
415 if (strind
== nextCharacter
)
417 strind
= nextCharacter
;
423 /* If strind isn't at the end of the string then it's an invalid
424 geometry specification. */
426 if (*strind
!= '\0') return (0);
432 if (mask
& WidthValue
)
434 if (mask
& HeightValue
)
435 *height
= tempHeight
;
439 /* x_sync is a no-op on W32. */