Mercurial > hg > xemacs-beta
view src/frame-msw.c @ 853:2b6fa2618f76
[xemacs-hg @ 2002-05-28 08:44:22 by ben]
merge my stderr-proc ws
make-docfile.c: Fix places where we forget to check for EOF.
code-init.el: Don't use CRLF conversion by default on process output. CMD.EXE and
friends work both ways but Cygwin programs don't like the CRs.
code-process.el, multicast.el, process.el: Removed.
Improvements to call-process-internal:
-- allows a buffer to be specified for input and stderr output
-- use it on all systems
-- implement C-g as documented
-- clean up and comment
call-process-region uses new call-process facilities; no temp file.
remove duplicate funs in process.el.
comment exactly how coding systems work and fix various problems.
open-multicast-group now does similar coding-system frobbing to
open-network-stream.
dumped-lisp.el, faces.el, msw-faces.el: Fix some hidden errors due to code not being defined at the right time.
xemacs.mak: Add -DSTRICT.
================================================================
ALLOW SEPARATION OF STDOUT AND STDERR IN PROCESSES
================================================================
Standard output and standard error can be processed separately in
a process. Each can have its own buffer, its own mark in that buffer,
and its filter function. You can specify a separate buffer for stderr
in `start-process' to get things started, or use the new primitives:
set-process-stderr-buffer
process-stderr-buffer
process-stderr-mark
set-process-stderr-filter
process-stderr-filter
Also, process-send-region takes a 4th optional arg, a buffer.
Currently always uses a pipe() under Unix to read the error output.
(#### Would a PTY be better?)
sysdep.h, sysproc.h, unexfreebsd.c, unexsunos4.c, nt.c, emacs.c, callproc.c, symsinit.h, sysdep.c, Makefile.in.in, process-unix.c: Delete callproc.c. Move child_setup() to process-unix.c.
wait_for_termination() now only needed on a few really old systems.
console-msw.h, event-Xt.c, event-msw.c, event-stream.c, event-tty.c, event-unixoid.c, events.h, process-nt.c, process-unix.c, process.c, process.h, procimpl.h: Rewrite the process methods to handle a separate channel for
error input. Create Lstreams for reading in the error channel.
Many process methods need change. In general the changes are
fairly clear as they involve duplicating what's used for reading
the normal stdout and changing for stderr -- although tedious,
as such changes are required throughout the entire process code.
Rewrote the code that reads process output to do two loops, one
for stdout and one for stderr.
gpmevent.c, tooltalk.c: set_process_filter takes an argument for stderr.
================================================================
NEW ERROR-TRAPPING MECHANISM
================================================================
Totally rewrite error trapping code to be unified and support more
features. Basic function is call_trapping_problems(), which lets
you specify, by means of flags, what sorts of problems you want
trapped. these can include
-- quit
-- errors
-- throws past the function
-- creation of "display objects" (e.g. buffers)
-- deletion of already-existing "display objects" (e.g. buffers)
-- modification of already-existing buffers
-- entering the debugger
-- gc
-- errors->warnings (ala suspended errors)
etc. All other error funs rewritten in terms of this one.
Various older mechanisms removed or rewritten.
window.c, insdel.c, console.c, buffer.c, device.c, frame.c: When creating a display object, added call to
note_object_created(), for use with trapping_problems mechanism.
When deleting, call check_allowed_operation() and note_object
deleted().
The trapping-problems code records the objects created since the
call-trapping-problems began. Those objects can be deleted, but
none others (i.e. previously existing ones).
bytecode.c, cmdloop.c: internal_catch takes another arg.
eval.c: Add long comments describing the "five lists" used to maintain
state (backtrace, gcpro, specbind, etc.) in the Lisp engine.
backtrace.h, eval.c: Implement trapping-problems mechanism, eliminate old mechanisms or
redo in terms of new one.
frame.c, gutter.c: Flush out the concept of "critical display section", defined by
the in_display() var. Use an internal_bind() to get it reset,
rather than just doing it at end, because there may be a non-local
exit.
event-msw.c, event-stream.c, console-msw.h, device.c, dialog-msw.c, frame.c, frame.h, intl.c, toolbar.c, menubar-msw.c, redisplay.c, alloc.c, menubar-x.c: Make use of new trapping-errors stuff and rewrite code based on
old mechanisms.
glyphs-widget.c, redisplay.h: Protect calling Lisp in redisplay.
insdel.c: Protect hooks against deleting existing buffers.
frame-msw.c: Use EQ, not EQUAL in hash tables whose keys are just numbers.
Otherwise we run into stickiness in redisplay because
internal_equal() can QUIT.
================================================================
SIGNAL, C-G CHANGES
================================================================
Here we change the way that C-g interacts with event reading. The
idea is that a C-g occurring while we're reading a user event
should be read as C-g, but elsewhere should be a QUIT. The former
code did all sorts of bizarreness -- requiring that no QUIT occurs
anywhere in event-reading code (impossible to enforce given the
stuff called or Lisp code invoked), and having some weird system
involving enqueue/dequeue of a C-g and interaction with Vquit_flag
-- and it didn't work.
Now, we simply enclose all code where we want C-g read as an event
with {begin/end}_dont_check_for_quit(). This completely turns off
the mechanism that checks (and may remove or alter) C-g in the
read-ahead queues, so we just get the C-g normal.
Signal.c documents this very carefully.
cmdloop.c: Correct use of dont_check_for_quit to new scheme, remove old
out-of-date comments.
event-stream.c: Fix C-g handling to actually work.
device-x.c: Disable quit checking when err out.
signal.c: Cleanup. Add large descriptive comment.
process-unix.c, process-nt.c, sysdep.c: Use QUIT instead of REALLY_QUIT.
It's not necessary to use REALLY_QUIT and just confuses the issue.
lisp.h: Comment quit handlers.
================================================================
CONS CHANGES
================================================================
free_cons() now takes a Lisp_Object not the result of XCONS().
car and cdr have been renamed so that they don't get used directly;
go through XCAR(), XCDR() instead.
alloc.c, dired.c, editfns.c, emodules.c, fns.c, glyphs-msw.c, glyphs-x.c, glyphs.c, keymap.c, minibuf.c, search.c, eval.c, lread.c, lisp.h: Correct free_cons calling convention: now takes Lisp_Object,
not Lisp_Cons
chartab.c: Eliminate direct use of ->car, ->cdr, should be black box.
callint.c: Rewrote using EXTERNAL_LIST_LOOP to avoid use of Lisp_Cons.
================================================================
USE INTERNAL-BIND-*
================================================================
eval.c: Cleanups of these funs.
alloc.c, fileio.c, undo.c, specifier.c, text.c, profile.c, lread.c, redisplay.c, menubar-x.c, macros.c: Rewrote to use internal_bind_int() and internal_bind_lisp_object()
in place of whatever varied and cumbersome mechanisms were
formerly there.
================================================================
SPECBIND SANITY
================================================================
backtrace.h: - Improved comments
backtrace.h, bytecode.c, eval.c: Add new mechanism check_specbind_stack_sanity() for sanity
checking code each time the catchlist or specbind stack change.
Removed older prototype of same mechanism.
================================================================
MISC
================================================================
lisp.h, insdel.c, window.c, device.c, console.c, buffer.c: Fleshed out authorship.
device-msw.c: Correct bad Unicode-ization.
print.c: Be more careful when not initialized or in fatal error handling.
search.c: Eliminate running_asynch_code, an FSF holdover.
alloc.c: Added comments about gc-cons-threshold.
dialog-x.c: Use begin_gc_forbidden() around code to build up a widget value
tree, like in menubar-x.c.
gui.c: Use Qunbound not Qnil as the default for
gethash.
lisp-disunion.h, lisp-union.h: Added warnings on use of VOID_TO_LISP().
lisp.h: Use ERROR_CHECK_STRUCTURES to turn on
ERROR_CHECK_TRAPPING_PROBLEMS and ERROR_CHECK_TYPECHECK
lisp.h: Add assert_with_message.
lisp.h: Add macros for gcproing entire arrays. (You could do this before
but it required manual twiddling the gcpro structure.)
lisp.h: Add prototypes for new functions defined elsewhere.
author | ben |
---|---|
date | Tue, 28 May 2002 08:45:36 +0000 |
parents | 28426972f654 |
children | 804517e16990 |
line wrap: on
line source
/* Functions for the mswindows window system. Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. Copyright (C) 1995, 1996, 2001, 2002 Ben Wing. This file is part of XEmacs. XEmacs is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. XEmacs is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with XEmacs; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Synched up with: Not synched with FSF. */ /* This file Mule-ized, 8-14-2000. */ /* Authorship: Ultimately based on FSF. Substantially rewritten for XEmacs by Ben Wing. Rewritten for mswindows by Jonathan Harris, November 1997 for 21.0. Graphics features added and frame resizing fiddled with by Andy Piper. */ #include <config.h> #include "lisp.h" #include "buffer.h" #include "device.h" #include "elhash.h" #include "events.h" #include "faces.h" #include "frame.h" #include "redisplay.h" #include "window.h" #include "console-msw.h" #include "glyphs-msw.h" #define MSWINDOWS_FRAME_STYLE (WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW) #define MSWINDOWS_POPUP_STYLE (WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_POPUP \ | WS_CAPTION | WS_BORDER | WS_SYSMENU | WS_MINIMIZEBOX) #define MSWINDOWS_FRAME_EXSTYLE WS_EX_OVERLAPPEDWINDOW #define MSWINDOWS_POPUP_EXSTYLE WS_EX_PALETTEWINDOW /* Default popup left top corner offset from the same corner of the parent frame, in pixel */ #define POPUP_OFFSET 30 /* Default popup size, in characters */ #define POPUP_WIDTH 30 #define POPUP_HEIGHT 10 /* Default regular frame size, in characters; if too big, it will get shrunk to the workspace size */ #define DEFAULT_FRAME_WIDTH 80 #define DEFAULT_FRAME_HEIGHT 50 #ifdef HAVE_MENUBARS #define ADJR_MENUFLAG TRUE #else #define ADJR_MENUFLAG FALSE #endif /* Default properties to use when creating frames. */ Lisp_Object Vdefault_mswindows_frame_plist; Lisp_Object Vdefault_msprinter_frame_plist; Lisp_Object Vmswindows_use_system_frame_size_defaults; /* This does not need to be GC protected, as it holds a frame Lisp_Object already protected by Fmake_frame */ Lisp_Object Vmswindows_frame_being_created; /*---------------------------------------------------------------------*/ /*----- DISPLAY FRAME -----*/ /*---------------------------------------------------------------------*/ HWND mswindows_get_selected_frame_hwnd (void) { Lisp_Object frame, device; device = Ffind_device (Qnil, Qmswindows); if (NILP (device)) return NULL; frame = DEVICE_SELECTED_FRAME (XDEVICE (device)); if (NILP (frame)) return NULL; return FRAME_MSWINDOWS_HANDLE (XFRAME (frame)); } static void mswindows_init_frame_1 (struct frame *f, Lisp_Object props, int frame_name_is_defaulted) { Lisp_Object initially_unmapped; Lisp_Object name, height, width, popup, top, left; Lisp_Object frame_obj = Qnil; RECT rect; XEMACS_RECT_WH rect_default; DWORD style, exstyle; HWND hwnd, hwnd_parent; /* Pick up relevant properties */ initially_unmapped = Fplist_get (props, Qinitially_unmapped, Qnil); name = Fplist_get (props, Qname, Qnil); popup = Fplist_get (props, Qpopup, Qnil); if (EQ (popup, Qt)) popup = Fselected_frame (Qnil); left = Fplist_get (props, Qleft, Qnil); if (!NILP (left)) CHECK_INT (left); top = Fplist_get (props, Qtop, Qnil); if (!NILP (top)) CHECK_INT (top); width = Fplist_get (props, Qwidth, Qnil); if (!NILP (width)) CHECK_INT (width); height = Fplist_get (props, Qheight, Qnil); if (!NILP (height)) CHECK_INT (height); f->frame_data = xnew_and_zero (struct mswindows_frame); FRAME_MSWINDOWS_TARGET_RECT (f) = xnew_and_zero (XEMACS_RECT_WH); FRAME_MSWINDOWS_TARGET_RECT (f)->left = NILP (left) ? -1 : abs (XINT (left)); FRAME_MSWINDOWS_TARGET_RECT (f)->top = NILP (top) ? -1 : abs (XINT (top)); FRAME_MSWINDOWS_TARGET_RECT (f)->width = NILP (width) ? -1 : abs (XINT (width)); FRAME_MSWINDOWS_TARGET_RECT (f)->height = NILP (height) ? -1 : abs (XINT (height)); /* Misc frame stuff */ FRAME_MSWINDOWS_MENU_HASH_TABLE (f) = Qnil; #ifdef HAVE_TOOLBARS FRAME_MSWINDOWS_TOOLBAR_HASH_TABLE (f) = make_lisp_hash_table (50, HASH_TABLE_NON_WEAK, HASH_TABLE_EQUAL); #endif /* hashtable of instantiated glyphs on the frame. make them EQ because we only use ints as keys. otherwise we run into stickiness in redisplay because internal_equal() can QUIT. */ FRAME_MSWINDOWS_WIDGET_HASH_TABLE1 (f) = make_lisp_hash_table (50, HASH_TABLE_VALUE_WEAK, HASH_TABLE_EQ); FRAME_MSWINDOWS_WIDGET_HASH_TABLE2 (f) = make_lisp_hash_table (50, HASH_TABLE_VALUE_WEAK, HASH_TABLE_EQ); FRAME_MSWINDOWS_WIDGET_HASH_TABLE3 (f) = make_lisp_hash_table (50, HASH_TABLE_VALUE_WEAK, HASH_TABLE_EQ); /* Will initialize these in WM_SIZE handler. We cannot do it now, because we do not know what is CW_USEDEFAULT height and width */ FRAME_WIDTH (f) = 0; FRAME_HEIGHT (f) = 0; FRAME_PIXWIDTH (f) = 0; FRAME_PIXHEIGHT (f) = 0; if (NILP (popup)) { style = MSWINDOWS_FRAME_STYLE; exstyle = MSWINDOWS_FRAME_EXSTYLE; hwnd_parent = NULL; rect_default.left = rect_default.top = CW_USEDEFAULT; rect_default.width = rect_default.height = CW_USEDEFAULT; } else { style = MSWINDOWS_POPUP_STYLE; exstyle = MSWINDOWS_POPUP_EXSTYLE; CHECK_MSWINDOWS_FRAME (popup); hwnd_parent = FRAME_MSWINDOWS_HANDLE (XFRAME (popup)); assert (IsWindow (hwnd_parent)); /* We cannot use CW_USEDEFAULT when creating a popup window. So by default, we offset the new popup 30 pixels right and down from its parent, and give it size of 30x10 characters. These dimensions look adequate on both high and low res monitors */ GetWindowRect (hwnd_parent, &rect); rect_default.left = rect.left + POPUP_OFFSET; rect_default.top = rect.top + POPUP_OFFSET; char_to_real_pixel_size (f, POPUP_WIDTH, POPUP_HEIGHT, &rect_default.width, &rect_default.height); FRAME_MSWINDOWS_POPUP (f) = 1; } AdjustWindowRectEx (&rect, style, ADJR_MENUFLAG, exstyle); frame_obj = wrap_frame (f); Vmswindows_frame_being_created = frame_obj; { const Extbyte *nameext = 0; if (STRINGP (f->name)) LISP_STRING_TO_TSTR (f->name, nameext); else if (STRINGP (name)) LISP_STRING_TO_TSTR (name, nameext); else nameext = XETEXT (XEMACS_CLASS); hwnd = qxeCreateWindowEx (exstyle, XETEXT (XEMACS_CLASS), nameext, style, rect_default.left, rect_default.top, rect_default.width, rect_default.height, hwnd_parent, NULL, NULL, NULL); } Vmswindows_frame_being_created = Qnil; if (hwnd == NULL) invalid_operation ("System call to create frame failed", STRINGP (f->name) ? f->name : STRINGP (name) ? name : Qunbound); FRAME_MSWINDOWS_HANDLE (f) = hwnd; qxeSetWindowLong (hwnd, XWL_FRAMEOBJ, (LONG)LISP_TO_VOID (frame_obj)); FRAME_MSWINDOWS_DC (f) = GetDC (hwnd); SetTextAlign (FRAME_MSWINDOWS_DC (f), TA_BASELINE | TA_LEFT | TA_NOUPDATECP); #ifdef HAVE_DIALOGS if (FRAME_MSWINDOWS_POPUP (f)) mswindows_register_popup_frame (frame_obj); #endif /* HAVE_DIALOGS */ } static void mswindows_init_frame_2 (struct frame *f, Lisp_Object props) { if (NILP (Vmswindows_use_system_frame_size_defaults)) { /* I don't think anything can set the frame size before this since we don't have X resources. This may change if we look at the registry. Even so these values can get overridden later.*/ XEMACS_RECT_WH dest = { -1, -1, DEFAULT_FRAME_WIDTH, DEFAULT_FRAME_HEIGHT }; mswindows_size_frame_internal (f, &dest); } } /* Called after frame's properties are set */ static void mswindows_init_frame_3 (struct frame *f) { /* Don't do this earlier or we get a WM_PAINT before the frame is ready */ ShowWindow (FRAME_MSWINDOWS_HANDLE (f), SW_SHOWNORMAL); SetForegroundWindow (FRAME_MSWINDOWS_HANDLE (f)); DragAcceptFiles (FRAME_MSWINDOWS_HANDLE (f), TRUE); } static void mswindows_after_init_frame (struct frame *f, int first_on_device, int first_on_console) { /* Windows, unlike X, is very synchronous. After the initial frame is created, it will never be displayed, except for hollow border, unless we start pumping messages. Load progress messages show in the bottom of the hollow frame, which is ugly. We redisplay the initial frame here, so modeline and root window background show. */ if (first_on_console) redisplay (); } static void mswindows_mark_frame (struct frame *f) { mark_object (FRAME_MSWINDOWS_MENU_HASH_TABLE (f)); #ifdef HAVE_TOOLBARS mark_object (FRAME_MSWINDOWS_TOOLBAR_HASH_TABLE (f)); #endif mark_object (FRAME_MSWINDOWS_WIDGET_HASH_TABLE1 (f)); mark_object (FRAME_MSWINDOWS_WIDGET_HASH_TABLE2 (f)); mark_object (FRAME_MSWINDOWS_WIDGET_HASH_TABLE3 (f)); } static void mswindows_focus_on_frame (struct frame *f) { SetForegroundWindow (FRAME_MSWINDOWS_HANDLE (f)); } static void mswindows_delete_frame (struct frame *f) { if (f->frame_data) { #ifdef HAVE_DIALOGS mswindows_unregister_popup_frame (wrap_frame (f)); #endif ReleaseDC (FRAME_MSWINDOWS_HANDLE (f), FRAME_MSWINDOWS_DC (f)); DestroyWindow (FRAME_MSWINDOWS_HANDLE (f)); xfree (f->frame_data); } f->frame_data = 0; } static void mswindows_set_frame_size (struct frame *f, int width, int height) { RECT rect; rect.left = rect.top = 0; rect.right = width; rect.bottom = height; AdjustWindowRectEx (&rect, qxeGetWindowLong (FRAME_MSWINDOWS_HANDLE (f), GWL_STYLE), GetMenu (FRAME_MSWINDOWS_HANDLE (f)) != NULL, qxeGetWindowLong (FRAME_MSWINDOWS_HANDLE (f), GWL_EXSTYLE)); if (IsIconic (FRAME_MSWINDOWS_HANDLE (f)) || IsZoomed (FRAME_MSWINDOWS_HANDLE (f))) ShowWindow (FRAME_MSWINDOWS_HANDLE (f), SW_RESTORE); SetWindowPos (FRAME_MSWINDOWS_HANDLE (f), NULL, 0, 0, rect.right-rect.left, rect.bottom-rect.top, SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSENDCHANGING | SWP_NOMOVE); } static void mswindows_set_frame_position (struct frame *f, int xoff, int yoff) { SetWindowPos (FRAME_MSWINDOWS_HANDLE (f), NULL, xoff, yoff, 0, 0, SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSENDCHANGING | SWP_NOSIZE); } static void mswindows_make_frame_visible (struct frame *f) { if (!FRAME_VISIBLE_P (f)) ShowWindow (FRAME_MSWINDOWS_HANDLE (f), SW_RESTORE); else ShowWindow (FRAME_MSWINDOWS_HANDLE (f), SW_SHOW); SetActiveWindow (FRAME_MSWINDOWS_HANDLE (f)); f->visible = 1; f->iconified = 0; } static void mswindows_make_frame_invisible (struct frame *f) { if (!FRAME_VISIBLE_P (f)) return; ShowWindow (FRAME_MSWINDOWS_HANDLE (f), SW_HIDE); f->visible = 0; } static int mswindows_frame_totally_visible_p (struct frame *f) { RECT rc_me, rc_other, rc_temp; HWND hwnd = FRAME_MSWINDOWS_HANDLE (f); /* We test against not a whole window rectangle, only against its client part. So, if non-client are is covered and client area is not, we return true. */ GetClientRect (hwnd, &rc_me); MapWindowPoints (hwnd, HWND_DESKTOP, (LPPOINT)&rc_me, 2); /* First see if we're off the desktop */ GetWindowRect (GetDesktopWindow (), &rc_other); UnionRect (&rc_temp, &rc_me, &rc_other); if (!EqualRect (&rc_temp, &rc_other)) return 0; /* Then see if any window above us obscures us */ while ((hwnd = GetWindow (hwnd, GW_HWNDPREV)) != NULL) if (IsWindowVisible (hwnd)) { GetWindowRect (hwnd, &rc_other); if (IntersectRect (&rc_temp, &rc_me, &rc_other)) return 0; } return 1; } static int mswindows_frame_visible_p (struct frame *f) { return IsWindowVisible (FRAME_MSWINDOWS_HANDLE (f)) && !IsIconic (FRAME_MSWINDOWS_HANDLE (f)); } static void mswindows_iconify_frame (struct frame *f) { ShowWindow (FRAME_MSWINDOWS_HANDLE (f), SW_MINIMIZE); f->visible = 0; f->iconified = 1; } static int mswindows_frame_iconified_p (struct frame *f) { return IsIconic (FRAME_MSWINDOWS_HANDLE (f)); } static void mswindows_set_frame_icon (struct frame *f) { if (IMAGE_INSTANCEP (f->icon) && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (f->icon))) { if (!XIMAGE_INSTANCE_MSWINDOWS_ICON (f->icon)) { mswindows_initialize_image_instance_icon (XIMAGE_INSTANCE (f->icon), FALSE); } qxeSetClassLong (FRAME_MSWINDOWS_HANDLE (f), GCL_HICON, (LONG) XIMAGE_INSTANCE_MSWINDOWS_ICON (f->icon)); } } static void mswindows_set_frame_pointer (struct frame *f) { if (IMAGE_INSTANCEP (f->pointer) && IMAGE_INSTANCE_TYPE (XIMAGE_INSTANCE (f->pointer)) == IMAGE_POINTER) { qxeSetClassLong (FRAME_MSWINDOWS_HANDLE (f), GCL_HCURSOR, (LONG) XIMAGE_INSTANCE_MSWINDOWS_ICON (f->pointer)); /* we only have to do this because GC doesn't cause a mouse event and doesn't give time to event processing even if it did. */ SetCursor (XIMAGE_INSTANCE_MSWINDOWS_ICON (f->pointer)); } } static void mswindows_set_mouse_position (struct window *w, int x, int y) { struct frame *f = XFRAME (w->frame); POINT pt; pt.x = w->pixel_left + x; pt.y = w->pixel_top + y; ClientToScreen (FRAME_MSWINDOWS_HANDLE (f), &pt); SetCursorPos (pt.x, pt.y); } static int mswindows_get_mouse_position (struct device *d, Lisp_Object *frame, int *x, int *y) { POINT pt; HWND hwnd; GetCursorPos (&pt); /* What's under cursor? */ hwnd = WindowFromPoint (pt); if (hwnd == NULL) return 0; /* Get grandest parent of the window */ { HWND hwnd_parent; while ((hwnd_parent = GetParent (hwnd)) != NULL) hwnd = hwnd_parent; } /* Make sure it belongs to us */ if (GetWindowThreadProcessId (hwnd, NULL) != GetCurrentThreadId ()) return 0; /* And that the window is an XEmacs frame */ if (!mswindows_window_is_xemacs (hwnd)) return 0; /* Yippie! */ ScreenToClient (hwnd, &pt); *frame = VOID_TO_LISP ((void *) qxeGetWindowLong (hwnd, XWL_FRAMEOBJ)); *x = pt.x; *y = pt.y; return 1; } static void mswindows_raise_frame (struct frame *f) { BringWindowToTop (FRAME_MSWINDOWS_HANDLE (f)); } static void mswindows_lower_frame (struct frame *f) { SetWindowPos (FRAME_MSWINDOWS_HANDLE (f), HWND_BOTTOM, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOSENDCHANGING); } static void mswindows_enable_frame (struct frame *f) { EnableWindow (FRAME_MSWINDOWS_HANDLE (f), TRUE); } static void mswindows_disable_frame (struct frame *f) { EnableWindow (FRAME_MSWINDOWS_HANDLE (f), FALSE); } static void mswindows_set_title_from_intbyte (struct frame *f, Intbyte *title) { unsigned int new_checksum = hash_string (title, qxestrlen (title)); if (new_checksum != FRAME_MSWINDOWS_TITLE_CHECKSUM (f)) { Extbyte *title_ext; FRAME_MSWINDOWS_TITLE_CHECKSUM (f) = new_checksum; C_STRING_TO_TSTR (title, title_ext); qxeSetWindowText (FRAME_MSWINDOWS_HANDLE (f), title_ext); } } static Lisp_Object mswindows_frame_property (struct frame *f, Lisp_Object property) { if (EQ (Qleft, property) || EQ (Qtop, property)) { RECT rc; GetWindowRect (FRAME_MSWINDOWS_HANDLE (f), &rc); return make_int (EQ (Qtop, property) ? rc.top : rc.left); } return Qunbound; } static int mswindows_internal_frame_property_p (struct frame *f, Lisp_Object property) { return EQ (property, Qleft) || EQ (property, Qtop); /* #### frame-x.c has also this. Why? || STRINGP (property); */ } static Lisp_Object mswindows_frame_properties (struct frame *f) { Lisp_Object props = Qnil; RECT rc; GetWindowRect (FRAME_MSWINDOWS_HANDLE (f), &rc); props = cons3 (Qtop, make_int (rc.top), props); props = cons3 (Qleft, make_int (rc.left), props); return props; } static void mswindows_set_frame_properties (struct frame *f, Lisp_Object plist) { int x=-1, y=-1; int width = -1, height = -1; BOOL width_specified_p = FALSE; BOOL height_specified_p = FALSE; BOOL x_specified_p = FALSE; BOOL y_specified_p = FALSE; Lisp_Object tail; /* Extract the properties from plist */ for (tail = plist; !NILP (tail); tail = Fcdr (Fcdr (tail))) { Lisp_Object prop = Fcar (tail); Lisp_Object val = Fcar (Fcdr (tail)); if (SYMBOLP (prop)) { /* Kludge to handle the font property. */ if (EQ (prop, Qfont)) { /* If the value is not a string we silently ignore it. */ if (STRINGP (val)) { Lisp_Object frm, font_spec; frm = wrap_frame (f); font_spec = Fget (Fget_face (Qdefault), Qfont, Qnil); Fadd_spec_to_specifier (font_spec, val, frm, Qnil, Qnil); update_frame_face_values (f); } } else if (EQ (prop, Qwidth)) { CHECK_INT (val); width = XINT (val); width_specified_p = TRUE; } else if (EQ (prop, Qheight)) { CHECK_INT (val); height = XINT (val); height_specified_p = TRUE; } else if (EQ (prop, Qleft)) { CHECK_INT (val); x = XINT (val); x_specified_p = TRUE; } else if (EQ (prop, Qtop)) { CHECK_INT (val); y = XINT (val); y_specified_p = TRUE; } } } /* Now we've extracted the properties, apply them. Do not apply geometric properties during frame creation. This is excessive anyways, and this loses because WM_SIZE has not been sent yet, so frame width and height fields are not initialized. unfortunately WM_SIZE loses as well since the resize is only applied once and the first time WM_SIZE is applied not everything is initialised in the frame (toolbars for instance). enabling this always makes no visible difference and fixes a whole host of bugs (and is more consistent with X) so I am going to reenable it. --andyp */ if ( FRAME_PIXWIDTH (f) && FRAME_PIXHEIGHT (f) && (width_specified_p || height_specified_p || x_specified_p || y_specified_p)) { XEMACS_RECT_WH dest = { x, y, width, height }; mswindows_size_frame_internal (f, &dest); } } void mswindows_size_frame_internal (struct frame *f, XEMACS_RECT_WH *dest) { RECT rect, ws_rect; int pixel_width, pixel_height; int size_p = (dest->width >=0 || dest->height >=0); int move_p = (dest->top >=0 || dest->left >=0); char_to_real_pixel_size (f, dest->width, dest->height, &pixel_width, &pixel_height); if (dest->width < 0) pixel_width = FRAME_PIXWIDTH (f); if (dest->height < 0) pixel_height = FRAME_PIXHEIGHT (f); GetWindowRect (FRAME_MSWINDOWS_HANDLE (f), &rect); if (dest->left < 0) dest->left = rect.left; if (dest->top < 0) dest->top = rect.top; rect.left = rect.top = 0; rect.right = pixel_width; rect.bottom = pixel_height; AdjustWindowRectEx (&rect, qxeGetWindowLong (FRAME_MSWINDOWS_HANDLE (f), GWL_STYLE), GetMenu (FRAME_MSWINDOWS_HANDLE (f)) != NULL, qxeGetWindowLong (FRAME_MSWINDOWS_HANDLE (f), GWL_EXSTYLE)); /* resize and move the window so that it fits in the workspace. This is not restrictive since this will happen later anyway in WM_SIZE. We have to do this after adjusting the rect to account for menubar etc. */ mswindows_get_workspace_coords (&ws_rect); pixel_width = rect.right - rect.left; pixel_height = rect.bottom - rect.top; if (pixel_width > ws_rect.right - ws_rect.left) { pixel_width = ws_rect.right - ws_rect.left; size_p=1; } if (pixel_height > ws_rect.bottom - ws_rect.top) { pixel_height = ws_rect.bottom - ws_rect.top; size_p=1; } /* adjust position so window is in workspace */ if (dest->left + pixel_width > ws_rect.right) { dest->left = ws_rect.right - pixel_width; move_p=1; } if (dest->left < ws_rect.left) { dest->left = ws_rect.left; move_p=1; } if (dest->top + pixel_height > ws_rect.bottom) { dest->top = ws_rect.bottom - pixel_height; move_p=1; } if (dest->top < ws_rect.top) { dest->top = ws_rect.top; move_p=1; } if (IsIconic (FRAME_MSWINDOWS_HANDLE (f)) || IsZoomed (FRAME_MSWINDOWS_HANDLE (f))) ShowWindow (FRAME_MSWINDOWS_HANDLE (f), SW_RESTORE); SetWindowPos (FRAME_MSWINDOWS_HANDLE (f), NULL, dest->left, dest->top, pixel_width, pixel_height, SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSENDCHANGING | (size_p ? 0 : SWP_NOSIZE) | (move_p ? 0 : SWP_NOMOVE)); } static Lisp_Object mswindows_get_frame_parent (struct frame *f) { HWND hwnd = FRAME_MSWINDOWS_HANDLE (f); hwnd = GetParent (hwnd); if (hwnd) { Lisp_Object parent; parent = VOID_TO_LISP ((void *) qxeGetWindowLong (hwnd, XWL_FRAMEOBJ)); assert (FRAME_MSWINDOWS_P (XFRAME (parent))); return parent; } else return Qnil; } static void mswindows_update_frame_external_traits (struct frame *frm, Lisp_Object name) { } static int mswindows_frame_size_fixed_p (struct frame *f) { /* Frame size cannot change if the frame is maximized */ return IsZoomed (FRAME_MSWINDOWS_HANDLE (f)); } /*---------------------------------------------------------------------*/ /*----- PRINTER FRAME -----*/ /*---------------------------------------------------------------------*/ /* * With some driver/os combination (I discovered this with HP drivers * under W2K), DC geometry is reset upon StartDoc and EndPage * calls. This is called every time one of these calls is made. */ static void apply_dc_geometry (struct frame* f) { HDC hdc = DEVICE_MSPRINTER_HDC (XDEVICE (FRAME_DEVICE (f))); SetTextAlign (hdc, TA_BASELINE | TA_LEFT | TA_NOUPDATECP); SetViewportOrgEx (hdc, FRAME_MSPRINTER_PIXLEFT(f), FRAME_MSPRINTER_PIXTOP(f), NULL); } void msprinter_start_page (struct frame *f) { if (!FRAME_MSPRINTER_PAGE_STARTED (f)) { FRAME_MSPRINTER_PAGE_STARTED (f) = 1; StartPage (DEVICE_MSPRINTER_HDC (XDEVICE (FRAME_DEVICE (f)))); apply_dc_geometry (f); } } static void error_frame_unsizable (struct frame *f) { Lisp_Object frame = wrap_frame (f); invalid_change ("Cannot resize frame (margins) after print job has started.", frame); } static void maybe_error_if_job_active (struct frame *f) { if (FRAME_MSPRINTER_JOB_STARTED (f)) error_frame_unsizable (f); } static void msprinter_init_frame_1 (struct frame *f, Lisp_Object props, int frame_name_is_defaulted) { /* Make sure this is the only frame on device. Windows printer can handle only one job at a time. */ if (!NILP (DEVICE_FRAME_LIST (XDEVICE (FRAME_DEVICE (f))))) invalid_operation ("Only one frame (print job) at a time is allowed on " "this printer device", FRAME_DEVICE (f)); f->frame_data = xnew_and_zero (struct msprinter_frame); FRAME_MSPRINTER_TOP_MARGIN (f) = mswindows_get_default_margin (Qtop_margin); FRAME_MSPRINTER_BOTTOM_MARGIN (f) = mswindows_get_default_margin (Qbottom_margin); FRAME_MSPRINTER_LEFT_MARGIN (f) = mswindows_get_default_margin (Qleft_margin); FRAME_MSPRINTER_RIGHT_MARGIN (f) = mswindows_get_default_margin (Qright_margin); /* Negative for "uinspecified" */ FRAME_MSPRINTER_CHARWIDTH (f) = -1; FRAME_MSPRINTER_CHARHEIGHT (f) = -1; } static void msprinter_init_frame_3 (struct frame *f) { DOCINFOW di; struct device *device = XDEVICE (FRAME_DEVICE (f)); HDC hdc; int frame_left, frame_top, frame_width, frame_height; /* DC might be recreated in msprinter_apply_devmode, so do not initialize until now */ hdc = DEVICE_MSPRINTER_HDC (device); /* Compute geometry properties */ frame_left = (MulDiv (GetDeviceCaps (hdc, LOGPIXELSX), FRAME_MSPRINTER_LEFT_MARGIN (f), 1440) - GetDeviceCaps (hdc, PHYSICALOFFSETX)); if (FRAME_MSPRINTER_CHARWIDTH (f) > 0) { char_to_real_pixel_size (f, FRAME_MSPRINTER_CHARWIDTH (f), 0, &frame_width, NULL); FRAME_MSPRINTER_RIGHT_MARGIN (f) = MulDiv (GetDeviceCaps (hdc, PHYSICALWIDTH) - (frame_left + frame_width), 1440, GetDeviceCaps (hdc, LOGPIXELSX)); } else frame_width = (GetDeviceCaps (hdc, PHYSICALWIDTH) - frame_left - MulDiv (GetDeviceCaps (hdc, LOGPIXELSX), FRAME_MSPRINTER_RIGHT_MARGIN (f), 1440)); frame_top = (MulDiv (GetDeviceCaps (hdc, LOGPIXELSY), FRAME_MSPRINTER_TOP_MARGIN (f), 1440) - GetDeviceCaps (hdc, PHYSICALOFFSETY)); if (FRAME_MSPRINTER_CHARHEIGHT (f) > 0) { char_to_real_pixel_size (f, 0, FRAME_MSPRINTER_CHARHEIGHT (f), NULL, &frame_height); FRAME_MSPRINTER_BOTTOM_MARGIN (f) = MulDiv (GetDeviceCaps (hdc, PHYSICALHEIGHT) - (frame_top + frame_height), 1440, GetDeviceCaps (hdc, LOGPIXELSY)); } else frame_height = (GetDeviceCaps (hdc, PHYSICALHEIGHT) - frame_top - MulDiv (GetDeviceCaps (hdc, LOGPIXELSY), FRAME_MSPRINTER_BOTTOM_MARGIN (f), 1440)); /* Geometry sanity checks */ if (!frame_pixsize_valid_p (f, frame_width, frame_height)) invalid_operation ("Area inside print margins has shrunk to naught", STRINGP (f->name) ? f->name : Qunbound); if (frame_left < 0 || frame_top < 0 || frame_left + frame_width > GetDeviceCaps (hdc, HORZRES) || frame_top + frame_height > GetDeviceCaps (hdc, VERTRES)) invalid_operation ("Print area is outside of the printer's " "hardware printable area", STRINGP (f->name) ? f->name : Qunbound); /* Apply XEmacs frame geometry and layout windows */ { int rows, columns; FRAME_PIXWIDTH (f) = frame_width; FRAME_PIXHEIGHT (f) = frame_height; pixel_to_char_size (f, frame_width, frame_height, &columns, &rows); change_frame_size (f, rows, columns, 0); } FRAME_MSPRINTER_PIXLEFT(f) = frame_left; FRAME_MSPRINTER_PIXTOP(f) = frame_top; /* Start print job */ di.cbSize = sizeof (di); { const Extbyte *nameext; if (STRINGP (f->name)) LISP_STRING_TO_TSTR (f->name, nameext); else nameext = XETEXT ("XEmacs print document"); di.lpszDocName = (XELPTSTR) nameext; } di.lpszOutput = NULL; di.lpszDatatype = NULL; di.fwType = 0; if (qxeStartDoc (hdc, &di) <= 0) invalid_operation ("Cannot start print job", STRINGP (f->name) ? f->name : Qunbound); apply_dc_geometry (f); /* Finish frame setup */ FRAME_MSPRINTER_JOB_STARTED (f) = 1; FRAME_VISIBLE_P (f) = 0; } static void msprinter_mark_frame (struct frame *f) { } static void msprinter_delete_frame (struct frame *f) { if (f->frame_data) { HDC hdc = DEVICE_MSPRINTER_HDC (XDEVICE (FRAME_DEVICE (f))); if (FRAME_MSPRINTER_PAGE_STARTED (f)) EndPage (hdc); if (FRAME_MSPRINTER_JOB_STARTED (f)) EndDoc (hdc); xfree (f->frame_data); } f->frame_data = 0; } static Lisp_Object msprinter_frame_property (struct frame *f, Lisp_Object property) { if (EQ (Qleft_margin, property)) return make_int (FRAME_MSPRINTER_LEFT_MARGIN (f)); else if (EQ (Qtop_margin, property)) return make_int (FRAME_MSPRINTER_TOP_MARGIN (f)); if (EQ (Qright_margin, property)) return make_int (FRAME_MSPRINTER_RIGHT_MARGIN (f)); else if (EQ (Qbottom_margin, property)) return make_int (FRAME_MSPRINTER_BOTTOM_MARGIN (f)); else return Qunbound; } static int msprinter_internal_frame_property_p (struct frame *f, Lisp_Object property) { return (EQ (Qleft_margin, property) || EQ (Qtop_margin, property) || EQ (Qright_margin, property) || EQ (Qbottom_margin, property)); } static Lisp_Object msprinter_frame_properties (struct frame *f) { Lisp_Object props = Qnil; props = cons3 (Qbottom_margin, make_int (FRAME_MSPRINTER_BOTTOM_MARGIN (f)), props); props = cons3 (Qright_margin, make_int (FRAME_MSPRINTER_RIGHT_MARGIN (f)), props); props = cons3 (Qtop_margin, make_int (FRAME_MSPRINTER_TOP_MARGIN (f)), props); props = cons3 (Qleft_margin, make_int (FRAME_MSPRINTER_LEFT_MARGIN (f)), props); return props; } static void msprinter_set_frame_properties (struct frame *f, Lisp_Object plist) { Lisp_Object tail; /* Extract the properties from plist */ for (tail = plist; !NILP (tail); tail = Fcdr (Fcdr (tail))) { Lisp_Object prop = Fcar (tail); Lisp_Object val = Fcar (Fcdr (tail)); if (SYMBOLP (prop)) { if (EQ (prop, Qwidth)) { maybe_error_if_job_active (f); if (!NILP (val)) { CHECK_NATNUM (val); FRAME_MSPRINTER_CHARWIDTH (f) = XINT (val); } } if (EQ (prop, Qheight)) { maybe_error_if_job_active (f); if (!NILP (val)) { CHECK_NATNUM (val); FRAME_MSPRINTER_CHARHEIGHT (f) = XINT (val); } } else if (EQ (prop, Qleft_margin)) { maybe_error_if_job_active (f); CHECK_NATNUM (val); FRAME_MSPRINTER_LEFT_MARGIN (f) = XINT (val); } else if (EQ (prop, Qtop_margin)) { maybe_error_if_job_active (f); CHECK_NATNUM (val); FRAME_MSPRINTER_TOP_MARGIN (f) = XINT (val); } else if (EQ (prop, Qright_margin)) { maybe_error_if_job_active (f); CHECK_NATNUM (val); FRAME_MSPRINTER_RIGHT_MARGIN (f) = XINT (val); } else if (EQ (prop, Qbottom_margin)) { maybe_error_if_job_active (f); CHECK_NATNUM (val); FRAME_MSPRINTER_BOTTOM_MARGIN (f) = XINT (val); } } } } static void msprinter_set_frame_size (struct frame *f, int width, int height) { /* We're absolutely unsizeable */ error_frame_unsizable (f); } static void msprinter_eject_page (struct frame *f) { /* #### Should we eject empty pages? */ if (FRAME_MSPRINTER_PAGE_STARTED (f)) { FRAME_MSPRINTER_PAGE_STARTED (f) = 0; EndPage (DEVICE_MSPRINTER_HDC (XDEVICE (FRAME_DEVICE (f)))); apply_dc_geometry (f); } } void console_type_create_frame_mswindows (void) { /* Display frames */ CONSOLE_HAS_METHOD (mswindows, init_frame_1); CONSOLE_HAS_METHOD (mswindows, init_frame_2); CONSOLE_HAS_METHOD (mswindows, init_frame_3); CONSOLE_HAS_METHOD (mswindows, after_init_frame); CONSOLE_HAS_METHOD (mswindows, mark_frame); CONSOLE_HAS_METHOD (mswindows, focus_on_frame); CONSOLE_HAS_METHOD (mswindows, delete_frame); CONSOLE_HAS_METHOD (mswindows, get_mouse_position); CONSOLE_HAS_METHOD (mswindows, set_mouse_position); CONSOLE_HAS_METHOD (mswindows, raise_frame); CONSOLE_HAS_METHOD (mswindows, lower_frame); CONSOLE_HAS_METHOD (mswindows, enable_frame); CONSOLE_HAS_METHOD (mswindows, disable_frame); CONSOLE_HAS_METHOD (mswindows, make_frame_visible); CONSOLE_HAS_METHOD (mswindows, make_frame_invisible); CONSOLE_HAS_METHOD (mswindows, iconify_frame); CONSOLE_HAS_METHOD (mswindows, set_frame_size); CONSOLE_HAS_METHOD (mswindows, set_frame_position); CONSOLE_HAS_METHOD (mswindows, frame_property); CONSOLE_HAS_METHOD (mswindows, internal_frame_property_p); CONSOLE_HAS_METHOD (mswindows, frame_properties); CONSOLE_HAS_METHOD (mswindows, set_frame_properties); CONSOLE_HAS_METHOD (mswindows, set_title_from_intbyte); /* CONSOLE_HAS_METHOD (mswindows, set_icon_name_from_intbyte); */ CONSOLE_HAS_METHOD (mswindows, frame_visible_p); CONSOLE_HAS_METHOD (mswindows, frame_totally_visible_p); CONSOLE_HAS_METHOD (mswindows, frame_iconified_p); CONSOLE_HAS_METHOD (mswindows, set_frame_pointer); CONSOLE_HAS_METHOD (mswindows, set_frame_icon); CONSOLE_HAS_METHOD (mswindows, get_frame_parent); CONSOLE_HAS_METHOD (mswindows, update_frame_external_traits); CONSOLE_HAS_METHOD (mswindows, frame_size_fixed_p); /* Printer frames, aka print jobs */ CONSOLE_HAS_METHOD (msprinter, init_frame_1); CONSOLE_HAS_METHOD (msprinter, init_frame_3); CONSOLE_HAS_METHOD (msprinter, mark_frame); CONSOLE_HAS_METHOD (msprinter, delete_frame); CONSOLE_HAS_METHOD (msprinter, frame_property); CONSOLE_HAS_METHOD (msprinter, internal_frame_property_p); CONSOLE_HAS_METHOD (msprinter, frame_properties); CONSOLE_HAS_METHOD (msprinter, set_frame_properties); CONSOLE_HAS_METHOD (msprinter, set_frame_size); CONSOLE_HAS_METHOD (msprinter, eject_page); } void syms_of_frame_mswindows (void) { } void reinit_vars_of_frame_mswindows (void) { /* Needn't staticpro -- see comment above. */ Vmswindows_frame_being_created = Qnil; } void vars_of_frame_mswindows (void) { reinit_vars_of_frame_mswindows (); DEFVAR_LISP ("mswindows-use-system-frame-size-defaults", &Vmswindows_use_system_frame_size_defaults /* Controls whether to use system or XEmacs defaults for frame size. If nil then reasonable defaults are used for initial frame sizes. If t then the system will choose default sizes for the frame. */ ); Vmswindows_use_system_frame_size_defaults = Qnil; DEFVAR_LISP ("default-mswindows-frame-plist", &Vdefault_mswindows_frame_plist /* Plist of default frame-creation properties for mswindows frames. These override what is specified in `default-frame-plist', but are overridden by the arguments to the particular call to `make-frame'. Note: In many cases, properties of a frame are available as specifiers instead of through the frame-properties mechanism. Here is a list of recognized frame properties, other than those documented in `set-frame-properties' (they can be queried and set at any time, except as otherwise noted): initially-unmapped If non-nil, the frame will not be visible when it is created. In this case, you need to call `make-frame-visible' to make the frame appear. popup If non-nil, it should be a frame, and this frame will be created as a "popup" frame whose parent is the given frame. This will make the window manager treat the frame as a dialog box, which may entail doing different things (e.g. not asking for positioning, and not iconifying separate from its parent). top Y position (in pixels) of the upper-left outermost corner of the frame (i.e. the upper-left of the window-manager decorations). left X position (in pixels) of the upper-left outermost corner of the frame (i.e. the upper-left of the window-manager decorations). See also `default-frame-plist', which specifies properties which apply to all frames, not just mswindows frames. */ ); Vdefault_mswindows_frame_plist = Qnil; mswindows_console_methods->device_specific_frame_props = &Vdefault_mswindows_frame_plist; DEFVAR_LISP ("default-msprinter-frame-plist", &Vdefault_msprinter_frame_plist /* Plist of default frame-creation properties for msprinter print job frames. These override what is specified in `default-frame-plist', but are overridden by the arguments to the particular call to `make-frame'. Note: In many cases, properties of a frame are available as specifiers instead of through the frame-properties mechanism. Here is a list of recognized frame properties, other than those documented in `set-frame-properties' (they can be queried and set at any time, except as otherwise noted): left-margin Margin of the page, in twips. Twip is a top-margin typographical unit of measurement, right-margin equal to 1/1440 of an inch, or 1/20 of a bottom-margin point, and roughly equal to 7/400 of a millimeter. If not specified, the left and right margins default to 1 inch (25.4 mm) and the top and bottom margins to 0.5 inch (12.7 mm). MARGINS NOTE. right-margin and bottom-margin are overridden by the height and width properties. If you want to specify size of the printable area in character, as with the rest of XEmacs, use these properties. If height and/or width are nil, then corresponding margin setting is taken into account. If you specify height and/or width in `default-frame-plist', but still want to specify right/bottom margins, set height/width in this plist to nil, as in this example: (setq default-frame-plist '(height 55 width 80) default-msprinter-frame-plist '(height nil width nil)) See also `default-frame-plist', which specifies properties which apply to all frames, not just mswindows frames. */ ); Vdefault_msprinter_frame_plist = Qnil; msprinter_console_methods->device_specific_frame_props = &Vdefault_msprinter_frame_plist; }