]> code.delx.au - gnu-emacs/blob - src/w32xfns.c
(Version, mh-version): Update for release 8.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, 2002, 2003, 2004,
3 2005, 2006 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 2, 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
196 bRet = TRUE;
197 }
198
199 if (nQueue == 0)
200 ResetEvent (input_available);
201
202 leave_crit ();
203
204 return (bRet);
205 }
206
207 BOOL
208 post_msg (lpmsg)
209 W32Msg * lpmsg;
210 {
211 int_msg * lpNew = (int_msg *) myalloc (sizeof (int_msg));
212
213 if (!lpNew)
214 return (FALSE);
215
216 bcopy (lpmsg, &(lpNew->w32msg), sizeof (W32Msg));
217 lpNew->lpNext = NULL;
218
219 enter_crit ();
220
221 if (nQueue++)
222 {
223 lpTail->lpNext = lpNew;
224 }
225 else
226 {
227 lpHead = lpNew;
228 }
229
230 lpTail = lpNew;
231 SetEvent (input_available);
232
233 leave_crit ();
234
235 return (TRUE);
236 }
237
238 BOOL
239 prepend_msg (W32Msg *lpmsg)
240 {
241 int_msg * lpNew = (int_msg *) myalloc (sizeof (int_msg));
242
243 if (!lpNew)
244 return (FALSE);
245
246 bcopy (lpmsg, &(lpNew->w32msg), sizeof (W32Msg));
247
248 enter_crit ();
249
250 nQueue++;
251 lpNew->lpNext = lpHead;
252 lpHead = lpNew;
253
254 leave_crit ();
255
256 return (TRUE);
257 }
258
259 /* Process all messages in the current thread's queue. */
260 void
261 drain_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
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
281 * not found, the corresponding argument is left unchanged.
282 */
283
284 static int
285 read_integer (string, NextString)
286 register char *string;
287 char **NextString;
288 {
289 register int Result = 0;
290 int Sign = 1;
291
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
310 int
311 XParseGeometry (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;
321
322 if ((string == NULL) || (*string == '\0')) return (mask);
323 if (*string == '=')
324 string++; /* ignore possible '=' at beg of geometry spec */
325
326 strind = (char *)string;
327 if (*strind != '+' && *strind != '-' && *strind != 'x')
328 {
329 tempWidth = read_integer (strind, &nextCharacter);
330 if (strind == nextCharacter)
331 return (0);
332 strind = nextCharacter;
333 mask |= WidthValue;
334 }
335
336 if (*strind == 'x' || *strind == 'X')
337 {
338 strind++;
339 tempHeight = read_integer (strind, &nextCharacter);
340 if (strind == nextCharacter)
341 return (0);
342 strind = nextCharacter;
343 mask |= HeightValue;
344 }
345
346 if ((*strind == '+') || (*strind == '-'))
347 {
348 if (*strind == '-')
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
359 {
360 strind++;
361 tempX = read_integer (strind, &nextCharacter);
362 if (strind == nextCharacter)
363 return (0);
364 strind = nextCharacter;
365 }
366 mask |= XValue;
367 if ((*strind == '+') || (*strind == '-'))
368 {
369 if (*strind == '-')
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 }
390
391 /* If strind isn't at the end of the string the it's an invalid
392 geometry specification. */
393
394 if (*strind != '\0') return (0);
395
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
407 /* x_sync is a no-op on W32. */
408 void
409 x_sync (f)
410 void *f;
411 {
412 }
413
414 /* arch-tag: 4fab3695-4ad3-4cc6-a2b1-fd2c67dc46be
415 (do not change this comment) */