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