(w32font_draw): Do clipping here.
[bpt/emacs.git] / src / w32xfns.c
CommitLineData
e9e23e23 1/* Functions taken directly from X sources for use with the Microsoft W32 API.
429ab54e
GM
2 Copyright (C) 1989, 1992, 1993, 1994, 1995, 1999, 2001, 2002, 2003,
3 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
ee78dc32
GV
4
5This file is part of GNU Emacs.
6
7GNU Emacs is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
684d6f5b 9the Free Software Foundation; either version 3, or (at your option)
ee78dc32
GV
10any later version.
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
18along with GNU Emacs; see the file COPYING. If not, write to
4fc5845f
LK
19the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20Boston, MA 02110-1301, USA. */
ee78dc32 21
ee78dc32 22#include <config.h>
68c45bf0 23#include <signal.h>
ee78dc32
GV
24#include <stdio.h>
25#include "lisp.h"
3e4731a3 26#include "keyboard.h"
97aab3a2 27#include "frame.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;
ee78dc32 38extern HANDLE keyboard_handle;
97aab3a2 39HANDLE input_available = NULL;
1ce3dc2b 40HANDLE interrupt_handle = NULL;
ee78dc32 41
177c0ea7 42void
ee78dc32
GV
43init_crit ()
44{
dd118a07 45 InitializeCriticalSection (&critsect);
ee78dc32 46
97aab3a2
GV
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);
1ce3dc2b
RS
50
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);
ee78dc32
GV
58}
59
177c0ea7 60void
97aab3a2 61delete_crit ()
ee78dc32 62{
97aab3a2
GV
63 DeleteCriticalSection (&critsect);
64
65 if (input_available)
66 {
67 CloseHandle (input_available);
68 input_available = NULL;
69 }
1ce3dc2b
RS
70 if (interrupt_handle)
71 {
72 CloseHandle (interrupt_handle);
73 interrupt_handle = NULL;
74 }
75}
76
77void
78signal_quit ()
79{
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);
d484dc55
GV
83}
84
97aab3a2
GV
85void
86select_palette (FRAME_PTR f, HDC hdc)
d484dc55 87{
90f4a9f8
AI
88 struct w32_display_info *display_info = FRAME_W32_DISPLAY_INFO (f);
89
90 if (!display_info->has_palette)
91 return;
92
93 if (display_info->palette == 0)
a8370d72 94 return;
90f4a9f8 95
fbd6baed
GV
96 if (!NILP (Vw32_enable_palette))
97 f->output_data.w32->old_palette =
90f4a9f8 98 SelectPalette (hdc, display_info->palette, FALSE);
97aab3a2 99 else
fbd6baed 100 f->output_data.w32->old_palette = NULL;
97aab3a2
GV
101
102 if (RealizePalette (hdc))
103 {
104 Lisp_Object frame, framelist;
105 FOR_EACH_FRAME (framelist, frame)
dd118a07 106 {
97aab3a2 107 SET_FRAME_GARBAGED (XFRAME (frame));
dd118a07 108 }
97aab3a2
GV
109 }
110}
111
112void
113deselect_palette (FRAME_PTR f, HDC hdc)
114{
fbd6baed
GV
115 if (f->output_data.w32->old_palette)
116 SelectPalette (hdc, f->output_data.w32->old_palette, FALSE);
97aab3a2
GV
117}
118
119/* Get a DC for frame and select palette for drawing; force an update of
120 all frames if palette's mapping changes. */
121HDC
122get_frame_dc (FRAME_PTR f)
123{
124 HDC hdc;
125
56c16321
AI
126 if (f->output_method != output_w32)
127 abort ();
128
97aab3a2
GV
129 enter_crit ();
130
fbd6baed 131 hdc = GetDC (f->output_data.w32->window_desc);
86d1db20
JR
132
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);
97aab3a2
GV
137
138 return hdc;
139}
140
141int
142release_frame_dc (FRAME_PTR f, HDC hdc)
143{
144 int ret;
145
146 deselect_palette (f, hdc);
fbd6baed 147 ret = ReleaseDC (f->output_data.w32->window_desc, hdc);
97aab3a2
GV
148
149 leave_crit ();
150
151 return ret;
ee78dc32
GV
152}
153
154typedef struct int_msg
155{
fbd6baed 156 W32Msg w32msg;
ee78dc32
GV
157 struct int_msg *lpNext;
158} int_msg;
159
160int_msg *lpHead = NULL;
161int_msg *lpTail = NULL;
162int nQueue = 0;
163
177c0ea7 164BOOL
ee78dc32 165get_next_msg (lpmsg, bWait)
fbd6baed 166 W32Msg * lpmsg;
ee78dc32
GV
167 BOOL bWait;
168{
169 BOOL bRet = FALSE;
177c0ea7 170
dd118a07 171 enter_crit ();
177c0ea7 172
ee78dc32 173 /* The while loop takes care of multiple sets */
177c0ea7 174
ee78dc32
GV
175 while (!nQueue && bWait)
176 {
dd118a07 177 leave_crit ();
97aab3a2 178 WaitForSingleObject (input_available, INFINITE);
dd118a07 179 enter_crit ();
ee78dc32 180 }
177c0ea7 181
ee78dc32
GV
182 if (nQueue)
183 {
fbd6baed 184 bcopy (&(lpHead->w32msg), lpmsg, sizeof (W32Msg));
ee78dc32
GV
185
186 {
187 int_msg * lpCur = lpHead;
177c0ea7 188
ee78dc32 189 lpHead = lpHead->lpNext;
177c0ea7 190
ee78dc32
GV
191 myfree (lpCur);
192 }
193
194 nQueue--;
195
196 bRet = TRUE;
197 }
97aab3a2
GV
198
199 if (nQueue == 0)
200 ResetEvent (input_available);
177c0ea7 201
dd118a07 202 leave_crit ();
177c0ea7 203
ee78dc32
GV
204 return (bRet);
205}
206
177c0ea7 207BOOL
ee78dc32 208post_msg (lpmsg)
fbd6baed 209 W32Msg * lpmsg;
ee78dc32
GV
210{
211 int_msg * lpNew = (int_msg *) myalloc (sizeof (int_msg));
212
97aab3a2
GV
213 if (!lpNew)
214 return (FALSE);
ee78dc32 215
fbd6baed 216 bcopy (lpmsg, &(lpNew->w32msg), sizeof (W32Msg));
ee78dc32
GV
217 lpNew->lpNext = NULL;
218
dd118a07 219 enter_crit ();
ee78dc32
GV
220
221 if (nQueue++)
dd118a07
GV
222 {
223 lpTail->lpNext = lpNew;
224 }
177c0ea7 225 else
dd118a07
GV
226 {
227 lpHead = lpNew;
dd118a07 228 }
ee78dc32
GV
229
230 lpTail = lpNew;
97aab3a2 231 SetEvent (input_available);
177c0ea7 232
dd118a07 233 leave_crit ();
ee78dc32
GV
234
235 return (TRUE);
236}
237
7c69181b 238BOOL
fbd6baed 239prepend_msg (W32Msg *lpmsg)
7c69181b
GV
240{
241 int_msg * lpNew = (int_msg *) myalloc (sizeof (int_msg));
242
243 if (!lpNew)
244 return (FALSE);
245
fbd6baed 246 bcopy (lpmsg, &(lpNew->w32msg), sizeof (W32Msg));
7c69181b
GV
247
248 enter_crit ();
249
250 nQueue++;
251 lpNew->lpNext = lpHead;
252 lpHead = lpNew;
253
254 leave_crit ();
255
256 return (TRUE);
257}
258
716490f0
AI
259/* Process all messages in the current thread's queue. */
260void
261drain_message_queue ()
262{
263 MSG msg;
264 while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
265 {
266 TranslateMessage (&msg);
267 DispatchMessage (&msg);
268 }
269}
270
271
ee78dc32
GV
272/*
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
177c0ea7 281 * not found, the corresponding argument is left unchanged.
ee78dc32
GV
282 */
283
284static int
285read_integer (string, NextString)
286 register char *string;
287 char **NextString;
288{
289 register int Result = 0;
290 int Sign = 1;
177c0ea7 291
ee78dc32
GV
292 if (*string == '+')
293 string++;
294 else if (*string == '-')
295 {
296 string++;
297 Sign = -1;
298 }
299 for (; (*string >= '0') && (*string <= '9'); string++)
300 {
301 Result = (Result * 10) + (*string - '0');
302 }
303 *NextString = string;
304 if (Sign >= 0)
305 return (Result);
306 else
307 return (-Result);
308}
309
177c0ea7 310int
ee78dc32
GV
311XParseGeometry (string, x, y, width, height)
312 char *string;
313 int *x, *y;
314 unsigned int *width, *height; /* RETURN */
315{
316 int mask = NoValue;
317 register char *strind;
318 unsigned int tempWidth, tempHeight;
319 int tempX, tempY;
320 char *nextCharacter;
177c0ea7 321
ee78dc32
GV
322 if ((string == NULL) || (*string == '\0')) return (mask);
323 if (*string == '=')
324 string++; /* ignore possible '=' at beg of geometry spec */
177c0ea7 325
ee78dc32 326 strind = (char *)string;
177c0ea7 327 if (*strind != '+' && *strind != '-' && *strind != 'x')
ee78dc32
GV
328 {
329 tempWidth = read_integer (strind, &nextCharacter);
177c0ea7 330 if (strind == nextCharacter)
ee78dc32
GV
331 return (0);
332 strind = nextCharacter;
333 mask |= WidthValue;
334 }
177c0ea7
JB
335
336 if (*strind == 'x' || *strind == 'X')
337 {
ee78dc32
GV
338 strind++;
339 tempHeight = read_integer (strind, &nextCharacter);
340 if (strind == nextCharacter)
341 return (0);
342 strind = nextCharacter;
343 mask |= HeightValue;
344 }
177c0ea7
JB
345
346 if ((*strind == '+') || (*strind == '-'))
ee78dc32 347 {
177c0ea7 348 if (*strind == '-')
ee78dc32
GV
349 {
350 strind++;
351 tempX = -read_integer (strind, &nextCharacter);
352 if (strind == nextCharacter)
353 return (0);
354 strind = nextCharacter;
355 mask |= XNegative;
356
357 }
358 else
177c0ea7 359 {
ee78dc32
GV
360 strind++;
361 tempX = read_integer (strind, &nextCharacter);
362 if (strind == nextCharacter)
363 return (0);
364 strind = nextCharacter;
365 }
366 mask |= XValue;
177c0ea7 367 if ((*strind == '+') || (*strind == '-'))
ee78dc32 368 {
177c0ea7 369 if (*strind == '-')
ee78dc32
GV
370 {
371 strind++;
372 tempY = -read_integer (strind, &nextCharacter);
373 if (strind == nextCharacter)
374 return (0);
375 strind = nextCharacter;
376 mask |= YNegative;
377
378 }
379 else
380 {
381 strind++;
382 tempY = read_integer (strind, &nextCharacter);
383 if (strind == nextCharacter)
384 return (0);
385 strind = nextCharacter;
386 }
387 mask |= YValue;
388 }
389 }
177c0ea7 390
ee78dc32
GV
391 /* If strind isn't at the end of the string the it's an invalid
392 geometry specification. */
177c0ea7 393
ee78dc32 394 if (*strind != '\0') return (0);
177c0ea7 395
ee78dc32
GV
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);
405}
406
fbd6baed 407/* x_sync is a no-op on W32. */
ee78dc32
GV
408void
409x_sync (f)
410 void *f;
411{
412}
ab5796a9
MB
413
414/* arch-tag: 4fab3695-4ad3-4cc6-a2b1-fd2c67dc46be
415 (do not change this comment) */