(iso-languages): For Portuguese ~c and
[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 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 "charset.h"
27 #include "fontset.h"
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
35 CRITICAL_SECTION critsect;
36 extern HANDLE keyboard_handle;
37 HANDLE input_available = NULL;
38 HANDLE interrupt_handle = NULL;
39
40 void
41 init_crit ()
42 {
43 InitializeCriticalSection (&critsect);
44
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);
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);
56 }
57
58 void
59 delete_crit ()
60 {
61 DeleteCriticalSection (&critsect);
62
63 if (input_available)
64 {
65 CloseHandle (input_available);
66 input_available = NULL;
67 }
68 if (interrupt_handle)
69 {
70 CloseHandle (interrupt_handle);
71 interrupt_handle = NULL;
72 }
73 }
74
75 void
76 signal_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);
81 }
82
83 void
84 select_palette (FRAME_PTR f, HDC hdc)
85 {
86 if (!NILP (Vw32_enable_palette))
87 f->output_data.w32->old_palette =
88 SelectPalette (hdc, one_w32_display_info.palette, FALSE);
89 else
90 f->output_data.w32->old_palette = NULL;
91
92 if (RealizePalette (hdc))
93 {
94 Lisp_Object frame, framelist;
95 FOR_EACH_FRAME (framelist, frame)
96 {
97 SET_FRAME_GARBAGED (XFRAME (frame));
98 }
99 }
100 }
101
102 void
103 deselect_palette (FRAME_PTR f, HDC hdc)
104 {
105 if (f->output_data.w32->old_palette)
106 SelectPalette (hdc, f->output_data.w32->old_palette, FALSE);
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. */
111 HDC
112 get_frame_dc (FRAME_PTR f)
113 {
114 HDC hdc;
115
116 enter_crit ();
117
118 hdc = GetDC (f->output_data.w32->window_desc);
119 select_palette (f, hdc);
120
121 return hdc;
122 }
123
124 int
125 release_frame_dc (FRAME_PTR f, HDC hdc)
126 {
127 int ret;
128
129 deselect_palette (f, hdc);
130 ret = ReleaseDC (f->output_data.w32->window_desc, hdc);
131
132 leave_crit ();
133
134 return ret;
135 }
136
137 typedef struct int_msg
138 {
139 W32Msg w32msg;
140 struct int_msg *lpNext;
141 } int_msg;
142
143 int_msg *lpHead = NULL;
144 int_msg *lpTail = NULL;
145 int nQueue = 0;
146
147 BOOL
148 get_next_msg (lpmsg, bWait)
149 W32Msg * lpmsg;
150 BOOL bWait;
151 {
152 BOOL bRet = FALSE;
153
154 enter_crit ();
155
156 /* The while loop takes care of multiple sets */
157
158 while (!nQueue && bWait)
159 {
160 leave_crit ();
161 WaitForSingleObject (input_available, INFINITE);
162 enter_crit ();
163 }
164
165 if (nQueue)
166 {
167 bcopy (&(lpHead->w32msg), lpmsg, sizeof (W32Msg));
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 }
181
182 if (nQueue == 0)
183 ResetEvent (input_available);
184
185 leave_crit ();
186
187 return (bRet);
188 }
189
190 BOOL
191 post_msg (lpmsg)
192 W32Msg * lpmsg;
193 {
194 int_msg * lpNew = (int_msg *) myalloc (sizeof (int_msg));
195
196 if (!lpNew)
197 return (FALSE);
198
199 bcopy (lpmsg, &(lpNew->w32msg), sizeof (W32Msg));
200 lpNew->lpNext = NULL;
201
202 enter_crit ();
203
204 if (nQueue++)
205 {
206 lpTail->lpNext = lpNew;
207 }
208 else
209 {
210 lpHead = lpNew;
211 }
212
213 lpTail = lpNew;
214 SetEvent (input_available);
215
216 leave_crit ();
217
218 return (TRUE);
219 }
220
221 BOOL
222 prepend_msg (W32Msg *lpmsg)
223 {
224 int_msg * lpNew = (int_msg *) myalloc (sizeof (int_msg));
225
226 if (!lpNew)
227 return (FALSE);
228
229 bcopy (lpmsg, &(lpNew->w32msg), sizeof (W32Msg));
230
231 enter_crit ();
232
233 nQueue++;
234 lpNew->lpNext = lpHead;
235 lpHead = lpNew;
236
237 leave_crit ();
238
239 return (TRUE);
240 }
241
242 /*
243 * XParseGeometry parses strings of the form
244 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
245 * width, height, xoffset, and yoffset are unsigned integers.
246 * Example: "=80x24+300-49"
247 * The equal sign is optional.
248 * It returns a bitmask that indicates which of the four values
249 * were actually found in the string. For each value found,
250 * the corresponding argument is updated; for each value
251 * not found, the corresponding argument is left unchanged.
252 */
253
254 static int
255 read_integer (string, NextString)
256 register char *string;
257 char **NextString;
258 {
259 register int Result = 0;
260 int Sign = 1;
261
262 if (*string == '+')
263 string++;
264 else if (*string == '-')
265 {
266 string++;
267 Sign = -1;
268 }
269 for (; (*string >= '0') && (*string <= '9'); string++)
270 {
271 Result = (Result * 10) + (*string - '0');
272 }
273 *NextString = string;
274 if (Sign >= 0)
275 return (Result);
276 else
277 return (-Result);
278 }
279
280 int
281 XParseGeometry (string, x, y, width, height)
282 char *string;
283 int *x, *y;
284 unsigned int *width, *height; /* RETURN */
285 {
286 int mask = NoValue;
287 register char *strind;
288 unsigned int tempWidth, tempHeight;
289 int tempX, tempY;
290 char *nextCharacter;
291
292 if ((string == NULL) || (*string == '\0')) return (mask);
293 if (*string == '=')
294 string++; /* ignore possible '=' at beg of geometry spec */
295
296 strind = (char *)string;
297 if (*strind != '+' && *strind != '-' && *strind != 'x')
298 {
299 tempWidth = read_integer (strind, &nextCharacter);
300 if (strind == nextCharacter)
301 return (0);
302 strind = nextCharacter;
303 mask |= WidthValue;
304 }
305
306 if (*strind == 'x' || *strind == 'X')
307 {
308 strind++;
309 tempHeight = read_integer (strind, &nextCharacter);
310 if (strind == nextCharacter)
311 return (0);
312 strind = nextCharacter;
313 mask |= HeightValue;
314 }
315
316 if ((*strind == '+') || (*strind == '-'))
317 {
318 if (*strind == '-')
319 {
320 strind++;
321 tempX = -read_integer (strind, &nextCharacter);
322 if (strind == nextCharacter)
323 return (0);
324 strind = nextCharacter;
325 mask |= XNegative;
326
327 }
328 else
329 {
330 strind++;
331 tempX = read_integer (strind, &nextCharacter);
332 if (strind == nextCharacter)
333 return (0);
334 strind = nextCharacter;
335 }
336 mask |= XValue;
337 if ((*strind == '+') || (*strind == '-'))
338 {
339 if (*strind == '-')
340 {
341 strind++;
342 tempY = -read_integer (strind, &nextCharacter);
343 if (strind == nextCharacter)
344 return (0);
345 strind = nextCharacter;
346 mask |= YNegative;
347
348 }
349 else
350 {
351 strind++;
352 tempY = read_integer (strind, &nextCharacter);
353 if (strind == nextCharacter)
354 return (0);
355 strind = nextCharacter;
356 }
357 mask |= YValue;
358 }
359 }
360
361 /* If strind isn't at the end of the string the it's an invalid
362 geometry specification. */
363
364 if (*strind != '\0') return (0);
365
366 if (mask & XValue)
367 *x = tempX;
368 if (mask & YValue)
369 *y = tempY;
370 if (mask & WidthValue)
371 *width = tempWidth;
372 if (mask & HeightValue)
373 *height = tempHeight;
374 return (mask);
375 }
376
377 /* x_sync is a no-op on W32. */
378 void
379 x_sync (f)
380 void *f;
381 {
382 }