Use @set and @value to avoid changing the edition and the Emacs version
[bpt/emacs.git] / src / w32xfns.c
CommitLineData
e9e23e23 1/* Functions taken directly from X sources for use with the Microsoft W32 API.
68c45bf0 2 Copyright (C) 1989, 1992, 1993, 1994, 1995, 1999 Free Software Foundation.
ee78dc32
GV
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
3b7ad313
EN
18the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
ee78dc32 20
ee78dc32 21#include <config.h>
68c45bf0 22#include <signal.h>
ee78dc32
GV
23#include <stdio.h>
24#include "lisp.h"
3e4731a3 25#include "keyboard.h"
97aab3a2 26#include "frame.h"
bd6bb544
GV
27#include "charset.h"
28#include "fontset.h"
ee78dc32
GV
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
dd118a07 36CRITICAL_SECTION critsect;
ee78dc32 37extern HANDLE keyboard_handle;
97aab3a2 38HANDLE input_available = NULL;
1ce3dc2b 39HANDLE interrupt_handle = NULL;
ee78dc32
GV
40
41void
42init_crit ()
43{
dd118a07 44 InitializeCriticalSection (&critsect);
ee78dc32 45
97aab3a2
GV
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);
1ce3dc2b
RS
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);
ee78dc32
GV
57}
58
dd118a07 59void
97aab3a2 60delete_crit ()
ee78dc32 61{
97aab3a2
GV
62 DeleteCriticalSection (&critsect);
63
64 if (input_available)
65 {
66 CloseHandle (input_available);
67 input_available = NULL;
68 }
1ce3dc2b
RS
69 if (interrupt_handle)
70 {
71 CloseHandle (interrupt_handle);
72 interrupt_handle = NULL;
73 }
74}
75
76void
77signal_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);
d484dc55
GV
82}
83
97aab3a2
GV
84void
85select_palette (FRAME_PTR f, HDC hdc)
d484dc55 86{
90f4a9f8
AI
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 abort ();
94
fbd6baed
GV
95 if (!NILP (Vw32_enable_palette))
96 f->output_data.w32->old_palette =
90f4a9f8 97 SelectPalette (hdc, display_info->palette, FALSE);
97aab3a2 98 else
fbd6baed 99 f->output_data.w32->old_palette = NULL;
97aab3a2
GV
100
101 if (RealizePalette (hdc))
102 {
103 Lisp_Object frame, framelist;
104 FOR_EACH_FRAME (framelist, frame)
dd118a07 105 {
97aab3a2 106 SET_FRAME_GARBAGED (XFRAME (frame));
dd118a07 107 }
97aab3a2
GV
108 }
109}
110
111void
112deselect_palette (FRAME_PTR f, HDC hdc)
113{
fbd6baed
GV
114 if (f->output_data.w32->old_palette)
115 SelectPalette (hdc, f->output_data.w32->old_palette, FALSE);
97aab3a2
GV
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. */
120HDC
121get_frame_dc (FRAME_PTR f)
122{
123 HDC hdc;
124
56c16321
AI
125 if (f->output_method != output_w32)
126 abort ();
127
97aab3a2
GV
128 enter_crit ();
129
fbd6baed 130 hdc = GetDC (f->output_data.w32->window_desc);
86d1db20
JR
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);
97aab3a2
GV
136
137 return hdc;
138}
139
140int
141release_frame_dc (FRAME_PTR f, HDC hdc)
142{
143 int ret;
144
145 deselect_palette (f, hdc);
fbd6baed 146 ret = ReleaseDC (f->output_data.w32->window_desc, hdc);
97aab3a2
GV
147
148 leave_crit ();
149
150 return ret;
ee78dc32
GV
151}
152
153typedef struct int_msg
154{
fbd6baed 155 W32Msg w32msg;
ee78dc32
GV
156 struct int_msg *lpNext;
157} int_msg;
158
159int_msg *lpHead = NULL;
160int_msg *lpTail = NULL;
161int nQueue = 0;
162
163BOOL
164get_next_msg (lpmsg, bWait)
fbd6baed 165 W32Msg * lpmsg;
ee78dc32
GV
166 BOOL bWait;
167{
168 BOOL bRet = FALSE;
169
dd118a07 170 enter_crit ();
ee78dc32
GV
171
172 /* The while loop takes care of multiple sets */
173
174 while (!nQueue && bWait)
175 {
dd118a07 176 leave_crit ();
97aab3a2 177 WaitForSingleObject (input_available, INFINITE);
dd118a07 178 enter_crit ();
ee78dc32
GV
179 }
180
181 if (nQueue)
182 {
fbd6baed 183 bcopy (&(lpHead->w32msg), lpmsg, sizeof (W32Msg));
ee78dc32
GV
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 }
97aab3a2
GV
197
198 if (nQueue == 0)
199 ResetEvent (input_available);
ee78dc32 200
dd118a07 201 leave_crit ();
ee78dc32
GV
202
203 return (bRet);
204}
205
206BOOL
207post_msg (lpmsg)
fbd6baed 208 W32Msg * lpmsg;
ee78dc32
GV
209{
210 int_msg * lpNew = (int_msg *) myalloc (sizeof (int_msg));
211
97aab3a2
GV
212 if (!lpNew)
213 return (FALSE);
ee78dc32 214
fbd6baed 215 bcopy (lpmsg, &(lpNew->w32msg), sizeof (W32Msg));
ee78dc32
GV
216 lpNew->lpNext = NULL;
217
dd118a07 218 enter_crit ();
ee78dc32
GV
219
220 if (nQueue++)
dd118a07
GV
221 {
222 lpTail->lpNext = lpNew;
223 }
ee78dc32 224 else
dd118a07
GV
225 {
226 lpHead = lpNew;
dd118a07 227 }
ee78dc32
GV
228
229 lpTail = lpNew;
97aab3a2 230 SetEvent (input_available);
ee78dc32 231
dd118a07 232 leave_crit ();
ee78dc32
GV
233
234 return (TRUE);
235}
236
7c69181b 237BOOL
fbd6baed 238prepend_msg (W32Msg *lpmsg)
7c69181b
GV
239{
240 int_msg * lpNew = (int_msg *) myalloc (sizeof (int_msg));
241
242 if (!lpNew)
243 return (FALSE);
244
fbd6baed 245 bcopy (lpmsg, &(lpNew->w32msg), sizeof (W32Msg));
7c69181b
GV
246
247 enter_crit ();
248
249 nQueue++;
250 lpNew->lpNext = lpHead;
251 lpHead = lpNew;
252
253 leave_crit ();
254
255 return (TRUE);
256}
257
716490f0
AI
258/* Process all messages in the current thread's queue. */
259void
260drain_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
ee78dc32
GV
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
283static int
284read_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
309int
310XParseGeometry (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
fbd6baed 406/* x_sync is a no-op on W32. */
ee78dc32
GV
407void
408x_sync (f)
409 void *f;
410{
411}