Mercurial > emacs
comparison src/w32fns.c @ 19707:0181cc080316
Include limits.h and errno.h.
Declare externs from other files.
(w32_in_use): New variable.
(check_w32, have_menus_p, x_set_title, w32_msg_worker,
find_deferred_msg, send_deferred_msg, complete_deferred_msg,
Fw32_focus_frame, W32-send-sys-command): New functions.
(last_mouse_movement_time): Delete variable.
(x_frame_parms): Alphabetize. Add title parm.
(x_set_icon_name): Use title if set.
(x_set_menu_bar_lines): Ensure client area remains the same.
(x_set_name): Don't update if the name is the same.
Use title for name if available.
(x_icon): Initial support for creating window iconified.
(x_display_info_for_name): Set w32_in_use.
(Fx_open_connection): Validate Vwindow_system. Set w32_in_use.
(w32_create_window): Set window size to frame dimensions.
Set font width, line height, border, scrollbar indexes.
Don't set X and Y units indexes.
(w32_msg_pump): Renamed from windows_msg_worker.
Make static. Don't post done message. No longer handle
create scrollbar message. Don't abort on anomalous messages.
Return when completion detected.
(w32_wnd_proc): Keep track of button state.
For WINDOWPOSCHANGING, force window dimensions to be multiples
of character dimensions.
Handle CREATESCROLLBAR.
Use correct arguments for SHOWWINDOW.
For SETWINDOWPOS, use WINDOWPOS structure.
(my_create_window): Abort if message post fails.
(Fx_create_frame): Use title instead of name.
GC protect frame before make_frame_without_minibuffer.
Set icon name.
Use courier new as default font (has bold and italic).
Set BufferPredicate and Title default parameters.
(x_to_w32_weight): Support semibold weight.
(x_to_w32_charset): Map # to numeric charset identifier.
(w32_to_x_charset): Encode unknown charsets as a number.
(enum_font_cb2): Don't restrict to ANSI and OEM charsets.
(Fx_color_values): Set high and low words of color values.
(syms_of_w32fns): Zero w32_in_use. defsubr new functions.
(w32_wnd_proc): Pass on WM_DISPLAYCHANGE messages.
(win32_wnd_proc): Capture and handle WM_MOUSEWHEEL events.
Capture and handle WM_EMACS_TRACKPOPUPMENU events.
Allow a dragged selection from a popup menu started up
by a mouse down event.
(x_to_win32_color): Support for X Windows RGB string specifications.
author | Geoff Voelker <voelker@cs.washington.edu> |
---|---|
date | Wed, 03 Sep 1997 00:47:47 +0000 |
parents | eaa60432140c |
children | d191a8737145 |
comparison
equal
deleted
inserted
replaced
19706:e21b63afe61f | 19707:0181cc080316 |
---|---|
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | 18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
19 Boston, MA 02111-1307, USA. */ | 19 Boston, MA 02111-1307, USA. */ |
20 | 20 |
21 /* Added by Kevin Gallo */ | 21 /* Added by Kevin Gallo */ |
22 | 22 |
23 #include <config.h> | |
24 | |
23 #include <signal.h> | 25 #include <signal.h> |
24 #include <config.h> | |
25 #include <stdio.h> | 26 #include <stdio.h> |
27 #include <limits.h> | |
28 #include <errno.h> | |
26 | 29 |
27 #include "lisp.h" | 30 #include "lisp.h" |
28 #include "w32term.h" | 31 #include "w32term.h" |
29 #include "frame.h" | 32 #include "frame.h" |
30 #include "window.h" | 33 #include "window.h" |
84 /* The shape when over mouse-sensitive text. */ | 87 /* The shape when over mouse-sensitive text. */ |
85 Lisp_Object Vx_sensitive_text_pointer_shape; | 88 Lisp_Object Vx_sensitive_text_pointer_shape; |
86 | 89 |
87 /* Color of chars displayed in cursor box. */ | 90 /* Color of chars displayed in cursor box. */ |
88 Lisp_Object Vx_cursor_fore_pixel; | 91 Lisp_Object Vx_cursor_fore_pixel; |
92 | |
93 /* Nonzero if using Windows. */ | |
94 static int w32_in_use; | |
89 | 95 |
90 /* Search path for bitmap files. */ | 96 /* Search path for bitmap files. */ |
91 Lisp_Object Vx_bitmap_file_path; | 97 Lisp_Object Vx_bitmap_file_path; |
92 | 98 |
93 /* Evaluate this expression to rebuild the section of syms_of_w32fns | 99 /* Evaluate this expression to rebuild the section of syms_of_w32fns |
173 #define MOUSE_BUTTON_ID 1 | 179 #define MOUSE_BUTTON_ID 1 |
174 #define MOUSE_MOVE_ID 2 | 180 #define MOUSE_MOVE_ID 2 |
175 | 181 |
176 /* The below are defined in frame.c. */ | 182 /* The below are defined in frame.c. */ |
177 extern Lisp_Object Qheight, Qminibuffer, Qname, Qonly, Qwidth; | 183 extern Lisp_Object Qheight, Qminibuffer, Qname, Qonly, Qwidth; |
178 extern Lisp_Object Qunsplittable, Qmenu_bar_lines; | 184 extern Lisp_Object Qunsplittable, Qmenu_bar_lines, Qbuffer_predicate, Qtitle; |
179 | 185 |
180 extern Lisp_Object Vwindow_system_version; | 186 extern Lisp_Object Vwindow_system_version; |
181 | 187 |
182 extern Lisp_Object last_mouse_scroll_bar; | 188 extern Lisp_Object last_mouse_scroll_bar; |
183 extern int last_mouse_scroll_bar_pos; | 189 extern int last_mouse_scroll_bar_pos; |
184 | 190 |
185 /* From w32term.c. */ | 191 /* From w32term.c. */ |
186 extern Lisp_Object Vw32_num_mouse_buttons; | 192 extern Lisp_Object Vw32_num_mouse_buttons; |
187 | 193 |
188 Time last_mouse_movement_time; | |
189 | |
190 | 194 |
195 /* Error if we are not connected to MS-Windows. */ | |
196 void | |
197 check_w32 () | |
198 { | |
199 if (! w32_in_use) | |
200 error ("MS-Windows not in use or not initialized"); | |
201 } | |
202 | |
203 /* Nonzero if we can use mouse menus. | |
204 You should not call this unless HAVE_MENUS is defined. */ | |
205 | |
206 int | |
207 have_menus_p () | |
208 { | |
209 return w32_in_use; | |
210 } | |
211 | |
191 /* Extract a frame as a FRAME_PTR, defaulting to the selected frame | 212 /* Extract a frame as a FRAME_PTR, defaulting to the selected frame |
192 and checking validity for W32. */ | 213 and checking validity for W32. */ |
193 | 214 |
194 FRAME_PTR | 215 FRAME_PTR |
195 check_x_frame (frame) | 216 check_x_frame (frame) |
535 void x_set_autolower (); | 556 void x_set_autolower (); |
536 void x_set_vertical_scroll_bars (); | 557 void x_set_vertical_scroll_bars (); |
537 void x_set_visibility (); | 558 void x_set_visibility (); |
538 void x_set_menu_bar_lines (); | 559 void x_set_menu_bar_lines (); |
539 void x_set_scroll_bar_width (); | 560 void x_set_scroll_bar_width (); |
561 void x_set_title (); | |
540 void x_set_unsplittable (); | 562 void x_set_unsplittable (); |
541 | 563 |
542 static struct x_frame_parm_table x_frame_parms[] = | 564 static struct x_frame_parm_table x_frame_parms[] = |
543 { | 565 { |
544 "foreground-color", x_set_foreground_color, | |
545 "background-color", x_set_background_color, | |
546 "mouse-color", x_set_mouse_color, | |
547 "cursor-color", x_set_cursor_color, | |
548 "border-color", x_set_border_color, | |
549 "cursor-type", x_set_cursor_type, | |
550 "icon-type", x_set_icon_type, | |
551 "icon-name", x_set_icon_name, | |
552 "font", x_set_font, | |
553 "border-width", x_set_border_width, | |
554 "internal-border-width", x_set_internal_border_width, | |
555 "name", x_explicitly_set_name, | |
556 "auto-raise", x_set_autoraise, | 566 "auto-raise", x_set_autoraise, |
557 "auto-lower", x_set_autolower, | 567 "auto-lower", x_set_autolower, |
568 "background-color", x_set_background_color, | |
569 "border-color", x_set_border_color, | |
570 "border-width", x_set_border_width, | |
571 "cursor-color", x_set_cursor_color, | |
572 "cursor-type", x_set_cursor_type, | |
573 "font", x_set_font, | |
574 "foreground-color", x_set_foreground_color, | |
575 "icon-name", x_set_icon_name, | |
576 "icon-type", x_set_icon_type, | |
577 "internal-border-width", x_set_internal_border_width, | |
578 "menu-bar-lines", x_set_menu_bar_lines, | |
579 "mouse-color", x_set_mouse_color, | |
580 "name", x_explicitly_set_name, | |
581 "scroll-bar-width", x_set_scroll_bar_width, | |
582 "title", x_set_title, | |
583 "unsplittable", x_set_unsplittable, | |
558 "vertical-scroll-bars", x_set_vertical_scroll_bars, | 584 "vertical-scroll-bars", x_set_vertical_scroll_bars, |
559 "visibility", x_set_visibility, | 585 "visibility", x_set_visibility, |
560 "menu-bar-lines", x_set_menu_bar_lines, | |
561 "scroll-bar-width", x_set_scroll_bar_width, | |
562 "unsplittable", x_set_unsplittable, | |
563 }; | 586 }; |
564 | 587 |
565 /* Attach the `x-frame-parameter' properties to | 588 /* Attach the `x-frame-parameter' properties to |
566 the Lisp symbol names of parameters relevant to W32. */ | 589 the Lisp symbol names of parameters relevant to W32. */ |
567 | 590 |
1242 char * colorname; | 1265 char * colorname; |
1243 { | 1266 { |
1244 register Lisp_Object tail, ret = Qnil; | 1267 register Lisp_Object tail, ret = Qnil; |
1245 | 1268 |
1246 BLOCK_INPUT; | 1269 BLOCK_INPUT; |
1270 | |
1271 if (colorname[0] == '#') | |
1272 { | |
1273 /* Could be an old-style RGB Device specification. */ | |
1274 char *color; | |
1275 int size; | |
1276 color = colorname + 1; | |
1277 | |
1278 size = strlen(color); | |
1279 if (size == 3 || size == 6 || size == 9 || size == 12) | |
1280 { | |
1281 UINT colorval; | |
1282 int i, pos; | |
1283 pos = 0; | |
1284 size /= 3; | |
1285 colorval = 0; | |
1286 | |
1287 for (i = 0; i < 3; i++) | |
1288 { | |
1289 char *end; | |
1290 char t; | |
1291 unsigned long value; | |
1292 | |
1293 /* The check for 'x' in the following conditional takes into | |
1294 account the fact that strtol allows a "0x" in front of | |
1295 our numbers, and we don't. */ | |
1296 if (!isxdigit(color[0]) || color[1] == 'x') | |
1297 break; | |
1298 t = color[size]; | |
1299 color[size] = '\0'; | |
1300 value = strtoul(color, &end, 16); | |
1301 color[size] = t; | |
1302 if (errno == ERANGE || end - color != size) | |
1303 break; | |
1304 switch (size) | |
1305 { | |
1306 case 1: | |
1307 value = value * 0x10; | |
1308 break; | |
1309 case 2: | |
1310 break; | |
1311 case 3: | |
1312 value /= 0x10; | |
1313 break; | |
1314 case 4: | |
1315 value /= 0x100; | |
1316 break; | |
1317 } | |
1318 colorval |= (value << pos); | |
1319 pos += 0x8; | |
1320 if (i == 2) | |
1321 { | |
1322 UNBLOCK_INPUT; | |
1323 return (colorval); | |
1324 } | |
1325 color = end; | |
1326 } | |
1327 } | |
1328 } | |
1329 else if (strnicmp(colorname, "rgb:", 4) == 0) | |
1330 { | |
1331 char *color; | |
1332 UINT colorval; | |
1333 int i, pos; | |
1334 pos = 0; | |
1335 | |
1336 colorval = 0; | |
1337 color = colorname + 4; | |
1338 for (i = 0; i < 3; i++) | |
1339 { | |
1340 char *end; | |
1341 unsigned long value; | |
1342 | |
1343 /* The check for 'x' in the following conditional takes into | |
1344 account the fact that strtol allows a "0x" in front of | |
1345 our numbers, and we don't. */ | |
1346 if (!isxdigit(color[0]) || color[1] == 'x') | |
1347 break; | |
1348 value = strtoul(color, &end, 16); | |
1349 if (errno == ERANGE) | |
1350 break; | |
1351 switch (end - color) | |
1352 { | |
1353 case 1: | |
1354 value = value * 0x10 + value; | |
1355 break; | |
1356 case 2: | |
1357 break; | |
1358 case 3: | |
1359 value /= 0x10; | |
1360 break; | |
1361 case 4: | |
1362 value /= 0x100; | |
1363 break; | |
1364 default: | |
1365 value = ULONG_MAX; | |
1366 } | |
1367 if (value == ULONG_MAX) | |
1368 break; | |
1369 colorval |= (value << pos); | |
1370 pos += 0x8; | |
1371 if (i == 2) | |
1372 { | |
1373 if (*end != '\0') | |
1374 break; | |
1375 UNBLOCK_INPUT; | |
1376 return (colorval); | |
1377 } | |
1378 if (*end != '/') | |
1379 break; | |
1380 color = end + 1; | |
1381 } | |
1382 } | |
1383 else if (strnicmp(colorname, "rgbi:", 5) == 0) | |
1384 { | |
1385 /* This is an RGB Intensity specification. */ | |
1386 char *color; | |
1387 UINT colorval; | |
1388 int i, pos; | |
1389 pos = 0; | |
1390 | |
1391 colorval = 0; | |
1392 color = colorname + 5; | |
1393 for (i = 0; i < 3; i++) | |
1394 { | |
1395 char *end; | |
1396 double value; | |
1397 UINT val; | |
1398 | |
1399 value = strtod(color, &end); | |
1400 if (errno == ERANGE) | |
1401 break; | |
1402 if (value < 0.0 || value > 1.0) | |
1403 break; | |
1404 val = (UINT)(0x100 * value); | |
1405 /* We used 0x100 instead of 0xFF to give an continuous | |
1406 range between 0.0 and 1.0 inclusive. The next statement | |
1407 fixes the 1.0 case. */ | |
1408 if (val == 0x100) | |
1409 val = 0xFF; | |
1410 colorval |= (val << pos); | |
1411 pos += 0x8; | |
1412 if (i == 2) | |
1413 { | |
1414 if (*end != '\0') | |
1415 break; | |
1416 UNBLOCK_INPUT; | |
1417 return (colorval); | |
1418 } | |
1419 if (*end != '/') | |
1420 break; | |
1421 color = end + 1; | |
1422 } | |
1423 } | |
1424 /* I am not going to attempt to handle any of the CIE color schemes | |
1425 or TekHVC, since I don't know the algorithms for conversion to | |
1426 RGB. */ | |
1247 | 1427 |
1248 for (tail = Vw32_color_map; !NILP (tail); tail = Fcdr (tail)) | 1428 for (tail = Vw32_color_map; !NILP (tail); tail = Fcdr (tail)) |
1249 { | 1429 { |
1250 register Lisp_Object elt, tem; | 1430 register Lisp_Object elt, tem; |
1251 | 1431 |
1825 return; | 2005 return; |
1826 | 2006 |
1827 BLOCK_INPUT; | 2007 BLOCK_INPUT; |
1828 | 2008 |
1829 result = x_text_icon (f, | 2009 result = x_text_icon (f, |
1830 (char *) XSTRING ((!NILP (f->icon_name) | 2010 (char *) XSTRING ((!NILP (f->icon_name) |
1831 ? f->icon_name | 2011 ? f->icon_name |
2012 : !NILP (f->title) | |
2013 ? f->title | |
1832 : f->name))->data); | 2014 : f->name))->data); |
1833 | 2015 |
1834 if (result) | 2016 if (result) |
1835 { | 2017 { |
1836 UNBLOCK_INPUT; | 2018 UNBLOCK_INPUT; |
1963 else | 2145 else |
1964 { | 2146 { |
1965 if (FRAME_EXTERNAL_MENU_BAR (f) == 1) | 2147 if (FRAME_EXTERNAL_MENU_BAR (f) == 1) |
1966 free_frame_menubar (f); | 2148 free_frame_menubar (f); |
1967 FRAME_EXTERNAL_MENU_BAR (f) = 0; | 2149 FRAME_EXTERNAL_MENU_BAR (f) = 0; |
2150 | |
2151 /* Adjust the frame size so that the client (text) dimensions | |
2152 remain the same. This depends on FRAME_EXTERNAL_MENU_BAR being | |
2153 set correctly. */ | |
2154 x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f)); | |
1968 } | 2155 } |
1969 } | 2156 } |
1970 | 2157 |
1971 /* Change the name of frame F to NAME. If NAME is nil, set F's name to | 2158 /* Change the name of frame F to NAME. If NAME is nil, set F's name to |
1972 w32_id_name. | 2159 w32_id_name. |
2014 | 2201 |
2015 /* Don't change the name if it's already NAME. */ | 2202 /* Don't change the name if it's already NAME. */ |
2016 if (! NILP (Fstring_equal (name, f->name))) | 2203 if (! NILP (Fstring_equal (name, f->name))) |
2017 return; | 2204 return; |
2018 | 2205 |
2206 f->name = name; | |
2207 | |
2208 /* For setting the frame title, the title parameter should override | |
2209 the name parameter. */ | |
2210 if (! NILP (f->title)) | |
2211 name = f->title; | |
2212 | |
2019 if (FRAME_W32_WINDOW (f)) | 2213 if (FRAME_W32_WINDOW (f)) |
2020 { | 2214 { |
2021 BLOCK_INPUT; | 2215 BLOCK_INPUT; |
2022 SetWindowText(FRAME_W32_WINDOW (f), XSTRING (name)->data); | 2216 SetWindowText(FRAME_W32_WINDOW (f), XSTRING (name)->data); |
2023 UNBLOCK_INPUT; | 2217 UNBLOCK_INPUT; |
2024 } | 2218 } |
2025 | |
2026 f->name = name; | |
2027 } | 2219 } |
2028 | 2220 |
2029 /* This function should be called when the user's lisp code has | 2221 /* This function should be called when the user's lisp code has |
2030 specified a name for the frame; the name will override any set by the | 2222 specified a name for the frame; the name will override any set by the |
2031 redisplay code. */ | 2223 redisplay code. */ |
2045 FRAME_PTR f; | 2237 FRAME_PTR f; |
2046 Lisp_Object arg, oldval; | 2238 Lisp_Object arg, oldval; |
2047 { | 2239 { |
2048 x_set_name (f, arg, 0); | 2240 x_set_name (f, arg, 0); |
2049 } | 2241 } |
2050 | 2242 |
2243 /* Change the title of frame F to NAME. | |
2244 If NAME is nil, use the frame name as the title. | |
2245 | |
2246 If EXPLICIT is non-zero, that indicates that lisp code is setting the | |
2247 name; if NAME is a string, set F's name to NAME and set | |
2248 F->explicit_name; if NAME is Qnil, then clear F->explicit_name. | |
2249 | |
2250 If EXPLICIT is zero, that indicates that Emacs redisplay code is | |
2251 suggesting a new name, which lisp code should override; if | |
2252 F->explicit_name is set, ignore the new name; otherwise, set it. */ | |
2253 | |
2254 void | |
2255 x_set_title (f, name) | |
2256 struct frame *f; | |
2257 Lisp_Object name; | |
2258 { | |
2259 /* Don't change the title if it's already NAME. */ | |
2260 if (EQ (name, f->title)) | |
2261 return; | |
2262 | |
2263 update_mode_lines = 1; | |
2264 | |
2265 f->title = name; | |
2266 | |
2267 if (NILP (name)) | |
2268 name = f->name; | |
2269 | |
2270 if (FRAME_W32_WINDOW (f)) | |
2271 { | |
2272 BLOCK_INPUT; | |
2273 SetWindowText(FRAME_W32_WINDOW (f), XSTRING (name)->data); | |
2274 UNBLOCK_INPUT; | |
2275 } | |
2276 } | |
2277 | |
2051 void | 2278 void |
2052 x_set_autoraise (f, arg, oldval) | 2279 x_set_autoraise (f, arg, oldval) |
2053 struct frame *f; | 2280 struct frame *f; |
2054 Lisp_Object arg, oldval; | 2281 Lisp_Object arg, oldval; |
2055 { | 2282 { |
2620 void | 2847 void |
2621 w32_createwindow (f) | 2848 w32_createwindow (f) |
2622 struct frame *f; | 2849 struct frame *f; |
2623 { | 2850 { |
2624 HWND hwnd; | 2851 HWND hwnd; |
2852 RECT rect; | |
2853 | |
2854 rect.left = rect.top = 0; | |
2855 rect.right = PIXEL_WIDTH (f); | |
2856 rect.bottom = PIXEL_HEIGHT (f); | |
2857 | |
2858 AdjustWindowRect (&rect, f->output_data.w32->dwStyle, | |
2859 FRAME_EXTERNAL_MENU_BAR (f)); | |
2625 | 2860 |
2626 /* Do first time app init */ | 2861 /* Do first time app init */ |
2627 | 2862 |
2628 if (!hprevinst) | 2863 if (!hprevinst) |
2629 { | 2864 { |
2630 w32_init_class (hinst); | 2865 w32_init_class (hinst); |
2631 } | 2866 } |
2632 | 2867 |
2633 FRAME_W32_WINDOW (f) = hwnd = CreateWindow (EMACS_CLASS, | 2868 FRAME_W32_WINDOW (f) = hwnd |
2634 f->namebuf, | 2869 = CreateWindow (EMACS_CLASS, |
2635 f->output_data.w32->dwStyle | WS_CLIPCHILDREN, | 2870 f->namebuf, |
2636 f->output_data.w32->left_pos, | 2871 f->output_data.w32->dwStyle | WS_CLIPCHILDREN, |
2637 f->output_data.w32->top_pos, | 2872 f->output_data.w32->left_pos, |
2638 PIXEL_WIDTH (f), | 2873 f->output_data.w32->top_pos, |
2639 PIXEL_HEIGHT (f), | 2874 rect.right - rect.left, |
2640 NULL, | 2875 rect.bottom - rect.top, |
2641 NULL, | 2876 NULL, |
2642 hinst, | 2877 NULL, |
2643 NULL); | 2878 hinst, |
2644 | 2879 NULL); |
2880 | |
2645 if (hwnd) | 2881 if (hwnd) |
2646 { | 2882 { |
2647 SetWindowLong (hwnd, WND_X_UNITS_INDEX, FONT_WIDTH (f->output_data.w32->font)); | 2883 SetWindowLong (hwnd, WND_FONTWIDTH_INDEX, FONT_WIDTH (f->output_data.w32->font)); |
2648 SetWindowLong (hwnd, WND_Y_UNITS_INDEX, f->output_data.w32->line_height); | 2884 SetWindowLong (hwnd, WND_LINEHEIGHT_INDEX, f->output_data.w32->line_height); |
2885 SetWindowLong (hwnd, WND_BORDER_INDEX, f->output_data.w32->internal_border_width); | |
2886 SetWindowLong (hwnd, WND_SCROLLBAR_INDEX, f->output_data.w32->vertical_scroll_bar_extra); | |
2649 SetWindowLong (hwnd, WND_BACKGROUND_INDEX, f->output_data.w32->background_pixel); | 2887 SetWindowLong (hwnd, WND_BACKGROUND_INDEX, f->output_data.w32->background_pixel); |
2650 | 2888 |
2651 /* Do this to discard the default setting specified by our parent. */ | 2889 /* Do this to discard the default setting specified by our parent. */ |
2652 ShowWindow (hwnd, SW_HIDE); | 2890 ShowWindow (hwnd, SW_HIDE); |
2653 } | 2891 } |
2877 return wparam; | 3115 return wparam; |
2878 } | 3116 } |
2879 | 3117 |
2880 /* Main message dispatch loop. */ | 3118 /* Main message dispatch loop. */ |
2881 | 3119 |
2882 DWORD | 3120 static void |
2883 windows_msg_worker (dw) | 3121 w32_msg_pump (deferred_msg * msg_buf) |
2884 DWORD dw; | |
2885 { | 3122 { |
2886 MSG msg; | 3123 MSG msg; |
2887 | |
2888 /* Ensure our message queue is created */ | |
2889 | |
2890 PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE); | |
2891 | |
2892 PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, 0, 0); | |
2893 | 3124 |
2894 while (GetMessage (&msg, NULL, 0, 0)) | 3125 while (GetMessage (&msg, NULL, 0, 0)) |
2895 { | 3126 { |
2896 if (msg.hwnd == NULL) | 3127 if (msg.hwnd == NULL) |
2897 { | 3128 { |
2898 switch (msg.message) | 3129 switch (msg.message) |
2899 { | 3130 { |
2900 case WM_EMACS_CREATEWINDOW: | 3131 case WM_EMACS_CREATEWINDOW: |
2901 w32_createwindow ((struct frame *) msg.wParam); | 3132 w32_createwindow ((struct frame *) msg.wParam); |
2902 PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, 0, 0); | 3133 if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, 0, 0)) |
3134 abort (); | |
2903 break; | 3135 break; |
2904 case WM_EMACS_CREATESCROLLBAR: | 3136 default: |
2905 { | 3137 /* No need to be so draconian! */ |
2906 HWND hwnd = w32_createscrollbar ((struct frame *) msg.wParam, | 3138 /* abort (); */ |
2907 (struct scroll_bar *) msg.lParam); | 3139 DebPrint (("msg %x not expected by w32_msg_pump\n", msg.message)); |
2908 PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, (WPARAM)hwnd, 0); | |
2909 } | |
2910 break; | |
2911 case WM_EMACS_KILL: | |
2912 return (0); | |
2913 } | 3140 } |
2914 } | 3141 } |
2915 else | 3142 else |
2916 { | 3143 { |
2917 DispatchMessage (&msg); | 3144 DispatchMessage (&msg); |
2918 } | 3145 } |
2919 } | 3146 |
3147 /* Exit nested loop when our deferred message has completed. */ | |
3148 if (msg_buf->completed) | |
3149 break; | |
3150 } | |
3151 } | |
3152 | |
3153 deferred_msg * deferred_msg_head; | |
3154 | |
3155 static deferred_msg * | |
3156 find_deferred_msg (HWND hwnd, UINT msg) | |
3157 { | |
3158 deferred_msg * item; | |
3159 | |
3160 /* Don't actually need synchronization for read access, since | |
3161 modification of single pointer is always atomic. */ | |
3162 /* enter_crit (); */ | |
3163 | |
3164 for (item = deferred_msg_head; item != NULL; item = item->next) | |
3165 if (item->w32msg.msg.hwnd == hwnd | |
3166 && item->w32msg.msg.message == msg) | |
3167 break; | |
3168 | |
3169 /* leave_crit (); */ | |
3170 | |
3171 return item; | |
3172 } | |
3173 | |
3174 static LRESULT | |
3175 send_deferred_msg (deferred_msg * msg_buf, | |
3176 HWND hwnd, | |
3177 UINT msg, | |
3178 WPARAM wParam, | |
3179 LPARAM lParam) | |
3180 { | |
3181 /* Only input thread can send deferred messages. */ | |
3182 if (GetCurrentThreadId () != dwWindowsThreadId) | |
3183 abort (); | |
3184 | |
3185 /* It is an error to send a message that is already deferred. */ | |
3186 if (find_deferred_msg (hwnd, msg) != NULL) | |
3187 abort (); | |
3188 | |
3189 /* Enforced synchronization is not needed because this is the only | |
3190 function that alters deferred_msg_head, and the following critical | |
3191 section is guaranteed to only be serially reentered (since only the | |
3192 input thread can call us). */ | |
3193 | |
3194 /* enter_crit (); */ | |
3195 | |
3196 msg_buf->completed = 0; | |
3197 msg_buf->next = deferred_msg_head; | |
3198 deferred_msg_head = msg_buf; | |
3199 my_post_msg (&msg_buf->w32msg, hwnd, msg, wParam, lParam); | |
3200 | |
3201 /* leave_crit (); */ | |
3202 | |
3203 /* Start a new nested message loop to process other messages until | |
3204 this one is completed. */ | |
3205 w32_msg_pump (msg_buf); | |
3206 | |
3207 deferred_msg_head = msg_buf->next; | |
3208 | |
3209 return msg_buf->result; | |
3210 } | |
3211 | |
3212 void | |
3213 complete_deferred_msg (HWND hwnd, UINT msg, LRESULT result) | |
3214 { | |
3215 deferred_msg * msg_buf = find_deferred_msg (hwnd, msg); | |
3216 | |
3217 if (msg_buf == NULL) | |
3218 abort (); | |
3219 | |
3220 msg_buf->result = result; | |
3221 msg_buf->completed = 1; | |
3222 | |
3223 /* Ensure input thread is woken so it notices the completion. */ | |
3224 PostThreadMessage (dwWindowsThreadId, WM_NULL, 0, 0); | |
3225 } | |
3226 | |
3227 | |
3228 DWORD | |
3229 w32_msg_worker (dw) | |
3230 DWORD dw; | |
3231 { | |
3232 MSG msg; | |
3233 deferred_msg dummy_buf; | |
3234 | |
3235 /* Ensure our message queue is created */ | |
2920 | 3236 |
2921 return (0); | 3237 PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE); |
3238 | |
3239 if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, 0, 0)) | |
3240 abort (); | |
3241 | |
3242 memset (&dummy_buf, 0, sizeof (dummy_buf)); | |
3243 dummy_buf.w32msg.msg.hwnd = NULL; | |
3244 dummy_buf.w32msg.msg.message = WM_NULL; | |
3245 | |
3246 /* This is the inital message loop which should only exit when the | |
3247 application quits. */ | |
3248 w32_msg_pump (&dummy_buf); | |
3249 | |
3250 return 0; | |
2922 } | 3251 } |
2923 | 3252 |
2924 /* Main window procedure */ | 3253 /* Main window procedure */ |
2925 | 3254 |
2926 extern char *lispy_function_keys[]; | 3255 extern char *lispy_function_keys[]; |
2931 UINT msg; | 3260 UINT msg; |
2932 WPARAM wParam; | 3261 WPARAM wParam; |
2933 LPARAM lParam; | 3262 LPARAM lParam; |
2934 { | 3263 { |
2935 struct frame *f; | 3264 struct frame *f; |
2936 LRESULT ret = 1; | |
2937 struct w32_display_info *dpyinfo = &one_w32_display_info; | 3265 struct w32_display_info *dpyinfo = &one_w32_display_info; |
2938 W32Msg wmsg; | 3266 W32Msg wmsg; |
2939 int windows_translate; | 3267 int windows_translate; |
2940 | 3268 |
2941 /* Note that it is okay to call x_window_to_frame, even though we are | 3269 /* Note that it is okay to call x_window_to_frame, even though we are |
3189 case WM_MBUTTONDOWN: | 3517 case WM_MBUTTONDOWN: |
3190 case WM_MBUTTONUP: | 3518 case WM_MBUTTONUP: |
3191 handle_plain_button: | 3519 handle_plain_button: |
3192 { | 3520 { |
3193 BOOL up; | 3521 BOOL up; |
3194 | 3522 int button; |
3195 if (parse_button (msg, NULL, &up)) | 3523 |
3524 if (parse_button (msg, &button, &up)) | |
3196 { | 3525 { |
3197 if (up) ReleaseCapture (); | 3526 if (up) ReleaseCapture (); |
3198 else SetCapture (hwnd); | 3527 else SetCapture (hwnd); |
3528 button = (button == 0) ? LMOUSE : | |
3529 ((button == 1) ? MMOUSE : RMOUSE); | |
3530 if (up) | |
3531 button_state &= ~button; | |
3532 else | |
3533 button_state |= button; | |
3199 } | 3534 } |
3200 } | 3535 } |
3201 | 3536 |
3202 wmsg.dwModifiers = w32_get_modifiers (); | 3537 wmsg.dwModifiers = w32_get_modifiers (); |
3203 my_post_msg (&wmsg, hwnd, msg, wParam, lParam); | 3538 my_post_msg (&wmsg, hwnd, msg, wParam, lParam); |
3228 saved_mouse_move_msg.msg.wParam = wParam; | 3563 saved_mouse_move_msg.msg.wParam = wParam; |
3229 saved_mouse_move_msg.msg.lParam = lParam; | 3564 saved_mouse_move_msg.msg.lParam = lParam; |
3230 saved_mouse_move_msg.msg.time = GetMessageTime (); | 3565 saved_mouse_move_msg.msg.time = GetMessageTime (); |
3231 saved_mouse_move_msg.dwModifiers = w32_get_modifiers (); | 3566 saved_mouse_move_msg.dwModifiers = w32_get_modifiers (); |
3232 | 3567 |
3568 return 0; | |
3569 | |
3570 case WM_MOUSEWHEEL: | |
3571 wmsg.dwModifiers = w32_get_modifiers (); | |
3572 my_post_msg (&wmsg, hwnd, msg, wParam, lParam); | |
3233 return 0; | 3573 return 0; |
3234 | 3574 |
3235 case WM_TIMER: | 3575 case WM_TIMER: |
3236 /* Flush out saved messages if necessary. */ | 3576 /* Flush out saved messages if necessary. */ |
3237 if (wParam == mouse_button_timer) | 3577 if (wParam == mouse_button_timer) |
3263 this message afterwards. So this is a good time to reset our | 3603 this message afterwards. So this is a good time to reset our |
3264 keyboard modifiers' state. */ | 3604 keyboard modifiers' state. */ |
3265 reset_modifiers (); | 3605 reset_modifiers (); |
3266 goto dflt; | 3606 goto dflt; |
3267 | 3607 |
3608 case WM_INITMENU: | |
3609 /* We must ensure menu bar is fully constructed and up to date | |
3610 before allowing user interaction with it. To achieve this | |
3611 we send this message to the lisp thread and wait for a | |
3612 reply (whose value is not actually needed) to indicate that | |
3613 the menu bar is now ready for use, so we can now return. | |
3614 | |
3615 To remain responsive in the meantime, we enter a nested message | |
3616 loop that can process all other messages. | |
3617 | |
3618 However, we skip all this if the message results from calling | |
3619 TrackPopupMenu - in fact, we must NOT attempt to send the lisp | |
3620 thread a message because it is blocked on us at this point. We | |
3621 set menubar_active before calling TrackPopupMenu to indicate | |
3622 this (there is no possibility of confusion with real menubar | |
3623 being active). */ | |
3624 | |
3625 f = x_window_to_frame (dpyinfo, hwnd); | |
3626 if (f | |
3627 && (f->output_data.w32->menubar_active | |
3628 /* We can receive this message even in the absence of a | |
3629 menubar (ie. when the system menu is activated) - in this | |
3630 case we do NOT want to forward the message, otherwise it | |
3631 will cause the menubar to suddenly appear when the user | |
3632 had requested it to be turned off! */ | |
3633 || f->output_data.w32->menubar_widget == NULL)) | |
3634 return 0; | |
3635 | |
3636 { | |
3637 deferred_msg msg_buf; | |
3638 | |
3639 /* Detect if message has already been deferred; in this case | |
3640 we cannot return any sensible value to ignore this. */ | |
3641 if (find_deferred_msg (hwnd, msg) != NULL) | |
3642 abort (); | |
3643 | |
3644 return send_deferred_msg (&msg_buf, hwnd, msg, wParam, lParam); | |
3645 } | |
3646 | |
3647 case WM_EXITMENULOOP: | |
3648 f = x_window_to_frame (dpyinfo, hwnd); | |
3649 | |
3650 /* Indicate that menubar can be modified again. */ | |
3651 if (f) | |
3652 f->output_data.w32->menubar_active = 0; | |
3653 goto dflt; | |
3654 | |
3655 #if 0 | |
3656 /* Still not right - can't distinguish between clicks in the | |
3657 client area of the frame from clicks forwarded from the scroll | |
3658 bars - may have to hook WM_NCHITTEST to remember the mouse | |
3659 position and then check if it is in the client area ourselves. */ | |
3660 case WM_MOUSEACTIVATE: | |
3661 /* Discard the mouse click that activates a frame, allowing the | |
3662 user to click anywhere without changing point (or worse!). | |
3663 Don't eat mouse clicks on scrollbars though!! */ | |
3664 if (LOWORD (lParam) == HTCLIENT ) | |
3665 return MA_ACTIVATEANDEAT; | |
3666 goto dflt; | |
3667 #endif | |
3668 | |
3669 case WM_ACTIVATE: | |
3670 case WM_ACTIVATEAPP: | |
3671 case WM_WINDOWPOSCHANGED: | |
3672 case WM_SHOWWINDOW: | |
3673 /* Inform lisp thread that a frame might have just been obscured | |
3674 or exposed, so should recheck visibility of all frames. */ | |
3675 my_post_msg (&wmsg, hwnd, msg, wParam, lParam); | |
3676 goto dflt; | |
3677 | |
3268 case WM_SETFOCUS: | 3678 case WM_SETFOCUS: |
3269 reset_modifiers (); | 3679 reset_modifiers (); |
3270 case WM_KILLFOCUS: | 3680 case WM_KILLFOCUS: |
3271 case WM_MOVE: | 3681 case WM_MOVE: |
3272 case WM_SIZE: | 3682 case WM_SIZE: |
3273 case WM_SYSCOMMAND: | |
3274 case WM_COMMAND: | 3683 case WM_COMMAND: |
3275 wmsg.dwModifiers = w32_get_modifiers (); | 3684 wmsg.dwModifiers = w32_get_modifiers (); |
3276 my_post_msg (&wmsg, hwnd, msg, wParam, lParam); | 3685 my_post_msg (&wmsg, hwnd, msg, wParam, lParam); |
3277 goto dflt; | 3686 goto dflt; |
3278 | 3687 |
3283 | 3692 |
3284 case WM_WINDOWPOSCHANGING: | 3693 case WM_WINDOWPOSCHANGING: |
3285 { | 3694 { |
3286 WINDOWPLACEMENT wp; | 3695 WINDOWPLACEMENT wp; |
3287 LPWINDOWPOS lppos = (WINDOWPOS *) lParam; | 3696 LPWINDOWPOS lppos = (WINDOWPOS *) lParam; |
3288 | 3697 |
3698 wp.length = sizeof (WINDOWPLACEMENT); | |
3289 GetWindowPlacement (hwnd, &wp); | 3699 GetWindowPlacement (hwnd, &wp); |
3290 | 3700 |
3291 if (wp.showCmd != SW_SHOWMINIMIZED && ! (lppos->flags & SWP_NOSIZE)) | 3701 if (wp.showCmd != SW_SHOWMINIMIZED && (lppos->flags & SWP_NOSIZE) == 0) |
3292 { | 3702 { |
3293 RECT rect; | 3703 RECT rect; |
3294 int wdiff; | 3704 int wdiff; |
3295 int hdiff; | 3705 int hdiff; |
3296 DWORD dwXUnits; | 3706 DWORD font_width; |
3297 DWORD dwYUnits; | 3707 DWORD line_height; |
3708 DWORD internal_border; | |
3709 DWORD scrollbar_extra; | |
3298 RECT wr; | 3710 RECT wr; |
3299 | 3711 |
3300 wp.length = sizeof(wp); | 3712 wp.length = sizeof(wp); |
3301 GetWindowRect (hwnd, &wr); | 3713 GetWindowRect (hwnd, &wr); |
3302 | 3714 |
3303 enter_crit (); | 3715 enter_crit (); |
3304 | 3716 |
3305 dwXUnits = GetWindowLong (hwnd, WND_X_UNITS_INDEX); | 3717 font_width = GetWindowLong (hwnd, WND_FONTWIDTH_INDEX); |
3306 dwYUnits = GetWindowLong (hwnd, WND_Y_UNITS_INDEX); | 3718 line_height = GetWindowLong (hwnd, WND_LINEHEIGHT_INDEX); |
3719 internal_border = GetWindowLong (hwnd, WND_BORDER_INDEX); | |
3720 scrollbar_extra = GetWindowLong (hwnd, WND_SCROLLBAR_INDEX); | |
3307 | 3721 |
3308 leave_crit (); | 3722 leave_crit (); |
3309 | 3723 |
3310 memset (&rect, 0, sizeof (rect)); | 3724 memset (&rect, 0, sizeof (rect)); |
3311 AdjustWindowRect (&rect, GetWindowLong (hwnd, GWL_STYLE), | 3725 AdjustWindowRect (&rect, GetWindowLong (hwnd, GWL_STYLE), |
3312 GetMenu (hwnd) != NULL); | 3726 GetMenu (hwnd) != NULL); |
3313 | 3727 |
3314 /* All windows have an extra pixel so subtract 1 */ | 3728 /* Force width and height of client area to be exact |
3315 | 3729 multiples of the character cell dimensions. */ |
3316 wdiff = (lppos->cx - (rect.right - rect.left) - 0) % dwXUnits; | 3730 wdiff = (lppos->cx - (rect.right - rect.left) |
3317 hdiff = (lppos->cy - (rect.bottom - rect.top) - 0) % dwYUnits; | 3731 - 2 * internal_border - scrollbar_extra) |
3732 % font_width; | |
3733 hdiff = (lppos->cy - (rect.bottom - rect.top) | |
3734 - 2 * internal_border) | |
3735 % line_height; | |
3318 | 3736 |
3319 if (wdiff || hdiff) | 3737 if (wdiff || hdiff) |
3320 { | 3738 { |
3321 /* For right/bottom sizing we can just fix the sizes. | 3739 /* For right/bottom sizing we can just fix the sizes. |
3322 However for top/left sizing we will need to fix the X | 3740 However for top/left sizing we will need to fix the X |
3324 | 3742 |
3325 lppos->cx -= wdiff; | 3743 lppos->cx -= wdiff; |
3326 lppos->cy -= hdiff; | 3744 lppos->cy -= hdiff; |
3327 | 3745 |
3328 if (wp.showCmd != SW_SHOWMAXIMIZED | 3746 if (wp.showCmd != SW_SHOWMAXIMIZED |
3329 && ! (lppos->flags & SWP_NOMOVE)) | 3747 && (lppos->flags & SWP_NOMOVE) == 0) |
3330 { | 3748 { |
3331 if (lppos->x != wr.left || lppos->y != wr.top) | 3749 if (lppos->x != wr.left || lppos->y != wr.top) |
3332 { | 3750 { |
3333 lppos->x += wdiff; | 3751 lppos->x += wdiff; |
3334 lppos->y += hdiff; | 3752 lppos->y += hdiff; |
3337 { | 3755 { |
3338 lppos->flags |= SWP_NOMOVE; | 3756 lppos->flags |= SWP_NOMOVE; |
3339 } | 3757 } |
3340 } | 3758 } |
3341 | 3759 |
3342 ret = 0; | 3760 return 0; |
3343 } | 3761 } |
3344 } | 3762 } |
3345 } | 3763 } |
3346 | |
3347 if (ret == 0) return (0); | |
3348 | 3764 |
3349 goto dflt; | 3765 goto dflt; |
3766 | |
3767 case WM_EMACS_CREATESCROLLBAR: | |
3768 return (LRESULT) w32_createscrollbar ((struct frame *) wParam, | |
3769 (struct scroll_bar *) lParam); | |
3770 | |
3350 case WM_EMACS_SHOWWINDOW: | 3771 case WM_EMACS_SHOWWINDOW: |
3351 return ShowWindow (hwnd, wParam); | 3772 return ShowWindow ((HWND) wParam, (WPARAM) lParam); |
3773 | |
3352 case WM_EMACS_SETWINDOWPOS: | 3774 case WM_EMACS_SETWINDOWPOS: |
3353 { | 3775 { |
3354 W32WindowPos * pos = (W32WindowPos *) wParam; | 3776 WINDOWPOS * pos = (WINDOWPOS *) wParam; |
3355 return SetWindowPos (hwnd, pos->hwndAfter, | 3777 return SetWindowPos (hwnd, pos->hwndInsertAfter, |
3356 pos->x, pos->y, pos->cx, pos->cy, pos->flags); | 3778 pos->x, pos->y, pos->cx, pos->cy, pos->flags); |
3357 } | 3779 } |
3780 | |
3358 case WM_EMACS_DESTROYWINDOW: | 3781 case WM_EMACS_DESTROYWINDOW: |
3359 DestroyWindow ((HWND) wParam); | 3782 return DestroyWindow ((HWND) wParam); |
3360 break; | 3783 |
3784 case WM_EMACS_TRACKPOPUPMENU: | |
3785 { | |
3786 UINT flags; | |
3787 POINT *pos; | |
3788 int retval; | |
3789 pos = (POINT *)lParam; | |
3790 flags = TPM_CENTERALIGN; | |
3791 if (button_state & LMOUSE) | |
3792 flags |= TPM_LEFTBUTTON; | |
3793 else if (button_state & RMOUSE) | |
3794 flags |= TPM_RIGHTBUTTON; | |
3795 | |
3796 /* Use menubar_active to indicate that WM_INITMENU is from | |
3797 TrackPopupMenu below, and should be ignored. */ | |
3798 f = x_window_to_frame (dpyinfo, hwnd); | |
3799 if (f) | |
3800 f->output_data.w32->menubar_active = 1; | |
3801 | |
3802 if (TrackPopupMenu ((HMENU)wParam, flags, pos->x, pos->y, | |
3803 0, hwnd, NULL)) | |
3804 { | |
3805 MSG amsg; | |
3806 /* Eat any mouse messages during popupmenu */ | |
3807 while (PeekMessage (&amsg, hwnd, WM_MOUSEFIRST, WM_MOUSELAST, | |
3808 PM_REMOVE)); | |
3809 /* Get the menu selection, if any */ | |
3810 if (PeekMessage (&amsg, hwnd, WM_COMMAND, WM_COMMAND, PM_REMOVE)) | |
3811 { | |
3812 retval = LOWORD (amsg.wParam); | |
3813 } | |
3814 else | |
3815 { | |
3816 retval = 0; | |
3817 } | |
3818 button_state = 0; | |
3819 | |
3820 /* Remember we did a SetCapture on the initial mouse down | |
3821 event, but window focus will usually have changed to the | |
3822 popup menu before we released the mouse button. For | |
3823 safety, we make sure the capture is cancelled now. */ | |
3824 ReleaseCapture (); | |
3825 } | |
3826 else | |
3827 { | |
3828 retval = -1; | |
3829 } | |
3830 | |
3831 return retval; | |
3832 } | |
3833 | |
3361 default: | 3834 default: |
3362 dflt: | 3835 dflt: |
3363 return DefWindowProc (hwnd, msg, wParam, lParam); | 3836 return DefWindowProc (hwnd, msg, wParam, lParam); |
3364 } | 3837 } |
3365 | 3838 |
3366 return (1); | 3839 |
3840 /* The most common default return code for handled messages is 0. */ | |
3841 return 0; | |
3367 } | 3842 } |
3368 | 3843 |
3369 void | 3844 void |
3370 my_create_window (f) | 3845 my_create_window (f) |
3371 struct frame * f; | 3846 struct frame * f; |
3372 { | 3847 { |
3373 MSG msg; | 3848 MSG msg; |
3374 | 3849 |
3375 PostThreadMessage (dwWindowsThreadId, WM_EMACS_CREATEWINDOW, (WPARAM)f, 0); | 3850 if (!PostThreadMessage (dwWindowsThreadId, WM_EMACS_CREATEWINDOW, (WPARAM)f, 0)) |
3851 abort (); | |
3376 GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE); | 3852 GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE); |
3377 } | 3853 } |
3378 | 3854 |
3379 /* Create and set up the w32 window for frame F. */ | 3855 /* Create and set up the w32 window for frame F. */ |
3380 | 3856 |
3450 | 3926 |
3451 BLOCK_INPUT; | 3927 BLOCK_INPUT; |
3452 | 3928 |
3453 if (! EQ (icon_x, Qunbound)) | 3929 if (! EQ (icon_x, Qunbound)) |
3454 x_wm_set_icon_position (f, XINT (icon_x), XINT (icon_y)); | 3930 x_wm_set_icon_position (f, XINT (icon_x), XINT (icon_y)); |
3931 | |
3932 #if 0 /* TODO */ | |
3933 /* Start up iconic or window? */ | |
3934 x_wm_set_window_state | |
3935 (f, (EQ (x_get_arg (parms, Qvisibility, 0, 0, symbol), Qicon) | |
3936 ? IconicState | |
3937 : NormalState)); | |
3938 | |
3939 x_text_icon (f, (char *) XSTRING ((!NILP (f->icon_name) | |
3940 ? f->icon_name | |
3941 : f->name))->data); | |
3942 #endif | |
3455 | 3943 |
3456 UNBLOCK_INPUT; | 3944 UNBLOCK_INPUT; |
3457 } | 3945 } |
3458 | 3946 |
3459 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame, | 3947 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame, |
3475 Lisp_Object name; | 3963 Lisp_Object name; |
3476 int minibuffer_only = 0; | 3964 int minibuffer_only = 0; |
3477 long window_prompting = 0; | 3965 long window_prompting = 0; |
3478 int width, height; | 3966 int width, height; |
3479 int count = specpdl_ptr - specpdl; | 3967 int count = specpdl_ptr - specpdl; |
3480 struct gcpro gcpro1; | 3968 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; |
3481 Lisp_Object display; | 3969 Lisp_Object display; |
3482 struct w32_display_info *dpyinfo; | 3970 struct w32_display_info *dpyinfo; |
3483 Lisp_Object parent; | 3971 Lisp_Object parent; |
3484 struct kboard *kb; | 3972 struct kboard *kb; |
3485 | 3973 |
3495 kb = dpyinfo->kboard; | 3983 kb = dpyinfo->kboard; |
3496 #else | 3984 #else |
3497 kb = &the_only_kboard; | 3985 kb = &the_only_kboard; |
3498 #endif | 3986 #endif |
3499 | 3987 |
3500 name = x_get_arg (parms, Qname, "title", "Title", string); | 3988 name = x_get_arg (parms, Qname, "name", "Name", string); |
3501 if (!STRINGP (name) | 3989 if (!STRINGP (name) |
3502 && ! EQ (name, Qunbound) | 3990 && ! EQ (name, Qunbound) |
3503 && ! NILP (name)) | 3991 && ! NILP (name)) |
3504 error ("Invalid frame name--not a string or nil"); | 3992 error ("Invalid frame name--not a string or nil"); |
3505 | 3993 |
3511 if (EQ (parent, Qunbound)) | 3999 if (EQ (parent, Qunbound)) |
3512 parent = Qnil; | 4000 parent = Qnil; |
3513 if (! NILP (parent)) | 4001 if (! NILP (parent)) |
3514 CHECK_NUMBER (parent, 0); | 4002 CHECK_NUMBER (parent, 0); |
3515 | 4003 |
4004 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */ | |
4005 /* No need to protect DISPLAY because that's not used after passing | |
4006 it to make_frame_without_minibuffer. */ | |
4007 frame = Qnil; | |
4008 GCPRO4 (parms, parent, name, frame); | |
3516 tem = x_get_arg (parms, Qminibuffer, 0, 0, symbol); | 4009 tem = x_get_arg (parms, Qminibuffer, 0, 0, symbol); |
3517 if (EQ (tem, Qnone) || NILP (tem)) | 4010 if (EQ (tem, Qnone) || NILP (tem)) |
3518 f = make_frame_without_minibuffer (Qnil, kb, display); | 4011 f = make_frame_without_minibuffer (Qnil, kb, display); |
3519 else if (EQ (tem, Qonly)) | 4012 else if (EQ (tem, Qonly)) |
3520 { | 4013 { |
3524 else if (WINDOWP (tem)) | 4017 else if (WINDOWP (tem)) |
3525 f = make_frame_without_minibuffer (tem, kb, display); | 4018 f = make_frame_without_minibuffer (tem, kb, display); |
3526 else | 4019 else |
3527 f = make_frame (1); | 4020 f = make_frame (1); |
3528 | 4021 |
4022 XSETFRAME (frame, f); | |
4023 | |
3529 /* Note that Windows does support scroll bars. */ | 4024 /* Note that Windows does support scroll bars. */ |
3530 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1; | 4025 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1; |
3531 /* By default, make scrollbars the system standard width. */ | 4026 /* By default, make scrollbars the system standard width. */ |
3532 f->scroll_bar_pixel_width = GetSystemMetrics (SM_CXVSCROLL); | 4027 f->scroll_bar_pixel_width = GetSystemMetrics (SM_CXVSCROLL); |
3533 | 4028 |
3534 XSETFRAME (frame, f); | |
3535 GCPRO1 (frame); | |
3536 | |
3537 f->output_method = output_w32; | 4029 f->output_method = output_w32; |
3538 f->output_data.w32 = (struct w32_output *) xmalloc (sizeof (struct w32_output)); | 4030 f->output_data.w32 = (struct w32_output *) xmalloc (sizeof (struct w32_output)); |
3539 bzero (f->output_data.w32, sizeof (struct w32_output)); | 4031 bzero (f->output_data.w32, sizeof (struct w32_output)); |
4032 | |
4033 f->icon_name | |
4034 = x_get_arg (parms, Qicon_name, "iconName", "Title", string); | |
4035 if (! STRINGP (f->icon_name)) | |
4036 f->icon_name = Qnil; | |
3540 | 4037 |
3541 /* FRAME_W32_DISPLAY_INFO (f) = dpyinfo; */ | 4038 /* FRAME_W32_DISPLAY_INFO (f) = dpyinfo; */ |
3542 #ifdef MULTI_KBOARD | 4039 #ifdef MULTI_KBOARD |
3543 FRAME_KBOARD (f) = kb; | 4040 FRAME_KBOARD (f) = kb; |
3544 #endif | 4041 #endif |
3582 font = x_get_arg (parms, Qfont, "font", "Font", string); | 4079 font = x_get_arg (parms, Qfont, "font", "Font", string); |
3583 BLOCK_INPUT; | 4080 BLOCK_INPUT; |
3584 /* First, try whatever font the caller has specified. */ | 4081 /* First, try whatever font the caller has specified. */ |
3585 if (STRINGP (font)) | 4082 if (STRINGP (font)) |
3586 font = x_new_font (f, XSTRING (font)->data); | 4083 font = x_new_font (f, XSTRING (font)->data); |
3587 #if 0 | |
3588 /* Try out a font which we hope has bold and italic variations. */ | 4084 /* Try out a font which we hope has bold and italic variations. */ |
3589 if (!STRINGP (font)) | 4085 if (!STRINGP (font)) |
3590 font = x_new_font (f, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1"); | 4086 font = x_new_font (f, "-*-Courier New-normal-r-*-*-13-97-*-*-c-*-*-ansi-"); |
3591 if (! STRINGP (font)) | 4087 if (! STRINGP (font)) |
3592 font = x_new_font (f, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1"); | 4088 font = x_new_font (f, "-*-Courier-normal-r-*-*-13-97-*-*-c-*-*-ansi-"); |
3593 if (! STRINGP (font)) | |
3594 /* This was formerly the first thing tried, but it finds too many fonts | |
3595 and takes too long. */ | |
3596 font = x_new_font (f, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1"); | |
3597 /* If those didn't work, look for something which will at least work. */ | 4089 /* If those didn't work, look for something which will at least work. */ |
3598 if (! STRINGP (font)) | 4090 if (! STRINGP (font)) |
3599 font = x_new_font (f, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1"); | 4091 font = x_new_font (f, "-*-Fixedsys-normal-r-*-*-13-97-*-*-c-*-*-ansi-"); |
3600 if (! STRINGP (font)) | |
3601 font = x_new_font (f, "-*-system-medium-r-normal-*-*-200-*-*-c-120-*-*"); | |
3602 #endif | |
3603 if (! STRINGP (font)) | |
3604 font = x_new_font (f, "-*-Fixedsys-*-r-*-*-12-90-*-*-c-*-*-*"); | |
3605 UNBLOCK_INPUT; | 4092 UNBLOCK_INPUT; |
3606 if (! STRINGP (font)) | 4093 if (! STRINGP (font)) |
3607 font = build_string ("-*-system"); | 4094 font = build_string ("Fixedsys"); |
3608 | 4095 |
3609 x_default_parameter (f, parms, Qfont, font, | 4096 x_default_parameter (f, parms, Qfont, font, |
3610 "font", "Font", string); | 4097 "font", "Font", string); |
3611 } | 4098 } |
3612 | 4099 |
3623 "internalBorder", "BorderWidth", number); | 4110 "internalBorder", "BorderWidth", number); |
3624 if (! EQ (value, Qunbound)) | 4111 if (! EQ (value, Qunbound)) |
3625 parms = Fcons (Fcons (Qinternal_border_width, value), | 4112 parms = Fcons (Fcons (Qinternal_border_width, value), |
3626 parms); | 4113 parms); |
3627 } | 4114 } |
4115 /* Default internalBorderWidth to 0 on Windows to match other programs. */ | |
3628 x_default_parameter (f, parms, Qinternal_border_width, make_number (0), | 4116 x_default_parameter (f, parms, Qinternal_border_width, make_number (0), |
3629 "internalBorderWidth", "BorderWidth", number); | 4117 "internalBorderWidth", "BorderWidth", number); |
3630 x_default_parameter (f, parms, Qvertical_scroll_bars, Qt, | 4118 x_default_parameter (f, parms, Qvertical_scroll_bars, Qt, |
3631 "verticalScrollBars", "ScrollBars", boolean); | 4119 "verticalScrollBars", "ScrollBars", boolean); |
3632 | 4120 |
3644 | 4132 |
3645 x_default_parameter (f, parms, Qmenu_bar_lines, make_number (1), | 4133 x_default_parameter (f, parms, Qmenu_bar_lines, make_number (1), |
3646 "menuBar", "MenuBar", number); | 4134 "menuBar", "MenuBar", number); |
3647 x_default_parameter (f, parms, Qscroll_bar_width, Qnil, | 4135 x_default_parameter (f, parms, Qscroll_bar_width, Qnil, |
3648 "scrollBarWidth", "ScrollBarWidth", number); | 4136 "scrollBarWidth", "ScrollBarWidth", number); |
4137 x_default_parameter (f, parms, Qbuffer_predicate, Qnil, | |
4138 "bufferPredicate", "BufferPredicate", symbol); | |
4139 x_default_parameter (f, parms, Qtitle, Qnil, | |
4140 "title", "Title", string); | |
3649 | 4141 |
3650 f->output_data.w32->dwStyle = WS_OVERLAPPEDWINDOW; | 4142 f->output_data.w32->dwStyle = WS_OVERLAPPEDWINDOW; |
3651 f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO (f)->root_window; | 4143 f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO (f)->root_window; |
3652 window_prompting = x_figure_window_size (f, parms); | 4144 window_prompting = x_figure_window_size (f, parms); |
3653 | 4145 |
3750 return Qnil; | 4242 return Qnil; |
3751 | 4243 |
3752 XSETFRAME (xfocus, dpyinfo->w32_focus_frame); | 4244 XSETFRAME (xfocus, dpyinfo->w32_focus_frame); |
3753 return xfocus; | 4245 return xfocus; |
3754 } | 4246 } |
4247 | |
4248 DEFUN ("w32-focus-frame", Fw32_focus_frame, Sw32_focus_frame, 1, 1, 0, | |
4249 "Give FRAME input focus, raising to foreground if necessary.") | |
4250 (frame) | |
4251 Lisp_Object frame; | |
4252 { | |
4253 x_focus_on_frame (check_x_frame (frame)); | |
4254 return Qnil; | |
4255 } | |
4256 | |
3755 | 4257 |
3756 XFontStruct * | 4258 XFontStruct * |
3757 w32_load_font (dpyinfo,name) | 4259 w32_load_font (dpyinfo,name) |
3758 struct w32_display_info *dpyinfo; | 4260 struct w32_display_info *dpyinfo; |
3759 char * name; | 4261 char * name; |
3894 | 4396 |
3895 if (stricmp (lpw,"heavy") == 0) return FW_HEAVY; | 4397 if (stricmp (lpw,"heavy") == 0) return FW_HEAVY; |
3896 else if (stricmp (lpw,"extrabold") == 0) return FW_EXTRABOLD; | 4398 else if (stricmp (lpw,"extrabold") == 0) return FW_EXTRABOLD; |
3897 else if (stricmp (lpw,"bold") == 0) return FW_BOLD; | 4399 else if (stricmp (lpw,"bold") == 0) return FW_BOLD; |
3898 else if (stricmp (lpw,"demibold") == 0) return FW_SEMIBOLD; | 4400 else if (stricmp (lpw,"demibold") == 0) return FW_SEMIBOLD; |
4401 else if (stricmp (lpw,"semibold") == 0) return FW_SEMIBOLD; | |
3899 else if (stricmp (lpw,"medium") == 0) return FW_MEDIUM; | 4402 else if (stricmp (lpw,"medium") == 0) return FW_MEDIUM; |
3900 else if (stricmp (lpw,"normal") == 0) return FW_NORMAL; | 4403 else if (stricmp (lpw,"normal") == 0) return FW_NORMAL; |
3901 else if (stricmp (lpw,"light") == 0) return FW_LIGHT; | 4404 else if (stricmp (lpw,"light") == 0) return FW_LIGHT; |
3902 else if (stricmp (lpw,"extralight") == 0) return FW_EXTRALIGHT; | 4405 else if (stricmp (lpw,"extralight") == 0) return FW_EXTRALIGHT; |
3903 else if (stricmp (lpw,"thin") == 0) return FW_THIN; | 4406 else if (stricmp (lpw,"thin") == 0) return FW_THIN; |
3935 else if (stricmp (lpcs,"oem") == 0) return OEM_CHARSET; | 4438 else if (stricmp (lpcs,"oem") == 0) return OEM_CHARSET; |
3936 #ifdef UNICODE_CHARSET | 4439 #ifdef UNICODE_CHARSET |
3937 else if (stricmp (lpcs,"unicode") == 0) return UNICODE_CHARSET; | 4440 else if (stricmp (lpcs,"unicode") == 0) return UNICODE_CHARSET; |
3938 else if (stricmp (lpcs,"iso10646") == 0) return UNICODE_CHARSET; | 4441 else if (stricmp (lpcs,"iso10646") == 0) return UNICODE_CHARSET; |
3939 #endif | 4442 #endif |
4443 else if (lpcs[0] == '#') return atoi (lpcs + 1); | |
3940 else | 4444 else |
3941 return 0; | 4445 return DEFAULT_CHARSET; |
3942 } | 4446 } |
3943 | 4447 |
3944 char * | 4448 char * |
3945 w32_to_x_charset (fncharset) | 4449 w32_to_x_charset (fncharset) |
3946 int fncharset; | 4450 int fncharset; |
3947 { | 4451 { |
4452 static char buf[16]; | |
4453 | |
3948 switch (fncharset) | 4454 switch (fncharset) |
3949 { | 4455 { |
3950 case ANSI_CHARSET: return "ansi"; | 4456 case ANSI_CHARSET: return "ansi"; |
3951 case OEM_CHARSET: return "oem"; | 4457 case OEM_CHARSET: return "oem"; |
3952 case SYMBOL_CHARSET: return "symbol"; | 4458 case SYMBOL_CHARSET: return "symbol"; |
3953 #ifdef UNICODE_CHARSET | 4459 #ifdef UNICODE_CHARSET |
3954 case UNICODE_CHARSET: return "unicode"; | 4460 case UNICODE_CHARSET: return "unicode"; |
3955 #endif | 4461 #endif |
3956 } | 4462 } |
3957 return "*"; | 4463 /* Encode numerical value of unknown charset. */ |
4464 sprintf (buf, "#%u", fncharset); | |
4465 return buf; | |
3958 } | 4466 } |
3959 | 4467 |
3960 BOOL | 4468 BOOL |
3961 w32_to_x_font (lplogfont, lpxstr, len) | 4469 w32_to_x_font (lplogfont, lpxstr, len) |
3962 LOGFONT * lplogfont; | 4470 LOGFONT * lplogfont; |
4192 ENUMLOGFONT * lplf; | 4700 ENUMLOGFONT * lplf; |
4193 NEWTEXTMETRIC * lptm; | 4701 NEWTEXTMETRIC * lptm; |
4194 int FontType; | 4702 int FontType; |
4195 enumfont_t * lpef; | 4703 enumfont_t * lpef; |
4196 { | 4704 { |
4197 if (lplf->elfLogFont.lfStrikeOut || lplf->elfLogFont.lfUnderline | 4705 if (lplf->elfLogFont.lfStrikeOut || lplf->elfLogFont.lfUnderline) |
4198 || (lplf->elfLogFont.lfCharSet != ANSI_CHARSET && lplf->elfLogFont.lfCharSet != OEM_CHARSET)) | |
4199 return (1); | 4706 return (1); |
4200 | 4707 |
4201 /* if (!lpef->size_ref || lptm->tmMaxCharWidth == FONT_WIDTH (lpef->size_ref)) */ | 4708 /* if (!lpef->size_ref || lptm->tmMaxCharWidth == FONT_WIDTH (lpef->size_ref)) */ |
4202 { | 4709 { |
4203 char buf[100]; | 4710 char buf[100]; |
4425 | 4932 |
4426 if (defined_color (f, XSTRING (color)->data, &foo, 0)) | 4933 if (defined_color (f, XSTRING (color)->data, &foo, 0)) |
4427 { | 4934 { |
4428 Lisp_Object rgb[3]; | 4935 Lisp_Object rgb[3]; |
4429 | 4936 |
4430 rgb[0] = make_number (GetRValue (foo)); | 4937 rgb[0] = make_number ((GetRValue (foo) << 8) | GetRValue (foo)); |
4431 rgb[1] = make_number (GetGValue (foo)); | 4938 rgb[1] = make_number ((GetGValue (foo) << 8) | GetGValue (foo)); |
4432 rgb[2] = make_number (GetBValue (foo)); | 4939 rgb[2] = make_number ((GetBValue (foo) << 8) | GetBValue (foo)); |
4433 return Flist (3, rgb); | 4940 return Flist (3, rgb); |
4434 } | 4941 } |
4435 else | 4942 else |
4436 return Qnil; | 4943 return Qnil; |
4437 } | 4944 } |
4763 (char *) XSTRING (Vx_resource_name)->data); | 5270 (char *) XSTRING (Vx_resource_name)->data); |
4764 | 5271 |
4765 if (dpyinfo == 0) | 5272 if (dpyinfo == 0) |
4766 error ("Cannot connect to server %s", XSTRING (name)->data); | 5273 error ("Cannot connect to server %s", XSTRING (name)->data); |
4767 | 5274 |
5275 w32_in_use = 1; | |
4768 XSETFASTINT (Vwindow_system_version, 3); | 5276 XSETFASTINT (Vwindow_system_version, 3); |
4769 | 5277 |
4770 return dpyinfo; | 5278 return dpyinfo; |
4771 } | 5279 } |
4772 | 5280 |
4785 | 5293 |
4786 CHECK_STRING (display, 0); | 5294 CHECK_STRING (display, 0); |
4787 if (! NILP (xrm_string)) | 5295 if (! NILP (xrm_string)) |
4788 CHECK_STRING (xrm_string, 1); | 5296 CHECK_STRING (xrm_string, 1); |
4789 | 5297 |
5298 if (! EQ (Vwindow_system, intern ("w32"))) | |
5299 error ("Not using Microsoft Windows"); | |
5300 | |
4790 /* Allow color mapping to be defined externally; first look in user's | 5301 /* Allow color mapping to be defined externally; first look in user's |
4791 HOME directory, then in Emacs etc dir for a file called rgb.txt. */ | 5302 HOME directory, then in Emacs etc dir for a file called rgb.txt. */ |
4792 { | 5303 { |
4793 Lisp_Object color_file; | 5304 Lisp_Object color_file; |
4794 struct gcpro gcpro1; | 5305 struct gcpro gcpro1; |
4839 fatal ("Cannot connect to server %s.\n", | 5350 fatal ("Cannot connect to server %s.\n", |
4840 XSTRING (display)->data); | 5351 XSTRING (display)->data); |
4841 else | 5352 else |
4842 error ("Cannot connect to server %s", XSTRING (display)->data); | 5353 error ("Cannot connect to server %s", XSTRING (display)->data); |
4843 } | 5354 } |
5355 | |
5356 w32_in_use = 1; | |
4844 | 5357 |
4845 XSETFASTINT (Vwindow_system_version, 3); | 5358 XSETFASTINT (Vwindow_system_version, 3); |
4846 return Qnil; | 5359 return Qnil; |
4847 } | 5360 } |
4848 | 5361 |
4931 return Qnil; | 5444 return Qnil; |
4932 | 5445 |
4933 return build_string (buf); | 5446 return build_string (buf); |
4934 } | 5447 } |
4935 | 5448 |
5449 DEFUN ("w32-send-sys-command", Fw32_send_sys_command, Sw32_send_sys_command, 1, 2, 0, | |
5450 "Send frame a Windows WM_SYSCOMMAND message of type COMMAND.\n\ | |
5451 Some useful values for command are 0xf030 to maximise frame (0xf020\n\ | |
5452 to minimize), 0xf120 to restore frame to original size, and 0xf100\n\ | |
5453 to activate the menubar for keyboard access. 0xf140 activates the\n\ | |
5454 screen saver if defined.\n\ | |
5455 \n\ | |
5456 If optional parameter FRAME is not specified, use selected frame.") | |
5457 (command, frame) | |
5458 Lisp_Object command, frame; | |
5459 { | |
5460 WPARAM code; | |
5461 FRAME_PTR f = check_x_frame (frame); | |
5462 | |
5463 CHECK_NUMBER (command, 0); | |
5464 | |
5465 PostMessage (FRAME_W32_WINDOW (f), WM_SYSCOMMAND, XINT (command), 0); | |
5466 | |
5467 return Qnil; | |
5468 } | |
5469 | |
4936 | 5470 |
4937 syms_of_w32fns () | 5471 syms_of_w32fns () |
4938 { | 5472 { |
5473 /* This is zero if not using MS-Windows. */ | |
5474 w32_in_use = 0; | |
5475 | |
4939 /* The section below is built by the lisp expression at the top of the file, | 5476 /* The section below is built by the lisp expression at the top of the file, |
4940 just above where these variables are declared. */ | 5477 just above where these variables are declared. */ |
4941 /*&&& init symbols here &&&*/ | 5478 /*&&& init symbols here &&&*/ |
4942 Qauto_raise = intern ("auto-raise"); | 5479 Qauto_raise = intern ("auto-raise"); |
4943 staticpro (&Qauto_raise); | 5480 staticpro (&Qauto_raise); |
5128 defsubr (&Sx_display_list); | 5665 defsubr (&Sx_display_list); |
5129 defsubr (&Sx_synchronize); | 5666 defsubr (&Sx_synchronize); |
5130 | 5667 |
5131 /* W32 specific functions */ | 5668 /* W32 specific functions */ |
5132 | 5669 |
5670 defsubr (&Sw32_focus_frame); | |
5133 defsubr (&Sw32_select_font); | 5671 defsubr (&Sw32_select_font); |
5134 defsubr (&Sw32_define_rgb_color); | 5672 defsubr (&Sw32_define_rgb_color); |
5135 defsubr (&Sw32_default_color_map); | 5673 defsubr (&Sw32_default_color_map); |
5136 defsubr (&Sw32_load_color_file); | 5674 defsubr (&Sw32_load_color_file); |
5675 defsubr (&Sw32_send_sys_command); | |
5137 } | 5676 } |
5138 | 5677 |
5139 #undef abort | 5678 #undef abort |
5140 | 5679 |
5141 void | 5680 void |