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