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