defun/defmacro autoload generation
[bpt/emacs.git] / src / w32xfns.c
CommitLineData
b46a6a83 1/* Functions taken directly from X sources for use with the Microsoft Windows API.
ba318903 2 Copyright (C) 1989, 1992-1995, 1999, 2001-2014 Free Software
ab422c4d 3 Foundation, Inc.
ee78dc32
GV
4
5This file is part of GNU Emacs.
6
9ec0b715 7GNU Emacs is free software: you can redistribute it and/or modify
ee78dc32 8it under the terms of the GNU General Public License as published by
9ec0b715
GM
9the Free Software Foundation, either version 3 of the License, or
10(at your option) any later version.
ee78dc32
GV
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
9ec0b715 18along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
ee78dc32 19
ee78dc32 20#include <config.h>
68c45bf0 21#include <signal.h>
ee78dc32 22#include <stdio.h>
0fda9b75 23
ee78dc32 24#include "lisp.h"
3e4731a3 25#include "keyboard.h"
97aab3a2 26#include "frame.h"
913250cf 27#include "window.h"
bd6bb544
GV
28#include "charset.h"
29#include "fontset.h"
ee78dc32
GV
30#include "blockinput.h"
31#include "w32term.h"
32#include "windowsx.h"
33
34#define myalloc(cb) GlobalAllocPtr (GPTR, cb)
35#define myfree(lp) GlobalFreePtr (lp)
36
dd118a07 37CRITICAL_SECTION critsect;
0fda9b75
DC
38
39#ifdef WINDOWSNT
ee78dc32 40extern HANDLE keyboard_handle;
0fda9b75
DC
41#endif /* WINDOWSNT */
42
97aab3a2 43HANDLE input_available = NULL;
1ce3dc2b 44HANDLE interrupt_handle = NULL;
ee78dc32 45
177c0ea7 46void
b56ceb92 47init_crit (void)
ee78dc32 48{
dd118a07 49 InitializeCriticalSection (&critsect);
ee78dc32 50
97aab3a2
GV
51 /* For safety, input_available should only be reset by get_next_msg
52 when the input queue is empty, so make it a manual reset event. */
0fda9b75
DC
53 input_available = CreateEvent (NULL, TRUE, FALSE, NULL);
54
55#ifdef WINDOWSNT
56 keyboard_handle = input_available;
57#endif /* WINDOWSNT */
1ce3dc2b 58
04bf5b65 59 /* interrupt_handle is signaled when quit (C-g) is detected, so that
1ce3dc2b
RS
60 blocking system calls can be interrupted. We make it a manual
61 reset event, so that if we should ever have multiple threads
62 performing system calls, they will all be interrupted (I'm guessing
63 that would the right response). Note that we use PulseEvent to
04bf5b65 64 signal this event, so that it never remains signaled. */
1ce3dc2b 65 interrupt_handle = CreateEvent (NULL, TRUE, FALSE, NULL);
ee78dc32
GV
66}
67
177c0ea7 68void
b56ceb92 69delete_crit (void)
ee78dc32 70{
97aab3a2
GV
71 DeleteCriticalSection (&critsect);
72
73 if (input_available)
74 {
75 CloseHandle (input_available);
76 input_available = NULL;
77 }
1ce3dc2b
RS
78 if (interrupt_handle)
79 {
80 CloseHandle (interrupt_handle);
81 interrupt_handle = NULL;
82 }
83}
84
85void
b56ceb92 86signal_quit (void)
1ce3dc2b 87{
04bf5b65 88 /* Make sure this event never remains signaled; if the main thread
1ce3dc2b
RS
89 isn't in a blocking call, then this should do nothing. */
90 PulseEvent (interrupt_handle);
d484dc55
GV
91}
92
97aab3a2 93void
a10c8269 94select_palette (struct frame *f, HDC hdc)
d484dc55 95{
aad3612f 96 struct w32_display_info *display_info = FRAME_DISPLAY_INFO (f);
90f4a9f8
AI
97
98 if (!display_info->has_palette)
99 return;
100
101 if (display_info->palette == 0)
a8370d72 102 return;
90f4a9f8 103
fbd6baed
GV
104 if (!NILP (Vw32_enable_palette))
105 f->output_data.w32->old_palette =
90f4a9f8 106 SelectPalette (hdc, display_info->palette, FALSE);
97aab3a2 107 else
fbd6baed 108 f->output_data.w32->old_palette = NULL;
97aab3a2 109
1c2cc4ef 110 if (RealizePalette (hdc) != GDI_ERROR)
97aab3a2
GV
111 {
112 Lisp_Object frame, framelist;
113 FOR_EACH_FRAME (framelist, frame)
dd118a07 114 {
97aab3a2 115 SET_FRAME_GARBAGED (XFRAME (frame));
dd118a07 116 }
97aab3a2
GV
117 }
118}
119
120void
a10c8269 121deselect_palette (struct frame *f, HDC hdc)
97aab3a2 122{
fbd6baed
GV
123 if (f->output_data.w32->old_palette)
124 SelectPalette (hdc, f->output_data.w32->old_palette, FALSE);
97aab3a2
GV
125}
126
127/* Get a DC for frame and select palette for drawing; force an update of
128 all frames if palette's mapping changes. */
129HDC
a10c8269 130get_frame_dc (struct frame *f)
97aab3a2
GV
131{
132 HDC hdc;
133
56c16321 134 if (f->output_method != output_w32)
1088b922 135 emacs_abort ();
56c16321 136
97aab3a2
GV
137 enter_crit ();
138
fbd6baed 139 hdc = GetDC (f->output_data.w32->window_desc);
86d1db20
JR
140
141 /* If this gets called during startup before the frame is valid,
142 there is a chance of corrupting random data or crashing. */
143 if (hdc)
144 select_palette (f, hdc);
97aab3a2
GV
145
146 return hdc;
147}
148
149int
a10c8269 150release_frame_dc (struct frame *f, HDC hdc)
97aab3a2
GV
151{
152 int ret;
153
154 deselect_palette (f, hdc);
fbd6baed 155 ret = ReleaseDC (f->output_data.w32->window_desc, hdc);
97aab3a2
GV
156
157 leave_crit ();
158
159 return ret;
ee78dc32
GV
160}
161
162typedef struct int_msg
163{
fbd6baed 164 W32Msg w32msg;
ee78dc32
GV
165 struct int_msg *lpNext;
166} int_msg;
167
168int_msg *lpHead = NULL;
169int_msg *lpTail = NULL;
170int nQueue = 0;
171
177c0ea7 172BOOL
b56ceb92 173get_next_msg (W32Msg * lpmsg, BOOL bWait)
ee78dc32
GV
174{
175 BOOL bRet = FALSE;
177c0ea7 176
dd118a07 177 enter_crit ();
177c0ea7 178
ee78dc32 179 /* The while loop takes care of multiple sets */
177c0ea7 180
ee78dc32
GV
181 while (!nQueue && bWait)
182 {
dd118a07 183 leave_crit ();
97aab3a2 184 WaitForSingleObject (input_available, INFINITE);
dd118a07 185 enter_crit ();
ee78dc32 186 }
177c0ea7 187
ee78dc32
GV
188 if (nQueue)
189 {
72af86bd 190 memcpy (lpmsg, &lpHead->w32msg, sizeof (W32Msg));
ee78dc32
GV
191
192 {
193 int_msg * lpCur = lpHead;
177c0ea7 194
ee78dc32 195 lpHead = lpHead->lpNext;
177c0ea7 196
ee78dc32
GV
197 myfree (lpCur);
198 }
199
200 nQueue--;
e1dbe924 201 /* Consolidate WM_PAINT messages to optimize redrawing. */
b668cc18
JR
202 if (lpmsg->msg.message == WM_PAINT && nQueue)
203 {
204 int_msg * lpCur = lpHead;
205 int_msg * lpPrev = NULL;
206 int_msg * lpNext = NULL;
207
208 while (lpCur && nQueue)
209 {
210 lpNext = lpCur->lpNext;
211 if (lpCur->w32msg.msg.message == WM_PAINT)
212 {
213 /* Remove this message from the queue. */
214 if (lpPrev)
215 lpPrev->lpNext = lpNext;
216 else
217 lpHead = lpNext;
218
219 if (lpCur == lpTail)
220 lpTail = lpPrev;
221
222 /* Adjust clip rectangle to cover both. */
223 if (!UnionRect (&(lpmsg->rect), &(lpmsg->rect),
224 &(lpCur->w32msg.rect)))
225 {
ed3751c8 226 SetRectEmpty (&(lpmsg->rect));
b668cc18
JR
227 }
228
229 myfree (lpCur);
230
231 nQueue--;
232
233 lpCur = lpNext;
234 }
235 else
236 {
237 lpPrev = lpCur;
238 lpCur = lpNext;
239 }
240 }
241 }
ee78dc32
GV
242
243 bRet = TRUE;
244 }
97aab3a2
GV
245
246 if (nQueue == 0)
247 ResetEvent (input_available);
177c0ea7 248
dd118a07 249 leave_crit ();
177c0ea7 250
ee78dc32
GV
251 return (bRet);
252}
253
0fda9b75
DC
254extern char * w32_strerror (int error_no);
255
256/* Tell the main thread that we have input available; if the main
257 thread is blocked in select(), we wake it up here. */
258static void
259notify_msg_ready (void)
260{
261 SetEvent (input_available);
262
263#ifdef CYGWIN
264 /* Wakes up the main thread, which is blocked select()ing for /dev/windows,
265 among other files. */
266 (void) PostThreadMessage (dwMainThreadId, WM_EMACS_INPUT_READY, 0, 0);
267#endif /* CYGWIN */
268}
269
177c0ea7 270BOOL
b56ceb92 271post_msg (W32Msg * lpmsg)
ee78dc32
GV
272{
273 int_msg * lpNew = (int_msg *) myalloc (sizeof (int_msg));
274
97aab3a2
GV
275 if (!lpNew)
276 return (FALSE);
ee78dc32 277
72af86bd 278 memcpy (&lpNew->w32msg, lpmsg, sizeof (W32Msg));
ee78dc32
GV
279 lpNew->lpNext = NULL;
280
dd118a07 281 enter_crit ();
ee78dc32
GV
282
283 if (nQueue++)
dd118a07
GV
284 {
285 lpTail->lpNext = lpNew;
286 }
177c0ea7 287 else
dd118a07
GV
288 {
289 lpHead = lpNew;
dd118a07 290 }
ee78dc32
GV
291
292 lpTail = lpNew;
0fda9b75 293 notify_msg_ready ();
dd118a07 294 leave_crit ();
ee78dc32
GV
295
296 return (TRUE);
297}
298
7c69181b 299BOOL
fbd6baed 300prepend_msg (W32Msg *lpmsg)
7c69181b
GV
301{
302 int_msg * lpNew = (int_msg *) myalloc (sizeof (int_msg));
303
304 if (!lpNew)
305 return (FALSE);
306
72af86bd 307 memcpy (&lpNew->w32msg, lpmsg, sizeof (W32Msg));
7c69181b
GV
308
309 enter_crit ();
310
311 nQueue++;
312 lpNew->lpNext = lpHead;
313 lpHead = lpNew;
0fda9b75 314 notify_msg_ready ();
7c69181b
GV
315 leave_crit ();
316
317 return (TRUE);
318}
319
977c6479
EZ
320/* Process all messages in the current thread's queue. Value is 1 if
321 one of these messages was WM_EMACS_FILENOTIFY, zero otherwise. */
322int
b56ceb92 323drain_message_queue (void)
716490f0
AI
324{
325 MSG msg;
977c6479
EZ
326 int retval = 0;
327
716490f0
AI
328 while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
329 {
977c6479
EZ
330 if (msg.message == WM_EMACS_FILENOTIFY)
331 retval = 1;
716490f0
AI
332 TranslateMessage (&msg);
333 DispatchMessage (&msg);
334 }
977c6479 335 return retval;
716490f0 336}