summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRichard M. Stallman <rms@gnu.org>1994-01-18 23:47:41 +0000
committerRichard M. Stallman <rms@gnu.org>1994-01-18 23:47:41 +0000
commit0e3cdce02d796625ee894bfa0ba1bd7b3237c2bc (patch)
treeb24a45c33225bf788e4935fb49a1dc996b57a59c /src
parent066417b1d9d45d7bcf05751e95ce70d3ad7e3522 (diff)
downloademacs-0e3cdce02d796625ee894bfa0ba1bd7b3237c2bc.tar.gz
Initial revision
Diffstat (limited to 'src')
-rw-r--r--src/widget.c900
-rw-r--r--src/widget.h90
2 files changed, 990 insertions, 0 deletions
diff --git a/src/widget.c b/src/widget.c
new file mode 100644
index 00000000000..fda3449be02
--- /dev/null
+++ b/src/widget.c
@@ -0,0 +1,900 @@
+/* The emacs frame widget.
+ Copyright (C) 1992, 1993 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs 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.
+
+GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Emacs 19 face widget ported by Fred Pierresteguy */
+
+#include <stdio.h>
+#include "config.h"
+#include "lisp.h"
+#include "xterm.h"
+
+#include "frame.h"
+
+#include "dispextern.h"
+
+
+#include <X11/StringDefs.h>
+#include <X11/IntrinsicP.h>
+#include <X11/cursorfont.h>
+#include "widgetprv.h"
+#include <X11/Shell.h>
+#include <X11/ShellP.h>
+
+#define max(a, b) ((a) > (b) ? (a) : (b))
+
+/* This sucks: this is the first default that x-faces.el tries. This won't
+ be used unless neither the "Emacs.EmacsFrame" resource nor the
+ "Emacs.EmacsFrame" resource is set; the frame
+ may have the wrong default size if this font doesn't exist, but some other
+ font that x-faces.el does. The workaround is to specify some font in the
+ resource database; I don't know a solution other than duplicating the font-
+ searching code from x-faces.el in this file.
+
+ This also means that if "Emacs.EmacsFrame" is specified as a non-
+ existent font, then Xt is going to substitute "XtDefaultFont" for it,
+ which is a different size than this one. The solution for this is to
+ make x-faces.el try to use XtDefaultFont. The problem with that is that
+ XtDefaultFont is almost certainly variable-width.
+
+ #### Perhaps we could have this code explicitly set XtDefaultFont to this?
+ */
+#define DEFAULT_FACE_FONT "-*-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-*"
+
+
+static void EmacsFrameInitialize (Widget, Widget, ArgList, Cardinal *);
+static void EmacsFrameDestroy (Widget);
+static void EmacsFrameRealize (Widget, XtValueMask*, XSetWindowAttributes*);
+void EmacsFrameResize (Widget widget);
+static Boolean EmacsFrameSetValues (Widget, Widget, Widget,
+ ArgList, Cardinal *);
+static XtGeometryResult EmacsFrameQueryGeometry (Widget, XtWidgetGeometry*,
+ XtWidgetGeometry*);
+
+
+#undef XtOffset
+#define XtOffset(p_type,field) \
+ ((Cardinal) (((char *) (&(((p_type)0)->field))) - ((char *)0)))
+#define offset(field) XtOffset(EmacsFrame, emacs_frame.field)
+
+static XtResource resources[] = {
+ {XtNgeometry, XtCGeometry, XtRString, sizeof(String),
+ offset (geometry), XtRString, (XtPointer) 0},
+ {XtNiconic, XtCIconic, XtRBoolean, sizeof(Boolean),
+ offset (iconic), XtRImmediate, (XtPointer) False},
+
+ {XtNemacsFrame, XtCEmacsFrame, XtRPointer, sizeof (XtPointer),
+ offset (frame), XtRImmediate, 0},
+
+ {XtNminibuffer, XtCMinibuffer, XtRInt, sizeof (int),
+ offset (minibuffer), XtRImmediate, (XtPointer)0},
+ {XtNunsplittable, XtCUnsplittable, XtRBoolean, sizeof (Boolean),
+ offset (unsplittable), XtRImmediate, (XtPointer)0},
+ {XtNinternalBorderWidth, XtCInternalBorderWidth, XtRInt, sizeof (int),
+ offset (internal_border_width), XtRImmediate, (XtPointer)4},
+ {XtNinterline, XtCInterline, XtRInt, sizeof (int),
+ offset (interline), XtRImmediate, (XtPointer)0},
+ {XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *),
+ offset(font),XtRString, DEFAULT_FACE_FONT},
+ {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
+ offset(foreground_pixel), XtRString, "XtDefaultForeground"},
+ {XtNcursorColor, XtCForeground, XtRPixel, sizeof(Pixel),
+ offset(cursor_color), XtRString, "XtDefaultForeground"},
+ {XtNbarCursor, XtCBarCursor, XtRBoolean, sizeof (Boolean),
+ offset (bar_cursor), XtRImmediate, (XtPointer)0},
+ {XtNvisualBell, XtCVisualBell, XtRBoolean, sizeof (Boolean),
+ offset (visual_bell), XtRImmediate, (XtPointer)0},
+ {XtNbellVolume, XtCBellVolume, XtRInt, sizeof (int),
+ offset (bell_volume), XtRImmediate, (XtPointer)0},
+};
+
+#undef offset
+
+/*
+static XtActionsRec
+emacsFrameActionsTable [] = {
+ {"keypress", key_press},
+ {"focus_in", emacs_frame_focus_handler},
+ {"focus_out", emacs_frame_focus_handler},
+};
+
+static char
+emacsFrameTranslations [] = "\
+<KeyPress>: keypress()\n\
+<FocusIn>: focus_in()\n\
+<FocusOut>: focus_out()\n\
+";
+*/
+
+EmacsFrameClassRec emacsFrameClassRec = {
+ { /* core fields */
+ /* superclass */ &widgetClassRec,
+ /* class_name */ "EmacsFrame",
+ /* widget_size */ sizeof(EmacsFrameRec),
+ /* class_initialize */ 0,
+ /* class_part_initialize */ 0,
+ /* class_inited */ FALSE,
+ /* initialize */ EmacsFrameInitialize,
+ /* initialize_hook */ 0,
+ /* realize */ EmacsFrameRealize,
+ /* actions */ 0, /*emacsFrameActionsTable*/
+ /* num_actions */ 0, /*XtNumber (emacsFrameActionsTable)*/
+ /* resources */ resources,
+ /* resource_count */ XtNumber(resources),
+ /* xrm_class */ NULLQUARK,
+ /* compress_motion */ TRUE,
+ /* compress_exposure */ TRUE,
+ /* compress_enterleave */ TRUE,
+ /* visible_interest */ FALSE,
+ /* destroy */ EmacsFrameDestroy,
+ /* resize */ EmacsFrameResize,
+ /* expose */ XtInheritExpose,
+ /* set_values */ EmacsFrameSetValues,
+ /* set_values_hook */ 0,
+ /* set_values_almost */ XtInheritSetValuesAlmost,
+ /* get_values_hook */ 0,
+ /* accept_focus */ XtInheritAcceptFocus,
+ /* version */ XtVersion,
+ /* callback_private */ 0,
+ /* tm_table */ 0, /*emacsFrameTranslations*/
+ /* query_geometry */ EmacsFrameQueryGeometry,
+ /* display_accelerator */ XtInheritDisplayAccelerator,
+ /* extension */ 0
+ }
+};
+
+WidgetClass emacsFrameClass = (WidgetClass) &emacsFrameClassRec;
+
+static void
+get_default_char_pixel_size (EmacsFrame ew, int* pixel_width,
+ int* pixel_height)
+{
+/*
+ *pixel_width = XTextWidth (ew->emacs_frame.font, "n", 1);
+ *pixel_height =
+ ew->emacs_frame.font->ascent + ew->emacs_frame.font->descent;
+*/
+ struct frame* f = ew->emacs_frame.frame;
+ *pixel_width = FONT_WIDTH (f->display.x->font);
+ *pixel_height = FONT_HEIGHT (f->display.x->font);
+}
+
+static void
+pixel_to_char_size (EmacsFrame ew,
+ Dimension pixel_width, Dimension pixel_height,
+ int* char_width, int* char_height)
+{
+ struct frame* f = ew->emacs_frame.frame;
+ *char_width = PIXEL_TO_CHAR_WIDTH (f, pixel_width);
+ *char_height = PIXEL_TO_CHAR_HEIGHT (f, pixel_height);
+}
+
+static void
+char_to_pixel_size (EmacsFrame ew, int char_width, int char_height,
+ Dimension* pixel_width, Dimension* pixel_height)
+{
+ struct frame* f = ew->emacs_frame.frame;
+ *pixel_width = CHAR_TO_PIXEL_WIDTH (f, char_width);
+ *pixel_height = CHAR_TO_PIXEL_HEIGHT (f, char_height);
+}
+
+static void
+round_size_to_char (EmacsFrame ew,
+ Dimension in_width, Dimension in_height,
+ Dimension* out_width, Dimension* out_height)
+{
+ int char_width;
+ int char_height;
+ pixel_to_char_size (ew, in_width, in_height, &char_width, &char_height);
+ char_to_pixel_size (ew, char_width, char_height, out_width, out_height);
+}
+
+static Widget
+get_wm_shell (Widget w)
+{
+ Widget wmshell;
+
+ for (wmshell = XtParent (w);
+ wmshell && !XtIsWMShell (wmshell);
+ wmshell = XtParent (wmshell));
+
+ return wmshell;
+}
+
+static void
+mark_shell_size_user_specified (Widget wmshell)
+{
+ if (! XtIsWMShell (wmshell)) abort ();
+ /* This is kind of sleazy, but I can't see how else to tell it to make it
+ mark the WM_SIZE_HINTS size as user specified when appropriate. */
+ ((WMShellWidget) wmshell)->wm.size_hints.flags |= USSize;
+}
+
+
+/* Can't have static frame locals because of some broken compilers.
+ Normally, initializing a variable like this doesn't work in emacs,
+ but it's ok in this file because it must come after lastfile (and
+ thus have its data not go into text space) because Xt needs to
+ write to initialized data objects too.
+ */
+static Boolean first_frame_p = True;
+
+static void
+set_frame_size (EmacsFrame ew)
+{
+ /* The widget hierarchy is
+
+ argv[0] emacsShell pane Frame-NAME
+ ApplicationShell EmacsShell Paned EmacsFrame
+
+ We accept geometry specs in this order:
+
+ *Frame-NAME.geometry
+ *EmacsFrame.geometry
+ Emacs.geometry
+
+ Other possibilities for widget hierarchies might be
+
+ argv[0] frame pane Frame-NAME
+ ApplicationShell EmacsShell Paned EmacsFrame
+ or
+ argv[0] Frame-NAME pane Frame-NAME
+ ApplicationShell EmacsShell Paned EmacsFrame
+ or
+ argv[0] Frame-NAME pane emacsTextPane
+ ApplicationShell EmacsFrame Paned EmacsTextPane
+
+ With the current setup, the text-display-area is the part which is
+ an emacs "frame", since that's the only part managed by emacs proper
+ (the menubar and the parent of the menubar and all that sort of thing
+ are managed by lwlib.)
+
+ The EmacsShell widget is simply a replacement for the Shell widget
+ which is able to deal with using an externally-supplied window instead
+ of always creating its own. It is not actually emacs specific, and
+ should possibly have class "Shell" instead of "EmacsShell" to simplify
+ the resources.
+
+ */
+
+ /* Geometry of the AppShell */
+ int app_flags = 0;
+ int app_x = 0;
+ int app_y = 0;
+ unsigned int app_w = 0;
+ unsigned int app_h = 0;
+
+ /* Geometry of the EmacsFrame */
+ int frame_flags = 0;
+ int frame_x = 0;
+ int frame_y = 0;
+ unsigned int frame_w = 0;
+ unsigned int frame_h = 0;
+
+ /* Hairily merged geometry */
+ int x = 0;
+ int y = 0;
+ unsigned int w = ew->emacs_frame.frame->width;
+ unsigned int h = ew->emacs_frame.frame->height;
+ int flags = 0;
+
+ Widget wmshell = get_wm_shell ((Widget) ew);
+ Widget app_shell = XtParent ((Widget) wmshell);
+
+
+ if (! XtIsSubclass (wmshell, shellWidgetClass)) abort ();
+ if (! XtIsSubclass (app_shell, shellWidgetClass)) abort ();
+
+ /* If the EmacsFrame doesn't have a geometry but the shell does,
+ treat that as the geometry of the frame. (Is this bogus?
+ I'm not sure.) */
+ if (ew->emacs_frame.geometry == 0)
+ XtVaGetValues (wmshell, XtNgeometry, &ew->emacs_frame.geometry, 0);
+
+ /* If the Shell is iconic, then the EmacsFrame is iconic. (Is
+ this bogus? I'm not sure.) */
+ if (!ew->emacs_frame.iconic)
+ XtVaGetValues (wmshell, XtNiconic, &ew->emacs_frame.iconic, 0);
+
+
+ {
+ char *geom = 0;
+ XtVaGetValues (app_shell, XtNgeometry, &geom, 0);
+ if (geom)
+ app_flags = XParseGeometry (geom, &app_x, &app_y, &app_w, &app_h);
+ }
+
+ if (ew->emacs_frame.geometry)
+ frame_flags = XParseGeometry (ew->emacs_frame.geometry,
+ &frame_x, &frame_y,
+ &frame_w, &frame_h);
+
+ if (first_frame_p)
+ {
+ /* If this is the first frame created:
+ ====================================
+
+ - Use the ApplicationShell's size/position, if specified.
+ (This is "Emacs.geometry", or the "-geometry" command line arg.)
+ - Else use the EmacsFrame's size/position.
+ (This is "*Frame-NAME.geometry")
+
+ - If the AppShell is iconic, the frame should be iconic.
+
+ AppShell comes first so that -geometry always applies to the first
+ frame created, even if there is an "every frame" entry in the
+ resource database.
+ */
+ if (app_flags & (XValue | YValue))
+ {
+ x = app_x; y = app_y;
+ flags |= (app_flags & (XValue | YValue | XNegative | YNegative));
+ }
+ else if (frame_flags & (XValue | YValue))
+ {
+ x = frame_x; y = frame_y;
+ flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
+ }
+
+ if (app_flags & (WidthValue | HeightValue))
+ {
+ w = app_w; h = app_h;
+ flags |= (app_flags & (WidthValue | HeightValue));
+ }
+ else if (frame_flags & (WidthValue | HeightValue))
+ {
+ w = frame_w; h = frame_h;
+ flags |= (frame_flags & (WidthValue | HeightValue));
+ }
+
+ /* If the AppShell is iconic, then the EmacsFrame is iconic. */
+ if (!ew->emacs_frame.iconic)
+ XtVaGetValues (app_shell, XtNiconic, &ew->emacs_frame.iconic, 0);
+
+ first_frame_p = False;
+ }
+ else
+ {
+ /* If this is not the first frame created:
+ ========================================
+
+ - use the EmacsFrame's size/position if specified
+ - Otherwise, use the ApplicationShell's size, but not position.
+
+ So that means that one can specify the position of the first frame
+ with "Emacs.geometry" or `-geometry'; but can only specify the
+ position of subsequent frames with "*Frame-NAME.geometry".
+
+ AppShell comes second so that -geometry does not apply to subsequent
+ frames when there is an "every frame" entry in the resource db,
+ but does apply to the first frame.
+ */
+ if (frame_flags & (XValue | YValue))
+ {
+ x = frame_x; y = frame_y;
+ flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
+ }
+
+ if (frame_flags & (WidthValue | HeightValue))
+ {
+ w = frame_w; h = frame_h;
+ flags |= (frame_flags & (WidthValue | HeightValue));
+ }
+ else if (app_flags & (WidthValue | HeightValue))
+ {
+ w = app_w;
+ h = app_h;
+ flags |= (app_flags & (WidthValue | HeightValue));
+ }
+ }
+
+ {
+ struct frame* frame = ew->emacs_frame.frame;
+ Dimension pixel_width, pixel_height;
+ char shell_position [32];
+
+ /* Take into account the size of the scrollbar */
+ frame->display.x->vertical_scroll_bar_extra
+ = (FRAME_HAS_VERTICAL_SCROLL_BARS (frame)
+ ? VERTICAL_SCROLL_BAR_PIXEL_WIDTH (frame)
+ : 0);
+
+
+ change_frame_size (frame, h, w, 1, 0);
+ char_to_pixel_size (ew, w, h, &pixel_width, &pixel_height);
+ ew->core.width = pixel_width;
+ ew->core.height = pixel_height;
+
+
+ /* If a position was specified, assign it to the shell widget.
+ (Else WM won't do anything with it.)
+ */
+ if (flags & (XValue | YValue))
+ {
+ /* the tricky things with the sign is to make sure that
+ -0 is printed -0. */
+ int len;
+ char *tem;
+ sprintf (shell_position, "=%c%d%c%d",
+ flags & XNegative ? '-' : '+', x < 0 ? -x : x,
+ flags & YNegative ? '-' : '+', y < 0 ? -y : y);
+ len = strlen (shell_position) + 1;
+ tem = (char *) xmalloc (len);
+ strncpy (tem, shell_position, len);
+ XtVaSetValues (wmshell, XtNgeometry, tem, 0);
+ }
+ else if (flags & (WidthValue | HeightValue))
+ {
+ int len;
+ char *tem;
+ sprintf (shell_position, "=%dx%d", pixel_width, pixel_height);
+ len = strlen (shell_position) + 1;
+ tem = (char *) xmalloc (len);
+ strncpy (tem, shell_position, len);
+ XtVaSetValues (wmshell, XtNgeometry, tem, 0);
+ }
+
+ /* If the geometry spec we're using has W/H components, mark the size
+ in the WM_SIZE_HINTS as user specified. */
+ if (flags & (WidthValue | HeightValue))
+ mark_shell_size_user_specified (wmshell);
+
+ /* Also assign the iconic status of the frame to the Shell, so that
+ the WM sees it. */
+ XtVaSetValues (wmshell, XtNiconic, ew->emacs_frame.iconic, 0);
+ }
+}
+
+
+static void
+update_wm_hints (EmacsFrame ew)
+{
+ Widget wmshell = get_wm_shell ((Widget)ew);
+ int cw;
+ int ch;
+ Dimension rounded_width;
+ Dimension rounded_height;
+ int char_width;
+ int char_height;
+ int base_width;
+ int base_height;
+ int min_rows = 0, min_cols = 0;
+
+ check_frame_size (ew->emacs_frame.frame, &min_rows, &min_cols);
+
+ pixel_to_char_size (ew, ew->core.width, ew->core.height,
+ &char_width, &char_height);
+ char_to_pixel_size (ew, char_width, char_height,
+ &rounded_width, &rounded_height);
+ get_default_char_pixel_size (ew, &cw, &ch);
+
+ base_width = (wmshell->core.width - ew->core.width
+ + (rounded_width - (char_width * cw)));
+ base_height = (wmshell->core.height - ew->core.height
+ + (rounded_height - (char_height * ch)));
+
+ /* This is kind of sleazy, but I can't see how else to tell it to
+ make it mark the WM_SIZE_HINTS size as user specified.
+ */
+/* ((WMShellWidget) wmshell)->wm.size_hints.flags |= USSize;*/
+
+ XtVaSetValues (wmshell,
+ XtNbaseWidth, base_width,
+ XtNbaseHeight, base_height,
+ XtNwidthInc, cw,
+ XtNheightInc, ch,
+ XtNminWidth, base_width + min_cols * cw,
+ XtNminHeight, base_height + min_rows * ch,
+ 0);
+}
+
+static void
+create_frame_gcs (EmacsFrame ew)
+{
+ struct frame* s = ew->emacs_frame.frame;
+
+ s->display.x->normal_gc =
+ XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)), 0, 0);
+ s->display.x->reverse_gc =
+ XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)), 0, 0);
+ s->display.x->cursor_gc =
+ XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)), 0, 0);
+}
+
+static void
+setup_frame_gcs (EmacsFrame ew)
+{
+ XGCValues gc_values;
+ struct frame* s = ew->emacs_frame.frame;
+ Pixmap blank_stipple, blank_tile;
+
+ static char cursor_bits[] =
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+ /* We have to initialize all of our GCs to have a stipple/tile, otherwise
+ XGetGCValues returns uninitialized data when we query the stipple
+ (instead of None or something sensible) and it makes things hard.
+
+ This should be fixed for real by not querying the GCs but instead having
+ some GC-based cache instead of the current face-based cache which doesn't
+ effectively cache all of the GC settings we need to use.
+ */
+
+ blank_stipple =
+ XCreateBitmapFromData (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)),
+ cursor_bits, 2, 2);
+
+ /* use fg = 0, bg = 1 below, but it's irrelevant since this pixmap should
+ never actually get used as a background tile!
+ */
+ blank_tile =
+ XCreatePixmapFromBitmapData (XtDisplay(ew),
+ RootWindowOfScreen (XtScreen (ew)),
+ cursor_bits, 2, 2, 0, 1, ew->core.depth);
+
+ /* Normal video */
+ gc_values.font = ew->emacs_frame.font->fid;
+ gc_values.foreground = ew->emacs_frame.foreground_pixel;
+ gc_values.background = ew->core.background_pixel;
+ gc_values.graphics_exposures = False;
+ gc_values.stipple = blank_stipple;
+ gc_values.tile = blank_tile;
+ XChangeGC (XtDisplay (ew), s->display.x->normal_gc,
+ (GCFont | GCForeground | GCBackground | GCGraphicsExposures
+ | GCStipple | GCTile),
+ &gc_values);
+
+ /* Reverse video style. */
+ gc_values.font = ew->emacs_frame.font->fid;
+ gc_values.foreground = ew->core.background_pixel;
+ gc_values.background = ew->emacs_frame.foreground_pixel;
+ gc_values.graphics_exposures = False;
+ gc_values.stipple = blank_stipple;
+ gc_values.tile = blank_tile;
+ XChangeGC (XtDisplay (ew), s->display.x->reverse_gc,
+ (GCFont | GCForeground | GCBackground | GCGraphicsExposures
+ | GCStipple | GCTile),
+ &gc_values);
+
+ /* Cursor has to have an empty stipple. */
+ gc_values.font = ew->emacs_frame.font->fid;
+ gc_values.foreground = ew->core.background_pixel;
+ gc_values.background = ew->emacs_frame.cursor_color;
+ gc_values.graphics_exposures = False;
+ gc_values.tile = blank_tile;
+ gc_values.stipple =
+ XCreateBitmapFromData (XtDisplay (ew),
+ RootWindowOfScreen (XtScreen (ew)),
+ cursor_bits, 16, 16);
+ XChangeGC (XtDisplay (ew), s->display.x->cursor_gc,
+ (GCFont | GCForeground | GCBackground | GCGraphicsExposures
+ | GCStipple | GCTile),
+ &gc_values);
+}
+
+static void
+update_various_frame_slots (EmacsFrame ew)
+{
+ struct x_display* x = ew->emacs_frame.frame->display.x;
+ x->pixel_height = ew->core.height;
+ x->pixel_width = ew->core.width;
+ x->internal_border_width = ew->emacs_frame.internal_border_width;
+
+}
+
+static void
+update_from_various_frame_slots (EmacsFrame ew)
+{
+ struct x_display* x = ew->emacs_frame.frame->display.x;
+ ew->core.height = x->pixel_height;
+ ew->core.width = x->pixel_width;
+ ew->core.background_pixel = x->background_pixel;
+ ew->emacs_frame.internal_border_width = x->internal_border_width;
+ ew->emacs_frame.font = x->font;
+ ew->emacs_frame.foreground_pixel = x->foreground_pixel;
+ ew->emacs_frame.cursor_color = x->cursor_pixel;
+ ew->core.border_pixel = x->border_pixel;
+}
+
+static void
+EmacsFrameInitialize (Widget request, Widget new,
+ ArgList dum1, Cardinal *dum2)
+{
+ EmacsFrame ew = (EmacsFrame)new;
+
+ if (!ew->emacs_frame.frame)
+ {
+ fprintf (stderr,
+ "can't create an emacs frame widget without a frame\n");
+ exit (1);
+ }
+
+#if 0 /* done in xfns.c */
+ /* If the "Emacs.EmacsFrame.{default,Face}.{attributeFont,AttributeFont}"
+ resource is set, then it always overrides "Emacs.EmacsFrame.{font,Font}".
+ It's unfortunate that we have to do this, but we need to know the font
+ size for frame-sizing purposes before the faces get initialized. If
+ the "default.attributeFont" isn't set, then we use the font of this
+ EmacsFrame itself, defaulting to XtDefaultFont. Up in the lisp code,
+ the "default" face will use the frame's font if its own is not set,
+ so everything stays in sync -- it's not possible for the frame's font
+ and the default face's font to be different.
+ */
+ {
+ XFontStruct *f = 0;
+ XtResource face_res;
+ face_res.resource_name = "attributeFont";
+ face_res.resource_class = "AttributeFont";
+ face_res.resource_type = XtRFontStruct;
+ face_res.resource_size = sizeof (XFontStruct *);
+ face_res.resource_offset = 0;
+ face_res.default_type = XtRImmediate;
+ face_res.default_addr = 0;
+ XtGetSubresources ((Widget) ew, (XtPointer) &f, "default", "Face",
+ &face_res, 1, NULL, 0);
+
+ if (f)
+ ew->emacs_frame.font = f;
+ else if (! ew->emacs_frame.font)
+ {
+ fprintf (stderr, "emacs frame widget could not load a font\n");
+ exit (1);
+ }
+ }
+
+/* Update the font field in frame */
+ ew->emacs_frame.frame->display.x->font = ew->emacs_frame.font;
+#endif
+
+ update_from_various_frame_slots (ew);
+ set_frame_size (ew);
+/*create_frame_gcs (ew);
+ setup_frame_gcs (ew);
+ update_various_frame_slots (ew); */
+}
+
+
+static void
+EmacsFrameRealize (Widget widget, XtValueMask *mask,
+ XSetWindowAttributes *attrs)
+{
+ EmacsFrame ew = (EmacsFrame)widget;
+
+ attrs->event_mask = (KeyPressMask | ExposureMask | ButtonPressMask |
+ ButtonReleaseMask | StructureNotifyMask |
+ FocusChangeMask | PointerMotionHintMask |
+ PointerMotionMask | LeaveWindowMask | EnterWindowMask |
+ VisibilityChangeMask | PropertyChangeMask |
+ StructureNotifyMask | SubstructureNotifyMask |
+ SubstructureRedirectMask);
+ *mask |= CWEventMask;
+ XtCreateWindow (widget, InputOutput, (Visual *)CopyFromParent, *mask,
+ attrs);
+ update_wm_hints (ew);
+}
+
+extern void free_frame_faces (struct frame *);
+
+static void
+EmacsFrameDestroy (Widget widget)
+{
+ EmacsFrame ew = (EmacsFrame) widget;
+ struct frame* s = ew->emacs_frame.frame;
+
+ if (! s) abort ();
+ if (! s->display.x) abort ();
+ if (! s->display.x->normal_gc) abort ();
+
+ /* this would be called from Fdelete_frame() but it needs to free some
+ stuff after the widget has been finalized but before the widget has
+ been freed. */
+ free_frame_faces (s);
+
+ /* need to be careful that the face-freeing code doesn't free these too */
+ XFreeGC (XtDisplay (widget), s->display.x->normal_gc);
+ XFreeGC (XtDisplay (widget), s->display.x->reverse_gc);
+ XFreeGC (XtDisplay (widget), s->display.x->cursor_gc);
+}
+
+void
+EmacsFrameResize (Widget widget)
+{
+ EmacsFrame ew = (EmacsFrame)widget;
+ struct frame *f = ew->emacs_frame.frame;
+ int columns;
+ int rows;
+
+ pixel_to_char_size (ew, ew->core.width, ew->core.height, &columns, &rows);
+ change_frame_size (f, rows, columns, 1, 0);
+ update_wm_hints (ew);
+ {
+ Window win, child;
+ int win_x, win_y;
+
+ /* Find the position of the outside upper-left corner of
+ the window, in the root coordinate system. Don't
+ refer to the parent window here; we may be processing
+ this event after the window manager has changed our
+ parent, but before we have reached the ReparentNotify. */
+ XTranslateCoordinates (x_current_display,
+
+ /* From-window, to-window. */
+ XtWindow(XtParent(ew)),
+ ROOT_WINDOW,
+
+ /* From-position, to-position. */
+ -f->display.x->widget->core.border_width,
+ -f->display.x->widget->core.border_width,
+ &win_x, &win_y,
+
+ /* Child of win. */
+ &child);
+ f->display.x->widget->core.x = win_x;
+ f->display.x->widget->core.y = win_y;
+ }
+ update_various_frame_slots (ew);
+}
+
+static Boolean
+EmacsFrameSetValues (Widget cur_widget, Widget req_widget, Widget new_widget,
+ ArgList dum1, Cardinal *dum2)
+{
+ EmacsFrame cur = (EmacsFrame)cur_widget;
+ EmacsFrame new = (EmacsFrame)new_widget;
+
+ Boolean needs_a_refresh = False;
+ Boolean has_to_recompute_size;
+ Boolean has_to_recompute_gcs;
+ Boolean has_to_update_hints;
+
+ int char_width, char_height;
+ Dimension pixel_width;
+ Dimension pixel_height;
+
+ has_to_recompute_gcs = (cur->emacs_frame.font != new->emacs_frame.font
+ || (cur->emacs_frame.foreground_pixel
+ != new->emacs_frame.foreground_pixel)
+ || (cur->core.background_pixel
+ != new->core.background_pixel)
+ );
+
+ has_to_recompute_size = (cur->emacs_frame.font != new->emacs_frame.font
+ && cur->core.width == new->core.width
+ && cur->core.height == new->core.height);
+
+ has_to_update_hints = (cur->emacs_frame.font != new->emacs_frame.font);
+
+ if (has_to_recompute_gcs)
+ {
+ setup_frame_gcs (new);
+ needs_a_refresh = True;
+ }
+
+ if (has_to_recompute_size)
+ {
+ pixel_width = new->core.width;
+ pixel_height = new->core.height;
+ pixel_to_char_size (new, pixel_width, pixel_height, &char_width,
+ &char_height);
+ char_to_pixel_size (new, char_width, char_height, &pixel_width,
+ &pixel_height);
+ new->core.width = pixel_width;
+ new->core.height = pixel_height;
+
+ change_frame_size (new->emacs_frame.frame, char_height, char_width,
+ 1, 0);
+ needs_a_refresh = True;
+ }
+
+ if (has_to_update_hints)
+ update_wm_hints (new);
+
+ update_various_frame_slots (new);
+
+ /* #### This doesn't work, I haven't been able to find ANY kludge that
+ will let (x-create-frame '((iconic . t))) work. It seems that changes
+ to wm_shell's iconic slot have no effect after it has been realized,
+ and calling XIconifyWindow doesn't work either (even thought the window
+ has been created.) Perhaps there is some property we could smash
+ directly, but I'm sick of this for now. Xt is a steaming pile of shit!
+ */
+ if (cur->emacs_frame.iconic != new->emacs_frame.iconic)
+ {
+ Widget wmshell = get_wm_shell ((Widget) cur);
+ XtVaSetValues (wmshell, XtNiconic, new->emacs_frame.iconic, 0);
+ }
+
+ return needs_a_refresh;
+}
+
+static XtGeometryResult
+EmacsFrameQueryGeometry (Widget widget, XtWidgetGeometry* request,
+ XtWidgetGeometry* result)
+{
+ EmacsFrame ew = (EmacsFrame)widget;
+
+ int mask = request->request_mode;
+ Dimension ok_width, ok_height;
+
+ if (mask & (CWWidth | CWHeight))
+ {
+ round_size_to_char (ew,
+ (mask & CWWidth) ? request->width : ew->core.width,
+ ((mask & CWHeight) ? request->height
+ : ew->core.height),
+ &ok_width, &ok_height);
+ if ((mask & CWWidth) && (ok_width != request->width))
+ {
+ result->request_mode |= CWWidth;
+ result->width = ok_width;
+ }
+ if ((mask & CWHeight) && (ok_height != request->height))
+ {
+ result->request_mode |= CWHeight;
+ result->height = ok_height;
+ }
+ }
+ return result->request_mode ? XtGeometryAlmost : XtGeometryYes;
+}
+
+#if 0
+/* I don't know why this is necessary; Matthieu said he had to do
+ it to make the focus handlers work??
+ */
+static void
+key_press (Widget w, XEvent* event, String *params, Cardinal *n_params)
+{
+}
+
+static void
+emacs_frame_focus_handler (Widget w, XEvent *event, String *params,
+ Cardinal *n_params)
+{
+ emacs_Xt_focus_event_handler (event, 0);
+}
+#endif
+
+/* Special entrypoints */
+void
+EmacsFrameSetCharSize (Widget widget, int columns, int rows)
+{
+ EmacsFrame ew = (EmacsFrame) widget;
+ Dimension pixel_width, pixel_height, granted_width, granted_height;
+ XtGeometryResult result;
+ if (columns < 3) columns = 3; /* no way buddy */
+ if (rows < 3) rows = 3;
+
+ char_to_pixel_size (ew, columns, rows, &pixel_width, &pixel_height);
+ result = XtMakeResizeRequest ((Widget)ew,
+ pixel_width, pixel_height,
+ &granted_width, &granted_height);
+ if (result == XtGeometryAlmost)
+ XtMakeResizeRequest ((Widget) ew, granted_width, granted_height,
+ NULL, NULL);
+ /* damn Paned widget won't ever change its width. Force it. */
+ if (ew->core.width != pixel_width)
+ {
+ XtVaSetValues (XtParent ((Widget) ew), XtNwidth, pixel_width, 0);
+ XtVaSetValues ((Widget) ew, XtNwidth, pixel_width, 0);
+ }
+}
diff --git a/src/widget.h b/src/widget.h
new file mode 100644
index 00000000000..91e74b43d37
--- /dev/null
+++ b/src/widget.h
@@ -0,0 +1,90 @@
+/* The emacs frame widget public header file.
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs 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.
+
+GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Emacs 19 face widget ported by Fred Pierresteguy */
+
+#ifndef _EmacsFrame_h
+#define _EmacsFrame_h
+
+#define XtNminibuffer "minibuffer"
+#define XtCMinibuffer "Minibuffer"
+#define XtNunsplittable "unsplittable"
+#define XtCUnsplittable "Unsplittable"
+#define XtNinternalBorderWidth "internalBorderWidth"
+#define XtCInternalBorderWidth "InternalBorderWidth"
+#define XtNinterline "interline"
+#define XtCInterline "Interline"
+
+#ifndef XtNfont
+#define XtNfont "font"
+#endif
+#ifndef XtCFont
+#define XtCFont "Font"
+#endif
+#ifndef XtNforeground
+#define XtNforeground "foreground"
+#endif
+#ifndef XtCForeground
+#define XtCForeground "Foreground"
+#endif
+
+#define XtNcursorColor "cursorColor"
+#define XtCCursorColor "CursorColor"
+#define XtNbarCursor "barCursor"
+#define XtCBarCursor "BarCursor"
+
+#define XtNvisualBell "visualBell"
+#define XtCVisualBell "VisualBell"
+#define XtCBellVolume "BellVolume"
+#define XtNbellVolume "bellVolume"
+
+#define XtNpointerBackground "pointerBackground"
+#define XtNpointerColor "pointerColor"
+
+#define XtNtextPointer "textPointer"
+#define XtNspacePointer "spacePointer"
+#define XtNmodeLinePointer "modePointer"
+#define XtNgcPointer "gcPointer"
+
+#define XtNemacsFrame "emacsFrame"
+#define XtCEmacsFrame "EmacsFrame"
+
+#ifndef XtNgeometry
+#define XtNgeometry "geometry"
+#endif
+#ifndef XtCGeometry
+#define XtCGeometry "Geometry"
+#endif
+
+#define XtNinitialGeometry "initialGeometry"
+#define XtCInitialGeometry "InitialGeometry"
+
+/* structures
+ */
+typedef struct _EmacsFrameRec *EmacsFrame;
+typedef struct _EmacsFrameClassRec *EmacsFrameClass;
+
+extern WidgetClass emacsFrameClass;
+
+extern struct _DisplayContext* display_context;
+
+/* Special entrypoints */
+void EmacsFrameSetCharSize (Widget widget, int rows, int cols);
+
+#endif /* _EmacsFrame_h */