home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 2: Applications / Linux Cubed Series 2 - Applications.iso / editors / emacs / xemacs / xemacs-1.004 / xemacs-1 / xemacs-19.13 / src / frame-x.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-08-26  |  67.5 KB  |  2,292 lines

  1. /* Functions for the X window system.
  2.    Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation.
  3.  
  4. This file is part of XEmacs.
  5.  
  6. XEmacs is free software; you can redistribute it and/or modify it
  7. under the terms of the GNU General Public License as published by the
  8. Free Software Foundation; either version 2, or (at your option) any
  9. later version.
  10.  
  11. XEmacs is distributed in the hope that it will be useful, but WITHOUT
  12. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13. FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14. for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with XEmacs; see the file COPYING.  If not, write to the Free
  18. Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. /* Synched up with: Not synched with FSF. */
  21.  
  22. /* Substantially rewritten for XEmacs.  */
  23.  
  24. #include <config.h>
  25. #include "lisp.h"
  26.  
  27. #include "device-x.h"
  28. #include "frame-x.h"
  29. #include "xintrinsicp.h"    /* CoreP.h needs this */
  30. #include <X11/CoreP.h>        /* Numerous places access the fields of
  31.                    a core widget directly.  We could
  32.                    use XtVaGetValues(), but ... */
  33. #include <X11/Shell.h>
  34. #include <X11/ShellP.h>
  35. #include "xmu.h"
  36. #include "EmacsManager.h"
  37. #include "EmacsFrameP.h"
  38. #include "EmacsShell.h"
  39. #ifdef EXTERNAL_WIDGET
  40. #include "ExternalShell.h"
  41. #endif
  42. #include "glyphs-x.h"
  43. #include "objects-x.h"
  44.  
  45. #include "buffer.h"
  46. #include "events.h"
  47. #include "extents.h"
  48. #include "faces.h"
  49. #include "scrollbar-x.h"
  50. #include "window.h"
  51.  
  52. Lisp_Object Vx_gc_pointer_shape;
  53. Lisp_Object Vx_scrollbar_pointer_shape;
  54.  
  55. /* Default parameters to use when creating frames.  */
  56. Lisp_Object Vdefault_x_frame_alist;
  57.  
  58. static Lisp_Object Vpre_gc_cursor;
  59.  
  60. Lisp_Object Qwindow_id;
  61. Lisp_Object Qpopup;
  62. Lisp_Object Qx_resource_name;
  63. Lisp_Object Qpointer;
  64. Lisp_Object Qscrollbar_pointer;
  65.  
  66.  
  67. /************************************************************************/
  68. /*                          helper functions                            */
  69. /************************************************************************/
  70.  
  71. /* Return the Emacs frame-object corresponding to an X window */
  72. struct frame *
  73. x_window_to_frame (struct device *d, Window wdesc)
  74. {
  75.   Lisp_Object tail, frame;
  76.   struct frame *f;
  77.  
  78.   /* This function was previously written to accept only a window argument
  79.      (and to loop over all devices looking for a matching window), but
  80.      that is incorrect because window ID's are not unique across displays. */
  81.  
  82.   for (tail = DEVICE_FRAME_LIST (d); CONSP (tail); tail = XCDR (tail))
  83.     {
  84.       frame = XCAR (tail);
  85.       if (!FRAMEP (frame))
  86.     continue;
  87.       f = XFRAME (frame);
  88.       if (FRAME_IS_X (f) && XtWindow (FRAME_X_TEXT_WIDGET (f)) == wdesc)
  89.     return f;
  90.     }
  91.   return 0;
  92. }
  93.  
  94. /* Like x_window_to_frame but also compares the window with the widget's
  95.    windows */
  96. struct frame *
  97. x_any_window_to_frame (struct device *d, Window wdesc)
  98. {
  99.   Lisp_Object tail, frame;
  100.   struct frame *f;
  101.  
  102.   /* This function was previously written to accept only a window argument
  103.      (and to loop over all devices looking for a matching window), but
  104.      that is incorrect because window ID's are not unique across displays. */
  105.  
  106.   for (tail = DEVICE_FRAME_LIST (d); CONSP (tail); tail = XCDR (tail))
  107.     {
  108.       int i;
  109.  
  110.       frame = XCAR (tail);
  111.       if (!FRAMEP (frame))
  112.     continue;
  113.       f = XFRAME (frame);
  114.       if (!FRAME_IS_X (f))
  115.     continue;
  116.       /* This frame matches if the window is any of its widgets. */
  117.       if (wdesc == XtWindow (FRAME_X_SHELL_WIDGET (f)) ||
  118.       wdesc == XtWindow (FRAME_X_CONTAINER_WIDGET (f)) ||
  119.       wdesc == XtWindow (FRAME_X_TEXT_WIDGET (f)))
  120.     return f;
  121.  
  122.       /* Match if the window is one of the widgets at the top of the frame
  123.      (menubar, Energize psheets). */
  124.  
  125.       /* Note: Jamie once said
  126.  
  127.      "Do *not* match if the window is this frame's psheet."
  128.  
  129.      But this is wrong and will screw up some functions that expect
  130.      x_any_window_to_frame() to work as advertised.  I think the reason
  131.      for this statement is that, in the old (broken) event loop, where
  132.      not all events went through XtDispatchEvent(), psheet events
  133.      would incorrectly get sucked away by Emacs if this function matched
  134.      on psheet widgets. */
  135.  
  136.       for (i = 0; i < FRAME_X_NUM_TOP_WIDGETS (f); i++)
  137.     {
  138.       Widget wid = FRAME_X_TOP_WIDGETS (f)[i];
  139.       if (wid && XtIsManaged (wid) && wdesc == XtWindow (wid))
  140.         return f;
  141.     }
  142.  
  143.       /* Match if the window is one of this frame's scrollbars. */
  144.       if (x_window_is_scrollbar (f, wdesc))
  145.     return f;
  146.     }
  147.  
  148.   return 0;
  149. }
  150.  
  151. struct frame *
  152. get_x_frame (Lisp_Object frame)
  153. {
  154.   if (NILP (frame))
  155.     XSETFRAME (frame, selected_frame ());
  156.   CHECK_LIVE_FRAME (frame, 0);
  157.   /* this will also catch dead frames, but putting in the above check
  158.      results in a more useful error */
  159.   CHECK_X_FRAME (frame, 0);
  160.   return XFRAME (frame);
  161. }
  162.  
  163.  
  164. /************************************************************************/
  165. /*            window-manager interactions            */
  166. /************************************************************************/
  167.  
  168. #if 0
  169. /* Not currently used. */
  170.  
  171. void
  172. x_wm_mark_shell_size_user_specified (Widget wmshell)
  173. {
  174.   if (! XtIsWMShell (wmshell)) abort ();
  175.   EmacsShellSetSizeUserSpecified (wmshell);
  176. }
  177.  
  178. void
  179. x_wm_mark_shell_position_user_specified (Widget wmshell)
  180. {
  181.   if (! XtIsWMShell (wmshell)) abort ();
  182.   EmacsShellSetPositionUserSpecified (wmshell);
  183. }
  184.  
  185. #endif
  186.  
  187. void
  188. x_wm_set_shell_iconic_p (Widget shell, int iconic_p)
  189. {
  190.   if (! XtIsWMShell (shell)) abort ();
  191.  
  192.   /* Because of questionable logic in Shell.c, this sequence can't work:
  193.  
  194.        w = XtCreatePopupShell (...);
  195.        XtVaSetValues (w, XtNiconic, True, 0);
  196.        XtRealizeWidget (w);
  197.  
  198.      The iconic resource is only consulted at initialization time (when
  199.      XtCreatePopupShell is called) instead of at realization time (just
  200.      before the window gets created, which would be more sensible) or
  201.      at management-time (just before the window gets mapped, which would
  202.      be most sensible of all).
  203.  
  204.      The bug is that Shell's SetValues method doesn't do anything to
  205.      w->wm.wm_hints.initial_state until after the widget has been realized.
  206.      Calls to XtSetValues are ignored in the window between creation and
  207.      realization.  This is true of MIT X11R5 patch level 25, at least.
  208.      (Apparently some other versions of Xt don't have this bug?)
  209.    */
  210.   XtVaSetValues (shell, XtNiconic, iconic_p, 0);
  211.   EmacsShellSmashIconicHint (shell, iconic_p);
  212. }
  213.  
  214. void
  215. x_wm_set_cell_size (Widget wmshell, int cw, int ch)
  216. {
  217.   if (!XtIsWMShell (wmshell))
  218.     abort ();
  219.   if (cw <= 0 || ch <= 0)
  220.     abort ();
  221.  
  222.   XtVaSetValues (wmshell,
  223.          XtNwidthInc, cw, 
  224.          XtNheightInc, ch,
  225.          0);
  226. }
  227.  
  228. void
  229. x_wm_set_variable_size (Widget wmshell, int width, int height)
  230. {
  231.   if (!XtIsWMShell (wmshell))
  232.     abort ();
  233. #ifdef DEBUG_GEOMETRY_MANAGEMENT
  234.   /* See comment in EmacsShell.c */
  235.   printf ("x_wm_set_variable_size: %d %d\n", width, height);
  236.   fflush (stdout);
  237. #endif
  238.   XtVaSetValues (wmshell,
  239.          XtNwidthCells, width,
  240.          XtNheightCells, height,
  241.          0);
  242. }
  243.  
  244. /* If the WM_PROTOCOLS property does not already contain WM_TAKE_FOCUS
  245.    and WM_DELETE_WINDOW, then add them.  (They may already be present
  246.    because of the toolkit (Motif adds them, for example, but Xt doesn't).
  247.  */
  248. static void
  249. x_wm_hack_wm_protocols (Widget widget)
  250. {
  251.   Display *dpy = XtDisplay (widget);
  252.   struct device *d = get_device_from_display (dpy);
  253.   Window w = XtWindow (widget);
  254.   int need_delete = 1;
  255.   int need_focus = 1;
  256.  
  257.   if (!XtIsWMShell (widget))
  258.     abort ();
  259.  
  260.   {
  261.     Atom type, *atoms = 0;
  262.     int format = 0;
  263.     unsigned long nitems = 0;
  264.     unsigned long bytes_after;
  265.  
  266.     if (Success == XGetWindowProperty (dpy, w, DEVICE_XATOM_WM_PROTOCOLS (d),
  267.                        0, 100, False, XA_ATOM,
  268.                        &type, &format, &nitems, &bytes_after,
  269.                        (unsigned char **) &atoms)
  270.     && format == 32 && type == XA_ATOM)
  271.       while (nitems > 0)
  272.     {
  273.       nitems--;
  274.       if (atoms [nitems] == DEVICE_XATOM_WM_DELETE_WINDOW (d))
  275.         need_delete = 0;
  276.       else if (atoms [nitems] == DEVICE_XATOM_WM_TAKE_FOCUS (d))
  277.         need_focus = 0;
  278.     }
  279.     if (atoms) XFree ((char *) atoms);
  280.   }
  281.   {
  282.     Atom props [10];
  283.     int count = 0;
  284.     if (need_delete) props[count++] = DEVICE_XATOM_WM_DELETE_WINDOW (d);
  285.     if (need_focus)  props[count++] = DEVICE_XATOM_WM_TAKE_FOCUS (d);
  286.     if (count)
  287.       XChangeProperty (dpy, w, DEVICE_XATOM_WM_PROTOCOLS (d), XA_ATOM, 32,
  288.                PropModeAppend, (unsigned char *) props, count);
  289.   }
  290. }
  291.  
  292. static void
  293. x_wm_store_class_hints (Widget shell, char *frame_name)
  294. {
  295.   Display *dpy = XtDisplay (shell);
  296.   char *app_name, *app_class;
  297.   XClassHint classhint;
  298.  
  299.   if (!XtIsWMShell (shell))
  300.     abort ();
  301.  
  302.   XtGetApplicationNameAndClass (dpy, &app_name, &app_class);
  303.   classhint.res_name = frame_name;
  304.   classhint.res_class = app_class;
  305.   XSetClassHint (dpy, XtWindow (shell), &classhint);
  306. }
  307.  
  308. static void
  309. x_wm_maybe_store_wm_command (struct frame *f)
  310. {
  311.   Widget w = FRAME_X_SHELL_WIDGET (f);
  312.   struct device *d = XDEVICE (FRAME_DEVICE (f));
  313.  
  314.   if (!XtIsWMShell (w))
  315.     abort ();
  316.  
  317.   if (NILP (DEVICE_X_WM_COMMAND_FRAME (d)))
  318.     {
  319.       int argc;
  320.       char **argv;
  321.       make_argc_argv (Vcommand_line_args, &argc, &argv);
  322.       XSetCommand (XtDisplay (w), XtWindow (w), argv, argc);
  323.       free_argc_argv (argv);
  324.       XSETFRAME (DEVICE_X_WM_COMMAND_FRAME (d), f);
  325.     }
  326. }
  327.  
  328. /* If we're deleting the frame on which the WM_COMMAND property has been
  329.    set, then move that property to another frame so that there is exactly
  330.    one frame that has that property set.
  331.  */
  332. static void
  333. x_wm_maybe_move_wm_command (struct frame *f)
  334. {
  335.   struct device *d = XDEVICE (FRAME_DEVICE (f));
  336.  
  337.   /* At this point there should always be a frame in
  338.      DEVICE_X_WM_COMMAND_FRAME() */
  339.   if (f == XFRAME (DEVICE_X_WM_COMMAND_FRAME (d)))
  340.     {
  341.       Lisp_Object rest = DEVICE_FRAME_LIST (d);
  342.       DEVICE_X_WM_COMMAND_FRAME (d) = Qnil;
  343.       /* find some random other X frame that is not this one, or give up */
  344.       /* skip non-top-level (ExternalClient) frames */
  345.       while (!NILP (rest) &&
  346.          (f == XFRAME (XCAR (rest)) ||
  347.           !FRAME_X_TOP_LEVEL_FRAME_P (XFRAME (XCAR (rest)))))
  348.     rest = XCDR (rest);
  349.       if (NILP (rest))
  350.     return;
  351.       f = XFRAME (XCAR (rest));
  352.       x_wm_maybe_store_wm_command (f);
  353.     }
  354. }
  355.  
  356. static int
  357. x_frame_iconified_p (struct frame *f)
  358. {
  359.   Atom actual_type;
  360.   int actual_format;
  361.   unsigned long nitems, bytesafter;
  362.   unsigned long *datap = 0;
  363.   Widget widget;
  364.   int result = 0;
  365.   struct device *d = XDEVICE (FRAME_DEVICE (f));
  366.  
  367.   widget = FRAME_X_SHELL_WIDGET (f);
  368.   if (Success == XGetWindowProperty (XtDisplay (widget), XtWindow (widget),
  369.                      DEVICE_XATOM_WM_STATE (d), 0, 2, False,
  370.                      DEVICE_XATOM_WM_STATE (d), &actual_type,
  371.                      &actual_format, &nitems, &bytesafter,
  372.                      (unsigned char **) &datap)
  373.       && datap)
  374.     {
  375.       if (nitems <= 2    /* "suggested" by ICCCM version 1 */
  376.       && datap[0] == IconicState)
  377.     result = 1;
  378.       XFree ((char *) datap);
  379.     }
  380.   return result;
  381. }
  382.  
  383.  
  384. /************************************************************************/
  385. /*                          frame parameters                            */
  386. /************************************************************************/
  387.  
  388. /* Connect the frame-parameter names (symbols) to the corresponding
  389.    X Resource Manager names.  The name of a parameter, as a Lisp symbol,
  390.    has an `x-resource-name' property which is a Lisp_String. */
  391.  
  392. static void
  393. init_x_parm_symbols (void)
  394. {
  395. #define def(sym, rsrc) \
  396.    pure_put (intern (sym), Qx_resource_name, build_string (rsrc))
  397. #define defi(sym,rsrc) \
  398.    def (sym, rsrc); pure_put (intern (sym), Qintegerp, Qt)
  399.  
  400.   def ("minibuffer", XtNminibuffer);
  401.   def ("unsplittable", XtNunsplittable);
  402.   defi("internal-border-width", XtNinternalBorderWidth);
  403.   defi("scrollbar-width", XtNscrollBarWidth);
  404.   def ("top-toolbar-shadow-color", XtNtopToolBarShadowColor);
  405.   def ("bottom-toolbar-shadow-color", XtNbottomToolBarShadowColor);
  406.   def ("background-toolbar-color", XtNbackgroundToolBarColor);
  407.   def ("top-toolbar-shadow-pixmap", XtNtopToolBarShadowPixmap);
  408.   def ("bottom-toolbar-shadow-pixmap", XtNbottomToolBarShadowPixmap);
  409.   defi("toolbar-shadow-thickness", XtNtoolBarShadowThickness);
  410.   def ("scrollbar-placement", XtNscrollBarPlacement);
  411.   defi("inter-line-space", XtNinterline);
  412.   /* font, foreground */
  413.   def ("iconic", XtNiconic);
  414.   def ("cursor-color", XtNcursorColor);
  415.   def ("bar-cursor", XtNbarCursor);
  416.   def ("visual-bell", XtNvisualBell);
  417.   defi("bell-volume", XtNbellVolume);
  418.   def ("pointer-background", XtNpointerBackground);
  419.   def ("pointer-color", XtNpointerColor);
  420.   def ("text-pointer", XtNtextPointer);
  421.   def ("space-pointer", XtNspacePointer);
  422.   def ("modeline-pointer", XtNmodeLinePointer);
  423.   def ("gc-pointer", XtNgcPointer);
  424.   /* geometry, initial-geometry */
  425.   def ("menubar", XtNmenubar);
  426.   def ("initially-unmapped", XtNinitiallyUnmapped);
  427.   /* preferred-width, preferred-height */
  428.   def ("use-backing-store", XtNuseBackingStore);
  429.  
  430.   /* inherited: */
  431.  
  432.   def ("border-color", XtNborderColor);
  433.   defi("border-width", XtNborderWidth);
  434.   defi("width", XtNwidth);
  435.   defi("height", XtNheight);
  436.   defi("left", XtNx);
  437.   defi("top", XtNy);
  438.   
  439. #undef def
  440. }
  441.  
  442. /* Insert a description of internally-recorded parameters of frame X
  443.    into the parameter alist *ALISTPTR that is to be given to the user.
  444.    Only parameters that are specific to the X window system
  445.    and whose values are not correctly recorded in the frame's
  446.    param_alist need to be considered here.  */
  447.  
  448. static void
  449. color_to_string (Widget w, unsigned long pixel, char *buf)
  450. {
  451.   XColor color;
  452.   color.pixel = pixel;
  453.   XQueryColor (XtDisplay (w), w->core.colormap, &color);
  454.   sprintf (buf, "#%04x%04x%04x", color.red, color.green, color.blue);
  455. }
  456.  
  457. static void
  458. x_get_top_level_position (Display *d, Window w, Position *x, Position *y)
  459. {
  460.   Window root, parent = w, *children;
  461.   unsigned int nchildren;
  462.   XWindowAttributes xwa;
  463.  
  464.   do
  465.     {
  466.       w = parent;
  467.       if (!XQueryTree (d, w, &root, &parent, &children, &nchildren))
  468.     {
  469.       *x = 0;
  470.       *y = 0;
  471.       return;
  472.     }
  473.       XFree (children);
  474.     } while (root != parent);
  475.   XGetWindowAttributes (d, w, &xwa);
  476.   *x = xwa.x;
  477.   *y = xwa.y;
  478. }
  479.  
  480. static void
  481. x_get_frame_params (struct frame *f, Lisp_Object *alistptr)
  482. {
  483.   Widget shell = FRAME_X_SHELL_WIDGET (f);
  484.   EmacsFrame w = (EmacsFrame) FRAME_X_TEXT_WIDGET (f);
  485.   char buf [255];
  486.  
  487. #define store_int(sym, slot) \
  488.   store_in_alist (alistptr, sym, make_number (slot))
  489. #define store_str(sym, slot) \
  490.   store_in_alist (alistptr, sym, build_string (slot))
  491. #define store_bool(sym, slot) \
  492.   store_in_alist (alistptr, sym, (slot) ? Qt : Qnil)
  493. #define store_color(sym, slot) \
  494.   color_to_string ((Widget) w, slot, buf); \
  495.   store_in_alist (alistptr, sym, build_string (buf))
  496.  
  497.   store_color ("cursor-color", w->emacs_frame.cursor_color);
  498.   store_color ("border-color", w->core.border_pixel);
  499.   /* Naturally those bastards who wrote Xt couldn't be bothered
  500.      to learn about race conditions and such.  We can't trust
  501.      the X and Y values to have any resemblance of correctness,
  502.      so we smash the right values in place. */
  503.   x_get_top_level_position (XtDisplay (shell), XtWindow (shell),
  504.                 &shell->core.x, &shell->core.y);
  505.   store_int ("left", shell->core.x);
  506.   store_int ("top", shell->core.y);
  507.   store_int ("border-width", w->core.border_width);
  508.   store_int ("internal-border-width", w->emacs_frame.internal_border_width);
  509.   store_int ("scrollbar-width", w->emacs_frame.scrollbar_width);
  510.   store_color ("top-toolbar-shadow-color",
  511.            w->emacs_frame.top_toolbar_shadow_pixel);
  512.   store_color ("bottom-toolbar-shadow-color",
  513.            w->emacs_frame.bottom_toolbar_shadow_pixel);
  514.   store_color ("background-toolbar-color",
  515.            w->emacs_frame.background_toolbar_pixel);
  516.   store_int ("toolbar-shadow-thickness",
  517.          w->emacs_frame.toolbar_shadow_thickness);
  518.   store_int ("inter-line-space", w->emacs_frame.interline);
  519.   store_bool ("minibuffer", w->emacs_frame.minibuffer);
  520.   store_bool ("unsplittable", w->emacs_frame.unsplittable);
  521.   sprintf (buf, "0x%x", (int) XtWindow (w));
  522.   store_str ("window-id", buf);
  523. }
  524.  
  525.  
  526. /* Functions called only from `x_set_frame_params' to set
  527. ** individual parameters. */
  528.  
  529. static void 
  530. x_set_title_from_char (struct frame *f, char* name)
  531. {
  532.   char *old_name = 0;
  533.   Arg av [1];
  534.   XtSetArg (av[0], XtNtitle, &old_name);
  535.   XtGetValues (FRAME_X_SHELL_WIDGET (f), av, 1);
  536.   if (!old_name || strcmp (name, old_name))
  537.     {
  538.       XtSetArg (av[0], XtNtitle, name);
  539.       XtSetValues (FRAME_X_SHELL_WIDGET (f), av, 1);
  540.     }
  541. }
  542.  
  543. static void
  544. x_set_icon_name_from_char (struct frame *f, char* name)
  545. {
  546.   char *old_name = 0;
  547.   Arg av [1];
  548.   XtSetArg (av[0], XtNiconName, &old_name);
  549.   XtGetValues (FRAME_X_SHELL_WIDGET (f), av, 1);
  550.   if (!old_name || strcmp (name, old_name))
  551.     {
  552.       XtSetArg (av[0], XtNiconName, name);
  553.       XtSetValues (FRAME_X_SHELL_WIDGET (f), av, 1);
  554.     }
  555. }
  556.  
  557. /* Set the initial frame size as specified.  This function is used
  558.    when the frame's widgets have not yet been realized.  In this
  559.    case, it is not sufficient just to set the width and height of
  560.    the EmacsFrame widget, because they will be ignored when the
  561.    widget is realized (instead, the shell's geometry resource is
  562.    used). */
  563.  
  564. static void
  565. x_set_initial_frame_size (struct frame *f, int flags, int x, int y,
  566.                unsigned int w, unsigned int h)
  567. {
  568.   char shell_geom [255];
  569.   int xval, yval;
  570.   char xsign, ysign;
  571.   char uspos = !!(flags & (XValue | YValue));
  572.   char ussize = !!(flags & (WidthValue | HeightValue));
  573.   char *temp;
  574.  
  575.   /* assign the correct size to the EmacsFrame widget ... */
  576.   EmacsFrameSetCharSize (FRAME_X_TEXT_WIDGET (f), w, h);
  577.  
  578.   /* and also set the WMShell's geometry */
  579.   (flags & XNegative) ? (xval = -x, xsign = '-') : (xval = x, xsign = '+');
  580.   (flags & YNegative) ? (yval = -y, ysign = '-') : (yval = y, ysign = '+');
  581.   
  582.   if (uspos && ussize)
  583.     sprintf (shell_geom, "=%dx%d%c%d%c%d", w, h, xsign, xval, ysign, yval);
  584.   else if (uspos)
  585.     sprintf (shell_geom, "=%c%d%c%d", xsign, xval, ysign, yval);
  586.   else if (ussize)
  587.     sprintf (shell_geom, "=%dx%d", w, h);
  588.   
  589.   if (uspos || ussize)
  590.     {
  591.       temp = xmalloc (1 + strlen (shell_geom));
  592.       strcpy (temp, shell_geom);
  593.       FRAME_X_GEOM_FREE_ME_PLEASE (f) = temp;
  594.     }
  595.   else
  596.     temp = NULL;
  597.   XtVaSetValues (FRAME_X_SHELL_WIDGET (f), XtNgeometry, temp, 0);
  598. }
  599.  
  600. /* Report to X that a frame parameter of frame S is being set or changed.
  601.    If the parameter is not specially recognized, do nothing.
  602.  */
  603.  
  604. static void
  605. x_set_frame_params_1 (struct frame *f, Lisp_Object alist, int initialized_p)
  606. {
  607.   int x = 0, y = 0;
  608.   Dimension width = 0, height = 0;
  609.   Bool width_specified_p = False;
  610.   Bool height_specified_p = False;
  611.   Bool x_position_specified_p = False;
  612.   Bool y_position_specified_p = False;
  613.   Bool internal_border_width_specified = False;
  614.   Lisp_Object tail;
  615.   Widget w = FRAME_X_TEXT_WIDGET (f);
  616.   
  617.   for (tail = alist; !EQ (tail, Qnil); tail = Fcdr (tail))
  618.     {
  619.       Lisp_Object elt = Fcar (tail);
  620.       Lisp_Object prop = Fcar (elt);
  621.       Lisp_Object val = Fcdr (elt);
  622.       
  623.       if (STRINGP (prop))
  624.     {
  625.       if (string_length (XSTRING (prop)) == 0)
  626.         continue;
  627.  
  628.       if (STRINGP (val))
  629.         XtVaSetValues (w, XtVaTypedArg, string_data (XSTRING (prop)),
  630.                XtRString, string_data (XSTRING (val)),
  631.                string_length (XSTRING (val)) + 1, 0);
  632.       else
  633.         XtVaSetValues (w, XtVaTypedArg,
  634.                string_data (XSTRING (prop)), XtRInt, XINT (val),
  635.                sizeof (int),
  636.                0);
  637.     }
  638. #if 0
  639.       /* mly wants this, but it's not reasonable to change the name of a
  640.      frame after it has been created, because the old name was used
  641.      for resource lookup. */
  642.       else if (EQ (elt, Qname))
  643.         {
  644.           CHECK_STRING (val, 0);
  645.           f->name = val;
  646.         }
  647. #endif /* 0 */
  648.       else
  649.     {
  650.       Lisp_Object str = Fget (prop, Qx_resource_name, Qnil);
  651.       int int_p = !NILP (Fget (prop, Qintegerp, Qnil));
  652.  
  653.       if (NILP (prop) || NILP (str))
  654.         {
  655.           /* #### No error-checking on property names!  FMH!!! */
  656.           /* RMS apparently thinks this is a feature.
  657.          This whole frame-parameters things has got to go. */
  658.  
  659.           /* Kludge to handle the font property. */
  660.           if (EQ (prop, Qfont))
  661.         {
  662.           /* If the value is not a string we silently ignore it. */
  663.           if (STRINGP (val))
  664.             {
  665.               Lisp_Object frm, font_spec;
  666.  
  667.               XSETFRAME (frm, f);
  668.               font_spec = Fget (Fget_face (Qdefault), Qfont, Qnil);
  669.  
  670.               Fadd_spec_to_specifier (font_spec, val, frm, Qnil, Qnil);
  671.               update_frame_face_values (f);
  672.             }
  673.  
  674.           continue;
  675.         }
  676.           else
  677.         continue;
  678.         }
  679.       CHECK_STRING (str, 0);
  680.  
  681.       /* Kludge the width/height so that we interpret them in characters
  682.          instead of pixels.  Yuck yuck yuck. */
  683.       if (!strcmp ((char *) string_data (XSTRING (str)), "width"))
  684.         {
  685.           CHECK_INT (val, 0);
  686.           width = XINT (val);
  687.           width_specified_p = True;
  688.           continue;
  689.         }
  690.       if (!strcmp ((char *) string_data (XSTRING (str)), "height"))
  691.         {
  692.           CHECK_INT (val, 0);
  693.           height = XINT (val);
  694.           height_specified_p = True;
  695.           continue;
  696.         }
  697.       /* Further kludge the x/y. */
  698.       if (!strcmp ((char *) string_data (XSTRING (str)), "x"))
  699.         {
  700.           CHECK_INT (val, 0);
  701.           x = XINT (val);
  702.           x_position_specified_p = True;
  703.           continue;
  704.         }
  705.       if (!strcmp ((char *) string_data (XSTRING (str)), "y"))
  706.         {
  707.           CHECK_INT (val, 0);
  708.           y = XINT (val);
  709.           y_position_specified_p = True;
  710.           continue;
  711.         }
  712.       /* Have you figured out by now that this entire function is
  713.              one gigantic kludge? */
  714.       if (!strcmp ((char *) string_data (XSTRING (str)),
  715.                "internalBorderWidth"))
  716.         {
  717.           internal_border_width_specified = True;
  718.         }
  719.  
  720.       if (int_p)
  721.         {
  722.           CHECK_INT (val, 0);
  723.           XtVaSetValues (w, (char *) string_data (XSTRING (str)),
  724.                  XINT (val), 0);
  725.         }
  726.       else if (EQ (val, Qt))
  727.         XtVaSetValues (w, (char *) string_data (XSTRING (str)), /* XtN... */
  728.                True,
  729.                0);
  730.       else if (EQ (val, Qnil))
  731.         XtVaSetValues (w, (char *) string_data (XSTRING (str)), /* XtN... */
  732.                False,
  733.                0);
  734.       else
  735.         {
  736.           CHECK_STRING (val, 0);
  737.           XtVaSetValues (w, XtVaTypedArg,
  738.                  (char *) string_data (XSTRING (str)), /* XtN... */
  739.                  XtRString,
  740.                  string_data (XSTRING (val)), string_length (XSTRING (val)) + 1,
  741.                  0);
  742.         }
  743.  
  744.       if (!strcmp ((char *) string_data (XSTRING (str)), "scrollBarWidth")
  745.           || !strcmp ((char *) string_data (XSTRING (str)),
  746.               "scrollBarHeight"))
  747.         {
  748.           x_update_frame_scrollbars (f);
  749.         }
  750.     }
  751.     }
  752.  
  753.   /* Kludge kludge kludge.   We need to deal with the size and position
  754.    specially. */
  755.   {
  756.     int size_specified_p = width_specified_p || height_specified_p;
  757.     int position_specified_p = x_position_specified_p ||
  758.       y_position_specified_p;
  759.  
  760.     if (!width_specified_p)
  761.       width = FRAME_WIDTH (f);
  762.     if (!height_specified_p)
  763.       height = FRAME_HEIGHT (f);
  764.     
  765.     /* Kludge kludge kludge kludge. */
  766.     if (!x_position_specified_p)
  767.       x = (int) (FRAME_X_SHELL_WIDGET (f)->core.x);
  768.     if (!y_position_specified_p)
  769.       y = (int) (FRAME_X_SHELL_WIDGET (f)->core.y);
  770.       
  771.     if (!initialized_p)
  772.       {
  773.     int flags = (size_specified_p ? WidthValue | HeightValue : 0) |
  774.       (position_specified_p ? XValue | YValue : 0) |
  775.       (x < 0 ? XNegative : 0) | (y < 0 ? YNegative : 0);
  776.     if (size_specified_p
  777.         || position_specified_p
  778.         || internal_border_width_specified)
  779.       x_set_initial_frame_size (f, flags, x, y, width, height);
  780.       }
  781.     else
  782.       {
  783.     if (size_specified_p || internal_border_width_specified)
  784.       {
  785.         Lisp_Object frame;
  786.         XSETFRAME (frame, f);
  787.         Fset_frame_size (frame, make_number (width),
  788.                   make_number (height), Qnil);
  789.     }
  790.     if (position_specified_p)
  791.       {
  792.         Lisp_Object frame;
  793.         XSETFRAME (frame, f);
  794.         Fset_frame_position (frame, make_number (x), make_number (y));
  795.       }
  796.       }
  797.   }
  798. }
  799.  
  800. static void
  801. x_set_frame_params (struct frame *f, Lisp_Object alist)
  802. {
  803.   x_set_frame_params_1 (f, alist, 1);
  804. }
  805.  
  806. static int frame_title_format_already_set;
  807.  
  808. static void
  809. maybe_set_frame_title_format (Widget shell)
  810. {
  811.  
  812.   /* Only do this if this is the first X frame we're creating.
  813.      
  814.      If the *title resource (or -title option) was specified, then
  815.      set frame-title-format to its value.
  816.      */
  817.  
  818.   if (!frame_title_format_already_set)
  819.     {
  820.       /* No doubt there's a less stupid way to do this. */
  821.       char *results [2];
  822.       XtResource resources [2];
  823.       results [0] = results [1] = 0;
  824.       resources [0].resource_name = XtNtitle;
  825.       resources [0].resource_class = XtCTitle;
  826.       resources [0].resource_type = XtRString;
  827.       resources [0].resource_size = sizeof (String);
  828.       resources [0].resource_offset = 0;
  829.       resources [0].default_type = XtRString;
  830.       resources [0].default_addr = 0;
  831.       resources [1].resource_name = XtNiconName;
  832.       resources [1].resource_class = XtCIconName;
  833.       resources [1].resource_type = XtRString;
  834.       resources [1].resource_size = sizeof (String);
  835.       resources [1].resource_offset = sizeof (char *);
  836.       resources [1].default_type = XtRString;
  837.       resources [1].default_addr = 0;
  838.       XtGetSubresources (XtParent(shell), (XtPointer)results, shell->core.name,
  839.              shell->core.widget_class->core_class.class_name,
  840.              resources, XtNumber (resources), 0, 0);
  841.       if (results[0])
  842.     Vframe_title_format = build_string (results[0]);
  843.       if (results[1])
  844.     Vframe_icon_title_format = build_string (results[1]);
  845.     }
  846.  
  847.   frame_title_format_already_set = 1;
  848. }
  849.  
  850.  
  851. /************************************************************************/
  852. /*                widget creation                */
  853. /************************************************************************/
  854.  
  855. /* The widget hierarchy is
  856.  
  857.     argv[0]            shell        container    FRAME-NAME
  858.     ApplicationShell    EmacsShell    EmacsManager    EmacsFrame
  859.  
  860.    We accept geometry specs in this order:
  861.  
  862.     *FRAME-NAME.geometry
  863.     *EmacsFrame.geometry
  864.     Emacs.geometry
  865.  
  866.    Other possibilities for widget hierarchies might be
  867.  
  868.     argv[0]            frame        container    FRAME-NAME
  869.     ApplicationShell    EmacsShell    EmacsManager    EmacsFrame
  870.    or
  871.     argv[0]            FRAME-NAME    container    FRAME-NAME
  872.     ApplicationShell    EmacsShell    EmacsManager    EmacsFrame
  873.    or
  874.     argv[0]            FRAME-NAME    container    emacsTextPane
  875.     ApplicationShell    EmacsShell    EmacsManager    EmacsFrame
  876.  
  877. #ifdef EXTERNAL_WIDGET
  878.    The ExternalShell widget is simply a replacement for the Shell widget 
  879.    which is able to deal with using an externally-supplied window instead
  880.    of always creating its own.
  881. #endif
  882.  
  883. */
  884.  
  885. #ifdef EXTERNAL_WIDGET
  886.  
  887. static int
  888. is_valid_window (Window w, struct device *d)
  889. {
  890.   XWindowAttributes xwa;
  891.   Display *dpy = DEVICE_X_DISPLAY (d);
  892.  
  893.   expect_x_error (dpy);
  894.   XGetWindowAttributes (dpy, w, &xwa);
  895.   return !x_error_occurred_p (dpy);
  896. }
  897.  
  898. #endif /* EXTERNAL_WIDGET */
  899.  
  900. /* This sends a synthetic mouse-motion event to the frame, if the mouse
  901.    is over the frame.  This ensures that the cursor gets set properly
  902.    before the user moves the mouse for the first time. */
  903.  
  904. static void
  905. x_send_synthetic_mouse_event (struct frame *f)
  906. {
  907.   /* #### write this function. */
  908. }
  909.  
  910. static int
  911. first_x_frame_p (struct frame *f)
  912. {
  913.   Lisp_Object rest = DEVICE_FRAME_LIST (XDEVICE (f->device));
  914.   while (!NILP (rest) &&
  915.      (f == XFRAME (XCAR (rest)) ||
  916.       !FRAME_IS_X (XFRAME (XCAR (rest)))))
  917.     rest = XCDR (rest);
  918.   return (NILP (rest));
  919. }
  920.  
  921. /* Figure out what size the EmacsFrame widget should initially be,
  922.    and set it.  Should be called after the default font has been
  923.    determined but before the widget has been realized. */
  924.  
  925. static void
  926. x_initialize_frame_size (struct frame *f)
  927. {
  928.   /* Geometry of the AppShell */
  929.   int app_flags = 0;
  930.   int app_x = 0;
  931.   int app_y = 0;
  932.   unsigned int app_w = 0;
  933.   unsigned int app_h = 0;
  934.   
  935.   /* Geometry of the EmacsFrame */
  936.   int frame_flags = 0;
  937.   int frame_x = 0;
  938.   int frame_y = 0;
  939.   unsigned int frame_w = 0;
  940.   unsigned int frame_h = 0;
  941.   
  942.   /* Hairily merged geometry */
  943.   int x = 0;
  944.   int y = 0;
  945.   unsigned int w = 80;
  946.   unsigned int h = 40;
  947.   int flags = 0;
  948.  
  949.   char *geom = 0, *ew_geom = 0;
  950.   Boolean iconic_p = False, ew_iconic_p = False;
  951.  
  952.   Widget wmshell = FRAME_X_SHELL_WIDGET (f);
  953.   /* #### This may not be an ApplicationShell any more, with the 'popup
  954.      frame parameter. */
  955.   Widget app_shell = XtParent (wmshell);
  956.   Widget ew = FRAME_X_TEXT_WIDGET (f);
  957.  
  958. /* set the position of the frame's root window now.  When the
  959.    frame was created, the position was initialized to (0,0). */
  960.   {
  961.     struct window *win = XWINDOW (f->root_window);
  962.  
  963.     WINDOW_LEFT (win) = FRAME_LEFT_BORDER_END (f);
  964.     WINDOW_TOP (win) = FRAME_TOP_BORDER_END (f);
  965.  
  966.     if (!NILP (f->minibuffer_window))
  967.       {
  968.     win = XWINDOW (f->minibuffer_window);
  969.     WINDOW_LEFT (win) = FRAME_LEFT_BORDER_END (f);
  970.       }
  971.   }
  972.  
  973. #ifdef EXTERNAL_WIDGET
  974.   /* If we're an external widget, then the size of the frame is predetermined
  975.      (by the client) and is not our decision to make. */
  976.   if (FRAME_X_EXTERNAL_WINDOW_P (f))
  977.     return;
  978. #endif
  979.  
  980. #if 0
  981.   /* #### this junk has not been tested; therefore it's
  982.      probably wrong.  Doesn't really matter at this point because
  983.      currently all frames are either top-level or external widgets. */
  984.  
  985.   /* If we're not our own top-level window, then we shouldn't go messing around
  986.      with top-level shells or "Emacs.geometry" or any such stuff.  Therefore,
  987.      we do as follows to determine the size of the frame:
  988.  
  989.      1) If a value for the frame's "geometry" resource was specified, then
  990.         use it.  (This specifies a size in characters.)
  991.      2) Else, if the "width" and "height" resources were specified, then
  992.         leave them alone.  (This is a value in pixels.  Sorry, we can't break
  993.     Xt conventions here.)
  994.      3) Else, assume a size of 64x12.  (This is somewhat arbitrary, but
  995.         it's unlikely that a size of 80x40 is desirable because we're probably
  996.     inside of a dialog box.)
  997.  
  998.      Set the widget's x, y, height, and width as determined.  Don't set the
  999.      top-level container widget, because we don't necessarily know what it
  1000.      is. (Assume it is smart and pays attention to our values.)
  1001.   */
  1002.  
  1003.   if (!FRAME_X_TOP_LEVEL_FRAME_P (f))
  1004.     {
  1005.       XtVaGetValues (ew, XtNgeometry, &ew_geom, 0);
  1006.       if (ew_geom)
  1007.     frame_flags = XParseGeometry (ew_geom, &frame_x, &frame_y,
  1008.                        &frame_w, &frame_h);
  1009.       if (! (frame_flags & (WidthValue | HeightValue)))
  1010.     {
  1011.       XtVaGetValues (ew, XtNwidth, &frame_w,
  1012.              XtNheight, &frame_h, 0);
  1013.       if (!frame_w && !frame_h)
  1014.         {
  1015.           frame_w = 64;
  1016.           frame_h = 12;
  1017.           frame_flags |= WidthValue | HeightValue;
  1018.         }
  1019.     }
  1020.       if (frame_flags & (WidthValue | HeightValue))
  1021.     EmacsFrameSetCharSize (ew, frame_w, frame_h);
  1022.       if (frame_flags & (XValue | YValue))
  1023.     {
  1024.       XtVaGetValues (ew, XtNwidth, &frame_w,
  1025.              XtNheight, &frame_h, 0);
  1026.       if (frame_flags & XNegative)
  1027.         frame_x += frame_w;
  1028.       if (frame_flags & YNegative)
  1029.         frame_y += frame_h;
  1030.       XtVaSetValues (ew, XtNx, frame_x, XtNy, frame_y, 0);
  1031.     }
  1032.       return;
  1033.     }
  1034. #endif
  1035.  
  1036.   /* OK, we're a top-level shell. */
  1037.  
  1038.   if (!XtIsWMShell (wmshell))
  1039.     abort ();
  1040.  
  1041.   /* If the EmacsFrame doesn't have a geometry but the shell does,
  1042.      treat that as the geometry of the frame.  (Is this bogus?
  1043.      I'm not sure.) */
  1044.  
  1045.   XtVaGetValues (ew, XtNgeometry, &ew_geom, 0);
  1046.   if (!ew_geom)
  1047.     {
  1048.       XtVaGetValues (wmshell, XtNgeometry, &geom, 0);
  1049.       if (geom)
  1050.     {
  1051.       ew_geom = geom;
  1052.       XtVaSetValues (ew, XtNgeometry, ew_geom, 0);
  1053.     }
  1054.     }
  1055.  
  1056.   /* If the Shell is iconic, then the EmacsFrame is iconic.  (Is
  1057.      this bogus? I'm not sure.) */
  1058.   XtVaGetValues (ew, XtNiconic, &ew_iconic_p, 0);
  1059.   if (!ew_iconic_p)
  1060.     {
  1061.       XtVaGetValues (wmshell, XtNiconic, &iconic_p, 0);
  1062.       if (iconic_p)
  1063.     {
  1064.       ew_iconic_p = iconic_p;
  1065.       XtVaSetValues (ew, XtNiconic, iconic_p, 0);
  1066.     }
  1067.     }
  1068.   
  1069.   XtVaGetValues (app_shell, XtNgeometry, &geom, 0);
  1070.   if (geom)
  1071.     app_flags = XParseGeometry (geom, &app_x, &app_y, &app_w, &app_h);
  1072.  
  1073.   if (ew_geom)
  1074.     frame_flags = XParseGeometry (ew_geom, &frame_x, &frame_y,
  1075.                    &frame_w, &frame_h);
  1076.   
  1077.   if (first_x_frame_p (f))
  1078.     {
  1079.       /* If this is the first frame created:
  1080.          ====================================
  1081.  
  1082.          - Use the ApplicationShell's size/position, if specified.
  1083.            (This is "Emacs.geometry", or the "-geometry" command line arg.)
  1084.          - Else use the EmacsFrame's size/position.
  1085.            (This is "*FRAME-NAME.geometry")
  1086.  
  1087.      - If the AppShell is iconic, the frame should be iconic.
  1088.  
  1089.      AppShell comes first so that -geometry always applies to the first
  1090.      frame created, even if there is an "every frame" entry in the
  1091.      resource database.
  1092.        */
  1093.       if (app_flags & (XValue | YValue))
  1094.     {
  1095.       x = app_x; y = app_y;
  1096.       flags |= (app_flags & (XValue | YValue | XNegative | YNegative));
  1097.     }
  1098.       else if (frame_flags & (XValue | YValue))
  1099.     {
  1100.       x = frame_x; y = frame_y;
  1101.       flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
  1102.     }
  1103.  
  1104.       if (app_flags & (WidthValue | HeightValue))
  1105.     {
  1106.       w = app_w; h = app_h;
  1107.       flags |= (app_flags & (WidthValue | HeightValue));
  1108.     }
  1109.       else if (frame_flags & (WidthValue | HeightValue))
  1110.     {
  1111.       w = frame_w; h = frame_h;
  1112.       flags |= (frame_flags & (WidthValue | HeightValue));
  1113.     }
  1114.  
  1115.       /* If the AppShell is iconic, then the EmacsFrame is iconic. */
  1116.       if (!ew_iconic_p)
  1117.     {
  1118.       XtVaGetValues (app_shell, XtNiconic, &iconic_p, 0);
  1119.       if (iconic_p)
  1120.         {
  1121.           ew_iconic_p = iconic_p;
  1122.           XtVaSetValues (ew, XtNiconic, iconic_p, 0);
  1123.         }
  1124.     }
  1125.     }
  1126.   else
  1127.     {
  1128.       /* If this is not the first frame created:
  1129.          ========================================
  1130.  
  1131.          - use the EmacsFrame's size/position if specified
  1132.          - Otherwise, use the ApplicationShell's size, but not position.
  1133.  
  1134.          So that means that one can specify the position of the first frame
  1135.          with "Emacs.geometry" or `-geometry'; but can only specify the
  1136.      position of subsequent frames with "*FRAME-NAME.geometry".
  1137.  
  1138.      AppShell comes second so that -geometry does not apply to subsequent
  1139.      frames when there is an "every frame" entry in the resource db,
  1140.      but does apply to the first frame.
  1141.        */
  1142.       if (frame_flags & (XValue | YValue))
  1143.     {
  1144.       x = frame_x; y = frame_y;
  1145.       flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
  1146.     }
  1147.  
  1148.       if (frame_flags & (WidthValue | HeightValue))
  1149.     {
  1150.       w = frame_w; h = frame_h;
  1151.       flags |= (frame_flags & (WidthValue | HeightValue));
  1152.     }
  1153.       else if (app_flags & (WidthValue | HeightValue))
  1154.     {
  1155.       w = app_w;
  1156.       h = app_h;
  1157.       flags |= (app_flags & (WidthValue | HeightValue));
  1158.     }
  1159.     }
  1160.  
  1161.   x_set_initial_frame_size (f, flags, x, y, w, h);
  1162. }
  1163.  
  1164. static void
  1165. x_get_layout_sizes (struct frame *f, Dimension *topbreadth)
  1166. {
  1167.   int i;
  1168.  
  1169.   /* compute height of all top-area widgets */
  1170.   for (i=0, *topbreadth = 0; i<FRAME_X_NUM_TOP_WIDGETS (f); i++)
  1171.     {
  1172.       Widget wid = FRAME_X_TOP_WIDGETS (f)[i];
  1173.       if (wid && XtIsManaged (wid))
  1174.     *topbreadth += wid->core.height + 2*wid->core.border_width;
  1175.     }
  1176. }
  1177.  
  1178. static void
  1179. x_layout_widgets (Widget w, XtPointer client_data, XtPointer call_data)
  1180. {
  1181.   struct frame *f = (struct frame *) client_data;
  1182.   EmacsManagerResizeStruct *emst = (EmacsManagerResizeStruct *) call_data;
  1183.   Dimension width = emst->width;
  1184.   Dimension height = emst->height;
  1185.   Widget text = FRAME_X_TEXT_WIDGET (f);
  1186.   Dimension textbord = text->core.border_width;
  1187.   Dimension topbreadth;
  1188.   Position text_x = 0, text_y = 0;
  1189.   int i;
  1190.   unsigned char scrollbar_placement;
  1191.  
  1192.   x_get_layout_sizes (f, &topbreadth);
  1193.  
  1194.   /* first the menubar and psheets ... */
  1195.   for (i=0; i<FRAME_X_NUM_TOP_WIDGETS (f); i++)
  1196.     {
  1197.       Widget wid = FRAME_X_TOP_WIDGETS (f)[i];
  1198.       if (wid && XtIsManaged (wid))
  1199.     {
  1200.       Dimension bord = wid->core.border_width;
  1201.       XtConfigureWidget (wid, 0, text_y,
  1202.                  width - 2*bord, wid->core.height,
  1203.                  bord);
  1204.       text_y += wid->core.height + 2*bord;
  1205.     }
  1206.     }
  1207.  
  1208.   /* The scrollbar positioning is completely handled by redisplay.  We
  1209.      just need to know which sides they are supposed to go on. */
  1210.   XtVaGetValues (text, XtNscrollBarPlacement, &scrollbar_placement, 0);
  1211.   if (scrollbar_placement == XtTOP_LEFT ||
  1212.       scrollbar_placement == XtBOTTOM_LEFT)
  1213.     {
  1214.       f->scrollbar_on_left = 1;
  1215.     }
  1216.   else
  1217.     f->scrollbar_on_left = 0;
  1218.  
  1219.   if (scrollbar_placement == XtTOP_LEFT ||
  1220.       scrollbar_placement == XtTOP_RIGHT)
  1221.     {
  1222.       f->scrollbar_on_top = 1;
  1223.     }
  1224.   else
  1225.     f->scrollbar_on_top = 0;
  1226.  
  1227.   f->scrollbar_y_offset = topbreadth + textbord;
  1228.  
  1229.   /* finally the text area */
  1230.   XtConfigureWidget (text, text_x, text_y,
  1231.              width - 2*textbord,
  1232.              height - text_y - 2*textbord,
  1233.              textbord);
  1234. }
  1235.  
  1236. static void
  1237. x_do_query_geometry (Widget w, XtPointer client_data, XtPointer call_data)
  1238. {
  1239.   struct frame *f = (struct frame *) client_data;
  1240.   EmacsManagerQueryGeometryStruct *emst =
  1241.     (EmacsManagerQueryGeometryStruct *) call_data;
  1242.   Widget text = FRAME_X_TEXT_WIDGET (f);
  1243.   Dimension textbord = text->core.border_width;
  1244.   Dimension topbreadth;
  1245.   XtWidgetGeometry req, repl;
  1246.   int mask = emst->request_mode & (CWWidth | CWHeight);
  1247.  
  1248.   x_get_layout_sizes (f, &topbreadth);
  1249.  
  1250.   /* strip away menubar from suggested size, and ask the text widget
  1251.      what size it wants to be */
  1252.   req.request_mode = mask;
  1253.   if (mask & CWWidth)
  1254.     req.width = emst->proposed_width - 2*textbord;
  1255.   if (mask & CWHeight)
  1256.     req.height = emst->proposed_height - topbreadth - 2*textbord;
  1257.   XtQueryGeometry (text, &req, &repl);
  1258.  
  1259.   /* Now add the menubar back again */
  1260.   emst->proposed_width = repl.width + 2*textbord;
  1261.   emst->proposed_height = repl.height + topbreadth + 2*textbord;
  1262. }
  1263.  
  1264. /* Creates the widgets for a frame.
  1265.    lisp_window_id is a Lisp description of an X window or Xt
  1266.    widget to parse.
  1267.  
  1268.    This function does not create or map the windows.  (That is
  1269.    done by x_popup_frame().)
  1270.  */
  1271. static void
  1272. x_create_widgets (struct frame *f, Lisp_Object lisp_window_id,
  1273.           Lisp_Object parent)
  1274. {
  1275.   int menubar_visible;
  1276.   struct device *d = XDEVICE (f->device);
  1277. #ifdef EXTERNAL_WIDGET
  1278.   Window window_id = 0;
  1279. #endif
  1280.   char *name;
  1281.   Arg av [25];
  1282.   int ac = 0;
  1283.   Widget text, container, menubar, shell;
  1284.   Widget parentwid = 0;
  1285.  
  1286.  
  1287.   if (STRINGP (f->name))
  1288.      name = string_ext_data (XSTRING (f->name));
  1289.   else
  1290.     name = "emacs";
  1291.        
  1292.   /* The widget hierarchy is
  1293.  
  1294.     argv[0]            shell        pane        FRAME-NAME
  1295.     ApplicationShell    EmacsShell    EmacsManager    EmacsFrame
  1296.  
  1297.     (the type of the shell is ExternalShell if this frame is running
  1298.     in another client's window)
  1299.  
  1300.     However the EmacsShell widget has WM_CLASS of FRAME-NAME/Emacs.
  1301.     Normally such shells have name/class shellname/appclass, which in this
  1302.     case would be "shell/Emacs" instead of "frame-name/Emacs".  We could
  1303.     also get around this by naming the shell "frame-name", but that would
  1304.     be confusing because the text area (the EmacsFrame widget inferior of
  1305.     the shell) is also called that.  So we just set the WM_CLASS property.
  1306.    */
  1307.  
  1308. #ifndef EXTERNAL_WIDGET
  1309.   if (!NILP (lisp_window_id))
  1310.     error ("support for external widgets was not enabled at compile-time");
  1311. #else
  1312.   if (!NILP (lisp_window_id))
  1313.     {
  1314.       char *string;
  1315.  
  1316.       CHECK_STRING (lisp_window_id, 0);
  1317.       string = (char *) (string_data (XSTRING (lisp_window_id)));
  1318.       if (string[0] == '0' && (string[1] == 'x' || string[1] == 'X'))
  1319.     sscanf (string+2, "%lxu", &window_id);
  1320. #if 0
  1321.       else if (string[0] == 'w')
  1322.     {
  1323.       sscanf (string+1, "%x", &parent_widget);
  1324.       if (parent_widget)
  1325.         window_id = XtWindow (parent_widget);
  1326.     }
  1327. #endif
  1328.       else
  1329.     sscanf (string, "%lu", &window_id);
  1330.       if (!is_valid_window (window_id, d))
  1331.     error ("Invalid window %d", window_id);
  1332.       FRAME_X_EXTERNAL_WINDOW_P (f) = 1;
  1333.     } else
  1334. #endif /* EXTERNAL_WIDGET */
  1335.       FRAME_X_TOP_LEVEL_FRAME_P (f) = 1;
  1336.  
  1337.   ac = 0;
  1338.   XtSetArg (av[ac], XtNallowShellResize, True); ac++;
  1339. #ifdef LWLIB_USES_MOTIF
  1340.   /* Motif sucks beans.  Without this in here, it will delete the window
  1341.      out from under us when it receives a WM_DESTROY_WINDOW message
  1342.      from the WM. */
  1343.   XtSetArg (av[ac], XmNdeleteResponse, XmDO_NOTHING); ac++;
  1344. #endif
  1345.  
  1346. #ifdef EXTERNAL_WIDGET
  1347.   if (window_id)
  1348.     {
  1349.       XtSetArg (av[ac], XtNwindow, window_id); ac++;
  1350.     }
  1351.   else
  1352. #endif
  1353.     {
  1354.       XtSetArg (av[ac], XtNinput, True); ac++;
  1355.       XtSetArg (av[ac], XtNminWidthCells, 10); ac++;
  1356.       XtSetArg (av[ac], XtNminHeightCells, 4); ac++;
  1357.     }
  1358.  
  1359.   if (!NILP (parent))
  1360.     {
  1361.       parentwid = FRAME_X_SHELL_WIDGET (XFRAME (parent));
  1362.       XtSetArg (av[ac], XtNtransientFor, parentwid); ac++;
  1363.     }
  1364.  
  1365.   shell = XtCreatePopupShell ("shell",
  1366.                   (
  1367. #ifdef EXTERNAL_WIDGET
  1368.                    window_id ? externalShellWidgetClass :
  1369. #endif
  1370.                    parentwid ? transientEmacsShellWidgetClass :
  1371.                    topLevelEmacsShellWidgetClass
  1372.                    ),
  1373.                   parentwid ? parentwid :
  1374.                   DEVICE_XT_APP_SHELL (d),
  1375.                   av, ac);
  1376.   FRAME_X_SHELL_WIDGET (f) = shell;
  1377.   maybe_set_frame_title_format (shell);
  1378.  
  1379.   /* Create the manager widget */
  1380.   container = XtVaCreateWidget ("container",
  1381.                 emacsManagerWidgetClass,
  1382.                 shell, 0);
  1383.   FRAME_X_CONTAINER_WIDGET (f) = container;
  1384.   XtAddCallback (container, XtNresizeCallback, x_layout_widgets,
  1385.          (XtPointer) f);
  1386.   XtAddCallback (container, XtNqueryGeometryCallback, x_do_query_geometry,
  1387.          (XtPointer) f);
  1388.  
  1389.   /* Create the text area */
  1390.   ac = 0;
  1391.   XtSetArg (av[ac], XtNborderWidth, 0); ac++;    /* should this be settable? */
  1392.   XtSetArg (av[ac], XtNemacsFrame, f); ac++;
  1393.   text = XtCreateWidget (name,
  1394.              emacsFrameClass,
  1395.              container, av, ac);
  1396.   FRAME_X_TEXT_WIDGET (f) = text;
  1397.   
  1398.   /* Create the initial menubar widget. */
  1399.   menubar_visible = initialize_frame_menubar (f);
  1400.   FRAME_X_TOP_WIDGETS (f)[0] = menubar = FRAME_X_MENUBAR_WIDGET (f);
  1401.   FRAME_X_NUM_TOP_WIDGETS (f) = 1;
  1402.   
  1403.   if (menubar_visible)
  1404.     XtManageChild (menubar);
  1405.   XtManageChild (text);
  1406.   XtManageChild (container);
  1407. }
  1408.  
  1409. /* We used to call XtPopup() in x_popup_frame, but that doesn't give
  1410.    you control over whether the widget is initially mapped or not
  1411.    because XtPopup() makes an unconditional call to XMapRaised().
  1412.    Boy, those Xt designers were clever.
  1413.  
  1414.    When we first removed it we only kept the XtRealizeWidget call in
  1415.    XtPopup.  For everything except HP's that was enough.  For HP's,
  1416.    though, the failure to call the popup callbacks resulted in XEmacs
  1417.    not accepting any input.  Bizarre but true.  Stupid but true.
  1418.  
  1419.    So, in case there are any other gotches floating out there along
  1420.    the same lines I've duplicated the majority of XtPopup here.  It
  1421.    assumes no grabs and that the widget is not already popped up, both
  1422.    valid assumptions for the one place this is called from. */
  1423. static void
  1424. xemacs_XtPopup (Widget widget)
  1425. {
  1426.   ShellWidget shell_widget = (ShellWidget) widget;
  1427.   XtGrabKind call_data = XtGrabNone;
  1428.  
  1429.   XtCallCallbacks(widget, XtNpopupCallback, (XtPointer)&call_data);
  1430.  
  1431.   shell_widget->shell.popped_up = TRUE;
  1432.   shell_widget->shell.grab_kind = XtGrabNone;
  1433.   shell_widget->shell.spring_loaded = False;
  1434.  
  1435.   if (shell_widget->shell.create_popup_child_proc != NULL)
  1436.     (*(shell_widget->shell.create_popup_child_proc))(widget);
  1437.  
  1438.   /* The XtVaSetValues below are not in XtPopup menu.  We just want to
  1439.      make absolutely sure... */
  1440.   XtVaSetValues (widget, XtNmappedWhenManaged, False, NULL);
  1441.   XtRealizeWidget (widget);
  1442.   XtVaSetValues (widget, XtNmappedWhenManaged, True, NULL);
  1443. }
  1444.  
  1445. /* create the windows for the specified frame and display them.
  1446.    Note that the widgets have already been created, and any
  1447.    necessary geometry calculations have already been done. */
  1448. static void
  1449. x_popup_frame (struct frame *f)
  1450. {
  1451.   Widget shell_widget = FRAME_X_SHELL_WIDGET (f);
  1452.   Widget frame_widget = FRAME_X_TEXT_WIDGET (f);
  1453.   struct device *d = XDEVICE (FRAME_DEVICE (f));
  1454.  
  1455.   /* Before mapping the window, make sure that the WMShell's notion of
  1456.      whether it should be iconified is synchronized with the EmacsFrame's
  1457.      notion.
  1458.      */
  1459.   if (FRAME_X_TOP_LEVEL_FRAME_P (f))
  1460.     x_wm_set_shell_iconic_p (shell_widget,
  1461.                  ((EmacsFrame) frame_widget)
  1462.                  ->emacs_frame.iconic);
  1463.  
  1464.   xemacs_XtPopup (shell_widget);
  1465.  
  1466.   if (!((EmacsFrame) frame_widget)->emacs_frame.initially_unmapped)
  1467.     XtMapWidget (shell_widget);
  1468.   else
  1469.     {
  1470.       /* We may have set f->visible to 1 in x_init_frame(), so undo
  1471.      that now. */
  1472.       FRAME_X_TOTALLY_VISIBLE_P (f) = 0;
  1473.       f->visible = 0;
  1474.     }
  1475.  
  1476. #ifdef EXTERNAL_WIDGET
  1477.   if (FRAME_X_EXTERNAL_WINDOW_P (f))
  1478.     ExternalShellReady (shell_widget, XtWindow (frame_widget), KeyPressMask);
  1479.   else
  1480. #endif
  1481.     if (FRAME_X_TOP_LEVEL_FRAME_P (f))
  1482.       {
  1483.     /* tell the window manager about us. */
  1484.     x_wm_store_class_hints (shell_widget, XtName (frame_widget));
  1485.     x_wm_maybe_store_wm_command (f);
  1486.     x_wm_hack_wm_protocols (shell_widget);
  1487.       }
  1488.  
  1489. #ifdef I18N4
  1490.   /* #### not device-independent. */
  1491.   if (initial_input_context)
  1492.     {
  1493.       Window main_window = XtWindow (frame_widget);
  1494.       static int initial_ic_used_already = 0;
  1495.       /* kludge alert...I want to make sure that init_input() actually
  1496.      completed its dirty work (event_mask setup) */
  1497.       
  1498.       if (!initial_ic_used_already)
  1499.     {
  1500.       /* I probably ought to just waste this initial_input_context crap and
  1501.          do all XIC setup here...  But then I'd have to mess around with
  1502.          event_masks. see init_input() */ 
  1503.       FRAME_X_INPUT_CONTEXT (f) = initial_input_context;
  1504.       initial_ic_used_already = 1;
  1505.     }
  1506.       else
  1507.     {
  1508.       FRAME_X_INPUT_CONTEXT (f) =
  1509.         XCreateIC (input_method,
  1510.                XNInputStyle, input_method_style,
  1511.                NULL);
  1512.     }
  1513.       
  1514.       XSetICValues (FRAME_X_INPUT_CONTEXT (x),
  1515.             XNClientWindow, main_window,
  1516.             XNFocusWindow, main_window,
  1517.             NULL);
  1518.     }
  1519. #endif /* I18N4 */
  1520.  
  1521. #ifdef HACK_EDITRES
  1522.   /* Allow XEmacs to respond to EditRes requests.  See the O'Reilly Xt */
  1523.   /* Instrinsics Programming Manual, Motif Edition, Aug 1993, Sect 14.14, */
  1524.   /* pp. 483-493. */
  1525.   XtAddEventHandler (shell_widget,               /* the widget in question */
  1526.              (EventMask) 0,   /* OR this mask with existing mask */
  1527.              True,              /* called on non-maskable events? */
  1528.              _XEditResCheckMessages,                /* the handler */
  1529.              NULL );
  1530. #endif
  1531.  
  1532.   /* Do a stupid property change to force the server to generate a
  1533.      propertyNotify event so that the event_stream server timestamp will
  1534.      be initialized to something relevant to the time we created the window.
  1535.      */
  1536.   XChangeProperty (XtDisplay (frame_widget), XtWindow (frame_widget),
  1537.            DEVICE_XATOM_WM_PROTOCOLS (d), XA_ATOM, 32, PropModeAppend,
  1538.            (unsigned char*) NULL, 0);
  1539.   
  1540.   x_send_synthetic_mouse_event (f);
  1541. }
  1542.  
  1543. static void
  1544. allocate_x_frame_struct (struct frame *f)
  1545. {
  1546.   /* zero out all slots. */
  1547.   f->frame_data = malloc_type_and_zero (struct x_frame);
  1548.  
  1549.   /* yeah, except the lisp ones */
  1550.   FRAME_X_ICON_PIXMAP (f) = Qnil;
  1551.   FRAME_X_ICON_PIXMAP_MASK (f) = Qnil;
  1552. #ifdef ENERGIZE
  1553.   FRAME_X_CURRENT_PSHEET_BUFFER (f) = Qnil;
  1554.   FRAME_X_DESIRED_PSHEET_BUFFER (f) = Qnil;
  1555. #endif
  1556. }
  1557.  
  1558.  
  1559. /************************************************************************/
  1560. /*                Lisp functions                */
  1561. /************************************************************************/
  1562.  
  1563. static void
  1564. x_init_frame (struct frame *f, Lisp_Object parms)
  1565. {
  1566.   /* This function can GC */
  1567.   Lisp_Object device = FRAME_DEVICE (f);
  1568.   struct device *d = XDEVICE (device);
  1569.   Lisp_Object lisp_window_id;
  1570.   Lisp_Object popup;
  1571.  
  1572.   lisp_window_id = Fassq (Qwindow_id, parms);
  1573.   if (!NILP (lisp_window_id))
  1574.     lisp_window_id = Fcdr (lisp_window_id);
  1575.   popup = Fassq (Qpopup, parms);
  1576.   if (!NILP (popup))
  1577.     {
  1578.       popup = XCDR (popup);
  1579.       if (EQ (popup, Qt))
  1580.     popup = Fselected_frame (device);
  1581.       CHECK_LIVE_FRAME (popup, 0);
  1582.       if (!EQ (device, FRAME_DEVICE (XFRAME (popup))))
  1583.     signal_simple_error_2 ("Parent must be on same device as frame",
  1584.                    device, popup);
  1585.     }
  1586.  
  1587.   if (NILP (DEVICE_SELECTED_FRAME (d)))
  1588.     {
  1589.       /* This means that this is the first frame on the device.
  1590.      So short-ciruit the delay in processing the initial MapNotify
  1591.      event so that output on the first frame shows up right
  1592.      away... */
  1593.       f->visible = 1;
  1594.     }
  1595.  
  1596.   allocate_x_frame_struct (f);
  1597.   x_create_widgets (f, lisp_window_id, popup);
  1598. }
  1599.  
  1600. static void
  1601. x_finish_init_frame (struct frame *f, Lisp_Object parms)
  1602. {
  1603.   /* Set up the values of the widget/frame.  A case could be made for putting
  1604.      this inside of the widget's initialize method. */
  1605.  
  1606.   update_frame_face_values (f);
  1607.   x_initialize_frame_size (f);
  1608.   update_frame_title (f);
  1609.   x_set_frame_params_1 (f, parms, 0);
  1610.  
  1611.   /* Pop up the frame. */
  1612.  
  1613.   x_popup_frame (f);
  1614. }
  1615.  
  1616. static void
  1617. x_mark_frame (struct frame *f, void (*markobj) (Lisp_Object))
  1618. {
  1619.   ((markobj) (FRAME_X_ICON_PIXMAP (f)));
  1620.   ((markobj) (FRAME_X_ICON_PIXMAP_MASK (f)));
  1621. #ifdef ENERGIZE
  1622.   ((markobj) (FRAME_X_CURRENT_PSHEET_BUFFER (f)));
  1623.   ((markobj) (FRAME_X_DESIRED_PSHEET_BUFFER (f)));
  1624. #endif
  1625. }
  1626.  
  1627. /* #### We need to update documentation once fully converted to glyph
  1628.    system. */
  1629. DEFUN ("x-set-frame-icon-pixmap", Fx_set_frame_icon_pixmap,
  1630.        Sx_set_frame_icon_pixmap, 2, 3, 0,
  1631.   "Set the icon of the given frame to the given image instance,\n\
  1632. which should be an image instance object (as returned by\n\
  1633. `make-image-instance'), a glyph object (as returned by `make-glyph'),\n\
  1634. or nil.  If a glyph object is given, the glyph will be instantiated on\n\
  1635. the frame to produce an image instance object.\n\
  1636. \n\
  1637. If the given image instance has a mask, that will be used as the icon mask;\n\
  1638. however, not all window managers support this.\n\
  1639. \n\
  1640. The window manager is also not required to support color pixmaps,\n\
  1641. only bitmaps (one plane deep).\n\
  1642. \n\
  1643. If the image instance does not have a mask, then the optional\n\
  1644. third argument may be the image instance to use as the mask (it must be\n\
  1645. one plane deep).")
  1646.   (frame, image_instance, mask)
  1647.     Lisp_Object frame, image_instance, mask;
  1648. {
  1649.   struct frame *f = get_x_frame (frame);
  1650.   Pixmap x_pixmap, x_mask;
  1651.  
  1652.   XSETFRAME (frame, f);
  1653.  
  1654.   if (!NILP (image_instance))
  1655.     {
  1656.       if (GLYPHP (image_instance))
  1657.     image_instance =
  1658.       glyph_image_instance (image_instance, frame, 0);
  1659.       CHECK_IMAGE_INSTANCE (image_instance, 0);
  1660.     }
  1661.   if (!NILP (mask))
  1662.     {
  1663.       if (GLYPHP (mask))
  1664.     mask = glyph_image_instance (mask, frame, 0);
  1665.       CHECK_IMAGE_INSTANCE (mask, 0);
  1666.     }
  1667.  
  1668.   if (IMAGE_INSTANCEP (image_instance)
  1669.       && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (image_instance)))
  1670.     {
  1671.       x_pixmap = XIMAGE_INSTANCE_X_PIXMAP (image_instance);
  1672.       x_mask = XIMAGE_INSTANCE_PIXMAP_DEPTH (image_instance);
  1673.       if (x_mask) mask = Qnil;
  1674.     }
  1675.   else
  1676.     {
  1677.       x_pixmap = 0;
  1678.       x_mask = 0;
  1679.       mask = Qnil;
  1680.     }
  1681.  
  1682.   if (IMAGE_INSTANCEP (mask)
  1683.       && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (mask)))
  1684.     {
  1685.       if (XIMAGE_INSTANCE_PIXMAP_DEPTH (mask) > 1)
  1686.     signal_simple_error ("mask must be one plane", mask);
  1687.       x_mask = XIMAGE_INSTANCE_X_PIXMAP (mask);
  1688.     }
  1689.  
  1690.   /* GC-protect the lisp objects (and underlying X data) */
  1691.   FRAME_X_ICON_PIXMAP (f) = image_instance;
  1692.   FRAME_X_ICON_PIXMAP_MASK (f) = mask;
  1693.  
  1694.   /* Store the X data into the widget. */
  1695.   {
  1696.     Arg av [10];
  1697.     int ac = 0;
  1698.     XtSetArg (av [ac], XtNiconPixmap, x_pixmap); ac++;
  1699.     XtSetArg (av [ac], XtNiconMask, x_mask); ac++;
  1700.     XtSetValues (FRAME_X_SHELL_WIDGET (f), av, ac);
  1701.   }
  1702.  
  1703.   return image_instance;
  1704. }
  1705.  
  1706. DEFUN ("x-set-frame-pointer", Fx_set_frame_pointer, Sx_set_frame_pointer,
  1707.        2, 2, 0,
  1708.        "Set the mouse cursor of FRAME to the given cursor,\n\
  1709. which should be an object returned by `make-cursor'.")
  1710.      (frame, cursor)
  1711.      Lisp_Object frame, cursor;
  1712. {
  1713.   /* #### seriously broken. */
  1714.   struct frame *f = get_x_frame (frame);
  1715.   CHECK_CURSOR (cursor, 0);
  1716.   if (! EQ (f->pointer, cursor))
  1717.     {
  1718.       XDefineCursor (XtDisplay (FRAME_X_TEXT_WIDGET (f)),
  1719.                 XtWindow (FRAME_X_TEXT_WIDGET (f)),
  1720.              XCURSOR (cursor)->cursor);
  1721.       XSync (XtDisplay (FRAME_X_TEXT_WIDGET (f)), 0);
  1722.       /* #### If the user cuts this pointer, we'll get X errors.
  1723.          This needs to be rethunk. */
  1724.       /* change_cursor_for_gc() accesses this */
  1725.       f->pointer = cursor;
  1726.     }
  1727.   return Qnil;
  1728. }
  1729.  
  1730. DEFUN ("x-set-scrollbar-pointer", Fx_set_scrollbar_pointer,
  1731.        Sx_set_scrollbar_pointer, 2, 2, 0,
  1732.        "Set the mouse cursor of the scrollbars on FRAME to the given\n\
  1733. cursor, which should be an object returned by `make-cursor'.")
  1734.      (frame, cursor)
  1735.      Lisp_Object frame, cursor;
  1736. {
  1737.   /* #### seriously broken. */
  1738.   struct frame *f = get_x_frame (frame);
  1739.   CHECK_CURSOR (cursor, 0);
  1740.   x_set_scrollbar_pointer (f, cursor);
  1741.   return Qnil;
  1742. }
  1743.  
  1744. /* GC calls x_show_gc_cursor() with a cursor object to turn on the GC cursor,
  1745.    and with nil to turn it off.
  1746. */
  1747.  
  1748. int
  1749. x_show_gc_cursor (struct frame *f, Lisp_Object cursor)
  1750. {
  1751.   int speccount = specpdl_depth ();
  1752.   Lisp_Object frame;
  1753.   int changed = 0;
  1754.  
  1755.   specbind (Qinhibit_quit, Qt);        /* some losers in here call Fassq() */
  1756.  
  1757.   XSETFRAME (frame, f);
  1758.   if (NILP (cursor))
  1759.     {
  1760.       if (!NILP (Vpre_gc_cursor))
  1761.     {
  1762.       if (!CURSORP (Vpre_gc_cursor)) abort ();
  1763.       /* We know it's a frame, we know it's a pointer, so
  1764.          x-set-frame-pointer won't error. */
  1765.       Fx_set_frame_pointer (frame, Vpre_gc_cursor);
  1766.       changed = 1;
  1767.     }
  1768.     }
  1769.   else if (CURSORP (cursor))
  1770.     {
  1771.       Vpre_gc_cursor = f->pointer;
  1772.  
  1773.       if (CURSORP (Vpre_gc_cursor))
  1774.     /* if we don't know what cursor is there, don't change to the GC
  1775.        cursor, because we'd have no way of changing back... */
  1776.     {
  1777.       /* We know it's a frame, we know it's a pointer, so
  1778.          x-set-frame-pointer won't error. */
  1779.       Fx_set_frame_pointer (frame, cursor);
  1780.       changed = 1;
  1781.     }
  1782.     }
  1783.  
  1784.   unbind_to (speccount, Qnil);
  1785.   return changed;
  1786. }
  1787.  
  1788. DEFUN ("x-window-id", Fx_window_id, Sx_window_id, 0, 1, 0,
  1789.        "Get the ID of the X11 window.\n\
  1790. This gives us a chance to manipulate the Emacs window from within a\n\
  1791. different program.  Since the ID is an unsigned long, we return it as\n\
  1792. a string.")
  1793.   (frame)
  1794.   Lisp_Object frame;
  1795. {
  1796.   char str[255];
  1797.   struct frame *f = get_x_frame (frame);
  1798.  
  1799.   sprintf (str, "%lu", XtWindow (FRAME_X_TEXT_WIDGET (f)));
  1800.   return build_string (str);
  1801. }
  1802.  
  1803.  
  1804. /************************************************************************/
  1805. /*            manipulating the X window            */
  1806. /************************************************************************/
  1807.  
  1808. static void
  1809. x_set_frame_position (struct frame *f, int xoff, int yoff)
  1810. {
  1811.   Widget w = FRAME_X_SHELL_WIDGET (f);
  1812.   Display *dpy = XtDisplay (w);
  1813.   Dimension frame_w = DisplayWidth (dpy, DefaultScreen (dpy));
  1814.   Dimension frame_h = DisplayHeight (dpy, DefaultScreen (dpy));
  1815.   Dimension shell_w, shell_h, shell_bord;
  1816.   int win_gravity;
  1817.  
  1818.   XtVaGetValues (w,
  1819.          XtNwidth, &shell_w,
  1820.          XtNheight, &shell_h,
  1821.          XtNborderWidth, &shell_bord,
  1822.          0);
  1823.  
  1824.   win_gravity =
  1825.     xoff >= 0 && yoff >= 0 ? NorthWestGravity :
  1826.     xoff >= 0 ? SouthWestGravity :
  1827.     yoff >= 0 ? NorthEastGravity :
  1828.     SouthEastGravity;
  1829.   if (xoff < 0)
  1830.     xoff += frame_w - shell_w - 2*shell_bord;
  1831.   if (yoff < 0)
  1832.     yoff += frame_h - shell_h - 2*shell_bord;
  1833.  
  1834.   /* Update the hints so that, if this window is currently iconified, it will
  1835.      come back at the right place.  We can't look at s->visible to determine
  1836.      whether it is iconified because it might not be up-to-date yet (the queue
  1837.      might not be processed). */
  1838.   XtVaSetValues (w,
  1839.          XtNwinGravity, win_gravity,
  1840.          XtNx, xoff,
  1841.          XtNy, yoff,
  1842.          0);
  1843.   /* Sometimes you will find that
  1844.  
  1845.      (set-frame-position (selected-frame) -50 -50)
  1846.  
  1847.      doesn't put the frame where you expect it to:
  1848.      i.e. it's closer to the lower-right corner than
  1849. )     it should be, and it appears that the size of
  1850.      the WM decorations was not taken into account.
  1851.      This is *not* a problem with this function.
  1852.      Both mwm and twm have bugs in handling this
  1853.      situation. (mwm ignores the window gravity
  1854.      and always assumes NorthWest, except the first
  1855.      time you map the window; twm gets things almost
  1856.      right, but forgets to account for the border
  1857.      width of the top-level window.) This function
  1858.      does what it's supposed to according to the ICCCM,
  1859.      and I'm not about to hack around window-manager
  1860.      bugs. */
  1861.  
  1862. #if 0
  1863.   /* This is not necessary under either mwm or twm */
  1864.   x_wm_mark_shell_position_user_specified (w);
  1865. #endif
  1866. }
  1867.  
  1868. /* Call this to change the size of frame S's x-window. */
  1869.  
  1870. static void
  1871. x_set_frame_size (struct frame *f, int cols, int rows)
  1872. {
  1873.   EmacsFrameSetCharSize (FRAME_X_TEXT_WIDGET (f), cols, rows);
  1874. #if 0
  1875.     /* this is not correct.  x_set_frame_size() is called from
  1876.        Fset_frame_size(), which may or may not have been called
  1877.        by the user (e.g. update_EmacsFrame() calls it when the font
  1878.        changes).  For now, don't bother with getting this right. */
  1879.   x_wm_mark_shell_size_user_specified (FRAME_X_SHELL_WIDGET (f));
  1880. #endif
  1881. }
  1882.  
  1883. static void
  1884. x_set_mouse_position (struct window *w, int x, int y)
  1885. {
  1886.   struct frame *f = XFRAME (w->frame);
  1887.  
  1888.   Display *display = DEVICE_X_DISPLAY (XDEVICE (f->device));
  1889.   XWarpPointer (display, None, XtWindow (FRAME_X_TEXT_WIDGET (f)),
  1890.                 0, 0, 0, 0, w->pixel_left + x, w->pixel_top + y);
  1891. }
  1892.  
  1893. static int
  1894. x_get_mouse_position (struct device *d, struct window **w, int *x, int *y)
  1895. {
  1896.   Display *display = DEVICE_X_DISPLAY (d);
  1897.   Window child_window;
  1898.   Window root_window;
  1899.   Window win;
  1900.   int root_x, root_y;
  1901.   int win_x, win_y;
  1902.   unsigned int keys_and_buttons;
  1903.   struct frame *f;
  1904.  
  1905.   if (XQueryPointer (display, RootWindow (display, DefaultScreen (display)),
  1906.              &root_window, &child_window, &root_x, &root_y,
  1907.              &win_x, &win_y, &keys_and_buttons) == False)
  1908.     return 0;
  1909.  
  1910.   if (child_window == None)
  1911.     return 0;    /* not over any window. */
  1912.  
  1913.   while (1)
  1914.     {
  1915.       win = child_window;
  1916.       if (XTranslateCoordinates (display, root_window, win, root_x, root_y,
  1917.                  &win_x, &win_y, &child_window) == False)
  1918.     /* Huh? */
  1919.     return 0;
  1920.  
  1921.       if (child_window == None)
  1922.     break;
  1923.     }
  1924.  
  1925.   /* At this point, win is the innermost window containing the pointer
  1926.      and win_x and win_y are the coordinates of that window. */
  1927.   f = x_any_window_to_frame (d, win);
  1928.   if (!f)
  1929.     return 0;
  1930.  
  1931.   if (XTranslateCoordinates (display, win,
  1932.                  XtWindow (FRAME_X_TEXT_WIDGET (f)),
  1933.                  win_x, win_y, x, y, &child_window) == False)
  1934.     /* Huh? */
  1935.     return 0;
  1936.  
  1937.   *w = find_window_by_pixel_pos (*x, *y, f->root_window);
  1938.   if (!*w)
  1939.     return 0;
  1940.  
  1941.   /* Adjust the position to be relative to the window. */
  1942.   *x -= (*w)->pixel_left;
  1943.   *y -= (*w)->pixel_top;
  1944.  
  1945.   return 1;
  1946. }
  1947.  
  1948. static void
  1949. x_cant_notify_wm_error (void)
  1950. {
  1951.   error ("Can't notify window manager of iconification.");
  1952. }
  1953.  
  1954. /* Raise frame F.  */
  1955. static void
  1956. x_raise_frame_1 (struct frame *f, int force)
  1957. {
  1958.   Widget bottom_dialog;
  1959.   Window emacs_window;
  1960.   XWindowChanges xwc;
  1961.   unsigned int flags;
  1962.   Display *display = DEVICE_X_DISPLAY (XDEVICE (f->device));
  1963.  
  1964.   if (f->visible || force)
  1965.     {
  1966.       emacs_window = XtWindow (FRAME_X_SHELL_WIDGET (f));
  1967.       /* first raises all the dialog boxes, then put emacs just below the 
  1968.        * bottom most dialog box */
  1969.       bottom_dialog = lw_raise_all_pop_up_widgets ();
  1970.       if (bottom_dialog && XtWindow (bottom_dialog))
  1971.     {
  1972.       xwc.sibling = XtWindow (bottom_dialog);
  1973.       xwc.stack_mode = Below;
  1974.       flags = CWSibling | CWStackMode;
  1975.     }
  1976.       else
  1977.     {
  1978.       xwc.stack_mode = Above;
  1979.       flags = CWStackMode;
  1980.     }
  1981.  
  1982.       if (!XReconfigureWMWindow (display, emacs_window,
  1983.                  DefaultScreen (display),
  1984.                  flags, &xwc))
  1985.     x_cant_notify_wm_error ();
  1986.     }
  1987. }
  1988.  
  1989. static void
  1990. x_raise_frame (struct frame *f)
  1991. {
  1992.   x_raise_frame_1 (f, 1);
  1993. }
  1994.  
  1995. /* Lower frame F.  */
  1996. static void
  1997. x_lower_frame (struct frame *f)
  1998. {
  1999.   Display *display = DEVICE_X_DISPLAY (XDEVICE (f->device));
  2000.   XWindowChanges xwc;
  2001.   unsigned int flags;
  2002.   
  2003.   if (f->visible)
  2004.     {
  2005.       xwc.stack_mode = Below;
  2006.       flags = CWStackMode;
  2007.       if (!XReconfigureWMWindow (display, XtWindow (FRAME_X_SHELL_WIDGET (f)),
  2008.                  DefaultScreen (display), flags, &xwc))
  2009.     x_cant_notify_wm_error ();
  2010.     }
  2011. }
  2012.  
  2013. /* Change from withdrawn state to mapped state. */
  2014. static void
  2015. x_make_frame_visible (struct frame *f)
  2016. {
  2017.   Display *display = DEVICE_X_DISPLAY (XDEVICE (f->device));
  2018.  
  2019.   if (!f->visible)
  2020.     XMapRaised (display, XtWindow (FRAME_X_SHELL_WIDGET (f)));
  2021.   else
  2022.     x_raise_frame_1 (f, 0);
  2023. }
  2024.  
  2025. /* Change from mapped state to withdrawn state. */
  2026. static void
  2027. x_make_frame_invisible (struct frame *f)
  2028. {
  2029.   Display *display = DEVICE_X_DISPLAY (XDEVICE (f->device));
  2030.  
  2031.   if (!f->visible)
  2032.     return;
  2033.  
  2034.   if (!XWithdrawWindow (display,
  2035.             XtWindow (FRAME_X_SHELL_WIDGET (f)),
  2036.             DefaultScreen (display)))
  2037.     x_cant_notify_wm_error ();
  2038. }
  2039.  
  2040. static int
  2041. x_frame_totally_visible_p (struct frame *f)
  2042. {
  2043.   return FRAME_X_TOTALLY_VISIBLE_P (f);
  2044. }
  2045.  
  2046. /* Change window state from mapped to iconified. */
  2047. static void
  2048. x_iconify_frame (struct frame *f)
  2049. {
  2050.   Display *display = DEVICE_X_DISPLAY (XDEVICE (f->device));
  2051.  
  2052.   if (!XIconifyWindow (display,
  2053.                XtWindow (FRAME_X_SHELL_WIDGET (f)),
  2054.                DefaultScreen (display)))
  2055.     x_cant_notify_wm_error ();
  2056.  
  2057.   f->iconified = 1;
  2058. }
  2059.  
  2060. /* Sets the X focus to frame f. */
  2061. static void
  2062. x_focus_on_frame (struct frame *f)
  2063. {
  2064.   XWindowAttributes xwa;
  2065.   Widget shell_widget;
  2066.  
  2067.   assert (FRAME_IS_X (f));
  2068.  
  2069.   shell_widget = FRAME_X_SHELL_WIDGET (f);
  2070.   if (!XtWindow (shell_widget))
  2071.     return;
  2072.  
  2073. #ifdef EXTERNAL_WIDGET
  2074.   if (FRAME_X_EXTERNAL_WINDOW_P (f))
  2075.     ExternalShellSetFocus (shell_widget);
  2076. #endif /* EXTERNAL_WIDGET */
  2077.  
  2078.   /* Do the ICCCM focus change if the window is still visible.
  2079.      The s->visible flag might not be up-to-date, because we might
  2080.      not have processed magic events recently.  So make a server
  2081.      round-trip to find out whether it's really mapped right now.
  2082.      We grab the server to do this, because that's the only way to
  2083.      eliminate the race condition.
  2084.    */
  2085.   XGrabServer (XtDisplay (shell_widget));
  2086.   if (XGetWindowAttributes (XtDisplay (shell_widget),
  2087.                 XtWindow (shell_widget),
  2088.                 &xwa))
  2089.     f->visible = xwa.map_state == IsViewable;
  2090.       
  2091.   if (f->visible)
  2092.     {
  2093.       Window focus;
  2094.       int revert_to;
  2095.       XGetInputFocus (XtDisplay (shell_widget), &focus, &revert_to);
  2096.       /* Don't explicitly set the focus on this window unless the focus
  2097.      was on some other window (not PointerRoot).  Note that, even when
  2098.      running a point-to-type window manager like *twm, there is always
  2099.      a focus window; the window manager maintains that based on the
  2100.      mouse position.  If you set the "NoTitleFocus" option in these
  2101.      window managers, then the server itself maintains the focus via
  2102.      PointerRoot, and changing that to focus on the window would make
  2103.      the window grab the focus.  Very bad.
  2104.      */
  2105.       if (focus != PointerRoot)
  2106.     {
  2107.       XSetInputFocus (XtDisplay (shell_widget),
  2108.               XtWindow (shell_widget),
  2109.               RevertToParent,
  2110.               DEVICE_X_MOUSE_TIMESTAMP
  2111.               (XDEVICE (FRAME_DEVICE (f))));
  2112.       XFlush (XtDisplay (shell_widget));
  2113.     }
  2114.     }
  2115.   XUngrabServer (XtDisplay (shell_widget));
  2116.   XFlush (XtDisplay (shell_widget)); /* hey, I'd like to DEBUG this... */
  2117. }
  2118.  
  2119. /* Destroy the X window of frame S.  */
  2120. static void
  2121. x_delete_frame (struct frame *f)
  2122. {
  2123.   Widget w = FRAME_X_SHELL_WIDGET (f);
  2124.  
  2125.   free_frame_menubar (f);
  2126.   free_frame_scrollbars (f);
  2127.   free_frame_toolbars (f);
  2128.  
  2129.   if (FRAME_X_TOP_LEVEL_FRAME_P (f))
  2130.     x_wm_maybe_move_wm_command (f);
  2131.  
  2132. #ifdef EXTERNAL_WIDGET
  2133.   {
  2134.     Display *dpy = XtDisplay (w);
  2135.     expect_x_error (dpy);
  2136.     /* for obscure reasons having (I think) to do with the internal
  2137.        window-to-widget hierarchy maintained by Xt, we have to call
  2138.        XtUnrealizeWidget() here.  Xt can really suck. */
  2139.     if (f->being_deleted)
  2140.       XtUnrealizeWidget (w);
  2141.     XtDestroyWidget (w);
  2142.     x_error_occurred_p (dpy);
  2143.   }
  2144. #else
  2145.   XtDestroyWidget (w);
  2146. #endif /* EXTERNAL_WIDGET */
  2147.  
  2148.   xfree (FRAME_X_GEOM_FREE_ME_PLEASE (f));
  2149.   xfree (f->frame_data);
  2150.   f->frame_data = 0;
  2151. }
  2152.  
  2153.  
  2154. /************************************************************************/
  2155. /*                            initialization                            */
  2156. /************************************************************************/
  2157.  
  2158. void
  2159. syms_of_frame_x (void)
  2160. {
  2161.   defsymbol (&Qwindow_id, "window-id");
  2162.   defsymbol (&Qpopup, "popup");
  2163.   defsymbol (&Qpointer, "pointer");
  2164.   defsymbol (&Qscrollbar_pointer, "scrollbar-pointer");
  2165.   defsymbol (&Qx_resource_name, "x-resource-name");
  2166.  
  2167.   defsubr (&Sx_set_frame_icon_pixmap);
  2168.   defsubr (&Sx_set_frame_pointer);
  2169.   defsubr (&Sx_set_scrollbar_pointer);
  2170.   defsubr (&Sx_window_id);
  2171. }
  2172.  
  2173. void
  2174. device_type_create_frame_x (void)
  2175. {
  2176.   /* frame methods */
  2177.   DEVICE_HAS_METHOD (x, init_frame);
  2178.   DEVICE_HAS_METHOD (x, finish_init_frame);
  2179.   DEVICE_HAS_METHOD (x, mark_frame);
  2180.   DEVICE_HAS_METHOD (x, focus_on_frame);
  2181.   DEVICE_HAS_METHOD (x, delete_frame);
  2182.   DEVICE_HAS_METHOD (x, get_mouse_position);
  2183.   DEVICE_HAS_METHOD (x, set_mouse_position);
  2184.   DEVICE_HAS_METHOD (x, raise_frame);
  2185.   DEVICE_HAS_METHOD (x, lower_frame);
  2186.   DEVICE_HAS_METHOD (x, make_frame_visible);
  2187.   DEVICE_HAS_METHOD (x, make_frame_invisible);
  2188.   DEVICE_HAS_METHOD (x, iconify_frame);
  2189.   DEVICE_HAS_METHOD (x, set_frame_size);
  2190.   DEVICE_HAS_METHOD (x, set_frame_position);
  2191.   DEVICE_HAS_METHOD (x, get_frame_params);
  2192.   DEVICE_HAS_METHOD (x, set_frame_params);
  2193.   DEVICE_HAS_METHOD (x, set_title_from_char);
  2194.   DEVICE_HAS_METHOD (x, set_icon_name_from_char);
  2195.   DEVICE_HAS_METHOD (x, frame_totally_visible_p);
  2196.   DEVICE_HAS_METHOD (x, frame_iconified_p);
  2197. }
  2198.  
  2199. void
  2200. vars_of_frame_x (void)
  2201. {
  2202.   DEFVAR_LISP ("x-gc-pointer-shape", &Vx_gc_pointer_shape,
  2203.    "The shape of the mouse-pointer during garbage collection.\n\
  2204. If this is nil, then the cursor will not be changed, and echo-area messages\n\
  2205. will be used instead.");
  2206.   Vx_gc_pointer_shape = Qnil;
  2207.  
  2208.   DEFVAR_LISP ("x-scrollbar-pointer-shape", &Vx_scrollbar_pointer_shape,
  2209.   "Currently under construction.  Use `x-set-scrollbar-pointer' instead.");
  2210.   Vx_scrollbar_pointer_shape = Qnil;
  2211.  
  2212.   staticpro (&Vpre_gc_cursor);
  2213.   Vpre_gc_cursor = Qnil;
  2214.  
  2215. #ifdef EXTERNAL_WIDGET
  2216.   Fprovide (intern ("external-widget"));
  2217. #endif
  2218.  
  2219.   /* this call uses only safe functions from emacs.c */
  2220.   init_x_parm_symbols ();
  2221.  
  2222.   DEFVAR_LISP ("default-x-frame-alist", &Vdefault_x_frame_alist,
  2223.     "Alist of default frame-creation parameters for X frames.\n\
  2224. These override what is specified in the resource database and in\n\
  2225. `default-frame-alist', but are overridden by the arguments to the\n\
  2226. particular call to `make-frame'.\n\
  2227. \n\
  2228. Note: frame parameters are pretty much out-of-fashion.  Using\n\
  2229. the functions `modify-frame-parameters' and `frame-parameters' is\n\
  2230. definitely out-of-fashion, and soon these functions will be made\n\
  2231. obsolete.  Most uses of the frame parameters below can be replaced\n\
  2232. more flexibly with uses of a specifier, and soon, all frame parameters\n\
  2233. will have specifier equivalents.\n\
  2234. \n\
  2235. Here is a list of recognized frame parameters (they can be queried and\n\
  2236. set at any time, except as otherwise noted):\n\
  2237. \n\
  2238.   window-id            The X window ID corresponding to the\n\
  2239.                 frame.  May be set only at startup, and\n\
  2240.                 only if external widget support was\n\
  2241.                 compiled in; doing so causes the frame\n\
  2242.                 to be created as an \"external widget\"\n\
  2243.                 in another program that uses an existing\n\
  2244.                 window in the program rather than creating\n\
  2245.                 a new one.\n\
  2246.   initially-unmapped        If non-nil, the frame will not be visible\n\
  2247.                 when it is created.  In this case, you\n\
  2248.                 need to call `make-frame-visible' to make\n\
  2249.                 the frame appear.\n\
  2250.   popup                If non-nil, it should be a frame, and this\n\
  2251.                 frame will be created as a \"popup\" frame\n\
  2252.                 whose parent is the given frame.  This\n\
  2253.                 will make the window manager treat the\n\
  2254.                 frame as a dialog box, which may entail\n\
  2255.                 doing different things (e.g. not asking\n\
  2256.                 for positioning, and not iconifying\n\
  2257.                 separate from its parent).\n\
  2258.   inter-line-space        Not currently implemented.\n\
  2259.   toolbar-shadow-thickness    Thickness of toolbar shadows.\n\
  2260.   background-toolbar-color    Color of toolbar background.\n\
  2261.   bottom-toolbar-shadow-color    Color of bottom shadows on toolbars.\n\
  2262.                 (*Not* specific to the bottom-toolbar.)\n\
  2263.   top-toolbar-shadow-color    Color of top shadows on toolbars.\n\
  2264.                 (*Not* specifier to the top-toolbar.)\n\
  2265.   scrollbar-height        Going to be removed.\n\
  2266.   internal-border-width        Width of internal border around text area.\n\
  2267.   border-width            Width of external border around text area.\n\
  2268.   top                Y position (in pixels) of the upper-left\n\
  2269.                 outermost corner of the frame (i.e. the\n\
  2270.                 upper-left of the window-manager\n\
  2271.                 decorations).\n\
  2272.   left                X position (in pixels) of the upper-left\n\
  2273.                 outermost corner of the frame (i.e. the\n\
  2274.                 upper-left of the window-manager\n\
  2275.                 decorations).\n\
  2276.   border-color            Color of external border around text area.\n\
  2277.   cursor-color            Color of text cursor.\n\
  2278.   unsplittable            Not currently implemented.\n\
  2279.   minibuffer            Not currently implemented.\n\
  2280.   width                See `default-frame-alist'.\n\
  2281.   height            See `default-frame-alist'.\n\
  2282.   name                See `default-frame-alist'.\n\
  2283.   scrollbar-pointer        Doesn't really work.\n\
  2284.   pointer            Doesn't really work.\n\
  2285. \n\
  2286. See also `default-frame-alist', which specifies parameters which apply\n\
  2287. to all frames, not just X frames.");
  2288.   Vdefault_x_frame_alist = Qnil;
  2289.  
  2290.   x_device_methods->device_specific_frame_params = &Vdefault_x_frame_alist;
  2291. }
  2292.