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) ? (LPCTSTR) XSTRING_DATA (f->name) :
203 (STRINGP (name) ? (LPCTSTR) XSTRING_DATA (name) :
206 rect_default.left, rect_default.top,
207 rect_default.width, rect_default.height,
208 hwnd_parent, NULL, NULL, NULL);
210 Vmswindows_frame_being_created = Qnil;
213 invalid_operation ("System call to create frame failed",
214 STRINGP (f->name) ? f->name :
215 STRINGP (name) ? name :
218 FRAME_MSWINDOWS_HANDLE(f) = hwnd;
220 SetWindowLong (hwnd, XWL_FRAMEOBJ, (LONG)LISP_TO_VOID(frame_obj));
221 FRAME_MSWINDOWS_DC(f) = GetDC (hwnd);
222 SetTextAlign (FRAME_MSWINDOWS_DC(f), TA_BASELINE | TA_LEFT | TA_NOUPDATECP);
224 if (FRAME_MSWINDOWS_POPUP (f))
225 mswindows_register_popup_frame (frame_obj);
229 mswindows_init_frame_2 (struct frame *f, Lisp_Object props)
231 if (NILP (Vmswindows_use_system_frame_size_defaults))
233 /* I don't think anything can set the frame size before this
234 since we don't have X resources. This may change if we look
235 at the registry. Even so these values can get overridden
237 XEMACS_RECT_WH dest = { -1, -1, DEFAULT_FRAME_WIDTH,
238 DEFAULT_FRAME_HEIGHT };
239 mswindows_size_frame_internal (f, &dest);
243 /* Called after frame's properties are set */
245 mswindows_init_frame_3 (struct frame *f)
247 /* Don't do this earlier or we get a WM_PAINT before the frame is ready.
248 * The SW_x parameter in the first call that an app makes to ShowWindow is
249 * ignored, and the parameter specified in the caller's STARTUPINFO is
250 * substituted instead. That parameter is SW_HIDE if we were started by
251 * runemacs, so call this twice. #### runemacs is evil */
252 ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_SHOWNORMAL);
253 ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_SHOWNORMAL);
254 SetForegroundWindow (FRAME_MSWINDOWS_HANDLE(f));
255 DragAcceptFiles (FRAME_MSWINDOWS_HANDLE(f), TRUE);
259 mswindows_after_init_frame (struct frame *f, int first_on_device,
260 int first_on_console)
262 /* Windows, unlike X, is very synchronous. After the initial
263 frame is created, it will never be displayed, except for
264 hollow border, unless we start pumping messages. Load progress
265 messages show in the bottom of the hollow frame, which is ugly.
266 We redisplay the initial frame here, so modeline and root window
269 if (first_on_console)
274 mswindows_mark_frame (struct frame *f)
276 mark_object (FRAME_MSWINDOWS_MENU_HASH_TABLE (f));
278 mark_object (FRAME_MSWINDOWS_TOOLBAR_HASH_TABLE (f));
280 mark_object (FRAME_MSWINDOWS_WIDGET_HASH_TABLE1 (f));
281 mark_object (FRAME_MSWINDOWS_WIDGET_HASH_TABLE2 (f));
282 mark_object (FRAME_MSWINDOWS_WIDGET_HASH_TABLE3 (f));
286 mswindows_focus_on_frame (struct frame *f)
288 SetForegroundWindow (FRAME_MSWINDOWS_HANDLE(f));
292 mswindows_delete_frame (struct frame *f)
297 XSETFRAME (frame, f);
298 mswindows_unregister_popup_frame (frame);
299 ReleaseDC(FRAME_MSWINDOWS_HANDLE(f), FRAME_MSWINDOWS_DC(f));
300 DestroyWindow(FRAME_MSWINDOWS_HANDLE(f));
301 xfree (f->frame_data);
307 mswindows_set_frame_size (struct frame *f, int width, int height)
310 rect.left = rect.top = 0;
312 rect.bottom = height;
314 AdjustWindowRectEx (&rect,
315 GetWindowLong (FRAME_MSWINDOWS_HANDLE(f), GWL_STYLE),
316 GetMenu (FRAME_MSWINDOWS_HANDLE(f)) != NULL,
317 GetWindowLong (FRAME_MSWINDOWS_HANDLE(f), GWL_EXSTYLE));
319 if (IsIconic (FRAME_MSWINDOWS_HANDLE(f)) || IsZoomed (FRAME_MSWINDOWS_HANDLE(f)))
320 ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_RESTORE);
322 SetWindowPos (FRAME_MSWINDOWS_HANDLE(f), NULL,
323 0, 0, rect.right-rect.left, rect.bottom-rect.top,
324 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSENDCHANGING | SWP_NOMOVE);
328 mswindows_set_frame_position (struct frame *f, int xoff, int yoff)
330 SetWindowPos (FRAME_MSWINDOWS_HANDLE(f), NULL,
332 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSENDCHANGING | SWP_NOSIZE);
336 mswindows_make_frame_visible (struct frame *f)
338 if (!FRAME_VISIBLE_P(f))
339 ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_RESTORE);
341 ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_SHOW);
347 mswindows_make_frame_invisible (struct frame *f)
349 if (!FRAME_VISIBLE_P(f))
352 ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_HIDE);
357 mswindows_frame_totally_visible_p (struct frame *f)
359 RECT rc_me, rc_other, rc_temp;
360 HWND hwnd = FRAME_MSWINDOWS_HANDLE(f);
362 /* We test against not a whole window rectangle, only against its
363 client part. So, if non-client are is covered and client area is
364 not, we return true. */
365 GetClientRect (hwnd, &rc_me);
366 MapWindowPoints (hwnd, HWND_DESKTOP, (LPPOINT)&rc_me, 2);
368 /* First see if we're off the desktop */
369 GetWindowRect (GetDesktopWindow(), &rc_other);
370 UnionRect(&rc_temp, &rc_me, &rc_other);
371 if (!EqualRect (&rc_temp, &rc_other))
374 /* Then see if any window above us obscures us */
375 while ((hwnd = GetWindow (hwnd, GW_HWNDPREV)) != NULL)
376 if (IsWindowVisible (hwnd))
378 GetWindowRect (hwnd, &rc_other);
379 if (IntersectRect(&rc_temp, &rc_me, &rc_other))
387 mswindows_frame_visible_p (struct frame *f)
389 return IsWindowVisible (FRAME_MSWINDOWS_HANDLE(f))
390 && !IsIconic (FRAME_MSWINDOWS_HANDLE(f));
395 mswindows_iconify_frame (struct frame *f)
397 ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_MINIMIZE);
403 mswindows_frame_iconified_p (struct frame *f)
405 return IsIconic (FRAME_MSWINDOWS_HANDLE(f));
409 mswindows_set_frame_icon (struct frame *f)
411 if (IMAGE_INSTANCEP (f->icon)
412 && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (f->icon)))
414 if (!XIMAGE_INSTANCE_MSWINDOWS_ICON (f->icon))
416 mswindows_initialize_image_instance_icon (XIMAGE_INSTANCE (f->icon),
420 SetClassLong (FRAME_MSWINDOWS_HANDLE (f), GCL_HICON,
421 (LONG) XIMAGE_INSTANCE_MSWINDOWS_ICON (f->icon));
426 mswindows_set_frame_pointer (struct frame *f)
428 if (IMAGE_INSTANCEP (f->pointer)
429 && IMAGE_INSTANCE_TYPE (XIMAGE_INSTANCE (f->pointer)) == IMAGE_POINTER)
431 SetClassLong (FRAME_MSWINDOWS_HANDLE (f), GCL_HCURSOR,
432 (LONG) XIMAGE_INSTANCE_MSWINDOWS_ICON (f->pointer));
433 /* we only have to do this because GC doesn't cause a mouse
434 event and doesn't give time to event processing even if it
436 SetCursor (XIMAGE_INSTANCE_MSWINDOWS_ICON (f->pointer));
441 mswindows_set_mouse_position (struct window *w, int x, int y)
443 struct frame *f = XFRAME (w->frame);
446 pt.x = w->pixel_left + x;
447 pt.y = w->pixel_top + y;
448 ClientToScreen (FRAME_MSWINDOWS_HANDLE(f), &pt);
449 SetCursorPos (pt.x, pt.y);
453 mswindows_get_mouse_position (struct device *d, Lisp_Object *frame, int *x, int *y)
460 /* What's under cursor? */
461 hwnd = WindowFromPoint (pt);
465 /* Get grandest parent of the window */
468 while ((hwnd_parent = GetParent (hwnd)) != NULL)
472 /* Make sure it belongs to us */
473 if (GetWindowThreadProcessId (hwnd, NULL) != GetCurrentThreadId ())
476 /* And that the window is an XEmacs frame */
478 char class_name [sizeof(XEMACS_CLASS) + 1];
479 if (!GetClassName (hwnd, class_name, sizeof(XEMACS_CLASS))
480 || strcmp (class_name, XEMACS_CLASS) != 0)
485 ScreenToClient (hwnd, &pt);
486 VOID_TO_LISP (*frame, GetWindowLong (hwnd, XWL_FRAMEOBJ));
493 mswindows_raise_frame (struct frame *f)
495 BringWindowToTop (FRAME_MSWINDOWS_HANDLE(f));
499 mswindows_lower_frame (struct frame *f)
501 SetWindowPos (FRAME_MSWINDOWS_HANDLE(f), HWND_BOTTOM, 0, 0, 0, 0,
502 SWP_NOSIZE | SWP_NOMOVE | SWP_NOSENDCHANGING);
506 mswindows_enable_frame (struct frame *f)
508 EnableWindow (FRAME_MSWINDOWS_HANDLE (f), TRUE);
512 mswindows_disable_frame (struct frame *f)
514 EnableWindow (FRAME_MSWINDOWS_HANDLE (f), FALSE);
518 mswindows_set_title_from_bufbyte (struct frame *f, Bufbyte *title)
520 unsigned int new_checksum = hash_string (title, strlen (title));
521 if (new_checksum != FRAME_MSWINDOWS_TITLE_CHECKSUM(f))
523 FRAME_MSWINDOWS_TITLE_CHECKSUM(f) = new_checksum;
524 SetWindowText (FRAME_MSWINDOWS_HANDLE(f), title);
529 mswindows_frame_property (struct frame *f, Lisp_Object property)
531 if (EQ (Qleft, property) || EQ (Qtop, property))
534 GetWindowRect (FRAME_MSWINDOWS_HANDLE(f), &rc);
535 return make_int (EQ (Qtop, property) ? rc.top : rc.left);
541 mswindows_internal_frame_property_p (struct frame *f, Lisp_Object property)
543 return EQ (property, Qleft)
544 || EQ (property, Qtop);
545 /* #### frame-x.c has also this. Why?
546 || STRINGP (property);
551 mswindows_frame_properties (struct frame *f)
553 Lisp_Object props = Qnil;
555 GetWindowRect (FRAME_MSWINDOWS_HANDLE(f), &rc);
557 props = cons3 (Qtop, make_int (rc.top), props);
558 props = cons3 (Qleft, make_int (rc.left), props);
564 mswindows_set_frame_properties (struct frame *f, Lisp_Object plist)
567 int width = -1, height = -1;
568 BOOL width_specified_p = FALSE;
569 BOOL height_specified_p = FALSE;
570 BOOL x_specified_p = FALSE;
571 BOOL y_specified_p = FALSE;
574 /* Extract the properties from plist */
575 for (tail = plist; !NILP (tail); tail = Fcdr (Fcdr (tail)))
577 Lisp_Object prop = Fcar (tail);
578 Lisp_Object val = Fcar (Fcdr (tail));
582 /* Kludge to handle the font property. */
583 if (EQ (prop, Qfont))
585 /* If the value is not a string we silently ignore it. */
588 Lisp_Object frm, font_spec;
591 font_spec = Fget (Fget_face (Qdefault), Qfont, Qnil);
593 Fadd_spec_to_specifier (font_spec, val, frm, Qnil, Qnil);
594 update_frame_face_values (f);
597 else if (EQ (prop, Qwidth))
601 width_specified_p = TRUE;
603 else if (EQ (prop, Qheight))
607 height_specified_p = TRUE;
609 else if (EQ (prop, Qleft))
613 x_specified_p = TRUE;
615 else if (EQ (prop, Qtop))
619 y_specified_p = TRUE;
624 /* Now we've extracted the properties, apply them.
625 Do not apply geometric properties during frame creation. This
626 is excessive anyways, and this loses because WM_SIZE has not
627 been sent yet, so frame width and height fields are not initialized.
629 unfortunately WM_SIZE loses as well since the resize is only
630 applied once and the first time WM_SIZE is applied not everything
631 is initialised in the frame (toolbars for instance). enabling
632 this always makes no visible difference and fixes a whole host of
633 bugs (and is more consistent with X) so I am going to reenable it.
635 if ( FRAME_PIXWIDTH (f) && FRAME_PIXHEIGHT (f)
636 && (width_specified_p || height_specified_p
637 || x_specified_p || y_specified_p))
639 XEMACS_RECT_WH dest = { x, y, width, height };
641 mswindows_size_frame_internal (f, &dest);
645 void mswindows_size_frame_internal (struct frame* f, XEMACS_RECT_WH* dest)
648 int pixel_width, pixel_height;
649 int size_p = (dest->width >=0 || dest->height >=0);
650 int move_p = (dest->top >=0 || dest->left >=0);
651 char_to_real_pixel_size (f, dest->width, dest->height, &pixel_width, &pixel_height);
654 pixel_width = FRAME_PIXWIDTH (f);
655 if (dest->height < 0)
656 pixel_height = FRAME_PIXHEIGHT (f);
658 GetWindowRect (FRAME_MSWINDOWS_HANDLE(f), &rect);
660 dest->left = rect.left;
662 dest->top = rect.top;
664 rect.left = rect.top = 0;
665 rect.right = pixel_width;
666 rect.bottom = pixel_height;
668 AdjustWindowRectEx (&rect,
669 GetWindowLong (FRAME_MSWINDOWS_HANDLE(f), GWL_STYLE),
670 GetMenu (FRAME_MSWINDOWS_HANDLE(f)) != NULL,
671 GetWindowLong (FRAME_MSWINDOWS_HANDLE(f), GWL_EXSTYLE));
673 /* resize and move the window so that it fits in the workspace. This is
674 not restrictive since this will happen later anyway in WM_SIZE. We
675 have to do this after adjusting the rect to account for menubar
677 mswindows_get_workspace_coords (&ws_rect);
678 pixel_width = rect.right - rect.left;
679 pixel_height = rect.bottom - rect.top;
680 if (pixel_width > ws_rect.right - ws_rect.left)
682 pixel_width = ws_rect.right - ws_rect.left;
685 if (pixel_height > ws_rect.bottom - ws_rect.top)
687 pixel_height = ws_rect.bottom - ws_rect.top;
691 /* adjust position so window is in workspace */
692 if (dest->left + pixel_width > ws_rect.right)
694 dest->left = ws_rect.right - pixel_width;
697 if (dest->left < ws_rect.left)
699 dest->left = ws_rect.left;
703 if (dest->top + pixel_height > ws_rect.bottom)
705 dest->top = ws_rect.bottom - pixel_height;
708 if (dest->top < ws_rect.top)
710 dest->top = ws_rect.top;
714 if (IsIconic (FRAME_MSWINDOWS_HANDLE(f))
715 || IsZoomed (FRAME_MSWINDOWS_HANDLE(f)))
716 ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_RESTORE);
718 SetWindowPos (FRAME_MSWINDOWS_HANDLE(f), NULL,
719 dest->left, dest->top, pixel_width, pixel_height,
720 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSENDCHANGING
721 | (size_p ? 0 : SWP_NOSIZE)
722 | (move_p ? 0 : SWP_NOMOVE));
726 mswindows_get_frame_parent (struct frame *f)
728 HWND hwnd = FRAME_MSWINDOWS_HANDLE(f);
729 hwnd = GetParent (hwnd);
733 VOID_TO_LISP (parent, GetWindowLong (hwnd, XWL_FRAMEOBJ));
734 assert (FRAME_MSWINDOWS_P (XFRAME (parent)));
742 mswindows_update_frame_external_traits (struct frame* frm, Lisp_Object name)
747 mswindows_frame_size_fixed_p (struct frame *f)
749 /* Frame size cannot change if the frame is maximized */
750 return IsZoomed (FRAME_MSWINDOWS_HANDLE (f));
753 /*---------------------------------------------------------------------*/
754 /*----- PRINTER FRAME -----*/
755 /*---------------------------------------------------------------------*/
758 * With some driver/os combination (I discovered this with HP drivers
759 * under W2K), DC geometry is reset upon StartDoc and EndPage
760 * calls. This is called every time one of these calls is made.
763 apply_dc_geometry (struct frame* f)
765 HDC hdc = DEVICE_MSPRINTER_HDC (XDEVICE (FRAME_DEVICE (f)));
766 SetTextAlign (hdc, TA_BASELINE | TA_LEFT | TA_NOUPDATECP);
767 SetViewportOrgEx (hdc, FRAME_MSPRINTER_PIXLEFT(f),
768 FRAME_MSPRINTER_PIXTOP(f), NULL);
772 msprinter_start_page (struct frame *f)
774 if (!FRAME_MSPRINTER_PAGE_STARTED (f))
776 FRAME_MSPRINTER_PAGE_STARTED (f) = 1;
777 StartPage (DEVICE_MSPRINTER_HDC (XDEVICE (FRAME_DEVICE (f))));
778 apply_dc_geometry (f);
783 error_frame_unsizable (struct frame *f)
786 XSETFRAME (frame, f);
787 invalid_change ("Cannot resize frame (margins) after print job has started.",
792 maybe_error_if_job_active (struct frame *f)
794 if (FRAME_MSPRINTER_JOB_STARTED (f))
795 error_frame_unsizable (f);
799 msprinter_init_frame_1 (struct frame *f, Lisp_Object props)
801 /* Make sure this is the only frame on device. Windows printer can
802 handle only one job at a time. */
803 if (!NILP (DEVICE_FRAME_LIST (XDEVICE (FRAME_DEVICE (f)))))
804 invalid_operation ("Only one frame (print job) at a time is allowed on "
805 "this printer device", FRAME_DEVICE (f));
807 f->frame_data = xnew_and_zero (struct msprinter_frame);
809 /* Default margin size is 1" = 1440 twips */
810 FRAME_MSPRINTER_TOP_MARGIN(f) = 1440;
811 FRAME_MSPRINTER_BOTTOM_MARGIN(f) = 1440;
812 FRAME_MSPRINTER_LEFT_MARGIN(f) = 1440;
813 FRAME_MSPRINTER_RIGHT_MARGIN(f) = 1440;
815 /* Negative for "uinspecified" */
816 FRAME_MSPRINTER_CHARWIDTH(f) = -1;
817 FRAME_MSPRINTER_CHARHEIGHT(f) = -1;
821 msprinter_init_frame_3 (struct frame *f)
824 struct device *device = XDEVICE (FRAME_DEVICE (f));
826 int frame_left, frame_top, frame_width, frame_height;
828 /* DC might be recreated in msprinter_apply_devmode,
829 so do not initialize until now */
830 hdc = DEVICE_MSPRINTER_HDC (device);
832 /* Compute geometry properties */
833 frame_left = (MulDiv (GetDeviceCaps (hdc, LOGPIXELSX),
834 FRAME_MSPRINTER_LEFT_MARGIN(f), 1440)
835 - GetDeviceCaps (hdc, PHYSICALOFFSETX));
837 if (FRAME_MSPRINTER_CHARWIDTH(f) > 0)
839 char_to_real_pixel_size (f, FRAME_MSPRINTER_CHARWIDTH(f), 0,
841 FRAME_MSPRINTER_RIGHT_MARGIN(f) =
842 MulDiv (GetDeviceCaps (hdc, PHYSICALWIDTH)
843 - (frame_left + frame_width), 1440,
844 GetDeviceCaps (hdc, LOGPIXELSX));
847 frame_width = (GetDeviceCaps (hdc, PHYSICALWIDTH)
849 - MulDiv (GetDeviceCaps (hdc, LOGPIXELSX),
850 FRAME_MSPRINTER_RIGHT_MARGIN(f), 1440));
852 frame_top = (MulDiv (GetDeviceCaps (hdc, LOGPIXELSY),
853 FRAME_MSPRINTER_TOP_MARGIN(f), 1440)
854 - GetDeviceCaps (hdc, PHYSICALOFFSETY));
856 if (FRAME_MSPRINTER_CHARHEIGHT(f) > 0)
858 char_to_real_pixel_size (f, 0, FRAME_MSPRINTER_CHARHEIGHT(f),
859 NULL, &frame_height);
861 FRAME_MSPRINTER_BOTTOM_MARGIN(f) =
862 MulDiv (GetDeviceCaps (hdc, PHYSICALHEIGHT)
863 - (frame_top + frame_height), 1440,
864 GetDeviceCaps (hdc, LOGPIXELSY));
867 frame_height = (GetDeviceCaps (hdc, PHYSICALHEIGHT)
869 - MulDiv (GetDeviceCaps (hdc, LOGPIXELSY),
870 FRAME_MSPRINTER_BOTTOM_MARGIN(f), 1440));
872 /* Geometry sanity checks */
873 if (!frame_pixsize_valid_p (f, frame_width, frame_height))
874 invalid_operation ("Area inside print margins has shrunk to naught",
875 STRINGP (f->name) ? f->name : Qunbound);
879 || frame_left + frame_width > GetDeviceCaps (hdc, HORZRES)
880 || frame_top + frame_height > GetDeviceCaps (hdc, VERTRES))
881 invalid_operation ("Print area is ouside of the printer's "
882 "hardware printable area",
883 STRINGP (f->name) ? f->name : Qunbound);
885 /* Apply XEmacs frame geometry and layout windows */
888 FRAME_PIXWIDTH(f) = frame_width;
889 FRAME_PIXHEIGHT(f) = frame_height;
890 pixel_to_char_size (f, frame_width, frame_height, &columns, &rows);
891 change_frame_size (f, rows, columns, 0);
894 FRAME_MSPRINTER_PIXLEFT(f) = frame_left;
895 FRAME_MSPRINTER_PIXTOP(f) = frame_top;
897 /* Start print job */
898 di.cbSize = sizeof (di);
899 di.lpszDocName = (STRINGP(f->name)
900 ? (char*) XSTRING_DATA(f->name)
901 : "XEmacs print document");
902 di.lpszOutput = NULL;
903 di.lpszDatatype = NULL;
906 if (StartDoc (hdc, &di) <= 0)
907 invalid_operation ("Cannot start print job",
908 STRINGP (f->name) ? f->name : Qunbound);
910 apply_dc_geometry (f);
912 /* Finish frame setup */
913 FRAME_MSPRINTER_JOB_STARTED (f) = 1;
914 FRAME_VISIBLE_P(f) = 0;
918 msprinter_mark_frame (struct frame *f)
923 msprinter_delete_frame (struct frame *f)
927 HDC hdc = DEVICE_MSPRINTER_HDC (XDEVICE (FRAME_DEVICE (f)));
928 if (FRAME_MSPRINTER_PAGE_STARTED (f))
930 if (FRAME_MSPRINTER_JOB_STARTED (f))
932 xfree (f->frame_data);
939 msprinter_frame_property (struct frame *f, Lisp_Object property)
941 if (EQ (Qleft_margin, property))
942 return make_int (FRAME_MSPRINTER_LEFT_MARGIN(f));
943 else if (EQ (Qtop_margin, property))
944 return make_int (FRAME_MSPRINTER_TOP_MARGIN(f));
945 if (EQ (Qright_margin, property))
946 return make_int (FRAME_MSPRINTER_RIGHT_MARGIN(f));
947 else if (EQ (Qbottom_margin, property))
948 return make_int (FRAME_MSPRINTER_BOTTOM_MARGIN(f));
954 msprinter_internal_frame_property_p (struct frame *f, Lisp_Object property)
956 return (EQ (Qleft_margin, property) || EQ (Qtop_margin, property) ||
957 EQ (Qright_margin, property) || EQ (Qbottom_margin, property));
961 msprinter_frame_properties (struct frame *f)
963 Lisp_Object props = Qnil;
964 props = cons3 (Qbottom_margin,
965 make_int (FRAME_MSPRINTER_BOTTOM_MARGIN(f)), props);
966 props = cons3 (Qright_margin,
967 make_int (FRAME_MSPRINTER_RIGHT_MARGIN(f)), props);
968 props = cons3 (Qtop_margin,
969 make_int (FRAME_MSPRINTER_TOP_MARGIN(f)), props);
970 props = cons3 (Qleft_margin,
971 make_int (FRAME_MSPRINTER_LEFT_MARGIN(f)), props);
976 msprinter_set_frame_properties (struct frame *f, Lisp_Object plist)
980 /* Extract the properties from plist */
981 for (tail = plist; !NILP (tail); tail = Fcdr (Fcdr (tail)))
983 Lisp_Object prop = Fcar (tail);
984 Lisp_Object val = Fcar (Fcdr (tail));
988 if (EQ (prop, Qwidth))
990 maybe_error_if_job_active (f);
994 FRAME_MSPRINTER_CHARWIDTH(f) = XINT (val);
997 if (EQ (prop, Qheight))
999 maybe_error_if_job_active (f);
1003 FRAME_MSPRINTER_CHARHEIGHT(f) = XINT (val);
1006 else if (EQ (prop, Qleft_margin))
1008 maybe_error_if_job_active (f);
1010 FRAME_MSPRINTER_LEFT_MARGIN(f) = XINT (val);
1012 else if (EQ (prop, Qtop_margin))
1014 maybe_error_if_job_active (f);
1016 FRAME_MSPRINTER_TOP_MARGIN(f) = XINT (val);
1018 else if (EQ (prop, Qright_margin))
1020 maybe_error_if_job_active (f);
1022 FRAME_MSPRINTER_RIGHT_MARGIN(f) = XINT (val);
1024 else if (EQ (prop, Qbottom_margin))
1026 maybe_error_if_job_active (f);
1028 FRAME_MSPRINTER_BOTTOM_MARGIN(f) = XINT (val);
1035 msprinter_set_frame_size (struct frame *f, int width, int height)
1037 /* We're absolutely unsizeable */
1038 error_frame_unsizable (f);
1042 msprinter_eject_page (struct frame *f)
1044 /* #### Should we eject empty pages? */
1045 if (FRAME_MSPRINTER_PAGE_STARTED (f))
1047 FRAME_MSPRINTER_PAGE_STARTED (f) = 0;
1048 EndPage (DEVICE_MSPRINTER_HDC (XDEVICE (FRAME_DEVICE (f))));
1049 apply_dc_geometry (f);
1055 console_type_create_frame_mswindows (void)
1057 /* Display frames */
1058 CONSOLE_HAS_METHOD (mswindows, init_frame_1);
1059 CONSOLE_HAS_METHOD (mswindows, init_frame_2);
1060 CONSOLE_HAS_METHOD (mswindows, init_frame_3);
1061 CONSOLE_HAS_METHOD (mswindows, after_init_frame);
1062 CONSOLE_HAS_METHOD (mswindows, mark_frame);
1063 CONSOLE_HAS_METHOD (mswindows, focus_on_frame);
1064 CONSOLE_HAS_METHOD (mswindows, delete_frame);
1065 CONSOLE_HAS_METHOD (mswindows, get_mouse_position);
1066 CONSOLE_HAS_METHOD (mswindows, set_mouse_position);
1067 CONSOLE_HAS_METHOD (mswindows, raise_frame);
1068 CONSOLE_HAS_METHOD (mswindows, lower_frame);
1069 CONSOLE_HAS_METHOD (mswindows, enable_frame);
1070 CONSOLE_HAS_METHOD (mswindows, disable_frame);
1071 CONSOLE_HAS_METHOD (mswindows, make_frame_visible);
1072 CONSOLE_HAS_METHOD (mswindows, make_frame_invisible);
1073 CONSOLE_HAS_METHOD (mswindows, iconify_frame);
1074 CONSOLE_HAS_METHOD (mswindows, set_frame_size);
1075 CONSOLE_HAS_METHOD (mswindows, set_frame_position);
1076 CONSOLE_HAS_METHOD (mswindows, frame_property);
1077 CONSOLE_HAS_METHOD (mswindows, internal_frame_property_p);
1078 CONSOLE_HAS_METHOD (mswindows, frame_properties);
1079 CONSOLE_HAS_METHOD (mswindows, set_frame_properties);
1080 CONSOLE_HAS_METHOD (mswindows, set_title_from_bufbyte);
1081 /* CONSOLE_HAS_METHOD (mswindows, set_icon_name_from_bufbyte); */
1082 CONSOLE_HAS_METHOD (mswindows, frame_visible_p);
1083 CONSOLE_HAS_METHOD (mswindows, frame_totally_visible_p);
1084 CONSOLE_HAS_METHOD (mswindows, frame_iconified_p);
1085 CONSOLE_HAS_METHOD (mswindows, set_frame_pointer);
1086 CONSOLE_HAS_METHOD (mswindows, set_frame_icon);
1087 CONSOLE_HAS_METHOD (mswindows, get_frame_parent);
1088 CONSOLE_HAS_METHOD (mswindows, update_frame_external_traits);
1089 CONSOLE_HAS_METHOD (mswindows, frame_size_fixed_p);
1091 /* Printer frames, aka print jobs */
1092 CONSOLE_HAS_METHOD (msprinter, init_frame_1);
1093 CONSOLE_HAS_METHOD (msprinter, init_frame_3);
1094 CONSOLE_HAS_METHOD (msprinter, mark_frame);
1095 CONSOLE_HAS_METHOD (msprinter, delete_frame);
1096 CONSOLE_HAS_METHOD (msprinter, frame_property);
1097 CONSOLE_HAS_METHOD (msprinter, internal_frame_property_p);
1098 CONSOLE_HAS_METHOD (msprinter, frame_properties);
1099 CONSOLE_HAS_METHOD (msprinter, set_frame_properties);
1100 CONSOLE_HAS_METHOD (msprinter, set_frame_size);
1101 CONSOLE_HAS_METHOD (msprinter, eject_page);
1105 syms_of_frame_mswindows (void)
1110 reinit_vars_of_frame_mswindows (void)
1112 /* Needn't staticpro -- see comment above. */
1113 Vmswindows_frame_being_created = Qnil;
1117 vars_of_frame_mswindows (void)
1119 reinit_vars_of_frame_mswindows ();
1121 DEFVAR_LISP ("mswindows-use-system-frame-size-defaults", &Vmswindows_use_system_frame_size_defaults /*
1122 Controls whether to use system or XEmacs defaults for frame size.
1123 If nil then reasonable defaults are used for initial frame sizes. If t
1124 then the system will choose default sizes for the frame.
1126 Vmswindows_use_system_frame_size_defaults = Qnil;
1128 DEFVAR_LISP ("default-mswindows-frame-plist", &Vdefault_mswindows_frame_plist /*
1129 Plist of default frame-creation properties for mswindows frames.
1130 These override what is specified in `default-frame-plist', but are
1131 overridden by the arguments to the particular call to `make-frame'.
1133 Note: In many cases, properties of a frame are available as specifiers
1134 instead of through the frame-properties mechanism.
1136 Here is a list of recognized frame properties, other than those
1137 documented in `set-frame-properties' (they can be queried and
1138 set at any time, except as otherwise noted):
1140 initially-unmapped If non-nil, the frame will not be visible
1141 when it is created. In this case, you
1142 need to call `make-frame-visible' to make
1144 popup If non-nil, it should be a frame, and this
1145 frame will be created as a "popup" frame
1146 whose parent is the given frame. This
1147 will make the window manager treat the
1148 frame as a dialog box, which may entail
1149 doing different things (e.g. not asking
1150 for positioning, and not iconifying
1151 separate from its parent).
1152 top Y position (in pixels) of the upper-left
1153 outermost corner of the frame (i.e. the
1154 upper-left of the window-manager
1156 left X position (in pixels) of the upper-left
1157 outermost corner of the frame (i.e. the
1158 upper-left of the window-manager
1161 See also `default-frame-plist', which specifies properties which apply
1162 to all frames, not just mswindows frames.
1164 Vdefault_mswindows_frame_plist = Qnil;
1166 mswindows_console_methods->device_specific_frame_props =
1167 &Vdefault_mswindows_frame_plist;
1169 DEFVAR_LISP ("default-msprinter-frame-plist", &Vdefault_msprinter_frame_plist /*
1170 Plist of default frame-creation properties for msprinter print job frames.
1171 These override what is specified in `default-frame-plist', but are
1172 overridden by the arguments to the particular call to `make-frame'.
1174 Note: In many cases, properties of a frame are available as specifiers
1175 instead of through the frame-properties mechanism.
1177 Here is a list of recognized frame properties, other than those
1178 documented in `set-frame-properties' (they can be queried and
1179 set at any time, except as otherwise noted):
1181 left-margin Margin of the page, in twips. Twip is a
1182 top-margin typographical unit of measurement,
1183 right-margin equal to 1/1440 of an inch, or 1/20 of a
1184 bottom-margin point, and roughly equal to 7/400 of a
1185 millimeter. If not specified, each margin
1186 defaults to one inch (25.4 mm).
1188 MARGINS NOTE. right-margin and bottom-margin are overridden by
1189 the height and width properties. If you want to specify size
1190 of the printable area in character, as with the rest of XEmacs,
1191 use these properties. If height and/or width are nil, then
1192 corresponding margin setting is taken into account. If you
1193 specify height and/or width in `default-frame-plist', but still
1194 want to specify right/bottom margins, set height/width in this
1195 plist to nil, as in this example:
1197 (setq default-frame-plist '(height 55 'width 80)
1198 default-msprinter-frame-plist '(height nil 'width nil))
1200 See also `default-frame-plist', which specifies properties which apply
1201 to all frames, not just mswindows frames.
1203 Vdefault_msprinter_frame_plist = Qnil;
1205 msprinter_console_methods->device_specific_frame_props =
1206 &Vdefault_msprinter_frame_plist;