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