1 /* Functions for the mswindows window system.
2 Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
3 Copyright (C) 1995, 1996 Ben Wing.
5 This file is part of XEmacs.
7 XEmacs is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 2, or (at your option) any
12 XEmacs is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 You should have received a copy of the GNU General Public License
18 along with XEmacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 /* Synched up with: Not synched with FSF. */
26 Ultimately based on FSF.
27 Substantially rewritten for XEmacs by Ben Wing.
28 Rewritten for mswindows by Jonathan Harris, November 1997 for 21.0.
29 Graphics features added and frame resizing fiddled with by Andy Piper.
37 #include "console-msw.h"
38 #include "glyphs-msw.h"
43 #include "redisplay.h"
46 #define MSWINDOWS_FRAME_STYLE (WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW)
47 #define MSWINDOWS_POPUP_STYLE (WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_POPUP \
48 | WS_CAPTION | WS_BORDER | WS_SYSMENU | WS_MINIMIZEBOX)
50 #define MSWINDOWS_FRAME_EXSTYLE WS_EX_OVERLAPPEDWINDOW
51 #define MSWINDOWS_POPUP_EXSTYLE WS_EX_PALETTEWINDOW
53 /* Default popup left top corner offset from the same
54 corner of the parent frame, in pixel */
55 #define POPUP_OFFSET 30
57 /* Default popup size, in characters */
58 #define POPUP_WIDTH 30
59 #define POPUP_HEIGHT 10
61 /* Default regular frame size, in characters */
62 #define DEFAULT_FRAME_WIDTH 80
63 #define DEFAULT_FRAME_HEIGHT 35
66 #define ADJR_MENUFLAG TRUE
68 #define ADJR_MENUFLAG FALSE
71 /* Default properties to use when creating frames. */
72 Lisp_Object Vdefault_mswindows_frame_plist;
73 Lisp_Object Vdefault_msprinter_frame_plist;
74 Lisp_Object Vmswindows_use_system_frame_size_defaults;
76 /* This does not need to be GC protected, as it holds a
77 frame Lisp_Object already protected by Fmake_frame */
78 Lisp_Object Vmswindows_frame_being_created;
80 /*---------------------------------------------------------------------*/
81 /*----- DISPLAY FRAME -----*/
82 /*---------------------------------------------------------------------*/
85 mswindows_get_selected_frame_hwnd (void)
87 Lisp_Object frame, device;
89 device = Ffind_device (Qnil, Qmswindows);
92 frame = DEVICE_SELECTED_FRAME (XDEVICE (device));
96 return FRAME_MSWINDOWS_HANDLE (XFRAME (frame));
100 mswindows_init_frame_1 (struct frame *f, Lisp_Object props)
102 Lisp_Object initially_unmapped;
103 Lisp_Object name, height, width, popup, top, left;
104 Lisp_Object frame_obj = Qnil;
106 XEMACS_RECT_WH rect_default;
107 DWORD style, exstyle;
108 HWND hwnd, hwnd_parent;
110 /* Pick up relevant properties */
111 initially_unmapped = Fplist_get (props, Qinitially_unmapped, Qnil);
112 name = Fplist_get (props, Qname, Qnil);
114 popup = Fplist_get (props, Qpopup, Qnil);
116 popup = Fselected_frame (Qnil);
118 left = Fplist_get (props, Qleft, Qnil);
122 top = Fplist_get (props, Qtop, Qnil);
126 width = Fplist_get (props, Qwidth, Qnil);
130 height = Fplist_get (props, Qheight, Qnil);
134 f->frame_data = xnew_and_zero (struct mswindows_frame);
135 FRAME_MSWINDOWS_TARGET_RECT (f) = xnew_and_zero (XEMACS_RECT_WH);
137 FRAME_MSWINDOWS_TARGET_RECT (f)->left = NILP (left) ? -1 : abs (XINT (left));
138 FRAME_MSWINDOWS_TARGET_RECT (f)->top = NILP (top) ? -1 : abs (XINT (top));
139 FRAME_MSWINDOWS_TARGET_RECT (f)->width = NILP (width) ? -1 :
141 FRAME_MSWINDOWS_TARGET_RECT (f)->height = NILP (height) ? -1 :
144 /* Misc frame stuff */
145 FRAME_MSWINDOWS_MENU_HASH_TABLE(f) = Qnil;
147 FRAME_MSWINDOWS_TOOLBAR_HASH_TABLE(f) =
148 make_lisp_hash_table (50, HASH_TABLE_NON_WEAK, HASH_TABLE_EQUAL);
150 /* hashtable of instantiated glyphs on the frame. */
151 FRAME_MSWINDOWS_WIDGET_HASH_TABLE1 (f) =
152 make_lisp_hash_table (50, HASH_TABLE_VALUE_WEAK, HASH_TABLE_EQUAL);
153 FRAME_MSWINDOWS_WIDGET_HASH_TABLE2 (f) =
154 make_lisp_hash_table (50, HASH_TABLE_VALUE_WEAK, HASH_TABLE_EQUAL);
155 FRAME_MSWINDOWS_WIDGET_HASH_TABLE3 (f) =
156 make_lisp_hash_table (50, HASH_TABLE_VALUE_WEAK, HASH_TABLE_EQUAL);
157 /* Will initialize these in WM_SIZE handler. We cannot do it now,
158 because we do not know what is CW_USEDEFAULT height and width */
160 FRAME_HEIGHT (f) = 0;
161 FRAME_PIXWIDTH (f) = 0;
162 FRAME_PIXHEIGHT (f) = 0;
166 style = MSWINDOWS_FRAME_STYLE;
167 exstyle = MSWINDOWS_FRAME_EXSTYLE;
170 rect_default.left = rect_default.top = CW_USEDEFAULT;
171 rect_default.width = rect_default.height = CW_USEDEFAULT;
175 style = MSWINDOWS_POPUP_STYLE;
176 exstyle = MSWINDOWS_POPUP_EXSTYLE;
178 CHECK_MSWINDOWS_FRAME (popup);
179 hwnd_parent = FRAME_MSWINDOWS_HANDLE (XFRAME (popup));
180 assert (IsWindow (hwnd_parent));
182 /* We cannot use CW_USEDEFAULT when creating a popup window.
183 So by default, we offset the new popup 30 pixels right
184 and down from its parent, and give it size of 30x10 characters.
185 These dimensions look adequate on both high and low res monitors */
186 GetWindowRect (hwnd_parent, &rect);
187 rect_default.left = rect.left + POPUP_OFFSET;
188 rect_default.top = rect.top + POPUP_OFFSET;
189 char_to_real_pixel_size (f, POPUP_WIDTH, POPUP_HEIGHT,
190 &rect_default.width, &rect_default.height);
191 FRAME_MSWINDOWS_POPUP (f) = 1;
194 AdjustWindowRectEx(&rect, style, ADJR_MENUFLAG, exstyle);
196 XSETFRAME (frame_obj, f);
198 Vmswindows_frame_being_created = frame_obj;
200 hwnd = CreateWindowEx (exstyle,
202 STRINGP(f->name) ? XSTRING_DATA(f->name) :
204 (const Extbyte*)XSTRING_DATA(name) :
205 (const Extbyte*)XEMACS_CLASS),
207 rect_default.left, rect_default.top,
208 rect_default.width, rect_default.height,
209 hwnd_parent, NULL, NULL, NULL);
211 Vmswindows_frame_being_created = Qnil;
214 invalid_operation ("System call to create frame failed",
215 STRINGP (f->name) ? f->name :
216 STRINGP (name) ? name :
219 FRAME_MSWINDOWS_HANDLE(f) = hwnd;
221 SetWindowLong (hwnd, XWL_FRAMEOBJ, (LONG)LISP_TO_VOID(frame_obj));
222 FRAME_MSWINDOWS_DC(f) = GetDC (hwnd);
223 SetTextAlign (FRAME_MSWINDOWS_DC(f), TA_BASELINE | TA_LEFT | TA_NOUPDATECP);
225 if (FRAME_MSWINDOWS_POPUP (f))
226 mswindows_register_popup_frame (frame_obj);
230 mswindows_init_frame_2 (struct frame *f, Lisp_Object props)
232 if (NILP (Vmswindows_use_system_frame_size_defaults))
234 /* I don't think anything can set the frame size before this
235 since we don't have X resources. This may change if we look
236 at the registry. Even so these values can get overridden
238 XEMACS_RECT_WH dest = { -1, -1, DEFAULT_FRAME_WIDTH,
239 DEFAULT_FRAME_HEIGHT };
240 mswindows_size_frame_internal (f, &dest);
244 /* Called after frame's properties are set */
246 mswindows_init_frame_3 (struct frame *f)
248 /* Don't do this earlier or we get a WM_PAINT before the frame is ready.
249 * The SW_x parameter in the first call that an app makes to ShowWindow is
250 * ignored, and the parameter specified in the caller's STARTUPINFO is
251 * substituted instead. That parameter is SW_HIDE if we were started by
252 * runemacs, so call this twice. #### runemacs is evil */
253 ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_SHOWNORMAL);
254 ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_SHOWNORMAL);
255 SetForegroundWindow (FRAME_MSWINDOWS_HANDLE(f));
256 DragAcceptFiles (FRAME_MSWINDOWS_HANDLE(f), TRUE);
260 mswindows_after_init_frame (struct frame *f, int first_on_device,
261 int first_on_console)
263 /* Windows, unlike X, is very synchronous. After the initial
264 frame is created, it will never be displayed, except for
265 hollow border, unless we start pumping messages. Load progress
266 messages show in the bottom of the hollow frame, which is ugly.
267 We redisplay the initial frame here, so modeline and root window
270 if (first_on_console)
275 mswindows_mark_frame (struct frame *f)
277 mark_object (FRAME_MSWINDOWS_MENU_HASH_TABLE (f));
279 mark_object (FRAME_MSWINDOWS_TOOLBAR_HASH_TABLE (f));
281 mark_object (FRAME_MSWINDOWS_WIDGET_HASH_TABLE1 (f));
282 mark_object (FRAME_MSWINDOWS_WIDGET_HASH_TABLE2 (f));
283 mark_object (FRAME_MSWINDOWS_WIDGET_HASH_TABLE3 (f));
287 mswindows_focus_on_frame (struct frame *f)
289 SetForegroundWindow (FRAME_MSWINDOWS_HANDLE(f));
293 mswindows_delete_frame (struct frame *f)
298 XSETFRAME (frame, f);
299 mswindows_unregister_popup_frame (frame);
300 ReleaseDC(FRAME_MSWINDOWS_HANDLE(f), FRAME_MSWINDOWS_DC(f));
301 DestroyWindow(FRAME_MSWINDOWS_HANDLE(f));
302 xfree (f->frame_data);
308 mswindows_set_frame_size (struct frame *f, int width, int height)
311 rect.left = rect.top = 0;
313 rect.bottom = height;
315 AdjustWindowRectEx (&rect,
316 GetWindowLong (FRAME_MSWINDOWS_HANDLE(f), GWL_STYLE),
317 GetMenu (FRAME_MSWINDOWS_HANDLE(f)) != NULL,
318 GetWindowLong (FRAME_MSWINDOWS_HANDLE(f), GWL_EXSTYLE));
320 if (IsIconic (FRAME_MSWINDOWS_HANDLE(f)) || IsZoomed (FRAME_MSWINDOWS_HANDLE(f)))
321 ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_RESTORE);
323 SetWindowPos (FRAME_MSWINDOWS_HANDLE(f), NULL,
324 0, 0, rect.right-rect.left, rect.bottom-rect.top,
325 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSENDCHANGING | SWP_NOMOVE);
329 mswindows_set_frame_position (struct frame *f, int xoff, int yoff)
331 SetWindowPos (FRAME_MSWINDOWS_HANDLE(f), NULL,
333 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSENDCHANGING | SWP_NOSIZE);
337 mswindows_make_frame_visible (struct frame *f)
339 if (!FRAME_VISIBLE_P(f))
340 ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_RESTORE);
342 ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_SHOW);
348 mswindows_make_frame_invisible (struct frame *f)
350 if (!FRAME_VISIBLE_P(f))
353 ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_HIDE);
358 mswindows_frame_totally_visible_p (struct frame *f)
360 RECT rc_me, rc_other, rc_temp;
361 HWND hwnd = FRAME_MSWINDOWS_HANDLE(f);
363 /* We test against not a whole window rectangle, only against its
364 client part. So, if non-client are is covered and client area is
365 not, we return true. */
366 GetClientRect (hwnd, &rc_me);
367 MapWindowPoints (hwnd, HWND_DESKTOP, (LPPOINT)&rc_me, 2);
369 /* First see if we're off the desktop */
370 GetWindowRect (GetDesktopWindow(), &rc_other);
371 UnionRect(&rc_temp, &rc_me, &rc_other);
372 if (!EqualRect (&rc_temp, &rc_other))
375 /* Then see if any window above us obscures us */
376 while ((hwnd = GetWindow (hwnd, GW_HWNDPREV)) != NULL)
377 if (IsWindowVisible (hwnd))
379 GetWindowRect (hwnd, &rc_other);
380 if (IntersectRect(&rc_temp, &rc_me, &rc_other))
388 mswindows_frame_visible_p (struct frame *f)
390 return IsWindowVisible (FRAME_MSWINDOWS_HANDLE(f))
391 && !IsIconic (FRAME_MSWINDOWS_HANDLE(f));
396 mswindows_iconify_frame (struct frame *f)
398 ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_MINIMIZE);
404 mswindows_frame_iconified_p (struct frame *f)
406 return IsIconic (FRAME_MSWINDOWS_HANDLE(f));
410 mswindows_set_frame_icon (struct frame *f)
412 if (IMAGE_INSTANCEP (f->icon)
413 && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (f->icon)))
415 if (!XIMAGE_INSTANCE_MSWINDOWS_ICON (f->icon))
417 mswindows_initialize_image_instance_icon (XIMAGE_INSTANCE (f->icon),
421 SetClassLong (FRAME_MSWINDOWS_HANDLE (f), GCL_HICON,
422 (LONG) XIMAGE_INSTANCE_MSWINDOWS_ICON (f->icon));
427 mswindows_set_frame_pointer (struct frame *f)
429 if (IMAGE_INSTANCEP (f->pointer)
430 && IMAGE_INSTANCE_TYPE (XIMAGE_INSTANCE (f->pointer)) == IMAGE_POINTER)
432 SetClassLong (FRAME_MSWINDOWS_HANDLE (f), GCL_HCURSOR,
433 (LONG) XIMAGE_INSTANCE_MSWINDOWS_ICON (f->pointer));
434 /* we only have to do this because GC doesn't cause a mouse
435 event and doesn't give time to event processing even if it
437 SetCursor (XIMAGE_INSTANCE_MSWINDOWS_ICON (f->pointer));
442 mswindows_set_mouse_position (struct window *w, int x, int y)
444 struct frame *f = XFRAME (w->frame);
447 pt.x = w->pixel_left + x;
448 pt.y = w->pixel_top + y;
449 ClientToScreen (FRAME_MSWINDOWS_HANDLE(f), &pt);
450 SetCursorPos (pt.x, pt.y);
454 mswindows_get_mouse_position (struct device *d, Lisp_Object *frame, int *x, int *y)
461 /* What's under cursor? */
462 hwnd = WindowFromPoint (pt);
466 /* Get grandest parent of the window */
469 while ((hwnd_parent = GetParent (hwnd)) != NULL)
473 /* Make sure it belongs to us */
474 if (GetWindowThreadProcessId (hwnd, NULL) != GetCurrentThreadId ())
477 /* And that the window is an XEmacs frame */
479 char class_name [sizeof(XEMACS_CLASS) + 1];
480 if (!GetClassName (hwnd, class_name, sizeof(XEMACS_CLASS))
481 || strcmp (class_name, XEMACS_CLASS) != 0)
486 ScreenToClient (hwnd, &pt);
487 VOID_TO_LISP (*frame, GetWindowLong (hwnd, XWL_FRAMEOBJ));
494 mswindows_raise_frame (struct frame *f)
496 BringWindowToTop (FRAME_MSWINDOWS_HANDLE(f));
500 mswindows_lower_frame (struct frame *f)
502 SetWindowPos (FRAME_MSWINDOWS_HANDLE(f), HWND_BOTTOM, 0, 0, 0, 0,
503 SWP_NOSIZE | SWP_NOMOVE | SWP_NOSENDCHANGING);
507 mswindows_enable_frame (struct frame *f)
509 EnableWindow (FRAME_MSWINDOWS_HANDLE (f), TRUE);
513 mswindows_disable_frame (struct frame *f)
515 EnableWindow (FRAME_MSWINDOWS_HANDLE (f), FALSE);
519 mswindows_set_title_from_bufbyte (struct frame *f, Bufbyte *title)
521 unsigned int new_checksum = hash_string (title, strlen (title));
522 if (new_checksum != FRAME_MSWINDOWS_TITLE_CHECKSUM(f))
524 FRAME_MSWINDOWS_TITLE_CHECKSUM(f) = new_checksum;
525 SetWindowText (FRAME_MSWINDOWS_HANDLE(f), title);
530 mswindows_frame_property (struct frame *f, Lisp_Object property)
532 if (EQ (Qleft, property) || EQ (Qtop, property))
535 GetWindowRect (FRAME_MSWINDOWS_HANDLE(f), &rc);
536 return make_int (EQ (Qtop, property) ? rc.top : rc.left);
542 mswindows_internal_frame_property_p (struct frame *f, Lisp_Object property)
544 return EQ (property, Qleft)
545 || EQ (property, Qtop);
546 /* #### frame-x.c has also this. Why?
547 || STRINGP (property);
552 mswindows_frame_properties (struct frame *f)
554 Lisp_Object props = Qnil;
556 GetWindowRect (FRAME_MSWINDOWS_HANDLE(f), &rc);
558 props = cons3 (Qtop, make_int (rc.top), props);
559 props = cons3 (Qleft, make_int (rc.left), props);
565 mswindows_set_frame_properties (struct frame *f, Lisp_Object plist)
568 int width = -1, height = -1;
569 BOOL width_specified_p = FALSE;
570 BOOL height_specified_p = FALSE;
571 BOOL x_specified_p = FALSE;
572 BOOL y_specified_p = FALSE;
575 /* Extract the properties from plist */
576 for (tail = plist; !NILP (tail); tail = Fcdr (Fcdr (tail)))
578 Lisp_Object prop = Fcar (tail);
579 Lisp_Object val = Fcar (Fcdr (tail));
583 /* Kludge to handle the font property. */
584 if (EQ (prop, Qfont))
586 /* If the value is not a string we silently ignore it. */
589 Lisp_Object frm, font_spec;
592 font_spec = Fget (Fget_face (Qdefault), Qfont, Qnil);
594 Fadd_spec_to_specifier (font_spec, val, frm, Qnil, Qnil);
595 update_frame_face_values (f);
598 else if (EQ (prop, Qwidth))
602 width_specified_p = TRUE;
604 else if (EQ (prop, Qheight))
608 height_specified_p = TRUE;
610 else if (EQ (prop, Qleft))
614 x_specified_p = TRUE;
616 else if (EQ (prop, Qtop))
620 y_specified_p = TRUE;
625 /* Now we've extracted the properties, apply them.
626 Do not apply geometric properties during frame creation. This
627 is excessive anyways, and this loses because WM_SIZE has not
628 been sent yet, so frame width and height fields are not initialized.
630 unfortunately WM_SIZE loses as well since the resize is only
631 applied once and the first time WM_SIZE is applied not everything
632 is initialised in the frame (toolbars for instance). enabling
633 this always makes no visible difference and fixes a whole host of
634 bugs (and is more consistent with X) so I am going to reenable it.
636 if ( FRAME_PIXWIDTH (f) && FRAME_PIXHEIGHT (f)
637 && (width_specified_p || height_specified_p
638 || x_specified_p || y_specified_p))
640 XEMACS_RECT_WH dest = { x, y, width, height };
642 mswindows_size_frame_internal (f, &dest);
646 void mswindows_size_frame_internal (struct frame* f, XEMACS_RECT_WH* dest)
649 int pixel_width, pixel_height;
650 int size_p = (dest->width >=0 || dest->height >=0);
651 int move_p = (dest->top >=0 || dest->left >=0);
652 char_to_real_pixel_size (f, dest->width, dest->height, &pixel_width, &pixel_height);
655 pixel_width = FRAME_PIXWIDTH (f);
656 if (dest->height < 0)
657 pixel_height = FRAME_PIXHEIGHT (f);
659 GetWindowRect (FRAME_MSWINDOWS_HANDLE(f), &rect);
661 dest->left = rect.left;
663 dest->top = rect.top;
665 rect.left = rect.top = 0;
666 rect.right = pixel_width;
667 rect.bottom = pixel_height;
669 AdjustWindowRectEx (&rect,
670 GetWindowLong (FRAME_MSWINDOWS_HANDLE(f), GWL_STYLE),
671 GetMenu (FRAME_MSWINDOWS_HANDLE(f)) != NULL,
672 GetWindowLong (FRAME_MSWINDOWS_HANDLE(f), GWL_EXSTYLE));
674 /* resize and move the window so that it fits in the workspace. This is
675 not restrictive since this will happen later anyway in WM_SIZE. We
676 have to do this after adjusting the rect to account for menubar
678 mswindows_get_workspace_coords (&ws_rect);
679 pixel_width = rect.right - rect.left;
680 pixel_height = rect.bottom - rect.top;
681 if (pixel_width > ws_rect.right - ws_rect.left)
683 pixel_width = ws_rect.right - ws_rect.left;
686 if (pixel_height > ws_rect.bottom - ws_rect.top)
688 pixel_height = ws_rect.bottom - ws_rect.top;
692 /* adjust position so window is in workspace */
693 if (dest->left + pixel_width > ws_rect.right)
695 dest->left = ws_rect.right - pixel_width;
698 if (dest->left < ws_rect.left)
700 dest->left = ws_rect.left;
704 if (dest->top + pixel_height > ws_rect.bottom)
706 dest->top = ws_rect.bottom - pixel_height;
709 if (dest->top < ws_rect.top)
711 dest->top = ws_rect.top;
715 if (IsIconic (FRAME_MSWINDOWS_HANDLE(f))
716 || IsZoomed (FRAME_MSWINDOWS_HANDLE(f)))
717 ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_RESTORE);
719 SetWindowPos (FRAME_MSWINDOWS_HANDLE(f), NULL,
720 dest->left, dest->top, pixel_width, pixel_height,
721 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSENDCHANGING
722 | (size_p ? 0 : SWP_NOSIZE)
723 | (move_p ? 0 : SWP_NOMOVE));
727 mswindows_get_frame_parent (struct frame *f)
729 HWND hwnd = FRAME_MSWINDOWS_HANDLE(f);
730 hwnd = GetParent (hwnd);
734 VOID_TO_LISP (parent, GetWindowLong (hwnd, XWL_FRAMEOBJ));
735 assert (FRAME_MSWINDOWS_P (XFRAME (parent)));
743 mswindows_update_frame_external_traits (struct frame* frm, Lisp_Object name)
748 mswindows_frame_size_fixed_p (struct frame *f)
750 /* Frame size cannot change if the frame is maximized */
751 return IsZoomed (FRAME_MSWINDOWS_HANDLE (f));
754 /*---------------------------------------------------------------------*/
755 /*----- PRINTER FRAME -----*/
756 /*---------------------------------------------------------------------*/
759 * With some driver/os combination (I discovered this with HP drivers
760 * under W2K), DC geometry is reset upon StartDoc and EndPage
761 * calls. This is called every time one of these calls is made.
764 apply_dc_geometry (struct frame* f)
766 HDC hdc = DEVICE_MSPRINTER_HDC (XDEVICE (FRAME_DEVICE (f)));
767 SetTextAlign (hdc, TA_BASELINE | TA_LEFT | TA_NOUPDATECP);
768 SetViewportOrgEx (hdc, FRAME_MSPRINTER_PIXLEFT(f),
769 FRAME_MSPRINTER_PIXTOP(f), NULL);
773 msprinter_start_page (struct frame *f)
775 if (!FRAME_MSPRINTER_PAGE_STARTED (f))
777 FRAME_MSPRINTER_PAGE_STARTED (f) = 1;
778 StartPage (DEVICE_MSPRINTER_HDC (XDEVICE (FRAME_DEVICE (f))));
779 apply_dc_geometry (f);
784 error_frame_unsizable (struct frame *f)
787 XSETFRAME (frame, f);
788 invalid_change ("Cannot resize frame (margins) after print job has started.",
793 maybe_error_if_job_active (struct frame *f)
795 if (FRAME_MSPRINTER_JOB_STARTED (f))
796 error_frame_unsizable (f);
800 msprinter_init_frame_1 (struct frame *f, Lisp_Object props)
802 /* Make sure this is the only frame on device. Windows printer can
803 handle only one job at a time. */
804 if (!NILP (DEVICE_FRAME_LIST (XDEVICE (FRAME_DEVICE (f)))))
805 invalid_operation ("Only one frame (print job) at a time is allowed on "
806 "this printer device", FRAME_DEVICE (f));
808 f->frame_data = xnew_and_zero (struct msprinter_frame);
810 /* Default margin size is 1" = 1440 twips */
811 FRAME_MSPRINTER_TOP_MARGIN(f) = 1440;
812 FRAME_MSPRINTER_BOTTOM_MARGIN(f) = 1440;
813 FRAME_MSPRINTER_LEFT_MARGIN(f) = 1440;
814 FRAME_MSPRINTER_RIGHT_MARGIN(f) = 1440;
816 /* Negative for "uinspecified" */
817 FRAME_MSPRINTER_CHARWIDTH(f) = -1;
818 FRAME_MSPRINTER_CHARHEIGHT(f) = -1;
822 msprinter_init_frame_3 (struct frame *f)
825 struct device *device = XDEVICE (FRAME_DEVICE (f));
827 int frame_left, frame_top, frame_width, frame_height;
829 /* DC might be recreated in msprinter_apply_devmode,
830 so do not initialize until now */
831 hdc = DEVICE_MSPRINTER_HDC (device);
833 /* Compute geometry properties */
834 frame_left = (MulDiv (GetDeviceCaps (hdc, LOGPIXELSX),
835 FRAME_MSPRINTER_LEFT_MARGIN(f), 1440)
836 - GetDeviceCaps (hdc, PHYSICALOFFSETX));
838 if (FRAME_MSPRINTER_CHARWIDTH(f) > 0)
840 char_to_real_pixel_size (f, FRAME_MSPRINTER_CHARWIDTH(f), 0,
842 FRAME_MSPRINTER_RIGHT_MARGIN(f) =
843 MulDiv (GetDeviceCaps (hdc, PHYSICALWIDTH)
844 - (frame_left + frame_width), 1440,
845 GetDeviceCaps (hdc, LOGPIXELSX));
848 frame_width = (GetDeviceCaps (hdc, PHYSICALWIDTH)
850 - MulDiv (GetDeviceCaps (hdc, LOGPIXELSX),
851 FRAME_MSPRINTER_RIGHT_MARGIN(f), 1440));
853 frame_top = (MulDiv (GetDeviceCaps (hdc, LOGPIXELSY),
854 FRAME_MSPRINTER_TOP_MARGIN(f), 1440)
855 - GetDeviceCaps (hdc, PHYSICALOFFSETY));
857 if (FRAME_MSPRINTER_CHARHEIGHT(f) > 0)
859 char_to_real_pixel_size (f, 0, FRAME_MSPRINTER_CHARHEIGHT(f),
860 NULL, &frame_height);
862 FRAME_MSPRINTER_BOTTOM_MARGIN(f) =
863 MulDiv (GetDeviceCaps (hdc, PHYSICALHEIGHT)
864 - (frame_top + frame_height), 1440,
865 GetDeviceCaps (hdc, LOGPIXELSY));
868 frame_height = (GetDeviceCaps (hdc, PHYSICALHEIGHT)
870 - MulDiv (GetDeviceCaps (hdc, LOGPIXELSY),
871 FRAME_MSPRINTER_BOTTOM_MARGIN(f), 1440));
873 /* Geometry sanity checks */
874 if (!frame_pixsize_valid_p (f, frame_width, frame_height))
875 invalid_operation ("Area inside print margins has shrunk to naught",
876 STRINGP (f->name) ? f->name : Qunbound);
880 || frame_left + frame_width > GetDeviceCaps (hdc, HORZRES)
881 || frame_top + frame_height > GetDeviceCaps (hdc, VERTRES))
882 invalid_operation ("Print area is ouside of the printer's "
883 "hardware printable area",
884 STRINGP (f->name) ? f->name : Qunbound);
886 /* Apply XEmacs frame geometry and layout windows */
889 FRAME_PIXWIDTH(f) = frame_width;
890 FRAME_PIXHEIGHT(f) = frame_height;
891 pixel_to_char_size (f, frame_width, frame_height, &columns, &rows);
892 change_frame_size (f, rows, columns, 0);
895 FRAME_MSPRINTER_PIXLEFT(f) = frame_left;
896 FRAME_MSPRINTER_PIXTOP(f) = frame_top;
898 /* Start print job */
899 di.cbSize = sizeof (di);
900 di.lpszDocName = (STRINGP(f->name)
901 ? (char*) XSTRING_DATA(f->name)
902 : "XEmacs print document");
903 di.lpszOutput = NULL;
904 di.lpszDatatype = NULL;
907 if (StartDoc (hdc, &di) <= 0)
908 invalid_operation ("Cannot start print job",
909 STRINGP (f->name) ? f->name : Qunbound);
911 apply_dc_geometry (f);
913 /* Finish frame setup */
914 FRAME_MSPRINTER_JOB_STARTED (f) = 1;
915 FRAME_VISIBLE_P(f) = 0;
919 msprinter_mark_frame (struct frame *f)
924 msprinter_delete_frame (struct frame *f)
928 HDC hdc = DEVICE_MSPRINTER_HDC (XDEVICE (FRAME_DEVICE (f)));
929 if (FRAME_MSPRINTER_PAGE_STARTED (f))
931 if (FRAME_MSPRINTER_JOB_STARTED (f))
933 xfree (f->frame_data);
940 msprinter_frame_property (struct frame *f, Lisp_Object property)
942 if (EQ (Qleft_margin, property))
943 return make_int (FRAME_MSPRINTER_LEFT_MARGIN(f));
944 else if (EQ (Qtop_margin, property))
945 return make_int (FRAME_MSPRINTER_TOP_MARGIN(f));
946 if (EQ (Qright_margin, property))
947 return make_int (FRAME_MSPRINTER_RIGHT_MARGIN(f));
948 else if (EQ (Qbottom_margin, property))
949 return make_int (FRAME_MSPRINTER_BOTTOM_MARGIN(f));
955 msprinter_internal_frame_property_p (struct frame *f, Lisp_Object property)
957 return (EQ (Qleft_margin, property) || EQ (Qtop_margin, property) ||
958 EQ (Qright_margin, property) || EQ (Qbottom_margin, property));
962 msprinter_frame_properties (struct frame *f)
964 Lisp_Object props = Qnil;
965 props = cons3 (Qbottom_margin,
966 make_int (FRAME_MSPRINTER_BOTTOM_MARGIN(f)), props);
967 props = cons3 (Qright_margin,
968 make_int (FRAME_MSPRINTER_RIGHT_MARGIN(f)), props);
969 props = cons3 (Qtop_margin,
970 make_int (FRAME_MSPRINTER_TOP_MARGIN(f)), props);
971 props = cons3 (Qleft_margin,
972 make_int (FRAME_MSPRINTER_LEFT_MARGIN(f)), props);
977 msprinter_set_frame_properties (struct frame *f, Lisp_Object plist)
981 /* Extract the properties from plist */
982 for (tail = plist; !NILP (tail); tail = Fcdr (Fcdr (tail)))
984 Lisp_Object prop = Fcar (tail);
985 Lisp_Object val = Fcar (Fcdr (tail));
989 if (EQ (prop, Qwidth))
991 maybe_error_if_job_active (f);
995 FRAME_MSPRINTER_CHARWIDTH(f) = XINT (val);
998 if (EQ (prop, Qheight))
1000 maybe_error_if_job_active (f);
1004 FRAME_MSPRINTER_CHARHEIGHT(f) = XINT (val);
1007 else if (EQ (prop, Qleft_margin))
1009 maybe_error_if_job_active (f);
1011 FRAME_MSPRINTER_LEFT_MARGIN(f) = XINT (val);
1013 else if (EQ (prop, Qtop_margin))
1015 maybe_error_if_job_active (f);
1017 FRAME_MSPRINTER_TOP_MARGIN(f) = XINT (val);
1019 else if (EQ (prop, Qright_margin))
1021 maybe_error_if_job_active (f);
1023 FRAME_MSPRINTER_RIGHT_MARGIN(f) = XINT (val);
1025 else if (EQ (prop, Qbottom_margin))
1027 maybe_error_if_job_active (f);
1029 FRAME_MSPRINTER_BOTTOM_MARGIN(f) = XINT (val);
1036 msprinter_set_frame_size (struct frame *f, int width, int height)
1038 /* We're absolutely unsizeable */
1039 error_frame_unsizable (f);
1043 msprinter_eject_page (struct frame *f)
1045 /* #### Should we eject empty pages? */
1046 if (FRAME_MSPRINTER_PAGE_STARTED (f))
1048 FRAME_MSPRINTER_PAGE_STARTED (f) = 0;
1049 EndPage (DEVICE_MSPRINTER_HDC (XDEVICE (FRAME_DEVICE (f))));
1050 apply_dc_geometry (f);
1056 console_type_create_frame_mswindows (void)
1058 /* Display frames */
1059 CONSOLE_HAS_METHOD (mswindows, init_frame_1);
1060 CONSOLE_HAS_METHOD (mswindows, init_frame_2);
1061 CONSOLE_HAS_METHOD (mswindows, init_frame_3);
1062 CONSOLE_HAS_METHOD (mswindows, after_init_frame);
1063 CONSOLE_HAS_METHOD (mswindows, mark_frame);
1064 CONSOLE_HAS_METHOD (mswindows, focus_on_frame);
1065 CONSOLE_HAS_METHOD (mswindows, delete_frame);
1066 CONSOLE_HAS_METHOD (mswindows, get_mouse_position);
1067 CONSOLE_HAS_METHOD (mswindows, set_mouse_position);
1068 CONSOLE_HAS_METHOD (mswindows, raise_frame);
1069 CONSOLE_HAS_METHOD (mswindows, lower_frame);
1070 CONSOLE_HAS_METHOD (mswindows, enable_frame);
1071 CONSOLE_HAS_METHOD (mswindows, disable_frame);
1072 CONSOLE_HAS_METHOD (mswindows, make_frame_visible);
1073 CONSOLE_HAS_METHOD (mswindows, make_frame_invisible);
1074 CONSOLE_HAS_METHOD (mswindows, iconify_frame);
1075 CONSOLE_HAS_METHOD (mswindows, set_frame_size);
1076 CONSOLE_HAS_METHOD (mswindows, set_frame_position);
1077 CONSOLE_HAS_METHOD (mswindows, frame_property);
1078 CONSOLE_HAS_METHOD (mswindows, internal_frame_property_p);
1079 CONSOLE_HAS_METHOD (mswindows, frame_properties);
1080 CONSOLE_HAS_METHOD (mswindows, set_frame_properties);
1081 CONSOLE_HAS_METHOD (mswindows, set_title_from_bufbyte);
1082 /* CONSOLE_HAS_METHOD (mswindows, set_icon_name_from_bufbyte); */
1083 CONSOLE_HAS_METHOD (mswindows, frame_visible_p);
1084 CONSOLE_HAS_METHOD (mswindows, frame_totally_visible_p);
1085 CONSOLE_HAS_METHOD (mswindows, frame_iconified_p);
1086 CONSOLE_HAS_METHOD (mswindows, set_frame_pointer);
1087 CONSOLE_HAS_METHOD (mswindows, set_frame_icon);
1088 CONSOLE_HAS_METHOD (mswindows, get_frame_parent);
1089 CONSOLE_HAS_METHOD (mswindows, update_frame_external_traits);
1090 CONSOLE_HAS_METHOD (mswindows, frame_size_fixed_p);
1092 /* Printer frames, aka print jobs */
1093 CONSOLE_HAS_METHOD (msprinter, init_frame_1);
1094 CONSOLE_HAS_METHOD (msprinter, init_frame_3);
1095 CONSOLE_HAS_METHOD (msprinter, mark_frame);
1096 CONSOLE_HAS_METHOD (msprinter, delete_frame);
1097 CONSOLE_HAS_METHOD (msprinter, frame_property);
1098 CONSOLE_HAS_METHOD (msprinter, internal_frame_property_p);
1099 CONSOLE_HAS_METHOD (msprinter, frame_properties);
1100 CONSOLE_HAS_METHOD (msprinter, set_frame_properties);
1101 CONSOLE_HAS_METHOD (msprinter, set_frame_size);
1102 CONSOLE_HAS_METHOD (msprinter, eject_page);
1106 syms_of_frame_mswindows (void)
1111 reinit_vars_of_frame_mswindows (void)
1113 /* Needn't staticpro -- see comment above. */
1114 Vmswindows_frame_being_created = Qnil;
1118 vars_of_frame_mswindows (void)
1120 reinit_vars_of_frame_mswindows ();
1122 DEFVAR_LISP ("mswindows-use-system-frame-size-defaults", &Vmswindows_use_system_frame_size_defaults /*
1123 Controls whether to use system or XEmacs defaults for frame size.
1124 If nil then reasonable defaults are used for initial frame sizes. If t
1125 then the system will choose default sizes for the frame.
1127 Vmswindows_use_system_frame_size_defaults = Qnil;
1129 DEFVAR_LISP ("default-mswindows-frame-plist", &Vdefault_mswindows_frame_plist /*
1130 Plist of default frame-creation properties for mswindows frames.
1131 These override what is specified in `default-frame-plist', but are
1132 overridden by the arguments to the particular call to `make-frame'.
1134 Note: In many cases, properties of a frame are available as specifiers
1135 instead of through the frame-properties mechanism.
1137 Here is a list of recognized frame properties, other than those
1138 documented in `set-frame-properties' (they can be queried and
1139 set at any time, except as otherwise noted):
1141 initially-unmapped If non-nil, the frame will not be visible
1142 when it is created. In this case, you
1143 need to call `make-frame-visible' to make
1145 popup If non-nil, it should be a frame, and this
1146 frame will be created as a "popup" frame
1147 whose parent is the given frame. This
1148 will make the window manager treat the
1149 frame as a dialog box, which may entail
1150 doing different things (e.g. not asking
1151 for positioning, and not iconifying
1152 separate from its parent).
1153 top Y position (in pixels) of the upper-left
1154 outermost corner of the frame (i.e. the
1155 upper-left of the window-manager
1157 left X position (in pixels) of the upper-left
1158 outermost corner of the frame (i.e. the
1159 upper-left of the window-manager
1162 See also `default-frame-plist', which specifies properties which apply
1163 to all frames, not just mswindows frames.
1165 Vdefault_mswindows_frame_plist = Qnil;
1167 mswindows_console_methods->device_specific_frame_props =
1168 &Vdefault_mswindows_frame_plist;
1170 DEFVAR_LISP ("default-msprinter-frame-plist", &Vdefault_msprinter_frame_plist /*
1171 Plist of default frame-creation properties for msprinter print job frames.
1172 These override what is specified in `default-frame-plist', but are
1173 overridden by the arguments to the particular call to `make-frame'.
1175 Note: In many cases, properties of a frame are available as specifiers
1176 instead of through the frame-properties mechanism.
1178 Here is a list of recognized frame properties, other than those
1179 documented in `set-frame-properties' (they can be queried and
1180 set at any time, except as otherwise noted):
1182 left-margin Margin of the page, in twips. Twip is a
1183 top-margin typographical unit of measurement,
1184 right-margin equal to 1/1440 of an inch, or 1/20 of a
1185 bottom-margin point, and roughly equal to 7/400 of a
1186 millimeter. If not specified, each margin
1187 defaults to one inch (25.4 mm).
1189 MARGINS NOTE. right-margin and bottom-margin are overridden by
1190 the height and width properties. If you want to specify size
1191 of the printable area in character, as with the rest of XEmacs,
1192 use these properties. If height and/or width are nil, then
1193 corresponding margin setting is taken into account. If you
1194 specify height and/or width in `default-frame-plist', but still
1195 want to specify right/bottom margins, set height/width in this
1196 plist to nil, as in this example:
1198 (setq default-frame-plist '(height 55 'width 80)
1199 default-msprinter-frame-plist '(height nil 'width nil))
1201 See also `default-frame-plist', which specifies properties which apply
1202 to all frames, not just mswindows frames.
1204 Vdefault_msprinter_frame_plist = Qnil;
1206 msprinter_console_methods->device_specific_frame_props =
1207 &Vdefault_msprinter_frame_plist;