]> code.delx.au - gnu-emacs/blob - src/w32xfns.c
(interrupt_handle): New variable.
[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 Free Software Foundation.
3
4 This file is part of GNU Emacs.
5
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
21 #include <signal.h>
22 #include <config.h>
23 #include <stdio.h>
24 #include "lisp.h"
25 #include "frame.h"
26 #include "blockinput.h"
27 #include "w32term.h"
28 #include "windowsx.h"
29
30 #define myalloc(cb) GlobalAllocPtr (GPTR, cb)
31 #define myfree(lp) GlobalFreePtr (lp)
32
33 CRITICAL_SECTION critsect;
34 extern HANDLE keyboard_handle;
35 HANDLE input_available = NULL;
36 HANDLE interrupt_handle = NULL;
37
38 void
39 init_crit ()
40 {
41 InitializeCriticalSection (&critsect);
42
43 /* For safety, input_available should only be reset by get_next_msg
44 when the input queue is empty, so make it a manual reset event. */
45 keyboard_handle = input_available = CreateEvent (NULL, TRUE, FALSE, NULL);
46
47 /* interrupt_handle is signalled when quit (C-g) is detected, so that
48 blocking system calls can be interrupted. We make it a manual
49 reset event, so that if we should ever have multiple threads
50 performing system calls, they will all be interrupted (I'm guessing
51 that would the right response). Note that we use PulseEvent to
52 signal this event, so that it never remains signalled. */
53 interrupt_handle = CreateEvent (NULL, TRUE, FALSE, NULL);
54 }
55
56 void
57 delete_crit ()
58 {
59 DeleteCriticalSection (&critsect);
60
61 if (input_available)
62 {
63 CloseHandle (input_available);
64 input_available = NULL;
65 }
66 if (interrupt_handle)
67 {
68 CloseHandle (interrupt_handle);
69 interrupt_handle = NULL;
70 }
71 }
72
73 void
74 signal_quit ()
75 {
76 /* Make sure this event never remains signalled; if the main thread
77 isn't in a blocking call, then this should do nothing. */
78 PulseEvent (interrupt_handle);
79 }
80
81 void
82 select_palette (FRAME_PTR f, HDC hdc)
83 {
84 if (!NILP (Vw32_enable_palette))
85 f->output_data.w32->old_palette =
86 SelectPalette (hdc, one_w32_display_info.palette, FALSE);
87 else
88 f->output_data.w32->old_palette = NULL;
89
90 if (RealizePalette (hdc))
91 {
92 Lisp_Object frame, framelist;
93 FOR_EACH_FRAME (framelist, frame)
94 {
95 SET_FRAME_GARBAGED (XFRAME (frame));
96 }
97 }
98 }
99
100 void
101 deselect_palette (FRAME_PTR f, HDC hdc)
102 {
103 if (f->output_data.w32->old_palette)
104 SelectPalette (hdc, f->output_data.w32->old_palette, FALSE);
105 }
106
107 /* Get a DC for frame and select palette for drawing; force an update of
108 all frames if palette's mapping changes. */
109 HDC
110 get_frame_dc (FRAME_PTR f)
111 {
112 HDC hdc;
113
114 enter_crit ();
115
116 hdc = GetDC (f->output_data.w32->window_desc);
117 select_palette (f, hdc);
118
119 return hdc;
120 }
121
122 int
123 release_frame_dc (FRAME_PTR f, HDC hdc)
124 {
125 int ret;
126
127 deselect_palette (f, hdc);
128 ret = ReleaseDC (f->output_data.w32->window_desc, hdc);
129
130 leave_crit ();
131
132 return ret;
133 }
134
135 typedef struct int_msg
136 {
137 W32Msg w32msg;
138 struct int_msg *lpNext;
139 } int_msg;
140
141 int_msg *lpHead = NULL;
142 int_msg *lpTail = NULL;
143 int nQueue = 0;
144
145 BOOL
146 get_next_msg (lpmsg, bWait)
147 W32Msg * lpmsg;
148 BOOL bWait;
149 {
150 BOOL bRet = FALSE;
151
152 enter_crit ();
153
154 /* The while loop takes care of multiple sets */
155
156 while (!nQueue && bWait)
157 {
158 leave_crit ();
159 WaitForSingleObject (input_available, INFINITE);
160 enter_crit ();
161 }
162
163 if (nQueue)
164 {
165 bcopy (&(lpHead->w32msg), lpmsg, sizeof (W32Msg));
166
167 {
168 int_msg * lpCur = lpHead;
169
170 lpHead = lpHead->lpNext;
171
172 myfree (lpCur);
173 }
174
175 nQueue--;
176
177 bRet = TRUE;
178 }
179
180 if (nQueue == 0)
181 ResetEvent (input_available);
182
183 leave_crit ();
184
185 return (bRet);
186 }
187
188 BOOL
189 post_msg (lpmsg)
190 W32Msg * lpmsg;
191 {
192 int_msg * lpNew = (int_msg *) myalloc (sizeof (int_msg));
193
194 if (!lpNew)
195 return (FALSE);
196
197 bcopy (lpmsg, &(lpNew->w32msg), sizeof (W32Msg));
198 lpNew->lpNext = NULL;
199
200 enter_crit ();
201
202 if (nQueue++)
203 {
204 lpTail->lpNext = lpNew;
205 }
206 else
207 {
208 lpHead = lpNew;
209 }
210
211 lpTail = lpNew;
212 SetEvent (input_available);
213
214 leave_crit ();
215
216 return (TRUE);
217 }
218
219 BOOL
220 prepend_msg (W32Msg *lpmsg)
221 {
222 int_msg * lpNew = (int_msg *) myalloc (sizeof (int_msg));
223
224 if (!lpNew)
225 return (FALSE);
226
227 bcopy (lpmsg, &(lpNew->w32msg), sizeof (W32Msg));
228
229 enter_crit ();
230
231 nQueue++;
232 lpNew->lpNext = lpHead;
233 lpHead = lpNew;
234
235 leave_crit ();
236
237 return (TRUE);
238 }
239
240 /*
241 * XParseGeometry parses strings of the form
242 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
243 * width, height, xoffset, and yoffset are unsigned integers.
244 * Example: "=80x24+300-49"
245 * The equal sign is optional.
246 * It returns a bitmask that indicates which of the four values
247 * were actually found in the string. For each value found,
248 * the corresponding argument is updated; for each value
249 * not found, the corresponding argument is left unchanged.
250 */
251
252 static int
253 read_integer (string, NextString)
254 register char *string;
255 char **NextString;
256 {
257 register int Result = 0;
258 int Sign = 1;
259
260 if (*string == '+')
261 string++;
262 else if (*string == '-')
263 {
264 string++;
265 Sign = -1;
266 }
267 for (; (*string >= '0') && (*string <= '9'); string++)
268 {
269 Result = (Result * 10) + (*string - '0');
270 }
271 *NextString = string;
272 if (Sign >= 0)
273 return (Result);
274 else
275 return (-Result);
276 }
277
278 int
279 XParseGeometry (string, x, y, width, height)
280 char *string;
281 int *x, *y;
282 unsigned int *width, *height; /* RETURN */
283 {
284 int mask = NoValue;
285 register char *strind;
286 unsigned int tempWidth, tempHeight;
287 int tempX, tempY;
288 char *nextCharacter;
289
290 if ((string == NULL) || (*string == '\0')) return (mask);
291 if (*string == '=')
292 string++; /* ignore possible '=' at beg of geometry spec */
293
294 strind = (char *)string;
295 if (*strind != '+' && *strind != '-' && *strind != 'x')
296 {
297 tempWidth = read_integer (strind, &nextCharacter);
298 if (strind == nextCharacter)
299 return (0);
300 strind = nextCharacter;
301 mask |= WidthValue;
302 }
303
304 if (*strind == 'x' || *strind == 'X')
305 {
306 strind++;
307 tempHeight = read_integer (strind, &nextCharacter);
308 if (strind == nextCharacter)
309 return (0);
310 strind = nextCharacter;
311 mask |= HeightValue;
312 }
313
314 if ((*strind == '+') || (*strind == '-'))
315 {
316 if (*strind == '-')
317 {
318 strind++;
319 tempX = -read_integer (strind, &nextCharacter);
320 if (strind == nextCharacter)
321 return (0);
322 strind = nextCharacter;
323 mask |= XNegative;
324
325 }
326 else
327 {
328 strind++;
329 tempX = read_integer (strind, &nextCharacter);
330 if (strind == nextCharacter)
331 return (0);
332 strind = nextCharacter;
333 }
334 mask |= XValue;
335 if ((*strind == '+') || (*strind == '-'))
336 {
337 if (*strind == '-')
338 {
339 strind++;
340 tempY = -read_integer (strind, &nextCharacter);
341 if (strind == nextCharacter)
342 return (0);
343 strind = nextCharacter;
344 mask |= YNegative;
345
346 }
347 else
348 {
349 strind++;
350 tempY = read_integer (strind, &nextCharacter);
351 if (strind == nextCharacter)
352 return (0);
353 strind = nextCharacter;
354 }
355 mask |= YValue;
356 }
357 }
358
359 /* If strind isn't at the end of the string the it's an invalid
360 geometry specification. */
361
362 if (*strind != '\0') return (0);
363
364 if (mask & XValue)
365 *x = tempX;
366 if (mask & YValue)
367 *y = tempY;
368 if (mask & WidthValue)
369 *width = tempWidth;
370 if (mask & HeightValue)
371 *height = tempHeight;
372 return (mask);
373 }
374
375 /* x_sync is a no-op on W32. */
376 void
377 x_sync (f)
378 void *f;
379 {
380 }
381