]> code.delx.au - gnu-emacs/blob - src/w32xfns.c
Merge from emacs--devo--0
[gnu-emacs] / src / w32xfns.c
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 Free Software Foundation, Inc.
4
5 This file is part of GNU Emacs.
6
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, or (at your option)
10 any later version.
11
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.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA. */
21
22 #include <config.h>
23 #include <signal.h>
24 #include <stdio.h>
25 #include "lisp.h"
26 #include "keyboard.h"
27 #include "frame.h"
28 #include "charset.h"
29 #include "fontset.h"
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
37 CRITICAL_SECTION critsect;
38 extern HANDLE keyboard_handle;
39 HANDLE input_available = NULL;
40 HANDLE interrupt_handle = NULL;
41
42 void
43 init_crit ()
44 {
45 InitializeCriticalSection (&critsect);
46
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);
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);
58 }
59
60 void
61 delete_crit ()
62 {
63 DeleteCriticalSection (&critsect);
64
65 if (input_available)
66 {
67 CloseHandle (input_available);
68 input_available = NULL;
69 }
70 if (interrupt_handle)
71 {
72 CloseHandle (interrupt_handle);
73 interrupt_handle = NULL;
74 }
75 }
76
77 void
78 signal_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);
83 }
84
85 void
86 select_palette (FRAME_PTR f, HDC hdc)
87 {
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)
94 return;
95
96 if (!NILP (Vw32_enable_palette))
97 f->output_data.w32->old_palette =
98 SelectPalette (hdc, display_info->palette, FALSE);
99 else
100 f->output_data.w32->old_palette = NULL;
101
102 if (RealizePalette (hdc))
103 {
104 Lisp_Object frame, framelist;
105 FOR_EACH_FRAME (framelist, frame)
106 {
107 SET_FRAME_GARBAGED (XFRAME (frame));
108 }
109 }
110 }
111
112 void
113 deselect_palette (FRAME_PTR f, HDC hdc)
114 {
115 if (f->output_data.w32->old_palette)
116 SelectPalette (hdc, f->output_data.w32->old_palette, FALSE);
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. */
121 HDC
122 get_frame_dc (FRAME_PTR f)
123 {
124 HDC hdc;
125
126 if (f->output_method != output_w32)
127 abort ();
128
129 enter_crit ();
130
131 hdc = GetDC (f->output_data.w32->window_desc);
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);
137
138 return hdc;
139 }
140
141 int
142 release_frame_dc (FRAME_PTR f, HDC hdc)
143 {
144 int ret;
145
146 deselect_palette (f, hdc);
147 ret = ReleaseDC (f->output_data.w32->window_desc, hdc);
148
149 leave_crit ();
150
151 return ret;
152 }
153
154 typedef struct int_msg
155 {
156 W32Msg w32msg;
157 struct int_msg *lpNext;
158 } int_msg;
159
160 int_msg *lpHead = NULL;
161 int_msg *lpTail = NULL;
162 int nQueue = 0;
163
164 BOOL
165 get_next_msg (lpmsg, bWait)
166 W32Msg * lpmsg;
167 BOOL bWait;
168 {
169 BOOL bRet = FALSE;
170
171 enter_crit ();
172
173 /* The while loop takes care of multiple sets */
174
175 while (!nQueue && bWait)
176 {
177 leave_crit ();
178 WaitForSingleObject (input_available, INFINITE);
179 enter_crit ();
180 }
181
182 if (nQueue)
183 {
184 bcopy (&(lpHead->w32msg), lpmsg, sizeof (W32Msg));
185
186 {
187 int_msg * lpCur = lpHead;
188
189 lpHead = lpHead->lpNext;
190
191 myfree (lpCur);
192 }
193
194 nQueue--;
195 /* Consolidate WM_PAINT messages to optimise redrawing. */
196 if (lpmsg->msg.message == WM_PAINT && nQueue)
197 {
198 int_msg * lpCur = lpHead;
199 int_msg * lpPrev = NULL;
200 int_msg * lpNext = NULL;
201
202 while (lpCur && nQueue)
203 {
204 lpNext = lpCur->lpNext;
205 if (lpCur->w32msg.msg.message == WM_PAINT)
206 {
207 /* Remove this message from the queue. */
208 if (lpPrev)
209 lpPrev->lpNext = lpNext;
210 else
211 lpHead = lpNext;
212
213 if (lpCur == lpTail)
214 lpTail = lpPrev;
215
216 /* Adjust clip rectangle to cover both. */
217 if (!UnionRect (&(lpmsg->rect), &(lpmsg->rect),
218 &(lpCur->w32msg.rect)))
219 {
220 SetRectEmpty(&(lpmsg->rect));
221 }
222
223 myfree (lpCur);
224
225 nQueue--;
226
227 lpCur = lpNext;
228 }
229 else
230 {
231 lpPrev = lpCur;
232 lpCur = lpNext;
233 }
234 }
235 }
236
237 bRet = TRUE;
238 }
239
240 if (nQueue == 0)
241 ResetEvent (input_available);
242
243 leave_crit ();
244
245 return (bRet);
246 }
247
248 BOOL
249 post_msg (lpmsg)
250 W32Msg * lpmsg;
251 {
252 int_msg * lpNew = (int_msg *) myalloc (sizeof (int_msg));
253
254 if (!lpNew)
255 return (FALSE);
256
257 bcopy (lpmsg, &(lpNew->w32msg), sizeof (W32Msg));
258 lpNew->lpNext = NULL;
259
260 enter_crit ();
261
262 if (nQueue++)
263 {
264 lpTail->lpNext = lpNew;
265 }
266 else
267 {
268 lpHead = lpNew;
269 }
270
271 lpTail = lpNew;
272 SetEvent (input_available);
273
274 leave_crit ();
275
276 return (TRUE);
277 }
278
279 BOOL
280 prepend_msg (W32Msg *lpmsg)
281 {
282 int_msg * lpNew = (int_msg *) myalloc (sizeof (int_msg));
283
284 if (!lpNew)
285 return (FALSE);
286
287 bcopy (lpmsg, &(lpNew->w32msg), sizeof (W32Msg));
288
289 enter_crit ();
290
291 nQueue++;
292 lpNew->lpNext = lpHead;
293 lpHead = lpNew;
294
295 leave_crit ();
296
297 return (TRUE);
298 }
299
300 /* Process all messages in the current thread's queue. */
301 void
302 drain_message_queue ()
303 {
304 MSG msg;
305 while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
306 {
307 TranslateMessage (&msg);
308 DispatchMessage (&msg);
309 }
310 }
311
312
313 /*
314 * XParseGeometry parses strings of the form
315 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
316 * width, height, xoffset, and yoffset are unsigned integers.
317 * Example: "=80x24+300-49"
318 * The equal sign is optional.
319 * It returns a bitmask that indicates which of the four values
320 * were actually found in the string. For each value found,
321 * the corresponding argument is updated; for each value
322 * not found, the corresponding argument is left unchanged.
323 */
324
325 static int
326 read_integer (string, NextString)
327 register char *string;
328 char **NextString;
329 {
330 register int Result = 0;
331 int Sign = 1;
332
333 if (*string == '+')
334 string++;
335 else if (*string == '-')
336 {
337 string++;
338 Sign = -1;
339 }
340 for (; (*string >= '0') && (*string <= '9'); string++)
341 {
342 Result = (Result * 10) + (*string - '0');
343 }
344 *NextString = string;
345 if (Sign >= 0)
346 return (Result);
347 else
348 return (-Result);
349 }
350
351 int
352 XParseGeometry (string, x, y, width, height)
353 char *string;
354 int *x, *y;
355 unsigned int *width, *height; /* RETURN */
356 {
357 int mask = NoValue;
358 register char *strind;
359 unsigned int tempWidth, tempHeight;
360 int tempX, tempY;
361 char *nextCharacter;
362
363 if ((string == NULL) || (*string == '\0')) return (mask);
364 if (*string == '=')
365 string++; /* ignore possible '=' at beg of geometry spec */
366
367 strind = (char *)string;
368 if (*strind != '+' && *strind != '-' && *strind != 'x')
369 {
370 tempWidth = read_integer (strind, &nextCharacter);
371 if (strind == nextCharacter)
372 return (0);
373 strind = nextCharacter;
374 mask |= WidthValue;
375 }
376
377 if (*strind == 'x' || *strind == 'X')
378 {
379 strind++;
380 tempHeight = read_integer (strind, &nextCharacter);
381 if (strind == nextCharacter)
382 return (0);
383 strind = nextCharacter;
384 mask |= HeightValue;
385 }
386
387 if ((*strind == '+') || (*strind == '-'))
388 {
389 if (*strind == '-')
390 {
391 strind++;
392 tempX = -read_integer (strind, &nextCharacter);
393 if (strind == nextCharacter)
394 return (0);
395 strind = nextCharacter;
396 mask |= XNegative;
397
398 }
399 else
400 {
401 strind++;
402 tempX = read_integer (strind, &nextCharacter);
403 if (strind == nextCharacter)
404 return (0);
405 strind = nextCharacter;
406 }
407 mask |= XValue;
408 if ((*strind == '+') || (*strind == '-'))
409 {
410 if (*strind == '-')
411 {
412 strind++;
413 tempY = -read_integer (strind, &nextCharacter);
414 if (strind == nextCharacter)
415 return (0);
416 strind = nextCharacter;
417 mask |= YNegative;
418
419 }
420 else
421 {
422 strind++;
423 tempY = read_integer (strind, &nextCharacter);
424 if (strind == nextCharacter)
425 return (0);
426 strind = nextCharacter;
427 }
428 mask |= YValue;
429 }
430 }
431
432 /* If strind isn't at the end of the string the it's an invalid
433 geometry specification. */
434
435 if (*strind != '\0') return (0);
436
437 if (mask & XValue)
438 *x = tempX;
439 if (mask & YValue)
440 *y = tempY;
441 if (mask & WidthValue)
442 *width = tempWidth;
443 if (mask & HeightValue)
444 *height = tempHeight;
445 return (mask);
446 }
447
448 /* x_sync is a no-op on W32. */
449 void
450 x_sync (f)
451 void *f;
452 {
453 }
454
455 /* arch-tag: 4fab3695-4ad3-4cc6-a2b1-fd2c67dc46be
456 (do not change this comment) */