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