Revision: miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-483
[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 40
177c0ea7 41void
ee78dc32
GV
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
177c0ea7 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)
a8370d72 93 return;
90f4a9f8 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
177c0ea7 163BOOL
ee78dc32 164get_next_msg (lpmsg, bWait)
fbd6baed 165 W32Msg * lpmsg;
ee78dc32
GV
166 BOOL bWait;
167{
168 BOOL bRet = FALSE;
177c0ea7 169
dd118a07 170 enter_crit ();
177c0ea7 171
ee78dc32 172 /* The while loop takes care of multiple sets */
177c0ea7 173
ee78dc32
GV
174 while (!nQueue && bWait)
175 {
dd118a07 176 leave_crit ();
97aab3a2 177 WaitForSingleObject (input_available, INFINITE);
dd118a07 178 enter_crit ();
ee78dc32 179 }
177c0ea7 180
ee78dc32
GV
181 if (nQueue)
182 {
fbd6baed 183 bcopy (&(lpHead->w32msg), lpmsg, sizeof (W32Msg));
ee78dc32
GV
184
185 {
186 int_msg * lpCur = lpHead;
177c0ea7 187
ee78dc32 188 lpHead = lpHead->lpNext;
177c0ea7 189
ee78dc32
GV
190 myfree (lpCur);
191 }
192
193 nQueue--;
194
195 bRet = TRUE;
196 }
97aab3a2
GV
197
198 if (nQueue == 0)
199 ResetEvent (input_available);
177c0ea7 200
dd118a07 201 leave_crit ();
177c0ea7 202
ee78dc32
GV
203 return (bRet);
204}
205
177c0ea7 206BOOL
ee78dc32 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 }
177c0ea7 224 else
dd118a07
GV
225 {
226 lpHead = lpNew;
dd118a07 227 }
ee78dc32
GV
228
229 lpTail = lpNew;
97aab3a2 230 SetEvent (input_available);
177c0ea7 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
177c0ea7 280 * not found, the corresponding argument is left unchanged.
ee78dc32
GV
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;
177c0ea7 290
ee78dc32
GV
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
177c0ea7 309int
ee78dc32
GV
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;
177c0ea7 320
ee78dc32
GV
321 if ((string == NULL) || (*string == '\0')) return (mask);
322 if (*string == '=')
323 string++; /* ignore possible '=' at beg of geometry spec */
177c0ea7 324
ee78dc32 325 strind = (char *)string;
177c0ea7 326 if (*strind != '+' && *strind != '-' && *strind != 'x')
ee78dc32
GV
327 {
328 tempWidth = read_integer (strind, &nextCharacter);
177c0ea7 329 if (strind == nextCharacter)
ee78dc32
GV
330 return (0);
331 strind = nextCharacter;
332 mask |= WidthValue;
333 }
177c0ea7
JB
334
335 if (*strind == 'x' || *strind == 'X')
336 {
ee78dc32
GV
337 strind++;
338 tempHeight = read_integer (strind, &nextCharacter);
339 if (strind == nextCharacter)
340 return (0);
341 strind = nextCharacter;
342 mask |= HeightValue;
343 }
177c0ea7
JB
344
345 if ((*strind == '+') || (*strind == '-'))
ee78dc32 346 {
177c0ea7 347 if (*strind == '-')
ee78dc32
GV
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
177c0ea7 358 {
ee78dc32
GV
359 strind++;
360 tempX = read_integer (strind, &nextCharacter);
361 if (strind == nextCharacter)
362 return (0);
363 strind = nextCharacter;
364 }
365 mask |= XValue;
177c0ea7 366 if ((*strind == '+') || (*strind == '-'))
ee78dc32 367 {
177c0ea7 368 if (*strind == '-')
ee78dc32
GV
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 }
177c0ea7 389
ee78dc32
GV
390 /* If strind isn't at the end of the string the it's an invalid
391 geometry specification. */
177c0ea7 392
ee78dc32 393 if (*strind != '\0') return (0);
177c0ea7 394
ee78dc32
GV
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}
ab5796a9
MB
412
413/* arch-tag: 4fab3695-4ad3-4cc6-a2b1-fd2c67dc46be
414 (do not change this comment) */